| 1 | /** |
| 2 | * docs-map.ts — canonical documentation registry for codewhale.net. |
| 3 | * |
| 4 | * Maps every first-class documentation topic area to its repo source file(s) |
| 5 | * and website route. This is the single source of truth for the docs hub |
| 6 | * sidebar, breadcrumbs, and drift/parity checks. |
| 7 | * |
| 8 | * EXTENSION PATH FOR NEW LOCALES: |
| 9 | * Labels are keyed by locale. Add a new locale column and update the page |
| 10 | * components that consume this map. The topic IDs, slugs, and repo sources |
| 11 | * are locale-agnostic. |
| 12 | */ |
| 13 | |
| 14 | export interface DocTopic { |
| 15 | /** Stable identifier used in routes and anchors. */ |
| 16 | id: string; |
| 17 | /** URL slug for the docs sub-route (e.g. "install"). */ |
| 18 | slug: string; |
| 19 | /** Label per locale. */ |
| 20 | label: { en: string; zh: string }; |
| 21 | /** Short description per locale. */ |
| 22 | description: { en: string; zh: string }; |
| 23 | /** Repo source file(s) — the canonical markdown doc in the repo. */ |
| 24 | repoSource: string | string[]; |
| 25 | /** Whether this topic has a dedicated website page (vs. linking out). */ |
| 26 | hasPage: boolean; |
| 27 | /** Locale-relative website path when the page lives outside `/docs/<slug>`. */ |
| 28 | sitePath?: string; |
| 29 | /** Category for grouping in the sidebar. */ |
| 30 | category: "getting-started" | "core-concepts" | "reference" | "extending" | "operations"; |
| 31 | } |
| 32 | |
| 33 | /** Sidebar and breadcrumb labels for each docs-map category. */ |
| 34 | export const DOC_CATEGORY_LABELS: Record<DocTopic["category"], { en: string; zh: string }> = { |
| 35 | "getting-started": { en: "Getting started", zh: "入门" }, |
| 36 | "core-concepts": { en: "Core concepts", zh: "核心概念" }, |
| 37 | reference: { en: "Reference", zh: "参考" }, |
| 38 | extending: { en: "Extending", zh: "扩展" }, |
| 39 | operations: { en: "Operations", zh: "运维" }, |
| 40 | }; |
| 41 | |
| 42 | export const DOC_TOPICS: DocTopic[] = [ |
| 43 | { |
| 44 | id: "install", |
| 45 | slug: "install", |
| 46 | label: { en: "Install", zh: "安装" }, |
| 47 | description: { |
| 48 | en: "npm, Cargo, Homebrew, Docker, prebuilt binaries, CNB mirror, and where config lives.", |
| 49 | zh: "npm、Cargo、Homebrew、Docker、预编译二进制、CNB 镜像,以及配置文件位置。", |
| 50 | }, |
| 51 | repoSource: "docs/INSTALL.md", |
| 52 | hasPage: true, |
| 53 | sitePath: "install", |
| 54 | category: "getting-started", |
| 55 | }, |
| 56 | { |
| 57 | id: "guide", |
| 58 | slug: "guide", |
| 59 | label: { en: "User Guide", zh: "使用指南" }, |
| 60 | description: { |
| 61 | en: "First run, sessions, commands, keyboard shortcuts, and everyday workflows.", |
| 62 | zh: "首次运行、会话、命令、快捷键和日常使用流程。", |
| 63 | }, |
| 64 | repoSource: ["docs/GUIDE.md", "docs/KEYBINDINGS.md"], |
| 65 | hasPage: true, |
| 66 | category: "getting-started", |
| 67 | }, |
| 68 | { |
| 69 | id: "vocabulary", |
| 70 | slug: "vocabulary", |
| 71 | label: { en: "Vocabulary", zh: "产品名词" }, |
| 72 | description: { |
| 73 | en: "The exact product nouns — Fleet, Workflow, Lane, Runtime; Plan / Work / Operate; Advisor; and explicit route provenance — plus measurement principles.", |
| 74 | zh: "确切的产品名词——Fleet、Workflow、Lane、Runtime;Plan / Work / Operate;Advisor;明确的路由来源——以及测量原则。", |
| 75 | }, |
| 76 | repoSource: ["docs/FLEET.md", "docs/MODES.md", "docs/public-surface-facts.json"], |
| 77 | hasPage: true, |
| 78 | category: "core-concepts", |
| 79 | }, |
| 80 | { |
| 81 | id: "configuration", |
| 82 | slug: "configuration", |
| 83 | label: { en: "Configuration", zh: "配置" }, |
| 84 | description: { |
| 85 | en: "config.toml reference, environment variables, project overrides, and legacy paths.", |
| 86 | zh: "config.toml 参考、环境变量、项目覆盖和旧版路径。", |
| 87 | }, |
| 88 | repoSource: ["docs/CONFIGURATION.md", "docs/LEGACY_PATHS.md"], |
| 89 | hasPage: true, |
| 90 | category: "getting-started", |
| 91 | }, |
| 92 | { |
| 93 | id: "auth", |
| 94 | slug: "auth", |
| 95 | label: { en: "Account & Keys", zh: "账户与密钥" }, |
| 96 | description: { |
| 97 | en: "Provider keys versus the optional Codewhale account: how each is set, where each is stored, and what needs no account.", |
| 98 | zh: "提供商密钥与可选的 Codewhale 账户:各自如何设置、存放在哪里,以及哪些操作不需要账户。", |
| 99 | }, |
| 100 | repoSource: ["docs/CONFIGURATION.md", "docs/CODEWHALE_AGENT.md"], |
| 101 | hasPage: true, |
| 102 | category: "getting-started", |
| 103 | }, |
| 104 | { |
| 105 | id: "providers", |
| 106 | slug: "providers", |
| 107 | label: { en: "Providers & Models", zh: "提供商与模型" }, |
| 108 | description: { |
| 109 | en: "Supported providers, model switching, local runtimes (vLLM, Ollama, SGLang), and Model Lab.", |
| 110 | zh: "支持的提供商、模型切换、本地运行时(vLLM、Ollama、SGLang)和模型实验室。", |
| 111 | }, |
| 112 | repoSource: ["docs/PROVIDERS.md", "docs/MODEL_LAB.md"], |
| 113 | hasPage: true, |
| 114 | sitePath: "models", |
| 115 | category: "reference", |
| 116 | }, |
| 117 | { |
| 118 | id: "constitution", |
| 119 | slug: "constitution", |
| 120 | label: { en: "Constitution", zh: "嵌套宪章" }, |
| 121 | description: { |
| 122 | en: "Agent identity, authority hierarchy, evidence rules, and the nested law system.", |
| 123 | zh: "Agent 自我模型、权威层次、证据规则和嵌套法律系统。", |
| 124 | }, |
| 125 | repoSource: "docs/ARCHITECTURE.md", |
| 126 | hasPage: true, |
| 127 | category: "core-concepts", |
| 128 | }, |
| 129 | { |
| 130 | id: "modes", |
| 131 | slug: "modes", |
| 132 | label: { en: "Modes", zh: "模式" }, |
| 133 | description: { |
| 134 | en: "Plan, Work, Operate modes and orthogonal permission posture.", |
| 135 | zh: "Plan、Work、Operate 三种模式与正交权限姿态。", |
| 136 | }, |
| 137 | repoSource: "docs/MODES.md", |
| 138 | hasPage: true, |
| 139 | category: "core-concepts", |
| 140 | }, |
| 141 | { |
| 142 | id: "tools", |
| 143 | slug: "tools", |
| 144 | label: { en: "Tools", zh: "工具" }, |
| 145 | description: { |
| 146 | en: "Canonical action tools, deferred discovery, and replay compatibility.", |
| 147 | zh: "小型核心工具、按需搜索、会话缓存与精确回放兼容边界。", |
| 148 | }, |
| 149 | repoSource: ["docs/TOOL_SURFACE.md", "docs/RUNTIME_SIMPLIFICATION_DESIGN.md"], |
| 150 | hasPage: true, |
| 151 | category: "core-concepts", |
| 152 | }, |
| 153 | { |
| 154 | id: "work", |
| 155 | slug: "work", |
| 156 | label: { en: "Work Surface", zh: "工作面板" }, |
| 157 | description: { |
| 158 | en: "The single To-do list, how the model sees it through its own tool results, and how work state flows to the sidebar, relay, and sub-agents.", |
| 159 | zh: "唯一的 To-do 列表、模型如何通过自己的工具结果看到它,以及工作状态如何流向侧栏、relay 和子 Agent。", |
| 160 | }, |
| 161 | repoSource: ["docs/TOOL_SURFACE.md", "docs/TOOL_LIFECYCLE.md"], |
| 162 | hasPage: true, |
| 163 | category: "core-concepts", |
| 164 | }, |
| 165 | { |
| 166 | id: "subagents", |
| 167 | slug: "subagents", |
| 168 | label: { en: "Sub-Agents", zh: "子 Agent" }, |
| 169 | description: { |
| 170 | en: "Parallel execution, role types, transcript handles, and nesting.", |
| 171 | zh: "并行执行、角色类型、transcript 句柄和嵌套。", |
| 172 | }, |
| 173 | repoSource: "docs/SUBAGENTS.md", |
| 174 | hasPage: true, |
| 175 | category: "core-concepts", |
| 176 | }, |
| 177 | { |
| 178 | id: "mcp", |
| 179 | slug: "mcp", |
| 180 | label: { en: "MCP", zh: "MCP" }, |
| 181 | description: { |
| 182 | en: "Model Context Protocol — consuming and exposing tools via stdio and HTTP/SSE.", |
| 183 | zh: "Model Context Protocol — 通过 stdio 和 HTTP/SSE 消费和暴露工具。", |
| 184 | }, |
| 185 | repoSource: "docs/MCP.md", |
| 186 | hasPage: true, |
| 187 | category: "extending", |
| 188 | }, |
| 189 | { |
| 190 | id: "hooks", |
| 191 | slug: "hooks", |
| 192 | label: { en: "Hooks", zh: "钩子" }, |
| 193 | description: { |
| 194 | en: "Lifecycle hooks for pre/post tool execution, mode changes, and session events.", |
| 195 | zh: "工具执行前后、模式切换和会话事件的生命周期钩子。", |
| 196 | }, |
| 197 | repoSource: ["docs/rfcs/1364-hooks-lifecycle.md", "docs/CONFIGURATION.md"], |
| 198 | hasPage: true, |
| 199 | category: "extending", |
| 200 | }, |
| 201 | { |
| 202 | id: "skills", |
| 203 | slug: "skills", |
| 204 | label: { en: "Skills", zh: "技能" }, |
| 205 | description: { |
| 206 | en: "Install, discover, trust, and load reusable instruction packages.", |
| 207 | zh: "安装、发现、信任并加载可复用的指令包。", |
| 208 | }, |
| 209 | repoSource: "docs/SKILLS.md", |
| 210 | hasPage: false, |
| 211 | category: "extending", |
| 212 | }, |
| 213 | { |
| 214 | id: "plugins", |
| 215 | slug: "plugins", |
| 216 | label: { en: "Plugins", zh: "插件" }, |
| 217 | description: { |
| 218 | en: "Plugin discovery, installation, bundles, trust boundaries, and runtime lifecycle.", |
| 219 | zh: "插件发现、安装、Bundle、信任边界与运行时生命周期。", |
| 220 | }, |
| 221 | repoSource: ["docs/PLUGINS.md", "docs/PLUGIN_BUNDLES.md"], |
| 222 | hasPage: false, |
| 223 | category: "extending", |
| 224 | }, |
| 225 | { |
| 226 | id: "sandbox", |
| 227 | slug: "sandbox", |
| 228 | label: { en: "Sandbox & Approval", zh: "沙箱与审批" }, |
| 229 | description: { |
| 230 | en: "Available Seatbelt (macOS), opt-in bubblewrap (Linux), platform gaps, and approval policies.", |
| 231 | zh: "可用的 Seatbelt(macOS)、显式启用的 bubblewrap(Linux)、平台缺口和审批策略。", |
| 232 | }, |
| 233 | repoSource: "docs/SANDBOX.md", |
| 234 | hasPage: true, |
| 235 | category: "core-concepts", |
| 236 | }, |
| 237 | { |
| 238 | id: "trust", |
| 239 | slug: "trust", |
| 240 | label: { en: "Security & Trust", zh: "安全与信任" }, |
| 241 | description: { |
| 242 | en: "What stays local, what a hosted provider receives, approvals versus the OS sandbox, telemetry field by field, and where to report a vulnerability.", |
| 243 | zh: "哪些留在本地、托管提供商收到什么、审批与 OS 沙箱的区别、逐项说明的遥测,以及在哪里报告漏洞。", |
| 244 | }, |
| 245 | repoSource: ["docs/SANDBOX.md", "docs/AUTHORIZATION_ORDER.md", "docs/TELEMETRY.md", "docs/public-surface-facts.json"], |
| 246 | hasPage: true, |
| 247 | category: "reference", |
| 248 | }, |
| 249 | { |
| 250 | id: "runtime-api", |
| 251 | slug: "runtime-api", |
| 252 | label: { en: "Runtime API", zh: "运行时 API" }, |
| 253 | description: { |
| 254 | en: "Public HTTP API for integrations, bridges, and automation.", |
| 255 | zh: "用于集成、桥接和自动化的公开 HTTP API。", |
| 256 | }, |
| 257 | repoSource: "docs/RUNTIME_API.md", |
| 258 | hasPage: true, |
| 259 | category: "extending", |
| 260 | }, |
| 261 | { |
| 262 | id: "web", |
| 263 | slug: "web", |
| 264 | label: { en: "Browser Client", zh: "浏览器客户端" }, |
| 265 | description: { |
| 266 | en: "Run the embedded browser client on loopback, with its one-time bootstrap and session boundaries.", |
| 267 | zh: "仅在本机回环地址运行内置浏览器客户端,了解一次性引导与会话边界。", |
| 268 | }, |
| 269 | repoSource: "docs/WEB.md", |
| 270 | hasPage: true, |
| 271 | category: "extending", |
| 272 | }, |
| 273 | // Fleet is the canonical customer noun; `/docs/pod` remains a |
| 274 | // permanent compatibility redirect in app/[locale]/docs/pod/page.tsx. |
| 275 | { |
| 276 | id: "computers", |
| 277 | slug: "computers", |
| 278 | label: { en: "Cloud Computers", zh: "云端计算机" }, |
| 279 | description: { |
| 280 | en: "Propose, confirm, and track a Daytona cloud agent against an explicit forge — fail-closed credentials and what is not built yet.", |
| 281 | zh: "向明确指定的代码托管平台提议、确认并跟踪 Daytona 云端 Agent——凭证缺失即拒绝,以及尚未实现的部分。", |
| 282 | }, |
| 283 | repoSource: ["docs/DAYTONA_CLOUD_DISPATCH.md", "docs/CODEWHALE_AGENT.md"], |
| 284 | hasPage: true, |
| 285 | category: "operations", |
| 286 | }, |
| 287 | { |
| 288 | id: "fleet", |
| 289 | slug: "fleet", |
| 290 | label: { en: "Fleet / Workflow", zh: "Fleet / Workflow" }, |
| 291 | description: { |
| 292 | en: "Durable task execution, fleet roster management, and Workflow authoring.", |
| 293 | zh: "持久任务执行、fleet 花名册管理和 Workflow 编写。", |
| 294 | }, |
| 295 | repoSource: ["docs/FLEET.md", "docs/WORKFLOW_AUTHORING.md"], |
| 296 | hasPage: true, |
| 297 | category: "operations", |
| 298 | }, |
| 299 | { |
| 300 | id: "troubleshooting", |
| 301 | slug: "troubleshooting", |
| 302 | label: { en: "Troubleshooting", zh: "排障" }, |
| 303 | description: { |
| 304 | en: "Common issues, diagnostics, operations runbook, and Docker notes.", |
| 305 | zh: "常见问题、诊断、运维手册和 Docker 说明。", |
| 306 | }, |
| 307 | repoSource: ["docs/OPERATIONS_RUNBOOK.md", "docs/DOCKER.md"], |
| 308 | hasPage: true, |
| 309 | category: "operations", |
| 310 | }, |
| 311 | { |
| 312 | id: "contribution", |
| 313 | slug: "contribution", |
| 314 | label: { en: "Contribution", zh: "贡献" }, |
| 315 | description: { |
| 316 | en: "Contributing guide, agent ethos, contributor credits, and release process.", |
| 317 | zh: "贡献指南、Agent 伦理、贡献者致谢和发布流程。", |
| 318 | }, |
| 319 | repoSource: [ |
| 320 | "CONTRIBUTING.md", |
| 321 | "docs/AGENT_ETHOS.md", |
| 322 | "docs/CONTRIBUTORS.md", |
| 323 | "docs/RELEASE_CHECKLIST.md", |
| 324 | ], |
| 325 | hasPage: false, |
| 326 | category: "operations", |
| 327 | }, |
| 328 | ]; |
| 329 | |
| 330 | /** Convenience lookup. */ |
| 331 | export function getTopic(id: string): DocTopic | undefined { |
| 332 | return DOC_TOPICS.find((t) => t.id === id); |
| 333 | } |
| 334 | |
| 335 | /** Group topics by category for sidebar rendering. */ |
| 336 | export function getTopicsByCategory(): Map<DocTopic["category"], DocTopic[]> { |
| 337 | const map = new Map<DocTopic["category"], DocTopic[]>(); |
| 338 | for (const t of DOC_TOPICS) { |
| 339 | const group = map.get(t.category) ?? []; |
| 340 | group.push(t); |
| 341 | map.set(t.category, group); |
| 342 | } |
| 343 | return map; |
| 344 | } |
| 345 | |
| 346 | /** Resolve a topic to its on-site route or canonical repository document. */ |
| 347 | export function docTopicHref(topic: DocTopic, locale: string): string { |
| 348 | if (topic.sitePath) return `/${locale}/${topic.sitePath}`; |
| 349 | if (topic.hasPage) return `/${locale}/docs/${topic.slug}`; |
| 350 | const source = Array.isArray(topic.repoSource) ? topic.repoSource[0] : topic.repoSource; |
| 351 | return `${REPO_DOCS_BASE}/${source}`; |
| 352 | } |
| 353 | |
| 354 | /** Whether following a topic leaves codewhale.net for the source document. */ |
| 355 | export function docTopicIsExternal(topic: DocTopic): boolean { |
| 356 | return !topic.hasPage; |
| 357 | } |
| 358 | |
| 359 | /** Repo source base URL for generating direct links. */ |
| 360 | export const REPO_DOCS_BASE = "https://github.com/Hmbown/CodeWhale/blob/main"; |
| 361 |