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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/chat.js +71 -827
  2. package/dist/chat.js.map +1 -1
  3. package/dist/chunks/ConversationMessageInputComposerWidgets-BxyaFBA6.js +631 -0
  4. package/dist/chunks/ConversationMessageInputComposerWidgets-BxyaFBA6.js.map +1 -0
  5. package/dist/chunks/{WebSearchResultsConversationWidget-DRBQvycE.js → WebSearchResultsConversationWidget-as3p5bHw.js} +92 -85
  6. package/dist/chunks/WebSearchResultsConversationWidget-as3p5bHw.js.map +1 -0
  7. package/dist/chunks/{decide-canvas-open-DBWoWtAC.js → canvas-behaviours-AvzKSYyv.js} +3 -19
  8. package/dist/chunks/canvas-behaviours-AvzKSYyv.js.map +1 -0
  9. package/dist/chunks/canvas-reducers-Bfp_i7lc.js +88 -0
  10. package/dist/chunks/canvas-reducers-Bfp_i7lc.js.map +1 -0
  11. package/dist/chunks/{canvasBodies-DLjDkviP.js → canvasBodies-Cvu3l38p.js} +6 -3
  12. package/dist/chunks/{canvasBodies-DLjDkviP.js.map → canvasBodies-Cvu3l38p.js.map} +1 -1
  13. package/dist/chunks/canvasStorage-EvQsGdto.js +65 -0
  14. package/dist/chunks/canvasStorage-EvQsGdto.js.map +1 -0
  15. package/dist/chunks/contract-BxmMxYPF.js +96 -0
  16. package/dist/chunks/contract-BxmMxYPF.js.map +1 -0
  17. package/dist/chunks/conversation-BEF0aesf.js +31 -0
  18. package/dist/chunks/conversation-BEF0aesf.js.map +1 -0
  19. package/dist/chunks/{ConversationMarkdown-CJhAnuVa.js → widget-click-signal-sources-DulRkNvZ.js} +22 -77
  20. package/dist/chunks/widget-click-signal-sources-DulRkNvZ.js.map +1 -0
  21. package/dist/chunks/{widget-name-resolver-C8SfpiR5.js → widget-name-resolver-BGN3HpoG.js} +61 -30
  22. package/dist/chunks/widget-name-resolver-BGN3HpoG.js.map +1 -0
  23. package/dist/chunks/{withPollingChangeSubscription-BLDAWF-o.js → withPollingChangeSubscription-B16htQGd.js} +2 -2
  24. package/dist/chunks/{withPollingChangeSubscription-BLDAWF-o.js.map → withPollingChangeSubscription-B16htQGd.js.map} +1 -1
  25. package/dist/client-testing.js +28 -6
  26. package/dist/client-testing.js.map +1 -1
  27. package/dist/client.js +1 -1
  28. package/dist/contract.js +8 -27
  29. package/dist/contract.js.map +1 -1
  30. package/dist/image-render.js +8 -8
  31. package/dist/index.js +6 -5
  32. package/dist/kit.js +2 -2
  33. package/dist/preview.js +44 -16
  34. package/dist/preview.js.map +1 -1
  35. package/dist/renderer.js +62 -57
  36. package/dist/renderer.js.map +1 -1
  37. package/dist/styles.css +55 -22
  38. package/dist/types/client/testing/widget-hydration-stand-ins.d.ts +12 -3
  39. package/dist/types/entries/chat.d.ts +2 -0
  40. package/dist/types/entries/client-testing.d.ts +2 -0
  41. package/dist/types/entries/contract.d.ts +1 -0
  42. package/dist/types/entries/index.d.ts +1 -1
  43. package/dist/types/entries/preview.d.ts +1 -0
  44. package/dist/types/entries/renderer.d.ts +3 -1
  45. package/dist/types/kit/components/data/chart-model.d.ts +2 -2
  46. package/dist/types/kit/components/data/use-chart-palette.d.ts +2 -2
  47. package/dist/types/kit/components/map/use-google-maps-auth-failure.d.ts +18 -0
  48. package/dist/types/kit/entity-detail/entity-detail-bodies.d.ts +2 -0
  49. package/dist/types/renderer/canvas/entity-detail-instance.d.ts +5 -3
  50. package/dist/types/renderer/widget-hydration/use-widget-hydration.d.ts +5 -0
  51. package/dist/types/widgets/EntityMentionConversationWidget/stories/EntityMentionAskFlowStory.d.ts +8 -0
  52. package/dist/widgets.js +33 -33
  53. package/package.json +1 -1
  54. package/public-api.json +19 -1
  55. package/dist/chunks/ConversationMarkdown-CJhAnuVa.js.map +0 -1
  56. package/dist/chunks/WebSearchResultsConversationWidget-DRBQvycE.js.map +0 -1
  57. package/dist/chunks/decide-canvas-open-DBWoWtAC.js.map +0 -1
  58. package/dist/chunks/widget-name-resolver-C8SfpiR5.js.map +0 -1
