package tools import ( "context" "encoding/json" "fmt" "strings" "time" "agent-native/runtime/codeorch" core "agent-system-core" ) // RegisterCodeTool 注册 run_tool_script。开关关闭时执行会被拒绝,清单侧另行隐藏。 func RegisterCodeTool(r *Registry) error { return r.Register(core.ToolDesc{ Name: "run_tool_script", Description: "用一段 Python 依次调用已有工具。禁止再调用解释器、本工具、派发和工作流。失败时会列出已经执行的调用", Source: core.SourceBuiltin, Risk: "medium", Parameters: json.RawMessage(`{"type":"object","properties":{"script":{"type":"string"},"timeout_sec":{"type":"integer"}},"required":["script"]}`), }, execCodeScript) } type toolCaller interface { ExecuteTool(call core.ToolCallRequest) core.ToolCallResult } func execCodeScript(rc ToolExecCtx, args json.RawMessage) (string, error) { if !rc.SettingBool("runtime.codeOrchestration", false) { return "", fmt.Errorf("代码编排未开启") } caller, ok := rc.(toolCaller) if !ok { return "", fmt.Errorf("代码编排未接入工具执行") } var req struct { Script string `json:"script"` Timeout int `json:"timeout_sec"` } if err := json.Unmarshal(args, &req); err != nil { return "", err } if strings.TrimSpace(req.Script) == "" { return "", fmt.Errorf("script 不能为空") } root := "" if s, ok := rc.(interface{ ConversationSandbox() string }); ok { root = s.ConversationSandbox() } if root == "" { root = rc.WorkspaceRoot() } if root == "" { return "", fmt.Errorf("代码编排没有会话目录") } lim := codeorch.Limits{FullDir: root} if req.Timeout > 0 { lim.Timeout = time.Duration(req.Timeout) * time.Second } out := codeorch.Run(context.Background(), root, req.Script, lim, nil, func(_ context.Context, call codeorch.Call) (string, error) { if call.Op != "tool.call" { return "", fmt.Errorf("不能调用 %s", call.Op) } if codeorch.Forbidden(call.Name) { return "", fmt.Errorf("不能调用 %s", call.Name) } res := caller.ExecuteTool(core.ToolCallRequest{Name: call.Name, Arguments: call.Args}) if res.Status == "error" { return "", fmt.Errorf("%s", res.Output) } return res.Output, nil }) if out.Err != nil { return out.ModelText(), fmt.Errorf("%s", out.ModelText()) } return out.ModelText(), nil }