@helpai/elements 0.45.0 → 0.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as Asset, B as BlocksConfig, C as ConnectionConfig, a as ConnectionConfigPartial, H as HandshakeResponse, L as Link, S as ServerConfig, b as SiteConfig, W as WidgetConfig, c as WidgetConfigPartial, d as WidgetSettings, e as WidgetSettingsPartial } from './deployment-oSJ2nv2G.js';
1
+ export { A as Asset, B as BlocksConfig, C as ConnectionConfig, a as ConnectionConfigPartial, H as HandshakeResponse, L as Link, S as ServerConfig, b as SiteConfig, W as WidgetConfig, c as WidgetConfigPartial, d as WidgetSettings, e as WidgetSettingsPartial } from './deployment-C_jlXJAe.js';
2
2
  import 'zod';
3
3
 
4
4
  /**
package/index.mjs CHANGED
@@ -30,7 +30,7 @@ var BRAND = {
30
30
  };
31
31
 
32
32
  // src/core/version.ts
33
- var ELEMENTS_VERSION = true ? "0.45.0" : "0.0.0-dev";
33
+ var ELEMENTS_VERSION = true ? "0.46.0" : "0.0.0-dev";
34
34
  var ELEMENTS_VERSION_PARAM = "_ev";
35
35
 
36
36
  // src/i18n/strings.ts
@@ -1664,13 +1664,11 @@ function buildSendMessageRequest(params) {
1664
1664
  conversationId: params.conversationId,
1665
1665
  trigger: params.trigger ?? "submit-message"
1666
1666
  };
1667
+ if (params.messageId) body.messageId = params.messageId;
1667
1668
  if (params.visitorId) body.visitorId = params.visitorId;
1668
1669
  if (params.userPrefs) body.userPrefs = params.userPrefs;
1669
- const data = {};
1670
1670
  const tools = params.tools?.map(normalizeToolRef).filter((t) => t !== null);
1671
- if (tools?.length) data.tools = tools;
1672
- if (params.responseMode) data.responseMode = params.responseMode;
1673
- if (Object.keys(data).length > 0) body.data = data;
1671
+ if (tools?.length) body.data = { tools };
1674
1672
  return body;
1675
1673
  }
1676
1674
  function isResolvedToolPart(p35) {
@@ -2081,9 +2079,9 @@ var AgentTransport = class {
2081
2079
  log6.debug("message \u2192", {
2082
2080
  conversationId: body.conversationId,
2083
2081
  visitorId: body.visitorId,
2082
+ messageId: body.messageId,
2084
2083
  messageCount: body.messages.length,
2085
2084
  trigger: body.trigger,
2086
- responseMode: body.data?.responseMode,
2087
2085
  tools: body.data?.tools?.map((t) => t.code)
2088
2086
  });
2089
2087
  const ctrl = new AbortController();
@@ -2665,18 +2663,6 @@ function applyTool(m, chunk) {
2665
2663
  }
2666
2664
  }
2667
2665
 
2668
- // src/stream/constants.ts
2669
- function isAskUserInputTool(toolName) {
2670
- if (!toolName) return false;
2671
- const name = toolName.startsWith("tool:") ? toolName.slice(5) : toolName;
2672
- return name === "ask-user-input" || name === "ask_user_input" || name === "request-user-input" || name === "request_user_input";
2673
- }
2674
- var TRIGGER = {
2675
- submitMessage: "submit-message",
2676
- toolResult: "tool-result",
2677
- toolApproval: "tool-approval"
2678
- };
2679
-
2680
2666
  // src/core/feedback/index.ts
2681
2667
  import { signal as signal3 } from "@preact/signals";
2682
2668
 
@@ -4783,6 +4769,13 @@ function FormDoneMarker({
4783
4769
  // src/ui/message-bubble.tsx
4784
4770
  import { useComputed as useComputed5 } from "@preact/signals";
4785
4771
 
4772
+ // src/stream/constants.ts
4773
+ function isAskUserInputTool(toolName) {
4774
+ if (!toolName) return false;
4775
+ const name = toolName.startsWith("tool:") ? toolName.slice(5) : toolName;
4776
+ return name === "ask-user-input" || name === "ask_user_input" || name === "request-user-input" || name === "request_user_input";
4777
+ }
4778
+
4786
4779
  // src/ui/markdown.tsx
4787
4780
  import { useLayoutEffect, useMemo, useRef as useRef4 } from "preact/hooks";
4788
4781
  import { effect, signal as signal4 } from "@preact/signals";
@@ -6936,6 +6929,13 @@ var p34 = BRAND.cssPrefix;
6936
6929
  function makeLocalizedWelcome(w, strings) {
6937
6930
  return makeInstantWelcomeMessage({ ...w, text: localizeText(strings, w.text) });
6938
6931
  }
6932
+ function allToolPartsSettled(msg) {
6933
+ const tools = msg.partsSig.value.filter((p35) => p35.kind === "tool");
6934
+ return tools.length > 0 && tools.every((p35) => {
6935
+ const s = p35.stateSig.value;
6936
+ return s === "output-available" || s === "output-error" || s === "output-denied" || s === "approval-responded";
6937
+ });
6938
+ }
6939
6939
  function App({ options, hostElement, bus }) {
6940
6940
  const [persistence] = useState13(
6941
6941
  () => createPersistence(options.widgetId, options.storage, options.aiAgentDeploymentId)
@@ -7402,19 +7402,20 @@ function App({ options, hostElement, bus }) {
7402
7402
  return () => document.removeEventListener("keydown", onKey);
7403
7403
  }, [isOpen, options.mode]);
7404
7404
  const streamAssistant = useCallback6(
7405
- async (assistantMsg, trigger) => {
7405
+ async (assistantMsg, { continueExisting }) => {
7406
7406
  const activeConversationId = conversationIdSig.value ?? uuid7();
7407
7407
  if (!conversationIdSig.value) {
7408
7408
  conversationIdSig.value = activeConversationId;
7409
7409
  persistence.saveConversationId(activeConversationId);
7410
7410
  }
7411
+ const thread = continueExisting ? messagesSig.value : messagesSig.value.slice(0, -1);
7411
7412
  const body = buildSendMessageRequest({
7412
- messages: messagesSig.value.slice(0, -1).map(fromReactive),
7413
+ messages: thread.map(fromReactive),
7413
7414
  conversationId: activeConversationId,
7415
+ // The assistant message being generated / resumed.
7416
+ messageId: assistantMsg.id,
7414
7417
  // textModel + imageModel are backend-only — selected per deployment.
7415
7418
  tools: options.features.tools,
7416
- responseMode: options.responseMode,
7417
- trigger,
7418
7419
  // Identity + preferences ride on every message — server may need
7419
7420
  // them to route, persist, or reconcile in-flight.
7420
7421
  visitorId,
@@ -7448,23 +7449,23 @@ function App({ options, hostElement, bus }) {
7448
7449
  },
7449
7450
  [transport, reducer, messagesSig, conversationIdSig, options, bus, feedback, persistence, visitorId]
7450
7451
  );
7451
- const resolveTool = useCallback6(
7452
- (toolCallId, trigger, mutate) => {
7452
+ const decideTool = useCallback6(
7453
+ (toolCallId, mutate) => {
7453
7454
  if (streaming) return;
7454
7455
  const last = messagesSig.value.at(-1);
7455
7456
  const part = last?.partsSig.value.find(
7456
7457
  (pt) => pt.kind === "tool" && pt.toolCallId === toolCallId
7457
7458
  );
7458
- if (!part) {
7459
- log17.warn("resolveTool: tool part not found", { toolCallId });
7459
+ if (!last || !part) {
7460
+ log17.warn("decideTool: tool part not found", { toolCallId });
7460
7461
  return;
7461
7462
  }
7462
7463
  mutate(part);
7463
- if (last) last.partsSig.value = [...last.partsSig.value];
7464
- const assistantMsg = makeAssistantMessage();
7465
- messagesSig.value = [...messagesSig.value, assistantMsg];
7466
- reducer.attach(assistantMsg);
7467
- void streamAssistant(assistantMsg, trigger);
7464
+ last.partsSig.value = [...last.partsSig.value];
7465
+ if (!allToolPartsSettled(last)) return;
7466
+ last.status = "streaming";
7467
+ reducer.attach(last);
7468
+ void streamAssistant(last, { continueExisting: true });
7468
7469
  },
7469
7470
  [streaming, messagesSig, reducer, streamAssistant]
7470
7471
  );
@@ -7472,24 +7473,24 @@ function App({ options, hostElement, bus }) {
7472
7473
  (toolCallId, output) => {
7473
7474
  log17.info("toolResult", { toolCallId });
7474
7475
  bus.emit("toolResult", { toolCallId });
7475
- resolveTool(toolCallId, TRIGGER.toolResult, (part) => {
7476
+ decideTool(toolCallId, (part) => {
7476
7477
  part.outputSig.value = output;
7477
7478
  part.stateSig.value = "output-available";
7478
7479
  });
7479
7480
  },
7480
- [bus, resolveTool]
7481
+ [bus, decideTool]
7481
7482
  );
7482
7483
  const handleToolDecision = useCallback6(
7483
7484
  (toolCallId, approved, reason) => {
7484
7485
  log17.info("toolDecision", { toolCallId, approved });
7485
7486
  bus.emit("toolDecision", { toolCallId, approved });
7486
- resolveTool(toolCallId, TRIGGER.toolApproval, (part) => {
7487
+ decideTool(toolCallId, (part) => {
7487
7488
  const id = part.approvalSig.value?.id ?? toolCallId;
7488
7489
  part.approvalSig.value = { id, approved, reason };
7489
7490
  part.stateSig.value = "approval-responded";
7490
7491
  });
7491
7492
  },
7492
- [bus, resolveTool]
7493
+ [bus, decideTool]
7493
7494
  );
7494
7495
  const toolInteraction = useMemo3(
7495
7496
  () => ({ humanInLoop: options.features.humanInLoop, onResult: handleToolResult, onDecision: handleToolDecision }),
@@ -7569,7 +7570,7 @@ function App({ options, hostElement, bus }) {
7569
7570
  messagesSig.value = [...messagesSig.value, userMsg, assistantMsg];
7570
7571
  reducer.attach(assistantMsg);
7571
7572
  emitMessage(bus, options, "user", text);
7572
- await streamAssistant(assistantMsg, TRIGGER.submitMessage);
7573
+ await streamAssistant(assistantMsg, { continueExisting: false });
7573
7574
  forms.fire("after-messages");
7574
7575
  },
7575
7576
  [streaming, transport, bus, options, suggestions.length, messagesSig, reducer, streamAssistant, forms]
package/package.json CHANGED
@@ -80,5 +80,5 @@
80
80
  ],
81
81
  "type": "module",
82
82
  "types": "./index.d.ts",
83
- "version": "0.45.0"
83
+ "version": "0.46.0"
84
84
  }
package/schema.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as Asset, B as BlocksConfig, C as ConnectionConfig, a as ConnectionConfigPartial, E as Endpoints, H as HandshakeResponse, L as Link, P as PAGE_AREA_SUGGESTIONS, f as PageContext, S as ServerConfig, b as SiteConfig, U as UserContext, W as WidgetConfig, c as WidgetConfigPartial, d as WidgetSettings, e as WidgetSettingsPartial, g as assetSchema, h as blocksConfigSchema, i as connectionConfigPartialSchema, j as connectionConfigSchema, k as cssColorSchema, l as cssLengthSchema, m as endpointsSchema, n as handshakeResponseSchema, o as linkSchema, p as localeSchema, q as pageContextSchema, s as serverConfigSchema, r as siteConfigSchema, u as userContextSchema, t as uuid7Schema, w as widgetConfigPartialSchema, v as widgetConfigSchema, x as widgetSettingsPartialSchema, y as widgetSettingsSchema } from './deployment-oSJ2nv2G.js';
1
+ export { A as Asset, B as BlocksConfig, C as ConnectionConfig, a as ConnectionConfigPartial, E as Endpoints, H as HandshakeResponse, L as Link, P as PAGE_AREA_SUGGESTIONS, f as PageContext, S as ServerConfig, b as SiteConfig, U as UserContext, W as WidgetConfig, c as WidgetConfigPartial, d as WidgetSettings, e as WidgetSettingsPartial, g as assetSchema, h as blocksConfigSchema, i as connectionConfigPartialSchema, j as connectionConfigSchema, k as cssColorSchema, l as cssLengthSchema, m as endpointsSchema, n as handshakeResponseSchema, o as linkSchema, p as localeSchema, q as pageContextSchema, s as serverConfigSchema, r as siteConfigSchema, u as userContextSchema, t as uuid7Schema, w as widgetConfigPartialSchema, v as widgetConfigSchema, x as widgetSettingsPartialSchema, y as widgetSettingsSchema } from './deployment-C_jlXJAe.js';
2
2
  import { z } from 'zod';
3
3
 
4
4
  /**
@@ -56,9 +56,9 @@ declare const presentationSchema: z.ZodObject<{
56
56
  inset: z.ZodOptional<z.ZodString>;
57
57
  initialSize: z.ZodDefault<z.ZodEnum<{
58
58
  fullscreen: "fullscreen";
59
- normal: "normal";
60
59
  expanded: "expanded";
61
60
  auto: "auto";
61
+ normal: "normal";
62
62
  }>>;
63
63
  autoSizeBreakpoint: z.ZodDefault<z.ZodNumber>;
64
64
  }, z.core.$loose>>;
@@ -240,9 +240,9 @@ type LauncherOptions = z.infer<typeof launcherOptionsSchema>;
240
240
 
241
241
  declare const initialSizeSchema: z.ZodEnum<{
242
242
  fullscreen: "fullscreen";
243
- normal: "normal";
244
243
  expanded: "expanded";
245
244
  auto: "auto";
245
+ normal: "normal";
246
246
  }>;
247
247
  declare const resizeOptionsSchema: z.ZodObject<{
248
248
  enabled: z.ZodDefault<z.ZodBoolean>;
@@ -269,9 +269,9 @@ declare const sizeOptionsSchema: z.ZodObject<{
269
269
  inset: z.ZodOptional<z.ZodString>;
270
270
  initialSize: z.ZodDefault<z.ZodEnum<{
271
271
  fullscreen: "fullscreen";
272
- normal: "normal";
273
272
  expanded: "expanded";
274
273
  auto: "auto";
274
+ normal: "normal";
275
275
  }>>;
276
276
  autoSizeBreakpoint: z.ZodDefault<z.ZodNumber>;
277
277
  }, z.core.$loose>;
@@ -323,40 +323,40 @@ type FeatureFlags = z.infer<typeof featureFlagsSchema>;
323
323
  */
