源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
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
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
This commit is contained in:
@@ -0,0 +1,244 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user