Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
97 lines
4.2 KiB
Go
97 lines
4.2 KiB
Go
package agentstatus
|
|
|
|
import (
|
|
"context"
|
|
"path/filepath"
|
|
"runtime"
|
|
"testing"
|
|
)
|
|
|
|
func TestValidateCodexRuntimeCandidatesImplicitlyUsesOnlyReadyCandidate(t *testing.T) {
|
|
home := t.TempDir()
|
|
broken := filepath.Join(home, "broken", "codex")
|
|
healthy := filepath.Join(home, "healthy", "codex")
|
|
broken = writeCodexVersionFixture(t, broken, "0.142.0")
|
|
healthy = writeCodexVersionFixture(t, healthy, "0.142.0")
|
|
|
|
service := probeTestService(home)
|
|
service.CodexProtocolProbe = func(_ context.Context, command, _ []string) CodexProbeEvidence {
|
|
if command[0] == broken {
|
|
return CodexProbeEvidence{CommandStarted: true, Category: "app_server_unsupported"}
|
|
}
|
|
return CodexProbeEvidence{CommandStarted: true, ProtocolReady: true}
|
|
}
|
|
validations := service.validateCodexRuntimeCandidates(context.Background(), ProviderSpec{
|
|
Provider: "codex",
|
|
MinVersion: MinSupportedCodexVersion,
|
|
}, []codexRuntimeCandidate{{LauncherPath: broken}, {LauncherPath: healthy}})
|
|
|
|
if got := validations[0].State; got != codexRuntimeCandidateValidationFailed {
|
|
t.Fatalf("broken candidate state = %q, want failed", got)
|
|
}
|
|
if got := validations[1].State; got != codexRuntimeCandidateValidationReady {
|
|
t.Fatalf("healthy candidate state = %q, want ready", got)
|
|
}
|
|
selection := decideCodexRuntimeImplicitSelection(validations)
|
|
if selection.CandidateIndex != 1 || !selection.Launchable || selection.State != CodexRuntimeSelectionImplicitUnique {
|
|
t.Fatalf("selection = %#v, want healthy second candidate", selection)
|
|
}
|
|
}
|
|
|
|
func TestValidateCodexRuntimeCandidatesSkipsUnsupportedCandidate(t *testing.T) {
|
|
home := t.TempDir()
|
|
old := filepath.Join(home, "old", "codex")
|
|
current := filepath.Join(home, "current", "codex")
|
|
old = writeCodexVersionFixture(t, old, "0.125.0")
|
|
current = writeCodexVersionFixture(t, current, "0.142.0")
|
|
|
|
service := probeTestService(home)
|
|
service.CodexProtocolProbe = codexProtocolReadyFixture
|
|
validations := service.validateCodexRuntimeCandidates(context.Background(), ProviderSpec{
|
|
Provider: "codex",
|
|
MinVersion: MinSupportedCodexVersion,
|
|
}, []codexRuntimeCandidate{{LauncherPath: old}, {LauncherPath: current}})
|
|
|
|
if got := validations[0].State; got != codexRuntimeCandidateValidationUnsupported {
|
|
t.Fatalf("old candidate state = %q, want unsupported", got)
|
|
}
|
|
if got := validations[1].State; got != codexRuntimeCandidateValidationReady {
|
|
t.Fatalf("current candidate state = %q, want ready", got)
|
|
}
|
|
if selection := decideCodexRuntimeImplicitSelection(validations); selection.CandidateIndex != 1 || !selection.Launchable || selection.State != CodexRuntimeSelectionImplicitUnique {
|
|
t.Fatalf("selection = %#v, want current candidate", selection)
|
|
}
|
|
}
|
|
|
|
func TestDecideCodexRuntimeImplicitSelectionRetainsFirstCandidateForDiagnosticsWhenNoneReady(t *testing.T) {
|
|
selection := decideCodexRuntimeImplicitSelection([]codexRuntimeCandidateValidation{
|
|
{State: codexRuntimeCandidateValidationFailed},
|
|
{State: codexRuntimeCandidateValidationUnsupported},
|
|
})
|
|
if selection.CandidateIndex != 0 || selection.Launchable || selection.ReasonCode != "no_ready_candidate" || selection.State != CodexRuntimeSelectionUnavailable {
|
|
t.Fatalf("selection = %#v, want first diagnostic candidate without launch permission", selection)
|
|
}
|
|
}
|
|
|
|
func TestDecideCodexRuntimeImplicitSelectionRequiresAUserChoiceForMultipleReadyCandidates(t *testing.T) {
|
|
selection := decideCodexRuntimeImplicitSelection([]codexRuntimeCandidateValidation{
|
|
{State: codexRuntimeCandidateValidationReady},
|
|
{State: codexRuntimeCandidateValidationReady},
|
|
{State: codexRuntimeCandidateValidationFailed},
|
|
})
|
|
if selection.CandidateIndex != -1 || selection.Launchable || selection.ReasonCode != "codex_runtime_selection_required" || selection.State != CodexRuntimeSelectionSelectionRequired {
|
|
t.Fatalf("selection = %#v, want a blocked multi-runtime selection", selection)
|
|
}
|
|
}
|
|
|
|
func writeCodexVersionFixture(t *testing.T, path string, version string) string {
|
|
t.Helper()
|
|
contents := "#!/bin/sh\nif [ \"$1\" = \"--version\" ]; then echo 'codex " + version + "'; exit 0; fi\nexit 0\n"
|
|
if runtime.GOOS == "windows" {
|
|
path += ".cmd"
|
|
contents = "@echo off\r\nif \"%~1\"==\"--version\" (\r\n echo codex " + version + "\r\n exit /b 0\r\n)\r\nexit /b 0\r\n"
|
|
}
|
|
writeExecutable(t, path, contents)
|
|
return path
|
|
}
|