@helpai/elements 0.58.2 → 0.59.1

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-BAOjO2dQ.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-Daefe1g1.js';
2
2
  import 'zod';
3
3
 
4
4
  /**
package/index.mjs CHANGED
@@ -29,7 +29,7 @@ var BRAND = {
29
29
  };
30
30
 
31
31
  // src/core/version.ts
32
- var ELEMENTS_VERSION = true ? "0.58.2" : "0.0.0-dev";
32
+ var ELEMENTS_VERSION = true ? "0.59.1" : "0.0.0-dev";
33
33
  var ELEMENTS_VERSION_PARAM = "_ev";
34
34
 
35
35
  // src/i18n/strings.ts
@@ -2149,6 +2149,22 @@ var DEFAULT_PATHS = {
2149
2149
  submitForm: "/pai/submit-form"
2150
2150
  };
2151
2151
  var CONTEXT_PARAM = "context";
2152
+ function parseSuggestions(data) {
2153
+ const raw = data?.suggestions;
2154
+ if (!Array.isArray(raw)) return [];
2155
+ const out = [];
2156
+ for (const item of raw) {
2157
+ if (!item || typeof item !== "object") continue;
2158
+ const { id, label, text } = item;
2159
+ if (typeof label !== "string" || !label) continue;
2160
+ out.push({
2161
+ id: typeof id === "string" && id ? id : `s${out.length}`,
2162
+ label,
2163
+ text: typeof text === "string" && text ? text : label
2164
+ });
2165
+ }
2166
+ return out;
2167
+ }
2152
2168
  function buildSendMessageRequest(params) {
2153
2169
  const wire = params.messages.map((m) => ({
2154
2170
  // Use the backend's id when known (adopted from the stream's `start` chunk)
@@ -2240,6 +2256,15 @@ function retryAfterMs(headers) {
2240
2256
  const ms = Number.isFinite(secs) ? secs * 1e3 : Date.parse(raw) - Date.now();
2241
2257
  return Number.isFinite(ms) && ms >= 0 ? Math.min(ms, 3e4) : null;
2242
2258
  }
2259
+ function followupsFromMessages(messages) {
2260
+ for (let i = messages.length - 1; i >= 0; i--) {
2261
+ const m = messages[i];
2262
+ if (!m || m.role !== "assistant") continue;
2263
+ const part = m.parts.find((p36) => p36.type === "data-suggestions");
2264
+ return part?.type === "data-suggestions" ? parseSuggestions(part.data) : void 0;
2265
+ }
2266
+ return void 0;
2267
+ }
2243
2268
  function sleep(ms, signal7) {
2244
2269
  return new Promise((resolve) => {
2245
2270
  if (signal7?.aborted) return resolve();
@@ -2486,7 +2511,10 @@ var AgentTransport = class {
2486
2511
  canContinue: res.canContinue ?? true,
2487
2512
  messages,
2488
2513
  agent: res.agent,
2489
- suggestions: res.suggestions
2514
+ // The latest turn's model follow-ups are persisted ON the assistant message (a `data-suggestions`
2515
+ // part), not in a top-level field — read them off there, falling back to any server-provided
2516
+ // top-level `suggestions` (e.g. resume chips) when the last turn carried none.
2517
+ suggestions: followupsFromMessages(messages) ?? res.suggestions
2490
2518
  };
2491
2519
  }
2492
2520
  /**
@@ -2726,6 +2754,7 @@ var AgentTransport = class {
2726
2754
  * (a drop), so the caller can attempt a resume.
2727
2755
  */
2728
2756
  async *drain(source, seenIds, ctrl) {
2757
+ let terminal = false;
2729
2758
  try {
2730
2759
  for await (const evt of source) {
2731
2760
  if (ctrl.signal.aborted) return true;
@@ -2734,14 +2763,14 @@ var AgentTransport = class {
2734
2763
  seenIds.add(evt.eventId);
2735
2764
  }
2736
2765
  yield evt;
2737
- if (evt.chunk.type === "finish" || evt.chunk.type === "error") return true;
2766
+ if (evt.chunk.type === "finish" || evt.chunk.type === "error") terminal = true;
2738
2767
  }
2739
2768
  } catch (err) {
2740
2769
  if (ctrl.signal.aborted) return true;
2741
2770
  if (err instanceof StreamError && err.status !== void 0) throw err;
2742
2771
  log6.debug("stream segment dropped", { err });
2743
2772
  }
2744
- return false;
2773
+ return terminal;
2745
2774
  }
