fix(memory): 时间线按声明渲染工具回执 + 能力判定改为配置层

时间线此前只写「→ 调用工具: a, b」,工具取回的正文下一轮彻底消失:
模型记得自己查过,却不记得查到了什么(刚说的话转头就忘)。
ToolDef 上的 Cleaner / NoMemory 声明一直存在,缺的是消费端。

- formatMergedTimeline 渲染 e.ToolResults:Cleaner 优先,NoMemory 工具跳过,
  单条 160 字、每事件最多 3 条(+N more),预算估算同步计入
- 模态能力改由配置层声明(ProviderManager.SetCapabilities),
  不再靠 provider.(ModalProvider) 断言穿过 adapter 与安全装饰器
- a2a 通道 RecallPolicy none→auto(NoMemory 仍 true:可读不写)
This commit is contained in:
JianFeeeee
2026-10-27 12:16:06 +08:00
parent 4af07d08fe
commit 051247e10f
6 changed files with 290 additions and 1 deletions

View File

@ -250,7 +250,7 @@ func (a *Agent) transcribeBlocksForFallback(blocks []agentAPI.ContentBlock) moda
// 为何逐模态判定而不是一刀切:一批块里可能图能看、音频不能听(很多视觉
// 模型就是这样)。全部走回退会白白把本可直视的图降级成二手文字描述。
func (a *Agent) prepareToolBlocks(blocks []agentAPI.ContentBlock) ([]agentAPI.ContentBlock, string) {
canVision := agentAPI.ProviderSupportsVision(a.provider)
canVision := a.providerCanVision()
canAudio := agentAPI.ProviderSupportsAudio(a.provider)
var native []agentAPI.ContentBlock
@ -358,3 +358,19 @@ func (a *Agent) chatModalFallbackBatch(p agentAPI.Provider, kind string, urls, d
}
return out, nil
}
// providerCanVision 判定**当前主 provider** 能否看图。
//
// 先查配置层声明的能力(ProviderManager.Capabilities),配置没说才退回
// 类型断言。这样 adapter/装饰器漏实现方法也不会让能力凭空消失。
func (a *Agent) providerCanVision() bool {
if a == nil || a.provider == nil {
return false
}
if a.providerManager != nil {
if _, ok := a.providerManager.Capabilities(a.provider.Name()); ok {
return a.providerManager.SupportsVision(a.provider.Name())
}
}
return agentAPI.ProviderSupportsVision(a.provider)
}