@mgamadeus/ddd-agents 0.1.0-alpha.23 → 0.1.0-alpha.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chat.js +71 -827
- package/dist/chat.js.map +1 -1
- package/dist/chunks/ConversationMessageInputComposerWidgets-BxyaFBA6.js +631 -0
- package/dist/chunks/ConversationMessageInputComposerWidgets-BxyaFBA6.js.map +1 -0
- package/dist/chunks/{WebSearchResultsConversationWidget-DRBQvycE.js → WebSearchResultsConversationWidget-as3p5bHw.js} +92 -85
- package/dist/chunks/WebSearchResultsConversationWidget-as3p5bHw.js.map +1 -0
- package/dist/chunks/{decide-canvas-open-DBWoWtAC.js → canvas-behaviours-AvzKSYyv.js} +3 -19
- package/dist/chunks/canvas-behaviours-AvzKSYyv.js.map +1 -0
- package/dist/chunks/canvas-reducers-Bfp_i7lc.js +88 -0
- package/dist/chunks/canvas-reducers-Bfp_i7lc.js.map +1 -0
- package/dist/chunks/{canvasBodies-DLjDkviP.js → canvasBodies-Cvu3l38p.js} +6 -3
- package/dist/chunks/{canvasBodies-DLjDkviP.js.map → canvasBodies-Cvu3l38p.js.map} +1 -1
- package/dist/chunks/canvasStorage-EvQsGdto.js +65 -0
- package/dist/chunks/canvasStorage-EvQsGdto.js.map +1 -0
- package/dist/chunks/contract-BxmMxYPF.js +96 -0
- package/dist/chunks/contract-BxmMxYPF.js.map +1 -0
- package/dist/chunks/conversation-BEF0aesf.js +31 -0
- package/dist/chunks/conversation-BEF0aesf.js.map +1 -0
- package/dist/chunks/{ConversationMarkdown-CJhAnuVa.js → widget-click-signal-sources-DulRkNvZ.js} +22 -77
- package/dist/chunks/widget-click-signal-sources-DulRkNvZ.js.map +1 -0
- package/dist/chunks/{widget-name-resolver-C8SfpiR5.js → widget-name-resolver-BGN3HpoG.js} +61 -30
- package/dist/chunks/widget-name-resolver-BGN3HpoG.js.map +1 -0
- package/dist/chunks/{withPollingChangeSubscription-BLDAWF-o.js → withPollingChangeSubscription-B16htQGd.js} +2 -2
- package/dist/chunks/{withPollingChangeSubscription-BLDAWF-o.js.map → withPollingChangeSubscription-B16htQGd.js.map} +1 -1
- package/dist/client-testing.js +28 -6
- package/dist/client-testing.js.map +1 -1
- package/dist/client.js +1 -1
- package/dist/contract.js +8 -27
- package/dist/contract.js.map +1 -1
- package/dist/image-render.js +8 -8
- package/dist/index.js +6 -5
- package/dist/kit.js +2 -2
- package/dist/preview.js +44 -16
- package/dist/preview.js.map +1 -1
- package/dist/renderer.js +62 -57
- package/dist/renderer.js.map +1 -1
- package/dist/styles.css +55 -22
- package/dist/types/client/testing/widget-hydration-stand-ins.d.ts +12 -3
- package/dist/types/entries/chat.d.ts +2 -0
- package/dist/types/entries/client-testing.d.ts +2 -0
- package/dist/types/entries/contract.d.ts +1 -0
- package/dist/types/entries/index.d.ts +1 -1
- package/dist/types/entries/preview.d.ts +1 -0
- package/dist/types/entries/renderer.d.ts +3 -1
- package/dist/types/kit/components/data/chart-model.d.ts +2 -2
- package/dist/types/kit/components/data/use-chart-palette.d.ts +2 -2
- package/dist/types/kit/components/map/use-google-maps-auth-failure.d.ts +18 -0
- package/dist/types/kit/entity-detail/entity-detail-bodies.d.ts +2 -0
- package/dist/types/renderer/canvas/entity-detail-instance.d.ts +5 -3
- package/dist/types/renderer/widget-hydration/use-widget-hydration.d.ts +5 -0
- package/dist/types/widgets/EntityMentionConversationWidget/stories/EntityMentionAskFlowStory.d.ts +8 -0
- package/dist/widgets.js +33 -33
- package/package.json +1 -1
- package/public-api.json +19 -1
- package/dist/chunks/ConversationMarkdown-CJhAnuVa.js.map +0 -1
- package/dist/chunks/WebSearchResultsConversationWidget-DRBQvycE.js.map +0 -1
- package/dist/chunks/decide-canvas-open-DBWoWtAC.js.map +0 -1
- package/dist/chunks/widget-name-resolver-C8SfpiR5.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebSearchResultsConversationWidget-as3p5bHw.js","sources":["../../src/renderer/ConversationWidgetRenderContext.ts","../../src/renderer/ConversationWidgetCallbacksContext.tsx","../../src/renderer/_agent-space/widget-agent-space-key-attribute.ts","../../src/renderer/canvas/canvas-state.ts","../../src/renderer/render-report/widget-render-report.ts","../../src/renderer/widget-hydration/widget-hydration.slice.ts","../../src/renderer/widget-hydration/widget-hydration.registry.ts","../../src/image-render/WidgetImageRenderContext.ts","../../src/renderer/widget-hydration/use-widget-hydration.ts","../../src/widgets/_shared/skeleton-primitives.tsx","../../src/widgets/_shared/modern/WidgetSurface.tsx","../../src/widgets/_shared/modern/WidgetKpiValue.tsx","../../src/kit/components/text/shared/text-node-values.ts","../../src/renderer/ConversationWidgetActions/ConversationWidgetActions.tsx","../../src/widgets/_shared/ConversationWidgetButton.tsx","../../src/widgets/_shared/DonePill.tsx","../../src/kit/ModelText/ModelText.tsx","../../src/widgets/ClockConversationWidget/shared/clock-time.ts","../../src/widgets/ClockConversationWidget/shared/clock-widget-payload.ts","../../src/widgets/ClockConversationWidget/shared/use-clock-settings.ts","../../src/widgets/ClockConversationWidget/ClockWidget/AnalogClockFace.tsx","../../src/widgets/ClockConversationWidget/ClockWidget/DayNightGlyph.tsx","../../src/widgets/ClockConversationWidget/ClockWidget/ClockRow.tsx","../../src/widgets/ClockConversationWidget/ClockWidget/ClockWidget.tsx","../../src/widgets/ClockConversationWidget/ClockConversationWidget.tsx","../../src/widgets/ConceptExplainerConversationWidget/shared/concept-explainer-types.ts","../../src/widgets/ConceptExplainerConversationWidget/shared/concept-explainer-widget-payload.ts","../../src/widgets/ConceptExplainerConversationWidget/shared/use-concept-explainer-language.ts","../../src/widgets/ConceptExplainerConversationWidget/shared/ConceptExplainerTextView.tsx","../../src/widgets/ConceptExplainerConversationWidget/ConceptExplainerWidget/ConceptExplainerWidget.tsx","../../src/widgets/ConceptExplainerConversationWidget/ConceptExplainerConversationWidget.tsx","../../src/widgets/CurrencyConverterConversationWidget/shared/currency-converter-widget-payload.ts","../../src/widgets/CurrencyConverterConversationWidget/shared/currency-display.ts","../../src/widgets/CurrencyConverterConversationWidget/CurrencyConverterWidget/CurrencyLabel/CurrencyLabel.tsx","../../src/widgets/CurrencyConverterConversationWidget/CurrencyConverterWidget/CurrencyConverterWidget.tsx","../../src/widgets/CurrencyConverterConversationWidget/CurrencyConverterConversationWidget.tsx","../../src/widgets/CustomVisualizationConversationWidget/shared/custom-visualization-libraries.ts","../../src/widgets/CustomVisualizationConversationWidget/shared/custom-visualization-frame-protocol.ts","../../src/widgets/CustomVisualizationConversationWidget/shared/custom-visualization-widget-payload.ts","../../src/widgets/CustomVisualizationConversationWidget/sandbox-frame/custom-visualization-frame.html?url","../../src/widgets/CustomVisualizationConversationWidget/shared/custom-visualization-sandbox-config.ts","../../src/widgets/CustomVisualizationConversationWidget/shared/read-custom-visualization-theme.ts","../../src/widgets/CustomVisualizationConversationWidget/CustomVisualizationWidget/CustomVisualizationFrame.tsx","../../src/widgets/CustomVisualizationConversationWidget/CustomVisualizationWidget/CustomVisualizationWidget.tsx","../../src/widgets/CustomVisualizationConversationWidget/CustomVisualizationConversationWidget.tsx","../../src/widgets/EntityMentionConversationWidget/shared/entity-mention-presentation.ts","../../src/widgets/EntityMentionConversationWidget/EntityMentionCard/EntityMentionCard.tsx","../../src/widgets/EntityMentionConversationWidget/shared/entity-mention.ts","../../src/widgets/EntityMentionConversationWidget/EntityMentionConversationWidget.tsx","../../src/widgets/WritingDraftConversationWidget/shared/writing-draft-widget-payload.ts","../../src/widgets/WritingDraftConversationWidget/shared/draft-plain-text.ts","../../src/widgets/WritingDraftConversationWidget/shared/draft-mail-link.ts","../../src/widgets/WritingDraftConversationWidget/shared/remark-draft-line-breaks.ts","../../src/widgets/WritingDraftConversationWidget/WritingDraftWidget/WritingDraftBody.tsx","../../src/widgets/WritingDraftConversationWidget/WritingDraftWidget/WritingDraftWidget.tsx","../../src/widgets/WritingDraftConversationWidget/WritingDraftConversationWidget.tsx","../../src/widgets/SuggestedActions/SuggestedActions.tsx","../../src/renderer/_agent-space/use-resolved-conversation-widget-agent-space-key.ts","../../src/renderer/_agent-space/agent-space-name.hydrator.ts","../../src/renderer/_agent-space/ConversationWidgetAgentSpaceHeader.tsx","../../src/renderer/_agent-space/ConversationWidgetAgentSpaceFrame.tsx","../../src/widgets/MultiChoiceConversationWidget/shared/multi-choice-widget-payload.ts","../../src/widgets/MultiChoiceConversationWidget/MultiChoiceConversationWidget.tsx","../../src/widgets/_shared/use-stack-when-wrapped.ts","../../src/widgets/QuickRepliesConversationWidget/shared/quick-replies-widget-payload.ts","../../src/widgets/QuickRepliesConversationWidget/QuickRepliesConversationWidget.tsx","../../src/widgets/ToolTraceConversationWidget/ToolTraceConversationWidget.tsx","../../src/widgets/CanvasWidgetCard/use-canvas-viable.ts","../../src/widgets/CanvasWidgetCard/CanvasWidgetCard.tsx","../../src/widgets/CanvasWidgetCard/CanvasWidgetSwitch.tsx","../../src/widgets/CanvasWidgetCard/canvas-for-message-widget.ts","../../src/widgets/ConversationSearchResultsConversationWidget/shared/search-hit-excerpt.ts","../../src/widgets/_shared/widget-payload-validation.ts","../../src/widgets/ConversationSearchResultsConversationWidget/shared/conversation-search-results-widget-payload.ts","../../src/widgets/ConversationSearchResultsConversationWidget/ConversationSearchResultsConversationWidget.tsx","../../src/widgets/WebSearchResultsConversationWidget/shared/web-search-results-widget-payload.ts","../../src/widgets/WebSearchResultsConversationWidget/WebSearchAnswer.tsx","../../src/widgets/WebSearchResultsConversationWidget/SourceFavicon.tsx","../../src/widgets/WebSearchResultsConversationWidget/shared/display-hostname.ts","../../src/widgets/WebSearchResultsConversationWidget/WebSearchSourcesList.tsx","../../src/widgets/WebSearchResultsConversationWidget/WebSearchReferences.tsx","../../src/widgets/WebSearchResultsConversationWidget/WebSearchResultsConversationWidget.tsx"],"sourcesContent":["import { createContext, useContext } from \"react\";\n\n/** Presentation scope, independent of hydration and a conversation's interactive/replay state. */\nexport const ConversationWidgetRenderContext = createContext<\"conversation\" | \"email\">(\"conversation\");\n\nexport const useIsEmailWidgetRender = () => useContext(ConversationWidgetRenderContext) === \"email\";\n","import { createContext, ReactNode, useContext, useMemo } from \"react\";\nimport { ConversationComposerWidget } from \"./conversation-composer-widget\";\nimport { CanvasOpenRequest, CanvasState, LastClosedCanvas } from \"./canvas/canvas-state\";\nimport type { CanvasCreatedEntity } from \"./canvas/canvas-reducers\";\n\n// The widget callbacks without the chat: their type, the no-op defaults, the context, the two hosts that need no chat\n// state and the hook every widget reads. `ConversationWidgetContext.tsx` adds the provider bound to the chat's state\n// partition and re-exports this module, so package code that renders widgets never loads the chat.\n\n/** A message of the transcript a widget reads (its id and author role); the chat's messages carry more. */\nexport interface ConversationWidgetTranscriptMessage {\n id?: number | string | null;\n role?: string | null;\n}\n\nexport type ChatEngagementMediaItem = {\n id?: number;\n publicUrl: string;\n publicThumbnailUrl?: string;\n type?: string;\n};\n\nexport type ChatEngagementMediaItems = ChatEngagementMediaItem[];\n\n/** A post or event the owner edits from the chat — the fields the edit widget reads off its payload. */\nexport type ChatEngagementTarget =\n | {\n kind: \"post\";\n id: number;\n title?: string;\n content?: string;\n status?: string;\n scheduleAt?: string;\n startDate?: string;\n endDate?: string;\n mediaItems?: ChatEngagementMediaItems;\n }\n | {\n kind: \"event\";\n id: number;\n title?: string;\n content?: string;\n status?: string;\n scheduleAt?: string;\n startDate?: string;\n endDate?: string;\n mediaItems?: ChatEngagementMediaItems;\n };\n\nexport interface OpenEngagementEditConversationWidgetPayload {\n target: ChatEngagementTarget;\n mode: \"edit\";\n}\n\n/**\n * What an opener passes to `openCanvas`: the request minus the two facts the PROVIDER knows better than any widget —\n * whether the viewport is wide enough for the split, and whether the host renders a canvas surface at all.\n */\nexport type CanvasOpenRequestFromOpener = Omit<CanvasOpenRequest, \"viewportViable\" | \"hostHasCanvasSurface\">;\n\nexport type InjectSignalOptions = {\n /**\n * The signal is context for the CURRENT turn (e.g. specialist instructions riding along a just-posted user\n * message) and must NOT drive its own agent turn / produce its own reply. The chat host delivers it only while a\n * turn is observed running — a signal appended mid-turn lands in the conversation history without re-driving the\n * agent (the backend only re-drives when the LAST message is an unanswered inbound). If no turn starts, the signal\n * is dropped.\n */\n withoutOwnAgentTurn?: boolean;\n /**\n * Overrides the server-side default signal source (FRONTEND_WIDGET_CLICK), e.g. the business-basics form\n * submit's own source.\n */\n signalSource?: string;\n /**\n * Who produced the signal. CUSTOMER_CLICK (the default when omitted): the customer pressed a widget button or CTA,\n * so the chat scrolls to follow the turn and a refusal (closed conversation, backend 400) goes on the error card.\n * PROGRAMMATIC: an effect or ride-along emitted it without a customer action (store-diff feedback, the\n * widget-invalid corrective, specialist instructions) — refusals are dropped silently, nothing scrolls.\n */\n signalOrigin?: \"CUSTOMER_CLICK\" | \"PROGRAMMATIC\";\n};\n\nexport interface ConversationWidgetCallbacks {\n /**\n * THE CANVAS MODEL. The canvas is data in the chat's slice\n * partition: a pointer to its anchor message (or page), an identity and a render generation — see\n * `canvas/canvas-state.ts`. `openCanvas` is the one way to open for all four origins; the opening rule\n * (`canvas/decide-canvas-open.ts`) decides inside the reducer. `closeCanvas(byCustomer)` keeps the canvas re-openable\n * as `lastClosedCanvas`. The shell (`CanvasPane`) renders the body from `canvasBodies`; nothing else\n * holds a canvas.\n */\n canvas: CanvasState | null;\n /**\n * Whether this host renders a canvas surface at all. A mount-time opener reads it to tell \"the customer has no\n * canvas here\" from \"my request was dropped while the host was still coming up\" — the latter is worth asking again.\n */\n hostHasCanvasSurface: boolean;\n lastClosedCanvas: LastClosedCanvas | null;\n openCanvas: (request: CanvasOpenRequestFromOpener) => void;\n closeCanvas: (byCustomer: boolean) => void;\n /**\n * Re-open `lastClosedCanvas` as a customer action (origin `cardClick`): the canvas toggle button on the divider, the\n * narrow-viewport re-open control, the compact → expand path. No-op when nothing was closed.\n */\n reopenLastClosedCanvas: () => void;\n /**\n * A body created its entity (the post editor's draft): remember the id on the canvas it was created for, so a\n * re-open or a restore edits that entity instead of creating another. Identity + generation checked in the reducer.\n */\n setCanvasCreatedEntityId: (created: CanvasCreatedEntity) => void;\n /**\n * Contracts (minimizes) the host drawer/modal so the app behind stays\n * visible during navigation. Called by the Navigate tool before animating.\n * No-op by default; hosts that support compacting override this.\n */\n minimizeChatHost: () => void;\n /**\n * Forget the canvas and the last closed one — a conversation switch, where the previous conversation's canvas is\n * stale outright (`clearCanvas` in the canvas model; the LEFT conversation keeps its stored pointer).\n */\n resetCanvas: () => void;\n /**\n * The SEND boundary of the canvas model, called by the shell on a typed send (the hosts call it for widget sends\n * too): a `turn` canvas is over for good, a `pinned` canvas stays open — see `canvas-reducers.ts`.\n */\n resetCanvasForNewTurn: () => void;\n /**\n * Post the message as a visible USER bubble and drive one agent turn — the widget-button twin of the typed input.\n * Mirrors `injectSignal`'s contract: a host may return a promise resolving to `true` only once the send was\n * actually accepted (dispatched/posted), `false` when a caller-side guard dropped it (a closed conversation, an\n * in-flight start). `void`/no result counts as accepted for a host that doesn't report (e.g. Conversation.tsx) —\n * only a widget that explicitly awaits `false` must keep its controls usable.\n */\n sendMessageToChat: (message: string) => void | Promise<boolean>;\n /**\n * Put text into the chat's composer (the message input) and focus it, WITHOUT sending — the widget-button twin\n * of a host-owned control using `ConversationMessageInputHandle.insertTextIntoInput` directly (e.g. the agent \"+\"\n * menu's \"Generate image\" entry). Used by a widget option that is a TEMPLATE with a blank the owner must still\n * fill in (QuickReplies' placeholder-option pill): sending it as-is would post the literal blank as the owner's\n * message. No-op by default; hosts that own a chat input wire it to that input's imperative handle.\n */\n prefillComposer: (text: string) => void;\n /**\n * Inject a model-visible / user-invisible SIGNAL into the CURRENT conversation and drive one agent turn. Unlike\n * `sendMessageToChat` (which posts a visible USER message), this does NOT render a chat bubble — it tells the agent\n * something happened (e.g. \"User selected image A\") and lets it continue. The reply lands via the existing realtime\n * signal, exactly like a posted message. Set by chat hosts that own a conversation id; no-op by default.\n * Hosts may return a promise resolving to true only after the signal was accepted. False or no result\n * means delivery is not confirmed; callers that retire controls must wait for true.\n */\n injectSignal: (signalText: string, options?: InjectSignalOptions) => void | Promise<boolean>;\n /**\n * Key of the agent space the chat is scoped to. Set by hosts that mount the chat outside a\n * route of the agent space (e.g. a host whose panel opens on a page with no agent space\n * in the URL). Widget hydrators fall back to this when the URL path / active-agent-space\n * store can't supply one — without it they fetch with a missing key and every section 404s.\n * Undefined for in-route hosts, which keep their existing behavior.\n */\n chatAgentSpaceKey?: number;\n /**\n * Whether the chat's agent turn is RUNNING right now (the slice partition's `aiThinking`). A status widget whose\n * backing run is still open reads this to tell \"being applied\" from \"paused — waiting for the owner's reply\": the\n * turn ended (a question, a step budget notice) while the run stays open. Read from the provider's slice, never\n * passed by a host.\n */\n isConversationRunning: boolean;\n /**\n * The conversation's run is over (`runState` COMPLETED or CANCELLED): the backend rejects further input. Read from\n * the provider's slice, for a canvas body, which gets no per-message `interactive` flag.\n */\n isConversationClosed: boolean;\n /**\n * Conversation id the chat is currently showing. Set by hosts that know it (AgentChat). Scopes the stored canvas\n * pointer (`canvas/canvasStorage.ts`) — undefined on hosts that don't set it simply means the canvas does not come\n * back after a reload there.\n */\n conversationId?: number;\n /**\n * Composer widgets currently held in the chat input — the composer-side twin of a rendered widget (a widget\n * instance that lives in the input before send; see `ConversationComposerWidget`). Rendered by the generic\n * `ConversationMessageInputComposerWidgets` strip via each entry's registry `composerComponent`.\n *\n * Always a concrete array (never undefined on the context value itself — only the CALLBACKS prop a host supplies\n * is optional, deciding ownership):\n * - **Controlled** — a host passes `composerWidgets` (e.g. an app's builder page, whose preview\n * is a *sibling* of `<Conversation>`). Every mutation below is then routed to the host's\n * `onComposerWidgetsChange(next)` instead of local state.\n * - **Uncontrolled** — the host omits it (every chat-as-host surface today). The provider owns a\n * `useState<ConversationComposerWidget[]>([])` and a *descendant* (e.g. an app's editor drawer) mutates it\n * directly via the functions below.\n */\n composerWidgets: ConversationComposerWidget[];\n /** Add a new composer widget (or the first element of one); returns its client-only `composerWidgetId`. */\n addComposerWidget: (widgetName: string, fields: Record<string, unknown>) => string;\n /** Replace one composer widget's fields in place (e.g. drop one element out of several). */\n replaceComposerWidgetFields: (composerWidgetId: string, fields: Record<string, unknown>) => void;\n /** Remove one composer widget entirely (its ✕, or Backspace when it has no removable parts left). */\n removeComposerWidget: (composerWidgetId: string) => void;\n /** Remove every composer widget — called on send. */\n clearComposerWidgets: () => void;\n /**\n * Controlled-mode sink: called with the FULL next array on every composer-widget mutation\n * (add/replace/remove/clear). Ignored (mutations apply to local state instead) when the host doesn't also pass\n * `composerWidgets`.\n */\n onComposerWidgetsChange?: (next: ConversationComposerWidget[]) => void;\n /* Jump to a past conversation (and, when a hit is clicked, scroll to that message by id). Set by chat hosts that can\n * switch the active conversation (a host) — used by the ConversationSearchResults widget's open-arrow. Undefined →\n * the arrow is a no-op (e.g. hosts with no conversation switcher).\n */\n onOpenConversation?: (conversationId: number, messageId?: number) => void;\n /**\n * Switch THIS chat to another conversation of the same agent space in place (no new tab) — the door a widget that links\n * to related work (\"Open the conversation\") takes when that conversation belongs to the agent space the chat is open\n * on. Undefined on hosts without a conversation switcher.\n */\n onSwitchConversation?: (conversationId: number) => void;\n /**\n * True while the chat is the guided first-run setup: the host mounts the agent on ONE conversation it may not\n * leave (the full-page setup route) AND that conversation's purpose declares a customer progress stepper — the\n * same presence contract the stepper itself renders on (no purpose-name checks in the frontend). Widgets read it\n * to offer setup-only affordances, e.g. a connect widget's \"Skip for now\" deferral. False on every\n * other surface (the floating widget, the website builder, a purposed setup conversation reopened from history).\n */\n isOnboardingSetupConversation?: boolean;\n /**\n * The transcript this widget lives in, read from the door's own partition (`sliceInstance.selectState`) — the same\n * source `canvas` above reads. `null` before the conversation loads. A one-shot widget (e.g. QuickReplies) reads\n * this to tell \"the owner already answered a later question\" from its own `messageId`: any message with\n * `role === \"USER\"` AFTER the widget's host message means the widget is stale, regardless of `interactive` (which\n * stays true for the whole live session, not just until the next owner message).\n */\n messages: ConversationWidgetTranscriptMessage[] | null;\n}\n\nexport const defaultConversationWidgetCallbacks: ConversationWidgetCallbacks = {\n canvas: null,\n hostHasCanvasSurface: false,\n lastClosedCanvas: null,\n openCanvas: () => {},\n closeCanvas: () => {},\n reopenLastClosedCanvas: () => {},\n setCanvasCreatedEntityId: () => {},\n resetCanvas: () => {},\n resetCanvasForNewTurn: () => {},\n sendMessageToChat: () => {},\n prefillComposer: () => {},\n injectSignal: () => {},\n minimizeChatHost: () => {},\n chatAgentSpaceKey: undefined,\n isConversationRunning: false,\n isConversationClosed: false,\n conversationId: undefined,\n composerWidgets: [],\n addComposerWidget: () => \"\",\n replaceComposerWidgetFields: () => {},\n removeComposerWidget: () => {},\n clearComposerWidgets: () => {},\n isOnboardingSetupConversation: false,\n messages: null,\n};\n\n/** The widget callbacks a chat host (or a standalone host) supplies to every widget below it. */\nexport const ConversationWidgetContext = createContext<ConversationWidgetCallbacks>(defaultConversationWidgetCallbacks);\n\n/** Static capture host: no conversation, persistence, canvas effects or action callbacks. */\nexport const ReadOnlyConversationWidgetProvider = (props: { children: ReactNode; agentSpaceKey: number }) => {\n const { children, agentSpaceKey } = props;\n return (\n <ConversationWidgetContext.Provider value={{ ...defaultConversationWidgetCallbacks, chatAgentSpaceKey: agentSpaceKey }}>\n {children}\n </ConversationWidgetContext.Provider>\n );\n};\n\n/**\n * A host outside the chat that supplies its OWN callbacks — the widget preview keeps its canvas and its\n * composer log itself. Every callback it leaves out keeps the no-op default; no conversation slice is involved.\n */\nexport const StandaloneConversationWidgetProvider = (props: {\n children: ReactNode;\n callbacks: Partial<ConversationWidgetCallbacks>;\n}) => {\n const { children, callbacks } = props;\n const value = useMemo(() => ({ ...defaultConversationWidgetCallbacks, ...callbacks }), [callbacks]);\n return <ConversationWidgetContext.Provider value={value}>{children}</ConversationWidgetContext.Provider>;\n};\n\nexport const useConversationWidgetContext = () => useContext(ConversationWidgetContext);\n","import { getWidgetSelfHydrationKeyFieldName } from \"../../provider/environment\";\n\n/** The key of a widget block's agent space as it arrives: a string from a markdown attribute, a number from a block field. */\nexport type WidgetAgentSpaceKeyAttribute = string | number | undefined;\n\n/**\n * Reads the key of the agent space a widget block names: the value of the block field the app declares\n * (`AgentsEnvironment.widgetSelfHydrationKeyFieldName`), among a widget's props or a block's fields. Undefined when the\n * block names none.\n */\nexport const readWidgetAgentSpaceKeyAttribute = (propsOrFields: object): WidgetAgentSpaceKeyAttribute => {\n const attribute = (propsOrFields as Record<string, unknown>)[getWidgetSelfHydrationKeyFieldName()];\n return typeof attribute === \"string\" || typeof attribute === \"number\" ? attribute : undefined;\n};\n\n/**\n * The props that hand a widget the key of its agent space under the block field the app declares, exactly as a\n * markdown attribute would carry it; no prop without a key.\n */\nexport const buildWidgetAgentSpaceKeyProps = (\n agentSpaceKeyAttribute: WidgetAgentSpaceKeyAttribute,\n): Record<string, string | number> =>\n agentSpaceKeyAttribute === undefined || agentSpaceKeyAttribute === \"\"\n ? {}\n : { [getWidgetSelfHydrationKeyFieldName()]: agentSpaceKeyAttribute };\n","import type { CanvasId } from \"./canvas-behaviours\";\n\n/**\n * The canvas STATE — plain, readonly, serialisable data (it lives in the Redux store, where RTK + Immer forbid class\n * instances). The value-object behaviour — invariants, equality, the transitions — lives in the pure functions of this\n * module and of `decide-canvas-open.ts` / `canvas-reducers.ts`.\n *\n * The canvas is a POINTER to its anchor: the data a canvas body needs already lives in the transcript — the\n * widget's fence in the anchor message is persisted, loaded and rendered. The shell finds the anchor message in the\n * loaded list, parses the fence with the widget's own parser and renders the body from the result. Nothing about the\n * content is stored a second time. A page-opened canvas (an app's editor opened from its page) has no message; its\n * anchor is the agent space and the body hydrates from it.\n */\nexport type CanvasAnchor =\n | { readonly kind: \"message\"; readonly messageId: number }\n | { readonly kind: \"page\"; readonly agentSpaceKey: number };\n\n/**\n * How a canvas came to be open — the one question the opening rule asks (`decide-canvas-open.ts`):\n * - `deliveredInMessage` a canvas widget in a message delivered live (`justDelivered`); replay never opens one\n * - `cardClick` the customer clicked a card in the transcript, or the canvas toggle button on the divider\n * - `openedByPage` a page handed the tool over (`openAgentWithWidget` / `?agentWidget=`)\n * - `restoredAfterReload` the pointer stored for this conversation, on the mount of the conversation\n * A restored or page-opened canvas never runs a body's creation side effects (a post editor with no created entity\n * renders its empty state instead of creating a draft).\n */\nexport type CanvasOrigin = \"deliveredInMessage\" | \"cardClick\" | \"openedByPage\" | \"restoredAfterReload\";\n\n/** The identity of a canvas: WHICH canvas, and which instance of it. Two canvases with the same identity are one. */\nexport interface CanvasIdentity {\n readonly canvasId: CanvasId;\n /**\n * Distinguishes instances of one canvas: lists per message (+ occurrence in the message), a work surface per\n * agent space, an entity editor or detail per entity. Built with the helpers below.\n * Never includes the conversation id — a cold chat receives its id after the first send.\n */\n readonly instanceId: string;\n}\n\nexport interface CanvasState extends CanvasIdentity {\n readonly anchor: CanvasAnchor;\n readonly origin: CanvasOrigin;\n /**\n * Bumped on every accepted open (also of the same identity from a card click) so the shell keys the body on it: a\n * list re-opened with other filters remounts and re-runs its mount effects. Monotonic within the conversation.\n */\n readonly mountGeneration: number;\n /**\n * The one datum not in a message: the id of the entity a body CREATED after opening (the post editor's draft).\n * Written back by `setCanvasCreatedEntityId`; a restored editor with no id renders its empty state.\n */\n readonly createdEntityId?: number;\n}\n\n/**\n * The canvas that was open last and is not open now — what the canvas toggle button on the divider, the narrow-\n * viewport re-open control and the compact → expand path re-open. `closedByCustomer` is the customer's veto: a live\n * delivery of the SAME identity is ignored until a send, a card click or a page hand-over clears it.\n */\nexport interface LastClosedCanvas extends CanvasIdentity {\n readonly anchor: CanvasAnchor;\n readonly mountGeneration: number;\n readonly closedByCustomer: boolean;\n readonly createdEntityId?: number;\n}\n\n/** What an opener hands to `openCanvas` — everything the opening rule needs to decide, nothing more. */\nexport interface CanvasOpenRequest extends CanvasIdentity {\n readonly anchor: CanvasAnchor;\n readonly origin: CanvasOrigin;\n /** The host message was delivered live right now (the widget's `justDelivered`). Irrelevant for other origins. */\n readonly justDelivered: boolean;\n /** The viewport is wide enough for the side split (`useCanvasViable`). */\n readonly viewportViable: boolean;\n /** The host renders the split at all (`disableSplitView` hosts have no canvas surface). */\n readonly hostHasCanvasSurface: boolean;\n /** Carried by a restored pointer so a re-opened editor keeps its created entity. */\n readonly createdEntityId?: number;\n}\n\nexport const sameCanvasIdentity = (a: CanvasIdentity, b: CanvasIdentity): boolean =>\n a.canvasId === b.canvasId && a.instanceId === b.instanceId;\n\nexport const sameCanvasAnchor = (a: CanvasAnchor, b: CanvasAnchor): boolean =>\n a.kind === \"message\" && b.kind === \"message\"\n ? a.messageId === b.messageId\n : a.kind === \"page\" && b.kind === \"page\"\n ? a.agentSpaceKey === b.agentSpaceKey\n : false;\n\nexport const messageAnchor = (messageId: number): CanvasAnchor => ({ kind: \"message\", messageId });\n\nexport const pageAnchor = (agentSpaceKey: number): CanvasAnchor => ({ kind: \"page\", agentSpaceKey });\n\n/** A list-like canvas: one instance per message, and per occurrence when a message carries the widget twice. */\nexport const canvasInstanceIdForMessage = (canvasId: CanvasId, messageId: number, occurrence = 0): string =>\n occurrence > 0 ? `${canvasId}:message:${messageId}:${occurrence}` : `${canvasId}:message:${messageId}`;\n\n/** A work surface unique per agent space (an app's editor): a later card for the same agent space never replaces it. */\nexport const canvasInstanceIdForAgentSpace = (canvasId: CanvasId, agentSpaceKey: number): string =>\n `${canvasId}:agentSpace:${agentSpaceKey}`;\n\n/**\n * A short, stable, dependency-free hash of a string (djb2, base 36) — identifies a widget's payload inside a message\n * without storing the payload. Not cryptographic; two payloads colliding would only merge two identical-looking\n * canvases of one message.\n */\nexport const shortStringHash = (value: string): string => {\n let hash = 5381;\n for (let index = 0; index < value.length; index += 1) {\n hash = ((hash << 5) + hash + value.charCodeAt(index)) | 0;\n }\n return (hash >>> 0).toString(36);\n};\n\n/**\n * A canvas opened by a widget WITH a payload (a list with filters, a search result): one instance per message and\n * payload, so two different widgets of one kind in one message are two canvases while two identical ones are one.\n * The body finds its fence again through the hash (`findWidgetFenceByPayloadHash`).\n */\nexport const canvasInstanceIdForMessagePayload = (canvasId: CanvasId, messageId: number, payload: string): string =>\n `${canvasId}:message:${messageId}:${shortStringHash(payload)}`;\n\n/** The payload hash a message+payload instance id carries, or undefined for another shape of instance id. */\nexport const payloadHashOfInstanceId = (instanceId: string): string | undefined => {\n const match = /^[a-zA-Z]+:message:\\d+:([0-9a-z]+)$/.exec(instanceId);\n return match ? match[1] : undefined;\n};\n\n/** The same work surface when no agent space key is known at open time (the body resolves the active agent space itself). */\nexport const canvasInstanceIdForActiveAgentSpace = (canvasId: CanvasId): string => `${canvasId}:agentSpace:active`;\n\n/** An editor / detail unique per entity (post, event, schedule). */\nexport const canvasInstanceIdForEntity = (canvasId: CanvasId, entityId: number): string =>\n `${canvasId}:entity:${entityId}`;\n\n/** The entity id an entity instance id carries, or undefined for another shape of instance id. */\nexport const entityIdOfInstanceId = (instanceId: string): number | undefined => {\n const match = /^[a-zA-Z]+:entity:(\\d+)$/.exec(instanceId);\n return match ? Number(match[1]) : undefined;\n};\n\n/** True when the anchor message of a canvas is among the loaded messages (a restored pointer must point somewhere). */\nexport const isCanvasAnchorLoaded = (\n anchor: CanvasAnchor,\n loadedMessageIds: ReadonlyArray<number | undefined | null>,\n): boolean => anchor.kind === \"page\" || loadedMessageIds.includes(anchor.messageId);\n","import { createContext, useContext, useEffect } from \"react\";\n\n/**\n * The render report of one widget block: after mount every block says whether it showed what it should —\n * `mounted`, `empty` (hydrated, nothing to show), `failed` (error boundary, hydration error, invalid tree) or `pending`\n * (still waiting for data; never a final answer). The chat host collects the statuses per message and tells the model\n * about the blocks that are not `mounted` (the `FRONTEND_WIDGET_RENDER_REPORT` signal). A widget reports\n * through {@link useReportWidgetRenderStatus}; a widget that reports nothing counts as `mounted` once it rendered\n * without throwing.\n */\n\nexport type WidgetRenderStatus = \"mounted\" | \"empty\" | \"failed\" | \"pending\";\n\n/**\n * Why a block is not `mounted`. The tree codes are the backend's (`ComposedViewValidationFinding`); the runtime codes\n * name what went wrong in the browser.\n */\nexport type WidgetRenderReportCode =\n | \"INVALID_NODE\"\n | \"INVALID_PROP\"\n | \"UNKNOWN_BINDING\"\n | \"INVALID_EXPRESSION\"\n | \"INVALID_STATE\"\n | \"INVALID_ACTION\"\n | \"BUDGET_EXCEEDED\"\n | \"INLINE_VALUE_WITHOUT_SOURCE\"\n | \"INVALID_INITIAL_CHOICE\"\n | \"UNREAD_STATE\"\n | \"UNKNOWN_ITEM_KEY\"\n | \"INVALID_SLOT_NODE_COUNT\"\n | \"WIDGET_LIFTED\"\n | \"UNRESOLVED_BINDING\"\n | \"UNRESOLVED_REF\"\n | \"HYDRATION_FAILED\"\n | \"RENDER_FAILED\"\n | \"NO_DATA\";\n\nexport interface WidgetRenderReportEntry {\n status: WidgetRenderStatus;\n code?: WidgetRenderReportCode;\n /** One short English sentence for the model (what was dropped / what failed); never customer data beyond names. */\n detail?: string;\n}\n\n/** What a block reports into — provided by the chat host per block; absent = nobody listens (a story, a test). */\nexport interface WidgetRenderReporter {\n report: (entry: WidgetRenderReportEntry) => void;\n}\n\nexport const WidgetRenderReportContext = createContext<WidgetRenderReporter | null>(null);\n\n/** Reports the block's status whenever it changes; a no-op without a reporter. */\nexport const useReportWidgetRenderStatus = (\n status: WidgetRenderStatus,\n code?: WidgetRenderReportCode,\n detail?: string,\n): void => {\n const reporter = useContext(WidgetRenderReportContext);\n useEffect(() => {\n reporter?.report({ status, ...(code ? { code } : {}), ...(detail ? { detail } : {}) });\n }, [reporter, status, code, detail]);\n};\n\n/** The reporter itself, for a widget that reports from an event (a failed action) rather than from a render. */\nexport const useWidgetRenderReporter = (): WidgetRenderReporter | null => useContext(WidgetRenderReportContext);\n","import { useAgentsStateSelector } from \"../../provider/AgentsProvider\";\nimport type { WidgetHydrationSliceState, WidgetMemory } from \"./widget-hydration.types\";\n\n// The reducer and its action creators live in `widget-hydration.reducer.ts` (no provider import, so the package's\n// default state store can build on them); this module adds the hooks that read the state through the provider.\nexport { WidgetHydrationReducer, WidgetHydrationSlice } from \"./widget-hydration.reducer\";\n\n/** A store state that carries the widget hydration state. */\ninterface StateWithWidgetHydration {\n AIExtensionsWidgetHydration?: WidgetHydrationSliceState;\n}\n\nexport const selectWidgetMemory = (key: string) => {\n return (state: StateWithWidgetHydration): WidgetMemory | undefined => {\n return state.AIExtensionsWidgetHydration?.widgets[key];\n };\n};\n\nexport const useWidgetMemory = (key: string) => {\n return useAgentsStateSelector((state: StateWithWidgetHydration) => {\n return state.AIExtensionsWidgetHydration?.widgets[key];\n });\n};\n","import { RegisteredWidget, WidgetHydratorOptions } from \"./widget-hydration.types\";\n\nconst registry = new Map<string, RegisteredWidget<any, any>>();\n\nconst defaultIsEqual = <TPayload>(prev: TPayload | undefined, next: TPayload): boolean => {\n if (prev === next) {\n return true;\n }\n try {\n return JSON.stringify(prev) === JSON.stringify(next);\n } catch {\n return false;\n }\n};\n\nexport const registerWidgetHydrator = <TPayload = unknown, TData = unknown>(\n type: string,\n options: WidgetHydratorOptions<TPayload, TData>,\n): void => {\n if (registry.has(type)) {\n console.warn(`[widget-hydration] Hydrator for \"${type}\" already registered. Overwriting.`);\n }\n\n registry.set(type, {\n hydrator: options.hydrator,\n deriveKey:\n options.deriveKey ??\n ((t) => {\n return t;\n }),\n isPayloadEqual: options.isPayloadEqual ?? defaultIsEqual,\n refetchOnNewInstance: options.refetchOnNewInstance ?? false,\n staleMs: options.staleMs ?? Number.POSITIVE_INFINITY,\n });\n};\n\nexport const getWidgetHydrator = <TPayload = unknown, TData = unknown>(\n type: string,\n): RegisteredWidget<TPayload, TData> | undefined => {\n return registry.get(type) as RegisteredWidget<TPayload, TData> | undefined;\n};\n\nexport const hasWidgetHydrator = (type: string): boolean => {\n return registry.has(type);\n};\n\n/** Every registered hydrator type — the widget preview answers them from its fixture (`widget-preview-hydration.ts`). */\nexport const listWidgetHydratorTypes = (): string[] => [...registry.keys()];\n\nexport const unregisterWidgetHydrator = (type: string): void => {\n registry.delete(type);\n};\n","import { createContext, useContext } from \"react\";\nimport type { createWidgetImageReadiness } from \"./widget-image-readiness\";\n\n/** Null in the regular app. Supplied results apply only in explicit frozen-test mode. */\nexport const WidgetImageRenderContext = createContext<Record<string, unknown> | null>(null);\nexport const useWidgetImageRender = () => useContext(WidgetImageRenderContext);\nexport const WidgetImageLiveHydrationContext = createContext(false);\nexport const useWidgetImageLiveHydration = () => useContext(WidgetImageLiveHydrationContext);\nexport const WidgetImageReadinessContext = createContext<ReturnType<typeof createWidgetImageReadiness> | null>(null);\n\nexport const readFrozenHydration = (hydration: Record<string, unknown>, type: string, key: string): unknown => {\n if (Object.prototype.hasOwnProperty.call(hydration, key)) return hydration[key];\n if (Object.prototype.hasOwnProperty.call(hydration, type)) return hydration[type];\n throw new Error(\"MISSING_FROZEN_HYDRATION\");\n};\n","import {\n readFrozenHydration,\n useWidgetImageRender,\n useWidgetImageLiveHydration,\n} from \"../../image-render/WidgetImageRenderContext\";\nimport { useCallback, useEffect, useId, useRef } from \"react\";\nimport { useAgentsStateDispatch } from \"../../provider/AgentsProvider\";\nimport { getWidgetHydrator } from \"./widget-hydration.registry\";\nimport { WidgetHydrationSlice, useWidgetMemory } from \"./widget-hydration.slice\";\nimport { WidgetHydrationStatus } from \"./widget-hydration.types\";\n\ninterface RuntimeEntry {\n controller: AbortController | null;\n refreshPending?: boolean;\n nextRequestId: number;\n /** Last payload handled for this key — compared via the hydrator's `isPayloadEqual`. */\n lastPayload: unknown;\n /** True once `lastPayload` has been set (distinguishes \"never handled\" from an undefined payload). */\n hasLastPayload: boolean;\n /**\n * RequestId of the currently in-flight fetch. Used to re-sync Redux memory\n * (which may have been wiped by `allWidgetsReset`) when a later instance\n * dedupes onto the same in-flight request — otherwise the success/failure\n * dispatch is dropped by the requestId guard.\n */\n inFlightRequestId: number | null;\n}\n\nconst runtime = new Map<string, RuntimeEntry>();\n\nconst getRuntime = (key: string): RuntimeEntry => {\n let entry = runtime.get(key);\n if (!entry) {\n entry = {\n controller: null,\n nextRequestId: 0,\n lastPayload: undefined,\n hasLastPayload: false,\n inFlightRequestId: null,\n };\n runtime.set(key, entry);\n }\n return entry;\n};\n\n/**\n * Aborts the in-flight read of each key and forgets the key, so the next mount reads anew instead of joining a read\n * that no store waits for any more. Test support: the hydration stand-ins call it when they are restored.\n */\nexport const abandonWidgetHydrationReads = (keys: Iterable<string>): void => {\n for (const key of keys) {\n runtime.get(key)?.controller?.abort();\n runtime.delete(key);\n }\n};\n\nexport interface UseWidgetHydrationResult<TData> {\n data: TData | null;\n status: WidgetHydrationStatus;\n isLoading: boolean;\n isError: boolean;\n error: string | null;\n /** Generation of the request the memory last started or settled (0 = none): newer results carry a higher id. */\n requestId: number;\n refetch: () => void;\n}\n\nexport interface UseWidgetHydrationOptions {\n /**\n * When true, force a fetch on the first render of this instance even if\n * memory holds a successful result for the same key. Used to honor the\n * `fresh` widget prop (streamed agent message → refetch; history\n * replay → reuse cache).\n */\n forceRefresh?: boolean;\n /**\n * Keep rendering the last loaded data for this key while a fetch runs, instead of the loading state. The fetch still\n * runs (and its result replaces the data); only a key with no data yet shows loading. For a snapshot whose copy may\n * already be on screen elsewhere — another agent window opening the same briefing.\n */\n showLastDataWhileRefreshing?: boolean;\n}\n\nexport const useWidgetHydration = <TData = unknown, TPayload = unknown>(\n type: string,\n payload: TPayload,\n options: UseWidgetHydrationOptions = {},\n): UseWidgetHydrationResult<TData> => {\n const { forceRefresh = false, showLastDataWhileRefreshing = false } = options;\n const dispatch = useAgentsStateDispatch();\n const instanceId = useId();\n\n const frozenHydration = useWidgetImageRender();\n const liveCapture = useWidgetImageLiveHydration();\n const hydrator = getWidgetHydrator<TPayload, TData>(type);\n const key = hydrator?.deriveKey(type, payload) ?? type;\n const registered = frozenHydration === null || liveCapture ? hydrator : undefined;\n\n const memory = useWidgetMemory(key);\n\n const runHydrationRef = useRef<((force: boolean) => void) | null>(null);\n const runHydration = useCallback(\n (force: boolean) => {\n if (!registered) {\n console.warn(`[widget-hydration] No hydrator registered for \"${type}\"`);\n return;\n }\n\n const entry = getRuntime(key);\n\n dispatch(WidgetHydrationSlice.instanceAttached({ key, instanceId }));\n\n // ONE in-flight request per key: a second consumer JOINS it instead of aborting it — an abort here cancelled a\n // sibling widget's read of the same run and left its memory in \"error\". A FORCED refresh\n // that meets an in-flight request is not dropped either: it is remembered and issued as a new generation the\n // moment the in-flight one settles, so a refresh after a mutation never accepts the older snapshot as fresh.\n if (entry.controller) {\n if (force) {\n entry.refreshPending = true;\n }\n return;\n }\n const controller = new AbortController();\n entry.controller = controller;\n const requestId = ++entry.nextRequestId;\n entry.inFlightRequestId = requestId;\n\n dispatch(\n WidgetHydrationSlice.hydrationStarted({\n key,\n instanceId,\n requestId,\n }),\n );\n\n registered\n .hydrator(payload, { signal: controller.signal })\n .then((data) => {\n if (controller.signal.aborted) {\n return;\n }\n entry.controller = null;\n entry.inFlightRequestId = null;\n dispatch(WidgetHydrationSlice.hydrationSucceeded({ key, requestId, data }));\n if (entry.refreshPending) {\n entry.refreshPending = false;\n runHydrationRef.current?.(true);\n }\n })\n .catch((err: unknown) => {\n if (controller.signal.aborted) {\n return;\n }\n entry.controller = null;\n entry.inFlightRequestId = null;\n const message = err instanceof Error ? err.message : String(err);\n dispatch(WidgetHydrationSlice.hydrationFailed({ key, requestId, error: message }));\n if (entry.refreshPending) {\n entry.refreshPending = false;\n runHydrationRef.current?.(true);\n }\n });\n },\n [dispatch, instanceId, key, payload, registered, type],\n );\n\n runHydrationRef.current = runHydration;\n\n const payloadJson = (() => {\n try {\n return JSON.stringify(payload);\n } catch {\n return null;\n }\n })();\n\n const lastHandledPayloadRef = useRef<string | null>(null);\n\n useEffect(() => {\n if (!registered) {\n return;\n }\n const entry = getRuntime(key);\n\n // Payload comparison goes through the hydrator's `isPayloadEqual` (e.g. only\n // the raw payload and the agent space key) so key-order/normalization noise in derived\n // payload fields doesn't trigger spurious refetches.\n const payloadChanged =\n !entry.hasLastPayload || !registered.isPayloadEqual(entry.lastPayload as TPayload | undefined, payload);\n const isFirstMountForKey = memory === undefined;\n const isIdle = memory?.status === \"idle\" || !memory;\n const isStale =\n memory?.status === \"success\" &&\n memory.lastLoadedAt !== null &&\n Date.now() - memory.lastLoadedAt > registered.staleMs;\n\n dispatch(WidgetHydrationSlice.instanceAttached({ key, instanceId }));\n\n const isFirstRenderOfInstance = lastHandledPayloadRef.current === null;\n // `payloadChanged` applies on first render too — `willStartHydrationOnMount`\n // below already promises a fetch in that case (renders the skeleton), so\n // skipping it here would freeze the widget on its skeleton forever.\n const shouldStart =\n isFirstMountForKey ||\n isIdle ||\n isStale ||\n payloadChanged ||\n (forceRefresh && isFirstRenderOfInstance) ||\n (registered.refetchOnNewInstance && memory?.status === \"success\");\n\n if (shouldStart) {\n // Dedupe concurrent mounts: if a request for this key is already in-flight\n // with the same payload, attach this instance to it instead of firing a\n // duplicate (which would also abort the original via runHydration's force path).\n if (entry.controller && !payloadChanged) {\n // Re-sync memory's requestId with the in-flight fetch. Required when\n // `allWidgetsReset` wiped memory mid-flight — `instanceAttached` above\n // recreated memory with default `requestId=0`, so without this the\n // in-flight success/failure dispatch would be dropped by the guard.\n if (entry.inFlightRequestId !== null) {\n dispatch(\n WidgetHydrationSlice.hydrationStarted({\n key,\n instanceId,\n requestId: entry.inFlightRequestId,\n }),\n );\n }\n lastHandledPayloadRef.current = payloadJson;\n return;\n }\n entry.lastPayload = payload;\n entry.hasLastPayload = true;\n lastHandledPayloadRef.current = payloadJson;\n runHydration(true);\n } else {\n lastHandledPayloadRef.current = payloadJson;\n }\n // `memory === undefined` re-fires the effect if Redux memory is wiped\n // externally (e.g. `allWidgetsReset` on conversation switch) while this\n // instance was mid-flight — otherwise the in-flight fetch's result is\n // dropped by the requestId guard and the widget stays loading forever.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [key, payloadJson, memory === undefined]);\n\n const refetch = useCallback(() => {\n runHydration(true);\n }, [runHydration]);\n\n const status: WidgetHydrationStatus = memory?.status ?? \"idle\";\n\n // Synchronously determine whether *this render* will trigger hydration via\n // the effect below — so the caller can show the loading state on the first\n // render instead of briefly flashing stale `memory.data` from a previous\n // instance, then transitioning into the skeleton on the next render.\n const willStartHydrationOnMount = (() => {\n if (!registered) return false;\n if (lastHandledPayloadRef.current !== null) return false; // only on first render\n const entry = runtime.get(key);\n const payloadChanged =\n !entry || !entry.hasLastPayload || !registered.isPayloadEqual(entry.lastPayload as TPayload | undefined, payload);\n const isFirstMountForKey = memory === undefined;\n const isIdle = !memory || memory.status === \"idle\";\n const isStale =\n memory?.status === \"success\" &&\n memory.lastLoadedAt !== null &&\n Date.now() - memory.lastLoadedAt > registered.staleMs;\n return (\n isFirstMountForKey ||\n isIdle ||\n isStale ||\n payloadChanged ||\n forceRefresh ||\n (registered.refetchOnNewInstance && memory?.status === \"success\")\n );\n })();\n\n const showsLastData = showLastDataWhileRefreshing && memory?.data !== null && memory?.data !== undefined;\n const isLoading =\n !showsLastData && ((status === \"loading\" && memory?.loadingInstanceId === instanceId) || willStartHydrationOnMount);\n\n if (frozenHydration !== null && !liveCapture) {\n return {\n data: readFrozenHydration(frozenHydration, type, key) as TData | null,\n status: \"success\",\n isLoading: false,\n isError: false,\n error: null,\n requestId: 0,\n refetch: () => {},\n };\n }\n\n return {\n data: willStartHydrationOnMount && !showsLastData ? null : ((memory?.data ?? null) as TData | null),\n status,\n isLoading,\n isError: status === \"error\",\n error: memory?.error ?? null,\n requestId: memory?.requestId ?? 0,\n refetch,\n };\n};\n","import { Skeleton } from \"../../provider/components\";\nimport React from \"react\";\n\ninterface LineProps {\n width?: number | string;\n height?: number;\n radius?: number;\n className?: string;\n}\n\nexport const SkeletonLine = ({ width = \"100%\", height = 12, radius = 6, className }: LineProps) => {\n return <Skeleton className={className} style={{ width, height, borderRadius: radius, display: \"block\" }} />;\n};\n\ninterface CircleProps {\n size: number;\n className?: string;\n}\n\nexport const SkeletonCircle = ({ size, className }: CircleProps) => {\n return (\n <Skeleton\n className={className}\n style={{ width: size, height: size, borderRadius: \"50%\", display: \"inline-block\", flexShrink: 0 }}\n />\n );\n};\n\ninterface PillProps {\n width?: number | string;\n height?: number;\n className?: string;\n}\n\nexport const SkeletonPill = ({ width = 140, height = 34, className }: PillProps) => {\n return <Skeleton className={className} style={{ width, height, borderRadius: 999, display: \"inline-block\" }} />;\n};\n\nexport const SkeletonWidgetLabel = () => {\n return <SkeletonLine width={120} height={10} radius={4} />;\n};\n","import { classNames } from \"../../../provider/class-names\";\nimport type { ReactNode } from \"react\";\nimport styles from \"./WidgetSurface.module.scss\";\n\nexport type WidgetSurfaceLevel = \"elevated\" | \"flat\";\n\nexport interface WidgetSurfaceProps {\n children: ReactNode;\n /** `elevated` on the chat; `flat` for a tile inside a surface or anything inside a canvas pane. */\n level?: WidgetSurfaceLevel;\n /** The compact radius and padding pair, for small nested tiles. */\n compact?: boolean;\n className?: string;\n testId?: string;\n}\n\n/** The surface every modern widget and kit component sits on — one radius, one padding, one shadow per level. */\nexport const WidgetSurface = (props: WidgetSurfaceProps) => {\n const { children, level = \"elevated\", compact = false, className, testId } = props;\n return (\n <div\n data-surface-level={level}\n data-testid={testId}\n className={classNames(styles.surface, styles[level], compact && styles.compact, className)}\n >\n {children}\n </div>\n );\n};\n","import { classNames } from \"../../../provider/class-names\";\nimport styles from \"./WidgetKpiValue.module.scss\";\nimport { HeroRow, HeroValue, SkeletonText, WidgetText } from \"../../../provider/components\";\nimport type { ReactNode } from \"react\";\n\nexport interface WidgetKpiValueProps {\n /** The label above the number — business content, so the caller passes it already in the owner's language. */\n label: ReactNode;\n /** The formatted number (`2.4K`, `87 %`). */\n value: ReactNode;\n /** Lower-case, describes the number; never repeats the label. */\n unit?: ReactNode;\n /** The change indicator (`TrendDelta`), on the unit line. */\n delta?: ReactNode;\n loading?: boolean;\n valuePresentation?: \"hero\" | \"text\";\n /** A small status badge at the end of the label line. */\n accent?: ReactNode;\n /** A score visual (a meter) directly under the value. */\n meter?: ReactNode;\n testId?: string;\n}\n\n/**\n * The KPI value of the chat widgets and the kit's KPI node: the hero scale (the app's dashboard scale) (48px bold,\n * tabular, scaled down to fit) re-used, never a second type scale. The label is known before the data, so it is never\n * a skeleton. A text value sits in the same hero line box, so the lines under it align across a row of KPIs.\n */\nexport const WidgetKpiValue = (props: WidgetKpiValueProps) => {\n const { label, value, unit, delta, loading = false, valuePresentation = \"hero\", accent, meter, testId } = props;\n const labelText = (\n <WidgetText variant=\"caption\" tone=\"light\" translate={false} testId={testId && `${testId}-label`}>\n {label}\n </WidgetText>\n );\n return (\n <div className={styles.kpi}>\n {accent ? (\n <div className={styles.labelRow}>\n {labelText}\n {accent}\n </div>\n ) : (\n labelText\n )}\n <div\n className={classNames(styles.valueBlock, valuePresentation === \"text\" && styles.textBlock)}\n data-testid={testId && `${testId}-value-block`}\n >\n {loading ? (\n <SkeletonText width=\"3em\" height={48} />\n ) : valuePresentation === \"text\" ? (\n <WidgetText variant=\"headline\" translate={false} className={styles.textValue}>\n {value}\n </WidgetText>\n ) : (\n <HeroRow>\n <HeroValue>{value}</HeroValue>\n </HeroRow>\n )}\n </div>\n {meter && !loading ? meter : null}\n {(unit || delta) && !loading ? (\n <div className={styles.unitRow}>\n {unit ? (\n <WidgetText variant=\"caption\" tone=\"light\" translate={false} testId={testId && `${testId}-unit`}>\n {unit}\n </WidgetText>\n ) : null}\n {delta}\n </div>\n ) : null}\n </div>\n );\n};\n","import { useEffect } from \"react\";\nimport type { ExpressionValue } from \"../../../../renderer/widget-tree/expression/evaluate-expression\";\nimport type { ComposedViewRuntime } from \"../../../composed-view-component-types\";\n\n/**\n * The value readers the text components of the `ComposedView` kit share. A prop arrives with its binding\n * resolved, so it may be anything an expression yields — every reader takes `ExpressionValue` and never throws: a value\n * that does not fit gives `invalid`, a missing one `missing`, and the component renders nothing for both and reports it.\n */\n\n/** What a text prop holds: the text to show, nothing, or a value no text can be made of (an object, a list). */\nexport type TextNodeContent = { kind: \"text\"; text: string } | { kind: \"missing\" } | { kind: \"invalid\" };\n\n/** A string, a finite number or a boolean is text; `null`, `undefined` and the empty string are missing; the rest is invalid. */\nexport const readTextNodeContent = (value: ExpressionValue): TextNodeContent => {\n if (value === undefined || value === null) return { kind: \"missing\" };\n if (typeof value === \"string\") return value.trim() === \"\" ? { kind: \"missing\" } : { kind: \"text\", text: value };\n if (typeof value === \"number\")\n return Number.isFinite(value) ? { kind: \"text\", text: String(value) } : { kind: \"missing\" };\n if (typeof value === \"boolean\") return { kind: \"text\", text: String(value) };\n return { kind: \"invalid\" };\n};\n\n/** The value when it is one of `allowedValues`, else `fallback` — an enum prop bound to state may hold anything. */\nexport const readAllowedValue = <T extends string>(\n value: ExpressionValue,\n allowedValues: readonly T[],\n fallback: T,\n): T => (typeof value === \"string\" && (allowedValues as readonly string[]).includes(value) ? (value as T) : fallback);\n\n/**\n * The address when it is an absolute http(s) URL, else null — `javascript:`, `data:`, `mailto:`, a relative path and a\n * malformed string are never a link target in the kit (the `openUrl` action holds the same rule).\n */\nexport const readSafeHttpUrl = (value: ExpressionValue): string | null => {\n if (typeof value !== \"string\" || value.trim() === \"\") return null;\n try {\n const parsedUrl = new URL(value.trim());\n return parsedUrl.protocol === \"http:\" || parsedUrl.protocol === \"https:\" ? parsedUrl.href : null;\n } catch {\n return null;\n }\n};\n\nconst HOSTNAME_PATTERN = /^(?=.{1,253}$)([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z]{2,63}$/i;\n\n/** The site's host name (without `www.`) of an http(s) URL or a bare domain (`wdr.de`), else null. */\nexport const readSiteHostname = (value: ExpressionValue): string | null => {\n if (typeof value !== \"string\" || value.trim() === \"\") return null;\n const trimmedValue = value.trim();\n const httpUrl = readSafeHttpUrl(/^[a-z][a-z0-9+.-]*:/i.test(trimmedValue) ? trimmedValue : `https://${trimmedValue}`);\n if (httpUrl === null) return null;\n const hostname = new URL(httpUrl).hostname.replace(/^www\\./i, \"\");\n return HOSTNAME_PATTERN.test(hostname) ? hostname : null;\n};\n\n/** The favicon of a host, from the Google favicon service — the source the web search references use. */\nexport const buildFaviconUrl = (hostname: string): string =>\n `https://www.google.com/s2/favicons?domain=${encodeURIComponent(hostname)}&sz=32`;\n\n/** What one text node reports: still waiting for a bound value, shown, nothing to show, or a value it cannot show. */\nexport type TextNodeRenderState = \"pending\" | \"shown\" | \"empty\" | \"invalid\";\n\n/**\n * Reports a text node's render state into the block report whenever it changes — never a silent nothing:\n * `empty` when there is nothing to show, `failed INVALID_PROP` when the value cannot be shown, `pending` while a bound\n * value waits for its data.\n */\nexport const useReportTextNodeRenderState = (\n runtime: ComposedViewRuntime,\n renderState: TextNodeRenderState,\n nodeType: string,\n invalidDetail?: string,\n): void => {\n const { reportNodeStatus } = runtime;\n useEffect(() => {\n if (renderState === \"pending\") reportNodeStatus(\"pending\");\n if (renderState === \"shown\") reportNodeStatus(\"mounted\");\n if (renderState === \"empty\") reportNodeStatus(\"empty\", \"NO_DATA\", `the ${nodeType} has no text to show`);\n if (renderState === \"invalid\") {\n reportNodeStatus(\"failed\", \"INVALID_PROP\", invalidDetail ?? `the ${nodeType} got a value that is not text`);\n }\n }, [reportNodeStatus, renderState, nodeType, invalidDetail]);\n};\n\n/** The render state of a node whose one text prop decides it. */\nexport const readTextNodeRenderState = (isPending: boolean, content: TextNodeContent): TextNodeRenderState => {\n if (isPending) return \"pending\";\n if (content.kind === \"text\") return \"shown\";\n return content.kind === \"invalid\" ? \"invalid\" : \"empty\";\n};\n","import type { ReactNode } from \"react\";\nimport { useIsEmailWidgetRender } from \"../ConversationWidgetRenderContext\";\n\ninterface ConversationWidgetActionsProps {\n children: ReactNode;\n}\n\n/** Wrap the entire action area, including its footer/divider, to omit it from email images. */\nexport const ConversationWidgetActions = (props: ConversationWidgetActionsProps) => {\n const { children } = props;\n const isEmailRender = useIsEmailWidgetRender();\n return isEmailRender ? null : <>{children}</>;\n};\n","import { Button } from \"../../provider/components\";\nimport type { ComponentProps } from \"react\";\nimport { ConversationWidgetActions } from \"../../renderer/ConversationWidgetActions/ConversationWidgetActions\";\n\n/** An action button inside a widget; screenshots retain the content surrounding the action. */\nexport const ConversationWidgetButton = (props: ComponentProps<typeof Button>) => (\n <ConversationWidgetActions>\n <Button {...props} />\n </ConversationWidgetActions>\n);\n","import { Icon, Text } from \"../../provider/components\";\nimport { useEffect, useRef } from \"react\";\nimport styles from \"./DonePill.module.scss\";\n\ninterface DonePillProps {\n children: string;\n /** False for a label the agent wrote at runtime — only the static copy goes through the translator. */\n translate?: boolean;\n /** `neutral` for an answer that declined or cancelled: no check. */\n status?: \"success\" | \"neutral\";\n testId?: string;\n}\n\n/**\n * What was done, where the answer buttons were: one pill naming the action the owner chose. It takes the focus the\n * button had when that button unmounts with it; mount it inside a live region that was already there.\n */\nexport const DonePill = (props: DonePillProps) => {\n const { children, translate = true, status = \"success\", testId } = props;\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (document.activeElement === document.body) ref.current?.focus();\n }, []);\n\n return (\n <div ref={ref} tabIndex={-1} className={styles.pill} data-testid={testId}>\n {status === \"success\" && (\n <Icon pixelSize={14} color=\"var(--agents-success-500)\" name=\"check\" />\n )}\n <Text role=\"help\" weight=\"medium\" color=\"var(--agents-fg-light)\" translate={translate}>\n {children}\n </Text>\n </div>\n );\n};\n","import { Text } from \"../../provider/components\";\nimport { escapePlainTextForText } from \"../../provider/environment\";\nimport type { ComponentProps } from \"react\";\n\nexport type ModelTextProps = Omit<ComponentProps<typeof Text>, \"children\" | \"translate\"> & {\n /** The model's words — shown as written: never translated, never parsed as markup. */\n children: string;\n};\n\n/**\n * The component library's `Text` for a string the MODEL wrote (`model-text.ts`): `translate={false}` and the string\n * escaped, so `<b onmouseover=\"…\">` or `<link href=\"…\">` in a model's label renders as those characters. Every other\n * `Text` prop passes through.\n */\nexport const ModelText = (props: ModelTextProps) => {\n const { children, ...textProps } = props;\n return (\n <Text {...textProps} translate={false}>\n {escapePlainTextForText(children)}\n </Text>\n );\n};\n","/**\n * The time arithmetic of the `Clock` widget — pure functions over a `Date` and IANA zone ids, computed from the\n * browser's own time-zone data (`Intl.DateTimeFormat`), so nothing is fetched and daylight-saving changes come with the\n * browser. Every function is total: an unknown zone is filtered out before (see {@link isKnownTimeZone}).\n */\n\n/**\n * An IANA id with an area: `Europe/Berlin`, `America/Argentina/Buenos_Aires`, `Etc/GMT+9`. No raw offsets (`+01:00`).\n * Browsers also take abbreviations (`JST`, `IST`) through their ICU aliases — ambiguous across the world, so a\n * single-segment id counts only when it is one of the IANA names below (the backend class keeps the same list).\n */\nconst IANA_TIME_ZONE_WITH_AREA_SHAPE = /^[A-Za-z][A-Za-z0-9_+-]*(\\/[A-Za-z0-9_+-]+)+$/;\nconst IANA_TIME_ZONES_WITHOUT_AREA: ReadonlySet<string> = new Set([\n \"UTC\",\n \"GMT\",\n \"CET\",\n \"EET\",\n \"WET\",\n \"MET\",\n \"EST\",\n \"MST\",\n \"HST\",\n \"EST5EDT\",\n \"CST6CDT\",\n \"MST7MDT\",\n \"PST8PDT\",\n]);\n\n/** The local hours a sun is shown for (06:00–19:59); a moon outside them. */\nconst FIRST_DAYTIME_HOUR = 6;\nconst FIRST_NIGHT_HOUR = 20;\n\nconst MILLISECONDS_PER_MINUTE = 60_000;\nconst MILLISECONDS_PER_DAY = 86_400_000;\n\n/** One zone's wall clock at one instant. */\nexport interface ZonedWallClock {\n year: number;\n month: number;\n day: number;\n hour: number;\n minute: number;\n second: number;\n /** Minutes east of UTC at that instant (Berlin in winter: 60, New York in summer: -240). */\n utcOffsetMinutes: number;\n}\n\n/** Whether the place there is today, yesterday or tomorrow, seen from the owner's zone. */\nexport type ClockRelativeDay = \"today\" | \"yesterday\" | \"tomorrow\";\n\nconst wallClockFormatterByTimeZone = new Map<string, Intl.DateTimeFormat>();\n\nconst buildWallClockFormatter = (timeZone: string): Intl.DateTimeFormat => {\n const cachedFormatter = wallClockFormatterByTimeZone.get(timeZone);\n if (cachedFormatter) return cachedFormatter;\n const wallClockFormatter = new Intl.DateTimeFormat(\"en-US\", {\n timeZone,\n hourCycle: \"h23\",\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"numeric\",\n second: \"numeric\",\n });\n wallClockFormatterByTimeZone.set(timeZone, wallClockFormatter);\n return wallClockFormatter;\n};\n\n/** True when the browser knows the zone — the widget drops (and reports) every other id. */\nexport const isKnownTimeZone = (timeZone: string): boolean => {\n if (!IANA_TIME_ZONE_WITH_AREA_SHAPE.test(timeZone) && !IANA_TIME_ZONES_WITHOUT_AREA.has(timeZone)) return false;\n try {\n buildWallClockFormatter(timeZone);\n return true;\n } catch {\n return false;\n }\n};\n\n/** The zone's wall clock at `instant`; the UTC offset is the difference between that wall clock and UTC. */\nexport const readZonedWallClock = (instant: Date, timeZone: string): ZonedWallClock => {\n const partValueByType: Record<string, number> = {};\n for (const datePart of buildWallClockFormatter(timeZone).formatToParts(instant)) {\n if (datePart.type !== \"literal\") partValueByType[datePart.type] = Number(datePart.value);\n }\n const hour = (partValueByType.hour ?? 0) % 24;\n const wallClockAsUtcMilliseconds = Date.UTC(\n partValueByType.year ?? 1970,\n (partValueByType.month ?? 1) - 1,\n partValueByType.day ?? 1,\n hour,\n partValueByType.minute ?? 0,\n partValueByType.second ?? 0,\n );\n const instantWholeSecondMilliseconds = Math.floor(instant.getTime() / 1000) * 1000;\n return {\n year: partValueByType.year ?? 1970,\n month: partValueByType.month ?? 1,\n day: partValueByType.day ?? 1,\n hour,\n minute: partValueByType.minute ?? 0,\n second: partValueByType.second ?? 0,\n utcOffsetMinutes: Math.round(\n (wallClockAsUtcMilliseconds - instantWholeSecondMilliseconds) / MILLISECONDS_PER_MINUTE,\n ),\n };\n};\n\nconst readDayNumber = (wallClock: ZonedWallClock): number =>\n Math.round(Date.UTC(wallClock.year, wallClock.month - 1, wallClock.day) / MILLISECONDS_PER_DAY);\n\n/** The calendar day at the clock's place compared with the owner's: one day apart at most (UTC−12 … UTC+14). */\nexport const readRelativeDay = (clockWallClock: ZonedWallClock, ownerWallClock: ZonedWallClock): ClockRelativeDay => {\n const dayDifference = readDayNumber(clockWallClock) - readDayNumber(ownerWallClock);\n if (dayDifference > 0) return \"tomorrow\";\n if (dayDifference < 0) return \"yesterday\";\n return \"today\";\n};\n\n/** `+0`, `+8`, `−5`, `+5:30` — hours (and minutes) the clock's zone is ahead of the owner's. */\nexport const formatHourDifference = (differenceMinutes: number): string => {\n const sign = differenceMinutes < 0 ? \"−\" : \"+\";\n const absoluteMinutes = Math.abs(differenceMinutes);\n const hours = Math.floor(absoluteMinutes / 60);\n const minutes = absoluteMinutes % 60;\n return minutes === 0 ? `${sign}${hours}` : `${sign}${hours}:${String(minutes).padStart(2, \"0\")}`;\n};\n\n/** `UTC+1`, `UTC−4`, `UTC+5:30`, and `UTC` for no offset. */\nexport const formatUtcOffset = (utcOffsetMinutes: number): string =>\n utcOffsetMinutes === 0 ? \"UTC\" : `UTC${formatHourDifference(utcOffsetMinutes)}`;\n\n/** The sun is shown from 06:00 to 19:59 local time, the moon otherwise. */\nexport const isDaytime = (wallClock: ZonedWallClock): boolean =>\n wallClock.hour >= FIRST_DAYTIME_HOUR && wallClock.hour < FIRST_NIGHT_HOUR;\n\n/** The place a zone id names: `America/New_York` → `New York`, `UTC` → `UTC`. */\nexport const readCityOfTimeZone = (timeZone: string): string => {\n const zoneSegments = timeZone.split(\"/\");\n return (zoneSegments[zoneSegments.length - 1] ?? timeZone).replace(/_/g, \" \");\n};\n\nconst readShortZoneName = (instant: Date, timeZone: string, locale: string): string | undefined => {\n try {\n const zoneName = new Intl.DateTimeFormat(locale, { timeZone, timeZoneName: \"short\" })\n .formatToParts(instant)\n .find((datePart) => datePart.type === \"timeZoneName\")\n ?.value.trim();\n return zoneName && !/^(GMT|UTC)/.test(zoneName) ? zoneName : undefined;\n } catch {\n return undefined;\n }\n};\n\n/**\n * The browser's short zone name in the owner's locale (`MEZ`), else in US English (`EDT` — most locales name foreign\n * zones only by offset), or undefined when both know only an offset (`GMT+9`): the UTC offset has its own line anyway.\n */\nexport const readZoneAbbreviation = (instant: Date, timeZone: string, locale: string): string | undefined =>\n readShortZoneName(instant, timeZone, locale) ?? readShortZoneName(instant, timeZone, \"en-US\");\n\n/** The digital time: `02:58` (24 h, zero-padded) or `2:58` plus the locale's day period (`AM`, `PM`) for 12 h. */\nexport const formatDigitalTime = (\n wallClock: ZonedWallClock,\n timeFormat: \"24h\" | \"12h\",\n instant: Date,\n timeZone: string,\n locale: string,\n): { time: string; dayPeriod?: string } => {\n const minute = String(wallClock.minute).padStart(2, \"0\");\n if (timeFormat === \"24h\") return { time: `${String(wallClock.hour).padStart(2, \"0\")}:${minute}` };\n let dayPeriod: string | undefined;\n try {\n dayPeriod = new Intl.DateTimeFormat(locale, { timeZone, hour: \"numeric\", hour12: true })\n .formatToParts(instant)\n .find((datePart) => datePart.type === \"dayPeriod\")\n ?.value.trim();\n } catch {\n dayPeriod = undefined;\n }\n return {\n time: `${wallClock.hour % 12 || 12}:${minute}`,\n dayPeriod: dayPeriod || (wallClock.hour < 12 ? \"AM\" : \"PM\"),\n };\n};\n\n/** The date at the clock's place in the owner's date locale: `So., 26. Okt.` / `Sun, Oct 26`. */\nexport const formatZonedDate = (instant: Date, timeZone: string, dateLocale: string): string => {\n try {\n return new Intl.DateTimeFormat(dateLocale, { timeZone, weekday: \"short\", day: \"numeric\", month: \"short\" }).format(\n instant,\n );\n } catch {\n return \"\";\n }\n};\n\n/** The capture moment of an e-mail render, in the owner's zone and date locale: `26.10.2026, 02:58`. */\nexport const formatCaptureMoment = (instant: Date, timeZone: string, dateLocale: string, timeFormat: \"24h\" | \"12h\") => {\n try {\n return new Intl.DateTimeFormat(dateLocale, {\n timeZone,\n dateStyle: \"medium\",\n timeStyle: \"short\",\n hour12: timeFormat === \"12h\",\n }).format(instant);\n } catch {\n return instant.toISOString();\n }\n};\n\n/** The angles of the three hands in degrees, clockwise from 12. */\nexport const readHandAngles = (wallClock: ZonedWallClock): { hour: number; minute: number; second: number } => ({\n hour: ((wallClock.hour % 12) + wallClock.minute / 60) * 30,\n minute: (wallClock.minute + wallClock.second / 60) * 6,\n second: wallClock.second * 6,\n});\n","/**\n * The `Clock` payload (DATA-COMPLETE: zone ids and labels only, the time is computed in the browser). The parser is\n * alias-tolerant (weak models rename fields while they write: `tz_name`, `city`, `zones`, …), caps every list and every\n * string, and never throws — malformed JSON gives an empty payload, which the widget reports as `empty`.\n */\n\n/** At most this many clocks render; the rest are dropped silently, as every list cap in the widgets. */\nexport const MAX_CLOCKS = 8;\n\nconst MAX_TITLE_LENGTH = 160;\nconst MAX_LABEL_LENGTH = 120;\nconst MAX_ABBREVIATION_LENGTH = 12;\nconst MAX_TIME_ZONE_LENGTH = 64;\n\nexport type ClockTimeFormat = \"24h\" | \"12h\";\n\n/** One clock as the model wrote it — the time zone not yet checked against the browser's zone data. */\nexport interface ClockPayloadEntry {\n /** The IANA time zone id exactly as written (trimmed): \"Europe/Berlin\". */\n timeZone: string;\n /** The place in the owner's language; undefined → derived from the zone id. */\n label?: string;\n /** The zone abbreviation the model passed (\"CET\"); undefined → the browser's short zone name. */\n abbreviation?: string;\n}\n\nexport interface ClockPayload {\n title?: string;\n timeFormat?: ClockTimeFormat;\n clocks: ClockPayloadEntry[];\n}\n\nconst CLOCK_LIST_KEYS = [\"clocks\", \"zones\", \"timeZones\", \"timezones\", \"items\"] as const;\nconst TIME_ZONE_KEYS = [\"timeZone\", \"timezone\", \"tz\", \"tz_name\", \"tzName\", \"zone\", \"ianaTimeZone\"] as const;\nconst LABEL_KEYS = [\"label\", \"city\", \"location\", \"name\", \"place\"] as const;\nconst ABBREVIATION_KEYS = [\"abbreviation\", \"tz_alias\", \"tzAlias\", \"alias\"] as const;\nconst TIME_FORMAT_KEYS = [\"timeFormat\", \"time_format\", \"hourCycle\"] as const;\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst readCappedString = (value: unknown, maxLength: number): string | undefined => {\n if (typeof value !== \"string\") return undefined;\n const trimmedValue = value.trim();\n return trimmedValue === \"\" ? undefined : trimmedValue.slice(0, maxLength);\n};\n\nconst readFirstString = (record: Record<string, unknown>, keys: readonly string[], maxLength: number) => {\n for (const key of keys) {\n const stringValue = readCappedString(record[key], maxLength);\n if (stringValue !== undefined) return stringValue;\n }\n return undefined;\n};\n\n/** `24h` / `12h`, also written `24` / `12` / `h23` / `h12`; anything else → undefined (the owner settings decide). */\nconst readTimeFormat = (record: Record<string, unknown>): ClockTimeFormat | undefined => {\n for (const key of TIME_FORMAT_KEYS) {\n const rawValue = record[key];\n const normalizedValue =\n typeof rawValue === \"number\"\n ? String(rawValue)\n : typeof rawValue === \"string\"\n ? rawValue.trim().toLowerCase()\n : \"\";\n if ([\"24h\", \"24\", \"h23\", \"h24\"].includes(normalizedValue)) return \"24h\";\n if ([\"12h\", \"12\", \"h12\", \"h11\", \"ampm\", \"am/pm\"].includes(normalizedValue)) return \"12h\";\n }\n return undefined;\n};\n\n/** One entry: a plain zone id string, or an object with the zone under one of its aliases (or `parameters.tz_name`). */\nconst readClockEntry = (rawEntry: unknown): ClockPayloadEntry | undefined => {\n if (typeof rawEntry === \"string\") {\n const timeZone = readCappedString(rawEntry, MAX_TIME_ZONE_LENGTH);\n return timeZone ? { timeZone } : undefined;\n }\n if (!isRecord(rawEntry)) return undefined;\n // ChatGPT's own shape nests the fields under `parameters` — accepted, the model may copy it.\n const entryRecord = isRecord(rawEntry.parameters) ? { ...rawEntry.parameters, ...rawEntry } : rawEntry;\n const timeZone = readFirstString(entryRecord, TIME_ZONE_KEYS, MAX_TIME_ZONE_LENGTH);\n if (!timeZone) return undefined;\n const label = readFirstString(entryRecord, LABEL_KEYS, MAX_LABEL_LENGTH);\n const abbreviation = readFirstString(entryRecord, ABBREVIATION_KEYS, MAX_ABBREVIATION_LENGTH);\n return { timeZone, ...(label ? { label } : {}), ...(abbreviation ? { abbreviation } : {}) };\n};\n\nconst readClockList = (payloadRecord: Record<string, unknown>): unknown[] => {\n for (const key of CLOCK_LIST_KEYS) {\n if (Array.isArray(payloadRecord[key])) return payloadRecord[key] as unknown[];\n }\n // One clock written at the top level: `{\"timeZone\": \"Asia/Tokyo\", \"label\": \"Tokio\"}`.\n return readFirstString(payloadRecord, TIME_ZONE_KEYS, MAX_TIME_ZONE_LENGTH) ? [payloadRecord] : [];\n};\n\nexport const parseClockPayload = (payload: string | undefined): ClockPayload => {\n let parsedPayload: unknown;\n try {\n parsedPayload = JSON.parse(payload ?? \"\");\n } catch {\n return { clocks: [] };\n }\n if (!isRecord(parsedPayload)) return { clocks: [] };\n const clocks = readClockList(parsedPayload)\n .slice(0, MAX_CLOCKS)\n .map(readClockEntry)\n .filter((clockEntry): clockEntry is ClockPayloadEntry => clockEntry !== undefined);\n const title = readCappedString(parsedPayload.title, MAX_TITLE_LENGTH);\n const timeFormat = readTimeFormat(parsedPayload);\n return { clocks, ...(title ? { title } : {}), ...(timeFormat ? { timeFormat } : {}) };\n};\n","import { useEffect, useState } from \"react\";\nimport { useAgentsOwnerSettings } from \"../../../provider/AgentsProvider\";\nimport { isKnownTimeZone } from \"./clock-time\";\nimport type { ClockTimeFormat } from \"./clock-widget-payload\";\n\nconst FALLBACK_DATE_LOCALE = \"en-GB\";\n\nconst readBrowserLanguage = (): string => (typeof navigator === \"undefined\" ? \"en\" : navigator.language || \"en\");\n\nconst readBrowserTimeZone = (): string => {\n try {\n const browserTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;\n return browserTimeZone && isKnownTimeZone(browserTimeZone) ? browserTimeZone : \"UTC\";\n } catch {\n return \"UTC\";\n }\n};\n\nexport interface ClockSettings {\n /** The owner's own zone: the one of the owner settings, else the browser's, else UTC. */\n ownerTimeZone: string;\n /** The owner's language — zone names and the 12 h day period. */\n language: string;\n /** The owner's date locale (`de-DE`) — the date lines. */\n dateLocale: string;\n /** `12h` when the owner settings use AM/PM. */\n ownerTimeFormat: ClockTimeFormat;\n}\n\n/** The owner's settings come from the app, read defensively: the widget renders in hosts that know only some of them. */\nexport const useClockSettings = (): ClockSettings => {\n const ownerSettings = useAgentsOwnerSettings();\n const ownerSettingsTimeZone = ownerSettings.timeZone;\n const useAmPm = ownerSettings.usesAmPm;\n const language = ownerSettings.languageCode || readBrowserLanguage();\n const dateLocale = ownerSettings.dateLocale || FALLBACK_DATE_LOCALE;\n const ownerTimeZone =\n ownerSettingsTimeZone && isKnownTimeZone(ownerSettingsTimeZone) ? ownerSettingsTimeZone : readBrowserTimeZone();\n return { ownerTimeZone, language, dateLocale, ownerTimeFormat: useAmPm ? \"12h\" : \"24h\" };\n};\n\n/**\n * The current instant, re-read at every full second while `isTicking` — the one timer of the widget, cleared on unmount.\n * Not ticking (the e-mail capture) keeps the instant of the first render: the capture time the \"As of\" line names.\n */\nexport const useClockNow = (isTicking: boolean): Date => {\n const [now, setNow] = useState(() => new Date());\n useEffect(() => {\n if (!isTicking) return undefined;\n let tickTimer: ReturnType<typeof setTimeout> | undefined;\n const scheduleNextTick = () => {\n // Aligned to the next full second, so the second hand and the digital minute flip together.\n tickTimer = setTimeout(\n () => {\n setNow(new Date());\n scheduleNextTick();\n },\n 1000 - (Date.now() % 1000),\n );\n };\n setNow(new Date());\n scheduleNextTick();\n return () => {\n if (tickTimer !== undefined) clearTimeout(tickTimer);\n };\n }, [isTicking]);\n return now;\n};\n","import { readHandAngles, type ZonedWallClock } from \"../shared/clock-time\";\nimport styles from \"./ClockWidget.module.scss\";\n\nexport interface AnalogClockFaceProps {\n wallClock: ZonedWallClock;\n /** The accessible name — the digital time it shows, already formatted. */\n accessibleLabel: string;\n}\n\nconst CENTER = 50;\nconst TICK_INDICES = Array.from({ length: 12 }, (unused, tickIndex) => tickIndex);\n\n/**\n * The analog dial of one clock: twelve ticks (the quarters longer), hour and minute hand in the text colour, the second\n * hand and the hub in the call-to-action colour — every colour a theme token, so it flips with the scheme. Purely a\n * picture of the digital time next to it: `role=\"img\"` with that time as its name.\n */\nexport const AnalogClockFace = (props: AnalogClockFaceProps) => {\n const { wallClock, accessibleLabel } = props;\n const handAngles = readHandAngles(wallClock);\n return (\n <svg className={styles.dial} viewBox=\"0 0 100 100\" role=\"img\" aria-label={accessibleLabel}>\n <circle className={styles.dialFace} cx={CENTER} cy={CENTER} r={48} />\n {TICK_INDICES.map((tickIndex) => (\n <line\n key={tickIndex}\n className={tickIndex % 3 === 0 ? styles.dialQuarterTick : styles.dialTick}\n x1={CENTER}\n y1={tickIndex % 3 === 0 ? 7 : 9}\n x2={CENTER}\n y2={14}\n transform={`rotate(${tickIndex * 30} ${CENTER} ${CENTER})`}\n />\n ))}\n <line\n className={styles.hourHand}\n x1={CENTER}\n y1={CENTER + 6}\n x2={CENTER}\n y2={24}\n transform={`rotate(${handAngles.hour} ${CENTER} ${CENTER})`}\n />\n <line\n className={styles.minuteHand}\n x1={CENTER}\n y1={CENTER + 7}\n x2={CENTER}\n y2={13}\n transform={`rotate(${handAngles.minute} ${CENTER} ${CENTER})`}\n />\n <line\n className={styles.secondHand}\n data-testid=\"clock-second-hand\"\n x1={CENTER}\n y1={CENTER + 10}\n x2={CENTER}\n y2={10}\n transform={`rotate(${handAngles.second} ${CENTER} ${CENTER})`}\n />\n <circle className={styles.dialHub} cx={CENTER} cy={CENTER} r={2.5} />\n </svg>\n );\n};\n","import styles from \"./ClockWidget.module.scss\";\n\nexport interface DayNightGlyphProps {\n isDaytime: boolean;\n}\n\nconst SUN_RAY_ANGLES = [0, 45, 90, 135, 180, 225, 270, 315];\n\n/**\n * A sun or a moon (the component library has neither icon) beside the \"Day\" / \"Night\" word — decoration only, the word carries the\n * meaning, so the glyph is hidden from assistive technology.\n */\nexport const DayNightGlyph = (props: DayNightGlyphProps) => {\n const { isDaytime } = props;\n if (isDaytime) {\n return (\n <svg className={styles.dayNightGlyph} viewBox=\"0 0 16 16\" aria-hidden=\"true\" data-testid=\"clock-sun\">\n <circle className={styles.sunDisc} cx={8} cy={8} r={3.2} />\n {SUN_RAY_ANGLES.map((rayAngle) => (\n <line\n key={rayAngle}\n className={styles.sunRay}\n x1={8}\n y1={1.5}\n x2={8}\n y2={3.2}\n transform={`rotate(${rayAngle} 8 8)`}\n />\n ))}\n </svg>\n );\n }\n return (\n <svg className={styles.dayNightGlyph} viewBox=\"0 0 16 16\" aria-hidden=\"true\" data-testid=\"clock-moon\">\n <path className={styles.moon} d=\"M10.8 2.2a6 6 0 1 0 3 9.6 5 5 0 0 1-3-9.6z\" />\n </svg>\n );\n};\n","import { Text } from \"../../../provider/components\";\nimport { escapePlainTextForText } from \"../../../provider/environment\";\nimport { HeroValue } from \"../../_shared/modern\";\nimport {\n formatDigitalTime,\n formatHourDifference,\n formatUtcOffset,\n formatZonedDate,\n isDaytime,\n readRelativeDay,\n readZoneAbbreviation,\n readZonedWallClock,\n type ClockRelativeDay,\n} from \"../shared/clock-time\";\nimport type { ClockTimeFormat } from \"../shared/clock-widget-payload\";\nimport { AnalogClockFace } from \"./AnalogClockFace\";\nimport { DayNightGlyph } from \"./DayNightGlyph\";\nimport styles from \"./ClockWidget.module.scss\";\n\n/** One clock ready to render: a zone the browser knows and the place's label. */\nexport interface ClockWidgetEntry {\n timeZone: string;\n /** The place — the model's label, or the city derived from the zone id; business content, never translated. */\n label: string;\n /** The model's zone abbreviation; undefined → the browser's short zone name. */\n abbreviation?: string;\n}\n\nexport interface ClockRowProps {\n clock: ClockWidgetEntry;\n now: Date;\n ownerTimeZone: string;\n timeFormat: ClockTimeFormat;\n language: string;\n dateLocale: string;\n testId?: string;\n}\n\n/** One translation key per relative day: the sentence keeps its word order in every language. */\nconst RELATIVE_DAY_KEYS: Record<ClockRelativeDay, string> = {\n today: \"Today, %hourDifference% h\",\n yesterday: \"Yesterday, %hourDifference% h\",\n tomorrow: \"Tomorrow, %hourDifference% h\",\n};\n\n/**\n * One place: the digital time as the hero, the place with its zone abbreviation, the day there and the hour difference\n * to the owner's zone, then the date, the UTC offset and day or night; the analog dial on the right.\n */\nexport const ClockRow = (props: ClockRowProps) => {\n const { clock, now, ownerTimeZone, timeFormat, language, dateLocale, testId = \"clock-widget-row\" } = props;\n const wallClock = readZonedWallClock(now, clock.timeZone);\n const ownerWallClock = readZonedWallClock(now, ownerTimeZone);\n const { time, dayPeriod } = formatDigitalTime(wallClock, timeFormat, now, clock.timeZone, language);\n const abbreviation = clock.abbreviation ?? readZoneAbbreviation(now, clock.timeZone, language);\n const placeLine = abbreviation ? `${clock.label} (${abbreviation})` : clock.label;\n const hourDifference = formatHourDifference(wallClock.utcOffsetMinutes - ownerWallClock.utcOffsetMinutes);\n const isDaytimeThere = isDaytime(wallClock);\n const dateLine = [formatZonedDate(now, clock.timeZone, dateLocale), formatUtcOffset(wallClock.utcOffsetMinutes)]\n .filter((linePart) => linePart !== \"\")\n .join(\" · \");\n const digitalTime = dayPeriod ? `${time} ${dayPeriod}` : time;\n\n return (\n <div className={styles.row} data-testid=\"clock-row\" data-time-zone={clock.timeZone}>\n <div className={styles.readout}>\n <span className={styles.digitalTime} data-testid=\"clock-digital-time\">\n <HeroValue>{time}</HeroValue>\n {dayPeriod ? (\n <Text role=\"intro\" weight=\"bold\" translate={false}>\n {dayPeriod}\n </Text>\n ) : null}\n </span>\n <Text\n role=\"body\"\n weight=\"bold\"\n translate={false}\n className={styles.wrappingText}\n testId={`${testId}-place`}\n >\n {escapePlainTextForText(placeLine)}\n </Text>\n <Text\n role=\"help\"\n color=\"var(--agents-fg-light)\"\n replacements={{ hourDifference }}\n testId={`${testId}-relative-day`}\n >\n {RELATIVE_DAY_KEYS[readRelativeDay(wallClock, ownerWallClock)]}\n </Text>\n <span className={styles.metaLine}>\n <Text\n role=\"caption\"\n color=\"var(--agents-fg-light)\"\n translate={false}\n testId={`${testId}-date`}\n >\n {dateLine}\n </Text>\n <span className={styles.dayNight}>\n <DayNightGlyph isDaytime={isDaytimeThere} />\n <Text role=\"caption\" color=\"var(--agents-fg-light)\">\n {isDaytimeThere ? \"Day\" : \"Night\"}\n </Text>\n </span>\n </span>\n </div>\n <AnalogClockFace wallClock={wallClock} accessibleLabel={`${clock.label} ${digitalTime}`} />\n </div>\n );\n};\n","import { Text } from \"../../../provider/components\";\nimport { escapePlainTextForText } from \"../../../provider/environment\";\nimport { WidgetSurface } from \"../../_shared/modern\";\nimport type { ClockTimeFormat } from \"../shared/clock-widget-payload\";\nimport { ClockRow, type ClockWidgetEntry } from \"./ClockRow\";\nimport styles from \"./ClockWidget.module.scss\";\n\nexport interface ClockWidgetProps {\n clocks: ClockWidgetEntry[];\n /** The model's headline, shown as written. */\n title?: string;\n now: Date;\n ownerTimeZone: string;\n timeFormat: ClockTimeFormat;\n language: string;\n dateLocale: string;\n /** Set in an e-mail render: the frozen capture moment the \"As of\" line names. */\n captureMoment?: string;\n testId?: string;\n}\n\n/**\n * The presentational clock: one elevated surface, one row per place divided by hairlines (one row = the single clock,\n * several = the world clock), the optional title above and, in an e-mail, the \"As of\" line below. Knows nothing about\n * payloads or the registry.\n */\nexport const ClockWidget = (props: ClockWidgetProps) => {\n const {\n clocks,\n title,\n now,\n ownerTimeZone,\n timeFormat,\n language,\n dateLocale,\n captureMoment,\n testId = \"clock-widget\",\n } = props;\n return (\n <WidgetSurface className={styles.root} testId={testId}>\n {title ? (\n <Text\n role=\"intro\"\n weight=\"bold\"\n translate={false}\n className={styles.wrappingText}\n testId={`${testId}-title`}\n >\n {escapePlainTextForText(title)}\n </Text>\n ) : null}\n <div className={styles.rows} data-testid={`${testId}-rows`}>\n {clocks.map((clock, clockIndex) => (\n <ClockRow\n key={`${clock.timeZone}-${clockIndex}`}\n testId={`${testId}-row-${clock.timeZone}`}\n clock={clock}\n now={now}\n ownerTimeZone={ownerTimeZone}\n timeFormat={timeFormat}\n language={language}\n dateLocale={dateLocale}\n />\n ))}\n </div>\n {captureMoment ? (\n <Text\n role=\"caption\"\n color=\"var(--agents-fg-light)\"\n replacements={{ captureMoment }}\n testId={`${testId}-as-of`}\n >\n {\"As of %captureMoment%\"}\n </Text>\n ) : null}\n </WidgetSurface>\n );\n};\n","import { Text } from \"../../provider/components\";\nimport { useMemo } from \"react\";\nimport type { PayloadConversationWidgetProps } from \"../../renderer/conversation-widget-props\";\nimport { useIsEmailWidgetRender } from \"../../renderer/ConversationWidgetRenderContext\";\nimport { useReportWidgetRenderStatus } from \"../../renderer/render-report/widget-render-report\";\nimport { useWidgetImageRender } from \"../../image-render/WidgetImageRenderContext\";\nimport { formatCaptureMoment, isKnownTimeZone, readCityOfTimeZone } from \"./shared/clock-time\";\nimport { parseClockPayload, type ClockPayloadEntry } from \"./shared/clock-widget-payload\";\nimport { useClockNow, useClockSettings } from \"./shared/use-clock-settings\";\nimport { ClockWidget } from \"./ClockWidget/ClockWidget\";\nimport type { ClockWidgetEntry } from \"./ClockWidget/ClockRow\";\nimport styles from \"./ClockConversationWidget.module.scss\";\n\ntype ClockConversationWidgetProps = PayloadConversationWidgetProps;\n\n/** The clocks the browser can show, and the zone ids it cannot (dropped and reported). */\ninterface ResolvedClocks {\n clocks: ClockWidgetEntry[];\n unknownTimeZones: string[];\n}\n\nconst resolveClocks = (payloadClocks: ClockPayloadEntry[]): ResolvedClocks => {\n const clocks: ClockWidgetEntry[] = [];\n const unknownTimeZones: string[] = [];\n for (const payloadClock of payloadClocks) {\n if (!isKnownTimeZone(payloadClock.timeZone)) {\n unknownTimeZones.push(payloadClock.timeZone);\n continue;\n }\n clocks.push({\n timeZone: payloadClock.timeZone,\n label: payloadClock.label ?? readCityOfTimeZone(payloadClock.timeZone),\n ...(payloadClock.abbreviation ? { abbreviation: payloadClock.abbreviation } : {}),\n });\n }\n return { clocks, unknownTimeZones };\n};\n\n/**\n * The `Clock` widget: the live time of one place or a world clock of several, from the\n * IANA zone ids and labels the model passes. DATA-COMPLETE without data: the time is computed in the browser every\n * second (`Intl`), nothing is fetched. A zone id the browser does not know is dropped and reported `failed`\n * (`INVALID_PROP`, the dropped ids in the detail) while the other clocks render; a payload without clocks reports\n * `empty`. In the e-mail capture the clocks freeze at the capture moment and an \"As of\" line names it. Inline only.\n */\nexport const ClockConversationWidget = (props: ClockConversationWidgetProps) => {\n const { payload } = props;\n const testId = \"clock-widget\";\n const isEmailRender = useIsEmailWidgetRender();\n const isCapture = useWidgetImageRender() !== null;\n const isFrozen = isEmailRender || isCapture;\n const {\n title,\n timeFormat: payloadTimeFormat,\n clocks: payloadClocks,\n } = useMemo(() => parseClockPayload(payload), [payload]);\n const { clocks, unknownTimeZones } = useMemo(() => resolveClocks(payloadClocks), [payloadClocks]);\n const { ownerTimeZone, language, dateLocale, ownerTimeFormat } = useClockSettings();\n const now = useClockNow(!isFrozen);\n const timeFormat = payloadTimeFormat ?? ownerTimeFormat;\n\n const unknownTimeZonesDetail =\n unknownTimeZones.length > 0 ? `Unknown time zone ids dropped: ${unknownTimeZones.join(\", \")}.` : undefined;\n useReportWidgetRenderStatus(\n payloadClocks.length === 0 ? \"empty\" : unknownTimeZones.length > 0 ? \"failed\" : \"mounted\",\n payloadClocks.length === 0 ? \"NO_DATA\" : unknownTimeZones.length > 0 ? \"INVALID_PROP\" : undefined,\n payloadClocks.length === 0 ? \"The Clock widget carries no time zone.\" : unknownTimeZonesDetail,\n );\n\n if (payloadClocks.length === 0) {\n return (\n <Text\n role=\"help\"\n color=\"var(--agents-fg-light)\"\n className={styles.notice}\n testId={`${testId}-empty`}\n >\n {\"No time zone to show.\"}\n </Text>\n );\n }\n if (clocks.length === 0) {\n return (\n <Text\n role=\"help\"\n color=\"var(--agents-fg-light)\"\n className={styles.notice}\n testId={`${testId}-error`}\n >\n {\"The time zones of this clock are unknown.\"}\n </Text>\n );\n }\n return (\n <ClockWidget\n clocks={clocks}\n title={title}\n now={now}\n ownerTimeZone={ownerTimeZone}\n timeFormat={timeFormat}\n language={language}\n dateLocale={dateLocale}\n testId={testId}\n captureMoment={isFrozen ? formatCaptureMoment(now, ownerTimeZone, dateLocale, timeFormat) : undefined}\n />\n );\n};\n","import type { ConceptExplainerTypeDefinition } from \"./concept-explainer-type\";\n\n/**\n * The ConceptExplainer type registry: every package `widgets/**\\/*.concept-explainer.tsx` that\n * exports `conceptExplainerType` registers itself by folder glob — a domain adds a type with one new file and edits no\n * list. An app registers its own types with `registerConceptExplainerTypes` (its glob stays in its code). Two files\n * for one type id are an error.\n */\nconst conceptExplainerTypeModules = import.meta.glob<{ conceptExplainerType?: ConceptExplainerTypeDefinition }>(\n [\"../../**/*.concept-explainer.tsx\"],\n { eager: true },\n);\n\nexport const buildConceptExplainerTypeRegistry = (\n definitions: readonly ConceptExplainerTypeDefinition[],\n): Readonly<Record<string, ConceptExplainerTypeDefinition>> => {\n const registry: Record<string, ConceptExplainerTypeDefinition> = {};\n for (const definition of definitions) {\n if (Object.prototype.hasOwnProperty.call(registry, definition.typeId)) {\n throw new Error(`Two ConceptExplainer types register the type id \"${definition.typeId}\".`);\n }\n registry[definition.typeId] = definition;\n }\n return registry;\n};\n\n/** The type definitions a set of `*.concept-explainer.tsx` modules export (the package's or an app's glob). */\nexport const readConceptExplainerTypeDefinitions = (\n modules: Record<string, { conceptExplainerType?: ConceptExplainerTypeDefinition }>,\n): ConceptExplainerTypeDefinition[] =>\n Object.values(modules)\n .map((typeModule) => typeModule.conceptExplainerType)\n .filter((definition): definition is ConceptExplainerTypeDefinition => definition !== undefined);\n\n/** Type id → type: the package's folders, then what an app registers (`registerConceptExplainerTypes`). */\nexport const conceptExplainerTypes: Record<string, ConceptExplainerTypeDefinition> = {\n ...buildConceptExplainerTypeRegistry(readConceptExplainerTypeDefinitions(conceptExplainerTypeModules)),\n};\n\n/** Adds an app's ConceptExplainer types. Runs outside React, before the first render; a type id registers once. */\nexport const registerConceptExplainerTypes = (definitions: readonly ConceptExplainerTypeDefinition[]): void => {\n Object.assign(\n conceptExplainerTypes,\n buildConceptExplainerTypeRegistry([...Object.values(conceptExplainerTypes), ...definitions]),\n );\n};\n\n/** `rankingFactors`, `RankingFactors`, `ranking_factors` and `ranking-factors` all read as `rankingfactors`. */\nexport const normalizeConceptExplainerTypeId = (typeId: string): string =>\n typeId.toLowerCase().replace(/[^a-z0-9]/g, \"\");\n\n/**\n * The registered type of an id — exact first, then ignoring case, `_` and `-` (a model writes `RankingFactors` or\n * `ranking_factors`; the backend's `ConceptExplainerTypes::findTypeClass()` applies the same rule); else undefined.\n */\nexport const findConceptExplainerType = (\n typeId: string,\n registry: Readonly<Record<string, ConceptExplainerTypeDefinition>> = conceptExplainerTypes,\n): ConceptExplainerTypeDefinition | undefined => {\n if (Object.prototype.hasOwnProperty.call(registry, typeId)) return registry[typeId];\n const normalizedTypeId = normalizeConceptExplainerTypeId(typeId);\n if (normalizedTypeId === \"\") return undefined;\n return Object.values(registry).find(\n (definition) => normalizeConceptExplainerTypeId(definition.typeId) === normalizedTypeId,\n );\n};\n","/**\n * The `ConceptExplainer` payload — DATA-COMPLETE and small: which explainer, an optional title,\n * the few numbers the type may show (copied from a read of this conversation) and an optional start step. Alias-\n * tolerant (weak models rename fields, and ChatGPT's own LearningViz writes `type_id` inside `parameters`), capped,\n * never throws: a payload that is not JSON reads as the empty shape.\n */\nexport interface ConceptExplainerPayload {\n /** The explainer type id as written (`rankingFactors`); \"\" when the payload names none. */\n explainer: string;\n /** The headline in the owner's language, model-written; undefined → the type's default title. */\n title?: string;\n /** The raw values for the type to read — every key kept as written, scalars only. */\n values: Readonly<Record<string, unknown>>;\n /** The step id or index to start at; undefined → the first step. */\n step?: string | number;\n}\n\n/** The backend's `ConceptExplainerConversationWidget::MAX_TITLE_LENGTH`. */\nexport const MAX_TITLE_LENGTH = 160;\n/** The backend's `ConceptExplainerConversationWidget::MAX_VALUES`. */\nexport const MAX_VALUES = 20;\nconst MAX_TYPE_ID_LENGTH = 64;\nconst MAX_STRING_VALUE_LENGTH = 120;\n\nconst EXPLAINER_ALIASES = [\"explainer\", \"explainerType\", \"explainer_type\", \"typeId\", \"type_id\", \"concept\", \"kind\"];\nconst VALUES_ALIASES = [\"values\", \"parameters\", \"params\", \"data\", \"inputs\"];\nconst TITLE_ALIASES = [\"title\", \"headline\", \"heading\"];\nconst STEP_ALIASES = [\"step\", \"initialStep\", \"initial_step\", \"startStep\", \"start_step\"];\n\nconst isPlainObject = (candidate: unknown): candidate is Record<string, unknown> =>\n typeof candidate === \"object\" && candidate !== null && !Array.isArray(candidate);\n\nconst readFirst = (source: Record<string, unknown>, aliases: readonly string[]): unknown => {\n for (const alias of aliases) {\n if (Object.prototype.hasOwnProperty.call(source, alias) && source[alias] !== undefined && source[alias] !== null) {\n return source[alias];\n }\n }\n return undefined;\n};\n\nconst readTrimmedString = (candidate: unknown, maxLength: number): string | undefined => {\n if (typeof candidate !== \"string\") return undefined;\n const trimmed = candidate.trim();\n return trimmed === \"\" ? undefined : trimmed.slice(0, maxLength);\n};\n\n/** Scalars only: a number, a numeric-looking string or a short string; objects, lists and prototype names are dropped. */\nconst readScalarValues = (rawValues: unknown): Record<string, unknown> => {\n const scalarValues: Record<string, unknown> = {};\n if (!isPlainObject(rawValues)) return scalarValues;\n for (const [valueName, value] of Object.entries(rawValues).slice(0, MAX_VALUES)) {\n if (valueName === \"__proto__\" || valueName === \"constructor\" || valueName === \"prototype\") continue;\n if (typeof value === \"number\" && Number.isFinite(value)) scalarValues[valueName] = value;\n else if (typeof value === \"string\") scalarValues[valueName] = value.trim().slice(0, MAX_STRING_VALUE_LENGTH);\n else if (typeof value === \"boolean\") scalarValues[valueName] = value;\n }\n return scalarValues;\n};\n\nexport const parseConceptExplainerPayload = (payload: string | undefined): ConceptExplainerPayload => {\n let parsed: unknown;\n try {\n parsed = JSON.parse(payload ?? \"\");\n } catch {\n return { explainer: \"\", values: {} };\n }\n if (!isPlainObject(parsed)) return { explainer: \"\", values: {} };\n const rawValues = readFirst(parsed, VALUES_ALIASES);\n // ChatGPT's LearningViz shape: `{\"parameters\": {\"type_id\": \"MOON_PHASES\"}}` — the id may sit inside the values.\n const explainer =\n readTrimmedString(readFirst(parsed, EXPLAINER_ALIASES), MAX_TYPE_ID_LENGTH) ??\n (isPlainObject(rawValues)\n ? readTrimmedString(readFirst(rawValues, EXPLAINER_ALIASES), MAX_TYPE_ID_LENGTH)\n : undefined) ??\n \"\";\n const title = readTrimmedString(readFirst(parsed, TITLE_ALIASES), MAX_TITLE_LENGTH);\n const rawStep = readFirst(parsed, STEP_ALIASES);\n const step =\n typeof rawStep === \"number\" && Number.isInteger(rawStep) && rawStep >= 0\n ? rawStep\n : readTrimmedString(rawStep, MAX_TYPE_ID_LENGTH);\n return {\n explainer,\n ...(title !== undefined ? { title } : {}),\n values: readScalarValues(rawValues),\n ...(step !== undefined ? { step } : {}),\n };\n};\n\n/** Reads a finite number from a value the model wrote as a number or a numeric string (`\"4,3\"` included). */\nexport const readConceptExplainerNumber = (value: unknown): number | undefined => {\n if (typeof value === \"number\") return Number.isFinite(value) ? value : undefined;\n if (typeof value !== \"string\") return undefined;\n const normalized = value.trim().replace(\",\", \".\");\n if (!/^-?\\d+(\\.\\d+)?$/.test(normalized)) return undefined;\n const parsedNumber = Number(normalized);\n return Number.isFinite(parsedNumber) ? parsedNumber : undefined;\n};\n\n/** The first value present under one of the aliases. */\nexport const readConceptExplainerValue = (\n rawValues: Readonly<Record<string, unknown>>,\n aliases: readonly string[],\n): unknown => readFirst(rawValues as Record<string, unknown>, aliases);\n","import { useAgentsOwnerSettings } from \"../../../provider/AgentsProvider\";\n\nconst readBrowserLanguage = (): string => (typeof navigator === \"undefined\" ? \"en\" : navigator.language || \"en\");\n\n/**\n * The owner's language for the numbers an explainer formats, from the app (`useOwnerSettings`). Read defensively — the\n * widget renders in hosts that know no language (the e-mail capture, the preview, a spec), and there the browser's\n * language stands in.\n */\nexport const useConceptExplainerLanguage = (): string => useAgentsOwnerSettings().languageCode || readBrowserLanguage();\n\n/** A number in the owner's language with a fixed count of decimals (`4,3` in German, `4.3` in English). */\nexport const formatConceptExplainerNumber = (value: number, decimals: number, languageCode: string): string => {\n try {\n return new Intl.NumberFormat(languageCode, {\n minimumFractionDigits: decimals,\n maximumFractionDigits: decimals,\n }).format(value);\n } catch {\n return value.toFixed(decimals);\n }\n};\n","import { Text } from \"../../../provider/components\";\nimport type { ComponentProps } from \"react\";\nimport type { ConceptExplainerText } from \"./concept-explainer-type\";\n\nexport type ConceptExplainerTextViewProps = Omit<\n ComponentProps<typeof Text>,\n \"children\" | \"translate\" | \"replacements\" | \"context\"\n> & {\n text: ConceptExplainerText;\n};\n\n/**\n * One translated text of an explainer: the key through the component library's `Text`, its `%placeholders%` from `replacements`, the\n * singular / plural value picked by `context`. Never model text — that goes through `ModelText`.\n */\nexport const ConceptExplainerTextView = (props: ConceptExplainerTextViewProps) => {\n const { text, ...textProps } = props;\n return (\n <Text {...textProps} replacements={text.replacements} context={text.context}>\n {text.key}\n </Text>\n );\n};\n","import { classNames } from \"../../../provider/class-names\";\nimport { RangeSlider } from \"../../../provider/components\";\nimport { WidgetSurface } from \"../../_shared/modern\";\nimport { ModelText } from \"../../../kit/ModelText/ModelText\";\nimport type {\n ConceptExplainerStep,\n ConceptExplainerTypeDefinition,\n ConceptExplainerValuesReading,\n ConceptExplainerVariant,\n} from \"../shared/concept-explainer-type\";\nimport { ConceptExplainerTextView } from \"../shared/ConceptExplainerTextView\";\nimport styles from \"./ConceptExplainerWidget.module.scss\";\n\n/** At most this many steps get a labelled button under the slider; more steps are reached by the slider alone. */\nexport const MAX_LABELLED_STEPS = 6;\n\nexport interface ConceptExplainerWidgetProps {\n definition: ConceptExplainerTypeDefinition;\n /** The model's headline; undefined → the type's default title. */\n modelTitle?: string;\n valuesReading: ConceptExplainerValuesReading;\n steps: ConceptExplainerStep[];\n stepIndex: number;\n onStepIndexChange: (stepIndex: number) => void;\n variants: ConceptExplainerVariant[];\n variantId: string | undefined;\n onVariantIdChange: (variantId: string) => void;\n languageCode: string;\n /** The static render (the report e-mail capture): the picture of one step, no controls. */\n isStatic: boolean;\n testId?: string;\n}\n\n/**\n * The ConceptExplainer frame — ChatGPT's LearningViz as the interaction model, our design: one\n * elevated surface with the title, the type's picture on a flat tile, the caption of the current state under it, the\n * variant pills (effect-free, so rounded), the slider over the states with its label and the current state's name,\n * labelled step buttons under the slider, and a footer naming the source and whether the picture carries the\n * business's numbers or is an illustration. Presentational: the outer widget owns the step and the variant.\n */\nexport const ConceptExplainerWidget = (props: ConceptExplainerWidgetProps) => {\n const {\n definition,\n modelTitle,\n valuesReading,\n steps,\n stepIndex,\n onStepIndexChange,\n variants,\n variantId,\n onVariantIdChange,\n languageCode,\n isStatic,\n testId = \"concept-explainer-widget\",\n } = props;\n const { Visual } = definition;\n const currentStep = steps[stepIndex] ?? steps[0];\n const lastStepIndex = steps.length - 1;\n const showsStepButtons = !isStatic && steps.length > 1 && steps.length <= MAX_LABELLED_STEPS;\n // Says what the figures are: computed from the block's numbers, or an illustration without them.\n const footerLine = valuesReading.carriesBlockNumbers ? definition.computedLine : definition.illustrationLine;\n\n return (\n <WidgetSurface className={styles.widget} testId={testId}>\n <header className={styles.header}>\n {modelTitle ? (\n <ModelText\n role=\"intro\"\n weight=\"bold\"\n className={styles.wrappingText}\n testId={`${testId}-title`}\n >\n {modelTitle}\n </ModelText>\n ) : (\n <ConceptExplainerTextView\n text={definition.defaultTitle}\n role=\"intro\"\n weight=\"bold\"\n className={styles.wrappingText}\n testId={`${testId}-title`}\n />\n )}\n <ConceptExplainerTextView\n text={definition.subtitle}\n role=\"help\"\n color=\"var(--agents-fg-light)\"\n className={styles.wrappingText}\n />\n </header>\n\n <div className={styles.scene} data-testid=\"concept-explainer-scene\">\n <Visual\n values={valuesReading.values}\n carriesBlockNumbers={valuesReading.carriesBlockNumbers}\n steps={steps}\n stepIndex={stepIndex}\n variantId={variantId}\n languageCode={languageCode}\n />\n </div>\n\n {currentStep ? (\n <div className={styles.caption} aria-live=\"polite\" data-testid=\"concept-explainer-caption\">\n <ConceptExplainerTextView\n text={currentStep.caption}\n role=\"body\"\n weight=\"bold\"\n className={styles.wrappingText}\n />\n <ConceptExplainerTextView\n text={currentStep.description}\n role=\"help\"\n color=\"var(--agents-fg-light)\"\n className={styles.wrappingText}\n />\n </div>\n ) : null}\n\n {!isStatic && variants.length > 1 && definition.variantLabel ? (\n <div className={styles.controlBlock}>\n <ConceptExplainerTextView\n text={definition.variantLabel}\n role=\"caption\"\n color=\"var(--agents-fg-light)\"\n />\n <div className={styles.pillRow} role=\"group\">\n {variants.map((variant) => (\n <button\n key={variant.id}\n type=\"button\"\n data-testid={`concept-explainer-variant-${variant.id}`}\n aria-pressed={variant.id === variantId}\n className={classNames(styles.pill, variant.id === variantId && styles.pillSelected)}\n onClick={() => onVariantIdChange(variant.id)}\n >\n <ConceptExplainerTextView text={variant.label} role=\"help\" />\n </button>\n ))}\n </div>\n </div>\n ) : null}\n\n {!isStatic && steps.length > 1 && currentStep ? (\n <div className={styles.controlBlock}>\n <div className={styles.sliderRow}>\n <ConceptExplainerTextView text={definition.controlLabel} role=\"help\" />\n <ConceptExplainerTextView\n text={currentStep.label}\n role=\"help\"\n weight=\"medium\"\n className={styles.sliderValue}\n testId={`${testId}-current-step`}\n />\n </div>\n <div className={styles.sliderTrack} data-testid=\"concept-explainer-slider\">\n <RangeSlider\n value={stepIndex}\n min={0}\n max={lastStepIndex}\n step={1}\n onMove={(movedValue) => {\n if (movedValue !== stepIndex) onStepIndexChange(movedValue);\n }}\n />\n </div>\n {showsStepButtons ? (\n <div className={styles.pillRow} role=\"group\">\n {steps.map((step, index) => (\n <button\n key={step.id}\n type=\"button\"\n data-testid={`concept-explainer-step-${step.id}`}\n aria-pressed={index === stepIndex}\n className={classNames(styles.pill, index === stepIndex && styles.pillSelected)}\n onClick={() => onStepIndexChange(index)}\n >\n <ConceptExplainerTextView text={step.label} role=\"help\" />\n </button>\n ))}\n </div>\n ) : null}\n </div>\n ) : null}\n\n <footer className={styles.footer}>\n {definition.sourceLine ? (\n <ConceptExplainerTextView\n text={definition.sourceLine}\n role=\"caption\"\n color=\"var(--agents-fg-lightest)\"\n className={styles.wrappingText}\n />\n ) : null}\n {footerLine ? (\n <ConceptExplainerTextView\n text={footerLine}\n role=\"caption\"\n color=\"var(--agents-fg-lightest)\"\n className={styles.wrappingText}\n testId=\"concept-explainer-data-line\"\n />\n ) : null}\n </footer>\n </WidgetSurface>\n );\n};\n","import { Text } from \"../../provider/components\";\nimport { useMemo, useState } from \"react\";\nimport type { PayloadConversationWidgetProps } from \"../../renderer/conversation-widget-props\";\nimport { useIsEmailWidgetRender } from \"../../renderer/ConversationWidgetRenderContext\";\nimport {\n useReportWidgetRenderStatus,\n type WidgetRenderReportCode,\n type WidgetRenderStatus,\n} from \"../../renderer/render-report/widget-render-report\";\nimport { useWidgetImageRender } from \"../../image-render/WidgetImageRenderContext\";\nimport type {\n ConceptExplainerStep,\n ConceptExplainerTypeDefinition,\n ConceptExplainerValuesReading,\n ConceptExplainerVariant,\n} from \"./shared/concept-explainer-type\";\nimport { conceptExplainerTypes, findConceptExplainerType } from \"./shared/concept-explainer-types\";\nimport { parseConceptExplainerPayload, type ConceptExplainerPayload } from \"./shared/concept-explainer-widget-payload\";\nimport { useConceptExplainerLanguage } from \"./shared/use-concept-explainer-language\";\nimport { ConceptExplainerWidget } from \"./ConceptExplainerWidget/ConceptExplainerWidget\";\nimport styles from \"./ConceptExplainerConversationWidget.module.scss\";\n\ntype ConceptExplainerConversationWidgetProps = PayloadConversationWidgetProps;\n\ninterface ConceptExplainerRenderReport {\n status: WidgetRenderStatus;\n code?: WidgetRenderReportCode;\n detail?: string;\n}\n\n/** The longest model-written type id a report quotes back. */\nconst MAX_QUOTED_TYPE_ID_LENGTH = 40;\n\n/** What the block reports to the model: the detail is English, for the model only. */\nconst buildConceptExplainerRenderReport = (\n payload: ConceptExplainerPayload,\n definition: ConceptExplainerTypeDefinition | undefined,\n valuesReading: ConceptExplainerValuesReading | undefined,\n): ConceptExplainerRenderReport => {\n if (payload.explainer === \"\") {\n return { status: \"empty\", code: \"NO_DATA\", detail: \"The ConceptExplainer widget names no explainer type.\" };\n }\n if (!definition) {\n return {\n status: \"failed\",\n code: \"INVALID_PROP\",\n detail: `Unknown explainer \"${payload.explainer.slice(0, MAX_QUOTED_TYPE_ID_LENGTH)}\" — nothing is shown. Known explainers: ${Object.keys(conceptExplainerTypes).sort().join(\", \")}.`,\n };\n }\n if (valuesReading && valuesReading.droppedValueProblems.length > 0) {\n return {\n status: \"failed\",\n code: \"INVALID_PROP\",\n detail: `Values dropped: ${valuesReading.droppedValueProblems.join(\"; \")}. The explainer shows an illustration without them.`,\n };\n }\n return { status: \"mounted\" };\n};\n\n/** The step to start at: the payload's `step` by id or index, else the type's static step in e-mail, else the first. */\nconst readInitialStepIndex = (\n steps: ConceptExplainerStep[],\n payloadStep: string | number | undefined,\n definition: ConceptExplainerTypeDefinition | undefined,\n isStatic: boolean,\n): number => {\n if (typeof payloadStep === \"number\" && payloadStep < steps.length) return payloadStep;\n if (typeof payloadStep === \"string\") {\n const namedStepIndex = steps.findIndex((step) => step.id.toLowerCase() === payloadStep.toLowerCase());\n if (namedStepIndex >= 0) return namedStepIndex;\n }\n if (isStatic && definition?.emailStepIndex) {\n const emailStepIndex = definition.emailStepIndex(steps);\n if (emailStepIndex >= 0 && emailStepIndex < steps.length) return emailStepIndex;\n }\n return 0;\n};\n\n/**\n * The `ConceptExplainer` widget (ChatGPT's LearningViz — as the interaction model): an\n * interactive explanation of how something works for the business, with a slider over the states, a picture per state\n * and a caption. Each explainer TYPE is one `*.concept-explainer.tsx` file in its domain, found by folder glob\n * (`shared/concept-explainer-types.ts`). DATA-COMPLETE and small: the block names the type and, where the type can\n * show the business's own figures, the few numbers it computes from (copied from a read of this conversation) —\n * without them the type shows an illustration that claims no number. The slider and the variants only change local\n * state, so they stay usable on a replay; the e-mail capture shows one step without controls. Reports `empty` for a\n * block without a type, `failed` for an unknown type (nothing shown) or dropped values (the illustration shown).\n */\nexport const ConceptExplainerConversationWidget = (props: ConceptExplainerConversationWidgetProps) => {\n const { payload } = props;\n const testId = \"concept-explainer-widget\";\n const isEmailRender = useIsEmailWidgetRender();\n const widgetImageRender = useWidgetImageRender();\n const isStatic = isEmailRender || widgetImageRender !== null;\n const languageCode = useConceptExplainerLanguage();\n const parsedPayload = useMemo(() => parseConceptExplainerPayload(payload), [payload]);\n const definition = parsedPayload.explainer === \"\" ? undefined : findConceptExplainerType(parsedPayload.explainer);\n const valuesReading = useMemo(() => definition?.readValues(parsedPayload.values), [definition, parsedPayload]);\n const variants = useMemo<ConceptExplainerVariant[]>(\n () =>\n definition && valuesReading\n ? (definition.buildVariants?.(valuesReading.values, valuesReading.carriesBlockNumbers) ?? [])\n : [],\n [definition, valuesReading],\n );\n const [pickedVariantId, setPickedVariantId] = useState<string | undefined>(undefined);\n const variantId = variants.some((variant) => variant.id === pickedVariantId) ? pickedVariantId : variants[0]?.id;\n const steps = useMemo<ConceptExplainerStep[]>(\n () =>\n definition && valuesReading\n ? definition.buildSteps({\n values: valuesReading.values,\n carriesBlockNumbers: valuesReading.carriesBlockNumbers,\n variantId,\n languageCode,\n })\n : [],\n [definition, valuesReading, variantId, languageCode],\n );\n const [pickedStepIndex, setPickedStepIndex] = useState<number | undefined>(undefined);\n const stepIndex = Math.min(\n pickedStepIndex ?? readInitialStepIndex(steps, parsedPayload.step, definition, isStatic),\n Math.max(steps.length - 1, 0),\n );\n\n const renderReport = buildConceptExplainerRenderReport(parsedPayload, definition, valuesReading);\n useReportWidgetRenderStatus(renderReport.status, renderReport.code, renderReport.detail);\n\n if (parsedPayload.explainer === \"\") {\n return (\n <Text\n role=\"help\"\n color=\"var(--agents-fg-light)\"\n className={styles.notice}\n testId={`${testId}-empty`}\n >\n {\"No explanation to show.\"}\n </Text>\n );\n }\n if (!definition || !valuesReading || steps.length === 0) {\n return (\n <Text\n role=\"help\"\n color=\"var(--agents-fg-light)\"\n className={styles.notice}\n testId={`${testId}-error`}\n >\n {\"This explanation is not available.\"}\n </Text>\n );\n }\n return (\n <ConceptExplainerWidget\n definition={definition}\n modelTitle={parsedPayload.title}\n valuesReading={valuesReading}\n steps={steps}\n stepIndex={stepIndex}\n onStepIndexChange={setPickedStepIndex}\n variants={variants}\n variantId={variantId}\n onVariantIdChange={setPickedVariantId}\n languageCode={languageCode}\n isStatic={isStatic}\n testId={testId}\n />\n );\n};\n","/**\n * The `CurrencyConverter` payload: two ISO 4217 codes, the amount, the rate the tool returned and\n * the day the rate is of. DATA-COMPLETE — the widget never re-fetches a rate. The parser is alias-tolerant (a model\n * that transcribes the block may rename a field) and never throws: an unusable payload gives `null`.\n */\nexport interface CurrencyConverterPayload {\n /** ISO 4217, upper case (`EUR`). */\n fromCurrency: string;\n /** ISO 4217, upper case (`USD`). */\n toCurrency: string;\n /** The amount in `fromCurrency` shown first; 1 when the block carries none. */\n amount: number;\n /** 1 `fromCurrency` = `rate` `toCurrency`; always finite and > 0. */\n rate: number;\n /** The day the rate is of (`Y-m-d`); `undefined` when the block carries no valid day. */\n rateDate?: string;\n}\n\n/** The largest amount the widget accepts — beyond it the float maths stops being exact to the cent. */\nexport const MAX_CURRENCY_CONVERTER_AMOUNT = 1_000_000_000_000;\n\nconst ISO_CURRENCY_CODE = /^[A-Z]{3}$/;\nconst ISO_DAY = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nconst readFirstField = (fields: Record<string, unknown>, aliases: readonly string[]): unknown => {\n for (const alias of aliases) {\n if (fields[alias] !== undefined && fields[alias] !== null) return fields[alias];\n }\n return undefined;\n};\n\nconst readCurrencyCode = (value: unknown): string | undefined => {\n if (typeof value !== \"string\") return undefined;\n const upperCaseCode = value.trim().toUpperCase();\n return ISO_CURRENCY_CODE.test(upperCaseCode) ? upperCaseCode : undefined;\n};\n\n/** A finite number, or a numeric string (`\"1,12\"` and `\"1.12\"` both read as 1.12). */\nexport const readCurrencyConverterNumber = (value: unknown): number | undefined => {\n if (typeof value === \"number\") return Number.isFinite(value) ? value : undefined;\n if (typeof value !== \"string\") return undefined;\n const trimmedText = value.trim().replace(/\\s/g, \"\").replace(\",\", \".\");\n if (trimmedText === \"\" || !/^-?\\d*\\.?\\d+$/.test(trimmedText)) return undefined;\n const parsedNumber = Number(trimmedText);\n return Number.isFinite(parsedNumber) ? parsedNumber : undefined;\n};\n\nconst readRateDate = (value: unknown): string | undefined => {\n if (typeof value !== \"string\" || !ISO_DAY.test(value.trim())) return undefined;\n const rateDate = value.trim();\n return Number.isNaN(Date.parse(`${rateDate}T00:00:00Z`)) ? undefined : rateDate;\n};\n\nexport const parseCurrencyConverterPayload = (payload: string | undefined): CurrencyConverterPayload | null => {\n if (!payload) return null;\n let parsedPayload: unknown;\n try {\n parsedPayload = JSON.parse(payload);\n } catch {\n return null;\n }\n if (typeof parsedPayload !== \"object\" || parsedPayload === null || Array.isArray(parsedPayload)) return null;\n const fields = parsedPayload as Record<string, unknown>;\n const fromCurrency = readCurrencyCode(\n readFirstField(fields, [\"fromCurrency\", \"from_currency\", \"from\", \"baseCurrency\"]),\n );\n const toCurrency = readCurrencyCode(readFirstField(fields, [\"toCurrency\", \"to_currency\", \"to\", \"targetCurrency\"]));\n const rate = readCurrencyConverterNumber(readFirstField(fields, [\"rate\", \"exchangeRate\", \"exchange_rate\"]));\n if (!fromCurrency || !toCurrency || rate === undefined || rate <= 0) return null;\n const amount = readCurrencyConverterNumber(readFirstField(fields, [\"amount\", \"fromAmount\", \"value\"]));\n return {\n fromCurrency,\n toCurrency,\n amount: amount !== undefined && amount >= 0 && amount <= MAX_CURRENCY_CONVERTER_AMOUNT ? amount : 1,\n rate,\n rateDate: readRateDate(readFirstField(fields, [\"rateDate\", \"rate_date\", \"date\"])),\n };\n};\n","/**\n * How a currency and its numbers read for the owner — all from the browser's `Intl`, in the app's\n * UI language: the currency's name (\"US-Dollar\"), its symbol (\"$\"), its flag, an amount, a rate and the day of a rate.\n */\n\n/** The locale the numbers are written in: the app's UI language, `en` when it is unset or invalid. */\nexport const toCurrencyLocale = (languageCode: string | undefined): string => {\n if (!languageCode) return \"en\";\n try {\n return Intl.NumberFormat.supportedLocalesOf([languageCode.replace(\"_\", \"-\")])[0] ?? \"en\";\n } catch {\n return \"en\";\n }\n};\n\n/** The currency's name in the locale (\"Euro\", \"US-Dollar\"); the code itself when the browser knows no name. */\nexport const readCurrencyName = (currencyCode: string, locale: string): string => {\n try {\n return new Intl.DisplayNames([locale], { type: \"currency\" }).of(currencyCode) ?? currencyCode;\n } catch {\n return currencyCode;\n }\n};\n\n/** The currency's narrow symbol (\"€\", \"$\", \"CHF\"); the code when there is none. */\nexport const readCurrencySymbol = (currencyCode: string, locale: string): string => {\n try {\n const currencyPart = new Intl.NumberFormat(locale, {\n style: \"currency\",\n currency: currencyCode,\n currencyDisplay: \"narrowSymbol\",\n })\n .formatToParts(0)\n .find((part) => part.type === \"currency\");\n return currencyPart?.value ?? currencyCode;\n } catch {\n return currencyCode;\n }\n};\n\n/**\n * The flag emoji of the currency's country — the first two letters of an ISO 4217 code are the ISO 3166 country\n * (`USD` → US); the euro takes the EU flag. Decorative only: the name next to it carries the meaning.\n */\nexport const readCurrencyFlag = (currencyCode: string): string => {\n const countryCode = currencyCode === \"EUR\" ? \"EU\" : currencyCode.slice(0, 2);\n if (!/^[A-Z]{2}$/.test(countryCode)) return \"\";\n return String.fromCodePoint(...[...countryCode].map((letter) => 0x1f1e6 + letter.charCodeAt(0) - 65));\n};\n\n/** An amount with the currency's own number of decimals (2 for EUR, 0 for JPY), grouped for the locale. */\nexport const formatCurrencyAmount = (amount: number, currencyCode: string, locale: string): string => {\n try {\n return new Intl.NumberFormat(locale, { style: \"currency\", currency: currencyCode, currencyDisplay: \"code\" })\n .formatToParts(amount)\n .filter((part) => part.type !== \"currency\" && part.type !== \"literal\")\n .map((part) => part.value)\n .join(\"\")\n .trim();\n } catch {\n return amount.toFixed(2);\n }\n};\n\n/** An exact figure without currency rounding (a rate, the exact product): up to six significant digits after rounding. */\nexport const formatExactNumber = (value: number, locale: string): string => {\n const maximumFractionDigits = value >= 1000 ? 2 : value >= 1 ? 5 : 6;\n try {\n return new Intl.NumberFormat(locale, { maximumFractionDigits }).format(value);\n } catch {\n return String(value);\n }\n};\n\n/** The day of a rate (`2026-10-25`) in the locale's medium date style (\"25.10.2026\", \"Oct 25, 2026\"). */\nexport const formatRateDate = (rateDate: string, locale: string): string => {\n try {\n return new Intl.DateTimeFormat(locale, { dateStyle: \"medium\", timeZone: \"UTC\" }).format(\n new Date(`${rateDate}T00:00:00Z`),\n );\n } catch {\n return rateDate;\n }\n};\n\n/** The amount as it rests in the field: grouped for the locale (`1,250,000`, `1.250.000`), its decimals kept. */\nexport const formatEditableAmount = (amount: number, locale: string): string => {\n try {\n return new Intl.NumberFormat(locale, { maximumFractionDigits: 6 }).format(amount);\n } catch {\n return String(amount);\n }\n};\n\nconst readNumberMarks = (locale: string): { groupMark: string; decimalMark: string } => {\n try {\n const parts = new Intl.NumberFormat(locale).formatToParts(12345.6);\n return {\n groupMark: parts.find((part) => part.type === \"group\")?.value ?? \",\",\n decimalMark: parts.find((part) => part.type === \"decimal\")?.value ?? \".\",\n };\n } catch {\n return { groupMark: \",\", decimalMark: \".\" };\n }\n};\n\n/**\n * The amount the owner typed, or undefined when it is no number: spaces and apostrophes are dropped. When both `.` and\n * `,` occur the LAST one is the decimal mark (`1,250.75`, `1.250,75`); a mark that repeats groups thousands; a lone\n * mark is the decimal mark, except the locale's own grouping mark between a 1-3 digit head and exactly three digits\n * (`1,250` in English is 1250, `1.250` in German too).\n */\nexport const parseTypedAmount = (typedText: string, locale = \"en\"): number | undefined => {\n const compactText = typedText.replace(/[\\s'’\\u00a0\\u202f]/g, \"\");\n if (compactText === \"\") return undefined;\n const marks = compactText.match(/[.,]/g) ?? [];\n const lastMarkIndex = Math.max(compactText.lastIndexOf(\".\"), compactText.lastIndexOf(\",\"));\n const { groupMark } = readNumberMarks(locale);\n const isGrouping =\n marks.length > 1 && new Set(marks).size === 1\n ? true\n : marks.length === 1 && compactText[lastMarkIndex] === groupMark && /^\\d{1,3}[.,]\\d{3}$/.test(compactText);\n const normalizedText = isGrouping\n ? compactText.replace(/[.,]/g, \"\")\n : lastMarkIndex < 0\n ? compactText\n : `${compactText.slice(0, lastMarkIndex).replace(/[.,]/g, \"\")}.${compactText.slice(lastMarkIndex + 1)}`;\n if (!/^\\d*\\.?\\d+$|^\\d+\\.$/.test(normalizedText)) return undefined;\n const typedAmount = Number(normalizedText);\n return Number.isFinite(typedAmount) ? typedAmount : undefined;\n};\n","import { Text } from \"../../../../provider/components\";\nimport { readCurrencyFlag, readCurrencyName } from \"../../shared/currency-display\";\nimport styles from \"./CurrencyLabel.module.scss\";\n\nexport interface CurrencyLabelProps {\n currencyCode: string;\n locale: string;\n /** Id of the name line, so the amount field beside it can be named by it. */\n nameId?: string;\n testId?: string;\n}\n\n/** One currency of the converter: a round flag badge, the ISO code and the currency's name in the UI language. */\nexport const CurrencyLabel = (props: CurrencyLabelProps) => {\n const { currencyCode, locale, nameId, testId } = props;\n return (\n <div className={styles.currency} data-testid={testId}>\n <span aria-hidden=\"true\" className={styles.flag}>\n {readCurrencyFlag(currencyCode)}\n </span>\n <div className={styles.text}>\n <Text role=\"help\" weight=\"bold\" translate={false}>\n {currencyCode}\n </Text>\n <span id={nameId}>\n <Text role=\"caption\" color=\"var(--agents-fg-light)\" ellipsis translate={false}>\n {readCurrencyName(currencyCode, locale)}\n </Text>\n </span>\n </div>\n </div>\n );\n};\n","import { Icon, Text } from \"../../../provider/components\";\nimport { classNames } from \"../../../provider/class-names\";\nimport { useId, useMemo, useState, type CSSProperties } from \"react\";\nimport { translateText } from \"../../../provider/environment\";\nimport { HeroValue, WidgetSurface } from \"../../_shared/modern\";\nimport {\n MAX_CURRENCY_CONVERTER_AMOUNT,\n type CurrencyConverterPayload,\n} from \"../shared/currency-converter-widget-payload\";\nimport {\n formatCurrencyAmount,\n formatEditableAmount,\n formatExactNumber,\n formatRateDate,\n parseTypedAmount,\n readCurrencySymbol,\n toCurrencyLocale,\n} from \"../shared/currency-display\";\nimport { CurrencyLabel } from \"./CurrencyLabel/CurrencyLabel\";\nimport styles from \"./CurrencyConverterWidget.module.scss\";\n\nexport interface CurrencyConverterWidgetProps {\n conversion: CurrencyConverterPayload;\n /** The app's UI language (`de`, `en_US`); numbers, dates and currency names follow it. */\n languageCode?: string;\n /** The e-mail capture: the amount is plain text and there is no swap button. */\n isStatic?: boolean;\n testId?: string;\n}\n\n/** The pair as shown right now: swapping turns the rate into its inverse, so nothing is fetched. */\nconst buildShownPair = (conversion: CurrencyConverterPayload, isSwapped: boolean) =>\n isSwapped\n ? { fromCurrency: conversion.toCurrency, toCurrency: conversion.fromCurrency, rate: 1 / conversion.rate }\n : { fromCurrency: conversion.fromCurrency, toCurrency: conversion.toCurrency, rate: conversion.rate };\n\n/**\n * The currency converter (ChatGPT's `CurrencyConverterWidgetWithSource`): the title above one\n * elevated card with two rows — the amount in the first currency (editable) and its value in the second, a round swap\n * button on the hairline between them — and a footer with the rate and the day it is of. Changing the amount and\n * swapping the currencies recompute in the browser from the one delivered rate; the rate is dated, so the widget says\n * \"Rate of <day>\" and never \"live\". The currencies are the delivered pair only — there is no picker.\n */\nexport const CurrencyConverterWidget = (props: CurrencyConverterWidgetProps) => {\n const { conversion, languageCode, isStatic = false, testId = \"currency-converter-widget\" } = props;\n const locale = useMemo(() => toCurrencyLocale(languageCode), [languageCode]);\n const fromNameId = useId();\n const [isSwapped, setIsSwapped] = useState(false);\n const [typedAmount, setTypedAmount] = useState(() => formatEditableAmount(conversion.amount, locale));\n const { fromCurrency, toCurrency, rate } = buildShownPair(conversion, isSwapped);\n\n const typedAmountNumber = parseTypedAmount(typedAmount, locale);\n const amount =\n typedAmountNumber !== undefined && typedAmountNumber >= 0 && typedAmountNumber <= MAX_CURRENCY_CONVERTER_AMOUNT\n ? typedAmountNumber\n : undefined;\n const isInvalid = typedAmount.trim() !== \"\" && amount === undefined;\n const convertedAmount = amount === undefined ? undefined : amount * rate;\n const fromSymbol = readCurrencySymbol(fromCurrency, locale);\n const toSymbol = readCurrencySymbol(toCurrency, locale);\n const rateDateText = conversion.rateDate ? formatRateDate(conversion.rateDate, locale) : undefined;\n // The field is as wide as what is typed (plus the caret), so the symbol sits right behind the number.\n const fieldWidth: CSSProperties = { width: `${Math.max(typedAmount.length, 1) + 0.5}ch` };\n\n return (\n <section className={styles.widget} data-testid={testId}>\n <div className={styles.title}>\n <Text role=\"intro\" weight=\"bold\" testId={`${testId}-title`}>\n {\"Currency converter\"}\n </Text>\n </div>\n <WidgetSurface>\n <div className={styles.row}>\n <CurrencyLabel\n currencyCode={fromCurrency}\n locale={locale}\n nameId={fromNameId}\n testId={`${testId}-from-currency`}\n />\n {isStatic ? (\n <div className={styles.amount}>\n <Text role=\"title\" translate={false} testId={`${testId}-amount-static`}>\n {amount === undefined ? \"–\" : formatCurrencyAmount(amount, fromCurrency, locale)}\n </Text>\n <Text role=\"intro\" color=\"var(--agents-fg-light)\" translate={false}>\n {fromSymbol}\n </Text>\n </div>\n ) : (\n <div\n className={classNames(styles.amount, styles.field, isInvalid && styles.fieldInvalid)}\n data-testid=\"currency-converter-amount\"\n >\n {/* A native input: the design is a borderless field as wide as its number, which the component library's outlined\n labelled Input cannot express. Named by the currency name beside it. */}\n <input\n className={styles.input}\n data-testid={`${testId}-input-amount`}\n type=\"text\"\n inputMode=\"decimal\"\n autoComplete=\"off\"\n aria-labelledby={fromNameId}\n aria-invalid={isInvalid || undefined}\n value={typedAmount}\n style={fieldWidth}\n onChange={(event) => setTypedAmount(event.target.value.slice(0, 18))}\n onBlur={() => amount !== undefined && setTypedAmount(formatEditableAmount(amount, locale))}\n />\n <Text role=\"intro\" color=\"var(--agents-fg-light)\" translate={false}>\n {fromSymbol}\n </Text>\n </div>\n )}\n </div>\n\n <div className={styles.divider}>\n {isStatic ? null : (\n <button\n type=\"button\"\n className={styles.swap}\n aria-label={translateText(\"Swap currencies\")}\n data-testid=\"currency-converter-swap\"\n onClick={() => setIsSwapped((wasSwapped) => !wasSwapped)}\n >\n <Icon name=\"sorting\" />\n </button>\n )}\n </div>\n\n <div className={styles.row}>\n <CurrencyLabel currencyCode={toCurrency} locale={locale} testId={`${testId}-to-currency`} />\n <div className={classNames(styles.amount, styles.result)} data-testid=\"currency-converter-result\">\n {/* HeroValue shrinks to the width of its hero row's parent: the slot beside the symbol, never wider. */}\n <span className={styles.heroSlot}>\n <span className={styles.heroRow} data-hero-row=\"\">\n <HeroValue>\n {convertedAmount === undefined ? \"–\" : formatCurrencyAmount(convertedAmount, toCurrency, locale)}\n </HeroValue>\n </span>\n </span>\n <Text role=\"intro\" color=\"var(--agents-fg-light)\" translate={false}>\n {toSymbol}\n </Text>\n </div>\n </div>\n\n <div className={styles.footer}>\n <Text\n role=\"caption\"\n weight=\"medium\"\n translate={false}\n testId={`${testId}-rate`}\n >\n {`1 ${fromCurrency} = ${formatExactNumber(rate, locale)} ${toCurrency}`}\n </Text>\n {rateDateText ? (\n <Text\n role=\"caption\"\n color=\"var(--agents-fg-light)\"\n replacements={{ rateDate: rateDateText }}\n testId={`${testId}-rate-date`}\n >\n {\"Rate of %rateDate%\"}\n </Text>\n ) : null}\n </div>\n {isInvalid ? (\n <Text\n role=\"caption\"\n color=\"var(--agents-danger-500)\"\n testId={`${testId}-amount-hint`}\n >\n {\"Enter an amount, such as 250 or 1,250.75\"}\n </Text>\n ) : null}\n </WidgetSurface>\n </section>\n );\n};\n","import { useMemo } from \"react\";\nimport type { PayloadConversationWidgetProps } from \"../../renderer/conversation-widget-props\";\nimport { useIsEmailWidgetRender } from \"../../renderer/ConversationWidgetRenderContext\";\nimport { useReportWidgetRenderStatus } from \"../../renderer/render-report/widget-render-report\";\nimport { useAgentsOwnerSettings } from \"../../provider/AgentsProvider\";\nimport { parseCurrencyConverterPayload } from \"./shared/currency-converter-widget-payload\";\nimport { CurrencyConverterWidget } from \"./CurrencyConverterWidget/CurrencyConverterWidget\";\n\n/**\n * `CurrencyConverter`: a currency conversion at the dated rate `getCurrencyExchangeRate` returned.\n * DATA-COMPLETE — the block carries the rate and its day; the widget never fetches. A block without a usable currency\n * pair or rate renders nothing and reports `failed`, so the model answers in prose instead of pointing at a widget\n * that is not there.\n */\nexport const CurrencyConverterConversationWidget = (props: PayloadConversationWidgetProps) => {\n const { payload } = props;\n const conversion = useMemo(() => parseCurrencyConverterPayload(payload), [payload]);\n const languageCode = useAgentsOwnerSettings().languageCode ?? \"\";\n const isEmailRender = useIsEmailWidgetRender();\n useReportWidgetRenderStatus(\n conversion ? \"mounted\" : \"failed\",\n conversion ? undefined : \"INVALID_PROP\",\n conversion ? undefined : \"The CurrencyConverter block has no valid fromCurrency, toCurrency and rate.\",\n );\n if (!conversion) return null;\n return (\n <CurrencyConverterWidget\n conversion={conversion}\n languageCode={languageCode}\n isStatic={isEmailRender}\n testId=\"currency-converter-widget\"\n />\n );\n};\n","/**\n * The fixed allow-list of libraries a CustomVisualization may ask for (libraries from a fixed allow-list\n * served by us). Each bundle is a pinned copy in `sandbox-frame/libraries/` (stored as `.txt`, so linters and type\n * checks skip the minified code), loaded lazily into its own chunk of our build and handed to the sandbox frame inside\n * the render message — the frame loads no script from any URL. The SHA-256 of each file is pinned here and checked by\n * `sandbox-frame/_custom-visualization-frame.spec.ts`, so a changed bundle is a deliberate re-pin. A block that names a\n * library outside this list is not run (it reports `failed`).\n */\nexport interface CustomVisualizationLibrary {\n /** The name the block writes in `libraries`. */\n name: string;\n version: string;\n /** The global the bundle defines in the frame (`window.d3`). */\n globalName: string;\n /** The bundle file in `sandbox-frame/libraries/`. */\n fileName: string;\n /** SHA-256 of the file, hex. */\n sha256: string;\n loadSource: () => Promise<string>;\n}\n\nexport const CUSTOM_VISUALIZATION_LIBRARIES: readonly CustomVisualizationLibrary[] = [\n {\n name: \"d3\",\n version: \"7.6.1\",\n globalName: \"d3\",\n fileName: \"d3-7.6.1.min.js.txt\",\n sha256: \"b384cf0baeec03aa9e1443fd670cd41c9ec984def9a7b4dbfd7ad2f197d5b573\",\n loadSource: () => import(\"../sandbox-frame/libraries/d3-7.6.1.min.js.txt?raw\").then((module) => module.default),\n },\n];\n\nexport const CUSTOM_VISUALIZATION_LIBRARY_NAMES: readonly string[] = CUSTOM_VISUALIZATION_LIBRARIES.map(\n (library) => library.name,\n);\n\nexport const findCustomVisualizationLibrary = (libraryName: string): CustomVisualizationLibrary | undefined =>\n CUSTOM_VISUALIZATION_LIBRARIES.find((library) => library.name === libraryName);\n\n/** The sources of the named libraries, in the given order; every name must be on the allow-list. */\nexport const loadCustomVisualizationLibrarySources = (libraryNames: readonly string[]): Promise<string[]> =>\n Promise.all(\n libraryNames.map((libraryName) => {\n const library = findCustomVisualizationLibrary(libraryName);\n return library\n ? library.loadSource()\n : Promise.reject(new Error(`The library \"${libraryName}\" is not on the allow-list.`));\n }),\n );\n","/**\n * The message protocol between the chat and the sandbox frame of a CustomVisualization. The frame\n * (`sandbox-frame/custom-visualization-frame.html`) runs the model's code on an opaque origin; everything it says is\n * untrusted. The host therefore accepts a message only when it comes from the frame's own `contentWindow`, names the\n * channel and the per-instance token, has exactly the keys of its type, stays under a size limit and — for a height —\n * carries a finite number, which the host clamps. A message is never a command: the host reads a height, a heartbeat,\n * \"ready\" and an error line, nothing else.\n */\n\nexport const CUSTOM_VISUALIZATION_FRAME_CHANNEL = \"agents-custom-visualization\";\n\n/** The global the visualization's script reads (`window.AGENTS_VISUALIZATION.data`, `.colorScheme`). */\nexport const CUSTOM_VISUALIZATION_GLOBAL_NAME = \"AGENTS_VISUALIZATION\";\n\n/** The prefix of the theme variables the frame sets (`--agents-fg`, `--agents-accent`, …). */\nexport const CUSTOM_VISUALIZATION_THEME_VARIABLE_PREFIX = \"--agents-\";\n\n/** The frame posts a heartbeat every second; this long without one (an endless loop) and the host removes the frame. */\nexport const CUSTOM_VISUALIZATION_HEARTBEAT_TIMEOUT_MS = 5000;\n\n/** From the frame's mount until its \"ready\" (libraries + script ran); longer and the host removes the frame. */\nexport const CUSTOM_VISUALIZATION_READY_TIMEOUT_MS = 15000;\n\n/** How often the host checks the two deadlines above. */\nexport const CUSTOM_VISUALIZATION_WATCHDOG_INTERVAL_MS = 500;\n\n/** The frame's height is clamped to this range (CSS px). */\nexport const CUSTOM_VISUALIZATION_MIN_HEIGHT_PX = 80;\nexport const CUSTOM_VISUALIZATION_MAX_HEIGHT_PX = 1200;\n\n/** At most this many height messages are applied per second; the rest are ignored. */\nexport const CUSTOM_VISUALIZATION_MAX_HEIGHT_MESSAGES_PER_SECOND = 20;\n\n/** A message whose JSON is longer than this is ignored. */\nexport const CUSTOM_VISUALIZATION_MAX_MESSAGE_CHARS = 1024;\n\n/** The frame cuts an error line to this length; a longer one is ignored as malformed. */\nexport const CUSTOM_VISUALIZATION_MAX_ERROR_MESSAGE_CHARS = 300;\n\nexport type CustomVisualizationFrameMessage =\n | { type: \"heartbeat\" }\n | { type: \"ready\" }\n | { type: \"height\"; height: number }\n | { type: \"error\"; message: string };\n\n/** The keys each message type carries — exactly these, nothing more. */\nconst FRAME_MESSAGE_KEYS: Readonly<Record<CustomVisualizationFrameMessage[\"type\"], readonly string[]>> = {\n heartbeat: [\"channel\", \"token\", \"type\"],\n ready: [\"channel\", \"token\", \"type\"],\n height: [\"channel\", \"token\", \"type\", \"height\"],\n error: [\"channel\", \"token\", \"type\", \"message\"],\n};\n\nconst isFrameMessageType = (type: unknown): type is CustomVisualizationFrameMessage[\"type\"] =>\n typeof type === \"string\" && Object.prototype.hasOwnProperty.call(FRAME_MESSAGE_KEYS, type);\n\nconst measureMessageChars = (data: unknown): number => {\n try {\n return JSON.stringify(data)?.length ?? Number.POSITIVE_INFINITY;\n } catch {\n return Number.POSITIVE_INFINITY;\n }\n};\n\n/**\n * The frame message `event` carries, or null when it is not one: another window sent it, the token or channel is not\n * this instance's, a key is missing or extra, the message is too large, or a value has the wrong type.\n */\nexport const readCustomVisualizationFrameMessage = (\n event: Pick<MessageEvent, \"data\" | \"source\">,\n expectedSource: MessageEventSource | null,\n expectedToken: string,\n): CustomVisualizationFrameMessage | null => {\n if (expectedSource === null || event.source !== expectedSource) return null;\n const data: unknown = event.data;\n if (typeof data !== \"object\" || data === null || Array.isArray(data)) return null;\n if (measureMessageChars(data) > CUSTOM_VISUALIZATION_MAX_MESSAGE_CHARS) return null;\n const fields = data as Record<string, unknown>;\n if (fields.channel !== CUSTOM_VISUALIZATION_FRAME_CHANNEL || fields.token !== expectedToken) return null;\n if (!isFrameMessageType(fields.type)) return null;\n const expectedKeys = FRAME_MESSAGE_KEYS[fields.type];\n const keys = Object.keys(fields);\n if (keys.length !== expectedKeys.length || !keys.every((key) => expectedKeys.includes(key))) return null;\n if (fields.type === \"height\") {\n return typeof fields.height === \"number\" && Number.isFinite(fields.height)\n ? { type: \"height\", height: fields.height }\n : null;\n }\n if (fields.type === \"error\") {\n return typeof fields.message === \"string\" && fields.message.length <= CUSTOM_VISUALIZATION_MAX_ERROR_MESSAGE_CHARS\n ? { type: \"error\", message: fields.message }\n : null;\n }\n return { type: fields.type };\n};\n\n/** A height the frame asked for, as the host applies it: rounded up and clamped to the allowed range. */\nexport const clampCustomVisualizationHeight = (requestedHeight: number): number =>\n Math.min(\n CUSTOM_VISUALIZATION_MAX_HEIGHT_PX,\n Math.max(CUSTOM_VISUALIZATION_MIN_HEIGHT_PX, Math.ceil(requestedHeight)),\n );\n\n/**\n * Whether one more height message may be applied now: keeps the times of the applied ones of the last second in\n * `appliedAtTimes` (mutated) and refuses beyond {@link CUSTOM_VISUALIZATION_MAX_HEIGHT_MESSAGES_PER_SECOND}.\n */\nexport const admitCustomVisualizationHeightMessage = (appliedAtTimes: number[], now: number): boolean => {\n while (appliedAtTimes.length > 0 && now - appliedAtTimes[0] >= 1000) appliedAtTimes.shift();\n if (appliedAtTimes.length >= CUSTOM_VISUALIZATION_MAX_HEIGHT_MESSAGES_PER_SECOND) return false;\n appliedAtTimes.push(now);\n return true;\n};\n\n/** A fresh per-instance token: 128 random bits as hex. */\nexport const createCustomVisualizationInstanceToken = (): string => {\n const randomBytes = new Uint8Array(16);\n crypto.getRandomValues(randomBytes);\n return Array.from(randomBytes, (randomByte) => randomByte.toString(16).padStart(2, \"0\")).join(\"\");\n};\n\n/** The one message the host sends: everything the frame shows and runs. */\nexport interface CustomVisualizationRenderMessage {\n channel: typeof CUSTOM_VISUALIZATION_FRAME_CHANNEL;\n type: \"render\";\n token: string;\n html: string;\n css: string;\n script: string;\n librarySources: string[];\n data: unknown;\n /** The theme variables under the package's prefix (`--agents-fg` → a resolved colour). */\n theme: Record<string, string>;\n colorScheme: \"light\" | \"dark\";\n /**\n * Further names the frame defines the same frozen global under, beside `AGENTS_VISUALIZATION` — the names the app\n * declares (`AgentsEnvironment.sandboxLegacyAliases.visualizationGlobalNames`). Empty without a declaration.\n */\n visualizationGlobalNames: string[];\n /**\n * Further prefixes the frame sets every theme variable under, beside `--agents-` — the prefixes the app declares\n * (`AgentsEnvironment.sandboxLegacyAliases.themeVariablePrefixes`). Empty without a declaration.\n */\n themeVariablePrefixes: string[];\n}\n","import { CUSTOM_VISUALIZATION_LIBRARY_NAMES } from \"./custom-visualization-libraries\";\nimport {\n CUSTOM_VISUALIZATION_MAX_HEIGHT_PX,\n CUSTOM_VISUALIZATION_MIN_HEIGHT_PX,\n} from \"./custom-visualization-frame-protocol\";\n\n/**\n * The payload of a CustomVisualization block: the model's own HTML, CSS and JavaScript plus the data the\n * script draws, run in a sandboxed frame. DATA-COMPLETE: the block carries everything; the frame fetches nothing.\n * Mirrors the backend class `CustomVisualizationConversationWidget` (fields, the source cap and its measure).\n */\nexport interface CustomVisualizationPayload {\n title: string;\n description: string;\n html: string;\n css: string;\n script: string;\n /** Names on the allow-list (`custom-visualization-libraries.ts`), loaded before the script. */\n libraries: string[];\n /** Any JSON the script reads as `window.AGENTS_VISUALIZATION.data`; null when the block has none. */\n data: unknown;\n /** The frame's height before the frame reports its own (CSS px, clamped). */\n initialHeight: number;\n}\n\nexport type CustomVisualizationPayloadProblem =\n | { code: \"NO_CONTENT\"; detail: string }\n | { code: \"SOURCE_TOO_LARGE\"; detail: string }\n | { code: \"UNKNOWN_LIBRARY\"; detail: string };\n\nexport type ParsedCustomVisualizationPayload =\n | { isValid: true; payload: CustomVisualizationPayload; sourceBytes: number }\n | { isValid: false; problem: CustomVisualizationPayloadProblem; title: string };\n\n/**\n * The most source a block may carry: the UTF-8 bytes of `html` + `css` + `script` + the JSON of `data`. Backend twin:\n * `CustomVisualizationConversationWidget::MAX_SOURCE_BYTES`.\n */\nexport const CUSTOM_VISUALIZATION_MAX_SOURCE_BYTES = 65536;\n\n/** The frame's height when the block names none. */\nexport const CUSTOM_VISUALIZATION_DEFAULT_HEIGHT_PX = 360;\n\nconst MAX_TITLE_CHARS = 160;\nconst MAX_DESCRIPTION_CHARS = 400;\nconst MAX_LIBRARIES = 4;\n\nconst readFirstString = (fields: Record<string, unknown>, keys: readonly string[]): string => {\n for (const key of keys) {\n const value = fields[key];\n if (typeof value === \"string\") return value;\n }\n return \"\";\n};\n\nconst readLibraryNames = (fields: Record<string, unknown>): string[] => {\n const librariesField = fields.libraries ?? fields.libs;\n const libraries = typeof librariesField === \"string\" ? [librariesField] : librariesField;\n if (!Array.isArray(libraries)) return [];\n return libraries\n .filter((libraryName): libraryName is string => typeof libraryName === \"string\")\n .map((libraryName) => libraryName.trim().toLowerCase())\n .filter(\n (libraryName, libraryIndex, libraryNames) =>\n libraryName !== \"\" && libraryNames.indexOf(libraryName) === libraryIndex,\n )\n .slice(0, MAX_LIBRARIES);\n};\n\nconst readInitialHeight = (fields: Record<string, unknown>): number => {\n const height = fields.height ?? fields.initialHeight;\n const heightNumber = typeof height === \"string\" ? Number(height) : height;\n if (typeof heightNumber !== \"number\" || !Number.isFinite(heightNumber)) return CUSTOM_VISUALIZATION_DEFAULT_HEIGHT_PX;\n return Math.min(\n CUSTOM_VISUALIZATION_MAX_HEIGHT_PX,\n Math.max(CUSTOM_VISUALIZATION_MIN_HEIGHT_PX, Math.round(heightNumber)),\n );\n};\n\nconst encodeUtf8Length = (text: string): number => new TextEncoder().encode(text).length;\n\n/**\n * The bytes the source cap counts: `html`, `css`, `script` and the compact JSON of `data` (nothing for no data), as\n * UTF-8 — the backend's `measureSourceBytes()` counts the same.\n */\nexport const measureCustomVisualizationSourceBytes = (\n payload: Pick<CustomVisualizationPayload, \"html\" | \"css\" | \"script\" | \"data\">,\n): number => {\n let dataJson = \"\";\n if (payload.data !== null && payload.data !== undefined) {\n try {\n dataJson = JSON.stringify(payload.data) ?? \"\";\n } catch {\n dataJson = \"\";\n }\n }\n return (\n encodeUtf8Length(payload.html) +\n encodeUtf8Length(payload.css) +\n encodeUtf8Length(payload.script) +\n encodeUtf8Length(dataJson)\n );\n};\n\n/**\n * Reads a block's payload. Alias-tolerant (`markup` / `styles` / `js` / `code`, `subtitle` / `caption`, `libs`,\n * `initialHeight`), never throws: a malformed payload, a block without HTML and script, a source above the cap or a\n * library outside the allow-list comes back invalid with the problem the widget reports.\n */\nexport const parseCustomVisualizationPayload = (rawPayload: string | undefined): ParsedCustomVisualizationPayload => {\n let fields: Record<string, unknown> = {};\n try {\n const parsedPayload: unknown = rawPayload ? JSON.parse(rawPayload) : {};\n if (typeof parsedPayload === \"object\" && parsedPayload !== null && !Array.isArray(parsedPayload)) {\n fields = parsedPayload as Record<string, unknown>;\n }\n } catch {\n fields = {};\n }\n\n const title = readFirstString(fields, [\"title\", \"name\"]).trim().slice(0, MAX_TITLE_CHARS);\n const payload: CustomVisualizationPayload = {\n title,\n description: readFirstString(fields, [\"description\", \"subtitle\", \"caption\"]).trim().slice(0, MAX_DESCRIPTION_CHARS),\n html: readFirstString(fields, [\"html\", \"markup\"]),\n css: readFirstString(fields, [\"css\", \"styles\", \"style\"]),\n script: readFirstString(fields, [\"script\", \"js\", \"javascript\", \"code\"]),\n libraries: readLibraryNames(fields),\n data: fields.data ?? null,\n initialHeight: readInitialHeight(fields),\n };\n\n if (payload.html.trim() === \"\" && payload.script.trim() === \"\") {\n return {\n isValid: false,\n title,\n problem: { code: \"NO_CONTENT\", detail: \"The CustomVisualization block carries neither html nor script.\" },\n };\n }\n const unknownLibraryName = payload.libraries.find(\n (libraryName) => !CUSTOM_VISUALIZATION_LIBRARY_NAMES.includes(libraryName),\n );\n if (unknownLibraryName !== undefined) {\n return {\n isValid: false,\n title,\n problem: {\n code: \"UNKNOWN_LIBRARY\",\n detail: `The library \"${unknownLibraryName.slice(0, 40)}\" is not available; allowed: ${CUSTOM_VISUALIZATION_LIBRARY_NAMES.join(\", \")}.`,\n },\n };\n }\n const sourceBytes = measureCustomVisualizationSourceBytes(payload);\n if (sourceBytes > CUSTOM_VISUALIZATION_MAX_SOURCE_BYTES) {\n return {\n isValid: false,\n title,\n problem: {\n code: \"SOURCE_TOO_LARGE\",\n detail: `The CustomVisualization source has ${sourceBytes} bytes; at most ${CUSTOM_VISUALIZATION_MAX_SOURCE_BYTES} are allowed.`,\n },\n };\n }\n return { isValid: true, payload, sourceBytes };\n};\n","export default \"data:text/html;base64,PCFkb2N0eXBlIGh0bWw+CjxodG1sIGxhbmc9ImVuIj4KPGhlYWQ+CjxtZXRhIGNoYXJzZXQ9InV0Zi04Ij4KPG1ldGEgaHR0cC1lcXVpdj0iQ29udGVudC1TZWN1cml0eS1Qb2xpY3kiIGNvbnRlbnQ9ImRlZmF1bHQtc3JjICdub25lJzsgc2NyaXB0LXNyYyAnc2hhMjU2LWxNMFhHbWhHaVpNSUhsalFsVFNLUHdoSmpsbmlTMytabExWY0Nob25VYkE9JyBibG9iOjsgc3R5bGUtc3JjICd1bnNhZmUtaW5saW5lJzsgaW1nLXNyYyBkYXRhOiBibG9iOjsgZm9udC1zcmMgZGF0YTo7IGZvcm0tYWN0aW9uICdub25lJzsgYmFzZS11cmkgJ25vbmUnIj4KPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xIj4KPG1ldGEgbmFtZT0icmVmZXJyZXIiIGNvbnRlbnQ9Im5vLXJlZmVycmVyIj4KPHRpdGxlPkN1c3RvbSB2aXN1YWxpemF0aW9uPC90aXRsZT4KPHN0eWxlPmh0bWwsYm9keXttYXJnaW46MDtwYWRkaW5nOjA7YmFja2dyb3VuZDp0cmFuc3BhcmVudDtjb2xvcjp2YXIoLS1hZ2VudHMtZmcsIzFkMWQxZik7Zm9udC1mYW1pbHk6dmFyKC0tYWdlbnRzLWZvbnQtZmFtaWx5LHN5c3RlbS11aSxzYW5zLXNlcmlmKTtmb250LXNpemU6MTRweDtsaW5lLWhlaWdodDoxLjQ7b3ZlcmZsb3cteDpoaWRkZW59KiwqOjpiZWZvcmUsKjo6YWZ0ZXJ7Ym94LXNpemluZzpib3JkZXItYm94fSN2aXN1YWxpemF0aW9ue2Rpc3BsYXk6Zmxvdy1yb290fTwvc3R5bGU+CjxzY3JpcHQ+CihmdW5jdGlvbiAoKSB7CiAgInVzZSBzdHJpY3QiOwogIC8vIFRoZSBzYW5kYm94IGhvc3Qgb2YgdGhlIEN1c3RvbVZpc3VhbGl6YXRpb24gd2lkZ2V0LiBJdCBydW5zIGluIGFuIGlmcmFtZSB3aXRoCiAgLy8gc2FuZGJveD0iYWxsb3ctc2NyaXB0cyIgKGFuIG9wYXF1ZSBvcmlnaW46IG5vIGNvb2tpZXMsIG5vIHN0b3JhZ2UsIG5vIHBhcmVudCBET00pIHVuZGVyIHRoZSBwb2xpY3kgYWJvdmUuIEl0IHdhaXRzCiAgLy8gZm9yIE9ORSByZW5kZXIgbWVzc2FnZSBmcm9tIGl0cyBwYXJlbnQgd2luZG93LCB0aGVuIHNob3dzIHRoZSBibG9jaydzIEhUTUwgYW5kIENTUywgbG9hZHMgdGhlIGFsbG93LWxpc3RlZAogIC8vIGxpYnJhcmllcyBhbmQgdGhlIGJsb2NrJ3Mgc2NyaXB0IGFzIGJsb2I6IHNjcmlwdHMgKHRoZSBvbmx5IHNjcmlwdHMgdGhlIHBvbGljeSBhZG1pdHMgYmVzaWRlcyB0aGlzIG9uZSksIGFuZCB0ZWxscwogIC8vIHRoZSBwYXJlbnQgaXRzIGhlaWdodCwgdGhhdCBpdCBpcyBhbGl2ZSAodGhlIGhlYXJ0YmVhdCksIHdoZW4gdGhlIHNjcmlwdCByYW4gKHJlYWR5KSBhbmQgd2hlbiBhIHNjcmlwdCBmYWlsZWQuIEl0CiAgLy8gYWN0cyBvbiBub3RoaW5nIGJ1dCB0aGF0IG9uZSBtZXNzYWdlLiBUaGUgc2NyaXB0IHJlYWRzIHdpbmRvdy5BR0VOVFNfVklTVUFMSVpBVElPTiBhbmQgdGhlIHRoZW1lIHZhcmlhYmxlcwogIC8vIC0tYWdlbnRzLSo7IHRoZSByZW5kZXIgbWVzc2FnZSBtYXkgbmFtZSBmdXJ0aGVyIGdsb2JhbCBuYW1lcyBhbmQgdmFyaWFibGUgcHJlZml4ZXMgdGhlIGFwcCBkZWNsYXJlZCAodGhlIG5hbWVzIGl0cwogIC8vIHN0b3JlZCBzY3JpcHRzIHJlYWQpLCBhbmQgdGhlIGZyYW1lIHRoZW4gZGVmaW5lcyB0aGUgc2FtZSBnbG9iYWwgYW5kIHNldHMgdGhlIHNhbWUgdmFyaWFibGVzIHVuZGVyIHRob3NlIGFzIHdlbGwuCiAgdmFyIENIQU5ORUwgPSAiYWdlbnRzLWN1c3RvbS12aXN1YWxpemF0aW9uIjsKICB2YXIgR0xPQkFMX05BTUUgPSAiQUdFTlRTX1ZJU1VBTElaQVRJT04iOwogIHZhciBUSEVNRV9WQVJJQUJMRV9QUkVGSVggPSAiLS1hZ2VudHMtIjsKICB2YXIgR0xPQkFMX05BTUVfUEFUVEVSTiA9IC9eW0EtWmEtel8kXVtBLVphLXowLTlfJF0qJC87CiAgdmFyIFRIRU1FX1ZBUklBQkxFX1BSRUZJWF9QQVRURVJOID0gL14tLVthLXpdW2EtejAtOS1dKi0kLzsKICB2YXIgSEVBUlRCRUFUX0lOVEVSVkFMX01TID0gMTAwMDsKICB2YXIgTUFYX0VSUk9SX01FU1NBR0VfTEVOR1RIID0gMzAwOwogIHZhciBwYXJlbnRXaW5kb3cgPSB3aW5kb3cucGFyZW50OwogIHZhciBwb3N0VG9QYXJlbnQgPSBwYXJlbnRXaW5kb3cucG9zdE1lc3NhZ2UuYmluZChwYXJlbnRXaW5kb3cpOwogIHZhciBpbnN0YW5jZVRva2VuID0gbnVsbDsKICB2YXIgbGFzdFBvc3RlZEhlaWdodCA9IC0xOwogIHZhciBoZWlnaHRNZWFzdXJlUmVxdWVzdGVkID0gZmFsc2U7CgogIHZhciBwb3N0ID0gZnVuY3Rpb24gKG1lc3NhZ2UpIHsKICAgIG1lc3NhZ2UuY2hhbm5lbCA9IENIQU5ORUw7CiAgICBtZXNzYWdlLnRva2VuID0gaW5zdGFuY2VUb2tlbjsKICAgIHBvc3RUb1BhcmVudChtZXNzYWdlLCAiKiIpOwogIH07CgogIHZhciByZXBvcnRFcnJvciA9IGZ1bmN0aW9uIChlcnJvclRleHQpIHsKICAgIHBvc3QoeyB0eXBlOiAiZXJyb3IiLCBtZXNzYWdlOiBTdHJpbmcoZXJyb3JUZXh0IHx8ICJVbmtub3duIHNjcmlwdCBlcnJvciIpLnNsaWNlKDAsIE1BWF9FUlJPUl9NRVNTQUdFX0xFTkdUSCkgfSk7CiAgfTsKCiAgLy8gVGhlIGNvbnRlbnQncyBvd24gaGVpZ2h0OiB0aGUgcm9vdCBpcyBhIGZsb3cgcm9vdCAobWFyZ2lucyBzdGF5IGluc2lkZSksIGFuZCB0aGUgZG9jdW1lbnQncyBzY3JvbGwgaGVpZ2h0IGlzIG5vCiAgLy8gbWVhc3VyZSDigJQgaW5zaWRlIGEgZnJhbWUgaXQgbmV2ZXIgZHJvcHMgYmVsb3cgdGhlIGZyYW1lJ3MgY3VycmVudCBoZWlnaHQuCiAgdmFyIG1lYXN1cmVIZWlnaHQgPSBmdW5jdGlvbiAoKSB7CiAgICBoZWlnaHRNZWFzdXJlUmVxdWVzdGVkID0gZmFsc2U7CiAgICB2YXIgdmlzdWFsaXphdGlvblJvb3QgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgidmlzdWFsaXphdGlvbiIpOwogICAgaWYgKCF2aXN1YWxpemF0aW9uUm9vdCkgcmV0dXJuOwogICAgdmFyIGNvbnRlbnRIZWlnaHQgPSBNYXRoLmNlaWwodmlzdWFsaXphdGlvblJvb3QuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0KTsKICAgIGlmIChjb250ZW50SGVpZ2h0ICE9PSBsYXN0UG9zdGVkSGVpZ2h0KSB7CiAgICAgIGxhc3RQb3N0ZWRIZWlnaHQgPSBjb250ZW50SGVpZ2h0OwogICAgICBwb3N0KHsgdHlwZTogImhlaWdodCIsIGhlaWdodDogY29udGVudEhlaWdodCB9KTsKICAgIH0KICB9OwoKICB2YXIgcmVxdWVzdEhlaWdodE1lYXN1cmUgPSBmdW5jdGlvbiAoKSB7CiAgICBpZiAoaGVpZ2h0TWVhc3VyZVJlcXVlc3RlZCkgcmV0dXJuOwogICAgaGVpZ2h0TWVhc3VyZVJlcXVlc3RlZCA9IHRydWU7CiAgICB3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lKG1lYXN1cmVIZWlnaHQpOwogIH07CgogIHZhciBsb2FkU2NyaXB0VGV4dCA9IGZ1bmN0aW9uIChzY3JpcHRUZXh0KSB7CiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkgewogICAgICB2YXIgc2NyaXB0VXJsID0gVVJMLmNyZWF0ZU9iamVjdFVSTChuZXcgQmxvYihbc2NyaXB0VGV4dF0sIHsgdHlwZTogInRleHQvamF2YXNjcmlwdCIgfSkpOwogICAgICB2YXIgc2NyaXB0RWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInNjcmlwdCIpOwogICAgICBzY3JpcHRFbGVtZW50LnNyYyA9IHNjcmlwdFVybDsKICAgICAgc2NyaXB0RWxlbWVudC5vbmxvYWQgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgVVJMLnJldm9rZU9iamVjdFVSTChzY3JpcHRVcmwpOwogICAgICAgIHJlc29sdmUoKTsKICAgICAgfTsKICAgICAgc2NyaXB0RWxlbWVudC5vbmVycm9yID0gZnVuY3Rpb24gKCkgewogICAgICAgIFVSTC5yZXZva2VPYmplY3RVUkwoc2NyaXB0VXJsKTsKICAgICAgICByZWplY3QobmV3IEVycm9yKCJBIHNjcmlwdCBjb3VsZCBub3QgYmUgbG9hZGVkIGluIHRoZSBzYW5kYm94LiIpKTsKICAgICAgfTsKICAgICAgZG9jdW1lbnQuaGVhZC5hcHBlbmRDaGlsZChzY3JpcHRFbGVtZW50KTsKICAgIH0pOwogIH07CgogIC8vIFRoZSB2YXJpYWJsZSdzIG5hbWUgd2l0aG91dCBpdHMgcHJlZml4IChmZy1saWdodCksIG9yIG51bGwgd2hlbiBpdCBjYXJyaWVzIG5vbmUgb2YgdGhlIGFjY2VwdGVkIHByZWZpeGVzLgogIHZhciByZWFkVGhlbWVWYXJpYWJsZVN1ZmZpeCA9IGZ1bmN0aW9uICh2YXJpYWJsZU5hbWUsIHRoZW1lVmFyaWFibGVQcmVmaXhlcykgewogICAgdmFyIGFjY2VwdGVkUHJlZml4ZXMgPSBbVEhFTUVfVkFSSUFCTEVfUFJFRklYXS5jb25jYXQodGhlbWVWYXJpYWJsZVByZWZpeGVzKTsKICAgIGZvciAodmFyIHByZWZpeEluZGV4ID0gMDsgcHJlZml4SW5kZXggPCBhY2NlcHRlZFByZWZpeGVzLmxlbmd0aDsgcHJlZml4SW5kZXgrKykgewogICAgICB2YXIgYWNjZXB0ZWRQcmVmaXggPSBhY2NlcHRlZFByZWZpeGVzW3ByZWZpeEluZGV4XTsKICAgICAgdmFyIHZhcmlhYmxlU3VmZml4ID0gdmFyaWFibGVOYW1lLnNsaWNlKGFjY2VwdGVkUHJlZml4Lmxlbmd0aCk7CiAgICAgIGlmICh2YXJpYWJsZU5hbWUuaW5kZXhPZihhY2NlcHRlZFByZWZpeCkgPT09IDAgJiYgL15bYS16LV0rJC8udGVzdCh2YXJpYWJsZVN1ZmZpeCkpIHJldHVybiB2YXJpYWJsZVN1ZmZpeDsKICAgIH0KICAgIHJldHVybiBudWxsOwogIH07CgogIC8vIEV2ZXJ5IGFjY2VwdGVkIHZhcmlhYmxlIGlzIHNldCB1bmRlciB0aGUgcGFja2FnZSdzIHByZWZpeCBhbmQgdW5kZXIgZWFjaCBkZWNsYXJlZCBwcmVmaXguCiAgdmFyIGFwcGx5VGhlbWVWYXJpYWJsZXMgPSBmdW5jdGlvbiAodGhlbWVWYXJpYWJsZXMsIHRoZW1lVmFyaWFibGVQcmVmaXhlcykgewogICAgaWYgKCF0aGVtZVZhcmlhYmxlcyB8fCB0eXBlb2YgdGhlbWVWYXJpYWJsZXMgIT09ICJvYmplY3QiKSByZXR1cm47CiAgICBPYmplY3Qua2V5cyh0aGVtZVZhcmlhYmxlcykuZm9yRWFjaChmdW5jdGlvbiAodmFyaWFibGVOYW1lKSB7CiAgICAgIHZhciB2YXJpYWJsZVZhbHVlID0gdGhlbWVWYXJpYWJsZXNbdmFyaWFibGVOYW1lXTsKICAgICAgdmFyIHZhcmlhYmxlU3VmZml4ID0gcmVhZFRoZW1lVmFyaWFibGVTdWZmaXgodmFyaWFibGVOYW1lLCB0aGVtZVZhcmlhYmxlUHJlZml4ZXMpOwogICAgICBpZiAodmFyaWFibGVTdWZmaXggPT09IG51bGwgfHwgdHlwZW9mIHZhcmlhYmxlVmFsdWUgIT09ICJzdHJpbmciKSByZXR1cm47CiAgICAgIFtUSEVNRV9WQVJJQUJMRV9QUkVGSVhdLmNvbmNhdCh0aGVtZVZhcmlhYmxlUHJlZml4ZXMpLmZvckVhY2goZnVuY3Rpb24gKHRoZW1lVmFyaWFibGVQcmVmaXgpIHsKICAgICAgICBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGUuc2V0UHJvcGVydHkodGhlbWVWYXJpYWJsZVByZWZpeCArIHZhcmlhYmxlU3VmZml4LCB2YXJpYWJsZVZhbHVlKTsKICAgICAgfSk7CiAgICB9KTsKICB9OwoKICB2YXIgcmVhZERlY2xhcmVkTmFtZXMgPSBmdW5jdGlvbiAoZGVjbGFyZWROYW1lcywgbmFtZVBhdHRlcm4pIHsKICAgIGlmICghQXJyYXkuaXNBcnJheShkZWNsYXJlZE5hbWVzKSkgcmV0dXJuIFtdOwogICAgcmV0dXJuIGRlY2xhcmVkTmFtZXMuZmlsdGVyKGZ1bmN0aW9uIChkZWNsYXJlZE5hbWUpIHsKICAgICAgcmV0dXJuIHR5cGVvZiBkZWNsYXJlZE5hbWUgPT09ICJzdHJpbmciICYmIG5hbWVQYXR0ZXJuLnRlc3QoZGVjbGFyZWROYW1lKTsKICAgIH0pOwogIH07CgogIHZhciBsb2FkTGlicmFyaWVzVGhlblNjcmlwdCA9IGZ1bmN0aW9uIChsaWJyYXJ5U291cmNlcywgdmlzdWFsaXphdGlvblNjcmlwdCwgbGlicmFyeUluZGV4KSB7CiAgICBpZiAobGlicmFyeUluZGV4IDwgbGlicmFyeVNvdXJjZXMubGVuZ3RoKSB7CiAgICAgIHJldHVybiBsb2FkU2NyaXB0VGV4dChsaWJyYXJ5U291cmNlc1tsaWJyYXJ5SW5kZXhdKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICByZXR1cm4gbG9hZExpYnJhcmllc1RoZW5TY3JpcHQobGlicmFyeVNvdXJjZXMsIHZpc3VhbGl6YXRpb25TY3JpcHQsIGxpYnJhcnlJbmRleCArIDEpOwogICAgICB9KTsKICAgIH0KICAgIHJldHVybiB2aXN1YWxpemF0aW9uU2NyaXB0ID8gbG9hZFNjcmlwdFRleHQodmlzdWFsaXphdGlvblNjcmlwdCkgOiBQcm9taXNlLnJlc29sdmUoKTsKICB9OwoKICB2YXIgcmVuZGVyID0gZnVuY3Rpb24gKHJlbmRlck1lc3NhZ2UpIHsKICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCJlcnJvciIsIGZ1bmN0aW9uIChlcnJvckV2ZW50KSB7CiAgICAgIHJlcG9ydEVycm9yKGVycm9yRXZlbnQgJiYgZXJyb3JFdmVudC5tZXNzYWdlID8gZXJyb3JFdmVudC5tZXNzYWdlIDogIlVua25vd24gc2NyaXB0IGVycm9yIik7CiAgICB9KTsKICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCJ1bmhhbmRsZWRyZWplY3Rpb24iLCBmdW5jdGlvbiAocmVqZWN0aW9uRXZlbnQpIHsKICAgICAgdmFyIHJlamVjdGlvblJlYXNvbiA9IHJlamVjdGlvbkV2ZW50ID8gcmVqZWN0aW9uRXZlbnQucmVhc29uIDogbnVsbDsKICAgICAgcmVwb3J0RXJyb3IocmVqZWN0aW9uUmVhc29uICYmIHJlamVjdGlvblJlYXNvbi5tZXNzYWdlID8gcmVqZWN0aW9uUmVhc29uLm1lc3NhZ2UgOiBTdHJpbmcocmVqZWN0aW9uUmVhc29uKSk7CiAgICB9KTsKICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoInNlY3VyaXR5cG9saWN5dmlvbGF0aW9uIiwgZnVuY3Rpb24gKHZpb2xhdGlvbkV2ZW50KSB7CiAgICAgIHJlcG9ydEVycm9yKCJCbG9ja2VkIGJ5IHRoZSBzYW5kYm94IHBvbGljeTogIiArIHZpb2xhdGlvbkV2ZW50LmVmZmVjdGl2ZURpcmVjdGl2ZSArICIgIgogICAgICAgICsgU3RyaW5nKHZpb2xhdGlvbkV2ZW50LmJsb2NrZWRVUkkgfHwgIiIpLnNsaWNlKDAsIDgwKSk7CiAgICB9KTsKICAgIHdpbmRvdy5zZXRJbnRlcnZhbChmdW5jdGlvbiAoKSB7CiAgICAgIHBvc3QoeyB0eXBlOiAiaGVhcnRiZWF0IiB9KTsKICAgIH0sIEhFQVJUQkVBVF9JTlRFUlZBTF9NUyk7CiAgICBwb3N0KHsgdHlwZTogImhlYXJ0YmVhdCIgfSk7CgogICAgdmFyIHRoZW1lVmFyaWFibGVQcmVmaXhlcyA9IHJlYWREZWNsYXJlZE5hbWVzKHJlbmRlck1lc3NhZ2UudGhlbWVWYXJpYWJsZVByZWZpeGVzLCBUSEVNRV9WQVJJQUJMRV9QUkVGSVhfUEFUVEVSTik7CiAgICBhcHBseVRoZW1lVmFyaWFibGVzKHJlbmRlck1lc3NhZ2UudGhlbWUsIHRoZW1lVmFyaWFibGVQcmVmaXhlcyk7CiAgICBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2V0QXR0cmlidXRlKCJkYXRhLWNvbG9yLXNjaGVtZSIsIHJlbmRlck1lc3NhZ2UuY29sb3JTY2hlbWUgPT09ICJkYXJrIiA/ICJkYXJrIiA6ICJsaWdodCIpOwogICAgdmFyIHN0eWxlRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInN0eWxlIik7CiAgICBzdHlsZUVsZW1lbnQudGV4dENvbnRlbnQgPSByZW5kZXJNZXNzYWdlLmNzczsKICAgIGRvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQoc3R5bGVFbGVtZW50KTsKICAgIHZhciB2aXN1YWxpemF0aW9uUm9vdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImRpdiIpOwogICAgdmlzdWFsaXphdGlvblJvb3QuaWQgPSAidmlzdWFsaXphdGlvbiI7CiAgICB2aXN1YWxpemF0aW9uUm9vdC5pbm5lckhUTUwgPSByZW5kZXJNZXNzYWdlLmh0bWw7CiAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHZpc3VhbGl6YXRpb25Sb290KTsKCiAgICB2YXIgdmlzdWFsaXphdGlvbiA9IE9iamVjdC5mcmVlemUoewogICAgICBkYXRhOiByZW5kZXJNZXNzYWdlLmRhdGEsCiAgICAgIGNvbG9yU2NoZW1lOiByZW5kZXJNZXNzYWdlLmNvbG9yU2NoZW1lID09PSAiZGFyayIgPyAiZGFyayIgOiAibGlnaHQiCiAgICB9KTsKICAgIFtHTE9CQUxfTkFNRV0uY29uY2F0KHJlYWREZWNsYXJlZE5hbWVzKHJlbmRlck1lc3NhZ2UudmlzdWFsaXphdGlvbkdsb2JhbE5hbWVzLCBHTE9CQUxfTkFNRV9QQVRURVJOKSkKICAgICAgLmZvckVhY2goZnVuY3Rpb24gKGdsb2JhbE5hbWUpIHsKICAgICAgICAvLyBBIGRlY2xhcmVkIG5hbWUgbmV2ZXIgcmVwbGFjZXMgYSBwcm9wZXJ0eSB0aGUgd2luZG93IGFscmVhZHkgaGFzIChsb2NhdGlvbiwgcGFyZW50LCDigKYpLgogICAgICAgIGlmICghKGdsb2JhbE5hbWUgaW4gd2luZG93KSkgd2luZG93W2dsb2JhbE5hbWVdID0gdmlzdWFsaXphdGlvbjsKICAgICAgfSk7CiAgICBpZiAodHlwZW9mIFJlc2l6ZU9ic2VydmVyID09PSAiZnVuY3Rpb24iKSB7CiAgICAgIG5ldyBSZXNpemVPYnNlcnZlcihyZXF1ZXN0SGVpZ2h0TWVhc3VyZSkub2JzZXJ2ZSh2aXN1YWxpemF0aW9uUm9vdCk7CiAgICB9CiAgICByZXF1ZXN0SGVpZ2h0TWVhc3VyZSgpOwoKICAgIGxvYWRMaWJyYXJpZXNUaGVuU2NyaXB0KHJlbmRlck1lc3NhZ2UubGlicmFyeVNvdXJjZXMsIHJlbmRlck1lc3NhZ2Uuc2NyaXB0LCAwKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgcmVxdWVzdEhlaWdodE1lYXN1cmUoKTsKICAgICAgcG9zdCh7IHR5cGU6ICJyZWFkeSIgfSk7CiAgICB9LCBmdW5jdGlvbiAobG9hZEVycm9yKSB7CiAgICAgIHJlcG9ydEVycm9yKGxvYWRFcnJvci5tZXNzYWdlKTsKICAgIH0pOwogIH07CgogIHZhciBpc1JlbmRlck1lc3NhZ2UgPSBmdW5jdGlvbiAobWVzc2FnZSkgewogICAgcmV0dXJuIG1lc3NhZ2UgIT09IG51bGwgJiYgdHlwZW9mIG1lc3NhZ2UgPT09ICJvYmplY3QiICYmIG1lc3NhZ2UuY2hhbm5lbCA9PT0gQ0hBTk5FTCAmJiBtZXNzYWdlLnR5cGUgPT09ICJyZW5kZXIiCiAgICAgICYmIHR5cGVvZiBtZXNzYWdlLnRva2VuID09PSAic3RyaW5nIiAmJiB0eXBlb2YgbWVzc2FnZS5odG1sID09PSAic3RyaW5nIiAmJiB0eXBlb2YgbWVzc2FnZS5jc3MgPT09ICJzdHJpbmciCiAgICAgICYmIHR5cGVvZiBtZXNzYWdlLnNjcmlwdCA9PT0gInN0cmluZyIgJiYgQXJyYXkuaXNBcnJheShtZXNzYWdlLmxpYnJhcnlTb3VyY2VzKQogICAgICAmJiBtZXNzYWdlLmxpYnJhcnlTb3VyY2VzLmV2ZXJ5KGZ1bmN0aW9uIChsaWJyYXJ5U291cmNlKSB7IHJldHVybiB0eXBlb2YgbGlicmFyeVNvdXJjZSA9PT0gInN0cmluZyI7IH0pCiAgICAgICYmIChtZXNzYWdlLnZpc3VhbGl6YXRpb25HbG9iYWxOYW1lcyA9PT0gdW5kZWZpbmVkIHx8IEFycmF5LmlzQXJyYXkobWVzc2FnZS52aXN1YWxpemF0aW9uR2xvYmFsTmFtZXMpKQogICAgICAmJiAobWVzc2FnZS50aGVtZVZhcmlhYmxlUHJlZml4ZXMgPT09IHVuZGVmaW5lZCB8fCBBcnJheS5pc0FycmF5KG1lc3NhZ2UudGhlbWVWYXJpYWJsZVByZWZpeGVzKSk7CiAgfTsKCiAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoIm1lc3NhZ2UiLCBmdW5jdGlvbiAobWVzc2FnZUV2ZW50KSB7CiAgICBpZiAobWVzc2FnZUV2ZW50LnNvdXJjZSAhPT0gcGFyZW50V2luZG93IHx8IGluc3RhbmNlVG9rZW4gIT09IG51bGwgfHwgIWlzUmVuZGVyTWVzc2FnZShtZXNzYWdlRXZlbnQuZGF0YSkpIHJldHVybjsKICAgIGluc3RhbmNlVG9rZW4gPSBtZXNzYWdlRXZlbnQuZGF0YS50b2tlbjsKICAgIHJlbmRlcihtZXNzYWdlRXZlbnQuZGF0YSk7CiAgfSk7Cn0pKCk7Cjwvc2NyaXB0Pgo8L2hlYWQ+Cjxib2R5PjwvYm9keT4KPC9odG1sPgo=\"","import bundledFrameUrl from \"../sandbox-frame/custom-visualization-frame.html?url\";\n\n/**\n * Where the sandbox frame of a CustomVisualization is served from — committed configuration, no\n * environment switch.\n *\n * `frameUrl: null` (the default) uses the frame page our own build emits (`app-build/assets/custom-visualization-frame-\n * <hash>.html`, the Vite dev server's copy locally): the app's own origin. The frame is still sandboxed\n * (`sandbox=\"allow-scripts\"`, an opaque origin: no cookies, no storage, no access to the chat's DOM), and Chromium puts\n * a sandboxed frame into a process of its own; a browser that does not (Safari, a Chromium without site isolation) runs\n * it in the chat's process, so an endless loop in the model's script can freeze the chat before the watchdog removes\n * the frame.\n *\n * Set `frameUrl` to the absolute URL of the same `custom-visualization-frame.html` on a host of ANOTHER registrable\n * domain (a separate site — a subdomain of the app's domain is the same site) to have every browser with site isolation\n * run it out of process. The file is self-contained (no relative references); the libraries travel in the render\n * message, so that host serves this one static file and nothing else.\n */\nexport const CUSTOM_VISUALIZATION_SANDBOX_CONFIG: { frameUrl: string | null } = {\n frameUrl: null,\n};\n\n/** The frame URL the widget loads. */\nexport const resolveCustomVisualizationFrameUrl = (): string =>\n CUSTOM_VISUALIZATION_SANDBOX_CONFIG.frameUrl ?? bundledFrameUrl;\n","/**\n * The chat's colours as plain values for the sandbox frame (the visualization may follow the theme). The\n * frame cannot read the chat's CSS, and a token's declared value is a `var()` / `light-dark()` expression that means\n * nothing there — so each token is RESOLVED once on a hidden probe inside the widget (its theme scope) and handed over as\n * a colour. The frame sets them as `--agents-*` custom properties (and under every prefix the app declares); the model's\n * CSS may use `var(--agents-fg)` and friends. The keys are the frame's variables, the values the chat's tokens.\n */\nconst THEME_TOKENS: Readonly<Record<string, string>> = {\n \"--agents-fg\": \"--agents-fg\",\n \"--agents-fg-light\": \"--agents-fg-light\",\n \"--agents-bg\": \"--agents-bg-surface\",\n \"--agents-bg-var\": \"--agents-bg-var\",\n \"--agents-accent\": \"--agents-fg-cta\",\n \"--agents-divider\": \"--agents-divider-gl\",\n};\n\nexport interface CustomVisualizationTheme {\n variables: Record<string, string>;\n colorScheme: \"light\" | \"dark\";\n}\n\n/** `rgb(r, g, b)` / `rgba(…)` → relative luminance 0…1; null for any other form. */\nconst readLuminance = (resolvedColor: string): number | null => {\n const channels = /^rgba?\\(\\s*([\\d.]+)[,\\s]+([\\d.]+)[,\\s]+([\\d.]+)/.exec(resolvedColor);\n if (!channels) return null;\n const [red, green, blue] = channels.slice(1, 4).map((channel) => Number(channel) / 255);\n return 0.2126 * red + 0.7152 * green + 0.0722 * blue;\n};\n\nexport const readCustomVisualizationTheme = (themeScopeElement: HTMLElement | null): CustomVisualizationTheme => {\n const variables: Record<string, string> = {};\n if (!themeScopeElement || typeof window.getComputedStyle !== \"function\") {\n return { variables, colorScheme: \"light\" };\n }\n const probeElement = document.createElement(\"span\");\n probeElement.setAttribute(\"aria-hidden\", \"true\");\n probeElement.hidden = true;\n themeScopeElement.appendChild(probeElement);\n try {\n for (const [frameVariable, chatToken] of Object.entries(THEME_TOKENS)) {\n probeElement.style.color = `var(${chatToken})`;\n const resolvedColor = window.getComputedStyle(probeElement).color;\n if (resolvedColor) variables[frameVariable] = resolvedColor;\n }\n const fontFamily = window.getComputedStyle(themeScopeElement).fontFamily;\n if (fontFamily) variables[\"--agents-font-family\"] = fontFamily;\n } finally {\n probeElement.remove();\n }\n const surfaceLuminance = readLuminance(variables[\"--agents-bg\"] ?? \"\");\n return { variables, colorScheme: surfaceLuminance !== null && surfaceLuminance < 0.5 ? \"dark\" : \"light\" };\n};\n","import { Text } from \"../../../provider/components\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { getSandboxLegacyAliases, translateText } from \"../../../provider/environment\";\nimport { SkeletonLine } from \"../../_shared/skeleton-primitives\";\nimport {\n useReportWidgetRenderStatus,\n type WidgetRenderReportCode,\n type WidgetRenderStatus,\n} from \"../../../renderer/render-report/widget-render-report\";\nimport type { CustomVisualizationPayload } from \"../shared/custom-visualization-widget-payload\";\nimport { loadCustomVisualizationLibrarySources } from \"../shared/custom-visualization-libraries\";\nimport { resolveCustomVisualizationFrameUrl } from \"../shared/custom-visualization-sandbox-config\";\nimport { readCustomVisualizationTheme } from \"../shared/read-custom-visualization-theme\";\nimport {\n admitCustomVisualizationHeightMessage,\n clampCustomVisualizationHeight,\n createCustomVisualizationInstanceToken,\n CUSTOM_VISUALIZATION_FRAME_CHANNEL,\n CUSTOM_VISUALIZATION_HEARTBEAT_TIMEOUT_MS,\n CUSTOM_VISUALIZATION_READY_TIMEOUT_MS,\n CUSTOM_VISUALIZATION_WATCHDOG_INTERVAL_MS,\n readCustomVisualizationFrameMessage,\n type CustomVisualizationRenderMessage,\n} from \"../shared/custom-visualization-frame-protocol\";\nimport styles from \"./CustomVisualizationFrame.module.scss\";\n\nexport interface CustomVisualizationFrameProps {\n payload: CustomVisualizationPayload;\n testId?: string;\n}\n\n/** Why the frame failed, in one English sentence for the model, and whether the frame was taken out. */\ninterface CustomVisualizationFrameFailure {\n detail: string;\n frameRemoved: boolean;\n}\n\ntype CustomVisualizationFramePhase = \"loading\" | \"ready\" | \"failed\";\n\nconst FRAME_RENDER_REPORTS: Readonly<\n Record<CustomVisualizationFramePhase, { status: WidgetRenderStatus; code?: WidgetRenderReportCode }>\n> = {\n loading: { status: \"pending\" },\n ready: { status: \"mounted\" },\n failed: { status: \"failed\", code: \"RENDER_FAILED\" },\n};\n\n/**\n * The model's visualization in its sandbox: an iframe `sandbox=\"allow-scripts\"` (never same-origin,\n * top-navigation, popups or forms) on the configured frame page, which holds the policy `default-src 'none'`. The host\n * sends ONE render message (html, css, script, the allow-listed library sources, the block's data, the chat's colours)\n * and from then on only listens: heights (clamped, rate-limited), heartbeats, \"ready\" and script errors — from this\n * frame's `contentWindow` with this instance's token only. A frame that stops beating (an endless loop) or never gets\n * ready is removed and the block reports `failed`; a script error reports `failed` and leaves what rendered.\n */\nexport const CustomVisualizationFrame = (props: CustomVisualizationFrameProps) => {\n const { payload, testId = \"custom-visualization-widget\" } = props;\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const themeScopeRef = useRef<HTMLDivElement>(null);\n const [instanceToken] = useState(createCustomVisualizationInstanceToken);\n const frameUrl = useMemo(resolveCustomVisualizationFrameUrl, []);\n const [librarySources, setLibrarySources] = useState<string[] | null>(payload.libraries.length === 0 ? [] : null);\n const [isFrameLoaded, setIsFrameLoaded] = useState(false);\n const [phase, setPhase] = useState<CustomVisualizationFramePhase>(\"loading\");\n const [failure, setFailure] = useState<CustomVisualizationFrameFailure | null>(null);\n const [frameHeight, setFrameHeight] = useState(payload.initialHeight);\n const renderMessageSentRef = useRef(false);\n const mountedAtRef = useRef(Date.now());\n const lastHeartbeatAtRef = useRef<number | null>(null);\n const appliedHeightTimesRef = useRef<number[]>([]);\n\n const failFrame = (detail: string, frameRemoved: boolean) => {\n setFailure((currentFailure) => currentFailure ?? { detail, frameRemoved });\n setPhase(\"failed\");\n };\n\n useEffect(() => {\n if (payload.libraries.length === 0) return undefined;\n let isCurrent = true;\n loadCustomVisualizationLibrarySources(payload.libraries).then(\n (loadedSources) => {\n if (isCurrent) setLibrarySources(loadedSources);\n },\n () => {\n if (isCurrent) failFrame(\"A library of the CustomVisualization could not be loaded.\", true);\n },\n );\n return () => {\n isCurrent = false;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [payload.libraries.join(\",\")]);\n\n // The one render message, once the frame page has loaded and the libraries are there.\n useEffect(() => {\n const frameWindow = iframeRef.current?.contentWindow;\n if (!isFrameLoaded || librarySources === null || renderMessageSentRef.current || !frameWindow) return;\n renderMessageSentRef.current = true;\n const theme = readCustomVisualizationTheme(themeScopeRef.current);\n const sandboxLegacyAliases = getSandboxLegacyAliases();\n const renderMessage: CustomVisualizationRenderMessage = {\n channel: CUSTOM_VISUALIZATION_FRAME_CHANNEL,\n type: \"render\",\n token: instanceToken,\n html: payload.html,\n css: payload.css,\n script: payload.script,\n librarySources,\n data: payload.data,\n theme: theme.variables,\n colorScheme: theme.colorScheme,\n visualizationGlobalNames: sandboxLegacyAliases.visualizationGlobalNames ?? [],\n themeVariablePrefixes: sandboxLegacyAliases.themeVariablePrefixes ?? [],\n };\n // The frame's origin is opaque, so no target origin can name it; the message goes to this frame's window only.\n frameWindow.postMessage(renderMessage, \"*\");\n }, [isFrameLoaded, librarySources, instanceToken, payload]);\n\n useEffect(() => {\n const receiveFrameMessage = (event: MessageEvent) => {\n const frameMessage = readCustomVisualizationFrameMessage(\n event,\n iframeRef.current?.contentWindow ?? null,\n instanceToken,\n );\n if (frameMessage === null) return;\n if (frameMessage.type === \"heartbeat\") {\n lastHeartbeatAtRef.current = Date.now();\n } else if (frameMessage.type === \"ready\") {\n lastHeartbeatAtRef.current = Date.now();\n setPhase((currentPhase) => (currentPhase === \"loading\" ? \"ready\" : currentPhase));\n } else if (frameMessage.type === \"height\") {\n if (admitCustomVisualizationHeightMessage(appliedHeightTimesRef.current, Date.now())) {\n setFrameHeight(clampCustomVisualizationHeight(frameMessage.height));\n }\n } else {\n failFrame(`The visualization's script failed: ${frameMessage.message.slice(0, 200)}`, false);\n }\n };\n window.addEventListener(\"message\", receiveFrameMessage);\n return () => window.removeEventListener(\"message\", receiveFrameMessage);\n }, [instanceToken]);\n\n // The watchdog: a frame that never gets ready, or that stops beating, is taken out. Paused while the tab is hidden\n // (the browser throttles the frame's timers there), restarted when it shows again.\n useEffect(() => {\n if (failure?.frameRemoved) return undefined;\n const restartDeadlinesWhenShown = () => {\n if (document.visibilityState !== \"visible\") return;\n const now = Date.now();\n if (lastHeartbeatAtRef.current !== null) lastHeartbeatAtRef.current = now;\n if (phase === \"loading\") mountedAtRef.current = now;\n };\n const checkDeadlines = () => {\n if (document.visibilityState === \"hidden\") return;\n const now = Date.now();\n if (phase === \"loading\" && now - mountedAtRef.current > CUSTOM_VISUALIZATION_READY_TIMEOUT_MS) {\n failFrame(\"The visualization did not finish loading in time and was closed.\", true);\n return;\n }\n const lastHeartbeatAt = lastHeartbeatAtRef.current;\n if (lastHeartbeatAt !== null && now - lastHeartbeatAt > CUSTOM_VISUALIZATION_HEARTBEAT_TIMEOUT_MS) {\n failFrame(\"The visualization's script stopped responding (an endless loop?) and was closed.\", true);\n }\n };\n const watchdogInterval = window.setInterval(checkDeadlines, CUSTOM_VISUALIZATION_WATCHDOG_INTERVAL_MS);\n document.addEventListener(\"visibilitychange\", restartDeadlinesWhenShown);\n return () => {\n window.clearInterval(watchdogInterval);\n document.removeEventListener(\"visibilitychange\", restartDeadlinesWhenShown);\n };\n }, [phase, failure?.frameRemoved]);\n\n const renderReport = FRAME_RENDER_REPORTS[phase];\n useReportWidgetRenderStatus(renderReport.status, renderReport.code, failure?.detail);\n\n if (failure?.frameRemoved) {\n return (\n <Text role=\"help\" color=\"var(--agents-fg-light)\" testId={`${testId}-closed`}>\n {\"The visualization stopped working and was closed.\"}\n </Text>\n );\n }\n\n return (\n <div ref={themeScopeRef} className={styles.frameArea}>\n <div className={styles.frameBox} data-frame-phase={phase} data-testid={`${testId}-frame-box`}>\n {/* The frame's height is the one value the sandbox decides (clamped); it cannot live in a stylesheet. */}\n <iframe\n ref={iframeRef}\n className={styles.frame}\n data-testid={`${testId}-frame`}\n style={{ height: frameHeight }}\n src={frameUrl}\n sandbox=\"allow-scripts\"\n referrerPolicy=\"no-referrer\"\n title={payload.title || translateText(\"Custom visualization\")}\n data-custom-visualization-frame=\"\"\n onLoad={() => setIsFrameLoaded(true)}\n />\n {phase === \"loading\" ? (\n <span className={styles.loadingCover} aria-busy=\"true\" data-testid={`${testId}-skeleton`}>\n <SkeletonLine height={frameHeight} radius={12} />\n </span>\n ) : null}\n </div>\n {phase === \"failed\" ? (\n <Text role=\"caption\" color=\"var(--agents-fg-light)\" testId={`${testId}-error`}>\n {\"Part of this visualization could not run.\"}\n </Text>\n ) : null}\n </div>\n );\n};\n","import { Icon, Text } from \"../../../provider/components\";\nimport type { ReactNode } from \"react\";\nimport { WidgetSurface } from \"../../_shared/modern\";\nimport { ModelText } from \"../../../kit/ModelText/ModelText\";\nimport type { CustomVisualizationPayload } from \"../shared/custom-visualization-widget-payload\";\nimport { CustomVisualizationFrame } from \"./CustomVisualizationFrame\";\nimport styles from \"./CustomVisualizationWidget.module.scss\";\n\ninterface CustomVisualizationHeaderProps {\n title: string;\n description: string;\n testId: string;\n}\n\n/** The model's title and caption above the frame — business text, shown as written. */\nconst CustomVisualizationHeader = (props: CustomVisualizationHeaderProps) => {\n const { title, description, testId } = props;\n if (title === \"\" && description === \"\") return null;\n return (\n <div className={styles.header}>\n {title !== \"\" ? (\n <ModelText role=\"intro\" weight=\"bold\" testId={`${testId}-title`}>\n {title}\n </ModelText>\n ) : null}\n {description !== \"\" ? (\n <ModelText role=\"caption\" color=\"var(--agents-fg-light)\" testId={`${testId}-description`}>\n {description}\n </ModelText>\n ) : null}\n </div>\n );\n};\n\nconst CustomVisualizationSurface = (props: { children: ReactNode; testId: string }) => {\n const { children, testId } = props;\n return (\n <WidgetSurface className={styles.widget} testId={testId}>\n <div className={styles.content}>{children}</div>\n </WidgetSurface>\n );\n};\n\n/** The live widget: the header and the sandboxed frame on one elevated card. */\nexport const CustomVisualizationWidget = (props: { payload: CustomVisualizationPayload; testId?: string }) => {\n const { payload, testId = \"custom-visualization-widget\" } = props;\n return (\n <CustomVisualizationSurface testId={testId}>\n <CustomVisualizationHeader title={payload.title} description={payload.description} testId={testId} />\n <CustomVisualizationFrame payload={payload} testId={testId} />\n </CustomVisualizationSurface>\n );\n};\n\n/**\n * The e-mail form (in e-mail only a static preview renders): no frame and no script — the header and one\n * flat tile saying the visualization is interactive and lives in the conversation.\n */\nexport const CustomVisualizationStaticPreview = (props: { title: string; description: string; testId?: string }) => {\n const { title, description, testId = \"custom-visualization-widget\" } = props;\n return (\n <CustomVisualizationSurface testId={testId}>\n <CustomVisualizationHeader title={title} description={description} testId={testId} />\n <div className={styles.staticPreviewTile} data-testid={`${testId}-static-preview`}>\n <Icon className={styles.staticPreviewIcon} name=\"barChart\" />\n <Text role=\"help\" color=\"var(--agents-fg-light)\">\n {\"Interactive visualization — open the conversation to use it.\"}\n </Text>\n </div>\n </CustomVisualizationSurface>\n );\n};\n","import { Text } from \"../../provider/components\";\nimport { useMemo } from \"react\";\nimport type { PayloadConversationWidgetProps } from \"../../renderer/conversation-widget-props\";\nimport { useIsEmailWidgetRender } from \"../../renderer/ConversationWidgetRenderContext\";\nimport { useWidgetImageRender } from \"../../image-render/WidgetImageRenderContext\";\nimport {\n useReportWidgetRenderStatus,\n type WidgetRenderReportCode,\n} from \"../../renderer/render-report/widget-render-report\";\nimport {\n parseCustomVisualizationPayload,\n type CustomVisualizationPayloadProblem,\n} from \"./shared/custom-visualization-widget-payload\";\nimport {\n CustomVisualizationStaticPreview,\n CustomVisualizationWidget,\n} from \"./CustomVisualizationWidget/CustomVisualizationWidget\";\n\ntype CustomVisualizationConversationWidgetProps = PayloadConversationWidgetProps;\n\n/** What each payload problem reports. */\nconst PROBLEM_REPORT_CODES: Readonly<Record<CustomVisualizationPayloadProblem[\"code\"], WidgetRenderReportCode>> = {\n NO_CONTENT: \"INVALID_PROP\",\n UNKNOWN_LIBRARY: \"INVALID_PROP\",\n SOURCE_TOO_LARGE: \"BUDGET_EXCEEDED\",\n};\n\n/** A block the widget does not run: one muted line, and the reason for the model. */\nconst CustomVisualizationNotRun = (props: { problem: CustomVisualizationPayloadProblem; testId: string }) => {\n const { problem, testId } = props;\n useReportWidgetRenderStatus(\"failed\", PROBLEM_REPORT_CODES[problem.code], problem.detail);\n return (\n <Text role=\"help\" color=\"var(--agents-fg-light)\" testId={`${testId}-error`}>\n {\"This visualization could not be shown.\"}\n </Text>\n );\n};\n\nconst CustomVisualizationEmailPreview = (props: { title: string; description: string; testId: string }) => {\n const { title, description, testId } = props;\n useReportWidgetRenderStatus(\"mounted\");\n return <CustomVisualizationStaticPreview title={title} description={description} testId={testId} />;\n};\n\n/**\n * A visualization the model wrote itself — its own HTML, CSS and JavaScript with the data in the block. DATA-COMPLETE and sandboxed: the code runs in an iframe without same-origin rights\n * under a policy that loads nothing from the network; only allow-listed libraries come along. For what no kit node of\n * `ComposedView` can express (a canvas animation, a custom projection) — never for a table, a chart or a map.\n * Reports `pending` until the script ran, `mounted` then, `failed` for a block it does not run, a script error or a\n * frame that stopped responding. In the e-mail it renders a static preview without the frame.\n */\nexport const CustomVisualizationConversationWidget = (props: CustomVisualizationConversationWidgetProps) => {\n const { payload } = props;\n const testId = \"custom-visualization-widget\";\n const parsedPayload = useMemo(() => parseCustomVisualizationPayload(payload), [payload]);\n const isEmailRender = useIsEmailWidgetRender();\n const widgetImageCapture = useWidgetImageRender();\n\n if (!parsedPayload.isValid) return <CustomVisualizationNotRun problem={parsedPayload.problem} testId={testId} />;\n if (isEmailRender || widgetImageCapture !== null) {\n return (\n <CustomVisualizationEmailPreview\n title={parsedPayload.payload.title}\n description={parsedPayload.payload.description}\n testId={testId}\n />\n );\n }\n // A new payload (an edited message) is a new instance: a new frame and a new token.\n return <CustomVisualizationWidget key={payload} payload={parsedPayload.payload} testId={testId} />;\n};\n","import { type AgentsIconName } from \"../../../provider/components\";\n\n/** The component-library glyph of an entity type — what the card's icon tile shows; a type not listed here gets `details`. */\nconst ENTITY_TYPE_ICONS: Record<string, AgentsIconName> = {\n competitor: \"business\",\n review: \"star\",\n keyword: \"search\",\n location: \"location\",\n business: \"home\",\n post: \"post\",\n page: \"browser\",\n};\n\n/** The name line for an entity without a label — one static translation key per type (no concatenated noun). */\nconst ENTITY_TYPE_FALLBACK_LABELS: Record<string, string> = {\n competitor: \"This competitor\",\n review: \"This review\",\n keyword: \"This keyword\",\n location: \"This location\",\n business: \"This business\",\n post: \"This post\",\n page: \"This page\",\n};\n\nexport const FALLBACK_ENTITY_LABEL = \"About this entry\";\n\nexport const entityTypeIcon = (entityType: string): AgentsIconName => ENTITY_TYPE_ICONS[entityType] ?? \"details\";\n\nexport const entityTypeFallbackLabel = (entityType: string): string =>\n ENTITY_TYPE_FALLBACK_LABELS[entityType] ?? FALLBACK_ENTITY_LABEL;\n","import { Icon, Text } from \"../../../provider/components\";\nimport { ModelText } from \"../../../kit/ModelText/ModelText\";\nimport type { EntityMentionFields } from \"../shared/entity-mention\";\nimport { entityTypeFallbackLabel, entityTypeIcon } from \"../shared/entity-mention-presentation\";\nimport styles from \"./EntityMentionCard.module.scss\";\n\nexport interface EntityMentionCardProps {\n mention: EntityMentionFields;\n testId?: string;\n}\n\n/**\n * The read-only echo of ONE mentioned entity above the owner's own message: a small elevated card with the entity\n * type's icon in a rounded tile, the caption \"Asking about\" and the entity's name below it. The name is business\n * content (`ModelText`: never translated, never parsed as markup); without one the line names the type (\"This review\").\n */\nexport const EntityMentionCard = (props: EntityMentionCardProps) => {\n const { mention, testId = \"entity-mention-chip\" } = props;\n return (\n <div className={styles.card} data-testid={testId}>\n <span className={styles.iconTile} data-testid={`${testId}-icon`}>\n <Icon color=\"var(--agents-fg-cta)\" pixelSize={16} name={entityTypeIcon(mention.entityType)} />\n </span>\n <span className={styles.text}>\n <Text\n className={styles.caption}\n role=\"caption\"\n color=\"var(--agents-fg-lightest)\"\n textWrap=\"nowrap\"\n testId={`${testId}-caption`}\n >\n {\"Asking about\"}\n </Text>\n {mention.label !== null ? (\n <ModelText\n className={styles.label}\n role=\"help\"\n weight=\"bold\"\n textWrap=\"nowrap\"\n testId={`${testId}-label`}\n >\n {mention.label}\n </ModelText>\n ) : (\n <Text\n className={styles.label}\n role=\"help\"\n weight=\"bold\"\n textWrap=\"nowrap\"\n testId={`${testId}-label`}\n >\n {entityTypeFallbackLabel(mention.entityType)}\n </Text>\n )}\n </span>\n </div>\n );\n};\n","/**\n * The `EntityMention` fence: ONE entity the owner picked from a detail panel (\"Ask about\n * this\"), carried in the owner's own next message as a ```widget fence, so the backend reads WHICH entity the\n * question is about (`EntityMentionConversationWidget.php`) instead of guessing it from a name. One widget per entity;\n * a message carries at most {@link MAX_ENTITY_MENTIONS_PER_MESSAGE}. Field names equal the backend class's properties.\n * Pure; every reader is alias-tolerant and never throws.\n */\nimport { getWidgetSelfHydrationKeyFieldName } from \"../../../provider/environment\";\n\nexport const ENTITY_MENTION_WIDGET_NAME = \"EntityMention\";\n\n/** Most entities one message mentions — one more \"Ask about this\" drops the oldest mention. */\nexport const MAX_ENTITY_MENTIONS_PER_MESSAGE = 5;\n\n/** Longest display name carried into the message (the name is shown, never trusted — the id identifies). */\nexport const MAX_ENTITY_MENTION_LABEL_LENGTH = 120;\n\n/** The backend resolver's `ENTITY_TYPE` form (`competitor`, `review`, `keyword`) — the `entityDetail` instance id rule. */\nconst ENTITY_TYPE_PATTERN = /^[a-zA-Z][a-zA-Z0-9]*$/;\n/** A row id or an external id — letters, digits, `_`, `-`, `.` (the `entityDetail` instance id rule). */\nconst ENTITY_ID_PATTERN = /^[A-Za-z0-9_.-]{1,256}$/;\n\nexport interface EntityMentionFields {\n entityType: string;\n entityId: string;\n /** The entity's name as the panel showed it; null when the opener knew none. */\n label: string | null;\n /** The key of the agent space the entity belongs to; null = the chat's agent space. */\n agentSpaceKey: number | null;\n}\n\n/** What an opener (the detail panel's button) knows about the entity. */\nexport interface EntityMentionTarget {\n entityType: string;\n entityId: string | number;\n label?: string | null;\n agentSpaceKey?: number | null;\n}\n\nconst readFirstDefined = (record: Record<string, unknown>, keys: string[]): unknown => {\n for (const key of keys) {\n if (Object.prototype.hasOwnProperty.call(record, key) && record[key] !== undefined && record[key] !== null) {\n return record[key];\n }\n }\n return undefined;\n};\n\nconst readEntityId = (value: unknown): string | null => {\n const entityIdText = typeof value === \"number\" && Number.isInteger(value) ? String(value) : value;\n return typeof entityIdText === \"string\" && ENTITY_ID_PATTERN.test(entityIdText) ? entityIdText : null;\n};\n\nconst readLabel = (value: unknown): string | null => {\n if (typeof value !== \"string\") return null;\n const label = value.replace(/\\s+/g, \" \").trim();\n return label === \"\" ? null : label.slice(0, MAX_ENTITY_MENTION_LABEL_LENGTH);\n};\n\nconst readAgentSpaceKey = (value: unknown): number | null => {\n const agentSpaceKey = typeof value === \"string\" && /^\\d{1,18}$/.test(value) ? Number(value) : value;\n return typeof agentSpaceKey === \"number\" && Number.isInteger(agentSpaceKey) && agentSpaceKey > 0\n ? agentSpaceKey\n : null;\n};\n\n/**\n * The mention a fence's fields (or a composer widget's fields) carry, or null when they name no entity. Tolerates the\n * spellings a copy might use (`type`/`kind` for the type, `id` for the id, `name`/`title` for the label).\n */\nexport const normalizeEntityMentionFields = (fields: unknown): EntityMentionFields | null => {\n if (typeof fields !== \"object\" || fields === null || Array.isArray(fields)) return null;\n const record = fields as Record<string, unknown>;\n const entityType = readFirstDefined(record, [\"entityType\", \"kind\"]);\n const entityId = readEntityId(readFirstDefined(record, [\"entityId\", \"id\"]));\n if (typeof entityType !== \"string\" || !ENTITY_TYPE_PATTERN.test(entityType) || entityId === null) return null;\n return {\n entityType,\n entityId,\n label: readLabel(readFirstDefined(record, [\"label\", \"name\", \"title\"])),\n agentSpaceKey: readAgentSpaceKey(record[getWidgetSelfHydrationKeyFieldName()]),\n };\n};\n\n/** The mention a widget `payload` (the fence's JSON string) carries, or null. */\nexport const parseEntityMentionPayload = (payload: string | undefined): EntityMentionFields | null => {\n if (typeof payload !== \"string\" || payload === \"\") return null;\n try {\n return normalizeEntityMentionFields(JSON.parse(payload));\n } catch {\n return null;\n }\n};\n\n/** The composer widget's fields for an opener's target, or null for a target that names no entity. */\nexport const buildEntityMentionFields = (target: EntityMentionTarget): EntityMentionFields | null =>\n normalizeEntityMentionFields({\n entityType: target.entityType,\n entityId: target.entityId,\n label: target.label ?? null,\n [getWidgetSelfHydrationKeyFieldName()]: target.agentSpaceKey ?? null,\n });\n\n/** The fields as the fence carries them: a null label or agent space key is not written. */\nexport const toEntityMentionWireFields = (mention: EntityMentionFields): Record<string, unknown> => {\n const wireFields: Record<string, unknown> = { entityType: mention.entityType, entityId: mention.entityId };\n if (mention.label !== null) wireFields.label = mention.label;\n if (mention.agentSpaceKey !== null) wireFields[getWidgetSelfHydrationKeyFieldName()] = mention.agentSpaceKey;\n return wireFields;\n};\n\n/** Identity of a mention: one entity is mentioned once per message. */\nexport const entityMentionKey = (mention: Pick<EntityMentionFields, \"entityType\" | \"entityId\">): string =>\n `${mention.entityType}:${mention.entityId}`;\n","import { useMemo } from \"react\";\nimport type { PayloadConversationWidgetProps } from \"../../renderer/conversation-widget-props\";\nimport { useReportWidgetRenderStatus } from \"../../renderer/render-report/widget-render-report\";\nimport { EntityMentionCard } from \"./EntityMentionCard/EntityMentionCard\";\nimport { parseEntityMentionPayload } from \"./shared/entity-mention\";\nimport styles from \"./EntityMentionConversationWidget.module.scss\";\n\n/**\n * The registry `component` of `EntityMention`: the read-only echo of the entity the owner asked\n * about, shown above the prose of the owner's OWN message (`ConversationMessageUserWidgets`) — the entity's card (type icon,\n * \"Asking about\", name) in place of the composer's chip. The owner put it there with the detail panel's \"Ask about this\" button\n * (`EntityMentionAskButton`); the agent never writes it. A payload that names no entity renders nothing and reports\n * `failed INVALID_PROP`.\n */\nexport const EntityMentionConversationWidget = (props: PayloadConversationWidgetProps) => {\n const { payload } = props;\n const mention = useMemo(() => parseEntityMentionPayload(payload), [payload]);\n useReportWidgetRenderStatus(\n mention === null ? \"failed\" : \"mounted\",\n mention === null ? \"INVALID_PROP\" : undefined,\n mention === null ? \"the EntityMention names no entity (entityType + entityId)\" : undefined,\n );\n if (mention === null) return null;\n return (\n <div className={styles.row} data-testid=\"entity-mention-message\">\n <EntityMentionCard mention={mention} />\n </div>\n );\n};\n","/**\n * The `WritingDraft` payload (DATA-COMPLETE: the model writes the whole draft). The parser is alias-tolerant (weak\n * models rename fields while they write, and ChatGPT's own `WritingArtifact` shape — `variant`, `content.text` — may be\n * copied), caps every string, and never throws: malformed JSON gives `isValidPayload: false`, which the widget reports\n * as `failed`; a payload without a text reports `empty`.\n */\n\n/** The body length shown at most (the backend's `WritingDraftConversationWidget::MAX_BODY_LENGTH`); the rest is cut. */\nexport const MAX_DRAFT_BODY_LENGTH = 20000;\n\nconst MAX_TITLE_LENGTH = 160;\nconst MAX_RECIPIENT_LENGTH = 320;\nconst MAX_SUBJECT_LENGTH = 240;\n\n/** The kinds the widget labels; the backend's `WritingDraftConversationWidget::KINDS`. */\nexport type WritingDraftKind = \"email\" | \"letter\" | \"post\" | \"reply\" | \"message\" | \"other\";\n\nexport interface WritingDraftPayload {\n /** False when the payload is not a JSON object at all. */\n isValidPayload: boolean;\n kind?: WritingDraftKind;\n title?: string;\n recipient?: string;\n subject?: string;\n /** The draft as Markdown; \"\" when the model wrote none. */\n body: string;\n /** A body field is there but holds no text (an object, a number, a list) — reported `failed`, not `empty`. */\n isBodyUnreadable: boolean;\n}\n\nconst KIND_KEYS = [\"kind\", \"variant\", \"draftType\", \"draft_type\", \"category\"] as const;\nconst TITLE_KEYS = [\"title\", \"heading\", \"name\"] as const;\nconst RECIPIENT_KEYS = [\"recipient\", \"recipients\", \"to\", \"addressee\", \"recipientEmail\", \"email\"] as const;\nconst SUBJECT_KEYS = [\"subject\", \"subjectLine\", \"subject_line\"] as const;\nconst BODY_KEYS = [\"body\", \"content\", \"text\", \"markdown\", \"message\", \"draft\"] as const;\n\n/** The words a model writes for \"no recipient yet\" — shown as an empty field, never as a recipient. */\nconst NO_RECIPIENT_WORDS = new Set([\"not specified\", \"unspecified\", \"unknown\", \"n/a\", \"none\", \"-\", \"tbd\"]);\n\nconst KIND_ALIASES: Record<string, WritingDraftKind> = {\n email: \"email\",\n \"e-mail\": \"email\",\n mail: \"email\",\n letter: \"letter\",\n brief: \"letter\",\n post: \"post\",\n socialpost: \"post\",\n social: \"post\",\n reply: \"reply\",\n response: \"reply\",\n answer: \"reply\",\n message: \"message\",\n sms: \"message\",\n chat: \"message\",\n dm: \"message\",\n other: \"other\",\n draft: \"other\",\n memo: \"other\",\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst readCappedString = (value: unknown, maxLength: number): string | undefined => {\n if (typeof value !== \"string\") return undefined;\n const trimmedValue = value.trim();\n return trimmedValue === \"\" ? undefined : trimmedValue.slice(0, maxLength);\n};\n\nconst readFirstString = (record: Record<string, unknown>, keys: readonly string[], maxLength: number) => {\n for (const key of keys) {\n const stringValue = readCappedString(record[key], maxLength);\n if (stringValue !== undefined) return stringValue;\n }\n return undefined;\n};\n\n/** `email`, `E-Mail`, `social_post` … → one of the kinds; another word → `other`; nothing → undefined. */\nconst readKind = (record: Record<string, unknown>): WritingDraftKind | undefined => {\n const kindWord = readFirstString(record, KIND_KEYS, 40);\n if (kindWord === undefined) return undefined;\n return KIND_ALIASES[kindWord.toLowerCase().replace(/[\\s_]/g, \"\")] ?? \"other\";\n};\n\n/** A recipient string, or a list of them joined by a comma; a \"not specified\" placeholder is no recipient. */\nconst readRecipient = (record: Record<string, unknown>): string | undefined => {\n for (const key of RECIPIENT_KEYS) {\n const rawValue = record[key];\n const recipient = Array.isArray(rawValue)\n ? readCappedString(\n rawValue.filter((entry): entry is string => typeof entry === \"string\").join(\", \"),\n MAX_RECIPIENT_LENGTH,\n )\n : readCappedString(rawValue, MAX_RECIPIENT_LENGTH);\n if (recipient !== undefined) return NO_RECIPIENT_WORDS.has(recipient.toLowerCase()) ? undefined : recipient;\n }\n return undefined;\n};\n\n/** The body as written (outer blank lines trimmed, inner kept); ChatGPT's `content: {format, text}` is read too. */\nconst readBody = (record: Record<string, unknown>): string => {\n for (const key of BODY_KEYS) {\n const rawValue = record[key];\n const bodyValue = isRecord(rawValue) ? (rawValue.text ?? rawValue.markdown ?? rawValue.body) : rawValue;\n if (typeof bodyValue === \"string\" && bodyValue.trim() !== \"\") {\n return bodyValue\n .replace(/^\\s*\\n/, \"\")\n .trimEnd()\n .slice(0, MAX_DRAFT_BODY_LENGTH);\n }\n }\n return \"\";\n};\n\n/** A body field that is present but no string the widget can read (`null` and `\"\"` count as \"no text\", not as this). */\nconst hasUnreadableBodyField = (record: Record<string, unknown>): boolean =>\n BODY_KEYS.some((key) => record[key] !== undefined && record[key] !== null && typeof record[key] !== \"string\");\n\nexport const parseWritingDraftPayload = (payload: string | undefined): WritingDraftPayload => {\n let parsedPayload: unknown;\n try {\n parsedPayload = JSON.parse(payload ?? \"\");\n } catch {\n return { isValidPayload: false, body: \"\", isBodyUnreadable: false };\n }\n if (!isRecord(parsedPayload)) return { isValidPayload: false, body: \"\", isBodyUnreadable: false };\n const kind = readKind(parsedPayload);\n const title = readFirstString(parsedPayload, TITLE_KEYS, MAX_TITLE_LENGTH);\n const recipient = readRecipient(parsedPayload);\n const subject = readFirstString(parsedPayload, SUBJECT_KEYS, MAX_SUBJECT_LENGTH);\n const body = readBody(parsedPayload);\n return {\n isValidPayload: true,\n body,\n isBodyUnreadable: body === \"\" && hasUnreadableBodyField(parsedPayload),\n ...(kind ? { kind } : {}),\n ...(title ? { title } : {}),\n ...(recipient ? { recipient } : {}),\n ...(subject ? { subject } : {}),\n };\n};\n","/**\n * The draft's Markdown as the plain text the owner pastes into a mail program, a letter or a post: the copy button and\n * the `mailto:` body use it, so no `**`, `#` or `[label](url)` syntax reaches the recipient. Paragraphs and line breaks\n * stay; list items keep a \"- \" / \"1. \" marker; a link keeps its label and, when the label is not the address itself,\n * the address in brackets. Pure, total, never throws.\n */\n\nconst replaceLinks = (line: string): string =>\n line.replace(/!?\\[([^\\]]*)\\]\\(([^)\\s]+)(?:\\s+\"[^\"]*\")?\\)/g, (_match, label: string, url: string) => {\n const trimmedLabel = label.trim();\n if (trimmedLabel === \"\" || trimmedLabel === url || `mailto:${trimmedLabel}` === url) {\n return url.replace(/^mailto:/i, \"\");\n }\n return `${trimmedLabel} (${url.replace(/^mailto:/i, \"\")})`;\n });\n\nconst removeEmphasis = (line: string): string =>\n line\n .replace(/(\\*\\*|__)(?=\\S)(.+?)(?<=\\S)\\1/g, \"$2\")\n .replace(/(^|[^*\\w])\\*(?=\\S)([^*]+?)(?<=\\S)\\*(?!\\*)/g, \"$1$2\")\n .replace(/(^|[^_\\w])_(?=\\S)([^_]+?)(?<=\\S)_(?![_\\w])/g, \"$1$2\")\n .replace(/~~(?=\\S)(.+?)(?<=\\S)~~/g, \"$1\")\n .replace(/`([^`]+)`/g, \"$1\");\n\nconst convertLine = (line: string): string => {\n if (/^\\s*([-*_])(\\s*\\1){2,}\\s*$/.test(line)) return \"\";\n const withoutHeading = line.replace(/^\\s{0,3}#{1,6}\\s+/, \"\").replace(/\\s+#+\\s*$/, \"\");\n const withoutQuote = withoutHeading.replace(/^\\s{0,3}>\\s?/, \"\");\n const withListMarker = withoutQuote.replace(/^(\\s*)[*+]\\s+/, \"$1- \");\n // A hard line break in Markdown (two trailing spaces or a backslash) is a plain line end here.\n const withoutHardBreak = withListMarker.replace(/(\\s{2,}|\\\\)$/, \"\");\n return removeEmphasis(replaceLinks(withoutHardBreak));\n};\n\nexport const convertDraftMarkdownToPlainText = (markdown: string): string =>\n markdown\n .replace(/\\r\\n?/g, \"\\n\")\n .split(\"\\n\")\n .map(convertLine)\n .join(\"\\n\")\n .replace(/\\n{3,}/g, \"\\n\\n\")\n .trim();\n","/**\n * The `mailto:` link that opens an e-mail draft in the owner's own mail program (RFC 6068). The widget never sends\n * anything: the link hands the recipient, the subject and the plain-text body to the mail program, which the owner\n * then sends — or not. Only real e-mail addresses go into the address part (a name such as \"Herr Müller\" opens a draft\n * without a recipient); a body that would make the link longer than mail programs reliably accept is left out, and\n * the caller tells the owner to copy the text instead.\n */\n\n/** Mail programs and browsers cut or refuse longer `mailto:` links (Outlook ~2,000, some browsers ~2,000). */\nexport const MAX_MAIL_LINK_LENGTH = 1900;\n\n/** A plain address: no spaces, one `@`, a dot in the domain, none of the characters that would break the link. */\nconst EMAIL_ADDRESS_PATTERN = /^[^\\s@<>()[\\]\"',;:\\\\]+@[^\\s@<>()[\\]\"',;:\\\\]+\\.[^\\s@<>()[\\]\"',;:\\\\.]{2,}$/;\n\nexport interface DraftMailLink {\n href: string;\n /** False when the body was left out because the link would be too long. */\n includesBody: boolean;\n}\n\n/** The addresses in a recipient line: `a@b.de, c@d.de`, `Anna Muster <anna@b.de>`; anything else is dropped. */\nexport const readEmailAddresses = (recipient: string | undefined): string[] =>\n (recipient ?? \"\")\n .split(/[,;]/)\n .map((recipientPart) => {\n const bracketedAddress = /<([^<>]+)>/.exec(recipientPart);\n return (bracketedAddress ? bracketedAddress[1] : recipientPart).trim().replace(/^mailto:/i, \"\");\n })\n .filter((address) => EMAIL_ADDRESS_PATTERN.test(address));\n\n/** RFC 6068 encoding of a header value: every reserved character percent-encoded, line breaks as CRLF. */\nconst encodeMailHeaderValue = (value: string): string => encodeURIComponent(value.replace(/\\r?\\n/g, \"\\r\\n\"));\n\nconst buildMailHref = (addressPart: string, queryParts: (string | undefined)[]): string => {\n const query = queryParts.filter((queryPart): queryPart is string => queryPart !== undefined).join(\"&\");\n return `mailto:${addressPart}${query === \"\" ? \"\" : `?${query}`}`;\n};\n\nexport const buildDraftMailLink = (\n recipient: string | undefined,\n subject: string | undefined,\n plainTextBody: string,\n): DraftMailLink => {\n const addressPart = readEmailAddresses(recipient)\n .map((address) => encodeURIComponent(address).replace(/%40/g, \"@\"))\n .join(\",\");\n const subjectPart = subject ? `subject=${encodeMailHeaderValue(subject)}` : undefined;\n const bodyPart = plainTextBody !== \"\" ? `body=${encodeMailHeaderValue(plainTextBody)}` : undefined;\n const hrefWithBody = buildMailHref(addressPart, [subjectPart, bodyPart]);\n if (hrefWithBody.length <= MAX_MAIL_LINK_LENGTH || bodyPart === undefined) {\n return { href: hrefWithBody, includesBody: bodyPart !== undefined } satisfies DraftMailLink;\n }\n return { href: buildMailHref(addressPart, [subjectPart]), includesBody: false } satisfies DraftMailLink;\n};\n","import { visit } from \"unist-util-visit\";\n\ninterface DraftMdastNode {\n type: string;\n value?: string;\n children?: DraftMdastNode[];\n}\n\n/**\n * A single line break in a draft is a line break on screen (a signature \"Viele Grüße\\nAnna Schmidt\", an address block)\n * — in plain Markdown it would join the two lines into one. Splits every text node at its newlines into text and\n * `break` nodes, the way `remark-breaks` does (not a dependency of the app); code is left alone. A blank line stays a\n * new paragraph, as in Markdown.\n */\nexport const remarkDraftLineBreaks = () => (tree: DraftMdastNode) => {\n visit(tree, \"text\", (node: DraftMdastNode, index: number | undefined, parent: DraftMdastNode | undefined) => {\n if (!parent?.children || index === undefined || typeof node.value !== \"string\" || !node.value.includes(\"\\n\")) {\n return;\n }\n const lineNodes: DraftMdastNode[] = [];\n node.value.split(\"\\n\").forEach((line, lineIndex) => {\n if (lineIndex > 0) lineNodes.push({ type: \"break\" });\n if (line !== \"\") lineNodes.push({ type: \"text\", value: line });\n });\n parent.children.splice(index, 1, ...lineNodes);\n return index + lineNodes.length;\n });\n};\n","import { Markdown, Text, type AgentsMarkdownProps } from \"../../../provider/components\";\nimport { escapePlainTextForText } from \"../../../provider/environment\";\nimport type { ReactNode } from \"react\";\nimport { readSafeHttpUrl } from \"../../../kit/components/text/shared/text-node-values\";\nimport { remarkDraftLineBreaks } from \"../shared/remark-draft-line-breaks\";\nimport styles from \"./WritingDraftWidget.module.scss\";\n\ninterface DraftMarkdownElementProps {\n children?: ReactNode;\n /** The hast element react-markdown renders (its text is what a heading shows). */\n node?: DraftMarkdownHastNode;\n}\n\ninterface DraftMarkdownHastNode {\n type: string;\n value?: string;\n children?: DraftMarkdownHastNode[];\n}\n\n/** The plain text of a hast element — a heading's inline formatting is not kept. */\nconst readHastText = (node: DraftMarkdownHastNode | undefined): string => {\n if (!node) return \"\";\n if (node.type === \"text\") return node.value ?? \"\";\n return (node.children ?? []).map(readHastText).join(\"\");\n};\n\n/** Every heading level as a bold line at the body size — a draft has no page-sized headlines. */\nconst renderHeading = (props: DraftMarkdownElementProps) => (\n <Text\n role=\"body\"\n weight=\"bold\"\n translate={false}\n display=\"block\"\n className={styles.bodyHeading}\n headingLevel={4}\n >\n {escapePlainTextForText(readHastText(props.node))}\n </Text>\n);\n\n/**\n * The safe subset of the draft's Markdown (the kit `Markdown` node's rule): no images (an outside request,\n * a tracking pixel in a model's text), headings at most a bold line, links only to http(s) pages in a new tab — a\n * `javascript:` or `mailto:` link renders its label alone. Raw HTML never reaches the DOM: the shared renderer has no\n * raw-HTML plugin, so react-markdown drops it.\n */\nconst SAFE_DRAFT_MARKDOWN_COMPONENTS = {\n img: () => null,\n h1: renderHeading,\n h2: renderHeading,\n h3: renderHeading,\n h4: renderHeading,\n h5: renderHeading,\n h6: renderHeading,\n a: (props: DraftMarkdownElementProps & { href?: string }) => {\n const safeUrl = readSafeHttpUrl(props.href);\n if (safeUrl === null) return <span>{props.children}</span>;\n return (\n <a className={styles.bodyLink} href={safeUrl} target=\"_blank\" rel=\"noopener noreferrer\">\n {props.children}\n </a>\n );\n },\n} as NonNullable<AgentsMarkdownProps[\"components\"]>;\n\nconst DRAFT_REMARK_PLUGINS: NonNullable<AgentsMarkdownProps[\"remarkPlugins\"]> = [remarkDraftLineBreaks];\n\nexport interface WritingDraftBodyProps {\n /** The draft text as Markdown, the model's words or the owner's edit. */\n markdown: string;\n}\n\n/**\n * The draft text, formatted: paragraphs, emphasis, lists and quotes through the shared conversation renderer; a single\n * line break stays a line break (a signature, an address block).\n */\nexport const WritingDraftBody = (props: WritingDraftBodyProps) => {\n const { markdown } = props;\n return (\n <div className={styles.body} data-testid=\"writing-draft-body\">\n <Markdown\n markdown={markdown}\n translate={false}\n components={SAFE_DRAFT_MARKDOWN_COMPONENTS}\n remarkPlugins={DRAFT_REMARK_PLUGINS}\n />\n </div>\n );\n};\n","import { Text, TextArea, TextInput, type AgentsIconName } from \"../../../provider/components\";\nimport { useId } from \"react\";\nimport { WidgetSurface } from \"../../_shared/modern\";\nimport { ConversationWidgetButton } from \"../../_shared/ConversationWidgetButton\";\nimport { ConversationWidgetActions } from \"../../../renderer/ConversationWidgetActions/ConversationWidgetActions\";\nimport { ModelText } from \"../../../kit/ModelText/ModelText\";\nimport type { WritingDraftKind } from \"../shared/writing-draft-widget-payload\";\nimport { WritingDraftBody } from \"./WritingDraftBody\";\nimport styles from \"./WritingDraftWidget.module.scss\";\n\n/** The draft as the widget shows it — the model's draft, or the owner's edit of it. */\nexport interface WritingDraftValues {\n recipient: string;\n subject: string;\n body: string;\n}\n\nexport type WritingDraftField = keyof WritingDraftValues;\n\n/** The label above the headline per kind — one translation key each, never a concatenated word. */\nexport const WRITING_DRAFT_KIND_LABELS: Record<WritingDraftKind | \"unknown\", string> = {\n email: \"E-mail draft\",\n letter: \"Letter draft\",\n post: \"Post draft\",\n reply: \"Reply draft\",\n message: \"Message draft\",\n other: \"Text draft\",\n unknown: \"Text draft\",\n};\n\nexport interface WritingDraftWidgetProps {\n kind?: WritingDraftKind;\n /** The model's headline; shown under the kind label when it says more than the subject already does. */\n title?: string;\n values: WritingDraftValues;\n /** Recipient and subject rows are part of this kind (an e-mail, a letter) even while empty. */\n showsAddressFields: boolean;\n isEditing: boolean;\n /** The owner changed something; Reset brings the model's draft back. */\n isEdited: boolean;\n /** A post shows its length (characters of the plain text); undefined for the other kinds. */\n characterCount?: number;\n /** The copy button confirms for a moment after a copy. */\n isCopied: boolean;\n /** Offered for an e-mail draft only. */\n canOpenInMail: boolean;\n /** The mail link leaves the body out (too long): the owner is told to copy it. */\n mailLinkOmitsBody: boolean;\n onChangeField: (field: WritingDraftField, value: string) => void;\n onStartEditing: () => void;\n onFinishEditing: () => void;\n onReset: () => void;\n onCopy: () => void;\n onOpenInMail: () => void;\n}\n\n/**\n * The presentational draft: the kind label with the model's headline above the card; the card reads like the message\n * itself — To and Subject as a mail header divided from the text by a hairline, then the text. The actions (Copy, Edit,\n * Open in mail) sit centred under the card as small pills. Editing happens in the same card: the header rows and the\n * text become fields, Done and Discard changes replace the actions and a note says the edit stays on this screen.\n * Knows nothing about payloads, the registry or the chat. The actions are left out of an e-mail capture\n * (`ConversationWidgetActions`).\n */\nexport const WritingDraftWidget = (props: WritingDraftWidgetProps) => {\n const {\n kind,\n title,\n values,\n showsAddressFields,\n isEditing,\n isEdited,\n characterCount,\n isCopied,\n canOpenInMail,\n mailLinkOmitsBody,\n onChangeField,\n onStartEditing,\n onFinishEditing,\n onReset,\n onCopy,\n onOpenInMail,\n } = props;\n const headingId = useId();\n const kindLabel = WRITING_DRAFT_KIND_LABELS[kind ?? \"unknown\"];\n const headline = title !== undefined && title !== values.subject ? title : undefined;\n const showsRecipientRow = showsAddressFields || values.recipient !== \"\";\n const showsSubjectRow = showsAddressFields || values.subject !== \"\";\n const showsNotes = isEditing || isEdited || mailLinkOmitsBody;\n\n const renderHeaderLine = (label: string, value: string, emptyLabel: string, testId: string) => (\n <div className={styles.headerLine} data-testid={testId}>\n <Text role=\"help\" color=\"var(--agents-fg-light)\">\n {label}\n </Text>\n {value !== \"\" ? (\n <ModelText role=\"help\" weight=\"medium\" className={styles.wrappingText}>\n {value}\n </ModelText>\n ) : (\n <Text role=\"help\" color=\"var(--agents-fg-lightest)\" className={styles.emptyValue}>\n {emptyLabel}\n </Text>\n )}\n </div>\n );\n\n const renderPill = (label: string, icon: AgentsIconName, onClick: () => void, testId: string, isPrimary = false) => (\n <ConversationWidgetButton\n variant={isPrimary ? \"primary\" : \"muted\"}\n size=\"small\"\n rounded\n icon={icon}\n onClick={onClick}\n testId={testId}\n >\n {label}\n </ConversationWidgetButton>\n );\n\n return (\n <section aria-labelledby={headingId} className={styles.root} data-testid=\"writing-draft-widget\">\n <div className={styles.titleBlock} id={headingId}>\n <Text\n role=\"intro\"\n weight=\"bold\"\n testId={headline ? \"writing-draft-widget-kind\" : \"writing-draft-widget-title\"}\n >\n {kindLabel}\n </Text>\n {headline ? (\n <ModelText role=\"help\" color=\"var(--agents-fg-light)\" className={styles.wrappingText} testId=\"writing-draft-widget-title\">\n {headline}\n </ModelText>\n ) : null}\n </div>\n\n <WidgetSurface className={styles.card} testId=\"writing-draft-widget-card\">\n {isEditing ? (\n <div className={styles.editFields}>\n {showsRecipientRow ? (\n <TextInput\n testId=\"writing-draft-recipient-input\"\n value={values.recipient}\n label={\"Recipient\"}\n onChange={(text) => onChangeField(\"recipient\", text)}\n />\n ) : null}\n {showsSubjectRow ? (\n <TextInput\n testId=\"writing-draft-subject-input\"\n value={values.subject}\n label={\"Subject\"}\n onChange={(text) => onChangeField(\"subject\", text)}\n />\n ) : null}\n <TextArea\n testId=\"writing-draft-body-input\"\n value={values.body}\n label={\"Text of the draft\"}\n minRows={6}\n rows={6}\n showsCounter={false}\n autoFocus\n onChange={(text) => onChangeField(\"body\", text)}\n />\n </div>\n ) : (\n <>\n {showsRecipientRow || showsSubjectRow ? (\n <div className={styles.header}>\n {showsRecipientRow\n ? renderHeaderLine(\"To\", values.recipient, \"No recipient yet\", \"writing-draft-recipient\")\n : null}\n {showsSubjectRow\n ? renderHeaderLine(\"Subject\", values.subject, \"No subject yet\", \"writing-draft-subject\")\n : null}\n </div>\n ) : null}\n {values.body.trim() !== \"\" ? (\n <WritingDraftBody markdown={values.body} />\n ) : (\n <Text role=\"help\" color=\"var(--agents-fg-light)\" className={styles.wrappingText}>\n {\"The text of this draft is empty.\"}\n </Text>\n )}\n </>\n )}\n\n <ConversationWidgetActions>\n {showsNotes ? (\n <div className={styles.notes}>\n {isEditing || isEdited ? (\n <Text role=\"caption\" color=\"var(--agents-fg-light)\" className={styles.wrappingText}>\n {\"Your changes stay on this screen — the assistant does not see them.\"}\n </Text>\n ) : null}\n {mailLinkOmitsBody ? (\n <Text role=\"caption\" color=\"var(--agents-fg-light)\" className={styles.wrappingText}>\n {\"The text is too long for a mail link: copy it and paste it into the e-mail.\"}\n </Text>\n ) : null}\n </div>\n ) : null}\n </ConversationWidgetActions>\n\n {isEdited || characterCount !== undefined ? (\n <div className={styles.meta}>\n {isEdited ? (\n <Text role=\"caption\" color=\"var(--agents-fg-light)\" testId=\"writing-draft-edited\">\n {\"Edited by you\"}\n </Text>\n ) : null}\n {characterCount !== undefined ? (\n <Text\n role=\"caption\"\n color=\"var(--agents-fg-light)\"\n replacements={{ count: characterCount }}\n context={characterCount === 1 ? \"one\" : \"other\"}\n testId=\"writing-draft-character-count\"\n >\n {\"%count% character\"}\n </Text>\n ) : null}\n </div>\n ) : null}\n </WidgetSurface>\n\n <ConversationWidgetActions>\n <div className={styles.actions}>\n {isEditing ? (\n <>\n {renderPill(\"Done\", \"check\", onFinishEditing, \"writing-draft-done\", true)}\n {isEdited ? renderPill(\"Discard changes\", \"refresh\", onReset, \"writing-draft-reset\") : null}\n </>\n ) : (\n <>\n {renderPill(isCopied ? \"Copied\" : \"Copy\", isCopied ? \"check\" : \"duplicate\", onCopy, \"writing-draft-copy\")}\n {renderPill(\"Edit\", \"edit\", onStartEditing, \"writing-draft-edit\")}\n {canOpenInMail ? renderPill(\"Open in mail\", \"mail\", onOpenInMail, \"writing-draft-open-in-mail\") : null}\n {isEdited ? renderPill(\"Discard changes\", \"refresh\", onReset, \"writing-draft-reset\") : null}\n </>\n )}\n </div>\n </ConversationWidgetActions>\n </section>\n );\n};\n","import { Text } from \"../../provider/components\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport type { PayloadConversationWidgetProps } from \"../../renderer/conversation-widget-props\";\nimport { useReportWidgetRenderStatus } from \"../../renderer/render-report/widget-render-report\";\nimport { parseWritingDraftPayload, type WritingDraftPayload } from \"./shared/writing-draft-widget-payload\";\nimport { convertDraftMarkdownToPlainText } from \"./shared/draft-plain-text\";\nimport { buildDraftMailLink } from \"./shared/draft-mail-link\";\nimport {\n WritingDraftWidget,\n type WritingDraftField,\n type WritingDraftValues,\n} from \"./WritingDraftWidget/WritingDraftWidget\";\nimport styles from \"./WritingDraftConversationWidget.module.scss\";\n\ntype WritingDraftConversationWidgetProps = PayloadConversationWidgetProps;\n\n/** How long the copy button says \"Copied\". */\nconst COPIED_CONFIRMATION_MS = 2000;\n\nconst readDraftValues = (writingDraftPayload: WritingDraftPayload): WritingDraftValues => ({\n recipient: writingDraftPayload.recipient ?? \"\",\n subject: writingDraftPayload.subject ?? \"\",\n body: writingDraftPayload.body,\n});\n\nconst areDraftValuesEqual = (firstValues: WritingDraftValues, secondValues: WritingDraftValues): boolean =>\n firstValues.recipient === secondValues.recipient &&\n firstValues.subject === secondValues.subject &&\n firstValues.body === secondValues.body;\n\n/** Opens the mail program through the `mailto:` link — the page itself stays where it is. */\nconst openMailLink = (href: string): void => {\n window.location.assign(href);\n};\n\ninterface WritingDraftEditorProps {\n writingDraftPayload: WritingDraftPayload;\n}\n\n/**\n * The draft with its local edit state. Keyed by the payload in the outer widget, so a new block (a reworked draft the\n * model sends in a later reply renders its own widget anyway) starts from the model's text, never from an old edit.\n */\nconst WritingDraftEditor = (props: WritingDraftEditorProps) => {\n const { writingDraftPayload } = props;\n const originalValues = useMemo(() => readDraftValues(writingDraftPayload), [writingDraftPayload]);\n const [values, setValues] = useState<WritingDraftValues>(originalValues);\n const [isEditing, setIsEditing] = useState(false);\n const [isCopied, setIsCopied] = useState(false);\n\n useEffect(() => {\n if (!isCopied) return;\n const confirmationTimer = setTimeout(() => setIsCopied(false), COPIED_CONFIRMATION_MS);\n return () => clearTimeout(confirmationTimer);\n }, [isCopied]);\n\n const plainTextBody = useMemo(() => convertDraftMarkdownToPlainText(values.body), [values.body]);\n const isEmailDraft = writingDraftPayload.kind === \"email\";\n const draftMailLink = useMemo(\n () => (isEmailDraft ? buildDraftMailLink(values.recipient, values.subject, plainTextBody) : undefined),\n [isEmailDraft, values.recipient, values.subject, plainTextBody],\n );\n\n const changeField = (field: WritingDraftField, value: string) =>\n setValues((previousValues) => ({ ...previousValues, [field]: value }));\n\n const copyDraft = () => {\n void navigator.clipboard\n ?.writeText(plainTextBody)\n .then(() => setIsCopied(true))\n .catch(() => undefined);\n };\n\n const resetDraft = () => {\n setValues(originalValues);\n setIsEditing(false);\n };\n\n return (\n <WritingDraftWidget\n kind={writingDraftPayload.kind}\n title={writingDraftPayload.title}\n values={values}\n showsAddressFields={isEmailDraft || writingDraftPayload.kind === \"letter\"}\n isEditing={isEditing}\n isEdited={!areDraftValuesEqual(values, originalValues)}\n characterCount={writingDraftPayload.kind === \"post\" ? plainTextBody.length : undefined}\n isCopied={isCopied}\n canOpenInMail={draftMailLink !== undefined}\n mailLinkOmitsBody={draftMailLink !== undefined && plainTextBody !== \"\" && !draftMailLink.includesBody}\n onChangeField={changeField}\n onStartEditing={() => setIsEditing(true)}\n onFinishEditing={() => setIsEditing(false)}\n onReset={resetDraft}\n onCopy={copyDraft}\n onOpenInMail={() => draftMailLink && openMailLink(draftMailLink.href)}\n />\n );\n};\n\n/**\n * The `WritingDraft` widget (ChatGPT's `WritingBlock`): a text the model drafted for the owner to\n * send or publish themselves — an e-mail, a letter, a post, a reply, a message. DATA-COMPLETE: the block carries the\n * whole draft (kind, title, recipient, subject, the body as Markdown); nothing is fetched. The owner edits it in place,\n * copies the plain text and opens an e-mail draft in their own mail program (`mailto:`).\n *\n * Nothing leaves the screen: an edit, a copy or the mail link sends nothing to the agent (no signal, no message — the\n * widget is not answerable) and nothing to anyone else; the footer says so while the owner edits. In a report e-mail it\n * renders the draft read-only, without actions. A block without a text reports `empty`; an unreadable payload or a `body` that is no text reports `failed`.\n */\nexport const WritingDraftConversationWidget = (props: WritingDraftConversationWidgetProps) => {\n const { payload } = props;\n const writingDraftPayload = useMemo(() => parseWritingDraftPayload(payload), [payload]);\n const hasBody = writingDraftPayload.body.trim() !== \"\";\n\n const isUnreadable = !writingDraftPayload.isValidPayload || writingDraftPayload.isBodyUnreadable;\n useReportWidgetRenderStatus(\n isUnreadable ? \"failed\" : hasBody ? \"mounted\" : \"empty\",\n isUnreadable ? \"INVALID_PROP\" : hasBody ? undefined : \"NO_DATA\",\n !writingDraftPayload.isValidPayload\n ? \"The WritingDraft payload is not a JSON object.\"\n : writingDraftPayload.isBodyUnreadable\n ? \"The WritingDraft `body` is not a text; write the draft as one Markdown string.\"\n : hasBody\n ? undefined\n : \"The WritingDraft widget carries no text (`body`).\",\n );\n\n if (isUnreadable) {\n return (\n <Text\n role=\"help\"\n color=\"var(--agents-fg-light)\"\n className={styles.notice}\n testId=\"writing-draft-widget-error\"\n >\n {\"This draft could not be shown.\"}\n </Text>\n );\n }\n if (!hasBody) {\n return (\n <Text\n role=\"help\"\n color=\"var(--agents-fg-light)\"\n className={styles.notice}\n testId=\"writing-draft-widget-empty\"\n >\n {\"This draft has no text yet.\"}\n </Text>\n );\n }\n return <WritingDraftEditor key={payload} writingDraftPayload={writingDraftPayload} />;\n};\n","import { Button, Text } from \"../../provider/components\";\nimport React from \"react\";\nimport { useIsEmailWidgetRender } from \"../../renderer/ConversationWidgetRenderContext\";\nimport styles from \"./SuggestedActions.module.scss\";\nimport { useConversationWidgetContext } from \"../../renderer/ConversationWidgetCallbacksContext\";\nimport { BaseConversationWidgetProps } from \"../../renderer/conversation-widget-props\";\nimport {\n useReportWidgetRenderStatus,\n type WidgetRenderReportEntry,\n} from \"../../renderer/render-report/widget-render-report\";\n\nexport interface SuggestedAction {\n displayText: string;\n userAction: string;\n}\n\ninterface SuggestedActionsProps extends BaseConversationWidgetProps {\n options: string; // JSON-encoded SuggestedAction[]\n}\n\nfunction parseOptions(options: string): SuggestedAction[] | null {\n let parsed: unknown;\n try {\n parsed = JSON.parse(options);\n } catch {\n console.warn(\"[SuggestedActions] Failed to parse options JSON:\", options);\n return null;\n }\n\n if (\n !Array.isArray(parsed) ||\n !parsed.every(\n (item) =>\n typeof item === \"object\" &&\n item !== null &&\n typeof (item as any).displayText === \"string\" &&\n typeof (item as any).userAction === \"string\",\n )\n ) {\n console.warn(\"[SuggestedActions] Options must be an array of { displayText, userAction }:\", parsed);\n return null;\n }\n\n return parsed as SuggestedAction[];\n}\n\n/** The block's render report: an unreadable options list, an empty one, or mounted. */\nconst readSuggestedActionsRenderReport = (parsedOptions: SuggestedAction[] | null): WidgetRenderReportEntry => {\n if (parsedOptions === null)\n return {\n status: \"failed\",\n code: \"INVALID_PROP\",\n detail: \"The SuggestedActions options must be a JSON array of { displayText, userAction }.\",\n };\n if (parsedOptions.length === 0)\n return { status: \"empty\", code: \"NO_DATA\", detail: \"The SuggestedActions options list is empty.\" };\n return { status: \"mounted\" };\n};\n\nconst testId = \"suggested-actions-widget\";\n\nexport const SuggestedActions = ({ options, interactive = false }: SuggestedActionsProps) => {\n const { sendMessageToChat } = useConversationWidgetContext();\n const isEmailRender = useIsEmailWidgetRender();\n const parsedOptions = parseOptions(options);\n const renderReport = readSuggestedActionsRenderReport(parsedOptions);\n useReportWidgetRenderStatus(renderReport.status, renderReport.code, renderReport.detail);\n\n if (!parsedOptions) {\n return null;\n }\n\n return (\n <div className={styles.suggestedActions} data-testid={testId}>\n {parsedOptions.map((option, index) =>\n isEmailRender ? (\n <Text key={index} translate={false} testId={`${testId}-option-${option.userAction}`}>\n {option.displayText}\n </Text>\n ) : (\n <Button\n key={index}\n variant=\"muted\"\n disabled={!interactive}\n onClick={() => sendMessageToChat(option.userAction)}\n testId={`${testId}-option-${option.userAction}`}\n >\n {option.displayText}\n </Button>\n ),\n )}\n </div>\n );\n};\n","import { useAgentsActiveAgentSpaceKey } from \"../../provider/AgentsProvider\";\n\nexport interface ResolvedConversationWidgetAgentSpaceKey {\n /**\n * The key of the agent space the widget renders for when the agent named ANOTHER one than the active one; undefined\n * when the block names none or names the active one. A widget takes its chat-only read path for this key.\n */\n anotherAgentSpaceKey: number | undefined;\n /** The key of the agent space the owner works in; undefined when the app has none selected. */\n activeAgentSpaceKey: number | undefined;\n isAnotherAgentSpace: boolean;\n}\n\nconst toPositiveInteger = (rawValue: unknown): number | undefined => {\n if (rawValue === undefined || rawValue === null || rawValue === \"\") return undefined;\n const numericValue = typeof rawValue === \"number\" ? rawValue : Number(rawValue);\n if (!Number.isFinite(numericValue) || !Number.isInteger(numericValue) || numericValue <= 0) return undefined;\n return numericValue;\n};\n\nconst parseAgentSpaceKeyAttribute = (agentSpaceKeyAttribute: unknown): number | undefined => {\n // A block without the field is the regular case (most widgets name no agent space): no warning for it.\n if (agentSpaceKeyAttribute === undefined || agentSpaceKeyAttribute === null || agentSpaceKeyAttribute === \"\") {\n return undefined;\n }\n const agentSpaceKey = toPositiveInteger(agentSpaceKeyAttribute);\n if (agentSpaceKey === undefined) {\n console.warn(`[agent-space] invalid agent space key on a widget block: ${String(agentSpaceKeyAttribute)}`);\n }\n return agentSpaceKey;\n};\n\n/**\n * Resolves the agent space a widget block names (`readWidgetAgentSpaceKeyAttribute`) against the agent space the owner\n * works in (`AgentsEnvironment.useActiveAgentSpaceKey`). Returns the key of another agent space only when the agent\n * explicitly names a different one than the active one; otherwise undefined, so the widget keeps its regular behaviour.\n */\nexport const useResolvedConversationWidgetAgentSpaceKey = (\n agentSpaceKeyAttribute: unknown,\n): ResolvedConversationWidgetAgentSpaceKey => {\n const activeAgentSpaceKey = toPositiveInteger(useAgentsActiveAgentSpaceKey());\n const namedAgentSpaceKey = parseAgentSpaceKeyAttribute(agentSpaceKeyAttribute);\n\n if (namedAgentSpaceKey === undefined || namedAgentSpaceKey === activeAgentSpaceKey) {\n return { anotherAgentSpaceKey: undefined, activeAgentSpaceKey, isAnotherAgentSpace: false };\n }\n\n return { anotherAgentSpaceKey: namedAgentSpaceKey, activeAgentSpaceKey, isAnotherAgentSpace: true };\n};\n","import { getAgentsEnvironment } from \"../../provider/environment\";\nimport { registerWidgetHydrator } from \"../widget-hydration\";\n\nexport const AGENT_SPACE_NAME_WIDGET_TYPE = \"__agent-space-name\";\n\nexport interface AgentSpaceNameHydrationInput {\n agentSpaceKey: number;\n}\n\nexport interface AgentSpaceNameData {\n name?: string;\n}\n\n/**\n * The name lookup of the header chip on a widget of another agent space. Registered as a widget hydrator, so every\n * widget of a conversation that renders for the same agent space shares one read, and the entry is cleared with the\n * other widget data when the conversation changes. The name comes from the app (`AgentsEnvironment.readAgentSpaceName`);\n * without it the header shows the label of an unnamed agent space.\n */\nregisterWidgetHydrator<AgentSpaceNameHydrationInput, AgentSpaceNameData>(AGENT_SPACE_NAME_WIDGET_TYPE, {\n deriveKey: (type, payload) => `${type}:${payload.agentSpaceKey}`,\n hydrator: async (input, { signal }) => {\n const name = await getAgentsEnvironment().readAgentSpaceName?.(input.agentSpaceKey, signal);\n if (signal.aborted) throw new DOMException(\"Aborted\", \"AbortError\");\n return { name };\n },\n refetchOnNewInstance: false,\n});\n","import React from \"react\";\nimport { Tooltip } from \"../../provider/components\";\nimport {\n buildUnnamedAgentSpaceLabel,\n buildWidgetOfAnotherAgentSpaceExplanation,\n translateText,\n} from \"../../provider/environment\";\nimport { useWidgetHydration } from \"../widget-hydration\";\nimport {\n AGENT_SPACE_NAME_WIDGET_TYPE,\n AgentSpaceNameData,\n AgentSpaceNameHydrationInput,\n} from \"./agent-space-name.hydrator\";\nimport styles from \"./ConversationWidgetAgentSpaceHeader.module.scss\";\n\nexport interface ConversationWidgetAgentSpaceHeaderProps {\n agentSpaceKey: number;\n /**\n * Render the chip in the normal flow instead of floating it over the top-right corner of the enclosing frame — for a\n * surface whose corner is taken (the open arrow of a canvas handle, a canvas heading). The parent places it.\n */\n inFlow?: boolean;\n}\n\n/**\n * The chip above a widget whose block names another agent space than the one the owner works in. The name is read\n * through the widget hydration, so several chips of one agent space share one read and the entry is cleared with the\n * other widget data when the conversation changes. The app words what kind of thing an agent space is\n * (`AgentsEnvironment.buildUnnamedAgentSpaceLabel`, `buildWidgetOfAnotherAgentSpaceExplanation`).\n */\nexport const ConversationWidgetAgentSpaceHeader = (props: ConversationWidgetAgentSpaceHeaderProps) => {\n const { agentSpaceKey, inFlow = false } = props;\n const { data } = useWidgetHydration<AgentSpaceNameData, AgentSpaceNameHydrationInput>(AGENT_SPACE_NAME_WIDGET_TYPE, {\n agentSpaceKey,\n });\n\n // Each text carries the name of the agent space, so it goes through the translation with a replacement instead of a\n // template string — a template string is a new key per agent space.\n const label = data?.name ?? buildUnnamedAgentSpaceLabel(agentSpaceKey);\n const explanation = buildWidgetOfAnotherAgentSpaceExplanation(label);\n const noteLabel = translateText(\"Showing data for %label%\", { label });\n\n return (\n <div className={inFlow ? styles.inFlowAnchor : styles.anchor}>\n <Tooltip text={explanation} placement=\"top\" dark wrapsChild>\n <span className={styles.root} role=\"note\" aria-label={noteLabel} tabIndex={0}>\n <span className={styles.name}>{label}</span>\n </span>\n </Tooltip>\n </div>\n );\n};\n","import { classNames } from \"../../provider/class-names\";\nimport React from \"react\";\nimport { ConversationWidgetAgentSpaceHeader } from \"./ConversationWidgetAgentSpaceHeader\";\nimport layout from \"../conversation-widget-layout.module.scss\";\nimport styles from \"./ConversationWidgetAgentSpaceFrame.module.scss\";\n\ninterface ConversationWidgetAgentSpaceFrameProps {\n /** The key of another agent space than the active one: the frame shows its header chip. Undefined → no header. */\n anotherAgentSpaceKey?: number;\n /** Apply the shared wide layout — the frame becomes the wide bounds the chip anchors to. */\n wide?: boolean;\n /** Extra class on the frame — e.g. a widget that needs the frame to fill the drawer height. */\n className?: string;\n children: React.ReactNode;\n}\n\nexport const ConversationWidgetAgentSpaceFrame = (props: ConversationWidgetAgentSpaceFrameProps) => {\n const { anotherAgentSpaceKey, wide = false, className, children } = props;\n\n return (\n <div className={classNames(styles.frame, wide && layout.wide, className)}>\n {anotherAgentSpaceKey !== undefined && <ConversationWidgetAgentSpaceHeader agentSpaceKey={anotherAgentSpaceKey} />}\n {children}\n </div>\n );\n};\n","export interface MultiChoiceOption {\n label: string;\n sublabel?: string;\n value: string;\n selected?: boolean;\n}\n\nexport interface MultiChoicePayload {\n title?: string;\n subtitle?: string;\n options: MultiChoiceOption[];\n selectAllLabel?: string;\n confirmLabelTemplate?: string;\n confirmAction?: string;\n}\n\n/** The `MultiChoice` fence payload: an object with an `options` list; anything else renders nothing. */\nexport const parseMultiChoicePayload = (raw: string): MultiChoicePayload | null => {\n try {\n const parsed = JSON.parse(raw);\n if (!parsed || !Array.isArray(parsed.options)) return null;\n return parsed;\n } catch {\n return null;\n }\n};\n","import { Button, Checkbox, InteractiveSurface, Text } from \"../../provider/components\";\nimport { classNames } from \"../../provider/class-names\";\nimport { escapePlainTextForText } from \"../../provider/environment\";\nimport React, { useMemo, useState } from \"react\";\nimport { useIsEmailWidgetRender } from \"../../renderer/ConversationWidgetRenderContext\";\nimport { useConversationWidgetContext } from \"../../renderer/ConversationWidgetCallbacksContext\";\nimport { PayloadConversationWidgetProps } from \"../../renderer/conversation-widget-props\";\nimport { appendAnotherAgentSpaceToOwnerText } from \"../../provider/environment\";\nimport { readWidgetAgentSpaceKeyAttribute } from \"../../renderer/_agent-space/widget-agent-space-key-attribute\";\nimport { useResolvedConversationWidgetAgentSpaceKey } from \"../../renderer/_agent-space/use-resolved-conversation-widget-agent-space-key\";\nimport { ConversationWidgetAgentSpaceFrame } from \"../../renderer/_agent-space/ConversationWidgetAgentSpaceFrame\";\nimport { translateText } from \"../../provider/environment\";\nimport styles from \"./MultiChoiceConversationWidget.module.scss\";\nimport { parseMultiChoicePayload } from \"./shared/multi-choice-widget-payload\";\nimport { useReportWidgetRenderStatus } from \"../../renderer/render-report/widget-render-report\";\n\n// Convert the `{count}` template token to the `%count%` placeholder the translation\n// service replaces, so the confirm label stays one translatable key (singular, with\n// its MANY value) instead of a per-count string baked in JS.\nconst toConfirmLabelKey = (template: string): string => template.replace(/\\{count\\}/g, \"%count%\");\n\nconst formatConfirmAction = (template: string, values: string[]): string =>\n template.replace(/\\{values\\}/g, values.join(\", \")).replace(/\\{count\\}/g, String(values.length));\n\nconst testId = \"multi-choice-widget\";\n\nexport const MultiChoiceConversationWidget = (props: PayloadConversationWidgetProps) => {\n const { payload, fresh = false } = props;\n const { sendMessageToChat } = useConversationWidgetContext();\n const isEmailRender = useIsEmailWidgetRender();\n const { anotherAgentSpaceKey, isAnotherAgentSpace } = useResolvedConversationWidgetAgentSpaceKey(\n readWidgetAgentSpaceKeyAttribute(props),\n );\n const data = useMemo(() => parseMultiChoicePayload(payload), [payload]);\n\n const initialSelected = useMemo(\n () => new Set((data?.options ?? []).filter((o) => o.selected).map((o) => o.value)),\n [data],\n );\n const [selected, setSelected] = useState<Set<string>>(initialSelected);\n const [confirmed, setConfirmed] = useState(false);\n const isUnreadable = data === null;\n useReportWidgetRenderStatus(\n isUnreadable ? \"failed\" : \"mounted\",\n isUnreadable ? \"INVALID_PROP\" : undefined,\n isUnreadable ? \"The MultiChoice payload is not an object with an options list.\" : undefined,\n );\n\n // History replay: the choice is a one-shot interactive prompt, so a stale\n // remount renders nothing rather than re-offering an answered choice.\n if (!fresh && !isEmailRender) return null;\n\n if (!data) return null;\n\n const { title, subtitle, options } = data;\n const selectAllLabel = data.selectAllLabel ?? \"Select all\";\n const confirmLabelTemplate = data.confirmLabelTemplate ?? \"Confirm {count} selection\";\n const confirmAction = data.confirmAction ?? \"Confirmed: {values}\";\n\n const allSelected = options.length > 0 && selected.size === options.length;\n\n const toggle = (value: string) => {\n if (confirmed) return;\n setSelected((prev) => {\n const next = new Set(prev);\n if (next.has(value)) next.delete(value);\n else next.add(value);\n return next;\n });\n };\n\n const handleSelectAll = () => {\n if (confirmed) return;\n setSelected(allSelected ? new Set() : new Set(options.map((o) => o.value)));\n };\n\n const handleConfirm = () => {\n if (confirmed || selected.size === 0) return;\n const values = options.filter((o) => selected.has(o.value)).map((o) => o.label);\n setConfirmed(true);\n const action = formatConfirmAction(confirmAction, values);\n sendMessageToChat?.(\n isAnotherAgentSpace && anotherAgentSpaceKey !== undefined\n ? appendAnotherAgentSpaceToOwnerText(action, anotherAgentSpaceKey)\n : action,\n );\n };\n\n return (\n <ConversationWidgetAgentSpaceFrame anotherAgentSpaceKey={isAnotherAgentSpace ? anotherAgentSpaceKey : undefined}>\n <div className={styles.wrap} data-testid={testId}>\n {(title || subtitle) && (\n <div className={styles.heading} data-testid={`${testId}-heading`}>\n {title ? (\n <Text\n role=\"intro\"\n weight=\"bold\"\n translate={false}\n testId={`${testId}-title`}\n >\n {escapePlainTextForText(title)}\n </Text>\n ) : null}\n {subtitle ? (\n <Text\n role=\"caption\"\n color=\"var(--agents-fg-light)\"\n translate={false}\n testId={`${testId}-subtitle`}\n >\n {escapePlainTextForText(subtitle)}\n </Text>\n ) : null}\n </div>\n )}\n\n <div className={styles.options} data-testid={`${testId}-options`}>\n {options.map((option) => {\n const isSelected = selected.has(option.value);\n return (\n <InteractiveSurface\n hoverable\n key={option.value}\n className={classNames(styles.option, isSelected ? styles.optionSelected : undefined)}\n >\n <div\n className={styles.optionControl}\n data-testid={`${testId}-option-${option.value}`}\n onClick={isEmailRender ? undefined : () => toggle(option.value)}\n role={isEmailRender ? undefined : \"checkbox\"}\n aria-checked={isEmailRender ? undefined : isSelected}\n tabIndex={isEmailRender || confirmed ? -1 : 0}\n onKeyDown={(e) => {\n if (!isEmailRender && (e.key === \" \" || e.key === \"Enter\")) {\n e.preventDefault();\n toggle(option.value);\n }\n }}\n >\n <div className={styles.optionBody}>\n <Text\n role=\"body\"\n weight=\"bold\"\n className={isSelected ? styles.optionLabelSelected : styles.optionLabel}\n translate={false}\n >\n {escapePlainTextForText(option.label)}\n </Text>\n {option.sublabel ? (\n <Text role=\"caption\" color=\"var(--agents-fg-light)\" translate={false}>\n {escapePlainTextForText(option.sublabel)}\n </Text>\n ) : null}\n </div>\n {!isEmailRender && (\n <Checkbox\n checked={isSelected}\n disabled={confirmed}\n onChange={() => toggle(option.value)}\n testId={`${testId}-option-${option.value}-checkbox`}\n />\n )}\n </div>\n </InteractiveSurface>\n );\n })}\n </div>\n\n {!isEmailRender && (\n <div className={styles.footer}>\n <Button\n variant=\"muted\"\n onClick={handleSelectAll}\n disabled={confirmed}\n testId={`${testId}-select-all`}\n >\n {allSelected ? \"Clear all\" : selectAllLabel}\n </Button>\n {/* Button takes no `context`: resolve the singular key or its MANY value here. */}\n <Button size=\"extraLarge\"\n variant=\"shimmer\"\n onClick={handleConfirm}\n disabled={confirmed || selected.size === 0}\n translate={false}\n testId={`${testId}-confirm`}\n >\n {\n // Nothing picked yet: \"Confirm 0 selection\" read as a defect — the disabled button says what it does.\n selected.size === 0 && data.confirmLabelTemplate === undefined\n ? translateText(\"Confirm selection\")\n : translateText(\n toConfirmLabelKey(confirmLabelTemplate),\n { count: selected.size },\n selected.size === 1 ? \"one\" : \"other\",\n )\n }\n </Button>\n </div>\n )}\n </div>\n </ConversationWidgetAgentSpaceFrame>\n );\n};\n","import { useLayoutEffect, useState } from \"react\";\n\n/**\n * A row of buttons that turns into a full-width column once it would wrap: `data-stacked` goes on the row (its CSS lays\n * the column out). The row is measured as a row whenever its width or `items` change, so it goes back as soon as the\n * buttons fit. Attach the returned callback ref to the row, which may mount later than the hook's host.\n */\nexport const useStackWhenWrapped = <T extends HTMLElement>(items: unknown) => {\n const [row, setRow] = useState<T | null>(null);\n\n useLayoutEffect(() => {\n if (!row) return;\n let width = -1;\n const measure = () => {\n // Only the row's width decides; its own height changing (stacked or not) must not loop.\n if (row.clientWidth === width) return;\n width = row.clientWidth;\n delete row.dataset.stacked;\n const buttons = Array.from(row.children) as HTMLElement[];\n if (buttons.some((button) => button.offsetTop !== buttons[0].offsetTop)) row.dataset.stacked = \"\";\n };\n measure();\n const observer = new ResizeObserver(measure);\n observer.observe(row);\n return () => observer.disconnect();\n }, [row, items]);\n\n return setRow;\n};\n","/**\n * The `QuickReplies` fence payload (a backend hard rule): a closed question answered by SHORT\n * pills, each a complete answer the owner could also type. Validated strictly — an invalid payload renders nothing\n * (the widget's own kill switch, same as an unresolved wire name).\n */\nexport interface QuickRepliesPayload {\n options: string[];\n}\n\nexport const QUICK_REPLIES_MIN_OPTIONS = 2;\nexport const QUICK_REPLIES_MAX_OPTIONS = 5;\n\n/** Longer options are cut with an ellipsis for DISPLAY only — the click still sends the option in full. */\nexport const QUICK_REPLIES_MAX_DISPLAY_LENGTH = 60;\n\n/**\n * `options` must be an array of 2 to 5 strings, each non-empty after trimming and unique (case-insensitive) — a\n * malformed shape or a violated bound drops the whole widget. Options are NOT silently deduplicated: a payload the\n * agent got wrong (two options that only differ by case) is invalid, not quietly repaired.\n */\nexport const parseQuickRepliesPayload = (raw: string): QuickRepliesPayload | null => {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return null;\n }\n if (!parsed || typeof parsed !== \"object\" || !Array.isArray((parsed as { options?: unknown }).options)) {\n return null;\n }\n\n const rawOptions = (parsed as { options: unknown[] }).options;\n if (!rawOptions.every((option) => typeof option === \"string\")) return null;\n\n const trimmedOptions = (rawOptions as string[]).map((option) => option.trim());\n if (trimmedOptions.some((option) => option.length === 0)) return null;\n if (trimmedOptions.length < QUICK_REPLIES_MIN_OPTIONS || trimmedOptions.length > QUICK_REPLIES_MAX_OPTIONS) {\n return null;\n }\n\n const seenCaseInsensitive = new Set<string>();\n for (const option of trimmedOptions) {\n const key = option.toLowerCase();\n if (seenCaseInsensitive.has(key)) return null;\n seenCaseInsensitive.add(key);\n }\n\n return { options: trimmedOptions };\n};\n\n/** The rendered pill label — never what is sent (the click always sends the full, untruncated option text). */\nexport const truncateQuickReplyLabel = (option: string): string =>\n option.length > QUICK_REPLIES_MAX_DISPLAY_LENGTH\n ? `${option.slice(0, QUICK_REPLIES_MAX_DISPLAY_LENGTH - 1)}…`\n : option;\n","import { Text } from \"../../provider/components\";\nimport { classNames } from \"../../provider/class-names\";\nimport { useMemo, useRef, useState } from \"react\";\nimport { useIsEmailWidgetRender } from \"../../renderer/ConversationWidgetRenderContext\";\nimport { useConversationWidgetContext } from \"../../renderer/ConversationWidgetCallbacksContext\";\nimport { PayloadConversationWidgetProps } from \"../../renderer/conversation-widget-props\";\nimport { appendAnotherAgentSpaceToOwnerText } from \"../../provider/environment\";\nimport { readWidgetAgentSpaceKeyAttribute } from \"../../renderer/_agent-space/widget-agent-space-key-attribute\";\nimport { useResolvedConversationWidgetAgentSpaceKey } from \"../../renderer/_agent-space/use-resolved-conversation-widget-agent-space-key\";\nimport { ConversationWidgetAgentSpaceFrame } from \"../../renderer/_agent-space/ConversationWidgetAgentSpaceFrame\";\nimport { DonePill } from \"../_shared/DonePill\";\nimport { useStackWhenWrapped } from \"../_shared/use-stack-when-wrapped\";\nimport { parseQuickRepliesPayload, truncateQuickReplyLabel } from \"./shared/quick-replies-widget-payload\";\nimport { useReportWidgetRenderStatus } from \"../../renderer/render-report/widget-render-report\";\nimport styles from \"./QuickRepliesConversationWidget.module.scss\";\n\ntype QuickRepliesConversationWidgetProps = PayloadConversationWidgetProps;\n\nconst testId = \"quick-replies-widget\";\n\n/** A blank marker inside an option's text: an ellipsis (either glyph), a bracketed placeholder (`[...]`/`[…]`), or a\n * run of underscores — the shapes a template-with-a-blank option takes. Not global: `isQuickReplyPlaceholderOption`\n * only needs yes/no; `stripQuickReplyPlaceholderMarker` makes its own global copy to remove every occurrence. */\nconst PLACEHOLDER_MARKER_PATTERN = /\\[\\s*(?:\\.\\.\\.|…)\\s*]|_{3,}|\\.\\.\\.|…/;\n\n/**\n * A \"placeholder option\" is a QuickReplies option that is a TEMPLATE with a blank rather than a complete answer the\n * owner could send as-is (the backend has a hard rule against this — this predicate is the widget's\n * own backstop, since a malformed agent turn can still emit one). Three tells, any one is enough: an ellipsis\n * (`…` or `...`), a bracketed/underscore blank (`[...]`, `[…]`, `___`),\n * or the option simply ending in a colon (introduces an answer it never supplies). Clicking such an option must\n * never send its literal text — see `handleClick` below.\n */\nexport const isQuickReplyPlaceholderOption = (option: string): boolean => {\n const trimmed = option.trim();\n return PLACEHOLDER_MARKER_PATTERN.test(trimmed) || trimmed.endsWith(\":\");\n};\n\n/**\n * The text a placeholder-option click puts into the composer: every blank marker removed, trailing whitespace\n * trimmed, then ONE trailing space so the owner's cursor lands ready to type (e.g. `\"Yes, we deliver to these\n * areas: …\"` → `\"Yes, we deliver to these areas: \"`). A colon-only ending (no separate marker) is left as-is before\n * the trailing space is added — the colon is the prompt, not the blank.\n */\nexport const stripQuickReplyPlaceholderMarker = (option: string): string => {\n const stripped = option.trim().replace(new RegExp(PLACEHOLDER_MARKER_PATTERN.source, \"g\"), \"\").trimEnd();\n return `${stripped} `;\n};\n\n/**\n * The closed-question answer pills (a backend hard rule): two to five short options, each a\n * complete answer the owner could also type. A click posts that option's text as the owner's message — single pick,\n * never a multi-select (that is `MultiChoiceConversationWidget`).\n *\n * A placeholder option (`isQuickReplyPlaceholderOption`) is the one exception: it never sends. The click instead\n * puts the stripped text into the composer and focuses it (`prefillComposer`), so the owner completes the sentence\n * themselves instead of the literal blank going out as their message.\n *\n * Locks only once the host CONFIRMS the send was accepted (`sendMessageToChat`'s `void | Promise<boolean>`\n * contract) — a rejected send (a closed conversation, an in-flight start) leaves the pills clickable again, and a\n * second click while one is already in flight is ignored. Once locked, the pills give way to one pill naming the\n * chosen answer (`DonePill`).\n *\n * Bound to its own host message (`messageId`): once a NEWER owner message exists in the conversation (the owner\n * typed past it, or answered a later question), the widget goes inert — `interactive` alone does not catch this,\n * since it stays true for the rest of the live session, not just until the next owner message.\n */\nexport const QuickRepliesConversationWidget = (props: QuickRepliesConversationWidgetProps) => {\n const { payload, interactive = false, messageId } = props;\n const { sendMessageToChat, prefillComposer, messages } = useConversationWidgetContext();\n const isEmailRender = useIsEmailWidgetRender();\n const { anotherAgentSpaceKey, isAnotherAgentSpace } = useResolvedConversationWidgetAgentSpaceKey(\n readWidgetAgentSpaceKeyAttribute(props),\n );\n\n const data = useMemo(() => parseQuickRepliesPayload(payload), [payload]);\n const rowRef = useStackWhenWrapped<HTMLDivElement>(data?.options);\n\n const [chosenOption, setChosenOption] = useState<string | null>(null);\n const [locked, setLocked] = useState(false);\n const [pending, setPending] = useState(false);\n const pendingRef = useRef(false);\n\n // A newer owner (USER) message exists past this widget's host message — the conversation moved on, so a stale pick\n // here can no longer answer it. `messages` is ordered oldest → newest (the transcript order), so everything past\n // the host message's position is a later turn.\n const isStale = useMemo(() => {\n if (!messages || messageId === undefined) return false;\n const hostIndex = messages.findIndex((message) => String(message.id) === String(messageId));\n if (hostIndex === -1) return false;\n return messages.slice(hostIndex + 1).some((message) => message.role === \"USER\");\n }, [messages, messageId]);\n\n const isUnreadable = data === null;\n useReportWidgetRenderStatus(\n isUnreadable ? \"failed\" : \"mounted\",\n isUnreadable ? \"INVALID_PROP\" : undefined,\n isUnreadable\n ? \"The QuickReplies options must be 2 to 5 distinct non-empty strings; the widget was dropped.\"\n : undefined,\n );\n\n if (!data) return null;\n\n const inert = !interactive || isStale;\n const disabled = inert || locked || pending;\n\n const handleClick = async (option: string) => {\n if (disabled || pendingRef.current) return;\n if (isQuickReplyPlaceholderOption(option)) {\n // A template-with-a-blank option — sending it as-is would post the literal blank as the owner's message.\n // Put the completed-so-far text into the composer instead and let the owner finish it.\n prefillComposer(stripQuickReplyPlaceholderMarker(option));\n return;\n }\n pendingRef.current = true;\n setPending(true);\n setChosenOption(option);\n try {\n const outgoing =\n isAnotherAgentSpace && anotherAgentSpaceKey !== undefined\n ? appendAnotherAgentSpaceToOwnerText(option, anotherAgentSpaceKey)\n : option;\n const result = await sendMessageToChat(outgoing);\n if (result === false) {\n // Not accepted — leave the widget usable, nothing was recorded as chosen.\n setChosenOption(null);\n } else {\n // `true` or `void` (a host that doesn't report) both count as accepted.\n setLocked(true);\n }\n } catch {\n setChosenOption(null);\n } finally {\n pendingRef.current = false;\n setPending(false);\n }\n };\n\n return (\n <ConversationWidgetAgentSpaceFrame anotherAgentSpaceKey={isAnotherAgentSpace ? anotherAgentSpaceKey : undefined}>\n {/* The live region is there before the pills give way to the pill, so a screen reader announces it. */}\n <div aria-live=\"polite\" data-testid={testId}>\n {locked && chosenOption !== null ? (\n <DonePill translate={false} testId={`${testId}-done`}>\n {truncateQuickReplyLabel(chosenOption)}\n </DonePill>\n ) : (\n <div ref={rowRef} className={styles.wrap} role=\"group\" data-testid={`${testId}-options`}>\n {data.options.map((option) => {\n if (isEmailRender)\n return (\n <Text key={option} role=\"help\" translate={false} testId={`${testId}-option-${option}`}>\n {option}\n </Text>\n );\n const isChosen = chosenOption === option;\n return (\n <button\n key={option}\n type=\"button\"\n className={classNames(styles.pill, isChosen && styles.pillChosen)}\n disabled={disabled}\n onClick={() => handleClick(option)}\n data-testid={`${testId}-option-${option}`}\n >\n <Text role=\"help\" translate={false} className={styles.pillLabel}>\n {truncateQuickReplyLabel(option)}\n </Text>\n </button>\n );\n })}\n </div>\n )}\n </div>\n </ConversationWidgetAgentSpaceFrame>\n );\n};\n","import { Icon, Text } from \"../../provider/components\";\nimport { PayloadConversationWidgetProps } from \"../../renderer/conversation-widget-props\";\nimport { useReportWidgetRenderStatus } from \"../../renderer/render-report/widget-render-report\";\nimport React, { useMemo } from \"react\";\n\ntype ToolTraceConversationWidgetProps = PayloadConversationWidgetProps;\n\nconst isRecord = (v: unknown): v is Record<string, unknown> => typeof v === \"object\" && v !== null && !Array.isArray(v);\n\ninterface TracePayload {\n name?: unknown;\n input?: unknown;\n}\n\nconst parsePayload = (raw: string): TracePayload | null => {\n try {\n const parsed = JSON.parse(raw) as unknown;\n return isRecord(parsed) ? (parsed as TracePayload) : null;\n } catch {\n return null;\n }\n};\n\n/**\n * Humanizes the last segment of a nav key.\n * \"NAV.PROJECT.EXAMPLE.TASKS\" → \"Example Tasks\"\n */\nconst humanizeNavKey = (key: string): string => {\n const lastSegment = key.split(\".\").pop() ?? key;\n return lastSegment\n .toLowerCase()\n .replace(/_/g, \" \")\n .replace(/\\b\\w/g, (c) => c.toUpperCase());\n};\n\nconst resolveLabel = (payload: TracePayload): string => {\n if (payload.name === \"Navigate\" && isRecord(payload.input)) {\n const destination = payload.input.destination;\n if (typeof destination === \"string\" && destination.length > 0) {\n return humanizeNavKey(destination);\n }\n }\n const toolName = typeof payload.name === \"string\" ? payload.name : \"Tool\";\n return toolName;\n};\n\n/**\n * Renders a muted single-line trace for a tool_use assistant part.\n * Renders both on live delivery and history replay — never executes.\n */\nexport const ToolTraceConversationWidget = (props: ToolTraceConversationWidgetProps) => {\n const { payload } = props;\n\n const label = useMemo(() => {\n const parsed = parsePayload(payload);\n if (!parsed) return null;\n return resolveLabel(parsed);\n }, [payload]);\n\n useReportWidgetRenderStatus(\n label ? \"mounted\" : \"failed\",\n label ? undefined : \"INVALID_PROP\",\n label ? undefined : \"The ToolTrace payload is not a JSON object.\",\n );\n\n if (!label) return null;\n\n return (\n <span\n data-testid=\"tool-trace-widget\"\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: \"4px\",\n fontSize: \"12px\",\n color: \"var(--agents-text-subtle, #8a8a8a)\",\n fontStyle: \"italic\",\n }}\n >\n <Icon name=\"arrowRight\" />\n <Text replacements={{ label }} testId=\"tool-trace-widget-label\">\n {\"Opened %label%\"}\n </Text>\n </span>\n );\n};\n","import { useEffect, useState } from \"react\";\n\n/**\n * Min viewport width (px) at which the canvas side-panel split is usable. Mirrors the ModalSplitView `autoCloseWidth`\n * in ConversationView — below it the split auto-collapses, so a canvas widget must render its content inline instead of opening\n * a panel that immediately closes.\n */\nexport const CANVAS_VIABLE_MIN_WIDTH = 850;\n\nconst isViable = () => window.innerWidth >= CANVAS_VIABLE_MIN_WIDTH;\n\n/**\n * True when the viewport is wide enough for the canvas side panel. Re-renders the consumer ONLY when the boolean\n * crosses {@link CANVAS_VIABLE_MIN_WIDTH} — NOT on every resize pixel. This matters because the consumers (the canvas\n * widgets, ConversationView) re-mount heavy, self-fetching lists; a width-tracking\n * hook would re-render them on every resize tick and make dragging the window janky. We store the derived boolean and\n * skip the state update when it hasn't flipped, so React bails out and a drag that stays on one side of the threshold\n * costs zero re-renders.\n */\nexport const useCanvasViable = (): boolean => {\n const [viable, setViable] = useState(isViable);\n\n useEffect(() => {\n const onResize = () =>\n setViable((previous) => {\n const next = isViable();\n return next === previous ? previous : next;\n });\n window.addEventListener(\"resize\", onResize);\n // Sync once in case the width changed between the initial render and this effect running.\n onResize();\n return () => window.removeEventListener(\"resize\", onResize);\n }, []);\n\n return viable;\n};\n","import { Icon, InteractiveSurface, Text, type AgentsIconName } from \"../../provider/components\";\nimport { classNames } from \"../../provider/class-names\";\nimport { useWidgetImageRender } from \"../../image-render/WidgetImageRenderContext\";\nimport { useIsEmailWidgetRender } from \"../../renderer/ConversationWidgetRenderContext\";\nimport React, { ReactNode, useEffect, useRef } from \"react\";\nimport { useConversationWidgetContext } from \"../../renderer/ConversationWidgetCallbacksContext\";\nimport { ConversationWidgetAgentSpaceHeader } from \"../../renderer/_agent-space/ConversationWidgetAgentSpaceHeader\";\nimport type { CanvasId } from \"../../renderer/canvas/canvas-behaviours\";\nimport {\n CanvasAnchor,\n sameCanvasIdentity,\n} from \"../../renderer/canvas/canvas-state\";\nimport { useCanvasViable } from \"./use-canvas-viable\";\nimport styles from \"./CanvasWidgetCard.module.scss\";\n\n/**\n * The canvas a card opens: which canvas, which instance, anchored on which message. The body comes from\n * `canvasBodies` and re-reads its payload from the anchor message — the card carries no rendered node. Layout\n * (width, narrow-viewport rule, full bleed) is the canvas's behaviour (`canvas-behaviours.ts`), not a card prop.\n */\nexport interface CanvasWidgetCardCanvas {\n canvasId: CanvasId;\n instanceId: string;\n anchor: CanvasAnchor;\n}\n\nexport interface CanvasWidgetCardProps {\n /**\n * Headline shown on the inline card (e.g. \"Search results for 'X'\"). Rendered through the component library's `Text`, so\n * it auto-translates: keep dynamic values out of the string and pass them via `titleReplacements` (`%token%`).\n */\n title: string;\n /** `%token%` → value replacements for `title`, so an interpolated headline stays one stable translation key. */\n titleReplacements?: Record<string, string | number>;\n /** False when `title` is a business/user value that must render as-is (not a translation key). Default true. */\n translateTitle?: boolean;\n /** Optional second line (e.g. \"5 conversations\", a filter summary). Auto-translates — interpolate via `subtitleReplacements`. */\n subtitle?: string;\n /** `%token%` → value replacements for `subtitle`, so an interpolated second line stays one stable translation key. */\n subtitleReplacements?: Record<string, string | number>;\n /** False when `subtitle` is a business/user value that must render as-is (not a translation key). Default true. */\n translateSubtitle?: boolean;\n /** Optional leading icon (a glyph hinting what the canvas holds). Falls back to a generic panel glyph. */\n icon?: AgentsIconName;\n /**\n * A preview of the picture the canvas opens with. Set → the RICH card: the thumbnail replaces the icon badge, the\n * title gets more weight, and the hover is the component library's `GlobalStateComponent` layer (e.g. an app's closing summary\n * card with a hero picture).\n */\n thumbnail?: ReactNode;\n /** True when the host message was delivered live right now — auto-opens the canvas once. Never true after a reload or on history replay. */\n justDelivered?: boolean;\n /**\n * The canvas this card opens (`canvasForMessageWidget`). Undefined while the widget does not know its message (the\n * reply is still streaming, a composer echo): the card renders but opens nothing.\n */\n canvas?: CanvasWidgetCardCanvas;\n /**\n * The other agent space the canvas shows, when it is not the active one. The named card shows that agent space's chip on\n * a row above it: floating over the card's corner, the chip would cover the open affordance, and inside the card\n * (a `<button>`) its focusable popover trigger would nest one control in another. A `preview` names the agent space\n * itself, so the narrow viewport's preview branch adds nothing.\n */\n anotherAgentSpaceKey?: number;\n /**\n * The real widget content (the lightweight inline list). Rendered directly in the chat on a NARROW viewport (no side\n * canvas) so the user still sees the data; on a wide viewport the content lives only in the side canvas and this is\n * not rendered — the card is just the card.\n */\n preview?: ReactNode;\n /**\n * The widget's root test id. The named card carries it, its open control `<testId>-open-canvas`; with a `preview`\n * the preview carries the root id itself and only the open control is marked.\n */\n testId?: string;\n}\n\n/** Generic fallback glyph so the badge never renders empty when a widget omits its own icon. */\nconst DEFAULT_ICON = \"maximize\";\n\n/**\n * The standard inline representation of a CANVAS widget in the conversation — ONE component shared by every canvas\n * widget (web search, conversation search, and every list, gallery or summary canvas an app's widgets open).\n *\n * Wide viewport: a compact card (icon badge + title + subtitle + \"open\" affordance) that opens the canvas as the side\n * split, auto-opening once on a just-delivered message. The opening rule (`decideCanvasOpen`) decides in the reducer:\n * replay, the narrow-viewport rule of the canvas's behaviour and the customer's veto all live there.\n *\n * Narrow viewport (no side split, the canvas opens as a full-screen overlay), two shapes:\n * - with a `preview`: the real inline content is rendered in the chat so the user sees the data, plus an \"Open in\n * canvas\" affordance to open the full view over the chat. Tap to open — a live delivery is not a takeover.\n * - without a `preview` (the canvas is the widget's only surface, behaviour `narrowViewport: \"overlay\"`): the same\n * named card as on the wide viewport, so closing the canvas leaves a card to re-open.\n */\nexport const CanvasWidgetCard = ({\n title,\n titleReplacements,\n translateTitle = true,\n subtitle,\n subtitleReplacements,\n translateSubtitle = true,\n icon,\n thumbnail,\n justDelivered = false,\n canvas,\n anotherAgentSpaceKey,\n preview,\n testId,\n}: CanvasWidgetCardProps) => {\n const { openCanvas, canvas: openCanvasState } = useConversationWidgetContext();\n const canvasViable = useCanvasViable();\n const openedRef = useRef(false);\n const capture = useWidgetImageRender();\n const isEmailRender = useIsEmailWidgetRender();\n\n // Auto-open once per mount on a just-delivered message; the reducer applies the opening rule.\n useEffect(() => {\n if (isEmailRender || capture !== null || openedRef.current || !canvas || !justDelivered) return;\n openedRef.current = true;\n openCanvas({ ...canvas, origin: \"deliveredInMessage\", justDelivered: true });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [justDelivered, canvas?.instanceId]);\n\n const open = () => {\n if (canvas) openCanvas({ ...canvas, origin: \"cardClick\", justDelivered: false });\n };\n\n // The inline preview is suppressed while THIS card's canvas is open.\n const isThisCanvasOpen =\n canvas !== undefined && openCanvasState !== null && sameCanvasIdentity(openCanvasState, canvas);\n\n // The card: icon badge + title + subtitle + open affordance. Opens the canvas — as the side split on a wide\n // viewport, as the full-screen overlay on a narrow one.\n const subtitleText = subtitle ? (\n <Text\n role=\"caption\"\n color=\"var(--agents-fg-light)\"\n ellipsis\n translate={translateSubtitle}\n replacements={subtitleReplacements}\n >\n {subtitle}\n </Text>\n ) : null;\n\n // Every card shape: GlobalStateComponent is the card surface and draws the hover layer (it takes no pointer events);\n // the native button inside keeps the click and keyboard focus.\n const openCanvasTestId = testId ? `${testId}-open-canvas` : undefined;\n const cardTestId = anotherAgentSpaceKey === undefined ? testId : undefined;\n const renderCard = (cardContent: ReactNode, isRich = false, surfaceTestId?: string) => (\n <InteractiveSurface\n hoverable\n className={classNames(styles.cardSurface, isRich && styles.richCardSurface)}\n testId={surfaceTestId}\n >\n <button\n type=\"button\"\n className={classNames(styles.cardButton, isRich && styles.richCardButton)}\n onClick={open}\n data-testid={openCanvasTestId}\n >\n {cardContent}\n </button>\n </InteractiveSurface>\n );\n\n const openAffordance = (\n <span className={styles.openAffordance}>\n <Icon className={styles.openIcon} name=\"arrowRight\" />\n </span>\n );\n\n // The rich card: thumbnail + title + caption.\n const card = thumbnail\n ? renderCard(\n <>\n <span className={styles.thumbnail}>{thumbnail}</span>\n <div className={styles.body}>\n <Text\n role=\"body\"\n weight=\"bold\"\n ellipsis\n translate={translateTitle}\n replacements={titleReplacements}\n >\n {title}\n </Text>\n {subtitleText}\n </div>\n <Icon className={styles.richOpenIcon} name=\"arrowRight\" />\n </>,\n true,\n cardTestId,\n )\n : renderCard(\n <>\n <span className={styles.leadingIconBadge}>\n <Icon name={icon ?? DEFAULT_ICON} />\n </span>\n <div className={styles.body}>\n <Text\n role=\"help\"\n weight=\"bold\"\n ellipsis\n translate={translateTitle}\n replacements={titleReplacements}\n >\n {title}\n </Text>\n {subtitleText}\n </div>\n {openAffordance}\n </>,\n false,\n cardTestId,\n );\n\n if (isEmailRender || capture !== null) {\n if (!preview) throw new Error(\"WIDGET_REQUIRES_STATIC_PREVIEW\");\n return <>{preview}</>;\n }\n\n // Narrow viewport WITH an inline render: show the content (so the user sees the data without a side panel), plus a\n // card-styled \"Open in canvas\" affordance to open the full view over the chat. The inline content is suppressed while\n // this canvas is open, so a self-fetching widget never runs two instances against one shared Redux slice.\n if (!canvasViable && preview) {\n return (\n <div className={styles.mobile}>\n {isThisCanvasOpen ? null : preview}\n {renderCard(\n <>\n <span className={styles.leadingIconBadge}>\n <Icon name=\"maximize\" />\n </span>\n <div className={styles.body}>\n <Text role=\"help\" weight=\"bold\" ellipsis>\n Open in canvas\n </Text>\n </div>\n {openAffordance}\n </>,\n )}\n </div>\n );\n }\n\n // Wide viewport, and narrow with no inline render (the canvas is the only surface): the named card.\n if (anotherAgentSpaceKey === undefined) return card;\n return (\n <div className={styles.cardOfAnotherBusiness} data-testid={testId}>\n <ConversationWidgetAgentSpaceHeader agentSpaceKey={anotherAgentSpaceKey} inFlow />\n {card}\n </div>\n );\n};\n","import { type AgentsIconName } from \"../../provider/components\";\nimport { useWidgetImageRender } from \"../../image-render/WidgetImageRenderContext\";\nimport { useIsEmailWidgetRender } from \"../../renderer/ConversationWidgetRenderContext\";\nimport React, { ReactNode } from \"react\";\nimport { CanvasWidgetCard, CanvasWidgetCardCanvas } from \"./CanvasWidgetCard\";\n\nexport interface CanvasWidgetInlineRenderOptions {\n /**\n * True only when the inline render is the narrow-viewport preview inside the {@link CanvasWidgetCard}, above its\n * \"Open in canvas\" button, so the canvas holds the full content. False in the chat's inline branch and in email /\n * image renders, where no canvas exists and the inline render is the whole widget: never shorten it there.\n */\n isWidgetPreview: boolean;\n}\n\nexport interface CanvasWidgetSwitchProps {\n /**\n * Agent hint that forces the branch. Normally OMITTED — the switch auto-picks by content size.\n * `\"canvas\"` forces the canvas; `\"inline\"` keeps the content inline regardless of size.\n */\n display?: \"inline\" | \"canvas\";\n /**\n * The per-widget content rule: true when the content is larger than fits comfortably inline (more items / a longer\n * answer than the widget's inline limit). Combined with `display` to decide whether this is a canvas widget. Ignored\n * when `display` is set. Canvas-only widgets pass `display=\"canvas\"` instead of this.\n */\n exceedsInlineLimit?: boolean;\n /** Headline on the inline card (e.g. \"Search results for 'X'\"). Used only when it opens as a canvas. */\n title: string;\n /** `%token%` → value replacements for `title`, so an interpolated headline stays one stable translation key. */\n titleReplacements?: Record<string, string | number>;\n /** Optional second line on the card (e.g. \"5 sources\", a filter summary). Used only when it opens as a canvas. */\n subtitle?: string;\n /** `%token%` → value replacements for `subtitle`, so an interpolated second line stays one stable translation key. */\n subtitleReplacements?: Record<string, string | number>;\n /** False when `subtitle` is already resolved text (a business value, a singular/plural value). Default true. */\n translateSubtitle?: boolean;\n /** Optional leading icon on the card. Used only when it opens as a canvas. */\n icon?: AgentsIconName;\n /** True when the host message was delivered live right now — auto-opens the canvas once. Never true after a reload or on history replay. */\n justDelivered?: boolean;\n /** The canvas the card opens (see {@link CanvasWidgetCardProps.canvas}). */\n canvas?: CanvasWidgetCardCanvas;\n /**\n * The other agent space the content belongs to, when it is not the active one: the named card shows its chip (see\n * {@link CanvasWidgetCardProps.anotherAgentSpaceKey}). The inline render names it itself.\n */\n anotherAgentSpaceKey?: number;\n /**\n * The inline render of the widget. Shown directly in the chat when the content is small enough to stay inline, and\n * reused by the {@link CanvasWidgetCard} as the narrow-viewport inline render below its card. Called once per render.\n * A widget that shortens its content for the widget preview does so only when `isWidgetPreview` is true.\n */\n renderInline: (options: CanvasWidgetInlineRenderOptions) => ReactNode;\n /** The widget's root test id (`<kebab wire name>-widget`), handed to the {@link CanvasWidgetCard}. */\n testId?: string;\n}\n\n/**\n * The single switch shared by every canvas widget. It owns the one decision — is this a CANVAS widget at all: the\n * agent forced it (`display`) or the content exceeds the widget's inline limit. Small content renders inline in the\n * chat. A canvas widget hands off to {@link CanvasWidgetCard}, which itself decides the viewport-dependent shape: on a\n * wide viewport a clickable card (opens the side split), on a narrow viewport the inline render plus an \"Open in\n * canvas\" CTA (opens over the chat). Centralising this here keeps all widgets consistent and free of the branch.\n */\nexport const CanvasWidgetSwitch = ({\n display,\n exceedsInlineLimit = false,\n title,\n titleReplacements,\n subtitle,\n subtitleReplacements,\n translateSubtitle,\n icon,\n justDelivered = false,\n canvas,\n anotherAgentSpaceKey,\n renderInline,\n testId,\n}: CanvasWidgetSwitchProps) => {\n const capture = useWidgetImageRender();\n const isEmailRender = useIsEmailWidgetRender();\n if (isEmailRender || capture !== null) return <>{renderInline({ isWidgetPreview: false })}</>;\n\n const isCanvasWidget = display === \"canvas\" || (display !== \"inline\" && exceedsInlineLimit);\n\n if (!isCanvasWidget) return <>{renderInline({ isWidgetPreview: false })}</>;\n\n return (\n <CanvasWidgetCard\n title={title}\n titleReplacements={titleReplacements}\n subtitle={subtitle}\n subtitleReplacements={subtitleReplacements}\n translateSubtitle={translateSubtitle}\n icon={icon}\n justDelivered={justDelivered}\n canvas={canvas}\n anotherAgentSpaceKey={anotherAgentSpaceKey}\n preview={renderInline({ isWidgetPreview: true })}\n testId={testId}\n />\n );\n};\n","import type { CanvasId } from \"../../renderer/canvas/canvas-behaviours\";\nimport {\n canvasInstanceIdForMessagePayload,\n messageAnchor,\n} from \"../../renderer/canvas/canvas-state\";\nimport type { CanvasWidgetCardCanvas } from \"./CanvasWidgetCard\";\n\n/**\n * The canvas a payload widget in a message opens: anchored on the host message, one instance per message + payload.\n * Undefined while the widget does not know its message (the reply is still streaming, a composer echo, a story that\n * mounts the widget without a message) — the card then renders but opens nothing.\n */\nexport const canvasForMessageWidget = (\n canvasId: CanvasId,\n messageId: string | number | undefined,\n payload: string,\n): CanvasWidgetCardCanvas | undefined => {\n const numericMessageId = messageId === undefined ? Number.NaN : Number(messageId);\n if (!Number.isFinite(numericMessageId)) return undefined;\n return {\n canvasId,\n instanceId: canvasInstanceIdForMessagePayload(canvasId, numericMessageId, payload),\n anchor: messageAnchor(numericMessageId),\n };\n};\n","type OpenAiTextPart = {\n type?: string;\n text?: string;\n};\n\ntype OpenAiTextPayload = {\n content?: OpenAiTextPart[] | string;\n text?: string;\n};\n\nconst parseJsonString = (value: string): unknown => {\n try {\n return JSON.parse(value);\n } catch {\n return undefined;\n }\n};\n\nconst readTextFromParsedPayload = (parsed: unknown): string | undefined => {\n if (typeof parsed === \"string\") {\n return parsed;\n }\n if (typeof parsed !== \"object\" || parsed === null) {\n return undefined;\n }\n const payload = parsed as OpenAiTextPayload;\n if (typeof payload.text === \"string\") {\n return payload.text;\n }\n if (typeof payload.content === \"string\") {\n return payload.content;\n }\n if (Array.isArray(payload.content)) {\n const textParts = payload.content\n .map((part) => (typeof part.text === \"string\" ? part.text : \"\"))\n .filter((text) => text.trim().length > 0);\n return textParts.length > 0 ? textParts.join(\"\\n\\n\") : undefined;\n }\n return undefined;\n};\n\nconst unescapeJsonString = (value: string): string => {\n const parsed = parseJsonString(`\"${value}\"`);\n return typeof parsed === \"string\" ? parsed : value;\n};\n\nconst readTextFromJsonExcerpt = (excerpt: string): string | undefined => {\n const matches = Array.from(excerpt.matchAll(/\"text\"\\s*:\\s*\"((?:\\\\.|[^\"\\\\])*)\"/g));\n if (matches.length === 0) {\n return undefined;\n }\n return matches\n .map((match) => unescapeJsonString(match[1] ?? \"\"))\n .filter((text) => text.trim().length > 0)\n .join(\"\\n\\n\");\n};\n\nexport const normalizeSearchHitExcerpt = (rawExcerpt: unknown): string => {\n if (typeof rawExcerpt !== \"string\") {\n const parsedText = readTextFromParsedPayload(rawExcerpt);\n return parsedText ?? \"\";\n }\n const trimmedExcerpt = rawExcerpt.trim();\n const parsedText = readTextFromParsedPayload(parseJsonString(trimmedExcerpt));\n if (parsedText !== undefined) {\n return parsedText;\n }\n return readTextFromJsonExcerpt(trimmedExcerpt) ?? rawExcerpt;\n};\n","/**\n * Whitelist helpers for LLM-emitted widget payload values. Filter values\n * flow into backend filter strings (`status eq '<value>'`, `directories in\n * ['<value>']`) and Redux filter slices, so nothing may pass through without\n * either matching a known literal or a safe-charset alias check — a stray\n * quote in a value would otherwise break or co-opt the filter expression.\n */\n\nconst SAFE_ALIAS = /^[a-z0-9_-]+$/i;\n\n/** Keep only values present in `allowed`; undefined when nothing survives. */\nexport const pickAllowed = <T extends string>(values: unknown, allowed: ReadonlyArray<T>): T[] | undefined => {\n if (!Array.isArray(values)) return undefined;\n const filtered = values.filter(\n (v): v is T => typeof v === \"string\" && (allowed as ReadonlyArray<string>).includes(v),\n );\n return filtered.length ? filtered : undefined;\n};\n\n/** Single-value variant of `pickAllowed`. */\nexport const pickAllowedValue = <T extends string>(value: unknown, allowed: ReadonlyArray<T>): T | undefined =>\n typeof value === \"string\" && (allowed as ReadonlyArray<string>).includes(value) ? (value as T) : undefined;\n\n/**\n * Keep only strings matching the safe alias charset (letters, digits, `_`, `-`).\n * For open-ended vocabularies (e.g. aliases of data sources an app adds at runtime) where a fixed\n * whitelist is impossible but quotes/spaces must never pass.\n */\nexport const pickSafeAliases = (values: unknown): string[] | undefined => {\n if (!Array.isArray(values)) return undefined;\n const filtered = values.filter((v): v is string => typeof v === \"string\" && SAFE_ALIAS.test(v));\n return filtered.length ? filtered : undefined;\n};\n\n/** Single-value variant of `pickSafeAliases` (e.g. a source alias or an id token of the app's own form). */\nexport const pickSafeAlias = (value: unknown): string | undefined =>\n typeof value === \"string\" && SAFE_ALIAS.test(value) ? value : undefined;\n\n/**\n * An opaque id token a widget uses ONLY as a URL path segment of a read endpoint (`/api/example/{sourceAlias}/{id}`)\n * — never injected into an OData filter string. Ids of external sources are often base64 (`+`, `/`, `=`), so the\n * `SAFE_ALIAS` charset is too strict and would silently drop them (the widget then falls back to a filtered read).\n * Allows the base64 charset; still rejects quotes, spaces and anything else that could break the path.\n */\nconst OPAQUE_PATH_SEGMENT_ID_TOKEN = /^[A-Za-z0-9_\\-+/=]+$/;\nexport const pickReviewExternalId = (value: unknown): string | undefined =>\n typeof value === \"string\" && value.length > 0 && OPAQUE_PATH_SEGMENT_ID_TOKEN.test(value) ? value : undefined;\n\n/** Keep a free-text string, capped at `maxLength` — e.g. a model-drafted reply pre-filled into an input. */\nexport const pickText = (value: unknown, maxLength = 2000): string | undefined =>\n typeof value === \"string\" && value.length > 0 ? value.slice(0, maxLength) : undefined;\n","import { normalizeSearchHitExcerpt } from \"./search-hit-excerpt\";\nimport { pickText } from \"../../_shared/widget-payload-validation\";\n\n/**\n * One matched message inside a conversation group — the fields the search results list renders\n * (`ConversationSearchResultsList`, a replaceable component).\n */\nexport interface ConversationSearchResultHit {\n role?: string;\n excerpt?: string;\n indexInConversation?: number;\n messageId?: number;\n created?: string;\n updated?: string;\n dateTime?: string;\n}\n\n/** One conversation's worth of matches. */\nexport interface ConversationSearchResultGroup {\n conversationId?: number;\n title?: string;\n summary?: string;\n created?: string;\n updated?: string;\n dateTime?: string;\n hits: ConversationSearchResultHit[];\n}\n\n/**\n * Payload carried by `::ConversationSearchResults{payload='...'}` — the result of `searchConversations`.\n *\n * DATA-COMPLETE: the widget renders ENTIRELY from this payload — it never re-runs the search or fetches anything\n * (unlike a self-hydrating widget that reads its rows by id). The agent copies the `query` + the grouped `groups` from\n * the `searchConversations` tool result straight into here.\n *\n * `display` lets the agent force inline vs canvas; omitted → the widget auto-picks (few groups inline, many in the\n * canvas side panel).\n */\nexport interface ConversationSearchResultsPayload {\n query: string;\n /** The LLM-written headline for the canvas card (e.g. \"Past chats about Facebook\"); falls back to the query. */\n title?: string;\n display?: \"inline\" | \"canvas\";\n /** The matched conversations, as the search results list takes them. */\n groups: ConversationSearchResultGroup[];\n}\n\nconst MAX_GROUPS = 20;\nconst MAX_HITS_PER_GROUP = 6;\nconst EXCERPT_MAX = 600;\n\nconst toFiniteInt = (value: unknown): number | undefined =>\n typeof value === \"number\" && Number.isFinite(value) ? Math.trunc(value) : undefined;\n\n/** First defined value among the given keys — tolerates the field-name variants weaker models emit when they\n * reconstruct the payload from the markdown result instead of copying the structured `groups` (e.g. `conversation_id`\n * for `conversationId`, `messages` for `hits`, `content` for `excerpt`). Defensive parsing of LLM output, not a guard. */\nconst pick = (candidate: Record<string, unknown>, ...keys: string[]): unknown => {\n for (const key of keys) {\n if (candidate[key] !== undefined && candidate[key] !== null) return candidate[key];\n }\n return undefined;\n};\n\nconst parseHit = (raw: unknown): ConversationSearchResultHit | null => {\n if (typeof raw !== \"object\" || raw === null) return null;\n const candidate = raw as Record<string, unknown>;\n const excerpt = pickText(\n normalizeSearchHitExcerpt(pick(candidate, \"excerpt\", \"content\", \"text\", \"message\")),\n EXCERPT_MAX,\n );\n if (!excerpt) return null; // a hit with no text is nothing to show\n return {\n role: pickText(pick(candidate, \"role\"), 32),\n excerpt,\n indexInConversation: toFiniteInt(pick(candidate, \"indexInConversation\", \"index\")),\n messageId: toFiniteInt(pick(candidate, \"messageId\", \"id\")),\n // The message's \"when\" is its created time; `dateTime`/`date` kept as back-compat aliases, `updated` as a last resort.\n created: pickText(pick(candidate, \"created\", \"dateTime\", \"date\", \"updated\"), 32),\n updated: pickText(pick(candidate, \"updated\"), 32),\n dateTime: pickText(pick(candidate, \"dateTime\", \"date\", \"created\", \"updated\"), 32),\n };\n};\n\nconst parseGroup = (raw: unknown): ConversationSearchResultGroup | null => {\n if (typeof raw !== \"object\" || raw === null) return null;\n const candidate = raw as Record<string, unknown>;\n const rawHits = pick(candidate, \"hits\", \"messages\");\n const hits = Array.isArray(rawHits)\n ? rawHits\n .map(parseHit)\n .filter((hit): hit is ConversationSearchResultHit => hit !== null)\n .slice(0, MAX_HITS_PER_GROUP)\n : [];\n if (hits.length === 0) return null; // a group with no shown hits is dropped\n return {\n conversationId: toFiniteInt(pick(candidate, \"conversationId\", \"conversation_id\")),\n title: pickText(pick(candidate, \"title\"), 200),\n summary: pickText(pick(candidate, \"summary\"), 600),\n // The group's display date is the conversation's most-recent activity (`updated`), falling back to its created time;\n // `dateTime`/`date` kept as back-compat aliases for older copied payloads.\n created: pickText(pick(candidate, \"created\", \"dateTime\", \"date\"), 32),\n updated: pickText(pick(candidate, \"updated\"), 32),\n dateTime: pickText(pick(candidate, \"dateTime\", \"date\", \"updated\", \"created\"), 32),\n hits,\n };\n};\n\nexport const parseConversationSearchResultsPayload = (\n payload: string | undefined,\n): ConversationSearchResultsPayload => {\n if (!payload) return { query: \"\", groups: [] };\n try {\n const parsed = JSON.parse(payload) as unknown;\n if (typeof parsed !== \"object\" || parsed === null) return { query: \"\", groups: [] };\n const candidate = parsed as Record<string, unknown>;\n const groups = Array.isArray(candidate.groups)\n ? candidate.groups\n .map(parseGroup)\n .filter((group): group is ConversationSearchResultGroup => group !== null)\n .slice(0, MAX_GROUPS)\n : [];\n const display = candidate.display === \"inline\" || candidate.display === \"canvas\" ? candidate.display : undefined;\n return {\n query: pickText(candidate.query, 200) ?? \"\",\n title: pickText(candidate.title, 120),\n display,\n groups,\n };\n } catch {\n console.warn(\"[ConversationSearchResultsConversationWidget] Failed to parse payload JSON\", payload);\n return { query: \"\", groups: [] };\n }\n};\n","import { ConversationSearchResultsList, Text } from \"../../provider/components\";\nimport { escapePlainTextForText } from \"../../provider/environment\";\nimport React, { useMemo } from \"react\";\nimport { PayloadConversationWidgetProps } from \"../../renderer/conversation-widget-props\";\nimport { useConversationWidgetContext } from \"../../renderer/ConversationWidgetCallbacksContext\";\nimport { CanvasWidgetSwitch } from \"../CanvasWidgetCard/CanvasWidgetSwitch\";\nimport { canvasForMessageWidget } from \"../CanvasWidgetCard/canvas-for-message-widget\";\nimport { parseConversationSearchResultsPayload } from \"./shared/conversation-search-results-widget-payload\";\nimport { useReportWidgetRenderStatus } from \"../../renderer/render-report/widget-render-report\";\nimport { WidgetSurface } from \"../_shared/modern\";\nimport styles from \"./ConversationSearchResultsConversationWidget.module.scss\";\n\ntype ConversationSearchResultsConversationWidgetProps = PayloadConversationWidgetProps;\n\n/** ≤ this many matching conversations render inline in the chat (1-5 short results); more open in the canvas side panel. */\nconst INLINE_GROUP_LIMIT = 5;\n\n/**\n * Renders the result of `searchConversations` (cross-chat semantic recall) — the grouped \"search all my chats\" view\n * (the replaceable `ConversationSearchResultsList`; the app supplies the component its chat's own search panel uses). DATA-COMPLETE: it\n * renders entirely from the payload the agent passes (query + grouped hits); it NEVER re-runs the search.\n *\n * Few groups → inline in the message; many → opens in the canvas side panel (or whatever `display` forces). The\n * open-conversation arrow jumps to the source chat via the widget context's `onOpenConversation` seam.\n *\n * The canvas is `conversationSearchResults`: the body (`ConversationSearchResultsCanvasBody`) re-reads this payload\n * from the anchor message. Without a message id (a composer echo, a streaming reply) the card opens nothing.\n */\nexport const ConversationSearchResultsConversationWidget = (\n props: ConversationSearchResultsConversationWidgetProps,\n) => {\n const { payload, justDelivered = false, messageId } = props;\n const testId = \"conversation-search-results-widget\";\n const { onOpenConversation } = useConversationWidgetContext();\n const canvas = canvasForMessageWidget(\"conversationSearchResults\", messageId, payload);\n const { query, title, display, groups } = useMemo(() => parseConversationSearchResultsPayload(payload), [payload]);\n\n const openConversation = (conversationId: number, messageId?: number) =>\n onOpenConversation?.(conversationId, messageId);\n\n const isEmpty = groups.length === 0;\n useReportWidgetRenderStatus(\n isEmpty ? \"empty\" : \"mounted\",\n isEmpty ? \"NO_DATA\" : undefined,\n isEmpty ? \"The ConversationSearchResults widget carries no conversation with a readable hit.\" : undefined,\n );\n\n if (isEmpty) return null;\n\n const customTitle = title?.trim();\n const headline = customTitle || 'Search results for \"%query%\"';\n // The query is model-written: the component library's Text parses a string as HTML, so it goes in escaped.\n const headlineReplacements = customTitle ? undefined : { query: escapePlainTextForText(query) };\n\n return (\n <CanvasWidgetSwitch\n display={display}\n exceedsInlineLimit={groups.length > INLINE_GROUP_LIMIT}\n title={headline}\n titleReplacements={headlineReplacements}\n subtitle={\"%count% conversations matched\"}\n subtitleReplacements={{ count: groups.length }}\n icon=\"message\"\n justDelivered={justDelivered}\n canvas={canvas}\n testId={testId}\n renderInline={() => (\n // The chat's inline results sit on one surface with their headline and match count (the canvas body keeps\n // the bare list — the canvas pane is the surface there).\n <WidgetSurface className={styles.inlineResults} testId={testId}>\n <div className={styles.header}>\n <Text\n role=\"intro\"\n weight=\"bold\"\n translate={!customTitle}\n replacements={headlineReplacements}\n testId={`${testId}-title`}\n >\n {customTitle ? escapePlainTextForText(customTitle) : headline}\n </Text>\n <Text\n role=\"caption\"\n color=\"var(--agents-fg-light)\"\n replacements={{ count: groups.length }}\n testId={`${testId}-count`}\n >\n {\"%count% conversations matched\"}\n </Text>\n </div>\n <div data-testid={`${testId}-results`}>\n <ConversationSearchResultsList groups={groups} query={query} onOpenConversation={openConversation} />\n </div>\n </WidgetSurface>\n )}\n />\n );\n};\n","import { pickText } from \"../../_shared/widget-payload-validation\";\n\n/** One cited web source — the fields the widget renders (a numbered link with an optional title). */\nexport interface WebSearchResultSource {\n url: string;\n title?: string;\n}\n\n/**\n * Payload carried by `::WebSearchResults{payload='...'}` — the references of a web research answer.\n *\n * DATA-COMPLETE: the widget renders ENTIRELY from this payload — it never re-runs the search or fetches anything.\n * The agent writes its answer as prose and the payload carries only the `sources` it used (url + title,\n * copied from the tool results) plus the `query`. `answer` is the legacy field of messages stored before: when present\n * the widget renders the full answer card.\n *\n * `display` lets the agent force inline vs canvas; omitted → the widget auto-picks (a short answer with few sources\n * renders inline in the chat, a long answer or many sources opens in the canvas side panel).\n */\nexport interface WebSearchResultsPayload {\n /** The query that was searched (shown as the headline / canvas card title fallback). */\n query: string;\n /** The LLM-written headline for the canvas card (user's language, e.g. \"Opening-hours rules in 2026\"); falls back to the query. */\n title?: string;\n /** The provider that produced the answer (PERPLEXITY | OPENAI | GEMINI) — shown as a small attribution. */\n provider?: string;\n display?: \"inline\" | \"canvas\";\n /** Legacy: the answer as markdown; empty in the references form. */\n answer: string;\n /** The cited sources (url + optional title), in citation order. */\n sources: WebSearchResultSource[];\n}\n\nconst MAX_SOURCES = 30;\nconst ANSWER_MAX = 12000;\n\n/**\n * First defined value among the given keys — tolerates the field-name variants a weaker model emits when it\n * reconstructs the payload from the markdown result instead of copying the structured fields (e.g. `link` for `url`,\n * `name` for `title`, `text`/`content` for `answer`). Defensive parsing of LLM output, not a guard.\n */\nconst pick = (candidate: Record<string, unknown>, ...keys: string[]): unknown => {\n for (const key of keys) {\n if (candidate[key] !== undefined && candidate[key] !== null) return candidate[key];\n }\n return undefined;\n};\n\n/** A source's url may arrive directly on the object or nested under a `url_citation` (the raw provider annotation shape). */\nconst parseSource = (raw: unknown): WebSearchResultSource | null => {\n if (typeof raw !== \"object\" || raw === null) return null;\n const candidate = raw as Record<string, unknown>;\n const nested = pick(candidate, \"url_citation\");\n const fields = typeof nested === \"object\" && nested !== null ? (nested as Record<string, unknown>) : candidate;\n const url = pickText(pick(fields, \"url\", \"link\", \"uri\"), 2000);\n if (!url) return null; // a source with no url is nothing to link\n return {\n url,\n title: pickText(pick(fields, \"title\", \"name\"), 300),\n };\n};\n\n/**\n * The `sources` may arrive flat (`[{url,title}]`) or wrapped in the serialized EntitySet shape (`{elements:[...]}`)\n * the structured tool result carries — accept both.\n */\nconst extractRawSources = (candidate: Record<string, unknown>): unknown[] => {\n const sources = pick(candidate, \"sources\");\n if (Array.isArray(sources)) return sources;\n if (typeof sources === \"object\" && sources !== null) {\n const elements = (sources as Record<string, unknown>).elements;\n if (Array.isArray(elements)) return elements;\n }\n return [];\n};\n\nexport const parseWebSearchResultsPayload = (payload: string | undefined): WebSearchResultsPayload => {\n if (!payload) return { query: \"\", answer: \"\", sources: [] };\n try {\n const parsed = JSON.parse(payload) as unknown;\n if (typeof parsed !== \"object\" || parsed === null) return { query: \"\", answer: \"\", sources: [] };\n const candidate = parsed as Record<string, unknown>;\n const sources = extractRawSources(candidate)\n .map(parseSource)\n .filter((source): source is WebSearchResultSource => source !== null)\n .slice(0, MAX_SOURCES);\n const display = candidate.display === \"inline\" || candidate.display === \"canvas\" ? candidate.display : undefined;\n return {\n query: pickText(pick(candidate, \"query\"), 300) ?? \"\",\n title: pickText(pick(candidate, \"title\"), 160),\n provider: pickText(pick(candidate, \"provider\"), 40),\n display,\n answer: pickText(pick(candidate, \"answer\", \"text\", \"content\"), ANSWER_MAX) ?? \"\",\n sources,\n };\n } catch {\n console.warn(\"[WebSearchResultsConversationWidget] Failed to parse payload JSON\", payload);\n return { query: \"\", answer: \"\", sources: [] };\n }\n};\n","import React from \"react\";\nimport { Markdown } from \"../../provider/components\";\n\ntype WebSearchAnswerProps = {\n answer: string;\n};\n\n/** The answer body — rendered as markdown so headings, lists and inline links from the provider show properly. */\nexport const WebSearchAnswer = (props: WebSearchAnswerProps) => {\n const { answer } = props;\n if (answer.trim() === \"\") return null;\n return <Markdown markdown={answer} usesTextComponent />;\n};\n","import { Icon } from \"../../provider/components\";\nimport React, { useState } from \"react\";\n\nconst sourceIconStyle: React.CSSProperties = { fontSize: 14, flexShrink: 0 };\nconst faviconStyle: React.CSSProperties = { width: 16, height: 16, flexShrink: 0, borderRadius: 3 };\n\n/** Best-effort hostname for an untitled source, so the link still reads as a place rather than a raw URL. */\nexport const hostnameOf = (url: string): string => {\n try {\n return new URL(url).hostname.replace(/^www\\./, \"\");\n } catch {\n return url;\n }\n};\n\n/**\n * The site's favicon (the small per-site icon WhatsApp/Slack show on a link), resolved from the Google favicon service\n * by domain. Falls back to the generic link glyph if the icon fails to load (no favicon, offline) — never a broken\n * image.\n */\nexport const SourceFavicon = ({ hostname }: { hostname: string }) => {\n const [failed, setFailed] = useState(false);\n if (failed || !hostname) {\n return (\n <Icon color=\"var(--agents-fg-light)\" style={sourceIconStyle} name=\"link\" />\n );\n }\n return (\n <img\n src={`https://www.google.com/s2/favicons?domain=${encodeURIComponent(hostname)}&sz=32`}\n alt=\"\"\n loading=\"lazy\"\n style={faviconStyle}\n onError={() => setFailed(true)}\n />\n );\n};\n","/**\n * The hostname as a reader writes it: an internationalised domain arrives from `URL.hostname` in its ASCII form\n * (`xn--bckerhandwerk-bfb.de`), which reads as noise on a source chip — each `xn--` label is decoded back to Unicode\n * (`bäckerhandwerk.de`) with the Punycode algorithm of RFC 3492. A label that does not decode stays as it was. The\n * favicon lookup keeps the ASCII form; this is for display only.\n */\n\nconst BASE = 36;\nconst T_MIN = 1;\nconst T_MAX = 26;\nconst SKEW = 38;\nconst DAMP = 700;\nconst INITIAL_BIAS = 72;\nconst INITIAL_N = 128;\nconst MAX_CODE_POINT = 0x10ffff;\n\nconst adaptBias = (delta: number, numPoints: number, isFirstTime: boolean): number => {\n let scaledDelta = isFirstTime ? Math.floor(delta / DAMP) : delta >> 1;\n scaledDelta += Math.floor(scaledDelta / numPoints);\n let k = 0;\n while (scaledDelta > ((BASE - T_MIN) * T_MAX) >> 1) {\n scaledDelta = Math.floor(scaledDelta / (BASE - T_MIN));\n k += BASE;\n }\n return k + Math.floor(((BASE - T_MIN + 1) * scaledDelta) / (scaledDelta + SKEW));\n};\n\nconst digitOf = (codeUnit: number): number => {\n if (codeUnit >= 0x30 && codeUnit <= 0x39) return codeUnit - 22; // 0-9 → 26-35\n if (codeUnit >= 0x41 && codeUnit <= 0x5a) return codeUnit - 0x41; // A-Z → 0-25\n if (codeUnit >= 0x61 && codeUnit <= 0x7a) return codeUnit - 0x61; // a-z → 0-25\n return BASE;\n};\n\n/** Decodes the part of a label after `xn--`; undefined when it is not valid Punycode. */\nexport const decodePunycodeLabel = (encodedLabel: string): string | undefined => {\n const delimiterIndex = encodedLabel.lastIndexOf(\"-\");\n const basicPart = delimiterIndex > 0 ? encodedLabel.slice(0, delimiterIndex) : \"\";\n if ([...basicPart].some((character) => character.charCodeAt(0) >= 0x80)) return undefined;\n const codePoints = [...basicPart].map((character) => character.charCodeAt(0));\n let n = INITIAL_N;\n let bias = INITIAL_BIAS;\n let i = 0;\n let position = delimiterIndex > 0 ? delimiterIndex + 1 : 0;\n while (position < encodedLabel.length) {\n const previousI = i;\n let weight = 1;\n for (let k = BASE; ; k += BASE) {\n if (position >= encodedLabel.length) return undefined;\n const digit = digitOf(encodedLabel.charCodeAt(position++));\n if (digit >= BASE) return undefined;\n i += digit * weight;\n if (i > Number.MAX_SAFE_INTEGER) return undefined;\n const threshold = k <= bias ? T_MIN : k >= bias + T_MAX ? T_MAX : k - bias;\n if (digit < threshold) break;\n weight *= BASE - threshold;\n }\n bias = adaptBias(i - previousI, codePoints.length + 1, previousI === 0);\n n += Math.floor(i / (codePoints.length + 1));\n if (n > MAX_CODE_POINT) return undefined;\n i %= codePoints.length + 1;\n codePoints.splice(i, 0, n);\n i++;\n }\n return String.fromCodePoint(...codePoints);\n};\n\nexport const toDisplayHostname = (hostname: string): string =>\n hostname\n .split(\".\")\n .map((label) => {\n if (!label.toLowerCase().startsWith(\"xn--\")) return label;\n const decodedLabel = decodePunycodeLabel(label.slice(4));\n return decodedLabel ? decodedLabel : label;\n })\n .join(\".\");\n","import { Text } from \"../../provider/components\";\nimport React from \"react\";\nimport { hostnameOf, SourceFavicon } from \"./SourceFavicon\";\nimport { toDisplayHostname } from \"./shared/display-hostname\";\nimport { WebSearchResultSource } from \"./shared/web-search-results-widget-payload\";\n\ntype WebSearchSourcesListProps = {\n sources: WebSearchResultSource[];\n provider?: string;\n testId?: string;\n};\n\nconst sourcesStyle: React.CSSProperties = { marginTop: 12, display: \"flex\", flexDirection: \"column\", gap: 4 };\nconst sourcesListStyle: React.CSSProperties = {\n listStyle: \"decimal\",\n margin: 0,\n paddingLeft: 20,\n display: \"flex\",\n flexDirection: \"column\",\n gap: 3,\n};\nconst sourceItemStyle: React.CSSProperties = { display: \"flex\", alignItems: \"center\", gap: 6 };\nconst sourceLinkStyle: React.CSSProperties = {\n color: \"var(--agents-primary-500)\",\n textDecoration: \"none\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n};\n\n/** The cited sources — a numbered list of links, each opening in a new tab with the site's favicon; falls back to the\n * hostname when untitled. */\nexport const WebSearchSourcesList = (props: WebSearchSourcesListProps) => {\n const { sources, provider, testId = \"web-search-results-widget\" } = props;\n if (sources.length === 0) return null;\n return (\n <div style={sourcesStyle}>\n <Text role=\"caption\" color=\"var(--agents-fg-light)\">\n Sources{provider ? ` · ${provider.toLowerCase()}` : \"\"}\n </Text>\n <ol style={sourcesListStyle} data-testid={`${testId}-sources`}>\n {sources.map((source, index) => {\n const hostname = hostnameOf(source.url);\n return (\n <li key={`${index}-${source.url}`} style={sourceItemStyle}>\n <SourceFavicon hostname={hostname} />\n <a\n href={source.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={sourceLinkStyle}\n data-testid={`${testId}-source-${index}`}\n >\n {source.title?.trim() || toDisplayHostname(hostname)}\n </a>\n </li>\n );\n })}\n </ol>\n </div>\n );\n};\n","import { Text } from \"../../provider/components\";\nimport { WebSearchResultSource } from \"./shared/web-search-results-widget-payload\";\nimport { hostnameOf, SourceFavicon } from \"./SourceFavicon\";\nimport { toDisplayHostname } from \"./shared/display-hostname\";\nimport { ModelText } from \"../../kit/ModelText/ModelText\";\nimport styles from \"./WebSearchReferences.module.scss\";\n\nexport interface WebSearchReferencesProps {\n sources: WebSearchResultSource[];\n testId?: string;\n}\n\n/**\n * The references of a web research answer the agent wrote itself: one link chip per page it used — the\n * site's favicon and its name (the page title instead when several pages of one site are listed, so no two chips read\n * the same), the page title on hover — placed by the agent under its own prose answer. Each opens the\n * page in a new tab. A chip wears the agent tray pill surface (Scheduled / Done) so the sources belong to the board.\n */\nexport const WebSearchReferences = (props: WebSearchReferencesProps) => {\n const { sources, testId = \"web-search-results-widget\" } = props;\n if (sources.length === 0) return null;\n const hostnames = sources.map((source) => hostnameOf(source.url));\n return (\n <div className={styles.references} data-testid={testId}>\n <Text role=\"caption\" color=\"var(--agents-fg-light)\">\n {\"Sources\"}\n </Text>\n <div role=\"list\" className={styles.chips} data-testid={`${testId}-sources`}>\n {sources.map((source, index) => {\n const hostname = hostnames[index];\n const displayHostname = toDisplayHostname(hostname);\n const pageTitle = source.title?.trim() || displayHostname;\n const isRepeatedSite = hostnames.filter((otherHostname) => otherHostname === hostname).length > 1;\n return (\n <div role=\"listitem\" key={`${index}-${source.url}`} className={styles.chipItem}>\n <a\n className={styles.chip}\n href={source.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n title={pageTitle}\n aria-label={pageTitle}\n data-testid={`${testId}-source-${index}`}\n >\n <SourceFavicon hostname={hostname} />\n {isRepeatedSite && source.title?.trim() ? (\n <ModelText role=\"caption\" weight=\"bold\" className={styles.chipLabel}>\n {source.title.trim()}\n </ModelText>\n ) : (\n <Text\n role=\"caption\"\n weight=\"bold\"\n translate={false}\n className={styles.chipLabel}\n >\n {displayHostname}\n </Text>\n )}\n </a>\n </div>\n );\n })}\n </div>\n </div>\n );\n};\n","import React, { useMemo } from \"react\";\nimport { PayloadConversationWidgetProps } from \"../../renderer/conversation-widget-props\";\nimport { CanvasWidgetSwitch } from \"../CanvasWidgetCard/CanvasWidgetSwitch\";\nimport { canvasForMessageWidget } from \"../CanvasWidgetCard/canvas-for-message-widget\";\nimport { parseWebSearchResultsPayload } from \"./shared/web-search-results-widget-payload\";\nimport { WebSearchAnswer } from \"./WebSearchAnswer\";\nimport { WebSearchSourcesList } from \"./WebSearchSourcesList\";\nimport { WebSearchReferences } from \"./WebSearchReferences\";\nimport { useReportWidgetRenderStatus } from \"../../renderer/render-report/widget-render-report\";\n\ntype WebSearchResultsConversationWidgetProps = PayloadConversationWidgetProps;\n\nconst inlineStyle: React.CSSProperties = { display: \"flex\", flexDirection: \"column\", gap: 8 };\n\n/**\n * The references of a web research answer: the agent writes its answer as prose and puts this widget under it with the\n * pages it used (`sources` only) — rendered as link chips with each site's favicon ({@link WebSearchReferences}).\n * DATA-COMPLETE: it renders entirely from the payload; it NEVER re-runs the search.\n *\n * Legacy form (older stored messages): a payload with an `answer` renders the full answer card below.\n *\n * Renders INLINE in the message (answer markdown + the cited sources, each with its site favicon). It only opens in the\n * canvas side panel if the agent explicitly sets `display: \"canvas\"` — by default a web answer stays inline.\n */\nexport const WebSearchResultsConversationWidget = (props: WebSearchResultsConversationWidgetProps) => {\n const { payload, justDelivered = false, messageId } = props;\n const testId = \"web-search-results-widget\";\n // The canvas is `webSearchResults`: the body re-reads this payload from the anchor message.\n const canvas = canvasForMessageWidget(\"webSearchResults\", messageId, payload);\n const { query, title, provider, display, answer, sources } = useMemo(\n () => parseWebSearchResultsPayload(payload),\n [payload],\n );\n\n const isEmpty = answer.trim() === \"\" && sources.length === 0;\n useReportWidgetRenderStatus(\n isEmpty ? \"empty\" : \"mounted\",\n isEmpty ? \"NO_DATA\" : undefined,\n isEmpty ? \"The WebSearchResults widget carries no answer and no source with a url.\" : undefined,\n );\n\n if (isEmpty) return null;\n\n // The references form: the agent wrote its answer as prose ABOVE the widget; the widget carries only the\n // pages it used. A stored message with an `answer` keeps the full answer card below.\n if (answer.trim() === \"\") return <WebSearchReferences sources={sources} testId={testId} />;\n\n // The source count and the optional provider are interpolated via `%token%` so each stays a single translatable\n // key (never a per-value string). The plural split keeps two clean keys; the provider variant folds the provider in\n // with a comma (no decorative separator in the key).\n const single = sources.length === 1;\n const lowercasedProvider = provider?.toLowerCase();\n const subtitle = lowercasedProvider\n ? single\n ? \"1 source, %provider%\"\n : \"%count% sources, %provider%\"\n : single\n ? \"1 source\"\n : \"%count% sources\";\n const subtitleReplacements = {\n count: sources.length,\n ...(lowercasedProvider ? { provider: lowercasedProvider } : {}),\n };\n\n const customTitle = title?.trim() || query;\n\n return (\n <CanvasWidgetSwitch\n display={display}\n exceedsInlineLimit={false}\n title={customTitle || \"Web search\"}\n subtitle={subtitle}\n subtitleReplacements={subtitleReplacements}\n icon=\"search\"\n justDelivered={justDelivered}\n canvas={canvas}\n testId={testId}\n renderInline={() => (\n <div style={inlineStyle} data-testid={testId}>\n <WebSearchAnswer answer={answer} />\n <WebSearchSourcesList sources={sources} provider={provider} testId={testId} />\n </div>\n )}\n />\n );\n};\n"],"names":["anchor","options","compact","testId","styles","label","runtime","content","MAX_TITLE_LENGTH","isRecord","readCappedString","readFirstString","timeZone","title","readBrowserLanguage","isDaytime","digitalTime","registry","text","amount","body","field","option","input","name","wide","row","result","thumbnail","openAffordance","card","parsedText","pick","messageId"],"mappings":"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"}
|