【3】kilo 消息交互完整示例

Kilo 消息交互完整示例

一、文档概述

本文档通过具体的示例,展示 Kilo 项目中用户与 AI 助手之间的完整消息交互过程,包括:

  • 消息的格式和结构
  • 消息流转示例分析
  • 流式响应的处理
  • 工具执行结果的返回

本文档是对 【2】kilo 消息流转过程 的补充,提供实际的消息示例,帮助理解整个交互过程。


二、消息格式基础

2.1 消息层次结构

Kilo 的消息系统分为三个层次:

复制代码
┌─────────────────────────────────────────────────────────────┐
│                    1. API 层消息 (ApiMessage)                │
│          用于与 LLM API 交互的标准格式消息                      │
│              基于 Anthropic.MessageParam                     │
│                                                             │
│          存储位置: api_conversation_history.json             │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│                  2. UI 层消息 (ClineMessage)                 │
│          用于 Extension 与 Webview 之间通信                   │
│              包含 UI 展示所需的所有信息                        │
│                                                             │
│              存储位置: ui_messages.json                      │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│                 3. 任务层事件 (TaskEvents)                   │
│          Task 内部事件系统,用于状态管理和通知                   │
│              基于 EventEmitter 的事件机制                     │
│                                                             │
└─────────────────────────────────────────────────────────────┘

各层作用:

  1. API 层 (ApiMessage)

    • 负责与 LLM API 的标准化通信
    • 维护完整的对话上下文(包括 tool_use 和 tool_result 的配对)
    • 支持上下文压缩和截断管理
    • 持久化存储以支持任务恢复
  2. UI 层 (ClineMessage)

    • 负责 Extension 与 Webview 之间的消息传递
    • 包含 UI 展示所需的所有信息(进度、状态、元数据等)
    • 支持流式更新(partial 消息机制)
    • 区分 ask(需要用户交互)和 say(信息展示)两种类型
  3. 任务层 (TaskEvents)

    • 负责任务状态管理和生命周期控制
    • 通过事件机制解耦任务逻辑与 UI 更新
    • 支持任务的创建、暂停、恢复、完成等状态转换
    • 提供 Token 使用统计和工具调用监控

2.2 API 层消息类型 (ApiMessage)

API 层消息基于 Anthropic 的标准 MessageParam 格式,用于与 LLM API 交互。

2.2.1 基本结构
typescript 复制代码
// 来源:src/core/task-persistence/apiMessages.ts
export type ApiMessage = Anthropic.MessageParam & {
  // 基础字段
  role: "user" | "assistant"
  content: string | ContentBlock[]
  
  // Kilo 扩展字段
  ts?: number                    // 时间戳
  id?: string                    // 消息唯一标识
  
  // 上下文管理字段
  isSummary?: boolean            // 是否为总结消息
  condenseId?: string            // 总结消息的唯一标识
  condenseParent?: string        // 指向被总结的消息
  truncationId?: string          // 截断标记的唯一标识
  truncationParent?: string      // 指向被截断的消息
  isTruncationMarker?: boolean   // 是否为截断边界标记
  
  // 推理相关字段
  type?: "reasoning"             // 推理类型消息
  reasoning_content?: string     // 推理内容(DeepSeek/Z.ai 格式)
  reasoning_details?: any[]      // 推理详情(OpenRouter 格式)
  
  // 其他字段
  summary?: any[]                // 总结内容
  encrypted_content?: string     // 加密内容
  text?: string                  // 文本内容
}
2.2.2 ContentBlock 类型详解

content 字段可以是字符串或 ContentBlock 数组:

1. TextBlock - 文本块

typescript 复制代码
{
  type: "text",
  text: "帮我创建一个 Button 组件,要支持不同的尺寸和颜色"
}
  • 用途:承载普通文本内容
  • 出现位置:user 和 assistant 消息中
  • 示例场景:用户输入、AI 回复

2. ImageBlock - 图片块

typescript 复制代码
// Base64 格式
{
  type: "image",
  source: {
    type: "base64",
    media_type: "image/png",  // 或 "image/jpeg", "image/gif", "image/webp"
    data: "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJ..."
  }
}

// URL 格式(Kilo 扩展)
{
  type: "image",
  source: {
    type: "url",
    url: "https://example.com/image.png"
  }
}
  • 用途:承载图片数据
  • 出现位置:仅在 user 消息中
  • 支持格式:PNG、JPEG、GIF、WebP
  • 大小限制:通常不超过 5MB(取决于 API 提供商)

3. ToolUseBlock - 工具调用块

typescript 复制代码
{
  type: "tool_use",
  id: "toolu_01A09q90qw90lq917835lq9",  // 唯一标识符
  name: "read_file",                     // 工具名称
  input: {                               // 工具参数
    path: "src/components/Button.tsx",
    should_read_entire_file: true
  }
}
  • 用途:表示 AI 调用的工具
  • 出现位置:仅在 assistant 消息中
  • 关键字段
    • id:用于关联 tool_result
    • name:工具名称(如 read_file、create_file 等)
    • input:工具的输入参数(JSON 对象)

4. ToolResultBlock - 工具结果块

