源码快照 @ 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,220 @@
|
||||
package runtimeprep
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTuttiAgentStableSkillsReuseRootAcrossSessions(t *testing.T) {
|
||||
stateDir := t.TempDir()
|
||||
storeRoot := filepath.Join(stateDir, "agent", "skill-bundles")
|
||||
preparer := TuttiAgentPreparer{
|
||||
ResolveAuthSource: func(context.Context, PrepareInput) (string, error) {
|
||||
return "", nil
|
||||
},
|
||||
StableSkillBundleRoot: storeRoot,
|
||||
StableSystemSkillBundleRoot: filepath.Join(stateDir, "agent", "system-skill-bundles"),
|
||||
}
|
||||
wantRoot := ""
|
||||
for _, sessionID := range []string{"session-a", "session-b"} {
|
||||
runtimeRoot := filepath.Join(stateDir, "agent", "runs", sessionID)
|
||||
result, err := preparer.Prepare(t.Context(), ProviderPrepareInput{
|
||||
PrepareInput: testResolvedInput(t, PrepareInput{
|
||||
AgentSessionID: sessionID,
|
||||
AgentTargetID: "local:tutti-agent",
|
||||
Provider: "tutti-agent",
|
||||
CLICommand: "tutti",
|
||||
}),
|
||||
RuntimeRoot: runtimeRoot,
|
||||
Store: LocalStore{StateDir: stateDir},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Prepare(%s) error = %v", sessionID, err)
|
||||
}
|
||||
var roots []string
|
||||
if err := json.Unmarshal(
|
||||
[]byte(envValue(result.Env, "TUTTI_AGENT_EXTRA_SKILL_ROOTS_JSON")),
|
||||
&roots,
|
||||
); err != nil {
|
||||
t.Fatalf("Prepare(%s) extra roots = %#v: %v", sessionID, result.Env, err)
|
||||
}
|
||||
if len(roots) != 1 || !filepath.IsAbs(roots[0]) {
|
||||
t.Fatalf("Prepare(%s) roots = %#v, want one absolute root", sessionID, roots)
|
||||
}
|
||||
if root := envValue(result.Env, "TUTTI_AGENT_STABLE_SYSTEM_SKILLS_ROOT"); root != filepath.Join(stateDir, "agent", "system-skill-bundles") {
|
||||
t.Fatalf("Prepare(%s) stable system root = %q", sessionID, root)
|
||||
}
|
||||
if wantRoot == "" {
|
||||
wantRoot = roots[0]
|
||||
} else if roots[0] != wantRoot {
|
||||
t.Fatalf("stable roots differ: %q != %q", roots[0], wantRoot)
|
||||
}
|
||||
home := filepath.Join(runtimeRoot, "tutti-agent-home")
|
||||
if _, err := os.Stat(filepath.Join(home, "skills")); !os.IsNotExist(err) {
|
||||
t.Fatalf("Prepare(%s) created legacy skills root, err = %v", sessionID, err)
|
||||
}
|
||||
instructions, err := os.ReadFile(filepath.Join(home, "AGENTS.md"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if strings.Contains(string(instructions), sessionID) {
|
||||
t.Fatalf("Prepare(%s) embedded session id in AGENTS.md", sessionID)
|
||||
}
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(wantRoot, tuttiSkillName, "SKILL.md")); err != nil {
|
||||
t.Fatalf("stable tutti-cli skill missing: %v", err)
|
||||
}
|
||||
if !strings.Contains(filepath.ToSlash(wantRoot), "/agent/skill-bundles/v1/") {
|
||||
t.Fatalf("stable root = %q, want versioned content-addressed path", wantRoot)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTuttiAgentAddsVerifiedConnectorSkillRoots(t *testing.T) {
|
||||
stateDir := t.TempDir()
|
||||
connectorRoot := filepath.Join(stateDir, "connectors", "lark-cli", "skills")
|
||||
if err := os.MkdirAll(connectorRoot, 0o700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
preparer := TuttiAgentPreparer{
|
||||
ResolveAuthSource: func(context.Context, PrepareInput) (string, error) { return "", nil },
|
||||
StableSkillBundleRoot: filepath.Join(stateDir, "agent", "skill-bundles"),
|
||||
}
|
||||
result, err := preparer.Prepare(t.Context(), ProviderPrepareInput{
|
||||
PrepareInput: testResolvedInput(t, PrepareInput{
|
||||
AgentSessionID: "session-a",
|
||||
AgentTargetID: "local:tutti-agent",
|
||||
Provider: "tutti-agent",
|
||||
CLICommand: "tutti",
|
||||
ConnectorRoutingHints: []ConnectorRoutingHint{
|
||||
{ConnectorKey: "lark-cli", SkillRoot: connectorRoot},
|
||||
{ConnectorKey: "lark-cli-copy", SkillRoot: connectorRoot},
|
||||
},
|
||||
}),
|
||||
RuntimeRoot: filepath.Join(stateDir, "agent", "runs", "session-a"),
|
||||
Store: LocalStore{StateDir: stateDir},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var roots []string
|
||||
if err := json.Unmarshal([]byte(envValue(result.Env, "TUTTI_AGENT_EXTRA_SKILL_ROOTS_JSON")), &roots); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(roots) != 2 || roots[1] != connectorRoot {
|
||||
t.Fatalf("extra roots = %#v, want stable provider root followed by deduplicated connector root", roots)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnectorSkillRootsRejectsRelativeOrSymlinkRoots(t *testing.T) {
|
||||
if _, err := connectorSkillRoots([]ConnectorRoutingHint{{ConnectorKey: "demo", SkillRoot: "relative/skills"}}); err == nil {
|
||||
t.Fatal("relative connector Skill root was accepted")
|
||||
}
|
||||
realRoot := t.TempDir()
|
||||
link := filepath.Join(t.TempDir(), "skills")
|
||||
if err := os.Symlink(realRoot, link); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := connectorSkillRoots([]ConnectorRoutingHint{{ConnectorKey: "demo", SkillRoot: link}}); err == nil {
|
||||
t.Fatal("symlink connector Skill root was accepted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStableSkillBundleDigestChangesWithContentNotMapOrder(t *testing.T) {
|
||||
specA := providerSkillSpec{
|
||||
baseName: "sample",
|
||||
skillID: "example/sample",
|
||||
files: map[string]string{
|
||||
"SKILL.md": "sample",
|
||||
"references/guide.md": "guide",
|
||||
},
|
||||
}
|
||||
specB := providerSkillSpec{
|
||||
baseName: "sample",
|
||||
skillID: "example/sample",
|
||||
files: map[string]string{
|
||||
"references/guide.md": "guide",
|
||||
"SKILL.md": "sample",
|
||||
},
|
||||
}
|
||||
first, _, err := canonicalizeStableProviderSkills("tutti-agent", []providerSkillSpec{specA})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
second, _, err := canonicalizeStableProviderSkills("tutti-agent", []providerSkillSpec{specB})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
firstJSON, _ := json.Marshal(first)
|
||||
secondJSON, _ := json.Marshal(second)
|
||||
if string(firstJSON) != string(secondJSON) {
|
||||
t.Fatalf("canonical bundle depends on map order:\n%s\n%s", firstJSON, secondJSON)
|
||||
}
|
||||
specB.files["SKILL.md"] = "changed"
|
||||
changed, _, err := canonicalizeStableProviderSkills("tutti-agent", []providerSkillSpec{specB})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
changedJSON, _ := json.Marshal(changed)
|
||||
if string(firstJSON) == string(changedJSON) {
|
||||
t.Fatal("canonical bundle did not change with skill content")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStableSkillBundleConcurrentMaterialization(t *testing.T) {
|
||||
input := testResolvedInput(t, PrepareInput{
|
||||
AgentSessionID: "session-a",
|
||||
AgentTargetID: "local:tutti-agent",
|
||||
Provider: "tutti-agent",
|
||||
CLICommand: "tutti",
|
||||
})
|
||||
storeRoot := filepath.Join(t.TempDir(), "skill-bundles")
|
||||
const workers = 8
|
||||
roots := make(chan string, workers)
|
||||
errors := make(chan error, workers)
|
||||
var group sync.WaitGroup
|
||||
for index := 0; index < workers; index++ {
|
||||
group.Add(1)
|
||||
go func() {
|
||||
defer group.Done()
|
||||
root, err := materializeStableProviderSkills(storeRoot, input)
|
||||
if err != nil {
|
||||
errors <- err
|
||||
return
|
||||
}
|
||||
roots <- root
|
||||
}()
|
||||
}
|
||||
group.Wait()
|
||||
close(roots)
|
||||
close(errors)
|
||||
for err := range errors {
|
||||
t.Fatalf("materializeStableProviderSkills() error = %v", err)
|
||||
}
|
||||
want := ""
|
||||
for root := range roots {
|
||||
if want == "" {
|
||||
want = root
|
||||
} else if root != want {
|
||||
t.Fatalf("concurrent roots differ: %q != %q", root, want)
|
||||
}
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(want, tuttiSkillName, "SKILL.md")); err != nil {
|
||||
t.Fatalf("concurrent bundle is incomplete: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStableSkillBundleRejectsEscapingSkillName(t *testing.T) {
|
||||
_, _, err := canonicalizeStableProviderSkills("tutti-agent", []providerSkillSpec{{
|
||||
baseName: "../escape",
|
||||
skillID: "example/escape",
|
||||
files: map[string]string{"SKILL.md": "escape"},
|
||||
}})
|
||||
if err == nil {
|
||||
t.Fatal("canonicalizeStableProviderSkills() error = nil, want escaping name rejection")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user