Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/daemon/internal/agent/claudesdk/cancellation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ func cancellationConfig(root, mode string) Config {
}

func cancellationRequest() proto.PromptRequestPayload {
return proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("hello"), AgentSessionID: "native-session", AgentOptions: map[string]any{"model": "fake-model", "system_prompt": "instructions"}}
return proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("hello"), AgentSessionID: "native-session", Turn: proto.TurnSettings{Model: "fake-model"}, AgentOptions: map[string]any{"system_prompt": "instructions"}}
}

func runCancellationHelper(request startRequest, mode string, scanner *bufio.Scanner, emit func(bridgeEvent)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func TestWorkspaceCommandFramesKeepStartIdentityAndObservedOutput(t *testing.T)
t.Fatal("preparation submitted a command")
}
out := make(chan proto.Envelope, 16)
s, err := resource.StartTurn(t.Context(), "actual-command-run", proto.TextInput("hello"), out)
s, err := resource.StartTurn(t.Context(), "actual-command-run", proto.TurnSettings{}, proto.TextInput("hello"), out)
if err != nil {
t.Fatal(err)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func TestClassifiedBridgeFailurePreservesTerminalEvidence(t *testing.T) {
root := t.TempDir()
t.Setenv("OAC_RUNTIME_HOME", root)
config := Config{Node: os.Args[0], Entrypoint: filepath.Join(root, "worker"), StateDir: filepath.Join(root, "state"), Env: []string{"GO_CLAUDE_SDK_HELPER=1", "SDK_HELPER_MODE=classified-" + mode, "GORACE=atexit_sleep_ms=0"}}
req := proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("hello"), AgentSessionID: "native-session", AgentOptions: map[string]any{"model": "fake-model", "system_prompt": "instructions"}}
req := proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("hello"), AgentSessionID: "native-session", Turn: proto.TurnSettings{Model: "fake-model"}, AgentOptions: map[string]any{"system_prompt": "instructions"}}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
out := make(chan proto.Envelope, 16)
Expand Down
39 changes: 20 additions & 19 deletions apps/daemon/internal/agent/claudesdk/execution_controls_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func TestExecutionControlsPreserveNativeDefaultsAndInstructions(t *testing.T) {
root := t.TempDir()
t.Setenv("OAC_RUNTIME_HOME", root)
config := Config{Entrypoint: filepath.Join(root, "worker"), StateDir: filepath.Join(root, "state")}
request := proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("Original input."), AgentSessionID: "native-session", AgentOptions: map[string]any{"model": "native-model", "system_prompt": "Keep these exact instructions.\nDo not replace them."}}
request := proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("Original input."), AgentSessionID: "native-session", Turn: proto.TurnSettings{Model: "native-model"}, AgentOptions: map[string]any{"system_prompt": "Keep these exact instructions.\nDo not replace them."}}
ordinary, _, err := prepareConfiguration(config, request)
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -49,7 +49,7 @@ func TestLiveWebSearchReachesTheBridgeOnEveryPlacement(t *testing.T) {
root := t.TempDir()
t.Setenv("OAC_RUNTIME_HOME", root)
none, _, err := prepareConfiguration(Config{Entrypoint: filepath.Join(root, "worker"), StateDir: filepath.Join(root, "state")}, proto.PromptRequestPayload{
RunID: "run", Input: proto.TextInput("Search."), ExecutionControls: live, AgentOptions: map[string]any{"model": "native-model"}})
RunID: "run", Input: proto.TextInput("Search."), ExecutionControls: live, Turn: proto.TurnSettings{Model: "native-model"}, AgentOptions: map[string]any{}})
if err != nil || none.WebSearch != "live" {
t.Fatal("live search on environment none did not reach the bridge", err)
}
Expand All @@ -63,23 +63,24 @@ func TestLiveWebSearchReachesTheBridgeOnEveryPlacement(t *testing.T) {

func TestExecutionControlsRejectUnsupportedProfilesBeforeLaunch(t *testing.T) {
enabled := true
cases := map[string]proto.ExecutionControls{
"cached-search": {WebSearch: &proto.WebSearchControl{Mode: "cached", ContextSize: "medium"}},
"enabled-ptc": {ProgrammaticToolCalling: &enabled},
"low-verbosity": {TextVerbosity: "low"},
"high-verbosity": {TextVerbosity: "high"},
"unknown-verbosity": {TextVerbosity: "invalid"},
"no-effort": {ReasoningEffort: "none"},
"minimal-effort": {ReasoningEffort: "minimal"},
"summary": {ReasoningSummary: "concise"},
"service-tier": {ServiceTier: "priority"},
}
for name, controls := range cases {
model := proto.TurnSettings{Model: "native-model"}
cases := map[string]proto.PromptRequestPayload{
"cached-search": {Turn: model, ExecutionControls: &proto.ExecutionControls{WebSearch: &proto.WebSearchControl{Mode: "cached", ContextSize: "medium"}}},
"enabled-ptc": {Turn: model, ExecutionControls: &proto.ExecutionControls{ProgrammaticToolCalling: &enabled}},
"low-verbosity": {Turn: model, ExecutionControls: &proto.ExecutionControls{TextVerbosity: "low"}},
"high-verbosity": {Turn: model, ExecutionControls: &proto.ExecutionControls{TextVerbosity: "high"}},
"unknown-verbosity": {Turn: model, ExecutionControls: &proto.ExecutionControls{TextVerbosity: "invalid"}},
"summary": {Turn: model, ExecutionControls: &proto.ExecutionControls{ReasoningSummary: "concise"}},
"no-effort": {Turn: proto.TurnSettings{Model: "native-model", ReasoningEffort: "none"}},
"minimal-effort": {Turn: proto.TurnSettings{Model: "native-model", ReasoningEffort: "minimal"}},
"service-tier": {Turn: proto.TurnSettings{Model: "native-model", ServiceTier: "priority"}},
}
for name, request := range cases {
t.Run(name, func(t *testing.T) {
root := t.TempDir()
t.Setenv("OAC_RUNTIME_HOME", root)
config := Config{Node: "must-not-run", Entrypoint: filepath.Join(root, "worker"), StateDir: filepath.Join(root, "state")}
request := proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("Original input."), ExecutionControls: &controls, AgentOptions: map[string]any{"model": "native-model"}}
request.RunID, request.Input = "run", proto.TextInput("Original input.")
_, err := startSingleTurn(t.Context(), config, request, make(chan proto.Envelope, 1))
if err == nil || !strings.Contains(err.Error(), "not supported by this Harness") {
t.Fatal("unsupported controls did not fail at admission", err)
Expand All @@ -96,7 +97,7 @@ func TestReasoningEffortReachesNativeOptions(t *testing.T) {
t.Setenv("OAC_RUNTIME_HOME", root)
config := Config{Entrypoint: filepath.Join(root, "worker"), StateDir: filepath.Join(root, "state")}
for _, effort := range []string{"low", "medium", "high", "xhigh", "max"} {
request := proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("hello"), ExecutionControls: &proto.ExecutionControls{TextVerbosity: "medium", ReasoningEffort: effort}, AgentOptions: map[string]any{"model": "native-model", "harness_config": map[string]any{"thinking": map[string]any{"type": "adaptive"}}}}
request := proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("hello"), ExecutionControls: &proto.ExecutionControls{TextVerbosity: "medium"}, Turn: proto.TurnSettings{Model: "native-model", ReasoningEffort: effort}, AgentOptions: map[string]any{"harness_config": map[string]any{"thinking": map[string]any{"type": "adaptive"}}}}
start, _, err := prepareConfiguration(config, request)
if err != nil {
t.Fatal(effort, err)
Expand Down Expand Up @@ -127,7 +128,7 @@ func TestStructuredOutputConfigurationReachesNativeUnchanged(t *testing.T) {
t.Setenv("OAC_RUNTIME_HOME", root)
config := Config{Entrypoint: filepath.Join(root, "worker"), StateDir: filepath.Join(root, "state")}
schema := json.RawMessage(`{"type":"object","properties":{"n":{"const":9007199254740992}}}`)
request := proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("Original input."), DisableSubagents: true, AgentOptions: map[string]any{"model": "model", "system_prompt": "Original instructions."}, ExecutionControls: &proto.ExecutionControls{TextVerbosity: "medium", OutputFormat: &proto.OutputFormat{Type: "json_schema", Schema: schema}}}
request := proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("Original input."), DisableSubagents: true, Turn: proto.TurnSettings{Model: "model"}, AgentOptions: map[string]any{"system_prompt": "Original instructions."}, ExecutionControls: &proto.ExecutionControls{TextVerbosity: "medium", OutputFormat: &proto.OutputFormat{Type: "json_schema", Schema: schema}}}
start, _, err := prepareConfiguration(config, request)
if err != nil {
t.Fatal(err)
Expand All @@ -151,7 +152,7 @@ func TestToolDiscoveryPreservesFrozenFunctionsBesideOtherProfiles(t *testing.T)
root := t.TempDir()
t.Setenv("OAC_RUNTIME_HOME", root)
config := Config{Entrypoint: filepath.Join(root, "worker"), StateDir: filepath.Join(root, "state")}
request := proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("Original input."), DisableSubagents: true, ToolSearch: true, AgentOptions: map[string]any{"model": "model"}, FunctionTools: []proto.FunctionTool{
request := proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("Original input."), DisableSubagents: true, ToolSearch: true, Turn: proto.TurnSettings{Model: "model"}, AgentOptions: map[string]any{}, FunctionTools: []proto.FunctionTool{
{Name: "lookup", Description: "Lookup", Parameters: json.RawMessage(`{"type":"object","properties":{"ticket":{"const":"original"}}}`), DeferLoading: true},
{Name: "clock", Description: "Clock", Parameters: json.RawMessage(`{"type":"object"}`)},
}}
Expand All @@ -174,7 +175,7 @@ func TestReasoningSummaryReachesTheBridgeOnlyWhenRequested(t *testing.T) {
root := t.TempDir()
t.Setenv("OAC_RUNTIME_HOME", root)
config := Config{Entrypoint: filepath.Join(root, "worker"), StateDir: filepath.Join(root, "state")}
request := proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("Input."), AgentOptions: map[string]any{"model": "native-model"}}
request := proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("Input."), Turn: proto.TurnSettings{Model: "native-model"}, AgentOptions: map[string]any{}}
for _, summary := range []string{"", "auto"} {
request.ExecutionControls = &proto.ExecutionControls{TextVerbosity: "medium", ReasoningSummary: summary}
start, _, err := prepareConfiguration(config, request)
Expand Down
2 changes: 1 addition & 1 deletion apps/daemon/internal/agent/claudesdk/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ func (e *executor) read() {
close(e.done)
}

func (e *executor) StartTurn(ctx context.Context, run string, input proto.MessageInput, out chan<- proto.Envelope) (agent.Turn, error) {
func (e *executor) StartTurn(ctx context.Context, run string, _ proto.TurnSettings, input proto.MessageInput, out chan<- proto.Envelope) (agent.Turn, error) {
if ctx == nil {
ctx = context.Background()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func startSingleTurn(ctx context.Context, config Config, req proto.PromptRequest
if err != nil {
return nil, err
}
turn, err := resource.StartTurn(ctx, run, input, out)
turn, err := resource.StartTurn(ctx, run, proto.TurnSettings{}, input, out)
if turn == nil {
_ = resource.Close(context.Background())
return nil, err
Expand Down
10 changes: 5 additions & 5 deletions apps/daemon/internal/agent/claudesdk/executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func persistentConfig(t *testing.T, mode string) (Config, proto.PromptRequestPay
if err := os.WriteFile(entry, []byte("version-one"), 0600); err != nil {
t.Fatal(err)
}
return Config{Node: os.Args[0], Entrypoint: entry, StateDir: filepath.Join(root, "state"), Env: []string{"GO_CLAUDE_EXECUTOR_HELPER=1", "SDK_EXECUTOR_DIR=" + root, "SDK_EXECUTOR_MODE=" + mode, "GORACE=atexit_sleep_ms=0"}}, proto.PromptRequestPayload{DisableExecutionEnvironment: true, AgentOptions: map[string]any{"model": "fixture"}}
return Config{Node: os.Args[0], Entrypoint: entry, StateDir: filepath.Join(root, "state"), Env: []string{"GO_CLAUDE_EXECUTOR_HELPER=1", "SDK_EXECUTOR_DIR=" + root, "SDK_EXECUTOR_MODE=" + mode, "GORACE=atexit_sleep_ms=0"}}, proto.PromptRequestPayload{DisableExecutionEnvironment: true, Turn: proto.TurnSettings{Model: "fixture"}, AgentOptions: map[string]any{}}
}

func runPersistentExecutorHelper() {
Expand Down Expand Up @@ -135,7 +135,7 @@ func runPersistentExecutorHelper() {
func consumeExecutorTurn(t *testing.T, owner agent.Executor, id, input string) (agent.Turn, <-chan proto.Envelope) {
t.Helper()
out := make(chan proto.Envelope, 16)
turn, err := owner.StartTurn(t.Context(), id, proto.TextInput(input), out)
turn, err := owner.StartTurn(t.Context(), id, proto.TurnSettings{}, proto.TextInput(input), out)
if err != nil || turn == nil {
t.Fatalf("StartTurn: %v", err)
}
Expand Down Expand Up @@ -215,7 +215,7 @@ func TestExecutorLateTurnEventInvalidatesWithoutRetargeting(t *testing.T) {
t.Fatal("unknown native outcome marked settled")
}
next := make(chan proto.Envelope, 1)
if turn, err := owner.StartTurn(t.Context(), "third", proto.TextInput("hello"), next); turn != nil || err == nil {
if turn, err := owner.StartTurn(t.Context(), "third", proto.TurnSettings{}, proto.TextInput("hello"), next); turn != nil || err == nil {
t.Fatal("invalid executor accepted input")
}
}
Expand Down Expand Up @@ -262,7 +262,7 @@ func TestExecutorSeparatesPreInputRejectionFromUnknownWrite(t *testing.T) {
rejected := make(chan proto.Envelope, 1)
cancelled, stop := context.WithCancel(t.Context())
stop()
if turn, err := owner.StartTurn(cancelled, "not-written", proto.TextInput("hello"), rejected); turn != nil || err == nil {
if turn, err := owner.StartTurn(cancelled, "not-written", proto.TurnSettings{}, proto.TextInput("hello"), rejected); turn != nil || err == nil {
t.Fatal("cancelled admission reached native input")
}
select {
Expand All @@ -275,7 +275,7 @@ func TestExecutorSeparatesPreInputRejectionFromUnknownWrite(t *testing.T) {
t.Fatal(err)
}
out := make(chan proto.Envelope, 8)
turn, err := owner.StartTurn(t.Context(), "unknown-write", proto.TextInput("hello"), out)
turn, err := owner.StartTurn(t.Context(), "unknown-write", proto.TurnSettings{}, proto.TextInput("hello"), out)
if turn == nil || err == nil {
t.Fatalf("attempted write must preserve unknown Turn ownership: %T %v", turn, err)
}
Expand Down
2 changes: 1 addition & 1 deletion apps/daemon/internal/agent/claudesdk/functions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func TestFunctionFactoryNativeReceipts(t *testing.T) {
root := t.TempDir()
t.Setenv("OAC_RUNTIME_HOME", root)
config := Config{Node: os.Args[0], Entrypoint: filepath.Join(root, "worker"), StateDir: filepath.Join(root, "state"), Env: []string{"GO_CLAUDE_SDK_HELPER=1", "SDK_HELPER_MODE=" + mode, "GORACE=atexit_sleep_ms=0"}}
request := proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("hello"), AgentSessionID: "native-session", AgentOptions: map[string]any{"model": "fake-model", "system_prompt": "instructions"}, FunctionTools: []proto.FunctionTool{{Name: "lookup", Description: "Lookup.", Parameters: json.RawMessage(`{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string"}}}}`)}}}
request := proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("hello"), AgentSessionID: "native-session", Turn: proto.TurnSettings{Model: "fake-model"}, AgentOptions: map[string]any{"system_prompt": "instructions"}, FunctionTools: []proto.FunctionTool{{Name: "lookup", Description: "Lookup.", Parameters: json.RawMessage(`{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string"}}}}`)}}}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
out := make(chan proto.Envelope, 16)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func TestHarnessConfigReachesBridgeAndOwnsSnapshot(t *testing.T) {
t.Setenv("OAC_RUNTIME_HOME", root)
config := Config{Entrypoint: filepath.Join(root, "main.js"), StateDir: filepath.Join(root, "state")}
native := map[string]any{"thinking": map[string]any{"type": "enabled", "budgetTokens": 1024}}
req := proto.PromptRequestPayload{AgentOptions: map[string]any{"model": "fixture", "harness_config": native}, ExecutionControls: &proto.ExecutionControls{TextVerbosity: "medium", ReasoningEffort: "high"}}
req := proto.PromptRequestPayload{Turn: proto.TurnSettings{Model: "fixture", ReasoningEffort: "high"}, AgentOptions: map[string]any{"harness_config": native}, ExecutionControls: &proto.ExecutionControls{TextVerbosity: "medium"}}
start, _, err := prepareConfiguration(config, req)
if err != nil {
t.Fatal(err)
Expand Down
4 changes: 2 additions & 2 deletions apps/daemon/internal/agent/claudesdk/mcp_bearer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func TestMCPBearerUsesFreshOwnedEnvironmentReferences(t *testing.T) {
{ConnectionOrigin: "service", ServerLabel: "second", ServerURL: "https://second.example/mcp", BearerToken: &tokens[1]},
{ConnectionOrigin: "service", ServerLabel: "anonymous", ServerURL: "http://anonymous.example/mcp"},
}
req := proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("hello"), DisableExecutionEnvironment: true, MCPHTTPServers: &servers, AgentOptions: map[string]any{"model": "fixture"}}
req := proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("hello"), DisableExecutionEnvironment: true, MCPHTTPServers: &servers, Turn: proto.TurnSettings{Model: "fixture"}, AgentOptions: map[string]any{}}
seen := map[string]bool{}
for range 2 {
start, env, err := prepareConfiguration(config, req)
Expand Down Expand Up @@ -66,7 +66,7 @@ func TestMCPBearerRejectsInvalidCredentialBeforeStateCreation(t *testing.T) {
t.Setenv("OAC_RUNTIME_HOME", root)
config := Config{Entrypoint: filepath.Join(root, "main.js"), StateDir: filepath.Join(root, "state")}
servers := []proto.MCPHTTPServer{{ConnectionOrigin: "service", ServerLabel: "fixture", ServerURL: "https://example.invalid/mcp", BearerToken: &token}}
req := proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("hello"), DisableExecutionEnvironment: true, MCPHTTPServers: &servers, AgentOptions: map[string]any{"model": "fixture"}}
req := proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("hello"), DisableExecutionEnvironment: true, MCPHTTPServers: &servers, Turn: proto.TurnSettings{Model: "fixture"}, AgentOptions: map[string]any{}}
if _, _, err := prepareConfiguration(config, req); err == nil || err.Error() != "claudesdk: unsupported HTTPS MCP bearer credential" {
t.Fatal("invalid bearer accepted or unsafe error returned")
}
Expand Down
2 changes: 1 addition & 1 deletion apps/daemon/internal/agent/claudesdk/mcp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func TestHTTPMCPDeclaration(t *testing.T) {
t.Setenv("OAC_RUNTIME_HOME", root)
config := Config{Entrypoint: filepath.Join(root, "main.js"), StateDir: filepath.Join(root, "state")}
servers := []proto.MCPHTTPServer{{ConnectionOrigin: "service", ServerLabel: "fixture", ServerURL: "https://example.invalid/mcp"}}
req := proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("hello"), DisableExecutionEnvironment: true, MCPHTTPServers: &servers, AgentOptions: map[string]any{"model": "fixture"}}
req := proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("hello"), DisableExecutionEnvironment: true, MCPHTTPServers: &servers, Turn: proto.TurnSettings{Model: "fixture"}, AgentOptions: map[string]any{}}
tools := []string{"echo"}
switch mode {
case "selected":
Expand Down
2 changes: 1 addition & 1 deletion apps/daemon/internal/agent/claudesdk/messages_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func TestMessageObservations(t *testing.T) {
root := t.TempDir()
t.Setenv("OAC_RUNTIME_HOME", root)
config := Config{Node: os.Args[0], Entrypoint: filepath.Join(root, "worker"), StateDir: filepath.Join(root, "state"), Env: []string{"GO_CLAUDE_SDK_HELPER=1", "SDK_HELPER_MODE=" + mode, "GORACE=atexit_sleep_ms=0"}}
request := proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("hello"), AgentSessionID: "native-session", AgentOptions: map[string]any{"model": "fake-model", "system_prompt": "instructions"}}
request := proto.PromptRequestPayload{RunID: "run", Input: proto.TextInput("hello"), AgentSessionID: "native-session", Turn: proto.TurnSettings{Model: "fake-model"}, AgentOptions: map[string]any{"system_prompt": "instructions"}}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
out := make(chan proto.Envelope, 16)
Expand Down
Loading
Loading