{"version":3,"file":"mock-router.mjs","names":[],"sources":["../../../../../../../ai/src/mock/mock-router.ts"],"sourcesContent":["import { END } from \"../contracts/end.type\";\nimport type { Next } from \"../contracts/supervisor/next.type\";\nimport type { RouteContext } from \"../contracts/supervisor/route-context.type\";\n\n/**\n * A canned routing decision for {@link mockRouter}. Either a literal\n * {@link Next} value (intent key, fan-out array, or the `END`\n * sentinel) or a predicate that derives the decision from the live\n * {@link RouteContext} — the latter lets a test branch on accumulated\n * state without scripting an exact per-iteration sequence.\n */\nexport type MockRouterDecision<TState = Record<string, unknown>> =\n  | Next\n  | ((context: RouteContext<TState>) => Next);\n\n/**\n * Behavior when the canned decision queue is exhausted before the\n * supervisor terminates on its own.\n *\n * - `\"end\"` (default) — return `END`, terminating the run cleanly. The\n *   common case: script the interesting turns, let the run stop.\n * - `\"throw\"` — throw, surfacing the over-run as a test failure. Use\n *   when every iteration must be accounted for.\n * - `\"repeat\"` — replay the last decision for every further iteration.\n *   Useful for \"keep routing to the same intent until evaluate is\n *   satisfied\" scenarios.\n */\nexport type MockRouterExhaustion = \"end\" | \"throw\" | \"repeat\";\n\n/**\n * Options for {@link mockRouter}.\n */\nexport type MockRouterOptions = {\n  /** What to do once the decision queue is exhausted. Default `\"end\"`. */\n  onExhausted?: MockRouterExhaustion;\n};\n\n/**\n * Build a deterministic `route` callback that replays a canned\n * sequence of routing decisions — one per supervisor iteration — for\n * testing supervisors without an LLM router.\n *\n * Drop the returned callback into `ai.supervisor({ route: mockRouter([...]) })`\n * in place of an LLM `router`. The Nth iteration consumes the Nth\n * decision; a function decision is evaluated against the live\n * `RouteContext`. When the queue runs out, behavior follows\n * `options.onExhausted` (default: terminate with `END`).\n *\n * Pairs with the `toRouteTo` / `toConverge` matchers to assert the\n * resulting report tree.\n *\n * @example\n * const supervisor = ai.supervisor({\n *   name: \"draft-then-review\",\n *   intents: { writer, critic },\n *   route: mockRouter([\"writer\", \"critic\", END]),\n * });\n *\n * @example\n * // Branch on accumulated state, repeat the last decision until done.\n * route: mockRouter(\n *   [\"research\", (ctx) => (ctx.state.summary ? END : \"research\")],\n *   { onExhausted: \"repeat\" },\n * );\n */\nexport function mockRouter<TState = Record<string, unknown>>(\n  decisions: MockRouterDecision<TState>[],\n  options: MockRouterOptions = {},\n): (context: RouteContext<TState>) => Next {\n  const onExhausted = options.onExhausted ?? \"end\";\n  let cursor = 0;\n\n  return (context: RouteContext<TState>): Next => {\n    if (cursor < decisions.length) {\n      const decision = decisions[cursor];\n      cursor++;\n\n      return resolveDecision(decision, context);\n    }\n\n    if (onExhausted === \"throw\") {\n      throw new Error(\n        `mockRouter exhausted after ${decisions.length} decision(s) at iteration ${context.iteration}`,\n      );\n    }\n\n    if (onExhausted === \"repeat\" && decisions.length > 0) {\n      return resolveDecision(decisions[decisions.length - 1], context);\n    }\n\n    return END;\n  };\n}\n\n/**\n * Resolve a single decision entry into a concrete {@link Next} —\n * invoking the predicate form against the live context, or returning\n * the literal form verbatim.\n */\nfunction resolveDecision<TState>(\n  decision: MockRouterDecision<TState>,\n  context: RouteContext<TState>,\n): Next {\n  if (typeof decision === \"function\") {\n    return decision(context);\n  }\n\n  return decision;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiEA,SAAgB,WACd,WACA,UAA6B,CAAC,GACW;CACzC,MAAM,cAAc,QAAQ,eAAe;CAC3C,IAAI,SAAS;CAEb,QAAQ,YAAwC;EAC9C,IAAI,SAAS,UAAU,QAAQ;GAC7B,MAAM,WAAW,UAAU;GAC3B;GAEA,OAAO,gBAAgB,UAAU,OAAO;EAC1C;EAEA,IAAI,gBAAgB,SAClB,MAAM,IAAI,MACR,8BAA8B,UAAU,OAAO,4BAA4B,QAAQ,WACrF;EAGF,IAAI,gBAAgB,YAAY,UAAU,SAAS,GACjD,OAAO,gBAAgB,UAAU,UAAU,SAAS,IAAI,OAAO;EAGjE,OAAO;CACT;AACF;;;;;;AAOA,SAAS,gBACP,UACA,SACM;CACN,IAAI,OAAO,aAAa,YACtB,OAAO,SAAS,OAAO;CAGzB,OAAO;AACT"}