1. kap-server 的定位
1.1 在 kimi-code 架构中的位置
packages/kap-server 是 agent-core-v2 的 HTTP 外围服务层。它不是一个独立的应用------它是引擎的"外壳",将 DI x Scope 容器内的所有能力暴露为标准化的 REST + WebSocket 接口。在 kimi-code 系统的分层结构中,它位于以下位置:
scss
┌───────────────────────────────────────────────────────────────────┐
│ 消费者层 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌───────────────────┐ │
│ │ kimi-web │ │kimi-inspect│ │ pi-tui │ │ kimi-code CLI │ │
│ │ (Web UI) │ │ (调试面板)│ │ (TUI) │ │ (web/daemon) │ │
│ └─────┬─────┘ └─────┬─────┘ └────┬────┘ └─────────┬─────────┘ │
│ │ │ │ │ │
│ │ HTTP + WebSocket │ process.fork() │
│ └──────────────┴──────────────┘ │ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────────────────┐ ┌──────────────────────────┐ │
│ │ kap-server │ │ kimi-code CLI │ │
│ │ Fastify HTTP Server + WS │ │ (Embedding Host via SDK)│ │
│ │ │ │ startServer({hostIdentity,...})│
│ │ ┌──────────────────────────┐ │ └──────────────────────────┘ │
│ │ │ agent-core-v2 (Core) │ │ │
│ │ │ DI × Scope 容器 │ │ │
│ │ └──────────────────────────┘ │ │
│ └─────────────────────────────────┘ │
└───────────────────────────────────────────────────────────────────┘
kap-server 是 kimi-web (Web 前端)和 kimi-inspect (调试面板)的后端。CLI 的 kimi web 命令本质上就是启动一个 kap-server 实例并将 web 静态资源挂载上去。每当用户在浏览器中打开 Web UI、提交 Prompt、查看会话记录、或者调试面板通过 RPC 调用引擎内部服务时,请求都先到达 kap-server。
1.2 核心职责
- 会话管理:创建、列表、更新、归档、fork、compact、undo、abort 会话
- Prompt 提交:接收用户输入、图片附件、文件引用,转发给引擎调度
- 事件广播:通过 WebSocket 实时推送会话事件(每个 token、工具调用、审批请求)
- 文件操作:上传/下载、工作空间文件系统浏览
- 审批与问题:工具审批流、Agent 问题交互
- 配置与模型:暴露 provider 和 model 目录、用户配置读写
- 认证与安全:Bearer Token 认证、Host/Origin 校验、速率限制
2. 技术栈全景
2.1 核心依赖
| 技术 | 角色 | 说明 |
|---|---|---|
| Fastify | HTTP 框架 | 高性能 Node.js Web 框架,内置日志(Pino)、Schema 验证、插件系统 |
| agent-core-v2 | 引擎核心 | DI x Scope 容器,提供 ISessionLifecycleService、IAgentPromptService 等全部引擎服务 |
| transcript | 会话数据层 | TranscriptStore 分级存储、WireRecord 持久化、实时增量投影 |
| @fastify/swagger | API 文档 | 从 Zod Schema 自动生成 OpenAPI 3.0 文档,暴露 /openapi.json |
| WebSocket (ws) | 实时通道 | 基于 ws 库的 WebSocket 服务器,noServer 模式与 Fastify 共享 HTTP Server |
| ulid | ID 生成 | 连接 ID、Server ID 的唯一标识 |
| Zod | 验证层 | 类型安全的请求/响应 Schema 验证,同时驱动 Swagger 文档生成 |
2.2 defineRoute:声明式路由定义
kap-server 没有使用 Fastify 原生的 AJV 验证。它通过自研的 defineRoute 中间件实现了一套声明式路由系统:一个对象同时声明 Zod Schema(运行时验证)和 OpenAPI Schema(Swagger 文档)。
Typescript
// packages/kap-server/src/routes/prompts.ts
const submitRoute = defineRoute(
{
method: 'POST',
path: '/sessions/{session_id}/prompts',
body: promptSubmissionSchema, // Zod --- 运行时验证
params: sessionIdParamSchema,
success: { data: promptSubmitResultSchema }, // 成功响应
errors: {
40001: { detailsSchema: z.array(/* ... */) }, // 校验失败
40401: {}, // 会话不存在
},
description: 'Submit a prompt to a session',
tags: ['prompts'],
},
async (req, reply) => {
// req.body → PromptSubmission (自动推断)
// req.params → { session_id: string }
// ...
},
);
app.post(submitRoute.path, submitRoute.options, submitRoute.handler);
这套系统带来的好处:
- 类型安全 :Handler 中的
req.body和req.params自动推断为正确的 Zod 类型 - 统一错误格式 :200 响应中通过
oneOf包含成功信封和所有可能的错误信封 - 文档即代码:定义 route 的同时就完成了 OpenAPI 文档的声明
- 零运行时开销:验证只在 preHandler 层执行一次
2.3 统一信封格式
所有 REST 响应都包裹在统一的信封中:
Typescript
// packages/kap-server/src/protocol/envelope.ts
interface Envelope<T> {
code: number; // 0 = 成功,4xxxx/5xxxx = 业务错误
msg: string; // 'success' 或错误描述
data: T | null; // 业务数据
request_id: string; // 请求追踪 ID
details?: unknown; // 结构化错误详情
stack?: string; // 堆栈信息(仅错误时)
}
code=0 表示成功,非零值为业务错误码。这与 HTTP 状态码分离------所有 kap-server 响应都是 HTTP 200 ,真正的结果通过信封中的 code 字段传达。Fastify 的 access log 因此被禁用,由 kap-server 自有的请求日志替代。
3. REST API 路由体系
3.1 路由注册总览
所有路由通过 registerApiV1Routes 统一注册,挂载在 /api/v1 前缀下。
Typescript
// packages/kap-server/src/routes/registerApiV1Routes.ts
export async function registerApiV1Routes(app, core, opts) {
await app.register(async (apiV1) => {
registerHealthRoute(apiV1); // /healthz
registerMetaRoute(apiV1); // /meta
registerAuthRoute(apiV1, core); // /auth/*
registerOAuthRoutes(apiV1, core); // /oauth/*
registerConfigRoutes(apiV1, core); // /config/*
registerModelCatalogRoutes(apiV1); // /models, /providers
registerSessionsRoutes(apiV1, core); // /sessions
registerPromptRoutes(apiV1, core); // /sessions/:id/prompts
registerMessagesRoutes(apiV1, core); // /sessions/:id/messages
registerApprovalsRoutes(apiV1, core); // /sessions/:id/approvals
registerQuestionsRoutes(apiV1, core); // /sessions/:id/questions
registerWorkspacesRoutes(apiV1); // /workspaces
registerFilesRoutes(apiV1, core); // /files
registerFsRoutes(apiV1, core); // /fs
registerToolsRoutes(apiV1, core); // /tools
registerTasksRoutes(apiV1, core); // /sessions/:id/tasks
registerTerminalsRoutes(apiV1, core); // /terminals
registerSkillsRoutes(apiV1, core); // /skills
registerTranscriptRoutes(apiV1); // /sessions/:id/transcript
registerSearchRoutes(apiV1, core); // /search
// ... 调试、快照、shutdown 等
}, { prefix: '/api/v1' });
}
3.2 核心路由详解
会话管理 --- /api/v1/sessions
会话路由是 kap-server 最复杂的路由模块,实现了 v1 的完整 wire contract:
| 方法 | 路径 | 功能 |
|---|---|---|
| POST | /sessions | 创建新会话(需 workspace_id 或 metadata.cwd) |
| GET | /sessions | 列表会话(支持 before_id/after_id 游标分页、workspace_id/status 过滤) |
| GET | /sessions/:id | 获取单个会话 |
| POST | /sessions/:id/profile | 更新标题、metadata、agent_config |
| GET | /sessions/:id/children | 列出子会话 |
| POST | /sessions/:id/children | 创建子会话(fork + tag) |
| POST | /sessions/:id/fork | Fork 会话(复制上下文到新会话) |
| POST | /sessions/:id/compact | 触发上下文压缩 |
| POST | /sessions/:id/undo | 撤销最后 N 轮对话 |
| POST | /sessions/:id/abort | 取消当前正在运行的 turn |
| POST | /sessions/:id/archive | 归档会话 |
| POST | /sessions/:id/restore | 恢复已归档会话 |
| POST | /sessions/:id/btw | 启动后台 Agent(side-channel) |
这些 action 路由通过统一的 /sessions/{tail} 模式处理------parseActionSuffix 从 tail 中解析出 { session_id, action },然后 dispatch 到对应的引擎服务。
Prompt 提交 --- /api/v1/sessions/:id/prompts
Prompt 路由处理用户输入的全流程:
- 会话恢复 :通过
resumeSessionById获取或冷加载会话 Scope - 图片处理 :提取 ContentPart 中的 base64 图片、解析
kimi-file://URL、压缩为模型可接受的尺寸 - 权限与策略 :应用
IAgentPermissionModeService和IAgentToolPolicyService - Profile 绑定 :通过
IAgentProfileService解析系统提示、工具集、Skills - 调度执行 :调用
IAgentPromptService.prompt()启动一次 turn - 事件广播:引擎产生的 token 流、工具调用、结果等事件通过 WebSocket 实时推送给前端
工作空间管理 --- /api/v1/workspaces
工作空间路由负责目录注册和文件浏览:
GET /workspaces--- 列表所有已注册的工作空间(从IWorkspaceService读取)POST /workspaces/register--- 注册新目录为工作空间GET /workspaces/:id/files--- 浏览工作空间目录树(folder picker)
4. WebSocket 实时通信
4.1 WebSocket 端点与升级流程
kap-server 在 /api/v1/ws 端点提供 WebSocket 实时通信。与传统的独立 WebSocket 服务器不同,它使用 ws 库的 noServer 模式 ------WebSocket 服务器不监听独立端口,而是挂载在 Fastify 的 HTTP Server 上,通过监听 upgrade 事件处理 WebSocket 握手。
Typescript
// packages/kap-server/src/start.ts
const wssV1 = registerWsV1(core, {
validateCredential,
registry: connectionRegistry,
broadcaster,
fsWatchBridge,
logger,
});
app.server.on('upgrade', (req, socket, head) => {
void handleUpgrade(req, socket, head).catch((error) =>
logger.error({ err: error }, 'ws upgrade handler failed'),
);
});
升级流程中会执行与 HTTP 路由相同的安全检查:Host/Origin 校验、Bearer Token 认证。所有检查通过后,WebSocket 连接才被建立。
4.2 WsConnectionV1:连接级协议
每个 WebSocket 连接由 WsConnectionV1 实例管理,该实例实现了 BroadcastTarget 接口,能够接收来自 SessionEventBroadcaster 的事件并转发给客户端。
连接建立后,服务器立即发送 server_hello 帧:
Typescript
// packages/kap-server/src/transport/ws/v1/wsConnectionV1.ts
this.sendImmediateFrame(
buildServerHello({
ws_connection_id: this.id,
protocol_version: WS_PROTOCOL_VERSION,
max_event_buffer_size: this.maxBufferSize,
capabilities: { event_batching: false, compression: false },
}),
);
4.3 控制帧协议
客户端通过 JSON 帧与服务器通信,支持以下控制帧类型:
| 帧类型 | 方向 | 说明 |
|---|---|---|
| server_hello | Server→Client | 连接建立后立即发送,宣告协议版本和能力 |
| client_hello | Client→Server | 客户端握手,可携带 initial subscriptions 和 cursors |
| subscribe | Client→Server | 订阅会话事件,指定 session_id + agents + 事件游标 |
| subscribe_v2 | Client→Server | v2 订阅:按 transcript grade 分级订阅(text、tool_call、thinking 等) |
| unsubscribe | Client→Server | 取消订阅指定会话 |
| unsubscribe_v2 | Client→Server | 取消 v2 的分级订阅 |
| ack | Server→Client | 确认客户端的事件序列号 |
| resync_required | Server→Client | 服务器无法增量补齐事件,客户端需全量重同步 |
| watch_fs_add | Client→Server | 请求监听文件系统变更 |
| watch_fs_remove | Client→Server | 取消文件系统监听 |
4.4 事件广播机制
SessionEventBroadcaster 是事件分发的核心。它维护一个持久化的事件日志(SessionEventJournal),每个会话事件被写入日志后广播给所有订阅该会话的连接。
事件分发分为两个通道:
- Global 通道 :全局事件(session created/deleted、workspace 变更、配置更新)推送给所有已建立连接的客户端,无需订阅
- Subscription 通道:会话级事件(token 增量、工具调用、审批请求)仅推送给已订阅该会话的连接
4.5 事件缓冲与背压控制
高频事件(尤其是 token 级别的文本增量)如果逐帧发送会造成大量小包。WsConnectionV1 使用了一个发送缓冲区:
- 订阅事件的发送采用 16ms 刷新间隔(约 60fps),支持最多 64 帧的批量发送
- 立即帧(公共事件、控制帧响应)作为 FIFO 屏障,会先刷新缓冲区中的订阅帧
- 当
socket.bufferedAmount超过 1 MiB 时触发背压,延迟发送直到缓冲区清空
Typescript
// 默认参数
const DEFAULT_FLUSH_INTERVAL_MS = 16; // 刷新间隔(约 60fps)
const DEFAULT_MAX_BATCH_SIZE = 64; // 单批最大帧数
const DEFAULT_HIGH_WATER_MARK_BYTES = 1 << 20; // 1 MiB
const DEFAULT_BACKPRESSURE_RETRY_MS = 5;
4.6 Transcript 增量同步
connect_v2 的 subscribe_v2 帧引入了按 Transcript Grade 的分级订阅。客户端可以只订阅自己关心的 Grade(如 text、tool_call、thinking),服务器只推送对应类型的事件。这大幅减少了不必要的数据传输,尤其是在长对话场景下。
TranscriptService 为每个活跃会话维护一个 TranscriptStore,引擎产生的每个 WireRecord 都会实时投影到 Store 中。当 WebSocket 客户端订阅某个 Grade 时,Store 会从客户端的游标位置开始增量推送,如果游标落后太多则发送 resync_required 要求客户端执行全量重同步。
5. 会话生命周期管理
5.1 会话创建流程
会话创建是 kap-server 中最关键的流程之一。从 REST 请求到引擎实例化,涉及多个步骤:
Typescript
// packages/kap-server/src/routes/sessions.ts --- POST /sessions
async (req, reply) => {
// 1. 解析 cwd:从 workspace_id 或 metadata.cwd 中获取工作目录
const workDir = workspaceId ? workspace.root : body.metadata.cwd;
// 2. 注册工作空间(createOrTouch 是幂等的)
const touched = await core.accessor.get(IWorkspaceService).createOrTouch(workDir);
// 3. 获取工作空间的生命周期 handler
const handler = await core.accessor.get(IWorkspaceLifecycleService).handlerFor({ root: workDir });
// 4. 通过 handler 的 SessionLifecycleService 创建会话
const handle = await handler.accessor.get(ISessionLifecycleService).create({ workDir });
// 5. 设置标题、读取元数据
await handle.accessor.get(ISessionMetadata).setTitle(body.title);
const meta = await handle.accessor.get(ISessionMetadata).read();
// 6. 发布 session.created 事件(WebSocket 广播)
core.accessor.get(IEventService).publish({
type: 'event.session.created',
payload: { agentId: 'main', sessionId: session.id, session },
});
}
5.2 Session Store 持久化
kap-server 的会话数据持久化完全委托给 agent-core-v2 引擎。在 bootstrap() 阶段,引擎通过 IFileSystemStorageService 将存储根路径设定为 <homeDir>。所有会话相关的持久化:
- 元数据 :通过
ISessionMetadata保存到 append-log 中(id、title、createdAt、custom metadata) - 会话索引 :
ISessionIndex维护FileSessionIndex,按 recency 排序 - Wire Records :每个 Agent 的消息、工具调用、任务状态等以 JSONL 格式写入
agents/<agentId>/wire.jsonl - 二进制数据 :上传的文件、图片等通过
IBlobStorageService存储
会话的 cwd 保存在 ISessionMetadata 的自定义字段中(gap G3 关闭)。即使工作空间被注销,会话仍然可以通过自有的 cwd 信息被列出和访问。
5.3 多 Agent 支持
kap-server 的会话模型支持多个 Agent 共存:
- Main Agent:每个会话默认有一个主 Agent,负责接收用户 Prompt 并生成回复
- Subagents / Side-channel :通过
POST /sessions/:id/btw启动后台 Agent,可以在不干扰主会话的情况下执行独立任务 - Children Sessions :通过
POST /sessions/:id/children创建子会话(fork + parent_tag)
每个 Agent 都是一个独立的 Scope 实例,拥有自己的上下文记忆(IAgentContextMemoryService)、工具集和生命周期。WebSocket 的 subscribe 帧通过 agents 字段指定订阅哪些 Agent 的事件。全局搜索扫描所有 Agent 的 WireRecord。
5.4 会话的暂停、恢复与 Fork
kap-server 中的会话并非始终在内存中。当连接断开或会话空闲时,会话 Scope 可以被释放;当客户端再次访问时,通过 resumeSessionById 从磁盘重建。
Fork 操作在 ISessionLifecycleService.fork() 中实现------它会创建一个新会话,复制源会话的上下文历史(作为系统消息注入),使新会话继承源会话的全部对话上下文但拥有独立的对话未来。
6. V2 引擎集成
6.1 引擎初始化
kap-server 在 startServer() 中通过 agent-core-v2 的 bootstrap() 函数创建 Core Scope:
Typescript
// packages/kap-server/src/start.ts
const { app: core } = bootstrap(
{
homeDir,
configPath,
clientIdentity: opts.hostIdentity,
},
[
...logSeed(logging), // 日志配置
...hostRequestHeadersSeed(kimiHeaders), // HTTP 请求头
...skillCatalogRuntimeOptionsSeed(skillDirs), // Skill 目录
...hostIdentitySeed(opts.hostIdentity), // 宿主身份
...(opts.seeds ?? []), // 额外配置
],
);
bootstrap() 返回的 core 是一个 App 级别的 Scope,它包含了所有引擎服务的注册。kap-server 的每个路由 handler 都通过 core.accessor.get(ISomeService) 获取需要的引擎服务实例。
6.2 DI x Scope 在服务层的应用
kap-server 不直接持有引擎状态------所有状态都在 Scope 层次结构中:
scss
App Scope (core)
├── ISessionIndex --- 全局会话索引
├── IWorkspaceService --- 工作空间注册表
├── IConfigService --- 配置读写
├── IEventService --- 事件总线
├── IProviderDiscoveryService --- Provider 发现
├── IWorkspaceLifecycleService
│ └── handlerFor(root) → Workspace Scope
│ ├── ISessionLifecycleService --- 会话的创建/fork/归档
│ │ └── create({ workDir }) → Session Scope
│ │ ├── ISessionMetadata --- 会话元数据
│ │ ├── ISessionContext --- cwd、workspaceId
│ │ ├── IAgentLifecycleService --- Agent 生命周期
│ │ │ └── createMainAgent() → Agent Scope
│ │ │ ├── IAgentPromptService --- Prompt 处理
│ │ │ ├── IAgentContextMemoryService --- 对话历史
│ │ │ ├── IAgentToolPolicyService --- 工具策略
│ │ │ ├── IAgentLoopService --- Agent 循环
│ │ │ └── ...
│ │ └── ...
│ └── ...
└── ...
这种三级嵌套 DI 的语义是:App 级别的服务是全局单例,Workspace 级别的服务在同一个工作空间的所有会话之间共享,Session 和 Agent 级别的服务是每个会话/Agent 独立的。kap-server 路由 handler 从 App Scope 进入,通过 handlerFor、resumeSessionById、ensureMainAgent 等函数逐步下沉到更细粒度的 Scope。
6.3 请求 → Agent → 响应的完整路径
以用户提交一个 Prompt 为例,完整路径如下:
scss
POST /api/v1/sessions/abc/prompts (HTTP)
│
▼
registerPromptsRoutes → defineRoute (Zod 验证 body/params)
│
▼
resumeSessionById(core.accessor, sessionId) --- 获取/冷加载 Session Scope
│
▼
ensureMainAgent(session) --- 获取 Main Agent Scope
│
▼
IAgentPromptService.prompt(content, options) --- 调度执行
│
├─→ IAgentLoopService --- Agent 循环(think → act → observe)
│ │
│ ├─→ LLM 调用 → token 流
│ ├─→ Tool 调用 → Bash / File / Search ...
│ └─→ 事件发射 → IEventService.publish(...)
│
▼
SessionEventBroadcaster --- 事件持久化 + 广播
│
├─→ SessionEventJournal --- 写入事件日志
└─→ WebSocket 推送 --- 分发给所有订阅的客户端
│
▼
kimi-web / kimi-inspect --- 实时渲染
6.4 引擎事件的 WebSocket 转发
引擎的 IEventService 是事件源。kap-server 的 SessionEventBroadcaster 订阅引擎事件总线的 session.* 前缀事件:
- agent.* :
agent.turn_started、agent.turn_ended、agent.text_delta、agent.tool_call等 --- 推送给订阅了该会话的 WebSocket 连接 - session.* :
session.created、session.meta.updated、session.archived--- 全局广播 - workspace.* :
workspace.created、workspace.deleted--- 全局广播
TranscriptService 在这些事件的基础上构建 TranscriptStore,将原始事件转换为结构化的 Transcript 操作(upsert、reset),供 REST transcript 端点和 WebSocket 的 subscribe_v2 使用。
7. 多引擎支持
7.1 V1 与 V2 的架构差异
kap-server 是 agent-core-v2 引擎的服务层,但 kimi-code 历史上还有一个基于 agent-core (V1) 的服务器(packages/server)。两者的架构差异显著:
| 对比维度 | V1 Server (agent-core) | V2 Server (kap-server) |
|---|---|---|
| DI 容器 | IInstantiationService(扁平 DI) | DI × Scope(三级嵌套 DI) |
| 事件模型 | EventEmitter + wsGatewayService | IEventService + SessionEventBroadcaster |
| 会话存储 | SessionService(单文件) | ISessionMetadata + FileSessionIndex + WireRecord |
| Agent 模型 | 单一 Agent | 多 Agent(main + subagent + children) |
| Transcript | 无标准 Transcript | TranscriptStore + Grade 分级订阅 |
| 路由定义 | Express 风格 | defineRoute(Zod → Swagger) |
7.2 引擎切换机制
在 kimi-code CLI 中,引擎切换通过配置项控制:
- KIMI_CODE_USE_V2 :环境变量,
"1"启用 V2 引擎 - config.json :配置文件中的
engine_version字段 - CLI flag :
--use-v2命令行参数
当 V2 引擎被激活时,CLI 的 kimi web 命令调用 startServer 启动 kap-server;否则启动 V1 Server。两者的 /api/v1 接口保持兼容,kimi-web 前端无需感知后端是哪个版本------它通过同一个 API 路径与任一引擎通信。
7.3 开发模式下的双引擎调试
在开发模式下,可以同时运行 V1 和 V2 引擎的服务器:
- V1 Server 默认在 58627 端口
- V2 (kap-server) 默认也在 58627 端口,使用 port+1 重试机制:如果端口被占用,自动尝试 58628、58629......最多重试 100 次
- 两个服务器通过
instanceRegistry独立注册在<homeDir>/server/instances/下,互不冲突
这种设计使得在迁移期间,前端可以同时连接两个后端进行对比测试。每个 kap-server 实例的注册信息(PID、host、port、启动时间、serverVersion)以 JSON 文件持久化,kimi server ps 和 kimi server kill 命令可以列出和管理所有实例。
8. 调试接口
8.1 Debug RPC 接口
kap-server 提供了一套完整的调试 RPC 接口,挂载在 /api/v1/debug/* 路径下。该接口仅在以下条件同时满足时启用:
- 启动时传入
--debug-endpoints参数 - 服务器绑定在 loopback 地址(127.0.0.1)
- 请确保携带有效的 Bearer Token
Typescript
// packages/kap-server/src/start.ts
const debugEndpoints = exposureClass === 'loopback' && opts.debugEndpoints === true;
// ...
if (debugEndpoints === true) {
registerDebugRoutes(apiV1, core);
}
这些限制确保了调试接口不会在非安全环境下暴露------它允许调用者访问引擎内部的所有 Service,是具有完全权限的管理接口。
8.2 DI 容器反射
Debug 路由实际注册的是 registerServiceDispatcherRoutes------一个基于 DI 反射的 Service 调度器:
Typescript
// packages/kap-server/src/transport/registerDebugRoutes.ts
export function registerDebugRoutes(app, core) {
registerServiceDispatcherRoutes(app, core, '/debug', {
lookup: resolveAnyScopedServiceId, // 跨所有 Scope 查找 Service
describe: describeAllChannels, // 列出所有可用的 RPC 通道
});
}
resolveAnyScopedServiceId 不仅能在 App Scope 中查找 Service,还能穿透 Session 和 Agent Scope------通过 session_id 和 agent_id 参数定位到正确的嵌套 Scope,然后从中取出目标 Service 实例。
describeAllChannels 暴露了所有可调用服务通道的完整列表,包括每个通道的输入/输出 Schema 和描述信息。这实际上是一个运行时的 DI 容器反射 API。
8.3 Service 面板
kimi-inspect 调试面板正是通过这组 Debug RPC 接口与 kap-server 交互。它提供两种核心操作:
- **数据查询(GET)**:读取 Service 的当前状态。例如读取
IAgentContextMemoryService的对话历史、ISessionMetadata的元数据、IConfigService的当前配置 - **触发按钮(POST)**:调用 Service 的方法。例如触发 compaction、重置对话上下文、切换 permission mode
典型的 debug 请求路径为 /api/v1/debug/<serviceId>/<method>,其中 serviceId 是 DI 注册的 Service 唯一标识,method 是 Service 暴露的 RPC 方法名。
8.4 kimi-inspect 的消费模式
kimi-inspect 是一个独立的 Web 应用,它作为 kap-server 的客户端运行。它通过以下方式消费调试接口:
- 启动时 :调用
describeAllChannels获取完整的 Service 清单,构建左侧导航树 - 选中 Service 时:自动调用该 Service 的只读方法来填充数据面板
- 用户点击按钮时:发送 POST 请求调用对应的 RPC 方法
- 实时更新:通过 WebSocket 订阅会话事件,面板中的数据实时刷新
这种设计使得 kimi-inspect 成为一个完全动态的调试工具------它不需要硬编码任何 Service 的名称或方法,所有能力都通过运行时的 DI 反射发现。