gemini-cli SDK/CLI 控制协议能力完整清单

📋 目录


1. CLI 端能力

1.1 控制请求类型(8种)

① initialize(初始化)

功能:初始化会话,接收 SDK 配置

请求参数

{
  subtype: 'initialize';
  hooks?: Record<string, HookMatcher[]> | null;         // Hook 注册(暂不处理)
  sdkMcpServers?: Record<string, SdkMcpServerConfig>;   // SDK MCP 服务器(暂不处理)
  mcpServers?: Record<string, McpServerConfig>;         // 外部 MCP 服务器(暂不处理)
  agents?: AgentConfig[];                               // Agent 配置(暂不处理)
}

实现位置packages/cli/src/sdk/controlProtocol.ts:190-221

实现状态:⚠️ 部分实现

返回值

{
  commands: string[];                          // 支持的工具列表
  output_style: 'stream-json';                 // 输出格式
  capabilities: {
    tools: string[];                          // 可用工具
    mcpServers: false;                        // ❌ 暂不支持 MCP
    hooks: false;                             // ❌ 暂不支持 Hook
    permissionControl: boolean;               // 是否支持权限控制
  };
  model: string;                              // 当前模型
  permissionMode: string;                     // 当前权限模式
}

行为

  • 接收所有配置参数但不处理(注释标注"暂不实现")
  • 返回初始化结果
  • 标记 mcpServers: false, hooks: false

② interrupt(中断)

功能:中断当前会话

请求参数

{
  subtype: 'interrupt';
}

实现位置packages/cli/src/sdk/controlProtocol.ts:287-296

实现状态:✅ 完整实现

返回值

null;  // 无返回值

行为

  1. 设置 interrupted = true
  2. 触发 emit('interrupt') 事件
  3. Session 监听该事件并调用 abortController.abort()

③ set_model(设置模型)

功能:设置当前模型(仅存储,不实际切换)

请求参数

{
  subtype: 'set_model';
  model: string | null;
}

实现位置packages/cli/src/sdk/controlProtocol.ts:317-330

实现状态:⚠️ 占位实现

返回值

null;

行为

if (model) {
  this.currentModel = model;
  // TODO: 实际切换模型(需要重新创建客户端)
}

差异:只存储模型名称,不进行验证或实际切换


④ supported_commands(支持的命令)

功能:获取支持的工具列表

请求参数

{
  subtype: 'supported_commands';
}

实现位置packages/cli/src/sdk/controlProtocol.ts:358-362

实现状态:✅ 完整实现

返回值

{
  commands: string[];  // 从构造函数传入的 supportedTools
}

⑤ can_use_tool(工具权限检查)

功能:检查工具使用权限

请求参数

{
  subtype: 'can_use_tool';
  tool_name: string;
  tool_use_id: string;
  input: unknown;
  permission_suggestions?: PermissionSuggestion[];
  blocked_path?: string | null;
}

实现位置packages/cli/src/sdk/controlProtocol.ts:226-282

实现状态:✅ 完整实现

返回值

{
  behavior: 'allow' | 'deny';     // 允许或拒绝
  updatedInput?: unknown;          // 修改后的输入
  message?: string;                // 拒绝原因
  interrupt?: boolean;             // 是否中断
}

行为

  1. 如果没有提供 canUseToolCallback,默认允许所有工具
  2. 如果有回调,创建 60 秒超时控制
  3. 调用用户回调函数
  4. 超时或错误时默认拒绝(安全策略)

超时配置

const DEFAULT_TIMEOUTS = {
  canUseTool: 60000,  // 60秒
  controlRequest: 60000,
  initialize: 60000,
};

⑥ set_permission_mode(设置权限模式)

功能:设置权限模式(仅存储,不实际切换)

请求参数

{
  subtype: 'set_permission_mode';
  mode: string;  // 'default' | 'plan' | 'auto-edit' | 'yolo'
}

实现位置packages/cli/src/sdk/controlProtocol.ts:301-312

实现状态:⚠️ 占位实现

返回值

null;

行为

this.currentPermissionMode = mode;
// TODO: 实际更新配置中的权限模式

差异:只存储模式字符串,不验证有效性或实际更新配置


⑦ mcp_server_status(MCP 服务器状态)

功能:获取 MCP 服务器状态(占位)

请求参数

{
  subtype: 'mcp_server_status';
}

实现位置packages/cli/src/sdk/controlProtocol.ts:349-353

实现状态:❌ 占位实现

返回值

{
  servers: {};  // 空对象
}

行为:返回空对象,不支持任何 MCP 服务器


⑧ mcp_message(MCP 消息传递)

功能:MCP 消息路由(占位)

请求参数

{
  subtype: 'mcp_message';
  server_name: string;
  message: McpMessage;
}

实现位置packages/cli/src/sdk/controlProtocol.ts:335-344

实现状态:❌ 明确不支持

返回值

{
  error: 'MCP servers are not supported in Gemini CLI';
  mcp_response: { jsonrpc: '2.0', result: {}, id: 0 };
}

行为:明确返回错误信息,不支持 MCP 消息


1.2 控制协议处理器

ControlProtocolHandler 类

位置packages/cli/src/sdk/controlProtocol.ts

继承extends EventEmitter

职责

  • 处理来自 SDK 的控制请求
  • 调用用户提供的回调函数
  • 返回控制响应
  • 管理待处理的请求(pendingRequests Map)

字段

