Version: 0.9.50.dev.260428

后端:
1. 工具执行结果协议升级为结构化 ToolExecutionResult——execute/tool_runtime、ToolRegistry、stream extra 与 timeline 持久化统一改为透传 observation_text / summary / argument_view / result_view,不再只回写纯文本结果;context_tools、upsert_task_class 与旧 schedule/web 工具通过兼容包装接入新协议
2. 日程写工具注册继续收口——place / move / swap / batch_move / unplace / queue_apply_head_move 从 registry 内联实现下沉为独立 handler,降低注册表内参数解析与业务逻辑混写
3. 工具结果展示基础能力补齐——新增 execution_result / schedule_operation_handlers 公共件,为日程操作结果、参数本地化展示、blocked/failed/done 状态统一建模

前端:
4. AssistantPanel 接入结构化工具卡片渲染——新增 ToolCardRenderer,tool_call / tool_result 支持 argument_view / result_view 展示;schedule_completed 恢复为时间线内的占位卡片块,避免排程卡片脱离原消息顺序
5. 时间线类型与渲染收敛——schedule_agent.ts 补齐 ToolView 协议,AssistantPanel 改为按块渲染 tool / schedule_card / business_card,并移除旧 demo/prototype 路由与页面,收束正式面板代码路径

仓库:
6. AGENTS.md 新增协作约束——禁止擅自回滚、覆盖或删除用户/其他代理产生的工作区改动
This commit is contained in:
LoveLosita
2026-04-28 11:55:34 +08:00
parent 32d5dd0262
commit 509e266626
17 changed files with 2431 additions and 2199 deletions

View File

