@noodleseed/assistant 1.27.0 → 1.29.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 (41) 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-3VZ3M5BE.js} +92 -9
  6. package/dist/{chunk-WJV4MJUR.js.map → chunk-3VZ3M5BE.js.map} +1 -1
  7. package/dist/{chunk-2A3ZEYZV.js → chunk-DOWFW3KA.js} +260 -55
  8. package/dist/chunk-DOWFW3KA.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 +91 -8
  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 +47 -47
  17. package/dist/index.cjs +349 -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 +91 -8
  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 +349 -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-2A3ZEYZV.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { A as AssistantClient, a as AssistantViewAvailableDetail, e as AssistantErrorDetail } from './client-CPFw8tfo.js';
1
+ import { A as AssistantClient, a as AssistantViewAvailableDetail, e as AssistantErrorDetail } from './client-contract-Bw9dtrhw.cjs';
2
2
 
3
3
  declare const APP_VIEW_TAG_NAME = "noodle-app-view";
4
4
  interface AssistantAppViewErrorDetail {
@@ -1,4 +1,4 @@
1
- import { A as AssistantClient, a as AssistantViewAvailableDetail, e as AssistantErrorDetail } from './client-_xivfs4q.cjs';
1
+ import { A as AssistantClient, a as AssistantViewAvailableDetail, e as AssistantErrorDetail } from './client-contract-DjU9qsoP.js';
2
2
 
3
3
  declare const APP_VIEW_TAG_NAME = "noodle-app-view";
4
4
  interface AssistantAppViewErrorDetail {
@@ -1,7 +1,7 @@
1
- export { A as APP_VIEW_TAG_NAME, a as AssistantAppViewErrorDetail, N as NoodleAppViewElement } from './app-view-element-BjRkwNN1.cjs';
2
- export { A as AssistantClient, a as AssistantViewAvailableDetail } from './client-_xivfs4q.cjs';
3
- import './appearance-BpVu3lpk.cjs';
1
+ export { A as APP_VIEW_TAG_NAME, a as AssistantAppViewErrorDetail, N as NoodleAppViewElement } from './app-view-element-kR8eqhyD.cjs';
2
+ export { A as AssistantClient, a as AssistantViewAvailableDetail } from './client-contract-Bw9dtrhw.cjs';
4
3
  import 'ai';
4
+ import './server-CMqlAnxs.cjs';
5
5
 
6
6
  /** Register the framework-neutral MCP App host. Safe to call more than once or during SSR. */
7
7
  declare function registerNoodleAppView(): void;
@@ -1,7 +1,7 @@
1
- export { A as APP_VIEW_TAG_NAME, a as AssistantAppViewErrorDetail, N as NoodleAppViewElement } from './app-view-element-mXHvcAXc.js';
2
- export { A as AssistantClient, a as AssistantViewAvailableDetail } from './client-CPFw8tfo.js';
3
- import './appearance-BpVu3lpk.js';
1
+ export { A as APP_VIEW_TAG_NAME, a as AssistantAppViewErrorDetail, N as NoodleAppViewElement } from './app-view-element-nY1svwHT.js';
2
+ export { A as AssistantClient, a as AssistantViewAvailableDetail } from './client-contract-DjU9qsoP.js';
4
3
  import 'ai';
4
+ import './server-CMqlAnxs.js';
5
5
 
6
6
  /** Register the framework-neutral MCP App host. Safe to call more than once or during SSR. */
7
7
  declare function registerNoodleAppView(): void;
@@ -4209,6 +4209,7 @@ var AssistantChatStateStore = class {
4209
4209
  #messages = [];
4210
4210
  #status = "ready";
4211
4211
  #error;
4212
+ #suggestions;
4212
4213
  #operation;
4213
4214
  #nextId = 0;
4214
4215
  subscribe(listener) {
@@ -4220,20 +4221,24 @@ var AssistantChatStateStore = class {
4220
4221
  return structuredClone({
4221
4222
  status: this.#status,
4222
4223
  messages: this.#messages,
4224
+ ...this.#suggestions ? { suggestions: this.#suggestions } : {},
4223
4225
  ...this.#error ? { error: this.#error } : {}
4224
4226
  });
4225
4227
  }
4226
4228
  handle(event) {
4227
4229
  switch (event.event) {
4228
4230
  case "message_started":
4231
+ this.#suggestions = void 0;
4229
4232
  this.#beginMessage(event.data.message);
4230
4233
  return;
4231
4234
  case "interaction_started":
4235
+ this.#suggestions = void 0;
4232
4236
  this.#beginInteraction(event.data.id);
4233
4237
  return;
4234
4238
  case "resume_started":
4235
4239
  this.#status = "submitted";
4236
4240
  this.#error = void 0;
4241
+ this.#suggestions = void 0;
4237
4242
  this.#startOperation();
4238
4243
  this.#notify();
4239
4244
  return;
@@ -4266,6 +4271,13 @@ var AssistantChatStateStore = class {
4266
4271
  case "view_available":
4267
4272
  this.#writeData("view", event.data.id, event.data);
4268
4273
  return;
4274
+ case "suggested_prompts":
4275
+ this.#suggestions = {
4276
+ phase: event.data.phase,
4277
+ prompts: [...event.data.prompts]
4278
+ };
4279
+ this.#notify();
4280
+ return;
4269
4281
  case "message_completed":
4270
4282
  this.#closeOperation("ready");
4271
4283
  return;
@@ -4306,6 +4318,7 @@ var AssistantChatStateStore = class {
4306
4318
  this.#messages = [...this.#messages, userMessage];
4307
4319
  this.#status = "submitted";
4308
4320
  this.#error = void 0;
4321
+ this.#suggestions = void 0;
4309
4322
  this.#startOperation();
4310
4323
  this.#notify();
4311
4324
  }
@@ -4635,7 +4648,8 @@ var assistantUiSchema = external_exports.object({
4635
4648
  privacyUrl: httpsUrlSchema.optional(),
4636
4649
  termsUrl: httpsUrlSchema.optional(),
4637
4650
  locale: external_exports.string().trim().min(2).max(35).optional(),
4638
- direction: external_exports.enum(["ltr", "rtl", "auto"]).optional()
4651
+ direction: external_exports.enum(["ltr", "rtl", "auto"]).optional(),
4652
+ webmcp: external_exports.object({ enabled: external_exports.boolean().optional() }).strict().optional()
4639
4653
  }).strict();
4640
4654
  var assistantConfigurationSchema = external_exports.object({ branding: brandingSchema.optional(), assistant: assistantUiSchema.optional() }).strict();
4641
4655
  function parseAssistantConfiguration(value) {
@@ -4697,7 +4711,8 @@ function parseSession(value) {
4697
4711
  const apps = value.endpoints.apps;
4698
4712
  const sandbox = value.endpoints.sandbox;
4699
4713
  const transcript = value.endpoints.transcript;
4700
- 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") {
4714
+ const suggestions = value.endpoints.suggestions;
4715
+ 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") {
4701
4716
  throw clientError("session_failed", "Assistant session response is invalid", true);
4702
4717
  }
4703
4718
  const configuration = parseAssistantConfiguration(value.configuration);
@@ -4710,7 +4725,8 @@ function parseSession(value) {
4710
4725
  ...typeof interactions === "string" ? { interactions } : {},
4711
4726
  ...typeof apps === "string" ? { apps } : {},
4712
4727
  ...typeof sandbox === "string" ? { sandbox } : {},
4713
- ...typeof transcript === "string" ? { transcript } : {}
4728
+ ...typeof transcript === "string" ? { transcript } : {},
4729
+ ...typeof suggestions === "string" ? { suggestions } : {}
4714
4730
  },
4715
4731
  ...configuration === void 0 ? {} : { configuration },
4716
4732
  ...isRecord2(value.resume) && typeof value.resume.tool === "string" ? { resume: { tool: value.resume.tool } } : {}
@@ -4794,6 +4810,10 @@ function toAssistantClientEvent(event) {
4794
4810
  return event;
4795
4811
  }
4796
4812
  break;
4813
+ case "suggested_prompts":
4814
+ if (isSuggestedPromptsDetail(value))
4815
+ return event;
4816
+ break;
4797
4817
  case "done":
4798
4818
  if (hasOptionalTurnId(value)) return event;
4799
4819
  break;
@@ -4805,6 +4825,12 @@ function toAssistantClientEvent(event) {
4805
4825
  }
4806
4826
  return { event: "unrecognized", data: { name: event.event, payload: value } };
4807
4827
  }
4828
+ function isSuggestedPromptsDetail(value) {
4829
+ if (!isRecord3(value)) return false;
4830
+ return (value.phase === "initial" || value.phase === "follow_up") && Array.isArray(value.prompts) && value.prompts.length <= 3 && value.prompts.every(
4831
+ (prompt) => typeof prompt === "string" && prompt.trim().length > 0 && prompt.length <= 240
4832
+ ) && hasOptionalTurnId(value);
4833
+ }
4808
4834
  function isViewAvailableDetail(value) {
4809
4835
  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);
4810
4836
  }
@@ -4996,6 +5022,11 @@ function parseTranscriptEntries(value) {
4996
5022
  }
4997
5023
  return parsed;
4998
5024
  }
5025
+ function parseTranscriptSuggestions(value) {
5026
+ if (typeof value !== "object" || value === null) return void 0;
5027
+ const suggestions = value.suggestions;
5028
+ return isSuggestedPromptsDetail(suggestions) && suggestions.phase === "follow_up" ? { phase: suggestions.phase, prompts: suggestions.prompts } : void 0;
5029
+ }
4999
5030
  function transcriptReplayEvents(entries) {
5000
5031
  const events = [];
5001
5032
  let open = false;
@@ -5158,6 +5189,7 @@ var DefaultAssistantClient = class {
5158
5189
  #context;
5159
5190
  #modelContext;
5160
5191
  #active;
5192
+ #initialSuggestions;
5161
5193
  #pendingAppInteractions = /* @__PURE__ */ new Map();
5162
5194
  constructor(options) {
5163
5195
  this.#source = resolveSessionSource(options);
@@ -5219,10 +5251,13 @@ var DefaultAssistantClient = class {
5219
5251
  "turn_failed"
5220
5252
  );
5221
5253
  if (!response.ok) return;
5222
- for (const event of transcriptReplayEvents(parseTranscriptEntries(await response.json()))) {
5254
+ const value = await response.json();
5255
+ for (const event of transcriptReplayEvents(parseTranscriptEntries(value))) {
5223
5256
  this.#emit(event);
5224
5257
  if (event.event === "message_completed") await this.#chat.flush();
5225
5258
  }
5259
+ const suggestions = parseTranscriptSuggestions(value);
5260
+ if (suggestions) this.#emit({ event: "suggested_prompts", data: suggestions });
5226
5261
  }
5227
5262
  /** POST the one-shot resume trigger; a 409 means nothing was pending, which renders as silence. */
5228
5263
  async #resumeTurn(session, signal) {
@@ -5231,7 +5266,10 @@ var DefaultAssistantClient = class {
5231
5266
  {
5232
5267
  method: "POST",
5233
5268
  headers: authorizedHeaders(session.token, "text/event-stream"),
5234
- body: JSON.stringify({ resume: true }),
5269
+ body: JSON.stringify({
5270
+ resume: true,
5271
+ ...session.endpoints.suggestions ? { suggestions: true } : {}
5272
+ }),
5235
5273
  signal
5236
5274
  },
5237
5275
  "turn_failed"
@@ -5254,6 +5292,7 @@ var DefaultAssistantClient = class {
5254
5292
  async sendMessage(text2) {
5255
5293
  const message = text2.trim();
5256
5294
  if (!message) return;
5295
+ this.#cancelInitialSuggestions();
5257
5296
  await this.#singleFlight(async (signal) => {
5258
5297
  await this.#runChatOperation(
5259
5298
  signal,
@@ -5261,10 +5300,42 @@ var DefaultAssistantClient = class {
5261
5300
  );
5262
5301
  });
5263
5302
  }
5303
+ async loadInitialSuggestions() {
5304
+ if (!this.#session) await this.connect();
5305
+ const session = this.#session;
5306
+ if (!session?.endpoints.suggestions) return;
5307
+ if (this.#initialSuggestions) return this.#initialSuggestions.promise;
5308
+ const controller = new AbortController();
5309
+ const clientContext = this.#resolveClientContext();
5310
+ const pageContext = this.#resolvePageContext();
5311
+ const promise = this.#request(
5312
+ session.endpoints.suggestions,
5313
+ {
5314
+ method: "POST",
5315
+ headers: authorizedHeaders(session.token, "text/event-stream"),
5316
+ body: JSON.stringify({
5317
+ ...clientContext ? { clientContext } : {},
5318
+ ...pageContext === void 0 ? {} : { pageContext },
5319
+ ...this.#modelContext ? { modelContext: this.#modelContext } : {}
5320
+ }),
5321
+ signal: controller.signal
5322
+ },
5323
+ "turn_failed"
5324
+ ).then(async (response) => {
5325
+ if (response.ok) await this.#consume(response);
5326
+ }).finally(() => {
5327
+ if (this.#initialSuggestions?.controller === controller) {
5328
+ this.#initialSuggestions = void 0;
5329
+ }
5330
+ });
5331
+ this.#initialSuggestions = { controller, promise };
5332
+ return promise;
5333
+ }
5264
5334
  async respond(id, resolution) {
5265
5335
  if (!id) {
5266
5336
  throw clientError("invalid_request", "interaction id is required", false);
5267
5337
  }
5338
+ this.#cancelInitialSuggestions();
5268
5339
  await this.#singleFlight(async (signal) => {
5269
5340
  await this.#runChatOperation(signal, async () => {
5270
5341
  const pendingApp = this.#pendingAppInteractions.get(id);
@@ -5284,6 +5355,7 @@ var DefaultAssistantClient = class {
5284
5355
  const body = modernEndpoint ? {
5285
5356
  id,
5286
5357
  action: resolution.action,
5358
+ ...session.endpoints.suggestions ? { suggestions: true } : {},
5287
5359
  ...resolution.action === "accept" && resolution.content !== void 0 ? { content: resolution.content } : {}
5288
5360
  } : { id };
5289
5361
  this.#emit({ event: "interaction_started", data: { id, action: resolution.action } });
@@ -5362,7 +5434,7 @@ var DefaultAssistantClient = class {
5362
5434
  this.#modelContext = copyAssistantModelContext(update);
5363
5435
  this.#emit({ event: "model_context_changed", data: { modelContext: this.#modelContext } });
5364
5436
  }
5365
- async requestApp(method, params) {
5437
+ async requestApp(method, params, options) {
5366
5438
  const session = this.#session;
5367
5439
  if (!session?.endpoints.apps) {
5368
5440
  throw clientError(
@@ -5376,7 +5448,11 @@ var DefaultAssistantClient = class {
5376
5448
  {
5377
5449
  method: "POST",
5378
5450
  headers: authorizedHeaders(session.token, "application/json"),
5379
- body: JSON.stringify({ method, params })
5451
+ body: JSON.stringify({
5452
+ ...options?.bridge ? { bridge: options.bridge } : {},
5453
+ method,
5454
+ params
5455
+ })
5380
5456
  },
5381
5457
  "app_request_failed"
5382
5458
  );
@@ -5391,6 +5467,7 @@ var DefaultAssistantClient = class {
5391
5467
  const value = await response.json();
5392
5468
  const interaction = parseAppInteraction(value);
5393
5469
  if (!interaction) return value;
5470
+ options?.onSuspended?.();
5394
5471
  return new Promise((resolve2, reject) => {
5395
5472
  const id = interaction.data.id;
5396
5473
  const replaced = this.#pendingAppInteractions.get(id);
@@ -5408,6 +5485,7 @@ var DefaultAssistantClient = class {
5408
5485
  return this.#session?.endpoints.sandbox;
5409
5486
  }
5410
5487
  resetSession() {
5488
+ this.#cancelInitialSuggestions();
5411
5489
  this.#rejectPendingAppInteractions(
5412
5490
  clientError("confirmation_expired", "assistant session is not active", false)
5413
5491
  );
@@ -5416,6 +5494,7 @@ var DefaultAssistantClient = class {
5416
5494
  }
5417
5495
  abort() {
5418
5496
  this.#active?.abort();
5497
+ this.#cancelInitialSuggestions();
5419
5498
  }
5420
5499
  async #sendTurn(message, mayRetry, signal, modelContext) {
5421
5500
  const session = this.#session ?? await this.#createSession(signal);
@@ -5431,7 +5510,8 @@ var DefaultAssistantClient = class {
5431
5510
  message,
5432
5511
  ...clientContext ? { clientContext } : {},
5433
5512
  ...pageContext === void 0 ? {} : { pageContext },
5434
- ...modelContext ? { modelContext } : {}
5513
+ ...modelContext ? { modelContext } : {},
5514
+ ...session.endpoints.suggestions ? { suggestions: true } : {}
5435
5515
  }),
5436
5516
  signal
5437
5517
  },
@@ -5620,6 +5700,9 @@ var DefaultAssistantClient = class {
5620
5700
  this.#active = void 0;
5621
5701
  }
5622
5702
  }
5703
+ #cancelInitialSuggestions() {
5704
+ this.#initialSuggestions?.controller.abort();
5705
+ }
5623
5706
  async #runChatOperation(signal, operation) {
5624
5707
  try {
5625
5708
  await operation();
@@ -5688,4 +5771,4 @@ export {
5688
5771
  sessionSourceKey,
5689
5772
  createAssistantClient
5690
5773
  };
5691
- //# sourceMappingURL=chunk-WJV4MJUR.js.map
5774
+ //# sourceMappingURL=chunk-3VZ3M5BE.js.map