{"version":3,"file":"run-context.mjs","names":[],"sources":["../../../../../../../ai/src/utils/run-context.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { BaseReport } from \"../contracts/result/base-report.type\";\n\n/**\n * The ambient run frame an executable reads when it finishes building\n * its report. When present, a child execution (an `agent.execute()`,\n * `workflow.execute()`, `supervisor.execute()` call) auto-attaches its\n * report to `sink` and inherits the frame's `rootRunId` / `sessionId`\n * lineage — so reports nest under the enclosing run with NO manual id\n * threading by the dev.\n *\n * Installed by orchestration primitives (supervisor / orchestrator /\n * team) around the synchronous + async body of an intent's callback,\n * so any agent the callback invokes directly — `agent.execute(...)`\n * rather than `ctx.run(...)` — still lands in the trace tree.\n */\nexport type RunFrame = {\n  /**\n   * The `children[]` array of the enclosing report node. A child\n   * execution pushes its assembled report here on completion.\n   */\n  sink: BaseReport[];\n  /**\n   * The outermost run-id this subtree belongs to. Propagated onto the\n   * child report's `rootRunId` so flat-row consumers group it with the\n   * enclosing run.\n   */\n  rootRunId: string;\n  /**\n   * Run-id of the enclosing node (the immediate parent of any child\n   * captured through this frame). Stamped onto the child's\n   * `parentRunId`.\n   */\n  parentRunId: string;\n  /**\n   * Session identifier propagated onto the captured child's subtree.\n   * `undefined` when the enclosing run had none.\n   */\n  sessionId?: string;\n};\n\n/**\n * Process-wide async-local store holding the current {@link RunFrame}.\n * A single shared instance so a frame installed by the supervisor is\n * visible to an agent running several `await`s deep inside a callback,\n * across module boundaries. Empty (returns `undefined`) outside any\n * orchestration callback — standalone `agent.execute()` is unaffected.\n */\nconst runFrameStore = new AsyncLocalStorage<RunFrame | undefined>();\n\n/**\n * A second async-local flag set whenever execution is nested inside a\n * parent capture — by BOTH {@link withRunFrame} (ambient capture) and\n * {@link withoutRunFrame} (explicit parent capture, which clears the frame).\n * Lets the `observeAll` gate skip self-routing a nested run regardless of\n * which capture path its parent uses — the parent already captures it.\n */\nconst nestedStore = new AsyncLocalStorage<boolean>();\n\n/**\n * Run `fn` with `frame` installed as the ambient {@link RunFrame} for\n * the entire async subtree it spawns. Restores the previous frame (or\n * none) when `fn` settles. Returns whatever `fn` returns.\n *\n * Nesting is natural: a callback that itself dispatches a nested\n * supervisor installs a fresh frame for the inner run, and the inner\n * frame shadows the outer one for the inner subtree only — exactly the\n * tree shape the report models.\n */\nexport function withRunFrame<T>(frame: RunFrame, fn: () => T): T {\n  return nestedStore.run(true, () => runFrameStore.run(frame, fn));\n}\n\n/**\n * Run `fn` with NO ambient {@link RunFrame} installed for its async\n * subtree, restoring the previous frame when `fn` settles. Used by the\n * supervisor's EXPLICIT capture paths (`ctx.run(...)` /\n * `ctx.intents.X.execute()`) — those already push the child report onto\n * the callback's `children[]` themselves, so the child must NOT also\n * self-capture via the ambient frame (which would double-count it).\n */\nexport function withoutRunFrame<T>(fn: () => T): T {\n  return nestedStore.run(true, () => runFrameStore.run(undefined, fn));\n}\n\n/**\n * Read the current ambient {@link RunFrame}, or `undefined` when no\n * orchestration callback is on the stack. An executable calls this at\n * report-build time: a present frame means \"you were invoked inside a\n * callback — attach yourself to its tree\".\n */\nexport function currentRunFrame(): RunFrame | undefined {\n  return runFrameStore.getStore();\n}\n\n/**\n * `true` when execution is nested inside a parent capture — set by\n * {@link withRunFrame} (ambient) or {@link withoutRunFrame} (explicit). Read\n * by the observe-all gate so a nested run, which its parent already captures\n * into the trace tree, is not also self-routed as a standalone top-level\n * trace. `false` for a standalone (root) run.\n */\nexport function isNestedRun(): boolean {\n  return nestedStore.getStore() === true;\n}\n\n/**\n * Capture a freshly-built child `report` onto the current ambient\n * {@link RunFrame} when one is installed. Pushes the report onto the\n * frame's `sink` so it nests under the enclosing node, and rewrites the\n * report's lineage (`rootRunId`, `parentRunId`, `sessionId`) to the\n * frame's — mirroring how `step.agent` / `ctx.run` capture child\n * reports explicitly, but driven ambiently.\n *\n * No-op (returns `false`) when no frame is installed — a standalone\n * `agent.execute()` keeps its self-root untouched. Returns `true` when\n * the report was captured so the caller can suppress its own terminal\n * lineage stamp if needed.\n *\n * The lineage rewrite is intentionally shallow on the root + deep on\n * descendants would double-stamp; callers pass the already-lineage-\n * stamped subtree (self-root), and this relinks only the root's\n * `rootRunId` / `parentRunId` / `sessionId`. Descendants already carry\n * the child's own self-root as their `rootRunId`; the enclosing\n * primitive's terminal `stampReportLineage` pass (run once on the\n * outer tree) rewrites the whole subtree to the true outer root. This\n * keeps capture cheap and defers the single authoritative relink to\n * the outer build.\n */\nexport function captureChildReport(report: BaseReport): boolean {\n  const frame = runFrameStore.getStore();\n\n  if (!frame) {\n    return false;\n  }\n\n  report.parentRunId = frame.parentRunId;\n  report.rootRunId = frame.rootRunId;\n\n  if (frame.sessionId !== undefined) {\n    report.sessionId = frame.sessionId;\n  }\n\n  frame.sink.push(report);\n\n  return true;\n}\n"],"mappings":";;;;;;;;;;AAgDA,MAAM,gBAAgB,IAAI,kBAAwC;;;;;;;;AASlE,MAAM,cAAc,IAAI,kBAA2B;;;;;;;;;;;AAYnD,SAAgB,aAAgB,OAAiB,IAAgB;CAC/D,OAAO,YAAY,IAAI,YAAY,cAAc,IAAI,OAAO,EAAE,CAAC;AACjE;;;;;;;;;AAUA,SAAgB,gBAAmB,IAAgB;CACjD,OAAO,YAAY,IAAI,YAAY,cAAc,IAAI,QAAW,EAAE,CAAC;AACrE;;;;;;;AAQA,SAAgB,kBAAwC;CACtD,OAAO,cAAc,SAAS;AAChC;;;;;;;;AASA,SAAgB,cAAuB;CACrC,OAAO,YAAY,SAAS,MAAM;AACpC;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,SAAgB,mBAAmB,QAA6B;CAC9D,MAAM,QAAQ,cAAc,SAAS;CAErC,IAAI,CAAC,OACH,OAAO;CAGT,OAAO,cAAc,MAAM;CAC3B,OAAO,YAAY,MAAM;CAEzB,IAAI,MAAM,cAAc,QACtB,OAAO,YAAY,MAAM;CAG3B,MAAM,KAAK,KAAK,MAAM;CAEtB,OAAO;AACT"}