From 4dba1cfdf04cb3aef6835927f322070926afcf54 Mon Sep 17 00:00:00 2001 From: yushen Date: Sun, 15 Feb 2026 06:31:00 +0800 Subject: [PATCH] refactor: unify API URL env var to MULTICA_API_URL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace scattered API_URL, MAIN_VITE_API_URL, and RENDERER_VITE_API_URL with a single MULTICA_API_URL across all apps and packages. - Desktop: use envPrefix to expose MULTICA_* to main process, rename RENDERER_VITE_API_URL → RENDERER_VITE_MULTICA_API_URL, remove MAIN_VITE_API_URL (now read directly via MULTICA_API_URL) - Web: add .env.development with MULTICA_API_URL, enforce required check in next.config.ts, update .gitignore to allow .env.development - Core: make MULTICA_API_URL required in api-client (no silent fallback) - Scripts: pass MULTICA_API_URL in dev-local.sh for web process - Turbo: update globalEnv from API_URL to MULTICA_API_URL - Docs: update references to the new env var name Co-Authored-By: Claude Opus 4.6 --- apps/desktop/.env.development | 6 ++-- apps/desktop/.env.example | 29 +++++++------------ apps/desktop/.env.production | 7 ++--- apps/desktop/electron.vite.config.ts | 1 + apps/desktop/src/main/electron-env.d.ts | 2 +- apps/desktop/src/main/index.ts | 4 +-- .../src/renderer/src/service/request.ts | 7 +++-- apps/desktop/src/renderer/src/vite-env.d.ts | 2 +- apps/web/.env.development | 1 + apps/web/.gitignore | 1 + apps/web/next.config.ts | 6 +++- docs/auth/desktop-integration.md | 2 +- docs/development.md | 4 +-- packages/core/src/hub/api-client.ts | 5 +++- scripts/dev-local.sh | 2 +- turbo.json | 2 +- 16 files changed, 41 insertions(+), 40 deletions(-) create mode 100644 apps/web/.env.development diff --git a/apps/desktop/.env.development b/apps/desktop/.env.development index 1baa4dd6..aca84c04 100644 --- a/apps/desktop/.env.development +++ b/apps/desktop/.env.development @@ -2,9 +2,7 @@ MAIN_VITE_GATEWAY_URL=https://multica-dev.copilothub.ai # Web URL for OAuth login (dev) MAIN_VITE_WEB_URL=http://localhost:3000 -# API URL for main process bridge (dev) -MAIN_VITE_API_URL=https://api-dev.copilothub.ai # API URL for renderer (dev) -RENDERER_VITE_API_URL=https://api-dev.copilothub.ai -# API URL for core/tools (dev) +RENDERER_VITE_MULTICA_API_URL=https://api-dev.copilothub.ai +# API URL for core/tools and main process bridge (dev) MULTICA_API_URL=https://api-dev.copilothub.ai diff --git a/apps/desktop/.env.example b/apps/desktop/.env.example index 0ee71ca1..6cd9f67a 100644 --- a/apps/desktop/.env.example +++ b/apps/desktop/.env.example @@ -44,17 +44,15 @@ # For production builds, create .env.production with the following variables: # # Required: -# MAIN_VITE_GATEWAY_URL - WebSocket Gateway URL for remote connections -# MAIN_VITE_WEB_URL - Web App URL for OAuth login flow -# MAIN_VITE_API_URL - API URL bridged to process.env for core package -# RENDERER_VITE_API_URL - API URL for renderer process (UI requests) -# MULTICA_API_URL - API URL for core/tools (web-search, finance) +# MAIN_VITE_GATEWAY_URL - WebSocket Gateway URL for remote connections +# MAIN_VITE_WEB_URL - Web App URL for OAuth login flow +# RENDERER_VITE_MULTICA_API_URL - API URL for renderer process (UI requests) +# MULTICA_API_URL - API URL for core/tools and main process bridge # # Example .env.production: # MAIN_VITE_GATEWAY_URL=https://gateway.multica.ai # MAIN_VITE_WEB_URL=https://www.multica.ai -# MAIN_VITE_API_URL=https://api.multica.ai -# RENDERER_VITE_API_URL=https://api.multica.ai +# RENDERER_VITE_MULTICA_API_URL=https://api.multica.ai # MULTICA_API_URL=https://api.multica.ai # # ============================================================================= @@ -65,6 +63,7 @@ # RENDERER_VITE_* - Renderer process only (browser context) # VITE_* - All processes # MULTICA_* - Core/CLI/Gateway (read via process.env at runtime) +# Also available in main process via envPrefix config # # ============================================================================= # Environment Variables @@ -80,21 +79,15 @@ MAIN_VITE_GATEWAY_URL=http://localhost:3000 # Production example: https://www.multica.ai MAIN_VITE_WEB_URL=http://localhost:3000 -# MAIN_VITE_API_URL -# API URL for main process - Bridged to process.env.MULTICA_API_URL at startup -# so that the externalized @multica/core package can read the correct API URL -# in packaged builds (where .env files are not bundled). -# Production example: https://api.multica.ai -MAIN_VITE_API_URL=http://localhost:8080 - -# RENDERER_VITE_API_URL +# RENDERER_VITE_MULTICA_API_URL # API URL for renderer process - Used by the React UI for login, user info, etc. # Production example: https://api.multica.ai -RENDERER_VITE_API_URL=http://localhost:8080 +RENDERER_VITE_MULTICA_API_URL=http://localhost:8080 # MULTICA_API_URL -# API URL for core/tools - Used by agent engine tools (web-search, finance) -# Read by core package via process.env.MULTICA_API_URL at runtime +# API URL for core/tools and main process bridge - Used by agent engine tools +# (web-search, finance) and bridged to process.env in packaged builds. +# Read by core package via process.env.MULTICA_API_URL at runtime. # Production example: https://api.multica.ai MULTICA_API_URL=http://localhost:8080 diff --git a/apps/desktop/.env.production b/apps/desktop/.env.production index 4ed19681..69f46e60 100644 --- a/apps/desktop/.env.production +++ b/apps/desktop/.env.production @@ -2,10 +2,7 @@ MAIN_VITE_GATEWAY_URL=https://gateway.multica.ai # Web URL for OAuth login MAIN_VITE_WEB_URL=https://www.multica.ai -# API URL for main process bridge → core package -MAIN_VITE_API_URL=https://api.multica.ai # API URL for renderer (UI requests) -RENDERER_VITE_API_URL=https://api.multica.ai -# API URL for core/tools — fallback already hardcoded in code; this documents the expected value -# In packaged builds, MAIN_VITE_API_URL bridges this via process.env +RENDERER_VITE_MULTICA_API_URL=https://api.multica.ai +# API URL for core/tools and main process bridge MULTICA_API_URL=https://api.multica.ai diff --git a/apps/desktop/electron.vite.config.ts b/apps/desktop/electron.vite.config.ts index a8502ec8..4f3c09df 100644 --- a/apps/desktop/electron.vite.config.ts +++ b/apps/desktop/electron.vite.config.ts @@ -6,6 +6,7 @@ import tailwindcss from '@tailwindcss/vite' export default defineConfig({ main: { plugins: [externalizeDepsPlugin()], + envPrefix: ['MAIN_VITE_', 'MULTICA_'], }, preload: { plugins: [externalizeDepsPlugin()], diff --git a/apps/desktop/src/main/electron-env.d.ts b/apps/desktop/src/main/electron-env.d.ts index da3774b4..c4d13f11 100644 --- a/apps/desktop/src/main/electron-env.d.ts +++ b/apps/desktop/src/main/electron-env.d.ts @@ -5,7 +5,7 @@ interface ImportMetaEnv { readonly MAIN_VITE_GATEWAY_URL: string readonly MAIN_VITE_WEB_URL: string - readonly MAIN_VITE_API_URL?: string + readonly MULTICA_API_URL?: string } interface ImportMeta { diff --git a/apps/desktop/src/main/index.ts b/apps/desktop/src/main/index.ts index da72ac87..352ea543 100644 --- a/apps/desktop/src/main/index.ts +++ b/apps/desktop/src/main/index.ts @@ -47,8 +47,8 @@ process.stderr?.on?.('error', (err: NodeJS.ErrnoException) => { // Bridge Vite build-time env to process.env for externalized @multica/core // In dev mode, electron-vite already loads .env into process.env; // In packaged builds, only import.meta.env has the value (injected at build time). -if (import.meta.env.MAIN_VITE_API_URL) { - process.env.MULTICA_API_URL ??= import.meta.env.MAIN_VITE_API_URL +if (import.meta.env.MULTICA_API_URL) { + process.env.MULTICA_API_URL ??= import.meta.env.MULTICA_API_URL } import { app, BrowserWindow, shell, ipcMain } from 'electron' diff --git a/apps/desktop/src/renderer/src/service/request.ts b/apps/desktop/src/renderer/src/service/request.ts index 53ab141d..e58e0eb0 100644 --- a/apps/desktop/src/renderer/src/service/request.ts +++ b/apps/desktop/src/renderer/src/service/request.ts @@ -1,7 +1,10 @@ import { useAuthStore } from '../stores/auth' -// Backend API host — driven by RENDERER_VITE_API_URL env var (set in .env.production / .env.development) -const API_HOST = import.meta.env.RENDERER_VITE_API_URL || 'https://api.multica.ai' +// Backend API host — driven by RENDERER_VITE_MULTICA_API_URL env var (set in .env.production / .env.development) +const API_HOST = import.meta.env.RENDERER_VITE_MULTICA_API_URL +if (!API_HOST) { + throw new Error('RENDERER_VITE_MULTICA_API_URL is required') +} /** * Fetch request wrapper for desktop app. diff --git a/apps/desktop/src/renderer/src/vite-env.d.ts b/apps/desktop/src/renderer/src/vite-env.d.ts index b165478f..c52de4ea 100644 --- a/apps/desktop/src/renderer/src/vite-env.d.ts +++ b/apps/desktop/src/renderer/src/vite-env.d.ts @@ -1,5 +1,5 @@ /// interface ImportMetaEnv { - readonly RENDERER_VITE_API_URL?: string + readonly RENDERER_VITE_MULTICA_API_URL?: string } diff --git a/apps/web/.env.development b/apps/web/.env.development new file mode 100644 index 00000000..d2f86570 --- /dev/null +++ b/apps/web/.env.development @@ -0,0 +1 @@ +MULTICA_API_URL=https://api-dev.copilothub.ai diff --git a/apps/web/.gitignore b/apps/web/.gitignore index 1ec5eb93..1df0151e 100644 --- a/apps/web/.gitignore +++ b/apps/web/.gitignore @@ -32,6 +32,7 @@ yarn-error.log* # env files (can opt-in for committing if needed) .env* +!.env.development # vercel .vercel diff --git a/apps/web/next.config.ts b/apps/web/next.config.ts index 9fbe55e8..8250f626 100644 --- a/apps/web/next.config.ts +++ b/apps/web/next.config.ts @@ -1,11 +1,15 @@ import type { NextConfig } from "next"; +if (!process.env.MULTICA_API_URL) { + throw new Error("MULTICA_API_URL is required"); +} + const nextConfig: NextConfig = { transpilePackages: ["@multica/ui", "@multica/store", "@multica/hooks", "@multica/sdk"], rewrites: async () => [ { source: "/api/:path*", - destination: `${process.env.API_URL || "https://api.multica.ai"}/api/:path*`, + destination: `${process.env.MULTICA_API_URL}/api/:path*`, }, ], headers: async () => [ diff --git a/docs/auth/desktop-integration.md b/docs/auth/desktop-integration.md index 7c776ad5..51871160 100644 --- a/docs/auth/desktop-integration.md +++ b/docs/auth/desktop-integration.md @@ -68,7 +68,7 @@ pnpm dev:web pnpm dev:desktop ``` -本地调试时,Next.js rewrites(配置在 `apps/web/next.config.ts`)自动将 `/api/*` 请求代理到 `api-dev.copilothub.ai`。 +本地调试时,Next.js rewrites(配置在 `apps/web/next.config.ts`)自动将 `/api/*` 请求代理到 `MULTICA_API_URL` 指定的后端。 ## 参考 diff --git a/docs/development.md b/docs/development.md index cd0144bc..5dc24c06 100644 --- a/docs/development.md +++ b/docs/development.md @@ -51,7 +51,7 @@ pnpm dev:local:archive # Archive dev data and start fresh | Variable | Description | |----------|-------------| -| `API_URL` | Backend API URL (default: `https://api-dev.copilothub.ai`) | +| `MULTICA_API_URL` | Backend API URL (required, no default) | **Build for different environments:** @@ -61,7 +61,7 @@ pnpm --filter @multica/desktop build # Production (.env.production) pnpm --filter @multica/desktop build:staging # Staging (.env.staging) # Web (Vercel) -# Set API_URL in Vercel Dashboard → Settings → Environment Variables +# Set MULTICA_API_URL in Vercel Dashboard → Settings → Environment Variables ``` See `apps/desktop/.env.example` for the full variable reference. diff --git a/packages/core/src/hub/api-client.ts b/packages/core/src/hub/api-client.ts index c5888b5b..c3254463 100644 --- a/packages/core/src/hub/api-client.ts +++ b/packages/core/src/hub/api-client.ts @@ -1,7 +1,10 @@ import { getLocalAuth } from "./auth-store.js"; export function getApiBaseUrl(): string { - return process.env.MULTICA_API_URL || "https://api.multica.ai"; + if (!process.env.MULTICA_API_URL) { + throw new Error("MULTICA_API_URL is required"); + } + return process.env.MULTICA_API_URL; } /** diff --git a/scripts/dev-local.sh b/scripts/dev-local.sh index 5c45b06a..d3319360 100755 --- a/scripts/dev-local.sh +++ b/scripts/dev-local.sh @@ -52,5 +52,5 @@ exec pnpm concurrently \ "pnpm --filter @multica/utils dev" \ "pnpm --filter @multica/core dev" \ "PORT=4000 SMC_DATA_DIR=~/.super-multica-dev MULTICA_WORKSPACE_DIR=~/Documents/Multica-dev MULTICA_RUN_LOG=1 pnpm --filter @multica/gateway dev" \ - "pnpm --filter @multica/web dev" \ + "MULTICA_API_URL=https://api-dev.copilothub.ai pnpm --filter @multica/web dev" \ "GATEWAY_URL=http://localhost:4000 MAIN_VITE_WEB_URL=http://localhost:3000 SMC_DATA_DIR=~/.super-multica-dev MULTICA_WORKSPACE_DIR=~/Documents/Multica-dev MULTICA_RUN_LOG=1 pnpm --filter @multica/desktop dev" diff --git a/turbo.json b/turbo.json index 25f29d58..624adc2e 100644 --- a/turbo.json +++ b/turbo.json @@ -1,7 +1,7 @@ { "$schema": "https://turbo.build/schema.json", "globalDependencies": ["tsconfig.json", "tsconfig.base.json"], - "globalEnv": ["API_URL"], + "globalEnv": ["MULTICA_API_URL"], "tasks": { "build": { "dependsOn": ["^build"],