Compare commits

...

1 Commits

Author SHA1 Message Date
Jiayuan Zhang
dc4c4ca722 feat(docs): add i18n support with Chinese translations
Set up Fumadocs i18n infrastructure with directory-based locale
organization. English docs moved to content/docs/en/, Chinese
translations added in content/docs/zh/. Routes restructured under
[lang]/ segment with middleware for automatic locale detection
and redirect. Language switcher added to navigation.
2026-04-12 21:45:27 +08:00
42 changed files with 1384 additions and 66 deletions

View File

@@ -1,7 +0,0 @@
import type { ReactNode } from "react";
import { HomeLayout } from "fumadocs-ui/layouts/home";
import { baseOptions } from "@/app/layout.config";
export default function Layout({ children }: { children: ReactNode }) {
return <HomeLayout {...baseOptions}>{children}</HomeLayout>;
}

View File

@@ -0,0 +1,14 @@
import type { ReactNode } from "react";
import { HomeLayout } from "fumadocs-ui/layouts/home";
import { baseOptions } from "@/lib/layout.shared";
export default async function Layout({
params,
children,
}: {
params: Promise<{ lang: string }>;
children: ReactNode;
}) {
const { lang } = await params;
return <HomeLayout {...baseOptions(lang)}>{children}</HomeLayout>;
}

View File

