{"version":3,"file":"team.mjs","names":[],"sources":["../../../../../../../ai/src/team/team.ts"],"sourcesContent":["import type {\n  EvaluateContext,\n  EvaluateResult,\n} from \"../contracts/supervisor/evaluate-context.type\";\nimport type { SupervisorIntentValue } from \"../contracts/supervisor/intent-entry.type\";\nimport type { SupervisorConfig } from \"../contracts/supervisor/supervisor-config.type\";\nimport type { SupervisorContract } from \"../contracts/supervisor/supervisor.contract\";\nimport type {\n  TeamConfig,\n  TeamGate,\n  TeamGateFn,\n  TeamMemberValue,\n} from \"../contracts/team/team-config.type\";\nimport { SupervisorFailedError } from \"../errors\";\nimport { supervisor } from \"../supervisor/supervisor\";\nimport { buildQualityGate, buildVerifyGate } from \"./gates\";\n\n/**\n * `ai.team(config)` — thin, transparent sugar over `ai.supervisor`.\n *\n * Builds a {@link SupervisorConfig} from the team-shaped config and\n * calls `supervisor(...)`, returning the **unchanged**\n * `SupervisorContract<TOutput>` — the same object `ai.supervisor`\n * returns, so `ctx.intents.<member>.execute()`, `.asTool()`,\n * `.resume()`, snapshots, and events all stay intact. `team()` owns no\n * loop: the manager becomes `route`/`router`, the members become\n * `intents`, and the `gate` becomes `evaluate`. Everything else passes\n * through 1:1.\n *\n * A `gate: \"quality\" | \"verify\"` string selects a pre-built `evaluate`\n * strategy ({@link buildQualityGate} / {@link buildVerifyGate}); a\n * function forwards straight to `SupervisorConfig.evaluate` (full\n * escape hatch). When the gate is a string, the resolved `fixer` (and,\n * for `\"quality\"`, the `reviewer`) roles are validated against\n * `members` at construction — a missing role throws an authoring-style\n * {@link SupervisorFailedError} (`context: { authoring: true }`) rather\n * than silently starving until `maxIterations`.\n *\n * @example\n * const codeTeam = ai.team({\n *   name: \"code-team\",\n *   goal: \"Ship a tested module that passes review.\",\n *   manager: techLeadRouter,\n *   members: { builder, reviewer, fixer },\n *   gate: \"quality\",\n *   output: v.object({ code: v.string() }),\n *   maxIterations: 6,\n * });\n *\n * const { data, report } = await codeTeam.execute(\"Build a debounce<T> utility.\");\n */\nexport function team<\n  TOutput = unknown,\n  TState = TOutput,\n  TMembers extends Record<string, TeamMemberValue> = Record<string, TeamMemberValue>,\n>(config: TeamConfig<TOutput, TState, TMembers>): SupervisorContract<TOutput> {\n  const supervisorConfig: SupervisorConfig<TOutput, TState> = {\n    name: config.name,\n    version: config.version,\n    // Stamp the report/result discriminator as \"team\" so team runs are\n    // distinguishable on the wire (Panoptic groups/filters them as their\n    // own type) — the only behavioural difference from a plain supervisor.\n    reportType: \"team\",\n    intents: config.members as unknown as Record<string, SupervisorIntentValue>,\n    evaluate: resolveGate<TOutput, TState, TMembers>(config),\n    goal: config.goal,\n    output: config.output,\n    state: config.state,\n    maxIterations: config.maxIterations,\n    snapshotStore: config.snapshotStore,\n    on: config.on,\n    // Forward observability verbatim — the supervisor `team()` returns\n    // routes its report through the generic Observer seam, so a team\n    // inherits observation with no team-specific wiring (F1/F3).\n    observe: config.observe,\n  };\n\n  // Manager → `route` XOR `router`. Reuse the supervisor's own XOR\n  // validation; team() forwards exactly one of the two, so a malformed\n  // manager surfaces the existing SupervisorFailedError downstream.\n  if (isRouteManager(config.manager)) {\n    supervisorConfig.route = config.manager.route;\n  } else {\n    supervisorConfig.router = config.manager;\n  }\n\n  return supervisor<TOutput, TState>(supervisorConfig);\n}\n\n/**\n * Resolve the team's `gate` into a concrete `evaluate` callback. A\n * function forwards untouched; a {@link TeamGate} string is validated\n * against `members` and desugared into the matching pre-built gate.\n */\nfunction resolveGate<\n  TOutput,\n  TState,\n  TMembers extends Record<string, TeamMemberValue>,\n>(\n  config: TeamConfig<TOutput, TState, TMembers>,\n): (ctx: EvaluateContext<TState>) => EvaluateResult | Promise<EvaluateResult> {\n  if (typeof config.gate === \"function\") {\n    return config.gate as TeamGateFn<TState>;\n  }\n\n  const gate: TeamGate = config.gate;\n  const fixerRole = config.roles?.fixer ?? \"fixer\";\n\n  assertMemberExists(config, fixerRole, \"fixer\");\n\n  if (gate === \"quality\") {\n    const reviewerRole = config.roles?.reviewer ?? \"reviewer\";\n\n    assertMemberExists(config, reviewerRole, \"reviewer\");\n\n    const gateKey = config.gateKey ?? \"approved\";\n\n    return buildQualityGate<TState>(gateKey, fixerRole);\n  }\n\n  const gateKey = config.gateKey ?? \"passed\";\n\n  return buildVerifyGate<TState>(gateKey, fixerRole);\n}\n\n/**\n * Construction-time guard: assert the resolved role key exists in\n * `members`, throwing an authoring-style {@link SupervisorFailedError}\n * (tagged `authoring: true`) listing the missing role when it doesn't.\n */\nfunction assertMemberExists<\n  TOutput,\n  TState,\n  TMembers extends Record<string, TeamMemberValue>,\n>(\n  config: TeamConfig<TOutput, TState, TMembers>,\n  role: string,\n  label: string,\n): void {\n  if (!Object.prototype.hasOwnProperty.call(config.members, role)) {\n    throw new SupervisorFailedError(\n      `ai.team(\"${config.name}\"): gate \"${config.gate as string}\" needs a \"${label}\" member but no \\`members.${role}\\` key exists`,\n      { context: { authoring: true } },\n    );\n  }\n}\n\n/**\n * Discriminate the `manager` union: `true` when it is the deterministic\n * `{ route }` form, `false` for a bare `AgentContract` / `RouterEntry`.\n */\nfunction isRouteManager<TOutput, TState>(\n  manager: TeamConfig<TOutput, TState>[\"manager\"],\n): manager is { route: NonNullable<SupervisorConfig<TOutput, TState>[\"route\"]> } {\n  return (\n    typeof manager === \"object\" &&\n    manager !== null &&\n    \"route\" in manager &&\n    typeof (manager as { route?: unknown }).route === \"function\"\n  );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmDA,SAAgB,KAId,QAA4E;CAC5E,MAAM,mBAAsD;EAC1D,MAAM,OAAO;EACb,SAAS,OAAO;EAIhB,YAAY;EACZ,SAAS,OAAO;EAChB,UAAU,YAAuC,MAAM;EACvD,MAAM,OAAO;EACb,QAAQ,OAAO;EACf,OAAO,OAAO;EACd,eAAe,OAAO;EACtB,eAAe,OAAO;EACtB,IAAI,OAAO;EAIX,SAAS,OAAO;CAClB;CAKA,IAAI,eAAe,OAAO,OAAO,GAC/B,iBAAiB,QAAQ,OAAO,QAAQ;MAExC,iBAAiB,SAAS,OAAO;CAGnC,OAAO,WAA4B,gBAAgB;AACrD;;;;;;AAOA,SAAS,YAKP,QAC4E;CAC5E,IAAI,OAAO,OAAO,SAAS,YACzB,OAAO,OAAO;CAGhB,MAAM,OAAiB,OAAO;CAC9B,MAAM,YAAY,OAAO,OAAO,SAAS;CAEzC,mBAAmB,QAAQ,WAAW,OAAO;CAE7C,IAAI,SAAS,WAAW;EAGtB,mBAAmB,QAFE,OAAO,OAAO,YAAY,YAEN,UAAU;EAInD,OAAO,iBAFS,OAAO,WAAW,YAEO,SAAS;CACpD;CAIA,OAAO,gBAFS,OAAO,WAAW,UAEM,SAAS;AACnD;;;;;;AAOA,SAAS,mBAKP,QACA,MACA,OACM;CACN,IAAI,CAAC,OAAO,UAAU,eAAe,KAAK,OAAO,SAAS,IAAI,GAC5D,MAAM,IAAI,sBACR,YAAY,OAAO,KAAK,YAAY,OAAO,KAAe,aAAa,MAAM,4BAA4B,KAAK,gBAC9G,EAAE,SAAS,EAAE,WAAW,KAAK,EAAE,CACjC;AAEJ;;;;;AAMA,SAAS,eACP,SAC+E;CAC/E,OACE,OAAO,YAAY,YACnB,YAAY,QACZ,WAAW,WACX,OAAQ,QAAgC,UAAU;AAEtD"}