324
324
 
325
325
  declare const actionNameSchema: z.ZodEnum<{
326
+ close: "close";
326
327
  expand: "expand";
327
328
  fullscreen: "fullscreen";
328
- close: "close";
329
- language: "language";
329
+ clear: "clear";
330
330
  theme: "theme";
331
+ language: "language";
331
332
  textSize: "textSize";
332
333
  history: "history";
333
- clear: "clear";
334
334
  sound: "sound";
335
335
  }>;
336
336
  type ActionName = z.infer<typeof actionNameSchema>;
337
337
  declare const headerActionsSchema: z.ZodArray<z.ZodEnum<{
338
+ close: "close";
338
339
  expand: "expand";
339
340
  fullscreen: "fullscreen";
340
- close: "close";
341
- language: "language";
341
+ clear: "clear";
342
342
  theme: "theme";
343
+ language: "language";
343
344
  textSize: "textSize";
344
345
  history: "history";
345
- clear: "clear";
346
346
  sound: "sound";
347
347
  }>>;
348
348
  type HeaderActions = z.infer<typeof headerActionsSchema>;
349
349
  /** Section wrapper — `actions` list wrapped under `header` in the dashboard form. */
350
350
  declare const headerSchema: z.ZodObject<{
351
351
  actions: z.ZodOptional<z.ZodArray<z.ZodEnum<{
352
+ close: "close";
352
353
  expand: "expand";
353
354
  fullscreen: "fullscreen";
354
- close: "close";
355
- language: "language";
355
+ clear: "clear";
356
356
  theme: "theme";
357
+ language: "language";
357
358
  textSize: "textSize";
358
359
  history: "history";
359
- clear: "clear";
360
360
  sound: "sound";
361
361
  }>>>;
362
362
  }, z.core.$loose>;
