@mgamadeus/ddd-agents 0.0.1-stage → 0.1.0-alpha.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -3
- package/dist/chat.js +5263 -0
- package/dist/chat.js.map +1 -0
- package/dist/chunks/AgentsConversationClientContext-C4T7g_Qk.js +22 -0
- package/dist/chunks/AgentsConversationClientContext-C4T7g_Qk.js.map +1 -0
- package/dist/chunks/ConversationMarkdown-W7NHglmL.js +399 -0
- package/dist/chunks/ConversationMarkdown-W7NHglmL.js.map +1 -0
- package/dist/chunks/WebSearchResultsConversationWidget-BvnLWHyi.js +5059 -0
- package/dist/chunks/WebSearchResultsConversationWidget-BvnLWHyi.js.map +1 -0
- package/dist/chunks/canvas-behaviours-BRFR1ALE.js +45 -0
- package/dist/chunks/canvas-behaviours-BRFR1ALE.js.map +1 -0
- package/dist/chunks/canvas-feature-flags-BmmxC3bz.js +11 -0
- package/dist/chunks/canvas-feature-flags-BmmxC3bz.js.map +1 -0
- package/dist/chunks/canvasBodies-9SuF6NAB.js +289 -0
- package/dist/chunks/canvasBodies-9SuF6NAB.js.map +1 -0
- package/dist/chunks/d3-7.6.1.min.js-DTmPafrl.js +6 -0
- package/dist/chunks/d3-7.6.1.min.js-DTmPafrl.js.map +1 -0
- package/dist/chunks/decide-canvas-open-Ct-wnNEJ.js +20 -0
- package/dist/chunks/decide-canvas-open-Ct-wnNEJ.js.map +1 -0
- package/dist/chunks/widget-image-readiness-signal-DeOuL89j.js +25 -0
- package/dist/chunks/widget-image-readiness-signal-DeOuL89j.js.map +1 -0
- package/dist/chunks/widget-name-resolver-DyIY6Zu4.js +9736 -0
- package/dist/chunks/widget-name-resolver-DyIY6Zu4.js.map +1 -0
- package/dist/chunks/withPollingChangeSubscription-BLDAWF-o.js +251 -0
- package/dist/chunks/withPollingChangeSubscription-BLDAWF-o.js.map +1 -0
- package/dist/client-testing.js +346 -0
- package/dist/client-testing.js.map +1 -0
- package/dist/client.js +16 -0
- package/dist/client.js.map +1 -0
- package/dist/contract.js +31 -0
- package/dist/contract.js.map +1 -0
- package/dist/image-render.js +334 -0
- package/dist/image-render.js.map +1 -0
- package/dist/index.js +80 -0
- package/dist/index.js.map +1 -0
- package/dist/kit.js +13 -0
- package/dist/kit.js.map +1 -0
- package/dist/preview.js +733 -0
- package/dist/preview.js.map +1 -0
- package/dist/renderer.js +115 -0
- package/dist/renderer.js.map +1 -0
- package/dist/styles.css +6768 -0
- package/dist/types/chat/AgentChat/AgentChat.d.ts +37 -0
- package/dist/types/chat/AgentChatActivityHistory/AgentChatActivityHistory.d.ts +6 -0
- package/dist/types/chat/AgentChatActivityIndicator/AgentChatActivityIndicator.d.ts +8 -0
- package/dist/types/chat/CanvasPane/CanvasPane.d.ts +15 -0
- package/dist/types/chat/CanvasResizeHandle/CanvasResizeHandle.d.ts +10 -0
- package/dist/types/chat/CanvasResizeHandle/use-canvas-resize.d.ts +43 -0
- package/dist/types/chat/ConversationClosedBar/ConversationClosedBar.d.ts +10 -0
- package/dist/types/chat/ConversationErrorCard/ConversationErrorCard.d.ts +13 -0
- package/dist/types/chat/ConversationIntroCard/ConversationIntroCard.d.ts +10 -0
- package/dist/types/chat/ConversationLoadingStates.d.ts +2 -0
- package/dist/types/chat/ConversationMessage/ConversationCallMarkerChip/ConversationCallMarkerChip.d.ts +14 -0
- package/dist/types/chat/ConversationMessage/ConversationCallMarkerChip/VoiceBarsIcon/VoiceBarsIcon.d.ts +8 -0
- package/dist/types/chat/ConversationMessage/ConversationMessageSystem/ConversationMessageSystem.d.ts +8 -0
- package/dist/types/chat/ConversationMessage/ConversationMessageSystem/ConversationMessageSystemHeader/ConversationMessageSystemHeader.d.ts +9 -0
- package/dist/types/chat/ConversationMessage/ConversationMessageUser/ConversationMessageUser.d.ts +7 -0
- package/dist/types/chat/ConversationMessage/ConversationMessageUser/ConversationMessageUserWidgets.d.ts +14 -0
- package/dist/types/chat/ConversationMessage/ConversationMessageWidgets/ConversationMessageHeader/ConversationMessageHeader.d.ts +7 -0
- package/dist/types/chat/ConversationMessage/ConversationMessageWidgets/ConversationMessageThinking/ConversationMessageThinking.d.ts +7 -0
- package/dist/types/chat/ConversationMessage/ConversationMessageWidgets/ConversationMessageWidgets.d.ts +29 -0
- package/dist/types/chat/ConversationMessage/ConversationMessageWidgets/copyRichToClipboard.d.ts +1 -0
- package/dist/types/chat/ConversationMessage/ConversationMessageWidgets/hooks/useFreshMessageBlockReveal.d.ts +14 -0
- package/dist/types/chat/ConversationMessage/ConversationMessageWidgets/hooks/useStreamingText.d.ts +8 -0
- package/dist/types/chat/ConversationMessage/ConversationMessageWidgets/hooks/useTypewriter.d.ts +12 -0
- package/dist/types/chat/ConversationMessage/ConversationTaskInstructionDisclosure/ConversationTaskInstructionDisclosure.d.ts +12 -0
- package/dist/types/chat/ConversationMessageInput/ConversationMessageInput.d.ts +111 -0
- package/dist/types/chat/ConversationMessageInput/ConversationMessageInputAttachments/ConversationMessageInputAttachmentPreviewCard.d.ts +34 -0
- package/dist/types/chat/ConversationMessageInput/ConversationMessageInputAttachments/ConversationMessageInputAttachmentsErrorBox.d.ts +22 -0
- package/dist/types/chat/ConversationMessageInput/ConversationMessageInputAttachments/ConversationMessageInputAttachmentsPreviewStrip.d.ts +12 -0
- package/dist/types/chat/ConversationMessageInput/ConversationMessageInputAttachments/convert-bytes-to-size-string.d.ts +2 -0
- package/dist/types/chat/ConversationMessageInput/ConversationMessageInputComposerWidgets/ConversationMessageInputComposerWidgets.d.ts +12 -0
- package/dist/types/chat/ConversationMessageList/ConversationMessageList.d.ts +75 -0
- package/dist/types/chat/ConversationScrollToLatestMessageButton/ConversationScrollToLatestMessageButton.d.ts +6 -0
- package/dist/types/chat/ConversationSuggestionCard/ConversationSuggestionCard.d.ts +7 -0
- package/dist/types/chat/ConversationView.d.ts +216 -0
- package/dist/types/chat/ConversationViewBody/ConversationViewBody.d.ts +214 -0
- package/dist/types/chat/ConversationViewBody/hooks/useIsMessagesBottomOutOfView.d.ts +2 -0
- package/dist/types/chat/ConversationViewBody/hooks/usePinQuestionOnSend.d.ts +24 -0
- package/dist/types/chat/assistant-message-has-renderable-markdown.d.ts +13 -0
- package/dist/types/chat/chat-assistant-identity.d.ts +24 -0
- package/dist/types/chat/chat-message.d.ts +11 -0
- package/dist/types/chat/controller/AgentChatController.d.ts +97 -0
- package/dist/types/chat/controller/activity-ticker.d.ts +120 -0
- package/dist/types/chat/controller/changed-messages-request.d.ts +12 -0
- package/dist/types/chat/controller/chat-scroll-target.d.ts +10 -0
- package/dist/types/chat/controller/conversation-change-signal-rules.d.ts +64 -0
- package/dist/types/chat/controller/derive-agent-activity.d.ts +31 -0
- package/dist/types/chat/controller/merge-activity-elements.d.ts +25 -0
- package/dist/types/chat/controller/pending-start-request.d.ts +38 -0
- package/dist/types/chat/controller/use-activity-ticker.d.ts +60 -0
- package/dist/types/chat/controller/use-conversation-activity.d.ts +38 -0
- package/dist/types/chat/controller/use-conversation-live-updates.d.ts +30 -0
- package/dist/types/chat/controller/use-conversation-message-pages.d.ts +24 -0
- package/dist/types/chat/controller/use-conversation-scroll-jump.d.ts +47 -0
- package/dist/types/chat/controller/use-conversation-search.d.ts +31 -0
- package/dist/types/chat/controller/use-conversation-signals.d.ts +44 -0
- package/dist/types/chat/controller/use-debounced-semantic-search.d.ts +15 -0
- package/dist/types/chat/conversation-send-message.d.ts +43 -0
- package/dist/types/chat/last-wire-message-is-unanswered-user-message.d.ts +22 -0
- package/dist/types/chat/normalize-server-message-to-markdown.d.ts +23 -0
- package/dist/types/chat/store/agents-chat-state.d.ts +132 -0
- package/dist/types/chat/store/conversation-error-type.d.ts +32 -0
- package/dist/types/chat/store/create-agents-chat-store.d.ts +23 -0
- package/dist/types/chat/store/index.d.ts +5 -0
- package/dist/types/chat/store/merge-chat-messages.d.ts +20 -0
- package/dist/types/chat/store/reduce-agents-chat-state.d.ts +7 -0
- package/dist/types/chat/store/use-agents-chat-store.d.ts +22 -0
- package/dist/types/chat/strip-pre-call-message-marker.d.ts +12 -0
- package/dist/types/chat/use-canvas-shell-transitions.d.ts +25 -0
- package/dist/types/client/AgentsConversationClient.d.ts +93 -0
- package/dist/types/client/AgentsConversationClientContext.d.ts +17 -0
- package/dist/types/client/polling/createPollingConversationChangeSubscription.d.ts +62 -0
- package/dist/types/client/polling/withPollingChangeSubscription.d.ts +11 -0
- package/dist/types/client/testing/createInMemoryAgentsConversationClient.d.ts +139 -0
- package/dist/types/contract/conversation.d.ts +370 -0
- package/dist/types/entries/chat.d.ts +21 -0
- package/dist/types/entries/client-testing.d.ts +1 -0
- package/dist/types/entries/client.d.ts +4 -0
- package/dist/types/entries/contract.d.ts +1 -0
- package/dist/types/entries/image-render.d.ts +9 -0
- package/dist/types/entries/index.d.ts +9 -0
- package/dist/types/entries/kit.d.ts +4 -0
- package/dist/types/entries/preview.d.ts +8 -0
- package/dist/types/entries/renderer.d.ts +15 -0
- package/dist/types/entries/widgets.d.ts +16 -0
- package/dist/types/image-render/ComposedViewEmailDataTimes/ComposedViewEmailDataTimes.d.ts +15 -0
- package/dist/types/image-render/WidgetImageRender.d.ts +55 -0
- package/dist/types/image-render/WidgetImageRenderContext.d.ts +14 -0
- package/dist/types/image-render/composed-view-data-times.d.ts +20 -0
- package/dist/types/image-render/frozen-widget-requests.d.ts +2 -0
- package/dist/types/image-render/live-widget-requests.d.ts +4 -0
- package/dist/types/image-render/widget-image-google-map.d.ts +7 -0
- package/dist/types/image-render/widget-image-readiness-signal.d.ts +16 -0
- package/dist/types/image-render/widget-image-readiness.d.ts +9 -0
- package/dist/types/image-render/widget-image-render.types.d.ts +47 -0
- package/dist/types/kit/ComposedViewConversationWidget.d.ts +14 -0
- package/dist/types/kit/ComposedViewDataSourceLoader.d.ts +20 -0
- package/dist/types/kit/ComposedViewRenderer.d.ts +30 -0
- package/dist/types/kit/ComposedViewSlotErrorBoundary.d.ts +23 -0
- package/dist/types/kit/ModelText/ModelText.d.ts +12 -0
- package/dist/types/kit/components/embedding/EmbeddedConversationWidget.d.ts +26 -0
- package/dist/types/kit/components/map/map-full-screen-instance.d.ts +26 -0
- package/dist/types/kit/components/map/map-presentation-context.d.ts +8 -0
- package/dist/types/kit/components/text/shared/text-node-values.d.ts +39 -0
- package/dist/types/kit/composed-view-component-types.d.ts +61 -0
- package/dist/types/kit/composed-view-components.d.ts +7 -0
- package/dist/types/kit/composed-view-tones.d.ts +20 -0
- package/dist/types/kit/entity-detail/EntityDetailCanvasBody.d.ts +9 -0
- package/dist/types/kit/entity-detail/entity-detail-bodies.d.ts +32 -0
- package/dist/types/kit/entity-detail/entity-detail-name.d.ts +9 -0
- package/dist/types/kit/hooks/use-debounced-value.d.ts +2 -0
- package/dist/types/kit/map-full-screen/MapFullScreenCanvasBody.d.ts +11 -0
- package/dist/types/preview/WidgetPreviewHost.d.ts +20 -0
- package/dist/types/preview/preview-stub-components.d.ts +3 -0
- package/dist/types/preview/widget-preview-fixtures.d.ts +17 -0
- package/dist/types/preview/widget-preview-hydration.d.ts +10 -0
- package/dist/types/preview/widget-preview-readiness.d.ts +27 -0
- package/dist/types/preview/widget-preview-requests.d.ts +16 -0
- package/dist/types/preview/widget-preview-signal.d.ts +10 -0
- package/dist/types/preview/widget-preview.types.d.ts +134 -0
- package/dist/types/provider/AgentsProvider.d.ts +33 -0
- package/dist/types/provider/class-names.d.ts +7 -0
- package/dist/types/provider/components/default-components.d.ts +3 -0
- package/dist/types/provider/components/icon-names.d.ts +9 -0
- package/dist/types/provider/components/index.d.ts +39 -0
- package/dist/types/provider/components/types.d.ts +463 -0
- package/dist/types/provider/environment.d.ts +262 -0
- package/dist/types/provider/index.d.ts +4 -0
- package/dist/types/renderer/ConversationDeepLinkedWidget.d.ts +18 -0
- package/dist/types/renderer/ConversationMarkdown.d.ts +21 -0
- package/dist/types/renderer/ConversationWidgetActions/ConversationWidgetActions.d.ts +7 -0
- package/dist/types/renderer/ConversationWidgetCallbacksContext.d.ts +234 -0
- package/dist/types/renderer/ConversationWidgetContext.d.ts +32 -0
- package/dist/types/renderer/ConversationWidgetErrorBoundary.d.ts +25 -0
- package/dist/types/renderer/ConversationWidgetHost.d.ts +36 -0
- package/dist/types/renderer/ConversationWidgetRenderContext.d.ts +3 -0
- package/dist/types/renderer/MarkdownLink.d.ts +6 -0
- package/dist/types/renderer/WindowedWidget/WindowedWidget.d.ts +16 -0
- package/dist/types/renderer/_access/ConversationWidgetFeatureGate.d.ts +21 -0
- package/dist/types/renderer/_agent-space/ConversationWidgetAgentSpaceFrame.d.ts +12 -0
- package/dist/types/renderer/_agent-space/ConversationWidgetAgentSpaceHeader.d.ts +15 -0
- package/dist/types/renderer/_agent-space/agent-space-name.hydrator.d.ts +7 -0
- package/dist/types/renderer/_agent-space/declared-agent-space-key-field-name.d.ts +8 -0
- package/dist/types/renderer/_agent-space/use-resolved-conversation-widget-agent-space-key.d.ts +16 -0
- package/dist/types/renderer/_agent-space/widget-agent-space-key-attribute.d.ts +13 -0
- package/dist/types/renderer/balanced-json-object.d.ts +12 -0
- package/dist/types/renderer/canvas/CanvasRestoreOnMount.d.ts +19 -0
- package/dist/types/renderer/canvas/canvas-behaviours.d.ts +84 -0
- package/dist/types/renderer/canvas/canvas-body-props.d.ts +18 -0
- package/dist/types/renderer/canvas/canvas-feature-flags.d.ts +11 -0
- package/dist/types/renderer/canvas/canvas-reducers.d.ts +46 -0
- package/dist/types/renderer/canvas/canvas-state.d.ts +107 -0
- package/dist/types/renderer/canvas/canvasBodies.d.ts +19 -0
- package/dist/types/renderer/canvas/canvasStorage.d.ts +25 -0
- package/dist/types/renderer/canvas/decide-canvas-open.d.ts +32 -0
- package/dist/types/renderer/canvas/entity-detail-instance.d.ts +27 -0
- package/dist/types/renderer/canvas/find-widget-fences-in-markdown.d.ts +32 -0
- package/dist/types/renderer/canvas/use-anchor-widget-payload.d.ts +8 -0
- package/dist/types/renderer/composer-widget-fence.d.ts +30 -0
- package/dist/types/renderer/conversation-composer-widget.d.ts +13 -0
- package/dist/types/renderer/conversation-widget-props.d.ts +54 -0
- package/dist/types/renderer/conversation-widget-state-partition.d.ts +31 -0
- package/dist/types/renderer/conversationWidgetAstPlugin.d.ts +11 -0
- package/dist/types/renderer/conversationWidgetRegistry.d.ts +74 -0
- package/dist/types/renderer/detect-unrendered-widgets.d.ts +42 -0
- package/dist/types/renderer/markdown-contains-widget.d.ts +13 -0
- package/dist/types/renderer/reference-naked-widget-json.d.ts +1 -0
- package/dist/types/renderer/remarkWidgetFencePlugin.d.ts +22 -0
- package/dist/types/renderer/render-report/widget-render-report-collector.d.ts +57 -0
- package/dist/types/renderer/render-report/widget-render-report.d.ts +29 -0
- package/dist/types/renderer/repair-malformed-widget-fences.d.ts +11 -0
- package/dist/types/renderer/resolve-deep-linkable-widget.d.ts +25 -0
- package/dist/types/renderer/restoreTextDirectivesPlugin.d.ts +12 -0
- package/dist/types/renderer/widget-click-signal-sources.d.ts +15 -0
- package/dist/types/renderer/widget-fence-json.d.ts +16 -0
- package/dist/types/renderer/widget-fence-syntax.d.ts +25 -0
- package/dist/types/renderer/widget-hydration/index.d.ts +8 -0
- package/dist/types/renderer/widget-hydration/section-hydration.d.ts +41 -0
- package/dist/types/renderer/widget-hydration/use-widget-hydration.d.ts +27 -0
- package/dist/types/renderer/widget-hydration/widget-hydration-state-store.d.ts +27 -0
- package/dist/types/renderer/widget-hydration/widget-hydration.reducer.d.ts +39 -0
- package/dist/types/renderer/widget-hydration/widget-hydration.registry.d.ts +7 -0
- package/dist/types/renderer/widget-hydration/widget-hydration.slice.d.ts +8 -0
- package/dist/types/renderer/widget-hydration/widget-hydration.types.d.ts +27 -0
- package/dist/types/renderer/widget-name-resolver.d.ts +22 -0
- package/dist/types/renderer/widget-tree/bounded-json.d.ts +23 -0
- package/dist/types/renderer/widget-tree/composed-node-schema.d.ts +143 -0
- package/dist/types/renderer/widget-tree/composed-view-data-sources.d.ts +41 -0
- package/dist/types/renderer/widget-tree/composed-view-tree.d.ts +111 -0
- package/dist/types/renderer/widget-tree/expression/evaluate-expression.d.ts +65 -0
- package/dist/types/renderer/widget-tree/expression/parse-expression.d.ts +71 -0
- package/dist/types/renderer/widget-tree/resolve-composed-view-values.d.ts +49 -0
- package/dist/types/renderer/widget-tree/use-composed-view-state.d.ts +16 -0
- package/dist/types/renderer/widget-windowing.d.ts +25 -0
- package/dist/types/widgets/CanvasWidgetCard/CanvasWidgetCard.d.ts +79 -0
- package/dist/types/widgets/CanvasWidgetCard/CanvasWidgetSwitch.d.ts +61 -0
- package/dist/types/widgets/CanvasWidgetCard/canvas-for-message-widget.d.ts +8 -0
- package/dist/types/widgets/CanvasWidgetCard/use-canvas-viable.d.ts +15 -0
- package/dist/types/widgets/ClockConversationWidget/ClockConversationWidget.d.ts +11 -0
- package/dist/types/widgets/ClockConversationWidget/ClockWidget/AnalogClockFace.d.ts +12 -0
- package/dist/types/widgets/ClockConversationWidget/ClockWidget/ClockRow.d.ts +23 -0
- package/dist/types/widgets/ClockConversationWidget/ClockWidget/ClockWidget.d.ts +21 -0
- package/dist/types/widgets/ClockConversationWidget/ClockWidget/DayNightGlyph.d.ts +8 -0
- package/dist/types/widgets/ClockConversationWidget/shared/clock-time.d.ts +52 -0
- package/dist/types/widgets/ClockConversationWidget/shared/clock-widget-payload.d.ts +23 -0
- package/dist/types/widgets/ClockConversationWidget/shared/use-clock-settings.d.ts +18 -0
- package/dist/types/widgets/ConceptExplainerConversationWidget/ConceptExplainerConversationWidget.d.ts +14 -0
- package/dist/types/widgets/ConceptExplainerConversationWidget/ConceptExplainerWidget/ConceptExplainerWidget.d.ts +27 -0
- package/dist/types/widgets/ConceptExplainerConversationWidget/shared/ConceptExplainerTextView.d.ts +11 -0
- package/dist/types/widgets/ConceptExplainerConversationWidget/shared/concept-explainer-type.d.ts +89 -0
- package/dist/types/widgets/ConceptExplainerConversationWidget/shared/concept-explainer-types.d.ts +17 -0
- package/dist/types/widgets/ConceptExplainerConversationWidget/shared/concept-explainer-widget-payload.d.ts +25 -0
- package/dist/types/widgets/ConceptExplainerConversationWidget/shared/use-concept-explainer-language.d.ts +8 -0
- package/dist/types/widgets/ConversationSearchResultsConversationWidget/ConversationSearchResultsCanvas.d.ts +9 -0
- package/dist/types/widgets/ConversationSearchResultsConversationWidget/ConversationSearchResultsCanvasBody.d.ts +7 -0
- package/dist/types/widgets/ConversationSearchResultsConversationWidget/ConversationSearchResultsConversationWidget.d.ts +15 -0
- package/dist/types/widgets/ConversationSearchResultsConversationWidget/shared/conversation-search-results-widget-payload.d.ts +42 -0
- package/dist/types/widgets/ConversationSearchResultsConversationWidget/shared/search-hit-excerpt.d.ts +1 -0
- package/dist/types/widgets/CurrencyConverterConversationWidget/CurrencyConverterConversationWidget.d.ts +8 -0
- package/dist/types/widgets/CurrencyConverterConversationWidget/CurrencyConverterWidget/CurrencyConverterWidget.d.ts +17 -0
- package/dist/types/widgets/CurrencyConverterConversationWidget/CurrencyConverterWidget/CurrencyLabel/CurrencyLabel.d.ts +9 -0
- package/dist/types/widgets/CurrencyConverterConversationWidget/shared/currency-converter-widget-payload.d.ts +22 -0
- package/dist/types/widgets/CurrencyConverterConversationWidget/shared/currency-display.d.ts +30 -0
- package/dist/types/widgets/CustomVisualizationConversationWidget/CustomVisualizationConversationWidget.d.ts +11 -0
- package/dist/types/widgets/CustomVisualizationConversationWidget/CustomVisualizationWidget/CustomVisualizationFrame.d.ts +14 -0
- package/dist/types/widgets/CustomVisualizationConversationWidget/CustomVisualizationWidget/CustomVisualizationWidget.d.ts +15 -0
- package/dist/types/widgets/CustomVisualizationConversationWidget/shared/custom-visualization-frame-protocol.d.ts +77 -0
- package/dist/types/widgets/CustomVisualizationConversationWidget/shared/custom-visualization-libraries.d.ts +25 -0
- package/dist/types/widgets/CustomVisualizationConversationWidget/shared/custom-visualization-sandbox-config.d.ts +21 -0
- package/dist/types/widgets/CustomVisualizationConversationWidget/shared/custom-visualization-widget-payload.d.ts +55 -0
- package/dist/types/widgets/CustomVisualizationConversationWidget/shared/read-custom-visualization-theme.d.ts +5 -0
- package/dist/types/widgets/EntityMentionConversationWidget/EntityMentionAskButton/EntityMentionAskButton.d.ts +13 -0
- package/dist/types/widgets/EntityMentionConversationWidget/EntityMentionCard/EntityMentionCard.d.ts +11 -0
- package/dist/types/widgets/EntityMentionConversationWidget/EntityMentionConversationWidget.d.ts +9 -0
- package/dist/types/widgets/EntityMentionConversationWidget/shared/entity-mention-presentation.d.ts +4 -0
- package/dist/types/widgets/EntityMentionConversationWidget/shared/entity-mention.d.ts +33 -0
- package/dist/types/widgets/EntityMentionConversationWidget/shared/use-entity-mention-composer.d.ts +17 -0
- package/dist/types/widgets/MultiChoiceConversationWidget/MultiChoiceConversationWidget.d.ts +2 -0
- package/dist/types/widgets/MultiChoiceConversationWidget/shared/multi-choice-widget-payload.d.ts +16 -0
- package/dist/types/widgets/QuickRepliesConversationWidget/QuickRepliesConversationWidget.d.ts +38 -0
- package/dist/types/widgets/QuickRepliesConversationWidget/shared/quick-replies-widget-payload.d.ts +20 -0
- package/dist/types/widgets/SuggestedActions/SuggestedActions.d.ts +10 -0
- package/dist/types/widgets/ToolTraceConversationWidget/ToolTraceConversationWidget.d.ts +8 -0
- package/dist/types/widgets/WebSearchResultsConversationWidget/SourceFavicon.d.ts +10 -0
- package/dist/types/widgets/WebSearchResultsConversationWidget/WebSearchAnswer.d.ts +6 -0
- package/dist/types/widgets/WebSearchResultsConversationWidget/WebSearchReferences.d.ts +12 -0
- package/dist/types/widgets/WebSearchResultsConversationWidget/WebSearchResultsCanvas.d.ts +10 -0
- package/dist/types/widgets/WebSearchResultsConversationWidget/WebSearchResultsCanvasBody.d.ts +7 -0
- package/dist/types/widgets/WebSearchResultsConversationWidget/WebSearchResultsConversationWidget.d.ts +14 -0
- package/dist/types/widgets/WebSearchResultsConversationWidget/WebSearchSourcesList.d.ts +10 -0
- package/dist/types/widgets/WebSearchResultsConversationWidget/shared/display-hostname.d.ts +9 -0
- package/dist/types/widgets/WebSearchResultsConversationWidget/shared/web-search-results-widget-payload.d.ts +30 -0
- package/dist/types/widgets/WritingDraftConversationWidget/WritingDraftConversationWidget.d.ts +14 -0
- package/dist/types/widgets/WritingDraftConversationWidget/WritingDraftWidget/WritingDraftBody.d.ts +9 -0
- package/dist/types/widgets/WritingDraftConversationWidget/WritingDraftWidget/WritingDraftWidget.d.ts +44 -0
- package/dist/types/widgets/WritingDraftConversationWidget/shared/draft-mail-link.d.ts +17 -0
- package/dist/types/widgets/WritingDraftConversationWidget/shared/draft-plain-text.d.ts +7 -0
- package/dist/types/widgets/WritingDraftConversationWidget/shared/remark-draft-line-breaks.d.ts +13 -0
- package/dist/types/widgets/WritingDraftConversationWidget/shared/writing-draft-widget-payload.d.ts +23 -0
- package/dist/types/widgets/_shared/ConversationWidgetButton.d.ts +4 -0
- package/dist/types/widgets/_shared/DonePill.d.ts +14 -0
- package/dist/types/widgets/_shared/modern/WidgetKpiValue.d.ts +24 -0
- package/dist/types/widgets/_shared/modern/WidgetListRow.d.ts +14 -0
- package/dist/types/widgets/_shared/modern/WidgetStatusChip.d.ts +8 -0
- package/dist/types/widgets/_shared/modern/WidgetSurface.d.ts +13 -0
- package/dist/types/widgets/_shared/modern/WidgetSurfaceSkeleton.d.ts +11 -0
- package/dist/types/widgets/_shared/modern/index.d.ts +16 -0
- package/dist/types/widgets/_shared/skeleton-primitives.d.ts +20 -0
- package/dist/types/widgets/_shared/use-stack-when-wrapped.d.ts +6 -0
- package/dist/types/widgets/_shared/widget-payload-validation.d.ts +22 -0
- package/dist/widgets.js +84 -0
- package/dist/widgets.js.map +1 -0
- package/package.json +120 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-testing.js","sources":["../src/client/testing/createInMemoryAgentsConversationClient.ts"],"sourcesContent":["import type { AgentsConversationClient, AgentsConversationOperation } from \"../AgentsConversationClient\";\nimport {\n AgentsClientError,\n type AgentsConversation,\n type AgentsConversationMessage,\n type ChangedConversationMessages,\n type ChangedMessagesRequest,\n type ConversationActivity,\n type ConversationAttachmentReference,\n type ConversationChangeSignal,\n type ConversationListQueryOptions,\n type ConversationMessageSearchHit,\n type ConversationMessageSentPayload,\n type ConversationMessagesPage,\n type ConversationRunStatus,\n CONVERSATION_RUN_STATES_THAT_END_THE_CONVERSATION,\n type ConversationSearchGroup,\n type ConversationSearchOptions,\n type ConversationSignal,\n type ConversationSubscriptionEndReason,\n type PostedMessage,\n readConversationRunStatusOfRunState,\n type SelectableModel,\n type StartedConversation,\n} from \"../../contract/conversation\";\n\n/** One recorded conversation handed to the in-memory client: plain data, as a fixture file holds it. */\nexport interface RecordedConversation {\n conversation: AgentsConversation;\n messages: AgentsConversationMessage[];\n /** What `getConversationActivity` answers for this conversation; an empty, finished turn when omitted. */\n activity?: ConversationActivity;\n}\n\nexport interface InMemoryAgentsConversationClientData {\n conversations: RecordedConversation[];\n /**\n * The assistant's answers to a post, an injected signal, a start or a retry, used in order; the last one repeats.\n * Default: one answer, \"Done.\".\n */\n scriptedAssistantAnswers?: string[];\n /** What `getSelectableModels` answers; the client has no `getSelectableModels` when omitted. */\n selectableModels?: SelectableModel[];\n /** The page size of `getChangedMessages` when the request names none. Default 50. */\n defaultPageSize?: number;\n /** What `getMessageSentPayload` answers, by message id; the client has no `getMessageSentPayload` when omitted. */\n sentPayloadsByMessageId?: Record<number, ConversationMessageSentPayload>;\n /**\n * The assistant answers this many milliseconds after the send, like a server's turn: the run state is RUNNING\n * meanwhile, then the answer is stored and the run state goes back to IDLE — no `emit()` involved, so a poller sees it.\n * Default 0: the answer is stored together with the send.\n */\n assistantAnswerDelayMs?: number;\n /**\n * The client has no `subscribeToConversationChanges` — a backend without push. The chat then follows the\n * conversation through the polling default (`withPollingChangeSubscription`). Default false.\n */\n withoutChangeSubscription?: boolean;\n}\n\n/** A subscriber of one conversation's live updates. */\ninterface ConversationChangeSubscriber {\n onChange: (signal: ConversationChangeSignal) => void;\n onEnded: (reason: ConversationSubscriptionEndReason) => void;\n}\n\n/** The live-update state of one conversation. */\ninterface ConversationSignalState {\n changeCounter: number;\n summaryUpdatedAt: number | null;\n}\n\nconst DEFAULT_SCRIPTED_ASSISTANT_ANSWER = \"Done.\";\nconst DEFAULT_PAGE_SIZE = 50;\n\n/** A deep copy, so a caller can never change the client's records through a returned object. */\nconst copyOf = <T>(value: T): T => JSON.parse(JSON.stringify(value)) as T;\n\nconst sortByIndexAscending = (messages: AgentsConversationMessage[]): AgentsConversationMessage[] =>\n [...messages].sort((first, second) => (first.indexInConversation ?? 0) - (second.indexInConversation ?? 0));\n\nconst textContains = (text: string | null | undefined, searchText: string): boolean =>\n (text ?? \"\").toLowerCase().includes(searchText.trim().toLowerCase());\n\n/** The message text a send stores: the typed text plus one reference line per attachment (as the host application's chat sends it). */\nconst buildStoredMessageText = (text: string, attachments: ConversationAttachmentReference[] | undefined): string =>\n attachments?.length\n ? `${text}\\n\\n${attachments\n .map((attachment) => `[Attached file: ${attachment.fileName ?? \"file\"} — ${attachment.publicUrl ?? \"\"}]`)\n .join(\"\\n\")}`\n : text;\n\n/**\n * The conversation client over recorded conversations, for specs, stories and the reference app\n * (`./testing`). Behaves like the server where the chat can see it: a post stores the owner's message and, at once,\n * the next scripted assistant answer — but live updates are driven by hand: `emit()` sends the conversation's next\n * signal to its subscribers (counter advanced, newest message id, the run status), `end()` ends the subscriptions.\n * With `assistantAnswerDelayMs` the answer is stored later, as a server turn would (RUNNING meanwhile); with\n * `withoutChangeSubscription` the client has no subscription at all and the chat polls it.\n */\nexport class InMemoryAgentsConversationClient implements AgentsConversationClient {\n protected readonly recordsByConversationId = new Map<number, RecordedConversation>();\n protected readonly subscribersByConversationId = new Map<number, Set<ConversationChangeSubscriber>>();\n protected readonly signalStateByConversationId = new Map<number, ConversationSignalState>();\n protected readonly scriptedAssistantAnswers: string[];\n protected readonly defaultPageSize: number;\n protected readonly selectableModels: SelectableModel[] | undefined;\n protected readonly sentPayloadsByMessageId: Record<number, ConversationMessageSentPayload> | undefined;\n protected readonly assistantAnswerDelayMs: number;\n protected readonly requestCountsByOperation = new Map<AgentsConversationOperation, number>();\n protected scriptedAssistantAnswersUsed = 0;\n protected nextMessageId: number;\n protected nextConversationId: number;\n\n /** Present only when the data names selectable models (the port function is optional). */\n readonly getSelectableModels?: () => Promise<SelectableModel[]>;\n /** Present only when the data names sent payloads (the port function is optional). */\n readonly getMessageSentPayload?: (conversationId: number, messageId: number) => Promise<ConversationMessageSentPayload>;\n /** Present unless the data asks for a client without push (`withoutChangeSubscription`). */\n readonly subscribeToConversationChanges?: (\n conversationId: number,\n onChange: (signal: ConversationChangeSignal) => void,\n onEnded: (reason: ConversationSubscriptionEndReason) => void,\n ) => () => void;\n\n constructor(data: InMemoryAgentsConversationClientData) {\n for (const recordedConversation of copyOf(data.conversations)) {\n this.recordsByConversationId.set(recordedConversation.conversation.id, recordedConversation);\n }\n const scriptedAssistantAnswers = data.scriptedAssistantAnswers ?? [];\n this.scriptedAssistantAnswers =\n scriptedAssistantAnswers.length > 0 ? [...scriptedAssistantAnswers] : [DEFAULT_SCRIPTED_ASSISTANT_ANSWER];\n this.defaultPageSize = data.defaultPageSize ?? DEFAULT_PAGE_SIZE;\n this.selectableModels = data.selectableModels ? copyOf(data.selectableModels) : undefined;\n if (this.selectableModels) {\n this.getSelectableModels = this.readSelectableModels;\n }\n this.sentPayloadsByMessageId = data.sentPayloadsByMessageId ? copyOf(data.sentPayloadsByMessageId) : undefined;\n if (this.sentPayloadsByMessageId) {\n this.getMessageSentPayload = this.readMessageSentPayload;\n }\n this.assistantAnswerDelayMs = data.assistantAnswerDelayMs ?? 0;\n if (!data.withoutChangeSubscription) {\n this.subscribeToConversationChanges = this.subscribeToRecordedConversationChanges;\n }\n const allMessageIds = data.conversations.flatMap((recorded) => recorded.messages.map((message) => message.id));\n const allConversationIds = data.conversations.map((recorded) => recorded.conversation.id);\n this.nextMessageId = Math.max(0, ...allMessageIds) + 1;\n this.nextConversationId = Math.max(0, ...allConversationIds) + 1;\n }\n\n // ── Port ──────────────────────────────────────────────────────────────────────────────────────────────────────\n\n listConversations = async (\n agentSpaceKey: number,\n options: ConversationListQueryOptions = {},\n ): Promise<AgentsConversation[]> => {\n this.countRequest(\"listConversations\");\n const { includeUnsummarized = false, paging = {} } = options;\n const { top, skip = 0 } = paging;\n const conversationsOfAgentSpace = [...this.recordsByConversationId.values()]\n .map((recorded) => recorded.conversation)\n .filter((conversation) => conversation.agentSpaceKey === agentSpaceKey)\n .filter((conversation) => includeUnsummarized || conversation.title !== null)\n .sort((first, second) => second.id - first.id);\n const end = top === undefined ? undefined : skip + top;\n return copyOf(conversationsOfAgentSpace.slice(skip, end));\n };\n\n /** Account-wide, like the server: every recorded conversation is searched. */\n searchConversations = async (text: string, options: ConversationSearchOptions = {}): Promise<ConversationSearchGroup[]> => {\n this.countRequest(\"searchConversations\");\n const searchGroups: ConversationSearchGroup[] = [];\n for (const recorded of this.recordsByConversationId.values()) {\n const hits = this.findMessageSearchHits(recorded, text);\n if (hits.length === 0) continue;\n searchGroups.push({\n conversationId: recorded.conversation.id,\n title: recorded.conversation.title,\n summary: null,\n created: recorded.messages[0]?.createdDate ?? null,\n updated: recorded.messages[recorded.messages.length - 1]?.createdDate ?? null,\n relevance: 1,\n hits,\n });\n }\n return copyOf(searchGroups.slice(0, options.limit));\n };\n\n /** The stored conversation with `lastMessageId` (the newest stored message), as a backend without push answers it. */\n getConversationMetadata = async (conversationId: number): Promise<AgentsConversation> => {\n this.countRequest(\"getConversationMetadata\");\n const recorded = this.readRecord(conversationId);\n return copyOf({ ...recorded.conversation, lastMessageId: sortByIndexAscending(recorded.messages).pop()?.id ?? null });\n };\n\n getNewestMessagesPage = async (conversationId: number, pageSize: number): Promise<ConversationMessagesPage> => {\n this.countRequest(\"getNewestMessagesPage\");\n const newestFirst = this.readMessagesNewestFirst(conversationId);\n return copyOf({ messages: newestFirst.slice(0, pageSize), hasMoreOlder: newestFirst.length > pageSize });\n };\n\n getOlderMessagesPage = async (\n conversationId: number,\n beforeIndex: number,\n pageSize: number,\n ): Promise<ConversationMessagesPage> => {\n this.countRequest(\"getOlderMessagesPage\");\n const olderMessages = this.readMessagesNewestFirst(conversationId).filter(\n (message) => (message.indexInConversation ?? Number.MAX_SAFE_INTEGER) < beforeIndex,\n );\n return copyOf({ messages: olderMessages.slice(0, pageSize), hasMoreOlder: olderMessages.length > pageSize });\n };\n\n getChangedMessages = async (\n conversationId: number,\n request: ChangedMessagesRequest,\n ): Promise<ChangedConversationMessages> => {\n this.countRequest(\"getChangedMessages\");\n const changedMessages = this.readMessagesNewestFirst(conversationId).filter(\n (message) => message.id > request.highestKnownId || (message.indexInConversation ?? -1) >= request.fromIndex,\n );\n return copyOf({ messages: changedMessages.slice(0, request.pageSize ?? this.defaultPageSize) });\n };\n\n searchConversationMessages = async (\n conversationId: number,\n text: string,\n options: ConversationSearchOptions = {},\n ): Promise<ConversationMessageSearchHit[]> => {\n this.countRequest(\"searchConversationMessages\");\n return copyOf(this.findMessageSearchHits(this.readRecord(conversationId), text).slice(0, options.limit));\n };\n\n getConversationActivity = async (conversationId: number): Promise<ConversationActivity> => {\n this.countRequest(\"getConversationActivity\");\n return copyOf(this.readRecord(conversationId).activity ?? { turnMessageId: null, turnRunning: false, elements: [] });\n };\n\n startConversation = async (request: {\n agentSpaceKey: number;\n text: string;\n startSignalText?: string;\n entryPointKey?: string;\n model?: string;\n attachments?: ConversationAttachmentReference[];\n }): Promise<StartedConversation> => {\n this.countRequest(\"startConversation\");\n if (request.text === \"\" && !request.startSignalText) {\n throw new AgentsClientError(\"other\", { httpStatus: 400, message: \"A start needs a message or a signal.\" });\n }\n const reopenedConversation = request.entryPointKey\n ? [...this.recordsByConversationId.values()].find(\n (recorded) =>\n recorded.conversation.agentSpaceKey === request.agentSpaceKey &&\n recorded.conversation.entryPointKey === request.entryPointKey,\n )\n : undefined;\n if (reopenedConversation) {\n return { conversation: copyOf(reopenedConversation.conversation), messages: [], reopenedExisting: true };\n }\n const recorded: RecordedConversation = {\n conversation: {\n id: this.nextConversationId,\n agentSpaceKey: request.agentSpaceKey,\n runState: \"IDLE\",\n agentTurnOwedAt: null,\n title: null,\n titleManuallyEdited: false,\n summary: null,\n created: null,\n updated: null,\n purposeName: null,\n initiatorType: null,\n scheduleId: null,\n entryPointKey: request.entryPointKey ?? null,\n progressSteps: [],\n },\n messages: [],\n };\n this.nextConversationId += 1;\n this.recordsByConversationId.set(recorded.conversation.id, recorded);\n if (request.startSignalText) {\n this.appendMessage(recorded, { role: \"USER\", messageType: \"SIGNAL\", authorType: \"USER\", message: request.startSignalText });\n }\n if (request.text !== \"\") {\n this.appendMessage(recorded, {\n role: \"USER\",\n messageType: \"TEXT\",\n authorType: \"USER\",\n message: buildStoredMessageText(request.text, request.attachments),\n });\n }\n const messagesBeforeTheAnswer = copyOf(recorded.messages);\n this.appendScriptedAssistantAnswer(recorded);\n return { conversation: copyOf(recorded.conversation), messages: messagesBeforeTheAnswer, reopenedExisting: false };\n };\n\n postMessage = async (\n conversationId: number,\n message: { text: string; model?: string; attachments?: ConversationAttachmentReference[] },\n ): Promise<PostedMessage> => {\n this.countRequest(\"postMessage\");\n const recorded = this.readOpenRecord(conversationId);\n this.appendMessage(recorded, {\n role: \"USER\",\n messageType: \"TEXT\",\n authorType: \"USER\",\n message: buildStoredMessageText(message.text, message.attachments),\n });\n const messagesBeforeTheAnswer = copyOf(recorded.messages);\n this.appendScriptedAssistantAnswer(recorded);\n return { messages: messagesBeforeTheAnswer };\n };\n\n injectSignal = async (conversationId: number, signal: ConversationSignal): Promise<void> => {\n this.countRequest(\"injectSignal\");\n const recorded = this.readOpenRecord(conversationId);\n this.appendMessage(recorded, {\n role: \"USER\",\n messageType: \"SIGNAL\",\n authorType: \"USER\",\n message: signal.text,\n signalSource: signal.source ?? \"FRONTEND_WIDGET_CLICK\",\n });\n this.appendScriptedAssistantAnswer(recorded);\n };\n\n retryConversation = async (conversationId: number): Promise<void> => {\n this.countRequest(\"retryConversation\");\n const recorded = this.readRecord(conversationId);\n const newestMessage = sortByIndexAscending(recorded.messages).pop();\n if (newestMessage === undefined || newestMessage.role === \"ASSISTANT\") {\n throw new AgentsClientError(\"other\", { httpStatus: 400, message: \"Nothing to retry.\" });\n }\n this.appendScriptedAssistantAnswer(recorded);\n };\n\n renameConversation = async (conversationId: number, title: string): Promise<AgentsConversation> => {\n this.countRequest(\"renameConversation\");\n const recorded = this.readRecord(conversationId);\n recorded.conversation.title = title;\n recorded.conversation.titleManuallyEdited = true;\n return copyOf(recorded.conversation);\n };\n\n deleteConversation = async (conversationId: number): Promise<void> => {\n this.countRequest(\"deleteConversation\");\n this.readRecord(conversationId);\n this.recordsByConversationId.delete(conversationId);\n };\n\n /** The port's `subscribeToConversationChanges` unless `withoutChangeSubscription`; signals come from `emit()`. */\n protected subscribeToRecordedConversationChanges = (\n conversationId: number,\n onChange: (signal: ConversationChangeSignal) => void,\n onEnded: (reason: ConversationSubscriptionEndReason) => void,\n ): (() => void) => {\n const subscriber: ConversationChangeSubscriber = { onChange, onEnded };\n const subscribers = this.subscribersByConversationId.get(conversationId) ?? new Set<ConversationChangeSubscriber>();\n subscribers.add(subscriber);\n this.subscribersByConversationId.set(conversationId, subscribers);\n // Like the realtime database: the current value arrives at once, before any change.\n const record = this.recordsByConversationId.get(conversationId);\n if (record) {\n onChange(this.buildSignal(record, this.readSignalState(conversationId), null));\n }\n return () => {\n subscribers.delete(subscriber);\n };\n };\n\n // ── Driving live updates by hand ──────────────────────────────────────────────────────────────────────────────\n\n /**\n * Sends the conversation's next signal to its subscribers: the counter advances, `lastMessageId` is the newest\n * stored message, the run status follows the stored run state unless `runStatus` is given. `summaryChanged` also\n * advances `summaryUpdatedAt`. Returns the sent signal.\n */\n emit = (\n conversationId: number,\n change: { runStatus?: ConversationRunStatus; summaryChanged?: boolean } = {},\n ): ConversationChangeSignal => {\n const record = this.readRecord(conversationId);\n const signalState = this.readSignalState(conversationId);\n signalState.changeCounter += 1;\n if (change.summaryChanged) {\n signalState.summaryUpdatedAt = (signalState.summaryUpdatedAt ?? 0) + 1;\n }\n const signal = this.buildSignal(record, signalState, change.runStatus ?? null);\n for (const subscriber of [...(this.subscribersByConversationId.get(conversationId) ?? [])]) {\n subscriber.onChange(copyOf(signal));\n }\n return signal;\n };\n\n /** Ends every subscription of the conversation with `reason`, as the server's deletion or a lost access would. */\n end = (conversationId: number, reason: ConversationSubscriptionEndReason): void => {\n const subscribers = [...(this.subscribersByConversationId.get(conversationId) ?? [])];\n this.subscribersByConversationId.delete(conversationId);\n for (const subscriber of subscribers) {\n subscriber.onEnded(reason);\n }\n };\n\n /** Sets a conversation's stored run state (a turn that runs, fails, or a conversation that closes). */\n setRunState = (conversationId: number, runState: AgentsConversation[\"runState\"]): void => {\n this.readRecord(conversationId).conversation.runState = runState;\n };\n\n /**\n * How many requests the client answered — of one port function, or of all when `operation` is omitted (the\n * subscription is no request). For assertions such as \"no read after the chat unmounted\".\n */\n readRequestCount = (operation?: AgentsConversationOperation): number => {\n if (operation !== undefined) return this.requestCountsByOperation.get(operation) ?? 0;\n let requestCount = 0;\n for (const operationRequestCount of this.requestCountsByOperation.values()) requestCount += operationRequestCount;\n return requestCount;\n };\n\n /** Every stored message of a conversation in index order — for assertions. */\n readStoredMessages = (conversationId: number): AgentsConversationMessage[] =>\n copyOf(sortByIndexAscending(this.readRecord(conversationId).messages));\n\n // ── Internals ─────────────────────────────────────────────────────────────────────────────────────────────────\n\n protected countRequest(operation: AgentsConversationOperation): void {\n this.requestCountsByOperation.set(operation, (this.requestCountsByOperation.get(operation) ?? 0) + 1);\n }\n\n protected readSelectableModels = async (): Promise<SelectableModel[]> => {\n this.countRequest(\"getSelectableModels\");\n return copyOf(this.selectableModels ?? []);\n };\n\n protected readMessageSentPayload = async (\n conversationId: number,\n messageId: number,\n ): Promise<ConversationMessageSentPayload> => {\n this.countRequest(\"getMessageSentPayload\");\n this.readRecord(conversationId);\n const sentPayload = this.sentPayloadsByMessageId?.[messageId];\n if (sentPayload === undefined) {\n throw new AgentsClientError(\"notFound\", { httpStatus: 404, message: `No sent payload for message ${messageId}.` });\n }\n return copyOf(sentPayload);\n };\n\n protected readMessagesNewestFirst(conversationId: number): AgentsConversationMessage[] {\n return sortByIndexAscending(this.readRecord(conversationId).messages).reverse();\n }\n\n protected readRecord(conversationId: number): RecordedConversation {\n const recorded = this.recordsByConversationId.get(conversationId);\n if (!recorded) {\n throw new AgentsClientError(\"notFound\", { httpStatus: 404, message: `Conversation ${conversationId} not found.` });\n }\n return recorded;\n }\n\n /** The record of a conversation that still takes input; a completed or cancelled one refuses like the server. */\n protected readOpenRecord(conversationId: number): RecordedConversation {\n const recorded = this.readRecord(conversationId);\n const runState = recorded.conversation.runState;\n if (runState !== null && CONVERSATION_RUN_STATES_THAT_END_THE_CONVERSATION.includes(runState)) {\n throw new AgentsClientError(\"closed\", { httpStatus: 400, code: \"CONVERSATION_CLOSED\" });\n }\n return recorded;\n }\n\n protected readSignalState(conversationId: number): ConversationSignalState {\n const existingSignalState = this.signalStateByConversationId.get(conversationId);\n if (existingSignalState) return existingSignalState;\n const signalState: ConversationSignalState = { changeCounter: 0, summaryUpdatedAt: null };\n this.signalStateByConversationId.set(conversationId, signalState);\n return signalState;\n }\n\n protected buildSignal(\n recorded: RecordedConversation,\n signalState: ConversationSignalState,\n runStatus: ConversationRunStatus | null,\n ): ConversationChangeSignal {\n const newestMessage = sortByIndexAscending(recorded.messages).pop();\n return {\n changeCounter: signalState.changeCounter,\n lastMessageId: newestMessage?.id ?? null,\n runStatus: runStatus ?? readConversationRunStatusOfRunState(recorded.conversation.runState),\n summaryUpdatedAt: signalState.summaryUpdatedAt,\n };\n }\n\n protected appendMessage(\n recorded: RecordedConversation,\n fields: Pick<AgentsConversationMessage, \"role\" | \"messageType\" | \"authorType\" | \"message\"> &\n Partial<Pick<AgentsConversationMessage, \"signalSource\">>,\n ): AgentsConversationMessage {\n const highestIndex = Math.max(-1, ...recorded.messages.map((message) => message.indexInConversation ?? -1));\n const storedMessage: AgentsConversationMessage = {\n id: this.nextMessageId,\n conversationId: recorded.conversation.id,\n indexInConversation: highestIndex + 1,\n status: \"COMPLETED\",\n signalSource: null,\n createdDate: null,\n toolCall: null,\n delegatedConversations: [],\n subAgent: null,\n ...fields,\n };\n this.nextMessageId += 1;\n recorded.messages.push(storedMessage);\n return storedMessage;\n }\n\n /** The next scripted answer: stored at once, or after `assistantAnswerDelayMs` with the run state RUNNING meanwhile. */\n protected appendScriptedAssistantAnswer(recorded: RecordedConversation): void {\n const answerIndex = Math.min(this.scriptedAssistantAnswersUsed, this.scriptedAssistantAnswers.length - 1);\n this.scriptedAssistantAnswersUsed += 1;\n const answerText = this.scriptedAssistantAnswers[answerIndex];\n if (this.assistantAnswerDelayMs <= 0) {\n this.storeAssistantAnswer(recorded, answerText);\n return;\n }\n recorded.conversation.runState = \"RUNNING\";\n setTimeout(this.storeAssistantAnswer, this.assistantAnswerDelayMs, recorded, answerText);\n }\n\n protected storeAssistantAnswer = (recorded: RecordedConversation, answerText: string): void => {\n this.appendMessage(recorded, {\n role: \"ASSISTANT\",\n messageType: \"TEXT\",\n authorType: \"ASSISTANT\",\n message: answerText,\n });\n recorded.conversation.runState = \"IDLE\";\n };\n\n protected findMessageSearchHits(recorded: RecordedConversation, text: string): ConversationMessageSearchHit[] {\n if (text.trim() === \"\") return [];\n return sortByIndexAscending(recorded.messages)\n .filter((message) => message.messageType === \"TEXT\" && textContains(message.message, text))\n .map((message) => ({\n messageId: message.id,\n conversationId: recorded.conversation.id,\n indexInConversation: message.indexInConversation,\n role: message.role,\n excerpt: message.message,\n relevance: 1,\n created: message.createdDate,\n updated: null,\n title: recorded.conversation.title,\n }));\n }\n}\n\n/** The in-memory conversation client over recorded conversations (plain data). */\nexport const createInMemoryAgentsConversationClient = (\n data: InMemoryAgentsConversationClientData,\n): InMemoryAgentsConversationClient => new InMemoryAgentsConversationClient(data);\n"],"names":["recorded"],"mappings":"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"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { A, u, a } from "./chunks/AgentsConversationClientContext-C4T7g_Qk.js";
|
|
3
|
+
import { P, a as a2, b, c, d, r, w } from "./chunks/withPollingChangeSubscription-BLDAWF-o.js";
|
|
4
|
+
export {
|
|
5
|
+
A as AgentsConversationClientProvider,
|
|
6
|
+
P as POLLING_IDLE_INTERVAL_MS,
|
|
7
|
+
a2 as POLLING_LOCAL_ACTIVITY_WINDOW_MS,
|
|
8
|
+
b as POLLING_MAX_BACKOFF_MS,
|
|
9
|
+
c as POLLING_RUNNING_INTERVAL_MS,
|
|
10
|
+
d as createPollingConversationChangeSubscription,
|
|
11
|
+
r as readPolledRunStatus,
|
|
12
|
+
u as useAgentsConversationClient,
|
|
13
|
+
a as useOptionalAgentsConversationClient,
|
|
14
|
+
w as withPollingChangeSubscription
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
|
package/dist/contract.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
const CONVERSATION_RUN_STATES_THAT_END_THE_CONVERSATION = [
|
|
3
|
+
"COMPLETED",
|
|
4
|
+
"CANCELLED"
|
|
5
|
+
];
|
|
6
|
+
const readConversationRunStatusOfRunState = (runState) => {
|
|
7
|
+
if (!runState) return null;
|
|
8
|
+
if (runState === "FAILED") return "failed";
|
|
9
|
+
if (runState === "RUNNING" || runState === "AWAITING_DELEGATES" || runState === "QUEUED") return "running";
|
|
10
|
+
return "idle";
|
|
11
|
+
};
|
|
12
|
+
const AGENTS_CLIENT_ERROR_CODE_REQUEST_ABORTED = "REQUEST_ABORTED";
|
|
13
|
+
class AgentsClientError extends Error {
|
|
14
|
+
constructor(kind, details = {}) {
|
|
15
|
+
super(details.message ?? kind);
|
|
16
|
+
this.name = "AgentsClientError";
|
|
17
|
+
this.kind = kind;
|
|
18
|
+
this.code = details.code ?? null;
|
|
19
|
+
this.retryAfterSeconds = kind === "rateLimit" ? details.retryAfterSeconds ?? null : null;
|
|
20
|
+
this.httpStatus = details.httpStatus ?? null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const isAgentsClientError = (value) => value instanceof AgentsClientError;
|
|
24
|
+
export {
|
|
25
|
+
AGENTS_CLIENT_ERROR_CODE_REQUEST_ABORTED,
|
|
26
|
+
AgentsClientError,
|
|
27
|
+
CONVERSATION_RUN_STATES_THAT_END_THE_CONVERSATION,
|
|
28
|
+
isAgentsClientError,
|
|
29
|
+
readConversationRunStatusOfRunState
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.js","sources":["../src/contract/conversation.ts"],"sourcesContent":["/**\n * The conversation contract of the package: plain TypeScript types the conversation client port\n * (`client/AgentsConversationClient.ts`) returns and the chat reads. Every field is derived from what the chat files and\n * the chat controller read from the server today (the host application's generated `AIConversation`, `AIConversationMessage`,\n * `AgentActivityLine`, `SemanticSearchHit`, `AIConversationSearchGroup`, `AgentCustomerSelectableModel`); nothing the\n * chat does not read is here.\n *\n * Naming: a field keeps the wire name where the name is neutral (`message`, `indexInConversation`, `role`, `status`,\n * `toolCall`); a name that carries an app's vocabulary is renamed (`aiConversationId` → `conversationId`,\n * the app's own key of the thing the agent works for → `agentSpaceKey`, `summary.title` → `title`). Each field carries a\n * one-line note:\n * - `generic` — every app that runs the agent conversation backend has it;\n * - `app extension` — read by the chat today but specific to one app's backend or debug surface; optional, and a\n * binding may leave it out.\n *\n * Client-side state is NOT part of the contract: the `fresh` tag of a live-arrived message, the optimistic user\n * message without an id and the `isNewConversation` / `isReopenedConversation` flags belong to the package store.\n */\n\n// ── Vocabulary ───────────────────────────────────────────────────────────────────────────────────────────────────\n\n/** The run state of a conversation as the server stores it (`AIConversationRunState`). */\nexport type ConversationRunState =\n | \"IDLE\"\n | \"QUEUED\"\n | \"RUNNING\"\n | \"AWAITING_DELEGATES\"\n | \"FAILED\"\n | \"COMPLETED\"\n | \"CANCELLED\";\n\n/** The three-value run status the live-update signal speaks; the chat keys its indicator and error card off it. */\nexport type ConversationRunStatus = \"running\" | \"idle\" | \"failed\";\n\nexport type ConversationMessageRole = \"SYSTEM\" | \"USER\" | \"ASSISTANT\";\n\nexport type ConversationMessageType = \"TEXT\" | \"TOOL_CALL\" | \"CHECKPOINT\" | \"ERROR\" | \"SIGNAL\" | \"TOOL_MESSAGE\";\n\nexport type ConversationMessageStatus =\n | \"PENDING\"\n | \"RUNNING\"\n | \"CANCEL_REQUESTED\"\n | \"CANCELLED\"\n | \"COMPLETED\"\n | \"FAILED\";\n\nexport type ConversationMessageAuthorType = \"USER\" | \"ASSISTANT\" | \"AGENT\" | \"TOOL\";\n\n/** Run states after which nothing runs any more and the server refuses further customer input. */\nexport const CONVERSATION_RUN_STATES_THAT_END_THE_CONVERSATION: readonly ConversationRunState[] = [\n \"COMPLETED\",\n \"CANCELLED\",\n];\n\n/** Maps a stored run state onto the signal's three-value status (`runStateToSignalStatus` of the live-update hook). */\nexport const readConversationRunStatusOfRunState = (\n runState: string | null | undefined,\n): ConversationRunStatus | null => {\n if (!runState) return null;\n if (runState === \"FAILED\") return \"failed\";\n if (runState === \"RUNNING\" || runState === \"AWAITING_DELEGATES\" || runState === \"QUEUED\") return \"running\";\n return \"idle\";\n};\n\n// ── Conversation ─────────────────────────────────────────────────────────────────────────────────────────────────\n\n/** One step of the progress stepper a purposed conversation declares (`CustomerProgressStep`). */\nexport interface ConversationProgressStep {\n /** generic */\n key: string;\n /** generic — already in the owner's language */\n label: string;\n /** generic */\n status: \"done\" | \"active\" | \"upcoming\";\n}\n\n/** A conversation as the chat, the conversation list and the window around the chat read it. */\nexport interface AgentsConversation {\n /** generic */\n id: number;\n /** generic — the key of the agent space the conversation belongs to */\n agentSpaceKey: number | null;\n /** generic */\n runState: ConversationRunState | null;\n /**\n * generic — set while the server owes a turn on an IDLE conversation (a failed hand-over the recovery re-drives);\n * an IDLE conversation with this set counts as running (`effectiveRunState`)\n */\n agentTurnOwedAt: string | null;\n /** generic — the display title (`summary.title`); null until the first title was generated */\n title: string | null;\n /** generic — the owner set the title by hand; the generated title never replaces it then */\n titleManuallyEdited: boolean;\n /** generic — the generated summary of what the conversation is about (`summary.text`); null until generated */\n summary: string | null;\n /** generic — when the conversation was created, in the server's date-time format */\n created: string | null;\n /** generic — when the conversation was last modified, in the server's date-time format */\n updated: string | null;\n /** generic — the purpose of a purposed conversation (e.g. `Example.Build`, a first-run setup purpose); null otherwise */\n purposeName: string | null;\n /** generic — who started the conversation (`SCHEDULE` for a run of a scheduled task) */\n initiatorType: string | null;\n /** generic — the scheduled task a `SCHEDULE` conversation is a run of */\n scheduleId: number | null;\n /** generic — the entry point a start came from; a start from the same entry point reopens this conversation */\n entryPointKey: string | null;\n /** generic — empty unless the purpose declares a progress stepper */\n progressSteps: ConversationProgressStep[];\n /**\n * generic — the id of the newest stored message; null before the first. The polling default of the live updates\n * (`client/polling/`) reads it to see a new message while the run status stays the same, and hands it to the rules as\n * the signal's `lastMessageId`. Optional: a binding with a push transport may leave it out (the host application's metadata\n * read does not carry it); without it the poller treats every poll of a running turn as a change.\n */\n lastMessageId?: number | null;\n /** app extension — the prompt extension of the host application's older AI-Extensions chat */\n promptExtensionId?: number | null;\n /** app extension — the category of that prompt extension (its colour and product name in the conversation list) */\n promptExtensionCategory?: { alias: string | null; name: string | null } | null;\n}\n\n// ── Messages ─────────────────────────────────────────────────────────────────────────────────────────────────────\n\n/** A sub-agent conversation a delegation started, as far as the chat reads it (`delegatedConversations(select=id,runState)`). */\nexport interface ConversationDelegatedConversation {\n /** generic */\n id: number;\n /** generic */\n runState: ConversationRunState | null;\n}\n\n/** One run of a sub-agent, as the activity derivation reads it (`DelegationSubAgentRun`). */\nexport interface ConversationSubAgentRun {\n /** generic */\n runNumber: number | null;\n /** generic */\n status: string | null;\n}\n\n/** The sub-agent record a newer `delegate` call row carries instead of expanded children (`DelegationSubAgentRecord`). */\nexport interface ConversationSubAgent {\n /** generic */\n currentRunNumber: number | null;\n /** generic */\n runs: ConversationSubAgentRun[];\n}\n\n/** The tool call a `TOOL_CALL` row carries, as far as the chat reads it. */\nexport interface ConversationToolCall {\n /** generic */\n toolCallId: string | null;\n /** generic */\n name: string | null;\n /** generic — the call's arguments as the model wrote them (the `delegate` call's `tasks` is read) */\n arguments: unknown;\n /** generic — the call's own progress; a row's `status` says nothing about it */\n status: string | null;\n}\n\n/** The admin debug numbers of one message (the message forensics panel). */\nexport interface ConversationMessageForensics {\n /** app extension */\n inputTokens: number | null;\n /** app extension */\n outputTokens: number | null;\n /** app extension */\n costInUSD: number | null;\n /** app extension — the stored request snapshot of the model call (model name, reasoning effort, sent at) */\n requestSnapshot: unknown;\n}\n\n/** One stored message of a conversation. */\nexport interface AgentsConversationMessage {\n /** generic */\n id: number;\n /** generic */\n conversationId: number | null;\n /** generic — the position in the conversation; the merge key of every page */\n indexInConversation: number | null;\n /** generic */\n role: ConversationMessageRole | null;\n /** generic */\n messageType: ConversationMessageType | null;\n /** generic — non-final only on a waiting signal row */\n status: ConversationMessageStatus | null;\n /** generic */\n authorType: ConversationMessageAuthorType | null;\n /** generic — the source of a SIGNAL or ERROR row (`AI_BUDGET_REACHED`, `FRONTEND_WIDGET_CLICK`, …) */\n signalSource: string | null;\n /** generic — the text in markdown, widget blocks included */\n message: string;\n /** generic */\n createdDate: string | null;\n /** generic */\n toolCall: ConversationToolCall | null;\n /** generic — the sub-agent conversations a `delegate` call started (older rows) */\n delegatedConversations: ConversationDelegatedConversation[];\n /** generic — the sub-agent record of a `delegate` call (newer rows) */\n subAgent: ConversationSubAgent | null;\n /** app extension — admin debug numbers; absent outside the admin surfaces */\n forensics?: ConversationMessageForensics;\n}\n\n/** A file from the app's media library that rides along with a message. */\nexport interface ConversationAttachmentReference {\n /** generic — the app's id of the file (host application: the media manager file id) */\n fileId: string | number | null;\n /** generic */\n fileName: string | null;\n /** generic — a URL the model and the tools can fetch */\n publicUrl: string | null;\n}\n\n// ── Pages and results of the port ────────────────────────────────────────────────────────────────────────────────\n\n/** A page of messages read newest first (the newest page on open, an older page on scroll-up). */\nexport interface ConversationMessagesPage {\n /** generic — in any order; the store merges by `indexInConversation` */\n messages: AgentsConversationMessage[];\n /** generic — an older page exists */\n hasMoreOlder: boolean;\n}\n\n/**\n * What a live update reads: every message written since the newest known id, plus every message from the lowest\n * loaded index that can still change (`build-live-refetch-query.ts`). The package computes both values.\n */\nexport interface ChangedMessagesRequest {\n /** generic — the highest message id loaded */\n highestKnownId: number;\n /** generic — the lowest index that can still change, never below the newest page */\n fromIndex: number;\n /** generic — the page size of the read; the binding's default (host application: 50, as the chat sends) when omitted */\n pageSize?: number;\n}\n\n/** The answer of a changed-messages read; it says nothing about older pages (the store keeps `hasMoreOlder`). */\nexport interface ChangedConversationMessages {\n /** generic */\n messages: AgentsConversationMessage[];\n}\n\n/** The answer of a start: the new conversation with what it holds so far, or the reopened one of the entry point. */\nexport interface StartedConversation {\n /** generic */\n conversation: AgentsConversation;\n /** generic — the stored messages of a new conversation; empty for a reopened one (the chat reads its newest page) */\n messages: AgentsConversationMessage[];\n /** generic — the start returned the recent conversation of its entry point; nothing was appended, no turn started */\n reopenedExisting: boolean;\n}\n\n/** The answer of a post: the conversation's messages so far (the reply arrives through live updates). */\nexport interface PostedMessage {\n /** generic */\n messages: AgentsConversationMessage[];\n}\n\n/** A model-visible, owner-invisible note into a conversation (a widget click, a render report, a correction). */\nexport interface ConversationSignal {\n /** generic */\n text: string;\n /** generic — the signal source; the server's default applies when omitted (a widget click) */\n source?: string;\n}\n\n/** How a list read pages and which conversations it includes. */\nexport interface ConversationListQueryOptions {\n /** generic — include conversations that have no summary (title) yet, e.g. a just-started one */\n includeUnsummarized?: boolean;\n /** generic — the host application's history reads the newest 50 */\n paging?: { top?: number; skip?: number };\n}\n\n/** The size of a search answer. */\nexport interface ConversationSearchOptions {\n /** generic — the most groups (or hits) returned; the host application's chat asks for 10 */\n limit?: number;\n /** generic — the excerpt length in characters; the host application's chat asks for 420 */\n excerptLength?: number;\n}\n\n/** app extension — the reconstructed request a model call was sent with (the admin details panel); opaque data. */\nexport type ConversationMessageSentPayload = unknown[];\n\n/** One matched message of a message search (`SemanticSearchHit`). */\nexport interface ConversationMessageSearchHit {\n /** generic */\n messageId: number | null;\n /** generic */\n conversationId: number | null;\n /** generic */\n indexInConversation: number | null;\n /** generic */\n role: string | null;\n /** generic */\n excerpt: string;\n /** generic */\n relevance: number;\n /** generic */\n created: string | null;\n /** generic */\n updated: string | null;\n /** generic — the conversation's title */\n title: string | null;\n}\n\n/** One conversation of a search across conversations, with its matched messages (`AIConversationSearchGroup`). */\nexport interface ConversationSearchGroup {\n /** generic */\n conversationId: number | null;\n /** generic */\n title: string | null;\n /** generic */\n summary: string | null;\n /** generic */\n created: string | null;\n /** generic */\n updated: string | null;\n /** generic */\n relevance: number;\n /** generic */\n hits: ConversationMessageSearchHit[];\n}\n\n/** One generated line of what the agent is doing (`AgentActivityLine`). */\nexport interface ConversationActivityElement {\n /** generic — the row the line narrates; the merge key */\n toolCallMessageId: number;\n /** generic */\n batchId: string | null;\n /** generic */\n state: \"queued\" | \"running\" | \"finished\" | \"failed\" | \"skipped\" | null;\n /** generic */\n kind: \"tool\" | \"delegation\" | \"background\" | \"long\" | \"turnStart\" | null;\n /** generic */\n childCount: number | null;\n /** generic — the 1-based delegation helper that ran the step; null for the assistant's own steps */\n helperIndex: number | null;\n /** generic — the sentence; null while the narrator has not answered */\n line: string | null;\n}\n\n/** The activity of one turn (`GET …/activity`). */\nexport interface ConversationActivity {\n /** generic — the message that started the narrated turn */\n turnMessageId: number | null;\n /** generic */\n turnRunning: boolean;\n /** generic */\n elements: ConversationActivityElement[];\n}\n\n/** A model the owner (host application: an impersonating admin) may pick for the next turns (`AgentCustomerSelectableModel`). */\nexport interface SelectableModel {\n /** generic — the name a send carries */\n name: string;\n /** generic */\n displayName: string;\n /** generic */\n description: string;\n /** generic */\n strengthLevel: number | null;\n /** generic */\n speedLevel: number | null;\n /** app extension — the host application's credit multiplier of the model */\n creditsMultiplier?: number | null;\n}\n\n// ── Live updates ─────────────────────────────────────────────────────────────────────────────────────────────────\n\n/**\n * What a live update carries: a claim check, never content. The chat reads the conversation again when\n * `changeCounter` advances, at once on a terminal status, and until `lastMessageId` is loaded.\n */\nexport interface ConversationChangeSignal {\n /** generic — advances on every change of the conversation */\n changeCounter: number;\n /** generic — the newest message the server wrote; null before the first */\n lastMessageId: number | null;\n /** generic */\n runStatus: ConversationRunStatus | null;\n /** generic — advances when the title or summary was generated again (a light metadata read is enough then) */\n summaryUpdatedAt: number | null;\n /**\n * generic — the binding produced this emission from a run-state read, not from a pushed change (a binding without\n * push, or a push transport whose path is not proven readable, or a check that corrects a stale status). It carries\n * only `runStatus` as news: `changeCounter`, `lastMessageId` and `summaryUpdatedAt` repeat the last pushed values\n * (before any push: a counter that counts down from -1, never equal to a pushed one). The package sets the status\n * from it and reads the conversation again on a status change while the push path is not alive (`isPushPathAlive`).\n */\n isStatusCheck?: boolean;\n /**\n * generic, on a status-check emission — the binding's push path delivers: a pushed change arrived and the path was not\n * denied since. False after a denied read until a push arrives again; then the status checks are the live path and a\n * status change reads the conversation again. A binding without push leaves it out: the package then counts the\n * pushed changes it saw itself.\n */\n isPushPathAlive?: boolean;\n}\n\n/** Why a subscription ended for good: the conversation was deleted or is no longer readable, or the account lost access. */\nexport type ConversationSubscriptionEndReason = \"gone\" | \"forbidden\";\n\n// ── Errors ───────────────────────────────────────────────────────────────────────────────────────────────────────\n\n/**\n * What went wrong, as the chat tells the owner. The codes the chat's error handling reads today map\n * onto it: `AI_BUDGET_REACHED` → `budget`, HTTP 429 / `RATE_LIMIT_EXCEEDED` → `rateLimit`, `CONVERSATION_CLOSED` →\n * `closed`, the not-found and no-access answers → `notFound` / `forbidden` (`conversation-not-found.ts`), no answer or a\n * server failure → `network`, everything else (a refused retry, a cancelled request) → `other` with its `code`.\n */\nexport type AgentsClientErrorKind = \"budget\" | \"rateLimit\" | \"closed\" | \"notFound\" | \"forbidden\" | \"network\" | \"other\";\n\n/** The code `other` carries for a request the client cancelled; the chat shows no error card for it. */\nexport const AGENTS_CLIENT_ERROR_CODE_REQUEST_ABORTED = \"REQUEST_ABORTED\";\n\n/** The one error shape every port function rejects with. */\nexport class AgentsClientError extends Error {\n readonly kind: AgentsClientErrorKind;\n /** The server's stable error code, or the client's own code (`REQUEST_ABORTED`); null when none arrived. */\n readonly code: string | null;\n /** Seconds until a quota frees up again; set only for `rateLimit`. */\n readonly retryAfterSeconds: number | null;\n /** The HTTP status when one arrived (not part of the contract's shape; kept for diagnostics). */\n readonly httpStatus: number | null;\n\n constructor(\n kind: AgentsClientErrorKind,\n details: { message?: string; code?: string | null; retryAfterSeconds?: number | null; httpStatus?: number | null } = {},\n ) {\n super(details.message ?? kind);\n this.name = \"AgentsClientError\";\n this.kind = kind;\n this.code = details.code ?? null;\n this.retryAfterSeconds = kind === \"rateLimit\" ? (details.retryAfterSeconds ?? null) : null;\n this.httpStatus = details.httpStatus ?? null;\n }\n}\n\nexport const isAgentsClientError = (value: unknown): value is AgentsClientError => value instanceof AgentsClientError;\n"],"names":[],"mappings":";AAiDO,MAAM,oDAAqF;AAAA,EAChG;AAAA,EACA;AACF;AAGO,MAAM,sCAAsC,CACjD,aACiC;AACjC,MAAI,CAAC,SAAU,QAAO;AACtB,MAAI,aAAa,SAAU,QAAO;AAClC,MAAI,aAAa,aAAa,aAAa,wBAAwB,aAAa,SAAU,QAAO;AACjG,SAAO;AACT;AAkWO,MAAM,2CAA2C;AAGjD,MAAM,0BAA0B,MAAM;AAAA,EAS3C,YACE,MACA,UAAqH,IACrH;AACA,UAAM,QAAQ,WAAW,IAAI;AAC7B,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,OAAO,QAAQ,QAAQ;AAC5B,SAAK,oBAAoB,SAAS,cAAe,QAAQ,qBAAqB,OAAQ;AACtF,SAAK,aAAa,QAAQ,cAAc;AAAA,EAC1C;AACF;AAEO,MAAM,sBAAsB,CAAC,UAA+C,iBAAiB;"}
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import React, { useRef, useEffect } from "react";
|
|
4
|
+
import { v as resolveWidgetName, o as conversationWidgetRegistry } from "./chunks/widget-name-resolver-DyIY6Zu4.js";
|
|
5
|
+
import { w } from "./chunks/widget-name-resolver-DyIY6Zu4.js";
|
|
6
|
+
import { aY as ConversationWidgetRenderContext, aZ as WidgetImageReadinessContext, ae as ReadOnlyConversationWidgetProvider, a_ as WidgetImageRenderContext, a$ as WidgetImageLiveHydrationContext, b0 as buildWidgetAgentSpaceKeyProps, O as getGoogleMapWidgetNames, U as getWidgetImageCaptureReadPathPrefix } from "./chunks/WebSearchResultsConversationWidget-BvnLWHyi.js";
|
|
7
|
+
import { b1, b2, b3 } from "./chunks/WebSearchResultsConversationWidget-BvnLWHyi.js";
|
|
8
|
+
import { r as readWidgetImageReadiness, p as publishWidgetImageReadiness } from "./chunks/widget-image-readiness-signal-DeOuL89j.js";
|
|
9
|
+
import { W, a } from "./chunks/widget-image-readiness-signal-DeOuL89j.js";
|
|
10
|
+
import axios from "axios";
|
|
11
|
+
const root = "agents_root_prMo3u";
|
|
12
|
+
const styles = {
|
|
13
|
+
root
|
|
14
|
+
};
|
|
15
|
+
const staticWidgetImageComponents = {};
|
|
16
|
+
const registerStaticWidgetImageComponents = (components) => {
|
|
17
|
+
Object.assign(staticWidgetImageComponents, components);
|
|
18
|
+
};
|
|
19
|
+
class WidgetImageCaptureBoundary extends React.Component {
|
|
20
|
+
constructor() {
|
|
21
|
+
super(...arguments);
|
|
22
|
+
this.state = { failed: false };
|
|
23
|
+
}
|
|
24
|
+
static getDerivedStateFromError() {
|
|
25
|
+
return { failed: true };
|
|
26
|
+
}
|
|
27
|
+
componentDidCatch() {
|
|
28
|
+
this.props.fail("WIDGET_RENDER_FAILED");
|
|
29
|
+
}
|
|
30
|
+
render() {
|
|
31
|
+
return this.state.failed ? null : this.props.children;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const WidgetImageRender = (props) => {
|
|
35
|
+
const { bootstrap, readiness } = props;
|
|
36
|
+
const ref = useRef(null);
|
|
37
|
+
const name = resolveWidgetName(bootstrap.input.widgetName);
|
|
38
|
+
const entry = conversationWidgetRegistry.widgets.find((widget) => widget.name === name);
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (!entry) readiness.fail("UNKNOWN_WIDGET");
|
|
41
|
+
else if (ref.current) return readiness.observe(ref.current);
|
|
42
|
+
}, [entry, readiness]);
|
|
43
|
+
if (!entry) return null;
|
|
44
|
+
const Component = bootstrap.input.mode === "live" ? entry.component : staticWidgetImageComponents[name ?? ""] ?? entry.component;
|
|
45
|
+
return /* @__PURE__ */ jsx("div", { ref, className: styles.root, inert: true, children: /* @__PURE__ */ jsx(ConversationWidgetRenderContext.Provider, { value: "email", children: /* @__PURE__ */ jsx(WidgetImageReadinessContext.Provider, { value: readiness, children: /* @__PURE__ */ jsx(ReadOnlyConversationWidgetProvider, { agentSpaceKey: bootstrap.siteId, children: /* @__PURE__ */ jsx(WidgetImageRenderContext.Provider, { value: bootstrap.input.hydration, children: /* @__PURE__ */ jsx(WidgetImageLiveHydrationContext.Provider, { value: bootstrap.input.mode === "live", children: /* @__PURE__ */ jsx(
|
|
46
|
+
Component,
|
|
47
|
+
{
|
|
48
|
+
...bootstrap.input.props,
|
|
49
|
+
...buildWidgetAgentSpaceKeyProps(bootstrap.siteId),
|
|
50
|
+
interactive: false,
|
|
51
|
+
fresh: false,
|
|
52
|
+
justDelivered: false,
|
|
53
|
+
openedByPage: false
|
|
54
|
+
}
|
|
55
|
+
) }) }) }) }) }) });
|
|
56
|
+
};
|
|
57
|
+
const followWidgetHydrationReadiness = (store, readiness) => store.subscribe(() => {
|
|
58
|
+
const widgets = Object.values(store.getState().AIExtensionsWidgetHydration.widgets);
|
|
59
|
+
if (widgets.some((widget) => widget.status === "error")) readiness.fail("WIDGET_HYDRATION_FAILED");
|
|
60
|
+
readiness.setHydrationPending(widgets.some((widget) => widget.status === "loading" || widget.status === "idle"));
|
|
61
|
+
});
|
|
62
|
+
const MAX_TIMER_DELAY_MS = 2 ** 31 - 1;
|
|
63
|
+
const createWidgetImageReadiness = (bootstrap) => {
|
|
64
|
+
let failed = readWidgetImageReadiness()?.state === "failed";
|
|
65
|
+
let requestsPending = 0;
|
|
66
|
+
let hydrationPending = false;
|
|
67
|
+
let notifyChanged = () => {
|
|
68
|
+
};
|
|
69
|
+
let observed = null;
|
|
70
|
+
const identity = {
|
|
71
|
+
version: 1,
|
|
72
|
+
snapshot_id: bootstrap.snapshotId,
|
|
73
|
+
attempt_id: bootstrap.attemptId,
|
|
74
|
+
input_sha256: bootstrap.inputSha256,
|
|
75
|
+
render_version: bootstrap.renderVersion
|
|
76
|
+
};
|
|
77
|
+
const publish = (state, extra = {}) => {
|
|
78
|
+
publishWidgetImageReadiness({ ...identity, state, ...extra });
|
|
79
|
+
document.documentElement.dataset.widgetImageState = state;
|
|
80
|
+
document.documentElement.dataset.widgetImageError = extra.error_code ?? "";
|
|
81
|
+
};
|
|
82
|
+
if (!failed) publish("loading");
|
|
83
|
+
const measure = (element) => {
|
|
84
|
+
const { x, y, width, height } = element.getBoundingClientRect();
|
|
85
|
+
return { x, y, width, height };
|
|
86
|
+
};
|
|
87
|
+
const fail = (code) => {
|
|
88
|
+
if (failed || readWidgetImageReadiness()?.state === "failed") return;
|
|
89
|
+
failed = true;
|
|
90
|
+
const rect = observed ? measure(observed) : void 0;
|
|
91
|
+
publish("failed", rect && rect.width > 0 && rect.height > 0 ? { error_code: code, rect } : { error_code: code });
|
|
92
|
+
};
|
|
93
|
+
const isFailed = () => failed || readWidgetImageReadiness()?.state === "failed";
|
|
94
|
+
const frame = () => new Promise((resolve) => requestAnimationFrame(() => resolve()));
|
|
95
|
+
const ready = async (element, isCurrent = () => true) => {
|
|
96
|
+
observed = element;
|
|
97
|
+
try {
|
|
98
|
+
await frame();
|
|
99
|
+
await frame();
|
|
100
|
+
await document.fonts.ready;
|
|
101
|
+
document.fonts.forEach((font) => {
|
|
102
|
+
if (font.status === "error") throw new Error("FONT_FAILED");
|
|
103
|
+
});
|
|
104
|
+
const images = Array.from(element.querySelectorAll("img"));
|
|
105
|
+
await Promise.all(
|
|
106
|
+
images.map(async (img) => {
|
|
107
|
+
if (!img.currentSrc && !img.getAttribute("src") && !img.getAttribute("srcset") && img.alt === "") return;
|
|
108
|
+
if (img.loading !== "eager") img.loading = "eager";
|
|
109
|
+
await img.decode();
|
|
110
|
+
if (!img.naturalWidth) throw new Error("ASSET_FAILED");
|
|
111
|
+
})
|
|
112
|
+
);
|
|
113
|
+
await frame();
|
|
114
|
+
await frame();
|
|
115
|
+
if (isFailed() || !isCurrent()) return;
|
|
116
|
+
if (requestsPending > 0 || hydrationPending) return;
|
|
117
|
+
if (Date.now() >= bootstrap.expiresAt * 1e3) return fail("TOKEN_EXPIRED");
|
|
118
|
+
if (element.querySelector(
|
|
119
|
+
'[aria-busy="true"], [role="progressbar"]:not([aria-valuenow]), [class*="Skeleton"], [class*="skeleton"]'
|
|
120
|
+
)) {
|
|
121
|
+
if (bootstrap.input.mode === "live") return;
|
|
122
|
+
return fail("WIDGET_STILL_LOADING");
|
|
123
|
+
}
|
|
124
|
+
const rect = element.getBoundingClientRect();
|
|
125
|
+
const width = bootstrap.input.width ?? 528;
|
|
126
|
+
const maxHeight = bootstrap.input.maxHeight ?? 1200;
|
|
127
|
+
if (!element.textContent?.trim() && !element.querySelector("img,svg,canvas")) return fail("EMPTY_WIDGET");
|
|
128
|
+
if (rect.width <= 0 || rect.height <= 0 || rect.width > width + 1 || rect.height > maxHeight || rect.x < 0 || rect.y < 0 || element.scrollWidth > Math.ceil(rect.width) || element.scrollHeight > Math.ceil(rect.height)) {
|
|
129
|
+
return fail("WIDGET_BOUNDS_EXCEEDED");
|
|
130
|
+
}
|
|
131
|
+
publish("ready", { rect: measure(element) });
|
|
132
|
+
} catch {
|
|
133
|
+
if (isCurrent()) fail("REQUIRED_ASSET_FAILED");
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
const observe = (element) => {
|
|
137
|
+
observed = element;
|
|
138
|
+
let revision = 0;
|
|
139
|
+
let timer;
|
|
140
|
+
let disposed = false;
|
|
141
|
+
const changed = () => {
|
|
142
|
+
if (disposed || isFailed()) return;
|
|
143
|
+
revision += 1;
|
|
144
|
+
const expected = revision;
|
|
145
|
+
publish("loading");
|
|
146
|
+
clearTimeout(timer);
|
|
147
|
+
timer = setTimeout(() => void ready(element, () => !disposed && expected === revision), 250);
|
|
148
|
+
};
|
|
149
|
+
const observer = new MutationObserver(changed);
|
|
150
|
+
notifyChanged = changed;
|
|
151
|
+
observer.observe(element, { childList: true, subtree: true, attributes: true, characterData: true });
|
|
152
|
+
const resize = new ResizeObserver(changed);
|
|
153
|
+
resize.observe(element);
|
|
154
|
+
changed();
|
|
155
|
+
const remaining = bootstrap.expiresAt * 1e3 - Date.now();
|
|
156
|
+
const expiry = remaining <= MAX_TIMER_DELAY_MS ? setTimeout(() => fail("TOKEN_EXPIRED"), Math.max(0, remaining)) : void 0;
|
|
157
|
+
const deadline = setTimeout(() => {
|
|
158
|
+
if (readWidgetImageReadiness()?.state !== "ready") fail("RENDER_DEADLINE_EXCEEDED");
|
|
159
|
+
}, 6e4);
|
|
160
|
+
return () => {
|
|
161
|
+
disposed = true;
|
|
162
|
+
observer.disconnect();
|
|
163
|
+
resize.disconnect();
|
|
164
|
+
clearTimeout(timer);
|
|
165
|
+
if (expiry !== void 0) clearTimeout(expiry);
|
|
166
|
+
clearTimeout(deadline);
|
|
167
|
+
notifyChanged = () => {
|
|
168
|
+
};
|
|
169
|
+
};
|
|
170
|
+
};
|
|
171
|
+
const beginRequest = () => {
|
|
172
|
+
requestsPending += 1;
|
|
173
|
+
if (!isFailed()) publish("loading");
|
|
174
|
+
notifyChanged();
|
|
175
|
+
return () => {
|
|
176
|
+
requestsPending -= 1;
|
|
177
|
+
notifyChanged();
|
|
178
|
+
};
|
|
179
|
+
};
|
|
180
|
+
const setHydrationPending = (pending) => {
|
|
181
|
+
if (hydrationPending === pending) return;
|
|
182
|
+
hydrationPending = pending;
|
|
183
|
+
if (!isFailed()) publish("loading");
|
|
184
|
+
notifyChanged();
|
|
185
|
+
};
|
|
186
|
+
return { ready, observe, fail, isFailed, beginRequest, setHydrationPending };
|
|
187
|
+
};
|
|
188
|
+
const installFrozenWidgetRequests = (responses, fail) => {
|
|
189
|
+
const originalAdapter = axios.defaults.adapter;
|
|
190
|
+
axios.defaults.adapter = async (config) => {
|
|
191
|
+
const url = new URL(axios.getUri(config), window.location.origin);
|
|
192
|
+
url.searchParams.sort();
|
|
193
|
+
const key = `${(config.method ?? "get").toUpperCase()} ${url.pathname}${url.search}`;
|
|
194
|
+
if ((config.method ?? "get").toLowerCase() !== "get" || !Object.prototype.hasOwnProperty.call(responses, key)) {
|
|
195
|
+
fail("MISSING_FROZEN_RESPONSE");
|
|
196
|
+
throw new Error("MISSING_FROZEN_RESPONSE");
|
|
197
|
+
}
|
|
198
|
+
return { data: structuredClone(responses[key]), status: 200, statusText: "OK", config, headers: {} };
|
|
199
|
+
};
|
|
200
|
+
return () => {
|
|
201
|
+
axios.defaults.adapter = originalAdapter;
|
|
202
|
+
};
|
|
203
|
+
};
|
|
204
|
+
const MAX_TREE_DEPTH = 32;
|
|
205
|
+
const isMapNodeInValue = (value, depth, googleMapWidgetNames) => {
|
|
206
|
+
if (depth > MAX_TREE_DEPTH || typeof value !== "object" || value === null) return false;
|
|
207
|
+
if (Array.isArray(value)) return value.some((element) => isMapNodeInValue(element, depth + 1, googleMapWidgetNames));
|
|
208
|
+
const wireObject = value;
|
|
209
|
+
if (wireObject.type === "Map") return true;
|
|
210
|
+
if (wireObject.type === "Widget" && typeof wireObject.widget === "string") {
|
|
211
|
+
const embeddedWidgetName = wireObject.widget.replace(/Directive$/, "");
|
|
212
|
+
if (googleMapWidgetNames.includes(embeddedWidgetName)) return true;
|
|
213
|
+
}
|
|
214
|
+
return Object.values(wireObject).some((nested) => isMapNodeInValue(nested, depth + 1, googleMapWidgetNames));
|
|
215
|
+
};
|
|
216
|
+
const isGoogleMapCapture = (widgetName, props) => {
|
|
217
|
+
const googleMapWidgetNames = getGoogleMapWidgetNames();
|
|
218
|
+
if (googleMapWidgetNames.includes(widgetName)) return true;
|
|
219
|
+
if (widgetName !== "ComposedView" || typeof props.payload !== "string") return false;
|
|
220
|
+
try {
|
|
221
|
+
return isMapNodeInValue(JSON.parse(props.payload)?.view, 0, googleMapWidgetNames);
|
|
222
|
+
} catch {
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
const STATIC_ASSET_PATH = /^\/react\/(?:app-build|widget-image-build)\/assets\/(?:[\w-]+\/)*[\w.-]+\.(?:svg|png|jpe?g|webp|gif)$/;
|
|
227
|
+
const installLiveWidgetRequests = (bootstrap, readiness) => {
|
|
228
|
+
const originalAdapter = axios.defaults.adapter;
|
|
229
|
+
const originalFetch = window.fetch;
|
|
230
|
+
const fetchRead = originalFetch.bind(window);
|
|
231
|
+
window.fetch = async (input, init) => {
|
|
232
|
+
const request = new Request(typeof input === "string" ? new URL(input, window.location.origin).href : input, init);
|
|
233
|
+
const url = new URL(request.url, window.location.origin);
|
|
234
|
+
const unavailable = readiness.isFailed() || Date.now() >= bootstrap.expiresAt * 1e3;
|
|
235
|
+
const isStaticAsset = url.origin === window.location.origin && STATIC_ASSET_PATH.test(url.pathname) && url.search === "" && request.method === "GET";
|
|
236
|
+
if (isStaticAsset && !unavailable) {
|
|
237
|
+
const finish2 = readiness.beginRequest();
|
|
238
|
+
try {
|
|
239
|
+
return await fetchRead(url.toString(), {
|
|
240
|
+
credentials: "omit",
|
|
241
|
+
redirect: "error",
|
|
242
|
+
referrerPolicy: "no-referrer"
|
|
243
|
+
});
|
|
244
|
+
} finally {
|
|
245
|
+
finish2();
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
const isMap = isGoogleMapCapture(bootstrap.input.widgetName, bootstrap.input.props);
|
|
249
|
+
const isGoogleMapRequest = url.protocol === "https:" && (url.hostname === "maps.googleapis.com" && (url.pathname.startsWith("/maps/") || url.pathname.startsWith("/$rpc/")) || url.hostname === "maps.gstatic.com" && url.pathname.startsWith("/mapfiles/"));
|
|
250
|
+
if (!isMap || !isGoogleMapRequest || !["GET", "POST"].includes(request.method) || unavailable) {
|
|
251
|
+
readiness.fail("UNSCOPED_REQUEST");
|
|
252
|
+
throw new Error("Unscoped render request");
|
|
253
|
+
}
|
|
254
|
+
const headers = new Headers();
|
|
255
|
+
for (const name of ["content-type", "x-goog-api-key", "x-goog-api-client", "x-user-agent"]) {
|
|
256
|
+
const value = request.headers.get(name);
|
|
257
|
+
if (value) headers.set(name, value);
|
|
258
|
+
}
|
|
259
|
+
const finish = readiness.beginRequest();
|
|
260
|
+
try {
|
|
261
|
+
const response = await fetchRead(request, {
|
|
262
|
+
credentials: "omit",
|
|
263
|
+
referrerPolicy: "no-referrer",
|
|
264
|
+
redirect: "error",
|
|
265
|
+
headers
|
|
266
|
+
});
|
|
267
|
+
if (!response.ok) throw new Error("Map request failed");
|
|
268
|
+
return response;
|
|
269
|
+
} catch {
|
|
270
|
+
readiness.fail("MAP_ASSET_FAILED");
|
|
271
|
+
throw new Error("Map request failed");
|
|
272
|
+
} finally {
|
|
273
|
+
finish();
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
axios.defaults.adapter = async (config) => {
|
|
277
|
+
const finish = readiness.beginRequest();
|
|
278
|
+
try {
|
|
279
|
+
const url = new URL(axios.getUri(config), window.location.origin);
|
|
280
|
+
if (!bootstrap.authToken || url.origin !== window.location.origin || !url.pathname.startsWith(getWidgetImageCaptureReadPathPrefix()) || (config.method ?? "get").toLowerCase() !== "get" || config.data !== void 0 || readiness.isFailed() || Date.now() >= bootstrap.expiresAt * 1e3)
|
|
281
|
+
throw new Error("RENDER_READ_DENIED");
|
|
282
|
+
url.searchParams.delete("debug");
|
|
283
|
+
url.searchParams.delete("noCache");
|
|
284
|
+
const response = await fetchRead(url.toString(), {
|
|
285
|
+
method: "GET",
|
|
286
|
+
credentials: "omit",
|
|
287
|
+
cache: "no-store",
|
|
288
|
+
redirect: "error",
|
|
289
|
+
referrerPolicy: "no-referrer",
|
|
290
|
+
signal: config.signal,
|
|
291
|
+
headers: {
|
|
292
|
+
Authorization: `Bearer ${bootstrap.authToken}`,
|
|
293
|
+
jwtSource: "internal_requests",
|
|
294
|
+
Accept: "application/json"
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
if (!response.ok) throw new Error("RENDER_READ_FAILED");
|
|
298
|
+
const data = await response.json();
|
|
299
|
+
return { data, status: response.status, statusText: "OK", config: {}, headers: {} };
|
|
300
|
+
} catch {
|
|
301
|
+
readiness.fail("WIDGET_HYDRATION_FAILED");
|
|
302
|
+
throw { message: "Widget hydration failed", response: { status: 0, data: { error: "Widget hydration failed" } } };
|
|
303
|
+
} finally {
|
|
304
|
+
finish();
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
return () => {
|
|
308
|
+
axios.defaults.adapter = originalAdapter;
|
|
309
|
+
window.fetch = originalFetch;
|
|
310
|
+
};
|
|
311
|
+
};
|
|
312
|
+
export {
|
|
313
|
+
W as WIDGET_IMAGE_READINESS_GLOBAL_NAME,
|
|
314
|
+
WidgetImageCaptureBoundary,
|
|
315
|
+
WidgetImageLiveHydrationContext,
|
|
316
|
+
WidgetImageReadinessContext,
|
|
317
|
+
WidgetImageRender,
|
|
318
|
+
WidgetImageRenderContext,
|
|
319
|
+
createWidgetImageReadiness,
|
|
320
|
+
followWidgetHydrationReadiness,
|
|
321
|
+
installFrozenWidgetRequests,
|
|
322
|
+
installLiveWidgetRequests,
|
|
323
|
+
isGoogleMapCapture,
|
|
324
|
+
publishWidgetImageReadiness,
|
|
325
|
+
w as readComposedViewDataTimes,
|
|
326
|
+
b1 as readFrozenHydration,
|
|
327
|
+
readWidgetImageReadiness,
|
|
328
|
+
a as readWidgetImageReadinessGlobalNames,
|
|
329
|
+
registerStaticWidgetImageComponents,
|
|
330
|
+
staticWidgetImageComponents,
|
|
331
|
+
b2 as useWidgetImageLiveHydration,
|
|
332
|
+
b3 as useWidgetImageRender
|
|
333
|
+
};
|
|
334
|
+
//# sourceMappingURL=image-render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-render.js","sources":["../src/image-render/WidgetImageRender.tsx","../src/image-render/widget-image-readiness.ts","../src/image-render/frozen-widget-requests.ts","../src/image-render/widget-image-google-map.ts","../src/image-render/live-widget-requests.ts"],"sourcesContent":["import React, { useEffect, useRef } from \"react\";\nimport { conversationWidgetRegistry } from \"../renderer/conversationWidgetRegistry\";\nimport { resolveWidgetName } from \"../renderer/widget-name-resolver\";\nimport { buildWidgetAgentSpaceKeyProps } from \"../renderer/_agent-space/widget-agent-space-key-attribute\";\nimport { ReadOnlyConversationWidgetProvider } from \"../renderer/ConversationWidgetContext\";\nimport { ConversationWidgetRenderContext } from \"../renderer/ConversationWidgetRenderContext\";\nimport {\n WidgetImageRenderContext,\n WidgetImageLiveHydrationContext,\n WidgetImageReadinessContext,\n} from \"./WidgetImageRenderContext\";\nimport type { WidgetImageRenderBootstrap } from \"./widget-image-render.types\";\nimport type { createWidgetImageReadiness } from \"./widget-image-readiness\";\nimport styles from \"./WidgetImageRender.module.scss\";\n\n/**\n * Capture-only components by wire name: a frozen render shows the widget's visual from its complete snapshot, without\n * mounting the live fetch / OAuth / polling wrappers. An app adds its own with `registerStaticWidgetImageComponents`.\n */\nexport const staticWidgetImageComponents: Record<string, React.ComponentType<Record<string, unknown>>> = {};\n\n/** Adds an app's capture-only components (wire name → component). Runs outside React, before the first render. */\nexport const registerStaticWidgetImageComponents = (\n components: Readonly<Record<string, React.ComponentType<Record<string, unknown>>>>,\n): void => {\n Object.assign(staticWidgetImageComponents, components);\n};\n\ntype Readiness = ReturnType<typeof createWidgetImageReadiness>;\ntype HostProps = { bootstrap: WidgetImageRenderBootstrap; readiness: Readiness };\n\n// React error boundaries require a class. Never log customer payloads or send telemetry from capture.\nexport class WidgetImageCaptureBoundary extends React.Component<\n { children: React.ReactNode; fail: Readiness[\"fail\"] },\n { failed: boolean }\n> {\n state = { failed: false };\n static getDerivedStateFromError() {\n return { failed: true };\n }\n componentDidCatch() {\n this.props.fail(\"WIDGET_RENDER_FAILED\");\n }\n render() {\n return this.state.failed ? null : this.props.children;\n }\n}\n\n/**\n * The static image render of one widget (the e-mail capture): the registered widget in its e-mail presentation, inside\n * the read-only widget context, with the capture's frozen or live hydration. A frozen render takes the widget's static\n * capture component when the app registered one (`registerStaticWidgetImageComponents`). The app mounts it inside its\n * own store and theme (`WidgetImageCaptureBoundary` around it).\n */\nexport const WidgetImageRender = (props: HostProps) => {\n const { bootstrap, readiness } = props;\n const ref = useRef<HTMLDivElement>(null);\n const name = resolveWidgetName(bootstrap.input.widgetName);\n const entry = conversationWidgetRegistry.widgets.find((widget) => widget.name === name);\n useEffect(() => {\n if (!entry) readiness.fail(\"UNKNOWN_WIDGET\");\n else if (ref.current) return readiness.observe(ref.current);\n }, [entry, readiness]);\n if (!entry) return null;\n const Component =\n bootstrap.input.mode === \"live\" ? entry.component : (staticWidgetImageComponents[name ?? \"\"] ?? entry.component);\n return (\n <div ref={ref} className={styles.root} inert>\n <ConversationWidgetRenderContext.Provider value=\"email\">\n <WidgetImageReadinessContext.Provider value={readiness}>\n <ReadOnlyConversationWidgetProvider agentSpaceKey={bootstrap.siteId}>\n <WidgetImageRenderContext.Provider value={bootstrap.input.hydration}>\n <WidgetImageLiveHydrationContext.Provider value={bootstrap.input.mode === \"live\"}>\n <Component\n {...bootstrap.input.props}\n {...buildWidgetAgentSpaceKeyProps(bootstrap.siteId)}\n interactive={false}\n fresh={false}\n justDelivered={false}\n openedByPage={false}\n />\n </WidgetImageLiveHydrationContext.Provider>\n </WidgetImageRenderContext.Provider>\n </ReadOnlyConversationWidgetProvider>\n </WidgetImageReadinessContext.Provider>\n </ConversationWidgetRenderContext.Provider>\n </div>\n );\n};\n\n/** The slice the capture reads its hydration state from; any store that carries it (the capture's, a spec's). */\ninterface StoreWithWidgetHydration {\n getState: () => { AIExtensionsWidgetHydration: { widgets: Record<string, { status: string }> } };\n subscribe: (listener: () => void) => () => void;\n}\n\n/**\n * Holds the capture's readiness open while any widget hydration is idle or loading, and fails it on a hydration error.\n * Every shared hydrator counts — a widget's own, and each `$source` binding of a `ComposedView` tree, which reads through\n * the same slice (`ComposedViewDataSource:<name>`), so the shot waits for the tree's mail-time rows.\n */\nexport const followWidgetHydrationReadiness = (store: StoreWithWidgetHydration, readiness: Readiness) =>\n store.subscribe(() => {\n const widgets = Object.values(store.getState().AIExtensionsWidgetHydration.widgets);\n if (widgets.some((widget) => widget.status === \"error\")) readiness.fail(\"WIDGET_HYDRATION_FAILED\");\n readiness.setHydrationPending(widgets.some((widget) => widget.status === \"loading\" || widget.status === \"idle\"));\n });\n","import { publishWidgetImageReadiness, readWidgetImageReadiness } from \"./widget-image-readiness-signal\";\nimport type { WidgetImageRenderBootstrap, WidgetImageReadiness } from \"./widget-image-render.types\";\n\nconst MAX_TIMER_DELAY_MS = 2 ** 31 - 1;\n\nexport const createWidgetImageReadiness = (bootstrap: WidgetImageRenderBootstrap) => {\n let failed = readWidgetImageReadiness()?.state === \"failed\";\n let requestsPending = 0;\n let hydrationPending = false;\n let notifyChanged = () => {};\n let observed: HTMLElement | null = null;\n const identity = {\n version: 1 as const,\n snapshot_id: bootstrap.snapshotId,\n attempt_id: bootstrap.attemptId,\n input_sha256: bootstrap.inputSha256,\n render_version: bootstrap.renderVersion,\n };\n const publish = (state: WidgetImageReadiness[\"state\"], extra: Partial<WidgetImageReadiness> = {}) => {\n publishWidgetImageReadiness({ ...identity, state, ...extra });\n // Mirror outside the observed widget subtree for browser checks without changing screenshot pixels.\n document.documentElement.dataset.widgetImageState = state;\n document.documentElement.dataset.widgetImageError = extra.error_code ?? \"\";\n };\n if (!failed) publish(\"loading\");\n const measure = (element: HTMLElement) => {\n const { x, y, width, height } = element.getBoundingClientRect();\n return { x, y, width, height };\n };\n // A failed state still reports the widget box so the renderer can capture it when the caller suppresses errors.\n const fail = (code: string) => {\n if (failed || readWidgetImageReadiness()?.state === \"failed\") return;\n failed = true;\n const rect = observed ? measure(observed) : undefined;\n publish(\"failed\", rect && rect.width > 0 && rect.height > 0 ? { error_code: code, rect } : { error_code: code });\n };\n const isFailed = () => failed || readWidgetImageReadiness()?.state === \"failed\";\n const frame = () => new Promise<void>((resolve) => requestAnimationFrame(() => resolve()));\n\n const ready = async (element: HTMLElement, isCurrent: () => boolean = () => true) => {\n observed = element;\n try {\n // Effects and their state updates must commit before inspecting the final content.\n await frame();\n await frame();\n await document.fonts.ready;\n document.fonts.forEach((font) => {\n if (font.status === \"error\") throw new Error(\"FONT_FAILED\");\n });\n const images = Array.from(element.querySelectorAll(\"img\"));\n await Promise.all(\n images.map(async (img) => {\n // Empty decorative image slots have nothing to download or decode.\n if (!img.currentSrc && !img.getAttribute(\"src\") && !img.getAttribute(\"srcset\") && img.alt === \"\") return;\n if (img.loading !== \"eager\") img.loading = \"eager\";\n await img.decode();\n if (!img.naturalWidth) throw new Error(\"ASSET_FAILED\");\n }),\n );\n await frame();\n await frame();\n if (isFailed() || !isCurrent()) return;\n if (requestsPending > 0 || hydrationPending) return;\n if (Date.now() >= bootstrap.expiresAt * 1000) return fail(\"TOKEN_EXPIRED\");\n // Determinate bars visualize scores too; only indeterminate bars imply loading.\n if (\n element.querySelector(\n '[aria-busy=\"true\"], [role=\"progressbar\"]:not([aria-valuenow]), [class*=\"Skeleton\"], [class*=\"skeleton\"]',\n )\n ) {\n if (bootstrap.input.mode === \"live\") return;\n return fail(\"WIDGET_STILL_LOADING\");\n }\n const rect = element.getBoundingClientRect();\n const width = bootstrap.input.width ?? 528;\n const maxHeight = bootstrap.input.maxHeight ?? 1200;\n if (!element.textContent?.trim() && !element.querySelector(\"img,svg,canvas\")) return fail(\"EMPTY_WIDGET\");\n if (\n rect.width <= 0 ||\n rect.height <= 0 ||\n rect.width > width + 1 ||\n rect.height > maxHeight ||\n rect.x < 0 ||\n rect.y < 0 ||\n element.scrollWidth > Math.ceil(rect.width) ||\n element.scrollHeight > Math.ceil(rect.height)\n ) {\n return fail(\"WIDGET_BOUNDS_EXCEEDED\");\n }\n // The capture viewport may be smaller than the widget; the renderer sizes its viewport/clip from this rect.\n publish(\"ready\", { rect: measure(element) });\n } catch {\n if (isCurrent()) fail(\"REQUIRED_ASSET_FAILED\");\n }\n };\n const observe = (element: HTMLElement) => {\n observed = element;\n let revision = 0;\n let timer: ReturnType<typeof setTimeout>;\n let disposed = false;\n const changed = () => {\n if (disposed || isFailed()) return;\n revision += 1;\n const expected = revision;\n publish(\"loading\");\n clearTimeout(timer);\n // Frozen hydrators resolve synchronously; legacy frozen GET effects and chart layout may commit later.\n timer = setTimeout(() => void ready(element, () => !disposed && expected === revision), 250);\n };\n const observer = new MutationObserver(changed);\n notifyChanged = changed;\n observer.observe(element, { childList: true, subtree: true, attributes: true, characterData: true });\n const resize = new ResizeObserver(changed);\n resize.observe(element);\n changed();\n const remaining = bootstrap.expiresAt * 1000 - Date.now();\n // Browsers fire delays above 2^31-1 ms immediately; long-lived URLs cannot expire within the render deadline.\n const expiry =\n remaining <= MAX_TIMER_DELAY_MS ? setTimeout(() => fail(\"TOKEN_EXPIRED\"), Math.max(0, remaining)) : undefined;\n const deadline = setTimeout(() => {\n if (readWidgetImageReadiness()?.state !== \"ready\") fail(\"RENDER_DEADLINE_EXCEEDED\");\n }, 60000);\n return () => {\n disposed = true;\n observer.disconnect();\n resize.disconnect();\n clearTimeout(timer);\n if (expiry !== undefined) clearTimeout(expiry);\n clearTimeout(deadline);\n notifyChanged = () => {};\n };\n };\n const beginRequest = () => {\n requestsPending += 1;\n if (!isFailed()) publish(\"loading\");\n notifyChanged();\n return () => {\n requestsPending -= 1;\n notifyChanged();\n };\n };\n const setHydrationPending = (pending: boolean) => {\n if (hydrationPending === pending) return;\n hydrationPending = pending;\n if (!isFailed()) publish(\"loading\");\n notifyChanged();\n };\n return { ready, observe, fail, isFailed, beginRequest, setHydrationPending };\n};\n","import axios, { AxiosRequestConfig } from \"axios\";\n\n/** The capture page serves supplied GET results in memory. It never lends the render token to the SDK. */\nexport const installFrozenWidgetRequests = (responses: Record<string, unknown>, fail: (code: string) => void) => {\n const originalAdapter = axios.defaults.adapter;\n axios.defaults.adapter = async (config: AxiosRequestConfig) => {\n const url = new URL(axios.getUri(config), window.location.origin);\n url.searchParams.sort();\n const key = `${(config.method ?? \"get\").toUpperCase()} ${url.pathname}${url.search}`;\n if ((config.method ?? \"get\").toLowerCase() !== \"get\" || !Object.prototype.hasOwnProperty.call(responses, key)) {\n fail(\"MISSING_FROZEN_RESPONSE\");\n throw new Error(\"MISSING_FROZEN_RESPONSE\");\n }\n return { data: structuredClone(responses[key]), status: 200, statusText: \"OK\", config, headers: {} };\n };\n return () => {\n axios.defaults.adapter = originalAdapter;\n };\n};\n","import { getGoogleMapWidgetNames } from \"../provider/environment\";\n\n/** The deepest tree the walk follows — the backend decodes a block with the same depth (`json_decode(…, 32)`). */\nconst MAX_TREE_DEPTH = 32;\n\nconst isMapNodeInValue = (value: unknown, depth: number, googleMapWidgetNames: readonly string[]): boolean => {\n if (depth > MAX_TREE_DEPTH || typeof value !== \"object\" || value === null) return false;\n if (Array.isArray(value)) return value.some((element) => isMapNodeInValue(element, depth + 1, googleMapWidgetNames));\n const wireObject = value as Record<string, unknown>;\n if (wireObject.type === \"Map\") return true;\n if (wireObject.type === \"Widget\" && typeof wireObject.widget === \"string\") {\n const embeddedWidgetName = wireObject.widget.replace(/Directive$/, \"\");\n if (googleMapWidgetNames.includes(embeddedWidgetName)) return true;\n }\n return Object.values(wireObject).some((nested) => isMapNodeInValue(nested, depth + 1, googleMapWidgetNames));\n};\n\n/**\n * Whether a capture renders a Google map and so may load the Maps SDK (the narrow CSP and transport exception).\n * The twin of the backend's check that opens the page's CSP: the app's map widgets themselves\n * (`AgentsEnvironment.googleMapWidgetNames`), and a `ComposedView` whose tree holds a `Map` node or embeds one of them.\n * The payload is read as written; a payload that does not parse renders no map.\n */\nexport const isGoogleMapCapture = (widgetName: string, props: Record<string, unknown>): boolean => {\n const googleMapWidgetNames = getGoogleMapWidgetNames();\n if (googleMapWidgetNames.includes(widgetName)) return true;\n if (widgetName !== \"ComposedView\" || typeof props.payload !== \"string\") return false;\n try {\n return isMapNodeInValue((JSON.parse(props.payload) as Record<string, unknown>)?.view, 0, googleMapWidgetNames);\n } catch {\n return false;\n }\n};\n","import axios, { AxiosRequestConfig } from \"axios\";\nimport type { WidgetImageRenderBootstrap } from \"./widget-image-render.types\";\nimport type { createWidgetImageReadiness } from \"./widget-image-readiness\";\nimport { isGoogleMapCapture } from \"./widget-image-google-map\";\nimport { getWidgetImageCaptureReadPathPrefix } from \"../provider/environment\";\n\nconst STATIC_ASSET_PATH =\n /^\\/react\\/(?:app-build|widget-image-build)\\/assets\\/(?:[\\w-]+\\/)*[\\w.-]+\\.(?:svg|png|jpe?g|webp|gif)$/;\n\n/** Loaded only by the capture entry. SDK signatures stay unchanged; no ambient credentials are sent. */\nexport const installLiveWidgetRequests = (\n bootstrap: WidgetImageRenderBootstrap,\n readiness: ReturnType<typeof createWidgetImageReadiness>,\n) => {\n const originalAdapter = axios.defaults.adapter;\n const originalFetch = window.fetch;\n const fetchRead = originalFetch.bind(window);\n // Captured widgets may import shared telemetry/helpers. They cannot bypass the scoped adapter. Two reads pass:\n // static bundle images (useDynamicImport fetches icons such as review-source logos) and, for map captures only,\n // the Google Maps SDK (a map widget, or a ComposedView tree holding a map).\n window.fetch = async (input, init) => {\n const request = new Request(typeof input === \"string\" ? new URL(input, window.location.origin).href : input, init);\n const url = new URL(request.url, window.location.origin);\n const unavailable = readiness.isFailed() || Date.now() >= bootstrap.expiresAt * 1000;\n const isStaticAsset =\n url.origin === window.location.origin &&\n STATIC_ASSET_PATH.test(url.pathname) &&\n url.search === \"\" &&\n request.method === \"GET\";\n if (isStaticAsset && !unavailable) {\n const finish = readiness.beginRequest();\n try {\n return await fetchRead(url.toString(), {\n credentials: \"omit\",\n redirect: \"error\",\n referrerPolicy: \"no-referrer\",\n });\n } finally {\n finish();\n }\n }\n const isMap = isGoogleMapCapture(bootstrap.input.widgetName, bootstrap.input.props);\n const isGoogleMapRequest =\n url.protocol === \"https:\" &&\n ((url.hostname === \"maps.googleapis.com\" &&\n (url.pathname.startsWith(\"/maps/\") || url.pathname.startsWith(\"/$rpc/\"))) ||\n (url.hostname === \"maps.gstatic.com\" && url.pathname.startsWith(\"/mapfiles/\")));\n if (!isMap || !isGoogleMapRequest || ![\"GET\", \"POST\"].includes(request.method) || unavailable) {\n readiness.fail(\"UNSCOPED_REQUEST\");\n throw new Error(\"Unscoped render request\");\n }\n const headers = new Headers();\n for (const name of [\"content-type\", \"x-goog-api-key\", \"x-goog-api-client\", \"x-user-agent\"]) {\n const value = request.headers.get(name);\n if (value) headers.set(name, value);\n }\n const finish = readiness.beginRequest();\n try {\n const response = await fetchRead(request, {\n credentials: \"omit\",\n referrerPolicy: \"no-referrer\",\n redirect: \"error\",\n headers,\n });\n if (!response.ok) throw new Error(\"Map request failed\");\n return response;\n } catch {\n readiness.fail(\"MAP_ASSET_FAILED\");\n throw new Error(\"Map request failed\");\n } finally {\n finish();\n }\n };\n axios.defaults.adapter = async (config: AxiosRequestConfig) => {\n const finish = readiness.beginRequest();\n try {\n const url = new URL(axios.getUri(config), window.location.origin);\n if (\n !bootstrap.authToken ||\n url.origin !== window.location.origin ||\n !url.pathname.startsWith(getWidgetImageCaptureReadPathPrefix()) ||\n (config.method ?? \"get\").toLowerCase() !== \"get\" ||\n config.data !== undefined ||\n readiness.isFailed() ||\n Date.now() >= bootstrap.expiresAt * 1000\n )\n throw new Error(\"RENDER_READ_DENIED\");\n // The ordinary helper propagates debug/noCache from the page; capture requests never do.\n url.searchParams.delete(\"debug\");\n url.searchParams.delete(\"noCache\");\n const response = await fetchRead(url.toString(), {\n method: \"GET\",\n credentials: \"omit\",\n cache: \"no-store\",\n redirect: \"error\",\n referrerPolicy: \"no-referrer\",\n signal: config.signal as AbortSignal | undefined,\n headers: {\n Authorization: `Bearer ${bootstrap.authToken}`,\n jwtSource: \"internal_requests\",\n Accept: \"application/json\",\n },\n });\n if (!response.ok) throw new Error(\"RENDER_READ_FAILED\");\n const data = await response.json();\n return { data, status: response.status, statusText: \"OK\", config: {}, headers: {} };\n } catch {\n readiness.fail(\"WIDGET_HYDRATION_FAILED\");\n // HttpStore logs errors and submits telemetry for status 500. Never expose the URL,\n // request headers, auth token or remote exception body to those shared interceptors.\n throw { message: \"Widget hydration failed\", response: { status: 0, data: { error: \"Widget hydration failed\" } } };\n } finally {\n finish();\n }\n };\n return () => {\n axios.defaults.adapter = originalAdapter;\n window.fetch = originalFetch;\n };\n};\n"],"names":["finish"],"mappings":"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"}
|