| 1 | /** |
| 2 | * docs-tasks.ts — the task-based index of codewhale.net documentation. |
| 3 | * |
| 4 | * `docs-map.ts` answers "what topics exist"; this registry answers "I am |
| 5 | * trying to do X — where do I go". Every task points at a first-party route |
| 6 | * (locale-relative, so `/${locale}${href}` always exists) and names the |
| 7 | * topic it belongs to, so the hub can search tasks and topics together and |
| 8 | * `docs-tasks.test.ts` can prove every target resolves. |
| 9 | * |
| 10 | * TRUTH CONTRACT: a task may only describe behaviour the target page (and |
| 11 | * its repository source document) actually documents. Keep the verbs |
| 12 | * concrete and keep the list short enough to read in one screen. |
| 13 | * |
| 14 | * Labels are `{ en, zh }` pairs like docs-map.ts; other locales fall back to |
| 15 | * English through `pickText`. |
| 16 | */ |
| 17 | import type { LocalizedText } from "./content/vocabulary"; |
| 18 | import { DOC_TOPICS, type DocTopic } from "./docs-map"; |
| 19 | |
| 20 | export interface DocTask { |
| 21 | id: string; |
| 22 | label: LocalizedText; |
| 23 | description: LocalizedText; |
| 24 | /** Locale-relative route, e.g. "/install" or "/docs/modes". */ |
| 25 | href: string; |
| 26 | /** Owning docs-map topic id, for grouping and source attribution. */ |
| 27 | topicId: DocTopic["id"]; |
| 28 | /** Extra search words, both languages, lowercase not required. */ |
| 29 | keywords: LocalizedText; |
| 30 | } |
| 31 | |
| 32 | export const DOC_TASKS: DocTask[] = [ |
| 33 | { |
| 34 | id: "install", |
| 35 | label: { en: "Install Codewhale", zh: "安装 Codewhale" }, |
| 36 | description: { |
| 37 | en: "One command on macOS or Linux; npm, Cargo, release binaries, and the Homebrew tap on Linux also work.", |
| 38 | zh: "在 macOS 或 Linux 上只需一条命令;也可以用 npm、Cargo、发布版二进制文件,或在 Linux 上用 Homebrew tap 安装。", |
| 39 | }, |
| 40 | href: "/install", |
| 41 | topicId: "install", |
| 42 | keywords: { en: "download setup brew npm cargo docker termux binary windows", zh: "下载 安装 二进制 镜像" }, |
| 43 | }, |
| 44 | { |
| 45 | id: "first-task", |
| 46 | label: { en: "Start your first task", zh: "开始第一个任务" }, |
| 47 | description: { |
| 48 | en: "Open Codewhale in a project, look around in Plan, then let it edit in Work.", |
| 49 | zh: "在项目中打开 Codewhale,先在 Plan 里了解项目,再让它在 Work 里动手修改。", |
| 50 | }, |
| 51 | href: "/docs/guide", |
| 52 | topicId: "guide", |
| 53 | keywords: { en: "getting started quickstart tutorial first run", zh: "入门 快速开始 教程 首次运行" }, |
| 54 | }, |
| 55 | { |
| 56 | id: "connect-provider", |
| 57 | label: { en: "Connect a provider", zh: "连接模型提供商" }, |
| 58 | description: { |
| 59 | en: "Save a key for DeepSeek, OpenAI, Anthropic, OpenRouter, or another provider — or run a local model with no key.", |
| 60 | zh: "为 DeepSeek、OpenAI、Anthropic、OpenRouter 等提供商保存密钥,或者不用密钥运行本地模型。", |
| 61 | }, |
| 62 | href: "/docs/auth", |
| 63 | topicId: "auth", |
| 64 | keywords: { en: "api key byok auth set login account ollama vllm sglang local", zh: "密钥 登录 账户 本地模型" }, |
| 65 | }, |
| 66 | { |
| 67 | id: "choose-model", |
| 68 | label: { en: "Choose or switch models", zh: "选择或切换模型" }, |
| 69 | description: { |
| 70 | en: "Supported providers, switching mid-session, and local runners.", |
| 71 | zh: "支持的提供商、在会话中切换模型,以及本地运行器。", |
| 72 | }, |
| 73 | href: "/models", |
| 74 | topicId: "providers", |
| 75 | keywords: { en: "model switch provider openai-compatible", zh: "模型 切换 提供商" }, |
| 76 | }, |
| 77 | { |
| 78 | id: "set-approvals", |
| 79 | label: { en: "Decide what runs without asking", zh: "决定哪些操作无需询问" }, |
| 80 | description: { |
| 81 | en: "Plan, Work, or Operate; Ask, Auto-Review, or Full Access; and how to answer a prompt.", |
| 82 | zh: "Plan、Work 或 Operate;Ask、Auto-Review 或 Full Access;以及如何回应审批提示。", |
| 83 | }, |
| 84 | href: "/docs/modes", |
| 85 | topicId: "modes", |
| 86 | keywords: { en: "mode tab shift+tab ask auto-review full access permission", zh: "模式 审批 权限" }, |
| 87 | }, |
| 88 | { |
| 89 | id: "review-changes", |
| 90 | label: { en: "Review what changed", zh: "查看改动" }, |
| 91 | description: { |
| 92 | en: "See every edit, roll files back to an earlier turn, and get a code review before you push.", |
| 93 | zh: "查看每一处修改,把文件回滚到之前的回合,并在推送前做代码审查。", |
| 94 | }, |
| 95 | href: "/docs/review", |
| 96 | topicId: "review", |
| 97 | keywords: { en: "diff undo restore rollback snapshot code review", zh: "差异 撤销 回滚 快照 审查" }, |
| 98 | }, |
| 99 | { |
| 100 | id: "receipts", |
| 101 | label: { en: "Keep a receipt of a review", zh: "为审查保留收据" }, |
| 102 | description: { |
| 103 | en: "Write a review receipt and check it before you push.", |
| 104 | zh: "生成审查收据,并在推送前核对它。", |
| 105 | }, |
| 106 | href: "/docs/review", |
| 107 | topicId: "review", |
| 108 | keywords: { en: "receipt write-receipt check-receipt pre-push export", zh: "收据 推送 导出" }, |
| 109 | }, |
| 110 | { |
| 111 | id: "run-workflow", |
| 112 | label: { en: "Run a workflow", zh: "运行 Workflow" }, |
| 113 | description: { |
| 114 | en: "Write a repeatable Workflow, run it as a Lane, and watch or stop it from any terminal.", |
| 115 | zh: "编写可重复的 Workflow,把它作为 Lane 运行,并在任何终端查看或停止它。", |
| 116 | }, |
| 117 | href: "/docs/fleet", |
| 118 | topicId: "fleet", |
| 119 | keywords: { en: "fleet workflow lane operate durable tasks.json", zh: "编排 持久 工作流" }, |
| 120 | }, |
| 121 | { |
| 122 | id: "parallel-agents", |
| 123 | label: { en: "Run agents in parallel", zh: "并行运行 Agent" }, |
| 124 | description: { |
| 125 | en: "Roles, separate worktrees for parallel edits, and how to watch sub-agents.", |
| 126 | zh: "角色、为并行修改准备的独立工作树,以及如何查看子 Agent。", |
| 127 | }, |
| 128 | href: "/docs/subagents", |
| 129 | topicId: "subagents", |
| 130 | keywords: { en: "agent explore reviewer implement worktree concurrency subagents", zh: "子代理 并行 角色 工作树" }, |
| 131 | }, |
| 132 | { |
| 133 | id: "mcp-server", |
| 134 | label: { en: "Connect tools with MCP", zh: "用 MCP 连接工具" }, |
| 135 | description: { |
| 136 | en: "Add a local or remote MCP server, sign in with OAuth, or serve Codewhale over MCP.", |
| 137 | zh: "添加本地或远程 MCP 服务器、用 OAuth 登录,或把 Codewhale 作为 MCP 服务器提供。", |
| 138 | }, |
| 139 | href: "/docs/mcp", |
| 140 | topicId: "mcp", |
| 141 | keywords: { en: "model context protocol tools stdio http oauth", zh: "工具 协议 服务器" }, |
| 142 | }, |
| 143 | { |
| 144 | id: "code-mode", |
| 145 | label: { en: "Try code mode", zh: "试用代码模式" }, |
| 146 | description: { |
| 147 | en: "Let the model compose several read-only tool calls in one short program. Experimental.", |
| 148 | zh: "让模型在一段简短的程序中组合多个只读工具调用。实验性功能。", |
| 149 | }, |
| 150 | href: "/docs/mcp", |
| 151 | topicId: "mcp", |
| 152 | keywords: { en: "code_mode execute_tools javascript experimental", zh: "代码模式 实验" }, |
| 153 | }, |
| 154 | { |
| 155 | id: "hooks", |
| 156 | label: { en: "Run commands on events", zh: "在事件发生时运行命令" }, |
| 157 | description: { |
| 158 | en: "Block a risky command, add context, or get notified when Codewhale waits for you.", |
| 159 | zh: "拦下危险命令、补充上下文,或在 Codewhale 等你回应时收到提醒。", |
| 160 | }, |
| 161 | href: "/docs/hooks", |
| 162 | topicId: "hooks", |
| 163 | keywords: { en: "hook lifecycle tool_call_before session_start event", zh: "钩子 生命周期 事件" }, |
| 164 | }, |
| 165 | { |
| 166 | id: "sandbox", |
| 167 | label: { en: "Limit what commands can touch", zh: "限制命令的访问范围" }, |
| 168 | description: { |
| 169 | en: "See which OS sandbox your platform has and turn on bubblewrap on Linux.", |
| 170 | zh: "了解你的平台有哪种操作系统沙箱,并在 Linux 上开启 bubblewrap。", |
| 171 | }, |
| 172 | href: "/docs/sandbox", |
| 173 | topicId: "sandbox", |
| 174 | keywords: { en: "sandbox seatbelt bwrap bubblewrap workspace-write", zh: "沙箱 隔离" }, |
| 175 | }, |
| 176 | { |
| 177 | id: "automate", |
| 178 | label: { en: "Automate with the Runtime API", zh: "用 Runtime API 自动化" }, |
| 179 | description: { |
| 180 | en: "Run one-shot jobs in CI, or drive threads and approvals over the local HTTP API.", |
| 181 | zh: "在 CI 中运行一次性任务,或通过本地 HTTP API 驱动线程和审批。", |
| 182 | }, |
| 183 | href: "/docs/runtime-api", |
| 184 | topicId: "runtime-api", |
| 185 | keywords: { en: "http api exec ci acp integration sse", zh: "接口 集成 脚本" }, |
| 186 | }, |
| 187 | { |
| 188 | id: "browser-client", |
| 189 | label: { en: "Open the browser client", zh: "打开浏览器客户端" }, |
| 190 | description: { |
| 191 | en: "Work in a local browser tab, or continue a session from the web app with /rc.", |
| 192 | zh: "在本机浏览器标签页中工作,或用 /rc 在网页应用中继续会话。", |
| 193 | }, |
| 194 | href: "/docs/web", |
| 195 | topicId: "web", |
| 196 | keywords: { en: "web ui localhost loopback remote control rc", zh: "网页 客户端 本机 远程" }, |
| 197 | }, |
| 198 | { |
| 199 | id: "cloud-computer", |
| 200 | label: { en: "Send a task to the cloud", zh: "把任务发送到云端" }, |
| 201 | description: { |
| 202 | en: "Preview: propose and confirm a cloud agent that opens a pull request.", |
| 203 | zh: "预览版:提议并确认一个会提交拉取请求的云端 Agent。", |
| 204 | }, |
| 205 | href: "/docs/computers", |
| 206 | topicId: "computers", |
| 207 | keywords: { en: "dispatch cloud agent daytona remote github cnb gitee", zh: "云端 派发 远程" }, |
| 208 | }, |
| 209 | { |
| 210 | id: "troubleshoot", |
| 211 | label: { en: "Fix a problem", zh: "排查问题" }, |
| 212 | description: { |
| 213 | en: "Diagnose in one command, then fix install, key, network, and stuck-turn problems.", |
| 214 | zh: "用一条命令诊断,再解决安装、密钥、网络和回合卡住等问题。", |
| 215 | }, |
| 216 | href: "/docs/troubleshooting", |
| 217 | topicId: "troubleshooting", |
| 218 | keywords: { en: "error crash doctor diagnose recover resume docker", zh: "错误 崩溃 诊断 恢复" }, |
| 219 | }, |
| 220 | { |
| 221 | id: "trust", |
| 222 | label: { en: "See what leaves your machine", zh: "了解哪些数据会离开本机" }, |
| 223 | description: { |
| 224 | en: "What a provider receives, what usage counting sends, and how to turn it off.", |
| 225 | zh: "提供商会收到什么、用量统计发送什么,以及如何关闭。", |
| 226 | }, |
| 227 | href: "/docs/trust", |
| 228 | topicId: "trust", |
| 229 | keywords: { en: "privacy security telemetry data vulnerability report", zh: "隐私 安全 遥测 数据 漏洞" }, |
| 230 | }, |
| 231 | ]; |
| 232 | |
| 233 | /** The owning topic for a task, or undefined if the registry drifted. */ |
| 234 | export function taskTopic(task: DocTask): DocTopic | undefined { |
| 235 | return DOC_TOPICS.find((t) => t.id === task.topicId); |
| 236 | } |
| 237 | |
| 238 | /** Lowercase haystack across both languages, the route, and the topic. */ |
| 239 | export function docTaskHaystack(task: DocTask): string { |
| 240 | return [ |
| 241 | task.id, |
| 242 | task.label.en, |
| 243 | task.label.zh, |
| 244 | task.description.en, |
| 245 | task.description.zh, |
| 246 | task.keywords.en, |
| 247 | task.keywords.zh, |
| 248 | task.href, |
| 249 | task.topicId, |
| 250 | ] |
| 251 | .join(" ") |
| 252 | .toLowerCase(); |
| 253 | } |
| 254 |