@deepseek-ai/dsh-tool-call-timeout-policy

September 11, 2026 · View on GitHub

English | 中文

概述

使用本包可为工具调用执行其配置的协作式时间上限,并在取消完成后向模型返回清晰的超时错误。按时完成的调用保持不变。忽略或缓慢处理取消的工具仍可能让调用方继续等待,因为本包无法硬性停止下游工作。每个工具分别提供自己的限时;本包无需配置,并随 dsh base 组合默认启用。

目录


使用本包

常用路径只有一行:把插件加入组合——dsh base 组合已经包含它。配置了限时的工具会被自动保护;其余工具完全不受影响。

何时选择

当模型会调用耗时很长的工具、这些工具会遵守 exec.signal,且你希望在取消完成后得到可预期的超时答复时,选择它。当工具必须在到达限时后被硬性停止时——插件只能请求工具停止,因此忽略取消的工具会继续运行并让调用方继续等待——以及当你希望为所有工具设置一个统一默认限时时(因为每个工具的限时来自该工具自身的配置),避免使用它。

设置

无需任何配置即可挂载插件:

- name: '@deepseek-ai/dsh-tool-call-timeout-policy'

限时在配置工具的位置设置。例如,dsh-tool-webfetchTimeoutMssearchTimeoutMs 设置(默认 30,000 ms)把限时放到 web_fetchweb_search 上。没有限时的工具——随附的 bashreadwriteedit——绝不会被切断。生成的配置目录列出会产生限时的工具设置。

你会得到什么

截止时间触发时,插件会中止派生的 exec.signal。下游代码遵守取消且 next() 完成后,模型会收到标记为错误的 Error: tool call timed out after <ms>ms 工具结果,从而决定重试、调整或放弃。忽略或缓慢处理该信号的工具会让调用方继续等待,并且在自身完成前不会产生超时结果;按时完成的调用保持不变。


理解实现

实现细节——点击展开

本节解释插件如何在每次分发周围设置截止时间并将其映射为 TOOL_TIMEOUT 结果,并指出实现它的代码位置;可观察行为已在使用本包中完整说明。

设计理念

包装层建立在四项承诺之上:

  • 强制执行归属,而非库。 dsh-timeout 负责时序与分类(deadlinetimeoutOf);本插件负责 tools/execute 上的单次调用接线;各能力负责终止。该拆分记录在超时截止时间库 Agent Note 中。
  • 工具声明自己的预算。 timeoutMs 位于工具的 ToolDefinition 上,从注册表读取(ctx.tools.get(exec.name, exec.agent)?.timeoutMs),因此不可能拼错工具名,未声明工具原样委派。
  • 作用域分类。 TOOL_TIMEOUT 同时用作内部 deadline 分类码与结构化错误 code;把 timeoutOf 限定到它,可避免嵌套的外层截止时间(先触发的另一包装层计时器)被误读为本插件的超时——它读作普通的上游取消。
  • 先交换信号,再恢复。 Cordis next() 忽略传入参数,因此包装层原地修改共享 exec:分发时把派生的截止时间信号换到 exec 上,并在 finally 中恢复调用方信号,使 tools/post-execute 监听器永远看不到本插件可能已中止的信号。

截止时间如何设置与映射

一个 tools/execute 监听器从注册表读取已分发工具声明的限时(ctx.tools.get(exec.name, exec.agent)?.timeoutMs);没有限时的工具原样委派。对有限时的工具,deadline(exec.signal, timeoutMs, TOOL_TIMEOUT) 构建融合信号,包装层在分发时把它换到 exec 上并在 finally 中恢复,使 tools/post-execute 监听器永远看不到派生信号。当包装层自己的计时器触发时——timeoutOf(d.signal, 'TOOL_TIMEOUT') 以代码限定作用域,因此嵌套的外层截止时间读作普通的上游取消——已被分发规范化为错误结果的分发结果会被替换为结构化结果:isError: true、内容 Error: tool call timed out after <ms>ms、错误信息 { name: 'ToolTimeoutError', code: 'TOOL_TIMEOUT' }

与其他包装层组合

多个 tools/execute 监听器按 Cordis 注册顺序组合,注册顺序决定语义:超时注册在外层时覆盖整个重试操作,注册在内层时覆盖每次尝试。

源码地图

文件职责
src/index.ts插件入口:TOOL_TIMEOUTnameinjectapplytools/execute 包装层
不发布运行时不变式伴生入口;无状态包装层不拥有包级事件历史。

进一步探索

当包级约定不够用时阅读以下页面。它们从工具调用流水线逐步进入超时库拆分、被执行的限时与 guard 组映射。


模型体验

条件工具结果

模型看到什么

此插件不添加提示词或 schema。如果已声明的截止时间先到且下游取消完成,它会用 Error: tool call timed out after <ms>ms 与结构化 TOOL_TIMEOUT 错误替换提供方结果;否则原结果保持不变。永不完成的下游调用无法产生超时结果。

Token 影响

未超时的调用不会增加 token。超时会添加一条会被保留的简短错误结果,并可防止体积更大、较晚返回的提供方结果进入上下文。

KV Cache 影响

仅追加;新可见内容位于可复用请求前缀之后,不会使现有 KV Cache 条目失效。

已知限制与延期工作

这些限制说明策略何时不合适。它们是当前包约束,不是任务积压。

  • 协作式,绝不是硬终止——截止时间只通过 exec.signal 通知;忽略该信号的工具不会在超时时停止,包装层仍停留在 await next() 内,模型要等下游完成后才可能收到超时结果。
  • 没有统一预算——只有声明 timeoutMs 并将其放在 ToolDefinition 上的工具才会获得截止时间;未声明工具(随附的 bashreadwriteedit 有意不声明)没有注册表级默认值。

开发备注

维护者的工作上下文——点击展开

本开发备注是维护者的工作上下文:开放问题与尚未决定的探索方向。它明确不具权威性——已交付的行为、限制与既定理由以上文、包代码和相关 Agent Note 为准。

src/index.ts 中的 FIXME 要求确定 @deepseek-ai/dsh-timeout-guard 改名;改名台账 已把 @deepseek-ai/dsh-tool-call-timeout-policy 记录为既定名称,因此该 FIXME 已陈旧,待代码清理。