{"version":3,"sources":["../src/agent.ts"],"sourcesContent":["/**\n * Copyright 2026 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n  GenkitError,\n  deepEqual,\n  defineAction,\n  defineBidiAction,\n  getContext,\n  run,\n  z,\n  type Action,\n  type ActionContext,\n  type ActionFnArg,\n  type BidiAction,\n} from '@genkit-ai/core';\nimport { Channel } from '@genkit-ai/core/async';\nimport type { Registry } from '@genkit-ai/core/registry';\nimport {\n  createAgentAPI,\n  type AgentAPI,\n  type AgentTransport,\n  type SnapshotLookup,\n} from './agent-core.mjs';\n\nimport { parseSchema, toJsonSchema } from '@genkit-ai/core/schema';\nimport {\n  setCustomMetadataAttribute,\n  setCustomMetadataAttributes,\n} from '@genkit-ai/core/tracing';\nimport {\n  AgentAbortRequestSchema,\n  AgentAbortResponseSchema,\n  AgentInitSchema,\n  AgentInputSchema,\n  AgentOutputSchema,\n  AgentStreamChunkSchema,\n  GetSnapshotRequestSchema,\n  type AgentInit,\n  type AgentInput,\n  type AgentResult,\n  type AgentStreamChunk,\n} from './agent-types.mjs';\nimport { generateStream } from './generate.mjs';\nimport { diff, type JsonPatch } from './json-patch.mjs';\nimport { MessageData } from './model-types.mjs';\nimport { type ToolRequestPart, type ToolResponsePart } from './parts.mjs';\nimport {\n  definePrompt,\n  type PromptAction,\n  type PromptConfig,\n} from './prompt.mjs';\nimport { InMemorySessionStore } from './session-stores.mjs';\nimport {\n  Session,\n  SessionSnapshot,\n  SessionSnapshotSchema,\n  SessionState,\n  SessionStore,\n  reserveSnapshotId,\n  runWithSession,\n  type AgentFinishReason,\n  type Artifact,\n  type SessionSnapshotInput,\n  type SessionStoreOptions,\n} from './session.mjs';\n\n// Re-export the shared agent/session wire schemas + types from their canonical\n// home (./agent-types.ts) so existing imports from './agent.mjs' (and the\n// package barrel) keep working.\nexport {\n  AgentAbortRequestSchema,\n  AgentAbortResponseSchema,\n  AgentInitSchema,\n  AgentInputSchema,\n  AgentOutputSchema,\n  AgentResultSchema,\n  AgentStreamChunkSchema,\n  GetSnapshotRequestSchema,\n  JsonPatchOperationSchema,\n  JsonPatchSchema,\n  TurnEndSchema,\n  type AgentInit,\n  type AgentInput,\n  type AgentResult,\n  type AgentStreamChunk,\n  type TurnEnd,\n} from './agent-types.mjs';\n\n/**\n * Default interval (ms) at which a detached (background) turn refreshes its\n * pending snapshot's heartbeat. Each beat is a write to the session store.\n */\nconst DEFAULT_HEARTBEAT_INTERVAL_MS = 30_000;\n\n/**\n * Default staleness threshold (ms) after which a `pending` snapshot whose\n * heartbeat has not advanced is reported as `expired` on read. Should be\n * comfortably larger than {@link DEFAULT_HEARTBEAT_INTERVAL_MS} so a single\n * missed beat does not trip expiry.\n */\nconst DEFAULT_HEARTBEAT_TIMEOUT_MS = 60_000;\n\n/**\n * Returns `true` when a snapshot is a `pending` (detached, in-flight) snapshot\n * whose heartbeat is older than `timeoutMs` - i.e. its background worker is\n * presumed dead. A pending snapshot that has not yet written a first heartbeat\n * is not considered expired (the beat may simply not have fired yet).\n */\nfunction isHeartbeatExpired(\n  snapshot: SessionSnapshot,\n  timeoutMs: number = DEFAULT_HEARTBEAT_TIMEOUT_MS\n): boolean {\n  if (snapshot.status !== 'pending' || !snapshot.heartbeatAt) {\n    return false;\n  }\n  const last = Date.parse(snapshot.heartbeatAt);\n  if (Number.isNaN(last)) {\n    return false;\n  }\n  return Date.now() - last > timeoutMs;\n}\n\n/**\n * Result returned by a single turn handler passed to {@link SessionRunner.run}.\n *\n * Returning a `finishReason` lets a custom agent explicitly state why the turn\n * ended (e.g. `interrupted`, `length`). When omitted, no per-turn reason is\n * reported.\n */\nexport interface TurnResult {\n  finishReason?: AgentFinishReason;\n}\n\n/**\n * Per-turn context handed to the handler passed to {@link SessionRunner.run}.\n *\n * The `snapshotId` is *reserved at turn start* (before the handler runs) and is\n * the id the snapshot persisted at turn end will reuse. This lets a handler\n * name external, snapshot-correlated resources - e.g. a git branch / worktree\n * named after the snapshot - up front, then commit them under that id, so a\n * later rollback to the snapshot can restore the external state too.\n */\nexport interface TurnContext {\n  /**\n   * The id the snapshot produced by this turn will be saved under (reserved\n   * ahead of time so it is known before the turn runs).\n   */\n  snapshotId: string;\n  /**\n   * The id of the parent snapshot this turn continues from, or `undefined` on\n   * the first turn of a fresh session.\n   */\n  parentSnapshotId?: string;\n  /** Zero-based index of this turn within the current invocation. */\n  turnIndex: number;\n}\n\n/**\n * Output returned at turn completion.\n */\nexport interface AgentOutput<S = unknown> {\n  sessionId?: string;\n  artifacts?: Artifact[];\n  message?: MessageData;\n  snapshotId?: string;\n  state?: SessionState<S>;\n  finishReason?: AgentFinishReason;\n  /**\n   * Present when `finishReason` is `failed`. Carries the original error\n   * details (RuntimeError shape); `state`/`snapshotId` hold the last-good state.\n   */\n  error?: {\n    status?: string;\n    message: string;\n    details?: any;\n  };\n}\n\n/**\n * Structured error details surfaced on the failure path.\n */\ninterface AgentErrorDetails {\n  status: string;\n  message: string;\n  details?: any;\n}\n\n/**\n * Normalizes a thrown value into the structured error shape used across the\n * agent (in `AgentOutput.error` and `SessionRunner.lastTurnError`).\n */\nfunction toErrorDetails(e: any): AgentErrorDetails {\n  return {\n    status: e?.status || 'INTERNAL',\n    message: e?.message || 'Internal failure',\n    // Only surface explicitly-provided structured details. Never fall back to\n    // the raw thrown value: it is serialized over the wire (AgentOutput.error)\n    // and persisted into snapshots, so leaking it could expose stack traces /\n    // internal state, or break JSON.stringify on circular error objects.\n    details: e?.detail ?? e?.details,\n  };\n}\n\n/**\n * Builds an abort-aware `saveSnapshot` mutator: it skips the write (returns\n * `null`) when the current snapshot was concurrently aborted, otherwise writes\n * `input`. This prevents a \"done\"/\"failed\" write from clobbering an \"aborted\"\n * status set by a concurrent abort.\n */\nfunction abortAwareMutator<S>(input: SessionSnapshotInput<S>) {\n  return (current: SessionSnapshot<S> | undefined) =>\n    current?.status === 'aborted' ? null : input;\n}\n\n/**\n * Asserts that an operation requiring a persistent store is not being invoked\n * on a store-less (client-managed) agent.\n */\nfunction requireStore<S>(\n  store: SessionStore<S> | undefined,\n  operation: string,\n  agentName: string\n): asserts store is SessionStore<S> {\n  if (!store) {\n    throw new GenkitError({\n      status: 'FAILED_PRECONDITION',\n      message: `${operation} requires a persistent store. Provide a 'store' when defining '${agentName}'.`,\n    });\n  }\n}\n\n/**\n * Sets a snapshot's status to `aborted` (unless it already reached a terminal\n * state) and returns its previous status, or `undefined` when the snapshot\n * does not exist.\n */\nasync function abortSnapshotInStore<S>(\n  store: SessionStore<S>,\n  snapshotId: string,\n  options?: SessionStoreOptions\n): Promise<SessionSnapshot['status'] | undefined> {\n  let previousStatus: SessionSnapshot['status'] | undefined;\n  await store.saveSnapshot(\n    snapshotId,\n    (current) => {\n      if (!current) return null;\n      previousStatus = current.status;\n      if (\n        current.status === 'completed' ||\n        current.status === 'failed' ||\n        current.status === 'aborted'\n      ) {\n        return null; // Already terminal - don't override.\n      }\n      return { ...current, status: 'aborted' };\n    },\n    options\n  );\n  return previousStatus;\n}\n\n/**\n * Executor responsible for running turns over input streams and persisting state.\n */\nexport class SessionRunner<State = unknown> {\n  readonly session: Session<State>;\n  readonly inputCh: AsyncIterable<AgentInput>;\n\n  turnIndex: number = 0;\n  public onEndTurn?: (\n    snapshotId?: string,\n    finishReason?: AgentFinishReason\n  ) => void;\n  public onDetach?: (snapshotId: string) => void;\n  public newSnapshotId?: string;\n  /** The finish reason of the most recently completed turn. */\n  public lastTurnFinishReason?: AgentFinishReason;\n  /**\n   * Error details of the most recent failed turn. Set when a turn throws and\n   * the runner resolves gracefully instead of propagating the exception.\n   */\n  public lastTurnError?: AgentErrorDetails;\n  /**\n   * The state the most recently *successful* turn left behind. On a failed\n   * turn this is the state the failed turn started with - the last-good state\n   * returned to the caller (for client-managed agents).\n   */\n  public lastGoodState?: SessionState<State>;\n  /**\n   * The snapshotId of the most recently *successful* (persisted, `done`) turn.\n   * On a failed turn this is the last-good snapshot the caller resumes from;\n   * `undefined` when no turn has succeeded yet (e.g. a first-turn failure).\n   */\n  public lastGoodSnapshotId?: string;\n  private lastSnapshot?: SessionSnapshot<State>;\n\n  private lastSnapshotVersion: number = 0;\n\n  private store?: SessionStore<State>;\n  public isDetached: boolean = false;\n  /**\n   * Aborts in-flight turns. When set and aborted, a turn that rejects out of\n   * `generate` is reported as `aborted` (not `failed`) and its failed snapshot\n   * write is skipped (the abort path already persisted the `aborted` status).\n   */\n  private abortSignal?: AbortSignal;\n\n  /**\n   * True until the first `customPatch` chunk of the current turn has been\n   * emitted. The first patch of every turn is a whole-document replace\n   * (re-basing clients that may not share the server's baseline); reset to\n   * `true` at the start of each turn.\n   */\n  public firstCustomPatchInTurn: boolean = true;\n\n  constructor(\n    session: Session<State>,\n    inputCh: AsyncIterable<AgentInput>,\n    options?: {\n      lastSnapshot?: SessionSnapshot<State>;\n      store?: SessionStore<State>;\n      abortSignal?: AbortSignal;\n      onEndTurn?: (\n        snapshotId?: string,\n        finishReason?: AgentFinishReason\n      ) => void;\n      onDetach?: (snapshotId: string) => void;\n    }\n  ) {\n    this.session = session;\n    this.inputCh = inputCh;\n\n    this.lastSnapshot = options?.lastSnapshot;\n    this.store = options?.store;\n    this.abortSignal = options?.abortSignal;\n    this.onEndTurn = options?.onEndTurn;\n    this.onDetach = options?.onDetach;\n\n    // Seed the last-good state with the initial session state so that a\n    // failure on the very first turn still has a valid state to fall back to\n    // (the seed/loaded state, excluding the failed turn's mutations). The\n    // last-good snapshotId is undefined until a turn successfully persists.\n    this.lastGoodState = this.session.getState();\n    this.lastGoodSnapshotId = options?.lastSnapshot?.snapshotId;\n  }\n\n  // ── Session delegate methods ────────────────────────────────────────\n  // These forward to `this.session` so callers can write `sess.addMessages()`\n  // instead of the verbose `sess.session.addMessages()`.\n\n  /** Returns a deep copy of the current session state. */\n  getState(): SessionState<State> {\n    return this.session.getState();\n  }\n\n  /** Retrieves all messages associated with the session. */\n  getMessages(): MessageData[] {\n    return this.session.getMessages();\n  }\n\n  /** Appends messages to the session. */\n  addMessages(messages: MessageData[]): void {\n    this.session.addMessages(messages);\n  }\n\n  /** Overwrites the session messages. */\n  setMessages(messages: MessageData[]): void {\n    this.session.setMessages(messages);\n  }\n\n  /** Retrieves the custom state of the session. */\n  getCustom(): State | undefined {\n    return this.session.getCustom();\n  }\n\n  /** Updates the custom state using a mutator function. */\n  updateCustom(fn: (custom?: State) => State): void {\n    this.session.updateCustom(fn);\n  }\n\n  /** Retrieves the list of artifacts generated during the session. */\n  getArtifacts(): Artifact[] {\n    return this.session.getArtifacts();\n  }\n\n  /** Adds artifacts to the session, deduplicating by name. */\n  addArtifacts(artifacts: Artifact[]): void {\n    this.session.addArtifacts(artifacts);\n  }\n\n  /** Invokes the end-of-turn callback, absorbing errors from a closed stream. */\n  private notifyEndTurn(\n    snapshotId: string | undefined,\n    finishReason?: AgentFinishReason\n  ): void {\n    try {\n      this.onEndTurn?.(snapshotId, finishReason);\n    } catch {\n      // Stream was closed, absorb exception.\n    }\n  }\n\n  /**\n   * Executes the flow handler against incoming input messages sequentially.\n   *\n   * The handler receives the turn's {@link AgentInput} and a {@link TurnContext}\n   * whose `snapshotId` is *reserved up front* - it is the id the snapshot\n   * persisted at turn end will reuse. This lets a handler set up external,\n   * snapshot-correlated state (e.g. a git branch/worktree named after the\n   * snapshot) before generating, then commit it under that id.\n   *\n   * The handler may return a {@link TurnResult} carrying an explicit\n   * `finishReason` for the just-completed turn. When omitted, no per-turn\n   * reason is reported. Failures always report `failed`.\n   */\n  async run(\n    fn: (input: AgentInput, ctx: TurnContext) => Promise<TurnResult | void>\n  ): Promise<void> {\n    for await (const input of this.inputCh) {\n      if (input.message) {\n        this.session.addMessages([input.message]);\n      }\n\n      // The first customPatch of every turn is a whole-document replace that\n      // re-bases clients which may not share the server's baseline.\n      this.firstCustomPatchInTurn = true;\n\n      const parentSnapshotId = this.lastSnapshot?.snapshotId;\n\n      // Reserve the turn's snapshotId up front (when a store is configured) so\n      // the handler can name snapshot-correlated external resources before the\n      // turn runs. The detach path may have already reserved one; reuse it.\n      // The persisted snapshot at turn end reuses this id (maybeSnapshot\n      // prefers `newSnapshotId`).\n      if (this.store && !this.newSnapshotId) {\n        this.newSnapshotId = reserveSnapshotId();\n      }\n\n      const turnSnapshotId = this.newSnapshotId;\n      this.newSnapshotId = undefined;\n\n      const turnContext: TurnContext = {\n        snapshotId: turnSnapshotId!,\n        parentSnapshotId,\n        turnIndex: this.turnIndex,\n      };\n\n      try {\n        await run(`runTurn-${this.turnIndex + 1}`, input, async () => {\n          const turnResult = await fn(input, turnContext);\n          const finishReason = turnResult?.finishReason;\n          this.lastTurnFinishReason = finishReason;\n          this.lastTurnError = undefined;\n\n          const snapshotId = await this.maybeSnapshot(\n            'completed',\n            undefined,\n            turnSnapshotId,\n            finishReason\n          );\n\n          // Capture the state this successful turn produced. This becomes the\n          // last-good state to fall back to if a later turn fails, and its\n          // snapshotId is the last-good snapshot a failed turn resumes from.\n          this.lastGoodState = this.session.getState();\n          this.lastGoodSnapshotId = snapshotId;\n\n          // Tag the turn span with the snapshotId this turn persisted under, so\n          // a trace can correlate the turn with its snapshot (server-managed\n          // agents only; client-managed turns have no snapshotId).\n          if (snapshotId) {\n            setCustomMetadataAttribute('agent:snapshotId', snapshotId);\n          }\n\n          this.notifyEndTurn(snapshotId, finishReason);\n\n          // The turn span's output is the session state this turn produced -\n          // applies to both client- and server-managed agents.\n          return { state: this.session.getState() };\n        });\n        this.turnIndex++;\n      } catch (e: any) {\n        // An aborted turn rejects out of `generate` and lands here. Treat it as\n        // `aborted` rather than `failed`: the abort path already persisted the\n        // `aborted` status (the abort-aware mutator would skip a `failed` write\n        // anyway), so we record the finish reason and skip the failed snapshot\n        // write entirely instead of reporting a spurious error.\n        if (this.abortSignal?.aborted) {\n          this.lastTurnFinishReason = 'aborted';\n          this.lastTurnError = undefined;\n          this.notifyEndTurn(this.lastSnapshot?.snapshotId, 'aborted');\n          break;\n        }\n\n        this.lastTurnFinishReason = 'failed';\n        this.lastTurnError = toErrorDetails(e);\n        const snapshotId = await this.maybeSnapshot(\n          'failed',\n          this.lastTurnError,\n          turnSnapshotId,\n          'failed'\n        );\n        this.notifyEndTurn(snapshotId, 'failed');\n\n        // Graceful failure: rather than propagating the exception (which would\n        // discard the action's final return - and with it the last-good state\n        // and all prior successful turns), stop processing further inputs and\n        // let the invocation resolve with `finishReason: 'failed'`. The caller\n        // recovers the last-good state from the returned AgentOutput.\n        break;\n      }\n    }\n  }\n\n  /**\n   * Saves a snapshot of the current session state to the persistent store.\n   *\n   * When a store is configured every turn is persisted (snapshotting is no\n   * longer opt-out). Uses the mutator-based `saveSnapshot` to atomically check\n   * that the snapshot has not been concurrently aborted before writing -\n   * preventing a race where a \"done\" write could overwrite a concurrent\n   * \"aborted\" status.\n   */\n  async maybeSnapshot(\n    status?: 'pending' | 'completed' | 'failed',\n    error?: { status?: string; message: string; details?: any },\n    snapshotId?: string,\n    finishReason?: AgentFinishReason\n  ): Promise<string | undefined> {\n    if (\n      !this.store ||\n      (this.isDetached && snapshotId !== this.lastSnapshot?.snapshotId)\n    )\n      return this.lastSnapshot?.snapshotId;\n\n    const currentVersion = this.session.getVersion();\n    if (currentVersion === this.lastSnapshotVersion && !status) {\n      return this.lastSnapshot?.snapshotId;\n    }\n\n    const currentState = this.session.getState();\n\n    const snapshotInput: SessionSnapshotInput<State> = {\n      ...(snapshotId || this.newSnapshotId\n        ? { snapshotId: (snapshotId || this.newSnapshotId)! }\n        : {}),\n      // Stamp the session id onto every snapshot in the chain so callers can\n      // resolve a snapshot's session without reaching into its state.\n      sessionId: this.session.sessionId,\n      createdAt: new Date().toISOString(),\n      updatedAt: new Date().toISOString(),\n      state: currentState as SessionState<State>,\n      parentId: this.lastSnapshot?.snapshotId,\n      // Default to a resumable `completed` status. The only caller that omits a\n      // status is the post-invocation write (which fires when the handler\n      // mutates state after the last turn); persisting it as `completed` keeps\n      // it a valid resume target under the \"only `completed` is resumable\" rule.\n      status: status ?? 'completed',\n      // Stamp an initial heartbeat on a `pending` (detached, in-flight)\n      // snapshot. A background heartbeat loop refreshes it; if it goes stale the\n      // snapshot is reported as `expired` on read (the worker is presumed dead).\n      ...(status === 'pending' && { heartbeatAt: new Date().toISOString() }),\n      ...(finishReason && { finishReason }),\n      error,\n    };\n\n    const effectiveId = snapshotId || this.newSnapshotId;\n\n    // Use the mutator-based saveSnapshot to atomically check the current\n    // status before writing.  If the snapshot was concurrently aborted,\n    // the mutator returns null and the write is skipped.\n    const assignedId = await this.store.saveSnapshot(\n      effectiveId,\n      abortAwareMutator(snapshotInput),\n      { context: getContext() }\n    );\n    if (assignedId === null) {\n      // Snapshot was aborted concurrently; preserve the existing ID\n      // without overwriting.\n      return effectiveId;\n    }\n\n    this.lastSnapshot = { ...snapshotInput, snapshotId: assignedId };\n    this.lastSnapshotVersion = currentVersion;\n\n    return assignedId;\n  }\n}\n\n/**\n * Projects an agent's server-side data onto the view a client should see.\n *\n * Every member is optional; an omitted member passes the corresponding data\n * through unchanged. Use this to redact sensitive fields or reshape data\n * before it leaves the server - covering both data at rest and data in flight:\n *\n * - `state` reshapes/redacts session state at rest. Applied to\n *   `AgentOutput.state` (client-managed agents), to snapshots returned by\n *   `getSnapshotData`, and as the baseline for streamed `customPatch` diffs\n *   (so streamed custom-state deltas stay consistent with the transformed\n *   full state). Note: `state.artifacts` is part of session state, so artifact\n *   redaction at rest happens here too.\n * - `chunk` reshapes/redacts each stream chunk in flight (`modelChunk`,\n *   `artifact`, `customPatch`, `turnEnd`) - e.g. filtering \"internal\" tool\n *   request/response parts out of model chunks, or redacting streamed\n *   artifacts. Return `null`/`undefined` to drop the chunk entirely.\n *\n * When both `state` and `chunk` touch the same data (e.g. artifacts), keeping\n * the two projections consistent is the author's responsibility.\n */\nexport interface ClientTransform<S = unknown> {\n  /**\n   * Reshapes/redacts session state before it is exposed to the client (at\n   * rest: `AgentOutput.state`, snapshots, and the streamed `customPatch`\n   * baseline).\n   */\n  state?: (state: SessionState<S>) => SessionState;\n  /**\n   * Reshapes/redacts each stream chunk before it is sent to the client.\n   * Return `null`/`undefined` to drop the chunk entirely.\n   */\n  chunk?: (chunk: AgentStreamChunk) => AgentStreamChunk | null | undefined;\n}\n\n/**\n * Function handler definition for custom agent actions.\n */\nexport type AgentFn<State> = (\n  sess: SessionRunner<State>,\n  options: {\n    sendChunk: (chunk: AgentStreamChunk) => void;\n    abortSignal?: AbortSignal;\n    context?: ActionContext;\n  }\n) => Promise<AgentResult>;\n\n/**\n * Lookup input for the `getSnapshotData` action / method.\n *\n * Mirrors {@link GetSnapshotOptions}: provide exactly one of `snapshotId`\n * (an exact snapshot) or `sessionId` (the session's latest leaf snapshot).\n */\nexport const GetSnapshotDataInputSchema = z.object({\n  snapshotId: z.string().optional(),\n  sessionId: z.string().optional(),\n});\n\n/**\n * Lookup input for `getSnapshotData`.\n */\nexport interface GetSnapshotDataInput {\n  snapshotId?: string;\n  sessionId?: string;\n  context?: ActionContext;\n}\n\nexport type GetSnapshotDataAction<S = unknown> = Action<\n  typeof GetSnapshotDataInputSchema,\n  z.ZodType<SessionSnapshot<S>>\n>;\n\n/**\n * Represents a configured, registered Agent.\n *\n * An `Agent` exposes two surfaces:\n *\n * 1. The ergonomic, transport-agnostic {@link AgentAPI} (`chat`, `loadChat`,\n *    `getSnapshot`, `abort`) - the same surface returned by `remoteAgent` on\n *    the client, so server- and client-side code share one interface.\n * 2. The lower-level {@link BidiAction} surface (`run`, `streamBidi`, …) for\n *    advanced use and for serving over HTTP.\n */\nexport interface Agent<State = unknown>\n  extends BidiAction<\n      typeof AgentInputSchema,\n      typeof AgentOutputSchema,\n      typeof AgentStreamChunkSchema,\n      typeof AgentInitSchema\n    >,\n    AgentAPI<State> {\n  getSnapshotData(\n    opts: GetSnapshotDataInput\n  ): Promise<SessionSnapshot<State> | undefined>;\n\n  abort(\n    snapshotId: string,\n    options?: SessionStoreOptions\n  ): Promise<SessionSnapshot['status'] | undefined>;\n\n  readonly getSnapshotDataAction: GetSnapshotDataAction<State>;\n  readonly abortAgentAction: Action<\n    typeof AgentAbortRequestSchema,\n    typeof AgentAbortResponseSchema\n  >;\n}\n\n/**\n * Error thrown for agent init *API misuse* that should surface to the caller as\n * a real, thrown error (mapped to an HTTP status by the server handler) rather\n * than being absorbed into a graceful `finishReason: 'failed'` result.\n *\n * Covers calling an agent with an init that does not match its state-management\n * mode (e.g. sending `state` to a server-managed agent, or `snapshotId`/\n * `sessionId` to a client-managed one) and the snapshot/session ownership\n * guard. Other pre-turn failures (missing snapshot, non-resumable snapshot,\n * invalid custom state) remain graceful.\n */\nexport class AgentInitError extends GenkitError {}\n\n/**\n * Asserts that the init strategy matches the agent's state-management mode,\n * throwing an {@link AgentInitError} on a mismatch.\n *\n * Server-managed agents (with a store) resume via a `snapshotId` / `sessionId`;\n * client-managed agents (no store) supply the full `state` blob. This is API\n * misuse, so it propagates as a thrown error rather than a graceful failure.\n */\nfunction assertInitMatchesStateManagement(\n  config: { name: string; store?: SessionStore<unknown> },\n  init: AgentInit | undefined\n): void {\n  if ((init?.snapshotId || init?.sessionId) && !config.store) {\n    throw new AgentInitError({\n      status: 'FAILED_PRECONDITION',\n      message:\n        `Cannot use '${init.snapshotId ? 'snapshotId' : 'sessionId'}' with ` +\n        `agent '${config.name}': this agent has no store configured ` +\n        `(client-managed state). Send 'state' instead.`,\n    });\n  }\n  if (init?.state && config.store) {\n    throw new AgentInitError({\n      status: 'FAILED_PRECONDITION',\n      message:\n        `Cannot send 'state' to agent '${config.name}': this agent uses ` +\n        `a server-managed store. Send 'snapshotId' or 'sessionId' instead.`,\n    });\n  }\n}\n\n/**\n * Resolves the {@link Session} (and originating snapshot, if any) for an agent\n * turn from its {@link AgentInit}.\n *\n * Server-managed agents (with a store) resume via a `snapshotId` (an exact\n * snapshot) or a `sessionId` (the session's latest snapshot); client-managed\n * agents (no store) supply the full `state` blob. Throws a {@link GenkitError}\n * on a missing snapshot, non-resumable snapshot, or invalid custom state - the\n * caller is expected to translate that into a graceful `finishReason: 'failed'`\n * result. The state-management mismatch checks are performed up front by\n * {@link assertInitMatchesStateManagement} and throw {@link AgentInitError}.\n */\nasync function resolveSession<State>(\n  config: { name: string; store?: SessionStore<State> },\n  store: SessionStore<State>,\n  init: AgentInit | undefined,\n  validateCustomState: (custom: unknown) => void\n): Promise<{ session: Session<State>; snapshot?: SessionSnapshot<State> }> {\n  if (init?.snapshotId) {\n    const snapshot = await store.getSnapshot({\n      snapshotId: init.snapshotId,\n      context: getContext(),\n    });\n    if (!snapshot) {\n      throw new GenkitError({\n        status: 'NOT_FOUND',\n        message: `Snapshot ${init.snapshotId} not found`,\n      });\n    }\n    // When both `snapshotId` and `sessionId` are supplied, `snapshotId` selects\n    // the exact snapshot to resume and `sessionId` acts as an ownership guard:\n    // the snapshot must belong to that session. A mismatch is API misuse, so it\n    // propagates as a thrown error (AgentInitError) rather than being absorbed\n    // into a graceful failure.\n    // Prefer the snapshot's top-level `sessionId`; fall back to the id carried\n    // in its state for rows written before snapshot-level ids existed.\n    const snapshotSessionId = snapshot.sessionId ?? snapshot.state?.sessionId;\n    if (init.sessionId && snapshotSessionId !== init.sessionId) {\n      throw new AgentInitError({\n        status: 'INVALID_ARGUMENT',\n        message:\n          `Snapshot ${init.snapshotId} does not belong to session ` +\n          `${init.sessionId} (it belongs to ` +\n          `${snapshotSessionId ?? 'an unknown session'}).`,\n      });\n    }\n\n    // Only `completed` snapshots are resumable. A failed/aborted/pending\n    // snapshot is persisted for inspection but is not a valid resume target.\n    if (snapshot.status !== 'completed') {\n      throw new GenkitError({\n        status: 'INVALID_ARGUMENT',\n        message:\n          `Snapshot ${init.snapshotId} is not resumable (status: ` +\n          `${snapshot.status ?? 'unknown'}). Only 'completed' snapshots can ` +\n          `be resumed.`,\n      });\n    }\n\n    validateCustomState(snapshot.state?.custom);\n    return {\n      snapshot,\n      session: new Session<State>(snapshot.state as SessionState<State>),\n    };\n  }\n\n  if (init?.sessionId) {\n    // Resume the session's latest snapshot. The store returns the latest leaf\n    // regardless of status, but only `completed` snapshots are resumable - so\n    // if the leaf is a non-resumable turn (e.g. a `failed`/`aborted`/`pending`\n    // turn) walk back over its parent chain to the last-good (`completed`)\n    // snapshot. When the session has no resumable snapshot (e.g. a first-turn\n    // failure) seed a fresh session bound to the requested sessionId so\n    // subsequent turns can find it.\n    let snapshot = await store.getSnapshot({\n      sessionId: init.sessionId,\n      context: getContext(),\n    });\n    // Walk back over non-resumable leaves to the last-good (`completed`)\n    // snapshot. Guard against a self-referential or cyclic `parentId` chain\n    // (corrupt history) with a visited set so we fail fast with\n    // `FAILED_PRECONDITION` instead of looping forever on store reads.\n    const visited = new Set<string>();\n    while (snapshot && snapshot.status !== 'completed') {\n      if (visited.has(snapshot.snapshotId)) {\n        throw new GenkitError({\n          status: 'FAILED_PRECONDITION',\n          message:\n            `Session '${init.sessionId}' has a cyclic snapshot parent chain ` +\n            `(snapshot '${snapshot.snapshotId}' was visited twice). Resume by ` +\n            `snapshotId instead.`,\n        });\n      }\n      visited.add(snapshot.snapshotId);\n      snapshot = snapshot.parentId\n        ? await store.getSnapshot({\n            snapshotId: snapshot.parentId,\n            context: getContext(),\n          })\n        : undefined;\n    }\n    if (snapshot) {\n      validateCustomState(snapshot.state?.custom);\n      return {\n        snapshot,\n        session: new Session<State>(snapshot.state as SessionState<State>),\n      };\n    }\n    return {\n      session: new Session<State>({\n        custom: undefined,\n        artifacts: [],\n        messages: [],\n        sessionId: init.sessionId,\n      }),\n    };\n  }\n\n  if (init?.state && !config.store) {\n    validateCustomState(init.state.custom);\n    return {\n      session: new Session<State>(init.state as SessionState<State>),\n    };\n  }\n\n  return {\n    session: new Session<State>({\n      custom: undefined,\n      artifacts: [],\n      messages: [],\n    }),\n  };\n}\n\n/**\n * Pumps the action's raw input stream into the runner's input channel while\n * intercepting `detach: true` directives.\n *\n * Running this proxy concurrently lets a detach directive take effect\n * immediately rather than waiting for the runner to drain a backlog of\n * pre-queued inputs. A detach-only message (no payload) is consumed here and\n * not forwarded, since it has no turn to process.\n */\nfunction pipeInputWithDetach<State>(\n  inputStream: AsyncIterable<AgentInput>,\n  target: Channel<AgentInput>,\n  getRunner: () => SessionRunner<State>,\n  storeEnabled: boolean,\n  rejectDetach: (reason: any) => void\n): void {\n  (async () => {\n    try {\n      for await (const input of inputStream) {\n        if (input.detach) {\n          if (!storeEnabled) {\n            rejectDetach(\n              new GenkitError({\n                status: 'FAILED_PRECONDITION',\n                message:\n                  'Detach is only supported when a session store is provided.',\n              })\n            );\n          } else {\n            const runner = getRunner();\n            // Reserve the in-flight snapshot's id up front so the detached\n            // snapshot and any handler-named external resources share one id.\n            const turnSnapshotId = runner.newSnapshotId || reserveSnapshotId();\n            runner.newSnapshotId = turnSnapshotId;\n            await runner.maybeSnapshot('pending', undefined, turnSnapshotId);\n            runner.isDetached = true;\n\n            if (runner.onDetach) {\n              runner.onDetach(turnSnapshotId);\n            }\n          }\n          // Only forward to the runner if the input carries a payload beyond\n          // the detach directive; a detach-only message has no turn to process.\n          const hasPayload = !!(\n            input.message ||\n            input.resume?.restart?.length ||\n            input.resume?.respond?.length\n          );\n          if (hasPayload) {\n            target.send(input);\n          }\n        } else {\n          target.send(input);\n        }\n      }\n      target.close();\n    } catch (e) {\n      target.error(e);\n    }\n  })();\n}\n\n/**\n * Registers a multi-turn custom agent action capable of maintaining persistent state.\n *\n * When `stateSchema` is provided the custom state is validated at load time\n * (from a snapshot store or from the client-supplied `init.state`) and the\n * JSON Schema representation is included in the action metadata so that\n * tooling (e.g. the Dev UI) can inspect / validate the state shape.\n */\nexport function defineCustomAgent<State = unknown>(\n  registry: Registry,\n  config: {\n    name: string;\n    description?: string;\n    stateSchema?: z.ZodType<State>;\n    store?: SessionStore<State>;\n    clientTransform?: ClientTransform<State>;\n  },\n  fn: AgentFn<State>\n): Agent<State> {\n  // Helper that applies the optional state transform before exposing state to\n  // the client.  When no transform is configured it returns the raw state.\n  const toClientState = (\n    state: SessionState<State>\n  ): SessionState | undefined => {\n    if (config.clientTransform?.state) {\n      return config.clientTransform.state(state);\n    }\n    return state as SessionState;\n  };\n\n  // If a state schema was provided, pre-compute the JSON schema once so it\n  // can be embedded in metadata and reused for validation.\n\n  const stateJsonSchema = config.stateSchema\n    ? toJsonSchema({ schema: config.stateSchema })\n    : undefined;\n\n  /**\n   * Validates the `custom` field of a session state against the configured\n   * `stateSchema`.  No-ops when no schema was provided.\n   */\n  const validateCustomState = (custom: unknown): void => {\n    if (config.stateSchema && custom !== undefined) {\n      parseSchema(custom, { schema: config.stateSchema });\n    }\n  };\n\n  const primaryAction = defineBidiAction(\n    registry,\n    {\n      name: config.name,\n      description: config.description,\n      actionType: 'agent',\n      inputSchema: AgentInputSchema,\n      outputSchema: AgentOutputSchema,\n      streamSchema: AgentStreamChunkSchema,\n      initSchema: AgentInitSchema,\n      metadata: {\n        agent: {\n          stateManagement: config.store ? 'server' : 'client',\n          abortable: !!config.store?.onSnapshotStateChange,\n          ...(stateJsonSchema && { stateSchema: stateJsonSchema }),\n        },\n      },\n    },\n    async function* (\n      arg: ActionFnArg<AgentStreamChunk, AgentInput, AgentInit>\n    ) {\n      const init = arg.init;\n      const store = config.store || new InMemorySessionStore<State>();\n\n      // API-misuse checks (init does not match the agent's state-management\n      // mode) throw out of the generator so the server handler maps them to a\n      // proper HTTP status, rather than being absorbed into a graceful\n      // `finishReason: 'failed'` result below.\n      assertInitMatchesStateManagement(config, init);\n\n      let session!: Session<State>;\n      let snapshot: SessionSnapshot<State> | undefined;\n\n      try {\n        ({ session, snapshot } = await resolveSession<State>(\n          config,\n          store,\n          init,\n          validateCustomState\n        ));\n      } catch (e: any) {\n        // An AgentInitError signals API misuse (e.g. the snapshot/session\n        // ownership guard) that must surface as a thrown error; re-throw it so\n        // the server handler maps it to a proper HTTP status.\n        if (e instanceof AgentInitError) {\n          throw e;\n        }\n        // Other pre-turn / setup failures (missing snapshot, non-resumable\n        // snapshot, invalid client state). Resolve gracefully with\n        // `finishReason: 'failed'` - preserving the original `error.status` -\n        // rather than throwing, so the caller gets a structured, inspectable\n        // result. There is no last-good turn yet; echo back the\n        // client-supplied state when present.\n        return {\n          finishReason: 'failed' as AgentFinishReason,\n          error: toErrorDetails(e),\n          ...(!config.store &&\n            init?.state && { state: init.state as SessionState }),\n        };\n      }\n\n      // Tag the current trace span with the sessionId so that traces\n      // belonging to the same agent conversation can be correlated.\n      setCustomMetadataAttributes({\n        'agent:sessionId': session.sessionId,\n      });\n\n      let detachedSnapshotId: string | undefined;\n      let resolveDetach:\n        | ((value: void | PromiseLike<void>) => void)\n        | undefined;\n      let rejectDetach: ((reason: any) => void) | undefined;\n      const detachPromise = new Promise<void>((resolve, reject) => {\n        resolveDetach = resolve;\n        rejectDetach = reject;\n      });\n\n      const abortController = new AbortController();\n      let unsubscribe: any = undefined;\n      // Background heartbeat timer for the detached snapshot. Started in\n      // `onDetach`, cleared when the flow settles (or on abort).\n      let heartbeatTimer: ReturnType<typeof setInterval> | undefined;\n      const stopHeartbeat = () => {\n        if (heartbeatTimer) {\n          clearInterval(heartbeatTimer);\n          heartbeatTimer = undefined;\n        }\n      };\n\n      let runner!: SessionRunner<State>;\n\n      // Centralized chunk emitter: every stream chunk passes through here so\n      // the optional `clientTransform.chunk` can reshape/redact it (or drop it\n      // by returning a nullish value) before it reaches the client.\n      //\n      // The actual dispatch is failure-isolated (like `notifyEndTurn`): the\n      // artifact/customPatch emitters fire synchronously from inside\n      // `Session.updateCustom`/`addArtifacts` (i.e. from the user's handler).\n      // If the client stream is already closed, `sendChunk` throws; absorbing\n      // it here prevents that from propagating out of the handler and turning\n      // a normal turn into a `failed` one.\n      const emitChunk = (chunk: AgentStreamChunk) => {\n        try {\n          let toSend: AgentStreamChunk | null | undefined = chunk;\n          if (config.clientTransform?.chunk) {\n            toSend = config.clientTransform.chunk(chunk);\n          }\n          if (!toSend) return;\n          arg.sendChunk(toSend);\n        } catch {\n          // Stream was closed (or the transform threw); absorb the exception.\n        }\n      };\n\n      // We construct an asynchronous proxy channel over the inputStream.\n      // This enables immediate interception of `detach: true` directives. Without this proxy,\n      // a backlog of pre-queued inputs would have to be resolved sequentially by the runner first.\n      const runnerInputChannel = new Channel<AgentInput>();\n\n      pipeInputWithDetach(\n        arg.inputStream,\n        runnerInputChannel,\n        () => runner,\n        !!config.store,\n        (reason) => rejectDetach?.(reason)\n      );\n\n      runner = new SessionRunner<State>(session, runnerInputChannel, {\n        store,\n        lastSnapshot: snapshot,\n        abortSignal: abortController.signal,\n\n        onDetach: (snapshotId) => {\n          detachedSnapshotId = snapshotId;\n          if (resolveDetach) {\n            resolveDetach();\n          }\n\n          // Refresh the detached snapshot's heartbeat periodically. The mutator\n          // only touches a still-`pending` snapshot (returns null otherwise) so\n          // it never resurrects a terminal snapshot or clobbers a concurrent\n          // abort. If a read sees this heartbeat go stale, the snapshot is\n          // reported as `expired` (the worker is presumed dead). `unref` so the\n          // timer never keeps the process alive on its own.\n          const ctx = getContext();\n          heartbeatTimer = setInterval(() => {\n            void store\n              .saveSnapshot(\n                snapshotId,\n                (current) =>\n                  current?.status === 'pending'\n                    ? { ...current, heartbeatAt: new Date().toISOString() }\n                    : null,\n                { context: ctx }\n              )\n              .catch(() => {\n                // Best-effort heartbeat; ignore transient store errors.\n              });\n          }, DEFAULT_HEARTBEAT_INTERVAL_MS);\n          heartbeatTimer.unref?.();\n\n          if (store.onSnapshotStateChange) {\n            unsubscribe = store.onSnapshotStateChange(\n              snapshotId,\n              (snap) => {\n                if (snap.status === 'aborted') {\n                  stopHeartbeat();\n                  abortController.abort();\n                  if (unsubscribe) unsubscribe();\n                }\n              },\n              { context: getContext() }\n            );\n          }\n        },\n\n        onEndTurn: (snapshotId, finishReason) => {\n          if (!runner.isDetached) {\n            emitChunk({\n              turnEnd: {\n                ...(config.store && { snapshotId }),\n                ...(finishReason && { finishReason }),\n              },\n            });\n          }\n        },\n      });\n\n      const sendArtifactChunk = (a: Artifact) => {\n        if (!runner.isDetached) {\n          emitChunk({ artifact: a });\n        }\n      };\n\n      session.on('artifactAdded', sendArtifactChunk);\n      session.on('artifactUpdated', sendArtifactChunk);\n\n      // Auto-emit a `customPatch` chunk whenever custom state is mutated.\n      // The diff is computed AFTER the clientStateTransform so streamed deltas\n      // honor redaction and stay consistent with the transformed full state in\n      // snapshots / final output. The first patch of every turn is a\n      // whole-document replace (re-basing clients that may lack the baseline);\n      // subsequent patches are incremental diffs against the last sent value.\n      let lastSentCustom: unknown;\n      const sendCustomPatch = () => {\n        if (runner.isDetached) return;\n        const transformed = toClientState(session.getState())?.custom;\n        let patch: JsonPatch;\n        if (runner.firstCustomPatchInTurn) {\n          patch = [\n            { op: 'replace', path: '', value: structuredClone(transformed) },\n          ];\n          runner.firstCustomPatchInTurn = false;\n        } else {\n          patch = diff(lastSentCustom, transformed);\n        }\n        lastSentCustom = structuredClone(transformed);\n        if (patch.length) {\n          emitChunk({ customPatch: patch });\n        }\n      };\n      session.on('customChanged', sendCustomPatch);\n\n      const sendChunk = (chunk: AgentStreamChunk) => {\n        if (!runner.isDetached) {\n          emitChunk(chunk);\n        }\n      };\n\n      const flowPromise = (async () => {\n        try {\n          const result = await runWithSession(registry, session, () =>\n            fn(runner, {\n              sendChunk,\n              abortSignal: abortController.signal,\n              context: getContext(),\n            })\n          );\n          // After the handler resolves, persist any state it mutated after the\n          // last turn. Omitting a status defaults to a resumable `completed`\n          // write, which the version guard skips when nothing changed.\n          const finalSnapshotId = await runner.maybeSnapshot();\n          return { result, finalSnapshotId };\n        } finally {\n          // The turn has settled (the snapshot reached a terminal status), so\n          // stop refreshing its heartbeat.\n          stopHeartbeat();\n          if (unsubscribe) unsubscribe();\n          session.off('artifactAdded', sendArtifactChunk);\n          session.off('artifactUpdated', sendArtifactChunk);\n          session.off('customChanged', sendCustomPatch);\n        }\n      })();\n\n      // We race the background flow execution against the detach signal.\n      // If detachment is requested, we yield output metadata early, but allow\n      // the flow handler promise to continue its asynchronous completion.\n      const outcome = await Promise.race([\n        flowPromise,\n        detachPromise.then(() => 'detached' as const),\n      ]);\n\n      if (outcome === 'detached') {\n        return {\n          sessionId: session.sessionId,\n          snapshotId: detachedSnapshotId!,\n          finishReason: 'detached' as AgentFinishReason,\n          ...(!config.store && { state: toClientState(session.getState()) }),\n        };\n      }\n\n      const { result, finalSnapshotId } = outcome;\n\n      // A turn failed: resolve gracefully with `finishReason: 'failed'` and the\n      // last-good state (what the failed turn started with), rather than the\n      // live state which may hold the failed turn's partial mutations.\n      if (runner.lastTurnFinishReason === 'failed' && runner.lastTurnError) {\n        const lastGood = (runner.lastGoodState ??\n          session.getState()) as SessionState<State>;\n        const lastGoodMessages = lastGood.messages;\n        return {\n          sessionId: session.sessionId,\n          finishReason: 'failed' as AgentFinishReason,\n          error: runner.lastTurnError,\n\n          ...(result.artifacts?.length && { artifacts: result.artifacts }),\n          ...(lastGoodMessages?.length && {\n            message: lastGoodMessages[lastGoodMessages.length - 1],\n          }),\n          // Server-managed: the last successful turn is already persisted (every\n          // turn is snapshotted), so point at its snapshot. The failed turn's\n          // own snapshot is persisted too but is not resumable - `sessionId`\n          // resume skips it back to this last-good `done` snapshot. Undefined on\n          // a first-turn failure (no successful turn yet; client holds the seed).\n          ...(config.store && { snapshotId: runner.lastGoodSnapshotId }),\n          // Client-managed: return the last-good state directly.\n          ...(!config.store && { state: toClientState(lastGood) }),\n        };\n      }\n\n      const finishReason = result.finishReason ?? runner.lastTurnFinishReason;\n\n      return {\n        sessionId: session.sessionId,\n        ...(result.artifacts?.length && { artifacts: result.artifacts }),\n        ...(result.message && { message: result.message }),\n        ...(finishReason && { finishReason }),\n        ...(config.store && { snapshotId: finalSnapshotId }),\n        ...(!config.store && { state: toClientState(session.getState()) }),\n      };\n    }\n  );\n\n  // Helper that applies the clientTransform.state projection to a snapshot's\n  // state, returning a new snapshot object with the transformed state.\n  const toClientSnapshot = (\n    snapshot: SessionSnapshot<State>\n  ): SessionSnapshot => {\n    if (!config.clientTransform?.state || !snapshot.state) {\n      return snapshot as SessionSnapshot;\n    }\n    return {\n      ...snapshot,\n      state: config.clientTransform.state(snapshot.state),\n    };\n  };\n\n  // Shared snapshot/abort implementations, reused by both the `defineAction`\n  // surfaces (which inject the ambient request context) and the ergonomic\n  // composite methods (which accept caller-supplied options).\n  const resolveSnapshot = async (\n    lookup: GetSnapshotDataInput\n  ): Promise<SessionSnapshot | undefined> => {\n    requireStore(config.store, 'getSnapshotData', config.name);\n    const snapshot = await config.store.getSnapshot(lookup);\n    if (!snapshot) return undefined;\n    // Compute `expired` on read: a `pending` snapshot whose heartbeat has gone\n    // stale is presumed orphaned (its background worker died), so surface it as\n    // `expired` rather than leaving it `pending` forever. This is read-only -\n    // the status is not written back to the store.\n    const effective = isHeartbeatExpired(snapshot)\n      ? { ...snapshot, status: 'expired' as const }\n      : snapshot;\n    return toClientSnapshot(effective);\n  };\n\n  const runAbort = (\n    snapshotId: string,\n    options?: SessionStoreOptions\n  ): Promise<SessionSnapshot['status'] | undefined> => {\n    requireStore(config.store, 'abort', config.name);\n    return abortSnapshotInStore(config.store, snapshotId, options);\n  };\n\n  const getSnapshotDataAction = defineAction(\n    registry,\n    {\n      name: config.name,\n      description: `Gets snapshot data for ${config.name} by snapshotId or sessionId`,\n      actionType: 'agent-snapshot',\n      inputSchema: GetSnapshotRequestSchema,\n      outputSchema: SessionSnapshotSchema.optional(),\n    },\n    async (lookup) => resolveSnapshot({ ...lookup, context: getContext() })\n  );\n\n  const abortAgentAction = defineAction(\n    registry,\n    {\n      name: config.name,\n      description: `Aborts ${config.name} agent by snapshotId. Returns the snapshot id and its status after the abort attempt.`,\n      actionType: 'agent-abort',\n      inputSchema: AgentAbortRequestSchema,\n      outputSchema: AgentAbortResponseSchema,\n    },\n    async ({ snapshotId }) => {\n      const status = await runAbort(snapshotId, { context: getContext() });\n      return { snapshotId, status };\n    }\n  );\n\n  const composite = Object.assign(primaryAction, {\n    getSnapshotData: (opts: GetSnapshotDataInput) => resolveSnapshot(opts),\n    abort: (snapshotId: string, options?: SessionStoreOptions) =>\n      runAbort(snapshotId, options),\n    getSnapshotDataAction:\n      getSnapshotDataAction as unknown as GetSnapshotDataAction<State>,\n    abortAgentAction: abortAgentAction as unknown as Action<\n      typeof AgentAbortRequestSchema,\n      typeof AgentAbortResponseSchema\n    >,\n  });\n\n  // Opens a single-turn bidi stream: send the input, close the send side, and\n  // hand back the live `{ stream, output }` handle.\n  const startBidi = (\n    input: AgentInput,\n    init: AgentInit,\n    opts: { abortSignal: AbortSignal }\n  ) => {\n    const bidi = primaryAction.streamBidi(init, {\n      abortSignal: opts.abortSignal,\n    });\n    bidi.send(input);\n    bidi.close();\n    return bidi;\n  };\n\n  // In-process transport: drives the agent action directly (no HTTP). This lets\n  // the server-side agent expose the same ergonomic AgentAPI (`chat`,\n  // `loadChat`, `getSnapshot`, `abort`) as the HTTP `remoteAgent` client.\n  const transport: AgentTransport = {\n    stateManagement: config.store ? 'server' : 'client',\n\n    runTurn(input, init, opts) {\n      const bidi = startBidi(input, init, opts);\n      return { stream: bidi.stream, output: bidi.output };\n    },\n\n    async getSnapshot(lookup: SnapshotLookup) {\n      return composite.getSnapshotData(lookup);\n    },\n\n    abort(snapshotId: string) {\n      return composite.abort(snapshotId);\n    },\n  };\n\n  const agentApi = createAgentAPI<State>(transport);\n\n  // Expose the AgentAPI surface on the composite. `abort`/`getSnapshotData`\n  // already exist on the composite (richer signatures); we add `chat`,\n  // `loadChat`, and `getSnapshot`.\n  Object.assign(composite, {\n    chat: agentApi.chat,\n    loadChat: agentApi.loadChat,\n    getSnapshot: agentApi.getSnapshot,\n  });\n\n  return composite as unknown as Agent<State>;\n}\n\n/**\n * Registers an agent from an existing PromptAction.\n *\n * The `promptInput` option supplies values for the referenced prompt's input\n * variables, so a single prompt can be reused and customized by multiple\n * agents. Provide the prompt's input schema as the `I` type parameter to get\n * a type-checked `promptInput`.\n */\nexport function definePromptAgent<\n  State = unknown,\n  I extends z.ZodTypeAny = z.ZodTypeAny,\n>(\n  registry: Registry,\n  config: {\n    promptName: string;\n    /** Human-readable description, surfaced on the agent action's metadata. */\n    description?: string;\n    /**\n     * Input values for the referenced prompt's input variables. Lets a single\n     * prompt be reused/customized across multiple agents (e.g. supplying a\n     * different `role` or `tone` to a shared dotprompt template).\n     */\n    promptInput?: z.infer<I>;\n    stateSchema?: z.ZodType<State>;\n    store?: SessionStore<State>;\n    clientTransform?: ClientTransform<State>;\n  }\n) {\n  let cachedPromptAction: PromptAction | undefined;\n\n  const fn: AgentFn<State> = async (sess, { sendChunk, abortSignal }) => {\n    await sess.run(async (input) => {\n      const promptInput = config.promptInput ?? {};\n\n      if (!cachedPromptAction) {\n        cachedPromptAction = (await registry.lookupAction(\n          `/prompt/${config.promptName}`\n        )) as PromptAction;\n        if (!cachedPromptAction) {\n          throw new Error(\n            `Prompt '${config.promptName}' not found. Ensure it is defined before the agent is invoked.`\n          );\n        }\n      }\n\n      const historyTag = '_genkit_history';\n      const promptTag = 'agentPreamble';\n\n      // Tag every history message so we can identify them after render.\n      const history = (sess.getMessages() || []).map((m) => ({\n        ...m,\n        metadata: { ...m.metadata, [historyTag]: true },\n      }));\n\n      // Let the prompt control where history is placed (e.g. dotprompt\n      // {{history}}).  When the prompt has no explicit `messages` config\n      // the render helper simply appends history after system/user.\n      const genOpts = await cachedPromptAction.__executablePrompt.render(\n        promptInput as unknown as z.ZodTypeAny,\n        { messages: history }\n      );\n\n      // After render: tag everything that is NOT history as a prompt\n      // message so we can strip it after generation.  Also strip the\n      // internal history tag - it is an implementation detail that\n      // should not leak to the model.\n      if (genOpts.messages) {\n        genOpts.messages = genOpts.messages.map((m) => {\n          if (m.metadata?.[historyTag]) {\n            // Strip the history tag before sending to the model.\n            const { [historyTag]: _, ...restMeta } = m.metadata!;\n            return {\n              ...m,\n              metadata: Object.keys(restMeta).length ? restMeta : undefined,\n            };\n          }\n          return { ...m, metadata: { ...m.metadata, [promptTag]: true } };\n        });\n      }\n\n      if (input.resume) {\n        // Safety: validate that every restart/respond entry references\n        // a tool request that actually exists in the session history.\n        // For restarts, also verify that the input has not been tampered with.\n        validateResumeAgainstHistory(input.resume, sess.getMessages());\n\n        genOpts.resume = {\n          ...(input.resume.restart?.length && {\n            restart: input.resume.restart as ToolRequestPart[],\n          }),\n          ...(input.resume.respond?.length && {\n            respond: input.resume.respond as ToolResponsePart[],\n          }),\n        };\n      }\n\n      const result = generateStream(registry, { ...genOpts, abortSignal });\n\n      for await (const chunk of result.stream) {\n        sendChunk({ modelChunk: chunk });\n      }\n\n      const res = await result.response;\n\n      // Keep everything that is NOT a prompt-template message:\n      //   • history messages (clean - history tag was stripped before generate)\n      //   • new messages from tool loops (untagged)\n      //   • model response\n      if (res.request?.messages) {\n        const msgs = res.request.messages.filter(\n          (m) => !m.metadata?.[promptTag]\n        );\n        if (res.message) {\n          msgs.push(res.message);\n        }\n        sess.setMessages(msgs);\n      } else if (res.message) {\n        sess.addMessages([res.message]);\n      }\n\n      if (res.finishReason === 'interrupted') {\n        const parts =\n          res.message?.content?.filter((p) => !!p.toolRequest) || [];\n        if (parts.length > 0) {\n          sendChunk({\n            modelChunk: {\n              role: 'tool',\n              content: parts,\n            },\n          });\n        }\n      }\n\n      // Surface the generate finish reason as the turn's finish reason. The\n      // generate `FinishReason` enum is a subset of `AgentFinishReason`, so it\n      // maps through directly.\n      return { finishReason: res.finishReason as AgentFinishReason };\n    });\n\n    const msgs = sess.getMessages();\n    return {\n      artifacts: sess.getArtifacts(),\n      message: msgs.length > 0 ? msgs[msgs.length - 1] : undefined,\n      ...(sess.lastTurnFinishReason && {\n        finishReason: sess.lastTurnFinishReason,\n      }),\n    };\n  };\n\n  return defineCustomAgent<State>(\n    registry,\n    {\n      name: config.promptName,\n      description: config.description,\n      stateSchema: config.stateSchema,\n      store: config.store,\n      clientTransform: config.clientTransform,\n    },\n    fn\n  );\n}\n\n// ---------------------------------------------------------------------------\n// Resume validation - ensure restart/respond entries match session history\n// ---------------------------------------------------------------------------\n\n/**\n * Validates that every `resume.restart` and `resume.respond` entry references\n * a tool request that actually exists in the session history.\n *\n * For **restart** entries, also validates that the `input` has not been modified\n * compared to the original tool request - preventing a malicious client from\n * forging tool inputs.\n *\n * For **respond** entries, validates that a matching tool request (by name + ref)\n * exists in history.\n *\n * Searches the **entire history** (all model messages), not just the last one.\n */\nexport function validateResumeAgainstHistory(\n  resume: {\n    restart?: Array<{\n      toolRequest: { name: string; ref?: string; input?: unknown };\n      metadata?: Record<string, unknown>;\n    }>;\n    respond?: Array<{\n      toolResponse: { name: string; ref?: string; output?: unknown };\n    }>;\n  },\n  history: MessageData[]\n): void {\n  // Collect all tool requests from all model messages in the stored history.\n  const allToolRequests: Array<{\n    name: string;\n    ref?: string;\n    input?: unknown;\n  }> = [];\n  for (const msg of history) {\n    if (msg.role === 'model') {\n      for (const part of msg.content) {\n        if (part.toolRequest) {\n          allToolRequests.push(part.toolRequest);\n        }\n      }\n    }\n  }\n\n  // Validate restart entries: name + ref must exist AND input must match exactly\n  for (const restart of resume.restart || []) {\n    const { name, ref, input } = restart.toolRequest;\n    const match = allToolRequests.find(\n      (tr) => tr.name === name && tr.ref === ref\n    );\n    if (!match) {\n      throw new GenkitError({\n        status: 'INVALID_ARGUMENT',\n        message:\n          `resume.restart references tool '${name}'` +\n          (ref ? ` (ref: ${ref})` : '') +\n          ` which was not found in session history.`,\n      });\n    }\n    if (!deepEqual(input, match.input)) {\n      throw new GenkitError({\n        status: 'INVALID_ARGUMENT',\n        message:\n          `resume.restart for tool '${name}'` +\n          (ref ? ` (ref: ${ref})` : '') +\n          ` has modified inputs that do not match the original tool request ` +\n          `in session history. Restart inputs must exactly match the ` +\n          `interrupted tool request.`,\n      });\n    }\n  }\n\n  // Validate respond entries: name + ref must match a tool request in history\n  for (const respond of resume.respond || []) {\n    const { name, ref } = respond.toolResponse;\n    const match = allToolRequests.find(\n      (tr) => tr.name === name && tr.ref === ref\n    );\n    if (!match) {\n      throw new GenkitError({\n        status: 'INVALID_ARGUMENT',\n        message:\n          `resume.respond references tool '${name}'` +\n          (ref ? ` (ref: ${ref})` : '') +\n          ` which was not found in session history.`,\n      });\n    }\n  }\n}\n\n// ---------------------------------------------------------------------------\n// defineAgent - shortcut that combines definePrompt + definePromptAgent\n// ---------------------------------------------------------------------------\n\n/**\n * Configuration for `defineAgent`, which combines prompt definition and agent\n * registration into a single call.\n */\nexport interface AgentConfig<\n  State = unknown,\n  I extends z.ZodTypeAny = z.ZodTypeAny,\n> extends PromptConfig<I> {\n  /**\n   * Optional Zod schema describing the shape of the custom session state.\n   *\n   * When provided:\n   * - The `State` type is inferred from the schema (no explicit generic needed).\n   * - The JSON Schema is included in action metadata (`metadata.agent.stateSchema`)\n   *   so the Dev UI and other tooling can inspect / validate the state.\n   * - Custom state is validated at load time (from a snapshot store or from the\n   *   client-supplied `init.state`).\n   */\n  stateSchema?: z.ZodType<State>;\n  store?: SessionStore<State>;\n  clientTransform?: ClientTransform<State>;\n  /**\n   * Input values for the prompt's input variables. Lets the same prompt\n   * definition power differently-customized agents (e.g. supplying a different\n   * `role` or `tone`). Type-checked against the prompt's `input.schema`.\n   */\n  promptInput?: z.infer<I>;\n}\n\n/**\n * Defines and registers an agent by creating a prompt and wiring it into a\n * multi-turn agent in one step.\n *\n * This is a convenience shortcut for:\n * ```ts\n * definePrompt(registry, promptConfig);\n * definePromptAgent(registry, { promptName: promptConfig.name, ... });\n * ```\n */\nexport function defineAgent<\n  State = unknown,\n  I extends z.ZodTypeAny = z.ZodTypeAny,\n>(registry: Registry, config: AgentConfig<State, I>): Agent<State> {\n  // Extract agent-specific fields from the combined config; the rest is\n  // forwarded to definePrompt.\n  const { stateSchema, store, clientTransform, promptInput, ...promptConfig } =\n    config;\n\n  // Register the prompt.\n  definePrompt(registry, promptConfig);\n\n  // Wire it into a prompt agent.\n  return definePromptAgent<State, I>(registry, {\n    promptName: promptConfig.name,\n    description: promptConfig.description,\n    promptInput,\n    stateSchema,\n    store,\n    clientTransform,\n  });\n}\n"],"mappings":"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","names":["AgentAbortRequestSchema","AgentAbortResponseSchema","AgentInitSchema","AgentInputSchema","AgentOutputSchema","AgentStreamChunkSchema","GetSnapshotRequestSchema","finishReason","result","finalSnapshotId","msgs"]}