refactor: unify API URL env var to MULTICA_API_URL

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 <noreply@anthropic.com>
This commit is contained in:
yushen 2026-02-15 06:31:00 +08:00
parent 25629f97ca
commit 4dba1cfdf0
16 changed files with 41 additions and 40 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -6,6 +6,7 @@ import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
main: {
plugins: [externalizeDepsPlugin()],
envPrefix: ['MAIN_VITE_', 'MULTICA_'],
},
preload: {
plugins: [externalizeDepsPlugin()],

View file

@ -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 {

View file

@ -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'

View file

@ -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.

View file

@ -1,5 +1,5 @@
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly RENDERER_VITE_API_URL?: string
readonly RENDERER_VITE_MULTICA_API_URL?: string
}

View file

@ -0,0 +1 @@
MULTICA_API_URL=https://api-dev.copilothub.ai

1
apps/web/.gitignore vendored
View file

@ -32,6 +32,7 @@ yarn-error.log*
# env files (can opt-in for committing if needed)
.env*
!.env.development
# vercel
.vercel

View file

@ -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 () => [

View file

@ -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` 指定的后端
## 参考

View file

@ -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.

View file

@ -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;
}
/**

View file

@ -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"

View file

@ -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"],