claude-code-best/docs/serve/api.md
2026-05-06 14:35:38 +08:00

22 KiB
Raw Blame History

csc serve — HTTP API 接口规范

csc serve 启动一个 HTTP 服务器,为 IDE 插件和 Web 客户端提供 REST API。 内部架构为 子进程模式:每个会话 spawn 一个 csc --print --input-format stream-json --output-format stream-json 子进程HTTP 层作为 NDJSON 协议的桥梁。

设计原则

  1. API 路径兼容 opencode servecs-cloud 通过路由表映射,客户端无需感知后端差异
  2. 子进程隔离1 session = 1 子进程,无进程内多会话
  3. 子进程复用:同一 session 的多次 prompt 复用同一子进程bridge 模式已验证)
  4. JSONL 持久化:会话数据沿用 csc 现有的 transcript JSONL 文件
  5. 文件系统操作由 cs-cloud 自有接口处理/api/v1/runtime/files 等不经过 csc serve

CLI 入口

csc serve [options]

Options:
  --port <port>        监听端口(默认 0 = 自动分配)
  --host <host>        监听地址(默认 127.0.0.1
  --auth-token <token>  Bearer token 认证
  --workspace <dir>     默认工作目录
  --max-sessions <n>    最大并发会话数(默认 32
  --idle-timeout <ms>   空闲会话超时(默认 1800000 = 30 分钟0 = 永不超时)

stdout 输出端口信息(供 cs-cloud 解析):

csc server listening on http://127.0.0.1:{port}

API 端点总览

分类 端点数 说明
Server 1 健康检查
Info 5 路径、VCS、命令、agent 模式、MCP 状态
Session 11 会话 CRUD、prompt、abort
Event 1 SSE 事件流
Permission 2 权限请求列表、回复
Question 3 问题请求列表、回复、拒绝
Message 3 消息历史、todo、diff
Provider 2 模型/Provider 信息
合计 28

1. Server

GET /health

服务健康检查。

Response 200:

{
  "status": "ok",
  "version": "4.0.1",
  "uptime_ms": 12345,
  "active_sessions": 3
}

2. Info

GET /path

获取路径信息。

Response 200:

{
  "home": "/Users/user",
  "state": "/Users/user/.claude",
  "config": "/Users/user/.claude",
  "directory": "/path/to/workspace"
}

GET /vcs

获取 VCS 信息。

Response 200:

{
  "branch": "main"
}

GET /command

列出可用 slash 命令。

Response 200:

[
  { "name": "compact", "description": "Compact conversation" },
  { "name": "clear", "description": "Clear conversation" },
  { "name": "help", "description": "Show help" }
]

数据来源:子进程 initialize response 中的 commands 字段。

GET /agent

列出可用的 agent 模式。

Response 200:

[
  { "id": "main", "name": "Main Agent" },
  { "id": "plan", "name": "Plan Mode" }
]

数据来源:子进程 initialize response 中的 agents 字段。

GET /mcp

获取 MCP 服务器状态。通过子进程 mcp_status control-request 获取。

Response 200:

{
  "servers": [
    { "name": "filesystem", "status": "connected", "tools": 5 },
    { "name": "github", "status": "disconnected", "error": "Connection refused" }
  ]
}

3. Session

POST /session

创建新会话。spawn 一个 csc --print 子进程。

Request Body:

{
  "cwd": "/path/to/project",
  "permission_mode": "default",
  "model": "claude-sonnet-4-20250514",
  "system_prompt": "optional system prompt",
  "resume_session_id": "optional-uuid-to-resume"
}
字段 类型 必填 说明
cwd string 工作目录,默认为 serve 的 --workspace
permission_mode string 权限模式:default / bypassPermissions / plan
model string 初始模型
system_prompt string 自定义 system prompt
resume_session_id string 恢复已有会话的 ID

Response 201:

{
  "session_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "starting",
  "cwd": "/path/to/project",
  "created_at": 1713001234567
}

子进程启动完成后通过 SSE 推送 session.ready 事件。

GET /session

列出所有会话。

Query Parameters:

参数 类型 说明
limit number 分页大小(默认 50
offset number 分页偏移
search string 搜索会话标题

Response 200:

{
  "sessions": [
    {
      "session_id": "uuid-1",
      "status": "running",
      "cwd": "/path/to/project",
      "title": "Fix authentication bug",
      "model": "claude-sonnet-4-20250514",
      "permission_mode": "default",
      "created_at": 1713001234567,
      "last_active_at": 1713001299999,
      "cost_usd": 0.0523,
      "api_duration_ms": 12345
    }
  ]
}

数据来源:内存中的活跃会话 + ~/.claude/server-sessions.json 持久化索引 + 各 session 的 transcript JSONL 头部。

GET /session/:sessionID

获取单个会话详情。

Response 200:

{
  "session_id": "uuid-1",
  "status": "running",
  "cwd": "/path/to/project",
  "title": "Fix authentication bug",
  "model": "claude-sonnet-4-20250514",
  "permission_mode": "default",
  "created_at": 1713001234567,
  "last_active_at": 1713001299999,
  "cost_usd": 0.0523,
  "api_duration_ms": 12345,
  "message_count": 12,
  "usage": {
    "input_tokens": 15000,
    "output_tokens": 5000,
    "cache_read_input_tokens": 10000,
    "cache_creation_input_tokens": 2000
  }
}

Response 404:

{ "error": "session not found" }

PATCH /session/:sessionID

更新会话属性。

Request Body:

{
  "title": "New title",
  "model": "claude-sonnet-4-20250514",
  "permission_mode": "bypassPermissions"
}

modelpermission_mode 的变更通过子进程的 control_request 实现(set_model / set_permission_mode)。

Response 200:

{
  "session_id": "uuid-1",
  "title": "New title",
  "model": "claude-sonnet-4-20250514",
  "permission_mode": "bypassPermissions"
}

DELETE /session/:sessionID

删除会话。kill 子进程 + 清理持久化索引。

Response 200:

{ "deleted": true }

GET /session/status

批量获取所有会话的状态。

Response 200:

{
  "sessions": {
    "uuid-1": { "status": "running", "has_pending_permission": false },
    "uuid-2": { "status": "idle", "has_pending_permission": true }
  }
}

POST /session/:sessionID/prompt

发送 prompt 并流式返回响应。对应子进程 stdin 写入 SDKUserMessage

Request Body:

{
  "content": "Fix the authentication bug in login.ts",
  "files": ["src/login.ts"],
  "images": []
}
字段 类型 必填 说明
content string 用户输入内容
files string[] 附带的文件路径(作为 context
images object[] 图片附件base64 或 URL

Response 200 (streaming):

Content-Type: text/event-stream

event: message
data: {"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"I'll fix the"}]}}

event: message
data: {"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":" authentication bug."}]}}

event: message
data: {"type":"tool_progress","tool_name":"Edit","elapsed_time_seconds":1}

event: message
data: {"type":"assistant","message":{"role":"assistant","content":[{"type":"tool_use","id":"toolu_xxx","name":"Edit","input":{...}}]}}

event: result
data: {"type":"result","subtype":"success","cost_usd":0.0123,"duration_ms":5432,"usage":{"input_tokens":5000,"output_tokens":2000}}

事件类型直接映射子进程 stdout NDJSON 的 SDKMessage.type

NDJSON type SSE event 说明
assistant message assistant 流式内容
partial_assistant message 原始 API 流式事件
tool_progress message 工具执行进度
result result 最终结果(含 cost/usage
result_success result 成功结果
system system 系统消息init、compact_boundary 等)
status system 状态变更
control_request control_request 权限/交互请求
permission_denial system 权限被拒绝

POST /session/:sessionID/prompt_async

异步 prompt。立即返回后台执行。通过 SSE 推送事件。

Request Body:prompt

Response 204: No Content

POST /session/:sessionID/abort

中止当前正在执行的 prompt。向子进程发送 control_request { subtype: "interrupt" },如果无响应则 SIGTERM。

Response 200:

{ "aborted": true }

POST /session/:sessionID/shell

在会话上下文中执行 shell 命令。转换为 prompt 发送到子进程。

Request Body:

{
  "command": "npm test"
}

Response 200 (streaming):prompt 的 SSE 流。

POST /session/:sessionID/command

执行 slash 命令。转换为对应 prompt 发送到子进程。

Request Body:

{
  "command": "/compact"
}

Response 200 (streaming):prompt 的 SSE 流。


4. Event

GET /event

全局 SSE 事件流。聚合所有会话的事件。

Query Parameters:

参数 类型 说明
session_id string 可选,只订阅特定会话的事件

Response 200 (SSE):

event: connected
data: {"type":"server.connected"}

event: session.created
data: {"session_id":"uuid-1","status":"starting"}

event: session.ready
data: {"session_id":"uuid-1","status":"running","model":"claude-sonnet-4-20250514"}

event: session.message
data: {"session_id":"uuid-1","type":"assistant","message":{...}}

event: session.result
data: {"session_id":"uuid-1","type":"result","cost_usd":0.0123,"duration_ms":5432}

event: session.control_request
data: {"session_id":"uuid-1","request_id":"req-1","request":{"subtype":"can_use_tool","tool_name":"Bash","input":{...}}}

event: session.status_changed
data: {"session_id":"uuid-1","status":"idle"}

event: session.deleted
data: {"session_id":"uuid-1"}

event: heartbeat
data: {"type":"server.heartbeat","ts":1713001234567}

所有 session 相关事件都带 session_id 字段。心跳间隔 10 秒。


5. Permission

GET /permission

列出所有待处理的权限请求。

Response 200:

{
  "permissions": [
    {
      "request_id": "req-1",
      "session_id": "uuid-1",
      "tool_name": "Bash",
      "tool_use_id": "toolu_xxx",
      "input": { "command": "rm -rf node_modules" },
      "title": "Bash: rm -rf node_modules",
      "description": "Execute bash command"
    }
  ]
}

数据来源:拦截子进程 stdout 的 control_request { subtype: "can_use_tool" } 消息,缓存在内存。

POST /permission/:requestID/reply

回复权限请求。向对应子进程 stdin 写入 control_response

Request Body (allow):

{
  "behavior": "allow",
  "updated_input": { "command": "rm -rf node_modules" }
}

Request Body (deny):

{
  "behavior": "deny",
  "message": "Command not allowed"
}

Response 200:

{ "resolved": true }

6. Question

csc 通过 control_request { subtype: "elicitation" } 实现 MCP elicitation 交互,映射为 question 端点。

GET /question

列出所有待处理的问题请求。

Response 200:

{
  "questions": [
    {
      "request_id": "req-2",
      "session_id": "uuid-1",
      "mcp_server_name": "my-server",
      "message": "Please provide your API key",
      "mode": "form",
      "requested_schema": { "type": "object", "properties": { "key": { "type": "string" } } }
    }
  ]
}

POST /question/:requestID/reply

回复问题请求。

Request Body:

{
  "action": "accept",
  "content": { "key": "sk-xxx" }
}

Response 200:

{ "resolved": true }

POST /question/:requestID/reject

拒绝问题请求。

Request Body:

{
  "action": "decline"
}

Response 200:

{ "resolved": true }

7. Message

GET /session/:sessionID/message

获取会话消息历史。读取 transcript JSONL 文件。

Query Parameters:

参数 类型 说明
limit number 返回条数(默认 50
before string 游标:返回此 UUID 之前的消息
include_system boolean 是否包含 system 消息(默认 false

Response 200:

{
  "messages": [
    {
      "uuid": "msg-uuid-1",
      "type": "user",
      "role": "user",
      "content": "Fix the auth bug",
      "timestamp": 1713001234567,
      "parent_uuid": null
    },
    {
      "uuid": "msg-uuid-2",
      "type": "assistant",
      "role": "assistant",
      "content": [
        { "type": "text", "text": "I'll fix the authentication bug." },
        { "type": "tool_use", "id": "toolu_xxx", "name": "Edit", "input": { "file_path": "src/login.ts", "old_string": "...", "new_string": "..." } }
      ],
      "timestamp": 1713001234999,
      "parent_uuid": "msg-uuid-1",
      "usage": { "input_tokens": 5000, "output_tokens": 2000 }
    }
  ]
}

Headers:

Link: </session/uuid-1/message?before=msg-uuid-first>; rel="prev"
X-Next-Cursor: msg-uuid-first

实现方式:解析 ~/.claude/projects/<project>/sessions/<sessionID>.jsonl,按 parentUuid 构建消息链。

GET /session/:sessionID/todo

获取会话中的 todo/plan 列表。从 transcript 中提取 tool_use[name=TodoWrite/TodoRead] 消息。

Response 200:

{
  "todos": [
    {
      "id": "todo-1",
      "content": "Fix authentication bug",
      "status": "in_progress",
      "priority": "high"
    },
    {
      "id": "todo-2",
      "content": "Add unit tests",
      "status": "pending",
      "priority": "medium"
    }
  ]
}

GET /session/:sessionID/diff

获取会话中的文件变更。读取 csc 的 file-history 快照目录。

Query Parameters:

参数 类型 说明
messageID string 可选,指定消息 ID 的变更

Response 200:

{
  "diffs": [
    {
      "file": "src/login.ts",
      "status": "modified",
      "additions": 5,
      "deletions": 2,
      "patch": "--- a/src/login.ts\n+++ b/src/login.ts\n@@ -10,3 +10,6 @@..."
    }
  ]
}

注意csc 的 file-history 没有索引,需要按 messageID 关联快照目录,实现复杂度中等。如果 messageID 未指定则返回全部变更。


8. Provider

GET /provider

列出所有可用的 AI providers 和模型。

Response 200:

{
  "connected": ["anthropic"],
  "default_model": "claude-sonnet-4-20250514",
  "providers": [
    {
      "id": "anthropic",
      "name": "Anthropic",
      "connected": true,
      "models": [
        {
          "id": "claude-sonnet-4-20250514",
          "name": "Claude Sonnet 4",
          "context_window": 200000,
          "max_output_tokens": 64000,
          "supports_images": true,
          "supports_streaming": true
        }
      ]
    }
  ]
}

数据来源:

  • 读取 ~/.claude/settings.json 中的 API key 配置
  • 通过子进程的 initialize response 中的 models 字段获取模型列表

GET /provider/capabilities

精简的模型能力列表(供模型选择 UI 使用)。

Response 200:

{
  "connected": [
    {
      "provider_id": "anthropic",
      "provider_name": "Anthropic",
      "models": [
        {
          "model_id": "claude-sonnet-4-20250514",
          "model_name": "Claude Sonnet 4",
          "context_window": 200000,
          "max_output_tokens": 64000,
          "supports_images": true,
          "input_cost_per_million": 3.0,
          "output_cost_per_million": 15.0
        }
      ]
    }
  ]
}

9. Find

GET /find/file

按文件名搜索文件。

Query Parameters:

参数 类型 说明
query string 搜索模式(必填)
dirs string 是否包含目录("true" / "false"
limit number 结果数量限制

Response 200:

["src/login.ts", "src/logout.ts", "tests/login.test.ts"]

错误格式

所有错误响应使用统一格式:

{
  "error": "ERROR_CODE",
  "message": "Human readable error message"
}
HTTP Status Code 说明
400 BAD_REQUEST 请求参数错误
401 UNAUTHORIZED 认证失败(需要 auth-token
404 NOT_FOUND 会话/资源不存在
409 CONFLICT 会话已在执行中(重复 prompt
429 TOO_MANY_SESSIONS 超过 max-sessions 限制
500 INTERNAL 内部错误
503 SESSION_ERROR 子进程崩溃或无响应

认证

如果启动时指定了 --auth-token,所有请求需要携带:

Authorization: Bearer <token>

未携带或 token 不匹配返回 401。


子进程生命周期

POST /session
  → spawn: csc --print --input-format stream-json --output-format stream-json
           [--session-id <id>] [--resume <id>] [--permission-mode <mode>]
           [--model <model>]
  → 状态: starting

子进程输出 system.init
  → 状态: running

POST /session/:id/prompt
  → stdin: SDKUserMessage
  → stdout → SSE: assistant/result/control_request
  → 状态: running → active → idle

POST /session/:id/abort
  → stdin: control_request { subtype: "interrupt" }
  → 如果无响应: SIGTERM

idle-timeout 到期
  → SIGTERM 子进程
  → 状态: stopped

DELETE /session/:id
  → SIGKILL 子进程
  → 清理 SessionIndex

cs-cloud 路由映射

cs-cloud 作为反向代理,将客户端 API 映射到 csc serve

cs-cloud 路由 → csc serve 路由 客户端调用
POST /api/v1/conversations POST /session conversation.create
GET /api/v1/conversations GET /session conversation.list
GET /api/v1/conversations/{id} GET /session/{id} conversation.get
PATCH /api/v1/conversations/{id} PATCH /session/{id} conversation.update
DELETE /api/v1/conversations/{id} DELETE /session/{id} conversation.delete
POST /api/v1/conversations/{id}/prompt POST /session/{id}/prompt conversation.prompt
POST /api/v1/conversations/{id}/prompt/async POST /session/{id}/prompt_async conversation.promptAsync
POST /api/v1/conversations/{id}/abort POST /session/{id}/abort conversation.abort
GET /api/v1/conversations/{id}/messages GET /session/{id}/message conversation.messages
GET /api/v1/conversations/{id}/todo GET /session/{id}/todo conversation.todo
GET /api/v1/conversations/{id}/diff GET /session/{id}/diff conversation.diff
POST /api/v1/conversations/{id}/shell POST /session/{id}/shell conversation.shell
POST /api/v1/conversations/{id}/command POST /session/{id}/command conversation.command
GET /api/v1/conversations/status GET /session/status conversation.status
GET /api/v1/events GET /event event.stream
GET /api/v1/permissions GET /permission interaction.permissions
POST /api/v1/permissions/{id}/reply POST /permission/{id}/reply interaction.permissionRespond
GET /api/v1/questions GET /question interaction.questions
POST /api/v1/questions/{id}/reply POST /question/{id}/reply interaction.questionReply
POST /api/v1/questions/{id}/reject POST /question/{id}/reject interaction.questionReject
GET /api/v1/agents/models GET /provider/capabilities runtime.modelCapabilities
GET /api/v1/agents/session-modes GET /agent runtime.sessionModes
GET /api/v1/agents GET /provider runtime.agentRuntimes

以下 cs-cloud 路由不代理到 csc serve由 cs-cloud 自有接口处理:

cs-cloud 自有路由 客户端调用 说明
GET /api/v1/runtime/health runtime.health cs-cloud 进程自身健康检查
GET /api/v1/runtime/files runtime.fileList cs-cloud 直接读文件系统
GET /api/v1/runtime/files/content runtime.fileRead cs-cloud 直接读文件内容

以下透传路由不经过 /api/v1 前缀cs-cloud 直接代理:

cs-cloud 透传路由 → csc serve 路由 客户端调用
GET /path GET /path runtime.targetContext
GET /vcs GET /vcs runtime.vcs
GET /command GET /command runtime.commands
GET /mcp GET /mcp runtime.mcpStatus
GET /find/file GET /find/file runtime.findFiles
POST /instance/dispose GET /health(带 shutdown 标记) runtime.instanceDispose

与 opencode serve 的差异

能力 opencode serve csc serve 说明
进程模型 1 进程多会话 1 进程 = 1 子进程 csc 单例架构限制
会话存储 SQLite 数据库 JSONL 文件 + 内存索引 csc 沿用现有 transcript
POST /session/:id/revert csc 有 rewind_files control-request 可部分替代,但无完整 revert
POST /session/:id/unrevert 同上
POST /session/:id/summarize csc 有 compact 但无独立 summarize
POST /session/:id/fork 需 JSONL 文件复制 + UUID 重映射
POST /session/:id/share csc 无 share 功能
DELETE /session/:id/share 同上
GET /session/:id/diff DB 索引) ⚠️(读 file-history 无索引,性能较差
GET /project csc 无项目数据库
GET /pty PTY 在子进程内部,无法外部操作
GET /tui/* 14 个端点) 仅 TUI 模式有意义
GET /experimental/* 11 个端点) 高级功能,暂不支持
文件操作 csc serve 处理 cs-cloud 自有接口 /api/v1/runtime/files 不经过 csc