Files
agent-radar 2ed3415fb7
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
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

309 lines
10 KiB
Go

package runtimeprep
import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"os"
"path/filepath"
"sort"
"strings"
)
const stableSkillBundleSchemaVersion = 1
type stableSkillBundleManifest struct {
SchemaVersion int `json:"schemaVersion"`
Digest string `json:"digest"`
Provider string `json:"provider"`
SkillCount int `json:"skillCount"`
}
type canonicalStableSkillBundle struct {
SchemaVersion int `json:"schemaVersion"`
Provider string `json:"provider"`
Skills []canonicalStableSkill `json:"skills"`
}
type canonicalStableSkill struct {
SkillID string `json:"skillId"`
Slug string `json:"slug"`
Directory string `json:"directory"`
Files []canonicalStableSkillFile `json:"files"`
}
type canonicalStableSkillFile struct {
Path string `json:"path"`
Content string `json:"content"`
}
type materializedStableSkill struct {
spec providerSkillSpec
directory string
}
func materializeStableProviderSkills(
storeRoot string,
input PrepareInput,
) (string, error) {
if input.SkipSkills {
return "", nil
}
storeRoot = filepath.Clean(strings.TrimSpace(storeRoot))
if storeRoot == "." || !filepath.IsAbs(storeRoot) {
return "", fmt.Errorf("stable provider skill bundle root must be absolute")
}
specs, err := providerSkills(input)
if err != nil {
return "", err
}
canonical, materialized, err := canonicalizeStableProviderSkills(input.Provider, specs)
if err != nil {
return "", err
}
canonicalJSON, err := json.Marshal(canonical)
if err != nil {
return "", fmt.Errorf("encode stable provider skill bundle: %w", err)
}
digestBytes := sha256.Sum256(canonicalJSON)
digest := hex.EncodeToString(digestBytes[:])
manifest := stableSkillBundleManifest{
SchemaVersion: stableSkillBundleSchemaVersion,
Digest: digest,
Provider: strings.TrimSpace(input.Provider),
SkillCount: len(materialized),
}
versionRoot := filepath.Join(storeRoot, fmt.Sprintf("v%d", stableSkillBundleSchemaVersion))
bundleRoot := filepath.Join(versionRoot, digest)
skillsRoot := filepath.Join(bundleRoot, "skills")
if err := validateStableSkillBundle(bundleRoot, manifest, materialized); err == nil {
return skillsRoot, nil
} else if !os.IsNotExist(err) {
return "", err
}
if err := os.MkdirAll(versionRoot, 0o755); err != nil {
return "", fmt.Errorf("create stable provider skill bundle store: %w", err)
}
temporaryRoot, err := os.MkdirTemp(versionRoot, ".tmp-"+digest+"-")
if err != nil {
return "", fmt.Errorf("create stable provider skill bundle temporary directory: %w", err)
}
defer func() { _ = os.RemoveAll(temporaryRoot) }()
temporarySkillsRoot := filepath.Join(temporaryRoot, "skills")
if err := os.MkdirAll(temporarySkillsRoot, 0o755); err != nil {
return "", fmt.Errorf("create stable provider skill root: %w", err)
}
for _, skill := range materialized {
if err := installProviderSkillFiles(
filepath.Join(temporarySkillsRoot, skill.directory),
skill.spec,
); err != nil {
return "", err
}
}
manifestJSON, err := stableSkillBundleManifestJSON(manifest)
if err != nil {
return "", fmt.Errorf("encode stable provider skill bundle manifest: %w", err)
}
if err := os.WriteFile(
filepath.Join(temporaryRoot, "bundle.json"),
manifestJSON,
0o644,
); err != nil {
return "", fmt.Errorf("write stable provider skill bundle manifest: %w", err)
}
if err := validateStableSkillBundle(temporaryRoot, manifest, materialized); err != nil {
return "", fmt.Errorf("validate staged provider skill bundle: %w", err)
}
if err := os.Rename(temporaryRoot, bundleRoot); err != nil {
if validationErr := validateStableSkillBundle(bundleRoot, manifest, materialized); validationErr == nil {
return skillsRoot, nil
}
return "", fmt.Errorf("commit stable provider skill bundle: %w", err)
}
return skillsRoot, nil
}
func canonicalizeStableProviderSkills(
provider string,
specs []providerSkillSpec,
) (canonicalStableSkillBundle, []materializedStableSkill, error) {
sorted := append([]providerSkillSpec(nil), specs...)
sort.Slice(sorted, func(left, right int) bool {
leftID, rightID := strings.TrimSpace(sorted[left].skillID), strings.TrimSpace(sorted[right].skillID)
if leftID != rightID {
return leftID < rightID
}
return strings.TrimSpace(sorted[left].baseName) < strings.TrimSpace(sorted[right].baseName)
})
canonical := canonicalStableSkillBundle{
SchemaVersion: stableSkillBundleSchemaVersion,
Provider: strings.TrimSpace(provider),
Skills: make([]canonicalStableSkill, 0, len(sorted)),
}
materialized := make([]materializedStableSkill, 0, len(sorted))
usedDirectories := make(map[string]struct{}, len(sorted))
for _, spec := range sorted {
directory, err := allocateStableBundleSkillDirectory(spec.baseName, usedDirectories)
if err != nil {
return canonicalStableSkillBundle{}, nil, err
}
normalizedFiles := make(map[string]string, len(spec.files))
paths := make([]string, 0, len(spec.files))
for filePath, content := range spec.files {
cleanPath, err := cleanProviderSkillFilePath(filePath)
if err != nil {
return canonicalStableSkillBundle{}, nil, err
}
if _, exists := normalizedFiles[cleanPath]; exists {
return canonicalStableSkillBundle{}, nil, fmt.Errorf(
"provider skill %s has duplicate normalized file path %q",
spec.skillID,
cleanPath,
)
}
normalizedFiles[cleanPath] = content
paths = append(paths, cleanPath)
}
sort.Strings(paths)
files := make([]canonicalStableSkillFile, 0, len(paths))
for _, filePath := range paths {
files = append(files, canonicalStableSkillFile{
Path: filePath,
Content: normalizedFiles[filePath],
})
}
canonical.Skills = append(canonical.Skills, canonicalStableSkill{
SkillID: strings.TrimSpace(spec.skillID),
Slug: strings.TrimSpace(spec.baseName),
Directory: directory,
Files: files,
})
materialized = append(materialized, materializedStableSkill{
spec: spec,
directory: directory,
})
}
return canonical, materialized, nil
}
func allocateStableBundleSkillDirectory(
baseName string,
used map[string]struct{},
) (string, error) {
baseName = strings.TrimSpace(baseName)
if baseName == "" || baseName == "." || baseName == ".." ||
filepath.Base(baseName) != baseName || strings.ContainsAny(baseName, `/\\`) {
return "", fmt.Errorf("provider skill name is invalid: %q", baseName)
}
candidates := []string{baseName, baseName + "-tutti"}
for index := 2; index <= 99; index++ {
candidates = append(candidates, fmt.Sprintf("%s-tutti-%d", baseName, index))
}
for _, candidate := range candidates {
if _, exists := used[candidate]; exists {
continue
}
used[candidate] = struct{}{}
return candidate, nil
}
return "", fmt.Errorf("allocate stable provider skill directory: exhausted names for %s", baseName)
}
func validateStableSkillBundle(
bundleRoot string,
wantManifest stableSkillBundleManifest,
skills []materializedStableSkill,
) error {
info, err := os.Stat(bundleRoot)
if err != nil {
return err
}
if !info.IsDir() {
return fmt.Errorf("stable provider skill bundle is not a directory: %s", bundleRoot)
}
manifestBytes, err := os.ReadFile(filepath.Join(bundleRoot, "bundle.json"))
if err != nil {
return fmt.Errorf("read stable provider skill bundle manifest: %w", err)
}
var manifest stableSkillBundleManifest
if err := json.Unmarshal(manifestBytes, &manifest); err != nil {
return fmt.Errorf("decode stable provider skill bundle manifest: %w", err)
}
if manifest != wantManifest {
return fmt.Errorf("stable provider skill bundle manifest does not match digest")
}
wantManifestBytes, err := stableSkillBundleManifestJSON(wantManifest)
if err != nil {
return err
}
wantFiles := map[string]string{"bundle.json": string(wantManifestBytes)}
wantDirectories := map[string]struct{}{".": {}, "skills": {}}
for _, skill := range skills {
directory := filepath.ToSlash(filepath.Join("skills", skill.directory))
wantDirectories[directory] = struct{}{}
wantFiles[filepath.ToSlash(filepath.Join(directory, ".tutti-managed-skill"))] =
skill.spec.skillID + "\n"
for filePath, content := range skill.spec.files {
cleanPath, err := cleanProviderSkillFilePath(filePath)
if err != nil {
return err
}
relative := filepath.ToSlash(filepath.Join(directory, filepath.FromSlash(cleanPath)))
wantFiles[relative] = content
for parent := filepath.ToSlash(filepath.Dir(relative)); parent != "."; parent = filepath.ToSlash(filepath.Dir(parent)) {
wantDirectories[parent] = struct{}{}
}
}
}
seenFiles := make(map[string]struct{}, len(wantFiles))
err = filepath.WalkDir(bundleRoot, func(path string, entry os.DirEntry, walkErr error) error {
if walkErr != nil {
return walkErr
}
relative, err := filepath.Rel(bundleRoot, path)
if err != nil {
return err
}
relative = filepath.ToSlash(relative)
if entry.Type()&os.ModeSymlink != 0 {
return fmt.Errorf("stable provider skill bundle contains symlink: %s", relative)
}
if entry.IsDir() {
if _, exists := wantDirectories[relative]; !exists {
return fmt.Errorf("stable provider skill bundle contains unexpected directory: %s", relative)
}
return nil
}
want, exists := wantFiles[relative]
if !exists {
return fmt.Errorf("stable provider skill bundle contains unexpected file: %s", relative)
}
content, err := os.ReadFile(path)
if err != nil {
return err
}
if string(content) != want {
return fmt.Errorf("stable provider skill bundle file does not match digest: %s", relative)
}
seenFiles[relative] = struct{}{}
return nil
})
if err != nil {
return err
}
if len(seenFiles) != len(wantFiles) {
return fmt.Errorf("stable provider skill bundle is incomplete")
}
return nil
}
func stableSkillBundleManifestJSON(manifest stableSkillBundleManifest) ([]byte, error) {
encoded, err := json.MarshalIndent(manifest, "", " ")
if err != nil {
return nil, fmt.Errorf("encode stable provider skill bundle manifest: %w", err)
}
return append(encoded, '\n'), nil
}