@noodleseed/assistant 1.28.0 → 1.30.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.
Files changed (42) hide show
  1. package/dist/{app-view-element-mXHvcAXc.d.ts → app-view-element-kR8eqhyD.d.cts} +1 -1
  2. package/dist/{app-view-element-BjRkwNN1.d.cts → app-view-element-nY1svwHT.d.ts} +1 -1
  3. package/dist/app-view.d.cts +3 -3
  4. package/dist/app-view.d.ts +3 -3
  5. package/dist/{chunk-WJV4MJUR.js → chunk-5EVZFPTD.js} +120 -10
  6. package/dist/chunk-5EVZFPTD.js.map +1 -0
  7. package/dist/{chunk-QH7PL3GU.js → chunk-T4PS6P2W.js} +259 -54
  8. package/dist/chunk-T4PS6P2W.js.map +1 -0
  9. package/dist/{client-CPFw8tfo.d.ts → client-contract-Bw9dtrhw.d.cts} +26 -35
  10. package/dist/{client-_xivfs4q.d.cts → client-contract-DjU9qsoP.d.ts} +26 -35
  11. package/dist/client.cjs +122 -9
  12. package/dist/client.cjs.map +1 -1
  13. package/dist/client.d.cts +12 -2
  14. package/dist/client.d.ts +12 -2
  15. package/dist/client.js +1 -1
  16. package/dist/embed.global.js +46 -46
  17. package/dist/index.cjs +376 -61
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.cts +3 -3
  20. package/dist/index.d.ts +3 -3
  21. package/dist/index.js +2 -2
  22. package/dist/react/client.cjs +122 -9
  23. package/dist/react/client.cjs.map +1 -1
  24. package/dist/react/client.d.cts +2 -2
  25. package/dist/react/client.d.ts +2 -2
  26. package/dist/react/client.js +1 -1
  27. package/dist/react.cjs +376 -61
  28. package/dist/react.cjs.map +1 -1
  29. package/dist/react.d.cts +3 -3
  30. package/dist/react.d.ts +3 -3
  31. package/dist/react.js +2 -2
  32. package/dist/server-CMqlAnxs.d.cts +270 -0
  33. package/dist/server-CMqlAnxs.d.ts +270 -0
  34. package/dist/server.cjs.map +1 -1
  35. package/dist/server.d.cts +1 -121
  36. package/dist/server.d.ts +1 -121
  37. package/dist/server.js.map +1 -1
  38. package/package.json +1 -1
  39. package/dist/appearance-BpVu3lpk.d.cts +0 -146
  40. package/dist/appearance-BpVu3lpk.d.ts +0 -146
  41. package/dist/chunk-QH7PL3GU.js.map +0 -1
  42. package/dist/chunk-WJV4MJUR.js.map +0 -1
@@ -1,5 +1,5 @@
1
- import { A as AssistantConfiguration } from './appearance-BpVu3lpk.js';
2
1
  import { ChatStatus, UIMessage } from 'ai';
2
+ import { a as AssistantConfiguration, b as AssistantSession } from './server-CMqlAnxs.cjs';
3
3
 