private pendingRequests = new Map<string, {
  resolve: (value: unknown) => void;
  reject: (error: Error) => void;
  timeout: NodeJS.Timeout;
  abortController: AbortController;
}>();

private canUseToolCallback?: (toolName: string, toolInput: unknown, context: ToolPermissionContext) => Promise<PermissionResult>;
private currentPermissionMode: string = 'default';
private currentModel: string;
private initializationResult: unknown = null;
private debugMode: boolean;
private supportedTools: string[];
private interrupted: boolean = false;

公共方法

  1. handleControlRequest(request: SDKControlRequest) - 处理控制请求
  2. isInterrupted() - 检查是否已中断
  3. resetInterrupt() - 重置中断状态
  4. getCurrentModel() - 获取当前模型
  5. getCurrentPermissionMode() - 获取当前权限模式
  6. cleanup() - 清理资源

1.3 Session 集成

SDK 模式检测

位置packages/cli/src/nonInteractive/session.ts:114-148

检测方式

this.isSdkMode = process.env['GEMINI_CHANNEL'] === 'SDK' ||
                 process.argv.includes('--channel=SDK') ||
                 process.argv.findIndex((x, i) => x === '--channel' && isChannelArg(i)) >= 0;

初始化

if (this.isSdkMode) {
  const supportedTools = this.config.getCoreTools?.() ?? [];
  const model = this.config.getModel();
  this.controlHandler = new ControlProtocolHandler(
    model,
    supportedTools,
    this.debugMode,
    undefined  // canUseToolCallback - 可选
  );

  // 监听中断事件
  this.controlHandler.on('interrupt', () => {
    this.abortController.abort();
  });
}

控制请求路由

// 在 Session.run() 主循环中
if (this.isSdkMode && isControlRequest(message)) {
  await this.handleControlRequest(message);
  continue;
}

1.4 输出写入机制

writeControlResponse() 方法

位置packages/cli/src/nonInteractive/io/StreamJsonOutputAdapter.ts:625-644

写入方式

writeControlResponse(response: SDKControlResponse): void {
  const jsonStr = `${JSON.stringify(response)}\n`;
  process.stderr.write(`[CONTROL_RESPONSE] Writing: ${jsonStr}`);

  try {
    // 获取 stdout 文件描述符
    const fd = (process.stdout as any)._handle?.fd || (process.stdout as any).fd || 1;
    const buffer = new TextEncoder().encode(jsonStr);
    // 使用 fs.writeSync 同步写入,绕过所有缓冲
    fsWriteSync(fd, buffer);
  } catch (error) {
    // 如果 writeSync 失败,回退到普通写入
    process.stderr.write(`[CONTROL_RESPONSE] writeSync failed: ${error}\n`);
    process.stdout.write(jsonStr);
  }
}

特点

  • 同步写入:使用 fs.writeSync(fd, buffer)
  • 绕过缓冲:直接写入文件描述符,确保可靠性
  • 回退机制:writeSync 失败时回退到 process.stdout.write()
  • 调试输出:写入 stderr 避免污染 stdout

对比

  • qwen-code:全部使用 process.stdout.write()(异步)
  • gemini-cli
    • 普通消息:process.stdout.write()(异步)
    • 控制响应:fs.writeSync()(同步)

2. SDK 端能力

2.1 类型定义(完整)

SDKControlRequest
interface SDKControlRequest {
  type: 'control_request';
  request_id: string;
  request: ControlRequestPayload;
}
ControlRequestPayload(8种)
type ControlRequestPayload =
  | InitializeRequest           // 初始化
  | CanUseToolRequest          // 工具权限
  | InterruptRequest           // 中断
  | SetPermissionModeRequest   // 设置权限模式
  | SetModelRequest            // 设置模型
  | McpMessageRequest          // MCP 消息
  | McpServerStatusRequest     // MCP 状态
  | SupportedCommandsRequest;  // 支持的命令
SDKControlResponse
interface SDKControlResponse {
  type: 'control_response';
  response: ControlSuccessResponse | ControlErrorResponse;
}

interface ControlSuccessResponse {
  subtype: 'success';
  request_id: string;
  response: unknown;
}

interface ControlErrorResponse {
  subtype: 'error';
  request_id: string;
  error: string | { message: string; [key: string]: unknown };
}
类型守卫
function isControlRequest(message: unknown): message is SDKControlRequest;
function isControlResponse(message: unknown): message is SDKControlResponse;
function isControlCancel(message: unknown): message is ControlCancelRequest;

位置packages/cli/src/sdk/types.ts


2.2 输入读取

StreamJsonInputReader

位置packages/cli/src/nonInteractive/io/StreamJsonInputReader.ts

功能:从 stdin 逐行读取 JSON 消息

实现

async *read(): AsyncGenerator<StreamJsonInputMessage> {
  const rl = createInterface({
    input: this.input,
    crlfDelay: Number.POSITIVE_INFINITY,  // 支持跨平台换行符
    terminal: false,                       // 非终端模式(管道输入)
  });

  for await (const rawLine of rl) {
    const line = rawLine.trim();
    if (!line) continue;
    yield this.parse(line);
  }
}

支持的消息类型

type StreamJsonInputMessage =
  | CLIMessage
  | CLIControlRequest
  | CLIControlResponse
  | ControlCancelRequest;

验证

  • 必须是对象
  • 必须有 type 字段
  • type 必须是字符串

2.3 消息输出

StreamJsonOutputAdapter