typescript 复制代码
// 简单文本结果
{
  type: "tool_result",
  tool_use_id: "toolu_01A09q90qw90lq917835lq9",  // 对应的 tool_use ID
  content: "文件内容..."
}
  • 用途:承载工具执行的结果
  • 出现位置:仅在 user 消息中
  • 关键字段
    • tool_use_id:必须对应某个 tool_use 的 id
    • content:可以是字符串或 ContentBlock 数组
    • is_error:标记是否为错误结果

2.3 UI 层消息类型 (ClineMessage)

UI 层消息用于 Extension 与 Webview 之间的通信,包含 UI 展示所需的所有信息。

2.3.1 基本结构
typescript 复制代码
// 来源:packages/types/src/message.ts
export type ClineMessage = {
  // 基础字段
  ts: number                           // 时间戳(毫秒)
  type: "ask" | "say"                  // 消息类型
  
  // ask 类型的字段
  ask?: ClineAsk                       // 询问类型(需要用户交互)
  
  // say 类型的字段
  say?: ClineSay                       // 说话类型(信息展示)
  
  // 内容字段
  text?: string                        // 文本内容
  images?: string[]                    // 图片列表(base64 或 URL)
  reasoning?: string                   // 推理过程
  
  // 流式相关
  partial?: boolean                    // 是否为部分消息(流式更新)
  progressStatus?: ToolProgressStatus  // 工具进度状态
  
  // 关联字段
  conversationHistoryIndex?: number    // 对应的 API 历史索引
  
  // 上下文管理
  contextCondense?: ContextCondense    // 上下文压缩信息
  contextTruncation?: ContextTruncation // 上下文截断信息
  
  // 检查点
  checkpoint?: Record<string, unknown> // 检查点数据
  
  // 状态字段
  isProtected?: boolean                // 是否受保护
  isAnswered?: boolean                 // 是否已回答
  apiProtocol?: "openai" | "anthropic" // API 协议
  
  // Kilo 扩展
  metadata?: {
    kiloCode?: KiloCodeMetaData
  }
}
2.3.2 ClineAsk 类型(需要用户交互)
typescript 复制代码
export type ClineAsk = 
  // 交互式询问(Interactive)- 需要用户立即响应
  | "followup"                    // 后续问题
  | "command"                     // 命令执行权限
  | "tool"                        // 工具使用权限
  | "browser_action_launch"       // 浏览器操作权限
  | "use_mcp_server"              // MCP 服务器使用权限
  | "report_bug"                  // 报告 Bug
  | "condense"                    // 压缩上下文
  | "checkpoint_restore"          // 恢复检查点
  
  // 空闲状态询问(Idle)- 任务暂停,等待用户决策
  | "completion_result"           // 任务完成
  | "api_req_failed"              // API 请求失败
  | "resume_completed_task"       // 恢复已完成任务
  | "mistake_limit_reached"       // 错误次数达到上限
  | "auto_approval_max_req_reached" // 自动批准次数达到上限
  | "payment_required_prompt"     // 需要付费
  | "invalid_model"               // 无效模型
  
  // 可恢复状态询问(Resumable)- 任务可以恢复
  | "resume_task"                 // 恢复任务
  
  // 非阻塞询问(Non-blocking)- 不阻塞任务执行
  | "command_output"              // 命令输出
2.3.3 ClineSay 类型(信息展示)
typescript 复制代码
export type ClineSay = 
  // 错误和状态
  | "error"                       // 错误消息
  | "api_req_started"             // API 请求开始
  | "api_req_finished"            // API 请求完成
  | "api_req_retried"             // API 请求重试
  | "api_req_retry_delayed"       // API 请求重试延迟
  | "api_req_rate_limit_wait"     // API 速率限制等待
  | "api_req_deleted"             // API 请求删除
  
  // 内容展示
  | "text"                        // 普通文本
  | "image"                       // 图片
  | "reasoning"                   // 推理过程
  | "completion_result"           // 完成结果
  | "user_feedback"               // 用户反馈
  | "user_feedback_diff"          // 用户反馈差异
  
  // 命令和浏览器
  | "command_output"              // 命令输出
  | "shell_integration_warning"   // Shell 集成警告
  | "browser_action"              // 浏览器操作
  | "browser_action_result"       // 浏览器操作结果
  | "browser_session_status"      // 浏览器会话状态
  
  // MCP 和子任务
  | "mcp_server_request_started"  // MCP 服务器请求开始
  | "mcp_server_response"         // MCP 服务器响应
  | "subtask_result"              // 子任务结果
  
  // 系统功能
  | "checkpoint_saved"            // 检查点保存
  | "rooignore_error"             // .rooignore 错误
  | "diff_error"                  // Diff 错误
  | "condense_context"            // 压缩上下文
  | "condense_context_error"      // 压缩上下文错误
  | "sliding_window_truncation"   // 滑动窗口截断
  | "codebase_search_result"      // 代码库搜索结果
  | "user_edit_todos"             // 用户编辑待办事项

三、完整对话示例

示例场景:用户请求设计一部心理悬疑电影

让我们通过一个完整的场景来展示消息交互的全过程。

第 1 轮:用户发起请求

用户输入:

复制代码
帮我设计一部悬疑电影

系统构建的用户消息(存入 api_conversation_history.json):

json 复制代码
{
  "role": "user",
  "content": [
    {
      "type": "text",
      "text": "帮我设计一部悬疑电影"
    }
  ],
  "ts": 1768187000000
}

同时存入 ui_messages.json 的消息:

json 复制代码
{
  "ts": 1768187000000,
  "type": "say",
  "say": "text",
  "text": "帮我设计一部悬疑电影",
  "conversationHistoryIndex": 0
}

发送到 API 的完整请求:

json 复制代码
{
  "model": "claude-sonnet-4",
  "max_tokens": 8192,
  "system": [
    {
      "type": "text",
      "text": "你是 Kilo,一个 AI 编程助手...",
      "cache_control": { "type": "ephemeral" }
    }
  ],
  "messages": [
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "帮我设计一部悬疑电影"
        }
      ],
      "ts": 1768187000000
    }
  ]
}

第 2 轮:AI 响应并调用工具

AI 流式响应(原始文本):

复制代码
好的!我很乐意帮你设计一部悬疑电影。首先让我了解一些关键信息:

<ask_followup_question>
<question>你希望这部悬疑电影属于哪种具体类型?</question>
<follow_up>
<option>心理悬疑 - 专注于角色的内心世界和心理状态</option>
<option>犯罪悬疑 - 围绕犯罪调查和侦破过程</option>
<option>惊悚悬疑 - 强调紧张刺激的氛围</option>
</follow_up>
</ask_followup_question>

流式解析过程:

  1. 第 1 个 chunk: "好的!我很乐意"

    typescript 复制代码
    // AssistantMessageParser 解析结果
    [
      { type: "text", content: "好的!我很乐意", partial: true }
    ]
  2. 第 2 个 chunk: "帮你设计一部悬疑电影。首先让我了解一些关键信息:\n\n<ask_followup_question>\n<question>"

    typescript 复制代码
    [
      { type: "text", content: "好的!我很乐意帮你设计一部悬疑电影。首先让我了解一些关键信息:", partial: false },
      { type: "tool_use", name: "ask_followup_question", params: {}, partial: true }
    ]
  3. 第 3 个 chunk: "你希望这部悬疑电影属于哪种具体类型?</question>\n..."

    typescript 复制代码
    [
      { type: "text", content: "好的!我很乐意帮你设计一部悬疑电影。首先让我了解一些关键信息:", partial: false },
      { type: "tool_use", name: "ask_followup_question", params: { question: "你希望这部悬疑电影属于哪种具体类型?", follow_up: [...] }, partial: false }
    ]

最终解析的助手消息(存入 api_conversation_history.json):

json 复制代码
{
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "好的!我很乐意帮你设计一部悬疑电影。首先让我了解一些关键信息:"
    },
    {
      "type": "tool_use",
      "id": "toolu_vrtx_01JVU2miNYbiFZJLeFcVAzi7",
      "name": "ask_followup_question",
      "input": {
        "question": "你希望这部悬疑电影属于哪种具体类型?",
        "follow_up": [
          {"text": "心理悬疑 - 专注于角色的内心世界和心理状态"},
          {"text": "犯罪悬疑 - 围绕犯罪调查和侦破过程"},
          {"text": "惊悚悬疑 - 强调紧张刺激的氛围"}
        ]
      }
    }
  ],
  "ts": 1768187030000
}

同时存入 ui_messages.json 的消息:

json 复制代码
[
  {
    "ts": 1768187030000,
    "type": "say",
    "say": "api_req_started",
    "text": "{\"apiProtocol\":\"openai\",\"tokensIn\":14439,\"tokensOut\":567}"
  },
  {
    "ts": 1768187033000,
    "type": "say",
    "say": "text",
    "text": "好的!我很乐意帮你设计一部悬疑电影。首先让我了解一些关键信息:",
    "partial": false
  },
  {
    "ts": 1768187045000,
    "type": "ask",
    "ask": "followup",
    "text": "{\"question\":\"你希望这部悬疑电影属于哪种具体类型?\",\"suggest\":[{\"answer\":\"心理悬疑 - 专注于角色的内心世界和心理状态\"},{\"answer\":\"犯罪悬疑 - 围绕犯罪调查和侦破过程\"},{\"answer\":\"惊悚悬疑 - 强调紧张刺激的氛围\"}]}",
    "isAnswered": true
  }
]

工具执行流程:

  1. presentAssistantMessage 检测到 ask_followup_question 调用

  2. 显示选项弹窗:

    • 心理悬疑 - 专注于角色的内心世界和心理状态
    • 犯罪悬疑 - 围绕犯罪调查和侦破过程
    • 惊悚悬疑 - 强调紧张刺激的氛围
  3. 用户选择"心理悬疑 - 专注于角色的内心世界和心理状态"

  4. 工具执行结果:

    复制代码
    用户选择:心理悬疑 - 专注于角色的内心世界和心理状态

构建的工具结果消息(存入 api_conversation_history.json):

json 复制代码
{
  "role": "user",
  "content": [
    {
      "type": "tool_result",
      "tool_use_id": "toolu_vrtx_01JVU2miNYbiFZJLeFcVAzi7",
      "content": "心理悬疑 - 专注于角色的内心世界和心理状态"
    }
  ],
  "ts": 1768187060000
}

同时存入 ui_messages.json 的消息:

json 复制代码
[
  {
    "ts": 1768187060000,
    "type": "say",
    "say": "user_feedback",
    "text": "心理悬疑 - 专注于角色的内心世界和心理状态",
    "conversationHistoryIndex": 2
  }
]

第 3 轮:AI 继续询问

AI 流式响应:

复制代码
很好的选择!心理悬疑能够深入探索人物的内心世界。接下来让我了解更多细节:

<ask_followup_question>
<question>你希望电影探讨什么样的核心主题?</question>
<follow_up>
<option>记忆与现实 - 主人公对自己记忆的真实性产生怀疑</option>
<option>身份认同 - 主人公不确定自己是谁</option>
<option>信任危机 - 主人公无法相信周围的人</option>
</follow_up>
</ask_followup_question>

解析的助手消息(存入 api_conversation_history.json):

json 复制代码
{
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "很好的选择!心理悬疑能够深入探索人物的内心世界。接下来让我了解更多细节:"
    },
    {
      "type": "tool_use",
      "id": "toolu_vrtx_01JVU2pQbWxNLdXYdqxZfCPV",
      "name": "ask_followup_question",
      "input": {
        "question": "你希望电影探讨什么样的核心主题?",
        "follow_up": [
          {"text": "记忆与现实 - 主人公对自己记忆的真实性产生怀疑"},
          {"text": "身份认同 - 主人公不确定自己是谁"},
          {"text": "信任危机 - 主人公无法相信周围的人"}
        ]
      }
    }
  ],
  "ts": 1768187090000
}

同时存入 ui_messages.json 的消息:

json 复制代码
[
  {
    "ts": 1768187090000,
    "type": "say",
    "say": "api_req_started",
    "text": "{\"apiProtocol\":\"openai\",\"tokensIn\":14439,\"tokensOut\":567}"
  },
  {
    "ts": 1768187093000,
    "type": "say",
    "say": "text",
    "text": "很好的选择!心理悬疑能够深入探索人物的内心世界。接下来让我了解更多细节:",
    "partial": false
  },
  {
    "ts": 1768187095000,
    "type": "ask",
    "ask": "followup",
    "text": "{\"question\":\"你希望电影探讨什么样的核心主题?\",\"suggest\":[{\"answer\":\"记忆与现实 - 主人公对自己记忆的真实性产生怀疑\"},{\"answer\":\"身份认同 - 主人公不确定自己是谁\"},{\"answer\":\"信任危机 - 主人公无法相信周围的人\"}]}",
    "isAnswered": true
  }
]

工具执行结果(存入 api_conversation_history.json):

json 复制代码
{
  "role": "user",
  "content": [
    {
      "type": "tool_result",
      "tool_use_id": "toolu_vrtx_01JVU2pQbWxNLdXYdqxZfCPV",
      "content": "记忆与现实 - 主人公对自己记忆的真实性产生怀疑"
    }
  ],
  "ts": 1768187120000
}

同时存入 ui_messages.json 的消息:

json 复制代码
[
  {
    "ts": 1768187120000,
    "type": "say",
    "say": "user_feedback",
    "text": "记忆与现实 - 主人公对自己记忆的真实性产生怀疑",
    "conversationHistoryIndex": 4
  }
]

第 4 轮:AI 继续询问并开始设计

用户回答"城市环境"后,AI 继续询问背景细节,然后开始创建 todo list 和设计电影方案。

AI 流式响应(询问背景):

复制代码
非常好!现代都市的背景能营造出孤立和疏离感。让我再确认一个细节:

<ask_followup_question>
<question>你希望故事发生在什么样的城市环境?</question>
<follow_up>
<option>城市环境 - 现代大都市,但主人公感到孤立和疏离</option>
<option>小镇环境 - 封闭的小镇社区</option>
<option>郊区环境 - 城市边缘的住宅区</option>
</follow_up>
</ask_followup_question>

用户选择"城市环境"后,AI 开始创建待办事项并设计电影:

AI 流式响应(创建 todo 和设计):

复制代码
完美!我现在开始为你设计这部心理悬疑电影。让我创建一个详细的设计方案。

<update_todo_list>
<todos>
[
  {"id": "1", "content": "设计主人公角色背景", "status": "in_progress"},
  {"id": "2", "content": "构建核心悬疑设定", "status": "pending"},
  {"id": "3", "content": "设计关键转折点", "status": "pending"},
  {"id": "4", "content": "设计结局真相", "status": "pending"},
  {"id": "5", "content": "设计配角关系网", "status": "pending"},
  {"id": "6", "content": "设计视觉风格", "status": "pending"},
  {"id": "7", "content": "设计叙事结构", "status": "pending"},
  {"id": "8", "content": "设计关键场景", "status": "pending"},
  {"id": "9", "content": "设计悬念布局", "status": "pending"},
  {"id": "10", "content": "设计情感曲线", "status": "pending"},
  {"id": "11", "content": "设计主题表达", "status": "pending"},
  {"id": "12", "content": "设计开场设定", "status": "pending"},
  {"id": "13", "content": "设计高潮冲突", "status": "pending"},
  {"id": "14", "content": "整合完整方案", "status": "pending"}
]
</todos>
</update_todo_list>

<create_file>
<path>心理悬疑电影设计方案.md</path>
<content>
# 心理悬疑电影设计方案

## 一、基本信息
- **类型**:心理悬疑
- **核心主题**:记忆与现实的界限
- **背景设定**:现代都市

## 二、主人公设定
**姓名**:林墨  
**年龄**:35岁  
**职业**:建筑师  
**性格特点**:理性、追求完美、对细节敏感

## 三、核心悬疑设定
林墨在一场车祸后失去部分记忆,醒来后发现自己的生活似乎"太完美"了...
</content>
</create_file>

