Why: Allow consumers to download an immutable module revision without nested source checkouts or local path replacements. Evidence: SELF package tests and the prior canonical-path rejection are recorded in the Dev dependency-workspace task card; remote consumption is replayed against the committed candidate. Impact: Change the module identity and its Go imports while preserving API behavior. Existing historical submodule revisions remain buildable. Refs: Versioned dependencies U1/U3; feature/dependency-workspace
60 lines
1.9 KiB
Go
60 lines
1.9 KiB
Go
package tools
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"git-ssh.u1680832.nyat.app/weichen/Agent-Native.git/runtime/codeorch"
|
|
)
|
|
|
|
// RegisterCodeTool 注册 run_tool_script。调用方在开关打开时才注册。
|
|
func RegisterCodeTool(reg *Registry) {
|
|
if reg == nil {
|
|
return
|
|
}
|
|
reg.Register(&codeScriptTool{reg: reg})
|
|
}
|
|
|
|
type codeScriptTool struct{ reg *Registry }
|
|
|
|
func (t *codeScriptTool) Name() string { return "run_tool_script" }
|
|
func (t *codeScriptTool) Description() string {
|
|
return "用一段 Python 依次调用已有工具。禁止再调用解释器、本工具、派发和工作流。失败时会列出已经执行的调用"
|
|
}
|
|
func (t *codeScriptTool) Parameters() json.RawMessage {
|
|
return json.RawMessage(`{"type":"object","properties":{"script":{"type":"string"},"timeout_sec":{"type":"integer"}},"required":["script"]}`)
|
|
}
|
|
func (t *codeScriptTool) Execute(ctx context.Context, args json.RawMessage) (Result, error) {
|
|
var req struct {
|
|
Script string `json:"script"`
|
|
Timeout int `json:"timeout_sec"`
|
|
}
|
|
if err := json.Unmarshal(args, &req); err != nil {
|
|
return Result{Content: err.Error(), IsError: true}, nil
|
|
}
|
|
if strings.TrimSpace(req.Script) == "" {
|
|
return Result{Content: "script 不能为空", IsError: true}, nil
|
|
}
|
|
lim := codeorch.Limits{FullDir: t.reg.Root()}
|
|
if req.Timeout > 0 {
|
|
lim.Timeout = time.Duration(req.Timeout) * time.Second
|
|
}
|
|
out := codeorch.Run(ctx, t.reg.Root(), req.Script, lim, nil, func(ctx 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 := t.reg.Execute(ctx, call.Name, call.Args)
|
|
if res.IsError {
|
|
return "", fmt.Errorf("%s", res.Content)
|
|
}
|
|
return res.Content, nil
|
|
})
|
|
return Result{Content: out.ModelText(), IsError: out.Err != nil}, nil
|
|
}
|