{"version":3,"file":"dispatch.mjs","names":["createSupervisor"],"sources":["../../../../../../../ai/src/orchestrator/dispatch.ts"],"sourcesContent":["import type { Message } from \"../contracts/conversation-message.type\";\nimport type { SnapshotStore } from \"../contracts/orchestrator/snapshot-store.contract\";\nimport type { SupervisorResult } from \"../contracts/result/supervisor-result.type\";\nimport type { TurnSnapshot } from \"../contracts/result/orchestrator-result.type\";\nimport type { SupervisorConfig } from \"../contracts/supervisor/supervisor-config.type\";\nimport type { SupervisorInput } from \"../contracts/supervisor/supervisor-input.type\";\nimport type { SupervisorReport } from \"../contracts/result/supervisor-result.type\";\nimport type { OrchestratorEngineContext } from \"./engine-context.type\";\nimport { supervisor as createSupervisor } from \"../supervisor/supervisor\";\n\n/**\n * Derive the deterministic supervisor `runId` for an `iterate: true`\n * turn (orchestrator.md §5 Phase 5 / §10.2 / §18.7):\n * `${sessionId}.${version ?? \"unversioned\"}.${turnIndex}`. No base64,\n * no hashing — the `sessionId` is the dev's responsibility to make\n * unique. Deploying a new `version` cleanly partitions in-flight runs\n * across deploys so old runIds never collide with new ones.\n */\nexport function deriveRunId(\n  sessionId: string,\n  version: string | undefined,\n  turnIndex: number,\n): string {\n  return `${sessionId}.${version ?? \"unversioned\"}.${turnIndex}`;\n}\n\n/** Parameters for one Phase-5 dispatch. */\nexport type DispatchParams<TOutput, TState> = {\n  ctx: OrchestratorEngineContext<TOutput, TState>;\n  sessionId: string;\n  input: SupervisorInput;\n  /** The session-state seed assembled in Phase 1 + the per-call patch. */\n  seedState: TState;\n  turnIndex: number;\n  /** Agent-windowed history from Phase 4. */\n  history: Message[];\n  context?: Record<string, unknown>;\n  signal?: AbortSignal;\n};\n\n/** Outcome of Phase 5 — the supervisor result plus the turn's snapshot. */\nexport type DispatchOutcome<TOutput> = {\n  result: SupervisorResult<TOutput>;\n  /** Post-dispatch session state (replaces session state per §5). */\n  state: unknown;\n  turnSnapshot: TurnSnapshot;\n};\n\n/**\n * Build the internal supervisor config by spreading the orchestrator's\n * supervisor-surface fields (orchestrator.md §1 / §5 Phase 5) and\n * seeding `state` from the session-state seed.\n *\n * `iterate: false` caps `maxIterations` at 1 — a single dispatch per\n * turn (\"the supervisor's Phase A + Phase B once, no iteration loop\" —\n * §5). `iterate: true` keeps the configured `maxIterations` (default\n * 10) and wires the `snapshotStore` for mid-turn resume.\n *\n * The orchestrator DELEGATES to the existing supervisor — it never\n * reimplements dispatch / route / evaluate / strip-merge logic.\n */\nfunction buildSupervisorConfig<TOutput, TState>(\n  ctx: OrchestratorEngineContext<TOutput, TState>,\n  seedState: TState,\n  iterate: boolean,\n  snapshotStore: SnapshotStore | undefined,\n): SupervisorConfig<TOutput, TState> {\n  const config = ctx.config;\n\n  const supervisorConfig: SupervisorConfig<TOutput, TState> = {\n    name: config.name,\n    version: config.version,\n    systemPrompt: config.systemPrompt,\n    intents: config.intents,\n    route: config.route,\n    router: config.router,\n    evaluate: config.evaluate,\n    state: seedState,\n    output: config.output,\n    initialAgent: config.initialAgent,\n    maxIterations: iterate ? config.maxIterations : 1,\n    historyWindow: config.historyWindow\n      ? { router: toNumber(config.historyWindow.router), agents: toNumber(config.historyWindow.agents) }\n      : undefined,\n    snapshotStore: iterate ? snapshotStore : undefined,\n  };\n\n  return supervisorConfig;\n}\n\n/**\n * The supervisor's `historyWindow` tiers accept only numbers; the\n * orchestrator's accept a number OR a slicer callback. The callback\n * form is already applied at the orchestrator level (Phase 4), so any\n * non-number here has already done its slicing — drop it for the\n * supervisor (which sees the pre-sliced history) by returning\n * `undefined`.\n */\nfunction toNumber(\n  value: number | ((messages: Message[]) => Message[]) | undefined,\n): number | undefined {\n  return typeof value === \"number\" ? value : undefined;\n}\n\n/**\n * Build the forensic {@link TurnSnapshot} for the dispatched turn from\n * the supervisor's result. Mirrors the supervisor's `IterationSnapshot`\n * shape (§15.5) so a turn reads uniformly whether one agent ran\n * (`iterate: false`) or the internal supervisor iterated\n * (`iterate: true`). The terminal iteration's branch records and\n * decision are lifted onto the turn; the supervisor's full report tree\n * becomes the turn's `childReport`.\n */\nfunction buildTurnSnapshot(\n  input: SupervisorInput,\n  turnIndex: number,\n  result: SupervisorResult<unknown>,\n  state: unknown,\n): TurnSnapshot {\n  const report = result.report;\n  const snapshots = report.snapshots;\n  const terminal = snapshots.length > 0 ? snapshots[snapshots.length - 1] : undefined;\n\n  const decisionSource = mapDecisionSource(terminal?.decision.source);\n\n  return Object.freeze({\n    turn: turnIndex,\n    input,\n    decision: {\n      source: decisionSource,\n      raw: terminal?.decision.next ?? null,\n      reasoning: terminal?.decision.reasoning,\n    },\n    result: terminal?.result ?? {},\n    state,\n    evaluate: terminal?.evaluateVerdict,\n    startedAt: report.startedAt,\n    endedAt: report.endedAt,\n    duration: report.duration,\n    usage: report.usage,\n    childReport: report,\n  });\n}\n\n/**\n * Map the supervisor's `DecisionSource` onto the narrower turn-snapshot\n * decision source (§15.5 — `\"route\" | \"router\" | \"intent.next\"`). The\n * supervisor's `initialAgent` / `classifier` first-turn sources collapse\n * to `\"intent.next\"` (a non-route/router origin) at the orchestrator\n * layer, which only distinguishes the three coarse decision origins.\n */\nfunction mapDecisionSource(\n  source: \"route\" | \"router\" | \"initialAgent\" | \"classifier\" | undefined,\n): \"route\" | \"router\" | \"intent.next\" {\n  if (source === \"route\" || source === \"router\") {\n    return source;\n  }\n\n  return \"intent.next\";\n}\n\n/**\n * Phase 5 — dispatch turn (orchestrator.md §3 / §4 Phase 5).\n *\n * Constructs a fresh internal supervisor seeded from the session state,\n * then:\n *\n * - `iterate: false` — runs a single dispatch (`maxIterations: 1`).\n * - `iterate: true` — runs the full supervisor with a deterministic\n *   `runId`, resuming an in-flight run when the `SnapshotStore` already\n *   has one for that `runId` (§5 step 5).\n *\n * The supervisor's final state replaces the session state (§5 — replace\n * semantics). The supervisor is never kept alive across turns\n * (single-call lifecycle invariant — §18.8).\n */\nexport async function dispatchTurn<TOutput, TState>(\n  params: DispatchParams<TOutput, TState>,\n): Promise<DispatchOutcome<TOutput>> {\n  const { ctx, sessionId, input, seedState, turnIndex, history, context, signal } =\n    params;\n\n  const iterate = ctx.config.iterate === true;\n  const sup = createSupervisor<TOutput, TState>(\n    buildSupervisorConfig(ctx, seedState, iterate, ctx.snapshotStore),\n  );\n\n  let result: SupervisorResult<TOutput>;\n\n  if (iterate) {\n    const runId = deriveRunId(sessionId, ctx.config.version, turnIndex);\n    const inFlight = ctx.snapshotStore\n      ? await ctx.snapshotStore.load(runId)\n      : undefined;\n\n    if (inFlight && inFlight.status === \"running\") {\n      result = await sup.resume(runId, { context, signal, history, sessionId });\n    } else {\n      result = await sup.execute(input, { runId, context, signal, history, sessionId });\n    }\n  } else {\n    result = await sup.execute(input, { context, signal, history, sessionId });\n  }\n\n  const state = deriveFinalState(result, seedState);\n  const turnSnapshot = buildTurnSnapshot(input, turnIndex, result, state);\n\n  return { result, state, turnSnapshot };\n}\n\n/**\n * Derive the post-turn session state from the supervisor result.\n * Prefers the terminal iteration's accumulated `state`; falls back to\n * the validated `data` (when an `output` schema reshaped it), then to\n * the seed when the run produced neither (e.g. it terminated before\n * dispatching anything). Replace semantics — the supervisor is the\n * authority on state evolution within its loop (§5).\n */\nfunction deriveFinalState<TOutput, TState>(\n  result: SupervisorResult<TOutput>,\n  seedState: TState,\n): unknown {\n  const report: SupervisorReport = result.report;\n  const snapshots = report.snapshots;\n  const terminal = snapshots.length > 0 ? snapshots[snapshots.length - 1] : undefined;\n\n  if (terminal && terminal.state !== undefined) {\n    return terminal.state;\n  }\n\n  if (result.data !== undefined) {\n    return result.data;\n  }\n\n  return seedState;\n}\n"],"mappings":";;;;;;;;;;;AAkBA,SAAgB,YACd,WACA,SACA,WACQ;CACR,OAAO,GAAG,UAAU,GAAG,WAAW,cAAc,GAAG;AACrD;;;;;;;;;;;;;;AAqCA,SAAS,sBACP,KACA,WACA,SACA,eACmC;CACnC,MAAM,SAAS,IAAI;CAoBnB,OAAO;EAjBL,MAAM,OAAO;EACb,SAAS,OAAO;EAChB,cAAc,OAAO;EACrB,SAAS,OAAO;EAChB,OAAO,OAAO;EACd,QAAQ,OAAO;EACf,UAAU,OAAO;EACjB,OAAO;EACP,QAAQ,OAAO;EACf,cAAc,OAAO;EACrB,eAAe,UAAU,OAAO,gBAAgB;EAChD,eAAe,OAAO,gBAClB;GAAE,QAAQ,SAAS,OAAO,cAAc,MAAM;GAAG,QAAQ,SAAS,OAAO,cAAc,MAAM;EAAE,IAC/F;EACJ,eAAe,UAAU,gBAAgB;CAGrB;AACxB;;;;;;;;;AAUA,SAAS,SACP,OACoB;CACpB,OAAO,OAAO,UAAU,WAAW,QAAQ;AAC7C;;;;;;;;;;AAWA,SAAS,kBACP,OACA,WACA,QACA,OACc;CACd,MAAM,SAAS,OAAO;CACtB,MAAM,YAAY,OAAO;CACzB,MAAM,WAAW,UAAU,SAAS,IAAI,UAAU,UAAU,SAAS,KAAK;CAE1E,MAAM,iBAAiB,kBAAkB,UAAU,SAAS,MAAM;CAElE,OAAO,OAAO,OAAO;EACnB,MAAM;EACN;EACA,UAAU;GACR,QAAQ;GACR,KAAK,UAAU,SAAS,QAAQ;GAChC,WAAW,UAAU,SAAS;EAChC;EACA,QAAQ,UAAU,UAAU,CAAC;EAC7B;EACA,UAAU,UAAU;EACpB,WAAW,OAAO;EAClB,SAAS,OAAO;EAChB,UAAU,OAAO;EACjB,OAAO,OAAO;EACd,aAAa;CACf,CAAC;AACH;;;;;;;;AASA,SAAS,kBACP,QACoC;CACpC,IAAI,WAAW,WAAW,WAAW,UACnC,OAAO;CAGT,OAAO;AACT;;;;;;;;;;;;;;;;AAiBA,eAAsB,aACpB,QACmC;CACnC,MAAM,EAAE,KAAK,WAAW,OAAO,WAAW,WAAW,SAAS,SAAS,WACrE;CAEF,MAAM,UAAU,IAAI,OAAO,YAAY;CACvC,MAAM,MAAMA,WACV,sBAAsB,KAAK,WAAW,SAAS,IAAI,aAAa,CAClE;CAEA,IAAI;CAEJ,IAAI,SAAS;EACX,MAAM,QAAQ,YAAY,WAAW,IAAI,OAAO,SAAS,SAAS;EAClE,MAAM,WAAW,IAAI,gBACjB,MAAM,IAAI,cAAc,KAAK,KAAK,IAClC;EAEJ,IAAI,YAAY,SAAS,WAAW,WAClC,SAAS,MAAM,IAAI,OAAO,OAAO;GAAE;GAAS;GAAQ;GAAS;EAAU,CAAC;OAExE,SAAS,MAAM,IAAI,QAAQ,OAAO;GAAE;GAAO;GAAS;GAAQ;GAAS;EAAU,CAAC;CAEpF,OACE,SAAS,MAAM,IAAI,QAAQ,OAAO;EAAE;EAAS;EAAQ;EAAS;CAAU,CAAC;CAG3E,MAAM,QAAQ,iBAAiB,QAAQ,SAAS;CAChD,MAAM,eAAe,kBAAkB,OAAO,WAAW,QAAQ,KAAK;CAEtE,OAAO;EAAE;EAAQ;EAAO;CAAa;AACvC;;;;;;;;;AAUA,SAAS,iBACP,QACA,WACS;CAET,MAAM,YAD2B,OAAO,OACf;CACzB,MAAM,WAAW,UAAU,SAAS,IAAI,UAAU,UAAU,SAAS,KAAK;CAE1E,IAAI,YAAY,SAAS,UAAU,QACjC,OAAO,SAAS;CAGlB,IAAI,OAAO,SAAS,QAClB,OAAO,OAAO;CAGhB,OAAO;AACT"}