位置packages/cli/src/nonInteractive/io/StreamJsonOutputAdapter.ts

职责

  • 处理 Gemini API 事件流
  • 构建标准格式的 JSON 消息
  • 输出到 stdout

输出方法

  1. emitMessageImpl(message: CLIMessage) - 发送消息(异步)
  2. writeControlResponse(response: SDKControlResponse) - 发送控制响应(同步)
  3. emitResult(options: ResultOptions) - 发送结果消息
  4. emitUserMessage(parts: Part[]) - 发送用户消息
  5. emitToolResult(request, response) - 发送工具结果
  6. emitSystemMessage(subtype, data) - 发送系统消息

写入方式对比

方法 写入方式 用途
emitMessageImpl() process.stdout.write() 普通消息(异步)
writeControlResponse() fs.writeSync(fd, buffer) 控制响应(同步)

3. 类型定义清单

3.1 控制请求载荷(8种)

InitializeRequest
interface InitializeRequest {
  subtype: 'initialize';
  hooks?: Record<string, HookMatcher[]> | null;
  sdkMcpServers?: Record<string, SdkMcpServerConfig>;
  mcpServers?: Record<string, McpServerConfig>;
  agents?: AgentConfig[];
}
CanUseToolRequest
interface CanUseToolRequest {
  subtype: 'can_use_tool';
  tool_name: string;
  tool_use_id: string;
  input: unknown;
  permission_suggestions?: PermissionSuggestion[];
  blocked_path?: string | null;
}
InterruptRequest
interface InterruptRequest {
  subtype: 'interrupt';
}
SetPermissionModeRequest
interface SetPermissionModeRequest {
  subtype: 'set_permission_mode';
  mode: string;
}
SetModelRequest
interface SetModelRequest {
  subtype: 'set_model';
  model: string | null;
}
McpMessageRequest
interface McpMessageRequest {
  subtype: 'mcp_message';
  server_name: string;
  message: McpMessage;
}

interface McpMessage {
  jsonrpc?: string;
  method: string;
  params?: Record<string, unknown>;
  id?: string | number | null;
}
McpServerStatusRequest
interface McpServerStatusRequest {
  subtype: 'mcp_server_status';
}
SupportedCommandsRequest
interface SupportedCommandsRequest {
  subtype: 'supported_commands';
}

3.2 配置类型

SdkMcpServerConfig
interface SdkMcpServerConfig {
  type: 'sdk';
  name: string;
}
McpServerConfig
interface McpServerConfig {
  command?: string;
  args?: string[];
  env?: Record<string, string>;
  cwd?: string;
  url?: string;
  httpUrl?: string;
  headers?: Record<string, string>;
  tcp?: string;
  timeout?: number;
  trust?: boolean;
  description?: string;
  includeTools?: string[];
  excludeTools?: string[];
  extensionName?: string;
}
AgentConfig
interface AgentConfig {
  name: string;
  description?: string;
  tools?: string[];
  systemPrompt?: string;
  level?: string;
  filePath?: string;
  modelConfig?: {
    model?: string;
    temp?: number;
    topP?: number;
  };
  runConfig?: {
    maxTimeMinutes?: number;
    maxTurns?: number;
  };
  color?: string;
}
PermissionSuggestion
interface PermissionSuggestion {
  type: 'allow' | 'deny' | 'modify';
  label: string;
  description?: string;
  modifiedInput?: unknown;
}
HookMatcher
interface HookMatcher {
  matcher?: string | null;
  hookCallbackIds: string[];
  timeout?: number;
}
PermissionMode
type PermissionMode = 'default' | 'plan' | 'auto-edit' | 'yolo';

3.3 消息类型

CLIMessage(5种)
type CLIMessage =
  | CLIUserMessage              // 用户消息
  | CLIAssistantMessage         // 助手消息
  | CLISystemMessage            // 系统消息
  | CLIResultMessage            // 结果消息
  | CLIPartialAssistantMessage; // 部分助手消息(流事件)
ContentBlock(4种)
type ContentBlock =
  | TextBlock          // { type: 'text', text: string }
  | ThinkingBlock      // { type: 'thinking', thinking: string }
  | ToolUseBlock       // { type: 'tool_use', id, name, input }
  | ToolResultBlock;   // { type: 'tool_result', tool_use_id, content }

4. 完整能力矩阵

4.1 控制请求能力矩阵

# 控制请求 CLI 处理 实现状态 完整度 说明
1 initialize ⚠️ 部分实现 30% 接收配置但不处理
2 interrupt ✅ 完整 100% 完整实现
3 set_model ⚠️ 占位 10% 仅存储,TODO
4 supported_commands ✅ 完整 100% 返回工具列表
5 can_use_tool ✅ 完整 100% 完整实现+超时
6 set_permission_mode ⚠️ 占位 10% 仅存储,TODO
7 mcp_server_status ❌ 占位 5% 返回空对象
8 mcp_message ❌ 不支持 0% 明确返回错误

4.2 架构能力矩阵

能力 gemini-cli qwen-code 实现差异
架构模式 单一 Handler 类 三层架构 ⚠️ 简化
控制器数量 1 个 5 个 ⚠️ 缺少分层
状态管理 字段存储 ControlContext ⚠️ 简化
请求路由 switch-case 自动路由 ⚠️ 手动分发
生命周期管理 ✅ pendingRequests Map ✅ 注册表+超时+取消 ✅ 相似
双向通信 ❌ 无 ✅ CLI→SDK 控制 ❌ 缺失
错误处理 ✅ 统一格式 ✅ 统一格式 ✅ 相似
类型安全 ✅ 完整类型 ✅ 完整类型 ✅ 相似
可扩展性 ⚠️ 需修改核心 ✅ 添加 Controller ⚠️ 中等