流式显示编辑过程:

在工具调用 partial: true 状态时,Kilo 会实时显示编辑内容:

  1. 显示 todo list 创建

  2. 打开文件编辑 diff 视图

  3. 逐步显示新内容:

    typescript 复制代码
    // 第 1 次更新
    "# 心理悬疑电影设计方案\n\n## 一、基本信息"
    
    // 第 2 次更新
    "# 心理悬疑电影设计方案\n\n## 一、基本信息\n- **类型**:心理悬疑\n- **核心主题**:记忆与现实的界限"
    
    // ... 持续更新直到完成

工具调用完成后的审批:

显示完整的 diff 预览:

diff 复制代码
+ 心理悬疑电影设计方案.md (新文件)
+ # 心理悬疑电影设计方案
+ 
+ ## 一、基本信息
+ - **类型**:心理悬疑
+ - **核心主题**:记忆与现实的界限
+ - **背景设定**:现代都市
+ 
+ ## 二、主人公设定
+ **姓名**:林墨
+ **年龄**:35岁
+ **职业**:建筑师
+ ...

用户点击"允许"后,工具执行结果:

typescript 复制代码
{
  role: "user",
  content: [
    {
      type: "tool_result",
      tool_use_id: "toolu_xxx_create_file",
      content: "Successfully created 心理悬疑电影设计方案.md"
    }
  ]
}

第 5 轮:AI 调用完成工具

AI 响应(调用 attempt_completion 工具):

复制代码
我已经为你完成了这部心理悬疑电影的完整设计方案!

<attempt_completion>
<result>
我已经为你完成了这部心理悬疑电影的完整设计方案!

## 核心设定

**主人公**:林墨,35岁建筑师  
**核心悬疑**:车祸后失忆,逐渐发现自己生活在一个"完美"但虚假的世界中  
**终极真相**:他是车祸的肇事者,医院为了治疗他的心理创伤,构建了一个治疗性的虚拟环境

## 主要特色

1. **记忆与现实的模糊界限**:通过建筑细节的不一致性暗示真相
2. **层层递进的悬念**:从日常异常到重大发现
3. **深刻的主题探讨**:罪责、救赎、自我认知

设计方案已保存到 `心理悬疑电影设计方案.md`,包含完整的角色设定、情节结构、关键场景等内容。
</result>
</attempt_completion>

解析的助手消息(存入 api_conversation_history.json):

json 复制代码
{
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "我已经为你完成了这部心理悬疑电影的完整设计方案!"
    },
    {
      "type": "tool_use",
      "id": "toolu_vrtx_01JVU2xVfZBRNhbhtBbZjGTY",
      "name": "attempt_completion",
      "input": {
        "result": "我已经为你完成了这部心理悬疑电影的完整设计方案!\n\n## 核心设定\n\n**主人公**:林墨,35岁建筑师\n**核心悬疑**:车祸后失忆,逐渐发现自己生活在一个\"完美\"但虚假的世界中\n**终极真相**:他是车祸的肇事者,医院为了治疗他的心理创伤,构建了一个治疗性的虚拟环境\n\n## 主要特色\n\n1. **记忆与现实的模糊界限**:通过建筑细节的不一致性暗示真相\n2. **层层递进的悬念**:从日常异常到重大发现\n3. **深刻的主题探讨**:罪责、救赎、自我认知\n\n设计方案已保存到 `心理悬疑电影设计方案.md`,包含完整的角色设定、情节结构、关键场景等内容。"
      }
    }
  ],
  "ts": 1768187250000
}

同时存入 ui_messages.json 的消息:

json 复制代码
[
  {
    "ts": 1768187250000,
    "type": "say",
    "say": "text",
    "text": "我已经为你完成了这部心理悬疑电影的完整设计方案!",
    "partial": false
  },
  {
    "ts": 1768187250100,
    "type": "ask",
    "ask": "completion_result",
    "text": "{\"result\":\"我已经为你完成了这部心理悬疑电影的完整设计方案!\\n\\n## 核心设定\\n\\n**主人公**:林墨,35岁建筑师\\n**核心悬疑**:车祸后失忆,逐渐发现自己生活在一个\\\"完美\\\"但虚假的世界中\\n**终极真相**:他是车祸的肇事者,医院为了治疗他的心理创伤,构建了一个治疗性的虚拟环境\\n\\n## 主要特色\\n\\n1. **记忆与现实的模糊界限**:通过建筑细节的不一致性暗示真相\\n2. **层层递进的悬念**:从日常异常到重大发现\\n3. **深刻的主题探讨**:罪责、救赎、自我认知\\n\\n设计方案已保存到 `心理悬疑电影设计方案.md`,包含完整的角色设定、情节结构、关键场景等内容。\"}",
    "isAnswered": false
  }
]

工具执行流程:

  1. 显示完成结果弹窗:展示任务完成的总结
  2. 用户可以选择
    • 点击"新任务":开始新的对话
    • 继续输入:提供反馈或要求调整
  3. 任务状态变更 :从 RunningIdle

四、更多工具调用示例

4.1 ask_followup_question 工具的多次使用

在悬疑电影设计的场景中,AI 连续使用了 3 次 ask_followup_question 工具来收集用户需求:

  1. 第一次:询问电影类型(心理悬疑/犯罪悬疑/惊悚悬疑)
  2. 第二次:询问核心主题(记忆与现实/身份认同/信任危机)
  3. 第三次:询问背景环境(城市/小镇/郊区)