@@ -372,33 +372,33 @@ type HeaderOptions = z.infer<typeof headerSchema>;
372
372
  */
373
373
 
374
374
  declare const feedbackEventSchema: z.ZodEnum<{
375
+ voiceStart: "voiceStart";
376
+ voiceStop: "voiceStop";
375
377
  error: "error";
376
378
  messageReceived: "messageReceived";
377
379
  messageSent: "messageSent";
378
- voiceStart: "voiceStart";
379
- voiceStop: "voiceStop";
380
380
  }>;
381
381
  type FeedbackEvent = z.infer<typeof feedbackEventSchema>;
382
382
  declare const soundOptionsSchema: z.ZodObject<{
383
383
  enabled: z.ZodDefault<z.ZodBoolean>;
384
384
  volume: z.ZodDefault<z.ZodNumber>;
385
385
  events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
386
+ voiceStart: "voiceStart";
387
+ voiceStop: "voiceStop";
386
388
  error: "error";
387
389
  messageReceived: "messageReceived";
388
390
  messageSent: "messageSent";
389
- voiceStart: "voiceStart";
390
- voiceStop: "voiceStop";
391
391
  }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>;
392
392
  }, z.core.$loose>;
393
393
  type SoundOptions = z.infer<typeof soundOptionsSchema>;
