{"version":3,"file":"signature.mjs","names":[],"sources":["../../../../../../../ai/src/agent/signature.ts"],"sourcesContent":["import type { AgentConfig } from \"./agent-config.type\";\n\n/**\n * Deterministic structural fingerprint of an agent definition.\n * Persisted on every durable snapshot so `agent.resume()` can detect\n * drift between the saved run and the current definition. Covers the\n * fields whose change would make a mid-run resume unsafe — i.e. would\n * make the persisted `messages` / `toolCalls` array inconsistent with\n * what the resumed trip loop would produce:\n *\n * - Model name + provider — a different model invalidates the prior\n *   conversation's continuation.\n * - The sorted tool names — adding / removing / renaming a tool changes\n *   which dispatches the persisted `toolCalls` could have come from.\n * - `maxTrips` — the loop bound is a semantic shape change.\n * - Whether a default `output` schema is configured — flips the\n *   structured-output instruction baked into the system turn.\n * - `version` — dev-curated; a bump is an explicit \"this changed\" signal.\n *\n * Does NOT cover: system-prompt text, middleware, per-event handlers,\n * placeholders, modelOptions — runtime knobs that don't change the\n * shape of a resumable run. Mirrors `supervisor/signature.ts`'s coarse\n * structural philosophy and reuses its FNV-1a `hash`.\n *\n * `tools` here is read off the resolved config (post-normalization), so\n * raw executables dropped into `tools: []` are already adapted to\n * `ToolContract`s carrying a stable `name`.\n */\nexport function computeAgentSignature(config: {\n  name?: string;\n  version?: AgentConfig[\"version\"];\n  model: { name?: string; provider?: string };\n  tools?: ReadonlyArray<{ name: string }>;\n  maxTrips?: number;\n  output?: unknown;\n}): string {\n  const toolNames = (config.tools ?? [])\n    .map((tool) => tool.name)\n    .sort((a, b) => a.localeCompare(b));\n\n  const fingerprint = {\n    n: config.name ?? null,\n    p: config.model?.provider ?? null,\n    m: config.model?.name ?? null,\n    t: toolNames,\n    x: config.maxTrips ?? null,\n    o: config.output ? 1 : 0,\n    v: config.version ?? null,\n  };\n\n  return hash(JSON.stringify(fingerprint));\n}\n\n/**\n * FNV-1a 32-bit — the same hash `supervisor/signature.ts` and\n * `workflow/signature.ts` use. Deterministic, no crypto dependency,\n * cheap; signatures are 8-char hex.\n */\nfunction hash(input: string): string {\n  let h = 0x811c9dc5;\n\n  for (let i = 0; i < input.length; i++) {\n    h ^= input.charCodeAt(i);\n    h = (h + ((h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24))) >>> 0;\n  }\n\n  return h.toString(16).padStart(8, \"0\");\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,sBAAsB,QAO3B;CACT,MAAM,aAAa,OAAO,SAAS,CAAC,EAAC,CAClC,KAAK,SAAS,KAAK,IAAI,CAAC,CACxB,MAAM,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;CAEpC,MAAM,cAAc;EAClB,GAAG,OAAO,QAAQ;EAClB,GAAG,OAAO,OAAO,YAAY;EAC7B,GAAG,OAAO,OAAO,QAAQ;EACzB,GAAG;EACH,GAAG,OAAO,YAAY;EACtB,GAAG,OAAO,SAAS,IAAI;EACvB,GAAG,OAAO,WAAW;CACvB;CAEA,OAAO,KAAK,KAAK,UAAU,WAAW,CAAC;AACzC;;;;;;AAOA,SAAS,KAAK,OAAuB;CACnC,IAAI,IAAI;CAER,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACrC,KAAK,MAAM,WAAW,CAAC;EACvB,IAAK,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,SAAU;CACxE;CAEA,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG;AACvC"}