@genkit-ai/ai
Version:
Genkit AI framework generative AI APIs.
1 lines • 44.8 kB
Source Map (JSON)
{"version":3,"sources":["../src/agent-core.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\n/**\n * Transport-agnostic agent client core.\n *\n * This module is browser-safe: it has **no** runtime dependency on the rest of\n * `@genkit-ai/ai` (it only imports types, which are erased at compile time) and\n * no Node-specific APIs. Both the in-process server agent (`ai.defineAgent`)\n * and the HTTP `remoteAgent` client compose the same {@link AgentChatImpl} /\n * {@link createAgentAPI} core over a transport that implements\n * {@link AgentTransport}.\n *\n * @module agent-core\n */\n\nimport type {\n AgentInit,\n AgentInput,\n AgentOutput,\n AgentStreamChunk,\n} from './agent.mjs';\nimport { applyPatch, type JsonPatch } from './json-patch.mjs';\nimport type { MessageData } from './model-types.mjs';\nimport type {\n Media,\n Part,\n ToolRequestPart,\n ToolResponsePart,\n} from './parts.mjs';\nimport type {\n AgentFinishReason,\n Artifact,\n SessionSnapshot,\n SessionState,\n} from './session.mjs';\n\n// ---------------------------------------------------------------------------\n// Public interfaces\n// ---------------------------------------------------------------------------\n\n/**\n * Identifies a snapshot to load: an exact `snapshotId`, or a `sessionId` (the\n * session's latest leaf snapshot). Provide exactly one.\n */\nexport type SnapshotLookup = { snapshotId: string } | { sessionId: string };\n\n/**\n * The transport-agnostic surface for talking to an agent. The same shape is\n * returned by `ai.defineAgent(...)` on the server and by `remoteAgent(...)` on\n * the client.\n */\n\nexport interface AgentAPI<State = unknown> {\n /** Starts a new chat, or attaches to one via init. */\n chat(init?: AgentInit<State>): AgentChat<State>;\n\n /**\n * Loads a server snapshot and returns a chat with history restored. Accepts\n * either a `snapshotId` (an exact snapshot) or a `sessionId` (the session's\n * latest snapshot).\n */\n loadChat(opts: SnapshotLookup): Promise<AgentChat<State>>;\n\n /**\n * Reads a snapshot without starting a chat. Requires a server store. Accepts\n * a `snapshotId` string, or a lookup object (`{ snapshotId }` /\n * `{ sessionId }`).\n */\n getSnapshot(\n lookup: string | SnapshotLookup\n ): Promise<SessionSnapshot<State> | undefined>;\n\n /** Aborts a running snapshot. Requires a server store. */\n abort(snapshotId: string): Promise<SessionSnapshot['status'] | undefined>;\n}\n\n/**\n * A stateful conversation with an agent. Tracks state across turns so callers\n * do not have to thread `snapshotId`/`state` by hand.\n */\nexport interface AgentChat<State = unknown> {\n /**\n * Runs a single turn and resolves with the completed {@link AgentResponse}.\n * The non-streaming analog of {@link generate}; for incremental chunks use\n * {@link sendStream}.\n */\n send(\n input: string | AgentInput,\n opts?: { abortSignal?: AbortSignal }\n ): Promise<AgentResponse<State>>;\n\n /**\n * Runs a single turn and returns an {@link AgentTurn} exposing `.stream` and\n * `.response`. The streaming analog of {@link generateStream}.\n */\n sendStream(\n input: string | AgentInput,\n opts?: { abortSignal?: AbortSignal }\n ): AgentTurn<State>;\n\n /** Resumes after an interrupt. Sugar for `send({ resume })`. */\n resume(\n resume: AgentInput['resume'],\n opts?: { abortSignal?: AbortSignal }\n ): Promise<AgentResponse<State>>;\n\n /** Streaming resume. Sugar for `sendStream({ resume })`. */\n resumeStream(\n resume: AgentInput['resume'],\n opts?: { abortSignal?: AbortSignal }\n ): AgentTurn<State>;\n\n /** Submits a detached (background) turn. */\n detach(input: string | AgentInput): Promise<DetachedTask<State>>;\n\n /** Aborts the current snapshot. */\n abort(): Promise<SessionSnapshot['status'] | undefined>;\n\n readonly snapshotId?: string;\n /** Stable identifier correlating snapshots/turns of this conversation. */\n readonly sessionId?: string;\n readonly state?: State;\n readonly messages: MessageData[];\n readonly artifacts: Artifact[];\n}\n\n/**\n * A single in-flight turn - the analog of `ai.generateStream`'s\n * `{ stream, response }`.\n */\nexport interface AgentTurn<State = unknown, O = unknown> {\n /** Chunks as the turn progresses. */\n readonly stream: AsyncIterable<AgentChunk<State>>;\n\n /** The completed turn, with generate-style accessors. */\n readonly response: Promise<AgentResponse<State, O>>;\n\n /** Aborts this in-flight turn. */\n abort(): void;\n}\n\n/**\n * The completed result of a turn. Mirrors `GenerateResponse` and adds the\n * agent fields (`snapshotId`, `state`, `artifacts`).\n */\nexport interface AgentResponse<State = unknown, O = unknown> {\n readonly message?: MessageData;\n readonly text: string;\n readonly reasoning: string;\n readonly media: Media | null;\n readonly data: O | null;\n readonly toolRequests: ToolRequestPart[];\n readonly interrupts: AgentInterrupt[];\n readonly messages: MessageData[];\n readonly finishReason: AgentFinishReason;\n readonly finishMessage?: string;\n readonly raw: AgentOutput<State>;\n assertValid(): void;\n\n readonly snapshotId?: string;\n /** Stable identifier correlating snapshots/turns of this conversation. */\n readonly sessionId?: string;\n readonly state?: State;\n readonly artifacts: Artifact[];\n}\n\n/**\n * A streamed chunk. Mirrors `GenerateResponseChunk` and adds the agent fields\n * (`artifact`, `custom`).\n */\nexport interface AgentChunk<State = unknown> {\n readonly text: string;\n readonly reasoning: string;\n readonly accumulatedText: string;\n readonly toolRequests: ToolRequestPart[];\n readonly data: unknown;\n readonly media: Media | null;\n\n readonly artifact?: Artifact;\n /**\n * The full, post-patch custom state. Present only on chunks that carry a\n * custom-state update; `undefined` on text / model chunks. Each value is a\n * fresh object reference (the client applies the streamed RFC 6902 JSON Patch\n * onto a clone), so it is safe to use for `===` change detection in UI\n * frameworks. Equivalent to the value {@link AgentChat.state} returns at the\n * moment this chunk is yielded.\n */\n readonly custom?: State;\n readonly raw: AgentStreamChunk;\n}\n\n/**\n * A single tool request a turn paused on. `respond`/`restart` are builders:\n * they return the part to put into a `resume` payload, they do not send.\n */\nexport interface AgentInterrupt<Input = unknown, Output = unknown> {\n name: string;\n ref?: string;\n input: Input;\n\n /** Builds a `respond` entry for this interrupt. Does not send. */\n respond(output: Output): ToolResponsePart;\n\n /** Builds a `restart` entry re-issuing the original tool request. */\n restart(): ToolRequestPart;\n}\n\n/**\n * A handle to a background (detached) task.\n */\nexport interface DetachedTask<State = unknown> {\n readonly snapshotId: string;\n\n /** Yields status until a terminal state. */\n poll(opts?: { intervalMs?: number }): AsyncIterable<SessionSnapshot<State>>;\n\n /** Resolves when the task reaches a terminal state. */\n wait(opts?: { intervalMs?: number }): Promise<SessionSnapshot<State>>;\n\n /** Aborts the task. */\n abort(): Promise<SessionSnapshot['status'] | undefined>;\n}\n\n/**\n * Thrown when a turn fails. Carries the last-good state so the session is\n * recoverable.\n */\nexport class AgentError<State = unknown> extends Error {\n readonly status: string;\n readonly details?: unknown;\n readonly state?: State;\n readonly snapshotId?: string;\n readonly response: AgentResponse<State>;\n\n constructor(opts: {\n message: string;\n status: string;\n details?: unknown;\n state?: State;\n snapshotId?: string;\n response: AgentResponse<State>;\n }) {\n super(opts.message);\n this.name = 'AgentError';\n this.status = opts.status;\n this.details = opts.details;\n this.state = opts.state;\n this.snapshotId = opts.snapshotId;\n this.response = opts.response;\n // Restore prototype chain for `instanceof` across transpilation targets.\n Object.setPrototypeOf(this, AgentError.prototype);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Transport\n// ---------------------------------------------------------------------------\n\n/**\n * The pluggable backend the agent-client core runs over. Implementations exist\n * for the in-process server agent (driving the agent action directly) and for\n * the HTTP `remoteAgent` (driving `streamFlow`/`runFlow`).\n */\nexport interface AgentTransport {\n /** Declares server- vs client-managed state; auto-detected when omitted. */\n stateManagement?: 'server' | 'client';\n\n /**\n * Runs a single turn. Returns the streamed chunks plus a promise for the\n * final, non-throwing {@link AgentOutput} (failures resolve with\n * `finishReason: 'failed'`).\n */\n runTurn(\n input: AgentInput,\n init: AgentInit,\n opts: { abortSignal: AbortSignal }\n ): {\n stream: AsyncIterable<AgentStreamChunk>;\n output: Promise<AgentOutput>;\n };\n\n /** Reads a snapshot. Requires a server store. */\n getSnapshot(\n lookup: SnapshotLookup\n ): Promise<SessionSnapshot<any> | undefined>;\n\n /** Aborts a running snapshot. Requires a server store. */\n abort(snapshotId: string): Promise<SessionSnapshot['status'] | undefined>;\n}\n\nconst TERMINAL_STATUSES = new Set([\n 'completed',\n 'failed',\n 'aborted',\n 'expired',\n]);\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction toAgentInput(input: string | AgentInput): AgentInput {\n if (typeof input === 'string') {\n return { message: { role: 'user', content: [{ text: input }] } };\n }\n return input;\n}\n\n// ── Message-derived accessor helpers (mirroring generate) ──────────────────\n\nfunction partsText(parts?: Part[]): string {\n return (parts ?? []).map((p) => p.text ?? '').join('');\n}\n\nfunction partsReasoning(parts?: Part[]): string {\n return (parts ?? [])\n .filter((p) => p.reasoning !== undefined)\n .map((p) => p.reasoning ?? '')\n .join('');\n}\n\nfunction firstMedia(parts?: Part[]): Media | null {\n const p = (parts ?? []).find((p) => !!p.media);\n return p?.media\n ? { url: p.media.url, contentType: p.media.contentType }\n : null;\n}\n\nfunction firstData(parts?: Part[]): any {\n const p = (parts ?? []).find((p) => p.data !== undefined);\n return p?.data ?? null;\n}\n\nfunction toolRequestParts(parts?: Part[]): ToolRequestPart[] {\n return (parts ?? []).filter((p) => !!p.toolRequest) as ToolRequestPart[];\n}\n\n// ---------------------------------------------------------------------------\n// AgentInterrupt\n// ---------------------------------------------------------------------------\n\nclass AgentInterruptImpl<Input = unknown, Output = unknown>\n implements AgentInterrupt<Input, Output>\n{\n readonly name: string;\n readonly ref?: string;\n readonly input: Input;\n\n constructor(part: ToolRequestPart) {\n this.name = part.toolRequest.name;\n this.ref = part.toolRequest.ref;\n this.input = part.toolRequest.input as Input;\n }\n\n respond(output: Output): ToolResponsePart {\n return {\n toolResponse: {\n name: this.name,\n ...(this.ref !== undefined && { ref: this.ref }),\n output,\n },\n } as ToolResponsePart;\n }\n\n restart(): ToolRequestPart {\n return {\n toolRequest: {\n name: this.name,\n ...(this.ref !== undefined && { ref: this.ref }),\n input: this.input,\n },\n } as ToolRequestPart;\n }\n}\n\n// ---------------------------------------------------------------------------\n// AgentResponse\n// ---------------------------------------------------------------------------\n\nclass AgentResponseImpl<State = unknown, O = unknown>\n implements AgentResponse<State, O>\n{\n constructor(\n private readonly _raw: AgentOutput<State>,\n private readonly _messages: MessageData[],\n /**\n * Fallback custom-state getter. Server-managed agents (with a store) do not\n * return `state` on the wire - they return a `snapshotId` and the chat\n * tracks custom state locally (via streamed `customPatch` chunks). In that\n * case `_raw.state` is undefined, so we fall back to the chat's tracked\n * custom state here, ensuring `res.state` matches `chat.state` as documented.\n */\n private readonly _fallbackState?: () => State | undefined,\n /**\n * Fallback sessionId getter. Server-managed agents may not echo `sessionId`\n * on every wire frame; fall back to the chat's tracked sessionId so\n * `res.sessionId` matches `chat.sessionId` as documented.\n */\n private readonly _fallbackSessionId?: () => string | undefined\n ) {}\n\n get message(): MessageData | undefined {\n return this._raw.message;\n }\n\n get text(): string {\n return partsText(this._raw.message?.content);\n }\n\n get reasoning(): string {\n return partsReasoning(this._raw.message?.content);\n }\n\n get media(): Media | null {\n return firstMedia(this._raw.message?.content);\n }\n\n get data(): O | null {\n return firstData(this._raw.message?.content) as O | null;\n }\n\n get toolRequests(): ToolRequestPart[] {\n return toolRequestParts(this._raw.message?.content);\n }\n\n get interrupts(): AgentInterrupt[] {\n return this.toolRequests\n .filter((p) => !!(p as any).metadata?.interrupt)\n .map((p) => new AgentInterruptImpl(p));\n }\n\n get messages(): MessageData[] {\n return this._messages;\n }\n\n get finishReason(): AgentFinishReason {\n return (this._raw.finishReason ?? 'unknown') as AgentFinishReason;\n }\n\n get finishMessage(): string | undefined {\n return this._raw.error?.message;\n }\n\n get raw(): AgentOutput<State> {\n return this._raw;\n }\n\n get snapshotId(): string | undefined {\n return this._raw.snapshotId;\n }\n\n get sessionId(): string | undefined {\n return this._raw.sessionId ?? this._fallbackSessionId?.();\n }\n\n get state(): State | undefined {\n const fromWire = this._raw.state?.custom as State | undefined;\n // Server-managed agents omit `state` on the wire; fall back to the chat's\n // locally tracked custom state so `res.state === chat.state` as documented.\n return fromWire !== undefined ? fromWire : this._fallbackState?.();\n }\n\n get artifacts(): Artifact[] {\n return this._raw.artifacts ?? this._raw.state?.artifacts ?? [];\n }\n\n assertValid(): void {\n if (this.finishReason === 'blocked') {\n throw new Error(\n `Generation blocked${this.finishMessage ? `: ${this.finishMessage}` : ''}.`\n );\n }\n if (!this._raw.message) {\n throw new Error('Agent response has no message.');\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// AgentChunk\n// ---------------------------------------------------------------------------\n\nclass AgentChunkImpl<State = unknown> implements AgentChunk<State> {\n /**\n * The post-patch custom state, set by the {@link AgentChatImpl.sendStream}\n * generator after it applies this chunk's `customPatch`. Left `undefined` on\n * chunks that do not carry a custom-state update.\n */\n private _custom?: State;\n\n constructor(\n private readonly _raw: AgentStreamChunk,\n private readonly _previousText: string\n ) {}\n\n /** Internal: records the post-patch custom state this chunk reports. */\n _setCustom(custom: State | undefined): void {\n this._custom = custom;\n }\n\n private get _content(): Part[] | undefined {\n return this._raw.modelChunk?.content as Part[] | undefined;\n }\n\n get text(): string {\n return partsText(this._content);\n }\n\n get reasoning(): string {\n return partsReasoning(this._content);\n }\n\n get accumulatedText(): string {\n return this._previousText + this.text;\n }\n\n get toolRequests(): ToolRequestPart[] {\n return toolRequestParts(this._content);\n }\n\n get data(): unknown {\n return firstData(this._content);\n }\n\n get media(): Media | null {\n return firstMedia(this._content);\n }\n\n get artifact(): Artifact | undefined {\n return this._raw.artifact;\n }\n\n get custom(): State | undefined {\n return this._custom;\n }\n\n get raw(): AgentStreamChunk {\n return this._raw;\n }\n}\n\n// ---------------------------------------------------------------------------\n// DetachedTask\n// ---------------------------------------------------------------------------\n\nclass DetachedTaskImpl<State = unknown> implements DetachedTask<State> {\n constructor(\n readonly snapshotId: string,\n private readonly transport: AgentTransport\n ) {}\n\n async *poll(opts?: {\n intervalMs?: number;\n }): AsyncIterable<SessionSnapshot<State>> {\n const intervalMs = opts?.intervalMs ?? 1000;\n while (true) {\n const snap = (await this.transport.getSnapshot({\n snapshotId: this.snapshotId,\n })) as SessionSnapshot<State> | undefined;\n\n if (snap) {\n yield snap;\n if (snap.status && TERMINAL_STATUSES.has(snap.status)) {\n return;\n }\n }\n await sleep(intervalMs);\n }\n }\n\n async wait(opts?: { intervalMs?: number }): Promise<SessionSnapshot<State>> {\n let last: SessionSnapshot<State> | undefined;\n for await (const snap of this.poll(opts)) {\n last = snap;\n }\n if (!last) {\n throw new Error(\n `Detached task ${this.snapshotId} did not produce a snapshot.`\n );\n }\n return last;\n }\n\n abort(): Promise<SessionSnapshot['status'] | undefined> {\n return this.transport.abort(this.snapshotId);\n }\n}\n\n// ---------------------------------------------------------------------------\n// AgentChat\n// ---------------------------------------------------------------------------\n\nexport class AgentChatImpl<State = unknown> implements AgentChat<State> {\n snapshotId?: string;\n sessionId?: string;\n messages: MessageData[] = [];\n artifacts: Artifact[] = [];\n\n private clientState?: SessionState<State>;\n\n constructor(\n private readonly transport: AgentTransport,\n private readonly connectInit?: AgentInit<State>\n ) {\n if (connectInit?.snapshotId) {\n this.snapshotId = connectInit.snapshotId;\n }\n if (connectInit?.sessionId) {\n this.sessionId = connectInit.sessionId;\n }\n if (connectInit?.state) {\n this.hydrateFromState(connectInit.state);\n }\n }\n\n get state(): State | undefined {\n return this.clientState?.custom as State | undefined;\n }\n\n /**\n * Replaces the tracked `clientState`/`messages`/`artifacts` aggregates with\n * (copies of) those carried by a session state.\n */\n private hydrateFromState(state: SessionState<State> | undefined): void {\n this.clientState = state;\n this.messages = state?.messages ? [...state.messages] : [];\n this.artifacts = state?.artifacts ? [...state.artifacts] : [];\n if (state?.sessionId) {\n this.sessionId = state.sessionId;\n }\n }\n\n /** Loads aggregates from a server snapshot (used by `loadChat`). */\n _loadFromSnapshot(snapshot: SessionSnapshot<State>): void {\n this.snapshotId = snapshot.snapshotId;\n this.hydrateFromState(snapshot.state);\n }\n\n /**\n * Builds the init for the next turn from tracked aggregates. Always returns\n * an object (never `undefined`) because the agent validates `init` against\n * `AgentInitSchema` - an empty object is the valid \"fresh session\" init.\n */\n private buildInit(): AgentInit<State> {\n if (this.snapshotId) {\n return { snapshotId: this.snapshotId };\n }\n if (this.clientState) {\n return { state: this.clientState };\n }\n return this.connectInit ?? {};\n }\n\n /** Applies a completed turn's output to the running aggregates. */\n private applyOutput(raw: AgentOutput<State>): void {\n if (raw.snapshotId !== undefined) {\n this.snapshotId = raw.snapshotId;\n }\n if (raw.sessionId !== undefined) {\n this.sessionId = raw.sessionId;\n }\n\n if (raw.state !== undefined) {\n this.clientState = raw.state;\n }\n if (this.transport.stateManagement === undefined) {\n if (raw.snapshotId !== undefined) {\n this.transport.stateManagement = 'server';\n } else if (raw.state !== undefined) {\n this.transport.stateManagement = 'client';\n }\n }\n if (raw.state?.messages !== undefined) {\n this.messages = [...raw.state.messages];\n } else if (raw.message) {\n this.messages.push(raw.message);\n }\n if (raw.state?.artifacts !== undefined) {\n this.artifacts = [...raw.state.artifacts];\n } else if (raw.artifacts?.length) {\n for (const a of raw.artifacts) {\n const idx = a.name\n ? this.artifacts.findIndex((x) => x.name === a.name)\n : -1;\n if (idx >= 0) {\n this.artifacts[idx] = a;\n } else {\n this.artifacts.push(a);\n }\n }\n }\n }\n\n /**\n * Wires an optional external abort signal to a fresh {@link AbortController}\n * and returns it alongside a getter for whether the turn was aborted.\n */\n private setupAbort(opts?: { abortSignal?: AbortSignal }): {\n controller: AbortController;\n isAborted: () => boolean;\n } {\n const controller = new AbortController();\n let aborted = false;\n if (opts?.abortSignal) {\n if (opts.abortSignal.aborted) {\n controller.abort();\n aborted = true;\n } else {\n opts.abortSignal.addEventListener('abort', () => {\n aborted = true;\n controller.abort();\n });\n }\n }\n return {\n controller,\n isAborted: () => aborted || controller.signal.aborted,\n };\n }\n\n /**\n * Resolves a turn's raw `output` into an {@link AgentResponse}, applying it to\n * the running aggregates and throwing an {@link AgentError} on a failed turn.\n * Aborted turns resolve to a synthetic `aborted` response. Shared by both\n * {@link send} and {@link sendStream}.\n */\n private buildResponse(\n output: Promise<AgentOutput>,\n isAborted: () => boolean,\n messageCountBeforeTurn: number\n ): Promise<AgentResponse<State>> {\n return (async (): Promise<AgentResponse<State>> => {\n let raw: AgentOutput<State>;\n try {\n raw = (await output) as AgentOutput<State>;\n } catch (e) {\n if (isAborted()) {\n raw = { finishReason: 'aborted' as AgentFinishReason };\n } else {\n throw this.toAgentError(e);\n }\n }\n // A failed/aborted turn that returns no authoritative messages leaves the\n // eagerly-pushed user message (see `sendStream`) orphaned in `this.messages`\n // with no reply. Roll it back so it isn't re-sent on the next turn. When the\n // turn returns authoritative `state.messages`, `applyOutput` replaces the\n // array wholesale, so this rollback is a no-op for the success path.\n if (\n (raw.finishReason === 'failed' || raw.finishReason === 'aborted') &&\n raw.state?.messages === undefined &&\n !raw.message\n ) {\n this.messages.length = messageCountBeforeTurn;\n }\n this.applyOutput(raw);\n const response = new AgentResponseImpl<State>(\n raw,\n [...this.messages],\n () => this.state,\n () => this.sessionId\n );\n if (raw.finishReason === 'failed') {\n throw new AgentError<State>({\n message: raw.error?.message ?? 'Agent turn failed.',\n status: raw.error?.status ?? 'UNKNOWN',\n details: raw.error?.details,\n state: raw.state?.custom as State | undefined,\n snapshotId: raw.snapshotId,\n response,\n });\n }\n return response;\n })();\n }\n\n async send(\n input: string | AgentInput,\n opts?: { abortSignal?: AbortSignal }\n ): Promise<AgentResponse<State>> {\n // `send()` is a non-streaming veneer over the streaming path: we run the\n // turn via `sendStream` and drain its stream internally before resolving.\n //\n // Draining matters for server-managed agents (with a store): they do not\n // return custom `state` on the wire (only a `snapshotId`); the chat's\n // tracked custom state is kept live by applying the streamed `customPatch`\n // chunks. A non-streaming path would skip those chunks and leave\n // `chat.state` (and the `res.state` fallback) stale after a `send()`.\n // Consuming the stream here keeps `send()` and `sendStream()` consistent.\n // Client-managed agents are unaffected (they round-trip full state on the\n // wire either way).\n const turn = this.sendStream(input, opts);\n // Drain the stream so custom-state patches are applied to the chat.\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n for await (const _ of turn.stream) {\n // no-op: side effects (custom-state patches) happen as we iterate.\n }\n return turn.response;\n }\n\n sendStream(\n input: string | AgentInput,\n opts?: { abortSignal?: AbortSignal }\n ): AgentTurn<State> {\n const agentInput = toAgentInput(input);\n\n // Bail before pushing the message or dispatching the turn if the caller's\n // signal is already aborted: there's no point starting work, and we must\n // not leave an orphaned user message in `this.messages`.\n if (opts?.abortSignal?.aborted) {\n const aborted = (async (): Promise<AgentResponse<State>> => {\n return new AgentResponseImpl<State>(\n { finishReason: 'aborted' as AgentFinishReason },\n [...this.messages],\n () => this.state,\n () => this.sessionId\n );\n })();\n aborted.catch(() => {});\n return {\n stream: (async function* (): AsyncIterable<AgentChunk<State>> {})(),\n response: aborted as Promise<AgentResponse<State, unknown>>,\n abort() {},\n };\n }\n\n // Remember the message count so a failed/aborted turn that returns no\n // authoritative messages can roll back the eager push below (see\n // `buildResponse`). Note: turns are assumed single-flight - this client\n // does not guard against overlapping `send`/`sendStream` calls on the same\n // chat (they would race on `messages`/`snapshotId`/`clientState`).\n const messageCountBeforeTurn = this.messages.length;\n if (agentInput.message) {\n this.messages.push(agentInput.message);\n }\n const init = this.buildInit();\n\n const { controller, isAborted } = this.setupAbort(opts);\n\n const { stream: rawStream, output } = this.transport.runTurn(\n agentInput,\n init,\n { abortSignal: controller.signal }\n );\n\n const responsePromise = this.buildResponse(\n output,\n isAborted,\n messageCountBeforeTurn\n );\n // Avoid unhandled-rejection warnings when only the stream is consumed.\n responsePromise.catch(() => {});\n\n const self = this;\n const stream = (async function* (): AsyncIterable<AgentChunk<State>> {\n let previousText = '';\n try {\n for await (const raw of rawStream) {\n const chunk = new AgentChunkImpl<State>(raw, previousText);\n previousText = chunk.accumulatedText;\n // Keep the locally tracked custom state live mid-stream by applying\n // each streamed JSON Patch to it, then surface the resulting\n // post-patch custom state on the chunk as `chunk.custom` so consumers\n // get an explicit change notification (with a fresh object reference\n // for `===`-based change detection). The first patch of a turn is a\n // whole-document replace that re-bases us onto the server baseline.\n if (raw.customPatch) {\n self.applyCustomPatch(raw.customPatch);\n chunk._setCustom(self.state);\n }\n yield chunk;\n }\n } catch (e) {\n if (!isAborted()) {\n // Surface a failed turn / transport error as an AgentError.\n await responsePromise;\n throw self.toAgentError(e);\n }\n }\n // Re-surface a failed turn (which resolves the wire, but rejects here).\n await responsePromise;\n })();\n\n return {\n stream,\n response: responsePromise as Promise<AgentResponse<State, unknown>>,\n abort() {\n controller.abort();\n },\n };\n }\n\n resume(\n resume: AgentInput['resume'],\n opts?: { abortSignal?: AbortSignal }\n ): Promise<AgentResponse<State>> {\n return this.send({ resume }, opts);\n }\n\n resumeStream(\n resume: AgentInput['resume'],\n opts?: { abortSignal?: AbortSignal }\n ): AgentTurn<State> {\n return this.sendStream({ resume }, opts);\n }\n\n /**\n * Applies a streamed RFC 6902 JSON Patch to the locally tracked custom\n * state, keeping {@link state} live as the turn streams. The first patch of\n * a turn is a whole-document replace (rooted at `\"\"`) that re-bases the\n * client onto the server's current baseline.\n *\n * Transport requirement: `customPatch` chunks carry no sequence number and\n * are applied positionally, so the transport MUST deliver them in order with\n * no loss. The in-order SSE channel used today satisfies this; a lossy or\n * reordering transport would yield silently-wrong state (each turn does begin\n * with a whole-document replace, so corruption cannot persist past a turn\n * boundary).\n */\n private applyCustomPatch(patch: JsonPatch): void {\n const current = this.clientState?.custom;\n const next = applyPatch(current, patch) as State;\n if (this.clientState) {\n this.clientState = { ...this.clientState, custom: next };\n } else {\n this.clientState = { custom: next } as SessionState<State>;\n }\n }\n\n async detach(input: string | AgentInput): Promise<DetachedTask<State>> {\n const agentInput: AgentInput = { ...toAgentInput(input), detach: true };\n if (agentInput.message) {\n this.messages.push(agentInput.message);\n }\n const init = this.buildInit();\n const controller = new AbortController();\n const { output } = this.transport.runTurn(agentInput, init, {\n abortSignal: controller.signal,\n });\n const raw = (await output) as AgentOutput<State>;\n this.applyOutput(raw);\n if (!raw.snapshotId) {\n throw new Error('detach did not return a snapshotId.');\n }\n return new DetachedTaskImpl<State>(raw.snapshotId, this.transport);\n }\n\n async abort(): Promise<SessionSnapshot['status'] | undefined> {\n if (!this.snapshotId) {\n return undefined;\n }\n return this.transport.abort(this.snapshotId);\n }\n\n private toAgentError(e: unknown): AgentError<State> {\n if (e instanceof AgentError) {\n return e;\n }\n const message = e instanceof Error ? e.message : String(e);\n const match = /^([A-Z_]+):/.exec(message);\n const status = match ? match[1] : 'UNKNOWN';\n const raw: AgentOutput<State> = {\n finishReason: 'failed' as AgentFinishReason,\n error: { status, message },\n };\n const response = new AgentResponseImpl<State>(\n raw,\n [...this.messages],\n () => this.clientState?.custom as State | undefined,\n () => this.sessionId\n );\n return new AgentError<State>({\n message,\n status,\n details: e,\n state: this.clientState?.custom as State | undefined,\n snapshotId: this.snapshotId,\n response,\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// createAgentAPI - builds the AgentAPI surface over any transport.\n// ---------------------------------------------------------------------------\n\n/**\n * Composes the {@link AgentAPI} surface (`chat`/`loadChat`/`getSnapshot`/\n * `abort`) over a {@link AgentTransport}. Shared by the in-process server agent\n * and the HTTP `remoteAgent`.\n */\nexport function createAgentAPI<State = unknown>(\n transport: AgentTransport\n): AgentAPI<State> {\n return {\n chat(init?: AgentInit<State>): AgentChat<State> {\n return new AgentChatImpl<State>(transport, init);\n },\n\n async loadChat(opts: SnapshotLookup): Promise<AgentChat<State>> {\n const snapshot = (await transport.getSnapshot(opts)) as\n | SessionSnapshot<State>\n | undefined;\n if (!snapshot) {\n const id =\n 'snapshotId' in opts ? opts.snapshotId : `session ${opts.sessionId}`;\n throw new Error(`Snapshot ${id} not found.`);\n }\n const chat = new AgentChatImpl<State>(transport);\n chat._loadFromSnapshot(snapshot);\n return chat;\n },\n\n getSnapshot(\n lookup: string | SnapshotLookup\n ): Promise<SessionSnapshot<State> | undefined> {\n const normalized: SnapshotLookup =\n typeof lookup === 'string' ? { snapshotId: lookup } : lookup;\n return transport.getSnapshot(normalized) as Promise<\n SessionSnapshot<State> | undefined\n >;\n },\n\n abort(snapshotId: string): Promise<SessionSnapshot['status'] | undefined> {\n return transport.abort(snapshotId);\n },\n };\n}\n"],"mappings":"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","names":["p"]}