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
245 lines
7.6 KiB
Go
245 lines
7.6 KiB
Go
package workspace
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
|
|
"github.com/tutti-os/tutti/packages/agent/daemon/providerregistry"
|
|
agenttargetbiz "github.com/tutti-os/tutti/services/tuttid/biz/agenttarget"
|
|
)
|
|
|
|
func TestDefaultTargetIDBackfillUsesMigratedProviderDescriptors(t *testing.T) {
|
|
descriptor, ok := providerregistry.Find(providerregistry.CodexProviderID)
|
|
if !ok {
|
|
t.Fatal("codex descriptor missing")
|
|
}
|
|
got := defaultTargetIDBackfillByProvider()
|
|
if got[descriptor.Identity.ID] != descriptor.Target.ID {
|
|
t.Fatalf("codex target backfill = %q, want %q", got[descriptor.Identity.ID], descriptor.Target.ID)
|
|
}
|
|
if got["claude-code"] != agenttargetbiz.IDLocalClaudeCode || got["cursor"] != agenttargetbiz.IDLocalCursor {
|
|
t.Fatalf("legacy target backfills = %#v", got)
|
|
}
|
|
}
|
|
|
|
func TestSQLiteStoreSeedsSystemAgentTargets(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
store := openTestSQLiteStore(t)
|
|
|
|
targets, err := store.ListAgentTargets(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("ListAgentTargets() error = %v", err)
|
|
}
|
|
descriptors := providerregistry.Migrated()
|
|
if len(targets) != len(descriptors) {
|
|
t.Fatalf("ListAgentTargets() len = %d, want descriptor count %d", len(targets), len(descriptors))
|
|
}
|
|
descriptorsByTargetID := make(map[string]providerregistry.ProviderDescriptor, len(descriptors))
|
|
for _, descriptor := range descriptors {
|
|
descriptorsByTargetID[descriptor.Target.ID] = descriptor
|
|
}
|
|
for index, target := range targets {
|
|
descriptor, ok := descriptorsByTargetID[target.ID]
|
|
if !ok || target.Provider != descriptor.Identity.ID || target.Enabled != descriptor.Target.Enabled {
|
|
t.Fatalf("target[%d] = %#v, want matching descriptor target", index, target)
|
|
}
|
|
if target.Source != agenttargetbiz.SourceSystem {
|
|
t.Fatalf("target %q source = %q, want system", target.ID, target.Source)
|
|
}
|
|
if target.IconURL == "" {
|
|
t.Fatalf("target %q icon url missing", target.ID)
|
|
}
|
|
if target.IconKey == "hermes" || target.IconKey == "openclaw" {
|
|
if target.MaskIconURL != "" {
|
|
t.Fatalf("target %q mask icon url = %q, want empty image fallback", target.ID, target.MaskIconURL)
|
|
}
|
|
} else if target.MaskIconURL == "" {
|
|
t.Fatalf("target %q mask icon url missing", target.ID)
|
|
}
|
|
if _, err := agenttargetbiz.CanonicalLaunchRefJSONString(target.Provider, target.LaunchRefJSON); err != nil {
|
|
t.Fatalf("target %q launch ref invalid: %v", target.ID, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSQLiteStoreListAgentTargetsSkipsInvalidRows(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ctx := context.Background()
|
|
store := openTestSQLiteStore(t)
|
|
now := int64(1700000000000)
|
|
if _, err := store.writeDB.ExecContext(ctx, `
|
|
INSERT INTO agent_targets (
|
|
id,
|
|
provider,
|
|
launch_ref_json,
|
|
name,
|
|
icon_key,
|
|
enabled,
|
|
source,
|
|
sort_order,
|
|
created_at_ms,
|
|
updated_at_ms
|
|
)
|
|
VALUES ('broken-target', 'codex', '{"type":"local_cli","provider":"claude-code"}', 'Broken Target', NULL, 1, 'user', 5, ?, ?);
|
|
`, now, now); err != nil {
|
|
t.Fatalf("insert invalid agent target fixture: %v", err)
|
|
}
|
|
|
|
targets, err := store.ListAgentTargets(ctx)
|
|
if err != nil {
|
|
t.Fatalf("ListAgentTargets() error = %v", err)
|
|
}
|
|
ids := make(map[string]bool, len(targets))
|
|
for _, target := range targets {
|
|
ids[target.ID] = true
|
|
}
|
|
if ids["broken-target"] {
|
|
t.Fatalf("ListAgentTargets() returned invalid target: %#v", targets)
|
|
}
|
|
if !ids[agenttargetbiz.IDLocalCodex] || !ids[agenttargetbiz.IDLocalClaudeCode] {
|
|
t.Fatalf("ListAgentTargets() ids = %#v, want system targets", ids)
|
|
}
|
|
}
|
|
|
|
func TestSQLiteStoreSeedReconcilesLegacySystemAgentTargetIDs(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ctx := context.Background()
|
|
store := openTestSQLiteStore(t)
|
|
now := int64(1700000000000)
|
|
if _, err := store.writeDB.ExecContext(ctx, `
|
|
INSERT INTO workspaces (id, name, created_at_unix_ms, updated_at_unix_ms)
|
|
VALUES ('ws-legacy-targets', 'Legacy Targets', ?, ?);
|
|
`, now, now); err != nil {
|
|
t.Fatalf("insert legacy workspace fixture: %v", err)
|
|
}
|
|
if _, err := store.writeDB.ExecContext(ctx, `
|
|
INSERT INTO agent_targets (
|
|
id,
|
|
provider,
|
|
launch_ref_json,
|
|
name,
|
|
icon_key,
|
|
enabled,
|
|
source,
|
|
sort_order,
|
|
created_at_ms,
|
|
updated_at_ms
|
|
)
|
|
VALUES (?, 'codex', ?, 'Legacy Codex', 'codex', 1, 'system', 10, ?, ?);
|
|
`, legacyIDLocalCodex, agenttargetbiz.MustLocalCLILaunchRefJSON("codex"), now, now); err != nil {
|
|
t.Fatalf("insert legacy agent target fixture: %v", err)
|
|
}
|
|
if _, err := store.writeDB.ExecContext(ctx, `
|
|
INSERT INTO workspace_agent_sessions (
|
|
workspace_id,
|
|
agent_session_id,
|
|
origin,
|
|
agent_target_id,
|
|
provider,
|
|
created_at_unix_ms,
|
|
updated_at_unix_ms
|
|
)
|
|
VALUES ('ws-legacy-targets', 'session-1', 'runtime', ?, 'codex', ?, ?);
|
|
`, legacyIDLocalCodex, now, now); err != nil {
|
|
t.Fatalf("insert legacy agent session fixture: %v", err)
|
|
}
|
|
|
|
// Seeding and legacy target ID reconciliation run on every Migrate.
|
|
if err := store.Migrate(ctx); err != nil {
|
|
t.Fatalf("Migrate() error = %v", err)
|
|
}
|
|
|
|
if _, err := store.GetAgentTarget(ctx, legacyIDLocalCodex); !errors.Is(err, ErrAgentTargetNotFound) {
|
|
t.Fatalf("GetAgentTarget(legacy) error = %v, want ErrAgentTargetNotFound", err)
|
|
}
|
|
if _, err := store.GetAgentTarget(ctx, agenttargetbiz.IDLocalCodex); err != nil {
|
|
t.Fatalf("GetAgentTarget(current) error = %v", err)
|
|
}
|
|
sessions, ok, err := store.ListSessions(ctx, "ws-legacy-targets")
|
|
if err != nil {
|
|
t.Fatalf("ListSessions() error = %v", err)
|
|
}
|
|
if !ok || len(sessions) != 1 {
|
|
t.Fatalf("ListSessions() ok/len = %v/%d, want true/1", ok, len(sessions))
|
|
}
|
|
if sessions[0].AgentTargetID != agenttargetbiz.IDLocalCodex {
|
|
t.Fatalf("session agent target id = %q, want %s", sessions[0].AgentTargetID, agenttargetbiz.IDLocalCodex)
|
|
}
|
|
}
|
|
|
|
func TestSQLiteStorePutAgentTargetRejectsInvalidLaunchRefs(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
for _, tc := range []struct {
|
|
name string
|
|
provider string
|
|
launchRefJSON string
|
|
}{
|
|
{
|
|
name: "unknown type",
|
|
provider: "codex",
|
|
launchRefJSON: `{"type":"agent_profile","provider":"codex"}`,
|
|
},
|
|
{
|
|
name: "provider mismatch",
|
|
provider: "codex",
|
|
launchRefJSON: `{"type":"local_cli","provider":"claude-code"}`,
|
|
},
|
|
{
|
|
name: "config blob",
|
|
provider: "codex",
|
|
launchRefJSON: `{"type":"local_cli","provider":"codex","model":"gpt-5"}`,
|
|
},
|
|
{
|
|
name: "prompt config",
|
|
provider: "codex",
|
|
launchRefJSON: `{"type":"local_cli","provider":"codex","prompt":"always plan"}`,
|
|
},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
store := openTestSQLiteStore(t)
|
|
_, err := store.PutAgentTarget(context.Background(), agenttargetbiz.Target{
|
|
ID: "custom",
|
|
Provider: tc.provider,
|
|
LaunchRefJSON: tc.launchRefJSON,
|
|
Name: "Custom",
|
|
Enabled: true,
|
|
Source: agenttargetbiz.SourceUser,
|
|
})
|
|
if !errors.Is(err, agenttargetbiz.ErrInvalidLaunchRef) {
|
|
t.Fatalf("PutAgentTarget() error = %v, want ErrInvalidLaunchRef", err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSQLiteStorePutAgentTargetCanonicalizesLaunchRef(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
store := openTestSQLiteStore(t)
|
|
target, err := store.PutAgentTarget(context.Background(), agenttargetbiz.Target{
|
|
ID: "custom-codex",
|
|
Provider: " codex ",
|
|
LaunchRefJSON: `{"provider":"codex","type":"local_cli"}`,
|
|
Name: " Custom Codex ",
|
|
Enabled: true,
|
|
Source: agenttargetbiz.SourceUser,
|
|
SortOrder: 30,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("PutAgentTarget() error = %v", err)
|
|
}
|
|
if target.LaunchRefJSON != `{"type":"builtin_local","provider":"codex"}` {
|
|
t.Fatalf("LaunchRefJSON = %q, want canonical builtin_local codex", target.LaunchRefJSON)
|
|
}
|
|
if target.Name != "Custom Codex" {
|
|
t.Fatalf("Name = %q, want trimmed Custom Codex", target.Name)
|
|
}
|
|
}
|