Effect AI 中 Anthropic `Memory_20250818` 工具 `requiresHandler` 修复:Provider 定义工具客户端执行语义与类型安全解析

发布时间:2026/9/15 16:10:04
Effect AI 中 Anthropic `Memory_20250818` 工具 `requiresHandler` 修复:Provider 定义工具客户端执行语义与类型安全解析 Effect AI 中 AnthropicMemory_20250818工具requiresHandler修复Provider 定义工具客户端执行语义与类型安全解析【免费下载链接】effectBuild production-ready applications in TypeScript项目地址: https://gitcode.com/GitHub_Trending/ef/effect导读本文基于effect/ai-anthropic的补丁记录.changeset/pre/fix-anthropic-memory-tool-requires-handler.md讲解一个关键修复Anthropic 官方 memory 工具Memory_20250818此前缺失requiresHandler: true标记导致该工具被排除出Tool.HandlersFor类型应用无法为其编写类型安全的处理器。读完本文你将掌握 Effect AI 中provider 定义工具provider-defined tool与客户端执行工具client-executed tool的区分、requiresHandler在类型系统中的实际作用以及如何在Toolkit.toLayer中为Memory_20250818提供处理器并完成端到端验证。背景一次 patch 记录背后的问题该补丁文件属于effect/ai-anthropic包标记为patch级别变更。核心描述如下FixMemory_20250818provider-defined tool missingrequiresHandler: true。与其他客户端执行工具TextEditor_20250728、Bash_2025*、ComputerUse_2025*一样memory 工具要求应用实现其执行逻辑对/memories/*的 view/create/str_replace/insert/delete/rename。缺少该标记时Tool.HandlersFor会将其从必需处理器中排除导致无法在Toolkit.toLayer中对Memory_20250818的处理器进行类型检查。这意味着此前的版本中如果你使用Toolkit.make(AnthropicTool.Memory_20250818({}))并尝试在toLayer中提供AnthropicMemory处理器TypeScript 会报错——因为类型层面该工具不被视为需要处理器的工具处理器键名不会进入HandlersFor联合类型。修复后该工具与其他客户端执行工具保持一致类型检查得以通过。什么是 provider 定义工具与客户端执行工具在 Effect AI 中工具分为两类用户定义工具user-defined tool由应用通过Tool.make创建处理器由应用自己提供工具执行完全在客户端完成。provider 定义工具provider-defined tool由模型提供商如 Anthropic定义的官方工具通过Tool.providerDefined创建。其中一部分工具由提供商在服务端执行如 WebSearch、WebFetch另一部分则要求应用在客户端实现执行逻辑如 Bash、Computer Use、Text Editor、Memory这类工具必须标记requiresHandler: true。从 Tool.ts 的源码可见providerDefined的类型签名export const providerDefined const Identifier extends ${string}.${string}, const Name extends string, Args extends Schema.Constraint typeof Schema.Void, Parameters extends Schema.Constraint typeof Schema.Void, Success extends Schema.Constraint typeof Schema.Void, Failure extends Schema.Constraint typeof Schema.Never, RequiresHandler extends boolean false (options: { readonly id: Identifier readonly customName: Name readonly providerName: string readonly args?: Args | undefined readonly requiresHandler?: RequiresHandler | undefined readonly parameters?: Parameters | undefined readonly success?: Success | undefined readonly failure?: Failure | undefined }) ...关键点requiresHandler的默认值为false。这正是 bug 的根源Memory_20250818在创建时未显式传入requiresHandler: true于是被当作无需客户端处理器的 provider 工具。当requiresHandler: true时构造函数的args参数会额外接受一个failureMode配置error默认 /return用于指定工具处理器执行出错时错误是进入调用 Effect 的错误通道还是作为工具调用结果的一部分返回。HandlersFor如何决定必需处理器requiresHandler标记最终通过Tool.HandlersFor类型影响Toolkit的处理器要求见 Tool.tsexport type HandlersForTools extends Recordstring, Any { [Name in keyof Tools]: RequiresHandlerTools[Name] extends true ? HandlerTools[Name][name] : never }[keyof Tools] export type RequiresHandlerTool extends Any Tool extends ProviderDefined infer _Name, infer _Config, infer _RequiresHandler ? _RequiresHandler : true可见对用户定义工具非ProviderDefinedRequiresHandler恒为true因此始终要求处理器对 provider 定义工具RequiresHandler直接取工具携带的_RequiresHandler泛型参数。当该参数为false时HandlersFor中对应成员被映射为never——工具被静默排除出必需处理器集合这正是本次修复要解决的行为。Memory_20250818的修复后定义修复后AnthropicTool.ts 中Memory_20250818的定义为export const Memory_20250818 Tool.providerDefined({ id: anthropic.memory_20250818, customName: AnthropicMemory, providerName: memory, requiresHandler: true, parameters: Memory_20250818_Commands, success: Schema.String })各字段语义id: anthropic.memory_20250818唯一标识命名空间为anthropiccustomName: AnthropicMemoryToolkit 中用于标识该工具的名称也是处理器注册时使用的键名providerName: memoryAnthropic API 线协议上使用的工具名。模型在响应中返回name: memory运行时需将其解析到自定义名AnthropicMemory否则会抛出ToolNotFoundrequiresHandler: true声明该工具由客户端实现执行是本次修复新增的关键标记parameters: Memory_20250818_Commands一个Schema.Union涵盖全部六种命令载荷success: Schema.String处理器返回字符串结果。六种命令载荷parameters 联合体Memory_20250818_CommandsAnthropicTool.ts由以下命令 Schema 联合而成均在/memories/*空间内操作命令载荷字段说明createpath: String、file_text: String创建新文件文件已存在则失败父目录必须已存在viewpath: String、view_range?: [start, end]查看文件内容或目录列表view_range为 1 起始的行范围-1表示读到文件末尾str_replacepath: String、old_str: String、new_str: String在文件中做字符串替换insertpath: String、insert_line: Int、insert_text: String在指定行号插入文本deletepath: String删除文件renameold_path: String、new_path: String重命名或移动文件/目录例如view命令的 SchemaAnthropicTool.tsexport const MemoryViewCommand Schema.Struct({ command: Schema.Literal(view), path: Schema.String, view_range: Schema.optionalKey(ViewRange) })注意测试中特别强调的一个细节可选参数必须使用Schema.optionalKey而非Schema.optional否则 Anthropic 编解码器会以 Unsupported AST Undefined 拒绝该工具 Schema见 AnthropicLanguageModel.test.ts。如何为Memory_20250818编写类型安全的处理器修复的直接收益现在可以像处理其他客户端执行工具一样在Toolkit.toLayer中为AnthropicMemory提供处理器并通过类型检查。以下是一个完整可运行的最小示例模拟模型调用 memory 工具的view命令import { Effect, Layer, Redacted, Schema } from effect import { LanguageModel, Toolkit } from effect/unstable/ai import { AnthropicTool } from effect/ai-anthropic import { AnthropicClient } from effect/ai-anthropic/AnthropicClient import { AnthropicLanguageModel } from effect/ai-anthropic/AnthropicLanguageModel // 1. 组装包含 Memory 工具的 Toolkit const toolkit Toolkit.make(AnthropicTool.Memory_20250818({})) // 2. 在 toLayer 中注册处理器键名必须是 customName: AnthropicMemory const toolkitLayer toolkit.toLayer({ AnthropicMemory: (params) { switch (params.command) { case view: return Effect.succeed(memory listing for ${params.path}) case create: return Effect.succeed(File created successfully at: ${params.path}) case str_replace: return Effect.succeed(Replaced text in: ${params.path}) case insert: return Effect.succeed(Inserted at line ${params.insert_line} in: ${params.path}) case delete: return Effect.succeed(Deleted: ${params.path}) case rename: return Effect.succeed(Renamed ${params.old_path} to ${params.new_path}) } } }) // 3. 提供模型与客户端 Layer const layer AnthropicClient.layer({ apiKey: Redacted.make(sk-test-key) }).pipe( Layer.provide(Layer.succeed( HttpClient.HttpClient, makeHttpClient(/* 你的 HTTP 客户端实现返回 tool_use 响应 */) )) ) const program LanguageModel.generateText({ prompt: check memory, toolkit }).pipe( Effect.provide(AnthropicLanguageModel.model(claude-sonnet-4-20250514)), Effect.provide(toolkitLayer), Effect.provide(layer) )关键约束均由测试验证见 AnthropicLanguageModel.test.ts处理器键名必须与customName一致即AnthropicMemory。若键名不匹配toLayer无法将处理器与工具关联线协议名解析模型返回的name: memory会被解析为自定义名AnthropicMemory因此处理器在customName下被调用并收到解码后的命令载荷处理器收到的参数是解码后的 Schema 类型例如view命令收到{ command: view, path: /memories }create命令收到{ command: create, path: /memories/notes.txt, file_text: hello world }。create必须携带file_text否则文件内容会被丢弃执行链路Toolkit.toLayer构建处理器上下文Tool.HandlersForToolstoHandlers将其转换为ContextToolkit本身是依赖Tool.HandlersForTools的Effect见 Toolkit.ts。调用时校验参数、运行处理器、编码结果、按failureMode应用失败策略。修复验证测试与回归保护本次修复伴随测试对回归做了三重保护AnthropicLanguageModel.test.ts线协议名到自定义名的解析模拟模型返回content: [{ type: tool_use, id: toolu_mem_1, name: memory, input: { command: view, path: /memories } }]断言处理器在AnthropicMemory名下收到{ command: view, path: /memories }且response.toolResults[0]的name为AnthropicMemory、结果为memory listing。这覆盖了 beta.98 上被破坏的往返链路issue #2615。create命令的file_text解码模拟create调用并断言file_text被完整传递给处理器。所有客户端执行工具的参数均可被 Anthropic 编解码器编译测试矩阵覆盖Bash_20241022、Bash_20250124、ComputerUse_*三个版本、Memory_20250818、TextEditor_*四个版本逐一断言toCodecAnthropic(tool.parametersSchema)非空。Memory_20250818与Bash_2025*、ComputerUse_2025*、TextEditor_20250728同属该矩阵正是补丁描述中与其他客户端执行工具保持一致的验证体现。相关资源补丁记录.changeset/pre/fix-anthropic-memory-tool-requires-handler.md工具定义源码AnthropicTool.tsMemory_20250818位于第 1620-1627 行providerDefined与HandlersFor实现Tool.ts、Tool.tsToolkit.toLayer/toHandlers实现Toolkit.ts回归测试AnthropicLanguageModel.test.ts总结requiresHandler: true是 provider 定义工具声明客户端执行语义的类型级契约。Memory_20250818缺失该标记后HandlersFor将其映射为never导致类型系统误判该工具无需处理器Toolkit.toLayer中的处理器声明无法通过类型检查。修复后该工具与Bash_2025*、ComputerUse_2025*、TextEditor_20250728等保持一致应用必须为AnthropicMemory实现六种命令view/create/str_replace/insert/delete/rename的执行逻辑并在Toolkit.toLayer中注册同名处理器。对于正在使用 Effect AI Anthropic 记忆功能的开发者升级到包含该补丁的effect/ai-anthropic版本即可恢复Memory_20250818处理器的类型安全支持。【免费下载链接】effectBuild production-ready applications in TypeScript项目地址: https://gitcode.com/GitHub_Trending/ef/effect创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考