@mgamadeus/ddd-agents 0.1.0-alpha.24 → 0.1.0-alpha.26

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.
Files changed (23) hide show
  1. package/dist/chat.js +6 -6
  2. package/dist/chunks/{ConversationMessageInputComposerWidgets-BxyaFBA6.js → ConversationMessageInputComposerWidgets-CzQnpW0h.js} +4 -4
  3. package/dist/chunks/{ConversationMessageInputComposerWidgets-BxyaFBA6.js.map → ConversationMessageInputComposerWidgets-CzQnpW0h.js.map} +1 -1
  4. package/dist/chunks/{WebSearchResultsConversationWidget-as3p5bHw.js → WebSearchResultsConversationWidget-tDhawe9f.js} +55 -50
  5. package/dist/chunks/{WebSearchResultsConversationWidget-as3p5bHw.js.map → WebSearchResultsConversationWidget-tDhawe9f.js.map} +1 -1
  6. package/dist/chunks/{canvas-reducers-Bfp_i7lc.js → canvas-reducers-BdIPZW_6.js} +2 -2
  7. package/dist/chunks/{canvas-reducers-Bfp_i7lc.js.map → canvas-reducers-BdIPZW_6.js.map} +1 -1
  8. package/dist/chunks/{canvasBodies-Cvu3l38p.js → canvasBodies-BiUt8MUG.js} +3 -3
  9. package/dist/chunks/{canvasBodies-Cvu3l38p.js.map → canvasBodies-BiUt8MUG.js.map} +1 -1
  10. package/dist/chunks/{widget-click-signal-sources-DulRkNvZ.js → widget-click-signal-sources-BR82QygL.js} +3 -3
  11. package/dist/chunks/{widget-click-signal-sources-DulRkNvZ.js.map → widget-click-signal-sources-BR82QygL.js.map} +1 -1
  12. package/dist/chunks/{widget-name-resolver-BGN3HpoG.js → widget-name-resolver-BaxKaRa3.js} +2 -2
  13. package/dist/chunks/{widget-name-resolver-BGN3HpoG.js.map → widget-name-resolver-BaxKaRa3.js.map} +1 -1
  14. package/dist/client-testing.js +3 -3
  15. package/dist/image-render.js +4 -4
  16. package/dist/index.js +3 -3
  17. package/dist/kit.js +2 -2
  18. package/dist/preview.js +5 -5
  19. package/dist/renderer.js +7 -7
  20. package/dist/types/entries/widgets.d.ts +1 -0
  21. package/dist/widgets.js +34 -32
  22. package/package.json +1 -1
  23. package/public-api.json +2 -0