这种渐进式的信息收集方式,让 AI 能够:

  • 逐步明确用户需求
  • 避免一次性询问过多问题
  • 根据前一个答案调整后续问题

4.2 execute_command 工具示例

场景: 用户请求安装依赖

AI 响应:

复制代码
让我安装 lodash 依赖包。

<execute_command>
<command>npm install lodash</command>
</execute_command>

解析结果(存入 api_conversation_history.json):

json 复制代码
{
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "让我安装 lodash 依赖包。"
    },
    {
      "type": "tool_use",
      "id": "toolu_01D30t03tw03ot040168ot2",
      "name": "execute_command",
      "input": {
        "command": "npm install lodash"
      }
    }
  ],
  "ts": 1736654500000
}

同时存入 ui_messages.json 的消息:

json 复制代码
[
  {
    "ts": 1736654500000,
    "type": "say",
    "say": "text",
    "text": "让我安装 lodash 依赖包。",
    "partial": false
  },
  {
    "ts": 1736654500100,
    "type": "ask",
    "ask": "tool",
    "text": "{\"tool\":\"executeCommand\",\"command\":\"npm install lodash\",\"cwd\":\"/Users/user/project\"}"
  }
]

工具执行过程:

  1. 显示审批弹窗:

    json 复制代码
    {
      "tool": "executeCommand",
      "command": "npm install lodash",
      "cwd": "/Users/user/project"
    }
  2. 用户点击"允许"

  3. 在终端执行命令,实时输出:

    复制代码
    npm WARN deprecated ...
    
    added 1 package in 2s
  4. 命令完成后返回结果(存入 api_conversation_history.json):

    json 复制代码
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "[execute_command for 'npm install lodash'] Result:"
        },
        {
          "type": "text",
          "text": "Command executed in terminal /Users/user/project. Exit code: 0\nOutput:\nnpm WARN deprecated ...\n\nadded 1 package in 2s"
        }
      ],
      "ts": 1736654502000
    }

    同时存入 ui_messages.json 的消息:

    json 复制代码
    [
      {
        "ts": 1736654502000,
        "type": "say",
        "say": "text",
        "text": "[execute_command for 'npm install lodash'] Result:",
        "conversationHistoryIndex": 10
      },
      {
        "ts": 1736654502100,
        "type": "say",
        "say": "command_output",
        "text": "Command executed in terminal /Users/user/project. Exit code: 0\nOutput:\nnpm WARN deprecated ...\n\nadded 1 package in 2s"
      }
    ]

4.3 attempt_completion 工具示例

场景: AI 完成任务后向用户汇报结果

attempt_completion 是 Kilo 中使用频率最高的工具之一,用于 AI 完成任务时:

  • 总结完成的工作
  • 展示关键成果
  • 询问用户是否需要进一步调整

AI 响应(完成 Button 组件创建后):

复制代码
我已经成功创建了 Button 组件!

<attempt_completion>
<result>
我已经成功创建了 Button 组件!这个组件支持:

1. **三种样式变体:**
   - `primary`:蓝色主按钮
   - `secondary`:灰色次要按钮
   - `outline`:边框按钮

2. **三种尺寸:**
   - `sm`:小尺寸
   - `md`:中等尺寸(默认)
   - `lg`:大尺寸

3. **完全的类型安全:** 继承了所有原生 button 的属性

使用示例:
```tsx
<Button variant="primary" size="lg">
  点击我
</Button>

组件文件已创建在 `src/components/Button.tsx`。
</result>
<command>npm run dev</command>
</attempt_completion>

解析结果(存入 api_conversation_history.json):

json 复制代码
{
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "我已经成功创建了 Button 组件!"
    },
    {
      "type": "tool_use",
      "id": "toolu_01F52v05vx05qv062390qv4",
      "name": "attempt_completion",
      "input": {
        "result": "我已经成功创建了 Button 组件!这个组件支持:\n\n1. **三种样式变体:**\n   - `primary`:蓝色主按钮\n   - `secondary`:灰色次要按钮\n   - `outline`:边框按钮\n\n2. **三种尺寸:**\n   - `sm`:小尺寸\n   - `md`:中等尺寸(默认)\n   - `lg`:大尺寸\n\n3. **完全的类型安全:** 继承了所有原生 button 的属性\n\n使用示例:\n```tsx\n<Button variant=\"primary\" size=\"lg\">\n  点击我\n</Button>\n```\n\n组件文件已创建在 `src/components/Button.tsx`。",
        "command": "npm run dev"
      }
    }
  ],
  "ts": 1736654800000
}

同时存入 ui_messages.json 的消息:

json 复制代码
[
  {
    "ts": 1736654800000,
    "type": "say",
    "say": "text",
    "text": "我已经成功创建了 Button 组件!",
    "partial": false
  },
  {
    "ts": 1736654800100,
    "type": "ask",
    "ask": "completion_result",
    "text": "{\"result\":\"我已经成功创建了 Button 组件!这个组件支持:\\n\\n1. **三种样式变体:**\\n   - `primary`:蓝色主按钮\\n   - `secondary`:灰色次要按钮\\n   - `outline`:边框按钮\\n\\n2. **三种尺寸:**\\n   - `sm`:小尺寸\\n   - `md`:中等尺寸(默认)\\n   - `lg`:大尺寸\\n\\n3. **完全的类型安全:** 继承了所有原生 button 的属性\\n\\n使用示例:\\n```tsx\\n<Button variant=\\\"primary\\\" size=\\\"lg\\\">\\n  点击我\\n</Button>\\n```\\n\\n组件文件已创建在 `src/components/Button.tsx`。\",\"command\":\"npm run dev\"}"
  }
]