4.3 功能特性矩阵

权限系统特性
特性 gemini-cli qwen-code 状态
4 种权限模式类型 ✅ 类型定义 ✅ 实际切换 ⚠️ 仅类型
工具权限回调 ✅ 支持 ✅ 支持 ✅ 相同
权限建议系统 ✅ 接收 ✅ 生成建议 ⚠️ 仅接收
超时控制 ✅ 60秒 ✅ 60秒 ✅ 相同
模式实际切换 ❌ TODO ✅ 验证+更新 ❌ 缺失
MCP 集成特性
特性 gemini-cli qwen-code 状态
SDK MCP 服务器 ❌ 不支持 ✅ 完整支持 ❌ 缺失
外部 MCP 服务器 ❌ 不支持 ✅ 完整支持 ❌ 缺失
OAuth 支持 ❌ 无 ✅ 3种认证 ❌ 缺失
消息路由 ❌ 返回错误 ✅ 双向路由 ❌ 缺失
服务器状态查询 ❌ 返回空 ✅ 实际状态 ❌ 缺失
系统控制特性
特性 gemini-cli qwen-code 状态
模型切换 ⚠️ 仅存储 ✅ 验证+切换+回滚 ❌ 缺失
中断控制 ✅ 完整 ✅ 完整 ✅ 相同
命令列表 ✅ 静态列表 ✅ 动态加载 ⚠️ 静态
系统消息通知 ✅ 支持 ✅ 支持 ✅ 相同
Agent 配置 ❌ 忽略 ✅ 实际处理 ❌ 缺失
写入机制特性
特性 gemini-cli qwen-code 差异
普通消息写入 异步 异步 ✅ 相同
控制响应写入 同步 异步 ⚠️ 不同
写入方式 fs.writeSync() process.stdout.write() ⚠️ 不同
缓冲策略 绕过缓冲 使用缓冲 ⚠️ 不同
回退机制 ✅ 支持 ❌ 无 ✅ 优势

4.4 写入机制对比详解

gemini-cli
// 控制响应:同步写入
writeControlResponse(response: SDKControlResponse): void {
  const fd = (process.stdout as any)._handle?.fd || 1;
  const buffer = new TextEncoder().encode(jsonStr);
  fsWriteSync(fd, buffer);  // 绕过缓冲,确保可靠性
}

// 普通消息:异步写入
emitMessageImpl(message: CLIMessage): void {
  process.stdout.write(`${JSON.stringify(message)}\n`);
}
qwen-code
// 所有消息:异步写入
emitMessageImpl(message: CLIMessage | ControlMessage): void {
  process.stdout.write(`${JSON.stringify(message)}\n`);
}

关键差异

  1. gemini-cli:控制响应使用同步写入,确保立即发送
  2. qwen-code:全部使用异步写入,依赖系统缓冲

5. 核心文件位置

5.1 CLI 端核心文件

packages/cli/src/
├── sdk/
│   ├── controlProtocol.ts              # 控制协议处理器(435行)
│   └── types.ts                        # SDK 类型定义(323行)
└── nonInteractive/
    ├── session.ts                      # 会话管理(748行)
    ├── types.ts                        # CLI 类型定义(573行)
    └── io/
        ├── StreamJsonInputReader.ts    # 输入读取器(98行)
        └── StreamJsonOutputAdapter.ts  # 输出适配器(892行)

5.2 关键代码位置

ControlProtocolHandler
  • 文件:packages/cli/src/sdk/controlProtocol.ts:67-434
  • 类定义:435行
  • 控制请求处理:handleControlRequest()
  • 初始化处理:handleInitialize() (line 190)
  • 权限检查:handleCanUseTool() (line 226)
  • 中断处理:handleInterrupt() (line 287)
  • 权限模式设置:handleSetPermissionMode() (line 301)
  • 模型设置:handleSetModel() (line 317)
  • MCP 消息:handleMcpMessage() (line 335)
  • MCP 状态:handleMcpServerStatus() (line 349)
  • 命令列表:handleSupportedCommands() (line 358)
Session 集成
  • SDK 模式检测:packages/cli/src/nonInteractive/session.ts:114-148
  • 控制请求路由:packages/cli/src/nonInteractive/session.ts:629-633
  • 控制请求处理:packages/cli/src/nonInteractive/session.ts:482-519
写入机制
  • 同步写入:packages/cli/src/nonInteractive/io/StreamJsonOutputAdapter.ts:625-644
  • 异步写入:packages/cli/src/nonInteractive/io/StreamJsonOutputAdapter.ts:523-536

6. 总结

6.1 功能统计

类别 数量 完整实现率
控制请求类型 8 种 43%(3.5/8)
完整实现 3 个 37.5%
部分实现 2 个 25%
占位实现 3 个 37.5%
核心文件数 5 个 -

6.2 实现完整度分析

✅ 完整实现(3个)
  1. interrupt - 中断控制
  2. supported_commands - 命令列表
  3. can_use_tool - 工具权限(含超时)
