mirror of
https://github.com/multica-ai/multica.git
synced 2026-06-28 01:49:18 +02:00
Compare commits
1 Commits
agent/lamb
...
agent/emac
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc4c4ca722 |
@@ -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>;
|
||||
}
|
||||
14
apps/docs/app/[lang]/(home)/layout.tsx
Normal file
14
apps/docs/app/[lang]/(home)/layout.tsx
Normal 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>;
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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 {
|
||||
19
apps/docs/app/[lang]/docs/layout.tsx
Normal file
19
apps/docs/app/[lang]/docs/layout.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
21
apps/docs/app/[lang]/layout.tsx
Normal file
21
apps/docs/app/[lang]/layout.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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",
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
90
apps/docs/content/docs/zh/cli/installation.mdx
Normal file
90
apps/docs/content/docs/zh/cli/installation.mdx
Normal file
@@ -0,0 +1,90 @@
|
||||
---
|
||||
title: CLI 安装
|
||||
description: 安装 Multica CLI 并启动智能体守护进程。
|
||||
---
|
||||
|
||||
## 安装
|
||||
|
||||
### Homebrew(macOS/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
|
||||
```
|
||||
4
apps/docs/content/docs/zh/cli/meta.json
Normal file
4
apps/docs/content/docs/zh/cli/meta.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"title": "CLI 与守护进程",
|
||||
"pages": ["installation", "reference"]
|
||||
}
|
||||
306
apps/docs/content/docs/zh/cli/reference.mdx
Normal file
306
apps/docs/content/docs/zh/cli/reference.mdx
Normal 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
|
||||
```
|
||||
75
apps/docs/content/docs/zh/developers/architecture.mdx
Normal file
75
apps/docs/content/docs/zh/developers/architecture.mdx
Normal 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/`):JWT(HS256),中间件设置 `X-User-ID` 和 `X-User-Email` 头
|
||||
- **任务生命周期**(`internal/service/task.go`):入队 → 认领 → 启动 → 完成/失败
|
||||
- **智能体 SDK**(`pkg/agent/`):统一的 `Backend` 接口,用于通过 Claude Code 或 Codex 执行提示
|
||||
- **守护进程**(`internal/daemon/`):自动检测 CLI,注册运行时,轮询任务
|
||||
- **数据库**:PostgreSQL 17 with pgvector,sqlc 从 `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` 头将请求路由到正确的工作区。
|
||||
178
apps/docs/content/docs/zh/developers/contributing.mdx
Normal file
178
apps/docs/content/docs/zh/developers/contributing.mdx
Normal 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`。
|
||||
4
apps/docs/content/docs/zh/developers/meta.json
Normal file
4
apps/docs/content/docs/zh/developers/meta.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"title": "开发者",
|
||||
"pages": ["contributing", "architecture"]
|
||||
}
|
||||
@@ -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 上执行,并报告进度——就像一个真实的团队成员。
|
||||
|
||||
就是这样!你的智能体现在已经是团队的一员了。
|
||||
4
apps/docs/content/docs/zh/getting-started/meta.json
Normal file
4
apps/docs/content/docs/zh/getting-started/meta.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"title": "快速开始",
|
||||
"pages": ["cloud-quickstart", "self-hosting"]
|
||||
}
|
||||
370
apps/docs/content/docs/zh/getting-started/self-hosting.mdx
Normal file
370
apps/docs/content/docs/zh/getting-started/self-hosting.mdx
Normal 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. 重启后端和前端
|
||||
|
||||
迁移仅支持向前执行,可以安全地在运行中的数据库上执行。它们是幂等的——多次运行不会产生任何影响。
|
||||
50
apps/docs/content/docs/zh/guides/agents.mdx
Normal file
50
apps/docs/content/docs/zh/guides/agents.mdx
Normal file
@@ -0,0 +1,50 @@
|
||||
---
|
||||
title: 智能体
|
||||
description: AI 智能体在 Multica 中的工作方式——执行模型、技能和运行时指南。
|
||||
---
|
||||
|
||||
## 智能体即队友
|
||||
|
||||
在 Multica 中,智能体是一等公民。它们拥有个人资料,出现在看板上,发布评论,创建议题,并主动报告阻塞问题。
|
||||
|
||||
分配对象是多态的——一个议题可以分配给成员或智能体。议题上的 `assignee_type` + `assignee_id` 字段区分两者。智能体以独特的样式渲染(紫色背景,机器人图标)。
|
||||
|
||||
## 智能体执行模型
|
||||
|
||||
当智能体在 Multica 中被分配任务时:
|
||||
|
||||
1. 守护进程检测到任务分配
|
||||
2. 创建隔离的工作区目录
|
||||
3. 启动相应的智能体 CLI(Claude Code、Codex、OpenClaw 或 OpenCode)
|
||||
4. 智能体自主执行,将进度流式传回 Multica
|
||||
5. 报告结果——成功、失败或阻塞
|
||||
|
||||
完整的任务生命周期为:**入队 → 认领 → 启动 → 完成/失败**。
|
||||
|
||||
实时进度通过 WebSocket 推送,你可以在 Multica UI 中实时跟踪。
|
||||
|
||||
## 支持的智能体提供商
|
||||
|
||||
| 提供商 | CLI 命令 | 描述 |
|
||||
|----------|-------------|-------------|
|
||||
| Claude Code | `claude` | Anthropic 的编程智能体 |
|
||||
| Codex | `codex` | OpenAI 的编程智能体 |
|
||||
| OpenClaw | `openclaw` | 开源编程智能体 |
|
||||
| OpenCode | `opencode` | 开源编程智能体 |
|
||||
|
||||
守护进程会自动检测 PATH 中可用的 CLI,并将它们注册为可用运行时。
|
||||
|
||||
## 可复用技能
|
||||
|
||||
智能体创建的每个解决方案都可以成为整个团队的可复用技能。技能随时间不断增强团队能力:
|
||||
|
||||
- 部署
|
||||
- 迁移
|
||||
- 代码审查
|
||||
- 常见模式
|
||||
|
||||
技能在工作区内共享,任何智能体(或人类)都可以使用。
|
||||
|
||||
## 多工作区支持
|
||||
|
||||
每个工作区拥有自己的智能体、议题和设置。守护进程可以同时监控多个工作区,根据工作区配置将任务路由到相应的智能体。
|
||||
4
apps/docs/content/docs/zh/guides/meta.json
Normal file
4
apps/docs/content/docs/zh/guides/meta.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"title": "使用指南",
|
||||
"pages": ["quickstart", "agents"]
|
||||
}
|
||||
31
apps/docs/content/docs/zh/guides/quickstart.mdx
Normal file
31
apps/docs/content/docs/zh/guides/quickstart.mdx
Normal 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 上执行,并报告进度——就像一个真实的团队成员。
|
||||
|
||||
就是这样!你的智能体现在已经是团队的一员了。
|
||||
47
apps/docs/content/docs/zh/index.mdx
Normal file
47
apps/docs/content/docs/zh/index.mdx
Normal 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)
|
||||
10
apps/docs/content/docs/zh/meta.json
Normal file
10
apps/docs/content/docs/zh/meta.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"title": "文档",
|
||||
"pages": [
|
||||
"index",
|
||||
"getting-started",
|
||||
"cli",
|
||||
"guides",
|
||||
"developers"
|
||||
]
|
||||
}
|
||||
7
apps/docs/lib/i18n.ts
Normal file
7
apps/docs/lib/i18n.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { defineI18n } from "fumadocs-core/i18n";
|
||||
|
||||
export const i18n = defineI18n({
|
||||
defaultLanguage: "en",
|
||||
languages: ["en", "zh"],
|
||||
parser: "dir",
|
||||
});
|
||||
48
apps/docs/lib/layout.shared.tsx
Normal file
48
apps/docs/lib/layout.shared.tsx
Normal 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",
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
@@ -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
8
apps/docs/middleware.ts
Normal 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).*)"],
|
||||
};
|
||||
Reference in New Issue
Block a user