394
394
  declare const hapticsOptionsSchema: z.ZodObject<{
395
395
  enabled: z.ZodDefault<z.ZodBoolean>;
396
396
  events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
397
+ voiceStart: "voiceStart";
398
+ voiceStop: "voiceStop";
397
399
  error: "error";
398
400
  messageReceived: "messageReceived";
399
401
  messageSent: "messageSent";
400
- voiceStart: "voiceStart";
401
- voiceStop: "voiceStop";
402
402
  }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodNumber, z.ZodArray<z.ZodNumber>]>>>;
403
403
  }, z.core.$loose>;
404
404
  type HapticsOptions = z.infer<typeof hapticsOptionsSchema>;
@@ -407,21 +407,21 @@ declare const feedbackSchema: z.ZodObject<{
407
407
  enabled: z.ZodDefault<z.ZodBoolean>;
408
408
  volume: z.ZodDefault<z.ZodNumber>;
409
409
  events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
410
+ voiceStart: "voiceStart";
411
+ voiceStop: "voiceStop";
410
412
  error: "error";
411
413
  messageReceived: "messageReceived";
412
414
  messageSent: "messageSent";
413
- voiceStart: "voiceStart";
414
- voiceStop: "voiceStop";
415
415
  }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>;
416
416
  }, z.core.$loose>>;
