98 lines
4.9 KiB
Go
98 lines
4.9 KiB
Go
package runtime
|
||
|
||
import (
|
||
agentllm "agent-native/runtime/llm"
|
||
agenttools "agent-native/runtime/tools"
|
||
core "agent-system-core"
|
||
"bytes"
|
||
"encoding/json"
|
||
"fmt"
|
||
"io"
|
||
)
|
||
|
||
const workCheckpointTool = "publish_work_checkpoint"
|
||
|
||
type WorkCheckpointSink interface {
|
||
PublishWorkCheckpoint(core.WorkCheckpointCandidate) (string, error)
|
||
}
|
||
|
||
func checkpointEnabled(rc RunCtx) bool {
|
||
if capability, ok := rc.(interface{ WorkCheckpointAvailable() bool }); ok && !capability.WorkCheckpointAvailable() {
|
||
return false
|
||
}
|
||
src, ok := rc.(interface{ SubagentID() string })
|
||
if !ok || src.SubagentID() != materialSubagentID {
|
||
return false
|
||
}
|
||
if _, ok = rc.(WorkCheckpointSink); !ok {
|
||
return false
|
||
}
|
||
if !rc.Profile().Tools.ToolAllowed(workCheckpointTool) || rc.Profile().Tools.NeedsConfirm(workCheckpointTool) {
|
||
return false
|
||
}
|
||
for _, tool := range rc.Tools() {
|
||
if tool.Name == workCheckpointTool {
|
||
return false
|
||
}
|
||
}
|
||
return true
|
||
}
|
||
func checkpointDecl() agentllm.ToolDecl {
|
||
return agentllm.ToolDecl{Name: workCheckpointTool, Description: "及时保存本次材料整理的阶段发现。只引用已提供的 sourceId/blockIndex 和连续原文短引;material_record 由宿主展示原句。数字、决定状态和分期归属若没有原文直接关系,须提供可核对的 evidence:direct_relation 指向明确原句;difference 给出 total/phase 与差额;unresolved_relation 给出 total/phase/dependent 并让宿主判断范围。sourceIndex 是本条 findings.sources 的零起始索引。宿主会把不能证明的判断改为待确认并在工具结果说明,不得把推测写成已批准或确定归属。不额外调用摘要模型;每次发布1至3条新发现,最多6次;更正旧发现时用 corrects。本工具不创建确认按钮或暂停执行。", Parameters: json.RawMessage(`{
|
||
"type":"object","additionalProperties":false,"required":["checkpointId","phaseId","findings"],
|
||
"properties":{
|
||
"checkpointId":{"type":"string"},
|
||
"phaseId":{"type":"string","enum":["reading","crosscheck","summarizing","draft-ready"]},
|
||
"focus":{"type":"string"},"remaining":{"type":"string"},"nextStep":{"type":"string"},
|
||
"findings":{"type":"array","minItems":1,"maxItems":3,"items":{
|
||
"type":"object","additionalProperties":false,"required":["findingKey","text","kind","sources"],
|
||
"properties":{
|
||
"findingKey":{"type":"string"},"text":{"type":"string"},"impact":{"type":"string"},
|
||
"kind":{"type":"string","enum":["material_record","analysis","provisional","needs_user"]},
|
||
"assumptions":{"type":"string"},"corrects":{"type":"string"},
|
||
"sources":{"type":"array","minItems":1,"items":{"type":"object","additionalProperties":false,
|
||
"required":["sourceId","blockIndex","quote"],"properties":{
|
||
"sourceId":{"type":"string"},"blockIndex":{"type":"integer","minimum":0},
|
||
"quote":{"type":"string","description":"同一段落连续出现的原文短句"}}}},
|
||
"evidence":{"type":"object","additionalProperties":false,"required":["mode","premises"],"properties":{
|
||
"mode":{"type":"string","enum":["direct_relation","difference","unresolved_relation"]},
|
||
"premises":{"type":"array","minItems":1,"maxItems":3,"items":{"type":"object","additionalProperties":false,
|
||
"required":["role","sourceIndex"],"properties":{
|
||
"role":{"type":"string","enum":["total","phase","dependent","direct_relation"]},
|
||
"sourceIndex":{"type":"integer","minimum":0},"value":{"type":"integer","minimum":0,"maximum":1000000}}}},
|
||
"result":{"type":"integer","minimum":0,"maximum":1000000}}}
|
||
}}}
|
||
}
|
||
}`)}
|
||
}
|
||
func publishCheckpoint(rc RunCtx, args string) agenttools.Result {
|
||
if !checkpointEnabled(rc) {
|
||
return agenttools.Result{IsError: true, Content: "检查点发布不适用于当前任务或工具策略不允许"}
|
||
}
|
||
if len(args) > 16*1024 {
|
||
return agenttools.Result{IsError: true, Content: "检查点超过16KiB;已有成果保留"}
|
||
}
|
||
var candidate core.WorkCheckpointCandidate
|
||
d := json.NewDecoder(bytes.NewBufferString(args))
|
||
d.DisallowUnknownFields()
|
||
if err := d.Decode(&candidate); err != nil {
|
||
return agenttools.Result{IsError: true, Content: err.Error()}
|
||
}
|
||
var extra any
|
||
if err := d.Decode(&extra); err != io.EOF {
|
||
return agenttools.Result{IsError: true, Content: "检查点只接受一个JSON对象"}
|
||
}
|
||
if err := core.ValidateWorkCheckpoint(candidate); err != nil {
|
||
return agenttools.Result{IsError: true, Content: err.Error()}
|
||
}
|
||
receipt, err := rc.(WorkCheckpointSink).PublishWorkCheckpoint(candidate)
|
||
if err != nil {
|
||
return agenttools.Result{IsError: true, Content: fmt.Sprintf("阶段发现未发布,已有成果保留:%v", err)}
|
||
}
|
||
content := "阶段发现已保存到当前任务卡。继续处理剩余工作;发布成功只表示来源片段通过校验,不表示分析结论已独立核实。"
|
||
if receipt != "" {
|
||
content += " " + receipt
|
||
}
|
||
return agenttools.Result{Content: content}
|
||
}
|