package llm import ( "crypto/sha256" "encoding/hex" "fmt" "io/fs" "os" "path/filepath" "sort" "strings" ) const ( promptKitProfileFingerprintName = "promptkit_profile_source" // The built-in profile catalog is compiled into this pinned PromptKit // release. Update this identity when the dependency is upgraded. promptKitBuiltinProfileCatalogID = "promptkit:v0.2.0:builtin-profiles" ) func promptKitProfileFingerprint(profileDir, profileFile string) (CheckpointFingerprint, error) { hasher := sha256.New() writeFingerprintPart(hasher, []byte(promptKitBuiltinProfileCatalogID)) switch { case strings.TrimSpace(profileFile) != "": data, err := os.ReadFile(strings.TrimSpace(profileFile)) if err != nil { return CheckpointFingerprint{}, fmt.Errorf("read PromptKit profile file for checkpoint identity: %w", err) } writeFingerprintPart(hasher, data) case strings.TrimSpace(profileDir) != "": digests, err := promptKitProfileFileDigests(strings.TrimSpace(profileDir)) if err != nil { return CheckpointFingerprint{}, err } for _, digest := range digests { writeFingerprintPart(hasher, digest) } } return CheckpointFingerprint{ Name: promptKitProfileFingerprintName, Value: "sha256:" + hex.EncodeToString(hasher.Sum(nil)), }, nil } func promptKitProfileFileDigests(root string) ([][]byte, error) { var digests [][]byte err := filepath.WalkDir(root, func(name string, entry fs.DirEntry, walkErr error) error { if walkErr != nil { return walkErr } if entry.IsDir() { return nil } extension := filepath.Ext(entry.Name()) if extension != ".yaml" && extension != ".yml" { return nil } data, err := os.ReadFile(name) if err != nil { return err } sum := sha256.Sum256(data) digests = append(digests, append([]byte(nil), sum[:]...)) return nil }) if err != nil { return nil, fmt.Errorf("read PromptKit profile directory for checkpoint identity: %w", err) } sort.Slice(digests, func(i, j int) bool { return string(digests[i]) < string(digests[j]) }) return digests, nil } func writeFingerprintPart(hasher interface{ Write([]byte) (int, error) }, value []byte) { length := []byte(fmt.Sprintf("%d:", len(value))) _, _ = hasher.Write(length) _, _ = hasher.Write(value) }