diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 988c49f5e..7873085bd 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -40,6 +40,8 @@ Closes # - [ ] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [ ] I have updated relevant documentation to reflect my changes +- [ ] If I added a new runtime / coding tool / UI tab, I synced the change to **landing copy** (`apps/web/features/landing/i18n/`), **starter-content** (`packages/views/onboarding/utils/starter-content-content-*.ts`), and **relevant docs** (`apps/docs/content/docs/`) +- [ ] If this PR touches Chinese product copy, I checked it against `apps/docs/content/docs/developers/conventions.zh.mdx` (terminology, mixed-rule for `task` / `issue` / `skill`) - [ ] I have considered and documented any risks above - [ ] I will address all reviewer comments before requesting merge diff --git a/apps/docs/content/docs/daemon-runtimes.mdx b/apps/docs/content/docs/daemon-runtimes.mdx index b60c07f5b..cbf4e3a1d 100644 --- a/apps/docs/content/docs/daemon-runtimes.mdx +++ b/apps/docs/content/docs/daemon-runtimes.mdx @@ -37,7 +37,7 @@ Common commands: Full CLI reference in [CLI commands](/cli). -**The desktop app ships with a daemon.** If you use the [desktop app](/desktop-app), you don't need to run `multica daemon start` manually — it launches the daemon automatically on startup. +**The desktop app ships with a daemon.** If you use the [desktop app](/desktop-app), you don't need to run `multica daemon start` manually — it launches the daemon automatically on startup. See the [Desktop app](/desktop-app) page for which option fits your workflow. ## Why one machine has multiple runtimes diff --git a/apps/docs/content/docs/daemon-runtimes.zh.mdx b/apps/docs/content/docs/daemon-runtimes.zh.mdx index 3de87d2a5..b9c2eaad7 100644 --- a/apps/docs/content/docs/daemon-runtimes.zh.mdx +++ b/apps/docs/content/docs/daemon-runtimes.zh.mdx @@ -37,7 +37,7 @@ multica daemon start 完整 CLI 参考见 [CLI 命令速查](/cli)。 -**桌面应用自带守护进程。**用 [桌面应用](/desktop-app) 就不必手动 `multica daemon start`——它启动时会自动拉起守护进程。 +**桌面应用自带守护进程。**用 [桌面应用](/desktop-app) 就不必手动 `multica daemon start`——它启动时会自动拉起守护进程。哪种方式更适合你的工作流,详见 [桌面应用](/desktop-app) 页面。 ## 为什么一台机器会有多个运行时 diff --git a/apps/docs/content/docs/developers/conventions.mdx b/apps/docs/content/docs/developers/conventions.mdx index 48bb3ace4..99d5d1fb9 100644 --- a/apps/docs/content/docs/developers/conventions.mdx +++ b/apps/docs/content/docs/developers/conventions.mdx @@ -95,17 +95,26 @@ Multica's product nouns split into two categories: This rule is aligned with `apps/docs/content/docs/*.zh.mdx` — the docs are the de facto Chinese voice standard and have been battle-tested across 20+ pages. -### Don't translate — entities (lowercase English) +### Entities — mixed rule (`issue` / `skill` / `task`) -| Term | Render in Chinese | Example | +`issue` / `skill` / `task` are Multica's core entities. They have schema columns, API fields, and product UI labels that are all English. In Chinese text, they follow a **mixed rule** — what to use depends on where the word appears: + +| Context | Render | Example | | --- | --- | --- | -| Issue | `issue` (lowercase) | "把 issue 分配给智能体"、"创建子 issue" | -| Skill | `skill` (lowercase) | "为智能体注入 skill" | -| Task | `task` (lowercase) | "排队中的 task" | +| **UI strings, state names, code references** | lowercase English | "排队中的 task"、"创建子 issue"、"为智能体注入 skill" | +| **Doc titles / section headings** | Title-case English **or** the Chinese term | "Issue 与 project"、"Skills"、"执行任务" | +| **Long-form doc prose, when the entity is the running subject** | Chinese term, with English in parentheses on first mention | "**执行任务**(task)是智能体每一次工作的单位" | +| **API / DB fields** | always `task` / `issue` / `skill` | `task_id`, `issue_status`, `skill_uuid` | -**Why `issue` / `skill` / `task` stay English while `project` / `autopilot` are translated**: +Chinese term reference: -- **`issue` / `task`**: dev teams talk in English. The Chinese candidates ("任务" — too vague, almost synonymous with "工作"; "工单" — IT ticket connotation; "议题" — GitHub-style but doesn't match the product feel) all read worse than `issue`. +- `task` ↔ `执行任务` (or shortened to `任务` once context is clear) +- `issue` has no settled Chinese translation — leave English; titles may capitalize as `Issue` +- `skill` has no settled Chinese translation — leave English; titles may capitalize as `Skills` + +**Why `issue` / `skill` / `task` aren't forced into Chinese the way `project` / `autopilot` are**: + +- **`issue` / `task`**: dev teams talk in English. The Chinese candidates ("任务" — too vague, almost synonymous with "工作"; "工单" — IT ticket connotation; "议题" — GitHub-style but doesn't match the product feel) all read worse than `issue`. **But** in long-form doc prose, repeating lowercase `task` 50× breaks the rhythm — so prose is allowed to use `执行任务`, while UI strings and state names stay lowercase English. - **`skill`**: Multica-specific concept with no established Chinese term. - **`project` → "项目"**: settled mainstream Chinese word. Feishu / Tower / Teambition / PingCode / GitHub Projects — every Chinese product translates it. No product keeps `project` in Chinese context. - **`autopilot` → "自动化"**: in Chinese, "autopilot" associates with Tesla's "自动驾驶" and doesn't match what the feature does (run tasks on a schedule). Notion and Feishu both use "自动化"; that's the industry consensus. diff --git a/apps/docs/content/docs/developers/conventions.zh.mdx b/apps/docs/content/docs/developers/conventions.zh.mdx index 48444a04f..4ab9ab711 100644 --- a/apps/docs/content/docs/developers/conventions.zh.mdx +++ b/apps/docs/content/docs/developers/conventions.zh.mdx @@ -95,20 +95,29 @@ Multica 的产品名词分两类: 这套规则与 `apps/docs/content/docs/*.zh.mdx` 完全对齐 —— docs 是已经实战 20+ 篇的 CN voice 标准。 -### 不翻 —— 实体(小写英文) +### 实体词的混合规则(`issue` / `skill` / `task`) -| 词 | 中文中的写法 | 例 | +`issue` / `skill` / `task` 是 Multica 的核心实体。schema 字段、API 字段、产品 UI 标签都用英文。中文里采用**混合规则** —— 词出现在哪里决定怎么写: + +| 场景 | 写法 | 例 | | --- | --- | --- | -| Issue | `issue`(小写) | "把 issue 分配给智能体"、"创建子 issue" | -| Skill | `skill`(小写) | "为智能体注入 skill" | -| Task | `task`(小写) | "排队中的 task" | +| **UI 短句 / 状态名 / 代码上下文** | 小写英文 | "排队中的 task"、"创建子 issue"、"为智能体注入 skill" | +| **doc 标题 / 章节标题** | 首字母大写英文,**或**对应中文术语 | "Issue 与 project"、"Skills"、"执行任务" | +| **doc 正文长篇讨论中作为主语** | 中文术语,首次出现配括号英文 | "**执行任务**(task)是智能体每一次工作的单位" | +| **API / DB 字段** | 永远 `task` / `issue` / `skill` | `task_id`、`issue_status`、`skill_uuid` | -**为什么 `issue` / `skill` / `task` 不翻而 `project` / `autopilot` 翻**: +中文术语对照: -- **`issue` / `task`**:dev 团队习惯说英文,"任务"在中文里和"工作"几乎同义太空泛,"工单"是 IT 工单语义,"议题"是 GitHub 风格但用户场景不匹配。三个候选都不如 `issue` 准确。 +- `task` ↔ `执行任务`(上下文清楚后可简写为「任务」) +- `issue` 没有公认中文译法 —— 保留英文;标题可大写为 `Issue` +- `skill` 没有公认中文译法 —— 保留英文;标题可大写为 `Skills` + +**为什么 `issue` / `skill` / `task` 不强制译,而 `project` / `autopilot` 必译**: + +- **`issue` / `task`**:dev 团队习惯说英文,"任务"在中文里和"工作"几乎同义太空泛,"工单"是 IT 工单语义,"议题"是 GitHub 风格但用户场景不匹配 —— 三个候选都不如 `issue` 准确。**但**在长篇 doc 正文里,重复 50 次 `task` 节奏不顺,所以正文允许用 `执行任务`,UI 短句、状态名仍保持小写英文。 - **`skill`**:Multica 特有概念,没有公认中文译法。 -- **`project` 翻成"项目"**:这是中文里早就稳定的日常词。飞书 / Tower / Teambition / PingCode / GitHub Projects 中文版 0 例外都翻译成"项目",没有产品保留 `project`。 -- **`autopilot` 翻成"自动化"**:autopilot 在中文里联想到特斯拉的"自动驾驶",跟产品功能(按周期跑 task)对应不上。Notion / 飞书都用"自动化",是行业共识。 +- **`project` 翻成「项目」**:中文里早就稳定的日常词。飞书 / Tower / Teambition / PingCode / GitHub Projects 中文版 0 例外都翻译成「项目」,没有产品保留 `project`。 +- **`autopilot` 翻成「自动化」**:autopilot 在中文里联想到特斯拉的「自动驾驶」,跟产品功能(按周期跑 task)对应不上。Notion / 飞书都用「自动化」,是行业共识。 ### 完整翻译 —— 概念词 diff --git a/apps/docs/content/docs/meta.json b/apps/docs/content/docs/meta.json index 1cd140483..7a05fd19d 100644 --- a/apps/docs/content/docs/meta.json +++ b/apps/docs/content/docs/meta.json @@ -9,6 +9,7 @@ "workspaces", "members-roles", "issues", + "projects", "comments", "project-resources", "---Agents---", diff --git a/apps/docs/content/docs/meta.zh.json b/apps/docs/content/docs/meta.zh.json index 32f5f9a8d..ae54761a1 100644 --- a/apps/docs/content/docs/meta.zh.json +++ b/apps/docs/content/docs/meta.zh.json @@ -9,6 +9,7 @@ "workspaces", "members-roles", "issues", + "projects", "comments", "---智能体---", "agents", diff --git a/apps/docs/content/docs/projects.mdx b/apps/docs/content/docs/projects.mdx new file mode 100644 index 000000000..fd5813f67 --- /dev/null +++ b/apps/docs/content/docs/projects.mdx @@ -0,0 +1,49 @@ +--- +title: Projects +description: Group related issues and track them as one unit — with priority, status, progress, and an owner. +--- + +import { Callout } from "fumadocs-ui/components/callout"; + +A **project** in Multica is a container for related [issues](/issues). Use it when a body of work is bigger than one issue but smaller than a full workspace — a launch, a migration, a feature with multiple parts, an investigation that branches into several threads. + +Each project has a name, an icon, a description, a **lead** (a member or an [agent](/agents)), a **status** (`planned` / `in_progress` / `paused` / `completed` / `cancelled`), a **priority** (`urgent` / `high` / `medium` / `low` / `none`), and a **progress** percentage that's auto-derived from the status of its linked issues. + +## How projects relate to issues + +Projects and issues are independent objects with a many-to-one relationship: an issue can belong to **at most one** project; a project holds **any number of** issues. Linking and unlinking is reversible at any time — drag in the board view, or use the project picker on the issue's right-side properties panel. + +The progress bar on a project is computed from its linked issues — the more issues hit `done`, the further it fills. Issues that are `cancelled` are excluded from the count; issues in `backlog` count toward the denominator but not the numerator. + +## Pinning to the sidebar + +Click the pin icon in a project's top-right corner to add it to your sidebar's pinned list. Pinned projects stay one click away no matter where you are in the workspace; everyone on the team can pin independently — pins are personal. + +The sidebar **Workspace → Projects** link always shows every project in the workspace; pinning is a personal shortcut on top of that. + +## Attaching resources + +Each project has a **Resources** section where you attach GitHub repositories. Once attached, any [agent](/agents) assigned to issues in this project can read and write to those repos when executing tasks — Multica passes the repo URLs as context to the [daemon](/daemon-runtimes). + +Resources are per-project; if multiple projects share a repo, attach it to each one. + +## Deleting a project + +Deleting a project **does not delete its issues**. The linked issues are simply unlinked and revert to the workspace's flat issue list. This is intentional — work that was scoped to a project is rarely throwaway, even when the framing of the project changes. + + +If you want to delete the work too, archive or delete the issues first, then delete the project. + + +## Project lead + +The lead is the person — or agent — accountable for the project. It's a soft signal, not an access control: any workspace member can edit a project regardless of who's lead. A project's lead can be: + +- A workspace member (human teammate) +- An [agent](/agents) — useful when the project's work is mostly delegated to an agent (e.g., "Weekly bug triage" led by a triage agent) + +## Next + +- [Issues](/issues) — the unit of work that lives inside projects +- [Agents as project lead](/agents) — when an agent is the right owner +- [How Multica works](/how-multica-works) — the broader picture diff --git a/apps/docs/content/docs/projects.zh.mdx b/apps/docs/content/docs/projects.zh.mdx new file mode 100644 index 000000000..68ce1aac6 --- /dev/null +++ b/apps/docs/content/docs/projects.zh.mdx @@ -0,0 +1,49 @@ +--- +title: 项目 +description: 把相关的 issue 归为一组当成一个单元来跟进 —— 有优先级、状态、进度和负责人。 +--- + +import { Callout } from "fumadocs-ui/components/callout"; + +Multica 里的**项目**(project)是相关 [issue](/issues) 的容器。当一摊工作比单个 issue 大、又比整个工作区小的时候用它 —— 一次发布、一次迁移、一个分多块做的功能、一个会拆出多个线索的调研。 + +每个项目有名字、图标、描述、**负责人**(lead,可以是成员,也可以是 [智能体](/agents))、**状态**(`planned` / `in_progress` / `paused` / `completed` / `cancelled`)、**优先级**(`urgent` / `high` / `medium` / `low` / `none`),以及一个根据关联 issue 状态自动算出来的**进度**百分比。 + +## 项目和 issue 的关系 + +项目和 issue 是独立对象,多对一关系:一个 issue **最多属于一个**项目;一个项目可以容纳**任意多个** issue。关联和解除关联随时可逆 —— 在看板视图里拖动,或者在 issue 右侧 properties 面板用项目选择器。 + +项目的进度条是按关联 issue 状态自动算出来的 —— 越多 issue 到 `done`,进度条越满。`cancelled` 的 issue 不计入分母;`backlog` 的 issue 计入分母但不计入分子。 + +## pin 到侧边栏 + +点项目右上角的 pin 图标,可以把这个项目加到侧边栏的固定区。pin 过的项目无论你在工作区哪里都一键可达;每个人独立 pin —— pin 是个人偏好。 + +侧边栏 **Workspace → Projects** 链接始终展示工作区里所有项目;pin 只是在这之上的个人快捷方式。 + +## 关联 resources + +每个项目有一个 **Resources** 区,可以挂 GitHub 仓库。挂上之后,被分配到这个项目里 issue 的 [智能体](/agents) 在执行 task 时可以读写这些仓库 —— Multica 会把仓库 URL 作为上下文传给 [守护进程](/daemon-runtimes)。 + +Resources 是项目级别的;多个项目要共享同一个仓库,要分别挂上。 + +## 删除项目 + +删除项目**不会**删除它的 issue。关联的 issue 只是解除关联,回到工作区的扁平 issue 列表。这是刻意的 —— 即使项目本身的框架变了,里面的工作通常也不会是一次性的。 + + +如果你确实想把工作也删掉,先归档或删除 issue,再删除项目。 + + +## 项目负责人 + +负责人是为这个项目负总责的人 —— 或者智能体。这是一个软信号,不是权限控制:工作区任何成员都可以编辑项目,不管谁是负责人。项目负责人可以是: + +- 工作区里的成员(人) +- [智能体](/agents) —— 当项目里的工作大部分要交给智能体时合适(例如"每周 bug 巡检"由一个巡检智能体担任 lead) + +## 下一步 + +- [Issues](/issues) —— 项目里装的工作单元 +- [智能体担任项目负责人](/agents) —— 什么时候由智能体当 lead 合适 +- [Multica 怎么运转](/how-multica-works) —— 整体视图 diff --git a/apps/docs/content/docs/tasks.mdx b/apps/docs/content/docs/tasks.mdx index 5952e80f8..bf3bab0a8 100644 --- a/apps/docs/content/docs/tasks.mdx +++ b/apps/docs/content/docs/tasks.mdx @@ -63,6 +63,8 @@ Automatic retry also has two extra conditions: **Autopilot tasks don't retry automatically** by design. An Autopilot has its own firing cadence (e.g. daily); automatic retries on failure would overlap with the next scheduled run. If you need an immediate re-run after failure, use a manual rerun (next section). + +**How you'll know an Autopilot task failed**: a notification lands in your [Inbox](/inbox), and the associated issue's status reverts from `in_progress` back to `todo`. The [Autopilots](/autopilots) page also shows the latest run result per autopilot. ## Manual rerun vs. automatic retry diff --git a/apps/docs/content/docs/tasks.zh.mdx b/apps/docs/content/docs/tasks.zh.mdx index f682ef5e0..6838e80cf 100644 --- a/apps/docs/content/docs/tasks.zh.mdx +++ b/apps/docs/content/docs/tasks.zh.mdx @@ -63,6 +63,8 @@ Multica 服务器每 30 秒扫描一次,有两种超时会触发失败: **Autopilots 任务不自动重试**是刻意设计。Autopilot 有自己的触发周期(例如每天一次);如果失败又自动重试,会和下一个周期的任务重叠。需要失败后立即重跑,用手动重跑(下一节)。 + +**怎么知道 Autopilot 失败了**:失败的 Autopilot 任务会在你的 [收件箱](/inbox) 里出现一条通知,关联的 issue 状态也会从 `in_progress` 退回 `todo`。直接打开 [Autopilots](/autopilots) 页面也能看到每条 autopilot 的最近运行结果。 ## 手动重跑和自动重试的区别 diff --git a/apps/web/features/landing/i18n/en.ts b/apps/web/features/landing/i18n/en.ts index d40f3a5e4..d8e8063ec 100644 --- a/apps/web/features/landing/i18n/en.ts +++ b/apps/web/features/landing/i18n/en.ts @@ -94,7 +94,7 @@ export function createEnDict(allowSignup: boolean): LandingDict { label: "RUNTIMES", title: "One dashboard for all your compute", description: - "Local daemons and cloud runtimes, managed from a single panel. Real-time monitoring of online/offline status, usage charts, and activity heatmaps. Auto-detects local CLIs \u2014 plug in and go.", + "Local daemons and cloud runtimes, managed from a single panel. Real-time monitoring of online/offline status, usage charts, and activity heatmaps. Auto-detects 11 supported coding tools on your machine.", cards: [ { title: "Unified runtime panel", @@ -107,9 +107,9 @@ export function createEnDict(allowSignup: boolean): LandingDict { "Online/offline status, usage charts, and activity heatmaps. Know exactly what your compute is doing at any moment.", }, { - title: "Auto-detection & plug-and-play", + title: "Auto-detection on first run", description: - "Multica detects available CLIs like Claude Code, Codex, OpenClaw, and OpenCode automatically. Connect a machine, and it\u2019s ready to work.", + "Multica scans for 11 supported coding tools \u2014 Claude Code, Codex, Cursor, Copilot, Gemini, Hermes, Kimi, Kiro CLI, OpenCode, OpenClaw, and Pi \u2014 and registers a runtime for each one it finds.", }, ], }, @@ -129,7 +129,7 @@ export function createEnDict(allowSignup: boolean): LandingDict { { title: "Install the CLI & connect your machine", description: - "Run multica setup to configure, authenticate, and start the daemon. It auto-detects Claude Code, Codex, OpenClaw, and OpenCode on your machine \u2014 plug in and go.", + "Run multica setup \u2014 it walks you through OAuth, starts the daemon, and scans for the 11 supported coding tools (Claude Code, Codex, Cursor, Copilot, Gemini, Hermes, Kimi, Kiro CLI, OpenCode, OpenClaw, Pi). Whichever ones you already have installed get registered as runtimes automatically.", }, { title: "Create your first agent", @@ -185,7 +185,7 @@ export function createEnDict(allowSignup: boolean): LandingDict { { question: "What coding agents does Multica support?", answer: - "Multica currently supports Claude Code, Codex, OpenClaw, and OpenCode out of the box. The daemon auto-detects whichever CLIs you have installed. Since it\u2019s open source, you can also add your own backends.", + "Multica supports 11 coding tools out of the box: Claude Code, Codex, Cursor, Copilot, Gemini, Hermes, Kimi, Kiro CLI, OpenCode, OpenClaw, and Pi. The daemon auto-detects whichever CLIs you already have installed and registers a runtime for each one. Since it's open source, you can also add your own backends.", }, { question: "Do I need to self-host, or is there a cloud version?", diff --git a/apps/web/features/landing/i18n/zh.ts b/apps/web/features/landing/i18n/zh.ts index b80871703..0cf597359 100644 --- a/apps/web/features/landing/i18n/zh.ts +++ b/apps/web/features/landing/i18n/zh.ts @@ -13,42 +13,42 @@ export function createZhDict(allowSignup: boolean): LandingDict { headlineLine1: "\u4f60\u7684\u4e0b\u4e00\u6279\u5458\u5de5", headlineLine2: "\u4e0d\u662f\u4eba\u7c7b\u3002", subheading: - "Multica \u662f\u4e00\u4e2a\u5f00\u6e90\u5e73\u53f0\uff0c\u5c06\u7f16\u7801 Agent \u53d8\u6210\u771f\u6b63\u7684\u961f\u53cb\u3002\u5206\u914d\u4efb\u52a1\u3001\u8ddf\u8e2a\u8fdb\u5ea6\u3001\u79ef\u7d2f\u6280\u80fd\u2014\u2014\u5728\u4e00\u4e2a\u5730\u65b9\u7ba1\u7406\u4f60\u7684\u4eba\u7c7b + Agent \u56e2\u961f\u3002", + "Multica \u662f\u4e00\u4e2a\u5f00\u6e90\u5e73\u53f0\uff0c\u5c06\u7f16\u7801 智能体 \u53d8\u6210\u771f\u6b63\u7684\u961f\u53cb\u3002\u5206\u914d\u4efb\u52a1\u3001\u8ddf\u8e2a\u8fdb\u5ea6\u3001\u79ef\u7d2f\u6280\u80fd\u2014\u2014\u5728\u4e00\u4e2a\u5730\u65b9\u7ba1\u7406\u4f60\u7684\u4eba\u7c7b + 智能体 \u56e2\u961f\u3002", cta: "免费开始", downloadDesktop: "下载桌面端", worksWith: "支持", - imageAlt: "Multica \u770b\u677f\u89c6\u56fe\u2014\u2014\u4eba\u7c7b\u548c Agent \u534f\u540c\u7ba1\u7406\u4efb\u52a1", + imageAlt: "Multica \u770b\u677f\u89c6\u56fe\u2014\u2014\u4eba\u7c7b\u548c 智能体 \u534f\u540c\u7ba1\u7406\u4efb\u52a1", }, features: { teammates: { label: "\u56e2\u961f\u534f\u4f5c", - title: "\u50cf\u5206\u914d\u7ed9\u540c\u4e8b\u4e00\u6837\u5206\u914d\u7ed9 Agent", + title: "\u50cf\u5206\u914d\u7ed9\u540c\u4e8b\u4e00\u6837\u5206\u914d\u7ed9 智能体", description: - "Agent \u4e0d\u662f\u88ab\u52a8\u5de5\u5177\u2014\u2014\u5b83\u4eec\u662f\u4e3b\u52a8\u53c2\u4e0e\u8005\u3002\u5b83\u4eec\u62e5\u6709\u4e2a\u4eba\u8d44\u6599\u3001\u62a5\u544a\u72b6\u6001\u3001\u521b\u5efa Issue\u3001\u53d1\u8868\u8bc4\u8bba\u3001\u66f4\u65b0\u72b6\u6001\u3002\u4f60\u7684\u6d3b\u52a8\u6d41\u5c55\u793a\u4eba\u7c7b\u548c Agent \u5e76\u80a9\u5de5\u4f5c\u3002", + "智能体 \u4e0d\u662f\u88ab\u52a8\u5de5\u5177\u2014\u2014\u5b83\u4eec\u662f\u4e3b\u52a8\u53c2\u4e0e\u8005\u3002\u5b83\u4eec\u62e5\u6709\u4e2a\u4eba\u8d44\u6599\u3001\u62a5\u544a\u72b6\u6001\u3001\u521b\u5efa Issue\u3001\u53d1\u8868\u8bc4\u8bba\u3001\u66f4\u65b0\u72b6\u6001\u3002\u4f60\u7684\u6d3b\u52a8\u6d41\u5c55\u793a\u4eba\u7c7b\u548c 智能体 \u5e76\u80a9\u5de5\u4f5c\u3002", cards: [ { - title: "Agent \u51fa\u73b0\u5728\u6307\u6d3e\u4eba\u9009\u62e9\u5668\u4e2d", + title: "智能体 \u51fa\u73b0\u5728\u6307\u6d3e\u4eba\u9009\u62e9\u5668\u4e2d", description: - "\u4eba\u7c7b\u548c Agent \u51fa\u73b0\u5728\u540c\u4e00\u4e2a\u4e0b\u62c9\u83dc\u5355\u91cc\u3002\u628a\u4efb\u52a1\u5206\u914d\u7ed9 Agent \u548c\u5206\u914d\u7ed9\u540c\u4e8b\u6ca1\u6709\u4efb\u4f55\u533a\u522b\u3002", + "\u4eba\u7c7b\u548c 智能体 \u51fa\u73b0\u5728\u540c\u4e00\u4e2a\u4e0b\u62c9\u83dc\u5355\u91cc\u3002\u628a\u4efb\u52a1\u5206\u914d\u7ed9 智能体 \u548c\u5206\u914d\u7ed9\u540c\u4e8b\u6ca1\u6709\u4efb\u4f55\u533a\u522b\u3002", }, { title: "\u81ea\u4e3b\u53c2\u4e0e", description: - "Agent \u4e3b\u52a8\u521b\u5efa Issue\u3001\u53d1\u8868\u8bc4\u8bba\u3001\u66f4\u65b0\u72b6\u6001\u2014\u2014\u800c\u4e0d\u662f\u53ea\u5728\u88ab\u63d0\u793a\u65f6\u624d\u884c\u52a8\u3002", + "智能体 \u4e3b\u52a8\u521b\u5efa Issue\u3001\u53d1\u8868\u8bc4\u8bba\u3001\u66f4\u65b0\u72b6\u6001\u2014\u2014\u800c\u4e0d\u662f\u53ea\u5728\u88ab\u63d0\u793a\u65f6\u624d\u884c\u52a8\u3002", }, { title: "\u7edf\u4e00\u7684\u6d3b\u52a8\u65f6\u95f4\u7ebf", description: - "\u6574\u4e2a\u56e2\u961f\u5171\u7528\u4e00\u4e2a\u6d3b\u52a8\u6d41\u3002\u4eba\u7c7b\u548c Agent \u7684\u64cd\u4f5c\u4ea4\u66ff\u5c55\u793a\uff0c\u4f60\u59cb\u7ec8\u77e5\u9053\u53d1\u751f\u4e86\u4ec0\u4e48\u3001\u662f\u8c01\u505a\u7684\u3002", + "\u6574\u4e2a\u56e2\u961f\u5171\u7528\u4e00\u4e2a\u6d3b\u52a8\u6d41\u3002\u4eba\u7c7b\u548c 智能体 \u7684\u64cd\u4f5c\u4ea4\u66ff\u5c55\u793a\uff0c\u4f60\u59cb\u7ec8\u77e5\u9053\u53d1\u751f\u4e86\u4ec0\u4e48\u3001\u662f\u8c01\u505a\u7684\u3002", }, ], }, autonomous: { label: "\u81ea\u4e3b\u6267\u884c", - title: "\u8bbe\u7f6e\u540e\u65e0\u9700\u7ba1\u7406\u2014\u2014Agent \u5728\u4f60\u7761\u89c9\u65f6\u5de5\u4f5c", + title: "\u8bbe\u7f6e\u540e\u65e0\u9700\u7ba1\u7406\u2014\u2014智能体 \u5728\u4f60\u7761\u89c9\u65f6\u5de5\u4f5c", description: - "\u4e0d\u53ea\u662f\u63d0\u793a-\u54cd\u5e94\u3002\u5b8c\u6574\u7684\u4efb\u52a1\u751f\u547d\u5468\u671f\u7ba1\u7406\uff1a\u5165\u961f\u3001\u9886\u53d6\u3001\u542f\u52a8\u3001\u5b8c\u6210\u6216\u5931\u8d25\u3002Agent \u4e3b\u52a8\u62a5\u544a\u963b\u585e\uff0c\u4f60\u901a\u8fc7 WebSocket \u83b7\u53d6\u5b9e\u65f6\u8fdb\u5ea6\u3002", + "\u4e0d\u53ea\u662f\u63d0\u793a-\u54cd\u5e94\u3002\u5b8c\u6574\u7684\u4efb\u52a1\u751f\u547d\u5468\u671f\u7ba1\u7406\uff1a\u5165\u961f\u3001\u9886\u53d6\u3001\u542f\u52a8\u3001\u5b8c\u6210\u6216\u5931\u8d25\u3002智能体 \u4e3b\u52a8\u62a5\u544a\u963b\u585e\uff0c\u4f60\u901a\u8fc7 WebSocket \u83b7\u53d6\u5b9e\u65f6\u8fdb\u5ea6\u3002", cards: [ { title: "\u5b8c\u6574\u7684\u4efb\u52a1\u751f\u547d\u5468\u671f", @@ -58,12 +58,12 @@ export function createZhDict(allowSignup: boolean): LandingDict { { title: "\u4e3b\u52a8\u62a5\u544a\u963b\u585e", description: - "\u5f53 Agent \u9047\u5230\u56f0\u96be\u65f6\uff0c\u4f1a\u7acb\u5373\u53d1\u51fa\u8b66\u62a5\u3002\u4e0d\u7528\u7b49\u51e0\u4e2a\u5c0f\u65f6\u540e\u624d\u53d1\u73b0\u4ec0\u4e48\u90fd\u6ca1\u53d1\u751f\u3002", + "\u5f53 智能体 \u9047\u5230\u56f0\u96be\u65f6\uff0c\u4f1a\u7acb\u5373\u53d1\u51fa\u8b66\u62a5\u3002\u4e0d\u7528\u7b49\u51e0\u4e2a\u5c0f\u65f6\u540e\u624d\u53d1\u73b0\u4ec0\u4e48\u90fd\u6ca1\u53d1\u751f\u3002", }, { title: "\u5b9e\u65f6\u8fdb\u5ea6\u63a8\u9001", description: - "\u57fa\u4e8e WebSocket \u7684\u5b9e\u65f6\u66f4\u65b0\u3002\u5b9e\u65f6\u89c2\u770b Agent \u5de5\u4f5c\uff0c\u6216\u968f\u65f6\u67e5\u770b\u2014\u2014\u65f6\u95f4\u7ebf\u59cb\u7ec8\u662f\u6700\u65b0\u7684\u3002", + "\u57fa\u4e8e WebSocket \u7684\u5b9e\u65f6\u66f4\u65b0\u3002\u5b9e\u65f6\u89c2\u770b 智能体 \u5de5\u4f5c\uff0c\u6216\u968f\u65f6\u67e5\u770b\u2014\u2014\u65f6\u95f4\u7ebf\u59cb\u7ec8\u662f\u6700\u65b0\u7684\u3002", }, ], }, @@ -71,22 +71,22 @@ export function createZhDict(allowSignup: boolean): LandingDict { label: "\u6280\u80fd\u5e93", title: "\u6bcf\u4e2a\u89e3\u51b3\u65b9\u6848\u90fd\u6210\u4e3a\u5168\u56e2\u961f\u53ef\u590d\u7528\u7684\u6280\u80fd", description: - "\u6280\u80fd\u662f\u53ef\u590d\u7528\u7684\u80fd\u529b\u5b9a\u4e49\u2014\u2014\u4ee3\u7801\u3001\u914d\u7f6e\u548c\u4e0a\u4e0b\u6587\u6253\u5305\u5728\u4e00\u8d77\u3002\u53ea\u9700\u7f16\u5199\u4e00\u6b21\uff0c\u56e2\u961f\u4e2d\u6bcf\u4e2a Agent \u90fd\u80fd\u4f7f\u7528\u3002\u4f60\u7684\u6280\u80fd\u5e93\u968f\u65f6\u95f4\u4e0d\u65ad\u79ef\u7d2f\u3002", + "\u6280\u80fd\u662f\u53ef\u590d\u7528\u7684\u80fd\u529b\u5b9a\u4e49\u2014\u2014\u4ee3\u7801\u3001\u914d\u7f6e\u548c\u4e0a\u4e0b\u6587\u6253\u5305\u5728\u4e00\u8d77\u3002\u53ea\u9700\u7f16\u5199\u4e00\u6b21\uff0c\u56e2\u961f\u4e2d\u6bcf\u4e2a 智能体 \u90fd\u80fd\u4f7f\u7528\u3002\u4f60\u7684\u6280\u80fd\u5e93\u968f\u65f6\u95f4\u4e0d\u65ad\u79ef\u7d2f\u3002", cards: [ { title: "\u53ef\u590d\u7528\u7684\u6280\u80fd\u5b9a\u4e49", description: - "\u5c06\u77e5\u8bc6\u5c01\u88c5\u6210\u4efb\u4f55 Agent \u90fd\u80fd\u6267\u884c\u7684\u6280\u80fd\u3002\u90e8\u7f72\u5230\u6d4b\u8bd5\u73af\u5883\u3001\u7f16\u5199\u8fc1\u79fb\u3001\u5ba1\u67e5 PR\u2014\u2014\u5168\u90e8\u4ee3\u7801\u5316\u3002", + "\u5c06\u77e5\u8bc6\u5c01\u88c5\u6210\u4efb\u4f55 智能体 \u90fd\u80fd\u6267\u884c\u7684\u6280\u80fd\u3002\u90e8\u7f72\u5230\u6d4b\u8bd5\u73af\u5883\u3001\u7f16\u5199\u8fc1\u79fb\u3001\u5ba1\u67e5 PR\u2014\u2014\u5168\u90e8\u4ee3\u7801\u5316\u3002", }, { title: "\u5168\u56e2\u961f\u5171\u4eab", description: - "\u4e00\u4e2a\u4eba\u7684\u6280\u80fd\u5c31\u662f\u6bcf\u4e2a Agent \u7684\u6280\u80fd\u3002\u7f16\u5199\u4e00\u6b21\uff0c\u5168\u56e2\u961f\u53d7\u76ca\u3002", + "\u4e00\u4e2a\u4eba\u7684\u6280\u80fd\u5c31\u662f\u6bcf\u4e2a 智能体 \u7684\u6280\u80fd\u3002\u7f16\u5199\u4e00\u6b21\uff0c\u5168\u56e2\u961f\u53d7\u76ca\u3002", }, { title: "\u590d\u5408\u589e\u957f", description: - "\u7b2c 1 \u5929\uff1a\u4f60\u6559 Agent \u90e8\u7f72\u3002\u7b2c 30 \u5929\uff1a\u6bcf\u4e2a Agent \u90fd\u80fd\u90e8\u7f72\u3001\u5199\u6d4b\u8bd5\u3001\u505a\u4ee3\u7801\u5ba1\u67e5\u3002\u56e2\u961f\u80fd\u529b\u6307\u6570\u7ea7\u589e\u957f\u3002", + "\u7b2c 1 \u5929\uff1a\u4f60\u6559 智能体 \u90e8\u7f72\u3002\u7b2c 30 \u5929\uff1a\u6bcf\u4e2a 智能体 \u90fd\u80fd\u90e8\u7f72\u3001\u5199\u6d4b\u8bd5\u3001\u505a\u4ee3\u7801\u5ba1\u67e5\u3002\u56e2\u961f\u80fd\u529b\u6307\u6570\u7ea7\u589e\u957f\u3002", }, ], }, @@ -94,7 +94,7 @@ export function createZhDict(allowSignup: boolean): LandingDict { label: "\u8fd0\u884c\u65f6", title: "\u4e00\u4e2a\u63a7\u5236\u53f0\u7ba1\u7406\u6240\u6709\u7b97\u529b", description: - "\u672c\u5730\u5b88\u62a4\u8fdb\u7a0b\u548c\u4e91\u7aef\u8fd0\u884c\u65f6\uff0c\u5728\u540c\u4e00\u4e2a\u9762\u677f\u4e2d\u7ba1\u7406\u3002\u5b9e\u65f6\u76d1\u63a7\u5728\u7ebf/\u79bb\u7ebf\u72b6\u6001\u3001\u4f7f\u7528\u91cf\u56fe\u8868\u548c\u6d3b\u52a8\u70ed\u529b\u56fe\u3002\u81ea\u52a8\u68c0\u6d4b\u672c\u5730 CLI\u2014\u2014\u63d2\u4e0a\u5c31\u7528\u3002", + "\u672c\u5730\u5b88\u62a4\u8fdb\u7a0b\u548c\u4e91\u7aef\u8fd0\u884c\u65f6\uff0c\u5728\u540c\u4e00\u4e2a\u9762\u677f\u4e2d\u7ba1\u7406\u3002\u5b9e\u65f6\u76d1\u63a7\u5728\u7ebf/\u79bb\u7ebf\u72b6\u6001\u3001\u4f7f\u7528\u91cf\u56fe\u8868\u548c\u6d3b\u52a8\u70ed\u529b\u56fe\u3002\u81ea\u52a8\u68c0\u6d4b\u672c\u673a\u5df2\u5b89\u88c5\u7684 11 \u6b3e\u652f\u6301\u7684 AI \u7f16\u7a0b\u5de5\u5177\u3002", cards: [ { title: "\u7edf\u4e00\u8fd0\u884c\u65f6\u9762\u677f", @@ -107,9 +107,9 @@ export function createZhDict(allowSignup: boolean): LandingDict { "\u5728\u7ebf/\u79bb\u7ebf\u72b6\u6001\u3001\u4f7f\u7528\u91cf\u56fe\u8868\u548c\u6d3b\u52a8\u70ed\u529b\u56fe\u3002\u968f\u65f6\u4e86\u89e3\u4f60\u7684\u7b97\u529b\u5728\u505a\u4ec0\u4e48\u3002", }, { - title: "\u81ea\u52a8\u68c0\u6d4b\u4e0e\u5373\u63d2\u5373\u7528", + title: "\u9996\u6b21\u542f\u52a8\u81ea\u52a8\u6ce8\u518c", description: - "Multica \u81ea\u52a8\u68c0\u6d4b Claude Code\u3001Codex\u3001OpenClaw \u548c OpenCode \u7b49\u53ef\u7528 CLI\u3002\u8fde\u63a5\u4e00\u53f0\u673a\u5668\uff0c\u5373\u53ef\u5f00\u59cb\u5de5\u4f5c\u3002", + "Multica \u626b\u63cf\u672c\u673a\u7684 11 \u6b3e\u652f\u6301\u7684 AI \u7f16\u7a0b\u5de5\u5177\u2014\u2014Claude Code\u3001Codex\u3001Cursor\u3001Copilot\u3001Gemini\u3001Hermes\u3001Kimi\u3001Kiro CLI\u3001OpenCode\u3001OpenClaw\u3001Pi\u2014\u2014\u5e76\u4e3a\u6bcf\u6b3e\u5df2\u5b89\u88c5\u7684\u5de5\u5177\u6ce8\u518c\u4e00\u4e2a\u8fd0\u884c\u65f6\u3002", }, ], }, @@ -129,17 +129,17 @@ export function createZhDict(allowSignup: boolean): LandingDict { { title: "\u5b89\u88c5 CLI \u5e76\u8fde\u63a5\u4f60\u7684\u673a\u5668", description: - "运行 multica setup 一键完成配置、认证和启动。守护进程自动检测你机器上的 Claude Code、Codex、OpenClaw 和 OpenCode——插上就用。", + "运行 multica setup——它会引导你完成 OAuth 登录、启动守护进程、并扫描 11 款支持的 AI 编程工具(Claude Code、Codex、Cursor、Copilot、Gemini、Hermes、Kimi、Kiro CLI、OpenCode、OpenClaw、Pi)。本机已安装的工具会被自动注册成运行时。", }, { - title: "\u521b\u5efa\u4f60\u7684\u7b2c\u4e00\u4e2a Agent", + title: "\u521b\u5efa\u4f60\u7684\u7b2c\u4e00\u4e2a 智能体", description: "\u7ed9\u5b83\u8d77\u4e2a\u540d\u5b57\uff0c\u5199\u597d\u6307\u4ee4\uff0c\u9644\u52a0\u6280\u80fd\uff0c\u8bbe\u7f6e\u89e6\u53d1\u5668\u3002\u9009\u62e9\u5b83\u4f55\u65f6\u6fc0\u6d3b\uff1a\u88ab\u6307\u6d3e\u65f6\u3001\u6709\u8bc4\u8bba\u65f6\u3001\u88ab @\u63d0\u53ca\u65f6\u3002", }, { title: "\u6307\u6d3e\u4e00\u4e2a Issue \u5e76\u89c2\u5bdf\u5b83\u5de5\u4f5c", description: - "\u4ece\u6307\u6d3e\u4eba\u4e0b\u62c9\u83dc\u5355\u4e2d\u9009\u62e9\u4f60\u7684 Agent\u2014\u2014\u5c31\u50cf\u6307\u6d3e\u7ed9\u540c\u4e8b\u4e00\u6837\u3002\u4efb\u52a1\u81ea\u52a8\u5165\u961f\u3001\u9886\u53d6\u3001\u6267\u884c\u3002\u5b9e\u65f6\u89c2\u770b\u8fdb\u5ea6\u3002", + "\u4ece\u6307\u6d3e\u4eba\u4e0b\u62c9\u83dc\u5355\u4e2d\u9009\u62e9\u4f60\u7684 智能体\u2014\u2014\u5c31\u50cf\u6307\u6d3e\u7ed9\u540c\u4e8b\u4e00\u6837\u3002\u4efb\u52a1\u81ea\u52a8\u5165\u961f\u3001\u9886\u53d6\u3001\u6267\u884c\u3002\u5b9e\u65f6\u89c2\u770b\u8fdb\u5ea6\u3002", }, ], cta: "\u5f00\u59cb\u4f7f\u7528", @@ -152,7 +152,7 @@ export function createZhDict(allowSignup: boolean): LandingDict { headlineLine1: "\u5f00\u6e90", headlineLine2: "\u4e3a\u6240\u6709\u4eba\u3002", description: - "Multica \u5b8c\u5168\u5f00\u6e90\u3002\u5ba1\u67e5\u6bcf\u4e00\u884c\u4ee3\u7801\uff0c\u6309\u4f60\u7684\u65b9\u5f0f\u81ea\u6258\u7ba1\uff0c\u5851\u9020\u4eba\u7c7b + Agent \u534f\u4f5c\u7684\u672a\u6765\u3002", + "Multica \u5b8c\u5168\u5f00\u6e90\u3002\u5ba1\u67e5\u6bcf\u4e00\u884c\u4ee3\u7801\uff0c\u6309\u4f60\u7684\u65b9\u5f0f\u81ea\u6258\u7ba1\uff0c\u5851\u9020\u4eba\u7c7b + 智能体 \u534f\u4f5c\u7684\u672a\u6765\u3002", cta: "\u5728 GitHub \u4e0a Star", highlights: [ { @@ -163,17 +163,17 @@ export function createZhDict(allowSignup: boolean): LandingDict { { title: "\u65e0\u4f9b\u5e94\u5546\u9501\u5b9a", description: - "\u81ea\u5e26 LLM \u63d0\u4f9b\u5546\u3001\u66f4\u6362 Agent \u540e\u7aef\u3001\u6269\u5c55 API\u3002\u4f60\u62e5\u6709\u6574\u4e2a\u6280\u672f\u6808\u7684\u63a7\u5236\u6743\u3002", + "\u81ea\u5e26 LLM \u63d0\u4f9b\u5546\u3001\u66f4\u6362 智能体 \u540e\u7aef\u3001\u6269\u5c55 API\u3002\u4f60\u62e5\u6709\u6574\u4e2a\u6280\u672f\u6808\u7684\u63a7\u5236\u6743\u3002", }, { title: "\u9ed8\u8ba4\u900f\u660e", description: - "\u6bcf\u4e00\u884c\u4ee3\u7801\u90fd\u53ef\u5ba1\u8ba1\u3002\u786e\u5207\u4e86\u89e3\u4f60\u7684 Agent \u5982\u4f55\u505a\u51b3\u7b56\u3001\u4efb\u52a1\u5982\u4f55\u8def\u7531\u3001\u6570\u636e\u6d41\u5411\u4f55\u65b9\u3002", + "\u6bcf\u4e00\u884c\u4ee3\u7801\u90fd\u53ef\u5ba1\u8ba1\u3002\u786e\u5207\u4e86\u89e3\u4f60\u7684 智能体 \u5982\u4f55\u505a\u51b3\u7b56\u3001\u4efb\u52a1\u5982\u4f55\u8def\u7531\u3001\u6570\u636e\u6d41\u5411\u4f55\u65b9\u3002", }, { title: "\u793e\u533a\u9a71\u52a8", description: - "\u4e0e\u793e\u533a\u4e00\u8d77\u5efa\u8bbe\uff0c\u800c\u4e0d\u4ec5\u4ec5\u662f\u4e3a\u793e\u533a\u5efa\u8bbe\u3002\u8d21\u732e\u6280\u80fd\u3001\u96c6\u6210\u548c Agent \u540e\u7aef\uff0c\u8ba9\u6bcf\u4e2a\u4eba\u53d7\u76ca\u3002", + "\u4e0e\u793e\u533a\u4e00\u8d77\u5efa\u8bbe\uff0c\u800c\u4e0d\u4ec5\u4ec5\u662f\u4e3a\u793e\u533a\u5efa\u8bbe\u3002\u8d21\u732e\u6280\u80fd\u3001\u96c6\u6210\u548c 智能体 \u540e\u7aef\uff0c\u8ba9\u6bcf\u4e2a\u4eba\u53d7\u76ca\u3002", }, ], }, @@ -183,9 +183,9 @@ export function createZhDict(allowSignup: boolean): LandingDict { headline: "\u95ee\u4e0e\u7b54\u3002", items: [ { - question: "Multica \u652f\u6301\u54ea\u4e9b\u7f16\u7801 Agent\uff1f", + question: "Multica \u652f\u6301\u54ea\u4e9b\u7f16\u7801 智能体\uff1f", answer: - "Multica \u76ee\u524d\u5f00\u7bb1\u5373\u7528\u652f\u6301 Claude Code\u3001Codex\u3001OpenClaw \u548c OpenCode\u3002\u5b88\u62a4\u8fdb\u7a0b\u81ea\u52a8\u68c0\u6d4b\u4f60\u5b89\u88c5\u7684 CLI\u3002\u56e0\u4e3a\u5f00\u6e90\uff0c\u4f60\u4e5f\u53ef\u4ee5\u81ea\u5df1\u6dfb\u52a0\u540e\u7aef\u3002", + "Multica \u5f00\u7bb1\u5373\u7528\u652f\u6301 11 \u6b3e AI \u7f16\u7a0b\u5de5\u5177\uff1aClaude Code\u3001Codex\u3001Cursor\u3001Copilot\u3001Gemini\u3001Hermes\u3001Kimi\u3001Kiro CLI\u3001OpenCode\u3001OpenClaw\u3001Pi\u3002\u5b88\u62a4\u8fdb\u7a0b\u4f1a\u81ea\u52a8\u68c0\u6d4b\u672c\u673a\u5df2\u5b89\u88c5\u7684 CLI \u5e76\u4e3a\u6bcf\u6b3e\u6ce8\u518c\u4e00\u4e2a\u8fd0\u884c\u65f6\u3002\u56e0\u4e3a\u5f00\u6e90\uff0c\u4f60\u4e5f\u53ef\u4ee5\u81ea\u5df1\u6dfb\u52a0\u540e\u7aef\u3002", }, { question: "\u9700\u8981\u81ea\u6258\u7ba1\u5417\uff0c\u8fd8\u662f\u6709\u4e91\u7248\u672c\uff1f", @@ -194,31 +194,31 @@ export function createZhDict(allowSignup: boolean): LandingDict { }, { question: - "\u8fd9\u548c\u76f4\u63a5\u7528\u7f16\u7801 Agent \u6709\u4ec0\u4e48\u533a\u522b\uff1f", + "\u8fd9\u548c\u76f4\u63a5\u7528\u7f16\u7801 智能体 \u6709\u4ec0\u4e48\u533a\u522b\uff1f", answer: - "\u7f16\u7801 Agent \u64c5\u957f\u6267\u884c\u3002Multica \u6dfb\u52a0\u7684\u662f\u7ba1\u7406\u5c42\uff1a\u4efb\u52a1\u961f\u5217\u3001\u56e2\u961f\u534f\u4f5c\u3001\u6280\u80fd\u590d\u7528\u3001\u8fd0\u884c\u65f6\u76d1\u63a7\uff0c\u4ee5\u53ca\u6bcf\u4e2a Agent \u5728\u505a\u4ec0\u4e48\u7684\u7edf\u4e00\u89c6\u56fe\u3002\u628a\u5b83\u60f3\u8c61\u6210\u4f60\u7684 Agent \u7684\u9879\u76ee\u7ecf\u7406\u3002", + "\u7f16\u7801 智能体 \u64c5\u957f\u6267\u884c\u3002Multica \u6dfb\u52a0\u7684\u662f\u7ba1\u7406\u5c42\uff1a\u4efb\u52a1\u961f\u5217\u3001\u56e2\u961f\u534f\u4f5c\u3001\u6280\u80fd\u590d\u7528\u3001\u8fd0\u884c\u65f6\u76d1\u63a7\uff0c\u4ee5\u53ca\u6bcf\u4e2a 智能体 \u5728\u505a\u4ec0\u4e48\u7684\u7edf\u4e00\u89c6\u56fe\u3002\u628a\u5b83\u60f3\u8c61\u6210\u4f60\u7684 智能体 \u7684\u9879\u76ee\u7ecf\u7406\u3002", }, { - question: "Agent \u80fd\u81ea\u4e3b\u5904\u7406\u957f\u65f6\u95f4\u4efb\u52a1\u5417\uff1f", + question: "智能体 \u80fd\u81ea\u4e3b\u5904\u7406\u957f\u65f6\u95f4\u4efb\u52a1\u5417\uff1f", answer: - "\u53ef\u4ee5\u3002Multica \u7ba1\u7406\u5b8c\u6574\u7684\u4efb\u52a1\u751f\u547d\u5468\u671f\u2014\u2014\u5165\u961f\u3001\u9886\u53d6\u3001\u6267\u884c\u3001\u5b8c\u6210\u6216\u5931\u8d25\u3002Agent \u4e3b\u52a8\u62a5\u544a\u963b\u585e\u5e76\u5b9e\u65f6\u63a8\u9001\u8fdb\u5ea6\u3002\u4f60\u53ef\u4ee5\u968f\u65f6\u67e5\u770b\uff0c\u4e5f\u53ef\u4ee5\u8ba9\u5b83\u4eec\u8fd0\u884c\u6574\u665a\u3002", + "\u53ef\u4ee5\u3002Multica \u7ba1\u7406\u5b8c\u6574\u7684\u4efb\u52a1\u751f\u547d\u5468\u671f\u2014\u2014\u5165\u961f\u3001\u9886\u53d6\u3001\u6267\u884c\u3001\u5b8c\u6210\u6216\u5931\u8d25\u3002智能体 \u4e3b\u52a8\u62a5\u544a\u963b\u585e\u5e76\u5b9e\u65f6\u63a8\u9001\u8fdb\u5ea6\u3002\u4f60\u53ef\u4ee5\u968f\u65f6\u67e5\u770b\uff0c\u4e5f\u53ef\u4ee5\u8ba9\u5b83\u4eec\u8fd0\u884c\u6574\u665a\u3002", }, { - question: "\u6211\u7684\u4ee3\u7801\u5b89\u5168\u5417\uff1fAgent \u5728\u54ea\u91cc\u6267\u884c\uff1f", + question: "\u6211\u7684\u4ee3\u7801\u5b89\u5168\u5417\uff1f智能体 \u5728\u54ea\u91cc\u6267\u884c\uff1f", answer: - "Agent \u5728\u4f60\u7684\u673a\u5668\uff08\u672c\u5730\u5b88\u62a4\u8fdb\u7a0b\uff09\u6216\u4f60\u81ea\u5df1\u7684\u4e91\u57fa\u7840\u8bbe\u65bd\u4e0a\u6267\u884c\u3002\u4ee3\u7801\u6c38\u8fdc\u4e0d\u4f1a\u7ecf\u8fc7 Multica \u670d\u52a1\u5668\u3002\u5e73\u53f0\u53ea\u534f\u8c03\u4efb\u52a1\u72b6\u6001\u548c\u5e7f\u64ad\u4e8b\u4ef6\u3002", + "智能体 \u5728\u4f60\u7684\u673a\u5668\uff08\u672c\u5730\u5b88\u62a4\u8fdb\u7a0b\uff09\u6216\u4f60\u81ea\u5df1\u7684\u4e91\u57fa\u7840\u8bbe\u65bd\u4e0a\u6267\u884c\u3002\u4ee3\u7801\u6c38\u8fdc\u4e0d\u4f1a\u7ecf\u8fc7 Multica \u670d\u52a1\u5668\u3002\u5e73\u53f0\u53ea\u534f\u8c03\u4efb\u52a1\u72b6\u6001\u548c\u5e7f\u64ad\u4e8b\u4ef6\u3002", }, { - question: "\u6211\u53ef\u4ee5\u8fd0\u884c\u591a\u5c11\u4e2a Agent\uff1f", + question: "\u6211\u53ef\u4ee5\u8fd0\u884c\u591a\u5c11\u4e2a 智能体\uff1f", answer: - "\u53d6\u51b3\u4e8e\u4f60\u7684\u786c\u4ef6\u3002\u6bcf\u4e2a Agent \u6709\u53ef\u914d\u7f6e\u7684\u5e76\u53d1\u9650\u5236\uff0c\u4f60\u53ef\u4ee5\u8fde\u63a5\u591a\u53f0\u673a\u5668\u4f5c\u4e3a\u8fd0\u884c\u65f6\u3002\u5f00\u6e90\u7248\u672c\u6ca1\u6709\u4efb\u4f55\u4eba\u4e3a\u9650\u5236\u3002", + "\u53d6\u51b3\u4e8e\u4f60\u7684\u786c\u4ef6\u3002\u6bcf\u4e2a 智能体 \u6709\u53ef\u914d\u7f6e\u7684\u5e76\u53d1\u9650\u5236\uff0c\u4f60\u53ef\u4ee5\u8fde\u63a5\u591a\u53f0\u673a\u5668\u4f5c\u4e3a\u8fd0\u884c\u65f6\u3002\u5f00\u6e90\u7248\u672c\u6ca1\u6709\u4efb\u4f55\u4eba\u4e3a\u9650\u5236\u3002", }, ], }, footer: { tagline: - "\u4eba\u7c7b + Agent \u56e2\u961f\u7684\u9879\u76ee\u7ba1\u7406\u3002\u5f00\u6e90\u3001\u53ef\u81ea\u6258\u7ba1\u3001\u4e3a\u672a\u6765\u7684\u5de5\u4f5c\u65b9\u5f0f\u800c\u5efa\u3002", + "\u4eba\u7c7b + 智能体 \u56e2\u961f\u7684\u9879\u76ee\u7ba1\u7406\u3002\u5f00\u6e90\u3001\u53ef\u81ea\u6258\u7ba1\u3001\u4e3a\u672a\u6765\u7684\u5de5\u4f5c\u65b9\u5f0f\u800c\u5efa\u3002", cta: "\u5f00\u59cb\u4f7f\u7528", groups: { product: { diff --git a/packages/views/locales/en/onboarding.json b/packages/views/locales/en/onboarding.json index 891d3ed06..abb2e53b3 100644 --- a/packages/views/locales/en/onboarding.json +++ b/packages/views/locales/en/onboarding.json @@ -77,7 +77,7 @@ "what_eyebrow": "What's a runtime?", "what_prefix": "A ", "what_term": "runtime", - "what_suffix": " is a small background process that runs on your machine. It connects your workspace to AI coding tools like Claude Code or Codex, and executes the tasks your agents pick up.", + "what_suffix": " pairs the daemon (a background process on your machine) with one AI coding tool — Claude Code, Codex, and so on. If you have several tools installed, you'll see one runtime per tool. The runtime is what actually executes the tasks your agents pick up.", "good_eyebrow": "Good to know", "swap_title": "Swap anytime", "swap_body": "Each agent's runtime is just a setting. Change it whenever you want.", @@ -264,8 +264,8 @@ }, "step_platform": { "eyebrow": "Step 3 · Runtime", - "headline": "Connect a runtime.", - "lede": "A runtime is what actually runs your agents' work. Pick how you'd like to set one up.", + "headline": "Pick a runtime source.", + "lede": "A runtime is where your agents' tasks actually execute. Pick how you'd like to install one on this machine.", "hint_default": "Pick a path above — or skip and configure a runtime later.", "hint_downloaded": "Finish setup on the download page, then come back to this tab.", "hint_waitlist": "You're on the waitlist — pick Skip to keep exploring.", diff --git a/packages/views/locales/zh-Hans/modals.json b/packages/views/locales/zh-Hans/modals.json index f7a33f494..92cd723b1 100644 --- a/packages/views/locales/zh-Hans/modals.json +++ b/packages/views/locales/zh-Hans/modals.json @@ -118,18 +118,18 @@ "select_agent_aria": "选择智能体", "pick_an_agent": "选一个智能体...", "no_agents": "暂无可用智能体。", - "version_missing": "该智能体的 daemon 没有报告 CLI 版本。通过智能体创建需要 multica CLI ≥ {{min}}。请升级 daemon 并重连,或切换到手动创建。", - "version_below": "该智能体的 daemon CLI 是 {{current}}——通过智能体创建需要 ≥ {{min}}。请升级 daemon,或切换到手动创建。", + "version_missing": "该智能体的守护进程没有报告 CLI 版本。通过智能体创建需要 multica CLI ≥ {{min}}。请升级守护进程并重连,或切换到手动创建。", + "version_below": "该智能体的守护进程 CLI 是 {{current}}——通过智能体创建需要 ≥ {{min}}。请升级守护进程,或切换到手动创建。", "prompt_placeholder": "告诉智能体要做什么,例如:\"让 Bohan 修一下 Web 项目里收件箱加载慢的问题\"", "submit": "创建", "sending": "发送中...", "uploading": "上传中...", "sent_label": "已发送", "sent_count": "已发送 {{count}}", - "version_blocked_tooltip": "daemon CLI 必须 ≥ {{min}}", + "version_blocked_tooltip": "守护进程 CLI 必须 ≥ {{min}}", "toast_sent": "已交给智能体——完成后会在收件箱通知你", "error_agent_unavailable_fallback": "智能体不可用,请换一个。", - "error_daemon_version": "该智能体的 daemon CLI({{current}})低于要求的 {{min}}。请升级 daemon 后再使用通过智能体创建。", + "error_daemon_version": "该智能体的守护进程 CLI({{current}})低于要求的 {{min}}。请升级守护进程后再使用通过智能体创建。", "error_unknown": "提交失败,请重试。" } } diff --git a/packages/views/locales/zh-Hans/onboarding.json b/packages/views/locales/zh-Hans/onboarding.json index 9020d2f33..01e1f8ec3 100644 --- a/packages/views/locales/zh-Hans/onboarding.json +++ b/packages/views/locales/zh-Hans/onboarding.json @@ -7,7 +7,7 @@ "headline_line1": "你的 AI 队友,", "headline_line2": "在", "headline_emphasis": "同一个工作区。", - "lede": "像分配给同事一样把任务交给它们——它们会接手、推进状态、完成后留下评论。", + "lede": "像分配给同事一样把 task 交给它们——它们会接手、推进状态、完成后留下评论。", "lede_web": "桌面端自带运行时,无需安装。在 web 端继续可以连接你自己的 CLI。", "lede_desktop": "完成本流程后,真实的智能体会回复你创建的第一个 issue。", "download_desktop": "下载桌面端", @@ -77,7 +77,7 @@ "what_eyebrow": "什么是运行时?", "what_prefix": "", "what_term": "运行时", - "what_suffix": "是跑在你机器上的一个后台进程。它把工作区连接到 Claude Code、Codex 这类 AI 编码工具,并执行智能体接到的 task。", + "what_suffix": "是守护进程和一款 AI 编程工具(Claude Code、Codex 等)的组合——一台机器装了多款工具就会出现多个运行时。它代替智能体执行接到的 task。", "good_eyebrow": "需要知道", "swap_title": "随时切换", "swap_body": "每个智能体的运行时只是一个设置。想换就换。", @@ -87,7 +87,7 @@ }, "cli_install": { "copy_aria": "复制", - "intro": "守护进程需要本机有一个 AI 编码工具(Claude Code、Codex、Cursor 等)才能执行真实工作。也支持服务器和远程开发机。", + "intro": "守护进程需要本机有一个 AI 编程工具(Claude Code、Codex、Cursor 等)才能执行真实工作。也支持服务器和远程开发机。", "step1_label": "安装 Multica CLI", "step2_label": "启动守护进程" }, @@ -230,7 +230,7 @@ }, "step_runtime": { "scanning_headline": "正在寻找你的工具...", - "scanning_lede_prefix": "Multica 驱动本地的 AI 编码工具,比如 ", + "scanning_lede_prefix": "Multica 驱动本地的 AI 编程工具,比如 ", "scanning_lede_suffix": " 等。等待你机器上的反馈中。", "found_headline": "找到了你的运行时。", "found_lede": "扫描到你机器上已经设置好的 AI 编码工具。挑一个给你的第一个智能体。", @@ -241,7 +241,7 @@ "online_label": "在线", "offline_label": "离线", "empty_headline": "未检测到支持的工具。", - "empty_lede_prefix": "Multica 驱动本地的 AI 编码工具,比如 ", + "empty_lede_prefix": "Multica 驱动本地的 AI 编程工具,比如 ", "empty_lede_suffix": " 等 —— 这台机器上没找到。装一个再回来,或在下面挑一条路。", "empty_skip_title": "暂时跳过", "empty_skip_subtitle": "进入工作区(只读模式)。没有运行时连接前,智能体无法执行 task —— 但你仍可以浏览、规划、邀请同事。", @@ -263,8 +263,8 @@ }, "step_platform": { "eyebrow": "第 3 步 · 运行时", - "headline": "连接一个运行时。", - "lede": "运行时是真正执行智能体工作的地方。挑一种你想用的方式。", + "headline": "挑一个运行时来源。", + "lede": "运行时是智能体真正执行 task 的地方。挑一种安装方式让本机出现一个运行时。", "hint_default": "在上方挑一条路 —— 或跳过,之后再配置运行时。", "hint_downloaded": "在下载页完成安装,然后回到此标签页。", "hint_waitlist": "已在候补名单 —— 选择\"跳过\"继续探索。", diff --git a/packages/views/onboarding/components/starter-content-prompt.tsx b/packages/views/onboarding/components/starter-content-prompt.tsx index 79a228c26..bef9639a6 100644 --- a/packages/views/onboarding/components/starter-content-prompt.tsx +++ b/packages/views/onboarding/components/starter-content-prompt.tsx @@ -25,7 +25,10 @@ import { DialogHeader, DialogTitle, } from "@multica/ui/components/ui/dialog"; -import { buildImportPayload } from "../utils/starter-content-templates"; +import { + buildImportPayload, + type StarterContentLocale, +} from "../utils/starter-content-templates"; import { useT } from "../../i18n"; /** @@ -44,7 +47,7 @@ import { useT } from "../../i18n"; * no client-side cache timing, no stale decisions, no Unknown bugs. */ export function StarterContentPrompt() { - const { t } = useT("onboarding"); + const { t, i18n } = useT("onboarding"); const workspace = useCurrentWorkspace(); const user = useAuthStore((s) => s.user); const refreshMe = useAuthStore((s) => s.refreshMe); @@ -87,6 +90,7 @@ export function StarterContentPrompt() { workspaceId: workspace.id, userName: user.name || user.email, questionnaire, + locale: resolveLocale(i18n.language), }); const result = await api.importStarterContent(payload); @@ -199,6 +203,12 @@ export function StarterContentPrompt() { ); } +// i18next resolves locale names like "zh-Hans-CN" or "en-US"; we only +// ship en + zh-Hans starter content, so default everything else to en. +function resolveLocale(language: string): StarterContentLocale { + return language.startsWith("zh") ? "zh-Hans" : "en"; +} + // Local helper — mirrors the onboarding flow's mergeQuestionnaire. function mergeQuestionnaire( raw: Record, diff --git a/packages/views/onboarding/utils/starter-content-content-en.ts b/packages/views/onboarding/utils/starter-content-content-en.ts new file mode 100644 index 000000000..db921e446 --- /dev/null +++ b/packages/views/onboarding/utils/starter-content-content-en.ts @@ -0,0 +1,586 @@ +import type { QuestionnaireAnswers } from "@multica/core/onboarding"; +import type { ImportStarterIssuePayload } from "@multica/core/api"; + +// ============================================================================= +// English starter-content body. Long-form markdown lives here (TypeScript, +// reviewed as UI). The orchestrator in starter-content-templates.ts picks +// between this file and starter-content-content-zh.ts based on the user's +// locale, then hands the result to buildImportPayload. +// ============================================================================= + +export const PROJECT = { + title: "Getting Started", + description: + "A few things to try in Multica. Work through them at your own pace.", +}; + +interface WelcomeIssueText { + title: string; + description: string; +} + +export function buildWelcomeIssueText( + q: QuestionnaireAnswers, + userName: string, +): WelcomeIssueText { + const name = userName.trim() || "there"; + + const header = [ + `Welcome to Multica! 👋`, + ``, + `This is your workspace's first issue. Below, your agent will reply in a moment — that's how work happens here: you write what you want, your agent (or a teammate) picks it up and replies in the comments.`, + ``, + `[Learn how Multica works →](https://multica.ai/docs/how-multica-works)`, + ``, + `---`, + ``, + ].join("\n"); + + const sharedInstructions = [ + `In your first reply, please:`, + ``, + `1. **Introduce yourself briefly** — your name, your role, what you're good at.`, + `2. **Explain how we work together in Multica**:`, + ` - Assigning an issue to you **and** setting its status to **Todo** is what triggers you to start (Backlog pauses you)`, + ` - @mentioning you inside a comment is for quick questions`, + ` - **Workspace Context** (in Settings → General) is shared background every agent here sees`, + `3. **Point them at the *Getting Started* project** in the sidebar and invite them to assign you a real task when they're ready.`, + ``, + `Keep it friendly and under 200 words. End with one short question that invites ${name} to reply.`, + ].join("\n"); + + const exploreInstructions = [ + `In your first reply, please:`, + ``, + `1. **Introduce yourself briefly** — your name, your role, what you're good at.`, + `2. **Explain how we work together in Multica**:`, + ` - Assigning an issue to you **and** setting its status to **Todo** triggers you to start (Backlog pauses you)`, + ` - @mentioning you inside a comment is for quick questions`, + ` - **Workspace Context** (in Settings → General) is shared background every agent here sees`, + `3. **Point them at the *Getting Started* project** in the sidebar.`, + ``, + `Keep it friendly and under 200 words. End with a small, curious question — something like "what's something you've been wondering about lately?" — so ${name} has an easy way to reply without having to come up with a real task yet.`, + ].join("\n"); + + switch (q.use_case) { + case "coding": + return { + title: "👋 Welcome to Multica — let's work together", + description: `${header}Hi agent, this is ${name}'s first time using Multica. They plan to use you mostly for **coding work**.\n\n${sharedInstructions}`, + }; + case "planning": + return { + title: "👋 Welcome to Multica — let's work together", + description: `${header}Hi agent, this is ${name}'s first time using Multica. They want your help with **planning and breaking down work**.\n\n${sharedInstructions}`, + }; + case "writing_research": + return { + title: "👋 Welcome to Multica — let's work together", + description: `${header}Hi agent, this is ${name}'s first time using Multica. They'll use you for **research and writing** — drafting, summarizing, analysis.\n\n${sharedInstructions}`, + }; + case "explore": + return { + title: "👋 Welcome to Multica — let's work together", + description: `${header}Hi agent, this is ${name}'s first time using Multica. They're **exploring** what Multica can do — no specific goal yet.\n\n${exploreInstructions}`, + }; + case "other": { + const customUseCase = (q.use_case_other ?? "").trim(); + const contextLine = customUseCase + ? `They told us they want to use you for: "${customUseCase}".` + : `They haven't narrowed down their use case yet.`; + return { + title: "👋 Welcome to Multica — let's work together", + description: `${header}Hi agent, this is ${name}'s first time using Multica. ${contextLine}\n\n${sharedInstructions}`, + }; + } + default: + return { + title: "👋 Welcome to Multica — let's work together", + description: `${header}Hi agent, this is ${name}'s first time using Multica.\n\n${sharedInstructions}`, + }; + } +} + +export function buildAgentGuidedSubIssues( + q: QuestionnaireAnswers, +): ImportStarterIssuePayload[] { + const tier1: ImportStarterIssuePayload[] = [ + { + status: "todo", + priority: "high", + assign_to_self: true, + title: "Learn how to trigger your agent on any issue", + description: [ + `**Every issue has a right-side panel** called **Properties**. From there you control who works on what. Agents in Multica are triggered when an issue has:`, + ``, + ` Assignee = your agent AND Status = Todo (not Backlog)`, + ``, + `**Try it now**:`, + `1. In the sidebar, click **New Issue** at the top (or press \`C\`)`, + `2. Give it a title like "Test run: summarize our product in 3 bullets"`, + `3. On the right panel, find **Assignee** → click → pick your agent`, + `4. Find **Status** → click → pick **Todo**`, + `5. Scroll down to Activity — a **Live card** appears as your agent starts working`, + ``, + `**⚠️ Gotcha**: new issues default to Backlog. Agents pause on backlog. A hint dialog will pop up the first time — it's telling you "flip to Todo to start".`, + ``, + `**You'll know it worked when**: the Live card shows your agent thinking, and the Status flips to **In Progress** automatically.`, + ``, + `[Learn about assigning issues →](https://multica.ai/docs/assigning-issues)`, + ].join("\n"), + }, + { + status: "todo", + priority: "high", + assign_to_self: true, + title: "Chat with your agent — no issue required", + description: [ + `Not every question needs a whole issue. For quick back-and-forth, use the **Chat panel**.`, + ``, + `**Where to find it**: look at the **bottom-right corner of the screen** — there's a round button with a **💬 speech bubble icon**. If your agent is working, the button pulses. If there are unread replies, a red badge sits on top of it.`, + ``, + `**Try it now**:`, + `1. Click the 💬 button → a panel slides in from the right`, + `2. At the **bottom-left of the input box**, click the agent avatar → pick your agent from the dropdown`, + `3. Type a quick question: "What can you help me with in this workspace?"`, + `4. Press **Enter**`, + ``, + `**Bonus — @mention an agent inside a comment**: on any issue, scroll to the comment box at the bottom. Type \`@\` and a dropdown appears listing members, agents, and other issues. Pick an agent → write your question → send. The mentioned agent replies in the comments.`, + ``, + `**You'll know it worked when**: the agent replies in the chat panel (or comment thread) within a few seconds.`, + ``, + `[Learn about chat →](https://multica.ai/docs/chat)`, + ].join("\n"), + }, + { + status: "todo", + priority: "high", + assign_to_self: true, + title: "Write your Workspace Context", + description: [ + `**Workspace Context** is a shared system prompt every agent in this workspace reads before starting any task. It's the single most impactful thing you can do to make agent replies sharper.`, + ``, + `**Where to find it**:`, + `1. Open the **sidebar** → scroll to the bottom section labeled **Configure**`, + `2. Click **Settings** (⚙️ gear icon, bottom-most item)`, + `3. In the left-side tab list, under the **[Your Workspace Name]** group, click **General**`, + `4. Scroll down to the **Context** textarea (placeholder says "Provide context to agents...")`, + ``, + `**Fill it with 3-5 lines**:`, + `- Who you are (name, role)`, + `- What you're building or working on`, + `- How agents should behave (tone, style, defaults)`, + ``, + `**Example**:`, + `> I'm a frontend engineer working on an AI-native task manager. Reply concisely in English. Always explain your reasoning. Prefer TypeScript over JavaScript.`, + ``, + `Click **Save**.`, + ``, + `**You'll know it worked when**: the next task you assign to an agent picks up details from this context without you explaining again.`, + ``, + `[Learn about workspaces →](https://multica.ai/docs/workspaces)`, + ].join("\n"), + }, + ]; + + const tier2: ImportStarterIssuePayload[] = []; + + if (q.team_size === "team") { + tier2.push({ + status: "todo", + priority: "medium", + assign_to_self: true, + title: "Invite your teammates", + description: [ + `Multica works best when a small team shares agents.`, + ``, + `**Where to find it**:`, + `1. Sidebar → **Settings** (⚙️, bottom)`, + `2. Left tab list → under **[Your Workspace]** group → click **Members** (people icon)`, + `3. At the top of the page, click **Add member**`, + `4. Enter their email, pick a role (**Owner / Admin / Member**)`, + `5. Click **Send invite**`, + ``, + `They'll receive an email with a join link. Pending invites show in the collapsible "Pending Invitations" section below the member list — you can revoke from there.`, + ``, + `[Learn about members and roles →](https://multica.ai/docs/members-roles)`, + ].join("\n"), + }); + } + + if (q.role === "developer" || q.use_case === "coding") { + tier2.push({ + status: "todo", + priority: "medium", + assign_to_self: true, + title: "Connect a Git repo", + description: [ + `Once connected, any agent can clone, read, and propose changes to your repo when you assign it a task.`, + ``, + `**Where to find it**:`, + `1. Sidebar → **Settings** (⚙️)`, + `2. Left tab list → under **[Your Workspace]** group → **Repositories** (folder with Git branch icon)`, + `3. At the bottom of the list, click **+ Add repository**`, + `4. Fill the two inline fields:`, + ` - **URL** — e.g. \`https://github.com/you/repo.git\``, + ` - **Description** — what this repo is for`, + `5. Click **Save** at the top of the page`, + ``, + `Repeat for as many repos as you want to expose.`, + ].join("\n"), + }); + } + + tier2.push({ + status: "todo", + priority: "medium", + assign_to_self: true, + title: "Create a second agent with a different role", + description: [ + `Running a small team of focused agents beats a single generalist. One for coding, one for planning, one for writing — each with their own instructions.`, + ``, + `**Note**: nothing locks a "Coding Agent" to coding. Instructions are just a system prompt, editable anytime. The split is about keeping each one's replies sharp.`, + ``, + `**Where to find it**:`, + `1. Sidebar → under **Workspace** group → click **Agents** (🤖 bot icon)`, + `2. In the left list header, click the **+** button (top-right corner of the list)`, + `3. Fill the 4 fields in order:`, + ` - **Name** — e.g. "Planning Agent"`, + ` - **Description** — "Breaks down loose ideas into scoped work"`, + ` - **Visibility** — Workspace (shared) or Private (only you)`, + ` - **Runtime** — pick from the dropdown (your connected runtime)`, + `4. Click **Create**`, + ``, + `**You'll know it worked when**: the new agent appears in the Assignee dropdown on any issue, and shows up in the left list on the Agents page.`, + ``, + `[Learn about creating agents →](https://multica.ai/docs/agents-create)`, + ].join("\n"), + }); + + const tier3: ImportStarterIssuePayload[] = [ + { + status: "backlog", + priority: "low", + assign_to_self: true, + title: "Polish your agent's Instructions", + description: [ + `Creating an agent is just the start. The **Instructions tab** is where you shape how it behaves.`, + ``, + `**Where to find it**:`, + `1. Sidebar → **Agents** (🤖)`, + `2. In the left list, click an agent you want to refine`, + `3. In the right panel, you'll see tabs at the top including **Instructions / Skills / Tasks / Settings**`, + `4. Click **Instructions**`, + `5. Edit the markdown — changes save automatically`, + ``, + `**Good instructions include**:`, + `- The role/persona (e.g. "You're a senior TypeScript engineer")`, + `- House rules (e.g. "Always propose tests alongside code")`, + `- Output format (e.g. "Return a short summary first, details below")`, + ``, + `Workspace Context and agent Instructions stack — both are sent on every task. Keep Instructions specific to this agent; keep Context specific to the whole workspace.`, + ].join("\n"), + }, + { + status: "backlog", + priority: "low", + assign_to_self: true, + title: "Watch your agent live in action", + description: [ + `**Heads-up task** — nothing to do now, just know this exists.`, + ``, + `When an agent is working on an issue, a **Live card** appears at the top of the **Activity** section (it sticks to the top of the viewport as you scroll).`, + ``, + `The card shows in real time:`, + `- Which tool the agent is calling (e.g. reading a file, web search)`, + `- Streaming thoughts and partial output`, + `- Current status (thinking / tool-running / done / failed)`, + ``, + `After the run finishes, the **Task Run History** below the card lists every past run. Click **View transcript** on any row to open the full interactive transcript — a timeline of every message, thinking step, tool call, and result.`, + ``, + `**Try it next time you assign an agent**: keep the issue open and watch the Live card appear below the description.`, + ``, + `[Learn about tasks →](https://multica.ai/docs/tasks)`, + ].join("\n"), + }, + { + status: "backlog", + priority: "low", + assign_to_self: true, + title: "Check your Inbox for @mentions and updates", + description: [ + `When someone — or an agent — @mentions you or assigns you an issue, it lands in your **Inbox**.`, + ``, + `**Where to find it**:`, + `1. Sidebar → the top section (above the **Workspace** group) → click **Inbox** (📥 icon) — an unread count badge shows on the right if you have new items`, + ``, + `**How it works**:`, + `- Left column: notification list, newest first`, + `- Right column: the linked issue opens inline, and the specific comment that mentioned you is **auto-highlighted and scrolled into view**`, + `- Top-right dropdown: **Mark all as read / Archive all / Archive all read / Archive completed** for bulk cleanup`, + ``, + `**Tip**: "Archive completed" is the fastest way to clear the noise from issues already finished.`, + ``, + `[Learn about the inbox →](https://multica.ai/docs/inbox)`, + ].join("\n"), + }, + { + status: "backlog", + priority: "low", + assign_to_self: true, + title: "Set up an Autopilot for recurring work", + description: [ + `**Autopilot** turns a prompt into a scheduled task. Every day/week/hour, it auto-creates an issue and assigns it to an agent.`, + ``, + `**Where to find it**:`, + `1. Sidebar → under **Workspace** group → click **Autopilot** (⚡ Zap icon)`, + `2. If you have no autopilots yet, a grid of templates shows up — pick any one to pre-fill the dialog, or click **+ New autopilot** for a blank one`, + `3. Fill: **Name** / **Prompt** / **Agent** / **Schedule** (frequency + time + timezone)`, + `4. Click **Create**`, + ``, + `**Good first autopilots**: daily digest of GitHub activity, weekly "what's blocked" check, or a Monday-morning triage of any issues still in Backlog.`, + ``, + `[Learn about autopilots →](https://multica.ai/docs/autopilots)`, + ].join("\n"), + }, + ]; + + return [...tier1, ...tier2, ...tier3]; +} + +export function buildSelfServeSubIssues( + q: QuestionnaireAnswers, +): ImportStarterIssuePayload[] { + const tier1: ImportStarterIssuePayload[] = [ + { + status: "todo", + priority: "high", + assign_to_self: true, + title: "Install a runtime (Desktop app or CLI)", + description: [ + `**Why this first**: no runtime = no agents can execute. Everything below Tier 1 waits on this.`, + ``, + `A **runtime** pairs the daemon (a small background process on your machine) with one AI coding tool — Claude Code, Codex, and so on. If you have several tools installed, you'll see one runtime per tool. The runtime is what executes the tasks your agents pick up.`, + ``, + `**Option A — Desktop app (macOS, recommended if you're on a Mac)**:`, + `1. Go to [github.com/multica-ai/multica/releases/latest](https://github.com/multica-ai/multica/releases/latest) and download the \`.dmg\` for macOS`, + `2. Install and open the app`, + `3. Sign in with the same account — the daemon is built in, you're done`, + ``, + `**Option B — CLI (macOS, Linux, or Windows via WSL)**:`, + `1. In a terminal, install the CLI:`, + ` \`\`\``, + ` curl -fsSL https://raw.githubusercontent.com/multica-ai/multica/main/scripts/install.sh | bash`, + ` \`\`\``, + `2. Then run setup (signs you in and starts a background daemon):`, + ` \`\`\``, + ` multica setup`, + ` \`\`\``, + ` The daemon keeps running after you close the terminal — you don't have to leave anything open.`, + ``, + `**Verify**: sidebar → bottom **Configure** section → **Runtimes** → you should see at least one connected runtime.`, + ``, + `[Learn about runtimes →](https://multica.ai/docs/daemon-runtimes)`, + ].join("\n"), + }, + { + status: "todo", + priority: "high", + assign_to_self: true, + title: "Create your first agent", + description: [ + `**Prerequisite**: task above done (runtime connected).`, + ``, + `**Where to find it**:`, + `1. Sidebar → under **Workspace** group → click **Agents** (🤖 bot icon)`, + `2. In the left list header, click the **+** button (top-right corner of the list)`, + `3. Fill the 4 fields in order:`, + ` - **Name** — e.g. "My Coding Agent"`, + ` - **Description** — one line about what it does`, + ` - **Visibility** — Workspace (shared) or Private (only you)`, + ` - **Runtime** — pick the one you just installed`, + `4. Click **Create**`, + ``, + `**Note**: an agent is just an LLM + instructions + workspace access. Nothing locks a "Coding Agent" to coding — same agent can do research, writing, planning. Keep it flexible.`, + ``, + `**You'll know it worked when**: the new agent appears in the Assignee dropdown on any issue.`, + ``, + `[Learn about creating agents →](https://multica.ai/docs/agents-create)`, + ].join("\n"), + }, + ]; + + const tier2: ImportStarterIssuePayload[] = [ + { + status: "todo", + priority: "medium", + assign_to_self: true, + title: "Assign your first real task to your agent", + description: [ + `**Prerequisite**: you have a runtime + agent from the two tasks above.`, + ``, + `**How Multica triggers agents**:`, + `- Assign an issue to an agent`, + `- Set status to **Todo** (not Backlog — backlog pauses agents)`, + `- The agent picks it up automatically`, + ``, + `**Try it now**:`, + `1. In the sidebar, click **New Issue** at the top (or press \`C\`)`, + `2. Title: something you actually want done`, + `3. On the right panel, find **Assignee** → click → pick your agent`, + `4. Find **Status** → change from Backlog to **Todo**`, + `5. Watch the agent reply in the comments and a **Live card** appear in Activity`, + ``, + `**⚠️ Gotcha**: new issues default to **Backlog**. You must flip to **Todo** to trigger the agent.`, + ``, + `[Learn about assigning issues →](https://multica.ai/docs/assigning-issues)`, + ].join("\n"), + }, + { + status: "todo", + priority: "medium", + assign_to_self: true, + title: "Write your Workspace Context", + description: [ + `**Workspace Context** is a shared system prompt every agent in this workspace reads before starting any task. It's the single most impactful thing you can do to make agent replies sharper.`, + ``, + `**Where to find it**:`, + `1. Open the **sidebar** → scroll to the bottom section labeled **Configure**`, + `2. Click **Settings** (⚙️ gear icon, bottom-most item)`, + `3. In the left-side tab list, under the **[Your Workspace Name]** group, click **General**`, + `4. Scroll down to the **Context** textarea`, + ``, + `**Fill it with 3-5 lines**:`, + `- Who you are (name, role)`, + `- What you're building or working on`, + `- How agents should behave (tone, style, defaults)`, + ``, + `Click **Save**.`, + ``, + `**You'll know it worked when**: the next task you assign to an agent picks up details from this context without you explaining again.`, + ``, + `[Learn about workspaces →](https://multica.ai/docs/workspaces)`, + ].join("\n"), + }, + ]; + + const tier3: ImportStarterIssuePayload[] = [ + { + status: "backlog", + priority: "low", + assign_to_self: true, + title: "Chat with an agent — once you've created one", + description: [ + `**Prerequisite**: you've created at least one agent (Tier 1 #2).`, + ``, + `Not every question needs a whole issue. For quick back-and-forth, use the **Chat panel**.`, + ``, + `**Where to find it**: the **bottom-right corner of the screen** has a round button with a **💬 speech bubble icon**.`, + ``, + `**Try it**:`, + `1. Click the 💬 button → a panel slides in from the right`, + `2. At the bottom-left of the input box, pick an agent from the dropdown`, + `3. Type a question → press **Enter**`, + ``, + `**Bonus**: inside any issue's comment box, type \`@\` to mention an agent or member.`, + ``, + `[Learn about chat →](https://multica.ai/docs/chat)`, + ].join("\n"), + }, + ]; + + if (q.role === "developer" || q.use_case === "coding") { + tier3.push({ + status: "backlog", + priority: "low", + assign_to_self: true, + title: "Connect a Git repo", + description: [ + `Once connected, any agent can clone, read, and propose changes to your repo when you assign it a task.`, + ``, + `**Where to find it**:`, + `1. Sidebar → **Settings** (⚙️)`, + `2. Left tab list → **Repositories** (folder with Git branch icon)`, + `3. At the bottom of the list, click **+ Add repository**`, + `4. Fill **URL** (e.g. \`https://github.com/you/repo.git\`) and **Description**`, + `5. Click **Save** at the top of the page`, + ].join("\n"), + }); + } + + if (q.team_size === "team") { + tier3.push({ + status: "backlog", + priority: "low", + assign_to_self: true, + title: "Invite your teammates", + description: [ + `Multica works best when a small team shares agents.`, + ``, + `**Where to find it**:`, + `1. Sidebar → **Settings** (⚙️, bottom)`, + `2. Left tab list → **Members** (people icon)`, + `3. Click **Add member** → enter email → pick role → **Send invite**`, + ``, + `[Learn about members and roles →](https://multica.ai/docs/members-roles)`, + ].join("\n"), + }); + } + + tier3.push( + { + status: "backlog", + priority: "low", + assign_to_self: true, + title: "Shape your agent's Instructions (once it's created)", + description: [ + `**Prerequisite**: you have at least one agent.`, + ``, + `Creating an agent is just the start. The **Instructions tab** is where you shape how it behaves.`, + ``, + `**Where to find it**:`, + `1. Sidebar → **Agents** (🤖)`, + `2. Click an agent in the left list`, + `3. Right panel → click the **Instructions** tab (alongside Skills / Tasks / Settings)`, + `4. Edit the markdown — changes save automatically`, + ``, + `Workspace Context and agent Instructions stack — both are sent on every task. Keep Instructions specific to this agent; keep Context specific to the whole workspace.`, + ].join("\n"), + }, + { + status: "backlog", + priority: "low", + assign_to_self: true, + title: "Watch an agent work live (once you've assigned one a task)", + description: [ + `**Heads-up task** — nothing to do now, just know this exists.`, + ``, + `When an agent is working on an issue, a **Live card** appears at the top of the **Activity** section (it sticks to the top of the viewport as you scroll).`, + ``, + `It shows in real time which tool the agent is calling, streaming thoughts, and current status. After the run finishes, the **Task Run History** below the card lists every past run — click **View transcript** to open the full timeline.`, + ``, + `[Learn about tasks →](https://multica.ai/docs/tasks)`, + ].join("\n"), + }, + { + status: "backlog", + priority: "low", + assign_to_self: true, + title: "Set up an Autopilot (once you have an agent)", + description: [ + `**Prerequisite**: you have at least one agent.`, + ``, + `**Autopilot** turns a prompt into a scheduled task. Every day/week/hour, it auto-creates an issue and assigns it to an agent.`, + ``, + `**Where to find it**:`, + `1. Sidebar → under **Workspace** group → click **Autopilot** (⚡ Zap icon)`, + `2. Pick a template, or click **+ New autopilot** for a blank one`, + `3. Fill: **Name** / **Prompt** / **Agent** / **Schedule** (frequency + time + timezone) → **Create**`, + ``, + `[Learn about autopilots →](https://multica.ai/docs/autopilots)`, + ].join("\n"), + }, + ); + + return [...tier1, ...tier2, ...tier3]; +} diff --git a/packages/views/onboarding/utils/starter-content-content-zh.ts b/packages/views/onboarding/utils/starter-content-content-zh.ts new file mode 100644 index 000000000..e99c9ba4a --- /dev/null +++ b/packages/views/onboarding/utils/starter-content-content-zh.ts @@ -0,0 +1,589 @@ +import type { QuestionnaireAnswers } from "@multica/core/onboarding"; +import type { ImportStarterIssuePayload } from "@multica/core/api"; + +// ============================================================================= +// Chinese starter-content body. Mirrors starter-content-content-en.ts in +// shape; translated and adapted to the conventions in +// apps/docs/content/docs/developers/conventions.zh.mdx — task / issue / +// skill stay lowercase English; agent / runtime / daemon / workspace are +// translated; product UI labels (Properties, Assignee, Status, Activity, +// Live card, Inbox, Members, Settings, Runtimes, Configure, Workspace, +// Repositories, Instructions, Tasks, Skills, Autopilot, etc.) stay in +// English with English code-style framing matching the actual UI. +// ============================================================================= + +export const PROJECT = { + title: "上手指南", + description: "几件可以在 Multica 里上手试一试的事,按你的节奏走。", +}; + +interface WelcomeIssueText { + title: string; + description: string; +} + +export function buildWelcomeIssueText( + q: QuestionnaireAnswers, + userName: string, +): WelcomeIssueText { + const name = userName.trim() || "你"; + + const header = [ + `欢迎来到 Multica!👋`, + ``, + `这是你工作区里的第一个 issue。下面你的智能体马上会回复——这就是 Multica 里工作的方式:你写下你想做的事,智能体(或同事)接手并在评论里回复。`, + ``, + `[了解 Multica 是怎么运转的 →](https://multica.ai/docs/zh/how-multica-works)`, + ``, + `---`, + ``, + ].join("\n"); + + const sharedInstructions = [ + `请你在第一条回复里:`, + ``, + `1. **简短地自我介绍** —— 名字、定位、擅长的事。`, + `2. **说明我们在 Multica 里怎么协作**:`, + ` - 把 issue 分配给你 **并** 把状态置为 **Todo** 才会触发你开工(Backlog 状态会让你暂停)`, + ` - 在评论里 @你 适合丢一个快速问题`, + ` - **Workspace Context**(在 Settings → General)是这个工作区里每个智能体都会读到的共享背景`, + `3. **把 ${name} 引到侧边栏的 *上手指南* 项目**,邀请 ${name} 准备好后给你分配一个真实的 task。`, + ``, + `语气友好、不超过 200 字。结尾抛一个简短的小问题让 ${name} 容易回复。`, + ].join("\n"); + + const exploreInstructions = [ + `请你在第一条回复里:`, + ``, + `1. **简短地自我介绍** —— 名字、定位、擅长的事。`, + `2. **说明我们在 Multica 里怎么协作**:`, + ` - 把 issue 分配给你 **并** 把状态置为 **Todo** 才会触发你开工(Backlog 状态会让你暂停)`, + ` - 在评论里 @你 适合丢一个快速问题`, + ` - **Workspace Context**(在 Settings → General)是这个工作区里每个智能体都会读到的共享背景`, + `3. **把 ${name} 引到侧边栏的 *上手指南* 项目**。`, + ``, + `语气友好、不超过 200 字。结尾抛一个轻松的小问题——比如"最近你在琢磨什么有意思的事?"——让 ${name} 不必先想好一个真实任务也能轻松回复。`, + ].join("\n"); + + switch (q.use_case) { + case "coding": + return { + title: "👋 欢迎来到 Multica —— 一起开工", + description: `${header}你好智能体,这是 ${name} 第一次用 Multica。${name} 主要会让你做 **编码相关的工作**。\n\n${sharedInstructions}`, + }; + case "planning": + return { + title: "👋 欢迎来到 Multica —— 一起开工", + description: `${header}你好智能体,这是 ${name} 第一次用 Multica。${name} 希望你帮忙做 **规划与拆解工作**。\n\n${sharedInstructions}`, + }; + case "writing_research": + return { + title: "👋 欢迎来到 Multica —— 一起开工", + description: `${header}你好智能体,这是 ${name} 第一次用 Multica。${name} 会让你做 **调研和写作** —— 起草、摘要、分析。\n\n${sharedInstructions}`, + }; + case "explore": + return { + title: "👋 欢迎来到 Multica —— 一起开工", + description: `${header}你好智能体,这是 ${name} 第一次用 Multica。${name} 还在 **探索** Multica 能做什么 —— 暂时没有具体目标。\n\n${exploreInstructions}`, + }; + case "other": { + const customUseCase = (q.use_case_other ?? "").trim(); + const contextLine = customUseCase + ? `${name} 告诉我们想让你做的事是:"${customUseCase}"。` + : `${name} 还没明确具体的使用场景。`; + return { + title: "👋 欢迎来到 Multica —— 一起开工", + description: `${header}你好智能体,这是 ${name} 第一次用 Multica。${contextLine}\n\n${sharedInstructions}`, + }; + } + default: + return { + title: "👋 欢迎来到 Multica —— 一起开工", + description: `${header}你好智能体,这是 ${name} 第一次用 Multica。\n\n${sharedInstructions}`, + }; + } +} + +export function buildAgentGuidedSubIssues( + q: QuestionnaireAnswers, +): ImportStarterIssuePayload[] { + const tier1: ImportStarterIssuePayload[] = [ + { + status: "todo", + priority: "high", + assign_to_self: true, + title: "学会怎么在任意 issue 上触发你的智能体", + description: [ + `**每个 issue 右侧都有一个 Properties 面板**。从这里控制谁来做什么。Multica 里的智能体被触发的条件是 issue 同时满足:`, + ``, + ` Assignee = 你的智能体 AND Status = Todo(不是 Backlog)`, + ``, + `**现在就试一下**:`, + `1. 在侧边栏顶部点 **New Issue**(或按 \`C\`)`, + `2. 标题写成类似"试运行:用 3 条 bullet 总结我们的产品"`, + `3. 在右侧面板找到 **Assignee** → 点击 → 选你的智能体`, + `4. 找到 **Status** → 点击 → 选 **Todo**`, + `5. 滚动到 Activity —— 智能体一开工就会出现一张 **Live card**`, + ``, + `**⚠️ 容易踩**:新建的 issue 默认是 Backlog 状态,智能体在 Backlog 是暂停的。第一次会弹一个提示——意思就是"翻到 Todo 才会开工"。`, + ``, + `**怎么算成功**:Live card 里出现智能体在思考的状态,Status 自动翻到 **In Progress**。`, + ``, + `[关于把 issue 分配给智能体 →](https://multica.ai/docs/zh/assigning-issues)`, + ].join("\n"), + }, + { + status: "todo", + priority: "high", + assign_to_self: true, + title: "和智能体聊天 —— 不需要建 issue", + description: [ + `不是每个问题都值得开一个 issue。要快速来回对话,用 **Chat 面板**。`, + ``, + `**在哪**:看屏幕 **右下角** —— 有一个圆形按钮,上面是一个 **💬 对话气泡**。智能体在工作时按钮会脉动;有未读回复时会有红色小角标。`, + ``, + `**现在就试一下**:`, + `1. 点 💬 按钮 → 一个面板从右侧滑入`, + `2. 在 **输入框左下角** 点智能体头像 → 从下拉里选你的智能体`, + `3. 输入一个简短问题:"这个工作区里你能帮我做什么?"`, + `4. 按 **Enter**`, + ``, + `**附赠技巧 —— 在评论里 @智能体**:在任何 issue 底部的评论框里输入 \`@\`,会弹出一个下拉,列出成员、智能体和其他 issue。选一个智能体 → 写下问题 → 发送。被 @ 的智能体会在评论里回复。`, + ``, + `**怎么算成功**:智能体在几秒内通过 chat 面板(或评论里)回复。`, + ``, + `[关于聊天 →](https://multica.ai/docs/zh/chat)`, + ].join("\n"), + }, + { + status: "todo", + priority: "high", + assign_to_self: true, + title: "写一份 Workspace Context", + description: [ + `**Workspace Context** 是一段共享系统提示,这个工作区里每个智能体在执行任何 task 之前都会读它。这是让智能体回复更精准、最有杠杆的一件事。`, + ``, + `**在哪**:`, + `1. 打开 **侧边栏** → 滚到底部 **Configure** 区`, + `2. 点 **Settings**(⚙️ 齿轮图标,最底部那个)`, + `3. 左侧 tab 列表里,在 **[你的工作区名]** 分组下,点 **General**`, + `4. 滚到 **Context** 文本框(占位符是"Provide context to agents...")`, + ``, + `**写 3-5 行**:`, + `- 你是谁(名字、定位)`, + `- 你在做什么(产品、项目)`, + `- 智能体应该怎么表现(语气、风格、默认行为)`, + ``, + `**例子**:`, + `> 我是前端工程师,在做一个 AI-native 任务管理产品。回复用中文、简短。永远解释你的推理。优先选 TypeScript 而不是 JavaScript。`, + ``, + `点 **Save**。`, + ``, + `**怎么算成功**:你下次分给智能体一个 task,它会自动用上 context 里的信息,不需要你再解释一遍。`, + ``, + `[关于工作区 →](https://multica.ai/docs/zh/workspaces)`, + ].join("\n"), + }, + ]; + + const tier2: ImportStarterIssuePayload[] = []; + + if (q.team_size === "team") { + tier2.push({ + status: "todo", + priority: "medium", + assign_to_self: true, + title: "邀请同事加入", + description: [ + `Multica 在小团队共享智能体的场景下最好用。`, + ``, + `**在哪**:`, + `1. 侧边栏 → **Settings**(⚙️,最底部)`, + `2. 左侧 tab 列表 → 在 **[你的工作区]** 分组下 → 点 **Members**(人形图标)`, + `3. 页面顶部点 **Add member**`, + `4. 填邮箱、选角色(**Owner / Admin / Member**)`, + `5. 点 **Send invite**`, + ``, + `他们会收到一封带加入链接的邮件。已发出的邀请会出现在成员列表下方"Pending Invitations"折叠区,从那里可以撤销。`, + ``, + `[关于成员与角色 →](https://multica.ai/docs/zh/members-roles)`, + ].join("\n"), + }); + } + + if (q.role === "developer" || q.use_case === "coding") { + tier2.push({ + status: "todo", + priority: "medium", + assign_to_self: true, + title: "接入一个 Git 仓库", + description: [ + `接入后,被分配 task 的智能体可以 clone、读取、提交对你仓库的修改。`, + ``, + `**在哪**:`, + `1. 侧边栏 → **Settings**(⚙️)`, + `2. 左侧 tab 列表 → 在 **[你的工作区]** 分组下 → **Repositories**(带 Git 分支图标的文件夹)`, + `3. 列表底部点 **+ Add repository**`, + `4. 填两个字段:`, + ` - **URL** —— 例如 \`https://github.com/you/repo.git\``, + ` - **Description** —— 这个仓库是干嘛的`, + `5. 在页面顶部点 **Save**`, + ``, + `想暴露多少个仓库就重复多少次。`, + ].join("\n"), + }); + } + + tier2.push({ + status: "todo", + priority: "medium", + assign_to_self: true, + title: "再创建一个不同分工的智能体", + description: [ + `跑一个分工明确的小型智能体团队,比一个万能选手更好用。一个写代码、一个做规划、一个写文 —— 各自有各自的指令。`, + ``, + `**说明**:没有什么强制把"编码智能体"锁死在编码上。指令本质就是 system prompt,随时可改。分开是为了让每个智能体的回复更聚焦。`, + ``, + `**在哪**:`, + `1. 侧边栏 → 在 **Workspace** 分组下点 **Agents**(🤖 图标)`, + `2. 在左侧列表头部点 **+** 按钮(列表右上角)`, + `3. 按顺序填 4 个字段:`, + ` - **Name** —— 例如"规划智能体"`, + ` - **Description** —— "把零散想法拆成可执行的任务"`, + ` - **Visibility** —— Workspace(共享)或 Private(仅自己)`, + ` - **Runtime** —— 从下拉里选(你已连接的运行时)`, + `4. 点 **Create**`, + ``, + `**怎么算成功**:新智能体出现在任意 issue 的 Assignee 下拉里,也出现在 Agents 页的左侧列表。`, + ``, + `[关于创建智能体 →](https://multica.ai/docs/zh/agents-create)`, + ].join("\n"), + }); + + const tier3: ImportStarterIssuePayload[] = [ + { + status: "backlog", + priority: "low", + assign_to_self: true, + title: "打磨智能体的 Instructions", + description: [ + `创建智能体只是开始。**Instructions tab** 才是塑造它行为的地方。`, + ``, + `**在哪**:`, + `1. 侧边栏 → **Agents**(🤖)`, + `2. 在左侧列表点你想调整的智能体`, + `3. 在右侧面板顶部能看到一组 tab,包括 **Instructions / Skills / Tasks / Settings**`, + `4. 点 **Instructions**`, + `5. 编辑 markdown —— 自动保存`, + ``, + `**好的指令包含**:`, + `- 角色/人设(例如"你是一名资深 TypeScript 工程师")`, + `- 内部规则(例如"代码改动一定要附带测试")`, + `- 输出格式(例如"先一句话总结,再展开细节")`, + ``, + `Workspace Context 和智能体 Instructions 是叠加的——每个 task 都会同时带上。Instructions 写这个智能体特有的,Context 写整个工作区都适用的。`, + ].join("\n"), + }, + { + status: "backlog", + priority: "low", + assign_to_self: true, + title: "实时观看智能体工作", + description: [ + `**了解性 task** —— 现在不用做什么,知道有这个东西就行。`, + ``, + `当智能体在某个 issue 上工作时,**Activity** 区顶部会出现一张 **Live card**(滚动时会粘在视口顶部)。`, + ``, + `Live card 实时展示:`, + `- 智能体正在调用哪个工具(例如读文件、网页搜索)`, + `- 流式输出的思考与中间结果`, + `- 当前状态(thinking / tool-running / done / failed)`, + ``, + `执行结束后,Live card 下方的 **Task Run History** 列出每一次运行。任意一行点 **View transcript** 可以打开完整的可交互转录 —— 从消息、思考、工具调用到结果的完整时间线。`, + ``, + `**下次分配 task 时试一下**:保持 issue 打开,观察 Live card 在描述下方出现。`, + ``, + `[关于执行任务 →](https://multica.ai/docs/zh/tasks)`, + ].join("\n"), + }, + { + status: "backlog", + priority: "low", + assign_to_self: true, + title: "在 Inbox 里看 @提及与更新", + description: [ + `当有人——或者智能体—— @你 或者把 issue 分给你时,事件会落到你的 **Inbox**。`, + ``, + `**在哪**:`, + `1. 侧边栏 → 顶部分区(**Workspace** 分组上方)→ 点 **Inbox**(📥 图标)—— 有新消息时右侧会显示未读角标`, + ``, + `**怎么用**:`, + `- 左栏:通知列表,最新在上`, + `- 右栏:关联的 issue 内嵌打开,**自动高亮并滚动到** @你的那条具体评论`, + `- 右上下拉:**Mark all as read / Archive all / Archive all read / Archive completed** 用于批量整理`, + ``, + `**小技巧**:"Archive completed" 是清掉已经完成 issue 噪音最快的方式。`, + ``, + `[关于收件箱 →](https://multica.ai/docs/zh/inbox)`, + ].join("\n"), + }, + { + status: "backlog", + priority: "low", + assign_to_self: true, + title: "用 Autopilot 处理周期性工作", + description: [ + `**Autopilot** 把一段 prompt 变成定时 task。每天/每周/每小时自动建一个 issue 并分给智能体。`, + ``, + `**在哪**:`, + `1. 侧边栏 → 在 **Workspace** 分组下点 **Autopilot**(⚡ 闪电图标)`, + `2. 还没有 autopilot 时,会出现一组模板——任选一个会预填弹窗,或者点 **+ New autopilot** 从空白开始`, + `3. 填:**Name** / **Prompt** / **Agent** / **Schedule**(频率 + 时间 + 时区)`, + `4. 点 **Create**`, + ``, + `**第一个 autopilot 可以试什么**:每日 GitHub 活动摘要、每周"哪些 issue 被卡住"巡检、每周一早上整理还停在 Backlog 的 issue。`, + ``, + `[关于自动化 →](https://multica.ai/docs/zh/autopilots)`, + ].join("\n"), + }, + ]; + + return [...tier1, ...tier2, ...tier3]; +} + +export function buildSelfServeSubIssues( + q: QuestionnaireAnswers, +): ImportStarterIssuePayload[] { + const tier1: ImportStarterIssuePayload[] = [ + { + status: "todo", + priority: "high", + assign_to_self: true, + title: "装一个运行时(桌面应用 或 CLI)", + description: [ + `**为什么先做这个**:没有运行时 = 智能体跑不了任何 task。Tier 1 之下的所有事情都等这个。`, + ``, + `**运行时**是守护进程(一个跑在你机器上的小后台进程)和一款 AI 编程工具——Claude Code、Codex 等等——的组合。装了多款工具就会出现多个运行时。运行时是真正执行智能体接到的 task 的那一层。`, + ``, + `**方案 A —— 桌面应用(macOS,Mac 推荐)**:`, + `1. 去 [github.com/multica-ai/multica/releases/latest](https://github.com/multica-ai/multica/releases/latest) 下载 macOS 的 \`.dmg\``, + `2. 安装并打开`, + `3. 用同一个账号登录 —— 守护进程内置,到此结束`, + ``, + `**方案 B —— CLI(macOS、Linux 或 Windows + WSL)**:`, + `1. 在终端装 CLI:`, + ` \`\`\``, + ` curl -fsSL https://raw.githubusercontent.com/multica-ai/multica/main/scripts/install.sh | bash`, + ` \`\`\``, + `2. 跑 setup(登录并启动后台守护进程):`, + ` \`\`\``, + ` multica setup`, + ` \`\`\``, + ` 守护进程会在终端关闭后继续运行 —— 不需要保留终端窗口。`, + ``, + `**验证**:侧边栏 → 底部 **Configure** 区 → **Runtimes** → 应该至少看到一个已连接的运行时。`, + ``, + `[关于守护进程与运行时 →](https://multica.ai/docs/zh/daemon-runtimes)`, + ].join("\n"), + }, + { + status: "todo", + priority: "high", + assign_to_self: true, + title: "创建你的第一个智能体", + description: [ + `**前置条件**:上面那条 task 完成(运行时已连接)。`, + ``, + `**在哪**:`, + `1. 侧边栏 → 在 **Workspace** 分组下点 **Agents**(🤖 图标)`, + `2. 在左侧列表头部点 **+** 按钮(列表右上角)`, + `3. 按顺序填 4 个字段:`, + ` - **Name** —— 例如"我的编码智能体"`, + ` - **Description** —— 一句话说它做什么`, + ` - **Visibility** —— Workspace(共享)或 Private(仅自己)`, + ` - **Runtime** —— 选你刚才装的那个`, + `4. 点 **Create**`, + ``, + `**说明**:智能体本质上就是 LLM + 指令 + 工作区访问权限。没有什么强制把"编码智能体"锁死在编码上 —— 同一个智能体可以做调研、写作、规划。保持灵活。`, + ``, + `**怎么算成功**:新智能体出现在任意 issue 的 Assignee 下拉里。`, + ``, + `[关于创建智能体 →](https://multica.ai/docs/zh/agents-create)`, + ].join("\n"), + }, + ]; + + const tier2: ImportStarterIssuePayload[] = [ + { + status: "todo", + priority: "medium", + assign_to_self: true, + title: "把第一个真实 task 分给智能体", + description: [ + `**前置条件**:上面两条 task 都做完,你已经有运行时 + 智能体。`, + ``, + `**Multica 怎么触发智能体**:`, + `- 把 issue 分给智能体`, + `- 状态置为 **Todo**(不是 Backlog —— Backlog 会让智能体暂停)`, + `- 智能体自动接手`, + ``, + `**现在就试一下**:`, + `1. 在侧边栏顶部点 **New Issue**(或按 \`C\`)`, + `2. 标题:你真正想做的事`, + `3. 在右侧面板找到 **Assignee** → 点击 → 选你的智能体`, + `4. 找到 **Status** → 从 Backlog 改为 **Todo**`, + `5. 看智能体在评论里回复,Activity 里出现 **Live card**`, + ``, + `**⚠️ 容易踩**:新 issue 默认是 **Backlog**。必须翻到 **Todo** 才会触发智能体。`, + ``, + `[关于把 issue 分配给智能体 →](https://multica.ai/docs/zh/assigning-issues)`, + ].join("\n"), + }, + { + status: "todo", + priority: "medium", + assign_to_self: true, + title: "写一份 Workspace Context", + description: [ + `**Workspace Context** 是一段共享系统提示,这个工作区里每个智能体在执行任何 task 之前都会读它。这是让智能体回复更精准、最有杠杆的一件事。`, + ``, + `**在哪**:`, + `1. 打开 **侧边栏** → 滚到底部 **Configure** 区`, + `2. 点 **Settings**(⚙️ 齿轮图标,最底部那个)`, + `3. 左侧 tab 列表里,在 **[你的工作区名]** 分组下,点 **General**`, + `4. 滚到 **Context** 文本框`, + ``, + `**写 3-5 行**:`, + `- 你是谁(名字、定位)`, + `- 你在做什么(产品、项目)`, + `- 智能体应该怎么表现(语气、风格、默认行为)`, + ``, + `点 **Save**。`, + ``, + `**怎么算成功**:你下次分给智能体一个 task,它会自动用上 context 里的信息,不需要你再解释一遍。`, + ``, + `[关于工作区 →](https://multica.ai/docs/zh/workspaces)`, + ].join("\n"), + }, + ]; + + const tier3: ImportStarterIssuePayload[] = [ + { + status: "backlog", + priority: "low", + assign_to_self: true, + title: "和智能体聊天 —— 创建之后再做", + description: [ + `**前置条件**:你至少创建了一个智能体(Tier 1 #2)。`, + ``, + `不是每个问题都值得开一个 issue。要快速来回对话,用 **Chat 面板**。`, + ``, + `**在哪**:屏幕 **右下角** 有一个圆形按钮,上面是 **💬 对话气泡**。`, + ``, + `**试一下**:`, + `1. 点 💬 按钮 → 一个面板从右侧滑入`, + `2. 在输入框左下角,从下拉里选一个智能体`, + `3. 输入问题 → 按 **Enter**`, + ``, + `**附赠技巧**:在任意 issue 的评论框里输入 \`@\` 可以提及智能体或成员。`, + ``, + `[关于聊天 →](https://multica.ai/docs/zh/chat)`, + ].join("\n"), + }, + ]; + + if (q.role === "developer" || q.use_case === "coding") { + tier3.push({ + status: "backlog", + priority: "low", + assign_to_self: true, + title: "接入一个 Git 仓库", + description: [ + `接入后,被分配 task 的智能体可以 clone、读取、提交对你仓库的修改。`, + ``, + `**在哪**:`, + `1. 侧边栏 → **Settings**(⚙️)`, + `2. 左侧 tab 列表 → **Repositories**(带 Git 分支图标的文件夹)`, + `3. 列表底部点 **+ Add repository**`, + `4. 填 **URL**(例如 \`https://github.com/you/repo.git\`)和 **Description**`, + `5. 在页面顶部点 **Save**`, + ].join("\n"), + }); + } + + if (q.team_size === "team") { + tier3.push({ + status: "backlog", + priority: "low", + assign_to_self: true, + title: "邀请同事加入", + description: [ + `Multica 在小团队共享智能体的场景下最好用。`, + ``, + `**在哪**:`, + `1. 侧边栏 → **Settings**(⚙️,最底部)`, + `2. 左侧 tab 列表 → **Members**(人形图标)`, + `3. 点 **Add member** → 填邮箱 → 选角色 → **Send invite**`, + ``, + `[关于成员与角色 →](https://multica.ai/docs/zh/members-roles)`, + ].join("\n"), + }); + } + + tier3.push( + { + status: "backlog", + priority: "low", + assign_to_self: true, + title: "塑造智能体的 Instructions(创建之后再做)", + description: [ + `**前置条件**:你至少有一个智能体。`, + ``, + `创建智能体只是开始。**Instructions tab** 才是塑造它行为的地方。`, + ``, + `**在哪**:`, + `1. 侧边栏 → **Agents**(🤖)`, + `2. 在左侧列表点一个智能体`, + `3. 右侧面板 → 点 **Instructions** tab(与 Skills / Tasks / Settings 并列)`, + `4. 编辑 markdown —— 自动保存`, + ``, + `Workspace Context 和智能体 Instructions 是叠加的——每个 task 都会同时带上。Instructions 写这个智能体特有的,Context 写整个工作区都适用的。`, + ].join("\n"), + }, + { + status: "backlog", + priority: "low", + assign_to_self: true, + title: "实时观看智能体工作(分配 task 之后再做)", + description: [ + `**了解性 task** —— 现在不用做什么,知道有这个东西就行。`, + ``, + `当智能体在某个 issue 上工作时,**Activity** 区顶部会出现一张 **Live card**(滚动时会粘在视口顶部)。`, + ``, + `Live card 实时展示智能体正在调用哪个工具、流式思考、当前状态。执行结束后,下方的 **Task Run History** 列出每一次运行 —— 点 **View transcript** 可以打开完整时间线。`, + ``, + `[关于执行任务 →](https://multica.ai/docs/zh/tasks)`, + ].join("\n"), + }, + { + status: "backlog", + priority: "low", + assign_to_self: true, + title: "搭一个 Autopilot(有了智能体之后再做)", + description: [ + `**前置条件**:你至少有一个智能体。`, + ``, + `**Autopilot** 把一段 prompt 变成定时 task。每天/每周/每小时自动建一个 issue 并分给智能体。`, + ``, + `**在哪**:`, + `1. 侧边栏 → 在 **Workspace** 分组下点 **Autopilot**(⚡ 闪电图标)`, + `2. 选一个模板,或者点 **+ New autopilot** 从空白开始`, + `3. 填:**Name** / **Prompt** / **Agent** / **Schedule**(频率 + 时间 + 时区)→ **Create**`, + ``, + `[关于自动化 →](https://multica.ai/docs/zh/autopilots)`, + ].join("\n"), + }, + ); + + return [...tier1, ...tier2, ...tier3]; +} diff --git a/packages/views/onboarding/utils/starter-content-templates.ts b/packages/views/onboarding/utils/starter-content-templates.ts index 37d3ded7d..bebe6885e 100644 --- a/packages/views/onboarding/utils/starter-content-templates.ts +++ b/packages/views/onboarding/utils/starter-content-templates.ts @@ -3,25 +3,31 @@ import type { ImportStarterContentPayload, ImportStarterIssuePayload, } from "@multica/core/api"; +import * as en from "./starter-content-content-en"; +import * as zh from "./starter-content-content-zh"; // ============================================================================= -// Starter content templates. +// Starter content orchestrator. // -// Pure functions that turn the user's questionnaire answers into the request -// payload for POST /api/me/starter-content/import. No side effects, no API -// calls, no DOM — the only consumer is `StarterContentPrompt`, which passes -// the output straight to the server. +// Pure functions that turn the user's questionnaire answers + locale into +// the request payload for POST /api/me/starter-content/import. No side +// effects, no API calls, no DOM — the only consumer is `StarterContentPrompt`, +// which passes the output straight to the server. // -// Separation of concerns: -// - Markdown/copy lives here (TypeScript, reviewed as UI) -// - Batch creation + idempotency + assignee resolution lives in Go -// (handler/onboarding.go → ImportStarterContent) +// Long-form markdown bodies live in sibling files keyed by locale: +// - starter-content-content-en.ts (English) +// - starter-content-content-zh.ts (Simplified Chinese) +// +// JSON locales were considered, but ~600 lines of multi-paragraph markdown +// per language are unreadable as escaped single-line strings; keeping the +// content in TS lets reviewers see the rendered shape and catch markdown +// regressions in code review. +// +// Server-side concerns (batch creation, idempotency, assignee resolution) +// live in Go: handler/onboarding.go → ImportStarterContent. // ============================================================================= -interface WelcomeIssueText { - title: string; - description: string; -} +export type StarterContentLocale = "en" | "zh-Hans"; // Prefix titles with 1. 2. 3. … AFTER the full list is assembled so // conditional items (invite team / connect repo) don't break numbering. @@ -31,582 +37,8 @@ function numberTitles( return issues.map((s, i) => ({ ...s, title: `${i + 1}. ${s.title}` })); } -export function buildWelcomeIssueText( - q: QuestionnaireAnswers, - userName: string, -): WelcomeIssueText { - const name = userName.trim() || "there"; - - const header = [ - `Welcome to Multica! 👋`, - ``, - `This is your workspace's first issue. Below, your agent will reply in a moment — that's how work happens here: you write what you want, your agent (or a teammate) picks it up and replies in the comments.`, - ``, - `[Learn how Multica works →](https://multica.ai/docs/how-multica-works)`, - ``, - `---`, - ``, - ].join("\n"); - - const sharedInstructions = [ - `In your first reply, please:`, - ``, - `1. **Introduce yourself briefly** — your name, your role, what you're good at.`, - `2. **Explain how we work together in Multica**:`, - ` - Assigning an issue to you **and** setting its status to **Todo** is what triggers you to start (Backlog pauses you)`, - ` - @mentioning you inside a comment is for quick questions`, - ` - **Workspace Context** (in Settings → General) is shared background every agent here sees`, - `3. **Point them at the *Getting Started* project** in the sidebar and invite them to assign you a real task when they're ready.`, - ``, - `Keep it friendly and under 200 words. End with one short question that invites ${name} to reply.`, - ].join("\n"); - - // Softer variant for users who said they're just exploring — no - // pressure to "assign a real task", just pull them into a - // low-stakes conversation. - const exploreInstructions = [ - `In your first reply, please:`, - ``, - `1. **Introduce yourself briefly** — your name, your role, what you're good at.`, - `2. **Explain how we work together in Multica**:`, - ` - Assigning an issue to you **and** setting its status to **Todo** triggers you to start (Backlog pauses you)`, - ` - @mentioning you inside a comment is for quick questions`, - ` - **Workspace Context** (in Settings → General) is shared background every agent here sees`, - `3. **Point them at the *Getting Started* project** in the sidebar.`, - ``, - `Keep it friendly and under 200 words. End with a small, curious question — something like "what's something you've been wondering about lately?" — so ${name} has an easy way to reply without having to come up with a real task yet.`, - ].join("\n"); - - switch (q.use_case) { - case "coding": - return { - title: "👋 Welcome to Multica — let's work together", - description: `${header}Hi agent, this is ${name}'s first time using Multica. They plan to use you mostly for **coding work**.\n\n${sharedInstructions}`, - }; - case "planning": - return { - title: "👋 Welcome to Multica — let's work together", - description: `${header}Hi agent, this is ${name}'s first time using Multica. They want your help with **planning and breaking down work**.\n\n${sharedInstructions}`, - }; - case "writing_research": - return { - title: "👋 Welcome to Multica — let's work together", - description: `${header}Hi agent, this is ${name}'s first time using Multica. They'll use you for **research and writing** — drafting, summarizing, analysis.\n\n${sharedInstructions}`, - }; - case "explore": - return { - title: "👋 Welcome to Multica — let's work together", - description: `${header}Hi agent, this is ${name}'s first time using Multica. They're **exploring** what Multica can do — no specific goal yet.\n\n${exploreInstructions}`, - }; - case "other": { - const customUseCase = (q.use_case_other ?? "").trim(); - const contextLine = customUseCase - ? `They told us they want to use you for: "${customUseCase}".` - : `They haven't narrowed down their use case yet.`; - return { - title: "👋 Welcome to Multica — let's work together", - description: `${header}Hi agent, this is ${name}'s first time using Multica. ${contextLine}\n\n${sharedInstructions}`, - }; - } - default: - return { - title: "👋 Welcome to Multica — let's work together", - description: `${header}Hi agent, this is ${name}'s first time using Multica.\n\n${sharedInstructions}`, - }; - } -} - -export function buildAgentGuidedSubIssues( - q: QuestionnaireAnswers, -): ImportStarterIssuePayload[] { - // --- Tier 1: Core must-learn (Todo / urgent) ------------------------------ - const tier1: ImportStarterIssuePayload[] = [ - { - status: "todo", - priority: "high", - assign_to_self: true, - title: "Learn how to trigger your agent on any issue", - description: [ - `**Every issue has a right-side panel** called **Properties**. From there you control who works on what. Agents in Multica are triggered when an issue has:`, - ``, - ` Assignee = your agent AND Status = Todo (not Backlog)`, - ``, - `**Try it now**:`, - `1. In the sidebar, click **New Issue** at the top (or press \`C\`)`, - `2. Give it a title like "Test run: summarize our product in 3 bullets"`, - `3. On the right panel, find **Assignee** (third row) → click → pick your agent`, - `4. Find **Status** (top row) → click → pick **Todo**`, - `5. Scroll down to Activity — a **Live card** appears as your agent starts working`, - ``, - `**⚠️ Gotcha**: new issues default to Backlog. Agents pause on backlog. A hint dialog will pop up the first time — it's telling you "flip to Todo to start".`, - ``, - `**You'll know it worked when**: the Live card shows your agent thinking, and the Status flips to **In Progress** automatically.`, - ``, - `[Learn about assigning issues →](https://multica.ai/docs/assigning-issues)`, - ].join("\n"), - }, - { - status: "todo", - priority: "high", - assign_to_self: true, - title: "Chat with your agent — no issue required", - description: [ - `Not every question needs a whole issue. For quick back-and-forth, use the **Chat panel**.`, - ``, - `**Where to find it**: look at the **bottom-right corner of the screen** — there's a round button with a **💬 speech bubble icon**. If your agent is working, the button pulses. If there are unread replies, a red badge sits on top of it.`, - ``, - `**Try it now**:`, - `1. Click the 💬 button → a panel slides in from the right`, - `2. At the **bottom-left of the input box**, click the agent avatar → pick your agent from the dropdown`, - `3. Type a quick question: "What can you help me with in this workspace?"`, - `4. Press **Enter**`, - ``, - `**Bonus — @mention an agent inside a comment**: on any issue, scroll to the comment box at the bottom. Type \`@\` and a dropdown appears listing members, agents, and other issues. Pick an agent → write your question → send. The mentioned agent replies in the comments.`, - ``, - `**You'll know it worked when**: the agent replies in the chat panel (or comment thread) within a few seconds.`, - ``, - `[Learn about chat →](https://multica.ai/docs/chat)`, - ].join("\n"), - }, - { - status: "todo", - priority: "high", - assign_to_self: true, - title: "Write your Workspace Context", - description: [ - `**Workspace Context** is a shared system prompt every agent in this workspace reads before starting any task. It's the single most impactful thing you can do to make agent replies sharper.`, - ``, - `**Where to find it**:`, - `1. Open the **sidebar** → scroll to the bottom section labeled **Configure**`, - `2. Click **Settings** (⚙️ gear icon, bottom-most item)`, - `3. In the left-side tab list, under the **[Your Workspace Name]** group, click **General**`, - `4. Scroll down to the **Context** textarea (placeholder says "Provide context to agents...")`, - ``, - `**Fill it with 3-5 lines**:`, - `- Who you are (name, role)`, - `- What you're building or working on`, - `- How agents should behave (tone, style, defaults)`, - ``, - `**Example**:`, - `> I'm a frontend engineer working on an AI-native task manager. Reply concisely in English. Always explain your reasoning. Prefer TypeScript over JavaScript.`, - ``, - `Click **Save**.`, - ``, - `**You'll know it worked when**: the next task you assign to an agent picks up details from this context without you explaining again.`, - ``, - `[Learn about workspaces →](https://multica.ai/docs/workspaces)`, - ].join("\n"), - }, - ]; - - // --- Tier 2: Setup (Todo / medium) ---------------------------------------- - const tier2: ImportStarterIssuePayload[] = []; - - if (q.team_size === "team") { - tier2.push({ - status: "todo", - priority: "medium", - assign_to_self: true, - title: "Invite your teammates", - description: [ - `Multica works best when a small team shares agents.`, - ``, - `**Where to find it**:`, - `1. Sidebar → **Settings** (⚙️, bottom)`, - `2. Left tab list → under **[Your Workspace]** group → click **Members** (people icon)`, - `3. At the top of the page, click **Add member**`, - `4. Enter their email, pick a role (**Owner / Admin / Member**)`, - `5. Click **Send invite**`, - ``, - `They'll receive an email with a join link. Pending invites show in the collapsible "Pending Invitations" section below the member list — you can revoke from there.`, - ``, - `[Learn about members and roles →](https://multica.ai/docs/members-roles)`, - ].join("\n"), - }); - } - - if (q.role === "developer" || q.use_case === "coding") { - tier2.push({ - status: "todo", - priority: "medium", - assign_to_self: true, - title: "Connect a Git repo", - description: [ - `Once connected, any agent can clone, read, and propose changes to your repo when you assign it a task.`, - ``, - `**Where to find it**:`, - `1. Sidebar → **Settings** (⚙️)`, - `2. Left tab list → under **[Your Workspace]** group → **Repositories** (folder with Git branch icon)`, - `3. At the bottom of the list, click **+ Add repository**`, - `4. Fill the two inline fields:`, - ` - **URL** — e.g. \`https://github.com/you/repo.git\``, - ` - **Description** — what this repo is for`, - `5. Click **Save** at the top of the page`, - ``, - `Repeat for as many repos as you want to expose.`, - ].join("\n"), - }); - } - - tier2.push({ - status: "todo", - priority: "medium", - assign_to_self: true, - title: "Create a second agent with a different role", - description: [ - `Running a small team of focused agents beats a single generalist. One for coding, one for planning, one for writing — each with their own instructions.`, - ``, - `**Note**: nothing locks a "Coding Agent" to coding. Instructions are just a system prompt, editable anytime. The split is about keeping each one's replies sharp.`, - ``, - `**Where to find it**:`, - `1. Sidebar → under **Workspace** group → click **Agents** (🤖 bot icon)`, - `2. In the left list header, click the **+** button (top-right corner of the list)`, - `3. Fill the 4 fields in order:`, - ` - **Name** — e.g. "Planning Agent"`, - ` - **Description** — "Breaks down loose ideas into scoped work"`, - ` - **Visibility** — Workspace (shared) or Private (only you)`, - ` - **Runtime** — pick from the dropdown (your connected runtime)`, - `4. Click **Create**`, - ``, - `**You'll know it worked when**: the new agent appears in the Assignee dropdown on any issue, and shows up in the left list on the Agents page.`, - ``, - `[Learn about creating agents →](https://multica.ai/docs/agents-create)`, - ].join("\n"), - }); - - // --- Tier 3: Advanced, discover later (Backlog) --------------------------- - const tier3: ImportStarterIssuePayload[] = [ - { - status: "backlog", - priority: "low", - assign_to_self: true, - title: "Polish your agent's Instructions", - description: [ - `Creating an agent is just the start. The **Instructions tab** is where you shape how it behaves.`, - ``, - `**Where to find it**:`, - `1. Sidebar → **Agents** (🤖)`, - `2. In the left list, click an agent you want to refine`, - `3. In the right panel, you'll see 6 tabs at the top: **Instructions / Skills / Tasks / Environment / Custom Args / Settings**`, - `4. Click **Instructions**`, - `5. Edit the markdown — changes save automatically`, - ``, - `**Good instructions include**:`, - `- The role/persona (e.g. "You're a senior TypeScript engineer")`, - `- House rules (e.g. "Always propose tests alongside code")`, - `- Output format (e.g. "Return a short summary first, details below")`, - ``, - `Workspace Context and agent Instructions stack — both are sent on every task. Keep Instructions specific to this agent; keep Context specific to the whole workspace.`, - ].join("\n"), - }, - { - status: "backlog", - priority: "low", - assign_to_self: true, - title: "Watch your agent live in action", - description: [ - `**Heads-up task** — nothing to do now, just know this exists.`, - ``, - `When an agent is working on an issue, a **Live card** appears at the top of the **Activity** section (it sticks to the top of the viewport as you scroll).`, - ``, - `The card shows in real time:`, - `- Which tool the agent is calling (e.g. reading a file, web search)`, - `- Streaming thoughts and partial output`, - `- Current status (thinking / tool-running / done / failed)`, - ``, - `After the run finishes, the **Task Run History** below the card lists every past run. Click **View transcript** on any row to open the full interactive transcript — a timeline of every message, thinking step, tool call, and result.`, - ``, - `**Try it next time you assign an agent**: keep the issue open and watch the Live card appear below the description.`, - ``, - `[Learn about tasks →](https://multica.ai/docs/tasks)`, - ].join("\n"), - }, - { - status: "backlog", - priority: "low", - assign_to_self: true, - title: "Check your Inbox for @mentions and updates", - description: [ - `When someone — or an agent — @mentions you or assigns you an issue, it lands in your **Inbox**.`, - ``, - `**Where to find it**:`, - `1. Sidebar → the top section (above the **Workspace** group) → click **Inbox** (📥 icon) — an unread count badge shows on the right if you have new items`, - ``, - `**How it works**:`, - `- Left column: notification list, newest first`, - `- Right column: the linked issue opens inline, and the specific comment that mentioned you is **auto-highlighted and scrolled into view**`, - `- Top-right dropdown: **Mark all as read / Archive all / Archive all read / Archive completed** for bulk cleanup`, - ``, - `**Tip**: "Archive completed" is the fastest way to clear the noise from issues already finished.`, - ``, - `[Learn about the inbox →](https://multica.ai/docs/inbox)`, - ].join("\n"), - }, - { - status: "backlog", - priority: "low", - assign_to_self: true, - title: "Set up an Autopilot for recurring work", - description: [ - `**Autopilot** turns a prompt into a scheduled task. Every day/week/hour, it auto-creates an issue and assigns it to an agent.`, - ``, - `**Where to find it**:`, - `1. Sidebar → under **Workspace** group → click **Autopilot** (⚡ Zap icon)`, - `2. If you have no autopilots yet, a grid of **6 templates** shows up: Daily news digest, PR review reminder, Bug triage, Weekly progress report, Dependency audit, Documentation check`, - `3. Click any template → creation dialog opens pre-filled (or click **+ New autopilot** top-right for a blank one)`, - `4. Fill: **Name** / **Prompt** (6-line textarea) / **Agent** / **Schedule** (frequency + time + timezone)`, - `5. Click **Create**`, - ``, - `**Good first autopilots**: daily digest of GitHub activity, weekly "what's blocked" check, or a Monday-morning triage of any issues still in Backlog.`, - ``, - `[Learn about autopilots →](https://multica.ai/docs/autopilots)`, - ].join("\n"), - }, - ]; - - return numberTitles([...tier1, ...tier2, ...tier3]); -} - -export function buildSelfServeSubIssues( - q: QuestionnaireAnswers, -): ImportStarterIssuePayload[] { - // --- Tier 1: Unlock agent ability (Todo / high) --------------------------- - // Without a runtime + an agent, nothing else in Multica works. These two - // are the gates — everything below them waits on them. - const tier1: ImportStarterIssuePayload[] = [ - { - status: "todo", - priority: "high", - assign_to_self: true, - title: "Install a runtime (Desktop app or CLI)", - description: [ - `**Why this first**: no runtime = no agents can execute. Everything below Tier 1 waits on this.`, - ``, - `A **runtime** is a small background process that runs on your machine. It connects your workspace to AI coding tools (Claude Code, Codex, …) and executes the tasks your agents pick up.`, - ``, - `**Option A — Desktop app (macOS, recommended if you're on a Mac)**:`, - `1. Go to [github.com/multica-ai/multica/releases/latest](https://github.com/multica-ai/multica/releases/latest) and download the \`.dmg\` for macOS`, - `2. Install and open the app`, - `3. Sign in with the same account — the runtime is built in, you're done`, - ``, - `**Option B — CLI (macOS, Linux, or Windows via WSL)**:`, - `1. In a terminal, install the CLI:`, - ` \`\`\``, - ` curl -fsSL https://raw.githubusercontent.com/multica-ai/multica/main/scripts/install.sh | bash`, - ` \`\`\``, - `2. Then run setup (signs you in and starts a background daemon):`, - ` \`\`\``, - ` multica setup`, - ` \`\`\``, - ` The daemon keeps running after you close the terminal — you don't have to leave anything open.`, - ``, - `**Verify**: sidebar → bottom **Configure** section → **Runtimes** → you should see at least one connected runtime.`, - ``, - `[Learn about runtimes →](https://multica.ai/docs/daemon-runtimes)`, - ].join("\n"), - }, - { - status: "todo", - priority: "high", - assign_to_self: true, - title: "Create your first agent", - description: [ - `**Prerequisite**: task above done (runtime connected).`, - ``, - `**Where to find it**:`, - `1. Sidebar → under **Workspace** group → click **Agents** (🤖 bot icon)`, - `2. In the left list header, click the **+** button (top-right corner of the list)`, - `3. Fill the 4 fields in order:`, - ` - **Name** — e.g. "My Coding Agent"`, - ` - **Description** — one line about what it does`, - ` - **Visibility** — Workspace (shared) or Private (only you)`, - ` - **Runtime** — pick the one you just installed`, - `4. Click **Create**`, - ``, - `**Note**: an agent is just an LLM + instructions + workspace access. Nothing locks a "Coding Agent" to coding — same agent can do research, writing, planning. Keep it flexible.`, - ``, - `**You'll know it worked when**: the new agent appears in the Assignee dropdown on any issue.`, - ``, - `[Learn about creating agents →](https://multica.ai/docs/agents-create)`, - ].join("\n"), - }, - ]; - - // --- Tier 2: Core usage after unlock (Todo / medium) ---------------------- - const tier2: ImportStarterIssuePayload[] = [ - { - status: "todo", - priority: "medium", - assign_to_self: true, - title: "Assign your first real task to your agent", - description: [ - `**Prerequisite**: you have a runtime + agent from the two tasks above.`, - ``, - `**How Multica triggers agents**:`, - `- Assign an issue to an agent`, - `- Set status to **Todo** (not Backlog — backlog pauses agents)`, - `- The agent picks it up automatically`, - ``, - `**Try it now**:`, - `1. In the sidebar, click **New Issue** at the top (or press \`C\`)`, - `2. Title: something you actually want done`, - `3. On the right panel, find **Assignee** → click → pick your agent`, - `4. Find **Status** → change from Backlog to **Todo**`, - `5. Watch the agent reply in the comments and a **Live card** appear in Activity`, - ``, - `**⚠️ Gotcha**: new issues default to **Backlog**. You must flip to **Todo** to trigger the agent.`, - ``, - `[Learn about assigning issues →](https://multica.ai/docs/assigning-issues)`, - ].join("\n"), - }, - { - status: "todo", - priority: "medium", - assign_to_self: true, - title: "Write your Workspace Context", - description: [ - `**Workspace Context** is a shared system prompt every agent in this workspace reads before starting any task. It's the single most impactful thing you can do to make agent replies sharper.`, - ``, - `**Where to find it**:`, - `1. Open the **sidebar** → scroll to the bottom section labeled **Configure**`, - `2. Click **Settings** (⚙️ gear icon, bottom-most item)`, - `3. In the left-side tab list, under the **[Your Workspace Name]** group, click **General**`, - `4. Scroll down to the **Context** textarea`, - ``, - `**Fill it with 3-5 lines**:`, - `- Who you are (name, role)`, - `- What you're building or working on`, - `- How agents should behave (tone, style, defaults)`, - ``, - `Click **Save**.`, - ``, - `**You'll know it worked when**: the next task you assign to an agent picks up details from this context without you explaining again.`, - ``, - `[Learn about workspaces →](https://multica.ai/docs/workspaces)`, - ].join("\n"), - }, - ]; - - // --- Tier 3: Advanced, discover later (Backlog) --------------------------- - const tier3: ImportStarterIssuePayload[] = [ - { - status: "backlog", - priority: "low", - assign_to_self: true, - title: "Chat with an agent — once you've created one", - description: [ - `**Prerequisite**: you've created at least one agent (Tier 1 #2).`, - ``, - `Not every question needs a whole issue. For quick back-and-forth, use the **Chat panel**.`, - ``, - `**Where to find it**: the **bottom-right corner of the screen** has a round button with a **💬 speech bubble icon**.`, - ``, - `**Try it**:`, - `1. Click the 💬 button → a panel slides in from the right`, - `2. At the bottom-left of the input box, pick an agent from the dropdown`, - `3. Type a question → press **Enter**`, - ``, - `**Bonus**: inside any issue's comment box, type \`@\` to mention an agent or member.`, - ``, - `[Learn about chat →](https://multica.ai/docs/chat)`, - ].join("\n"), - }, - ]; - - if (q.role === "developer" || q.use_case === "coding") { - tier3.push({ - status: "backlog", - priority: "low", - assign_to_self: true, - title: "Connect a Git repo", - description: [ - `Once connected, any agent can clone, read, and propose changes to your repo when you assign it a task.`, - ``, - `**Where to find it**:`, - `1. Sidebar → **Settings** (⚙️)`, - `2. Left tab list → **Repositories** (folder with Git branch icon)`, - `3. At the bottom of the list, click **+ Add repository**`, - `4. Fill **URL** (e.g. \`https://github.com/you/repo.git\`) and **Description**`, - `5. Click **Save** at the top of the page`, - ].join("\n"), - }); - } - - if (q.team_size === "team") { - tier3.push({ - status: "backlog", - priority: "low", - assign_to_self: true, - title: "Invite your teammates", - description: [ - `Multica works best when a small team shares agents.`, - ``, - `**Where to find it**:`, - `1. Sidebar → **Settings** (⚙️, bottom)`, - `2. Left tab list → **Members** (people icon)`, - `3. Click **Add member** → enter email → pick role → **Send invite**`, - ``, - `[Learn about members and roles →](https://multica.ai/docs/members-roles)`, - ].join("\n"), - }); - } - - tier3.push( - { - status: "backlog", - priority: "low", - assign_to_self: true, - title: "Shape your agent's Instructions (once it's created)", - description: [ - `**Prerequisite**: you have at least one agent.`, - ``, - `Creating an agent is just the start. The **Instructions tab** is where you shape how it behaves.`, - ``, - `**Where to find it**:`, - `1. Sidebar → **Agents** (🤖)`, - `2. Click an agent in the left list`, - `3. Right panel → click the **Instructions** tab (out of 6: Instructions / Skills / Tasks / Environment / Custom Args / Settings)`, - `4. Edit the markdown — changes save automatically`, - ``, - `Workspace Context and agent Instructions stack — both are sent on every task. Keep Instructions specific to this agent; keep Context specific to the whole workspace.`, - ].join("\n"), - }, - { - status: "backlog", - priority: "low", - assign_to_self: true, - title: "Watch an agent work live (once you've assigned one a task)", - description: [ - `**Heads-up task** — nothing to do now, just know this exists.`, - ``, - `When an agent is working on an issue, a **Live card** appears at the top of the **Activity** section (it sticks to the top of the viewport as you scroll).`, - ``, - `It shows in real time which tool the agent is calling, streaming thoughts, and current status. After the run finishes, the **Task Run History** below the card lists every past run — click **View transcript** to open the full timeline.`, - ``, - `[Learn about tasks →](https://multica.ai/docs/tasks)`, - ].join("\n"), - }, - { - status: "backlog", - priority: "low", - assign_to_self: true, - title: "Set up an Autopilot (once you have an agent)", - description: [ - `**Prerequisite**: you have at least one agent.`, - ``, - `**Autopilot** turns a prompt into a scheduled task. Every day/week/hour, it auto-creates an issue and assigns it to an agent.`, - ``, - `**Where to find it**:`, - `1. Sidebar → under **Workspace** group → click **Autopilot** (⚡ Zap icon)`, - `2. Pick one of 6 templates, or click **+ New autopilot** top-right`, - `3. Fill: **Name** / **Prompt** / **Agent** / **Schedule** (frequency + time + timezone) → **Create**`, - ``, - `[Learn about autopilots →](https://multica.ai/docs/autopilots)`, - ].join("\n"), - }, - ); - - return numberTitles([...tier1, ...tier2, ...tier3]); +function pickContent(locale: StarterContentLocale) { + return locale === "zh-Hans" ? zh : en; } /** @@ -620,18 +52,20 @@ export function buildImportPayload({ workspaceId, userName, questionnaire, + locale, }: { workspaceId: string; userName: string; questionnaire: QuestionnaireAnswers; + locale: StarterContentLocale; }): ImportStarterContentPayload { - const welcome = buildWelcomeIssueText(questionnaire, userName); + const content = pickContent(locale); + const welcome = content.buildWelcomeIssueText(questionnaire, userName); return { workspace_id: workspaceId, project: { - title: "Getting Started", - description: - "A few things to try in Multica. Work through them at your own pace.", + title: content.PROJECT.title, + description: content.PROJECT.description, icon: "👋", }, welcome_issue_template: { @@ -639,7 +73,11 @@ export function buildImportPayload({ description: welcome.description, priority: "high", }, - agent_guided_sub_issues: buildAgentGuidedSubIssues(questionnaire), - self_serve_sub_issues: buildSelfServeSubIssues(questionnaire), + agent_guided_sub_issues: numberTitles( + content.buildAgentGuidedSubIssues(questionnaire), + ), + self_serve_sub_issues: numberTitles( + content.buildSelfServeSubIssues(questionnaire), + ), }; }