news 2026/7/6 20:26:00

第十二篇:MessageBuilder 深度解析 —— Claude Code 如何构建对话消息

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第十二篇:MessageBuilder 深度解析 —— Claude Code 如何构建对话消息

第十二篇:MessageBuilder 深度解析 —— Claude Code 如何构建对话消息

📚系列文章 第12篇/共100篇· 2026年7月 · ⏱️ 阅读时间约 13 分钟
源码位置:src/services/anthropic/MessageBuilder.ts


一、引言:为什么需要 MessageBuilder?

上一篇我们拆解了AnthropicClient.ts,它负责"连接" Anthropic API。但在这之前还有一个关键问题:

API 需要的不是零散的字符串,而是结构化的消息对象。这些消息从哪来?如何把用户的文本、系统提示、历史对话、工具调用结果、甚至图片,拼装成符合 Anthropic 规范的messages数组?

答案就是MessageBuilder.ts

它是 Claude Code 对话流水线的第一道加工车间

  • 🧱 把多源输入(用户输入、系统提示、工具结果、图片)统一成标准Message结构
  • 🖼️ 处理多模态:把图片转成base64或 URL 引用的imagecontent block
  • 📐 管理对话上下文:裁剪过长历史、压缩旧消息、控制 token 预算
  • 🔗 串联工具调用:把tool_use/tool_result配对成合法对话轮次

可以说,没有 MessageBuilder,AnthropicClient 拿到的就是一堆无法发送的数据


二、MessageBuilder 架构概览

┌─────────────────────────────────────────────────────────────┐ │ MessageBuilder │ ├─────────────────────────────────────────────────────────────┤ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │ │ │ Text Builder │ │ Image Builder│ │ System Builder │ │ │ │ (纯文本块) │ │ (多模态) │ │ (系统提示) │ │ │ └──────────────┘ └──────────────┘ └──────────────────┘ │ ├─────────────────────────────────────────────────────────────┤ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │ │ │ History Mgr │ │ Token Budget │ │ Tool Round Mgr │ │ │ │ (历史裁剪) │ │ (预算控制) │ │ (工具轮次配对) │ │ │ └──────────────┘ └──────────────┘ └──────────────────┘ │ └─────────────────────────────────────────────────────────────┘ │ ▼ AnthropicClient.sendMessage(messages)

数据流:

用户输入 + 系统提示 + 工具结果 + 图片 │ ▼ MessageBuilder.build() │ ├── 文本 → { type: 'text', text } ├── 图片 → { type: 'image', source } ├── 工具 → { type: 'tool_use' / 'tool_result' } ▼ 标准 Message[] ──► AnthropicClient ──► /v1/messages

三、核心类型定义

3.1 Anthropic 消息协议

MessageBuilder 的产物必须严格符合 Anthropic Messages API 的 schema:

interfaceMessage{role:'user'|'assistant';content:ContentBlock[];// 注意:content 是数组,不是字符串}typeContentBlock=|{type:'text';text:string}|{type:'image';source:ImageSource}|{type:'tool_use';id:string;name:string;input:unknown}|{type:'tool_result';tool_use_id:string;content:ContentBlock[]};interfaceImageSource{type:'base64';media_type:'image/jpeg'|'image/png'|'image/gif'|'image/webp';data:string;// base64 编码的图片数据}

关键认知:Anthropic 的content是一个块数组,而不是单个字符串。这正是多模态和工具调用的基础。MessageBuilder 的核心职责,就是正确地生成这个数组。

3.2 Builder 配置

interfaceMessageBuilderConfig{maxTokens:number;// 总 token 预算(如 200000)systemPrompt:string;// 系统提示reserveTokens:number;// 为回复预留的 token 数imageCompression?:boolean;// 是否压缩大图truncateStrategy:'head'|'tail'|'smart';// 裁剪策略}

四、文本与系统提示构建

4.1 构建系统提示

系统提示(system prompt)在 Anthropic API 中是顶层参数,不是 messages 的一部分:

buildSystem():string{constblocks:string[]=[];// 1. 基础身份提示blocks.push(this.config.systemPrompt);// 2. 注入当前环境信息(OS、shell、cwd、日期)blocks.push(this.buildEnvironmentContext());// 3. 注入工具定义摘要blocks.push(this.buildToolCatalog());returnblocks.join('\n\n');}privatebuildEnvironmentContext():string{constenv=this.envCollector.collect();return[`<environment>`,`OS:${env.os}`,`Shell:${env.shell}`,`CWD:${env.cwd}`,`Date:${env.isoDate}`,`</environment>`].join('\n');}

设计要点:系统提示是动态拼装的,会实时注入环境上下文,让模型"知道自己在哪台机器上工作"。

4.2 构建用户文本消息

addUserText(text:string):this{this.pendingUserBlocks.push({type:'text',text});returnthis;// 支持链式调用}// 用法builder.addUserText('帮我重构这个函数').addUserText('注意保留测试用例').build();

五、多模态:图片处理

这是 MessageBuilder 最精彩的部分——把图片塞进对话。

5.1 从文件路径读取并编码

asyncaddUserImage(filePath:string):Promise<this>{constbuffer=awaitfs.readFile(filePath);constmediaType=this.detectMediaType(filePath);// 大图压缩(可选)constdata=this.config.imageCompression?awaitthis.compressImage(buffer):buffer;constbase64=data.toString('base64');this.pendingUserBlocks.push({type:'image',source:{type:'base64',media_type:mediaType,data:base64}});returnthis;}

5.2 从 URL 引用图片

Claude 也支持直接传 URL(无需 base64):

addUserImageUrl(url:string):this{this.pendingUserBlocks.push({type:'image',source:{type:'url',url:url}});returnthis;}

5.3 多模态消息示例

constmessage=awaitbuilder.addUserText('这张截图里有什么错误?').addUserImage('./error-screenshot.png').build();// 生成的 content 块:// [// { type: 'text', text: '这张截图里有什么错误?' },// { type: 'image', source: { type: 'base64', media_type: 'image/png', data: 'iVBOR...' } }// ]

💡 实战价值:这就是为什么 Claude Code 能"看"截图、读取设计稿、分析图表。MessageBuilder 把图片转成模型可消费的块,是多模态能力的根基。


六、工具调用轮次管理

工具调用在 Anthropic 协议里是一对配对块,必须严格交替:

assistant: { type: 'tool_use', id: 't1', name: 'Read', input: {...} } user: { type: 'tool_result', tool_use_id: 't1', content: [...] }

6.1 配对管理

addToolUse(block:ToolUseBlock):this{// tool_use 必须来自 assistant 消息if(this.lastRole!=='assistant'){this.flush();// 先结束当前轮次}this.pendingAssistantBlocks.push(block);this.lastRole='assistant';returnthis;}addToolResult(toolUseId:string,content:ContentBlock[]):this{// tool_result 必须来自 user 消息this.pendingUserBlocks.push({type:'tool_result',tool_use_id:toolUseId,content});this.lastRole='user';returnthis;}

6.2 关键约束校验

validateToolPairs():void{// 每个 tool_use 必须有对应的 tool_resultconstuseIds=this.collectToolUseIds();constresultIds=this.collectToolResultIds();for(constidofuseIds){if(!resultIds.has(id)){thrownewMessageBuildError(`工具调用${id}缺少对应的 tool_result`);}}}

⚠️ 血的教训:Anthropic API 对工具配对极其严格。如果tool_use没有配对的tool_result,或反之,API 会直接返回 400。MessageBuilder 的校验逻辑正是为了拦截这类错误。


七、上下文与 Token 预算管理

这是 MessageBuilder 最复杂、也最能体现工程功力的部分。

7.1 Token 估算

privateestimateTokens(blocks:ContentBlock[]):number{lettotal=0;for(constblockofblocks){switch(block.type){case'text':total+=this.tokenizer.count(block.text);break;case'image':// 图片按像素估算 token(约 每 512x512 ≈ 85 token)total+=this.estimateImageTokens(block.source);break;case'tool_use':case'tool_result':total+=this.tokenizer.count(JSON.stringify(block.input??block.content));break;}}returntotal;}

7.2 智能裁剪

当历史超出预算时,按策略裁剪:

privatefitToBudget(messages:Message[]):Message[]{constbudget=this.config.maxTokens-this.config.reserveTokens;letused=this.estimateMessagesTokens(messages);if(used<=budget)returnmessages;// 从最旧的消息开始裁剪(保留最近对话)constresult=[...messages];while(used>budget&&result.length>1){constremoved=result.shift()!;// 移除最旧的一条used-=this.estimateMessagesTokens([removed]);}// 在开头插入截断标记result.unshift(this.buildTruncationNotice());returnresult;}

7.3 三种裁剪策略对比

策略行为适用场景
head丢弃最旧消息长对话,最近内容最重要
tail丢弃最新消息罕见,保留早期上下文
smart保留首尾,压缩中间需要全局上下文的复杂任务

💡 设计哲学:Claude Code 默认用head策略——因为编程对话中,最近的指令和上下文通常最关键。但smart策略会在处理超大文件/跨文件重构时启用,避免丢失早期的重要约束。


八、完整构建流程

build():BuiltMessages{// 1. 收尾当前 pending 的块this.flush();// 2. 组装 messages 数组constmessages=this.assembleMessages();// 3. 校验工具配对this.validateToolPairs();// 4. Token 预算裁剪constfitted=this.fitToBudget(messages);// 5. 构建系统提示constsystem=this.buildSystem();return{messages:fitted,system};}// 最终交给 AnthropicClientconst{messages,system}=builder.build();constresponse=awaitclient.sendMessage(messages,{system});

完整 ASCII 时序:

用户/工具 ──► MessageBuilder │ ├─ addUserText() ─┐ ├─ addUserImage() ├─ 累积 pending 块 ├─ addToolUse() │ ├─ addToolResult() ─┘ │ ▼ build() ├─ flush() 收尾轮次 ├─ assemble() 组装 messages ├─ validateToolPairs() 校验 ├─ fitToBudget() token 裁剪 └─ buildSystem() 系统提示 │ ▼ { messages, system } ──► AnthropicClient

九、使用示例

9.1 最简用法

constbuilder=newMessageBuilder({maxTokens:200000,systemPrompt:'你是一个编程助手',reserveTokens:4096,truncateStrategy:'head'});const{messages,system}=builder.addUserText('用 TypeScript 写一个快速排序').build();client.sendMessage(messages,{system});

9.2 多模态 + 工具混合

const{messages,system}=awaitbuilder.addUserText('这个 UI 有问题,看图').addUserImage('./ui-bug.png')// 多模态.addToolUse({// 工具调用type:'tool_use',id:'t1',name:'Read',input:{file_path:'./App.tsx'}})// (tool_result 会在下一轮由工具执行结果填入).build();

9.3 长对话自动裁剪

// 假设已经累积了 300 轮对话,远超 200k token 预算const{messages}=builder.addUserText('继续').build();// 内部自动裁剪最旧的消息,保留最近上下文

十、源码亮点总结

特性实现方式价值
多模态块content块数组 +imagesource支持图片输入
动态系统提示实时注入环境/工具上下文模型"身临其境"
工具配对校验validateToolPairs()避免 400 错误
Token 预算fitToBudget()智能裁剪永不超窗口
链式 APIaddX().addY().build()调用优雅
策略可配head/tail/smart灵活适配场景

十一、下一篇预告

第13篇我们将深入流式编排(StreamProcessor / query.ts),看看 Claude Code 如何把消息推送到 API、处理流式响应中的tool_use增量块、并实时渲染终端 UI。敬请期待!


📚Claude Code 源码解析系列

  1. 源码泄露事件深度解析
  2. 开发环境搭建指南
  3. CLI入口与命令系统
  4. AI对话引擎全解析
  5. 工具系统深度解析
  6. CLI命令行解析核心
  7. Handler处理器链
  8. QueryEngine查询引擎
  9. query.ts API对话层
  10. callModel.ts API调用层
  11. AnthropicClient API客户端
  12. MessageBuilder 消息构建器← 本文
  13. StreamProcessor 流式编排(待续)

💡如果这篇文章对你有帮助,欢迎点赞、收藏、关注!

有问题欢迎在评论区讨论!

#ClaudeCode #源码分析 #MessageBuilder #多模态 #TypeScript #AI编程

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/6 20:25:34

5个提升英雄联盟游戏体验的智能功能:League Akari实战指南

5个提升英雄联盟游戏体验的智能功能&#xff1a;League Akari实战指南 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power &#x1f680;. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 还在为繁琐的游戏操作浪…

作者头像 李华
网站建设 2026/7/6 20:23:03

yuzu模拟器终极指南:5分钟在PC上畅玩任天堂Switch游戏的完整教程

yuzu模拟器终极指南&#xff1a;5分钟在PC上畅玩任天堂Switch游戏的完整教程 【免费下载链接】yuzu 任天堂 Switch 模拟器 项目地址: https://gitcode.com/GitHub_Trending/yu/yuzu yuzu是一款开源免费的任天堂Switch模拟器&#xff0c;让你在Windows、Linux和Android设…

作者头像 李华
网站建设 2026/7/6 20:22:22

AMP by Example入门教程:如何在5分钟内创建你的第一个AMP页面

AMP by Example入门教程&#xff1a;如何在5分钟内创建你的第一个AMP页面 【免费下载链接】amp-by-example DEPRECATED: AMP by Example has been merged into amp.dev 项目地址: https://gitcode.com/gh_mirrors/am/amp-by-example 想要构建快速加载的移动网页吗&#…

作者头像 李华
网站建设 2026/7/6 20:21:56

GeoQ用户权限管理:构建多层次地理数据访问控制体系

GeoQ用户权限管理&#xff1a;构建多层次地理数据访问控制体系 【免费下载链接】geoq Django web application to collect geospatial features and manage feature collection among groups of users 项目地址: https://gitcode.com/gh_mirrors/ge/geoq GeoQ作为一个专…

作者头像 李华
网站建设 2026/7/6 20:21:12

免费开源风扇控制软件:FanControl终极静音散热指南

免费开源风扇控制软件&#xff1a;FanControl终极静音散热指南 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Trending/fa/Fa…

作者头像 李华