@adzenai/ai 1.1.0 → 1.2.0
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 +51 -3
- package/dist/copilotkit/index.cjs +499 -66
- package/dist/copilotkit/index.cjs.map +1 -1
- package/dist/copilotkit/index.d.cts +56 -8
- package/dist/copilotkit/index.d.ts +56 -8
- package/dist/copilotkit/index.js +498 -65
- package/dist/copilotkit/index.js.map +1 -1
- package/dist/copilotkit/react/index.cjs +222 -42
- package/dist/copilotkit/react/index.cjs.map +1 -1
- package/dist/copilotkit/react/index.d.cts +64 -10
- package/dist/copilotkit/react/index.d.ts +64 -10
- package/dist/copilotkit/react/index.js +218 -42
- 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 +3 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/copilotkit/middleware.ts","../../src/copilotkit/impressionHandler.ts"],"sourcesContent":["import type { AdzenDecision, AdzenPlacement } from \"@adzenai/core\";\n\nexport interface AdzenAsyncConfig {\n endpointUrl?: string;\n apiKey: string;\n timeoutMs?: number;\n adUnitPosition?: string;\n}\n\ninterface MessageBuffer {\n content: string;\n startedAt: number;\n fetched: boolean;\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\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 }\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 \"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 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 },\n body: JSON.stringify({\n content,\n message_id: messageId,\n }),\n signal: controller.signal,\n });\n\n if (!res.ok) return null;\n\n const data = (await res.json()) as AdzenDecision;\n if (data.decision === \"serve\" && data.ad) return data.ad;\n return null;\n } catch {\n return null;\n } finally {\n clearTimeout(timeout);\n }\n }\n\n private makePlacementEvent(\n placement: AdzenPlacement,\n messageId: string,\n ): Record<string, unknown> {\n return {\n type: \"CUSTOM_EVENT\",\n name: \"adzen_placement\",\n messageId,\n value: {\n ...placement,\n message_id: messageId,\n },\n };\n }\n}\n","export interface ImpressionHandlerConfig {\n apiKey: string;\n endpointUrl?: string;\n}\n\ninterface ImpressionRequestBody {\n type: \"render\" | \"view\";\n ad_id: string;\n message_id: string;\n ad_unit_position: string;\n timestamp: string;\n viewability_ms?: number;\n}\n\nconst REQUIRED_FIELDS: (keyof ImpressionRequestBody)[] = [\n \"type\",\n \"ad_id\",\n \"message_id\",\n \"ad_unit_position\",\n \"timestamp\",\n];\n\n/**\n * Creates a web-standard Request -> Response handler that proxies impression\n * beacons to the Adzen API with the publisher's API key. Mount this on your\n * server at any path (default convention: `/api/adzen/impressions`).\n *\n * Works in Next.js App Router, Remix, Hono, Express (via adapter),\n * Cloudflare Workers, and any framework supporting the Fetch API.\n */\nexport function createImpressionHandler(config: ImpressionHandlerConfig) {\n const endpointUrl = config.endpointUrl ?? \"https://api.adzen.ai/v1/ai\";\n\n return async (request: Request): Promise<Response> => {\n if (request.method !== \"POST\") {\n return new Response(JSON.stringify({ error: \"Method not allowed\" }), {\n status: 405,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n let body: ImpressionRequestBody;\n try {\n body = (await request.json()) as ImpressionRequestBody;\n } catch {\n return new Response(JSON.stringify({ error: \"Invalid JSON\" }), {\n status: 400,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n for (const field of REQUIRED_FIELDS) {\n if (!body[field]) {\n return new Response(\n JSON.stringify({ error: `Missing required field: ${field}` }),\n { status: 400, headers: { \"Content-Type\": \"application/json\" } },\n );\n }\n }\n\n if (body.type !== \"render\" && body.type !== \"view\") {\n return new Response(\n JSON.stringify({ error: 'Invalid type: must be \"render\" or \"view\"' }),\n { status: 400, headers: { \"Content-Type\": \"application/json\" } },\n );\n }\n\n const upstreamPath =\n body.type === \"render\" ? \"/impressions/render\" : \"/impressions/view\";\n\n const { type: _type, ...forwardBody } = body;\n\n try {\n const upstream = await fetch(`${endpointUrl}${upstreamPath}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": config.apiKey,\n },\n body: JSON.stringify(forwardBody),\n });\n\n return new Response(upstream.body, {\n status: upstream.status,\n headers: { \"Content-Type\": \"application/json\" },\n });\n } catch {\n return new Response(\n JSON.stringify({ error: \"Upstream request failed\" }),\n { status: 502, headers: { \"Content-Type\": \"application/json\" } },\n );\n }\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/copilotkit/middleware.ts","../../src/copilotkit/AdzenStreamClient.ts","../../src/copilotkit/parseSSE.ts","../../src/copilotkit/streamMiddleware.ts"],"sourcesContent":["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 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\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.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,\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, 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 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: { \"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":"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","names":["value"]}
|
|
@@ -21,8 +21,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var react_exports = {};
|
|
22
22
|
__export(react_exports, {
|
|
23
23
|
AdzenCard: () => AdzenCard,
|
|
24
|
+
InlineAd: () => InlineAd,
|
|
25
|
+
buildInlineAdSegments: () => buildInlineAdSegments,
|
|
26
|
+
dispatchInlineAdEvent: () => dispatchInlineAdEvent,
|
|
24
27
|
dispatchPlacementEvent: () => dispatchPlacementEvent,
|
|
25
28
|
dispatchPlacementEvents: () => dispatchPlacementEvents,
|
|
29
|
+
useAdzenInlineAds: () => useAdzenInlineAds,
|
|
26
30
|
useAdzenPlacement: () => useAdzenPlacement
|
|
27
31
|
});
|
|
28
32
|
module.exports = __toCommonJS(react_exports);
|
|
@@ -66,19 +70,10 @@ function useAdzenPlacement() {
|
|
|
66
70
|
|
|
67
71
|
// src/copilotkit/react/AdzenCard.tsx
|
|
68
72
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
fetch(url, {
|
|
72
|
-
method: "POST",
|
|
73
|
-
headers: { "Content-Type": "application/json" },
|
|
74
|
-
body
|
|
75
|
-
}).catch(() => {
|
|
73
|
+
function fireBeacon(url) {
|
|
74
|
+
fetch(url, { method: "GET", keepalive: true }).catch(() => {
|
|
76
75
|
setTimeout(() => {
|
|
77
|
-
fetch(url, {
|
|
78
|
-
method: "POST",
|
|
79
|
-
headers: { "Content-Type": "application/json" },
|
|
80
|
-
body
|
|
81
|
-
}).catch(() => {
|
|
76
|
+
fetch(url, { method: "GET", keepalive: true }).catch(() => {
|
|
82
77
|
});
|
|
83
78
|
}, 1e3);
|
|
84
79
|
});
|
|
@@ -87,8 +82,7 @@ function AdzenCard({
|
|
|
87
82
|
messageId,
|
|
88
83
|
adUnitPosition = "chin",
|
|
89
84
|
viewabilityThresholdMs = 1e3,
|
|
90
|
-
className
|
|
91
|
-
impressionProxyPath = DEFAULT_PROXY_PATH
|
|
85
|
+
className
|
|
92
86
|
}) {
|
|
93
87
|
const { getAdForMessage } = useAdzenPlacement();
|
|
94
88
|
const ad = getAdForMessage(messageId);
|
|
@@ -96,40 +90,29 @@ function AdzenCard({
|
|
|
96
90
|
const [renderFired, setRenderFired] = (0, import_react2.useState)(false);
|
|
97
91
|
const [viewed, setViewed] = (0, import_react2.useState)(false);
|
|
98
92
|
(0, import_react2.useEffect)(() => {
|
|
99
|
-
if (!ad || renderFired) return;
|
|
93
|
+
if (!ad || renderFired || !ad.render_impression_url) return;
|
|
100
94
|
setRenderFired(true);
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
message_id: messageId,
|
|
107
|
-
ad_unit_position: adUnitPosition,
|
|
108
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
109
|
-
})
|
|
110
|
-
);
|
|
111
|
-
}, [ad, renderFired, messageId, adUnitPosition, impressionProxyPath]);
|
|
95
|
+
const url = new URL(ad.render_impression_url);
|
|
96
|
+
url.searchParams.set("ad_unit_position", adUnitPosition);
|
|
97
|
+
url.searchParams.set("timestamp", (/* @__PURE__ */ new Date()).toISOString());
|
|
98
|
+
fireBeacon(url.toString());
|
|
99
|
+
}, [ad, renderFired, adUnitPosition]);
|
|
112
100
|
(0, import_react2.useEffect)(() => {
|
|
113
|
-
if (!ad || !cardRef.current || viewed) return;
|
|
101
|
+
if (!ad || !cardRef.current || viewed || !ad.view_impression_url) return;
|
|
114
102
|
return (0, import_core.observeViewability)({
|
|
115
103
|
element: cardRef.current,
|
|
116
104
|
thresholdMs: viewabilityThresholdMs,
|
|
117
105
|
onViewed: () => {
|
|
118
106
|
setViewed(true);
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
ad_unit_position: adUnitPosition,
|
|
126
|
-
viewability_ms: viewabilityThresholdMs,
|
|
127
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
128
|
-
})
|
|
129
|
-
);
|
|
107
|
+
if (!ad.view_impression_url) return;
|
|
108
|
+
const url = new URL(ad.view_impression_url);
|
|
109
|
+
url.searchParams.set("ad_unit_position", adUnitPosition);
|
|
110
|
+
url.searchParams.set("viewability_ms", String(viewabilityThresholdMs));
|
|
111
|
+
url.searchParams.set("timestamp", (/* @__PURE__ */ new Date()).toISOString());
|
|
112
|
+
fireBeacon(url.toString());
|
|
130
113
|
}
|
|
131
114
|
});
|
|
132
|
-
}, [ad, viewed,
|
|
115
|
+
}, [ad, viewed, adUnitPosition, viewabilityThresholdMs]);
|
|
133
116
|
if (!ad) return null;
|
|
134
117
|
const initial = ad.advertiser_name?.charAt(0).toUpperCase() ?? "?";
|
|
135
118
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
@@ -241,13 +224,194 @@ var cardStyles = {
|
|
|
241
224
|
}
|
|
242
225
|
};
|
|
243
226
|
|
|
227
|
+
// src/copilotkit/react/InlineAd.tsx
|
|
228
|
+
var import_react3 = require("react");
|
|
229
|
+
var import_core2 = require("@adzenai/core");
|
|
230
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
231
|
+
function fireBeacon2(url) {
|
|
232
|
+
fetch(url, { method: "GET", keepalive: true }).catch(() => {
|
|
233
|
+
setTimeout(() => {
|
|
234
|
+
fetch(url, { method: "GET", keepalive: true }).catch(() => {
|
|
235
|
+
});
|
|
236
|
+
}, 1e3);
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
function InlineAd({
|
|
240
|
+
ad,
|
|
241
|
+
viewabilityThresholdMs = 1e3,
|
|
242
|
+
className
|
|
243
|
+
}) {
|
|
244
|
+
const ref = (0, import_react3.useRef)(null);
|
|
245
|
+
const [renderFired, setRenderFired] = (0, import_react3.useState)(false);
|
|
246
|
+
const [viewed, setViewed] = (0, import_react3.useState)(false);
|
|
247
|
+
(0, import_react3.useEffect)(() => {
|
|
248
|
+
if (renderFired || !ad.tracking.impression_url) return;
|
|
249
|
+
setRenderFired(true);
|
|
250
|
+
const url = new URL(ad.tracking.impression_url);
|
|
251
|
+
url.searchParams.set("timestamp", (/* @__PURE__ */ new Date()).toISOString());
|
|
252
|
+
fireBeacon2(url.toString());
|
|
253
|
+
}, [ad, renderFired]);
|
|
254
|
+
(0, import_react3.useEffect)(() => {
|
|
255
|
+
if (!ref.current || viewed || !ad.tracking.impression_url) return;
|
|
256
|
+
return (0, import_core2.observeViewability)({
|
|
257
|
+
element: ref.current,
|
|
258
|
+
thresholdMs: viewabilityThresholdMs,
|
|
259
|
+
onViewed: () => {
|
|
260
|
+
setViewed(true);
|
|
261
|
+
if (!ad.tracking.impression_url) return;
|
|
262
|
+
const url = new URL(ad.tracking.impression_url);
|
|
263
|
+
url.searchParams.set("type", "view");
|
|
264
|
+
url.searchParams.set("viewability_ms", String(viewabilityThresholdMs));
|
|
265
|
+
url.searchParams.set("timestamp", (/* @__PURE__ */ new Date()).toISOString());
|
|
266
|
+
fireBeacon2(url.toString());
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
}, [ad, viewed, viewabilityThresholdMs]);
|
|
270
|
+
const advertiser = ad.creative.advertiser_name ?? ad.creative.headline;
|
|
271
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { ref, className, style: inlineStyles.wrapper, children: [
|
|
272
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: inlineStyles.badge, "aria-label": "Advertisement", children: "Ad" }),
|
|
273
|
+
advertiser ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: inlineStyles.advertiser, children: [
|
|
274
|
+
advertiser,
|
|
275
|
+
" "
|
|
276
|
+
] }) : null,
|
|
277
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
278
|
+
"a",
|
|
279
|
+
{
|
|
280
|
+
href: ad.creative.destination_url,
|
|
281
|
+
target: "_blank",
|
|
282
|
+
rel: "noopener sponsored",
|
|
283
|
+
style: inlineStyles.cta,
|
|
284
|
+
children: ad.creative.cta_text
|
|
285
|
+
}
|
|
286
|
+
)
|
|
287
|
+
] });
|
|
288
|
+
}
|
|
289
|
+
var inlineStyles = {
|
|
290
|
+
// Block-level so the snippet starts on its own line below the text it
|
|
291
|
+
// follows, but otherwise plain: no border, background, or padding.
|
|
292
|
+
wrapper: {
|
|
293
|
+
display: "block",
|
|
294
|
+
margin: "0.5rem 0",
|
|
295
|
+
fontSize: "0.9em",
|
|
296
|
+
lineHeight: 1.5
|
|
297
|
+
},
|
|
298
|
+
badge: {
|
|
299
|
+
display: "inline-block",
|
|
300
|
+
marginRight: "0.4em",
|
|
301
|
+
padding: "0.1em 0.4em",
|
|
302
|
+
borderRadius: 4,
|
|
303
|
+
background: "#30363d",
|
|
304
|
+
color: "#8b949e",
|
|
305
|
+
fontSize: "0.75em",
|
|
306
|
+
fontWeight: 700,
|
|
307
|
+
letterSpacing: "0.05em",
|
|
308
|
+
textTransform: "uppercase",
|
|
309
|
+
verticalAlign: "middle"
|
|
310
|
+
},
|
|
311
|
+
advertiser: {
|
|
312
|
+
color: "#8b949e"
|
|
313
|
+
},
|
|
314
|
+
cta: {
|
|
315
|
+
color: "#58a6ff",
|
|
316
|
+
textDecoration: "none",
|
|
317
|
+
fontWeight: 500
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
// src/copilotkit/react/useAdzenInlineAds.ts
|
|
322
|
+
var import_react4 = require("react");
|
|
323
|
+
function readOffset(payload) {
|
|
324
|
+
return typeof payload.content_offset === "number" ? payload.content_offset : Number.MAX_SAFE_INTEGER;
|
|
325
|
+
}
|
|
326
|
+
var PARAGRAPH_BREAK = /\n[ \t]*\n/;
|
|
327
|
+
var ENDS_ON_PARAGRAPH_BREAK = /\n[ \t]*\n$/;
|
|
328
|
+
function snapToParagraphEnd(content, offset) {
|
|
329
|
+
if (offset >= content.length) return content.length;
|
|
330
|
+
if (ENDS_ON_PARAGRAPH_BREAK.test(content.slice(0, offset))) return offset;
|
|
331
|
+
return nextParagraphEnd(content, Math.max(0, offset - 1));
|
|
332
|
+
}
|
|
333
|
+
function nextParagraphEnd(content, from) {
|
|
334
|
+
if (from >= content.length) return content.length;
|
|
335
|
+
const match = PARAGRAPH_BREAK.exec(content.slice(from));
|
|
336
|
+
return match ? from + match.index + match[0].length : content.length;
|
|
337
|
+
}
|
|
338
|
+
function buildInlineAdSegments(content, ads) {
|
|
339
|
+
if (ads.length === 0) {
|
|
340
|
+
return content ? [{ kind: "text", text: content }] : [];
|
|
341
|
+
}
|
|
342
|
+
const segments = [];
|
|
343
|
+
let cursor = 0;
|
|
344
|
+
let lastAnchor = -1;
|
|
345
|
+
for (const ad of ads) {
|
|
346
|
+
let anchor = snapToParagraphEnd(content, Math.max(ad.content_offset, 0));
|
|
347
|
+
if (anchor <= lastAnchor) anchor = nextParagraphEnd(content, lastAnchor);
|
|
348
|
+
if (anchor <= lastAnchor) continue;
|
|
349
|
+
if (anchor > cursor) {
|
|
350
|
+
segments.push({ kind: "text", text: content.slice(cursor, anchor) });
|
|
351
|
+
}
|
|
352
|
+
segments.push({ kind: "ad", ad });
|
|
353
|
+
cursor = anchor;
|
|
354
|
+
lastAnchor = anchor;
|
|
355
|
+
}
|
|
356
|
+
if (cursor < content.length) {
|
|
357
|
+
segments.push({ kind: "text", text: content.slice(cursor) });
|
|
358
|
+
}
|
|
359
|
+
return segments;
|
|
360
|
+
}
|
|
361
|
+
function useAdzenInlineAds() {
|
|
362
|
+
const [adsMap, setAdsMap] = (0, import_react4.useState)(
|
|
363
|
+
() => /* @__PURE__ */ new Map()
|
|
364
|
+
);
|
|
365
|
+
(0, import_react4.useEffect)(() => {
|
|
366
|
+
function handler(e) {
|
|
367
|
+
const detail = e.detail;
|
|
368
|
+
if (!detail || typeof detail !== "object") return;
|
|
369
|
+
const payload = detail;
|
|
370
|
+
const messageId = payload.message_id;
|
|
371
|
+
if (!messageId) return;
|
|
372
|
+
const anchored = {
|
|
373
|
+
...payload,
|
|
374
|
+
message_id: messageId,
|
|
375
|
+
content_offset: readOffset(payload)
|
|
376
|
+
};
|
|
377
|
+
setAdsMap((prev) => {
|
|
378
|
+
const existing = prev.get(messageId) ?? [];
|
|
379
|
+
if (existing.some((a) => a.ad_id === anchored.ad_id)) return prev;
|
|
380
|
+
const next = new Map(prev);
|
|
381
|
+
next.set(
|
|
382
|
+
messageId,
|
|
383
|
+
[...existing, anchored].sort(
|
|
384
|
+
(a, b) => a.content_offset - b.content_offset
|
|
385
|
+
)
|
|
386
|
+
);
|
|
387
|
+
return next;
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
window.addEventListener("adzen_inline_ad", handler);
|
|
391
|
+
return () => window.removeEventListener("adzen_inline_ad", handler);
|
|
392
|
+
}, []);
|
|
393
|
+
const getInlineAdsForMessage = (0, import_react4.useCallback)(
|
|
394
|
+
(messageId) => {
|
|
395
|
+
return adsMap.get(messageId) ?? [];
|
|
396
|
+
},
|
|
397
|
+
[adsMap]
|
|
398
|
+
);
|
|
399
|
+
const getInlineAdSegments = (0, import_react4.useCallback)(
|
|
400
|
+
(messageId, content) => buildInlineAdSegments(content, adsMap.get(messageId) ?? []),
|
|
401
|
+
[adsMap]
|
|
402
|
+
);
|
|
403
|
+
return { getInlineAdsForMessage, getInlineAdSegments };
|
|
404
|
+
}
|
|
405
|
+
|
|
244
406
|
// src/copilotkit/react/bridge.ts
|
|
407
|
+
function isCustomEvent(event) {
|
|
408
|
+
const type = String(event.type ?? "");
|
|
409
|
+
return type === "CUSTOM_EVENT" || type === "CUSTOM" || type === "CustomEvent";
|
|
410
|
+
}
|
|
245
411
|
function dispatchPlacementEvent(event) {
|
|
246
412
|
if (typeof window === "undefined") return false;
|
|
247
413
|
if (event.name !== "adzen_placement") return false;
|
|
248
|
-
|
|
249
|
-
if (type !== "CUSTOM_EVENT" && type !== "CUSTOM" && type !== "CustomEvent")
|
|
250
|
-
return false;
|
|
414
|
+
if (!isCustomEvent(event)) return false;
|
|
251
415
|
const value = event.value;
|
|
252
416
|
if (!value) return false;
|
|
253
417
|
window.dispatchEvent(
|
|
@@ -255,16 +419,32 @@ function dispatchPlacementEvent(event) {
|
|
|
255
419
|
);
|
|
256
420
|
return true;
|
|
257
421
|
}
|
|
422
|
+
function dispatchInlineAdEvent(event) {
|
|
423
|
+
if (typeof window === "undefined") return false;
|
|
424
|
+
if (event.name !== "adzen_inline_ad") return false;
|
|
425
|
+
if (!isCustomEvent(event)) return false;
|
|
426
|
+
const value = event.value;
|
|
427
|
+
if (!value) return false;
|
|
428
|
+
window.dispatchEvent(
|
|
429
|
+
new CustomEvent("adzen_inline_ad", { detail: value })
|
|
430
|
+
);
|
|
431
|
+
return true;
|
|
432
|
+
}
|
|
258
433
|
function dispatchPlacementEvents(events) {
|
|
259
434
|
for (const event of events) {
|
|
260
435
|
dispatchPlacementEvent(event);
|
|
436
|
+
dispatchInlineAdEvent(event);
|
|
261
437
|
}
|
|
262
438
|
}
|
|
263
439
|
// Annotate the CommonJS export names for ESM import in node:
|
|
264
440
|
0 && (module.exports = {
|
|
265
441
|
AdzenCard,
|
|
442
|
+
InlineAd,
|
|
443
|
+
buildInlineAdSegments,
|
|
444
|
+
dispatchInlineAdEvent,
|
|
266
445
|
dispatchPlacementEvent,
|
|
267
446
|
dispatchPlacementEvents,
|
|
447
|
+
useAdzenInlineAds,
|
|
268
448
|
useAdzenPlacement
|
|
269
449
|
});
|
|
270
450
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/copilotkit/react/index.ts","../../../src/copilotkit/react/AdzenCard.tsx","../../../src/copilotkit/react/useAdzenPlacement.ts","../../../src/copilotkit/react/bridge.ts"],"sourcesContent":["export { AdzenCard } from \"./AdzenCard.js\";\nexport type { AdzenCardProps } from \"./AdzenCard.js\";\nexport { useAdzenPlacement } from \"./useAdzenPlacement.js\";\nexport type { UseAdzenPlacementReturn } from \"./useAdzenPlacement.js\";\nexport { dispatchPlacementEvent, dispatchPlacementEvents } from \"./bridge.js\";\n","import { useRef, useEffect, useState } from \"react\";\nimport { observeViewability } from \"@adzenai/core\";\nimport { useAdzenPlacement } from \"./useAdzenPlacement.js\";\n\nexport interface AdzenCardProps {\n messageId: string;\n adUnitPosition?: string;\n viewabilityThresholdMs?: number;\n className?: string;\n /** Relative path on the integrator's server that proxies impression calls. */\n impressionProxyPath?: string;\n}\n\nconst DEFAULT_PROXY_PATH = \"/api/adzen/impressions\";\n\nfunction fireBeacon(url: string, body: string): void {\n fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body,\n }).catch(() => {\n setTimeout(() => {\n fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body,\n }).catch(() => {});\n }, 1000);\n });\n}\n\n/**\n * Renders a sponsored ad card for a given assistant message. Returns `null`\n * (no DOM output) when there is no ad for the message.\n */\nexport function AdzenCard({\n messageId,\n adUnitPosition = \"chin\",\n viewabilityThresholdMs = 1000,\n className,\n impressionProxyPath = DEFAULT_PROXY_PATH,\n}: AdzenCardProps) {\n const { getAdForMessage } = useAdzenPlacement();\n const ad = getAdForMessage(messageId);\n const cardRef = useRef<HTMLDivElement>(null);\n const [renderFired, setRenderFired] = useState(false);\n const [viewed, setViewed] = useState(false);\n\n useEffect(() => {\n if (!ad || renderFired) return;\n setRenderFired(true);\n\n fireBeacon(\n impressionProxyPath,\n JSON.stringify({\n type: \"render\",\n ad_id: ad.ad_id,\n message_id: messageId,\n ad_unit_position: adUnitPosition,\n timestamp: new Date().toISOString(),\n }),\n );\n }, [ad, renderFired, messageId, adUnitPosition, impressionProxyPath]);\n\n useEffect(() => {\n if (!ad || !cardRef.current || viewed) return;\n\n return observeViewability({\n element: cardRef.current,\n thresholdMs: viewabilityThresholdMs,\n onViewed: () => {\n setViewed(true);\n fireBeacon(\n impressionProxyPath,\n JSON.stringify({\n type: \"view\",\n ad_id: ad.ad_id,\n message_id: messageId,\n ad_unit_position: adUnitPosition,\n viewability_ms: viewabilityThresholdMs,\n timestamp: new Date().toISOString(),\n }),\n );\n },\n });\n }, [ad, viewed, messageId, adUnitPosition, viewabilityThresholdMs, impressionProxyPath]);\n\n if (!ad) return null;\n\n const initial = ad.advertiser_name?.charAt(0).toUpperCase() ?? \"?\";\n\n return (\n <div\n ref={cardRef}\n className={className}\n data-adzen-ad-unit-position={adUnitPosition}\n style={cardStyles.wrapper}\n >\n <div style={cardStyles.avatar}>\n {ad.advertiser_image_url ? (\n <img\n src={ad.advertiser_image_url}\n alt={ad.advertiser_name}\n style={cardStyles.avatarImg}\n />\n ) : (\n <span style={cardStyles.avatarLetter}>{initial}</span>\n )}\n </div>\n\n <div style={cardStyles.content}>\n <div style={cardStyles.topRow}>\n <span style={cardStyles.advertiserName}>{ad.advertiser_name}</span>\n <span style={cardStyles.relevantAd}>Relevant Ad</span>\n </div>\n <div style={cardStyles.bottomRow}>\n <span style={cardStyles.headline}>{ad.headline}</span>\n <a\n href={ad.destination_url}\n target=\"_blank\"\n rel=\"noopener sponsored\"\n style={cardStyles.cta}\n >\n {ad.cta_text}\n </a>\n </div>\n </div>\n </div>\n );\n}\n\nconst cardStyles: Record<string, React.CSSProperties> = {\n wrapper: {\n display: \"flex\",\n alignItems: \"center\",\n gap: \"0.625rem\",\n fontSize: \"0.85rem\",\n padding: \"0.625rem 0.75rem\",\n },\n avatar: {\n width: 32,\n height: 32,\n borderRadius: \"50%\",\n background: \"#d1d5db\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n overflow: \"hidden\",\n },\n avatarImg: {\n width: \"100%\",\n height: \"100%\",\n objectFit: \"cover\" as const,\n borderRadius: \"50%\",\n },\n avatarLetter: {\n fontSize: \"0.8rem\",\n fontWeight: 700,\n color: \"#374151\",\n lineHeight: 1,\n },\n content: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"0.125rem\",\n minWidth: 0,\n },\n topRow: {\n display: \"flex\",\n alignItems: \"center\",\n gap: \"0.5rem\",\n },\n advertiserName: {\n fontWeight: 700,\n color: \"inherit\",\n },\n relevantAd: {\n color: \"#8b949e\",\n fontSize: \"0.8rem\",\n },\n bottomRow: {\n display: \"flex\",\n alignItems: \"center\",\n gap: \"0.5rem\",\n whiteSpace: \"nowrap\" as const,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n },\n headline: {\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n },\n cta: {\n color: \"#58a6ff\",\n textDecoration: \"none\",\n fontWeight: 500,\n flexShrink: 0,\n },\n};\n","import { useState, useEffect, useCallback } from \"react\";\nimport type { AdzenPlacement } from \"@adzenai/core\";\n\nexport interface UseAdzenPlacementReturn {\n getAdForMessage(messageId: string): AdzenPlacement | null;\n placements: Map<string, AdzenPlacement>;\n}\n\n/**\n * React hook that subscribes to `adzen_placement` custom events and\n * maintains a map of messageId -> AdzenPlacement.\n *\n * Works anywhere in the React tree below `<CopilotKit>` — no wrapper\n * provider required.\n */\nexport function useAdzenPlacement(): UseAdzenPlacementReturn {\n const [placements, setPlacements] = useState<Map<string, AdzenPlacement>>(\n () => new Map(),\n );\n\n useEffect(() => {\n function handler(e: Event) {\n const detail = (e as CustomEvent).detail;\n if (!detail || typeof detail !== \"object\") return;\n\n const placement = detail as AdzenPlacement & { message_id?: string };\n const messageId = placement.message_id;\n if (!messageId) return;\n\n setPlacements((prev) => {\n const existing = prev.get(messageId);\n if (existing && existing.ad_id === placement.ad_id) return prev;\n const next = new Map(prev);\n next.set(messageId, placement);\n return next;\n });\n }\n\n window.addEventListener(\"adzen_placement\", handler);\n return () => window.removeEventListener(\"adzen_placement\", handler);\n }, []);\n\n const getAdForMessage = useCallback(\n (messageId: string): AdzenPlacement | null => {\n return placements.get(messageId) ?? null;\n },\n [placements],\n );\n\n return { getAdForMessage, placements };\n}\n","import type { AdzenPlacement } from \"@adzenai/core\";\n\n/**\n * Checks whether an AG-UI event is an `adzen_placement` custom event\n * and, if so, dispatches it as a browser `CustomEvent` on `window`\n * so that `useAdzenPlacement` can pick it up.\n *\n * Call this for every event returned by `AdzenAsyncMiddleware.processEvent()`.\n * Non-placement events are silently ignored.\n */\nexport function dispatchPlacementEvent(\n event: Record<string, unknown>,\n): boolean {\n if (typeof window === \"undefined\") return false;\n if (event.name !== \"adzen_placement\") return false;\n\n const type = String(event.type ?? \"\");\n if (type !== \"CUSTOM_EVENT\" && type !== \"CUSTOM\" && type !== \"CustomEvent\")\n return false;\n\n const value = event.value as (AdzenPlacement & { message_id?: string }) | undefined;\n if (!value) return false;\n\n window.dispatchEvent(\n new CustomEvent(\"adzen_placement\", { detail: value }),\n );\n return true;\n}\n\n/**\n * Convenience wrapper: iterates an array of AG-UI events (as returned by\n * `AdzenAsyncMiddleware.processEvent()`) and dispatches any placement\n * events to the browser.\n */\nexport function dispatchPlacementEvents(\n events: Record<string, unknown>[],\n): void {\n for (const event of events) {\n dispatchPlacementEvent(event);\n }\n}\n"],"mappings":"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","names":["import_react"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/copilotkit/react/index.ts","../../../src/copilotkit/react/AdzenCard.tsx","../../../src/copilotkit/react/useAdzenPlacement.ts","../../../src/copilotkit/react/InlineAd.tsx","../../../src/copilotkit/react/useAdzenInlineAds.ts","../../../src/copilotkit/react/bridge.ts"],"sourcesContent":["export { AdzenCard } from \"./AdzenCard.js\";\nexport type { AdzenCardProps } from \"./AdzenCard.js\";\nexport { InlineAd } from \"./InlineAd.js\";\nexport type { InlineAdProps } from \"./InlineAd.js\";\nexport { useAdzenPlacement } from \"./useAdzenPlacement.js\";\nexport type { UseAdzenPlacementReturn } from \"./useAdzenPlacement.js\";\nexport {\n useAdzenInlineAds,\n buildInlineAdSegments,\n} from \"./useAdzenInlineAds.js\";\nexport type {\n UseAdzenInlineAdsReturn,\n InlineAdSegment,\n} from \"./useAdzenInlineAds.js\";\nexport {\n dispatchPlacementEvent,\n dispatchInlineAdEvent,\n dispatchPlacementEvents,\n} from \"./bridge.js\";\n","import { useRef, useEffect, useState } from \"react\";\nimport { observeViewability } from \"@adzenai/core\";\nimport { useAdzenPlacement } from \"./useAdzenPlacement.js\";\n\nexport interface AdzenCardProps {\n messageId: string;\n adUnitPosition?: string;\n viewabilityThresholdMs?: number;\n className?: string;\n}\n\nfunction fireBeacon(url: string): void {\n fetch(url, { method: \"GET\", keepalive: true }).catch(() => {\n setTimeout(() => {\n fetch(url, { method: \"GET\", keepalive: true }).catch(() => {});\n }, 1000);\n });\n}\n\n/**\n * Renders a sponsored ad card for a given assistant message. Returns `null`\n * (no DOM output) when there is no ad for the message.\n */\nexport function AdzenCard({\n messageId,\n adUnitPosition = \"chin\",\n viewabilityThresholdMs = 1000,\n className,\n}: AdzenCardProps) {\n const { getAdForMessage } = useAdzenPlacement();\n const ad = getAdForMessage(messageId);\n const cardRef = useRef<HTMLDivElement>(null);\n const [renderFired, setRenderFired] = useState(false);\n const [viewed, setViewed] = useState(false);\n\n useEffect(() => {\n if (!ad || renderFired || !ad.render_impression_url) return;\n setRenderFired(true);\n\n const url = new URL(ad.render_impression_url);\n url.searchParams.set(\"ad_unit_position\", adUnitPosition);\n url.searchParams.set(\"timestamp\", new Date().toISOString());\n fireBeacon(url.toString());\n }, [ad, renderFired, adUnitPosition]);\n\n useEffect(() => {\n if (!ad || !cardRef.current || viewed || !ad.view_impression_url) return;\n\n return observeViewability({\n element: cardRef.current,\n thresholdMs: viewabilityThresholdMs,\n onViewed: () => {\n setViewed(true);\n if (!ad.view_impression_url) return;\n const url = new URL(ad.view_impression_url);\n url.searchParams.set(\"ad_unit_position\", adUnitPosition);\n url.searchParams.set(\"viewability_ms\", String(viewabilityThresholdMs));\n url.searchParams.set(\"timestamp\", new Date().toISOString());\n fireBeacon(url.toString());\n },\n });\n }, [ad, viewed, adUnitPosition, viewabilityThresholdMs]);\n\n if (!ad) return null;\n\n const initial = ad.advertiser_name?.charAt(0).toUpperCase() ?? \"?\";\n\n return (\n <div\n ref={cardRef}\n className={className}\n data-adzen-ad-unit-position={adUnitPosition}\n style={cardStyles.wrapper}\n >\n <div style={cardStyles.avatar}>\n {ad.advertiser_image_url ? (\n <img\n src={ad.advertiser_image_url}\n alt={ad.advertiser_name}\n style={cardStyles.avatarImg}\n />\n ) : (\n <span style={cardStyles.avatarLetter}>{initial}</span>\n )}\n </div>\n\n <div style={cardStyles.content}>\n <div style={cardStyles.topRow}>\n <span style={cardStyles.advertiserName}>{ad.advertiser_name}</span>\n <span style={cardStyles.relevantAd}>Relevant Ad</span>\n </div>\n <div style={cardStyles.bottomRow}>\n <span style={cardStyles.headline}>{ad.headline}</span>\n <a\n href={ad.destination_url}\n target=\"_blank\"\n rel=\"noopener sponsored\"\n style={cardStyles.cta}\n >\n {ad.cta_text}\n </a>\n </div>\n </div>\n </div>\n );\n}\n\nconst cardStyles: Record<string, React.CSSProperties> = {\n wrapper: {\n display: \"flex\",\n alignItems: \"center\",\n gap: \"0.625rem\",\n fontSize: \"0.85rem\",\n padding: \"0.625rem 0.75rem\",\n },\n avatar: {\n width: 32,\n height: 32,\n borderRadius: \"50%\",\n background: \"#d1d5db\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n overflow: \"hidden\",\n },\n avatarImg: {\n width: \"100%\",\n height: \"100%\",\n objectFit: \"cover\" as const,\n borderRadius: \"50%\",\n },\n avatarLetter: {\n fontSize: \"0.8rem\",\n fontWeight: 700,\n color: \"#374151\",\n lineHeight: 1,\n },\n content: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"0.125rem\",\n minWidth: 0,\n },\n topRow: {\n display: \"flex\",\n alignItems: \"center\",\n gap: \"0.5rem\",\n },\n advertiserName: {\n fontWeight: 700,\n color: \"inherit\",\n },\n relevantAd: {\n color: \"#8b949e\",\n fontSize: \"0.8rem\",\n },\n bottomRow: {\n display: \"flex\",\n alignItems: \"center\",\n gap: \"0.5rem\",\n whiteSpace: \"nowrap\" as const,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n },\n headline: {\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n },\n cta: {\n color: \"#58a6ff\",\n textDecoration: \"none\",\n fontWeight: 500,\n flexShrink: 0,\n },\n};\n","import { useState, useEffect, useCallback } from \"react\";\nimport type { AdzenPlacement } from \"@adzenai/core\";\n\nexport interface UseAdzenPlacementReturn {\n getAdForMessage(messageId: string): AdzenPlacement | null;\n placements: Map<string, AdzenPlacement>;\n}\n\n/**\n * React hook that subscribes to `adzen_placement` custom events and\n * maintains a map of messageId -> AdzenPlacement.\n *\n * Works anywhere in the React tree below `<CopilotKit>` — no wrapper\n * provider required.\n */\nexport function useAdzenPlacement(): UseAdzenPlacementReturn {\n const [placements, setPlacements] = useState<Map<string, AdzenPlacement>>(\n () => new Map(),\n );\n\n useEffect(() => {\n function handler(e: Event) {\n const detail = (e as CustomEvent).detail;\n if (!detail || typeof detail !== \"object\") return;\n\n const placement = detail as AdzenPlacement & { message_id?: string };\n const messageId = placement.message_id;\n if (!messageId) return;\n\n setPlacements((prev) => {\n const existing = prev.get(messageId);\n if (existing && existing.ad_id === placement.ad_id) return prev;\n const next = new Map(prev);\n next.set(messageId, placement);\n return next;\n });\n }\n\n window.addEventListener(\"adzen_placement\", handler);\n return () => window.removeEventListener(\"adzen_placement\", handler);\n }, []);\n\n const getAdForMessage = useCallback(\n (messageId: string): AdzenPlacement | null => {\n return placements.get(messageId) ?? null;\n },\n [placements],\n );\n\n return { getAdForMessage, placements };\n}\n","import { useRef, useEffect, useState } from \"react\";\nimport { observeViewability } from \"@adzenai/core\";\nimport type { InlineAdEvent } from \"@adzenai/core\";\n\nexport interface InlineAdProps {\n ad: InlineAdEvent;\n viewabilityThresholdMs?: number;\n className?: string;\n}\n\nfunction fireBeacon(url: string): void {\n fetch(url, { method: \"GET\", keepalive: true }).catch(() => {\n setTimeout(() => {\n fetch(url, { method: \"GET\", keepalive: true }).catch(() => {});\n }, 1000);\n });\n}\n\n/**\n * Renders an inline ad as a single line of text — an \"Ad\" pill, the advertiser\n * name, and the CTA as the only link — rather than a card, so it sits in the\n * message body without competing with the assistant's own content.\n *\n * Tracks render/view impressions via the same beacon pattern as AdzenCard.\n */\nexport function InlineAd({\n ad,\n viewabilityThresholdMs = 1000,\n className,\n}: InlineAdProps) {\n const ref = useRef<HTMLDivElement>(null);\n const [renderFired, setRenderFired] = useState(false);\n const [viewed, setViewed] = useState(false);\n\n useEffect(() => {\n if (renderFired || !ad.tracking.impression_url) return;\n setRenderFired(true);\n\n const url = new URL(ad.tracking.impression_url);\n url.searchParams.set(\"timestamp\", new Date().toISOString());\n fireBeacon(url.toString());\n }, [ad, renderFired]);\n\n useEffect(() => {\n if (!ref.current || viewed || !ad.tracking.impression_url) return;\n\n return observeViewability({\n element: ref.current,\n thresholdMs: viewabilityThresholdMs,\n onViewed: () => {\n setViewed(true);\n if (!ad.tracking.impression_url) return;\n const url = new URL(ad.tracking.impression_url);\n url.searchParams.set(\"type\", \"view\");\n url.searchParams.set(\"viewability_ms\", String(viewabilityThresholdMs));\n url.searchParams.set(\"timestamp\", new Date().toISOString());\n fireBeacon(url.toString());\n },\n });\n }, [ad, viewed, viewabilityThresholdMs]);\n\n const advertiser = ad.creative.advertiser_name ?? ad.creative.headline;\n\n return (\n <div ref={ref} className={className} style={inlineStyles.wrapper}>\n <span style={inlineStyles.badge} aria-label=\"Advertisement\">\n Ad\n </span>\n {advertiser ? (\n <span style={inlineStyles.advertiser}>{advertiser} </span>\n ) : null}\n <a\n href={ad.creative.destination_url}\n target=\"_blank\"\n rel=\"noopener sponsored\"\n style={inlineStyles.cta}\n >\n {ad.creative.cta_text}\n </a>\n </div>\n );\n}\n\nconst inlineStyles: Record<string, React.CSSProperties> = {\n // Block-level so the snippet starts on its own line below the text it\n // follows, but otherwise plain: no border, background, or padding.\n wrapper: {\n display: \"block\",\n margin: \"0.5rem 0\",\n fontSize: \"0.9em\",\n lineHeight: 1.5,\n },\n badge: {\n display: \"inline-block\",\n marginRight: \"0.4em\",\n padding: \"0.1em 0.4em\",\n borderRadius: 4,\n background: \"#30363d\",\n color: \"#8b949e\",\n fontSize: \"0.75em\",\n fontWeight: 700,\n letterSpacing: \"0.05em\",\n textTransform: \"uppercase\" as const,\n verticalAlign: \"middle\",\n },\n advertiser: {\n color: \"#8b949e\",\n },\n cta: {\n color: \"#58a6ff\",\n textDecoration: \"none\",\n fontWeight: 500,\n },\n};\n","import { useState, useEffect, useCallback } from \"react\";\nimport type { InlineAdEvent, InlineAdEventPayload } from \"@adzenai/core\";\n\n/** A run of message text, or an ad anchored to the end of the run before it. */\nexport type InlineAdSegment =\n | { kind: \"text\"; text: string }\n | { kind: \"ad\"; ad: InlineAdEventPayload };\n\nexport interface UseAdzenInlineAdsReturn {\n getInlineAdsForMessage(messageId: string): InlineAdEventPayload[];\n getInlineAdSegments(messageId: string, content: string): InlineAdSegment[];\n}\n\n/**\n * Ads without an anchor sort last so they render at the end of the message,\n * which is the best guess for a payload that predates `content_offset`.\n */\nfunction readOffset(payload: InlineAdEvent & { content_offset?: unknown }): number {\n return typeof payload.content_offset === \"number\"\n ? payload.content_offset\n : Number.MAX_SAFE_INTEGER;\n}\n\n/** A blank line, which ends a paragraph in both plain text and Markdown. */\nconst PARAGRAPH_BREAK = /\\n[ \\t]*\\n/;\nconst ENDS_ON_PARAGRAPH_BREAK = /\\n[ \\t]*\\n$/;\n\n/**\n * Moves an anchor forward to the end of the paragraph it falls in.\n *\n * Deltas are token-sized, so a raw offset routinely lands mid-word or inside\n * a Markdown construct (`**bold te|xt**`). Splitting there would break both\n * the sentence and the Markdown, so the ad is deferred to the next paragraph\n * break — the `paragraph_break` position the API asks for. While the paragraph\n * is still streaming there is no break yet, so the ad sits at the end of the\n * content and settles into place once the paragraph closes.\n */\nfunction snapToParagraphEnd(content: string, offset: number): number {\n if (offset >= content.length) return content.length;\n\n // The preceding frame already ended on a blank line, so this is the start of\n // a fresh paragraph and the ad belongs here.\n if (ENDS_ON_PARAGRAPH_BREAK.test(content.slice(0, offset))) return offset;\n\n // Search from one character back so an offset landing inside the blank line\n // itself still resolves to that break rather than skipping to the next one.\n return nextParagraphEnd(content, Math.max(0, offset - 1));\n}\n\n/**\n * Position just past the first paragraph break at or after `from`, or the end\n * of the content when no break follows.\n */\nfunction nextParagraphEnd(content: string, from: number): number {\n if (from >= content.length) return content.length;\n const match = PARAGRAPH_BREAK.exec(content.slice(from));\n return match ? from + match.index + match[0].length : content.length;\n}\n\n/**\n * Splits `content` into text and ad segments, placing each ad after the text\n * that had streamed when it arrived.\n *\n * At most one ad is placed per paragraph break. Several ads routinely resolve\n * to the same break — the API can emit a burst of them, and every ad anchored\n * inside one paragraph snaps to that paragraph's end — so each ad after the\n * first is moved to the next free break, with the end of the content usable as\n * a final slot. An ad with no free slot is left out and appears once the\n * message has grown enough to hold it, which keeps ads from piling up in one\n * spot while a paragraph is still streaming.\n *\n * @param ads Must be sorted by `content_offset` ascending.\n */\nexport function buildInlineAdSegments(\n content: string,\n ads: InlineAdEventPayload[],\n): InlineAdSegment[] {\n if (ads.length === 0) {\n return content ? [{ kind: \"text\", text: content }] : [];\n }\n\n const segments: InlineAdSegment[] = [];\n let cursor = 0;\n let lastAnchor = -1;\n\n for (const ad of ads) {\n let anchor = snapToParagraphEnd(content, Math.max(ad.content_offset, 0));\n if (anchor <= lastAnchor) anchor = nextParagraphEnd(content, lastAnchor);\n if (anchor <= lastAnchor) continue;\n\n if (anchor > cursor) {\n segments.push({ kind: \"text\", text: content.slice(cursor, anchor) });\n }\n segments.push({ kind: \"ad\", ad });\n cursor = anchor;\n lastAnchor = anchor;\n }\n\n if (cursor < content.length) {\n segments.push({ kind: \"text\", text: content.slice(cursor) });\n }\n\n return segments;\n}\n\n/**\n * React hook that subscribes to `adzen_inline_ad` custom events on\n * `window` and maintains a map of messageId -> InlineAdEventPayload[].\n *\n * Supports multiple inline ads per message per the cardinality requirements.\n * Ads are kept sorted by `content_offset` so they can be interleaved with the\n * message text at the point in the stream where they arrived.\n */\nexport function useAdzenInlineAds(): UseAdzenInlineAdsReturn {\n const [adsMap, setAdsMap] = useState<Map<string, InlineAdEventPayload[]>>(\n () => new Map(),\n );\n\n useEffect(() => {\n function handler(e: Event) {\n const detail = (e as CustomEvent).detail;\n if (!detail || typeof detail !== \"object\") return;\n\n const payload = detail as InlineAdEvent & { message_id?: string };\n const messageId = payload.message_id;\n if (!messageId) return;\n\n const anchored: InlineAdEventPayload = {\n ...payload,\n message_id: messageId,\n content_offset: readOffset(payload),\n };\n\n setAdsMap((prev) => {\n const existing = prev.get(messageId) ?? [];\n if (existing.some((a) => a.ad_id === anchored.ad_id)) return prev;\n const next = new Map(prev);\n next.set(\n messageId,\n [...existing, anchored].sort(\n (a, b) => a.content_offset - b.content_offset,\n ),\n );\n return next;\n });\n }\n\n window.addEventListener(\"adzen_inline_ad\", handler);\n return () => window.removeEventListener(\"adzen_inline_ad\", handler);\n }, []);\n\n const getInlineAdsForMessage = useCallback(\n (messageId: string): InlineAdEventPayload[] => {\n return adsMap.get(messageId) ?? [];\n },\n [adsMap],\n );\n\n const getInlineAdSegments = useCallback(\n (messageId: string, content: string): InlineAdSegment[] =>\n buildInlineAdSegments(content, adsMap.get(messageId) ?? []),\n [adsMap],\n );\n\n return { getInlineAdsForMessage, getInlineAdSegments };\n}\n","import type { AdzenPlacement, InlineAdEventPayload } from \"@adzenai/core\";\n\nfunction isCustomEvent(event: Record<string, unknown>): boolean {\n const type = String(event.type ?? \"\");\n return type === \"CUSTOM_EVENT\" || type === \"CUSTOM\" || type === \"CustomEvent\";\n}\n\n/**\n * Checks whether an AG-UI event is an `adzen_placement` custom event\n * and, if so, dispatches it as a browser `CustomEvent` on `window`\n * so that `useAdzenPlacement` can pick it up.\n *\n * Call this for every event returned by middleware `processEvent()` or\n * `processStream()`. Non-placement events are silently ignored.\n */\nexport function dispatchPlacementEvent(\n event: Record<string, unknown>,\n): boolean {\n if (typeof window === \"undefined\") return false;\n if (event.name !== \"adzen_placement\") return false;\n if (!isCustomEvent(event)) return false;\n\n const value = event.value as (AdzenPlacement & { message_id?: string }) | undefined;\n if (!value) return false;\n\n window.dispatchEvent(\n new CustomEvent(\"adzen_placement\", { detail: value }),\n );\n return true;\n}\n\n/**\n * Checks whether an AG-UI event is an `adzen_inline_ad` custom event\n * and, if so, dispatches it as a browser `CustomEvent` on `window`\n * so that `useAdzenInlineAds` can pick it up.\n */\nexport function dispatchInlineAdEvent(\n event: Record<string, unknown>,\n): boolean {\n if (typeof window === \"undefined\") return false;\n if (event.name !== \"adzen_inline_ad\") return false;\n if (!isCustomEvent(event)) return false;\n\n const value = event.value as Partial<InlineAdEventPayload> | undefined;\n if (!value) return false;\n\n window.dispatchEvent(\n new CustomEvent(\"adzen_inline_ad\", { detail: value }),\n );\n return true;\n}\n\n/**\n * Convenience wrapper: iterates an array of AG-UI events and dispatches\n * any placement or inline ad events to the browser.\n */\nexport function dispatchPlacementEvents(\n events: Record<string, unknown>[],\n): void {\n for (const event of events) {\n dispatchPlacementEvent(event);\n dispatchInlineAdEvent(event);\n }\n}\n"],"mappings":"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","names":["import_react","import_react","import_core","import_jsx_runtime","fireBeacon","import_react"]}
|