417
417
  haptics: z.ZodOptional<z.ZodObject<{
418
418
  enabled: z.ZodDefault<z.ZodBoolean>;
419
419
  events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
420
+ voiceStart: "voiceStart";
421
+ voiceStop: "voiceStop";
420
422
  error: "error";
421
423
  messageReceived: "messageReceived";
422
424
  messageSent: "messageSent";
423
- voiceStart: "voiceStart";
424
- voiceStop: "voiceStop";
425
425
  }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodNumber, z.ZodArray<z.ZodNumber>]>>>;
426
426
  }, z.core.$loose>>;
427
427
  }, z.core.$loose>;
@@ -856,18 +856,18 @@ type I18nOptions = z.infer<typeof i18nSchema>;
856
856
  */
857
857
 
858
858
  declare const moduleLayoutSchema: z.ZodEnum<{
859
+ home: "home";
859
860
  chat: "chat";
860
861
  help: "help";
861
- home: "home";
862
862
  news: "news";
863
863
  }>;
864
864
  type ModuleLayout = z.infer<typeof moduleLayoutSchema>;
865
865
  declare const moduleSchema: z.ZodObject<{
866
866
  label: z.ZodString;
867
867
  layout: z.ZodEnum<{
868
+ home: "home";
868
869
  chat: "chat";
869
870
  help: "help";
870
- home: "home";
871
871
  news: "news";
872
872
  }>;
873
873
  contentTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -893,9 +893,9 @@ type ModuleOptions = z.infer<typeof moduleSchema>;
893
893
  declare const modulesSchema: z.ZodArray<z.ZodObject<{
894
894
  label: z.ZodString;
895
895
  layout: z.ZodEnum<{
896
+ home: "home";
896
897
  chat: "chat";
897
898
  help: "help";
898
- home: "home";
899
899
  news: "news";
900
900
  }>;
901
901
  contentTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
package/web-component.mjs CHANGED
@@ -1445,7 +1445,7 @@ function createAuth(opts) {
1445
1445
  }
1446
1446
 
1447
1447
  // src/core/version.ts
1448
- var ELEMENTS_VERSION = true ? "0.45.0" : "0.0.0-dev";
1448
+ var ELEMENTS_VERSION = true ? "0.46.0" : "0.0.0-dev";
1449
1449
  var ELEMENTS_VERSION_PARAM = "_ev";
1450
1450
 
1451
1451
  // src/stream/types.ts
@@ -1623,13 +1623,11 @@ function buildSendMessageRequest(params) {
1623
1623
  conversationId: params.conversationId,
1624
1624
  trigger: params.trigger ?? "submit-message"
1625
1625
  };
1626
+ if (params.messageId) body.messageId = params.messageId;
1626
1627
  if (params.visitorId) body.visitorId = params.visitorId;
1627
1628
  if (params.userPrefs) body.userPrefs = params.userPrefs;
1628
- const data = {};
1629
1629
  const tools = params.tools?.map(normalizeToolRef).filter((t) => t !== null);
1630
- if (tools?.length) data.tools = tools;
1631
- if (params.responseMode) data.responseMode = params.responseMode;
1632
- if (Object.keys(data).length > 0) body.data = data;
1630
+ if (tools?.length) body.data = { tools };
1633
1631
  return body;
1634
1632
  }
1635
1633
  function isResolvedToolPart(p35) {
@@ -2040,9 +2038,9 @@ var AgentTransport = class {
2040
2038
  log5.debug("message \u2192", {
2041
2039
  conversationId: body.conversationId,
2042
2040
  visitorId: body.visitorId,
2041
+ messageId: body.messageId,
2043
2042
  messageCount: body.messages.length,
2044
2043
  trigger: body.trigger,
2045
- responseMode: body.data?.responseMode,
2046
2044
  tools: body.data?.tools?.map((t) => t.code)
2047
2045
  });
2048
2046
  const ctrl = new AbortController();
@@ -2624,18 +2622,6 @@ function applyTool(m, chunk) {
2624
2622
  }
2625
2623
  }
2626
2624
 
2627
- // src/stream/constants.ts
2628
- function isAskUserInputTool(toolName) {
2629
- if (!toolName) return false;
2630
- const name = toolName.startsWith("tool:") ? toolName.slice(5) : toolName;
2631
- return name === "ask-user-input" || name === "ask_user_input" || name === "request-user-input" || name === "request_user_input";
2632
- }
2633
- var TRIGGER = {
2634
- submitMessage: "submit-message",
2635
- toolResult: "tool-result",
2636
- toolApproval: "tool-approval"
2637
- };
2638
-
2639
2625
  // src/core/feedback/index.ts
2640
2626
  import { signal as signal3 } from "@preact/signals";
2641
2627
 
@@ -4742,6 +4728,13 @@ function FormDoneMarker({
4742
4728
  // src/ui/message-bubble.tsx
4743
4729
  import { useComputed as useComputed5 } from "@preact/signals";
4744
4730
 
4731
+ // src/stream/constants.ts
4732
+ function isAskUserInputTool(toolName) {
4733
+ if (!toolName) return false;
4734
+ const name = toolName.startsWith("tool:") ? toolName.slice(5) : toolName;
4735
+ return name === "ask-user-input" || name === "ask_user_input" || name === "request-user-input" || name === "request_user_input";
4736
+ }
4737
+
4745
4738
  // src/ui/markdown.tsx
4746
4739
  import { useLayoutEffect, useMemo, useRef as useRef4 } from "preact/hooks";
4747
4740
  import { effect, signal as signal4 } from "@preact/signals";
@@ -6895,6 +6888,13 @@ var p34 = BRAND.cssPrefix;
6895
6888
  function makeLocalizedWelcome(w, strings) {
6896
6889
  return makeInstantWelcomeMessage({ ...w, text: localizeText(strings, w.text) });
6897
6890
  }
6891
+ function allToolPartsSettled(msg) {
6892
+ const tools = msg.partsSig.value.filter((p35) => p35.kind === "tool");
6893
+ return tools.length > 0 && tools.every((p35) => {
6894
+ const s = p35.stateSig.value;
6895
+ return s === "output-available" || s === "output-error" || s === "output-denied" || s === "approval-responded";
6896
+ });
6897
+ }
6898
6898
  function App({ options, hostElement, bus }) {
6899
6899
  const [persistence] = useState13(
6900
6900
  () => createPersistence(options.widgetId, options.storage, options.aiAgentDeploymentId)
@@ -7361,19 +7361,20 @@ function App({ options, hostElement, bus }) {
7361
7361
  return () => document.removeEventListener("keydown", onKey);
7362
7362
  }, [isOpen, options.mode]);
7363
7363
  const streamAssistant = useCallback6(
7364
- async (assistantMsg, trigger) => {
7364
+ async (assistantMsg, { continueExisting }) => {
7365
7365
  const activeConversationId = conversationIdSig.value ?? uuid7();
7366
7366
  if (!conversationIdSig.value) {
7367
7367
  conversationIdSig.value = activeConversationId;
7368
7368
  persistence.saveConversationId(activeConversationId);
7369
7369
  }
7370
+ const thread = continueExisting ? messagesSig.value : messagesSig.value.slice(0, -1);
7370
7371
  const body = buildSendMessageRequest({
7371
- messages: messagesSig.value.slice(0, -1).map(fromReactive),
7372
+ messages: thread.map(fromReactive),
7372
7373
  conversationId: activeConversationId,
7374
+ // The assistant message being generated / resumed.
7375
+ messageId: assistantMsg.id,
7373
7376
  // textModel + imageModel are backend-only — selected per deployment.
7374
7377
  tools: options.features.tools,
7375
- responseMode: options.responseMode,
7376
- trigger,
7377
7378
  // Identity + preferences ride on every message — server may need
7378
7379
  // them to route, persist, or reconcile in-flight.
7379
7380
  visitorId,
@@ -7407,23 +7408,23 @@ function App({ options, hostElement, bus }) {
7407
7408
  },
7408
7409
  [transport, reducer, messagesSig, conversationIdSig, options, bus, feedback, persistence, visitorId]
7409
7410
  );
7410
- const resolveTool = useCallback6(
7411
- (toolCallId, trigger, mutate) => {
7411
+ const decideTool = useCallback6(
7412
+ (toolCallId, mutate) => {
7412
7413
  if (streaming) return;
7413
7414
  const last = messagesSig.value.at(-1);
7414
7415
  const part = last?.partsSig.value.find(
7415
7416
  (pt) => pt.kind === "tool" && pt.toolCallId === toolCallId
7416
7417
  );
7417
- if (!part) {
7418
- log16.warn("resolveTool: tool part not found", { toolCallId });
7418
+ if (!last || !part) {
7419
+ log16.warn("decideTool: tool part not found", { toolCallId });
7419
7420
  return;
7420
7421
  }
7421
7422
  mutate(part);
7422
- if (last) last.partsSig.value = [...last.partsSig.value];
7423
- const assistantMsg = makeAssistantMessage();
7424
- messagesSig.value = [...messagesSig.value, assistantMsg];
7425
- reducer.attach(assistantMsg);
7426
- void streamAssistant(assistantMsg, trigger);
7423
+ last.partsSig.value = [...last.partsSig.value];
7424
+ if (!allToolPartsSettled(last)) return;
7425
+ last.status = "streaming";
7426
+ reducer.attach(last);
7427
+ void streamAssistant(last, { continueExisting: true });
7427
7428
  },
7428
7429
  [streaming, messagesSig, reducer, streamAssistant]
7429
7430
  );
@@ -7431,24 +7432,24 @@ function App({ options, hostElement, bus }) {
7431
7432
  (toolCallId, output) => {
7432
7433
  log16.info("toolResult", { toolCallId });
7433
7434
  bus.emit("toolResult", { toolCallId });
7434
- resolveTool(toolCallId, TRIGGER.toolResult, (part) => {
7435
+ decideTool(toolCallId, (part) => {
7435
7436
  part.outputSig.value = output;
7436
7437
  part.stateSig.value = "output-available";
7437
7438
  });
7438
7439
  },
7439
- [bus, resolveTool]
7440
+ [bus, decideTool]
7440
7441
  );
7441
7442
  const handleToolDecision = useCallback6(
7442
7443
  (toolCallId, approved, reason) => {
7443
7444
  log16.info("toolDecision", { toolCallId, approved });
7444
7445
  bus.emit("toolDecision", { toolCallId, approved });
7445
- resolveTool(toolCallId, TRIGGER.toolApproval, (part) => {
7446
+ decideTool(toolCallId, (part) => {
7446
7447
  const id = part.approvalSig.value?.id ?? toolCallId;
7447
7448
  part.approvalSig.value = { id, approved, reason };
7448
7449
  part.stateSig.value = "approval-responded";
7449
7450
  });
7450
7451
  },
7451
- [bus, resolveTool]
7452
+ [bus, decideTool]
7452
7453
  );
7453
7454
  const toolInteraction = useMemo3(
7454
7455
  () => ({ humanInLoop: options.features.humanInLoop, onResult: handleToolResult, onDecision: handleToolDecision }),
@@ -7528,7 +7529,7 @@ function App({ options, hostElement, bus }) {
7528
7529
  messagesSig.value = [...messagesSig.value, userMsg, assistantMsg];
7529
7530
  reducer.attach(assistantMsg);
7530
7531
  emitMessage(bus, options, "user", text);
7531
- await streamAssistant(assistantMsg, TRIGGER.submitMessage);
7532
+ await streamAssistant(assistantMsg, { continueExisting: false });
7532
7533
  forms.fire("after-messages");
7533
7534
  },
7534
7535
  [streaming, transport, bus, options, suggestions.length, messagesSig, reducer, streamAssistant, forms]