⚠️ 部分实现(2个)
  1. initialize - 接收配置但不处理
    • hooks: 忽略
    • sdkMcpServers: 忽略
    • mcpServers: 忽略
    • agents: 忽略
  2. can_use_tool - 仅回调,无工具注册表检查
❌ 占位/不支持(3个)
  1. set_model - 仅存储,TODO
  2. set_permission_mode - 仅存储,TODO
  3. mcp_server_status - 返回空对象
  4. mcp_message - 明确返回错误

6.3 关键特性

  1. 基础控制协议:8 种控制请求全部定义
  2. 权限回调机制:完整的 canUseTool 回调系统
  3. 超时控制:60秒超时保护
  4. 中断机制:完整的中断控制
  5. ⚠️ 权限模式切换:仅存储,不实际生效
  6. ⚠️ 模型切换:仅存储,不实际切换
  7. MCP 集成:完全不支持
  8. Hook 系统:类型定义存在但不处理
  9. Agent 配置:忽略所有配置
  10. 同步写入:控制响应使用 fs.writeSync

6.4 与 qwen-code 对比

维度 gemini-cli qwen-code 差距
架构复杂度 简单(单类) 复杂(三层) -2 层
代码行数 ~3,000 行 ~5,000 行 -40%
控制请求完整度 43% 95% -52%
MCP 支持 完全缺失
权限系统 ⚠️ 基础 ✅ 完整 缺少实际切换
模型切换 ⚠️ 占位 ✅ 完整 缺少验证+切换
可扩展性 ⚠️ 中等 ✅ 高 需重构

6.5 实现优势

  1. 同步写入机制:控制响应使用 fs.writeSync(),确保可靠性
  2. 类型安全:完整的 TypeScript 类型定义
  3. 简洁架构:单一 Handler 类,易于理解
  4. 超时保护:60秒超时,防止阻塞

6.6 实现劣势

  1. 功能完整度低:仅 43% 控制请求完整实现
  2. MCP 完全缺失:不支持任何 MCP 功能
  3. TODO 标记多:多个核心功能仅占位
  4. ⚠️ 架构可扩展性差:添加新功能需修改核心类
  5. 配置忽略:初始化配置全部不处理

qwen-code SDK/CLI 控制协议能力完整清单

📋 目录


1. CLI 端能力

1.1 控制请求类型(8种)

① initialize(初始化)

功能:初始化会话,配置 SDK MCP 服务器和外部 MCP 服务器

请求参数

{
  subtype: 'initialize';
  hooks?: HookRegistration[] | null;              // Hook 注册
  sdkMcpServers?: Record<string, {
    type: 'sdk';
    name: string;
  }>;                                          // SDK 端管理的 MCP 服务器
  mcpServers?: Record<string, {
    command?: string;
    args?: string[];
    env?: Record<string, string>;
    cwd?: string;
    url?: string;
    httpUrl?: string;
    headers?: Record<string, string>;
    tcp?: string;
    timeout?: number;
    trust?: boolean;
    description?: string;
    includeTools?: string[];
    excludeTools?: string[];
    extensionName?: string;
    oauth?: { /* OAuth 配置 */ };
    authProviderType?: 'dynamic_discovery' | 'google_credentials' | 'service_account_impersonation';
    targetAudience?: string;
    targetServiceAccount?: string;
  }>;                                          // CLI 端管理的外部 MCP 服务器
  agents?: Array<{
    name: string;
    description?: string;
    tools?: string[];
    systemPrompt?: string;
    level?: string;
    filePath?: string;
    modelConfig?: {
      model?: string;
      temp?: number;
      topP?: number;
    };
    runConfig?: {
      maxTimeMinutes?: number;
      maxTurns?: number;
    };
    color?: string;
  }>;                                          // 会话子代理配置
}

实现位置packages/cli/src/nonInteractive/control/controllers/systemController.ts - handleInitialize()

返回值

{
  commands: string[];                          // 支持的工具/命令
  output_style: 'stream-json';                  // 输出格式
  capabilities: {
    tools: string[];                           // 可用工具列表
    mcpServers: boolean;                       // 是否支持 MCP 服务器
    hooks: boolean;                            // 是否支持 Hook
    permissionControl: boolean;                // 是否支持权限控制
  };
  model: string;                               // 当前模型
  permissionMode: string;                      // 当前权限模式
  agents?: string[];                           // 支持的子代理
}

② interrupt(中断)

功能:中断当前正在执行的 AI 对话,触发中断回调

请求参数

{
  subtype: 'interrupt';
}

实现位置packages/cli/src/nonInteractive/control/controllers/systemController.ts - handleInterrupt()

返回值

null;  // 无返回值,直接触发中断事件

行为

  • 设置 interrupted 标志
  • 触发 abortController.abort()
  • 发送 interrupt 事件

③ set_model(设置模型)

功能:动态切换 AI 模型

请求参数

{
  subtype: 'set_model';
  model: string;  // 模型名称(如 "gemini-2.5-flash")
}

实现位置packages/cli/src/nonInteractive/control/controllers/systemController.ts - handleSetModel()

返回值

{
  subtype: 'set_model';
  model: string;  // 新模型名称
}

行为

  1. 验证模型名称有效性
  2. 保存旧模型(用于回滚)
  3. 更新当前模型
  4. 重新创建 Gemini 客户端
  5. 发送系统消息通知用户
  6. 失败时自动回滚

④ supported_commands(支持的命令)

功能:获取 CLI 支持的所有斜杠命令列表

请求参数

