package oneshot_test import ( "context" "strings" "testing" "time" "go.uber.org/zap" clipkg "iop/apps/node/internal/adapters/cli" "iop/apps/node/internal/adapters/cli/internal/testutil" noderuntime "iop/apps/node/internal/runtime" "iop/packages/config" ) func TestCLIExecuteOneShotPassesPromptAsArg(t *testing.T) { testutil.RequireUnixShell(t) cfg := config.CLIConf{ Enabled: true, Profiles: map[string]config.CLIProfileConf{ "echo": { Command: "sh", Args: []string{"-c", `printf "reply:%s\n" "$1"`, "sh"}, }, }, } c := clipkg.New(cfg, zap.NewNop()) sink := &testutil.FakeSink{} err := c.Execute(context.Background(), noderuntime.ExecutionSpec{ RunID: "run-1", Model: "echo", Input: map[string]any{"prompt": "hello"}, }, sink) if err != nil { t.Fatalf("execute: %v", err) } events := sink.Events() var types []string for _, e := range events { types = append(types, string(e.Type)) } if len(events) < 3 { t.Fatalf("expected at least 3 events (start/delta/complete), got %v", types) } if events[0].Type != noderuntime.EventTypeStart { t.Fatalf("first event should be start, got %q", events[0].Type) } if events[len(events)-1].Type != noderuntime.EventTypeComplete { t.Fatalf("last event should be complete, got %q", events[len(events)-1].Type) } if combined := testutil.CollectDeltas(events); !strings.Contains(combined, "reply:hello") { t.Fatalf("expected reply:hello in deltas, got %q", combined) } } func TestCLIExecuteOneShotDrainsStderrConcurrently(t *testing.T) { testutil.RequireUnixShell(t) cfg := config.CLIConf{ Enabled: true, Profiles: map[string]config.CLIProfileConf{ "noisy": { Command: "sh", Args: []string{ "-c", `i=0; while [ "$i" -lt 20000 ]; do echo "warning line $i" >&2; i=$((i+1)); done; printf "reply:%s\n" "$1"`, "sh", }, }, }, } c := clipkg.New(cfg, zap.NewNop()) sink := &testutil.FakeSink{} ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() err := c.Execute(ctx, noderuntime.ExecutionSpec{ RunID: "run-noisy", Model: "noisy", Input: map[string]any{"prompt": "hello"}, }, sink) if err != nil { t.Fatalf("execute: %v", err) } if combined := testutil.CollectDeltas(sink.Events()); !strings.Contains(combined, "reply:hello") { t.Fatalf("expected reply:hello in deltas, got %q", combined) } }