- Consolidated environment variable management by centralizing all variables in the root .env file. - Updated development scripts across various packages to utilize the new environment loading mechanism. - Enhanced error handling for missing environment variables in the bot and server packages. - Adjusted Next.js configuration to map environment variables for client-side access.
Unified · Split
| @@ -1,24 +1,25 @@ | |||
| 1 | # Required for the assistant to call Claude | 1 | # All env vars live in this single root .env file. |
| 2 | ANTHROPIC_API_KEY=sk-ant-... | 2 | # Sub-packages load it via `with-env` scripts (bun --env-file). |
| 3 | # Or use Claude Max OAuth token instead: | 3 | # Next.js vars are mapped from canonical names in next.config.ts. |
| 4 | # ANTHROPIC_OAUTH_TOKEN=... | ||
| 5 | 4 | ||
| 6 | # Required for the Discord bot | 5 | # ── Convex (required) ── |
| 7 | DISCORD_BOT_TOKEN=... | 6 | CONVEX_DEPLOYMENT=dev:your-deployment-slug |
| 7 | CONVEX_URL=https://your-deployment.convex.cloud | ||
| 8 | CONVEX_SITE_URL=https://your-deployment.convex.site | ||
| 8 | 9 | ||
| 9 | # Optional: executor URL (defaults to http://localhost:4001) | 10 | # ── WorkOS (optional — enables auth, omit for guest-only mode) ── |
| 10 | # EXECUTOR_URL=http://localhost:4001 | 11 | # WORKOS_CLIENT_ID=client_... |
| 12 | # WORKOS_API_KEY=sk_test_... | ||
| 13 | # WORKOS_WEBHOOK_SECRET=... | ||
| 11 | 14 | ||
| 12 | # Optional: assistant server URL for the bot (defaults to http://localhost:3000) | 15 | # ── Discord bot (optional — omit to skip bot startup) ── |
| 13 | # ASSISTANT_SERVER_URL=http://localhost:3000 | 16 | # DISCORD_BOT_TOKEN=... |
| 14 | 17 | ||
| 15 | # Optional: assistant server port (defaults to 3000) | 18 | # ── Assistant (optional) ── |
| 16 | # PORT=3000 | 19 | # OPENASSISTANT_EXECUTOR_URL=http://localhost:3001 |
| 20 | # OPENASSISTANT_CALLBACK_BASE_URL=http://localhost:3000 | ||
| 17 | 21 | ||
| 18 | # Optional: executor server port (defaults to 4001) | 22 | # ── Tool source API keys (optional) ── |
| 19 | # Configured in executor/.env or as env var | ||
| 20 | |||
| 21 | # Optional: tool source API keys | ||
| 22 | # POSTHOG_PERSONAL_API_KEY=... | 23 | # POSTHOG_PERSONAL_API_KEY=... |
| 23 | # POSTHOG_PROJECT_ID=... | 24 | # POSTHOG_PROJECT_ID=... |
| 24 | # OPENASSISTANT_GITHUB_TOKEN=... | 25 | # OPENASSISTANT_GITHUB_TOKEN=... |
| @@ -3,8 +3,9 @@ · 2 unmodified lines | |||
| 3 | "private": true, | 3 | "private": true, |
| 4 | "type": "module", | 4 | "type": "module", |
| 5 | "scripts": { | 5 | "scripts": { |
| 6 | "dev": "bun --hot src/index.ts", | 6 | "with-env": "bun run --env-file=../../../.env --", |
| 7 | "start": "bun src/index.ts" | 7 | "dev": "bun with-env bun --hot src/index.ts", |
| 8 | "start": "bun with-env bun src/index.ts" | ||
| 8 | }, | 9 | }, |
| 9 | "dependencies": { | 10 | "dependencies": { |
| 10 | "@assistant/core": "workspace:*", | 11 | "@assistant/core": "workspace:*", |
| @@ -27,7 +27,10 @@ if (!DISCORD_TOKEN) { · 26 unmodified lines | |||
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | const SERVER_URL = Bun.env.ASSISTANT_SERVER_URL ?? "http://localhost:3000"; | 29 | const SERVER_URL = Bun.env.ASSISTANT_SERVER_URL ?? "http://localhost:3000"; |
| 30 | const CONVEX_URL = Bun.env.CONVEX_URL ?? "http://127.0.0.1:3210"; | 30 | const CONVEX_URL = Bun.env.CONVEX_URL; |
| 31 | if (!CONVEX_URL) { | ||
| 32 | throw new Error("CONVEX_URL is required. Set it in your environment."); | ||
| 33 | } | ||
| 31 | 34 | ||
| 32 | // --------------------------------------------------------------------------- | 35 | // --------------------------------------------------------------------------- |
| 33 | // Clients | 36 | // Clients |
| @@ -7,8 +7,9 @@ · 6 unmodified lines | |||
| 7 | "./client": "./src/client.ts" | 7 | "./client": "./src/client.ts" |
| 8 | }, | 8 | }, |
| 9 | "scripts": { | 9 | "scripts": { |
| 10 | "dev": "bun --hot src/index.ts", | 10 | "with-env": "bun run --env-file=../../../.env --", |
| 11 | "start": "bun src/index.ts" | 11 | "dev": "bun with-env bun --hot src/index.ts", |
| 12 | "start": "bun with-env bun src/index.ts" | ||
| 12 | }, | 13 | }, |
| 13 | "dependencies": { | 14 | "dependencies": { |
| 14 | "@assistant/core": "workspace:*", | 15 | "@assistant/core": "workspace:*", |
| @@ -7,7 +7,10 @@ import { ConvexHttpClient } from "convex/browser"; · 6 unmodified lines | |||
| 7 | import { api } from "@executor/convex/_generated/api"; | 7 | import { api } from "@executor/convex/_generated/api"; |
| 8 | 8 | ||
| 9 | const PORT = Number(Bun.env.PORT ?? 3000); | 9 | const PORT = Number(Bun.env.PORT ?? 3000); |
| 10 | const CONVEX_URL = Bun.env.CONVEX_URL ?? "http://127.0.0.1:3210"; | 10 | const CONVEX_URL = Bun.env.CONVEX_URL; |
| 11 | if (!CONVEX_URL) { | ||
| 12 | throw new Error("CONVEX_URL is required. Set it in your environment."); | ||
| 13 | } | ||
| 11 | const EXECUTOR_URL = Bun.env.EXECUTOR_URL | 14 | const EXECUTOR_URL = Bun.env.EXECUTOR_URL |
| 12 | ?? Bun.env.CONVEX_SITE_URL | 15 | ?? Bun.env.CONVEX_SITE_URL |
| 13 | ?? (CONVEX_URL.includes(".convex.cloud") | 16 | ?? (CONVEX_URL.includes(".convex.cloud") |
| @@ -3,6 +3,8 @@ · 2 unmodified lines | |||
| 3 | * | 3 | * |
| 4 | * Usage: bun dev | 4 | * Usage: bun dev |
| 5 | * | 5 | * |
| 6 | * Reads all configuration from the root .env file (auto-loaded by Bun). | ||
| 7 | * | ||
| 6 | * Starts: | 8 | * Starts: |
| 7 | * 1. Convex cloud dev function push (once) | 9 | * 1. Convex cloud dev function push (once) |
| 8 | * 2. Convex cloud dev function watcher | 10 | * 2. Convex cloud dev function watcher |
| @@ -36,39 +38,12 @@ function toSiteUrl(convexUrl: string): string { · 27 unmodified lines | |||
| 36 | return convexUrl; | 38 | return convexUrl; |
| 37 | } | 39 | } |
| 38 | 40 | ||
| 39 | async function resolveExecutorUrls(): Promise<{ convexUrl: string; executorUrl: string }> { | 41 | function resolveExecutorUrls(): { convexUrl: string; executorUrl: string } { |
| 40 | if (Bun.env.CONVEX_URL) { | 42 | const convexUrl = Bun.env.CONVEX_URL; |
| 41 | const convexUrl = Bun.env.CONVEX_URL; | ||
| 42 | const executorUrl = Bun.env.CONVEX_SITE_URL ?? toSiteUrl(convexUrl); | ||
| 43 | return { convexUrl, executorUrl }; | ||
| 44 | } | ||
| 45 | |||
| 46 | const envFile = Bun.file("./executor/.env.local"); | ||
| 47 | if (!(await envFile.exists())) { | ||
| 48 | throw new Error("Missing executor/.env.local with CONVEX_URL"); | ||
| 49 | } | ||
| 50 | |||
| 51 | const content = await envFile.text(); | ||
| 52 | const lines = content | ||
| 53 | .split("\n") | ||
| 54 | .map((entry) => entry.trim()); | ||
| 55 | |||
| 56 | const convexLine = lines.find((entry) => entry.startsWith("CONVEX_URL=")); | ||
| 57 | const siteLine = lines.find((entry) => entry.startsWith("CONVEX_SITE_URL=")); | ||
| 58 | |||
| 59 | if (!convexLine) { | ||
| 60 | throw new Error("CONVEX_URL not found in executor/.env.local"); | ||
| 61 | } | ||
| 62 | |||
| 63 | const convexUrl = convexLine.slice("CONVEX_URL=".length).trim(); | ||
| 64 | if (!convexUrl) { | 43 | if (!convexUrl) { |
| 65 | throw new Error("CONVEX_URL is empty in executor/.env.local"); | 44 | throw new Error("CONVEX_URL is not set. Add it to the root .env file."); |
| 66 | } | 45 | } |
| 67 | 46 | const executorUrl = Bun.env.CONVEX_SITE_URL ?? toSiteUrl(convexUrl); | |
| 68 | const executorUrl = siteLine | ||
| 69 | ? siteLine.slice("CONVEX_SITE_URL=".length).trim() | ||
| 70 | : toSiteUrl(convexUrl); | ||
| 71 | |||
| 72 | return { convexUrl, executorUrl }; | 47 | return { convexUrl, executorUrl }; |
| 73 | } | 48 | } |
| 74 | 49 | ||
| @@ -161,7 +136,7 @@ if (!Bun.env.DISCORD_BOT_TOKEN) { · 86 unmodified lines | |||
| 161 | // 1. Push functions (must complete before executor starts) | 136 | // 1. Push functions (must complete before executor starts) |
| 162 | await pushConvexFunctions(); | 137 | await pushConvexFunctions(); |
| 163 | 138 | ||
| 164 | const urls = await resolveExecutorUrls(); | 139 | const urls = resolveExecutorUrls(); |
| 165 | console.log(prefix("convex", `Using Convex URL: ${urls.convexUrl}`)); | 140 | console.log(prefix("convex", `Using Convex URL: ${urls.convexUrl}`)); |
| 166 | console.log(prefix("convex", `Using executor HTTP URL: ${urls.executorUrl}`)); | 141 | console.log(prefix("convex", `Using executor HTTP URL: ${urls.executorUrl}`)); |
| 167 | 142 | ||
| @@ -181,8 +156,8 @@ spawnService("web", ["bun", "run", "dev", "--", "-p", "3002"], { · 13 unmodified lines | |||
| 181 | // Small delay for web to be ready | 156 | // Small delay for web to be ready |
| 182 | await Bun.sleep(1200); | 157 | await Bun.sleep(1200); |
| 183 | 158 | ||
| 184 | spawnService("assistant", ["bun", "run", "--cwd", "packages/server", "dev"], { | 159 | spawnService("assistant", ["bun", "run", "dev"], { |
| 185 | cwd: "./assistant", | 160 | cwd: "./assistant/packages/server", |
| 186 | env: { | 161 | env: { |
| 187 | EXECUTOR_URL: urls.executorUrl, | 162 | EXECUTOR_URL: urls.executorUrl, |
| 188 | CONVEX_URL: urls.convexUrl, | 163 | CONVEX_URL: urls.convexUrl, |
| @@ -193,8 +168,8 @@ spawnService("assistant", ["bun", "run", "--cwd", "packages/server", "dev"], { · 4 unmodified lines | |||
| 193 | 168 | ||
| 194 | if (Bun.env.DISCORD_BOT_TOKEN) { | 169 | if (Bun.env.DISCORD_BOT_TOKEN) { |
| 195 | await Bun.sleep(1000); | 170 | await Bun.sleep(1000); |
| 196 | spawnService("bot", ["bun", "run", "--cwd", "packages/bot", "dev"], { | 171 | spawnService("bot", ["bun", "run", "dev"], { |
| 197 | cwd: "./assistant", | 172 | cwd: "./assistant/packages/bot", |
| 198 | env: { | 173 | env: { |
| 199 | CONVEX_URL: urls.convexUrl, | 174 | CONVEX_URL: urls.convexUrl, |
| 200 | }, | 175 | }, |
| @@ -1,6 +1,12 @@ | |||
| 1 | import type { NextConfig } from "next"; | 1 | import type { NextConfig } from "next"; |
| 2 | const nextConfig: NextConfig = { | 2 | const nextConfig: NextConfig = { |
| 3 | transpilePackages: ["@executor/contracts"], | 3 | transpilePackages: ["@executor/contracts"], |
| 4 | env: { | ||
| 5 | // Map canonical env vars to NEXT_PUBLIC_ so they're available client-side. | ||
| 6 | // This lets us keep a single root .env without NEXT_PUBLIC_ prefixes. | ||
| 7 | NEXT_PUBLIC_CONVEX_URL: process.env.CONVEX_URL, | ||
| 8 | NEXT_PUBLIC_WORKOS_CLIENT_ID: process.env.WORKOS_CLIENT_ID, | ||
| 9 | }, | ||
| 4 | }; | 10 | }; |
| 5 | 11 | ||
| 6 | export default nextConfig; | 12 | export default nextConfig; |
| @@ -3,9 +3,10 @@ · 2 unmodified lines | |||
| 3 | "version": "0.1.0", | 3 | "version": "0.1.0", |
| 4 | "private": true, | 4 | "private": true, |
| 5 | "scripts": { | 5 | "scripts": { |
| 6 | "dev": "next dev", | 6 | "with-env": "bun run --env-file=../../../.env --", |
| 7 | "build": "next build", | 7 | "dev": "bun with-env next dev", |
| 8 | "start": "next start", | 8 | "build": "bun with-env next build", |
| 9 | "start": "bun with-env next start", | ||
| 9 | "lint": "eslint" | 10 | "lint": "eslint" |
| 10 | }, | 11 | }, |
| 11 | "dependencies": { | 12 | "dependencies": { |
| @@ -10,7 +10,10 @@ import { ConvexProvider, ConvexReactClient } from "convex/react"; · 9 unmodified lines | |||
| 10 | import type { ReactNode } from "react"; | 10 | import type { ReactNode } from "react"; |
| 11 | import { workosEnabled } from "@/lib/auth-capabilities"; | 11 | import { workosEnabled } from "@/lib/auth-capabilities"; |
| 12 | 12 | ||
| 13 | const convexUrl = process.env.NEXT_PUBLIC_CONVEX_URL ?? "http://127.0.0.1:3210"; | 13 | const convexUrl = process.env.NEXT_PUBLIC_CONVEX_URL; |
| 14 | if (!convexUrl) { | ||
| 15 | throw new Error("CONVEX_URL is not set. Add it to the root .env file."); | ||
| 16 | } | ||
| 14 | const convexClient = new ConvexReactClient(convexUrl, { | 17 | const convexClient = new ConvexReactClient(convexUrl, { |
| 15 | unsavedChangesWarning: false, | 18 | unsavedChangesWarning: false, |
| 16 | }); | 19 | }); |
| @@ -10,18 +10,18 @@ · 9 unmodified lines | |||
| 10 | "assistant/packages/reacord" | 10 | "assistant/packages/reacord" |
| 11 | ], | 11 | ], |
| 12 | "scripts": { | 12 | "scripts": { |
| 13 | "with-env": "bun run --env-file=.env --", | ||
| 13 | "dev": "bun run dev.ts", | 14 | "dev": "bun run dev.ts", |
| 14 | "dev:executor": "bun run dev:executor:convex", | ||
| 15 | "dev:executor:convex": "bunx --cwd executor convex dev", | 15 | "dev:executor:convex": "bunx --cwd executor convex dev", |
| 16 | "dev:executor:web": "bun run --cwd executor/apps/web dev", | 16 | "dev:executor:web": "bun run --cwd executor/apps/web dev", |
| 17 | "dev:executor:all": "bun run dev:executor:convex & bun run dev:executor:web", | 17 | "dev:executor:all": "bun run dev:executor:convex & bun run dev:executor:web", |
| 18 | "dev:assistant": "bun run --cwd assistant dev:server", | 18 | "dev:assistant": "bun run --cwd assistant/packages/server dev", |
| 19 | "dev:bot": "bun run --cwd assistant dev:bot", | 19 | "dev:bot": "bun run --cwd assistant/packages/bot dev", |
| 20 | "test": "bun run test:executor && bun run test:assistant", | 20 | "test": "bun run test:executor && bun run test:assistant", |
| 21 | "test:executor": "bun test --cwd executor", | 21 | "test:executor": "bun test --cwd executor", |
| 22 | "test:assistant": "bun run --cwd assistant test", | 22 | "test:assistant": "bun run --cwd assistant test", |
| 23 | "typecheck:executor": "bunx tsc --noEmit -p executor/tsconfig.json", | 23 | "typecheck:executor": "bunx tsc --noEmit -p executor/tsconfig.json", |
| 24 | "db:clear:executor": "bun run executor/wipe-convex-db.ts", | 24 | "db:clear:executor": "bun with-env bun run executor/wipe-convex-db.ts", |
| 25 | "convex:codegen": "bunx --cwd executor convex codegen" | 25 | "convex:codegen": "bunx --cwd executor convex codegen" |
| 26 | }, | 26 | }, |
| 27 | "dependencies": { | 27 | "dependencies": { |