{
  subtype: 'supported_commands';
}

实现位置packages/cli/src/nonInteractive/control/controllers/systemController.ts - handleSupportedCommands()

返回值

{
  commands: string[];  // 支持的命令名称列表(动态加载)
}

行为:动态从配置加载可用的斜杠命令


⑤ can_use_tool(工具权限检查)

功能:检查工具使用权限,支持权限验证和建议系统

请求参数

{
  subtype: 'can_use_tool';
  tool_name: string;                           // 工具名称
  tool_use_id: string;                          // 工具调用 ID
  input: unknown;                              // 工具输入参数
  permission_suggestions?: PermissionSuggestion[] | null;  // 权限建议
  blocked_path?: string | null;                // 被阻塞的路径
}

实现位置packages/cli/src/nonInteractive/control/controllers/permissionController.ts - handleCanUseTool()

返回值

{
  subtype: 'can_use_tool';
  behavior: 'allow' | 'deny';                // 允许或拒绝
  message?: string;                            // 拒绝原因
  updatedInput?: unknown;                       // 修改后的输入
  interrupt?: boolean;                          // 是否中断
}

决策逻辑

  1. 检查工具注册表(已注册的工具自动允许)
  2. 根据权限模式决策:
    • yolo:全部允许
    • auto-edit:安全操作自动允许
    • plan:只读操作自动允许
    • default:需要用户确认
  3. 调用用户回调(如果有)
  4. 超时或错误时默认拒绝

⑥ set_permission_mode(设置权限模式)

功能:动态设置权限模式

请求参数

{
  subtype: 'set_permission_mode';
  mode: 'default' | 'plan' | 'auto-edit' | 'yolo';
}

实现位置packages/cli/src/nonInteractive/control/controllers/permissionController.ts - handleSetPermissionMode()

返回值

{
  status: 'updated';
  mode: PermissionMode;  // 新的权限模式
}

行为

  1. 验证模式有效性
  2. 更新 PermissionSystem 的模式
  3. 发送系统消息通知用户
  4. 记录模式变更

权限模式说明

  • default:默认模式,需要用户确认
  • plan:计划模式,只允许只读操作
  • auto-edit:自动编辑模式,安全操作自动允许
  • yolo:完全信任模式,所有操作自动允许

⑦ mcp_server_status(MCP 服务器状态)

功能:获取 SDK 端 MCP 服务器状态

请求参数

{
  subtype: 'mcp_server_status';
}

实现位置packages/cli/src/nonInteractive/control/controllers/sdkMcpController.ts - handleMcpStatus()

返回值

{
  subtype: 'mcp_server_status';
  status: Record<string, string>;  // 服务器名 → 状态映射
}

行为:返回所有 SDK MCP 服务器的连接状态


⑧ mcp_message(MCP 消息传递)

功能:在 CLI 和 SDK 之间路由 MCP 协议消息

请求参数

{
  subtype: 'mcp_message';
  server_name: string;                          // MCP 服务器名称
  message: {
    jsonrpc?: string;                            // JSON-RPC 版本(如 "2.0")
    method: string;                               // 方法名
    params?: Record<string, unknown>;             // 方法参数
    id?: string | number | null;                   // 请求 ID
  };
}

实现位置packages/cli/src/nonInteractive/control/controllers/sdkMcpController.ts - handleMcpMessage()

返回值

{
  error: string | null;                          // 错误信息
  mcp_response: {
    jsonrpc: string;
    result: Record<string, unknown>;
    id: string | number;
  };
}

行为

  1. 查找或创建 MCP 客户端
  2. 转发消息到 MCP 服务器
  3. 返回响应或错误

⑧ hook_callback(Hook 回调)

功能:处理 Hook 回调(占位符实现)

请求参数

{
  subtype: 'hook_callback';
  callback_id: string;                          // 回调 ID
  input: unknown;                                // 回调输入
  tool_use_id: string | null;                    // 工具使用 ID
}

实现位置packages/cli/src/nonInteractive/control/controllers/hookController.ts - handleHookCallback()

返回值

{
  result: string;  // "Hook callback processing not yet implemented"
  callback_id: string;
}

状态:框架存在,但实际功能未实现


1.2 服务 API 能力(4 个域)

PermissionServiceAPI(权限服务)

方法列表

  1. buildPermissionSuggestions

    • 功能:为工具确认对话框构建 UI 建议
    • 参数:confirmationDetails: ToolConfirmationDetails
    • 返回:PermissionSuggestion[] | null
    • 位置:permissionController.ts:246-356
  2. getToolCallUpdateCallback

    • 功能:获取监控工具调用状态更新的回调函数
    • 返回:(toolCalls: WaitingToolCall[]) => void
    • 用途:集成到 CoreToolScheduler
  3. setCanUseToolCallback

    • 功能:设置自定义工具权限回调
    • 参数:callback: CanUseToolCallback
    • 用途:允许外部自定义权限逻辑

SystemServiceAPI(系统服务)

方法列表

  1. getControlCapabilities
    • 功能:获取控制系统能力对象
    • 返回:Record<string, unknown>
    • 包含:commands, output_style, capabilities, model, permissionMode

McpServiceAPI(MCP 服务)

方法列表

  1. getMcpClient

    • 功能:获取或创建 MCP 客户端(懒加载)
    • 参数:serverName: string
    • 返回:Promise<{ client: Client; config: MCPServerConfig }>
  2. listServers

    • 功能:列出所有可用的 MCP 服务器
    • 返回:string[](服务器名称列表)