4
4
  interface AssistantSurfaceAppearance {
5
5
  readonly surface?: string;
@@ -60,6 +60,16 @@ interface AssistantEvent {
60
60
  readonly event: string;
61
61
  readonly data: Readonly<Record<string, unknown>>;
62
62
  }
63
+ /**
64
+ * Per-request options for an MCP App request. `bridge` marks the call's originating surface for
65
+ * attribution (ADR 0220) — a body field: a header would have to join the route's CORS allowlist.
66
+ * `onSuspended` fires when that request parks on an interaction, before its promise can settle: the
67
+ * only way to answer a caller that must not block on a human.
68
+ */
69
+ interface AppRequestOptions {
70
+ readonly bridge?: string;
71
+ onSuspended?(): void;
72
+ }
63
73
  interface AssistantErrorDetail {
64
74
  readonly code: string;
65
75
  readonly status?: number;
@@ -149,6 +159,10 @@ interface AssistantErrorEventDetail extends TurnDetail {
149
159
  readonly status?: number;
150
160
  readonly retryable?: boolean;
151
161
  }
162
+ interface AssistantSuggestedPromptsDetail extends TurnDetail {
163
+ readonly phase: 'initial' | 'follow_up';
164
+ readonly prompts: readonly string[];
165
+ }
152
166
  type AssistantContentEvent = NamedEvent<'content', AssistantContentDetail>;
153
167
  type AssistantToolStartedEvent = NamedEvent<'tool_started', AssistantToolStartedDetail>;
154
168
  type AssistantToolProposedEvent = NamedEvent<'tool_proposed', AssistantToolProposedDetail>;
@@ -158,6 +172,7 @@ type AssistantInteractionResolvedEvent = NamedEvent<'interaction_resolved', Assi
158
172
  type AssistantToolCompletedEvent = NamedEvent<'tool_completed', AssistantToolCompletedDetail>;
159
173
  type AssistantViewAvailableEvent = NamedEvent<'view_available', AssistantViewAvailableDetail>;
160
174
  type AssistantErrorEvent = NamedEvent<'error', AssistantErrorEventDetail>;
175
+ type AssistantSuggestedPromptsEvent = NamedEvent<'suggested_prompts', AssistantSuggestedPromptsDetail>;
161
176
  type AssistantDoneEvent = NamedEvent<'done', TurnDetail>;
162
177
  interface AssistantLegacyInteractionProposedDetail {
163
178
  readonly id: string;
@@ -192,7 +207,7 @@ interface AssistantUnrecognizedEvent {
192
207
  };
193
208
  }
194
209
  /** Closed event union for the DOM-free client; unknown future SSE names remain observable safely. */
195
- type AssistantClientEvent = AssistantContentEvent | AssistantToolStartedEvent | AssistantToolProposedEvent | AssistantInputRequestedEvent | AssistantAuthRequestedEvent | AssistantInteractionResolvedEvent | AssistantToolCompletedEvent | AssistantViewAvailableEvent | AssistantErrorEvent | AssistantDoneEvent | NamedEvent<'interaction_proposed', AssistantLegacyInteractionProposedDetail> | AssistantClientLifecycleEvent | AssistantUnrecognizedEvent;
210
+ type AssistantClientEvent = AssistantContentEvent | AssistantToolStartedEvent | AssistantToolProposedEvent | AssistantInputRequestedEvent | AssistantAuthRequestedEvent | AssistantInteractionResolvedEvent | AssistantToolCompletedEvent | AssistantViewAvailableEvent | AssistantErrorEvent | AssistantSuggestedPromptsEvent | AssistantDoneEvent | NamedEvent<'interaction_proposed', AssistantLegacyInteractionProposedDetail> | AssistantClientLifecycleEvent | AssistantUnrecognizedEvent;
196
211
  declare global {
197
212
  interface HTMLElementEventMap {
198
213
  'assistant-view-available': CustomEvent<AssistantViewAvailableDetail>;
@@ -243,6 +258,9 @@ interface AssistantChatError {
243
258
  interface AssistantChatState {
244
259
  readonly status: ChatStatus;
245
260
  readonly messages: readonly AssistantUIMessage[];
261
+ readonly suggestions?: Extract<AssistantClientEvent, {
262
+ event: 'suggested_prompts';
263
+ }>['data'];
246
264
  readonly error?: AssistantChatError;
247
265
  }
248
266
 
@@ -260,44 +278,19 @@ type AssistantSessionSourceOptions = {
260
278
  readonly sessionEndpoint?: undefined;
261
279
  };
262
280
 
263
- declare class AssistantClientError extends Error {
264
- readonly detail: AssistantErrorDetail;
265
- constructor(detail: AssistantErrorDetail, message: string, options?: ErrorOptions);
266
- }
267
-
268
281
  type AssistantContextValue = string | number | boolean | null;
269
282
  type AssistantContext = Readonly<Record<string, AssistantContextValue>>;
270
283
  interface AssistantClientContext {
271
284
  readonly locale?: string;
272
285
  readonly timeZone?: string;
273
286
  }
274
-
275
287
  type AssistantInteractionResponse = {
276
288
  readonly action: 'accept';
277
289
  readonly content?: AssistantJsonValue;
278
290
  } | {
279
291
  readonly action: 'decline' | 'cancel';
280
292
  };
281
- interface AssistantSessionResponse {
282
- readonly token: string;
283
- readonly expiresAt: string;
284
- readonly endpoints: {
285
- readonly turns: string;
286
- readonly toolConfirmations: string;
287
- readonly interactions?: string;
288
- readonly apps?: string;
289
- /** Additive hosted sandbox document for widget frames; absent on older services. */
290
- readonly sandbox?: string;
291
- /** Additive bounded visible-transcript endpoint; absent on older services. */
292
- readonly transcript?: string;
293
- };
294
- readonly configuration?: AssistantConfiguration;
295
- /** Armed post-sign-in resume hint: present only on an elevation exchange (issue #1177). */
296
- readonly resume?: {
297
- readonly tool: string;
298
- };
299
- }
300
-
293
+ type AssistantSessionResponse = AssistantSession;
301
294
  interface AssistantClientBehaviorOptions<TPageContext extends AssistantPageContext = AssistantContext> {
302
295
  readonly fetch?: typeof fetch;
303
296
  /** Untrusted page context sent only when exchanging a session. */
@@ -326,19 +319,17 @@ interface AssistantClient<TPageContext extends AssistantPageContext = AssistantC
326
319
  /** A request holds the single-flight slot. Optional so external implementations stay valid. */
327
320
  isBusy?(): boolean;
328
321
  sendMessage(message: string): Promise<void>;
322
+ /** Request the session's idempotent initial prompts when effective config omitted them. */
323
+ loadInitialSuggestions?(): Promise<void>;
329
324
  respond(id: string, response: AssistantInteractionResponse): Promise<void>;
330
325
  updateContext(context: AssistantContext): void;
331
326
  updatePageContext(context: TPageContext): void;
332
327
  updateModelContext(update: AssistantModelContextUpdate): void;
333
- requestApp(method: string, params: Readonly<Record<string, unknown>>): Promise<unknown>;
334
- /**
335
- * Hosted sandbox document URL for widget frames, when the active session advertises one.
336
- * Optional so existing external implementations of this interface stay valid.
337
- */
328
+ requestApp(method: string, params: Readonly<Record<string, unknown>>, options?: AppRequestOptions): Promise<unknown>;
329
+ /** Hosted sandbox document URL for widget frames, when the active session advertises one. */
338
330
  appSandboxUrl?(): string | undefined;
339
331
  resetSession(): void;
340
332
  abort(): void;
341
333
  }
342
- declare function createAssistantClient<TPageContext extends AssistantPageContext = AssistantContext>(options: CreateAssistantClientOptions<TPageContext>): AssistantClient<TPageContext>;
343
334
 
344
- export { type AssistantClient as A, type AssistantInputRequestedDetail as B, type CreateAssistantClientOptions as C, type AssistantInputRequestedEvent as D, type AssistantInteractionResolvedDetail as E, type AssistantInteractionResolvedEvent as F, type AssistantInteractionStatus as G, type AssistantJsonValue as H, type AssistantSessionResponse as I, type AssistantToolCompletedDetail as J, type AssistantToolCompletedEvent as K, type AssistantToolProposedDetail as L, type AssistantToolProposedEvent as M, type AssistantToolResultData as N, type AssistantToolStartedDetail as O, type AssistantToolStartedEvent as P, type AssistantUIDataTypes as Q, type AssistantUIMessage as R, type AssistantUnrecognizedEvent as S, type AssistantViewData as T, createAssistantClient as U, type AssistantViewAvailableDetail as a, type AssistantPageContext as b, type AssistantContext as c, type AssistantChatState as d, type AssistantErrorDetail as e, type AssistantAppearance as f, type AssistantModelContextUpdate as g, type AssistantClientEvent as h, type AssistantAppearanceWarning as i, type AssistantInteractionResponse as j, type AssistantAppearanceTheme as k, type AssistantEvent as l, type AssistantSurfaceAppearance as m, type AssistantViewAvailableEvent as n, type AssistantChatError as o, type AssistantClientContext as p, AssistantClientError as q, type AssistantClientLifecycleEvent as r, type AssistantConfirmationData as s, type AssistantContentDetail as t, type AssistantContentEvent as u, type AssistantContextValue as v, type AssistantDoneEvent as w, type AssistantErrorEvent as x, type AssistantErrorEventDetail as y, type AssistantInputRequestData as z };
335
+ export type { AssistantClient as A, AssistantSuggestedPromptsDetail as B, CreateAssistantClientOptions as C, AssistantSuggestedPromptsEvent as D, AssistantToolCompletedDetail as E, AssistantToolCompletedEvent as F, AssistantToolProposedDetail as G, AssistantToolProposedEvent as H, AssistantToolResultData as I, AssistantToolStartedDetail as J, AssistantToolStartedEvent as K, AssistantUIDataTypes as L, AssistantUIMessage as M, AssistantUnrecognizedEvent as N, AssistantViewAvailableEvent as O, AssistantViewData as P, AssistantAppearance as Q, AssistantAppearanceWarning as R, AssistantAppearanceTheme as S, AssistantEvent as T, AssistantSurfaceAppearance as U, AssistantViewAvailableDetail as a, AssistantPageContext as b, AssistantContext as c, AssistantChatState as d, AssistantErrorDetail as e, AssistantChatError as f, AssistantClientContext as g, AssistantClientEvent as h, AssistantClientLifecycleEvent as i, AssistantConfirmationData as j, AssistantContentDetail as k, AssistantContentEvent as l, AssistantContextValue as m, AssistantDoneEvent as n, AssistantErrorEvent as o, AssistantErrorEventDetail as p, AssistantInputRequestData as q, AssistantInputRequestedDetail as r, AssistantInputRequestedEvent as s, AssistantInteractionResolvedDetail as t, AssistantInteractionResolvedEvent as u, AssistantInteractionResponse as v, AssistantInteractionStatus as w, AssistantJsonValue as x, AssistantModelContextUpdate as y, AssistantSessionResponse as z };
@@ -1,5 +1,5 @@
1
- import { A as AssistantConfiguration } from './appearance-BpVu3lpk.cjs';
2
1
  import { ChatStatus, UIMessage } from 'ai';
2
+ import { a as AssistantConfiguration, b as AssistantSession } from './server-CMqlAnxs.js';
3
3
 
4
4
  interface AssistantSurfaceAppearance {
5
5
  readonly surface?: string;
@@ -60,6 +60,16 @@ interface AssistantEvent {
60
60
  readonly event: string;
61
61
  readonly data: Readonly<Record<string, unknown>>;
62
62
  }
63
+ /**
64
+ * Per-request options for an MCP App request. `bridge` marks the call's originating surface for
65
+ * attribution (ADR 0220) — a body field: a header would have to join the route's CORS allowlist.
66
+ * `onSuspended` fires when that request parks on an interaction, before its promise can settle: the
67
+ * only way to answer a caller that must not block on a human.
68
+ */
69
+ interface AppRequestOptions {
70
+ readonly bridge?: string;
71
+ onSuspended?(): void;
72
+ }
63
73
  interface AssistantErrorDetail {
64
74
  readonly code: string;
65
75
  readonly status?: number;
@@ -149,6 +159,10 @@ interface AssistantErrorEventDetail extends TurnDetail {
149
159
  readonly status?: number;
150
160
  readonly retryable?: boolean;
151
161
  }
162
+ interface AssistantSuggestedPromptsDetail extends TurnDetail {
163
+ readonly phase: 'initial' | 'follow_up';
164
+ readonly prompts: readonly string[];
165
+ }
152
166
  type AssistantContentEvent = NamedEvent<'content', AssistantContentDetail>;
153
167
  type AssistantToolStartedEvent = NamedEvent<'tool_started', AssistantToolStartedDetail>;
154
168
  type AssistantToolProposedEvent = NamedEvent<'tool_proposed', AssistantToolProposedDetail>;
@@ -158,6 +172,7 @@ type AssistantInteractionResolvedEvent = NamedEvent<'interaction_resolved', Assi
158
172
  type AssistantToolCompletedEvent = NamedEvent<'tool_completed', AssistantToolCompletedDetail>;
159
173
  type AssistantViewAvailableEvent = NamedEvent<'view_available', AssistantViewAvailableDetail>;
160
174
  type AssistantErrorEvent = NamedEvent<'error', AssistantErrorEventDetail>;
175
+ type AssistantSuggestedPromptsEvent = NamedEvent<'suggested_prompts', AssistantSuggestedPromptsDetail>;
161
176
  type AssistantDoneEvent = NamedEvent<'done', TurnDetail>;
162
177
  interface AssistantLegacyInteractionProposedDetail {
163
178
  readonly id: string;
@@ -192,7 +207,7 @@ interface AssistantUnrecognizedEvent {
192
207
  };
193
208
  }
194
209
  /** Closed event union for the DOM-free client; unknown future SSE names remain observable safely. */
195
- type AssistantClientEvent = AssistantContentEvent | AssistantToolStartedEvent | AssistantToolProposedEvent | AssistantInputRequestedEvent | AssistantAuthRequestedEvent | AssistantInteractionResolvedEvent | AssistantToolCompletedEvent | AssistantViewAvailableEvent | AssistantErrorEvent | AssistantDoneEvent | NamedEvent<'interaction_proposed', AssistantLegacyInteractionProposedDetail> | AssistantClientLifecycleEvent | AssistantUnrecognizedEvent;
210
+ type AssistantClientEvent = AssistantContentEvent | AssistantToolStartedEvent | AssistantToolProposedEvent | AssistantInputRequestedEvent | AssistantAuthRequestedEvent | AssistantInteractionResolvedEvent | AssistantToolCompletedEvent | AssistantViewAvailableEvent | AssistantErrorEvent | AssistantSuggestedPromptsEvent | AssistantDoneEvent | NamedEvent<'interaction_proposed', AssistantLegacyInteractionProposedDetail> | AssistantClientLifecycleEvent | AssistantUnrecognizedEvent;
196
211
  declare global {
197
212
  interface HTMLElementEventMap {
198
213
  'assistant-view-available': CustomEvent<AssistantViewAvailableDetail>;
@@ -243,6 +258,9 @@ interface AssistantChatError {
243
258
  interface AssistantChatState {
244
259
  readonly status: ChatStatus;
245
260
  readonly messages: readonly AssistantUIMessage[];
261
+ readonly suggestions?: Extract<AssistantClientEvent, {
262
+ event: 'suggested_prompts';
263
+ }>['data'];
246
264
  readonly error?: AssistantChatError;
247
265
  }
248
266
 
@@ -260,44 +278,19 @@ type AssistantSessionSourceOptions = {
260
278
  readonly sessionEndpoint?: undefined;
261
279
  };
262
280
 
263
- declare class AssistantClientError extends Error {
264
- readonly detail: AssistantErrorDetail;
265
- constructor(detail: AssistantErrorDetail, message: string, options?: ErrorOptions);
266
- }
267
-
268
281
  type AssistantContextValue = string | number | boolean | null;
269
282
  type AssistantContext = Readonly<Record<string, AssistantContextValue>>;
270
283
  interface AssistantClientContext {
271
284
  readonly locale?: string;
272
285
  readonly timeZone?: string;
273
286
  }
274
-
275
287
  type AssistantInteractionResponse = {
276
288
  readonly action: 'accept';
277
289
  readonly content?: AssistantJsonValue;
278
290
  } | {
279
291
  readonly action: 'decline' | 'cancel';
280
292
  };
281
- interface AssistantSessionResponse {
282
- readonly token: string;
283
- readonly expiresAt: string;
284
- readonly endpoints: {
285
- readonly turns: string;
286
- readonly toolConfirmations: string;
287
- readonly interactions?: string;
288
- readonly apps?: string;
289
- /** Additive hosted sandbox document for widget frames; absent on older services. */
290
- readonly sandbox?: string;
291
- /** Additive bounded visible-transcript endpoint; absent on older services. */
292
- readonly transcript?: string;
293
- };
294
- readonly configuration?: AssistantConfiguration;
295
- /** Armed post-sign-in resume hint: present only on an elevation exchange (issue #1177). */
296
- readonly resume?: {
297
- readonly tool: string;
298
- };
299
- }
300
-
293
+ type AssistantSessionResponse = AssistantSession;
301
294
  interface AssistantClientBehaviorOptions<TPageContext extends AssistantPageContext = AssistantContext> {
302
295
  readonly fetch?: typeof fetch;
303
296
  /** Untrusted page context sent only when exchanging a session. */
@@ -326,19 +319,17 @@ interface AssistantClient<TPageContext extends AssistantPageContext = AssistantC
326
319
  /** A request holds the single-flight slot. Optional so external implementations stay valid. */
327
320
  isBusy?(): boolean;
328
321
  sendMessage(message: string): Promise<void>;
322
+ /** Request the session's idempotent initial prompts when effective config omitted them. */
323
+ loadInitialSuggestions?(): Promise<void>;
329
324
  respond(id: string, response: AssistantInteractionResponse): Promise<void>;
330
325
  updateContext(context: AssistantContext): void;
331
326
  updatePageContext(context: TPageContext): void;
332
327
  updateModelContext(update: AssistantModelContextUpdate): void;
333
- requestApp(method: string, params: Readonly<Record<string, unknown>>): Promise<unknown>;
334
- /**
335
- * Hosted sandbox document URL for widget frames, when the active session advertises one.
336
- * Optional so existing external implementations of this interface stay valid.
337
- */
328
+ requestApp(method: string, params: Readonly<Record<string, unknown>>, options?: AppRequestOptions): Promise<unknown>;
329
+ /** Hosted sandbox document URL for widget frames, when the active session advertises one. */
338
330
  appSandboxUrl?(): string | undefined;
339
331
  resetSession(): void;
340
332
  abort(): void;
341
333
  }
342
- declare function createAssistantClient<TPageContext extends AssistantPageContext = AssistantContext>(options: CreateAssistantClientOptions<TPageContext>): AssistantClient<TPageContext>;
343
334
 
344
- export { type AssistantClient as A, type AssistantInputRequestedDetail as B, type CreateAssistantClientOptions as C, type AssistantInputRequestedEvent as D, type AssistantInteractionResolvedDetail as E, type AssistantInteractionResolvedEvent as F, type AssistantInteractionStatus as G, type AssistantJsonValue as H, type AssistantSessionResponse as I, type AssistantToolCompletedDetail as J, type AssistantToolCompletedEvent as K, type AssistantToolProposedDetail as L, type AssistantToolProposedEvent as M, type AssistantToolResultData as N, type AssistantToolStartedDetail as O, type AssistantToolStartedEvent as P, type AssistantUIDataTypes as Q, type AssistantUIMessage as R, type AssistantUnrecognizedEvent as S, type AssistantViewData as T, createAssistantClient as U, type AssistantViewAvailableDetail as a, type AssistantPageContext as b, type AssistantContext as c, type AssistantChatState as d, type AssistantErrorDetail as e, type AssistantAppearance as f, type AssistantModelContextUpdate as g, type AssistantClientEvent as h, type AssistantAppearanceWarning as i, type AssistantInteractionResponse as j, type AssistantAppearanceTheme as k, type AssistantEvent as l, type AssistantSurfaceAppearance as m, type AssistantViewAvailableEvent as n, type AssistantChatError as o, type AssistantClientContext as p, AssistantClientError as q, type AssistantClientLifecycleEvent as r, type AssistantConfirmationData as s, type AssistantContentDetail as t, type AssistantContentEvent as u, type AssistantContextValue as v, type AssistantDoneEvent as w, type AssistantErrorEvent as x, type AssistantErrorEventDetail as y, type AssistantInputRequestData as z };
335
+ export type { AssistantClient as A, AssistantSuggestedPromptsDetail as B, CreateAssistantClientOptions as C, AssistantSuggestedPromptsEvent as D, AssistantToolCompletedDetail as E, AssistantToolCompletedEvent as F, AssistantToolProposedDetail as G, AssistantToolProposedEvent as H, AssistantToolResultData as I, AssistantToolStartedDetail as J, AssistantToolStartedEvent as K, AssistantUIDataTypes as L, AssistantUIMessage as M, AssistantUnrecognizedEvent as N, AssistantViewAvailableEvent as O, AssistantViewData as P, AssistantAppearance as Q, AssistantAppearanceWarning as R, AssistantAppearanceTheme as S, AssistantEvent as T, AssistantSurfaceAppearance as U, AssistantViewAvailableDetail as a, AssistantPageContext as b, AssistantContext as c, AssistantChatState as d, AssistantErrorDetail as e, AssistantChatError as f, AssistantClientContext as g, AssistantClientEvent as h, AssistantClientLifecycleEvent as i, AssistantConfirmationData as j, AssistantContentDetail as k, AssistantContentEvent as l, AssistantContextValue as m, AssistantDoneEvent as n, AssistantErrorEvent as o, AssistantErrorEventDetail as p, AssistantInputRequestData as q, AssistantInputRequestedDetail as r, AssistantInputRequestedEvent as s, AssistantInteractionResolvedDetail as t, AssistantInteractionResolvedEvent as u, AssistantInteractionResponse as v, AssistantInteractionStatus as w, AssistantJsonValue as x, AssistantModelContextUpdate as y, AssistantSessionResponse as z };
package/dist/client.cjs CHANGED
@@ -22617,6 +22617,7 @@ var AssistantChatStateStore = class {
22617
22617
  #messages = [];
22618
22618
  #status = "ready";
22619
22619
  #error;
22620
+ #suggestions;
22620
22621
  #operation;
22621
22622
  #nextId = 0;
22622
22623
  subscribe(listener) {
@@ -22628,20 +22629,24 @@ var AssistantChatStateStore = class {
22628
22629
  return structuredClone({
22629
22630
  status: this.#status,
22630
22631
  messages: this.#messages,
22632
+ ...this.#suggestions ? { suggestions: this.#suggestions } : {},
22631
22633
  ...this.#error ? { error: this.#error } : {}
22632
22634
  });
22633
22635
  }
22634
22636
  handle(event) {
22635
22637
  switch (event.event) {
22636
22638
  case "message_started":
22639
+ this.#suggestions = void 0;
22637
22640
  this.#beginMessage(event.data.message);
22638
22641
  return;
22639
22642
  case "interaction_started":
22643
+ this.#suggestions = void 0;
22640
22644
  this.#beginInteraction(event.data.id);
22641
22645
  return;
22642
22646
  case "resume_started":
22643
22647
  this.#status = "submitted";
22644
22648
  this.#error = void 0;
22649
+ this.#suggestions = void 0;
22645
22650
  this.#startOperation();
22646
22651
  this.#notify();
22647
22652
  return;
@@ -22674,6 +22679,13 @@ var AssistantChatStateStore = class {
22674
22679
  case "view_available":
22675
22680
  this.#writeData("view", event.data.id, event.data);
22676
22681
  return;
22682
+ case "suggested_prompts":
22683
+ this.#suggestions = {
22684
+ phase: event.data.phase,
22685
+ prompts: [...event.data.prompts]
22686
+ };
22687
+ this.#notify();
22688
+ return;
22677
22689
  case "message_completed":
22678
22690
  this.#closeOperation("ready");
22679
22691
  return;
@@ -22714,6 +22726,7 @@ var AssistantChatStateStore = class {
22714
22726
  this.#messages = [...this.#messages, userMessage];
22715
22727
  this.#status = "submitted";
22716
22728
  this.#error = void 0;
22729
+ this.#suggestions = void 0;
22717
22730
  this.#startOperation();
22718
22731
  this.#notify();
22719
22732
  }
@@ -23043,7 +23056,8 @@ var assistantUiSchema = external_exports.object({
23043
23056
  privacyUrl: httpsUrlSchema.optional(),
23044
23057
  termsUrl: httpsUrlSchema.optional(),
23045
23058
  locale: external_exports.string().trim().min(2).max(35).optional(),
23046
- direction: external_exports.enum(["ltr", "rtl", "auto"]).optional()
23059
+ direction: external_exports.enum(["ltr", "rtl", "auto"]).optional(),
23060
+ webmcp: external_exports.object({ enabled: external_exports.boolean().optional() }).strict().optional()
23047
23061
  }).strict();
23048
23062
  var assistantConfigurationSchema = external_exports.object({ branding: brandingSchema.optional(), assistant: assistantUiSchema.optional() }).strict();
23049
23063
  function parseAssistantConfiguration(value) {
@@ -23105,7 +23119,8 @@ function parseSession(value) {
23105
23119
  const apps = value.endpoints.apps;
23106
23120
  const sandbox = value.endpoints.sandbox;
23107
23121
  const transcript = value.endpoints.transcript;
23108
- if (typeof value.token !== "string" || typeof value.expiresAt !== "string" || typeof value.endpoints.turns !== "string" || typeof value.endpoints.toolConfirmations !== "string" || interactions !== void 0 && typeof interactions !== "string" || apps !== void 0 && typeof apps !== "string" || sandbox !== void 0 && typeof sandbox !== "string" || transcript !== void 0 && typeof transcript !== "string") {
23122
+ const suggestions = value.endpoints.suggestions;
23123
+ if (typeof value.token !== "string" || typeof value.expiresAt !== "string" || typeof value.endpoints.turns !== "string" || typeof value.endpoints.toolConfirmations !== "string" || interactions !== void 0 && typeof interactions !== "string" || apps !== void 0 && typeof apps !== "string" || sandbox !== void 0 && typeof sandbox !== "string" || transcript !== void 0 && typeof transcript !== "string" || suggestions !== void 0 && typeof suggestions !== "string") {
23109
23124
  throw clientError("session_failed", "Assistant session response is invalid", true);
23110
23125
  }
23111
23126
  const configuration = parseAssistantConfiguration(value.configuration);
@@ -23118,7 +23133,8 @@ function parseSession(value) {
23118
23133
  ...typeof interactions === "string" ? { interactions } : {},
23119
23134
  ...typeof apps === "string" ? { apps } : {},
23120
23135
  ...typeof sandbox === "string" ? { sandbox } : {},
23121
- ...typeof transcript === "string" ? { transcript } : {}
23136
+ ...typeof transcript === "string" ? { transcript } : {},
23137
+ ...typeof suggestions === "string" ? { suggestions } : {}
23122
23138
  },
23123
23139
  ...configuration === void 0 ? {} : { configuration },
23124
23140
  ...isRecord2(value.resume) && typeof value.resume.tool === "string" ? { resume: { tool: value.resume.tool } } : {}
@@ -23202,6 +23218,10 @@ function toAssistantClientEvent(event) {
23202
23218
  return event;
23203
23219
  }
23204
23220
  break;
23221
+ case "suggested_prompts":
23222
+ if (isSuggestedPromptsDetail(value))
23223
+ return event;
23224
+ break;
23205
23225
  case "done":
23206
23226
  if (hasOptionalTurnId(value)) return event;
23207
23227
  break;
@@ -23213,6 +23233,12 @@ function toAssistantClientEvent(event) {
23213
23233
  }
23214
23234
  return { event: "unrecognized", data: { name: event.event, payload: value } };
23215
23235
  }
23236
+ function isSuggestedPromptsDetail(value) {
23237
+ if (!isRecord3(value)) return false;
23238
+ return (value.phase === "initial" || value.phase === "follow_up") && Array.isArray(value.prompts) && value.prompts.length <= 3 && value.prompts.every(
23239
+ (prompt) => typeof prompt === "string" && prompt.trim().length > 0 && prompt.length <= 240
23240
+ ) && hasOptionalTurnId(value);
23241
+ }
23216
23242
  function isViewAvailableDetail(value) {
23217
23243
  return hasString(value, "id") && hasString(value, "tool") && typeof value.resourceUri === "string" && value.resourceUri.startsWith("ui://") && hasOptionalString(value.title) && (value.replayed === void 0 || value.replayed === true) && isJsonValue(value.result, 0) && hasOptionalJson(value.arguments) && hasOptionalString(value.html) && (value.resourceMeta === void 0 || isRecord3(value.resourceMeta)) && (value.allowedOpenDomains === void 0 || Array.isArray(value.allowedOpenDomains) && value.allowedOpenDomains.every(isHttpsUrl2)) && hasOptionalTurnId(value);
23218
23244
  }
@@ -23382,6 +23408,9 @@ function resolveSessionSource(options) {
23382
23408
  }
23383
23409
  return { kind: "exchange", url: sessionEndpoint };
23384
23410
  }
23411
+ function sessionSourceKey(options) {
23412
+ return `${options.embedId ?? ""}|${options.serviceUrl ?? ""}|${options.sessionEndpoint ?? ""}`;
23413
+ }
23385
23414
 
23386
23415
  // src/transcript-replay.ts
23387
23416
  function parseTranscriptEntries(value) {
@@ -23396,6 +23425,11 @@ function parseTranscriptEntries(value) {
23396
23425
  }
23397
23426
  return parsed;
23398
23427
  }
23428
+ function parseTranscriptSuggestions(value) {
23429
+ if (typeof value !== "object" || value === null) return void 0;
23430
+ const suggestions = value.suggestions;
23431
+ return isSuggestedPromptsDetail(suggestions) && suggestions.phase === "follow_up" ? { phase: suggestions.phase, prompts: suggestions.prompts } : void 0;
23432
+ }
23399
23433
  function transcriptReplayEvents(entries) {
23400
23434
  const events = [];
23401
23435
  let open = false;
@@ -23546,6 +23580,32 @@ function isAbortError2(error51) {
23546
23580
  return error51 instanceof DOMException && error51.name === "AbortError";
23547
23581
  }
23548
23582
 
23583
+ // src/visitor-id.ts
23584
+ var STORAGE_PREFIX = "noodleseed.assistant.visitor.";
23585
+ function randomVisitorId() {
23586
+ try {
23587
+ return globalThis.crypto.randomUUID();
23588
+ } catch {
23589
+ return void 0;
23590
+ }
23591
+ }
23592
+ function visitorIdForSource(sourceKey) {
23593
+ const key = `${STORAGE_PREFIX}${sourceKey}`;
23594
+ try {
23595
+ const stored = globalThis.localStorage?.getItem(key);
23596
+ if (typeof stored === "string" && stored.length > 0) return stored;
23597
+ } catch {
23598
+ return void 0;
23599
+ }
23600
+ const created = randomVisitorId();
23601
+ if (created === void 0) return void 0;
23602
+ try {
23603
+ globalThis.localStorage?.setItem(key, created);
23604
+ } catch {
23605
+ }
23606
+ return created;
23607
+ }
23608
+
23549
23609
  // src/client.ts
23550
23610
  var DefaultAssistantClient = class {
23551
23611
  #source;
@@ -23558,6 +23618,7 @@ var DefaultAssistantClient = class {
23558
23618
  #context;
23559
23619
  #modelContext;
23560
23620
  #active;
23621
+ #initialSuggestions;
23561
23622
  #pendingAppInteractions = /* @__PURE__ */ new Map();
23562
23623
  constructor(options) {
23563
23624
  this.#source = resolveSessionSource(options);
@@ -23619,10 +23680,13 @@ var DefaultAssistantClient = class {
23619
23680
  "turn_failed"
23620
23681
  );
23621
23682
  if (!response.ok) return;
23622
- for (const event of transcriptReplayEvents(parseTranscriptEntries(await response.json()))) {
23683
+ const value = await response.json();
23684
+ for (const event of transcriptReplayEvents(parseTranscriptEntries(value))) {
23623
23685
  this.#emit(event);
23624
23686
  if (event.event === "message_completed") await this.#chat.flush();
23625
23687
  }
23688
+ const suggestions = parseTranscriptSuggestions(value);
23689
+ if (suggestions) this.#emit({ event: "suggested_prompts", data: suggestions });
23626
23690
  }
23627
23691
  /** POST the one-shot resume trigger; a 409 means nothing was pending, which renders as silence. */
23628
23692
  async #resumeTurn(session, signal) {
@@ -23631,7 +23695,10 @@ var DefaultAssistantClient = class {
23631
23695
  {
23632
23696
  method: "POST",
23633
23697
  headers: authorizedHeaders(session.token, "text/event-stream"),
23634
- body: JSON.stringify({ resume: true }),
23698
+ body: JSON.stringify({
23699
+ resume: true,
23700
+ ...session.endpoints.suggestions ? { suggestions: true } : {}
23701
+ }),
23635
23702
  signal
23636
23703
  },
23637
23704
  "turn_failed"
@@ -23654,6 +23721,7 @@ var DefaultAssistantClient = class {
23654
23721
  async sendMessage(text2) {
23655
23722
  const message = text2.trim();
23656
23723
  if (!message) return;
23724
+ this.#cancelInitialSuggestions();
23657
23725
  await this.#singleFlight(async (signal) => {
23658
23726
  await this.#runChatOperation(
23659
23727
  signal,
@@ -23661,10 +23729,42 @@ var DefaultAssistantClient = class {
23661
23729
  );
23662
23730
  });
23663
23731
  }
23732
+ async loadInitialSuggestions() {
23733
+ if (!this.#session) await this.connect();
23734
+ const session = this.#session;
23735
+ if (!session?.endpoints.suggestions) return;
23736
+ if (this.#initialSuggestions) return this.#initialSuggestions.promise;
23737
+ const controller = new AbortController();
23738
+ const clientContext = this.#resolveClientContext();
23739
+ const pageContext = this.#resolvePageContext();
23740
+ const promise2 = this.#request(
23741
+ session.endpoints.suggestions,
23742
+ {
23743
+ method: "POST",
23744
+ headers: authorizedHeaders(session.token, "text/event-stream"),
23745
+ body: JSON.stringify({
23746
+ ...clientContext ? { clientContext } : {},
23747
+ ...pageContext === void 0 ? {} : { pageContext },
23748
+ ...this.#modelContext ? { modelContext: this.#modelContext } : {}
23749
+ }),
23750
+ signal: controller.signal
23751
+ },
23752
+ "turn_failed"
23753
+ ).then(async (response) => {
23754
+ if (response.ok) await this.#consume(response);
23755
+ }).finally(() => {
23756
+ if (this.#initialSuggestions?.controller === controller) {
23757
+ this.#initialSuggestions = void 0;
23758
+ }
23759
+ });
23760
+ this.#initialSuggestions = { controller, promise: promise2 };
23761
+ return promise2;
23762
+ }
23664
23763
  async respond(id, resolution) {
23665
23764
  if (!id) {
23666
23765
  throw clientError("invalid_request", "interaction id is required", false);
23667
23766
  }
23767
+ this.#cancelInitialSuggestions();
23668
23768
  await this.#singleFlight(async (signal) => {
23669
23769
  await this.#runChatOperation(signal, async () => {
23670
23770
  const pendingApp = this.#pendingAppInteractions.get(id);
@@ -23684,6 +23784,7 @@ var DefaultAssistantClient = class {
23684
23784
  const body = modernEndpoint ? {
23685
23785
  id,
23686
23786
  action: resolution.action,
23787
+ ...session.endpoints.suggestions ? { suggestions: true } : {},
23687
23788
  ...resolution.action === "accept" && resolution.content !== void 0 ? { content: resolution.content } : {}
23688
23789
  } : { id };
23689
23790
  this.#emit({ event: "interaction_started", data: { id, action: resolution.action } });
@@ -23762,7 +23863,7 @@ var DefaultAssistantClient = class {
23762
23863
  this.#modelContext = copyAssistantModelContext(update);
23763
23864
  this.#emit({ event: "model_context_changed", data: { modelContext: this.#modelContext } });
23764
23865
  }
23765
- async requestApp(method, params) {
23866
+ async requestApp(method, params, options) {
23766
23867
  const session = this.#session;
23767
23868
  if (!session?.endpoints.apps) {
23768
23869
  throw clientError(
@@ -23776,7 +23877,11 @@ var DefaultAssistantClient = class {
23776
23877
  {
23777
23878
  method: "POST",
23778
23879
  headers: authorizedHeaders(session.token, "application/json"),
23779
- body: JSON.stringify({ method, params })
23880
+ body: JSON.stringify({
23881
+ ...options?.bridge ? { bridge: options.bridge } : {},
23882
+ method,
23883
+ params
23884
+ })
23780
23885
  },
23781
23886
  "app_request_failed"
23782
23887
  );
@@ -23791,6 +23896,7 @@ var DefaultAssistantClient = class {
23791
23896
  const value = await response.json();
23792
23897
  const interaction = parseAppInteraction(value);
23793
23898
  if (!interaction) return value;
23899
+ options?.onSuspended?.();
23794
23900
  return new Promise((resolve2, reject) => {
23795
23901
  const id = interaction.data.id;
23796
23902
  const replaced = this.#pendingAppInteractions.get(id);
@@ -23808,6 +23914,7 @@ var DefaultAssistantClient = class {
23808
23914
  return this.#session?.endpoints.sandbox;
23809
23915
  }
23810
23916
  resetSession() {
23917
+ this.#cancelInitialSuggestions();
23811
23918
  this.#rejectPendingAppInteractions(
23812
23919
  clientError("confirmation_expired", "assistant session is not active", false)
23813
23920
  );
@@ -23816,6 +23923,7 @@ var DefaultAssistantClient = class {
23816
23923
  }
23817
23924
  abort() {
23818
23925
  this.#active?.abort();
23926
+ this.#cancelInitialSuggestions();
23819
23927
  }
23820
23928
  async #sendTurn(message, mayRetry, signal, modelContext) {
23821
23929
  const session = this.#session ?? await this.#createSession(signal);
@@ -23831,7 +23939,8 @@ var DefaultAssistantClient = class {
23831
23939
  message,
23832
23940
  ...clientContext ? { clientContext } : {},
23833
23941
  ...pageContext === void 0 ? {} : { pageContext },
23834
- ...modelContext ? { modelContext } : {}
23942
+ ...modelContext ? { modelContext } : {},
23943
+ ...session.endpoints.suggestions ? { suggestions: true } : {}
23835
23944
  }),
23836
23945
  signal
23837
23946
  },
@@ -23891,11 +24000,12 @@ var DefaultAssistantClient = class {
23891
24000
  }
23892
24001
  async #createSession(signal) {
23893
24002
  const source = this.#source;
24003
+ const visitorId = source.kind === "public" ? visitorIdForSource(sessionSourceKey({ embedId: source.embedId, serviceUrl: source.url })) : void 0;
23894
24004
  const response = await this.#requestSession(source, {
23895
24005
  method: "POST",
23896
24006
  headers: { Accept: "application/json", "Content-Type": "application/json" },
23897
24007
  body: JSON.stringify(
23898
- source.kind === "public" ? { embedId: source.embedId } : this.#context ? { context: this.#context } : {}
24008
+ source.kind === "public" ? { embedId: source.embedId, ...visitorId ? { visitorId } : {} } : this.#context ? { context: this.#context } : {}
23899
24009
  ),
23900
24010
  credentials: source.kind === "public" ? "omit" : "same-origin",
23901
24011
  signal
@@ -24020,6 +24130,9 @@ var DefaultAssistantClient = class {
24020
24130
  this.#active = void 0;
24021
24131
  }
24022
24132
  }
24133
+ #cancelInitialSuggestions() {
24134
+ this.#initialSuggestions?.controller.abort();
24135
+ }
24023
24136
  async #runChatOperation(signal, operation) {
24024
24137
  try {
24025
24138
  await operation();