package runtime import ( "context" "os" "path/filepath" "strings" "testing" agentllm "agent-native/runtime/llm" core "agent-system-core" ) // 裁定 1:会话沙箱配置时,内核工作区工具(read/edit/multi_edit/grep/glob/list) // 进入直连工具面;计划模式只留只读子集。 func TestDirectRunExposesKernelWorkspaceTools(t *testing.T) { sandbox := t.TempDir() if err := os.WriteFile(filepath.Join(sandbox, "note.txt"), []byte("alpha\nbeta\n"), 0o644); err != nil { t.Fatal(err) } rc := &fakeRunCtx{ ctx: context.Background(), sandbox: sandbox, prof: core.AgentProfile{Model: core.ModelRoute{Chat: "test-model"}}, } // 第一步 read_file(行号分页),第二步 edit_file(须先读过),第三步 grep。 turns := padTurns( textDeltaTurn("", toolCall("read_file", `{"path":"note.txt"}`)), textDeltaTurn("", toolCall("edit_file", `{"path":"note.txt","old":"alpha","new":"gamma"}`)), textDeltaTurn("", toolCall("grep", `{"pattern":"gamma"}`)), textDeltaTurn("改完了。"), ) r := &LLMRunner{Stream: scriptStream(turns, nil)} if err := r.Execute(rc); err != nil { t.Fatalf("Execute: %v", err) } raw, err := os.ReadFile(filepath.Join(sandbox, "note.txt")) if err != nil { t.Fatal(err) } if !strings.Contains(string(raw), "gamma") || strings.Contains(string(raw), "alpha") { t.Fatalf("edit_file did not apply: %q", string(raw)) } found := 0 for _, p := range rc.assistant { if p.ToolResult != nil && p.ToolResult.Summary != "" { found++ } } if found < 3 { t.Fatalf("workspace tool results missing from assistant parts: %+v", rc.assistant) } } // 无沙箱(未配置工作区)时内核工具不注册,模型看不到。 func TestDirectRunWithoutSandboxHidesKernelTools(t *testing.T) { rc := &fakeRunCtx{ ctx: context.Background(), prof: core.AgentProfile{Model: core.ModelRoute{Chat: "test-model"}}, } r := &LLMRunner{Stream: scriptStream(textTurns("你好。"), nil)} if err := r.Execute(rc); err != nil { t.Fatalf("Execute: %v", err) } for _, p := range rc.assistant { if p.ToolCall != nil && p.ToolCall.Name == "read_file" { t.Fatalf("read_file must not be visible without a sandbox") } } } var _ = agentllm.RoleUser