HookServiceAPI(Hook 服务)

方法列表

  1. registerHookCallback
    • 功能:注册钩子回调(占位符)
    • 参数:callback: unknown
    • 状态:框架存在,待实现

1.3 控制服务架构

三层架构
┌─────────────────────────────────────┐
│     ControlService (门面层)         │
│  - 提供 domain-grouped APIs          │
│  - PermissionServiceAPI              │
│  - SystemServiceAPI                  │
│  - McpServiceAPI                     │
│  - HookServiceAPI                    │
└──────────────┬──────────────────────┘
               │
               ▼
┌─────────────────────────────────────┐
│   ControlDispatcher (路由层)        │
│  - 控制请求路由                      │
│  - 待处理请求管理 (Map)              │
│  - 超时和取消处理                    │
│  - 响应生成                          │
└──────┬───────────────┬────────┬───────┘
       │               │        │
       ▼               ▼        ▼
┌──────────┐  ┌──────────┐ ┌──────────┐
│ System   │  │Permission│ │ SdkMcp   │
│Controller│  │Controller│ │Controller│
└──────────┘  └──────────┘ └──────────┘
┌──────────┐
│ Hook     │
│Controller│
└──────────┘
       │
       ▼
┌──────────────────┐
│ BaseController │ (基类)
└──────────────────┘

2. SDK 端能力

2.1 控制请求发送

Query.sendControlRequest() 方法

功能:发送控制请求到 CLI

参数

{
  subtype: string;                     // 请求类型
  data?: Record<string, unknown>;     // 附加数据
  options?: {
    signal?: AbortSignal;            // 取消信号
    timeout?: number;                 // 超时时间(毫秒)
  };
}

实现位置packages/sdk-typescript/src/query/Query.ts

超时配置

const DEFAULT_TIMEOUTS = {
  canUseTool: 60000,        // 工具权限:60秒
  mcpRequest: 60000,        // MCP 请求:60秒
  controlRequest: 60000,    // 控制请求:60秒
  streamClose: 60000,       // 流关闭:60秒
};

2.2 可发送的控制请求类型(9种)

控制请求枚举
enum ControlRequestType {
  INITIALIZE = 'initialize',
  INTERRUPT = 'interrupt',
  SET_MODEL = 'set_model',
  SUPPORTED_COMMANDS = 'supported_commands',
  CAN_USE_TOOL = 'can_use_tool',
  SET_PERMISSION_MODE = 'set_permission_mode',
  MCP_MESSAGE = 'mcp_message',
  MCP_SERVER_STATUS = 'mcp_server_status',
  HOOK_CALLBACK = 'hook_callback',
}
SDK 提供的便捷方法
  1. initialize()

    • 发送初始化请求
    • 配置 SDK MCP 服务器、外部 MCP 服务器、Agent
  2. interrupt()

    • 发送中断请求
    • 取消当前操作
  3. setModel(model)

    • 切换 AI 模型
    • 支持运行时动态切换
  4. supportedCommands()

    • 获取支持的命令列表
    • 返回字符串数组
  5. canUseTool(toolName, input)

    • 检查工具权限
    • 支持权限建议和超时
  6. setPermissionMode(mode)

    • 设置权限模式
    • 支持 ‘default’, ‘plan’, ‘auto-edit’, ‘yolo’
  7. mcpServerStatus()

    • 获取 MCP 服务器状态
    • 返回服务器状态映射
  8. mcpMessage(serverName, message)

    • 发送 MCP 消息
    • 支持双向通信

2.3 控制响应处理

handleControlResponse() 方法

功能:处理来自 CLI 的控制响应

实现位置packages/sdk-typescript/src/query/Query.ts

处理逻辑

1. 根据 request_id 查找 pendingControlRequests
2. 清理定时器和回调监听器
3. 根据 subtype(success/error):
   - success: resolve Promise
   - error: reject Promise with error

响应格式

成功响应

{
  subtype: 'success';
  request_id: string;
  response: unknown;  // 具体响应数据
}

错误响应

{
  subtype: 'error';
  request_id: string;
  error: string | { message: string; [key: string]: unknown };
}

2.4 传输层能力

ProcessTransport 方法

write(message: string)

  • 功能:发送控制请求到 CLI 进程
  • 实现:通过 stdin 写入 JSON Lines 格式
  • 错误处理:检查进程状态、写入权限
  • 日志记录:记录写入操作和字节数
  • 背压控制:检测缓冲区满时等待 drain 事件

readMessages()

  • 功能:从 CLI 进程读取响应消息
  • 实现:通过 stdout 读取 JSON Lines 流
  • 解析:使用 parseJsonLinesStream 解析消息
  • 消息路由:根据消息类型分发

进程管理

  • 自动启动 CLI 子进程
  • 自动关闭和清理
  • 信号处理(SIGINT, SIGTERM)
  • 错误恢复

2.5 SDK 消息路由

消息类型处理
消息类型 处理方法
control_request handleControlRequest()
control_response handleControlResponse()
control_cancel_request handleControlCancelRequest()
SDK 消息 传递到输出流
初始化流程
  1. 初始化 SDK MCP 服务器连接
  2. 发送 initialize 请求到 CLI
  3. 等待初始化完成
  4. 启动消息路由器

3. 类型定义清单

3.1 控制请求载荷(9种)

