{"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/services/workflowWatcher/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport {\n  completeWorkflowRunView,\n  foldWorkflowProgress,\n  type ParsedWorkflowRun,\n  parseWorkflowProgress,\n  parseWorkflowRunRecord,\n  PROGRESS_FILE_NAME,\n  resolveWorkflowHome,\n  RUN_RECORD_FILE_NAME,\n  WORKFLOW_HOME_ENV,\n  WORKFLOW_STAGES,\n  WORKSPACES_DIR_NAME,\n} from '../workflowRuns';\n\nexport interface ReadWorkflowRunsOptions {\n  /** Registry home override, primarily for tests. */\n  homeDir?: string;\n  /** Admitted session environment used to resolve the registry home. */\n  environment?: Readonly<Record<string, string | undefined>>;\n}\n\n/**\n * Read the durable workflow registry once.\n *\n * The registry is an initial snapshot only. Live delivery belongs to the\n * session lifecycle and is routed through the host-owned direct event bus.\n */\nexport function readWorkflowRuns(options: ReadWorkflowRunsOptions = {}): ParsedWorkflowRun[] {\n  const environment = options.environment;\n  const homeDir =\n    options.homeDir ??\n    resolveWorkflowHome({\n      envValue: environment?.[WORKFLOW_HOME_ENV],\n      homeDir: os.homedir(),\n    });\n  const workspacesDir = path.join(homeDir, WORKSPACES_DIR_NAME);\n  const recordCache = new Map<string, { size: number; mtimeMs: number; value: ParsedWorkflowRun | undefined }>();\n  const progressCache = new Map<\n    string,\n    { size: number; mtimeMs: number; value: ReturnType<typeof foldWorkflowProgress> }\n  >();\n\n  const cachedParse = <T>(\n    cache: Map<string, { size: number; mtimeMs: number; value: T }>,\n    filePath: string,\n    parse: (raw: string) => T,\n    empty: T,\n  ): T => {\n    let stat: fs.Stats;\n    try {\n      stat = fs.statSync(filePath);\n    } catch {\n      cache.delete(filePath);\n      return empty;\n    }\n    const cached = cache.get(filePath);\n    if (cached && cached.size === stat.size && cached.mtimeMs === stat.mtimeMs) return cached.value;\n    let raw: string;\n    try {\n      raw = fs.readFileSync(filePath, 'utf8');\n    } catch {\n      cache.delete(filePath);\n      return empty;\n    }\n    const value = parse(raw);\n    cache.set(filePath, { size: stat.size, mtimeMs: stat.mtimeMs, value });\n    return value;\n  };\n\n  const listDir = (directory: string): string[] => {\n    try {\n      return fs.readdirSync(directory).sort();\n    } catch {\n      return [];\n    }\n  };\n\n  const runs: ParsedWorkflowRun[] = [];\n  for (const workspace of listDir(workspacesDir)) {\n    for (const stage of WORKFLOW_STAGES) {\n      const stageDir = path.join(workspacesDir, workspace, stage);\n      for (const runKey of listDir(stageDir)) {\n        const runDir = path.join(stageDir, runKey);\n        const recordPath = path.join(runDir, RUN_RECORD_FILE_NAME);\n        const progressPath = path.join(runDir, PROGRESS_FILE_NAME);\n        const parsed = cachedParse(recordCache, recordPath, parseWorkflowRunRecord, undefined);\n        if (parsed === undefined) continue;\n        const jobs = cachedParse(\n          progressCache,\n          progressPath,\n          (raw) => foldWorkflowProgress(parseWorkflowProgress(raw)),\n          [],\n        );\n        runs.push({ ...parsed, view: completeWorkflowRunView(parsed.view, jobs) });\n      }\n    }\n  }\n  return runs;\n}\n"],"mappings":";;;;;;;;;;;AA+BA,SAAgB,iBAAiB,UAAmC,CAAC,GAAwB;CAC3F,MAAM,cAAc,QAAQ;CAC5B,MAAM,UACJ,QAAQ,WACR,oBAAoB;EAClB,UAAU,cAAA;EACV,SAAS,GAAG,QAAQ;CACtB,CAAC;CACH,MAAM,gBAAgB,KAAK,KAAK,SAAS,mBAAmB;CAC5D,MAAM,8BAAc,IAAI,IAAqF;CAC7G,MAAM,gCAAgB,IAAI,IAGxB;CAEF,MAAM,eACJ,OACA,UACA,OACA,UACM;EACN,IAAI;EACJ,IAAI;GACF,OAAO,GAAG,SAAS,QAAQ;EAC7B,QAAQ;GACN,MAAM,OAAO,QAAQ;GACrB,OAAO;EACT;EACA,MAAM,SAAS,MAAM,IAAI,QAAQ;EACjC,IAAI,UAAU,OAAO,SAAS,KAAK,QAAQ,OAAO,YAAY,KAAK,SAAS,OAAO,OAAO;EAC1F,IAAI;EACJ,IAAI;GACF,MAAM,GAAG,aAAa,UAAU,MAAM;EACxC,QAAQ;GACN,MAAM,OAAO,QAAQ;GACrB,OAAO;EACT;EACA,MAAM,QAAQ,MAAM,GAAG;EACvB,MAAM,IAAI,UAAU;GAAE,MAAM,KAAK;GAAM,SAAS,KAAK;GAAS;EAAM,CAAC;EACrE,OAAO;CACT;CAEA,MAAM,WAAW,cAAgC;EAC/C,IAAI;GACF,OAAO,GAAG,YAAY,SAAS,CAAC,CAAC,KAAK;EACxC,QAAQ;GACN,OAAO,CAAC;EACV;CACF;CAEA,MAAM,OAA4B,CAAC;CACnC,KAAK,MAAM,aAAa,QAAQ,aAAa,GAC3C,KAAK,MAAM,SAAS,iBAAiB;EACnC,MAAM,WAAW,KAAK,KAAK,eAAe,WAAW,KAAK;EAC1D,KAAK,MAAM,UAAU,QAAQ,QAAQ,GAAG;GACtC,MAAM,SAAS,KAAK,KAAK,UAAU,MAAM;GACzC,MAAM,aAAa,KAAK,KAAK,QAAQ,oBAAoB;GACzD,MAAM,eAAe,KAAK,KAAK,QAAQ,kBAAkB;GACzD,MAAM,SAAS,YAAY,aAAa,YAAY,wBAAwB,KAAA,CAAS;GACrF,IAAI,WAAW,KAAA,GAAW;GAC1B,MAAM,OAAO,YACX,eACA,eACC,QAAQ,qBAAqB,sBAAsB,GAAG,CAAC,GACxD,CAAC,CACH;GACA,KAAK,KAAK;IAAE,GAAG;IAAQ,MAAM,wBAAwB,OAAO,MAAM,IAAI;GAAE,CAAC;EAC3E;CACF;CAEF,OAAO;AACT"}