2746
2775
  /** Abort + fire-and-forget POST to `/pai/cancel-stream`. Idempotent. */
2747
2776
  cancelStream(ctrl, conversationId) {
@@ -2969,6 +2998,9 @@ function fromWireMessage(w) {
2969
2998
  mediaType: part.mediaType
2970
2999
  };
2971
3000
  }
3001
+ if (part.type === "data-suggestions") {
3002
+ return null;
3003
+ }
2972
3004
  if (part.type.startsWith("tool-")) {
2973
3005
  return {
2974
3006
  kind: "tool",
@@ -3208,6 +3240,8 @@ var StreamReducer = class {
3208
3240
  return;
3209
3241
  case "data-conversation-rebind":
3210
3242
  return;
3243
+ case "data-suggestions":
3244
+ return;
3211
3245
  default: {
3212
3246
  const _exhaustive = chunk;
3213
3247
  void _exhaustive;
@@ -8407,6 +8441,18 @@ function App({ options, hostElement, bus }) {
8407
8441
  useEffect16(() => {
8408
8442
  if (effectiveLocale !== activeLocale) setActiveLocale(effectiveLocale);
8409
8443
  }, [effectiveLocale, activeLocale]);
8444
+ const pendingSuggestionsRef = useRef9(null);
8445
+ const captureSuggestions = useCallback6((chunk) => {
8446
+ if (chunk.type !== "data-suggestions") return false;
8447
+ pendingSuggestionsRef.current = parseSuggestions(chunk.data);
8448
+ return true;
8449
+ }, []);
8450
+ const flushSuggestions = useCallback6(() => {
8451
+ if (pendingSuggestionsRef.current) {
8452
+ setSuggestions(pendingSuggestionsRef.current);
8453
+ pendingSuggestionsRef.current = null;
8454
+ }
8455
+ }, []);
8410
8456
  const adoptConversationRebind = useCallback6(
8411
8457
  (chunk) => {
8412
8458
  if (chunk.type !== "data-conversation-rebind") return false;
@@ -8426,9 +8472,10 @@ function App({ options, hostElement, bus }) {
8426
8472
  const runResume = useCallback6(
8427
8473
  async (handle) => {
8428
8474
  let bubble = null;
8475
+ pendingSuggestionsRef.current = null;
8429
8476
  try {
8430
8477
  for await (const evt of handle.iter) {
8431
- if (adoptConversationRebind(evt.chunk)) continue;
8478
+ if (adoptConversationRebind(evt.chunk) || captureSuggestions(evt.chunk)) continue;
8432
8479
  if (!bubble) {
8433
8480
  bubble = makeAssistantMessage();
8434
8481
  resumeBubbleRef.current = bubble;
@@ -8454,6 +8501,7 @@ function App({ options, hostElement, bus }) {
8454
8501
  bubble.status = "complete";
8455
8502
  feedback.play("messageReceived");
8456
8503
  emitMessage(bus, options, "assistant", assistantText(bubble));
8504
+ flushSuggestions();
8457
8505
  }
8458
8506
  }
8459
8507
  } catch (err) {
@@ -8592,12 +8640,13 @@ function App({ options, hostElement, bus }) {
8592
8640
  userPrefs: persistence.loadUserPrefs()
8593
8641
  });
8594
8642
  setStreaming(true);
8643
+ pendingSuggestionsRef.current = null;
8595
8644
  const handle = transport.sendMessage(body);
8596
8645
  setActiveCancel(() => handle.cancel);
8597
8646
  setActiveDetach(() => handle.detach);
8598
8647
  try {
8599
8648
  for await (const evt of handle.iter) {
8600
- if (adoptConversationRebind(evt.chunk)) continue;
8649
+ if (adoptConversationRebind(evt.chunk) || captureSuggestions(evt.chunk)) continue;
8601
8650
  reducer.apply(evt.chunk);
8602
8651
  if (evt.chunk.type === "finish" && evt.chunk.canContinue === false) {
8603
8652
  setCanSend(false);
@@ -8616,6 +8665,7 @@ function App({ options, hostElement, bus }) {
8616
8665
  assistantMsg.status = "complete";
8617
8666
  feedback.play("messageReceived");
8618
8667
  emitMessage(bus, options, "assistant", assistantText(assistantMsg));
8668
+ flushSuggestions();
8619
8669
  }
8620
8670
  } catch (error) {
8621
8671
  if (isAbortError(error)) {
package/package.json CHANGED
@@ -80,5 +80,5 @@
80
80
  ],
81
81
  "type": "module",
82
82
  "types": "./index.d.ts",
83
- "version": "0.58.2"
83
+ "version": "0.59.1"
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-BAOjO2dQ.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-Daefe1g1.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>>;
@@ -242,9 +242,9 @@ type LauncherOptions = z.infer<typeof launcherOptionsSchema>;
242
242
 
243
243
  declare const initialSizeSchema: z.ZodEnum<{
244
244
  fullscreen: "fullscreen";
245
- normal: "normal";
246
245
  expanded: "expanded";
247
246
  auto: "auto";
247
+ normal: "normal";
248
248
  }>;
249
249
  declare const resizeOptionsSchema: z.ZodObject<{
250
250
  enabled: z.ZodDefault<z.ZodBoolean>;
@@ -271,9 +271,9 @@ declare const sizeOptionsSchema: z.ZodObject<{
271
271
  inset: z.ZodOptional<z.ZodString>;
272
272
  initialSize: z.ZodDefault<z.ZodEnum<{
273
273
  fullscreen: "fullscreen";
274
- normal: "normal";
275
274
  expanded: "expanded";
276
275
  auto: "auto";
276
+ normal: "normal";
277
277
  }>>;
278
278
  autoSizeBreakpoint: z.ZodDefault<z.ZodNumber>;
279
279
  }, z.core.$loose>;
@@ -325,40 +325,40 @@ type FeatureFlags = z.infer<typeof featureFlagsSchema>;
325
325
  */
326
326
 
327
327
  declare const actionNameSchema: z.ZodEnum<{
328
+ close: "close";
328
329
  expand: "expand";
329
330
  fullscreen: "fullscreen";
330
- close: "close";
331
- language: "language";
331
+ clear: "clear";
332
332
  theme: "theme";
333
+ language: "language";
333
334
  textSize: "textSize";
334
335
  history: "history";
335
- clear: "clear";
336
336
  sound: "sound";
337
337
  }>;
338
338
  type ActionName = z.infer<typeof actionNameSchema>;
339
339
  declare const headerActionsSchema: z.ZodArray<z.ZodEnum<{
340
+ close: "close";
340
341
  expand: "expand";
341
342
  fullscreen: "fullscreen";
342
- close: "close";
343
- language: "language";
343
+ clear: "clear";
344
344
  theme: "theme";
345
+ language: "language";
345
346
  textSize: "textSize";
346
347
  history: "history";
347
- clear: "clear";
348
348
  sound: "sound";
349
349
  }>>;
350
350
  type HeaderActions = z.infer<typeof headerActionsSchema>;
351
351
  /** Section wrapper — `actions` list wrapped under `header` in the dashboard form. */
352
352
  declare const headerSchema: z.ZodObject<{
353
353
  actions: z.ZodOptional<z.ZodArray<z.ZodEnum<{
354
+ close: "close";
354
355
  expand: "expand";
355
356
  fullscreen: "fullscreen";
356
- close: "close";
357
- language: "language";
357
+ clear: "clear";
358
358
  theme: "theme";
359
+ language: "language";
359
360
  textSize: "textSize";
360
361
  history: "history";
361
- clear: "clear";
362
362
  sound: "sound";
363
363
  }>>>;
364
364
  }, z.core.$loose>;
@@ -374,33 +374,33 @@ type HeaderOptions = z.infer<typeof headerSchema>;
374
374
  */
375
375
 
376
376
  declare const feedbackEventSchema: z.ZodEnum<{
377
+ voiceStart: "voiceStart";
378
+ voiceStop: "voiceStop";
377
379
  error: "error";
378
380
  messageReceived: "messageReceived";
379
381
  messageSent: "messageSent";
380
- voiceStart: "voiceStart";
381
- voiceStop: "voiceStop";
382
382
  }>;
383
383
  type FeedbackEvent = z.infer<typeof feedbackEventSchema>;
384
384
  declare const soundOptionsSchema: z.ZodObject<{
385
385
  enabled: z.ZodDefault<z.ZodBoolean>;
386
386
  volume: z.ZodDefault<z.ZodNumber>;
387
387
  events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
388
+ voiceStart: "voiceStart";
389
+ voiceStop: "voiceStop";
388
390
  error: "error";
389
391
  messageReceived: "messageReceived";
390
392
  messageSent: "messageSent";
391
- voiceStart: "voiceStart";
392
- voiceStop: "voiceStop";
393
393
  }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>;
394
394
  }, z.core.$loose>;
395
395
  type SoundOptions = z.infer<typeof soundOptionsSchema>;
396
396
  declare const hapticsOptionsSchema: z.ZodObject<{
397
397
  enabled: z.ZodDefault<z.ZodBoolean>;
398
398
  events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
399
+ voiceStart: "voiceStart";
400
+ voiceStop: "voiceStop";
399
401
  error: "error";
400
402
  messageReceived: "messageReceived";
401
403
  messageSent: "messageSent";
402
- voiceStart: "voiceStart";
403
- voiceStop: "voiceStop";
404
404
  }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodNumber, z.ZodArray<z.ZodNumber>]>>>;
405
405
  }, z.core.$loose>;
406
406
  type HapticsOptions = z.infer<typeof hapticsOptionsSchema>;
@@ -409,21 +409,21 @@ declare const feedbackSchema: z.ZodObject<{
409
409
  enabled: z.ZodDefault<z.ZodBoolean>;
410
410
  volume: z.ZodDefault<z.ZodNumber>;
411
411
  events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
412
+ voiceStart: "voiceStart";
413
+ voiceStop: "voiceStop";
412
414
  error: "error";
413
415
  messageReceived: "messageReceived";
414
416
  messageSent: "messageSent";
415
- voiceStart: "voiceStart";
416
- voiceStop: "voiceStop";
417
417
  }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>;
418
418
  }, z.core.$loose>>;
419
419
  haptics: z.ZodOptional<z.ZodObject<{
420
420
  enabled: z.ZodDefault<z.ZodBoolean>;
421
421
  events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
422
+ voiceStart: "voiceStart";
423
+ voiceStop: "voiceStop";
422
424
  error: "error";
423
425
  messageReceived: "messageReceived";
424
426
  messageSent: "messageSent";
425
- voiceStart: "voiceStart";
426
- voiceStop: "voiceStop";
427
427
  }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodNumber, z.ZodArray<z.ZodNumber>]>>>;
428
428
  }, z.core.$loose>>;
429
429
  }, z.core.$loose>;
@@ -858,18 +858,18 @@ type I18nOptions = z.infer<typeof i18nSchema>;
858
858
  */
859
859
 
860
860
  declare const moduleLayoutSchema: z.ZodEnum<{
861
+ home: "home";
861
862
  chat: "chat";
862
863
  help: "help";
863
- home: "home";
864
864
  news: "news";
865
865
  }>;
866
866
  type ModuleLayout = z.infer<typeof moduleLayoutSchema>;
867
867
  declare const moduleSchema: z.ZodObject<{
868
868
  label: z.ZodString;
869
869
  layout: z.ZodEnum<{
870
+ home: "home";
870
871
  chat: "chat";
871
872
  help: "help";
872
- home: "home";
873
873
  news: "news";
874
874
  }>;
875
875
  contentTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -895,9 +895,9 @@ type ModuleOptions = z.infer<typeof moduleSchema>;
895
895
  declare const modulesSchema: z.ZodArray<z.ZodObject<{
896
896
  label: z.ZodString;
897
897
  layout: z.ZodEnum<{
898
+ home: "home";
898
899
  chat: "chat";
899
900
  help: "help";
900
- home: "home";
901
901
  news: "news";
902
902
  }>;
903
903
  contentTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
package/web-component.mjs CHANGED
@@ -1934,7 +1934,7 @@ function createAuth(opts) {
1934
1934
  }
1935
1935
 
1936
1936
  // src/core/version.ts
1937
- var ELEMENTS_VERSION = true ? "0.58.2" : "0.0.0-dev";
1937
+ var ELEMENTS_VERSION = true ? "0.59.1" : "0.0.0-dev";
1938
1938
  var ELEMENTS_VERSION_PARAM = "_ev";
1939
1939
 
1940
1940
  // src/stream/types.ts
@@ -2108,6 +2108,22 @@ var DEFAULT_PATHS = {
2108
2108
  submitForm: "/pai/submit-form"
2109
2109
  };
2110
2110
  var CONTEXT_PARAM = "context";
2111
+ function parseSuggestions(data) {
2112
+ const raw = data?.suggestions;
2113
+ if (!Array.isArray(raw)) return [];
2114
+ const out = [];
2115
+ for (const item of raw) {
2116
+ if (!item || typeof item !== "object") continue;
2117
+ const { id, label, text } = item;
2118
+ if (typeof label !== "string" || !label) continue;
2119
+ out.push({
2120
+ id: typeof id === "string" && id ? id : `s${out.length}`,
2121
+ label,
2122
+ text: typeof text === "string" && text ? text : label
2123
+ });
2124
+ }
2125
+ return out;
2126
+ }
2111
2127
  function buildSendMessageRequest(params) {
2112
2128
  const wire = params.messages.map((m) => ({
2113
2129
  // Use the backend's id when known (adopted from the stream's `start` chunk)
@@ -2199,6 +2215,15 @@ function retryAfterMs(headers) {
2199
2215
  const ms = Number.isFinite(secs) ? secs * 1e3 : Date.parse(raw) - Date.now();
2200
2216
  return Number.isFinite(ms) && ms >= 0 ? Math.min(ms, 3e4) : null;
2201
2217
  }
2218
+ function followupsFromMessages(messages) {
2219
+ for (let i = messages.length - 1; i >= 0; i--) {
2220
+ const m = messages[i];
2221
+ if (!m || m.role !== "assistant") continue;
2222
+ const part = m.parts.find((p36) => p36.type === "data-suggestions");
2223
+ return part?.type === "data-suggestions" ? parseSuggestions(part.data) : void 0;
2224
+ }
2225
+ return void 0;
2226
+ }
2202
2227
  function sleep(ms, signal7) {
2203
2228
  return new Promise((resolve) => {
2204
2229
  if (signal7?.aborted) return resolve();
@@ -2445,7 +2470,10 @@ var AgentTransport = class {
2445
2470
  canContinue: res.canContinue ?? true,
2446
2471
  messages,
2447
2472
  agent: res.agent,
2448
- suggestions: res.suggestions
2473
+ // The latest turn's model follow-ups are persisted ON the assistant message (a `data-suggestions`
2474
+ // part), not in a top-level field — read them off there, falling back to any server-provided
2475
+ // top-level `suggestions` (e.g. resume chips) when the last turn carried none.
2476
+ suggestions: followupsFromMessages(messages) ?? res.suggestions
2449
2477
  };
2450
2478
  }
2451
2479
  /**
@@ -2685,6 +2713,7 @@ var AgentTransport = class {
2685
2713
  * (a drop), so the caller can attempt a resume.
2686
2714
  */
2687
2715
  async *drain(source, seenIds, ctrl) {
2716
+ let terminal = false;
2688
2717
  try {
2689
2718
  for await (const evt of source) {
2690
2719
  if (ctrl.signal.aborted) return true;
@@ -2693,14 +2722,14 @@ var AgentTransport = class {
2693
2722
  seenIds.add(evt.eventId);
2694
2723
  }
2695
2724
  yield evt;
2696
- if (evt.chunk.type === "finish" || evt.chunk.type === "error") return true;
2725
+ if (evt.chunk.type === "finish" || evt.chunk.type === "error") terminal = true;
2697
2726
  }
2698
2727
  } catch (err) {
2699
2728
  if (ctrl.signal.aborted) return true;
2700
2729
  if (err instanceof StreamError && err.status !== void 0) throw err;
2701
2730
  log5.debug("stream segment dropped", { err });
2702
2731
  }
2703
- return false;
2732
+ return terminal;
2704
2733
  }
2705
2734
  /** Abort + fire-and-forget POST to `/pai/cancel-stream`. Idempotent. */
2706
2735
  cancelStream(ctrl, conversationId) {
@@ -2928,6 +2957,9 @@ function fromWireMessage(w) {
2928
2957
  mediaType: part.mediaType
2929
2958
  };
2930
2959
  }
2960
+ if (part.type === "data-suggestions") {
2961
+ return null;
2962
+ }
2931
2963
  if (part.type.startsWith("tool-")) {
2932
2964
  return {
2933
2965
  kind: "tool",
@@ -3167,6 +3199,8 @@ var StreamReducer = class {
3167
3199
  return;
3168
3200
  case "data-conversation-rebind":
3169
3201
  return;
3202
+ case "data-suggestions":
3203
+ return;
3170
3204
  default: {
3171
3205
  const _exhaustive = chunk;
3172
3206
  void _exhaustive;
@@ -8366,6 +8400,18 @@ function App({ options, hostElement, bus }) {
8366
8400
  useEffect16(() => {
8367
8401
  if (effectiveLocale !== activeLocale) setActiveLocale(effectiveLocale);
8368
8402
  }, [effectiveLocale, activeLocale]);
8403
+ const pendingSuggestionsRef = useRef9(null);
8404
+ const captureSuggestions = useCallback6((chunk) => {
8405
+ if (chunk.type !== "data-suggestions") return false;
8406
+ pendingSuggestionsRef.current = parseSuggestions(chunk.data);
8407
+ return true;
8408
+ }, []);
8409
+ const flushSuggestions = useCallback6(() => {
8410
+ if (pendingSuggestionsRef.current) {
8411
+ setSuggestions(pendingSuggestionsRef.current);
8412
+ pendingSuggestionsRef.current = null;
8413
+ }
8414
+ }, []);
8369
8415
  const adoptConversationRebind = useCallback6(
8370
8416
  (chunk) => {
8371
8417
  if (chunk.type !== "data-conversation-rebind") return false;
@@ -8385,9 +8431,10 @@ function App({ options, hostElement, bus }) {
8385
8431
  const runResume = useCallback6(
8386
8432
  async (handle) => {
8387
8433
  let bubble = null;
8434
+ pendingSuggestionsRef.current = null;
8388
8435
  try {
8389
8436
  for await (const evt of handle.iter) {
8390
- if (adoptConversationRebind(evt.chunk)) continue;
8437
+ if (adoptConversationRebind(evt.chunk) || captureSuggestions(evt.chunk)) continue;
8391
8438
  if (!bubble) {
8392
8439
  bubble = makeAssistantMessage();
8393
8440
  resumeBubbleRef.current = bubble;
@@ -8413,6 +8460,7 @@ function App({ options, hostElement, bus }) {
8413
8460
  bubble.status = "complete";
8414
8461
  feedback.play("messageReceived");
8415
8462
  emitMessage(bus, options, "assistant", assistantText(bubble));
8463
+ flushSuggestions();
8416
8464
  }
8417
8465
  }
8418
8466
  } catch (err) {
@@ -8551,12 +8599,13 @@ function App({ options, hostElement, bus }) {
8551
8599
  userPrefs: persistence.loadUserPrefs()
8552
8600
  });
8553
8601
  setStreaming(true);
8602
+ pendingSuggestionsRef.current = null;
8554
8603
  const handle = transport.sendMessage(body);
8555
8604
  setActiveCancel(() => handle.cancel);
8556
8605
  setActiveDetach(() => handle.detach);
8557
8606
  try {
8558
8607
  for await (const evt of handle.iter) {
8559
- if (adoptConversationRebind(evt.chunk)) continue;
8608
+ if (adoptConversationRebind(evt.chunk) || captureSuggestions(evt.chunk)) continue;
8560
8609
  reducer.apply(evt.chunk);
8561
8610
  if (evt.chunk.type === "finish" && evt.chunk.canContinue === false) {
8562
8611
  setCanSend(false);
@@ -8575,6 +8624,7 @@ function App({ options, hostElement, bus }) {
8575
8624
  assistantMsg.status = "complete";
8576
8625
  feedback.play("messageReceived");
8577
8626
  emitMessage(bus, options, "assistant", assistantText(assistantMsg));
8627
+ flushSuggestions();
8578
8628
  }
8579
8629
  } catch (error) {
8580
8630
  if (isAbortError(error)) {