@@ -0,0 +1,631 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { useCallback, useSyncExternalStore, useContext, createContext, useMemo, useState, useRef, useEffect } from "react";
4
+ import { a3 as useAgentsEnvironment, a6 as useAgentsStateDispatch, a7 as useAgentsStateSelector, z as classNames } from "./index-7Qc_3GbG.js";
5
+ import { e as applySetCanvasCreatedEntityId, a as applyClearCanvas, d as applyResetCanvasForNewTurn, b as applyCloseCanvas, c as applyOpenCanvas } from "./canvas-reducers-Bfp_i7lc.js";
6
+ import { T as CANVAS_VIABLE_MIN_WIDTH, h as ConversationWidgetContext, E as useConversationWidgetContext } from "./WebSearchResultsConversationWidget-as3p5bHw.js";
7
+ import { s as storeOpenCanvas, c as clearStoredCanvas } from "./canvasStorage-EvQsGdto.js";
8
+ import { j as conversationWidgetRegistry } from "./widget-name-resolver-BGN3HpoG.js";
9
+ const EMPTY_AGENTS_CHAT_OPENING_REQUEST = {
10
+ userMessage: null,
11
+ startSignalText: null,
12
+ entryPointKey: null,
13
+ deepLinkedWidgetName: null
14
+ };
15
+ const INITIAL_AGENTS_CHAT_STATE = {
16
+ conversation: null,
17
+ messages: null,
18
+ conversationLoading: false,
19
+ conversationLoaded: false,
20
+ hasMoreOlder: false,
21
+ aiThinking: false,
22
+ error: null,
23
+ rateLimitRetryAfterSeconds: null,
24
+ requestedConversationId: null,
25
+ startingNewConversation: false,
26
+ pendingStartToken: null,
27
+ startTokenCount: 0,
28
+ openingRequest: EMPTY_AGENTS_CHAT_OPENING_REQUEST,
29
+ canvas: null,
30
+ lastClosedCanvas: null,
31
+ canvasMountCount: 0
32
+ };
33
+ const ConversationErrorType = {
34
+ AI_BUDGET: "AI_BUDGET",
35
+ /**
36
+ * HTTP 429 from an AI endpoint — a per-minute/hour/day usage quota was hit. Distinct from AI_BUDGET (monthly budget):
37
+ * this one clears on its own after the Retry-After window.
38
+ */
39
+ RATE_LIMIT: "RATE_LIMIT",
40
+ NETWORK_ERROR: "NETWORK_ERROR",
41
+ CONVERSATION_NOT_FOUND: "CONVERSATION_NOT_FOUND",
42
+ /**
43
+ * The backend run FAILED (e.g. the model provider returned an error). The raw provider error is admin-only (never
44
+ * shown here); the owner gets a generic "something went wrong" card.
45
+ */
46
+ AGENT_ERROR: "AGENT_ERROR",
47
+ /**
48
+ * The conversation is COMPLETED/CANCELLED and refuses further owner input. Set from the server's stable error code
49
+ * `CONVERSATION_CLOSED` or by the chat's own pre-send guard; the error card owns the copy.
50
+ */
51
+ CONVERSATION_CLOSED: "CONVERSATION_CLOSED"
52
+ };
53
+ const readConversationErrorTypeOfRefusedSend = (error) => {
54
+ if (error.kind === "budget") return ConversationErrorType.AI_BUDGET;
55
+ if (error.kind === "rateLimit") return ConversationErrorType.RATE_LIMIT;
56
+ if (error.kind === "closed") return ConversationErrorType.CONVERSATION_CLOSED;
57
+ return ConversationErrorType.NETWORK_ERROR;
58
+ };
59
+ const mergeChatMessagesByIndex = (existing, incoming) => {
60
+ const messagesByIndex = /* @__PURE__ */ new Map();
61
+ const messagesWithoutIndex = [];
62
+ const collectMessage = (message) => {
63
+ if (message.indexInConversation != null) {
64
+ messagesByIndex.set(message.indexInConversation, message);
65
+ } else {
66
+ messagesWithoutIndex.push(message);
67
+ }
68
+ };
69
+ existing.forEach(collectMessage);
70
+ incoming.forEach(collectMessage);
71
+ const indexedMessages = Array.from(messagesByIndex.values()).sort(
72
+ (first, second) => (first.indexInConversation ?? 0) - (second.indexInConversation ?? 0)
73
+ );
74
+ return [...indexedMessages, ...messagesWithoutIndex];
75
+ };
76
+ const tagFreshChatMessages = (incoming, previousMessages) => {
77
+ const previousIds = new Set(previousMessages.map((message) => message.id).filter((id) => id != null));
78
+ return incoming.map((message) => ({ ...message, fresh: message.id != null && !previousIds.has(message.id) }));
79
+ };
80
+ const mergeMessagesPage = (loadedMessages, page, requestedConversationId) => {
81
+ const shownConversationId = loadedMessages?.find((message) => message.conversationId != null)?.conversationId;
82
+ const replacesShownConversation = shownConversationId != null && shownConversationId !== requestedConversationId;
83
+ const existingMessages = replacesShownConversation ? [] : loadedMessages ?? [];
84
+ const messagesByIndex = /* @__PURE__ */ new Map();
85
+ for (const existingMessage of existingMessages) {
86
+ if (existingMessage.indexInConversation != null) {
87
+ messagesByIndex.set(existingMessage.indexInConversation, existingMessage);
88
+ }
89
+ }
90
+ const hadMessagesBeforeMerge = existingMessages.length > 0;
91
+ const highestShownIndex = Math.max(-1, ...existingMessages.map((message) => message.indexInConversation ?? -1));
92
+ for (const incomingMessage of page) {
93
+ if (incomingMessage.indexInConversation == null) continue;
94
+ const previousMessage = messagesByIndex.get(incomingMessage.indexInConversation);
95
+ const isLiveArrival = hadMessagesBeforeMerge && previousMessage == null && incomingMessage.indexInConversation > highestShownIndex;
96
+ messagesByIndex.set(incomingMessage.indexInConversation, {
97
+ ...incomingMessage,
98
+ fresh: previousMessage?.fresh ?? isLiveArrival
99
+ });
100
+ }
101
+ return Array.from(messagesByIndex.values()).sort(
102
+ (first, second) => (first.indexInConversation ?? 0) - (second.indexInConversation ?? 0)
103
+ );
104
+ };
105
+ const withRefusedSendError = (state, error) => {
106
+ const conversationErrorType = readConversationErrorTypeOfRefusedSend(error);
107
+ return {
108
+ ...state,
109
+ error: conversationErrorType,
110
+ rateLimitRetryAfterSeconds: conversationErrorType === ConversationErrorType.RATE_LIMIT ? error.retryAfterSeconds ?? null : null
111
+ };
112
+ };
113
+ const mergeSendAnswer = (loadedMessages, answerMessages) => {
114
+ const messagesWithoutOptimisticMessage = loadedMessages ? loadedMessages.slice(0, loadedMessages.length - 1) : [];
115
+ return mergeChatMessagesByIndex(
116
+ messagesWithoutOptimisticMessage,
117
+ tagFreshChatMessages(answerMessages, messagesWithoutOptimisticMessage)
118
+ );
119
+ };
120
+ const withCanvasTransition = (state, applyCanvasTransition) => {
121
+ const nextState = { ...state };
122
+ applyCanvasTransition(nextState);
123
+ const changed = nextState.canvas !== state.canvas || nextState.lastClosedCanvas !== state.lastClosedCanvas || nextState.canvasMountCount !== state.canvasMountCount;
124
+ return changed ? nextState : state;
125
+ };
126
+ const reduceAgentsChatState = (state, event) => {
127
+ switch (event.type) {
128
+ case "reset":
129
+ return {
130
+ ...INITIAL_AGENTS_CHAT_STATE,
131
+ openingRequest: state.openingRequest,
132
+ canvasMountCount: state.canvasMountCount,
133
+ startTokenCount: state.startTokenCount
134
+ };
135
+ case "conversationMetadataRequested":
136
+ case "messagesPageRequested":
137
+ return state.requestedConversationId === event.conversationId ? state : { ...state, requestedConversationId: event.conversationId };
138
+ case "conversationMetadataReceived":
139
+ if (state.requestedConversationId === null || state.requestedConversationId !== event.conversationId) {
140
+ return state;
141
+ }
142
+ return { ...state, conversation: event.conversation, conversationLoaded: true };
143
+ case "conversationMetadataFailed":
144
+ return { ...state, conversationLoaded: true };
145
+ case "messagesPageReceived": {
146
+ if (state.requestedConversationId === null || state.requestedConversationId !== event.conversationId) {
147
+ return state;
148
+ }
149
+ if (state.conversation !== null && state.conversation.id !== event.conversationId) {
150
+ return state;
151
+ }
152
+ return {
153
+ ...state,
154
+ messages: mergeMessagesPage(state.messages, event.messages, event.conversationId),
155
+ hasMoreOlder: event.hasMoreOlder ?? state.hasMoreOlder,
156
+ conversationLoaded: true
157
+ };
158
+ }
159
+ case "messagePostRequested":
160
+ return {
161
+ ...state,
162
+ conversationLoading: true,
163
+ conversationLoaded: false,
164
+ aiThinking: true,
165
+ error: null,
166
+ rateLimitRetryAfterSeconds: null,
167
+ messages: [...state.messages ?? [], event.message]
168
+ };
169
+ case "messagePostReceived":
170
+ if (event.conversationId !== state.conversation?.id) {
171
+ return state;
172
+ }
173
+ return {
174
+ ...state,
175
+ messages: mergeSendAnswer(state.messages, event.posted.messages),
176
+ conversationLoading: false,
177
+ conversationLoaded: true,
178
+ error: null
179
+ };
180
+ case "messagePostFailed":
181
+ return withRefusedSendError(
182
+ { ...state, conversationLoading: false, conversationLoaded: true, aiThinking: false },
183
+ event.error
184
+ );
185
+ case "startRequested":
186
+ return {
187
+ ...state,
188
+ conversation: null,
189
+ conversationLoading: true,
190
+ conversationLoaded: false,
191
+ aiThinking: true,
192
+ error: null,
193
+ rateLimitRetryAfterSeconds: null,
194
+ startingNewConversation: true,
195
+ startTokenCount: state.startTokenCount + 1,
196
+ pendingStartToken: state.startTokenCount + 1,
197
+ // A signal-only start (an empty visible message carries the start signal) seeds no empty bubble.
198
+ messages: event.message.message ? [event.message] : []
199
+ };
200
+ case "startReceived": {
201
+ if (event.startToken !== state.pendingStartToken) {
202
+ return state;
203
+ }
204
+ const { started } = event;
205
+ if (started.reopenedExisting) {
206
+ return {
207
+ ...state,
208
+ conversation: started.conversation,
209
+ messages: [],
210
+ conversationLoading: false,
211
+ conversationLoaded: true,
212
+ aiThinking: false,
213
+ startingNewConversation: false,
214
+ pendingStartToken: null
215
+ };
216
+ }
217
+ return {
218
+ ...state,
219
+ conversation: started.conversation,
220
+ messages: mergeSendAnswer(state.messages, started.messages),
221
+ conversationLoading: false,
222
+ conversationLoaded: true,
223
+ startingNewConversation: false,
224
+ pendingStartToken: null
225
+ };
226
+ }
227
+ case "startFailed":
228
+ return withRefusedSendError(
229
+ {
230
+ ...state,
231
+ conversation: null,
232
+ conversationLoading: false,
233
+ conversationLoaded: true,
234
+ aiThinking: false,
235
+ startingNewConversation: false,
236
+ pendingStartToken: null
237
+ },
238
+ event.error
239
+ );
240
+ case "errorSet":
241
+ return state.error === event.error ? state : { ...state, error: event.error };
242
+ case "aiThinkingSet":
243
+ return state.aiThinking === event.aiThinking ? state : { ...state, aiThinking: event.aiThinking };
244
+ case "openingRequestSet":
245
+ return { ...state, openingRequest: { ...state.openingRequest, ...event.openingRequest } };
246
+ case "canvasOpened":
247
+ return withCanvasTransition(state, (nextState) => {
248
+ applyOpenCanvas(nextState, event.request);
249
+ });
250
+ case "canvasClosed":
251
+ return withCanvasTransition(state, (nextState) => applyCloseCanvas(nextState, event.byCustomer));
252
+ case "canvasResetForNewTurn":
253
+ return withCanvasTransition(state, applyResetCanvasForNewTurn);
254
+ case "canvasCleared":
255
+ return withCanvasTransition(state, applyClearCanvas);
256
+ case "canvasCreatedEntityIdSet":
257
+ return withCanvasTransition(state, (nextState) => {
258
+ applySetCanvasCreatedEntityId(nextState, event.created);
259
+ });
260
+ }
261
+ };
262
+ class AgentsChatStateContainer {
263
+ constructor(initialState = INITIAL_AGENTS_CHAT_STATE) {
264
+ this.listeners = /* @__PURE__ */ new Set();
265
+ this.getState = () => this.state;
266
+ this.subscribe = (listener) => {
267
+ this.listeners.add(listener);
268
+ return () => {
269
+ this.listeners.delete(listener);
270
+ };
271
+ };
272
+ this.dispatch = (event) => {
273
+ const nextState = reduceAgentsChatState(this.state, event);
274
+ if (nextState === this.state) return;
275
+ this.state = nextState;
276
+ for (const notifyListener of [...this.listeners]) notifyListener();
277
+ };
278
+ this.state = initialState;
279
+ }
280
+ }
281
+ const createAgentsChatStore = (initialState) => new AgentsChatStateContainer(initialState);
282
+ const AgentsChatStoreContext = createContext(null);
283
+ const AgentsChatStoreProvider = (props) => {
284
+ const { chatStore, children } = props;
285
+ return /* @__PURE__ */ jsx(AgentsChatStoreContext.Provider, { value: chatStore, children });
286
+ };
287
+ const useAgentsChatStore = () => {
288
+ const chatStore = useContext(AgentsChatStoreContext);
289
+ if (chatStore === null) {
290
+ throw new Error("A chat component rendered outside AgentsChatStoreProvider: the app has to mount its chat store.");
291
+ }
292
+ return chatStore;
293
+ };
294
+ const useOptionalAgentsChatStore = () => useContext(AgentsChatStoreContext);
295
+ const subscribeToNothing = () => () => void 0;
296
+ const useAgentsChatSelector = (chatStore, selector, valueWithoutStore) => {
297
+ const subscribe = chatStore ? chatStore.subscribe : subscribeToNothing;
298
+ const readSelectedValue = useCallback(
299
+ () => chatStore ? selector(chatStore.getState()) : valueWithoutStore,
300
+ [chatStore, selector, valueWithoutStore]
301
+ );
302
+ return useSyncExternalStore(subscribe, readSelectedValue, readSelectedValue);
303
+ };
304
+ const useAgentsChatState = (selector) => useAgentsChatSelector(useAgentsChatStore(), selector);
305
+ let agenticChatMountCount = 0;
306
+ const selectCanvas = (state) => state.canvas;
307
+ const selectLastClosedCanvas = (state) => state.lastClosedCanvas;
308
+ const selectAiThinking = (state) => state.aiThinking;
309
+ const selectRunState = (state) => state.conversation?.runState;
310
+ const selectMessages = (state) => state.messages;
311
+ const ChatStoreConversationWidgetProvider = (props) => {
312
+ const { chatStore, ...bodyProps } = props;
313
+ const canvas = useAgentsChatSelector(chatStore, selectCanvas);
314
+ const lastClosedCanvas = useAgentsChatSelector(chatStore, selectLastClosedCanvas);
315
+ const isConversationRunning = useAgentsChatSelector(chatStore, selectAiThinking);
316
+ const runState = useAgentsChatSelector(chatStore, selectRunState);
317
+ const messages = useAgentsChatSelector(chatStore, selectMessages);
318
+ const chatState = useMemo(
319
+ () => ({
320
+ canvas,
321
+ lastClosedCanvas,
322
+ isConversationRunning,
323
+ runState,
324
+ messages,
325
+ dispatchCanvasEvent: chatStore.dispatch
326
+ }),
327
+ [canvas, lastClosedCanvas, isConversationRunning, runState, messages, chatStore]
328
+ );
329
+ return /* @__PURE__ */ jsx(ConversationWidgetProviderBody, { ...bodyProps, chatState });
330
+ };
331
+ const SliceConversationWidgetProvider = (props) => {
332
+ const { sliceInstance, ...bodyProps } = props;
333
+ const dispatch = useAgentsStateDispatch();
334
+ const canvas = useAgentsStateSelector((state) => sliceInstance.selectState(state).canvas);
335
+ const lastClosedCanvas = useAgentsStateSelector((state) => sliceInstance.selectState(state).lastClosedCanvas);
336
+ const isConversationRunning = useAgentsStateSelector((state) => sliceInstance.selectState(state).aiThinking);
337
+ const runState = useAgentsStateSelector((state) => sliceInstance.selectState(state).conversation?.runState);
338
+ const messages = useAgentsStateSelector((state) => sliceInstance.selectState(state).messages);
339
+ const dispatchCanvasEvent = useCallback(
340
+ (event) => {
341
+ const { actions } = sliceInstance;
342
+ if (event.type === "canvasOpened") dispatch(actions.openCanvas(event.request));
343
+ else if (event.type === "canvasClosed") dispatch(actions.closeCanvas({ byCustomer: event.byCustomer }));
344
+ else if (event.type === "canvasResetForNewTurn") dispatch(actions.resetCanvasForNewTurn());
345
+ else if (event.type === "canvasCleared") dispatch(actions.clearCanvas());
346
+ else dispatch(actions.setCanvasCreatedEntityId(event.created));
347
+ },
348
+ [dispatch, sliceInstance]
349
+ );
350
+ const chatState = useMemo(
351
+ () => ({ canvas, lastClosedCanvas, isConversationRunning, runState, messages, dispatchCanvasEvent }),
352
+ [canvas, lastClosedCanvas, isConversationRunning, runState, messages, dispatchCanvasEvent]
353
+ );
354
+ return /* @__PURE__ */ jsx(ConversationWidgetProviderBody, { ...bodyProps, chatState });
355
+ };
356
+ const OwnChatStoreConversationWidgetProvider = (props) => {
357
+ const [ownChatStore] = useState(createAgentsChatStore);
358
+ return /* @__PURE__ */ jsx(ChatStoreConversationWidgetProvider, { ...props, chatStore: ownChatStore });
359
+ };
360
+ const ConversationWidgetProvider = (props) => {
361
+ const { sliceInstance, chatStore, ...bodyProps } = props;
362
+ const { defaultChatStatePartition } = useAgentsEnvironment();
363
+ const statePartition = sliceInstance ?? defaultChatStatePartition;
364
+ if (chatStore) return /* @__PURE__ */ jsx(ChatStoreConversationWidgetProvider, { ...bodyProps, chatStore });
365
+ if (statePartition) return /* @__PURE__ */ jsx(SliceConversationWidgetProvider, { ...bodyProps, sliceInstance: statePartition });
366
+ return /* @__PURE__ */ jsx(OwnChatStoreConversationWidgetProvider, { ...bodyProps });
367
+ };
368
+ const ConversationWidgetProviderBody = ({
369
+ children,
370
+ callbacks,
371
+ hostHasCanvasSurface = true,
372
+ chatState
373
+ }) => {
374
+ const dispatch = useAgentsStateDispatch();
375
+ const { buildChatSurfaceOpenChangedAction } = useAgentsEnvironment();
376
+ const { canvas, lastClosedCanvas, isConversationRunning, runState, messages } = chatState;
377
+ const isConversationClosed = runState === "COMPLETED" || runState === "CANCELLED";
378
+ const dispatchCanvasEventRef = useRef(chatState.dispatchCanvasEvent);
379
+ dispatchCanvasEventRef.current = chatState.dispatchCanvasEvent;
380
+ const hostHasCanvasSurfaceRef = useRef(hostHasCanvasSurface);
381
+ hostHasCanvasSurfaceRef.current = hostHasCanvasSurface;
382
+ const buildChatSurfaceOpenChangedActionRef = useRef(buildChatSurfaceOpenChangedAction);
383
+ buildChatSurfaceOpenChangedActionRef.current = buildChatSurfaceOpenChangedAction;
384
+ useEffect(() => {
385
+ agenticChatMountCount += 1;
386
+ if (agenticChatMountCount === 1 && buildChatSurfaceOpenChangedActionRef.current) {
387
+ dispatch(buildChatSurfaceOpenChangedActionRef.current(true));
388
+ }
389
+ return () => {
390
+ agenticChatMountCount -= 1;
391
+ if (agenticChatMountCount === 0 && buildChatSurfaceOpenChangedActionRef.current) {
392
+ dispatch(buildChatSurfaceOpenChangedActionRef.current(false));
393
+ }
394
+ };
395
+ }, [dispatch]);
396
+ const callbacksRef = useRef(callbacks);
397
+ callbacksRef.current = callbacks;
398
+ const isComposerWidgetsControlled = callbacks.composerWidgets !== void 0;
399
+ const [internalComposerWidgets, setInternalComposerWidgets] = useState([]);
400
+ const composerWidgets = isComposerWidgetsControlled ? callbacks.composerWidgets : internalComposerWidgets;
401
+ const composerWidgetsStateRef = useRef({ composerWidgets, isComposerWidgetsControlled });
402
+ composerWidgetsStateRef.current = { composerWidgets, isComposerWidgetsControlled };
403
+ const publishComposerWidgets = useCallback((next) => {
404
+ if (composerWidgetsStateRef.current.isComposerWidgetsControlled) {
405
+ callbacksRef.current.onComposerWidgetsChange?.(next);
406
+ } else {
407
+ setInternalComposerWidgets(next);
408
+ }
409
+ }, []);
410
+ const addComposerWidget = useCallback(
411
+ (widgetName, fields) => {
412
+ const composerWidgetId = crypto.randomUUID();
413
+ publishComposerWidgets([
414
+ ...composerWidgetsStateRef.current.composerWidgets,
415
+ { composerWidgetId, widgetName, fields }
416
+ ]);
417
+ return composerWidgetId;
418
+ },
419
+ [publishComposerWidgets]
420
+ );
421
+ const replaceComposerWidgetFields = useCallback(
422
+ (composerWidgetId, fields) => {
423
+ publishComposerWidgets(
424
+ composerWidgetsStateRef.current.composerWidgets.map(
425
+ (widget) => widget.composerWidgetId === composerWidgetId ? { ...widget, fields } : widget
426
+ )
427
+ );
428
+ },
429
+ [publishComposerWidgets]
430
+ );
431
+ const removeComposerWidget = useCallback(
432
+ (composerWidgetId) => {
433
+ publishComposerWidgets(
434
+ composerWidgetsStateRef.current.composerWidgets.filter(
435
+ (widget) => widget.composerWidgetId !== composerWidgetId
436
+ )
437
+ );
438
+ },
439
+ [publishComposerWidgets]
440
+ );
441
+ const clearComposerWidgets = useCallback(() => {
442
+ publishComposerWidgets([]);
443
+ }, [publishComposerWidgets]);
444
+ const openCanvas = useCallback(
445
+ (request) => {
446
+ dispatchCanvasEventRef.current({
447
+ type: "canvasOpened",
448
+ request: {
449
+ ...request,
450
+ viewportViable: window.innerWidth >= CANVAS_VIABLE_MIN_WIDTH,
451
+ hostHasCanvasSurface: hostHasCanvasSurfaceRef.current
452
+ }
453
+ });
454
+ },
455
+ []
456
+ );
457
+ const closeCanvas = useCallback(
458
+ (byCustomer) => {
459
+ dispatchCanvasEventRef.current({ type: "canvasClosed", byCustomer });
460
+ },
461
+ []
462
+ );
463
+ const lastClosedCanvasRef = useRef(lastClosedCanvas);
464
+ lastClosedCanvasRef.current = lastClosedCanvas;
465
+ const reopenLastClosedCanvas = useCallback(() => {
466
+ const last = lastClosedCanvasRef.current;
467
+ if (last === null) return;
468
+ dispatchCanvasEventRef.current({
469
+ type: "canvasOpened",
470
+ request: {
471
+ canvasId: last.canvasId,
472
+ instanceId: last.instanceId,
473
+ anchor: last.anchor,
474
+ origin: "cardClick",
475
+ justDelivered: false,
476
+ viewportViable: window.innerWidth >= CANVAS_VIABLE_MIN_WIDTH,
477
+ hostHasCanvasSurface: hostHasCanvasSurfaceRef.current,
478
+ ...last.createdEntityId !== void 0 ? { createdEntityId: last.createdEntityId } : {}
479
+ }
480
+ });
481
+ }, []);
482
+ const setCanvasCreatedEntityId = useCallback(
483
+ (created) => {
484
+ dispatchCanvasEventRef.current({ type: "canvasCreatedEntityIdSet", created });
485
+ },
486
+ []
487
+ );
488
+ const storedCanvasConversationIdRef = useRef(void 0);
489
+ const conversationIdForStorage = callbacks.conversationId;
490
+ useEffect(() => {
491
+ if (canvas !== null) {
492
+ storeOpenCanvas(conversationIdForStorage, canvas);
493
+ storedCanvasConversationIdRef.current = conversationIdForStorage;
494
+ return;
495
+ }
496
+ if (storedCanvasConversationIdRef.current !== void 0 && storedCanvasConversationIdRef.current === conversationIdForStorage) {
497
+ clearStoredCanvas(conversationIdForStorage);
498
+ }
499
+ storedCanvasConversationIdRef.current = void 0;
500
+ }, [canvas, conversationIdForStorage]);
501
+ const resetCanvas = useCallback(() => {
502
+ dispatchCanvasEventRef.current({ type: "canvasCleared" });
503
+ }, []);
504
+ const resetCanvasForNewTurn = useCallback(() => {
505
+ dispatchCanvasEventRef.current({ type: "canvasResetForNewTurn" });
506
+ }, []);
507
+ const sendMessageToChat = useCallback((message) => {
508
+ return callbacksRef.current.sendMessageToChat?.(message);
509
+ }, []);
510
+ const prefillComposer = useCallback((text) => {
511
+ callbacksRef.current.prefillComposer?.(text);
512
+ }, []);
513
+ const injectSignal = useCallback((signalText, options) => {
514
+ return callbacksRef.current.injectSignal?.(signalText, options);
515
+ }, []);
516
+ const minimizeChatHost = useCallback(() => {
517
+ callbacksRef.current.minimizeChatHost?.();
518
+ }, []);
519
+ const contextValue = useMemo(
520
+ () => ({
521
+ canvas,
522
+ hostHasCanvasSurface,
523
+ lastClosedCanvas,
524
+ openCanvas,
525
+ closeCanvas,
526
+ reopenLastClosedCanvas,
527
+ setCanvasCreatedEntityId,
528
+ resetCanvas,
529
+ resetCanvasForNewTurn,
530
+ sendMessageToChat,
531
+ prefillComposer,
532
+ injectSignal,
533
+ minimizeChatHost,
534
+ chatAgentSpaceKey: callbacks.chatAgentSpaceKey,
535
+ isConversationRunning,
536
+ isConversationClosed,
537
+ conversationId: callbacks.conversationId,
538
+ composerWidgets,
539
+ addComposerWidget,
540
+ replaceComposerWidgetFields,
541
+ removeComposerWidget,
542
+ clearComposerWidgets,
543
+ onOpenConversation: callbacks.onOpenConversation,
544
+ onSwitchConversation: callbacks.onSwitchConversation,
545
+ isOnboardingSetupConversation: callbacks.isOnboardingSetupConversation ?? false,
546
+ messages
547
+ }),
548
+ [
549
+ canvas,
550
+ hostHasCanvasSurface,
551
+ lastClosedCanvas,
552
+ openCanvas,
553
+ closeCanvas,
554
+ reopenLastClosedCanvas,
555
+ setCanvasCreatedEntityId,
556
+ resetCanvas,
557
+ resetCanvasForNewTurn,
558
+ sendMessageToChat,
559
+ prefillComposer,
560
+ injectSignal,
561
+ minimizeChatHost,
562
+ callbacks.chatAgentSpaceKey,
563
+ isConversationRunning,
564
+ isConversationClosed,
565
+ callbacks.conversationId,
566
+ composerWidgets,
567
+ addComposerWidget,
568
+ replaceComposerWidgetFields,
569
+ removeComposerWidget,
570
+ clearComposerWidgets,
571
+ callbacks.onOpenConversation,
572
+ callbacks.onSwitchConversation,
573
+ callbacks.isOnboardingSetupConversation,
574
+ messages
575
+ ]
576
+ );
577
+ return /* @__PURE__ */ jsx(ConversationWidgetContext.Provider, { value: contextValue, children });
578
+ };
579
+ const stripReveal = "agents_stripReveal_6XAjCM";
580
+ const stripRevealOpen = "agents_stripRevealOpen_sWkJwh";
581
+ const stripRevealInner = "agents_stripRevealInner_C2VlV7";
582
+ const strip = "agents_strip_rKQFvx";
583
+ const styles = {
584
+ stripReveal,
585
+ stripRevealOpen,
586
+ stripRevealInner,
587
+ strip
588
+ };
589
+ const ConversationMessageInputComposerWidgets = (props) => {
590
+ const { testId = "chat-input" } = props;
591
+ const { composerWidgets, replaceComposerWidgetFields, removeComposerWidget } = useConversationWidgetContext();
592
+ const renderableWidgets = composerWidgets.flatMap((widget) => {
593
+ const entry = conversationWidgetRegistry.widgets.find((candidate) => candidate.name === widget.widgetName);
594
+ return entry?.composerComponent ? [{ widget, Component: entry.composerComponent }] : [];
595
+ });
596
+ return /* @__PURE__ */ jsx(
597
+ "div",
598
+ {
599
+ className: classNames(styles.stripReveal, { [styles.stripRevealOpen]: renderableWidgets.length > 0 }),
600
+ "data-testid": `${testId}-composer-widgets-strip`,
601
+ children: /* @__PURE__ */ jsx("div", { className: styles.stripRevealInner, children: /* @__PURE__ */ jsx("div", { className: styles.strip, children: renderableWidgets.map(({ widget, Component }) => /* @__PURE__ */ jsx(
602
+ Component,
603
+ {
604
+ composerWidgetId: widget.composerWidgetId,
605
+ fields: widget.fields,
606
+ replaceFields: (nextFields) => replaceComposerWidgetFields(widget.composerWidgetId, nextFields),
607
+ remove: () => removeComposerWidget(widget.composerWidgetId),
608
+ testId: `${testId}-composer-widget-${widget.composerWidgetId}`
609
+ },
610
+ widget.composerWidgetId
611
+ )) }) })
612
+ }
613
+ );
614
+ };
615
+ export {
616
+ AgentsChatStateContainer as A,
617
+ ConversationWidgetProvider as C,
618
+ EMPTY_AGENTS_CHAT_OPENING_REQUEST as E,
619
+ INITIAL_AGENTS_CHAT_STATE as I,
620
+ ConversationMessageInputComposerWidgets as a,
621
+ ConversationErrorType as b,
622
+ createAgentsChatStore as c,
623
+ AgentsChatStoreProvider as d,
624
+ reduceAgentsChatState as e,
625
+ useAgentsChatState as f,
626
+ useAgentsChatStore as g,
627
+ useOptionalAgentsChatStore as h,
628
+ readConversationErrorTypeOfRefusedSend as r,
629
+ useAgentsChatSelector as u
630
+ };
631
+ //# sourceMappingURL=ConversationMessageInputComposerWidgets-BxyaFBA6.js.map