attempt_completion 的关键特点:

  1. 必填参数:

    • result:任务完成的详细总结(支持 Markdown 格式)
  2. 可选参数:

    • command:建议用户执行的命令(如启动开发服务器、运行测试等)
  3. 使用时机:

    • 完成用户请求的所有任务
    • 所有文件编辑已完成
    • 所有测试已通过(如果需要)
    • 没有待处理的 linter 错误
  4. 最佳实践:

    • 总结要清晰、结构化,使用 Markdown 格式
    • 突出关键成果和重要变更
    • 提供使用示例或下一步建议
    • 如果有建议的命令,确保命令是可执行的

五、关键技术点总结

5.1 消息格式转换

Kilo 支持多个 LLM Provider,需要在不同格式之间转换:

Anthropic 原生格式:

typescript 复制代码
{
  role: "assistant",
  content: [
    { type: "text", text: "..." },
    { type: "tool_use", id: "...", name: "...", input: {...} }
  ]
}

OpenAI 格式:

typescript 复制代码
{
  role: "assistant",
  content: "...",
  tool_calls: [
    {
      id: "...",
      type: "function",
      function: {
        name: "...",
        arguments: "{...}"
      }
    }
  ]
}

转换逻辑: 参见 src/api/transform/openai-format.ts

5.2 工具重复检测

目的: 防止 AI 陷入死循环,重复调用相同的工具

检测逻辑:

typescript 复制代码
class ToolRepetitionDetector {
  check(toolUse: ToolUse): { allowExecution: boolean; reason?: string } {
    // 检查最近 5 次工具调用
    const recentCalls = this.history.slice(-5)
    
    // 如果连续 3 次调用相同工具且参数相同
    const repetitionCount = recentCalls.filter(call => 
      call.name === toolUse.name && 
      JSON.stringify(call.input) === JSON.stringify(toolUse.input)
    ).length
    
    if (repetitionCount >= 3) {
      return {
        allowExecution: false,
        reason: "检测到重复的工具调用,已自动跳过"
      }
    }
    
    return { allowExecution: true }
  }
}

5.3 自动批准机制

目的: 减少用户干预,提升效率

规则:

  1. 基于请求次数: 前 N 次工具调用自动批准
  2. 基于成本: 累计成本低于阈值时自动批准
  3. 基于工具类型: 某些安全工具(如 read_file)自动批准

实现: 参见 src/core/task/AutoApprovalHandler.ts


六、完整的 API 对话历史

经过上述多轮交互后,apiConversationHistory 的完整内容如下:

typescript 复制代码
[
  // 第 1 轮:用户请求
  {
    role: "user",
    content: [
      {
        type: "text",
        text: "帮我设计一部悬疑电影"
      }
    ],
    ts: 1768187000000
  },
  
  // 第 2 轮:AI 询问电影类型
  {
    role: "assistant",
    content: [
      {
        type: "text",
        text: "好的!我很乐意帮你设计一部悬疑电影。首先让我了解一些关键信息:"
      },
      {
        type: "tool_use",
        id: "toolu_vrtx_01JVU2miNYbiFZJLeFcVAzi7",
        name: "ask_followup_question",
        input: {
          question: "你希望这部悬疑电影属于哪种具体类型?",
          follow_up: [
            {text: "心理悬疑 - 专注于角色的内心世界和心理状态"},
            {text: "犯罪悬疑 - 围绕犯罪调查和侦破过程"},
            {text: "惊悚悬疑 - 强调紧张刺激的氛围"}
          ]
        }
      }
    ],
    ts: 1768187030000
  },
  
  // 用户选择"心理悬疑"
  {
    role: "user",
    content: [
      {
        type: "tool_result",
        tool_use_id: "toolu_vrtx_01JVU2miNYbiFZJLeFcVAzi7",
        content: "心理悬疑 - 专注于角色的内心世界和心理状态"
      }
    ],
    ts: 1768187060000
  },
  
  // 第 3 轮:AI 询问核心主题
  {
    role: "assistant",
    content: [
      {
        type: "text",
        text: "很好的选择!心理悬疑能够深入探索人物的内心世界。接下来让我了解更多细节:"
      },
      {
        type: "tool_use",
        id: "toolu_vrtx_01JVU2pQbWxNLdXYdqxZfCPV",
        name: "ask_followup_question",
        input: {
          question: "你希望电影探讨什么样的核心主题?",
          follow_up: [
            {text: "记忆与现实 - 主人公对自己记忆的真实性产生怀疑"},
            {text: "身份认同 - 主人公不确定自己是谁"},
            {text: "信任危机 - 主人公无法相信周围的人"}
          ]
        }
      }
    ],
    ts: 1768187090000
  },
  
  // 用户选择"记忆与现实"
  {
    role: "user",
    content: [
      {
        type: "tool_result",
        tool_use_id: "toolu_vrtx_01JVU2pQbWxNLdXYdqxZfCPV",
        content: "记忆与现实 - 主人公对自己记忆的真实性产生怀疑"
      }
    ],
    ts: 1768187120000
  },
  
  // 第 4 轮:AI 询问背景并开始设计
  {
    role: "assistant",
    content: [
      {
        type: "text",
        text: "非常好!现代都市的背景能营造出孤立和疏离感。让我再确认一个细节:"
      },
      {
        type: "tool_use",
        id: "toolu_vrtx_01JVU2sRcXyOLeYZeqyZgDQW",
        name: "ask_followup_question",
        input: {
          question: "你希望故事发生在什么样的城市环境?",
          follow_up: [
            {text: "城市环境 - 现代大都市,但主人公感到孤立和疏离"},
            {text: "小镇环境 - 封闭的小镇社区"},
            {text: "郊区环境 - 城市边缘的住宅区"}
          ]
        }
      }
    ],
    ts: 1768187150000
  },
  
  // 用户选择"城市环境"后,AI 创建 todo 和文件
  {
    role: "user",
    content: [
      {
        type: "tool_result",
        tool_use_id: "toolu_vrtx_01JVU2sRcXyOLeYZeqyZgDQW",
        content: "城市环境 - 现代大都市,但主人公感到孤立和疏离"
      }
    ],
    ts: 1768187180000
  },
  
  // 第 5 轮:AI 创建设计方案
  {
    role: "assistant",
    content: [
      {
        type: "text",
        text: "完美!我现在开始为你设计这部心理悬疑电影。让我创建一个详细的设计方案。"
      },
      {
        type: "tool_use",
        id: "toolu_vrtx_01JVU2vTdYzPMfZfrzyZhERX",
        name: "update_todo_list",
        input: {
          todos: [
            {id: "1", content: "设计主人公角色背景", status: "in_progress"},
            {id: "2", content: "构建核心悬疑设定", status: "pending"},
            // ... 其他 12 个待办事项
          ]
        }
      },
      {
        type: "tool_use",
        id: "toolu_vrtx_01JVU2wUeZAQNgagsAaZiFS",
        name: "create_file",
        input: {
          path: "心理悬疑电影设计方案.md",
          content: "# 心理悬疑电影设计方案\n\n## 一、基本信息\n- **类型**:心理悬疑\n..."
        }
      }
    ],
    ts: 1768187210000
  },
  
  // 工具执行结果
  {
    role: "user",
    content: [
      {
        type: "tool_result",
        tool_use_id: "toolu_vrtx_01JVU2wUeZAQNgagsAaZiFS",
        content: "Successfully created 心理悬疑电影设计方案.md"
      }
    ],
    ts: 1768187240000
  },
  
  // 第 6 轮:AI 完成任务
  {
    role: "assistant",
    content: [
      {
        type: "text",
        text: "我已经为你完成了这部心理悬疑电影的完整设计方案!\n\n## 核心设定\n\n**主人公**:林墨,35岁建筑师\n**核心悬疑**:车祸后失忆,逐渐发现自己生活在一个\"完美\"但虚假的世界中\n**终极真相**:他是车祸的肇事者,医院为了治疗他的心理创伤,构建了一个治疗性的虚拟环境\n\n## 主要特色\n\n1. **记忆与现实的模糊界限**:通过建筑细节的不一致性暗示真相\n2. **层层递进的悬念**:从日常异常到重大发现\n3. **深刻的主题探讨**:罪责、救赎、自我认知\n\n设计方案已保存到 `心理悬疑电影设计方案.md`,包含完整的角色设定、情节结构、关键场景等内容。\n\n还需要我补充或调整什么吗?"
      }
    ],
    ts: 1768187250000
  }
]

七、总结

本文档通过具体的示例展示了 Kilo 项目中消息交互的完整过程,包括:

  1. 消息格式: 基于 Anthropic 的标准格式,支持文本、图片、工具调用和工具结果
  2. 流式处理: 通过 AssistantMessageParser 实现增量解析,实时显示和执行
  3. 工具执行: 从解析到执行到结果返回的完整闭环
  4. 错误处理: 工具失败、用户拒绝等场景的处理
  5. 保护机制: 重复检测、自动批准等智能机制
相关推荐
光影少年13 小时前
flex布局和grid布局区别,实现两边固定布局中间自适应
前端·css3·web·ai编程
cjqbg15 小时前
灵芽API:企业级大模型API聚合网关架构解析与成本效益对比
人工智能·架构·aigc·ai编程
EdisonZhou16 小时前
MAF快速入门(13)常见智能体编排模式
llm·agent·.net core
HyperAI超神经17 小时前
具身智能资源汇总:机器人学习数据集,在线体验世界建模模型,英伟达/字节/小米等最新研究论文
人工智能·深度学习·学习·机器学习·机器人·ai编程·图形生成
墨抒颖 msy.plus21 小时前
如何构建现代Agent以OpenManus为例
python·ai编程
心易行者1 天前
Agent Skills 终极指南:入门、精通、预测
ai编程
github.com/starRTC1 天前
Claude Code中英文系列教程14:在JetBrain,Android Studio,PyCharm等IDE中使用Claude Code
ai编程
AskHarries1 天前
在 Qoder CLI 集成墨刀 MCP(modao-proto)完整指南
人工智能·ai编程
github.com/starRTC1 天前
Claude Code中英文系列教程15:将Claude Code集成在Github Actions工作流里面
ai编程