@@ -1,21 +1,42 @@
import Link from "next/link";
export default function HomePage() {
const texts = {
en: {
title: "Multica Documentation",
description:
"The open-source managed agents platform. Turn coding agents into real teammates — assign tasks, track progress, compound skills.",
getStarted: "Get Started",
},
zh: {
title: "Multica 文档",
description:
"开源的托管智能体平台。将编程智能体变成真正的队友——分配任务、跟踪进度、积累技能。",
getStarted: "快速开始",
},
} as const;
export default async function HomePage({
params,
}: {
params: Promise<{ lang: string }>;
}) {
const { lang } = await params;
const t = texts[lang as keyof typeof texts] ?? texts.en;
return (
<main className="flex min-h-screen flex-col items-center justify-center gap-6 text-center px-4">
<h1 className="text-4xl font-bold tracking-tight sm:text-5xl">
Multica Documentation
{t.title}
</h1>
<p className="max-w-2xl text-lg text-fd-muted-foreground">
The open-source managed agents platform. Turn coding agents into real
teammates assign tasks, track progress, compound skills.
{t.description}
</p>
<div className="flex gap-4">
<Link
href="/docs"
href={`/${lang}/docs`}
className="inline-flex items-center rounded-md bg-fd-primary px-6 py-3 text-sm font-medium text-fd-primary-foreground transition-colors hover:bg-fd-primary/90"
>
Get Started
{t.getStarted}
</Link>
<Link
href="https://github.com/multica-ai/multica"

View File

@@ -10,10 +10,10 @@ import defaultMdxComponents from "fumadocs-ui/mdx";
import type { Metadata } from "next";
export default async function Page(props: {
params: Promise<{ slug?: string[] }>;
params: Promise<{ lang: string; slug?: string[] }>;
}) {
const params = await props.params;
const page = source.getPage(params.slug);
const { lang, slug } = await props.params;
const page = source.getPage(slug, lang);
if (!page) notFound();
const MDX = page.data.body;
@@ -30,14 +30,14 @@ export default async function Page(props: {
}
export async function generateStaticParams() {
return source.generateParams();
return source.generateParams("slug", "lang");
}
export async function generateMetadata(props: {
params: Promise<{ slug?: string[] }>;
params: Promise<{ lang: string; slug?: string[] }>;
}): Promise<Metadata> {
const params = await props.params;
const page = source.getPage(params.slug);
const { lang, slug } = await props.params;
const page = source.getPage(slug, lang);
if (!page) notFound();
return {

View File

@@ -0,0 +1,19 @@
import { DocsLayout } from "fumadocs-ui/layouts/docs";
import type { ReactNode } from "react";
import { baseOptions } from "@/lib/layout.shared";
import { source } from "@/lib/source";
export default async function Layout({
params,
children,
}: {
params: Promise<{ lang: string }>;
children: ReactNode;
}) {
const { lang } = await params;
return (
<DocsLayout tree={source.getPageTree(lang)} {...baseOptions(lang)}>
{children}
</DocsLayout>
);
}

View File

@@ -0,0 +1,21 @@
import { RootProvider } from "fumadocs-ui/provider";
import type { ReactNode } from "react";
import { i18nUI } from "@/lib/layout.shared";
export default async function LangLayout({
params,
children,
}: {
params: Promise<{ lang: string }>;
children: ReactNode;
}) {
const { lang } = await params;
return (
<html lang={lang} suppressHydrationWarning>
<body>
<RootProvider i18n={i18nUI.provider(lang)}>{children}</RootProvider>
</body>
</html>
);
}

View File

@@ -1,4 +1,12 @@
import { source } from "@/lib/source";
import { createFromSource } from "fumadocs-core/search/server";
export const { GET } = createFromSource(source);
export const { GET } = createFromSource(source, {
localeMap: {
zh: {
// Orama doesn't have a built-in Chinese tokenizer,
// so we disable language-specific stemming for zh
language: undefined,
},
},
});

View File

@@ -1,12 +0,0 @@
import { DocsLayout } from "fumadocs-ui/layouts/docs";
import type { ReactNode } from "react";
import { baseOptions } from "@/app/layout.config";
import { source } from "@/lib/source";
export default function Layout({ children }: { children: ReactNode }) {
return (
<DocsLayout tree={source.pageTree} {...baseOptions}>
{children}
</DocsLayout>
);
}

View File

@@ -1,25 +0,0 @@
import type { BaseLayoutProps } from "fumadocs-ui/layouts/shared";
import { BookOpen, Terminal, Rocket, Code } from "lucide-react";
export const baseOptions: BaseLayoutProps = {
nav: {
title: (
<span className="font-semibold text-base">Multica Docs</span>
),
},
links: [
{
text: "Documentation",
url: "/docs",
active: "nested-url",
},
{
text: "GitHub",
url: "https://github.com/multica-ai/multica",
},
{
text: "Cloud",
url: "https://multica.ai",
},
],
};

View File

@@ -1,5 +1,4 @@
import "./global.css";
import { RootProvider } from "fumadocs-ui/provider";
import type { ReactNode } from "react";
import type { Metadata } from "next";
@@ -13,11 +12,5 @@ export const metadata: Metadata = {
};
export default function Layout({ children }: { children: ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<RootProvider>{children}</RootProvider>
</body>
</html>
);
return children;
}

View File

@@ -0,0 +1,90 @@
---
title: CLI 安装
description: 安装 Multica CLI 并启动智能体守护进程。
---
## 安装
### HomebrewmacOS/Linux
```bash
brew tap multica-ai/tap
brew install multica
```
### 从源码构建
```bash
git clone https://github.com/multica-ai/multica.git
cd multica
make build
cp server/bin/multica /usr/local/bin/multica
```
### 从 GitHub Releases 下载
如果 Homebrew 不可用,可以直接下载二进制文件:
```bash
OS=$(uname -s | tr '[:upper:]' '[:lower:]') # "darwin" or "linux"
ARCH=$(uname -m) # "x86_64" or "arm64"
# Normalize architecture name
if [ "$ARCH" = "x86_64" ]; then
ARCH="amd64"
fi
# Get the latest release tag from GitHub
LATEST=$(curl -sI https://github.com/multica-ai/multica/releases/latest \
| grep -i '^location:' | sed 's/.*tag\///' | tr -d '\r\n')
# Download and extract
curl -sL "https://github.com/multica-ai/multica/releases/download/${LATEST}/multica_${OS}_${ARCH}.tar.gz" \
-o /tmp/multica.tar.gz
tar -xzf /tmp/multica.tar.gz -C /tmp multica
sudo mv /tmp/multica /usr/local/bin/multica
rm /tmp/multica.tar.gz
```
### 更新
```bash
multica update
```
该命令会自动检测你的安装方式Homebrew 或手动安装)并相应升级。
## 快速开始
```bash
# 1. 认证(打开浏览器登录)
multica login
# 2. 启动智能体守护进程
multica daemon start
# 3. 完成——你所关注的工作区中的智能体现在可以在你的机器上执行任务了
```
`multica login` 会自动发现你所属的所有工作区,并将它们添加到守护进程的监控列表中。
## 验证
```bash
multica daemon status
```
确认以下内容:
1. 状态为 `running`
2. 至少列出一个智能体(例如 `claude`、`codex`
3. 至少有一个工作区正在被监控
如果智能体列表为空,请安装至少一个 AI 智能体 CLI
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code)`claude`
- [Codex](https://github.com/openai/codex)`codex`
然后重启守护进程:
```bash
multica daemon stop && multica daemon start
```

View File

@@ -0,0 +1,4 @@
{
"title": "CLI 与守护进程",
"pages": ["installation", "reference"]
}

View File

@@ -0,0 +1,306 @@
---
title: CLI 参考
description: Multica CLI 和智能体守护进程的完整命令参考。
---
`multica` CLI 将你的本地机器连接到 Multica。它负责认证、工作区管理、议题追踪并运行在本地执行 AI 任务的智能体守护进程。
## 认证
### 浏览器登录
```bash
multica login
```
打开浏览器进行 OAuth 认证,创建有效期为 90 天的个人访问令牌,并自动配置你的工作区。
### 令牌登录
```bash
multica login --token
```
通过直接粘贴个人访问令牌进行认证。适用于无图形界面的环境。
### 检查状态
```bash
multica auth status
```
显示当前的服务器、用户和令牌有效性。
### 登出
```bash
multica auth logout
```
移除已存储的认证令牌。
## 智能体守护进程
守护进程是本地的智能体运行时。它检测你机器上可用的 AI CLI向 Multica 服务器注册,并在智能体被分配工作时执行任务。
### 启动
```bash
multica daemon start
```
默认情况下,守护进程在后台运行,日志记录到 `~/.multica/daemon.log`。
在前台运行(便于调试):
```bash
multica daemon start --foreground
```
### 停止
```bash
multica daemon stop
```
### 状态
```bash
multica daemon status
multica daemon status --output json
```
显示 PID、运行时间、检测到的智能体和监控的工作区。
### 日志
```bash
multica daemon logs # 最近 50 行
multica daemon logs -f # 实时跟踪tail -f
multica daemon logs -n 100 # 最近 100 行
```
### 支持的智能体
守护进程会自动检测 PATH 中的以下 AI CLI
| CLI | 命令 | 描述 |
|-----|---------|-------------|
| [Claude Code](https://docs.anthropic.com/en/docs/claude-code) | `claude` | Anthropic 的编程智能体 |
| [Codex](https://github.com/openai/codex) | `codex` | OpenAI 的编程智能体 |
你至少需要安装一个。守护进程会将每个检测到的 CLI 注册为可用运行时。
### 工作原理
1. 启动时,守护进程检测已安装的智能体 CLI并为每个监控的工作区中的每个智能体注册运行时
2. 它以可配置的间隔默认3 秒)轮询服务器获取已认领的任务
3. 当任务到达时,它会创建隔离的工作区目录,启动智能体 CLI并将结果流式传回
4. 定期发送心跳默认15 秒),以便服务器知道守护进程仍然活跃
5. 关闭时,所有运行时将被注销
### 配置
守护进程的行为通过标志或环境变量配置:
| 设置 | 标志 | 环境变量 | 默认值 |
|---------|------|--------------|---------|
| 轮询间隔 | `--poll-interval` | `MULTICA_DAEMON_POLL_INTERVAL` | `3s` |
| 心跳间隔 | `--heartbeat-interval` | `MULTICA_DAEMON_HEARTBEAT_INTERVAL` | `15s` |
| 智能体超时 | `--agent-timeout` | `MULTICA_AGENT_TIMEOUT` | `2h` |
| 最大并发任务数 | `--max-concurrent-tasks` | `MULTICA_DAEMON_MAX_CONCURRENT_TASKS` | `20` |
| 守护进程 ID | `--daemon-id` | `MULTICA_DAEMON_ID` | 主机名 |
| 设备名称 | `--device-name` | `MULTICA_DAEMON_DEVICE_NAME` | 主机名 |
| 运行时名称 | `--runtime-name` | `MULTICA_AGENT_RUNTIME_NAME` | `Local Agent` |
| 工作区根目录 | — | `MULTICA_WORKSPACES_ROOT` | `~/multica_workspaces` |
智能体专属覆盖配置:
| 变量 | 描述 |
|----------|-------------|
| `MULTICA_CLAUDE_PATH` | `claude` 二进制文件的自定义路径 |
| `MULTICA_CLAUDE_MODEL` | 覆盖使用的 Claude 模型 |
| `MULTICA_CODEX_PATH` | `codex` 二进制文件的自定义路径 |
| `MULTICA_CODEX_MODEL` | 覆盖使用的 Codex 模型 |
### 自托管服务器
连接到自托管的 Multica 实例时,在登录前将 CLI 指向你的服务器:
```bash
export MULTICA_APP_URL=https://app.example.com
export MULTICA_SERVER_URL=wss://api.example.com/ws
multica login
multica daemon start
```
或持久化设置:
```bash
multica config set app_url https://app.example.com
multica config set server_url wss://api.example.com/ws
```
### 配置文件
配置文件允许你在同一台机器上运行多个守护进程——例如,一个用于生产环境,一个用于预发布服务器。
```bash
# 为预发布服务器启动守护进程
multica --profile staging login
multica --profile staging daemon start
# 默认配置文件单独运行
multica daemon start
```
每个配置文件有自己的配置目录(`~/.multica/profiles/<name>/`)、守护进程状态、健康检查端口和工作区根目录。
## 工作区
### 列出工作区
```bash
multica workspace list
```
被监控的工作区用 `*` 标记。守护进程只处理被监控工作区的任务。
### 监控 / 取消监控
```bash
multica workspace watch <workspace-id>
multica workspace unwatch <workspace-id>
```
### 获取详情
```bash
multica workspace get <workspace-id>
multica workspace get <workspace-id> --output json
```
### 列出成员
```bash
multica workspace members <workspace-id>
```
## 议题
### 列出议题
```bash
multica issue list
multica issue list --status in_progress
multica issue list --priority urgent --assignee "Agent Name"
multica issue list --limit 20 --output json
```
可用过滤器:`--status`、`--priority`、`--assignee`、`--limit`。
### 获取议题
```bash
multica issue get <id>
multica issue get <id> --output json
```
### 创建议题
```bash
multica issue create --title "Fix login bug" --description "..." --priority high --assignee "Lambda"
```
标志:`--title`(必需)、`--description`、`--status`、`--priority`、`--assignee`、`--parent`、`--due-date`。
### 更新议题
```bash
multica issue update <id> --title "New title" --priority urgent
```
### 分配议题
```bash
multica issue assign <id> --to "Lambda"
multica issue assign <id> --unassign
```
### 更改状态
```bash
multica issue status <id> in_progress
```
有效状态:`backlog`、`todo`、`in_progress`、`in_review`、`done`、`blocked`、`cancelled`。
### 评论
```bash
# 列出评论
multica issue comment list <issue-id>
# 添加评论
multica issue comment add <issue-id> --content "Looks good, merging now"
# 回复特定评论
multica issue comment add <issue-id> --parent <comment-id> --content "Thanks!"
# 删除评论
multica issue comment delete <comment-id>
```
### 执行历史
```bash
# 列出某个议题的所有执行记录
multica issue runs <issue-id>
multica issue runs <issue-id> --output json
# 查看特定执行记录的消息
multica issue run-messages <task-id>
multica issue run-messages <task-id> --output json
# 增量获取(仅获取指定序列号之后的消息)
multica issue run-messages <task-id> --since 42 --output json
```
## 配置
### 查看配置
```bash
multica config show
```
显示配置文件路径、服务器 URL、应用 URL 和默认工作区。
### 设置值
```bash
multica config set server_url wss://api.example.com/ws
multica config set app_url https://app.example.com
multica config set workspace_id <workspace-id>
```
## 其他命令
```bash
multica version # 显示 CLI 版本和提交哈希
multica update # 更新到最新版本
multica agent list # 列出当前工作区中的智能体
```
## 输出格式
大多数命令支持 `--output`,有两种格式:
- `table` —— 人类可读的表格(列表命令的默认格式)
- `json` —— 结构化 JSON适用于脚本和自动化
```bash
multica issue list --output json
multica daemon status --output json
```

View File

@@ -0,0 +1,75 @@
---
title: 架构
description: Multica 平台的技术架构。
---
## 概览
Multica 由 Go 后端 + 单仓前端pnpm workspaces + Turborepo以及共享包组成。
```
┌──────────────┐ ┌──────────────┐ ┌──────────────────┐
│ Next.js │────>│ Go Backend │────>│ PostgreSQL │
│ Frontend │<────│ (Chi + WS) │<────│ (pgvector) │
└──────────────┘ └──────┬───────┘ └──────────────────┘
┌──────┴───────┐
│ Agent Daemon │ (runs on your machine)
│Claude/Codex/ │
│OpenClaw/Code │
└──────────────┘
```
## 项目结构
| 目录 | 用途 | 技术 |
|-----------|---------|------------|
| `server/` | Go 后端 | Chi router, sqlc for DB, gorilla/websocket |
| `apps/web/` | Next.js 前端 | App Router |
| `apps/desktop/` | Electron 桌面应用 | electron-vite |
| `apps/docs/` | 文档站点 | Fumadocs |
| `packages/core/` | 无头业务逻辑 | 零 react-dom 依赖,全平台复用 |
| `packages/ui/` | 原子级 UI 组件 | 零业务逻辑,基于 shadcn |
| `packages/views/` | 共享业务页面 | 零 next/\*、零 react-router 导入 |
| `packages/tsconfig/` | 共享 TypeScript 配置 | — |
| `packages/eslint-config/` | 共享 ESLint 配置 | — |
## 后端结构
- **入口点**`cmd/``server`HTTP API、`multica`CLI + 守护进程)、`migrate`
- **处理器**`internal/handler/`每个领域一个文件issue、comment、agent、auth、daemon
- **实时通信**`internal/realtime/`Hub 管理 WebSocket 客户端,服务器广播事件
- **认证**`internal/auth/` + `internal/middleware/`JWTHS256中间件设置 `X-User-ID` 和 `X-User-Email` 头
- **任务生命周期**`internal/service/task.go`):入队 → 认领 → 启动 → 完成/失败
- **智能体 SDK**`pkg/agent/`):统一的 `Backend` 接口,用于通过 Claude Code 或 Codex 执行提示
- **守护进程**`internal/daemon/`):自动检测 CLI注册运行时轮询任务
- **数据库**PostgreSQL 17 with pgvectorsqlc 从 `pkg/db/queries/` 中的 SQL 生成代码
## 前端架构
### 内部包模式
所有共享包导出原始的 `.ts`/`.tsx` 文件(无预编译)。消费方应用的打包器直接编译它们。这提供了零配置的 HMR 和即时的跳转到定义功能。
### 包边界
- `packages/core/` —— 零 react-dom零 localStorage零 UI 库。所有 Zustand store 在此。
- `packages/ui/` —— 纯 UI 组件,零业务逻辑。
- `packages/views/` —— 零 `next/*`,零 `react-router-dom`。使用 `NavigationAdapter` 进行路由。
### 状态管理
- **TanStack Query** 管理所有服务端状态(议题、用户、工作区)
- **Zustand** 管理所有客户端状态UI 选择、筛选器、草稿)
- **React Context** 仅用于跨切面基础设施(`WorkspaceIdProvider`、`NavigationProvider`
### 数据流
```
Browser → ApiClient (shared/api) → REST API (Chi handlers) → sqlc queries → PostgreSQL
Browser ← WSClient (shared/api) ← WebSocket ← Hub.Broadcast() ← Handlers/TaskService
```
## 多租户
所有查询按 `workspace_id` 过滤。成员资格检查控制访问。`X-Workspace-ID` 头将请求路由到正确的工作区。

View File

@@ -0,0 +1,178 @@
---
title: 参与贡献
description: 贡献者的本地开发工作流程。
---
## 开发模式
本地开发使用一个共享的 PostgreSQL 容器,每个 checkout 使用独立的数据库。
- 主 checkout 通常使用 `.env` 和 `POSTGRES_DB=multica`
- 每个 Git worktree 使用自己的 `.env.worktree`
- 所有 checkout 连接到同一个 PostgreSQL 主机:`localhost:5432`
- 隔离在数据库级别实现,而不是通过启动单独的 Docker Compose 项目
- 后端和前端端口在每个 worktree 中仍然是唯一的
## 前置要求
- Node.js `v20+`
- `pnpm` `v10.28+`
- Go `v1.26+`
- Docker
## 首次设置
### 主 checkout
```bash
cp .env.example .env
make setup-main
```
`make setup-main` 会执行以下操作:
- 使用 `pnpm install` 安装 JavaScript 依赖
- 确保共享的 PostgreSQL 容器正在运行
- 如果应用数据库不存在则创建它
- 对该数据库运行所有迁移
启动应用:
```bash
make start-main
```
### Worktree
从 worktree 目录中:
```bash
make worktree-env
make setup-worktree
```
启动 worktree 应用:
```bash
make start-worktree
```
## 日常工作流
### 主 checkout
```bash
make start-main
make stop-main
make check-main
```
### 功能 worktree
```bash
git worktree add ../multica-feature -b feat/my-change main
cd ../multica-feature
make worktree-env
make setup-worktree
make start-worktree
```
日常操作:
```bash
make start-worktree
make stop-worktree
make check-worktree
```
## 同时运行主 checkout 和 worktree
这是一等工作流。两个 checkout 使用同一个 PostgreSQL 容器,但使用不同的数据库和端口:
| | 主 checkout | Worktree |
|---|---|---|
| 数据库 | `multica` | `multica_my_feature_702` |
| 后端端口 | `8080` | 自动生成(例如 `18782` |
| 前端端口 | `3000` | 自动生成(例如 `13702` |
## 命令
```bash
# 前端(所有命令通过 Turborepo 执行)
pnpm install
pnpm dev:web # Next.js 开发服务器(端口 3000
pnpm dev:desktop # Electron 开发electron-vite, HMR
pnpm build # 构建所有前端应用
pnpm typecheck # TypeScript 检查
pnpm lint # ESLint
pnpm test # TS 测试Vitest
# 后端Go
make dev # 运行 Go 服务器(端口 8080
make daemon # 运行本地守护进程
make build # 构建服务器 + CLI 二进制文件
make test # Go 测试
make sqlc # 重新生成 sqlc 代码
make migrate-up # 运行数据库迁移
make migrate-down # 回滚迁移
```
## 测试
运行所有本地检查:
```bash
make check
```
这会运行:
1. TypeScript 类型检查
2. TypeScript 单元测试
3. Go 测试
4. Playwright E2E 测试
## 故障排除
### 缺少环境文件
创建所需的环境文件:
```bash
# 主 checkout
cp .env.example .env
# Worktree
make worktree-env
```
### 检查 checkout 使用的数据库
```bash
cat .env # 或 .env.worktree
```
查看 `POSTGRES_DB`、`DATABASE_URL`、`PORT`、`FRONTEND_PORT`。
### 列出所有本地数据库
```bash
docker compose exec -T postgres psql -U multica -d postgres \
-At -c "select datname from pg_database order by datname;"
```
### 破坏性重置
停止 PostgreSQL 并保留本地数据库:
```bash
make db-down
```
清除所有本地 PostgreSQL 数据:
```bash
docker compose down -v
```
> **警告:** 此操作会删除共享的 Docker 卷和所有数据库。之后你必须重新运行 `make setup-main` 或 `make setup-worktree`。

View File

@@ -0,0 +1,4 @@
{
"title": "开发者",
"pages": ["contributing", "architecture"]
}

View File

@@ -0,0 +1,48 @@
---
title: 云端快速开始
description: 开始使用 Multica Cloud —— 无需任何配置。
---
使用 Multica 最快的方式——无需任何配置。
## 1. 注册账号
前往 [multica.ai](https://multica.ai) 创建账号。
## 2. 安装 CLI 并启动守护进程
将以下指令交给你的 AI 智能体Claude Code、Codex、OpenClaw、OpenCode 等):
```
Fetch https://github.com/multica-ai/multica/blob/main/CLI_INSTALL.md and follow the instructions to install Multica CLI, log in, and start the daemon on this machine.
```
或手动安装:
```bash
# 安装
brew tap multica-ai/tap
brew install multica
# 认证并启动
multica login
multica daemon start
```
守护进程会自动检测 PATH 中可用的智能体 CLI`claude`、`codex`、`openclaw`、`opencode`)。当智能体被分配任务时,守护进程会创建隔离的环境,运行智能体,并将结果回报。
## 3. 验证运行时
在 Multica Web 应用中打开你的工作区。导航到 **Settings → Runtimes**——你应该能看到你的机器被列为一个活跃的 **Runtime**。
> **什么是 Runtime** Runtime 是可以执行智能体任务的计算环境。它可以是你的本地机器(通过守护进程)或云端实例。每个 Runtime 会报告可用的智能体 CLI以便 Multica 知道将工作路由到哪里。
## 4. 创建智能体
前往 **Settings → Agents** 并点击 **New Agent**。选择你刚连接的 Runtime然后选择一个提供商Claude Code、Codex、OpenClaw 或 OpenCode。为你的智能体命名——这将是它在看板、评论和分配中显示的名称。
## 5. 分配你的第一个任务
在看板上创建一个议题(或通过 `multica issue create`),然后将其分配给你的新智能体。智能体会自动接手任务,在你的 Runtime 上执行,并报告进度——就像一个真实的团队成员。
就是这样!你的智能体现在已经是团队的一员了。

View File

@@ -0,0 +1,4 @@
{
"title": "快速开始",
"pages": ["cloud-quickstart", "self-hosting"]
}

View File

@@ -0,0 +1,370 @@
---
title: 自托管指南
description: 在你自己的基础设施上部署 Multica。
---
## 架构概览
Multica 包含三个组件:
| 组件 | 描述 | 技术 |
|-----------|-------------|------------|
| **后端** | REST API + WebSocket 服务器 | Go单一二进制文件 |
| **前端** | Web 应用 | Next.js 16 |
| **数据库** | 主数据存储 | PostgreSQL 17 with pgvector |
每个需要在本地运行 AI 智能体的用户还需要安装 **`multica` CLI** 并在自己的机器上运行**智能体守护进程**。
## 前置要求
- Docker 和 Docker Compose
## 快速安装
一条命令完成所有设置:
```bash
curl -fsSL https://raw.githubusercontent.com/multica-ai/multica/main/scripts/install.sh | bash -s -- --local
```
该脚本会克隆仓库、启动所有服务、安装 CLI 并完成配置。然后:
1. 打开 http://localhost:3000——使用任意邮箱 + 验证码 **`888888`** 登录
2. 运行 `multica login` 和 `multica daemon start`
<Callout>
如需分步设置,请参阅下方内容。
</Callout>
## 分步设置
### 步骤 1 —— 启动服务器
```bash
git clone https://github.com/multica-ai/multica.git
cd multica
make selfhost
```
`make selfhost` 会自动创建 `.env`,生成随机的 `JWT_SECRET`,并通过 Docker Compose 启动所有服务。
启动完成后:
- **前端:** http://localhost:3000
- **后端 API** http://localhost:8080
<Callout>
如果你更喜欢手动执行 Docker Compose 步骤:`cp .env.example .env`,编辑 `JWT_SECRET`,然后 `docker compose -f docker-compose.selfhost.yml up -d`。
</Callout>
### 步骤 2 —— 登录
打开 http://localhost:3000。输入任意邮箱地址使用验证码 **`888888`** 登录。
<Callout>
此万能验证码在所有非生产环境中均可使用(当 `APP_ENV` 未设置为 `production` 时)。生产环境请配置邮件服务——参见下方[配置](#configuration)部分。
</Callout>
### 步骤 3 —— 安装 CLI 并启动守护进程
守护进程运行在你的本地机器上(不在 Docker 内部)。它会检测已安装的 AI 智能体 CLI向服务器注册并执行任务。
### a) 安装 CLI 和 AI 智能体
```bash
brew install multica-ai/tap/multica
```
你还需要至少一个 AI 智能体 CLI
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code)PATH 中有 `claude`
- [Codex](https://github.com/openai/codex)PATH 中有 `codex`
### b) 一键设置
```bash
multica setup --local
```
该命令会自动:
1. 配置 CLI 连接到 `localhost`
2. 打开浏览器进行认证
3. 发现你的工作区
4. 在后台启动守护进程
验证守护进程是否正在运行:
```bash
multica daemon status
```
<Callout>
也可以手动配置:`multica config local && multica login && multica daemon start`
</Callout>
### 步骤 4 —— 验证并开始使用
1. 在 http://localhost:3000 打开你的工作区
2. 导航到 **Settings → Runtimes**——你应该能看到你的机器
3. 前往 **Settings → Agents** 创建一个新智能体
4. 创建一个议题并分配给你的智能体
## 停止服务
```bash
# 停止 Docker Compose 服务
make selfhost-stop
# 停止本地守护进程
multica daemon stop
```
## 切换到 Multica Cloud
如果你一直在自托管,现在想将 CLI 切换到 [Multica Cloud](https://multica.ai)
```bash
multica config set server_url https://api.multica.ai
multica config set app_url https://multica.ai
multica login
```
或者重新运行安装脚本(不带 `--local`)——它会自动重新配置 CLI
```bash
curl -fsSL https://raw.githubusercontent.com/multica-ai/multica/main/scripts/install.sh | bash
```
<Callout>
你的本地 Docker 服务不受影响。如果不再需要,请单独停止它们。
</Callout>
## 更新后重新构建
```bash
git pull
make selfhost
```
数据库迁移会在后端启动时自动执行。
---
## 配置
所有配置通过环境变量完成。以 `.env.example` 为起点。
### 必需变量
| 变量 | 描述 | 示例 |
|----------|-------------|---------|
| `DATABASE_URL` | PostgreSQL 连接字符串 | `postgres://multica:multica@localhost:5432/multica?sslmode=disable` |
| `JWT_SECRET` | **必须修改默认值。** 用于签署 JWT 令牌的密钥。使用长随机字符串。 | `openssl rand -hex 32` |
| `FRONTEND_ORIGIN` | 前端服务的 URL用于 CORS | `https://app.example.com` |
### 邮件(认证必需)
Multica 通过 [Resend](https://resend.com) 使用基于邮件的魔法链接认证。
| 变量 | 描述 |
|----------|-------------|
| `RESEND_API_KEY` | 你的 Resend API 密钥 |
| `RESEND_FROM_EMAIL` | 发件人邮箱地址(默认:`noreply@multica.ai` |
### Google OAuth可选
| 变量 | 描述 |
|----------|-------------|
| `GOOGLE_CLIENT_ID` | Google OAuth 客户端 ID |
| `GOOGLE_CLIENT_SECRET` | Google OAuth 客户端密钥 |
| `GOOGLE_REDIRECT_URI` | OAuth 回调 URL例如 `https://app.example.com/auth/callback` |
### 文件存储(可选)
对于文件上传和附件,配置 S3 和 CloudFront
| 变量 | 描述 |
|----------|-------------|
| `S3_BUCKET` | S3 存储桶名称 |
| `S3_REGION` | AWS 区域(默认:`us-west-2` |
| `CLOUDFRONT_DOMAIN` | CloudFront 分发域名 |
| `CLOUDFRONT_KEY_PAIR_ID` | CloudFront 密钥对 ID用于签名 URL |
| `CLOUDFRONT_PRIVATE_KEY` | CloudFront 私钥PEM 格式) |
| `COOKIE_DOMAIN` | CloudFront 认证 Cookie 的域名 |
### 服务器
| 变量 | 默认值 | 描述 |
|----------|---------|-------------|
| `PORT` | `8080` | 后端服务器端口 |
| `FRONTEND_PORT` | `3000` | 前端端口 |
| `CORS_ALLOWED_ORIGINS` | `FRONTEND_ORIGIN` 的值 | 逗号分隔的允许来源列表 |
| `LOG_LEVEL` | `info` | 日志级别:`debug`、`info`、`warn`、`error` |
### CLI / 守护进程
以下配置在每个用户的机器上设置,不在服务器上:
| 变量 | 默认值 | 描述 |
|----------|---------|-------------|
| `MULTICA_SERVER_URL` | `ws://localhost:8080/ws` | 守护进程到服务器的 WebSocket URL |
| `MULTICA_APP_URL` | `http://localhost:3000` | CLI 登录流程的前端 URL |
| `MULTICA_DAEMON_POLL_INTERVAL` | `3s` | 守护进程轮询任务的间隔 |
| `MULTICA_DAEMON_HEARTBEAT_INTERVAL` | `15s` | 心跳频率 |
## 数据库设置
Multica 需要安装了 pgvector 扩展的 PostgreSQL 17。
### 使用自带的 Docker Compose
```bash
docker compose up -d postgres
```
这会在端口 5432 上启动一个 `pgvector/pgvector:pg17` 容器,使用默认凭据(`multica`/`multica`)。
### 使用你自己的 PostgreSQL
确保 pgvector 扩展可用:
```sql
CREATE EXTENSION IF NOT EXISTS vector;
```
### 运行迁移
在启动服务器之前必须运行迁移:
```bash
# 使用已构建的二进制文件
./server/bin/migrate up
# 或从源码运行
cd server && go run ./cmd/migrate up
```
## 手动设置(不使用 Docker Compose
如果你更喜欢手动构建和运行服务:
**前置要求:** Go 1.26+、Node.js 20+、pnpm 10.28+、PostgreSQL 17 with pgvector。
```bash
# 启动你的 PostgreSQL或使用docker compose up -d postgres
# 构建后端
make build
# 运行数据库迁移
DATABASE_URL="your-database-url" ./server/bin/migrate up
# 启动后端服务器
DATABASE_URL="your-database-url" PORT=8080 JWT_SECRET="your-secret" ./server/bin/server
```
前端:
```bash
pnpm install
pnpm build
# 启动前端(生产模式)
cd apps/web
REMOTE_API_URL=http://localhost:8080 pnpm start
```
## 反向代理
在生产环境中,在后端和前端之前放置反向代理来处理 TLS 和路由。
### Caddy推荐
```
app.example.com {
reverse_proxy localhost:3000
}
api.example.com {
reverse_proxy localhost:8080
}
```
### Nginx
```nginx
# 前端
server {
listen 443 ssl;
server_name app.example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# 后端 API
server {
listen 443 ssl;
server_name api.example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# WebSocket 支持
location /ws {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 86400;
}
}
```
当前端和后端使用不同域名时,请相应设置以下环境变量:
```bash
# 后端
FRONTEND_ORIGIN=https://app.example.com
CORS_ALLOWED_ORIGINS=https://app.example.com
# 前端
REMOTE_API_URL=https://api.example.com
NEXT_PUBLIC_API_URL=https://api.example.com
NEXT_PUBLIC_WS_URL=wss://api.example.com/ws
```
## 健康检查
后端暴露了一个健康检查端点:
```
GET /health
→ {"status":"ok"}
```
可用于负载均衡器健康检查或监控。
## 升级
1. 拉取最新代码或镜像
2. 运行迁移:`./server/bin/migrate up`
3. 重启后端和前端
迁移仅支持向前执行,可以安全地在运行中的数据库上执行。它们是幂等的——多次运行不会产生任何影响。

View File

@@ -0,0 +1,50 @@
---
title: 智能体
description: AI 智能体在 Multica 中的工作方式——执行模型、技能和运行时指南。
---
## 智能体即队友
在 Multica 中,智能体是一等公民。它们拥有个人资料,出现在看板上,发布评论,创建议题,并主动报告阻塞问题。
分配对象是多态的——一个议题可以分配给成员或智能体。议题上的 `assignee_type` + `assignee_id` 字段区分两者。智能体以独特的样式渲染(紫色背景,机器人图标)。
## 智能体执行模型
当智能体在 Multica 中被分配任务时:
1. 守护进程检测到任务分配
2. 创建隔离的工作区目录
3. 启动相应的智能体 CLIClaude Code、Codex、OpenClaw 或 OpenCode
4. 智能体自主执行,将进度流式传回 Multica
5. 报告结果——成功、失败或阻塞
完整的任务生命周期为:**入队 → 认领 → 启动 → 完成/失败**。
实时进度通过 WebSocket 推送,你可以在 Multica UI 中实时跟踪。
## 支持的智能体提供商
| 提供商 | CLI 命令 | 描述 |
|----------|-------------|-------------|
| Claude Code | `claude` | Anthropic 的编程智能体 |
| Codex | `codex` | OpenAI 的编程智能体 |
| OpenClaw | `openclaw` | 开源编程智能体 |
| OpenCode | `opencode` | 开源编程智能体 |
守护进程会自动检测 PATH 中可用的 CLI并将它们注册为可用运行时。
## 可复用技能
智能体创建的每个解决方案都可以成为整个团队的可复用技能。技能随时间不断增强团队能力:
- 部署
- 迁移
- 代码审查
- 常见模式
技能在工作区内共享,任何智能体(或人类)都可以使用。
## 多工作区支持
每个工作区拥有自己的智能体、议题和设置。守护进程可以同时监控多个工作区,根据工作区配置将任务路由到相应的智能体。

View File

@@ -0,0 +1,4 @@
{
"title": "使用指南",
"pages": ["quickstart", "agents"]
}

View File

@@ -0,0 +1,31 @@
---
title: 快速开始
description: 在 5 分钟内将你的第一个任务分配给智能体。
---
安装 CLI 完成后(或注册了 [Multica Cloud](https://multica.ai)),按照以下步骤将你的第一个任务分配给智能体。
## 1. 登录并启动守护进程
```bash
multica login # 使用你的 Multica 账号进行认证
multica daemon start # 启动本地智能体运行时
```
守护进程在后台运行,保持你的机器与 Multica 的连接。它会自动检测 PATH 中可用的智能体 CLI`claude`、`codex`、`openclaw`、`opencode`)。
## 2. 验证运行时
在 Multica Web 应用中打开你的工作区。导航到 **Settings → Runtimes**——你应该能看到你的机器被列为一个活跃的 **Runtime**。
> **什么是 Runtime** Runtime 是可以执行智能体任务的计算环境。它可以是你的本地机器(通过守护进程)或云端实例。每个 Runtime 会报告可用的智能体 CLI以便 Multica 知道将工作路由到哪里。
## 3. 创建智能体
前往 **Settings → Agents** 并点击 **New Agent**。选择你刚连接的 Runtime然后选择一个提供商Claude Code、Codex、OpenClaw 或 OpenCode。为你的智能体命名——这将是它在看板、评论和分配中显示的名称。
## 4. 分配你的第一个任务
在看板上创建一个议题(或通过 `multica issue create`),然后将其分配给你的新智能体。智能体会自动接手任务,在你的 Runtime 上执行,并报告进度——就像一个真实的团队成员。
就是这样!你的智能体现在已经是团队的一员了。

View File

@@ -0,0 +1,47 @@
---
title: 简介
description: Multica —— 开源的托管智能体平台。让编程智能体成为真正的团队成员。
---
## 什么是 Multica
Multica 让编程智能体成为真正的团队成员。像分配任务给同事一样,将议题分配给智能体——它们会自动接手工作、编写代码、报告阻塞问题并更新状态。
无需再复制粘贴提示词,无需再人工盯着运行过程。你的智能体会出现在看板上、参与讨论,并随着时间积累可复用的技能。可以把它看作托管智能体的开源基础设施——厂商中立、可自托管,专为人机协作团队设计。支持 **Claude Code**、**Codex**、**OpenClaw** 和 **OpenCode**。
## 功能特性
- **智能体即队友** —— 像分配给同事一样分配给智能体。它们拥有个人资料,出现在看板上,发布评论,创建议题,并主动报告阻塞问题。
- **自主执行** —— 设定后即可无需干预。完整的任务生命周期管理(入队、认领、启动、完成/失败),通过 WebSocket 实时推送进度。
- **可复用技能** —— 每个解决方案都会成为整个团队可复用的技能。部署、迁移、代码审查——技能随时间不断增强团队能力。
- **统一运行时** —— 一个仪表盘管理所有计算资源。本地守护进程和云端运行时,自动检测可用的 CLI实时监控。
- **多工作区** —— 跨团队组织工作,工作区级别隔离。每个工作区拥有自己的智能体、议题和设置。
## 架构
| 层级 | 技术栈 |
|-------|-------|
| 前端 | Next.js 16 (App Router) |
| 后端 | Go (Chi router, sqlc, gorilla/websocket) |
| 数据库 | PostgreSQL 17 with pgvector |
| 智能体运行时 | 本地守护进程,执行 Claude Code、Codex、OpenClaw 或 OpenCode |
```
┌──────────────┐ ┌──────────────┐ ┌──────────────────┐
│ Next.js │────>│ Go Backend │────>│ PostgreSQL │
│ Frontend │<────│ (Chi + WS) │<────│ (pgvector) │
└──────────────┘ └──────┬───────┘ └──────────────────┘
┌──────┴───────┐
│ Agent Daemon │ (runs on your machine)
│Claude/Codex/ │
│OpenClaw/Code │
└──────────────┘
```
## 下一步
- [云端快速开始](/docs/getting-started/cloud-quickstart)
- [自托管部署](/docs/getting-started/self-hosting)
- [CLI 安装](/docs/cli/installation)
- [参与贡献](/docs/developers/contributing)

View File

@@ -0,0 +1,10 @@
{
"title": "文档",
"pages": [
"index",
"getting-started",
"cli",
"guides",
"developers"
]
}

7
apps/docs/lib/i18n.ts Normal file
View File

@@ -0,0 +1,7 @@
import { defineI18n } from "fumadocs-core/i18n";
export const i18n = defineI18n({
defaultLanguage: "en",
languages: ["en", "zh"],
parser: "dir",
});

View File

@@ -0,0 +1,48 @@
import type { BaseLayoutProps } from "fumadocs-ui/layouts/shared";
import { i18n } from "@/lib/i18n";
import { defineI18nUI } from "fumadocs-ui/i18n";
export const i18nUI = defineI18nUI(i18n, {
translations: {
en: {
displayName: "English",
},
zh: {
displayName: "中文",
search: "搜索文档",
searchNoResult: "未找到结果",
toc: "目录",
tocNoHeadings: "无标题",
lastUpdate: "最后更新",
chooseLanguage: "选择语言",
nextPage: "下一页",
previousPage: "上一页",
chooseTheme: "选择主题",
},
},
});
export function baseOptions(locale: string): BaseLayoutProps {
return {
nav: {
title: (
<span className="font-semibold text-base">Multica Docs</span>
),
},
links: [
{
text: locale === "zh" ? "文档" : "Documentation",
url: `/${locale}/docs`,
active: "nested-url",
},
{
text: "GitHub",
url: "https://github.com/multica-ai/multica",
},
{
text: locale === "zh" ? "云服务" : "Cloud",
url: "https://multica.ai",
},
],
};
}

View File

@@ -1,7 +1,9 @@
import { docs } from "@/.source";
import { loader } from "fumadocs-core/source";
import { i18n } from "@/lib/i18n";
export const source = loader({
baseUrl: "/docs",
source: docs.toFumadocsSource(),
i18n,
});

8
apps/docs/middleware.ts Normal file
View File

@@ -0,0 +1,8 @@
import { createI18nMiddleware } from "fumadocs-core/i18n/middleware";
import { i18n } from "@/lib/i18n";
export default createI18nMiddleware(i18n);
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
};