| 1 | import { buildPageMetadata } from "@/lib/page-meta"; |
| 2 | |
| 3 | export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }) { |
| 4 | const { locale } = await params; |
| 5 | const isZh = locale === "zh"; |
| 6 | return buildPageMetadata({ |
| 7 | path: "/docs/runtime-api", |
| 8 | locale, |
| 9 | title: isZh ? "运行时 API · Codewhale 文档" : "Runtime API · Codewhale Docs", |
| 10 | description: isZh |
| 11 | ? "面向集成、桥接和自动化的本地 HTTP/SSE、JSON-RPC stdio 与 ACP 入口。" |
| 12 | : "Local HTTP/SSE, JSON-RPC stdio, and ACP entrypoints for integrations, bridges, and automation.", |
| 13 | }); |
| 14 | } |
| 15 | |
| 16 | export default async function RuntimeApiPage({ params }: { params: Promise<{ locale: string }> }) { |
| 17 | const { locale } = await params; |
| 18 | const isZh = locale === "zh"; |
| 19 | const bodyClass = isZh |
| 20 | ? "text-ink-soft leading-[1.9] tracking-wide" |
| 21 | : "text-ink-soft leading-relaxed"; |
| 22 | const entries = isZh |
| 23 | ? [ |
| 24 | { cmd: "codewhale app-server --http", detail: "完整 /v1/* HTTP/SSE 运行时 API(canonical 入口),默认 127.0.0.1:7878。" }, |
| 25 | { cmd: "codewhale app-server --mobile", detail: "运行时 API 加 /mobile 手机控制页。" }, |
| 26 | { cmd: "codewhale app-server --stdio", detail: "换行分隔的 JSON-RPC 2.0 控制传输,无监听端口,适合本地 SDK 和探针。" }, |
| 27 | { cmd: "codewhale web [--port 7878]", detail: "仅回环的浏览器客户端,内嵌于二进制并打开默认浏览器。" }, |
| 28 | { cmd: "codewhale doctor --json", detail: "机器可读的健康与能力报告。" }, |
| 29 | { cmd: "codewhale serve --acp", detail: "面向 Zed 等编辑器的 ACP(Agent Client Protocol)stdio 适配器。" }, |
| 30 | { cmd: "codewhale exec [args]", detail: "一次性无头 worker(stream-json、Fleet 子进程、CI 原语)——不属于本 API,但共享同一运行时与事件词汇。" }, |
| 31 | ] |
| 32 | : [ |
| 33 | { cmd: "codewhale app-server --http", detail: "The full /v1/* HTTP/SSE runtime API (canonical entry), default 127.0.0.1:7878." }, |
| 34 | { cmd: "codewhale app-server --mobile", detail: "The runtime API plus the /mobile phone control page." }, |
| 35 | { cmd: "codewhale app-server --stdio", detail: "Newline-delimited JSON-RPC 2.0 control transport with no listener, for local SDKs and probes." }, |
| 36 | { cmd: "codewhale web [--port 7878]", detail: "The loopback-only browser client, embedded in the binary and opened in the default browser." }, |
| 37 | { cmd: "codewhale doctor --json", detail: "Machine-readable health and capability report." }, |
| 38 | { cmd: "codewhale serve --acp", detail: "ACP (Agent Client Protocol) stdio adapter for editors such as Zed." }, |
| 39 | { cmd: "codewhale exec [args]", detail: "The one-shot headless worker (stream-json, fleet subprocess, CI primitive) — not part of this API, but it shares the same runtime and event vocabulary." }, |
| 40 | ]; |
| 41 | |
| 42 | return ( |
| 43 | <section className="space-y-10"> |
| 44 | <section id="overview" className="scroll-mt-32"> |
| 45 | <h2 className="font-display text-3xl mb-1">{isZh ? "运行时 API" : "Runtime API"}</h2> |
| 46 | <p className={`${bodyClass} mt-3`}> |
| 47 | {isZh |
| 48 | ? "codewhale app-server 是 canonical 的本地运行时 API 与控制平面。本地 SDK、移动/远控客户端和编辑器集成直接与它对话,而不是抓终端输出。引擎只作为本地进程运行:所有 API 默认绑定 localhost——没有托管中继,不托管 provider 令牌,不泄露秘密。codewhale serve --http / --mobile 保留为 app-server --http / --mobile 的兼容别名,启动的是同一个服务器;新集成应面向 app-server。" |
| 49 | : "codewhale app-server is the canonical local runtime API and control plane. Local SDKs, mobile/remote-control clients, and editor integrations talk to it instead of screen-scraping terminal output. The engine runs as a local-only process: every API binds to localhost by default — no hosted relay, no provider-token custody, no secret leakage. codewhale serve --http / --mobile remain compatibility aliases for app-server --http / --mobile and launch the identical server; new integrations should target app-server."} |
| 50 | </p> |
| 51 | <div className="hairline-t mt-6"> |
| 52 | {entries.map((row) => ( |
| 53 | <section key={row.cmd} className="py-4 hairline-b"> |
| 54 | <h3 className="font-mono text-sm font-semibold">{row.cmd}</h3> |
| 55 | <p className={`${bodyClass} mt-1 text-sm`}>{row.detail}</p> |
| 56 | </section> |
| 57 | ))} |
| 58 | </div> |
| 59 | </section> |
| 60 | |
| 61 | <section id="stdio" className="scroll-mt-32"> |
| 62 | <h2 className="font-display text-2xl mb-1">{isZh ? "零成本探测" : "Probe without model tokens"}</h2> |
| 63 | <p className={`${bodyClass} mt-3`}> |
| 64 | {isZh |
| 65 | ? "stdio 控制传输可以不花模型 token 地探测。capabilities 返回声明的方法族(thread/*、app/*、prompt/*)和完整方法列表;方法集由 crates/app-server/src/lib.rs 中的漂移测试固定,SDK 和本地集成可以放心依赖它不会悄悄变化。" |
| 66 | : "The stdio control transport can be probed without spending model tokens. capabilities returns the advertised method families (thread/*, app/*, prompt/*) and the full method list; the method set is pinned by a drift test in crates/app-server/src/lib.rs, so SDK and local integration clients can rely on it not changing silently."} |
| 67 | </p> |
| 68 | <pre className="code-block mt-4">{`printf '%s\n' \\ |
| 69 | '{"jsonrpc":"2.0","id":1,"method":"healthz"}' \\ |
| 70 | '{"jsonrpc":"2.0","id":2,"method":"capabilities"}' \\ |
| 71 | '{"jsonrpc":"2.0","id":3,"method":"shutdown"}' \\ |
| 72 | | codewhale app-server --stdio`}</pre> |
| 73 | <p className={`${bodyClass} mt-3`}> |
| 74 | {isZh |
| 75 | ? "进行中的回合可以用 thread/interrupt(或 HTTP 的 POST /v1/threads/{id}/turns/{turn_id}/interrupt)请求中断;没有正在流式输出的回合时返回 interrupted: false——这不是错误,只是没有可停的东西。" |
| 76 | : "A live turn can be asked to stop with thread/interrupt (or POST /v1/threads/{id}/turns/{turn_id}/interrupt over HTTP); when no turn is streaming the reply carries interrupted: false — not an error, just nothing to stop."} |
| 77 | </p> |
| 78 | </section> |
| 79 | |
| 80 | <section id="security" className="scroll-mt-32"> |
| 81 | <h2 className="font-display text-2xl mb-1">{isZh ? "安全边界" : "Security boundary"}</h2> |
| 82 | <p className={`${bodyClass} mt-3`}> |
| 83 | {isZh ? ( |
| 84 | <> |
| 85 | 运行时 API 令牌按 <code className="inline">--auth-token</code>、 |
| 86 | <code className="inline">CODEWHALE_RUNTIME_TOKEN</code>、 |
| 87 | <code className="inline">DEEPSEEK_RUNTIME_TOKEN</code> 的顺序读取; |
| 88 | <code className="inline">--insecure-no-auth</code> 只允许与回环绑定一起使用。浏览器侧的跨源请求会被 |
| 89 | CORS 允许列表拒绝。选择非回环绑定(尤其是{" "} |
| 90 | <code className="inline">app-server --mobile</code>)之前,请阅读 docs/RUNTIME_API.md |
| 91 | 的完整部署与认证约定。 |
| 92 | </> |
| 93 | ) : ( |
| 94 | <> |
| 95 | The runtime API token is read from <code className="inline">--auth-token</code>, then{" "} |
| 96 | <code className="inline">CODEWHALE_RUNTIME_TOKEN</code>, then{" "} |
| 97 | <code className="inline">DEEPSEEK_RUNTIME_TOKEN</code>;{" "} |
| 98 | <code className="inline">--insecure-no-auth</code> is only accepted with a loopback bind. |
| 99 | Cross-origin browser requests are rejected by the CORS allow-list. Before selecting a |
| 100 | non-loopback bind — especially <code className="inline">app-server --mobile</code> — read |
| 101 | the full deployment and authentication contract in docs/RUNTIME_API.md. |
| 102 | </> |
| 103 | )} |
| 104 | </p> |
| 105 | </section> |
| 106 | |
| 107 | <section id="source" className="hairline-t pt-8"> |
| 108 | <p className="text-sm text-ink-mute"> |
| 109 | {isZh |
| 110 | ? "来源文档:docs/RUNTIME_API.md · 更新时请同步修改 docs-map.ts。" |
| 111 | : "Source document: docs/RUNTIME_API.md · Update docs-map.ts when changing."} |
| 112 | </p> |
| 113 | </section> |
| 114 | </section> |
| 115 | ); |
| 116 | } |
| 117 |