import * as fs from "node:fs"; import * as path from "node:path"; import { DEFAULT_PATHS } from "../config/defaults.ts"; import { projectCrewRoot, userCrewRoot } from "../utils/paths.ts"; import { isSafePathId, resolveRealContainedPath } from "../utils/safe-paths.ts"; export interface ImportedRunIndexEntry { runId: string; scope: "project" | "user"; bundlePath: string; summaryPath: string; importedAt?: string; status?: string; team?: string; workflow?: string; goal?: string; } function readEntry(root: string, scope: "project" | "user", runId: string): ImportedRunIndexEntry | undefined { if (!isSafePathId(runId)) return undefined; let bundlePath: string; let summaryPath: string; try { const entryRoot = resolveRealContainedPath(root, runId); bundlePath = resolveRealContainedPath(root, path.join(runId, "run-export.json")); summaryPath = path.join(entryRoot, "README.md"); } catch { return undefined; } if (!fs.existsSync(bundlePath)) return undefined; try { const raw = JSON.parse(fs.readFileSync(bundlePath, "utf-8")) as Record; const manifest = raw.manifest && typeof raw.manifest === "object" && !Array.isArray(raw.manifest) ? (raw.manifest as Record) : {}; return { runId, scope, bundlePath, summaryPath, importedAt: typeof raw.importedAt === "string" ? raw.importedAt : undefined, status: typeof manifest.status === "string" ? manifest.status : undefined, team: typeof manifest.team === "string" ? manifest.team : undefined, workflow: typeof manifest.workflow === "string" ? manifest.workflow : undefined, goal: typeof manifest.goal === "string" ? manifest.goal : undefined, }; } catch { return { runId, scope, bundlePath, summaryPath }; } } function collect(root: string, scope: "project" | "user"): ImportedRunIndexEntry[] { if (!fs.existsSync(root)) return []; try { if (fs.lstatSync(root).isSymbolicLink()) return []; resolveRealContainedPath(path.dirname(root), path.basename(root)); } catch { return []; } return fs .readdirSync(root) .filter((entry) => isSafePathId(entry)) .map((entry) => readEntry(root, scope, entry)) .filter((entry): entry is ImportedRunIndexEntry => entry !== undefined); } export function listImportedRuns(cwd: string): ImportedRunIndexEntry[] { const projectRoot = path.join(projectCrewRoot(cwd), DEFAULT_PATHS.state.importsSubdir); const userRoot = path.join(userCrewRoot(), DEFAULT_PATHS.state.importsSubdir); return [...collect(userRoot, "user"), ...collect(projectRoot, "project")].sort((a, b) => (b.importedAt ?? "").localeCompare(a.importedAt ?? ""), ); }