type ControlRequestPayload =
  | CLIControlInitializeRequest      // 初始化
  | CLIControlInterruptRequest       // 中断
  | CLIControlSetModelRequest        // 设置模型
  | CLIControlSupportedCommandsRequest  // 支持的命令
  | CLIControlPermissionRequest      // 权限检查
  | CLIControlSetPermissionModeRequest  // 设置权限模式
  | CLIControlMcpMessageRequest     // MCP 消息
  | CLIControlMcpStatusRequest     // MCP 状态
  | CLIHookCallbackRequest         // Hook 回调

3.2 控制响应(2种)

type ControlResponse =
  | ControlResponse      // 成功响应
  | ControlErrorResponse; // 错误响应

3.3 配置类型

MCP 配置
  • SDKMcpServerConfig - SDK 端 MCP 服务器
  • CLIMcpServerConfig - CLI 端 MCP 服务器
  • MCPOAuthConfig - OAuth 配置
  • AuthProviderType - 认证提供者类型
权限配置
  • PermissionMode - 权限模式枚举
  • PermissionSuggestion - 权限建议
  • ToolConfirmationDetails - 工具确认详情
子代理配置
  • SubagentConfig - 子代理配置
  • ModelConfig - 模型配置
  • RunConfig - 运行配置

4. 完整能力矩阵

4.1 控制请求能力矩阵

# 控制请求 CLI 处理 SDK 发送 权限控制 MCP Hook 实现状态
1 initialize ⚠️ 完整
2 interrupt 完整
3 set_model 完整
4 supported_commands 完整
5 can_use_tool 完整
6 set_permission_mode 完整
7 mcp_server_status 完整
8 mcp_message 完整
9 hook_callback 🚧 🚧 框架

4.2 架构能力矩阵

能力 qwen-code 实现复杂度
分层架构 ✅ 3层(Service→Dispatcher→Controllers) 复杂
状态管理 ✅ ControlContext 共享状态 中等
请求路由 ✅ 自动路由到对应 Controller 简单
生命周期管理 ✅ 超时、取消、清理 中等
双向通信 ✅ CLI↔SDK 控制请求 复杂
错误处理 ✅ 统一错误响应格式 简单
类型安全 ✅ 完整 TypeScript 类型 中等
可扩展性 ✅ 添加新 Controller 无需修改核心 中等

4.3 功能特性矩阵

权限系统特性
特性 状态 描述
4 种权限模式 default, plan, auto-edit, yolo
工具注册表 已注册工具自动允许
权限建议系统 为不同工具类型生成 UI 建议
安全操作识别 识别安全/只读操作
用户回调支持 自定义权限逻辑
超时控制 60秒超时,可配置
MCP 集成特性
特性 状态 描述
SDK MCP 服务器 SDK 进程中的 MCP 服务器
外部 MCP 服务器 CLI 进程中的 MCP 服务器
OAuth 支持 支持 3 种认证方式
消息路由 双向 MCP 消息传递
客户端缓存 懒加载和缓存 MCP 客户端
服务器状态查询 实时连接状态
系统控制特性
特性 状态 描述
模型切换 运行时动态切换,带验证和回滚
中断控制 立即中断当前操作
动态命令加载 动态获取支持的斜杠命令
系统消息通知 向用户发送系统事件通知
Agent 配置 支持会话子代理配置

5. 核心文件位置

5.1 CLI 端核心文件

packages/cli/src/nonInteractive/control/
├── ControlContext.ts                    # 控制上下文(共享状态)
├── ControlDispatcher.ts                 # 控制调度器(请求路由)
├── ControlService.ts                    # 控制服务(门面层)
├── controllers/
│   ├── BaseController.ts               # 基础控制器
│   ├── SystemController.ts            # 系统控制器
│   ├── PermissionController.ts        # 权限控制器
│   ├── SdkMcpController.ts           # MCP 控制器
│   └── HookController.ts             # Hook 控制器
└── types/
    └── serviceAPIs.ts                 # 服务 API 类型定义

5.2 SDK 端核心文件

packages/sdk-typescript/src/
├── query/Query.ts                        # 查询类(控制请求发送)
├── transport/
│   ├── ProcessTransport.ts             # 进程传输层
│   └── Transport.ts                   # 传输接口
├── mcp/
│   ├── SdkControlServerTransport.ts    # SDK MCP 服务器传输
│   └── ...
└── types/
    ├── protocol.ts                     # 协议类型定义
    └── types.ts                        # 通用类型定义

6. 总结

6.1 功能统计

类别 数量
控制请求类型 9 种
服务 API 域 4 个(Permission/System/Mcp/Hook)
Controller 类 5 个(Base + 4个具体)
权限模式 4 种
核心文件数 12 个

6.2 关键特性

  1. 完整的控制协议:9 种控制请求全部实现
  2. 分层架构:Service → Dispatcher → Controllers
  3. 权限系统:4 种模式 + 工具注册表 + 权限建议
  4. MCP 集成:SDK + 外部服务器 + OAuth 支持
  5. 双向通信:CLI ↔ SDK 控制请求
  6. 生命周期管理:超时、取消、清理
  7. 类型安全:完整的 TypeScript 类型定义

6.3 实现完整度

  • 功能完整度:95%(只有 Hook 是占位符)
  • 生产就绪度:高(已用于 qwen-code 生产环境)
  • 可维护性:高(分层架构,职责清晰)
  • 可扩展性:高(易于添加新功能)
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