@adzenai/ai 1.1.1 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -3
- package/dist/copilotkit/index.cjs +481 -10
- package/dist/copilotkit/index.cjs.map +1 -1
- package/dist/copilotkit/index.d.cts +66 -1
- package/dist/copilotkit/index.d.ts +66 -1
- package/dist/copilotkit/index.js +479 -9
- package/dist/copilotkit/index.js.map +1 -1
- package/dist/copilotkit/react/index.cjs +204 -3
- package/dist/copilotkit/react/index.cjs.map +1 -1
- package/dist/copilotkit/react/index.d.cts +63 -7
- package/dist/copilotkit/react/index.d.ts +63 -7
- package/dist/copilotkit/react/index.js +200 -3
- package/dist/copilotkit/react/index.js.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/package.json +12 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/copilotkit/index.ts","../../src/copilotkit/middleware.ts"],"sourcesContent":["export { AdzenAsyncMiddleware } from \"./middleware.js\";\nexport type { AdzenAsyncConfig } from \"./middleware.js\";\n","import type { AdzenPlacement, ProcessResponse, ProcessResponseAd } from \"@adzenai/core\";\n\nexport interface AdzenAsyncConfig {\n endpointUrl?: string;\n apiKey: string;\n timeoutMs?: number;\n adUnitPosition?: string;\n location?: string;\n conversationId?: string;\n}\n\ninterface MessageBuffer {\n content: string;\n startedAt: number;\n fetched: boolean;\n}\n\nfunction generateIdempotencyKey(): string {\n const globalCrypto = (globalThis as { crypto?: { randomUUID?: () => string } })\n .crypto;\n if (globalCrypto?.randomUUID) return globalCrypto.randomUUID();\n return `adzen-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n}\n\nfunction isFinalOutputEvent(event: Record<string, unknown>): boolean {\n const type = String(event.type ?? \"\");\n if (type === \"RUN_FINISHED\" || type === \"RunFinished\") return false;\n if (type !== \"CUSTOM\" && type !== \"CUSTOM_EVENT\" && type !== \"CustomEvent\")\n return false;\n if (event.final === true || event.isFinal === true) return true;\n const name = String(event.name ?? event.event ?? \"\").toLowerCase();\n return name.includes(\"assistant_final\") || name.includes(\"final_output\");\n}\n\nfunction extractContentFromEvent(event: Record<string, unknown>): string | null {\n for (const key of [\"output\", \"result\", \"data\", \"payload\", \"message\"]) {\n const val = event[key];\n if (typeof val === \"string\" && val.length > 0) return val;\n if (typeof val === \"object\" && val !== null) {\n try {\n return JSON.stringify(val);\n } catch {\n continue;\n }\n }\n }\n return null;\n}\n\n/**\n * AG-UI middleware that intercepts the event stream and calls AI-API after\n * each assistant message, emitting `adzen_placement` custom events when an\n * ad is returned.\n *\n * All upstream events pass through immediately — zero latency is added to\n * the text stream. Ad fetches run as a side-effect and `RUN_FINISHED` is\n * held until all pending fetches settle.\n */\nexport class AdzenAsyncMiddleware {\n private config: Required<Pick<AdzenAsyncConfig, \"endpointUrl\" | \"timeoutMs\" | \"adUnitPosition\">> &\n AdzenAsyncConfig;\n private buffers = new Map<string, MessageBuffer>();\n private fetchedIds = new Set<string>();\n private pendingFetches: Promise<void>[] = [];\n private fallbackCounter = 0;\n private conversationId: string | undefined;\n\n constructor(config: AdzenAsyncConfig) {\n this.config = {\n ...config,\n endpointUrl: config.endpointUrl ?? \"https://api.adzen.ai/v1/ai\",\n timeoutMs: config.timeoutMs ?? 3000,\n adUnitPosition: config.adUnitPosition ?? \"chin\",\n };\n this.conversationId = config.conversationId;\n }\n\n /**\n * Process a single AG-UI event. Returns an array of events to emit\n * downstream (always includes the original event, possibly followed\n * by an `adzen_placement` custom event).\n */\n async processEvent(event: Record<string, unknown>): Promise<Record<string, unknown>[]> {\n const type = String(event.type ?? \"\");\n\n switch (type) {\n case \"RUN_STARTED\":\n case \"RunStarted\": {\n const threadId = String(event.threadId ?? \"\");\n if (threadId) this.conversationId = threadId;\n return [event];\n }\n\n case \"TEXT_MESSAGE_START\":\n case \"TextMessageStart\": {\n const messageId = this.resolveMessageId(event);\n this.evictStaleBuffers();\n this.buffers.set(messageId, {\n content: \"\",\n startedAt: Date.now(),\n fetched: false,\n });\n return [event];\n }\n\n case \"TEXT_MESSAGE_CONTENT\":\n case \"TextMessageContent\": {\n const messageId = String(event.messageId ?? \"\");\n const buf = this.buffers.get(messageId);\n if (buf) buf.content += String(event.delta ?? \"\");\n return [event];\n }\n\n case \"TEXT_MESSAGE_END\":\n case \"TextMessageEnd\": {\n const messageId = String(event.messageId ?? \"\");\n const buf = this.buffers.get(messageId);\n const out: Record<string, unknown>[] = [event];\n\n if (buf && !buf.fetched) {\n buf.fetched = true;\n this.fetchedIds.add(messageId);\n const fetchPromise = this.fetchAd(buf.content, messageId).then(\n (placement) => {\n if (placement) out.push(this.makePlacementEvent(placement, messageId));\n },\n );\n this.pendingFetches.push(fetchPromise);\n await fetchPromise;\n this.buffers.delete(messageId);\n }\n\n return out;\n }\n\n case \"CUSTOM\":\n case \"CUSTOM_EVENT\":\n case \"CustomEvent\": {\n if (isFinalOutputEvent(event)) {\n const messageId = String(event.messageId ?? \"\");\n if (!this.fetchedIds.has(messageId)) {\n const buf = this.buffers.get(messageId);\n const content = extractContentFromEvent(event);\n if (content) {\n const out: Record<string, unknown>[] = [event];\n if (buf) buf.fetched = true;\n this.fetchedIds.add(messageId);\n const fetchPromise = this.fetchAd(content, messageId).then(\n (placement) => {\n if (placement) out.push(this.makePlacementEvent(placement, messageId));\n },\n );\n this.pendingFetches.push(fetchPromise);\n await fetchPromise;\n return out;\n }\n }\n }\n return [event];\n }\n\n case \"RUN_FINISHED\":\n case \"RunFinished\": {\n await Promise.allSettled(this.pendingFetches);\n this.pendingFetches = [];\n return [event];\n }\n\n default:\n return [event];\n }\n }\n\n private resolveMessageId(event: Record<string, unknown>): string {\n const id = String(event.messageId ?? \"\");\n if (id) return id;\n return `__adzen_fallback_${Date.now()}_${this.fallbackCounter++}`;\n }\n\n private evictStaleBuffers(): void {\n const cutoff = Date.now() - this.config.timeoutMs * 2;\n for (const [key, buf] of this.buffers) {\n if (buf.startedAt < cutoff) this.buffers.delete(key);\n }\n }\n\n private async fetchAd(\n content: string,\n messageId: string,\n ): Promise<AdzenPlacement | null> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), this.config.timeoutMs);\n\n try {\n const body: Record<string, unknown> = {\n content,\n message_id: messageId,\n };\n if (this.config.location) body.location = this.config.location;\n if (this.conversationId) body.conversation_id = this.conversationId;\n\n const res = await fetch(`${this.config.endpointUrl}/process`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": this.config.apiKey,\n // AI-API requires an Idempotency-Key on /process (400 otherwise).\n // One per ad fetch — each completed message is a distinct request.\n \"Idempotency-Key\": generateIdempotencyKey(),\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n if (!res.ok) return null;\n\n const data = (await res.json()) as ProcessResponse;\n const first = data.ads?.[0];\n if (!first) return null;\n return this.mapResponseToPlacement(first);\n } catch {\n return null;\n } finally {\n clearTimeout(timeout);\n }\n }\n\n private mapResponseToPlacement(ad: ProcessResponseAd): AdzenPlacement {\n return {\n ad_id: String(ad.ad_id),\n advertiser_name: ad.advertiser_name,\n advertiser_image_url: ad.sponsor_logo_url || undefined,\n headline: ad.title,\n description: ad.description,\n cta_text: ad.cta,\n destination_url: ad.click_through_url,\n creative_url: ad.creative_url ?? undefined,\n adUnitPosition: ad.placement ?? this.config.adUnitPosition,\n render_impression_url: ad.render_impression_url,\n view_impression_url: ad.view_impression_url,\n };\n }\n\n private makePlacementEvent(\n placement: AdzenPlacement,\n messageId: string,\n ): Record<string, unknown> {\n return {\n // AG-UI's event schema only accepts \"CUSTOM\"; @ag-ui/client zod-validates\n // every SSE frame and aborts the run on an unknown type. \"CUSTOM_EVENT\"\n // was rejected downstream.\n type: \"CUSTOM\",\n name: \"adzen_placement\",\n messageId,\n value: {\n ...placement,\n message_id: messageId,\n },\n };\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/copilotkit/index.ts","../../src/copilotkit/middleware.ts","../../src/copilotkit/AdzenStreamClient.ts","../../src/copilotkit/parseSSE.ts","../../src/copilotkit/streamMiddleware.ts"],"sourcesContent":["export { AdzenAsyncMiddleware } from \"./middleware.js\";\nexport type { AdzenAsyncConfig } from \"./middleware.js\";\nexport { AdzenStreamMiddleware } from \"./streamMiddleware.js\";\nexport type { AdzenStreamMiddlewareConfig } from \"./streamMiddleware.js\";\nexport type { AdzenStreamConfig } from \"./AdzenStreamClient.js\";\n","import type { AdzenPlacement, ProcessResponse, ProcessResponseAd } from \"@adzenai/core\";\n\nexport interface AdzenAsyncConfig {\n endpointUrl?: string;\n apiKey: string;\n timeoutMs?: number;\n adUnitPosition?: string;\n location?: string;\n conversationId?: string;\n profileId?: string;\n}\n\ninterface MessageBuffer {\n content: string;\n startedAt: number;\n fetched: boolean;\n}\n\nfunction generateIdempotencyKey(): string {\n const globalCrypto = (globalThis as { crypto?: { randomUUID?: () => string } })\n .crypto;\n if (globalCrypto?.randomUUID) return globalCrypto.randomUUID();\n return `adzen-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n}\n\nfunction isFinalOutputEvent(event: Record<string, unknown>): boolean {\n const type = String(event.type ?? \"\");\n if (type === \"RUN_FINISHED\" || type === \"RunFinished\") return false;\n if (type !== \"CUSTOM\" && type !== \"CUSTOM_EVENT\" && type !== \"CustomEvent\")\n return false;\n if (event.final === true || event.isFinal === true) return true;\n const name = String(event.name ?? event.event ?? \"\").toLowerCase();\n return name.includes(\"assistant_final\") || name.includes(\"final_output\");\n}\n\nfunction extractContentFromEvent(event: Record<string, unknown>): string | null {\n for (const key of [\"output\", \"result\", \"data\", \"payload\", \"message\"]) {\n const val = event[key];\n if (typeof val === \"string\" && val.length > 0) return val;\n if (typeof val === \"object\" && val !== null) {\n try {\n return JSON.stringify(val);\n } catch {\n continue;\n }\n }\n }\n return null;\n}\n\n/**\n * AG-UI middleware that intercepts the event stream and calls AI-API after\n * each assistant message, emitting `adzen_placement` custom events when an\n * ad is returned.\n *\n * All upstream events pass through immediately — zero latency is added to\n * the text stream. Ad fetches run as a side-effect and `RUN_FINISHED` is\n * held until all pending fetches settle.\n */\nexport class AdzenAsyncMiddleware {\n private config: Required<Pick<AdzenAsyncConfig, \"endpointUrl\" | \"timeoutMs\" | \"adUnitPosition\">> &\n AdzenAsyncConfig;\n private buffers = new Map<string, MessageBuffer>();\n private fetchedIds = new Set<string>();\n private pendingFetches: Promise<void>[] = [];\n private fallbackCounter = 0;\n private conversationId: string | undefined;\n\n constructor(config: AdzenAsyncConfig) {\n this.config = {\n ...config,\n endpointUrl: config.endpointUrl ?? \"https://api.adzen.ai/v1\",\n timeoutMs: config.timeoutMs ?? 3000,\n adUnitPosition: config.adUnitPosition ?? \"chin\",\n };\n this.conversationId = config.conversationId;\n }\n\n /**\n * Process a single AG-UI event. Returns an array of events to emit\n * downstream (always includes the original event, possibly followed\n * by an `adzen_placement` custom event).\n */\n async processEvent(event: Record<string, unknown>): Promise<Record<string, unknown>[]> {\n const type = String(event.type ?? \"\");\n\n switch (type) {\n case \"RUN_STARTED\":\n case \"RunStarted\": {\n const threadId = String(event.threadId ?? \"\");\n if (threadId) this.conversationId = threadId;\n return [event];\n }\n\n case \"TEXT_MESSAGE_START\":\n case \"TextMessageStart\": {\n const messageId = this.resolveMessageId(event);\n this.evictStaleBuffers();\n this.buffers.set(messageId, {\n content: \"\",\n startedAt: Date.now(),\n fetched: false,\n });\n return [event];\n }\n\n case \"TEXT_MESSAGE_CONTENT\":\n case \"TextMessageContent\": {\n const messageId = String(event.messageId ?? \"\");\n const buf = this.buffers.get(messageId);\n if (buf) buf.content += String(event.delta ?? \"\");\n return [event];\n }\n\n case \"TEXT_MESSAGE_END\":\n case \"TextMessageEnd\": {\n const messageId = String(event.messageId ?? \"\");\n const buf = this.buffers.get(messageId);\n const out: Record<string, unknown>[] = [event];\n\n if (buf && !buf.fetched) {\n buf.fetched = true;\n this.fetchedIds.add(messageId);\n const fetchPromise = this.fetchAd(buf.content, messageId).then(\n (placement) => {\n if (placement) out.push(this.makePlacementEvent(placement, messageId));\n },\n );\n this.pendingFetches.push(fetchPromise);\n await fetchPromise;\n this.buffers.delete(messageId);\n }\n\n return out;\n }\n\n case \"CUSTOM\":\n case \"CUSTOM_EVENT\":\n case \"CustomEvent\": {\n if (isFinalOutputEvent(event)) {\n const messageId = String(event.messageId ?? \"\");\n if (!this.fetchedIds.has(messageId)) {\n const buf = this.buffers.get(messageId);\n const content = extractContentFromEvent(event);\n if (content) {\n const out: Record<string, unknown>[] = [event];\n if (buf) buf.fetched = true;\n this.fetchedIds.add(messageId);\n const fetchPromise = this.fetchAd(content, messageId).then(\n (placement) => {\n if (placement) out.push(this.makePlacementEvent(placement, messageId));\n },\n );\n this.pendingFetches.push(fetchPromise);\n await fetchPromise;\n return out;\n }\n }\n }\n return [event];\n }\n\n case \"RUN_FINISHED\":\n case \"RunFinished\": {\n await Promise.allSettled(this.pendingFetches);\n this.pendingFetches = [];\n return [event];\n }\n\n default:\n return [event];\n }\n }\n\n private resolveMessageId(event: Record<string, unknown>): string {\n const id = String(event.messageId ?? \"\");\n if (id) return id;\n return `__adzen_fallback_${Date.now()}_${this.fallbackCounter++}`;\n }\n\n private evictStaleBuffers(): void {\n const cutoff = Date.now() - this.config.timeoutMs * 2;\n for (const [key, buf] of this.buffers) {\n if (buf.startedAt < cutoff) this.buffers.delete(key);\n }\n }\n\n private async fetchAd(\n content: string,\n messageId: string,\n ): Promise<AdzenPlacement | null> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), this.config.timeoutMs);\n\n try {\n const body: Record<string, unknown> = {\n content,\n message_id: messageId,\n };\n if (this.config.location) body.location = this.config.location;\n if (this.conversationId) body.conversation_id = this.conversationId;\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": this.config.apiKey,\n // AI-API requires an Idempotency-Key on /process (400 otherwise).\n // One per ad fetch — each completed message is a distinct request.\n \"Idempotency-Key\": generateIdempotencyKey(),\n };\n if (this.config.profileId) headers[\"X-Profile-Id\"] = this.config.profileId;\n\n const res = await fetch(`${this.config.endpointUrl}/process`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n if (!res.ok) return null;\n\n const data = (await res.json()) as ProcessResponse;\n const first = data.ads?.[0];\n if (!first) return null;\n return this.mapResponseToPlacement(first);\n } catch {\n return null;\n } finally {\n clearTimeout(timeout);\n }\n }\n\n private mapResponseToPlacement(ad: ProcessResponseAd): AdzenPlacement {\n return {\n ad_id: String(ad.ad_id),\n advertiser_name: ad.advertiser_name,\n advertiser_image_url: ad.sponsor_logo_url || undefined,\n headline: ad.title,\n description: ad.description,\n cta_text: ad.cta,\n destination_url: ad.click_through_url,\n creative_url: ad.creative_url ?? undefined,\n adUnitPosition: ad.placement ?? this.config.adUnitPosition,\n render_impression_url: ad.render_impression_url,\n view_impression_url: ad.view_impression_url,\n };\n }\n\n private makePlacementEvent(\n placement: AdzenPlacement,\n messageId: string,\n ): Record<string, unknown> {\n return {\n // AG-UI's event schema only accepts \"CUSTOM\"; @ag-ui/client zod-validates\n // every SSE frame and aborts the run on an unknown type. \"CUSTOM_EVENT\"\n // was rejected downstream.\n type: \"CUSTOM\",\n name: \"adzen_placement\",\n messageId,\n value: {\n ...placement,\n message_id: messageId,\n },\n };\n }\n}\n","import type {\n InlineAdEvent,\n PlacementRecord,\n PlacementsResponse,\n AdzenStreamStartEvent,\n AdzenStreamEndEvent,\n AdzenStreamErrorEvent,\n} from \"@adzenai/core\";\nimport { uuidv4 } from \"@adzenai/core\";\nimport { parseSSE } from \"./parseSSE.js\";\n\nexport interface AdzenStreamConfig {\n apiKey: string;\n endpointUrl?: string;\n timeoutMs?: number;\n location?: string;\n conversationId?: string;\n profileId?: string;\n placementPollIntervalMs?: number;\n prefetch?: boolean;\n /**\n * Whether to poll the sidecar placement endpoint for out-of-stream ads\n * rendered outside the message body. Defaults to `true`. Set to `false`\n * to run inline-only, leaving `adzen_inline` events unaffected.\n */\n sidecar?: boolean;\n /**\n * Extra request headers merged into every outbound Adzen request\n * (/stream, /process, placement polling). Intended for internal\n * debugging (e.g. `X-Adzen-Debug-*`). SDK-managed headers\n * (auth, content-type, correlation IDs) always take precedence.\n */\n headers?: Record<string, string>;\n onInlineAd?: (ad: InlineAdEvent) => void;\n onPlacement?: (placement: PlacementRecord) => void;\n onError?: (error: AdzenStreamErrorEvent) => void;\n onStreamStart?: (event: AdzenStreamStartEvent) => void;\n onStreamEnd?: (event: AdzenStreamEndEvent) => void;\n}\n\nconst DEFAULT_ENDPOINT = \"https://api.adzen.ai/v1\";\nconst DEFAULT_TIMEOUT_MS = 3000;\nconst DEFAULT_POLL_INTERVAL_MS = 2000;\n\n/**\n * Whether the current runtime can send a ReadableStream as a fetch request\n * body. Node 18+ (undici) supports this; Safari and Firefox do not, and\n * silently coerce the stream to the string \"[object ReadableStream]\" via the\n * WebIDL BodyInit union's USVString member.\n *\n * Detection works by checking whether the `duplex` getter is read and whether\n * the runtime set a Content-Type — a coerced string body gets `text/plain`.\n */\nconst SUPPORTS_REQUEST_STREAMS = (() => {\n try {\n let duplexAccessed = false;\n const hasContentType = new Request(\"http://localhost\", {\n method: \"POST\",\n body: new ReadableStream(),\n get duplex() {\n duplexAccessed = true;\n return \"half\";\n },\n } as RequestInit).headers.has(\"Content-Type\");\n return duplexAccessed && !hasContentType;\n } catch {\n return false;\n }\n})();\n\n/**\n * Framework-agnostic client for the Adzen streaming ad enrichment API.\n *\n * Handles connecting to `/v1/stream`, parsing SSE events, optional prefetch\n * via `/process`, and sidecar placement polling. Framework adapters (AG-UI\n * middleware, React hooks) wrap this class.\n */\nexport class AdzenStreamClient {\n private endpointUrl: string;\n private apiKey: string;\n private timeoutMs: number;\n private location?: string;\n private profileId?: string;\n private placementPollIntervalMs: number;\n private prefetchEnabled: boolean;\n private sidecarEnabled: boolean;\n private customHeaders: Record<string, string>;\n\n private conversationId: string;\n private abortController: AbortController | null = null;\n private placementEndpoint: string | null = null;\n private pollTimer: ReturnType<typeof setInterval> | null = null;\n private streamEnded = false;\n private inlineAdQueue: InlineAdEvent[] = [];\n private streamPromise: Promise<void> | null = null;\n private prefetchPromise: Promise<void> | null = null;\n\n private onInlineAd?: (ad: InlineAdEvent) => void;\n private onPlacement?: (placement: PlacementRecord) => void;\n private onError?: (error: AdzenStreamErrorEvent) => void;\n private onStreamStart?: (event: AdzenStreamStartEvent) => void;\n private onStreamEnd?: (event: AdzenStreamEndEvent) => void;\n\n constructor(config: AdzenStreamConfig) {\n this.endpointUrl = config.endpointUrl ?? DEFAULT_ENDPOINT;\n this.apiKey = config.apiKey;\n this.timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n this.location = config.location;\n this.profileId = config.profileId;\n this.placementPollIntervalMs =\n config.placementPollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;\n this.prefetchEnabled = config.prefetch ?? false;\n this.sidecarEnabled = config.sidecar ?? true;\n this.customHeaders = config.headers ?? {};\n this.conversationId = config.conversationId ?? uuidv4();\n\n this.onInlineAd = config.onInlineAd;\n this.onPlacement = config.onPlacement;\n this.onError = config.onError;\n this.onStreamStart = config.onStreamStart;\n this.onStreamEnd = config.onStreamEnd;\n }\n\n getConversationId(): string {\n return this.conversationId;\n }\n\n setConversationId(id: string): void {\n this.conversationId = id;\n }\n\n /**\n * Dispatches the prefetch without waiting for it.\n *\n * The request leaves before `connect()` opens `/stream`, which is all the\n * 2-step chained flow needs — the two calls are correlated server-side by\n * `conversation_id`. Awaiting the response here would stall the assistant\n * message behind a full ad-matching round trip while the LLM keeps\n * streaming, so the buffered tokens would then arrive in one burst.\n */\n startPrefetch(prompt: string): void {\n if (!this.prefetchEnabled) return;\n this.prefetchPromise = this.prefetchProcess(prompt);\n }\n\n /**\n * 2-step chained flow: POST /process with the user prompt and\n * conversationId. Awaits the response (or timeout) but discards the\n * result. If it fails, logs and continues — the stream will proceed\n * in degraded mode.\n */\n async prefetchProcess(prompt: string): Promise<void> {\n if (!this.prefetchEnabled) return;\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), this.timeoutMs);\n\n try {\n const body: Record<string, unknown> = {\n content: prompt,\n message_id: uuidv4(),\n conversation_id: this.conversationId,\n };\n if (this.location) body.location = this.location;\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": this.apiKey,\n \"Idempotency-Key\": uuidv4(),\n };\n if (this.profileId) headers[\"X-Profile-Id\"] = this.profileId;\n\n await fetch(`${this.endpointUrl}/process`, {\n method: \"POST\",\n headers: this.mergeHeaders(headers),\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n } catch {\n // Prefetch failure is non-fatal — stream continues without pre-match context\n } finally {\n clearTimeout(timeout);\n }\n }\n\n /**\n * Opens a streaming POST to /stream, piping the upstream LLM response\n * body directly. The API reads the raw LLM stream in real time and\n * sends SSE ad events back on the response side.\n *\n * @param messageId Unique ID for this assistant message\n * @param body The upstream LLM response body (one branch of a tee)\n */\n connect(messageId: string, body: ReadableStream<Uint8Array>): void {\n this.streamEnded = false;\n this.inlineAdQueue = [];\n this.placementEndpoint = null;\n this.streamPromise = null;\n this.abortController = new AbortController();\n\n if (!SUPPORTS_REQUEST_STREAMS) {\n this.streamEnded = true;\n this.onError?.({\n type: \"adzen_error\",\n code: \"request_streams_unsupported\",\n message:\n \"This runtime cannot send a ReadableStream as a request body, so the \" +\n \"LLM stream cannot be proxied. Run AdzenStreamMiddleware server-side \" +\n \"(Node 18+) — browsers other than Chromium do not support fetch upload streams.\",\n });\n void body.cancel().catch(() => {});\n return;\n }\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/octet-stream\",\n \"X-API-Key\": this.apiKey,\n \"Idempotency-Key\": uuidv4(),\n \"X-Message-Id\": messageId,\n \"X-Conversation-Id\": this.conversationId,\n };\n if (this.profileId) headers[\"X-Profile-Id\"] = this.profileId;\n if (this.location) headers[\"X-Location\"] = this.location;\n\n this.streamPromise = this.executeStreamFetch(body, this.mergeHeaders(headers));\n }\n\n /**\n * Waits for the SSE response stream from the API to finish, along with any\n * prefetch still in flight. Neither can reject — both swallow their errors.\n */\n async finalize(): Promise<void> {\n await Promise.all([this.prefetchPromise, this.streamPromise]);\n }\n\n /**\n * Merges caller-provided passthrough headers with the SDK's fixed headers.\n * Fixed headers are spread last so SDK-managed keys (auth, content-type,\n * correlation IDs) always win over any passthrough value.\n */\n private mergeHeaders(\n fixed: Record<string, string>,\n ): Record<string, string> {\n return { ...this.customHeaders, ...fixed };\n }\n\n private async executeStreamFetch(\n body: ReadableStream<Uint8Array>,\n headers: Record<string, string>,\n ): Promise<void> {\n const timeout = setTimeout(\n () => this.abortController?.abort(),\n this.timeoutMs,\n );\n\n try {\n const res = await fetch(`${this.endpointUrl}/stream`, {\n method: \"POST\",\n headers,\n body,\n signal: this.abortController?.signal,\n // @ts-expect-error -- required for streaming request bodies (Node/undici)\n duplex: \"half\",\n });\n\n clearTimeout(timeout);\n\n if (!res.ok || !res.body) return;\n\n await this.readStream(res.body);\n } catch {\n clearTimeout(timeout);\n }\n }\n\n /** Drains and returns any queued inline ad events. */\n drainInlineAds(): InlineAdEvent[] {\n const ads = this.inlineAdQueue.splice(0);\n return ads;\n }\n\n /** Cancels pending requests and cleans up state. */\n abort(): void {\n this.abortController?.abort();\n this.stopPolling();\n this.streamEnded = true;\n }\n\n /** Polls the placement endpoint once. Called on an interval internally. */\n async pollPlacements(): Promise<void> {\n if (!this.sidecarEnabled || !this.placementEndpoint) return;\n\n try {\n const res = await fetch(this.placementEndpoint, {\n method: \"GET\",\n headers: this.mergeHeaders({ \"X-API-Key\": this.apiKey }),\n });\n if (!res.ok) return;\n\n const data = (await res.json()) as PlacementsResponse;\n for (const placement of data.placements) {\n this.onPlacement?.(placement);\n }\n } catch {\n // Polling failure is non-fatal\n }\n }\n\n private async readStream(body: ReadableStream<Uint8Array>): Promise<void> {\n try {\n for await (const frame of parseSSE(body)) {\n if (this.abortController?.signal.aborted) break;\n this.handleFrame(frame.event, frame.data);\n }\n } catch {\n // Stream read error — degrade gracefully\n } finally {\n this.streamEnded = true;\n this.stopPolling();\n }\n }\n\n private handleFrame(event: string | undefined, data: string): void {\n switch (event) {\n case \"adzen_stream_start\": {\n try {\n const parsed = JSON.parse(data) as Omit<AdzenStreamStartEvent, \"type\">;\n const evt: AdzenStreamStartEvent = { type: \"adzen_stream_start\", ...parsed };\n this.placementEndpoint = parsed.placement_endpoint;\n this.onStreamStart?.(evt);\n this.startPolling();\n } catch { /* malformed — skip */ }\n break;\n }\n case \"adzen_inline\": {\n try {\n const ad = JSON.parse(data) as InlineAdEvent;\n this.inlineAdQueue.push(ad);\n this.onInlineAd?.(ad);\n } catch { /* malformed — skip */ }\n break;\n }\n case \"adzen_error\": {\n try {\n const parsed = JSON.parse(data) as Omit<AdzenStreamErrorEvent, \"type\">;\n this.onError?.({ type: \"adzen_error\", ...parsed });\n } catch { /* malformed — skip */ }\n break;\n }\n case \"adzen_stream_end\": {\n try {\n const parsed = JSON.parse(data) as Omit<AdzenStreamEndEvent, \"type\">;\n const evt: AdzenStreamEndEvent = { type: \"adzen_stream_end\", ...parsed };\n this.onStreamEnd?.(evt);\n } catch { /* malformed — skip */ }\n this.streamEnded = true;\n this.stopPolling();\n break;\n }\n default: {\n if (event?.startsWith(\"adzen_debug_\")) break;\n break;\n }\n }\n }\n\n private startPolling(): void {\n if (!this.sidecarEnabled) return;\n if (this.pollTimer || !this.placementEndpoint) return;\n this.pollTimer = setInterval(\n () => this.pollPlacements(),\n this.placementPollIntervalMs,\n );\n }\n\n private stopPolling(): void {\n if (this.pollTimer) {\n clearInterval(this.pollTimer);\n this.pollTimer = null;\n }\n }\n}\n","/**\n * Lightweight SSE parser that reads a ReadableStream<Uint8Array> and yields\n * parsed frames. Handles multi-line `data:` fields, named event types, and\n * ignores `id:` / `retry:` fields per the SSE spec.\n */\n\nexport interface SSEFrame {\n event?: string;\n data: string;\n}\n\nexport async function* parseSSE(\n stream: ReadableStream<Uint8Array>,\n): AsyncGenerator<SSEFrame> {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n let currentEvent: string | undefined;\n let dataLines: string[] = [];\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop()!;\n\n for (const raw of lines) {\n const line = raw.endsWith(\"\\r\") ? raw.slice(0, -1) : raw;\n\n if (line === \"\") {\n if (dataLines.length > 0) {\n yield { event: currentEvent, data: dataLines.join(\"\\n\") };\n dataLines = [];\n currentEvent = undefined;\n }\n continue;\n }\n\n if (line.startsWith(\":\")) continue;\n\n const colonIdx = line.indexOf(\":\");\n if (colonIdx === -1) continue;\n\n const field = line.slice(0, colonIdx);\n const value = line.slice(colonIdx + 1).replace(/^ /, \"\");\n\n switch (field) {\n case \"data\":\n dataLines.push(value);\n break;\n case \"event\":\n currentEvent = value;\n break;\n // id and retry are intentionally ignored\n }\n }\n }\n\n if (dataLines.length > 0) {\n yield { event: currentEvent, data: dataLines.join(\"\\n\") };\n }\n } finally {\n reader.releaseLock();\n }\n}\n","import type {\n AdzenPlacement,\n InlineAdEvent,\n InlineAdEventPayload,\n PlacementRecord,\n AdzenStreamErrorEvent,\n} from \"@adzenai/core\";\nimport { AdzenStreamClient } from \"./AdzenStreamClient.js\";\nimport type { AdzenStreamConfig } from \"./AdzenStreamClient.js\";\n\nexport interface AdzenStreamMiddlewareConfig extends AdzenStreamConfig {\n adUnitPosition?: string;\n}\n\n/**\n * AG-UI middleware that proxies the LLM response stream through Adzen's\n * streaming endpoint for real-time ad enrichment.\n *\n * Uses a stream transformer pattern: `processStream()` takes an\n * AsyncIterable of AG-UI events and yields an enriched stream that\n * includes inline ad events and sidecar placements.\n *\n * Supports the 2-step chained flow: when `prefetch: true` and a `prompt`\n * is provided, fires POST /process before opening the stream connection.\n */\nexport class AdzenStreamMiddleware {\n private config: AdzenStreamMiddlewareConfig;\n private adUnitPosition: string;\n\n constructor(config: AdzenStreamMiddlewareConfig) {\n this.config = config;\n this.adUnitPosition = config.adUnitPosition ?? \"chin\";\n }\n\n async *processStream(\n events: AsyncIterable<Record<string, unknown>>,\n options?: { prompt?: string; upstreamBody?: ReadableStream<Uint8Array> },\n ): AsyncGenerator<Record<string, unknown>> {\n const sidecarPlacements: AdzenPlacement[] = [];\n let client: AdzenStreamClient | null = null;\n let currentMessageId = \"\";\n let contentOffset = 0;\n\n const onPlacement = (record: PlacementRecord) => {\n sidecarPlacements.push(this.mapPlacementRecord(record, currentMessageId));\n };\n\n const onError = (error: AdzenStreamErrorEvent) => {\n console.warn(`[adzen-stream] ${error.code}: ${error.message}`);\n };\n\n for await (const event of events) {\n const type = String(event.type ?? \"\");\n\n switch (type) {\n case \"RUN_STARTED\":\n case \"RunStarted\": {\n const threadId = String(event.threadId ?? \"\");\n\n client = new AdzenStreamClient({\n ...this.config,\n conversationId: threadId || this.config.conversationId,\n onPlacement,\n onError,\n });\n\n if (this.config.prefetch && options?.prompt) {\n client.startPrefetch(options.prompt);\n }\n\n yield event;\n break;\n }\n\n case \"TEXT_MESSAGE_START\":\n case \"TextMessageStart\": {\n currentMessageId = String(event.messageId ?? \"\");\n contentOffset = 0;\n if (client && options?.upstreamBody) {\n client.connect(currentMessageId, options.upstreamBody);\n }\n yield event;\n break;\n }\n\n case \"TEXT_MESSAGE_CONTENT\":\n case \"TextMessageContent\": {\n yield event;\n contentOffset += String(event.delta ?? \"\").length;\n\n if (client) {\n for (const ad of client.drainInlineAds()) {\n yield this.makeInlineAdEvent(ad, currentMessageId, contentOffset);\n }\n }\n break;\n }\n\n case \"TEXT_MESSAGE_END\":\n case \"TextMessageEnd\": {\n if (client) {\n await client.finalize();\n for (const ad of client.drainInlineAds()) {\n yield this.makeInlineAdEvent(ad, currentMessageId, contentOffset);\n }\n }\n yield event;\n break;\n }\n\n case \"RUN_FINISHED\":\n case \"RunFinished\": {\n if (client) {\n await client.pollPlacements();\n client.abort();\n }\n\n for (const placement of sidecarPlacements) {\n yield this.makePlacementEvent(placement, placement.ad_id);\n }\n\n yield event;\n break;\n }\n\n default:\n yield event;\n }\n }\n }\n\n /**\n * Wraps an inline ad as an AG-UI custom event anchored to `contentOffset`,\n * the number of message characters emitted before the ad arrived. Clients\n * use it to render the ad directly after that content instead of at the\n * end of the message.\n */\n private makeInlineAdEvent(\n ad: InlineAdEvent,\n messageId: string,\n contentOffset: number,\n ): Record<string, unknown> {\n const value: InlineAdEventPayload = {\n ...ad,\n message_id: messageId,\n content_offset: contentOffset,\n };\n return {\n type: \"CUSTOM_EVENT\",\n name: \"adzen_inline_ad\",\n messageId,\n value,\n };\n }\n\n private makePlacementEvent(\n placement: AdzenPlacement,\n adId: string,\n ): Record<string, unknown> {\n return {\n type: \"CUSTOM_EVENT\",\n name: \"adzen_placement\",\n messageId: adId,\n value: {\n ...placement,\n message_id: placement.ad_id,\n },\n };\n }\n\n private mapPlacementRecord(\n record: PlacementRecord,\n messageId: string,\n ): AdzenPlacement {\n return {\n ad_id: String(record.ad_id),\n advertiser_name: \"\",\n headline: record.headline,\n cta_text: record.cta_text,\n destination_url: record.destination_url,\n adUnitPosition: record.placement || this.adUnitPosition,\n render_impression_url: record.tracking.impression_url,\n view_impression_url: record.tracking.impression_url,\n };\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACkBA,SAAS,yBAAiC;AACxC,QAAM,eAAgB,WACnB;AACH,MAAI,cAAc,WAAY,QAAO,aAAa,WAAW;AAC7D,SAAO,SAAS,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;AACnE;AAEA,SAAS,mBAAmB,OAAyC;AACnE,QAAM,OAAO,OAAO,MAAM,QAAQ,EAAE;AACpC,MAAI,SAAS,kBAAkB,SAAS,cAAe,QAAO;AAC9D,MAAI,SAAS,YAAY,SAAS,kBAAkB,SAAS;AAC3D,WAAO;AACT,MAAI,MAAM,UAAU,QAAQ,MAAM,YAAY,KAAM,QAAO;AAC3D,QAAM,OAAO,OAAO,MAAM,QAAQ,MAAM,SAAS,EAAE,EAAE,YAAY;AACjE,SAAO,KAAK,SAAS,iBAAiB,KAAK,KAAK,SAAS,cAAc;AACzE;AAEA,SAAS,wBAAwB,OAA+C;AAC9E,aAAW,OAAO,CAAC,UAAU,UAAU,QAAQ,WAAW,SAAS,GAAG;AACpE,UAAM,MAAM,MAAM,GAAG;AACrB,QAAI,OAAO,QAAQ,YAAY,IAAI,SAAS,EAAG,QAAO;AACtD,QAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM;AAC3C,UAAI;AACF,eAAO,KAAK,UAAU,GAAG;AAAA,MAC3B,QAAQ;AACN;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAWO,IAAM,uBAAN,MAA2B;AAAA,EACxB;AAAA,EAEA,UAAU,oBAAI,IAA2B;AAAA,EACzC,aAAa,oBAAI,IAAY;AAAA,EAC7B,iBAAkC,CAAC;AAAA,EACnC,kBAAkB;AAAA,EAClB;AAAA,EAER,YAAY,QAA0B;AACpC,SAAK,SAAS;AAAA,MACZ,GAAG;AAAA,MACH,aAAa,OAAO,eAAe;AAAA,MACnC,WAAW,OAAO,aAAa;AAAA,MAC/B,gBAAgB,OAAO,kBAAkB;AAAA,IAC3C;AACA,SAAK,iBAAiB,OAAO;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,aAAa,OAAoE;AACrF,UAAM,OAAO,OAAO,MAAM,QAAQ,EAAE;AAEpC,YAAQ,MAAM;AAAA,MACZ,KAAK;AAAA,MACL,KAAK,cAAc;AACjB,cAAM,WAAW,OAAO,MAAM,YAAY,EAAE;AAC5C,YAAI,SAAU,MAAK,iBAAiB;AACpC,eAAO,CAAC,KAAK;AAAA,MACf;AAAA,MAEA,KAAK;AAAA,MACL,KAAK,oBAAoB;AACvB,cAAM,YAAY,KAAK,iBAAiB,KAAK;AAC7C,aAAK,kBAAkB;AACvB,aAAK,QAAQ,IAAI,WAAW;AAAA,UAC1B,SAAS;AAAA,UACT,WAAW,KAAK,IAAI;AAAA,UACpB,SAAS;AAAA,QACX,CAAC;AACD,eAAO,CAAC,KAAK;AAAA,MACf;AAAA,MAEA,KAAK;AAAA,MACL,KAAK,sBAAsB;AACzB,cAAM,YAAY,OAAO,MAAM,aAAa,EAAE;AAC9C,cAAM,MAAM,KAAK,QAAQ,IAAI,SAAS;AACtC,YAAI,IAAK,KAAI,WAAW,OAAO,MAAM,SAAS,EAAE;AAChD,eAAO,CAAC,KAAK;AAAA,MACf;AAAA,MAEA,KAAK;AAAA,MACL,KAAK,kBAAkB;AACrB,cAAM,YAAY,OAAO,MAAM,aAAa,EAAE;AAC9C,cAAM,MAAM,KAAK,QAAQ,IAAI,SAAS;AACtC,cAAM,MAAiC,CAAC,KAAK;AAE7C,YAAI,OAAO,CAAC,IAAI,SAAS;AACvB,cAAI,UAAU;AACd,eAAK,WAAW,IAAI,SAAS;AAC7B,gBAAM,eAAe,KAAK,QAAQ,IAAI,SAAS,SAAS,EAAE;AAAA,YACxD,CAAC,cAAc;AACb,kBAAI,UAAW,KAAI,KAAK,KAAK,mBAAmB,WAAW,SAAS,CAAC;AAAA,YACvE;AAAA,UACF;AACA,eAAK,eAAe,KAAK,YAAY;AACrC,gBAAM;AACN,eAAK,QAAQ,OAAO,SAAS;AAAA,QAC/B;AAEA,eAAO;AAAA,MACT;AAAA,MAEA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK,eAAe;AAClB,YAAI,mBAAmB,KAAK,GAAG;AAC7B,gBAAM,YAAY,OAAO,MAAM,aAAa,EAAE;AAC9C,cAAI,CAAC,KAAK,WAAW,IAAI,SAAS,GAAG;AACnC,kBAAM,MAAM,KAAK,QAAQ,IAAI,SAAS;AACtC,kBAAM,UAAU,wBAAwB,KAAK;AAC7C,gBAAI,SAAS;AACX,oBAAM,MAAiC,CAAC,KAAK;AAC7C,kBAAI,IAAK,KAAI,UAAU;AACvB,mBAAK,WAAW,IAAI,SAAS;AAC7B,oBAAM,eAAe,KAAK,QAAQ,SAAS,SAAS,EAAE;AAAA,gBACpD,CAAC,cAAc;AACb,sBAAI,UAAW,KAAI,KAAK,KAAK,mBAAmB,WAAW,SAAS,CAAC;AAAA,gBACvE;AAAA,cACF;AACA,mBAAK,eAAe,KAAK,YAAY;AACrC,oBAAM;AACN,qBAAO;AAAA,YACT;AAAA,UACF;AAAA,QACF;AACA,eAAO,CAAC,KAAK;AAAA,MACf;AAAA,MAEA,KAAK;AAAA,MACL,KAAK,eAAe;AAClB,cAAM,QAAQ,WAAW,KAAK,cAAc;AAC5C,aAAK,iBAAiB,CAAC;AACvB,eAAO,CAAC,KAAK;AAAA,MACf;AAAA,MAEA;AACE,eAAO,CAAC,KAAK;AAAA,IACjB;AAAA,EACF;AAAA,EAEQ,iBAAiB,OAAwC;AAC/D,UAAM,KAAK,OAAO,MAAM,aAAa,EAAE;AACvC,QAAI,GAAI,QAAO;AACf,WAAO,oBAAoB,KAAK,IAAI,CAAC,IAAI,KAAK,iBAAiB;AAAA,EACjE;AAAA,EAEQ,oBAA0B;AAChC,UAAM,SAAS,KAAK,IAAI,IAAI,KAAK,OAAO,YAAY;AACpD,eAAW,CAAC,KAAK,GAAG,KAAK,KAAK,SAAS;AACrC,UAAI,IAAI,YAAY,OAAQ,MAAK,QAAQ,OAAO,GAAG;AAAA,IACrD;AAAA,EACF;AAAA,EAEA,MAAc,QACZ,SACA,WACgC;AAChC,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,OAAO,SAAS;AAE1E,QAAI;AACF,YAAM,OAAgC;AAAA,QACpC;AAAA,QACA,YAAY;AAAA,MACd;AACA,UAAI,KAAK,OAAO,SAAU,MAAK,WAAW,KAAK,OAAO;AACtD,UAAI,KAAK,eAAgB,MAAK,kBAAkB,KAAK;AAErD,YAAM,UAAkC;AAAA,QACtC,gBAAgB;AAAA,QAChB,aAAa,KAAK,OAAO;AAAA;AAAA;AAAA,QAGzB,mBAAmB,uBAAuB;AAAA,MAC5C;AACA,UAAI,KAAK,OAAO,UAAW,SAAQ,cAAc,IAAI,KAAK,OAAO;AAEjE,YAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,WAAW,YAAY;AAAA,QAC5D,QAAQ;AAAA,QACR;AAAA,QACA,MAAM,KAAK,UAAU,IAAI;AAAA,QACzB,QAAQ,WAAW;AAAA,MACrB,CAAC;AAED,UAAI,CAAC,IAAI,GAAI,QAAO;AAEpB,YAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,YAAM,QAAQ,KAAK,MAAM,CAAC;AAC1B,UAAI,CAAC,MAAO,QAAO;AACnB,aAAO,KAAK,uBAAuB,KAAK;AAAA,IAC1C,QAAQ;AACN,aAAO;AAAA,IACT,UAAE;AACA,mBAAa,OAAO;AAAA,IACtB;AAAA,EACF;AAAA,EAEQ,uBAAuB,IAAuC;AACpE,WAAO;AAAA,MACL,OAAO,OAAO,GAAG,KAAK;AAAA,MACtB,iBAAiB,GAAG;AAAA,MACpB,sBAAsB,GAAG,oBAAoB;AAAA,MAC7C,UAAU,GAAG;AAAA,MACb,aAAa,GAAG;AAAA,MAChB,UAAU,GAAG;AAAA,MACb,iBAAiB,GAAG;AAAA,MACpB,cAAc,GAAG,gBAAgB;AAAA,MACjC,gBAAgB,GAAG,aAAa,KAAK,OAAO;AAAA,MAC5C,uBAAuB,GAAG;AAAA,MAC1B,qBAAqB,GAAG;AAAA,IAC1B;AAAA,EACF;AAAA,EAEQ,mBACN,WACA,WACyB;AACzB,WAAO;AAAA;AAAA;AAAA;AAAA,MAIL,MAAM;AAAA,MACN,MAAM;AAAA,MACN;AAAA,MACA,OAAO;AAAA,QACL,GAAG;AAAA,QACH,YAAY;AAAA,MACd;AAAA,IACF;AAAA,EACF;AACF;;;AChQA,kBAAuB;;;ACGvB,gBAAuB,SACrB,QAC0B;AAC1B,QAAM,SAAS,OAAO,UAAU;AAChC,QAAM,UAAU,IAAI,YAAY;AAChC,MAAI,SAAS;AACb,MAAI;AACJ,MAAI,YAAsB,CAAC;AAE3B,MAAI;AACF,WAAO,MAAM;AACX,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AAEV,gBAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAChD,YAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,eAAS,MAAM,IAAI;AAEnB,iBAAW,OAAO,OAAO;AACvB,cAAM,OAAO,IAAI,SAAS,IAAI,IAAI,IAAI,MAAM,GAAG,EAAE,IAAI;AAErD,YAAI,SAAS,IAAI;AACf,cAAI,UAAU,SAAS,GAAG;AACxB,kBAAM,EAAE,OAAO,cAAc,MAAM,UAAU,KAAK,IAAI,EAAE;AACxD,wBAAY,CAAC;AACb,2BAAe;AAAA,UACjB;AACA;AAAA,QACF;AAEA,YAAI,KAAK,WAAW,GAAG,EAAG;AAE1B,cAAM,WAAW,KAAK,QAAQ,GAAG;AACjC,YAAI,aAAa,GAAI;AAErB,cAAM,QAAQ,KAAK,MAAM,GAAG,QAAQ;AACpC,cAAMA,SAAQ,KAAK,MAAM,WAAW,CAAC,EAAE,QAAQ,MAAM,EAAE;AAEvD,gBAAQ,OAAO;AAAA,UACb,KAAK;AACH,sBAAU,KAAKA,MAAK;AACpB;AAAA,UACF,KAAK;AACH,2BAAeA;AACf;AAAA,QAEJ;AAAA,MACF;AAAA,IACF;AAEA,QAAI,UAAU,SAAS,GAAG;AACxB,YAAM,EAAE,OAAO,cAAc,MAAM,UAAU,KAAK,IAAI,EAAE;AAAA,IAC1D;AAAA,EACF,UAAE;AACA,WAAO,YAAY;AAAA,EACrB;AACF;;;AD3BA,IAAM,mBAAmB;AACzB,IAAM,qBAAqB;AAC3B,IAAM,2BAA2B;AAWjC,IAAM,4BAA4B,MAAM;AACtC,MAAI;AACF,QAAI,iBAAiB;AACrB,UAAM,iBAAiB,IAAI,QAAQ,oBAAoB;AAAA,MACrD,QAAQ;AAAA,MACR,MAAM,IAAI,eAAe;AAAA,MACzB,IAAI,SAAS;AACX,yBAAiB;AACjB,eAAO;AAAA,MACT;AAAA,IACF,CAAgB,EAAE,QAAQ,IAAI,cAAc;AAC5C,WAAO,kBAAkB,CAAC;AAAA,EAC5B,QAAQ;AACN,WAAO;AAAA,EACT;AACF,GAAG;AASI,IAAM,oBAAN,MAAwB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA,kBAA0C;AAAA,EAC1C,oBAAmC;AAAA,EACnC,YAAmD;AAAA,EACnD,cAAc;AAAA,EACd,gBAAiC,CAAC;AAAA,EAClC,gBAAsC;AAAA,EACtC,kBAAwC;AAAA,EAExC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,QAA2B;AACrC,SAAK,cAAc,OAAO,eAAe;AACzC,SAAK,SAAS,OAAO;AACrB,SAAK,YAAY,OAAO,aAAa;AACrC,SAAK,WAAW,OAAO;AACvB,SAAK,YAAY,OAAO;AACxB,SAAK,0BACH,OAAO,2BAA2B;AACpC,SAAK,kBAAkB,OAAO,YAAY;AAC1C,SAAK,iBAAiB,OAAO,WAAW;AACxC,SAAK,gBAAgB,OAAO,WAAW,CAAC;AACxC,SAAK,iBAAiB,OAAO,sBAAkB,oBAAO;AAEtD,SAAK,aAAa,OAAO;AACzB,SAAK,cAAc,OAAO;AAC1B,SAAK,UAAU,OAAO;AACtB,SAAK,gBAAgB,OAAO;AAC5B,SAAK,cAAc,OAAO;AAAA,EAC5B;AAAA,EAEA,oBAA4B;AAC1B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,kBAAkB,IAAkB;AAClC,SAAK,iBAAiB;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,cAAc,QAAsB;AAClC,QAAI,CAAC,KAAK,gBAAiB;AAC3B,SAAK,kBAAkB,KAAK,gBAAgB,MAAM;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,gBAAgB,QAA+B;AACnD,QAAI,CAAC,KAAK,gBAAiB;AAE3B,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,SAAS;AAEnE,QAAI;AACF,YAAM,OAAgC;AAAA,QACpC,SAAS;AAAA,QACT,gBAAY,oBAAO;AAAA,QACnB,iBAAiB,KAAK;AAAA,MACxB;AACA,UAAI,KAAK,SAAU,MAAK,WAAW,KAAK;AAExC,YAAM,UAAkC;AAAA,QACtC,gBAAgB;AAAA,QAChB,aAAa,KAAK;AAAA,QAClB,uBAAmB,oBAAO;AAAA,MAC5B;AACA,UAAI,KAAK,UAAW,SAAQ,cAAc,IAAI,KAAK;AAEnD,YAAM,MAAM,GAAG,KAAK,WAAW,YAAY;AAAA,QACzC,QAAQ;AAAA,QACR,SAAS,KAAK,aAAa,OAAO;AAAA,QAClC,MAAM,KAAK,UAAU,IAAI;AAAA,QACzB,QAAQ,WAAW;AAAA,MACrB,CAAC;AAAA,IACH,QAAQ;AAAA,IAER,UAAE;AACA,mBAAa,OAAO;AAAA,IACtB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,QAAQ,WAAmB,MAAwC;AACjE,SAAK,cAAc;AACnB,SAAK,gBAAgB,CAAC;AACtB,SAAK,oBAAoB;AACzB,SAAK,gBAAgB;AACrB,SAAK,kBAAkB,IAAI,gBAAgB;AAE3C,QAAI,CAAC,0BAA0B;AAC7B,WAAK,cAAc;AACnB,WAAK,UAAU;AAAA,QACb,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SACE;AAAA,MAGJ,CAAC;AACD,WAAK,KAAK,OAAO,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AACjC;AAAA,IACF;AAEA,UAAM,UAAkC;AAAA,MACtC,gBAAgB;AAAA,MAChB,aAAa,KAAK;AAAA,MAClB,uBAAmB,oBAAO;AAAA,MAC1B,gBAAgB;AAAA,MAChB,qBAAqB,KAAK;AAAA,IAC5B;AACA,QAAI,KAAK,UAAW,SAAQ,cAAc,IAAI,KAAK;AACnD,QAAI,KAAK,SAAU,SAAQ,YAAY,IAAI,KAAK;AAEhD,SAAK,gBAAgB,KAAK,mBAAmB,MAAM,KAAK,aAAa,OAAO,CAAC;AAAA,EAC/E;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,WAA0B;AAC9B,UAAM,QAAQ,IAAI,CAAC,KAAK,iBAAiB,KAAK,aAAa,CAAC;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,aACN,OACwB;AACxB,WAAO,EAAE,GAAG,KAAK,eAAe,GAAG,MAAM;AAAA,EAC3C;AAAA,EAEA,MAAc,mBACZ,MACA,SACe;AACf,UAAM,UAAU;AAAA,MACd,MAAM,KAAK,iBAAiB,MAAM;AAAA,MAClC,KAAK;AAAA,IACP;AAEA,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,GAAG,KAAK,WAAW,WAAW;AAAA,QACpD,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA,QAAQ,KAAK,iBAAiB;AAAA;AAAA,QAE9B,QAAQ;AAAA,MACV,CAAC;AAED,mBAAa,OAAO;AAEpB,UAAI,CAAC,IAAI,MAAM,CAAC,IAAI,KAAM;AAE1B,YAAM,KAAK,WAAW,IAAI,IAAI;AAAA,IAChC,QAAQ;AACN,mBAAa,OAAO;AAAA,IACtB;AAAA,EACF;AAAA;AAAA,EAGA,iBAAkC;AAChC,UAAM,MAAM,KAAK,cAAc,OAAO,CAAC;AACvC,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,QAAc;AACZ,SAAK,iBAAiB,MAAM;AAC5B,SAAK,YAAY;AACjB,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA,EAGA,MAAM,iBAAgC;AACpC,QAAI,CAAC,KAAK,kBAAkB,CAAC,KAAK,kBAAmB;AAErD,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,KAAK,mBAAmB;AAAA,QAC9C,QAAQ;AAAA,QACR,SAAS,KAAK,aAAa,EAAE,aAAa,KAAK,OAAO,CAAC;AAAA,MACzD,CAAC;AACD,UAAI,CAAC,IAAI,GAAI;AAEb,YAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,iBAAW,aAAa,KAAK,YAAY;AACvC,aAAK,cAAc,SAAS;AAAA,MAC9B;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,MAAc,WAAW,MAAiD;AACxE,QAAI;AACF,uBAAiB,SAAS,SAAS,IAAI,GAAG;AACxC,YAAI,KAAK,iBAAiB,OAAO,QAAS;AAC1C,aAAK,YAAY,MAAM,OAAO,MAAM,IAAI;AAAA,MAC1C;AAAA,IACF,QAAQ;AAAA,IAER,UAAE;AACA,WAAK,cAAc;AACnB,WAAK,YAAY;AAAA,IACnB;AAAA,EACF;AAAA,EAEQ,YAAY,OAA2B,MAAoB;AACjE,YAAQ,OAAO;AAAA,MACb,KAAK,sBAAsB;AACzB,YAAI;AACF,gBAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,gBAAM,MAA6B,EAAE,MAAM,sBAAsB,GAAG,OAAO;AAC3E,eAAK,oBAAoB,OAAO;AAChC,eAAK,gBAAgB,GAAG;AACxB,eAAK,aAAa;AAAA,QACpB,QAAQ;AAAA,QAAyB;AACjC;AAAA,MACF;AAAA,MACA,KAAK,gBAAgB;AACnB,YAAI;AACF,gBAAM,KAAK,KAAK,MAAM,IAAI;AAC1B,eAAK,cAAc,KAAK,EAAE;AAC1B,eAAK,aAAa,EAAE;AAAA,QACtB,QAAQ;AAAA,QAAyB;AACjC;AAAA,MACF;AAAA,MACA,KAAK,eAAe;AAClB,YAAI;AACF,gBAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,eAAK,UAAU,EAAE,MAAM,eAAe,GAAG,OAAO,CAAC;AAAA,QACnD,QAAQ;AAAA,QAAyB;AACjC;AAAA,MACF;AAAA,MACA,KAAK,oBAAoB;AACvB,YAAI;AACF,gBAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,gBAAM,MAA2B,EAAE,MAAM,oBAAoB,GAAG,OAAO;AACvE,eAAK,cAAc,GAAG;AAAA,QACxB,QAAQ;AAAA,QAAyB;AACjC,aAAK,cAAc;AACnB,aAAK,YAAY;AACjB;AAAA,MACF;AAAA,MACA,SAAS;AACP,YAAI,OAAO,WAAW,cAAc,EAAG;AACvC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,eAAqB;AAC3B,QAAI,CAAC,KAAK,eAAgB;AAC1B,QAAI,KAAK,aAAa,CAAC,KAAK,kBAAmB;AAC/C,SAAK,YAAY;AAAA,MACf,MAAM,KAAK,eAAe;AAAA,MAC1B,KAAK;AAAA,IACP;AAAA,EACF;AAAA,EAEQ,cAAoB;AAC1B,QAAI,KAAK,WAAW;AAClB,oBAAc,KAAK,SAAS;AAC5B,WAAK,YAAY;AAAA,IACnB;AAAA,EACF;AACF;;;AEpWO,IAAM,wBAAN,MAA4B;AAAA,EACzB;AAAA,EACA;AAAA,EAER,YAAY,QAAqC;AAC/C,SAAK,SAAS;AACd,SAAK,iBAAiB,OAAO,kBAAkB;AAAA,EACjD;AAAA,EAEA,OAAO,cACL,QACA,SACyC;AACzC,UAAM,oBAAsC,CAAC;AAC7C,QAAI,SAAmC;AACvC,QAAI,mBAAmB;AACvB,QAAI,gBAAgB;AAEpB,UAAM,cAAc,CAAC,WAA4B;AAC/C,wBAAkB,KAAK,KAAK,mBAAmB,QAAQ,gBAAgB,CAAC;AAAA,IAC1E;AAEA,UAAM,UAAU,CAAC,UAAiC;AAChD,cAAQ,KAAK,kBAAkB,MAAM,IAAI,KAAK,MAAM,OAAO,EAAE;AAAA,IAC/D;AAEA,qBAAiB,SAAS,QAAQ;AAChC,YAAM,OAAO,OAAO,MAAM,QAAQ,EAAE;AAEpC,cAAQ,MAAM;AAAA,QACZ,KAAK;AAAA,QACL,KAAK,cAAc;AACjB,gBAAM,WAAW,OAAO,MAAM,YAAY,EAAE;AAE5C,mBAAS,IAAI,kBAAkB;AAAA,YAC7B,GAAG,KAAK;AAAA,YACR,gBAAgB,YAAY,KAAK,OAAO;AAAA,YACxC;AAAA,YACA;AAAA,UACF,CAAC;AAED,cAAI,KAAK,OAAO,YAAY,SAAS,QAAQ;AAC3C,mBAAO,cAAc,QAAQ,MAAM;AAAA,UACrC;AAEA,gBAAM;AACN;AAAA,QACF;AAAA,QAEA,KAAK;AAAA,QACL,KAAK,oBAAoB;AACvB,6BAAmB,OAAO,MAAM,aAAa,EAAE;AAC/C,0BAAgB;AAChB,cAAI,UAAU,SAAS,cAAc;AACnC,mBAAO,QAAQ,kBAAkB,QAAQ,YAAY;AAAA,UACvD;AACA,gBAAM;AACN;AAAA,QACF;AAAA,QAEA,KAAK;AAAA,QACL,KAAK,sBAAsB;AACzB,gBAAM;AACN,2BAAiB,OAAO,MAAM,SAAS,EAAE,EAAE;AAE3C,cAAI,QAAQ;AACV,uBAAW,MAAM,OAAO,eAAe,GAAG;AACxC,oBAAM,KAAK,kBAAkB,IAAI,kBAAkB,aAAa;AAAA,YAClE;AAAA,UACF;AACA;AAAA,QACF;AAAA,QAEA,KAAK;AAAA,QACL,KAAK,kBAAkB;AACrB,cAAI,QAAQ;AACV,kBAAM,OAAO,SAAS;AACtB,uBAAW,MAAM,OAAO,eAAe,GAAG;AACxC,oBAAM,KAAK,kBAAkB,IAAI,kBAAkB,aAAa;AAAA,YAClE;AAAA,UACF;AACA,gBAAM;AACN;AAAA,QACF;AAAA,QAEA,KAAK;AAAA,QACL,KAAK,eAAe;AAClB,cAAI,QAAQ;AACV,kBAAM,OAAO,eAAe;AAC5B,mBAAO,MAAM;AAAA,UACf;AAEA,qBAAW,aAAa,mBAAmB;AACzC,kBAAM,KAAK,mBAAmB,WAAW,UAAU,KAAK;AAAA,UAC1D;AAEA,gBAAM;AACN;AAAA,QACF;AAAA,QAEA;AACE,gBAAM;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,kBACN,IACA,WACA,eACyB;AACzB,UAAM,QAA8B;AAAA,MAClC,GAAG;AAAA,MACH,YAAY;AAAA,MACZ,gBAAgB;AAAA,IAClB;AACA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,MAAM;AAAA,MACN;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,mBACN,WACA,MACyB;AACzB,WAAO;AAAA,MACL,MAAM;AAAA,MACN,MAAM;AAAA,MACN,WAAW;AAAA,MACX,OAAO;AAAA,QACL,GAAG;AAAA,QACH,YAAY,UAAU;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,mBACN,QACA,WACgB;AAChB,WAAO;AAAA,MACL,OAAO,OAAO,OAAO,KAAK;AAAA,MAC1B,iBAAiB;AAAA,MACjB,UAAU,OAAO;AAAA,MACjB,UAAU,OAAO;AAAA,MACjB,iBAAiB,OAAO;AAAA,MACxB,gBAAgB,OAAO,aAAa,KAAK;AAAA,MACzC,uBAAuB,OAAO,SAAS;AAAA,MACvC,qBAAqB,OAAO,SAAS;AAAA,IACvC;AAAA,EACF;AACF;","names":["value"]}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { InlineAdEvent, PlacementRecord, AdzenStreamErrorEvent, AdzenStreamStartEvent, AdzenStreamEndEvent } from '@adzenai/core';
|
|
2
|
+
|
|
1
3
|
interface AdzenAsyncConfig {
|
|
2
4
|
endpointUrl?: string;
|
|
3
5
|
apiKey: string;
|
|
@@ -5,6 +7,7 @@ interface AdzenAsyncConfig {
|
|
|
5
7
|
adUnitPosition?: string;
|
|
6
8
|
location?: string;
|
|
7
9
|
conversationId?: string;
|
|
10
|
+
profileId?: string;
|
|
8
11
|
}
|
|
9
12
|
/**
|
|
10
13
|
* AG-UI middleware that intercepts the event stream and calls AI-API after
|
|
@@ -36,4 +39,66 @@ declare class AdzenAsyncMiddleware {
|
|
|
36
39
|
private makePlacementEvent;
|
|
37
40
|
}
|
|
38
41
|
|
|
39
|
-
|
|
42
|
+
interface AdzenStreamConfig {
|
|
43
|
+
apiKey: string;
|
|
44
|
+
endpointUrl?: string;
|
|
45
|
+
timeoutMs?: number;
|
|
46
|
+
location?: string;
|
|
47
|
+
conversationId?: string;
|
|
48
|
+
profileId?: string;
|
|
49
|
+
placementPollIntervalMs?: number;
|
|
50
|
+
prefetch?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Whether to poll the sidecar placement endpoint for out-of-stream ads
|
|
53
|
+
* rendered outside the message body. Defaults to `true`. Set to `false`
|
|
54
|
+
* to run inline-only, leaving `adzen_inline` events unaffected.
|
|
55
|
+
*/
|
|
56
|
+
sidecar?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Extra request headers merged into every outbound Adzen request
|
|
59
|
+
* (/stream, /process, placement polling). Intended for internal
|
|
60
|
+
* debugging (e.g. `X-Adzen-Debug-*`). SDK-managed headers
|
|
61
|
+
* (auth, content-type, correlation IDs) always take precedence.
|
|
62
|
+
*/
|
|
63
|
+
headers?: Record<string, string>;
|
|
64
|
+
onInlineAd?: (ad: InlineAdEvent) => void;
|
|
65
|
+
onPlacement?: (placement: PlacementRecord) => void;
|
|
66
|
+
onError?: (error: AdzenStreamErrorEvent) => void;
|
|
67
|
+
onStreamStart?: (event: AdzenStreamStartEvent) => void;
|
|
68
|
+
onStreamEnd?: (event: AdzenStreamEndEvent) => void;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
interface AdzenStreamMiddlewareConfig extends AdzenStreamConfig {
|
|
72
|
+
adUnitPosition?: string;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* AG-UI middleware that proxies the LLM response stream through Adzen's
|
|
76
|
+
* streaming endpoint for real-time ad enrichment.
|
|
77
|
+
*
|
|
78
|
+
* Uses a stream transformer pattern: `processStream()` takes an
|
|
79
|
+
* AsyncIterable of AG-UI events and yields an enriched stream that
|
|
80
|
+
* includes inline ad events and sidecar placements.
|
|
81
|
+
*
|
|
82
|
+
* Supports the 2-step chained flow: when `prefetch: true` and a `prompt`
|
|
83
|
+
* is provided, fires POST /process before opening the stream connection.
|
|
84
|
+
*/
|
|
85
|
+
declare class AdzenStreamMiddleware {
|
|
86
|
+
private config;
|
|
87
|
+
private adUnitPosition;
|
|
88
|
+
constructor(config: AdzenStreamMiddlewareConfig);
|
|
89
|
+
processStream(events: AsyncIterable<Record<string, unknown>>, options?: {
|
|
90
|
+
prompt?: string;
|
|
91
|
+
upstreamBody?: ReadableStream<Uint8Array>;
|
|
92
|
+
}): AsyncGenerator<Record<string, unknown>>;
|
|
93
|
+
/**
|
|
94
|
+
* Wraps an inline ad as an AG-UI custom event anchored to `contentOffset`,
|
|
95
|
+
* the number of message characters emitted before the ad arrived. Clients
|
|
96
|
+
* use it to render the ad directly after that content instead of at the
|
|
97
|
+
* end of the message.
|
|
98
|
+
*/
|
|
99
|
+
private makeInlineAdEvent;
|
|
100
|
+
private makePlacementEvent;
|
|
101
|
+
private mapPlacementRecord;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export { type AdzenAsyncConfig, AdzenAsyncMiddleware, type AdzenStreamConfig, AdzenStreamMiddleware, type AdzenStreamMiddlewareConfig };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { InlineAdEvent, PlacementRecord, AdzenStreamErrorEvent, AdzenStreamStartEvent, AdzenStreamEndEvent } from '@adzenai/core';
|
|
2
|
+
|
|
1
3
|
interface AdzenAsyncConfig {
|
|
2
4
|
endpointUrl?: string;
|
|
3
5
|
apiKey: string;
|
|
@@ -5,6 +7,7 @@ interface AdzenAsyncConfig {
|
|
|
5
7
|
adUnitPosition?: string;
|
|
6
8
|
location?: string;
|
|
7
9
|
conversationId?: string;
|
|
10
|
+
profileId?: string;
|
|
8
11
|
}
|
|
9
12
|
/**
|
|
10
13
|
* AG-UI middleware that intercepts the event stream and calls AI-API after
|
|
@@ -36,4 +39,66 @@ declare class AdzenAsyncMiddleware {
|
|
|
36
39
|
private makePlacementEvent;
|
|
37
40
|
}
|
|
38
41
|
|
|
39
|
-
|
|
42
|
+
interface AdzenStreamConfig {
|
|
43
|
+
apiKey: string;
|
|
44
|
+
endpointUrl?: string;
|
|
45
|
+
timeoutMs?: number;
|
|
46
|
+
location?: string;
|
|
47
|
+
conversationId?: string;
|
|
48
|
+
profileId?: string;
|
|
49
|
+
placementPollIntervalMs?: number;
|
|
50
|
+
prefetch?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Whether to poll the sidecar placement endpoint for out-of-stream ads
|
|
53
|
+
* rendered outside the message body. Defaults to `true`. Set to `false`
|
|
54
|
+
* to run inline-only, leaving `adzen_inline` events unaffected.
|
|
55
|
+
*/
|
|
56
|
+
sidecar?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Extra request headers merged into every outbound Adzen request
|
|
59
|
+
* (/stream, /process, placement polling). Intended for internal
|
|
60
|
+
* debugging (e.g. `X-Adzen-Debug-*`). SDK-managed headers
|
|
61
|
+
* (auth, content-type, correlation IDs) always take precedence.
|
|
62
|
+
*/
|
|
63
|
+
headers?: Record<string, string>;
|
|
64
|
+
onInlineAd?: (ad: InlineAdEvent) => void;
|
|
65
|
+
onPlacement?: (placement: PlacementRecord) => void;
|
|
66
|
+
onError?: (error: AdzenStreamErrorEvent) => void;
|
|
67
|
+
onStreamStart?: (event: AdzenStreamStartEvent) => void;
|
|
68
|
+
onStreamEnd?: (event: AdzenStreamEndEvent) => void;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
interface AdzenStreamMiddlewareConfig extends AdzenStreamConfig {
|
|
72
|
+
adUnitPosition?: string;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* AG-UI middleware that proxies the LLM response stream through Adzen's
|
|
76
|
+
* streaming endpoint for real-time ad enrichment.
|
|
77
|
+
*
|
|
78
|
+
* Uses a stream transformer pattern: `processStream()` takes an
|
|
79
|
+
* AsyncIterable of AG-UI events and yields an enriched stream that
|
|
80
|
+
* includes inline ad events and sidecar placements.
|
|
81
|
+
*
|
|
82
|
+
* Supports the 2-step chained flow: when `prefetch: true` and a `prompt`
|
|
83
|
+
* is provided, fires POST /process before opening the stream connection.
|
|
84
|
+
*/
|
|
85
|
+
declare class AdzenStreamMiddleware {
|
|
86
|
+
private config;
|
|
87
|
+
private adUnitPosition;
|
|
88
|
+
constructor(config: AdzenStreamMiddlewareConfig);
|
|
89
|
+
processStream(events: AsyncIterable<Record<string, unknown>>, options?: {
|
|
90
|
+
prompt?: string;
|
|
91
|
+
upstreamBody?: ReadableStream<Uint8Array>;
|
|
92
|
+
}): AsyncGenerator<Record<string, unknown>>;
|
|
93
|
+
/**
|
|
94
|
+
* Wraps an inline ad as an AG-UI custom event anchored to `contentOffset`,
|
|
95
|
+
* the number of message characters emitted before the ad arrived. Clients
|
|
96
|
+
* use it to render the ad directly after that content instead of at the
|
|
97
|
+
* end of the message.
|
|
98
|
+
*/
|
|
99
|
+
private makeInlineAdEvent;
|
|
100
|
+
private makePlacementEvent;
|
|
101
|
+
private mapPlacementRecord;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export { type AdzenAsyncConfig, AdzenAsyncMiddleware, type AdzenStreamConfig, AdzenStreamMiddleware, type AdzenStreamMiddlewareConfig };
|