package/dist/chat.js CHANGED
@@ -5,14 +5,14 @@ import { u as useAgentsConversationClient, a as useOptionalAgentsConversationCli
5
5
  import { w as withPollingChangeSubscription } from "./chunks/withPollingChangeSubscription-B16htQGd.js";
6
6
  import { q as Text, I as Icon, $ as translateText, G as GlowFrame, t as Tooltip, B as Button, z as classNames, l as Skeleton, a3 as useAgentsEnvironment, h as Markdown, F as getAgentDisplayName, a1 as useAgentsBudgetLimit, f as InteractiveSurface, L as LoadingSpinner, n as SplitView, Y as reportRunningTurn, a0 as useAgentsActiveAgentSpaceKey, P as ProgressBar } from "./chunks/index-7Qc_3GbG.js";
7
7
  import { i as isAgentsClientError, A as AgentsClientError } from "./chunks/conversation-BEF0aesf.js";
8
- import { W as WIDGET_FENCE_LANG, G as resolveWidgetName, j as conversationWidgetRegistry, n as findWidgetFencesInMarkdown, o as ConversationWidgetErrorBoundary, p as ConversationWidgetFeatureGate, T as parseWidgetJsonObject, F as resolveCanonicalWidgetName, y as getConversationWidgetRegistryRevision, U as BARE_WIDGET_LINE_GLOBAL, t as closestWidgetNames } from "./chunks/widget-name-resolver-BGN3HpoG.js";
9
- import { E as useConversationWidgetContext, p as payloadHashOfInstanceId, j as buildWidgetAgentSpaceKeyProps, ap as useCanvasViable } from "./chunks/WebSearchResultsConversationWidget-as3p5bHw.js";
8
+ import { W as WIDGET_FENCE_LANG, G as resolveWidgetName, j as conversationWidgetRegistry, n as findWidgetFencesInMarkdown, o as ConversationWidgetErrorBoundary, p as ConversationWidgetFeatureGate, T as parseWidgetJsonObject, F as resolveCanonicalWidgetName, y as getConversationWidgetRegistryRevision, U as BARE_WIDGET_LINE_GLOBAL, t as closestWidgetNames } from "./chunks/widget-name-resolver-BaxKaRa3.js";
9
+ import { E as useConversationWidgetContext, p as payloadHashOfInstanceId, j as buildWidgetAgentSpaceKeyProps, ar as useCanvasViable } from "./chunks/WebSearchResultsConversationWidget-tDhawe9f.js";
10
10
  import { c as canvasBehaviourOf, d as CHAT_COLUMN_MIN_WIDTH_PX, b as CANVAS_MIN_WIDTH_PX, D as DEFAULT_CANVAS_WIDTH_PERCENT, e as canvasWidthPercentOf, C as CANVAS_BOXED_INSET_PX } from "./chunks/canvas-behaviours-AvzKSYyv.js";
11
11
  import { r as readStoredCanvas, c as clearStoredCanvas } from "./chunks/canvasStorage-EvQsGdto.js";
12
- import { r as resolveDeepLinkableWidget, c as WidgetWindowRootContext, C as ConversationMarkdown, i as isWidgetClickSignalSource, b as buildWidgetRenderReportSignal, W as WIDGET_RENDER_REPORT_SIGNAL_SOURCE, e as createWidgetRenderReportCollector, f as WidgetRenderReportCollectorContext } from "./chunks/widget-click-signal-sources-DulRkNvZ.js";
13
- import { b as ConversationErrorType, a as ConversationMessageInputComposerWidgets, u as useAgentsChatSelector, C as ConversationWidgetProvider, c as createAgentsChatStore } from "./chunks/ConversationMessageInputComposerWidgets-BxyaFBA6.js";
14
- import { A, d, E, I, r, e, f, g, h } from "./chunks/ConversationMessageInputComposerWidgets-BxyaFBA6.js";
15
- import { c as canvasBodies } from "./chunks/canvasBodies-Cvu3l38p.js";
12
+ import { r as resolveDeepLinkableWidget, c as WidgetWindowRootContext, C as ConversationMarkdown, i as isWidgetClickSignalSource, b as buildWidgetRenderReportSignal, W as WIDGET_RENDER_REPORT_SIGNAL_SOURCE, e as createWidgetRenderReportCollector, f as WidgetRenderReportCollectorContext } from "./chunks/widget-click-signal-sources-BR82QygL.js";
13
+ import { b as ConversationErrorType, a as ConversationMessageInputComposerWidgets, u as useAgentsChatSelector, C as ConversationWidgetProvider, c as createAgentsChatStore } from "./chunks/ConversationMessageInputComposerWidgets-CzQnpW0h.js";
14
+ import { A, d, E, I, r, e, f, g, h } from "./chunks/ConversationMessageInputComposerWidgets-CzQnpW0h.js";
15
+ import { c as canvasBodies } from "./chunks/canvasBodies-BiUt8MUG.js";
16
16
  import { c as canvasFeatureFlagOf } from "./chunks/canvas-feature-flags-BmmxC3bz.js";
17
17
  import { flushSync } from "react-dom";
18
18
  import { b as buildChangedMessagesRequest, d as deriveAgentActivity } from "./chunks/contract-BxmMxYPF.js";
@@ -2,10 +2,10 @@
2
2
  import { jsx } from "react/jsx-runtime";
3
3
  import { useCallback, useSyncExternalStore, useContext, createContext, useMemo, useState, useRef, useEffect } from "react";
4
4
  import { a3 as useAgentsEnvironment, a6 as useAgentsStateDispatch, a7 as useAgentsStateSelector, z as classNames } from "./index-7Qc_3GbG.js";
5
- import { e as applySetCanvasCreatedEntityId, a as applyClearCanvas, d as applyResetCanvasForNewTurn, b as applyCloseCanvas, c as applyOpenCanvas } from "./canvas-reducers-Bfp_i7lc.js";
6
- import { T as CANVAS_VIABLE_MIN_WIDTH, h as ConversationWidgetContext, E as useConversationWidgetContext } from "./WebSearchResultsConversationWidget-as3p5bHw.js";
5
+ import { e as applySetCanvasCreatedEntityId, a as applyClearCanvas, d as applyResetCanvasForNewTurn, b as applyCloseCanvas, c as applyOpenCanvas } from "./canvas-reducers-BdIPZW_6.js";
6
+ import { T as CANVAS_VIABLE_MIN_WIDTH, h as ConversationWidgetContext, E as useConversationWidgetContext } from "./WebSearchResultsConversationWidget-tDhawe9f.js";
7
7
  import { s as storeOpenCanvas, c as clearStoredCanvas } from "./canvasStorage-EvQsGdto.js";
8
- import { j as conversationWidgetRegistry } from "./widget-name-resolver-BGN3HpoG.js";
8
+ import { j as conversationWidgetRegistry } from "./widget-name-resolver-BaxKaRa3.js";
9
9
  const EMPTY_AGENTS_CHAT_OPENING_REQUEST = {
10
10
  userMessage: null,
11
11
  startSignalText: null,
@@ -628,4 +628,4 @@ export {
628
628
  readConversationErrorTypeOfRefusedSend as r,
629
629
  useAgentsChatSelector as u
630
630
  };
631
- //# sourceMappingURL=ConversationMessageInputComposerWidgets-BxyaFBA6.js.map
631
+ //# sourceMappingURL=ConversationMessageInputComposerWidgets-CzQnpW0h.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ConversationMessageInputComposerWidgets-BxyaFBA6.js","sources":["../../src/chat/store/agents-chat-state.ts","../../src/chat/store/conversation-error-type.ts","../../src/chat/store/merge-chat-messages.ts","../../src/chat/store/reduce-agents-chat-state.ts","../../src/chat/store/create-agents-chat-store.ts","../../src/chat/store/use-agents-chat-store.tsx","../../src/renderer/ConversationWidgetContext.tsx","../../src/chat/ConversationMessageInput/ConversationMessageInputComposerWidgets/ConversationMessageInputComposerWidgets.tsx"],"sourcesContent":["import type {\n AgentsClientError,\n AgentsConversation,\n AgentsConversationMessage,\n PostedMessage,\n StartedConversation,\n} from \"../../contract/conversation\";\nimport type { ChatMessage } from \"../chat-message\";\nimport type { CanvasCreatedEntity, CanvasSliceState } from \"../../renderer/canvas/canvas-reducers\";\nimport type { CanvasOpenRequest } from \"../../renderer/canvas/canvas-state\";\nimport type { ConversationErrorType } from \"./conversation-error-type\";\n\n/**\n * How an entry point outside the chat hands a job over to the chat that opens next (one generic opening\n * request): the first visible message, or an invisible start signal so the agent speaks first, the entry point the\n * start comes from, and a widget to mount without a message (a page handing over a tool). Set before the chat mounts,\n * so a reset keeps it; the chat clears each part once it consumed it.\n */\nexport interface AgentsChatOpeningRequest {\n /** The first visible owner message of the next started conversation. */\n userMessage: string | null;\n /** The invisible start signal of the next started conversation (an empty visible message carries it). */\n startSignalText: string | null;\n /** The entry point the start comes from; the server reopens that entry point's recent conversation instead. */\n entryPointKey: string | null;\n /** The canonical wire name of a deep-linkable widget the chat mounts once, without a message. */\n deepLinkedWidgetName: string | null;\n}\n\n/** The state of one chat instance. */\nexport interface AgentsChatState extends CanvasSliceState {\n /** The conversation shown; null for a cold chat until a start or the metadata read brings it. */\n conversation: AgentsConversation | null;\n /** Null until the first page or a send; ordered by `indexInConversation`, the optimistic message last. */\n messages: ChatMessage[] | null;\n /** A send is on its way. */\n conversationLoading: boolean;\n /** The last read or send for this conversation came back. */\n conversationLoaded: boolean;\n /** An older page exists: the scroll-up load stays armed. */\n hasMoreOlder: boolean;\n /** The agent works on a turn (the controller mirrors the derived activity here; read by the launcher). */\n aiThinking: boolean;\n error: ConversationErrorType | null;\n /** Seconds until the quota frees up again; set only while `error` is RATE_LIMIT. */\n rateLimitRetryAfterSeconds: number | null;\n /**\n * The conversation the newest metadata or page read asked for; null after a reset. A late answer for another\n * conversation — or one that lands after a reset — is dropped.\n */\n requestedConversationId: number | null;\n /** A start is on its way; no second start is sent meanwhile. */\n startingNewConversation: boolean;\n /** The token of the start on its way; its answer applies only while it is still the pending one. */\n pendingStartToken: number | null;\n /**\n * How many starts this chat instance sent — the source of `pendingStartToken`. Survives a reset (like\n * `canvasMountCount`): the store outlives a remount of the chat, so a token is never reused for another start.\n */\n startTokenCount: number;\n openingRequest: AgentsChatOpeningRequest;\n}\n\nexport const EMPTY_AGENTS_CHAT_OPENING_REQUEST: AgentsChatOpeningRequest = {\n userMessage: null,\n startSignalText: null,\n entryPointKey: null,\n deepLinkedWidgetName: null,\n};\n\nexport const INITIAL_AGENTS_CHAT_STATE: AgentsChatState = {\n conversation: null,\n messages: null,\n conversationLoading: false,\n conversationLoaded: false,\n hasMoreOlder: false,\n aiThinking: false,\n error: null,\n rateLimitRetryAfterSeconds: null,\n requestedConversationId: null,\n startingNewConversation: false,\n pendingStartToken: null,\n startTokenCount: 0,\n openingRequest: EMPTY_AGENTS_CHAT_OPENING_REQUEST,\n canvas: null,\n lastClosedCanvas: null,\n canvasMountCount: 0,\n};\n\n/**\n * What happens to a chat instance. The read and send events carry the port's answers (`AgentsConversationClient`);\n * the controller dispatches the `…Requested` event before it calls the port and the `…Received` / `…Failed` event\n * with the answer.\n */\nexport type AgentsChatEvent =\n /** A conversation switch, an empty chat, the chat's unmount: everything goes except the opening request and the two counters. */\n | { type: \"reset\" }\n | { type: \"conversationMetadataRequested\"; conversationId: number }\n | { type: \"conversationMetadataReceived\"; conversationId: number; conversation: AgentsConversation }\n | { type: \"conversationMetadataFailed\"; conversationId: number }\n | { type: \"messagesPageRequested\"; conversationId: number }\n /** `hasMoreOlder` null: a changed-messages read, which says nothing about older pages. */\n | {\n type: \"messagesPageReceived\";\n conversationId: number;\n messages: AgentsConversationMessage[];\n hasMoreOlder: boolean | null;\n }\n | { type: \"messagePostRequested\"; message: ChatMessage }\n | { type: \"messagePostReceived\"; conversationId: number; posted: PostedMessage }\n | { type: \"messagePostFailed\"; error: AgentsClientError }\n /** Takes the next start token (`pendingStartToken`); the controller reads it after the dispatch. */\n | { type: \"startRequested\"; message: ChatMessage }\n | { type: \"startReceived\"; startToken: number; started: StartedConversation }\n | { type: \"startFailed\"; error: AgentsClientError }\n | { type: \"errorSet\"; error: ConversationErrorType | null }\n | { type: \"aiThinkingSet\"; aiThinking: boolean }\n /** Sets the named parts of the opening request; the others stay. */\n | { type: \"openingRequestSet\"; openingRequest: Partial<AgentsChatOpeningRequest> }\n | { type: \"canvasOpened\"; request: CanvasOpenRequest }\n | { type: \"canvasClosed\"; byCustomer: boolean }\n | { type: \"canvasResetForNewTurn\" }\n | { type: \"canvasCleared\" }\n | { type: \"canvasCreatedEntityIdSet\"; created: CanvasCreatedEntity };\n","import type { AgentsClientError } from \"../../contract/conversation\";\n\n/**\n * The error card the chat shows. A plain object with string values (not a TypeScript `enum`), so the chat store, the\n * view and an app's older chat state share one vocabulary without a nominal type in between.\n */\nexport const ConversationErrorType = {\n AI_BUDGET: \"AI_BUDGET\",\n /**\n * HTTP 429 from an AI endpoint — a per-minute/hour/day usage quota was hit. Distinct from AI_BUDGET (monthly budget):\n * this one clears on its own after the Retry-After window.\n */\n RATE_LIMIT: \"RATE_LIMIT\",\n NETWORK_ERROR: \"NETWORK_ERROR\",\n CONVERSATION_NOT_FOUND: \"CONVERSATION_NOT_FOUND\",\n /**\n * The backend run FAILED (e.g. the model provider returned an error). The raw provider error is admin-only (never\n * shown here); the owner gets a generic \"something went wrong\" card.\n */\n AGENT_ERROR: \"AGENT_ERROR\",\n /**\n * The conversation is COMPLETED/CANCELLED and refuses further owner input. Set from the server's stable error code\n * `CONVERSATION_CLOSED` or by the chat's own pre-send guard; the error card owns the copy.\n */\n CONVERSATION_CLOSED: \"CONVERSATION_CLOSED\",\n} as const;\n\nexport type ConversationErrorType = (typeof ConversationErrorType)[keyof typeof ConversationErrorType];\n\n/**\n * The error card of a refused send (post or start), read from the port's error. Only the stable outcomes select a\n * dedicated card; every other refusal is a generic network error — the same classification the older chat applies to\n * the server's error codes (`AI_BUDGET_REACHED`, `RATE_LIMIT_EXCEEDED`, `CONVERSATION_CLOSED`).\n */\nexport const readConversationErrorTypeOfRefusedSend = (error: AgentsClientError): ConversationErrorType => {\n if (error.kind === \"budget\") return ConversationErrorType.AI_BUDGET;\n if (error.kind === \"rateLimit\") return ConversationErrorType.RATE_LIMIT;\n if (error.kind === \"closed\") return ConversationErrorType.CONVERSATION_CLOSED;\n return ConversationErrorType.NETWORK_ERROR;\n};\n","import type { ChatMessage } from \"../chat-message\";\n\n/**\n * Merges two message lists by `indexInConversation`, preferring `incoming` on a collision, sorted ascending by index.\n * Messages without an index (the optimistic owner message) cannot be matched, so they follow the indexed ones in order.\n * A start or post answer carries the whole list and a live read brings it again: concatenating would show every\n * message twice.\n */\nexport const mergeChatMessagesByIndex = (existing: ChatMessage[], incoming: ChatMessage[]): ChatMessage[] => {\n const messagesByIndex = new Map<number, ChatMessage>();\n const messagesWithoutIndex: ChatMessage[] = [];\n const collectMessage = (message: ChatMessage) => {\n if (message.indexInConversation != null) {\n messagesByIndex.set(message.indexInConversation, message);\n } else {\n messagesWithoutIndex.push(message);\n }\n };\n existing.forEach(collectMessage);\n incoming.forEach(collectMessage);\n const indexedMessages = Array.from(messagesByIndex.values()).sort(\n (first, second) => (first.indexInConversation ?? 0) - (second.indexInConversation ?? 0),\n );\n return [...indexedMessages, ...messagesWithoutIndex];\n};\n\n/**\n * Tags the messages of a send's answer: `fresh` when the id was not in the list before — the server just delivered it,\n * so its one-shot widgets may fire; a replayed message never fires them again.\n */\nexport const tagFreshChatMessages = (incoming: ChatMessage[], previousMessages: ChatMessage[]): ChatMessage[] => {\n const previousIds = new Set(previousMessages.map((message) => message.id).filter((id): id is number => id != null));\n return incoming.map((message) => ({ ...message, fresh: message.id != null && !previousIds.has(message.id) }));\n};\n\n/**\n * Merges a page of a keyset read (the newest page, an older page, the changed tail) into the loaded messages by index.\n * A message is `fresh` only when it is a live arrival: never shown before and newer than everything loaded — so the\n * streamed reply opens its canvas while a scroll-up page and the first page on open stay history. A message already\n * shown keeps its tag. A page of another conversation than the one shown replaces the list.\n */\nexport const mergeMessagesPage = (\n loadedMessages: ChatMessage[] | null,\n page: ChatMessage[],\n requestedConversationId: number,\n): ChatMessage[] => {\n const shownConversationId = loadedMessages?.find((message) => message.conversationId != null)?.conversationId;\n const replacesShownConversation = shownConversationId != null && shownConversationId !== requestedConversationId;\n const existingMessages = replacesShownConversation ? [] : (loadedMessages ?? []);\n const messagesByIndex = new Map<number, ChatMessage>();\n for (const existingMessage of existingMessages) {\n if (existingMessage.indexInConversation != null) {\n messagesByIndex.set(existingMessage.indexInConversation, existingMessage);\n }\n }\n const hadMessagesBeforeMerge = existingMessages.length > 0;\n const highestShownIndex = Math.max(-1, ...existingMessages.map((message) => message.indexInConversation ?? -1));\n for (const incomingMessage of page) {\n if (incomingMessage.indexInConversation == null) continue;\n const previousMessage = messagesByIndex.get(incomingMessage.indexInConversation);\n const isLiveArrival =\n hadMessagesBeforeMerge && previousMessage == null && incomingMessage.indexInConversation > highestShownIndex;\n messagesByIndex.set(incomingMessage.indexInConversation, {\n ...incomingMessage,\n fresh: previousMessage?.fresh ?? isLiveArrival,\n });\n }\n return Array.from(messagesByIndex.values()).sort(\n (first, second) => (first.indexInConversation ?? 0) - (second.indexInConversation ?? 0),\n );\n};\n","import {\n applyClearCanvas,\n applyCloseCanvas,\n applyOpenCanvas,\n applyResetCanvasForNewTurn,\n applySetCanvasCreatedEntityId,\n} from \"../../renderer/canvas/canvas-reducers\";\nimport type { AgentsClientError } from \"../../contract/conversation\";\nimport type { ChatMessage } from \"../chat-message\";\nimport { type AgentsChatEvent, type AgentsChatState, INITIAL_AGENTS_CHAT_STATE } from \"./agents-chat-state\";\nimport { ConversationErrorType, readConversationErrorTypeOfRefusedSend } from \"./conversation-error-type\";\nimport { mergeChatMessagesByIndex, mergeMessagesPage, tagFreshChatMessages } from \"./merge-chat-messages\";\n\n/** The error card and the quota wait of a refused send. */\nconst withRefusedSendError = (state: AgentsChatState, error: AgentsClientError): AgentsChatState => {\n const conversationErrorType = readConversationErrorTypeOfRefusedSend(error);\n return {\n ...state,\n error: conversationErrorType,\n rateLimitRetryAfterSeconds:\n conversationErrorType === ConversationErrorType.RATE_LIMIT ? (error.retryAfterSeconds ?? null) : null,\n };\n};\n\n/** The messages a send's answer brings, merged over the loaded ones without the optimistic message (the last one). */\nconst mergeSendAnswer = (loadedMessages: ChatMessage[] | null, answerMessages: ChatMessage[]): ChatMessage[] => {\n const messagesWithoutOptimisticMessage = loadedMessages ? loadedMessages.slice(0, loadedMessages.length - 1) : [];\n return mergeChatMessagesByIndex(\n messagesWithoutOptimisticMessage,\n tagFreshChatMessages(answerMessages, messagesWithoutOptimisticMessage),\n );\n};\n\n/** The canvas transitions mutate the fields of the object they get (`canvas-reducers.ts`); this keeps the state immutable. */\nconst withCanvasTransition = (\n state: AgentsChatState,\n applyCanvasTransition: (nextState: AgentsChatState) => void,\n): AgentsChatState => {\n const nextState = { ...state };\n applyCanvasTransition(nextState);\n const changed =\n nextState.canvas !== state.canvas ||\n nextState.lastClosedCanvas !== state.lastClosedCanvas ||\n nextState.canvasMountCount !== state.canvasMountCount;\n return changed ? nextState : state;\n};\n\n/**\n * The chat store's reducer: plain functions over the contract types. Each case is the one of the older\n * chat state (a Redux slice and its cases) it replaces, reading the port's answers instead of the\n * generated client's actions; the replay spec feeds both the same recorded sequence.\n */\nexport const reduceAgentsChatState = (state: AgentsChatState, event: AgentsChatEvent): AgentsChatState => {\n switch (event.type) {\n case \"reset\":\n // The opening request is set from outside before the chat mounts (a cold chat resets as it comes up); the canvas\n // mount count and the start token count are monotonic sources of identities: all three survive.\n return {\n ...INITIAL_AGENTS_CHAT_STATE,\n openingRequest: state.openingRequest,\n canvasMountCount: state.canvasMountCount,\n startTokenCount: state.startTokenCount,\n };\n\n case \"conversationMetadataRequested\":\n case \"messagesPageRequested\":\n return state.requestedConversationId === event.conversationId\n ? state\n : { ...state, requestedConversationId: event.conversationId };\n\n case \"conversationMetadataReceived\":\n // Dropped after a reset or when another conversation was asked for since: a late answer would put the old\n // conversation back, and the next send would post into it instead of starting a new one.\n if (state.requestedConversationId === null || state.requestedConversationId !== event.conversationId) {\n return state;\n }\n return { ...state, conversation: event.conversation, conversationLoaded: true };\n\n case \"conversationMetadataFailed\":\n // A metadata read is best-effort: the chat stays as it is.\n return { ...state, conversationLoaded: true };\n\n case \"messagesPageReceived\": {\n if (state.requestedConversationId === null || state.requestedConversationId !== event.conversationId) {\n return state;\n }\n if (state.conversation !== null && state.conversation.id !== event.conversationId) {\n return state;\n }\n return {\n ...state,\n messages: mergeMessagesPage(state.messages, event.messages, event.conversationId),\n hasMoreOlder: event.hasMoreOlder ?? state.hasMoreOlder,\n conversationLoaded: true,\n };\n }\n\n case \"messagePostRequested\":\n return {\n ...state,\n conversationLoading: true,\n conversationLoaded: false,\n aiThinking: true,\n error: null,\n rateLimitRetryAfterSeconds: null,\n messages: [...(state.messages ?? []), event.message],\n };\n\n case \"messagePostReceived\":\n if (event.conversationId !== state.conversation?.id) {\n return state;\n }\n // The reply arrives through live updates, not in this answer: `aiThinking` stays as it is.\n return {\n ...state,\n messages: mergeSendAnswer(state.messages, event.posted.messages),\n conversationLoading: false,\n conversationLoaded: true,\n error: null,\n };\n\n case \"messagePostFailed\":\n return withRefusedSendError(\n { ...state, conversationLoading: false, conversationLoaded: true, aiThinking: false },\n event.error,\n );\n\n case \"startRequested\":\n return {\n ...state,\n conversation: null,\n conversationLoading: true,\n conversationLoaded: false,\n aiThinking: true,\n error: null,\n rateLimitRetryAfterSeconds: null,\n startingNewConversation: true,\n startTokenCount: state.startTokenCount + 1,\n pendingStartToken: state.startTokenCount + 1,\n // A signal-only start (an empty visible message carries the start signal) seeds no empty bubble.\n messages: event.message.message ? [event.message] : [],\n };\n\n case \"startReceived\": {\n if (event.startToken !== state.pendingStartToken) {\n return state;\n }\n const { started } = event;\n if (started.reopenedExisting) {\n // The recent conversation of the start's entry point: nothing was appended, no turn started. Its messages are\n // not in the answer — the controller reads its newest page — so the optimistic bubble goes.\n return {\n ...state,\n conversation: started.conversation,\n messages: [],\n conversationLoading: false,\n conversationLoaded: true,\n aiThinking: false,\n startingNewConversation: false,\n pendingStartToken: null,\n };\n }\n // The reply arrives through live updates: `aiThinking` stays on.\n return {\n ...state,\n conversation: started.conversation,\n messages: mergeSendAnswer(state.messages, started.messages),\n conversationLoading: false,\n conversationLoaded: true,\n startingNewConversation: false,\n pendingStartToken: null,\n };\n }\n\n case \"startFailed\":\n return withRefusedSendError(\n {\n ...state,\n conversation: null,\n conversationLoading: false,\n conversationLoaded: true,\n aiThinking: false,\n startingNewConversation: false,\n pendingStartToken: null,\n },\n event.error,\n );\n\n case \"errorSet\":\n return state.error === event.error ? state : { ...state, error: event.error };\n\n case \"aiThinkingSet\":\n return state.aiThinking === event.aiThinking ? state : { ...state, aiThinking: event.aiThinking };\n\n case \"openingRequestSet\":\n return { ...state, openingRequest: { ...state.openingRequest, ...event.openingRequest } };\n\n case \"canvasOpened\":\n return withCanvasTransition(state, (nextState) => {\n applyOpenCanvas(nextState, event.request);\n });\n\n case \"canvasClosed\":\n return withCanvasTransition(state, (nextState) => applyCloseCanvas(nextState, event.byCustomer));\n\n case \"canvasResetForNewTurn\":\n return withCanvasTransition(state, applyResetCanvasForNewTurn);\n\n case \"canvasCleared\":\n return withCanvasTransition(state, applyClearCanvas);\n\n case \"canvasCreatedEntityIdSet\":\n return withCanvasTransition(state, (nextState) => {\n applySetCanvasCreatedEntityId(nextState, event.created);\n });\n }\n};\n","import { type AgentsChatEvent, type AgentsChatState, INITIAL_AGENTS_CHAT_STATE } from \"./agents-chat-state\";\nimport { reduceAgentsChatState } from \"./reduce-agents-chat-state\";\n\n/**\n * The state handle of one chat instance. The app creates one per chat (host application: one per agent\n * window, created before the window's chat mounts) and releases it with the chat; the chat and the app's code outside\n * the chat read and dispatch through the same handle. React reads it through `useAgentsChatSelector`.\n */\nexport interface AgentsChatStore {\n getState: () => AgentsChatState;\n /** Calls the listener after every state change; returns the unsubscribe. */\n subscribe: (listener: () => void) => () => void;\n dispatch: (event: AgentsChatEvent) => void;\n}\n\n/** The plain implementation of `AgentsChatStore`: one state object, replaced by the reducer on every event. */\nexport class AgentsChatStateContainer implements AgentsChatStore {\n protected state: AgentsChatState;\n protected readonly listeners = new Set<() => void>();\n\n constructor(initialState: AgentsChatState = INITIAL_AGENTS_CHAT_STATE) {\n this.state = initialState;\n }\n\n getState = (): AgentsChatState => this.state;\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n dispatch = (event: AgentsChatEvent): void => {\n const nextState = reduceAgentsChatState(this.state, event);\n if (nextState === this.state) return;\n this.state = nextState;\n for (const notifyListener of [...this.listeners]) notifyListener();\n };\n}\n\n/** Creates the state handle of one chat instance. */\nexport const createAgentsChatStore = (initialState?: AgentsChatState): AgentsChatStore =>\n new AgentsChatStateContainer(initialState);\n","import { createContext, type ReactNode, useCallback, useContext, useSyncExternalStore } from \"react\";\nimport type { AgentsChatState } from \"./agents-chat-state\";\nimport type { AgentsChatStore } from \"./create-agents-chat-store\";\n\nconst AgentsChatStoreContext = createContext<AgentsChatStore | null>(null);\n\nexport interface AgentsChatStoreProviderProps {\n /** The state handle of the chat below (the app creates and releases it). */\n chatStore: AgentsChatStore;\n children?: ReactNode;\n}\n\n/** Puts one chat instance's state handle in reach of the chat and of the app's components inside it. */\nexport const AgentsChatStoreProvider = (props: AgentsChatStoreProviderProps) => {\n const { chatStore, children } = props;\n return <AgentsChatStoreContext.Provider value={chatStore}>{children}</AgentsChatStoreContext.Provider>;\n};\n\n/** The state handle of the chat this component renders in; throws outside `AgentsChatStoreProvider`. */\nexport const useAgentsChatStore = (): AgentsChatStore => {\n const chatStore = useContext(AgentsChatStoreContext);\n if (chatStore === null) {\n throw new Error(\"A chat component rendered outside AgentsChatStoreProvider: the app has to mount its chat store.\");\n }\n return chatStore;\n};\n\n/** The state handle of the chat this component renders in, or null outside a chat. */\nexport const useOptionalAgentsChatStore = (): AgentsChatStore | null => useContext(AgentsChatStoreContext);\n\nconst subscribeToNothing = () => () => undefined;\n\n/**\n * Reads one value of a chat instance's state and re-renders when it changes. The selector must return a value that\n * keeps its identity while the state does not change (a state field, not a new object). Without a store it returns\n * `valueWithoutStore`.\n */\nexport const useAgentsChatSelector = <Selected,>(\n chatStore: AgentsChatStore | null | undefined,\n selector: (state: AgentsChatState) => Selected,\n valueWithoutStore?: Selected,\n): Selected => {\n const subscribe = chatStore ? chatStore.subscribe : subscribeToNothing;\n const readSelectedValue = useCallback(\n () => (chatStore ? selector(chatStore.getState()) : (valueWithoutStore as Selected)),\n [chatStore, selector, valueWithoutStore],\n );\n return useSyncExternalStore(subscribe, readSelectedValue, readSelectedValue);\n};\n\n/** Reads one value of the state of the chat this component renders in. */\nexport const useAgentsChatState = <Selected,>(selector: (state: AgentsChatState) => Selected): Selected =>\n useAgentsChatSelector(useAgentsChatStore(), selector);\n","import React, { ReactNode, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useAgentsEnvironment, useAgentsStateDispatch, useAgentsStateSelector } from \"../provider/AgentsProvider\";\nimport type { ConversationWidgetStatePartition } from \"./conversation-widget-state-partition\";\nimport { createAgentsChatStore } from \"../chat/store/create-agents-chat-store\";\nimport type { AgentsChatEvent } from \"../chat/store/agents-chat-state\";\nimport type { AgentsChatStore } from \"../chat/store/create-agents-chat-store\";\nimport { useAgentsChatSelector } from \"../chat/store/use-agents-chat-store\";\nimport type { CanvasState, LastClosedCanvas } from \"./canvas/canvas-state\";\nimport { CANVAS_VIABLE_MIN_WIDTH } from \"../widgets/CanvasWidgetCard/use-canvas-viable\";\nimport { ConversationComposerWidget } from \"./conversation-composer-widget\";\nimport type { CanvasCreatedEntity } from \"./canvas/canvas-reducers\";\nimport { clearStoredCanvas, storeOpenCanvas } from \"./canvas/canvasStorage\";\nimport {\n type CanvasOpenRequestFromOpener,\n type ConversationWidgetCallbacks,\n ConversationWidgetContext,\n defaultConversationWidgetCallbacks,\n type InjectSignalOptions,\n} from \"./ConversationWidgetCallbacksContext\";\n\n// The callbacks, their context and the chat-free hosts live in `ConversationWidgetCallbacksContext.tsx`; this module\n// adds the provider that reads the chat's state (the package chat store or an app's partition) and re-exports the rest.\nexport * from \"./ConversationWidgetCallbacksContext\";\n\n// Number of mounted agentic chat surfaces (widget, full-page chat, dashboard). Drives the app's \"a chat surface is\n// open\" action (`buildChatSurfaceOpenChangedAction`, e.g. a flag of the app's own flows): true while ≥1 is open.\n// Module-level so multiple providers share one count.\nlet agenticChatMountCount = 0;\n\nexport interface ConversationWidgetProviderProps {\n children: ReactNode;\n callbacks: Partial<ConversationWidgetCallbacks>;\n /**\n * The chat slice partition this provider's canvas lives in. The shell is shared by the two chat doors, so the door\n * says which partition: `AgentChat` passes `AgentChatInstance`; the AI-Extensions chat, every story and every spec\n * keep the default. A prop, not a callback — `callbacks` is `Partial`, and the partition is not optional.\n */\n sliceInstance?: ConversationWidgetStatePartition;\n /**\n * The package chat store of the chat: the agent chat passes its window's store and the provider reads\n * and writes the canvas there. Without it the provider reads a partition of the app's own chat state\n * (`sliceInstance`, else the environment's `defaultChatStatePartition`).\n */\n chatStore?: AgentsChatStore;\n /**\n * False for a host that renders the chat without the split (`ConversationView.disableSplitView`): there is nowhere\n * to open a canvas, so every open request is ignored with reason `noSurface`. Default true.\n */\n hostHasCanvasSurface?: boolean;\n}\n\n/** The canvas transitions the provider dispatches — the canvas events of the package chat store. */\ntype ConversationWidgetCanvasEvent = Extract<\n AgentsChatEvent,\n { type: \"canvasOpened\" | \"canvasClosed\" | \"canvasResetForNewTurn\" | \"canvasCleared\" | \"canvasCreatedEntityIdSet\" }\n>;\n\n/** What the provider reads from the chat's state and how it writes a canvas transition back. */\ninterface ConversationWidgetChatState {\n canvas: CanvasState | null;\n lastClosedCanvas: LastClosedCanvas | null;\n isConversationRunning: boolean;\n runState: string | null | undefined;\n messages: ConversationWidgetCallbacks[\"messages\"];\n dispatchCanvasEvent: (event: ConversationWidgetCanvasEvent) => void;\n}\n\ntype ConversationWidgetProviderBodyProps = Omit<ConversationWidgetProviderProps, \"sliceInstance\" | \"chatStore\"> & {\n chatState: ConversationWidgetChatState;\n};\n\nconst selectCanvas = (state: { canvas: CanvasState | null }) => state.canvas;\nconst selectLastClosedCanvas = (state: { lastClosedCanvas: LastClosedCanvas | null }) => state.lastClosedCanvas;\nconst selectAiThinking = (state: { aiThinking: boolean }) => state.aiThinking;\nconst selectRunState = (state: { conversation: { runState?: string | null } | null }) => state.conversation?.runState;\nconst selectMessages = (state: { messages: ConversationWidgetCallbacks[\"messages\"] }) => state.messages;\n\n/** The provider over the package chat store of the chat. */\nconst ChatStoreConversationWidgetProvider = (\n props: Omit<ConversationWidgetProviderProps, \"sliceInstance\" | \"chatStore\"> & { chatStore: AgentsChatStore },\n) => {\n const { chatStore, ...bodyProps } = props;\n const canvas = useAgentsChatSelector(chatStore, selectCanvas);\n const lastClosedCanvas = useAgentsChatSelector(chatStore, selectLastClosedCanvas);\n const isConversationRunning = useAgentsChatSelector(chatStore, selectAiThinking);\n const runState = useAgentsChatSelector(chatStore, selectRunState);\n const messages = useAgentsChatSelector(chatStore, selectMessages);\n const chatState = useMemo<ConversationWidgetChatState>(\n () => ({\n canvas,\n lastClosedCanvas,\n isConversationRunning,\n runState,\n messages,\n dispatchCanvasEvent: chatStore.dispatch,\n }),\n [canvas, lastClosedCanvas, isConversationRunning, runState, messages, chatStore],\n );\n return <ConversationWidgetProviderBody {...bodyProps} chatState={chatState} />;\n};\n\n/** The provider over a partition of the older chat state (the AI-Extensions chat, stories, specs). */\nconst SliceConversationWidgetProvider = (\n props: Omit<ConversationWidgetProviderProps, \"sliceInstance\" | \"chatStore\"> & {\n sliceInstance: ConversationWidgetStatePartition;\n },\n) => {\n const { sliceInstance, ...bodyProps } = props;\n const dispatch = useAgentsStateDispatch();\n // One selector per field, not one returning an object, so an unrelated store change does not re-render every widget\n // through a fresh object identity.\n const canvas = useAgentsStateSelector((state) => sliceInstance.selectState(state).canvas);\n const lastClosedCanvas = useAgentsStateSelector((state) => sliceInstance.selectState(state).lastClosedCanvas);\n const isConversationRunning = useAgentsStateSelector((state) => sliceInstance.selectState(state).aiThinking);\n const runState = useAgentsStateSelector((state) => sliceInstance.selectState(state).conversation?.runState);\n const messages = useAgentsStateSelector((state) => sliceInstance.selectState(state).messages);\n const dispatchCanvasEvent = useCallback(\n (event: ConversationWidgetCanvasEvent) => {\n const { actions } = sliceInstance;\n if (event.type === \"canvasOpened\") dispatch(actions.openCanvas(event.request));\n else if (event.type === \"canvasClosed\") dispatch(actions.closeCanvas({ byCustomer: event.byCustomer }));\n else if (event.type === \"canvasResetForNewTurn\") dispatch(actions.resetCanvasForNewTurn());\n else if (event.type === \"canvasCleared\") dispatch(actions.clearCanvas());\n else dispatch(actions.setCanvasCreatedEntityId(event.created));\n },\n [dispatch, sliceInstance],\n );\n const chatState = useMemo<ConversationWidgetChatState>(\n () => ({ canvas, lastClosedCanvas, isConversationRunning, runState, messages, dispatchCanvasEvent }),\n [canvas, lastClosedCanvas, isConversationRunning, runState, messages, dispatchCanvasEvent],\n );\n return <ConversationWidgetProviderBody {...bodyProps} chatState={chatState} />;\n};\n\n/** The provider over a chat store of its own — a host that brings neither a chat store nor a partition (a story). */\nconst OwnChatStoreConversationWidgetProvider = (\n props: Omit<ConversationWidgetProviderProps, \"sliceInstance\" | \"chatStore\">,\n) => {\n const [ownChatStore] = useState(createAgentsChatStore);\n return <ChatStoreConversationWidgetProvider {...props} chatStore={ownChatStore} />;\n};\n\n/**\n * The widget callbacks of one chat, the canvas model included. Reads the chat's state from the package chat store when\n * the host passes one (`chatStore`), else from a partition of the app's own chat state (`sliceInstance`, or the\n * environment's `defaultChatStatePartition` — host application: the AI-Extensions chat), else from a store of its own.\n */\nexport const ConversationWidgetProvider = (props: ConversationWidgetProviderProps) => {\n const { sliceInstance, chatStore, ...bodyProps } = props;\n const { defaultChatStatePartition } = useAgentsEnvironment();\n const statePartition = sliceInstance ?? defaultChatStatePartition;\n if (chatStore) return <ChatStoreConversationWidgetProvider {...bodyProps} chatStore={chatStore} />;\n if (statePartition) return <SliceConversationWidgetProvider {...bodyProps} sliceInstance={statePartition} />;\n return <OwnChatStoreConversationWidgetProvider {...bodyProps} />;\n};\n\nconst ConversationWidgetProviderBody = ({\n children,\n callbacks,\n hostHasCanvasSurface = true,\n chatState,\n}: ConversationWidgetProviderBodyProps) => {\n const dispatch = useAgentsStateDispatch();\n const { buildChatSurfaceOpenChangedAction } = useAgentsEnvironment();\n const { canvas, lastClosedCanvas, isConversationRunning, runState, messages } = chatState;\n const isConversationClosed = runState === \"COMPLETED\" || runState === \"CANCELLED\";\n const dispatchCanvasEventRef = useRef(chatState.dispatchCanvasEvent);\n dispatchCanvasEventRef.current = chatState.dispatchCanvasEvent;\n const hostHasCanvasSurfaceRef = useRef(hostHasCanvasSurface);\n hostHasCanvasSurfaceRef.current = hostHasCanvasSurface;\n\n // An agentic chat surface is open: the app hears it through its action (e.g. a flag every connect/create/verify flow\n // launched from inside the chat reads to stay in-widget instead of navigating away).\n // Set here (not at the connect button) so it also covers the verify path, where there is no connect click.\n // Ref-counted so concurrently-mounted chat surfaces don't clear each other's flag.\n const buildChatSurfaceOpenChangedActionRef = useRef(buildChatSurfaceOpenChangedAction);\n buildChatSurfaceOpenChangedActionRef.current = buildChatSurfaceOpenChangedAction;\n useEffect(() => {\n agenticChatMountCount += 1;\n if (agenticChatMountCount === 1 && buildChatSurfaceOpenChangedActionRef.current) {\n dispatch(buildChatSurfaceOpenChangedActionRef.current(true));\n }\n return () => {\n agenticChatMountCount -= 1;\n if (agenticChatMountCount === 0 && buildChatSurfaceOpenChangedActionRef.current) {\n dispatch(buildChatSurfaceOpenChangedActionRef.current(false));\n }\n };\n }, [dispatch]);\n\n // Mirror the latest callbacks in a ref so the exposed functions stay stable across\n // renders even if the parent passes a fresh `callbacks` object every render.\n const callbacksRef = useRef(callbacks);\n callbacksRef.current = callbacks;\n\n // Composer-widget ownership — controlled when the host supplies `composerWidgets` (the builder page, click-bridge\n // F), otherwise uncontrolled: the provider owns the state so a descendant (e.g. an app's editor drawer) can\n // mutate it directly. See ConversationWidgetCallbacks.\n const isComposerWidgetsControlled = callbacks.composerWidgets !== undefined;\n const [internalComposerWidgets, setInternalComposerWidgets] = useState<ConversationComposerWidget[]>([]);\n const composerWidgets = isComposerWidgetsControlled\n ? (callbacks.composerWidgets as ConversationComposerWidget[])\n : internalComposerWidgets;\n\n // Mirrors the latest resolved composerWidgets + controlled flag so the mutator callbacks below can compute the\n // next array off REAL current state while keeping stable identities across renders ([] deps) — same trick as\n // `callbacksRef` above.\n const composerWidgetsStateRef = useRef({ composerWidgets, isComposerWidgetsControlled });\n composerWidgetsStateRef.current = { composerWidgets, isComposerWidgetsControlled };\n\n const publishComposerWidgets = useCallback((next: ConversationComposerWidget[]) => {\n if (composerWidgetsStateRef.current.isComposerWidgetsControlled) {\n callbacksRef.current.onComposerWidgetsChange?.(next);\n } else {\n setInternalComposerWidgets(next);\n }\n }, []);\n\n const addComposerWidget = useCallback(\n (widgetName: string, fields: Record<string, unknown>): string => {\n const composerWidgetId = crypto.randomUUID();\n publishComposerWidgets([\n ...composerWidgetsStateRef.current.composerWidgets,\n { composerWidgetId, widgetName, fields },\n ]);\n return composerWidgetId;\n },\n [publishComposerWidgets],\n );\n\n const replaceComposerWidgetFields = useCallback(\n (composerWidgetId: string, fields: Record<string, unknown>) => {\n publishComposerWidgets(\n composerWidgetsStateRef.current.composerWidgets.map((widget) =>\n widget.composerWidgetId === composerWidgetId ? { ...widget, fields } : widget,\n ),\n );\n },\n [publishComposerWidgets],\n );\n\n const removeComposerWidget = useCallback(\n (composerWidgetId: string) => {\n publishComposerWidgets(\n composerWidgetsStateRef.current.composerWidgets.filter(\n (widget) => widget.composerWidgetId !== composerWidgetId,\n ),\n );\n },\n [publishComposerWidgets],\n );\n\n const clearComposerWidgets = useCallback(() => {\n publishComposerWidgets([]);\n }, [publishComposerWidgets]);\n\n // The one way to open a canvas (all four origins). The provider supplies what only it knows — the split's viability\n // (measured on the window, like `useCanvasViable`) and whether this host has a canvas surface — and the reducer\n // applies the opening rule. Ignored requests change nothing.\n const openCanvas = useCallback(\n (request: CanvasOpenRequestFromOpener) => {\n dispatchCanvasEventRef.current({\n type: \"canvasOpened\",\n request: {\n ...request,\n viewportViable: window.innerWidth >= CANVAS_VIABLE_MIN_WIDTH,\n hostHasCanvasSurface: hostHasCanvasSurfaceRef.current,\n },\n });\n },\n [],\n );\n\n // Close the open canvas; it stays re-openable as `lastClosedCanvas`. `byCustomer` = the canvas's own close control,\n // which vetoes a live re-delivery of the same identity until the next send / click / page hand-over.\n const closeCanvas = useCallback(\n (byCustomer: boolean) => {\n dispatchCanvasEventRef.current({ type: \"canvasClosed\", byCustomer });\n },\n [],\n );\n\n const lastClosedCanvasRef = useRef(lastClosedCanvas);\n lastClosedCanvasRef.current = lastClosedCanvas;\n const reopenLastClosedCanvas = useCallback(() => {\n const last = lastClosedCanvasRef.current;\n if (last === null) return;\n dispatchCanvasEventRef.current({\n type: \"canvasOpened\",\n request: {\n canvasId: last.canvasId,\n instanceId: last.instanceId,\n anchor: last.anchor,\n origin: \"cardClick\",\n justDelivered: false,\n viewportViable: window.innerWidth >= CANVAS_VIABLE_MIN_WIDTH,\n hostHasCanvasSurface: hostHasCanvasSurfaceRef.current,\n ...(last.createdEntityId !== undefined ? { createdEntityId: last.createdEntityId } : {}),\n },\n });\n }, []);\n\n const setCanvasCreatedEntityId = useCallback(\n (created: CanvasCreatedEntity) => {\n dispatchCanvasEventRef.current({ type: \"canvasCreatedEntityIdSet\", created });\n },\n [],\n );\n\n // The pointer of the OPEN canvas is remembered per conversation for a reload (`canvasStorage.ts`), for any\n // lifetime. Cleared when the canvas closes INSIDE the same conversation; a conversation switch clears the slice too,\n // but the LEFT conversation keeps its entry so coming back restores it.\n const storedCanvasConversationIdRef = useRef<number | undefined>(undefined);\n const conversationIdForStorage = callbacks.conversationId;\n useEffect(() => {\n if (canvas !== null) {\n storeOpenCanvas(conversationIdForStorage, canvas);\n storedCanvasConversationIdRef.current = conversationIdForStorage;\n return;\n }\n if (\n storedCanvasConversationIdRef.current !== undefined &&\n storedCanvasConversationIdRef.current === conversationIdForStorage\n ) {\n clearStoredCanvas(conversationIdForStorage);\n }\n storedCanvasConversationIdRef.current = undefined;\n }, [canvas, conversationIdForStorage]);\n\n // A conversation switch forgets the canvas and the last closed one (the LEFT conversation keeps its stored pointer).\n const resetCanvas = useCallback(() => {\n dispatchCanvasEventRef.current({ type: \"canvasCleared\" });\n }, []);\n\n // The SEND boundary: a turn canvas is over for good, a pinned one stays (`canvas-reducers.ts`).\n const resetCanvasForNewTurn = useCallback(() => {\n dispatchCanvasEventRef.current({ type: \"canvasResetForNewTurn\" });\n }, []);\n\n const sendMessageToChat = useCallback((message: string) => {\n return callbacksRef.current.sendMessageToChat?.(message);\n }, []);\n\n const prefillComposer = useCallback((text: string) => {\n callbacksRef.current.prefillComposer?.(text);\n }, []);\n\n const injectSignal = useCallback((signalText: string, options?: InjectSignalOptions) => {\n return callbacksRef.current.injectSignal?.(signalText, options);\n }, []);\n\n const minimizeChatHost = useCallback(() => {\n callbacksRef.current.minimizeChatHost?.();\n }, []);\n\n const contextValue = useMemo<ConversationWidgetCallbacks>(\n () => ({\n canvas,\n hostHasCanvasSurface,\n lastClosedCanvas,\n openCanvas,\n closeCanvas,\n reopenLastClosedCanvas,\n setCanvasCreatedEntityId,\n resetCanvas,\n resetCanvasForNewTurn,\n sendMessageToChat,\n prefillComposer,\n injectSignal,\n minimizeChatHost,\n chatAgentSpaceKey: callbacks.chatAgentSpaceKey,\n isConversationRunning,\n isConversationClosed,\n conversationId: callbacks.conversationId,\n composerWidgets,\n addComposerWidget,\n replaceComposerWidgetFields,\n removeComposerWidget,\n clearComposerWidgets,\n onOpenConversation: callbacks.onOpenConversation,\n onSwitchConversation: callbacks.onSwitchConversation,\n isOnboardingSetupConversation: callbacks.isOnboardingSetupConversation ?? false,\n messages,\n }),\n [\n canvas,\n hostHasCanvasSurface,\n lastClosedCanvas,\n openCanvas,\n closeCanvas,\n reopenLastClosedCanvas,\n setCanvasCreatedEntityId,\n resetCanvas,\n resetCanvasForNewTurn,\n sendMessageToChat,\n prefillComposer,\n injectSignal,\n minimizeChatHost,\n callbacks.chatAgentSpaceKey,\n isConversationRunning,\n isConversationClosed,\n callbacks.conversationId,\n composerWidgets,\n addComposerWidget,\n replaceComposerWidgetFields,\n removeComposerWidget,\n clearComposerWidgets,\n callbacks.onOpenConversation,\n callbacks.onSwitchConversation,\n callbacks.isOnboardingSetupConversation,\n messages,\n ],\n );\n\n return <ConversationWidgetContext.Provider value={contextValue}>{children}</ConversationWidgetContext.Provider>;\n};\n\n","import React from \"react\";\nimport { classNames } from \"../../../provider/class-names\";\nimport styles from \"./ConversationMessageInputComposerWidgets.module.scss\";\nimport { useConversationWidgetContext } from \"../../../renderer/ConversationWidgetContext\";\nimport { conversationWidgetRegistry } from \"../../../renderer/conversationWidgetRegistry\";\n\nexport interface ConversationMessageInputComposerWidgetsProps {\n testId?: string;\n}\n\n/**\n * Generic strip of composer widgets above the chat input's text area — the composer-side twin of\n * `ConversationMessageInputAttachmentsPreviewStrip`, same grid-rows 0fr→1fr reveal. Reads `composerWidgets` from the\n * widget context itself (so every ConversationView host gets it for free, mirroring the deleted selection chip),\n * and for each widget resolves the registry entry by `widgetName` and renders its `composerComponent` with\n * `{ composerWidgetId, fields, replaceFields, remove }`. An unknown name, or an entry without a `composerComponent`,\n * renders nothing for that widget — the same kill switch the fence plugin applies.\n */\nexport const ConversationMessageInputComposerWidgets = (props: ConversationMessageInputComposerWidgetsProps) => {\n const { testId = \"chat-input\" } = props;\n const { composerWidgets, replaceComposerWidgetFields, removeComposerWidget } = useConversationWidgetContext();\n\n const renderableWidgets = composerWidgets.flatMap((widget) => {\n const entry = conversationWidgetRegistry.widgets.find((candidate) => candidate.name === widget.widgetName);\n return entry?.composerComponent ? [{ widget, Component: entry.composerComponent }] : [];\n });\n\n return (\n <div\n className={classNames(styles.stripReveal, { [styles.stripRevealOpen]: renderableWidgets.length > 0 })}\n data-testid={`${testId}-composer-widgets-strip`}\n >\n <div className={styles.stripRevealInner}>\n <div className={styles.strip}>\n {renderableWidgets.map(({ widget, Component }) => (\n <Component\n key={widget.composerWidgetId}\n composerWidgetId={widget.composerWidgetId}\n fields={widget.fields}\n replaceFields={(nextFields) => replaceComposerWidgetFields(widget.composerWidgetId, nextFields)}\n remove={() => removeComposerWidget(widget.composerWidgetId)}\n testId={`${testId}-composer-widget-${widget.composerWidgetId}`}\n />\n ))}\n </div>\n </div>\n </div>\n );\n};\n"],"names":[],"mappings":";;;;;;;;AA+DO,MAAM,oCAA8D;AAAA,EACzE,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,sBAAsB;AACxB;AAEO,MAAM,4BAA6C;AAAA,EACxD,cAAc;AAAA,EACd,UAAU;AAAA,EACV,qBAAqB;AAAA,EACrB,oBAAoB;AAAA,EACpB,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,4BAA4B;AAAA,EAC5B,yBAAyB;AAAA,EACzB,yBAAyB;AAAA,EACzB,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,gBAAgB;AAAA,EAChB,QAAQ;AAAA,EACR,kBAAkB;AAAA,EAClB,kBAAkB;AACpB;ACjFO,MAAM,wBAAwB;AAAA,EACnC,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA,EAKX,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,wBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKxB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA,EAKb,qBAAqB;AACvB;AASO,MAAM,yCAAyC,CAAC,UAAoD;AACzG,MAAI,MAAM,SAAS,SAAU,QAAO,sBAAsB;AAC1D,MAAI,MAAM,SAAS,YAAa,QAAO,sBAAsB;AAC7D,MAAI,MAAM,SAAS,SAAU,QAAO,sBAAsB;AAC1D,SAAO,sBAAsB;AAC/B;AC/BO,MAAM,2BAA2B,CAAC,UAAyB,aAA2C;AAC3G,QAAM,sCAAsB,IAAA;AAC5B,QAAM,uBAAsC,CAAA;AAC5C,QAAM,iBAAiB,CAAC,YAAyB;AAC/C,QAAI,QAAQ,uBAAuB,MAAM;AACvC,sBAAgB,IAAI,QAAQ,qBAAqB,OAAO;AAAA,IAC1D,OAAO;AACL,2BAAqB,KAAK,OAAO;AAAA,IACnC;AAAA,EACF;AACA,WAAS,QAAQ,cAAc;AAC/B,WAAS,QAAQ,cAAc;AAC/B,QAAM,kBAAkB,MAAM,KAAK,gBAAgB,OAAA,CAAQ,EAAE;AAAA,IAC3D,CAAC,OAAO,YAAY,MAAM,uBAAuB,MAAM,OAAO,uBAAuB;AAAA,EAAA;AAEvF,SAAO,CAAC,GAAG,iBAAiB,GAAG,oBAAoB;AACrD;AAMO,MAAM,uBAAuB,CAAC,UAAyB,qBAAmD;AAC/G,QAAM,cAAc,IAAI,IAAI,iBAAiB,IAAI,CAAC,YAAY,QAAQ,EAAE,EAAE,OAAO,CAAC,OAAqB,MAAM,IAAI,CAAC;AAClH,SAAO,SAAS,IAAI,CAAC,aAAa,EAAE,GAAG,SAAS,OAAO,QAAQ,MAAM,QAAQ,CAAC,YAAY,IAAI,QAAQ,EAAE,IAAI;AAC9G;AAQO,MAAM,oBAAoB,CAC/B,gBACA,MACA,4BACkB;AAClB,QAAM,sBAAsB,gBAAgB,KAAK,CAAC,YAAY,QAAQ,kBAAkB,IAAI,GAAG;AAC/F,QAAM,4BAA4B,uBAAuB,QAAQ,wBAAwB;AACzF,QAAM,mBAAmB,4BAA4B,CAAA,IAAM,kBAAkB,CAAA;AAC7E,QAAM,sCAAsB,IAAA;AAC5B,aAAW,mBAAmB,kBAAkB;AAC9C,QAAI,gBAAgB,uBAAuB,MAAM;AAC/C,sBAAgB,IAAI,gBAAgB,qBAAqB,eAAe;AAAA,IAC1E;AAAA,EACF;AACA,QAAM,yBAAyB,iBAAiB,SAAS;AACzD,QAAM,oBAAoB,KAAK,IAAI,IAAI,GAAG,iBAAiB,IAAI,CAAC,YAAY,QAAQ,uBAAuB,EAAE,CAAC;AAC9G,aAAW,mBAAmB,MAAM;AAClC,QAAI,gBAAgB,uBAAuB,KAAM;AACjD,UAAM,kBAAkB,gBAAgB,IAAI,gBAAgB,mBAAmB;AAC/E,UAAM,gBACJ,0BAA0B,mBAAmB,QAAQ,gBAAgB,sBAAsB;AAC7F,oBAAgB,IAAI,gBAAgB,qBAAqB;AAAA,MACvD,GAAG;AAAA,MACH,OAAO,iBAAiB,SAAS;AAAA,IAAA,CAClC;AAAA,EACH;AACA,SAAO,MAAM,KAAK,gBAAgB,OAAA,CAAQ,EAAE;AAAA,IAC1C,CAAC,OAAO,YAAY,MAAM,uBAAuB,MAAM,OAAO,uBAAuB;AAAA,EAAA;AAEzF;ACxDA,MAAM,uBAAuB,CAAC,OAAwB,UAA8C;AAClG,QAAM,wBAAwB,uCAAuC,KAAK;AAC1E,SAAO;AAAA,IACL,GAAG;AAAA,IACH,OAAO;AAAA,IACP,4BACE,0BAA0B,sBAAsB,aAAc,MAAM,qBAAqB,OAAQ;AAAA,EAAA;AAEvG;AAGA,MAAM,kBAAkB,CAAC,gBAAsC,mBAAiD;AAC9G,QAAM,mCAAmC,iBAAiB,eAAe,MAAM,GAAG,eAAe,SAAS,CAAC,IAAI,CAAA;AAC/G,SAAO;AAAA,IACL;AAAA,IACA,qBAAqB,gBAAgB,gCAAgC;AAAA,EAAA;AAEzE;AAGA,MAAM,uBAAuB,CAC3B,OACA,0BACoB;AACpB,QAAM,YAAY,EAAE,GAAG,MAAA;AACvB,wBAAsB,SAAS;AAC/B,QAAM,UACJ,UAAU,WAAW,MAAM,UAC3B,UAAU,qBAAqB,MAAM,oBACrC,UAAU,qBAAqB,MAAM;AACvC,SAAO,UAAU,YAAY;AAC/B;AAOO,MAAM,wBAAwB,CAAC,OAAwB,UAA4C;AACxG,UAAQ,MAAM,MAAA;AAAA,IACZ,KAAK;AAGH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,gBAAgB,MAAM;AAAA,QACtB,kBAAkB,MAAM;AAAA,QACxB,iBAAiB,MAAM;AAAA,MAAA;AAAA,IAG3B,KAAK;AAAA,IACL,KAAK;AACH,aAAO,MAAM,4BAA4B,MAAM,iBAC3C,QACA,EAAE,GAAG,OAAO,yBAAyB,MAAM,eAAA;AAAA,IAEjD,KAAK;AAGH,UAAI,MAAM,4BAA4B,QAAQ,MAAM,4BAA4B,MAAM,gBAAgB;AACpG,eAAO;AAAA,MACT;AACA,aAAO,EAAE,GAAG,OAAO,cAAc,MAAM,cAAc,oBAAoB,KAAA;AAAA,IAE3E,KAAK;AAEH,aAAO,EAAE,GAAG,OAAO,oBAAoB,KAAA;AAAA,IAEzC,KAAK,wBAAwB;AAC3B,UAAI,MAAM,4BAA4B,QAAQ,MAAM,4BAA4B,MAAM,gBAAgB;AACpG,eAAO;AAAA,MACT;AACA,UAAI,MAAM,iBAAiB,QAAQ,MAAM,aAAa,OAAO,MAAM,gBAAgB;AACjF,eAAO;AAAA,MACT;AACA,aAAO;AAAA,QACL,GAAG;AAAA,QACH,UAAU,kBAAkB,MAAM,UAAU,MAAM,UAAU,MAAM,cAAc;AAAA,QAChF,cAAc,MAAM,gBAAgB,MAAM;AAAA,QAC1C,oBAAoB;AAAA,MAAA;AAAA,IAExB;AAAA,IAEA,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,qBAAqB;AAAA,QACrB,oBAAoB;AAAA,QACpB,YAAY;AAAA,QACZ,OAAO;AAAA,QACP,4BAA4B;AAAA,QAC5B,UAAU,CAAC,GAAI,MAAM,YAAY,CAAA,GAAK,MAAM,OAAO;AAAA,MAAA;AAAA,IAGvD,KAAK;AACH,UAAI,MAAM,mBAAmB,MAAM,cAAc,IAAI;AACnD,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,QACL,GAAG;AAAA,QACH,UAAU,gBAAgB,MAAM,UAAU,MAAM,OAAO,QAAQ;AAAA,QAC/D,qBAAqB;AAAA,QACrB,oBAAoB;AAAA,QACpB,OAAO;AAAA,MAAA;AAAA,IAGX,KAAK;AACH,aAAO;AAAA,QACL,EAAE,GAAG,OAAO,qBAAqB,OAAO,oBAAoB,MAAM,YAAY,MAAA;AAAA,QAC9E,MAAM;AAAA,MAAA;AAAA,IAGV,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,cAAc;AAAA,QACd,qBAAqB;AAAA,QACrB,oBAAoB;AAAA,QACpB,YAAY;AAAA,QACZ,OAAO;AAAA,QACP,4BAA4B;AAAA,QAC5B,yBAAyB;AAAA,QACzB,iBAAiB,MAAM,kBAAkB;AAAA,QACzC,mBAAmB,MAAM,kBAAkB;AAAA;AAAA,QAE3C,UAAU,MAAM,QAAQ,UAAU,CAAC,MAAM,OAAO,IAAI,CAAA;AAAA,MAAC;AAAA,IAGzD,KAAK,iBAAiB;AACpB,UAAI,MAAM,eAAe,MAAM,mBAAmB;AAChD,eAAO;AAAA,MACT;AACA,YAAM,EAAE,YAAY;AACpB,UAAI,QAAQ,kBAAkB;AAG5B,eAAO;AAAA,UACL,GAAG;AAAA,UACH,cAAc,QAAQ;AAAA,UACtB,UAAU,CAAA;AAAA,UACV,qBAAqB;AAAA,UACrB,oBAAoB;AAAA,UACpB,YAAY;AAAA,UACZ,yBAAyB;AAAA,UACzB,mBAAmB;AAAA,QAAA;AAAA,MAEvB;AAEA,aAAO;AAAA,QACL,GAAG;AAAA,QACH,cAAc,QAAQ;AAAA,QACtB,UAAU,gBAAgB,MAAM,UAAU,QAAQ,QAAQ;AAAA,QAC1D,qBAAqB;AAAA,QACrB,oBAAoB;AAAA,QACpB,yBAAyB;AAAA,QACzB,mBAAmB;AAAA,MAAA;AAAA,IAEvB;AAAA,IAEA,KAAK;AACH,aAAO;AAAA,QACL;AAAA,UACE,GAAG;AAAA,UACH,cAAc;AAAA,UACd,qBAAqB;AAAA,UACrB,oBAAoB;AAAA,UACpB,YAAY;AAAA,UACZ,yBAAyB;AAAA,UACzB,mBAAmB;AAAA,QAAA;AAAA,QAErB,MAAM;AAAA,MAAA;AAAA,IAGV,KAAK;AACH,aAAO,MAAM,UAAU,MAAM,QAAQ,QAAQ,EAAE,GAAG,OAAO,OAAO,MAAM,MAAA;AAAA,IAExE,KAAK;AACH,aAAO,MAAM,eAAe,MAAM,aAAa,QAAQ,EAAE,GAAG,OAAO,YAAY,MAAM,WAAA;AAAA,IAEvF,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,gBAAgB,EAAE,GAAG,MAAM,gBAAgB,GAAG,MAAM,iBAAe;AAAA,IAExF,KAAK;AACH,aAAO,qBAAqB,OAAO,CAAC,cAAc;AAChD,wBAAgB,WAAW,MAAM,OAAO;AAAA,MAC1C,CAAC;AAAA,IAEH,KAAK;AACH,aAAO,qBAAqB,OAAO,CAAC,cAAc,iBAAiB,WAAW,MAAM,UAAU,CAAC;AAAA,IAEjG,KAAK;AACH,aAAO,qBAAqB,OAAO,0BAA0B;AAAA,IAE/D,KAAK;AACH,aAAO,qBAAqB,OAAO,gBAAgB;AAAA,IAErD,KAAK;AACH,aAAO,qBAAqB,OAAO,CAAC,cAAc;AAChD,sCAA8B,WAAW,MAAM,OAAO;AAAA,MACxD,CAAC;AAAA,EAAA;AAEP;ACxMO,MAAM,yBAAoD;AAAA,EAI/D,YAAY,eAAgC,2BAA2B;AAFvE,SAAmB,gCAAgB,IAAA;AAMnC,SAAA,WAAW,MAAuB,KAAK;AAEvC,SAAA,YAAY,CAAC,aAAuC;AAClD,WAAK,UAAU,IAAI,QAAQ;AAC3B,aAAO,MAAM;AACX,aAAK,UAAU,OAAO,QAAQ;AAAA,MAChC;AAAA,IACF;AAEA,SAAA,WAAW,CAAC,UAAiC;AAC3C,YAAM,YAAY,sBAAsB,KAAK,OAAO,KAAK;AACzD,UAAI,cAAc,KAAK,MAAO;AAC9B,WAAK,QAAQ;AACb,iBAAW,kBAAkB,CAAC,GAAG,KAAK,SAAS,EAAG,gBAAA;AAAA,IACpD;AAjBE,SAAK,QAAQ;AAAA,EACf;AAiBF;AAGO,MAAM,wBAAwB,CAAC,iBACpC,IAAI,yBAAyB,YAAY;ACvC3C,MAAM,yBAAyB,cAAsC,IAAI;AASlE,MAAM,0BAA0B,CAAC,UAAwC;AAC9E,QAAM,EAAE,WAAW,SAAA,IAAa;AAChC,6BAAQ,uBAAuB,UAAvB,EAAgC,OAAO,WAAY,UAAS;AACtE;AAGO,MAAM,qBAAqB,MAAuB;AACvD,QAAM,YAAY,WAAW,sBAAsB;AACnD,MAAI,cAAc,MAAM;AACtB,UAAM,IAAI,MAAM,iGAAiG;AAAA,EACnH;AACA,SAAO;AACT;AAGO,MAAM,6BAA6B,MAA8B,WAAW,sBAAsB;AAEzG,MAAM,qBAAqB,MAAM,MAAM;AAOhC,MAAM,wBAAwB,CACnC,WACA,UACA,sBACa;AACb,QAAM,YAAY,YAAY,UAAU,YAAY;AACpD,QAAM,oBAAoB;AAAA,IACxB,MAAO,YAAY,SAAS,UAAU,SAAA,CAAU,IAAK;AAAA,IACrD,CAAC,WAAW,UAAU,iBAAiB;AAAA,EAAA;AAEzC,SAAO,qBAAqB,WAAW,mBAAmB,iBAAiB;AAC7E;AAGO,MAAM,qBAAqB,CAAY,aAC5C,sBAAsB,mBAAA,GAAsB,QAAQ;ACzBtD,IAAI,wBAAwB;AA4C5B,MAAM,eAAe,CAAC,UAA0C,MAAM;AACtE,MAAM,yBAAyB,CAAC,UAAyD,MAAM;AAC/F,MAAM,mBAAmB,CAAC,UAAmC,MAAM;AACnE,MAAM,iBAAiB,CAAC,UAAiE,MAAM,cAAc;AAC7G,MAAM,iBAAiB,CAAC,UAAiE,MAAM;AAG/F,MAAM,sCAAsC,CAC1C,UACG;AACH,QAAM,EAAE,WAAW,GAAG,UAAA,IAAc;AACpC,QAAM,SAAS,sBAAsB,WAAW,YAAY;AAC5D,QAAM,mBAAmB,sBAAsB,WAAW,sBAAsB;AAChF,QAAM,wBAAwB,sBAAsB,WAAW,gBAAgB;AAC/E,QAAM,WAAW,sBAAsB,WAAW,cAAc;AAChE,QAAM,WAAW,sBAAsB,WAAW,cAAc;AAChE,QAAM,YAAY;AAAA,IAChB,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,qBAAqB,UAAU;AAAA,IAAA;AAAA,IAEjC,CAAC,QAAQ,kBAAkB,uBAAuB,UAAU,UAAU,SAAS;AAAA,EAAA;AAEjF,SAAO,oBAAC,gCAAA,EAAgC,GAAG,WAAW,UAAA,CAAsB;AAC9E;AAGA,MAAM,kCAAkC,CACtC,UAGG;AACH,QAAM,EAAE,eAAe,GAAG,UAAA,IAAc;AACxC,QAAM,WAAW,uBAAA;AAGjB,QAAM,SAAS,uBAAuB,CAAC,UAAU,cAAc,YAAY,KAAK,EAAE,MAAM;AACxF,QAAM,mBAAmB,uBAAuB,CAAC,UAAU,cAAc,YAAY,KAAK,EAAE,gBAAgB;AAC5G,QAAM,wBAAwB,uBAAuB,CAAC,UAAU,cAAc,YAAY,KAAK,EAAE,UAAU;AAC3G,QAAM,WAAW,uBAAuB,CAAC,UAAU,cAAc,YAAY,KAAK,EAAE,cAAc,QAAQ;AAC1G,QAAM,WAAW,uBAAuB,CAAC,UAAU,cAAc,YAAY,KAAK,EAAE,QAAQ;AAC5F,QAAM,sBAAsB;AAAA,IAC1B,CAAC,UAAyC;AACxC,YAAM,EAAE,YAAY;AACpB,UAAI,MAAM,SAAS,eAAgB,UAAS,QAAQ,WAAW,MAAM,OAAO,CAAC;AAAA,eACpE,MAAM,SAAS,eAAgB,UAAS,QAAQ,YAAY,EAAE,YAAY,MAAM,WAAA,CAAY,CAAC;AAAA,eAC7F,MAAM,SAAS,wBAAyB,UAAS,QAAQ,uBAAuB;AAAA,eAChF,MAAM,SAAS,gBAAiB,UAAS,QAAQ,aAAa;AAAA,UAClE,UAAS,QAAQ,yBAAyB,MAAM,OAAO,CAAC;AAAA,IAC/D;AAAA,IACA,CAAC,UAAU,aAAa;AAAA,EAAA;AAE1B,QAAM,YAAY;AAAA,IAChB,OAAO,EAAE,QAAQ,kBAAkB,uBAAuB,UAAU,UAAU;IAC9E,CAAC,QAAQ,kBAAkB,uBAAuB,UAAU,UAAU,mBAAmB;AAAA,EAAA;AAE3F,SAAO,oBAAC,gCAAA,EAAgC,GAAG,WAAW,UAAA,CAAsB;AAC9E;AAGA,MAAM,yCAAyC,CAC7C,UACG;AACH,QAAM,CAAC,YAAY,IAAI,SAAS,qBAAqB;AACrD,SAAO,oBAAC,qCAAA,EAAqC,GAAG,OAAO,WAAW,cAAc;AAClF;AAOO,MAAM,6BAA6B,CAAC,UAA2C;AACpF,QAAM,EAAE,eAAe,WAAW,GAAG,cAAc;AACnD,QAAM,EAAE,0BAAA,IAA8B,qBAAA;AACtC,QAAM,iBAAiB,iBAAiB;AACxC,MAAI,UAAW,QAAO,oBAAC,qCAAA,EAAqC,GAAG,WAAW,WAAsB;AAChG,MAAI,eAAgB,QAAO,oBAAC,mCAAiC,GAAG,WAAW,eAAe,gBAAgB;AAC1G,SAAO,oBAAC,wCAAA,EAAwC,GAAG,UAAA,CAAW;AAChE;AAEA,MAAM,iCAAiC,CAAC;AAAA,EACtC;AAAA,EACA;AAAA,EACA,uBAAuB;AAAA,EACvB;AACF,MAA2C;AACzC,QAAM,WAAW,uBAAA;AACjB,QAAM,EAAE,kCAAA,IAAsC,qBAAA;AAC9C,QAAM,EAAE,QAAQ,kBAAkB,uBAAuB,UAAU,aAAa;AAChF,QAAM,uBAAuB,aAAa,eAAe,aAAa;AACtE,QAAM,yBAAyB,OAAO,UAAU,mBAAmB;AACnE,yBAAuB,UAAU,UAAU;AAC3C,QAAM,0BAA0B,OAAO,oBAAoB;AAC3D,0BAAwB,UAAU;AAMlC,QAAM,uCAAuC,OAAO,iCAAiC;AACrF,uCAAqC,UAAU;AAC/C,YAAU,MAAM;AACd,6BAAyB;AACzB,QAAI,0BAA0B,KAAK,qCAAqC,SAAS;AAC/E,eAAS,qCAAqC,QAAQ,IAAI,CAAC;AAAA,IAC7D;AACA,WAAO,MAAM;AACX,+BAAyB;AACzB,UAAI,0BAA0B,KAAK,qCAAqC,SAAS;AAC/E,iBAAS,qCAAqC,QAAQ,KAAK,CAAC;AAAA,MAC9D;AAAA,IACF;AAAA,EACF,GAAG,CAAC,QAAQ,CAAC;AAIb,QAAM,eAAe,OAAO,SAAS;AACrC,eAAa,UAAU;AAKvB,QAAM,8BAA8B,UAAU,oBAAoB;AAClE,QAAM,CAAC,yBAAyB,0BAA0B,IAAI,SAAuC,CAAA,CAAE;AACvG,QAAM,kBAAkB,8BACnB,UAAU,kBACX;AAKJ,QAAM,0BAA0B,OAAO,EAAE,iBAAiB,6BAA6B;AACvF,0BAAwB,UAAU,EAAE,iBAAiB,4BAAA;AAErD,QAAM,yBAAyB,YAAY,CAAC,SAAuC;AACjF,QAAI,wBAAwB,QAAQ,6BAA6B;AAC/D,mBAAa,QAAQ,0BAA0B,IAAI;AAAA,IACrD,OAAO;AACL,iCAA2B,IAAI;AAAA,IACjC;AAAA,EACF,GAAG,CAAA,CAAE;AAEL,QAAM,oBAAoB;AAAA,IACxB,CAAC,YAAoB,WAA4C;AAC/D,YAAM,mBAAmB,OAAO,WAAA;AAChC,6BAAuB;AAAA,QACrB,GAAG,wBAAwB,QAAQ;AAAA,QACnC,EAAE,kBAAkB,YAAY,OAAA;AAAA,MAAO,CACxC;AACD,aAAO;AAAA,IACT;AAAA,IACA,CAAC,sBAAsB;AAAA,EAAA;AAGzB,QAAM,8BAA8B;AAAA,IAClC,CAAC,kBAA0B,WAAoC;AAC7D;AAAA,QACE,wBAAwB,QAAQ,gBAAgB;AAAA,UAAI,CAAC,WACnD,OAAO,qBAAqB,mBAAmB,EAAE,GAAG,QAAQ,WAAW;AAAA,QAAA;AAAA,MACzE;AAAA,IAEJ;AAAA,IACA,CAAC,sBAAsB;AAAA,EAAA;AAGzB,QAAM,uBAAuB;AAAA,IAC3B,CAAC,qBAA6B;AAC5B;AAAA,QACE,wBAAwB,QAAQ,gBAAgB;AAAA,UAC9C,CAAC,WAAW,OAAO,qBAAqB;AAAA,QAAA;AAAA,MAC1C;AAAA,IAEJ;AAAA,IACA,CAAC,sBAAsB;AAAA,EAAA;AAGzB,QAAM,uBAAuB,YAAY,MAAM;AAC7C,2BAAuB,CAAA,CAAE;AAAA,EAC3B,GAAG,CAAC,sBAAsB,CAAC;AAK3B,QAAM,aAAa;AAAA,IACjB,CAAC,YAAyC;AACxC,6BAAuB,QAAQ;AAAA,QAC7B,MAAM;AAAA,QACN,SAAS;AAAA,UACP,GAAG;AAAA,UACH,gBAAgB,OAAO,cAAc;AAAA,UACrC,sBAAsB,wBAAwB;AAAA,QAAA;AAAA,MAChD,CACD;AAAA,IACH;AAAA,IACA,CAAA;AAAA,EAAC;AAKH,QAAM,cAAc;AAAA,IAClB,CAAC,eAAwB;AACvB,6BAAuB,QAAQ,EAAE,MAAM,gBAAgB,YAAY;AAAA,IACrE;AAAA,IACA,CAAA;AAAA,EAAC;AAGH,QAAM,sBAAsB,OAAO,gBAAgB;AACnD,sBAAoB,UAAU;AAC9B,QAAM,yBAAyB,YAAY,MAAM;AAC/C,UAAM,OAAO,oBAAoB;AACjC,QAAI,SAAS,KAAM;AACnB,2BAAuB,QAAQ;AAAA,MAC7B,MAAM;AAAA,MACN,SAAS;AAAA,QACP,UAAU,KAAK;AAAA,QACf,YAAY,KAAK;AAAA,QACjB,QAAQ,KAAK;AAAA,QACb,QAAQ;AAAA,QACR,eAAe;AAAA,QACf,gBAAgB,OAAO,cAAc;AAAA,QACrC,sBAAsB,wBAAwB;AAAA,QAC9C,GAAI,KAAK,oBAAoB,SAAY,EAAE,iBAAiB,KAAK,oBAAoB,CAAA;AAAA,MAAC;AAAA,IACxF,CACD;AAAA,EACH,GAAG,CAAA,CAAE;AAEL,QAAM,2BAA2B;AAAA,IAC/B,CAAC,YAAiC;AAChC,6BAAuB,QAAQ,EAAE,MAAM,4BAA4B,SAAS;AAAA,IAC9E;AAAA,IACA,CAAA;AAAA,EAAC;AAMH,QAAM,gCAAgC,OAA2B,MAAS;AAC1E,QAAM,2BAA2B,UAAU;AAC3C,YAAU,MAAM;AACd,QAAI,WAAW,MAAM;AACnB,sBAAgB,0BAA0B,MAAM;AAChD,oCAA8B,UAAU;AACxC;AAAA,IACF;AACA,QACE,8BAA8B,YAAY,UAC1C,8BAA8B,YAAY,0BAC1C;AACA,wBAAkB,wBAAwB;AAAA,IAC5C;AACA,kCAA8B,UAAU;AAAA,EAC1C,GAAG,CAAC,QAAQ,wBAAwB,CAAC;AAGrC,QAAM,cAAc,YAAY,MAAM;AACpC,2BAAuB,QAAQ,EAAE,MAAM,gBAAA,CAAiB;AAAA,EAC1D,GAAG,CAAA,CAAE;AAGL,QAAM,wBAAwB,YAAY,MAAM;AAC9C,2BAAuB,QAAQ,EAAE,MAAM,wBAAA,CAAyB;AAAA,EAClE,GAAG,CAAA,CAAE;AAEL,QAAM,oBAAoB,YAAY,CAAC,YAAoB;AACzD,WAAO,aAAa,QAAQ,oBAAoB,OAAO;AAAA,EACzD,GAAG,CAAA,CAAE;AAEL,QAAM,kBAAkB,YAAY,CAAC,SAAiB;AACpD,iBAAa,QAAQ,kBAAkB,IAAI;AAAA,EAC7C,GAAG,CAAA,CAAE;AAEL,QAAM,eAAe,YAAY,CAAC,YAAoB,YAAkC;AACtF,WAAO,aAAa,QAAQ,eAAe,YAAY,OAAO;AAAA,EAChE,GAAG,CAAA,CAAE;AAEL,QAAM,mBAAmB,YAAY,MAAM;AACzC,iBAAa,QAAQ,mBAAA;AAAA,EACvB,GAAG,CAAA,CAAE;AAEL,QAAM,eAAe;AAAA,IACnB,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,mBAAmB,UAAU;AAAA,MAC7B;AAAA,MACA;AAAA,MACA,gBAAgB,UAAU;AAAA,MAC1B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,oBAAoB,UAAU;AAAA,MAC9B,sBAAsB,UAAU;AAAA,MAChC,+BAA+B,UAAU,iCAAiC;AAAA,MAC1E;AAAA,IAAA;AAAA,IAEF;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,MACV;AAAA,IAAA;AAAA,EACF;AAGF,6BAAQ,0BAA0B,UAA1B,EAAmC,OAAO,cAAe,UAAS;AAC5E;;;;;;;;;;;AC7YO,MAAM,0CAA0C,CAAC,UAAwD;AAC9G,QAAM,EAAE,SAAS,aAAA,IAAiB;AAClC,QAAM,EAAE,iBAAiB,6BAA6B,qBAAA,IAAyB,6BAAA;AAE/E,QAAM,oBAAoB,gBAAgB,QAAQ,CAAC,WAAW;AAC5D,UAAM,QAAQ,2BAA2B,QAAQ,KAAK,CAAC,cAAc,UAAU,SAAS,OAAO,UAAU;AACzG,WAAO,OAAO,oBAAoB,CAAC,EAAE,QAAQ,WAAW,MAAM,kBAAA,CAAmB,IAAI,CAAA;AAAA,EACvF,CAAC;AAED,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,WAAW,OAAO,aAAa,EAAE,CAAC,OAAO,eAAe,GAAG,kBAAkB,SAAS,GAAG;AAAA,MACpG,eAAa,GAAG,MAAM;AAAA,MAEtB,8BAAC,OAAA,EAAI,WAAW,OAAO,kBACrB,8BAAC,OAAA,EAAI,WAAW,OAAO,OACpB,4BAAkB,IAAI,CAAC,EAAE,QAAQ,gBAChC;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,kBAAkB,OAAO;AAAA,UACzB,QAAQ,OAAO;AAAA,UACf,eAAe,CAAC,eAAe,4BAA4B,OAAO,kBAAkB,UAAU;AAAA,UAC9F,QAAQ,MAAM,qBAAqB,OAAO,gBAAgB;AAAA,UAC1D,QAAQ,GAAG,MAAM,oBAAoB,OAAO,gBAAgB;AAAA,QAAA;AAAA,QALvD,OAAO;AAAA,MAAA,CAOf,GACH,EAAA,CACF;AAAA,IAAA;AAAA,EAAA;AAGN;"}
1
+ {"version":3,"file":"ConversationMessageInputComposerWidgets-CzQnpW0h.js","sources":["../../src/chat/store/agents-chat-state.ts","../../src/chat/store/conversation-error-type.ts","../../src/chat/store/merge-chat-messages.ts","../../src/chat/store/reduce-agents-chat-state.ts","../../src/chat/store/create-agents-chat-store.ts","../../src/chat/store/use-agents-chat-store.tsx","../../src/renderer/ConversationWidgetContext.tsx","../../src/chat/ConversationMessageInput/ConversationMessageInputComposerWidgets/ConversationMessageInputComposerWidgets.tsx"],"sourcesContent":["import type {\n AgentsClientError,\n AgentsConversation,\n AgentsConversationMessage,\n PostedMessage,\n StartedConversation,\n} from \"../../contract/conversation\";\nimport type { ChatMessage } from \"../chat-message\";\nimport type { CanvasCreatedEntity, CanvasSliceState } from \"../../renderer/canvas/canvas-reducers\";\nimport type { CanvasOpenRequest } from \"../../renderer/canvas/canvas-state\";\nimport type { ConversationErrorType } from \"./conversation-error-type\";\n\n/**\n * How an entry point outside the chat hands a job over to the chat that opens next (one generic opening\n * request): the first visible message, or an invisible start signal so the agent speaks first, the entry point the\n * start comes from, and a widget to mount without a message (a page handing over a tool). Set before the chat mounts,\n * so a reset keeps it; the chat clears each part once it consumed it.\n */\nexport interface AgentsChatOpeningRequest {\n /** The first visible owner message of the next started conversation. */\n userMessage: string | null;\n /** The invisible start signal of the next started conversation (an empty visible message carries it). */\n startSignalText: string | null;\n /** The entry point the start comes from; the server reopens that entry point's recent conversation instead. */\n entryPointKey: string | null;\n /** The canonical wire name of a deep-linkable widget the chat mounts once, without a message. */\n deepLinkedWidgetName: string | null;\n}\n\n/** The state of one chat instance. */\nexport interface AgentsChatState extends CanvasSliceState {\n /** The conversation shown; null for a cold chat until a start or the metadata read brings it. */\n conversation: AgentsConversation | null;\n /** Null until the first page or a send; ordered by `indexInConversation`, the optimistic message last. */\n messages: ChatMessage[] | null;\n /** A send is on its way. */\n conversationLoading: boolean;\n /** The last read or send for this conversation came back. */\n conversationLoaded: boolean;\n /** An older page exists: the scroll-up load stays armed. */\n hasMoreOlder: boolean;\n /** The agent works on a turn (the controller mirrors the derived activity here; read by the launcher). */\n aiThinking: boolean;\n error: ConversationErrorType | null;\n /** Seconds until the quota frees up again; set only while `error` is RATE_LIMIT. */\n rateLimitRetryAfterSeconds: number | null;\n /**\n * The conversation the newest metadata or page read asked for; null after a reset. A late answer for another\n * conversation — or one that lands after a reset — is dropped.\n */\n requestedConversationId: number | null;\n /** A start is on its way; no second start is sent meanwhile. */\n startingNewConversation: boolean;\n /** The token of the start on its way; its answer applies only while it is still the pending one. */\n pendingStartToken: number | null;\n /**\n * How many starts this chat instance sent — the source of `pendingStartToken`. Survives a reset (like\n * `canvasMountCount`): the store outlives a remount of the chat, so a token is never reused for another start.\n */\n startTokenCount: number;\n openingRequest: AgentsChatOpeningRequest;\n}\n\nexport const EMPTY_AGENTS_CHAT_OPENING_REQUEST: AgentsChatOpeningRequest = {\n userMessage: null,\n startSignalText: null,\n entryPointKey: null,\n deepLinkedWidgetName: null,\n};\n\nexport const INITIAL_AGENTS_CHAT_STATE: AgentsChatState = {\n conversation: null,\n messages: null,\n conversationLoading: false,\n conversationLoaded: false,\n hasMoreOlder: false,\n aiThinking: false,\n error: null,\n rateLimitRetryAfterSeconds: null,\n requestedConversationId: null,\n startingNewConversation: false,\n pendingStartToken: null,\n startTokenCount: 0,\n openingRequest: EMPTY_AGENTS_CHAT_OPENING_REQUEST,\n canvas: null,\n lastClosedCanvas: null,\n canvasMountCount: 0,\n};\n\n/**\n * What happens to a chat instance. The read and send events carry the port's answers (`AgentsConversationClient`);\n * the controller dispatches the `…Requested` event before it calls the port and the `…Received` / `…Failed` event\n * with the answer.\n */\nexport type AgentsChatEvent =\n /** A conversation switch, an empty chat, the chat's unmount: everything goes except the opening request and the two counters. */\n | { type: \"reset\" }\n | { type: \"conversationMetadataRequested\"; conversationId: number }\n | { type: \"conversationMetadataReceived\"; conversationId: number; conversation: AgentsConversation }\n | { type: \"conversationMetadataFailed\"; conversationId: number }\n | { type: \"messagesPageRequested\"; conversationId: number }\n /** `hasMoreOlder` null: a changed-messages read, which says nothing about older pages. */\n | {\n type: \"messagesPageReceived\";\n conversationId: number;\n messages: AgentsConversationMessage[];\n hasMoreOlder: boolean | null;\n }\n | { type: \"messagePostRequested\"; message: ChatMessage }\n | { type: \"messagePostReceived\"; conversationId: number; posted: PostedMessage }\n | { type: \"messagePostFailed\"; error: AgentsClientError }\n /** Takes the next start token (`pendingStartToken`); the controller reads it after the dispatch. */\n | { type: \"startRequested\"; message: ChatMessage }\n | { type: \"startReceived\"; startToken: number; started: StartedConversation }\n | { type: \"startFailed\"; error: AgentsClientError }\n | { type: \"errorSet\"; error: ConversationErrorType | null }\n | { type: \"aiThinkingSet\"; aiThinking: boolean }\n /** Sets the named parts of the opening request; the others stay. */\n | { type: \"openingRequestSet\"; openingRequest: Partial<AgentsChatOpeningRequest> }\n | { type: \"canvasOpened\"; request: CanvasOpenRequest }\n | { type: \"canvasClosed\"; byCustomer: boolean }\n | { type: \"canvasResetForNewTurn\" }\n | { type: \"canvasCleared\" }\n | { type: \"canvasCreatedEntityIdSet\"; created: CanvasCreatedEntity };\n","import type { AgentsClientError } from \"../../contract/conversation\";\n\n/**\n * The error card the chat shows. A plain object with string values (not a TypeScript `enum`), so the chat store, the\n * view and an app's older chat state share one vocabulary without a nominal type in between.\n */\nexport const ConversationErrorType = {\n AI_BUDGET: \"AI_BUDGET\",\n /**\n * HTTP 429 from an AI endpoint — a per-minute/hour/day usage quota was hit. Distinct from AI_BUDGET (monthly budget):\n * this one clears on its own after the Retry-After window.\n */\n RATE_LIMIT: \"RATE_LIMIT\",\n NETWORK_ERROR: \"NETWORK_ERROR\",\n CONVERSATION_NOT_FOUND: \"CONVERSATION_NOT_FOUND\",\n /**\n * The backend run FAILED (e.g. the model provider returned an error). The raw provider error is admin-only (never\n * shown here); the owner gets a generic \"something went wrong\" card.\n */\n AGENT_ERROR: \"AGENT_ERROR\",\n /**\n * The conversation is COMPLETED/CANCELLED and refuses further owner input. Set from the server's stable error code\n * `CONVERSATION_CLOSED` or by the chat's own pre-send guard; the error card owns the copy.\n */\n CONVERSATION_CLOSED: \"CONVERSATION_CLOSED\",\n} as const;\n\nexport type ConversationErrorType = (typeof ConversationErrorType)[keyof typeof ConversationErrorType];\n\n/**\n * The error card of a refused send (post or start), read from the port's error. Only the stable outcomes select a\n * dedicated card; every other refusal is a generic network error — the same classification the older chat applies to\n * the server's error codes (`AI_BUDGET_REACHED`, `RATE_LIMIT_EXCEEDED`, `CONVERSATION_CLOSED`).\n */\nexport const readConversationErrorTypeOfRefusedSend = (error: AgentsClientError): ConversationErrorType => {\n if (error.kind === \"budget\") return ConversationErrorType.AI_BUDGET;\n if (error.kind === \"rateLimit\") return ConversationErrorType.RATE_LIMIT;\n if (error.kind === \"closed\") return ConversationErrorType.CONVERSATION_CLOSED;\n return ConversationErrorType.NETWORK_ERROR;\n};\n","import type { ChatMessage } from \"../chat-message\";\n\n/**\n * Merges two message lists by `indexInConversation`, preferring `incoming` on a collision, sorted ascending by index.\n * Messages without an index (the optimistic owner message) cannot be matched, so they follow the indexed ones in order.\n * A start or post answer carries the whole list and a live read brings it again: concatenating would show every\n * message twice.\n */\nexport const mergeChatMessagesByIndex = (existing: ChatMessage[], incoming: ChatMessage[]): ChatMessage[] => {\n const messagesByIndex = new Map<number, ChatMessage>();\n const messagesWithoutIndex: ChatMessage[] = [];\n const collectMessage = (message: ChatMessage) => {\n if (message.indexInConversation != null) {\n messagesByIndex.set(message.indexInConversation, message);\n } else {\n messagesWithoutIndex.push(message);\n }\n };\n existing.forEach(collectMessage);\n incoming.forEach(collectMessage);\n const indexedMessages = Array.from(messagesByIndex.values()).sort(\n (first, second) => (first.indexInConversation ?? 0) - (second.indexInConversation ?? 0),\n );\n return [...indexedMessages, ...messagesWithoutIndex];\n};\n\n/**\n * Tags the messages of a send's answer: `fresh` when the id was not in the list before — the server just delivered it,\n * so its one-shot widgets may fire; a replayed message never fires them again.\n */\nexport const tagFreshChatMessages = (incoming: ChatMessage[], previousMessages: ChatMessage[]): ChatMessage[] => {\n const previousIds = new Set(previousMessages.map((message) => message.id).filter((id): id is number => id != null));\n return incoming.map((message) => ({ ...message, fresh: message.id != null && !previousIds.has(message.id) }));\n};\n\n/**\n * Merges a page of a keyset read (the newest page, an older page, the changed tail) into the loaded messages by index.\n * A message is `fresh` only when it is a live arrival: never shown before and newer than everything loaded — so the\n * streamed reply opens its canvas while a scroll-up page and the first page on open stay history. A message already\n * shown keeps its tag. A page of another conversation than the one shown replaces the list.\n */\nexport const mergeMessagesPage = (\n loadedMessages: ChatMessage[] | null,\n page: ChatMessage[],\n requestedConversationId: number,\n): ChatMessage[] => {\n const shownConversationId = loadedMessages?.find((message) => message.conversationId != null)?.conversationId;\n const replacesShownConversation = shownConversationId != null && shownConversationId !== requestedConversationId;\n const existingMessages = replacesShownConversation ? [] : (loadedMessages ?? []);\n const messagesByIndex = new Map<number, ChatMessage>();\n for (const existingMessage of existingMessages) {\n if (existingMessage.indexInConversation != null) {\n messagesByIndex.set(existingMessage.indexInConversation, existingMessage);\n }\n }\n const hadMessagesBeforeMerge = existingMessages.length > 0;\n const highestShownIndex = Math.max(-1, ...existingMessages.map((message) => message.indexInConversation ?? -1));\n for (const incomingMessage of page) {\n if (incomingMessage.indexInConversation == null) continue;\n const previousMessage = messagesByIndex.get(incomingMessage.indexInConversation);\n const isLiveArrival =\n hadMessagesBeforeMerge && previousMessage == null && incomingMessage.indexInConversation > highestShownIndex;\n messagesByIndex.set(incomingMessage.indexInConversation, {\n ...incomingMessage,\n fresh: previousMessage?.fresh ?? isLiveArrival,\n });\n }\n return Array.from(messagesByIndex.values()).sort(\n (first, second) => (first.indexInConversation ?? 0) - (second.indexInConversation ?? 0),\n );\n};\n","import {\n applyClearCanvas,\n applyCloseCanvas,\n applyOpenCanvas,\n applyResetCanvasForNewTurn,\n applySetCanvasCreatedEntityId,\n} from \"../../renderer/canvas/canvas-reducers\";\nimport type { AgentsClientError } from \"../../contract/conversation\";\nimport type { ChatMessage } from \"../chat-message\";\nimport { type AgentsChatEvent, type AgentsChatState, INITIAL_AGENTS_CHAT_STATE } from \"./agents-chat-state\";\nimport { ConversationErrorType, readConversationErrorTypeOfRefusedSend } from \"./conversation-error-type\";\nimport { mergeChatMessagesByIndex, mergeMessagesPage, tagFreshChatMessages } from \"./merge-chat-messages\";\n\n/** The error card and the quota wait of a refused send. */\nconst withRefusedSendError = (state: AgentsChatState, error: AgentsClientError): AgentsChatState => {\n const conversationErrorType = readConversationErrorTypeOfRefusedSend(error);\n return {\n ...state,\n error: conversationErrorType,\n rateLimitRetryAfterSeconds:\n conversationErrorType === ConversationErrorType.RATE_LIMIT ? (error.retryAfterSeconds ?? null) : null,\n };\n};\n\n/** The messages a send's answer brings, merged over the loaded ones without the optimistic message (the last one). */\nconst mergeSendAnswer = (loadedMessages: ChatMessage[] | null, answerMessages: ChatMessage[]): ChatMessage[] => {\n const messagesWithoutOptimisticMessage = loadedMessages ? loadedMessages.slice(0, loadedMessages.length - 1) : [];\n return mergeChatMessagesByIndex(\n messagesWithoutOptimisticMessage,\n tagFreshChatMessages(answerMessages, messagesWithoutOptimisticMessage),\n );\n};\n\n/** The canvas transitions mutate the fields of the object they get (`canvas-reducers.ts`); this keeps the state immutable. */\nconst withCanvasTransition = (\n state: AgentsChatState,\n applyCanvasTransition: (nextState: AgentsChatState) => void,\n): AgentsChatState => {\n const nextState = { ...state };\n applyCanvasTransition(nextState);\n const changed =\n nextState.canvas !== state.canvas ||\n nextState.lastClosedCanvas !== state.lastClosedCanvas ||\n nextState.canvasMountCount !== state.canvasMountCount;\n return changed ? nextState : state;\n};\n\n/**\n * The chat store's reducer: plain functions over the contract types. Each case is the one of the older\n * chat state (a Redux slice and its cases) it replaces, reading the port's answers instead of the\n * generated client's actions; the replay spec feeds both the same recorded sequence.\n */\nexport const reduceAgentsChatState = (state: AgentsChatState, event: AgentsChatEvent): AgentsChatState => {\n switch (event.type) {\n case \"reset\":\n // The opening request is set from outside before the chat mounts (a cold chat resets as it comes up); the canvas\n // mount count and the start token count are monotonic sources of identities: all three survive.\n return {\n ...INITIAL_AGENTS_CHAT_STATE,\n openingRequest: state.openingRequest,\n canvasMountCount: state.canvasMountCount,\n startTokenCount: state.startTokenCount,\n };\n\n case \"conversationMetadataRequested\":\n case \"messagesPageRequested\":\n return state.requestedConversationId === event.conversationId\n ? state\n : { ...state, requestedConversationId: event.conversationId };\n\n case \"conversationMetadataReceived\":\n // Dropped after a reset or when another conversation was asked for since: a late answer would put the old\n // conversation back, and the next send would post into it instead of starting a new one.\n if (state.requestedConversationId === null || state.requestedConversationId !== event.conversationId) {\n return state;\n }\n return { ...state, conversation: event.conversation, conversationLoaded: true };\n\n case \"conversationMetadataFailed\":\n // A metadata read is best-effort: the chat stays as it is.\n return { ...state, conversationLoaded: true };\n\n case \"messagesPageReceived\": {\n if (state.requestedConversationId === null || state.requestedConversationId !== event.conversationId) {\n return state;\n }\n if (state.conversation !== null && state.conversation.id !== event.conversationId) {\n return state;\n }\n return {\n ...state,\n messages: mergeMessagesPage(state.messages, event.messages, event.conversationId),\n hasMoreOlder: event.hasMoreOlder ?? state.hasMoreOlder,\n conversationLoaded: true,\n };\n }\n\n case \"messagePostRequested\":\n return {\n ...state,\n conversationLoading: true,\n conversationLoaded: false,\n aiThinking: true,\n error: null,\n rateLimitRetryAfterSeconds: null,\n messages: [...(state.messages ?? []), event.message],\n };\n\n case \"messagePostReceived\":\n if (event.conversationId !== state.conversation?.id) {\n return state;\n }\n // The reply arrives through live updates, not in this answer: `aiThinking` stays as it is.\n return {\n ...state,\n messages: mergeSendAnswer(state.messages, event.posted.messages),\n conversationLoading: false,\n conversationLoaded: true,\n error: null,\n };\n\n case \"messagePostFailed\":\n return withRefusedSendError(\n { ...state, conversationLoading: false, conversationLoaded: true, aiThinking: false },\n event.error,\n );\n\n case \"startRequested\":\n return {\n ...state,\n conversation: null,\n conversationLoading: true,\n conversationLoaded: false,\n aiThinking: true,\n error: null,\n rateLimitRetryAfterSeconds: null,\n startingNewConversation: true,\n startTokenCount: state.startTokenCount + 1,\n pendingStartToken: state.startTokenCount + 1,\n // A signal-only start (an empty visible message carries the start signal) seeds no empty bubble.\n messages: event.message.message ? [event.message] : [],\n };\n\n case \"startReceived\": {\n if (event.startToken !== state.pendingStartToken) {\n return state;\n }\n const { started } = event;\n if (started.reopenedExisting) {\n // The recent conversation of the start's entry point: nothing was appended, no turn started. Its messages are\n // not in the answer — the controller reads its newest page — so the optimistic bubble goes.\n return {\n ...state,\n conversation: started.conversation,\n messages: [],\n conversationLoading: false,\n conversationLoaded: true,\n aiThinking: false,\n startingNewConversation: false,\n pendingStartToken: null,\n };\n }\n // The reply arrives through live updates: `aiThinking` stays on.\n return {\n ...state,\n conversation: started.conversation,\n messages: mergeSendAnswer(state.messages, started.messages),\n conversationLoading: false,\n conversationLoaded: true,\n startingNewConversation: false,\n pendingStartToken: null,\n };\n }\n\n case \"startFailed\":\n return withRefusedSendError(\n {\n ...state,\n conversation: null,\n conversationLoading: false,\n conversationLoaded: true,\n aiThinking: false,\n startingNewConversation: false,\n pendingStartToken: null,\n },\n event.error,\n );\n\n case \"errorSet\":\n return state.error === event.error ? state : { ...state, error: event.error };\n\n case \"aiThinkingSet\":\n return state.aiThinking === event.aiThinking ? state : { ...state, aiThinking: event.aiThinking };\n\n case \"openingRequestSet\":\n return { ...state, openingRequest: { ...state.openingRequest, ...event.openingRequest } };\n\n case \"canvasOpened\":\n return withCanvasTransition(state, (nextState) => {\n applyOpenCanvas(nextState, event.request);\n });\n\n case \"canvasClosed\":\n return withCanvasTransition(state, (nextState) => applyCloseCanvas(nextState, event.byCustomer));\n\n case \"canvasResetForNewTurn\":\n return withCanvasTransition(state, applyResetCanvasForNewTurn);\n\n case \"canvasCleared\":\n return withCanvasTransition(state, applyClearCanvas);\n\n case \"canvasCreatedEntityIdSet\":\n return withCanvasTransition(state, (nextState) => {\n applySetCanvasCreatedEntityId(nextState, event.created);\n });\n }\n};\n","import { type AgentsChatEvent, type AgentsChatState, INITIAL_AGENTS_CHAT_STATE } from \"./agents-chat-state\";\nimport { reduceAgentsChatState } from \"./reduce-agents-chat-state\";\n\n/**\n * The state handle of one chat instance. The app creates one per chat (host application: one per agent\n * window, created before the window's chat mounts) and releases it with the chat; the chat and the app's code outside\n * the chat read and dispatch through the same handle. React reads it through `useAgentsChatSelector`.\n */\nexport interface AgentsChatStore {\n getState: () => AgentsChatState;\n /** Calls the listener after every state change; returns the unsubscribe. */\n subscribe: (listener: () => void) => () => void;\n dispatch: (event: AgentsChatEvent) => void;\n}\n\n/** The plain implementation of `AgentsChatStore`: one state object, replaced by the reducer on every event. */\nexport class AgentsChatStateContainer implements AgentsChatStore {\n protected state: AgentsChatState;\n protected readonly listeners = new Set<() => void>();\n\n constructor(initialState: AgentsChatState = INITIAL_AGENTS_CHAT_STATE) {\n this.state = initialState;\n }\n\n getState = (): AgentsChatState => this.state;\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n dispatch = (event: AgentsChatEvent): void => {\n const nextState = reduceAgentsChatState(this.state, event);\n if (nextState === this.state) return;\n this.state = nextState;\n for (const notifyListener of [...this.listeners]) notifyListener();\n };\n}\n\n/** Creates the state handle of one chat instance. */\nexport const createAgentsChatStore = (initialState?: AgentsChatState): AgentsChatStore =>\n new AgentsChatStateContainer(initialState);\n","import { createContext, type ReactNode, useCallback, useContext, useSyncExternalStore } from \"react\";\nimport type { AgentsChatState } from \"./agents-chat-state\";\nimport type { AgentsChatStore } from \"./create-agents-chat-store\";\n\nconst AgentsChatStoreContext = createContext<AgentsChatStore | null>(null);\n\nexport interface AgentsChatStoreProviderProps {\n /** The state handle of the chat below (the app creates and releases it). */\n chatStore: AgentsChatStore;\n children?: ReactNode;\n}\n\n/** Puts one chat instance's state handle in reach of the chat and of the app's components inside it. */\nexport const AgentsChatStoreProvider = (props: AgentsChatStoreProviderProps) => {\n const { chatStore, children } = props;\n return <AgentsChatStoreContext.Provider value={chatStore}>{children}</AgentsChatStoreContext.Provider>;\n};\n\n/** The state handle of the chat this component renders in; throws outside `AgentsChatStoreProvider`. */\nexport const useAgentsChatStore = (): AgentsChatStore => {\n const chatStore = useContext(AgentsChatStoreContext);\n if (chatStore === null) {\n throw new Error(\"A chat component rendered outside AgentsChatStoreProvider: the app has to mount its chat store.\");\n }\n return chatStore;\n};\n\n/** The state handle of the chat this component renders in, or null outside a chat. */\nexport const useOptionalAgentsChatStore = (): AgentsChatStore | null => useContext(AgentsChatStoreContext);\n\nconst subscribeToNothing = () => () => undefined;\n\n/**\n * Reads one value of a chat instance's state and re-renders when it changes. The selector must return a value that\n * keeps its identity while the state does not change (a state field, not a new object). Without a store it returns\n * `valueWithoutStore`.\n */\nexport const useAgentsChatSelector = <Selected,>(\n chatStore: AgentsChatStore | null | undefined,\n selector: (state: AgentsChatState) => Selected,\n valueWithoutStore?: Selected,\n): Selected => {\n const subscribe = chatStore ? chatStore.subscribe : subscribeToNothing;\n const readSelectedValue = useCallback(\n () => (chatStore ? selector(chatStore.getState()) : (valueWithoutStore as Selected)),\n [chatStore, selector, valueWithoutStore],\n );\n return useSyncExternalStore(subscribe, readSelectedValue, readSelectedValue);\n};\n\n/** Reads one value of the state of the chat this component renders in. */\nexport const useAgentsChatState = <Selected,>(selector: (state: AgentsChatState) => Selected): Selected =>\n useAgentsChatSelector(useAgentsChatStore(), selector);\n","import React, { ReactNode, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useAgentsEnvironment, useAgentsStateDispatch, useAgentsStateSelector } from \"../provider/AgentsProvider\";\nimport type { ConversationWidgetStatePartition } from \"./conversation-widget-state-partition\";\nimport { createAgentsChatStore } from \"../chat/store/create-agents-chat-store\";\nimport type { AgentsChatEvent } from \"../chat/store/agents-chat-state\";\nimport type { AgentsChatStore } from \"../chat/store/create-agents-chat-store\";\nimport { useAgentsChatSelector } from \"../chat/store/use-agents-chat-store\";\nimport type { CanvasState, LastClosedCanvas } from \"./canvas/canvas-state\";\nimport { CANVAS_VIABLE_MIN_WIDTH } from \"../widgets/CanvasWidgetCard/use-canvas-viable\";\nimport { ConversationComposerWidget } from \"./conversation-composer-widget\";\nimport type { CanvasCreatedEntity } from \"./canvas/canvas-reducers\";\nimport { clearStoredCanvas, storeOpenCanvas } from \"./canvas/canvasStorage\";\nimport {\n type CanvasOpenRequestFromOpener,\n type ConversationWidgetCallbacks,\n ConversationWidgetContext,\n defaultConversationWidgetCallbacks,\n type InjectSignalOptions,\n} from \"./ConversationWidgetCallbacksContext\";\n\n// The callbacks, their context and the chat-free hosts live in `ConversationWidgetCallbacksContext.tsx`; this module\n// adds the provider that reads the chat's state (the package chat store or an app's partition) and re-exports the rest.\nexport * from \"./ConversationWidgetCallbacksContext\";\n\n// Number of mounted agentic chat surfaces (widget, full-page chat, dashboard). Drives the app's \"a chat surface is\n// open\" action (`buildChatSurfaceOpenChangedAction`, e.g. a flag of the app's own flows): true while ≥1 is open.\n// Module-level so multiple providers share one count.\nlet agenticChatMountCount = 0;\n\nexport interface ConversationWidgetProviderProps {\n children: ReactNode;\n callbacks: Partial<ConversationWidgetCallbacks>;\n /**\n * The chat slice partition this provider's canvas lives in. The shell is shared by the two chat doors, so the door\n * says which partition: `AgentChat` passes `AgentChatInstance`; the AI-Extensions chat, every story and every spec\n * keep the default. A prop, not a callback — `callbacks` is `Partial`, and the partition is not optional.\n */\n sliceInstance?: ConversationWidgetStatePartition;\n /**\n * The package chat store of the chat: the agent chat passes its window's store and the provider reads\n * and writes the canvas there. Without it the provider reads a partition of the app's own chat state\n * (`sliceInstance`, else the environment's `defaultChatStatePartition`).\n */\n chatStore?: AgentsChatStore;\n /**\n * False for a host that renders the chat without the split (`ConversationView.disableSplitView`): there is nowhere\n * to open a canvas, so every open request is ignored with reason `noSurface`. Default true.\n */\n hostHasCanvasSurface?: boolean;\n}\n\n/** The canvas transitions the provider dispatches — the canvas events of the package chat store. */\ntype ConversationWidgetCanvasEvent = Extract<\n AgentsChatEvent,\n { type: \"canvasOpened\" | \"canvasClosed\" | \"canvasResetForNewTurn\" | \"canvasCleared\" | \"canvasCreatedEntityIdSet\" }\n>;\n\n/** What the provider reads from the chat's state and how it writes a canvas transition back. */\ninterface ConversationWidgetChatState {\n canvas: CanvasState | null;\n lastClosedCanvas: LastClosedCanvas | null;\n isConversationRunning: boolean;\n runState: string | null | undefined;\n messages: ConversationWidgetCallbacks[\"messages\"];\n dispatchCanvasEvent: (event: ConversationWidgetCanvasEvent) => void;\n}\n\ntype ConversationWidgetProviderBodyProps = Omit<ConversationWidgetProviderProps, \"sliceInstance\" | \"chatStore\"> & {\n chatState: ConversationWidgetChatState;\n};\n\nconst selectCanvas = (state: { canvas: CanvasState | null }) => state.canvas;\nconst selectLastClosedCanvas = (state: { lastClosedCanvas: LastClosedCanvas | null }) => state.lastClosedCanvas;\nconst selectAiThinking = (state: { aiThinking: boolean }) => state.aiThinking;\nconst selectRunState = (state: { conversation: { runState?: string | null } | null }) => state.conversation?.runState;\nconst selectMessages = (state: { messages: ConversationWidgetCallbacks[\"messages\"] }) => state.messages;\n\n/** The provider over the package chat store of the chat. */\nconst ChatStoreConversationWidgetProvider = (\n props: Omit<ConversationWidgetProviderProps, \"sliceInstance\" | \"chatStore\"> & { chatStore: AgentsChatStore },\n) => {\n const { chatStore, ...bodyProps } = props;\n const canvas = useAgentsChatSelector(chatStore, selectCanvas);\n const lastClosedCanvas = useAgentsChatSelector(chatStore, selectLastClosedCanvas);\n const isConversationRunning = useAgentsChatSelector(chatStore, selectAiThinking);\n const runState = useAgentsChatSelector(chatStore, selectRunState);\n const messages = useAgentsChatSelector(chatStore, selectMessages);\n const chatState = useMemo<ConversationWidgetChatState>(\n () => ({\n canvas,\n lastClosedCanvas,\n isConversationRunning,\n runState,\n messages,\n dispatchCanvasEvent: chatStore.dispatch,\n }),\n [canvas, lastClosedCanvas, isConversationRunning, runState, messages, chatStore],\n );\n return <ConversationWidgetProviderBody {...bodyProps} chatState={chatState} />;\n};\n\n/** The provider over a partition of the older chat state (the AI-Extensions chat, stories, specs). */\nconst SliceConversationWidgetProvider = (\n props: Omit<ConversationWidgetProviderProps, \"sliceInstance\" | \"chatStore\"> & {\n sliceInstance: ConversationWidgetStatePartition;\n },\n) => {\n const { sliceInstance, ...bodyProps } = props;\n const dispatch = useAgentsStateDispatch();\n // One selector per field, not one returning an object, so an unrelated store change does not re-render every widget\n // through a fresh object identity.\n const canvas = useAgentsStateSelector((state) => sliceInstance.selectState(state).canvas);\n const lastClosedCanvas = useAgentsStateSelector((state) => sliceInstance.selectState(state).lastClosedCanvas);\n const isConversationRunning = useAgentsStateSelector((state) => sliceInstance.selectState(state).aiThinking);\n const runState = useAgentsStateSelector((state) => sliceInstance.selectState(state).conversation?.runState);\n const messages = useAgentsStateSelector((state) => sliceInstance.selectState(state).messages);\n const dispatchCanvasEvent = useCallback(\n (event: ConversationWidgetCanvasEvent) => {\n const { actions } = sliceInstance;\n if (event.type === \"canvasOpened\") dispatch(actions.openCanvas(event.request));\n else if (event.type === \"canvasClosed\") dispatch(actions.closeCanvas({ byCustomer: event.byCustomer }));\n else if (event.type === \"canvasResetForNewTurn\") dispatch(actions.resetCanvasForNewTurn());\n else if (event.type === \"canvasCleared\") dispatch(actions.clearCanvas());\n else dispatch(actions.setCanvasCreatedEntityId(event.created));\n },\n [dispatch, sliceInstance],\n );\n const chatState = useMemo<ConversationWidgetChatState>(\n () => ({ canvas, lastClosedCanvas, isConversationRunning, runState, messages, dispatchCanvasEvent }),\n [canvas, lastClosedCanvas, isConversationRunning, runState, messages, dispatchCanvasEvent],\n );\n return <ConversationWidgetProviderBody {...bodyProps} chatState={chatState} />;\n};\n\n/** The provider over a chat store of its own — a host that brings neither a chat store nor a partition (a story). */\nconst OwnChatStoreConversationWidgetProvider = (\n props: Omit<ConversationWidgetProviderProps, \"sliceInstance\" | \"chatStore\">,\n) => {\n const [ownChatStore] = useState(createAgentsChatStore);\n return <ChatStoreConversationWidgetProvider {...props} chatStore={ownChatStore} />;\n};\n\n/**\n * The widget callbacks of one chat, the canvas model included. Reads the chat's state from the package chat store when\n * the host passes one (`chatStore`), else from a partition of the app's own chat state (`sliceInstance`, or the\n * environment's `defaultChatStatePartition` — host application: the AI-Extensions chat), else from a store of its own.\n */\nexport const ConversationWidgetProvider = (props: ConversationWidgetProviderProps) => {\n const { sliceInstance, chatStore, ...bodyProps } = props;\n const { defaultChatStatePartition } = useAgentsEnvironment();\n const statePartition = sliceInstance ?? defaultChatStatePartition;\n if (chatStore) return <ChatStoreConversationWidgetProvider {...bodyProps} chatStore={chatStore} />;\n if (statePartition) return <SliceConversationWidgetProvider {...bodyProps} sliceInstance={statePartition} />;\n return <OwnChatStoreConversationWidgetProvider {...bodyProps} />;\n};\n\nconst ConversationWidgetProviderBody = ({\n children,\n callbacks,\n hostHasCanvasSurface = true,\n chatState,\n}: ConversationWidgetProviderBodyProps) => {\n const dispatch = useAgentsStateDispatch();\n const { buildChatSurfaceOpenChangedAction } = useAgentsEnvironment();\n const { canvas, lastClosedCanvas, isConversationRunning, runState, messages } = chatState;\n const isConversationClosed = runState === \"COMPLETED\" || runState === \"CANCELLED\";\n const dispatchCanvasEventRef = useRef(chatState.dispatchCanvasEvent);\n dispatchCanvasEventRef.current = chatState.dispatchCanvasEvent;\n const hostHasCanvasSurfaceRef = useRef(hostHasCanvasSurface);\n hostHasCanvasSurfaceRef.current = hostHasCanvasSurface;\n\n // An agentic chat surface is open: the app hears it through its action (e.g. a flag every connect/create/verify flow\n // launched from inside the chat reads to stay in-widget instead of navigating away).\n // Set here (not at the connect button) so it also covers the verify path, where there is no connect click.\n // Ref-counted so concurrently-mounted chat surfaces don't clear each other's flag.\n const buildChatSurfaceOpenChangedActionRef = useRef(buildChatSurfaceOpenChangedAction);\n buildChatSurfaceOpenChangedActionRef.current = buildChatSurfaceOpenChangedAction;\n useEffect(() => {\n agenticChatMountCount += 1;\n if (agenticChatMountCount === 1 && buildChatSurfaceOpenChangedActionRef.current) {\n dispatch(buildChatSurfaceOpenChangedActionRef.current(true));\n }\n return () => {\n agenticChatMountCount -= 1;\n if (agenticChatMountCount === 0 && buildChatSurfaceOpenChangedActionRef.current) {\n dispatch(buildChatSurfaceOpenChangedActionRef.current(false));\n }\n };\n }, [dispatch]);\n\n // Mirror the latest callbacks in a ref so the exposed functions stay stable across\n // renders even if the parent passes a fresh `callbacks` object every render.\n const callbacksRef = useRef(callbacks);\n callbacksRef.current = callbacks;\n\n // Composer-widget ownership — controlled when the host supplies `composerWidgets` (the builder page, click-bridge\n // F), otherwise uncontrolled: the provider owns the state so a descendant (e.g. an app's editor drawer) can\n // mutate it directly. See ConversationWidgetCallbacks.\n const isComposerWidgetsControlled = callbacks.composerWidgets !== undefined;\n const [internalComposerWidgets, setInternalComposerWidgets] = useState<ConversationComposerWidget[]>([]);\n const composerWidgets = isComposerWidgetsControlled\n ? (callbacks.composerWidgets as ConversationComposerWidget[])\n : internalComposerWidgets;\n\n // Mirrors the latest resolved composerWidgets + controlled flag so the mutator callbacks below can compute the\n // next array off REAL current state while keeping stable identities across renders ([] deps) — same trick as\n // `callbacksRef` above.\n const composerWidgetsStateRef = useRef({ composerWidgets, isComposerWidgetsControlled });\n composerWidgetsStateRef.current = { composerWidgets, isComposerWidgetsControlled };\n\n const publishComposerWidgets = useCallback((next: ConversationComposerWidget[]) => {\n if (composerWidgetsStateRef.current.isComposerWidgetsControlled) {\n callbacksRef.current.onComposerWidgetsChange?.(next);\n } else {\n setInternalComposerWidgets(next);\n }\n }, []);\n\n const addComposerWidget = useCallback(\n (widgetName: string, fields: Record<string, unknown>): string => {\n const composerWidgetId = crypto.randomUUID();\n publishComposerWidgets([\n ...composerWidgetsStateRef.current.composerWidgets,\n { composerWidgetId, widgetName, fields },\n ]);\n return composerWidgetId;\n },\n [publishComposerWidgets],\n );\n\n const replaceComposerWidgetFields = useCallback(\n (composerWidgetId: string, fields: Record<string, unknown>) => {\n publishComposerWidgets(\n composerWidgetsStateRef.current.composerWidgets.map((widget) =>\n widget.composerWidgetId === composerWidgetId ? { ...widget, fields } : widget,\n ),\n );\n },\n [publishComposerWidgets],\n );\n\n const removeComposerWidget = useCallback(\n (composerWidgetId: string) => {\n publishComposerWidgets(\n composerWidgetsStateRef.current.composerWidgets.filter(\n (widget) => widget.composerWidgetId !== composerWidgetId,\n ),\n );\n },\n [publishComposerWidgets],\n );\n\n const clearComposerWidgets = useCallback(() => {\n publishComposerWidgets([]);\n }, [publishComposerWidgets]);\n\n // The one way to open a canvas (all four origins). The provider supplies what only it knows — the split's viability\n // (measured on the window, like `useCanvasViable`) and whether this host has a canvas surface — and the reducer\n // applies the opening rule. Ignored requests change nothing.\n const openCanvas = useCallback(\n (request: CanvasOpenRequestFromOpener) => {\n dispatchCanvasEventRef.current({\n type: \"canvasOpened\",\n request: {\n ...request,\n viewportViable: window.innerWidth >= CANVAS_VIABLE_MIN_WIDTH,\n hostHasCanvasSurface: hostHasCanvasSurfaceRef.current,\n },\n });\n },\n [],\n );\n\n // Close the open canvas; it stays re-openable as `lastClosedCanvas`. `byCustomer` = the canvas's own close control,\n // which vetoes a live re-delivery of the same identity until the next send / click / page hand-over.\n const closeCanvas = useCallback(\n (byCustomer: boolean) => {\n dispatchCanvasEventRef.current({ type: \"canvasClosed\", byCustomer });\n },\n [],\n );\n\n const lastClosedCanvasRef = useRef(lastClosedCanvas);\n lastClosedCanvasRef.current = lastClosedCanvas;\n const reopenLastClosedCanvas = useCallback(() => {\n const last = lastClosedCanvasRef.current;\n if (last === null) return;\n dispatchCanvasEventRef.current({\n type: \"canvasOpened\",\n request: {\n canvasId: last.canvasId,\n instanceId: last.instanceId,\n anchor: last.anchor,\n origin: \"cardClick\",\n justDelivered: false,\n viewportViable: window.innerWidth >= CANVAS_VIABLE_MIN_WIDTH,\n hostHasCanvasSurface: hostHasCanvasSurfaceRef.current,\n ...(last.createdEntityId !== undefined ? { createdEntityId: last.createdEntityId } : {}),\n },\n });\n }, []);\n\n const setCanvasCreatedEntityId = useCallback(\n (created: CanvasCreatedEntity) => {\n dispatchCanvasEventRef.current({ type: \"canvasCreatedEntityIdSet\", created });\n },\n [],\n );\n\n // The pointer of the OPEN canvas is remembered per conversation for a reload (`canvasStorage.ts`), for any\n // lifetime. Cleared when the canvas closes INSIDE the same conversation; a conversation switch clears the slice too,\n // but the LEFT conversation keeps its entry so coming back restores it.\n const storedCanvasConversationIdRef = useRef<number | undefined>(undefined);\n const conversationIdForStorage = callbacks.conversationId;\n useEffect(() => {\n if (canvas !== null) {\n storeOpenCanvas(conversationIdForStorage, canvas);\n storedCanvasConversationIdRef.current = conversationIdForStorage;\n return;\n }\n if (\n storedCanvasConversationIdRef.current !== undefined &&\n storedCanvasConversationIdRef.current === conversationIdForStorage\n ) {\n clearStoredCanvas(conversationIdForStorage);\n }\n storedCanvasConversationIdRef.current = undefined;\n }, [canvas, conversationIdForStorage]);\n\n // A conversation switch forgets the canvas and the last closed one (the LEFT conversation keeps its stored pointer).\n const resetCanvas = useCallback(() => {\n dispatchCanvasEventRef.current({ type: \"canvasCleared\" });\n }, []);\n\n // The SEND boundary: a turn canvas is over for good, a pinned one stays (`canvas-reducers.ts`).\n const resetCanvasForNewTurn = useCallback(() => {\n dispatchCanvasEventRef.current({ type: \"canvasResetForNewTurn\" });\n }, []);\n\n const sendMessageToChat = useCallback((message: string) => {\n return callbacksRef.current.sendMessageToChat?.(message);\n }, []);\n\n const prefillComposer = useCallback((text: string) => {\n callbacksRef.current.prefillComposer?.(text);\n }, []);\n\n const injectSignal = useCallback((signalText: string, options?: InjectSignalOptions) => {\n return callbacksRef.current.injectSignal?.(signalText, options);\n }, []);\n\n const minimizeChatHost = useCallback(() => {\n callbacksRef.current.minimizeChatHost?.();\n }, []);\n\n const contextValue = useMemo<ConversationWidgetCallbacks>(\n () => ({\n canvas,\n hostHasCanvasSurface,\n lastClosedCanvas,\n openCanvas,\n closeCanvas,\n reopenLastClosedCanvas,\n setCanvasCreatedEntityId,\n resetCanvas,\n resetCanvasForNewTurn,\n sendMessageToChat,\n prefillComposer,\n injectSignal,\n minimizeChatHost,\n chatAgentSpaceKey: callbacks.chatAgentSpaceKey,\n isConversationRunning,\n isConversationClosed,\n conversationId: callbacks.conversationId,\n composerWidgets,\n addComposerWidget,\n replaceComposerWidgetFields,\n removeComposerWidget,\n clearComposerWidgets,\n onOpenConversation: callbacks.onOpenConversation,\n onSwitchConversation: callbacks.onSwitchConversation,\n isOnboardingSetupConversation: callbacks.isOnboardingSetupConversation ?? false,\n messages,\n }),\n [\n canvas,\n hostHasCanvasSurface,\n lastClosedCanvas,\n openCanvas,\n closeCanvas,\n reopenLastClosedCanvas,\n setCanvasCreatedEntityId,\n resetCanvas,\n resetCanvasForNewTurn,\n sendMessageToChat,\n prefillComposer,\n injectSignal,\n minimizeChatHost,\n callbacks.chatAgentSpaceKey,\n isConversationRunning,\n isConversationClosed,\n callbacks.conversationId,\n composerWidgets,\n addComposerWidget,\n replaceComposerWidgetFields,\n removeComposerWidget,\n clearComposerWidgets,\n callbacks.onOpenConversation,\n callbacks.onSwitchConversation,\n callbacks.isOnboardingSetupConversation,\n messages,\n ],\n );\n\n return <ConversationWidgetContext.Provider value={contextValue}>{children}</ConversationWidgetContext.Provider>;\n};\n\n","import React from \"react\";\nimport { classNames } from \"../../../provider/class-names\";\nimport styles from \"./ConversationMessageInputComposerWidgets.module.scss\";\nimport { useConversationWidgetContext } from \"../../../renderer/ConversationWidgetContext\";\nimport { conversationWidgetRegistry } from \"../../../renderer/conversationWidgetRegistry\";\n\nexport interface ConversationMessageInputComposerWidgetsProps {\n testId?: string;\n}\n\n/**\n * Generic strip of composer widgets above the chat input's text area — the composer-side twin of\n * `ConversationMessageInputAttachmentsPreviewStrip`, same grid-rows 0fr→1fr reveal. Reads `composerWidgets` from the\n * widget context itself (so every ConversationView host gets it for free, mirroring the deleted selection chip),\n * and for each widget resolves the registry entry by `widgetName` and renders its `composerComponent` with\n * `{ composerWidgetId, fields, replaceFields, remove }`. An unknown name, or an entry without a `composerComponent`,\n * renders nothing for that widget — the same kill switch the fence plugin applies.\n */\nexport const ConversationMessageInputComposerWidgets = (props: ConversationMessageInputComposerWidgetsProps) => {\n const { testId = \"chat-input\" } = props;\n const { composerWidgets, replaceComposerWidgetFields, removeComposerWidget } = useConversationWidgetContext();\n\n const renderableWidgets = composerWidgets.flatMap((widget) => {\n const entry = conversationWidgetRegistry.widgets.find((candidate) => candidate.name === widget.widgetName);\n return entry?.composerComponent ? [{ widget, Component: entry.composerComponent }] : [];\n });\n\n return (\n <div\n className={classNames(styles.stripReveal, { [styles.stripRevealOpen]: renderableWidgets.length > 0 })}\n data-testid={`${testId}-composer-widgets-strip`}\n >\n <div className={styles.stripRevealInner}>\n <div className={styles.strip}>\n {renderableWidgets.map(({ widget, Component }) => (\n <Component\n key={widget.composerWidgetId}\n composerWidgetId={widget.composerWidgetId}\n fields={widget.fields}\n replaceFields={(nextFields) => replaceComposerWidgetFields(widget.composerWidgetId, nextFields)}\n remove={() => removeComposerWidget(widget.composerWidgetId)}\n testId={`${testId}-composer-widget-${widget.composerWidgetId}`}\n />\n ))}\n </div>\n </div>\n </div>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -1916,7 +1916,10 @@ const parseCustomVisualizationPayload = (rawPayload) => {
1916
1916
  return { isValid: true, payload, sourceBytes };
1917
1917
  };
1918
1918
  const bundledFrameUrl = "data:text/html;base64,PCFkb2N0eXBlIGh0bWw+CjxodG1sIGxhbmc9ImVuIj4KPGhlYWQ+CjxtZXRhIGNoYXJzZXQ9InV0Zi04Ij4KPG1ldGEgaHR0cC1lcXVpdj0iQ29udGVudC1TZWN1cml0eS1Qb2xpY3kiIGNvbnRlbnQ9ImRlZmF1bHQtc3JjICdub25lJzsgc2NyaXB0LXNyYyAnc2hhMjU2LWxNMFhHbWhHaVpNSUhsalFsVFNLUHdoSmpsbmlTMytabExWY0Nob25VYkE9JyBibG9iOjsgc3R5bGUtc3JjICd1bnNhZmUtaW5saW5lJzsgaW1nLXNyYyBkYXRhOiBibG9iOjsgZm9udC1zcmMgZGF0YTo7IGZvcm0tYWN0aW9uICdub25lJzsgYmFzZS11cmkgJ25vbmUnIj4KPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xIj4KPG1ldGEgbmFtZT0icmVmZXJyZXIiIGNvbnRlbnQ9Im5vLXJlZmVycmVyIj4KPHRpdGxlPkN1c3RvbSB2aXN1YWxpemF0aW9uPC90aXRsZT4KPHN0eWxlPmh0bWwsYm9keXttYXJnaW46MDtwYWRkaW5nOjA7YmFja2dyb3VuZDp0cmFuc3BhcmVudDtjb2xvcjp2YXIoLS1hZ2VudHMtZmcsIzFkMWQxZik7Zm9udC1mYW1pbHk6dmFyKC0tYWdlbnRzLWZvbnQtZmFtaWx5LHN5c3RlbS11aSxzYW5zLXNlcmlmKTtmb250LXNpemU6MTRweDtsaW5lLWhlaWdodDoxLjQ7b3ZlcmZsb3cteDpoaWRkZW59KiwqOjpiZWZvcmUsKjo6YWZ0ZXJ7Ym94LXNpemluZzpib3JkZXItYm94fSN2aXN1YWxpemF0aW9ue2Rpc3BsYXk6Zmxvdy1yb290fTwvc3R5bGU+CjxzY3JpcHQ+CihmdW5jdGlvbiAoKSB7CiAgInVzZSBzdHJpY3QiOwogIC8vIFRoZSBzYW5kYm94IGhvc3Qgb2YgdGhlIEN1c3RvbVZpc3VhbGl6YXRpb24gd2lkZ2V0LiBJdCBydW5zIGluIGFuIGlmcmFtZSB3aXRoCiAgLy8gc2FuZGJveD0iYWxsb3ctc2NyaXB0cyIgKGFuIG9wYXF1ZSBvcmlnaW46IG5vIGNvb2tpZXMsIG5vIHN0b3JhZ2UsIG5vIHBhcmVudCBET00pIHVuZGVyIHRoZSBwb2xpY3kgYWJvdmUuIEl0IHdhaXRzCiAgLy8gZm9yIE9ORSByZW5kZXIgbWVzc2FnZSBmcm9tIGl0cyBwYXJlbnQgd2luZG93LCB0aGVuIHNob3dzIHRoZSBibG9jaydzIEhUTUwgYW5kIENTUywgbG9hZHMgdGhlIGFsbG93LWxpc3RlZAogIC8vIGxpYnJhcmllcyBhbmQgdGhlIGJsb2NrJ3Mgc2NyaXB0IGFzIGJsb2I6IHNjcmlwdHMgKHRoZSBvbmx5IHNjcmlwdHMgdGhlIHBvbGljeSBhZG1pdHMgYmVzaWRlcyB0aGlzIG9uZSksIGFuZCB0ZWxscwogIC8vIHRoZSBwYXJlbnQgaXRzIGhlaWdodCwgdGhhdCBpdCBpcyBhbGl2ZSAodGhlIGhlYXJ0YmVhdCksIHdoZW4gdGhlIHNjcmlwdCByYW4gKHJlYWR5KSBhbmQgd2hlbiBhIHNjcmlwdCBmYWlsZWQuIEl0CiAgLy8gYWN0cyBvbiBub3RoaW5nIGJ1dCB0aGF0IG9uZSBtZXNzYWdlLiBUaGUgc2NyaXB0IHJlYWRzIHdpbmRvdy5BR0VOVFNfVklTVUFMSVpBVElPTiBhbmQgdGhlIHRoZW1lIHZhcmlhYmxlcwogIC8vIC0tYWdlbnRzLSo7IHRoZSByZW5kZXIgbWVzc2FnZSBtYXkgbmFtZSBmdXJ0aGVyIGdsb2JhbCBuYW1lcyBhbmQgdmFyaWFibGUgcHJlZml4ZXMgdGhlIGFwcCBkZWNsYXJlZCAodGhlIG5hbWVzIGl0cwogIC8vIHN0b3JlZCBzY3JpcHRzIHJlYWQpLCBhbmQgdGhlIGZyYW1lIHRoZW4gZGVmaW5lcyB0aGUgc2FtZSBnbG9iYWwgYW5kIHNldHMgdGhlIHNhbWUgdmFyaWFibGVzIHVuZGVyIHRob3NlIGFzIHdlbGwuCiAgdmFyIENIQU5ORUwgPSAiYWdlbnRzLWN1c3RvbS12aXN1YWxpemF0aW9uIjsKICB2YXIgR0xPQkFMX05BTUUgPSAiQUdFTlRTX1ZJU1VBTElaQVRJT04iOwogIHZhciBUSEVNRV9WQVJJQUJMRV9QUkVGSVggPSAiLS1hZ2VudHMtIjsKICB2YXIgR0xPQkFMX05BTUVfUEFUVEVSTiA9IC9eW0EtWmEtel8kXVtBLVphLXowLTlfJF0qJC87CiAgdmFyIFRIRU1FX1ZBUklBQkxFX1BSRUZJWF9QQVRURVJOID0gL14tLVthLXpdW2EtejAtOS1dKi0kLzsKICB2YXIgSEVBUlRCRUFUX0lOVEVSVkFMX01TID0gMTAwMDsKICB2YXIgTUFYX0VSUk9SX01FU1NBR0VfTEVOR1RIID0gMzAwOwogIHZhciBwYXJlbnRXaW5kb3cgPSB3aW5kb3cucGFyZW50OwogIHZhciBwb3N0VG9QYXJlbnQgPSBwYXJlbnRXaW5kb3cucG9zdE1lc3NhZ2UuYmluZChwYXJlbnRXaW5kb3cpOwogIHZhciBpbnN0YW5jZVRva2VuID0gbnVsbDsKICB2YXIgbGFzdFBvc3RlZEhlaWdodCA9IC0xOwogIHZhciBoZWlnaHRNZWFzdXJlUmVxdWVzdGVkID0gZmFsc2U7CgogIHZhciBwb3N0ID0gZnVuY3Rpb24gKG1lc3NhZ2UpIHsKICAgIG1lc3NhZ2UuY2hhbm5lbCA9IENIQU5ORUw7CiAgICBtZXNzYWdlLnRva2VuID0gaW5zdGFuY2VUb2tlbjsKICAgIHBvc3RUb1BhcmVudChtZXNzYWdlLCAiKiIpOwogIH07CgogIHZhciByZXBvcnRFcnJvciA9IGZ1bmN0aW9uIChlcnJvclRleHQpIHsKICAgIHBvc3QoeyB0eXBlOiAiZXJyb3IiLCBtZXNzYWdlOiBTdHJpbmcoZXJyb3JUZXh0IHx8ICJVbmtub3duIHNjcmlwdCBlcnJvciIpLnNsaWNlKDAsIE1BWF9FUlJPUl9NRVNTQUdFX0xFTkdUSCkgfSk7CiAgfTsKCiAgLy8gVGhlIGNvbnRlbnQncyBvd24gaGVpZ2h0OiB0aGUgcm9vdCBpcyBhIGZsb3cgcm9vdCAobWFyZ2lucyBzdGF5IGluc2lkZSksIGFuZCB0aGUgZG9jdW1lbnQncyBzY3JvbGwgaGVpZ2h0IGlzIG5vCiAgLy8gbWVhc3VyZSDigJQgaW5zaWRlIGEgZnJhbWUgaXQgbmV2ZXIgZHJvcHMgYmVsb3cgdGhlIGZyYW1lJ3MgY3VycmVudCBoZWlnaHQuCiAgdmFyIG1lYXN1cmVIZWlnaHQgPSBmdW5jdGlvbiAoKSB7CiAgICBoZWlnaHRNZWFzdXJlUmVxdWVzdGVkID0gZmFsc2U7CiAgICB2YXIgdmlzdWFsaXphdGlvblJvb3QgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgidmlzdWFsaXphdGlvbiIpOwogICAgaWYgKCF2aXN1YWxpemF0aW9uUm9vdCkgcmV0dXJuOwogICAgdmFyIGNvbnRlbnRIZWlnaHQgPSBNYXRoLmNlaWwodmlzdWFsaXphdGlvblJvb3QuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0KTsKICAgIGlmIChjb250ZW50SGVpZ2h0ICE9PSBsYXN0UG9zdGVkSGVpZ2h0KSB7CiAgICAgIGxhc3RQb3N0ZWRIZWlnaHQgPSBjb250ZW50SGVpZ2h0OwogICAgICBwb3N0KHsgdHlwZTogImhlaWdodCIsIGhlaWdodDogY29udGVudEhlaWdodCB9KTsKICAgIH0KICB9OwoKICB2YXIgcmVxdWVzdEhlaWdodE1lYXN1cmUgPSBmdW5jdGlvbiAoKSB7CiAgICBpZiAoaGVpZ2h0TWVhc3VyZVJlcXVlc3RlZCkgcmV0dXJuOwogICAgaGVpZ2h0TWVhc3VyZVJlcXVlc3RlZCA9IHRydWU7CiAgICB3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lKG1lYXN1cmVIZWlnaHQpOwogIH07CgogIHZhciBsb2FkU2NyaXB0VGV4dCA9IGZ1bmN0aW9uIChzY3JpcHRUZXh0KSB7CiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkgewogICAgICB2YXIgc2NyaXB0VXJsID0gVVJMLmNyZWF0ZU9iamVjdFVSTChuZXcgQmxvYihbc2NyaXB0VGV4dF0sIHsgdHlwZTogInRleHQvamF2YXNjcmlwdCIgfSkpOwogICAgICB2YXIgc2NyaXB0RWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInNjcmlwdCIpOwogICAgICBzY3JpcHRFbGVtZW50LnNyYyA9IHNjcmlwdFVybDsKICAgICAgc2NyaXB0RWxlbWVudC5vbmxvYWQgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgVVJMLnJldm9rZU9iamVjdFVSTChzY3JpcHRVcmwpOwogICAgICAgIHJlc29sdmUoKTsKICAgICAgfTsKICAgICAgc2NyaXB0RWxlbWVudC5vbmVycm9yID0gZnVuY3Rpb24gKCkgewogICAgICAgIFVSTC5yZXZva2VPYmplY3RVUkwoc2NyaXB0VXJsKTsKICAgICAgICByZWplY3QobmV3IEVycm9yKCJBIHNjcmlwdCBjb3VsZCBub3QgYmUgbG9hZGVkIGluIHRoZSBzYW5kYm94LiIpKTsKICAgICAgfTsKICAgICAgZG9jdW1lbnQuaGVhZC5hcHBlbmRDaGlsZChzY3JpcHRFbGVtZW50KTsKICAgIH0pOwogIH07CgogIC8vIFRoZSB2YXJpYWJsZSdzIG5hbWUgd2l0aG91dCBpdHMgcHJlZml4IChmZy1saWdodCksIG9yIG51bGwgd2hlbiBpdCBjYXJyaWVzIG5vbmUgb2YgdGhlIGFjY2VwdGVkIHByZWZpeGVzLgogIHZhciByZWFkVGhlbWVWYXJpYWJsZVN1ZmZpeCA9IGZ1bmN0aW9uICh2YXJpYWJsZU5hbWUsIHRoZW1lVmFyaWFibGVQcmVmaXhlcykgewogICAgdmFyIGFjY2VwdGVkUHJlZml4ZXMgPSBbVEhFTUVfVkFSSUFCTEVfUFJFRklYXS5jb25jYXQodGhlbWVWYXJpYWJsZVByZWZpeGVzKTsKICAgIGZvciAodmFyIHByZWZpeEluZGV4ID0gMDsgcHJlZml4SW5kZXggPCBhY2NlcHRlZFByZWZpeGVzLmxlbmd0aDsgcHJlZml4SW5kZXgrKykgewogICAgICB2YXIgYWNjZXB0ZWRQcmVmaXggPSBhY2NlcHRlZFByZWZpeGVzW3ByZWZpeEluZGV4XTsKICAgICAgdmFyIHZhcmlhYmxlU3VmZml4ID0gdmFyaWFibGVOYW1lLnNsaWNlKGFjY2VwdGVkUHJlZml4Lmxlbmd0aCk7CiAgICAgIGlmICh2YXJpYWJsZU5hbWUuaW5kZXhPZihhY2NlcHRlZFByZWZpeCkgPT09IDAgJiYgL15bYS16LV0rJC8udGVzdCh2YXJpYWJsZVN1ZmZpeCkpIHJldHVybiB2YXJpYWJsZVN1ZmZpeDsKICAgIH0KICAgIHJldHVybiBudWxsOwogIH07CgogIC8vIEV2ZXJ5IGFjY2VwdGVkIHZhcmlhYmxlIGlzIHNldCB1bmRlciB0aGUgcGFja2FnZSdzIHByZWZpeCBhbmQgdW5kZXIgZWFjaCBkZWNsYXJlZCBwcmVmaXguCiAgdmFyIGFwcGx5VGhlbWVWYXJpYWJsZXMgPSBmdW5jdGlvbiAodGhlbWVWYXJpYWJsZXMsIHRoZW1lVmFyaWFibGVQcmVmaXhlcykgewogICAgaWYgKCF0aGVtZVZhcmlhYmxlcyB8fCB0eXBlb2YgdGhlbWVWYXJpYWJsZXMgIT09ICJvYmplY3QiKSByZXR1cm47CiAgICBPYmplY3Qua2V5cyh0aGVtZVZhcmlhYmxlcykuZm9yRWFjaChmdW5jdGlvbiAodmFyaWFibGVOYW1lKSB7CiAgICAgIHZhciB2YXJpYWJsZVZhbHVlID0gdGhlbWVWYXJpYWJsZXNbdmFyaWFibGVOYW1lXTsKICAgICAgdmFyIHZhcmlhYmxlU3VmZml4ID0gcmVhZFRoZW1lVmFyaWFibGVTdWZmaXgodmFyaWFibGVOYW1lLCB0aGVtZVZhcmlhYmxlUHJlZml4ZXMpOwogICAgICBpZiAodmFyaWFibGVTdWZmaXggPT09IG51bGwgfHwgdHlwZW9mIHZhcmlhYmxlVmFsdWUgIT09ICJzdHJpbmciKSByZXR1cm47CiAgICAgIFtUSEVNRV9WQVJJQUJMRV9QUkVGSVhdLmNvbmNhdCh0aGVtZVZhcmlhYmxlUHJlZml4ZXMpLmZvckVhY2goZnVuY3Rpb24gKHRoZW1lVmFyaWFibGVQcmVmaXgpIHsKICAgICAgICBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGUuc2V0UHJvcGVydHkodGhlbWVWYXJpYWJsZVByZWZpeCArIHZhcmlhYmxlU3VmZml4LCB2YXJpYWJsZVZhbHVlKTsKICAgICAgfSk7CiAgICB9KTsKICB9OwoKICB2YXIgcmVhZERlY2xhcmVkTmFtZXMgPSBmdW5jdGlvbiAoZGVjbGFyZWROYW1lcywgbmFtZVBhdHRlcm4pIHsKICAgIGlmICghQXJyYXkuaXNBcnJheShkZWNsYXJlZE5hbWVzKSkgcmV0dXJuIFtdOwogICAgcmV0dXJuIGRlY2xhcmVkTmFtZXMuZmlsdGVyKGZ1bmN0aW9uIChkZWNsYXJlZE5hbWUpIHsKICAgICAgcmV0dXJuIHR5cGVvZiBkZWNsYXJlZE5hbWUgPT09ICJzdHJpbmciICYmIG5hbWVQYXR0ZXJuLnRlc3QoZGVjbGFyZWROYW1lKTsKICAgIH0pOwogIH07CgogIHZhciBsb2FkTGlicmFyaWVzVGhlblNjcmlwdCA9IGZ1bmN0aW9uIChsaWJyYXJ5U291cmNlcywgdmlzdWFsaXphdGlvblNjcmlwdCwgbGlicmFyeUluZGV4KSB7CiAgICBpZiAobGlicmFyeUluZGV4IDwgbGlicmFyeVNvdXJjZXMubGVuZ3RoKSB7CiAgICAgIHJldHVybiBsb2FkU2NyaXB0VGV4dChsaWJyYXJ5U291cmNlc1tsaWJyYXJ5SW5kZXhdKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICByZXR1cm4gbG9hZExpYnJhcmllc1RoZW5TY3JpcHQobGlicmFyeVNvdXJjZXMsIHZpc3VhbGl6YXRpb25TY3JpcHQsIGxpYnJhcnlJbmRleCArIDEpOwogICAgICB9KTsKICAgIH0KICAgIHJldHVybiB2aXN1YWxpemF0aW9uU2NyaXB0ID8gbG9hZFNjcmlwdFRleHQodmlzdWFsaXphdGlvblNjcmlwdCkgOiBQcm9taXNlLnJlc29sdmUoKTsKICB9OwoKICB2YXIgcmVuZGVyID0gZnVuY3Rpb24gKHJlbmRlck1lc3NhZ2UpIHsKICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCJlcnJvciIsIGZ1bmN0aW9uIChlcnJvckV2ZW50KSB7CiAgICAgIHJlcG9ydEVycm9yKGVycm9yRXZlbnQgJiYgZXJyb3JFdmVudC5tZXNzYWdlID8gZXJyb3JFdmVudC5tZXNzYWdlIDogIlVua25vd24gc2NyaXB0IGVycm9yIik7CiAgICB9KTsKICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCJ1bmhhbmRsZWRyZWplY3Rpb24iLCBmdW5jdGlvbiAocmVqZWN0aW9uRXZlbnQpIHsKICAgICAgdmFyIHJlamVjdGlvblJlYXNvbiA9IHJlamVjdGlvbkV2ZW50ID8gcmVqZWN0aW9uRXZlbnQucmVhc29uIDogbnVsbDsKICAgICAgcmVwb3J0RXJyb3IocmVqZWN0aW9uUmVhc29uICYmIHJlamVjdGlvblJlYXNvbi5tZXNzYWdlID8gcmVqZWN0aW9uUmVhc29uLm1lc3NhZ2UgOiBTdHJpbmcocmVqZWN0aW9uUmVhc29uKSk7CiAgICB9KTsKICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoInNlY3VyaXR5cG9saWN5dmlvbGF0aW9uIiwgZnVuY3Rpb24gKHZpb2xhdGlvbkV2ZW50KSB7CiAgICAgIHJlcG9ydEVycm9yKCJCbG9ja2VkIGJ5IHRoZSBzYW5kYm94IHBvbGljeTogIiArIHZpb2xhdGlvbkV2ZW50LmVmZmVjdGl2ZURpcmVjdGl2ZSArICIgIgogICAgICAgICsgU3RyaW5nKHZpb2xhdGlvbkV2ZW50LmJsb2NrZWRVUkkgfHwgIiIpLnNsaWNlKDAsIDgwKSk7CiAgICB9KTsKICAgIHdpbmRvdy5zZXRJbnRlcnZhbChmdW5jdGlvbiAoKSB7CiAgICAgIHBvc3QoeyB0eXBlOiAiaGVhcnRiZWF0IiB9KTsKICAgIH0sIEhFQVJUQkVBVF9JTlRFUlZBTF9NUyk7CiAgICBwb3N0KHsgdHlwZTogImhlYXJ0YmVhdCIgfSk7CgogICAgdmFyIHRoZW1lVmFyaWFibGVQcmVmaXhlcyA9IHJlYWREZWNsYXJlZE5hbWVzKHJlbmRlck1lc3NhZ2UudGhlbWVWYXJpYWJsZVByZWZpeGVzLCBUSEVNRV9WQVJJQUJMRV9QUkVGSVhfUEFUVEVSTik7CiAgICBhcHBseVRoZW1lVmFyaWFibGVzKHJlbmRlck1lc3NhZ2UudGhlbWUsIHRoZW1lVmFyaWFibGVQcmVmaXhlcyk7CiAgICBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2V0QXR0cmlidXRlKCJkYXRhLWNvbG9yLXNjaGVtZSIsIHJlbmRlck1lc3NhZ2UuY29sb3JTY2hlbWUgPT09ICJkYXJrIiA/ICJkYXJrIiA6ICJsaWdodCIpOwogICAgdmFyIHN0eWxlRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInN0eWxlIik7CiAgICBzdHlsZUVsZW1lbnQudGV4dENvbnRlbnQgPSByZW5kZXJNZXNzYWdlLmNzczsKICAgIGRvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQoc3R5bGVFbGVtZW50KTsKICAgIHZhciB2aXN1YWxpemF0aW9uUm9vdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImRpdiIpOwogICAgdmlzdWFsaXphdGlvblJvb3QuaWQgPSAidmlzdWFsaXphdGlvbiI7CiAgICB2aXN1YWxpemF0aW9uUm9vdC5pbm5lckhUTUwgPSByZW5kZXJNZXNzYWdlLmh0bWw7CiAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHZpc3VhbGl6YXRpb25Sb290KTsKCiAgICB2YXIgdmlzdWFsaXphdGlvbiA9IE9iamVjdC5mcmVlemUoewogICAgICBkYXRhOiByZW5kZXJNZXNzYWdlLmRhdGEsCiAgICAgIGNvbG9yU2NoZW1lOiByZW5kZXJNZXNzYWdlLmNvbG9yU2NoZW1lID09PSAiZGFyayIgPyAiZGFyayIgOiAibGlnaHQiCiAgICB9KTsKICAgIFtHTE9CQUxfTkFNRV0uY29uY2F0KHJlYWREZWNsYXJlZE5hbWVzKHJlbmRlck1lc3NhZ2UudmlzdWFsaXphdGlvbkdsb2JhbE5hbWVzLCBHTE9CQUxfTkFNRV9QQVRURVJOKSkKICAgICAgLmZvckVhY2goZnVuY3Rpb24gKGdsb2JhbE5hbWUpIHsKICAgICAgICAvLyBBIGRlY2xhcmVkIG5hbWUgbmV2ZXIgcmVwbGFjZXMgYSBwcm9wZXJ0eSB0aGUgd2luZG93IGFscmVhZHkgaGFzIChsb2NhdGlvbiwgcGFyZW50LCDigKYpLgogICAgICAgIGlmICghKGdsb2JhbE5hbWUgaW4gd2luZG93KSkgd2luZG93W2dsb2JhbE5hbWVdID0gdmlzdWFsaXphdGlvbjsKICAgICAgfSk7CiAgICBpZiAodHlwZW9mIFJlc2l6ZU9ic2VydmVyID09PSAiZnVuY3Rpb24iKSB7CiAgICAgIG5ldyBSZXNpemVPYnNlcnZlcihyZXF1ZXN0SGVpZ2h0TWVhc3VyZSkub2JzZXJ2ZSh2aXN1YWxpemF0aW9uUm9vdCk7CiAgICB9CiAgICByZXF1ZXN0SGVpZ2h0TWVhc3VyZSgpOwoKICAgIGxvYWRMaWJyYXJpZXNUaGVuU2NyaXB0KHJlbmRlck1lc3NhZ2UubGlicmFyeVNvdXJjZXMsIHJlbmRlck1lc3NhZ2Uuc2NyaXB0LCAwKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgcmVxdWVzdEhlaWdodE1lYXN1cmUoKTsKICAgICAgcG9zdCh7IHR5cGU6ICJyZWFkeSIgfSk7CiAgICB9LCBmdW5jdGlvbiAobG9hZEVycm9yKSB7CiAgICAgIHJlcG9ydEVycm9yKGxvYWRFcnJvci5tZXNzYWdlKTsKICAgIH0pOwogIH07CgogIHZhciBpc1JlbmRlck1lc3NhZ2UgPSBmdW5jdGlvbiAobWVzc2FnZSkgewogICAgcmV0dXJuIG1lc3NhZ2UgIT09IG51bGwgJiYgdHlwZW9mIG1lc3NhZ2UgPT09ICJvYmplY3QiICYmIG1lc3NhZ2UuY2hhbm5lbCA9PT0gQ0hBTk5FTCAmJiBtZXNzYWdlLnR5cGUgPT09ICJyZW5kZXIiCiAgICAgICYmIHR5cGVvZiBtZXNzYWdlLnRva2VuID09PSAic3RyaW5nIiAmJiB0eXBlb2YgbWVzc2FnZS5odG1sID09PSAic3RyaW5nIiAmJiB0eXBlb2YgbWVzc2FnZS5jc3MgPT09ICJzdHJpbmciCiAgICAgICYmIHR5cGVvZiBtZXNzYWdlLnNjcmlwdCA9PT0gInN0cmluZyIgJiYgQXJyYXkuaXNBcnJheShtZXNzYWdlLmxpYnJhcnlTb3VyY2VzKQogICAgICAmJiBtZXNzYWdlLmxpYnJhcnlTb3VyY2VzLmV2ZXJ5KGZ1bmN0aW9uIChsaWJyYXJ5U291cmNlKSB7IHJldHVybiB0eXBlb2YgbGlicmFyeVNvdXJjZSA9PT0gInN0cmluZyI7IH0pCiAgICAgICYmIChtZXNzYWdlLnZpc3VhbGl6YXRpb25HbG9iYWxOYW1lcyA9PT0gdW5kZWZpbmVkIHx8IEFycmF5LmlzQXJyYXkobWVzc2FnZS52aXN1YWxpemF0aW9uR2xvYmFsTmFtZXMpKQogICAgICAmJiAobWVzc2FnZS50aGVtZVZhcmlhYmxlUHJlZml4ZXMgPT09IHVuZGVmaW5lZCB8fCBBcnJheS5pc0FycmF5KG1lc3NhZ2UudGhlbWVWYXJpYWJsZVByZWZpeGVzKSk7CiAgfTsKCiAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoIm1lc3NhZ2UiLCBmdW5jdGlvbiAobWVzc2FnZUV2ZW50KSB7CiAgICBpZiAobWVzc2FnZUV2ZW50LnNvdXJjZSAhPT0gcGFyZW50V2luZG93IHx8IGluc3RhbmNlVG9rZW4gIT09IG51bGwgfHwgIWlzUmVuZGVyTWVzc2FnZShtZXNzYWdlRXZlbnQuZGF0YSkpIHJldHVybjsKICAgIGluc3RhbmNlVG9rZW4gPSBtZXNzYWdlRXZlbnQuZGF0YS50b2tlbjsKICAgIHJlbmRlcihtZXNzYWdlRXZlbnQuZGF0YSk7CiAgfSk7Cn0pKCk7Cjwvc2NyaXB0Pgo8L2hlYWQ+Cjxib2R5PjwvYm9keT4KPC9odG1sPgo=";
1919
- const resolveCustomVisualizationFrameUrl = () => bundledFrameUrl;
1919
+ const CUSTOM_VISUALIZATION_SANDBOX_CONFIG = {
1920
+ frameUrl: null
1921
+ };
1922
+ const resolveCustomVisualizationFrameUrl = () => CUSTOM_VISUALIZATION_SANDBOX_CONFIG.frameUrl ?? bundledFrameUrl;
1920
1923
  const THEME_TOKENS = {
1921
1924
  "--agents-fg": "--agents-fg",
1922
1925
  "--agents-fg-light": "--agents-fg-light",
@@ -3979,7 +3982,7 @@ const WebSearchResultsConversationWidget = (props) => {
3979
3982
  );
3980
3983
  };
3981
3984
  export {
3982
- ConceptExplainerConversationWidget as $,
3985
+ ClockConversationWidget as $,
3983
3986
  readWidgetAgentSpaceKeyAttribute as A,
3984
3987
  sameCanvasAnchor as B,
3985
3988
  ConversationWidgetActions as C,
@@ -4004,54 +4007,56 @@ export {
4004
4007
  SkeletonCircle as V,
4005
4008
  WidgetRenderReportContext as W,
4006
4009
  SkeletonLine as X,
4007
- CanvasWidgetCard as Y,
4008
- CanvasWidgetSwitch as Z,
4009
- ClockConversationWidget as _,
4010
+ CUSTOM_VISUALIZATION_SANDBOX_CONFIG as Y,
4011
+ CanvasWidgetCard as Z,
4012
+ CanvasWidgetSwitch as _,
4010
4013
  registerConceptExplainerTypes as a,
4011
- ConversationSearchResultsConversationWidget as a0,
4012
- CurrencyConverterConversationWidget as a1,
4013
- CustomVisualizationConversationWidget as a2,
4014
- DonePill as a3,
4015
- EntityMentionConversationWidget as a4,
4016
- MultiChoiceConversationWidget as a5,
4017
- QuickRepliesConversationWidget as a6,
4018
- SkeletonPill as a7,
4019
- SkeletonWidgetLabel as a8,
4020
- SuggestedActions as a9,
4021
- ConversationWidgetButton as aA,
4022
- readTextNodeContent as aB,
4023
- readAllowedValue as aC,
4024
- useReportTextNodeRenderState as aD,
4025
- readTextNodeRenderState as aE,
4026
- buildFaviconUrl as aF,
4027
- readSiteHostname as aG,
4028
- readSafeHttpUrl as aH,
4029
- ToolTraceConversationWidget as aa,
4030
- WebSearchResultsConversationWidget as ab,
4031
- WidgetKpiValue as ac,
4032
- WritingDraftConversationWidget as ad,
4033
- canvasForMessageWidget as ae,
4034
- formatConceptExplainerNumber as af,
4035
- normalizeSearchHitExcerpt as ag,
4036
- pickAllowed as ah,
4037
- pickAllowedValue as ai,
4038
- pickReviewExternalId as aj,
4039
- pickSafeAlias as ak,
4040
- pickSafeAliases as al,
4041
- pickText as am,
4042
- readConceptExplainerNumber as an,
4043
- readConceptExplainerValue as ao,
4044
- useCanvasViable as ap,
4045
- parseConversationSearchResultsPayload as aq,
4046
- WebSearchAnswer as ar,
4047
- WebSearchSourcesList as as,
4048
- parseWebSearchResultsPayload as at,
4049
- ENTITY_MENTION_WIDGET_NAME as au,
4050
- buildEntityMentionFields as av,
4051
- normalizeEntityMentionFields as aw,
4052
- entityMentionKey as ax,
4053
- MAX_ENTITY_MENTIONS_PER_MESSAGE as ay,
4054
- toEntityMentionWireFields as az,
4014
+ ConceptExplainerConversationWidget as a0,
4015
+ ConversationSearchResultsConversationWidget as a1,
4016
+ CurrencyConverterConversationWidget as a2,
4017
+ CustomVisualizationConversationWidget as a3,
4018
+ DonePill as a4,
4019
+ EntityMentionConversationWidget as a5,
4020
+ MultiChoiceConversationWidget as a6,
4021
+ QuickRepliesConversationWidget as a7,
4022
+ SkeletonPill as a8,
4023
+ SkeletonWidgetLabel as a9,
4024
+ MAX_ENTITY_MENTIONS_PER_MESSAGE as aA,
4025
+ toEntityMentionWireFields as aB,
4026
+ ConversationWidgetButton as aC,
4027
+ readTextNodeContent as aD,
4028
+ readAllowedValue as aE,
4029
+ useReportTextNodeRenderState as aF,
4030
+ readTextNodeRenderState as aG,
4031
+ buildFaviconUrl as aH,
4032
+ readSiteHostname as aI,
4033
+ readSafeHttpUrl as aJ,
4034
+ SuggestedActions as aa,
4035
+ ToolTraceConversationWidget as ab,
4036
+ WebSearchResultsConversationWidget as ac,
4037
+ WidgetKpiValue as ad,
4038
+ WritingDraftConversationWidget as ae,
4039
+ canvasForMessageWidget as af,
4040
+ formatConceptExplainerNumber as ag,
4041
+ normalizeSearchHitExcerpt as ah,
4042
+ pickAllowed as ai,
4043
+ pickAllowedValue as aj,
4044
+ pickReviewExternalId as ak,
4045
+ pickSafeAlias as al,
4046
+ pickSafeAliases as am,
4047
+ pickText as an,
4048
+ readConceptExplainerNumber as ao,
4049
+ readConceptExplainerValue as ap,
4050
+ resolveCustomVisualizationFrameUrl as aq,
4051
+ useCanvasViable as ar,
4052
+ parseConversationSearchResultsPayload as as,
4053
+ WebSearchAnswer as at,
4054
+ WebSearchSourcesList as au,
4055
+ parseWebSearchResultsPayload as av,
4056
+ ENTITY_MENTION_WIDGET_NAME as aw,
4057
+ buildEntityMentionFields as ax,
4058
+ normalizeEntityMentionFields as ay,
4059
+ entityMentionKey as az,
4055
4060
  registerWidgetHydrator as b,
4056
4061
  abandonWidgetHydrationReads as c,
4057
4062
  useResolvedConversationWidgetAgentSpaceKey as d,
@@ -4078,4 +4083,4 @@ export {
4078
4083
  messageAnchor as y,
4079
4084
  pageAnchor as z
4080
4085
  };
4081
- //# sourceMappingURL=WebSearchResultsConversationWidget-as3p5bHw.js.map
4086
+ //# sourceMappingURL=WebSearchResultsConversationWidget-tDhawe9f.js.map