Decouple runmgr from cmdbus via view types in CommandSource (EXT-14 lint fix) #116
+20
-4
@@ -707,10 +707,26 @@ func splitKeyPool(s string) []string {
|
||||
return out
|
||||
}
|
||||
|
||||
// busAdapter EXT-14:cmdbus.Bus 适配 runmgr.CommandSource(工具投影 + 命令分发)。
|
||||
// busAdapter EXT-14:cmdbus.Bus 适配 runmgr.CommandSource。视图类型转换在此收口
|
||||
// (runmgr 不依赖 cmdbus,边不进架构基线);Entrance 由 runmgr 固定为 agent。
|
||||
type busAdapter struct{ bus *cmdbus.Bus }
|
||||
|
||||
func (a busAdapter) CommandTools() []cmdbus.CommandTool { return a.bus.CommandTools() }
|
||||
func (a busAdapter) DispatchCommand(ctx context.Context, req cmdbus.Request) cmdbus.Response {
|
||||
return a.bus.Dispatch(ctx, req)
|
||||
func (a busAdapter) CommandTools() []runmgr.CommandTool {
|
||||
src := a.bus.CommandTools()
|
||||
out := make([]runmgr.CommandTool, len(src))
|
||||
for i, ct := range src {
|
||||
out[i] = runmgr.CommandTool{ID: ct.ID, Description: ct.Description, Params: ct.Params, Risk: ct.Risk}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (a busAdapter) DispatchCommand(ctx context.Context, req runmgr.CommandRequest) runmgr.CommandResponse {
|
||||
resp := a.bus.Dispatch(ctx, cmdbus.Request{
|
||||
ID: req.ID, Params: req.Params, Entrance: req.Entrance,
|
||||
Actor: req.Actor, Owner: req.Owner, ConversationID: req.ConversationID,
|
||||
})
|
||||
return runmgr.CommandResponse{
|
||||
State: string(resp.Receipt.State), Reason: resp.Receipt.Reason,
|
||||
Payload: resp.Payload, Card: resp.Card != nil,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,26 +8,21 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
agentcommand "agent-command"
|
||||
"agent-system-backend/internal/cmdbus"
|
||||
"agent-system-backend/internal/tools"
|
||||
core "agent-system-core"
|
||||
)
|
||||
|
||||
func agentcommandCommitted() agentcommand.ExecReceipt {
|
||||
return agentcommand.ExecReceipt{State: agentcommand.StateCommitted}
|
||||
}
|
||||
|
||||
// fakeBusSource EXT-14 测试桩:命令清单 + 分发记录。
|
||||
// fakeBusSource EXT-14 测试桩:命令清单 + 分发记录(说话用 runmgr 视图类型,
|
||||
// 与生产代码同口径——runmgr 不依赖 cmdbus)。
|
||||
type fakeBusSource struct {
|
||||
cmds []cmdbus.CommandTool
|
||||
lastReq cmdbus.Request
|
||||
resp cmdbus.Response
|
||||
cmds []CommandTool
|
||||
lastReq CommandRequest
|
||||
resp CommandResponse
|
||||
}
|
||||
|
||||
func (f *fakeBusSource) CommandTools() []cmdbus.CommandTool { return f.cmds }
|
||||
func (f *fakeBusSource) CommandTools() []CommandTool { return f.cmds }
|
||||
|
||||
func (f *fakeBusSource) DispatchCommand(ctx context.Context, req cmdbus.Request) cmdbus.Response {
|
||||
func (f *fakeBusSource) DispatchCommand(ctx context.Context, req CommandRequest) CommandResponse {
|
||||
f.lastReq = req
|
||||
return f.resp
|
||||
}
|
||||
@@ -35,8 +30,8 @@ func (f *fakeBusSource) DispatchCommand(ctx context.Context, req cmdbus.Request)
|
||||
func TestCommandToolsProjected(t *testing.T) {
|
||||
rc0, _ := newExecEnv(t)
|
||||
m := rc0.mgr
|
||||
src := &fakeBusSource{cmds: []cmdbus.CommandTool{
|
||||
{ID: "rdm.trace", Title: "追溯查询", Description: "查追溯网", Params: []byte(`{"type":"object"}`), Risk: "low"},
|
||||
src := &fakeBusSource{cmds: []CommandTool{
|
||||
{ID: "rdm.trace", Description: "查追溯网", Params: []byte(`{"type":"object"}`), Risk: "low"},
|
||||
}}
|
||||
m.SetCommandSource(src)
|
||||
rc := rc0
|
||||
@@ -57,8 +52,8 @@ func TestCommandToolDispatchesThroughBus(t *testing.T) {
|
||||
rc0, _ := newExecEnv(t)
|
||||
m := rc0.mgr
|
||||
src := &fakeBusSource{
|
||||
cmds: []cmdbus.CommandTool{{ID: "rdm.trace", Title: "追溯查询", Params: []byte(`{"type":"object"}`), Risk: "low"}},
|
||||
resp: cmdbus.Response{Receipt: agentcommandCommitted()},
|
||||
cmds: []CommandTool{{ID: "rdm.trace", Params: []byte(`{"type":"object"}`), Risk: "low"}},
|
||||
resp: CommandResponse{State: "committed"},
|
||||
}
|
||||
m.SetCommandSource(src)
|
||||
rc := rc0
|
||||
|
||||
+36
-10
@@ -24,7 +24,6 @@ import (
|
||||
|
||||
"agent-system-backend/internal/bus"
|
||||
"agent-system-backend/internal/cardsvc"
|
||||
"agent-system-backend/internal/cmdbus"
|
||||
"agent-system-backend/internal/ingest"
|
||||
"agent-system-backend/internal/intentgate"
|
||||
"agent-system-backend/internal/profiles"
|
||||
@@ -177,10 +176,38 @@ func (m *Manager) SetIndexer(i core.DocumentIndexer) { m.indexer = i }
|
||||
func (m *Manager) SetWorkspaceRoot(dir string) { m.workspaceRoot = dir }
|
||||
|
||||
// CommandSource EXT-14:命令总线暴露给回合执行的两个面——工具投影清单与
|
||||
// 经命令总的分发(同审计信封与 HITL 收口)。组合根以 cmdbus.Bus 适配注入。
|
||||
// 经命令总的分发(同审计信封与 HITL 收口)。runmgr 只认本包视图类型,
|
||||
// 组合根以 cmdbus.Bus 适配注入(app.busAdapter 负责转换),runmgr 不依赖总线包。
|
||||
type CommandSource interface {
|
||||
CommandTools() []cmdbus.CommandTool
|
||||
DispatchCommand(ctx context.Context, req cmdbus.Request) cmdbus.Response
|
||||
CommandTools() []CommandTool
|
||||
DispatchCommand(ctx context.Context, req CommandRequest) CommandResponse
|
||||
}
|
||||
|
||||
// CommandTool EXT-14 工具投影视图:组合根从命令总线的投影清单转换注入。
|
||||
type CommandTool struct {
|
||||
ID string
|
||||
Description string
|
||||
Params json.RawMessage
|
||||
Risk string
|
||||
}
|
||||
|
||||
// CommandRequest 一次命令工具分发请求(runmgr 固定以 Entrance=agent 发起,
|
||||
// Actor/Owner 绑定会话 owner、带会话上下文)。
|
||||
type CommandRequest struct {
|
||||
ID string
|
||||
Params map[string]any
|
||||
Entrance string
|
||||
Actor string
|
||||
Owner string
|
||||
ConversationID string
|
||||
}
|
||||
|
||||
// CommandResponse 分发结果视图:回执状态/原因 + 负载 + 是否挂起确认卡。
|
||||
type CommandResponse struct {
|
||||
State string
|
||||
Reason string
|
||||
Payload any
|
||||
Card bool
|
||||
}
|
||||
|
||||
// sharedRetriever EXT-13:检索器具备共享通道(rag.Pipeline.RetrieveShared 同形)。
|
||||
@@ -824,19 +851,18 @@ func (c *runCtx) ExecuteTool(call core.ToolCallRequest) core.ToolCallResult {
|
||||
if len(call.Arguments) > 0 {
|
||||
_ = json.Unmarshal(call.Arguments, ¶ms)
|
||||
}
|
||||
resp := c.mgr.commands.DispatchCommand(c.ctx, cmdbus.Request{
|
||||
resp := c.mgr.commands.DispatchCommand(c.ctx, CommandRequest{
|
||||
ID: call.Name, Params: params, Entrance: "agent",
|
||||
Actor: c.run.Owner, Owner: c.run.Owner, ConversationID: c.run.ConversationID,
|
||||
})
|
||||
out, _ := json.Marshal(resp.Payload)
|
||||
state := string(resp.Receipt.State)
|
||||
if resp.Card != nil && state == "accepted" {
|
||||
if resp.Card && resp.State == "accepted" {
|
||||
return core.ToolCallResult{CallID: call.CallID, Status: "ok",
|
||||
Output: "已创建确认卡,等待用户确认后执行:" + resp.Receipt.Reason}
|
||||
Output: "已创建确认卡,等待用户确认后执行:" + resp.Reason}
|
||||
}
|
||||
if state != "committed" && state != "accepted" {
|
||||
if resp.State != "committed" && resp.State != "accepted" {
|
||||
return core.ToolCallResult{CallID: call.CallID, Status: "error",
|
||||
Output: "命令 " + call.Name + " " + state + ": " + resp.Receipt.Reason}
|
||||
Output: "命令 " + call.Name + " " + resp.State + ": " + resp.Reason}
|
||||
}
|
||||
return core.ToolCallResult{CallID: call.CallID, Status: "ok", Output: string(out)}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user