@@ -21,7 +21,7 @@ func appendToolCallResultHistory(
conversationContext *newagentmodel.ConversationContext,
toolName string,
args map[string]any,
result string,
result newagenttools.ToolExecutionResult,
) {
if conversationContext == nil {
return
@@ -50,7 +50,7 @@ func appendToolCallResultHistory(
})
conversationContext.AppendHistory(&schema.Message{
Role: schema.Tool,
Content: result,
Content: result.ObservationText,
ToolCallID: toolCallID,
ToolName: toolName,
})
@@ -98,16 +98,9 @@ func executeToolCall(
return fmt.Errorf("连续 %d 次调用临时禁用工具,终止执行: %s",
flowState.ConsecutiveCorrections, toolName)
}
blockedResult := buildTemporarilyDisabledToolResult(toolName)
_ = emitter.EmitToolCallResult(
executeStatusBlockID,
executeStageName,
toolName,
"blocked",
blockedResult,
buildToolArgumentsPreviewCN(toolCall.Arguments),
false,
)
blockedText := buildTemporarilyDisabledToolResult(toolName)
blockedResult := newagenttools.BlockedResult(toolName, toolCall.Arguments, blockedText, "tool_temporarily_disabled", blockedText)
emitToolCallResultEvent(emitter, executeStatusBlockID, executeStageName, blockedResult, toolCall.Arguments)
appendToolCallResultHistory(conversationContext, toolName, toolCall.Arguments, blockedResult)
newagentshared.AppendLLMCorrectionWithHint(
conversationContext,
@@ -165,16 +158,9 @@ func executeToolCall(
}
if shouldForceFeasibilityNegotiation(flowState, registry, toolName) {
blockedResult := buildInfeasibleBlockedResult(flowState)
_ = emitter.EmitToolCallResult(
executeStatusBlockID,
executeStageName,
toolName,
"blocked",
blockedResult,
buildToolArgumentsPreviewCN(toolCall.Arguments),
false,
)
blockedText := buildInfeasibleBlockedResult(flowState)
blockedResult := newagenttools.BlockedResult(toolName, toolCall.Arguments, blockedText, "health_negotiation_required", blockedText)
emitToolCallResultEvent(emitter, executeStatusBlockID, executeStageName, blockedResult, toolCall.Arguments)
appendToolCallResultHistory(conversationContext, toolName, toolCall.Arguments, blockedResult)
return nil
}
@@ -187,9 +173,10 @@ func executeToolCall(
toolCall.Arguments["_user_id"] = flowState.UserID
}
result := registry.Execute(scheduleState, toolName, toolCall.Arguments)
updateHealthSnapshotV2(flowState, toolName, result)
updateTaskClassUpsertSnapshot(flowState, toolName, result)
updateActiveToolDomainSnapshot(flowState, toolName, result)
result = newagenttools.EnsureToolResultDefaults(result, toolCall.Arguments)
updateHealthSnapshotV2(flowState, toolName, result.ObservationText)
updateTaskClassUpsertSnapshot(flowState, toolName, result.ObservationText)
updateActiveToolDomainSnapshot(flowState, toolName, result.ObservationText)
afterDigest := summarizeScheduleStateForDebug(scheduleState)
log.Printf(
"[DEBUG] execute tool chat=%s round=%d tool=%s args=%s before=%s after=%s result_preview=%.200s",
@@ -199,17 +186,9 @@ func executeToolCall(
marshalArgsForDebug(toolCall.Arguments),
beforeDigest,
afterDigest,
flattenForLog(result),
)
_ = emitter.EmitToolCallResult(
executeStatusBlockID,
executeStageName,
toolName,
resolveToolEventResultStatus(result),
buildToolEventResultSummary(result),
buildToolArgumentsPreviewCN(toolCall.Arguments),
false,
flattenForLog(result.ObservationText),
)
emitToolCallResultEvent(emitter, executeStatusBlockID, executeStageName, result, toolCall.Arguments)
appendToolCallResultHistory(conversationContext, toolName, toolCall.Arguments, result)
@@ -301,32 +280,18 @@ func executePendingTool(
}
flowState := runtimeState.EnsureCommonState()
if registry.IsToolTemporarilyDisabled(pending.ToolName) {
blockedResult := buildTemporarilyDisabledToolResult(pending.ToolName)
_ = emitter.EmitToolCallResult(
executeStatusBlockID,
executeStageName,
pending.ToolName,
"blocked",
blockedResult,
buildToolArgumentsPreviewCN(args),
false,
)
blockedText := buildTemporarilyDisabledToolResult(pending.ToolName)
blockedResult := newagenttools.BlockedResult(pending.ToolName, args, blockedText, "tool_temporarily_disabled", blockedText)
emitToolCallResultEvent(emitter, executeStatusBlockID, executeStageName, blockedResult, args)
appendToolCallResultHistory(conversationContext, pending.ToolName, args, blockedResult)
runtimeState.PendingConfirmTool = nil
return nil
}
if shouldForceFeasibilityNegotiation(flowState, registry, pending.ToolName) {
blockedResult := buildInfeasibleBlockedResult(flowState)
_ = emitter.EmitToolCallResult(
executeStatusBlockID,
executeStageName,
pending.ToolName,
"blocked",
blockedResult,
buildToolArgumentsPreviewCN(args),
false,
)
blockedText := buildInfeasibleBlockedResult(flowState)
blockedResult := newagenttools.BlockedResult(pending.ToolName, args, blockedText, "health_negotiation_required", blockedText)
emitToolCallResultEvent(emitter, executeStatusBlockID, executeStageName, blockedResult, args)
appendToolCallResultHistory(conversationContext, pending.ToolName, args, blockedResult)
runtimeState.PendingConfirmTool = nil
return nil
@@ -340,9 +305,10 @@ func executePendingTool(
args["_user_id"] = flowState.UserID
}
result := registry.Execute(scheduleState, pending.ToolName, args)
updateHealthSnapshotV2(flowState, pending.ToolName, result)
updateTaskClassUpsertSnapshot(flowState, pending.ToolName, result)
updateActiveToolDomainSnapshot(flowState, pending.ToolName, result)
result = newagenttools.EnsureToolResultDefaults(result, args)
updateHealthSnapshotV2(flowState, pending.ToolName, result.ObservationText)
updateTaskClassUpsertSnapshot(flowState, pending.ToolName, result.ObservationText)
updateActiveToolDomainSnapshot(flowState, pending.ToolName, result.ObservationText)
afterDigest := summarizeScheduleStateForDebug(scheduleState)
log.Printf(
"[DEBUG] execute pending tool chat=%s round=%d tool=%s args=%s before=%s after=%s result_preview=%.200s",
@@ -352,17 +318,9 @@ func executePendingTool(
marshalArgsForDebug(args),
beforeDigest,
afterDigest,
flattenForLog(result),
)
_ = emitter.EmitToolCallResult(
executeStatusBlockID,
executeStageName,
pending.ToolName,
resolveToolEventResultStatus(result),
buildToolEventResultSummary(result),
buildToolArgumentsPreviewCN(args),
false,
flattenForLog(result.ObservationText),
)
emitToolCallResultEvent(emitter, executeStatusBlockID, executeStageName, result, args)
appendToolCallResultHistory(conversationContext, pending.ToolName, args, result)
@@ -434,3 +392,27 @@ func buildExecuteNormalizedSpeakTail(streamed, normalized string) string {
}
return normalized[len(streamed):]
}
func emitToolCallResultEvent(
emitter *newagentstream.ChunkEmitter,
blockID string,
stage string,
result newagenttools.ToolExecutionResult,
args map[string]any,
) {
if emitter == nil {
return
}
result = newagenttools.EnsureToolResultDefaults(result, args)
_ = emitter.EmitToolCallResult(
blockID,
stage,
result.Tool,
result.Status,
result.Summary,
result.ArgumentsPreview,
newagenttools.ToolArgumentViewToMap(result.ArgumentView),
newagenttools.ToolDisplayViewToMap(result.ResultView),
false,
)
}