package llm import ( "fmt" "path/filepath" "sort" "strconv" "strings" ck "go.maximumdirect.net/configkit" pk "go.maximumdirect.net/promptkit" "gopkg.in/yaml.v3" ) func capturedSourcePaths(engine *pk.Engine) ([]string, error) { inspection, err := engine.InspectConfiguration() if err != nil { return nil, fmt.Errorf("inspect configuration: %w", err) } sources := inspection.Sources() byID := make(map[string]ck.SourceInfo, len(sources)) paths := make(map[string]struct{}, len(sources)) hostPath := func(source ck.SourceInfo) string { if source.Kind == ck.SourceKindFile { return source.Path } return "" } for _, source := range sources { byID[source.ID] = source if path := hostPath(source); path != "" { paths[path] = struct{}{} } } metadata := inspection.Metadata() for _, path := range metadata.HistoricalPaths() { segments := strings.Split(strings.TrimPrefix(path.String(), "/"), "/") // Prompt resources are lists at the root or inside a collection. if len(segments) == 7 && segments[0] == "collections" { segments = segments[2:] } if len(segments) != 5 || segments[0] != "prompts" || segments[2] != "messages" || segments[4] != "content_file" { continue } if _, err := strconv.Atoi(segments[1]); err != nil { continue } if _, err := strconv.Atoi(segments[3]); err != nil { continue } field, ok := metadata.Lookup(path) if !ok || field.Null || len(field.Origin.Locations) != 1 { continue } source, ok := byID[field.Origin.Locations[0].SourceID] if !ok || hostPath(source) == "" { continue } explanation, ok := inspection.Explain(path) if !ok || !explanation.Effective.Present || explanation.Effective.Redacted { continue } var resource string if err := yaml.Unmarshal([]byte(explanation.Effective.YAML), &resource); err != nil { return nil, fmt.Errorf("decode captured message resource at %s: %w", path.String(), err) } paths[filepath.Join(filepath.Dir(hostPath(source)), filepath.FromSlash(resource))] = struct{}{} } result := make([]string, 0, len(paths)) for path := range paths { result = append(result, path) } sort.Strings(result) return result, nil }