@noodleseed/assistant 1.19.0 → 1.21.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/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { d as AssistantViewAvailableDetail, f as AssistantClientEvent, a as AssistantContext, e as AssistantModelContextUpdate, A as AssistantPageContext, h as AssistantInteractionResponse } from './client-BQ30Fq-c.cjs';
2
- export { g as AssistantErrorDetail, i as AssistantEvent, j as AssistantViewAvailableEvent } from './client-BQ30Fq-c.cjs';
1
+ import { d as AssistantViewAvailableDetail, f as AssistantClientEvent, a as AssistantContext, e as AssistantModelContextUpdate, A as AssistantPageContext, h as AssistantInteractionResponse } from './client-BZ7xPwfW.cjs';
2
+ export { g as AssistantErrorDetail, i as AssistantEvent, j as AssistantViewAvailableEvent } from './client-BZ7xPwfW.cjs';
3
3
  import './appearance-Cc-eqSbp.cjs';
4
4
  import 'ai';
5
5
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { d as AssistantViewAvailableDetail, f as AssistantClientEvent, a as AssistantContext, e as AssistantModelContextUpdate, A as AssistantPageContext, h as AssistantInteractionResponse } from './client-B6pnBmF8.js';
2
- export { g as AssistantErrorDetail, i as AssistantEvent, j as AssistantViewAvailableEvent } from './client-B6pnBmF8.js';
1
+ import { d as AssistantViewAvailableDetail, f as AssistantClientEvent, a as AssistantContext, e as AssistantModelContextUpdate, A as AssistantPageContext, h as AssistantInteractionResponse } from './client-BkJlpN5N.js';
2
+ export { g as AssistantErrorDetail, i as AssistantEvent, j as AssistantViewAvailableEvent } from './client-BkJlpN5N.js';
3
3
  import './appearance-Cc-eqSbp.js';
4
4
  import 'ai';
5
5
 
package/dist/index.js CHANGED
@@ -2,8 +2,8 @@ import {
2
2
  ASSISTANT_TAG_NAME,
3
3
  NoodleAssistantElement,
4
4
  registerNoodleAssistant
5
- } from "./chunk-RFETV5KQ.js";
6
- import "./chunk-S373FCAI.js";
5
+ } from "./chunk-LEKEIHJV.js";
6
+ import "./chunk-ZPZHPXIQ.js";
7
7
  import "./chunk-3YYTUJPJ.js";
8
8
  import "./chunk-5FUTL2UF.js";
9
9
 
@@ -22640,6 +22640,12 @@ var AssistantChatStateStore = class {
22640
22640
  case "interaction_started":
22641
22641
  this.#beginInteraction(event.data.id);
22642
22642
  return;
22643
+ case "resume_started":
22644
+ this.#status = "submitted";
22645
+ this.#error = void 0;
22646
+ this.#startOperation();
22647
+ this.#notify();
22648
+ return;
22643
22649
  case "content":
22644
22650
  this.#writeText(event.data.delta);
22645
22651
  return;
@@ -22895,6 +22901,78 @@ function isRecord(value) {
22895
22901
  return typeof value === "object" && value !== null && !Array.isArray(value);
22896
22902
  }
22897
22903
 
22904
+ // src/client-errors.ts
22905
+ async function refusalCode(response) {
22906
+ try {
22907
+ const body = await response.clone().json();
22908
+ const code = body.code;
22909
+ return typeof code === "string" ? code : void 0;
22910
+ } catch {
22911
+ return void 0;
22912
+ }
22913
+ }
22914
+ var UNRETRYABLE_SERVICE_CODES = /* @__PURE__ */ new Set([
22915
+ "daily_turn_budget_exhausted",
22916
+ "daily_session_budget_exhausted"
22917
+ ]);
22918
+ var AssistantClientError = class extends Error {
22919
+ detail;
22920
+ constructor(detail, message, options) {
22921
+ super(message, options);
22922
+ this.name = "AssistantClientError";
22923
+ this.detail = detail;
22924
+ }
22925
+ };
22926
+ function parseSession(value) {
22927
+ if (!isRecord2(value) || !isRecord2(value.endpoints)) {
22928
+ throw clientError("session_failed", "Assistant session response is invalid", true);
22929
+ }
22930
+ const interactions = value.endpoints.interactions;
22931
+ const apps = value.endpoints.apps;
22932
+ const sandbox = value.endpoints.sandbox;
22933
+ 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") {
22934
+ throw clientError("session_failed", "Assistant session response is invalid", true);
22935
+ }
22936
+ return {
22937
+ token: value.token,
22938
+ expiresAt: value.expiresAt,
22939
+ endpoints: {
22940
+ turns: value.endpoints.turns,
22941
+ toolConfirmations: value.endpoints.toolConfirmations,
22942
+ ...typeof interactions === "string" ? { interactions } : {},
22943
+ ...typeof apps === "string" ? { apps } : {},
22944
+ ...typeof sandbox === "string" ? { sandbox } : {}
22945
+ },
22946
+ ...isRecord2(value.configuration) ? { configuration: value.configuration } : {},
22947
+ ...isRecord2(value.resume) && typeof value.resume.tool === "string" ? { resume: { tool: value.resume.tool } } : {}
22948
+ };
22949
+ }
22950
+ function isRecord2(value) {
22951
+ return typeof value === "object" && value !== null && !Array.isArray(value);
22952
+ }
22953
+ async function readStableErrorCode(response) {
22954
+ let value;
22955
+ try {
22956
+ value = await response.json();
22957
+ } catch {
22958
+ return void 0;
22959
+ }
22960
+ if (!isRecord2(value) || typeof value.code !== "string") return void 0;
22961
+ return /^[A-Za-z0-9_.-]{1,64}$/.test(value.code) ? value.code : void 0;
22962
+ }
22963
+ function clientError(code, message, retryable, status, options, serviceCode) {
22964
+ return new AssistantClientError(
22965
+ {
22966
+ code,
22967
+ ...status === void 0 ? {} : { status },
22968
+ retryable,
22969
+ ...serviceCode === void 0 ? {} : { serviceCode }
22970
+ },
22971
+ message,
22972
+ options
22973
+ );
22974
+ }
22975
+
22898
22976
  // src/events.ts
22899
22977
  function toAssistantClientEvent(event) {
22900
22978
  const value = event.data;
@@ -22910,20 +22988,25 @@ function toAssistantClientEvent(event) {
22910
22988
  }
22911
22989
  break;
22912
22990
  case "tool_proposed":
22913
- if (hasString(value, "id") && hasString(value, "tool") && hasOptionalString(value.title) && hasOptionalString(value.description) && hasOptionalJson(value.arguments) && (value.reviewSchema === void 0 || isRecord2(value.reviewSchema)) && hasOptionalString(value.expiresAt) && (value.requiresConfirmation === void 0 || value.requiresConfirmation === true) && hasOptionalTurnId(value)) {
22991
+ if (hasString(value, "id") && hasString(value, "tool") && hasOptionalString(value.title) && hasOptionalString(value.description) && hasOptionalJson(value.arguments) && (value.reviewSchema === void 0 || isRecord3(value.reviewSchema)) && hasOptionalString(value.expiresAt) && (value.requiresConfirmation === void 0 || value.requiresConfirmation === true) && hasOptionalTurnId(value)) {
22914
22992
  return event;
22915
22993
  }
22916
22994
  break;
22917
22995
  case "input_requested":
22918
- if (hasString(value, "id") && hasString(value, "message") && isRecord2(value.requestedSchema) && hasString(value, "expiresAt") && hasOptionalTurnId(value)) {
22996
+ if (hasString(value, "id") && hasString(value, "message") && isRecord3(value.requestedSchema) && hasString(value, "expiresAt") && hasOptionalTurnId(value)) {
22919
22997
  return event;
22920
22998
  }
22921
22999
  break;
22922
- case "auth_requested":
22923
- if (hasString(value, "id") && hasString(value, "tool") && hasString(value, "continuation") && hasString(value, "expiresAt") && hasOptionalTurnId(value)) {
22924
- return event;
23000
+ case "auth_requested": {
23001
+ const signInTicket = typeof value.signInTicket === "string" ? value.signInTicket : typeof value.continuation === "string" ? value.continuation : void 0;
23002
+ if (hasString(value, "id") && hasString(value, "tool") && signInTicket !== void 0 && hasString(value, "expiresAt") && hasOptionalTurnId(value)) {
23003
+ return {
23004
+ event: "auth_requested",
23005
+ data: { ...value, signInTicket }
23006
+ };
22925
23007
  }
22926
23008
  break;
23009
+ }
22927
23010
  case "interaction_resolved":
22928
23011
  if (hasString(value, "id") && (value.action === void 0 || isInteractionAction(value.action)) && hasOptionalTurnId(value)) {
22929
23012
  return event;
@@ -22954,7 +23037,7 @@ function toAssistantClientEvent(event) {
22954
23037
  return { event: "unrecognized", data: { name: event.event, payload: value } };
22955
23038
  }
22956
23039
  function isViewAvailableDetail(value) {
22957
- 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 || isRecord2(value.resourceMeta)) && (value.allowedOpenDomains === void 0 || Array.isArray(value.allowedOpenDomains) && value.allowedOpenDomains.every(isHttpsUrl)) && hasOptionalTurnId(value);
23040
+ 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(isHttpsUrl)) && hasOptionalTurnId(value);
22958
23041
  }
22959
23042
  function isHttpsUrl(value) {
22960
23043
  if (typeof value !== "string") return false;
@@ -22987,11 +23070,11 @@ function isJsonValue(value, depth) {
22987
23070
  if (Array.isArray(value)) {
22988
23071
  return value.length <= 256 && value.every((entry) => isJsonValue(entry, depth + 1));
22989
23072
  }
22990
- if (!isRecord2(value)) return false;
23073
+ if (!isRecord3(value)) return false;
22991
23074
  const entries = Object.entries(value);
22992
23075
  return entries.length <= 256 && entries.every(([, entry]) => isJsonValue(entry, depth + 1));
22993
23076
  }
22994
- function isRecord2(value) {
23077
+ function isRecord3(value) {
22995
23078
  return typeof value === "object" && value !== null && !Array.isArray(value);
22996
23079
  }
22997
23080
 
@@ -23231,15 +23314,15 @@ function parseFrame(frame) {
23231
23314
  if (event === "done" && !isValidDonePayload(parsed)) {
23232
23315
  throw invalidStream("assistant event stream contained an invalid done event");
23233
23316
  }
23234
- return { event, data: isRecord3(parsed) ? parsed : { value: parsed } };
23317
+ return { event, data: isRecord4(parsed) ? parsed : { value: parsed } };
23235
23318
  }
23236
23319
  function normalizeLineEndings(input) {
23237
23320
  return input.replaceAll("\r\n", "\n").replaceAll("\r", "\n");
23238
23321
  }
23239
23322
  function isValidDonePayload(value) {
23240
- return isRecord3(value) && (value.turnId === void 0 || typeof value.turnId === "string" && value.turnId.length > 0);
23323
+ return isRecord4(value) && (value.turnId === void 0 || typeof value.turnId === "string" && value.turnId.length > 0);
23241
23324
  }
23242
- function isRecord3(value) {
23325
+ function isRecord4(value) {
23243
23326
  return typeof value === "object" && value !== null && !Array.isArray(value);
23244
23327
  }
23245
23328
  function invalidStream(message, cause) {
@@ -23250,27 +23333,6 @@ function isAbortError2(error51) {
23250
23333
  }
23251
23334
 
23252
23335
  // src/client.ts
23253
- async function refusalCode(response) {
23254
- try {
23255
- const body = await response.clone().json();
23256
- const code = body.code;
23257
- return typeof code === "string" ? code : void 0;
23258
- } catch {
23259
- return void 0;
23260
- }
23261
- }
23262
- var UNRETRYABLE_SERVICE_CODES = /* @__PURE__ */ new Set([
23263
- "daily_turn_budget_exhausted",
23264
- "daily_session_budget_exhausted"
23265
- ]);
23266
- var AssistantClientError = class extends Error {
23267
- detail;
23268
- constructor(detail, message, options) {
23269
- super(message, options);
23270
- this.name = "AssistantClientError";
23271
- this.detail = detail;
23272
- }
23273
- };
23274
23336
  var DefaultAssistantClient = class {
23275
23337
  #source;
23276
23338
  #fetch;
@@ -23305,12 +23367,50 @@ var DefaultAssistantClient = class {
23305
23367
  hasSession() {
23306
23368
  return this.#session !== void 0;
23307
23369
  }
23370
+ /** Whether a request holds the single-flight slot, so callers can refuse before mutating UI. */
23371
+ isBusy() {
23372
+ return this.#active !== void 0;
23373
+ }
23308
23374
  async connect() {
23309
23375
  if (this.#session) return;
23310
23376
  await this.#singleFlight(async (signal) => {
23311
- if (!this.#session) await this.#createSession(signal);
23377
+ if (this.#session) return;
23378
+ const session = await this.#createSession(signal);
23379
+ if (session.resume) {
23380
+ try {
23381
+ await this.#runChatOperation(signal, () => this.#resumeTurn(session, signal));
23382
+ } catch {
23383
+ }
23384
+ }
23312
23385
  });
23313
23386
  }
23387
+ /** POST the one-shot resume trigger; a 409 means nothing was pending, which renders as silence. */
23388
+ async #resumeTurn(session, signal) {
23389
+ const response = await this.#request(
23390
+ session.endpoints.turns,
23391
+ {
23392
+ method: "POST",
23393
+ headers: authorizedHeaders(session.token, "text/event-stream"),
23394
+ body: JSON.stringify({ resume: true }),
23395
+ signal
23396
+ },
23397
+ "turn_failed"
23398
+ );
23399
+ if (response.status === 409) return;
23400
+ if (!response.ok) {
23401
+ throw clientError(
23402
+ "turn_failed",
23403
+ `Assistant turn failed (${response.status})`,
23404
+ false,
23405
+ response.status,
23406
+ void 0,
23407
+ await refusalCode(response)
23408
+ );
23409
+ }
23410
+ this.#emit({ event: "resume_started", data: { tool: session.resume?.tool ?? "" } });
23411
+ await this.#consume(response);
23412
+ this.#emit({ event: "message_completed", data: {} });
23413
+ }
23314
23414
  async sendMessage(text2) {
23315
23415
  const message = text2.trim();
23316
23416
  if (!message) return;
@@ -23715,10 +23815,10 @@ function authorizedHeaders(token, accept) {
23715
23815
  };
23716
23816
  }
23717
23817
  function parseAppInteraction(value) {
23718
- if (!isRecord4(value) || !isRecord4(value.interaction)) return void 0;
23818
+ if (!isRecord2(value) || !isRecord2(value.interaction)) return void 0;
23719
23819
  const event = value.interaction.event;
23720
23820
  const data = value.interaction.data;
23721
- if (event !== "tool_proposed" && event !== "input_requested" || !isRecord4(data)) {
23821
+ if (event !== "tool_proposed" && event !== "input_requested" || !isRecord2(data)) {
23722
23822
  return void 0;
23723
23823
  }
23724
23824
  const parsed = toAssistantClientEvent({ event, data });
@@ -23738,54 +23838,6 @@ function appInteractionStopped(action) {
23738
23838
  isError: true
23739
23839
  };
23740
23840
  }
23741
- function parseSession(value) {
23742
- if (!isRecord4(value) || !isRecord4(value.endpoints)) {
23743
- throw clientError("session_failed", "Assistant session response is invalid", true);
23744
- }
23745
- const interactions = value.endpoints.interactions;
23746
- const apps = value.endpoints.apps;
23747
- const sandbox = value.endpoints.sandbox;
23748
- 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") {
23749
- throw clientError("session_failed", "Assistant session response is invalid", true);
23750
- }
23751
- return {
23752
- token: value.token,
23753
- expiresAt: value.expiresAt,
23754
- endpoints: {
23755
- turns: value.endpoints.turns,
23756
- toolConfirmations: value.endpoints.toolConfirmations,
23757
- ...typeof interactions === "string" ? { interactions } : {},
23758
- ...typeof apps === "string" ? { apps } : {},
23759
- ...typeof sandbox === "string" ? { sandbox } : {}
23760
- },
23761
- ...isRecord4(value.configuration) ? { configuration: value.configuration } : {}
23762
- };
23763
- }
23764
- function isRecord4(value) {
23765
- return typeof value === "object" && value !== null && !Array.isArray(value);
23766
- }
23767
- async function readStableErrorCode(response) {
23768
- let value;
23769
- try {
23770
- value = await response.json();
23771
- } catch {
23772
- return void 0;
23773
- }
23774
- if (!isRecord4(value) || typeof value.code !== "string") return void 0;
23775
- return /^[A-Za-z0-9_.-]{1,64}$/.test(value.code) ? value.code : void 0;
23776
- }
23777
- function clientError(code, message, retryable, status, options, serviceCode) {
23778
- return new AssistantClientError(
23779
- {
23780
- code,
23781
- ...status === void 0 ? {} : { status },
23782
- retryable,
23783
- ...serviceCode === void 0 ? {} : { serviceCode }
23784
- },
23785
- message,
23786
- options
23787
- );
23788
- }
23789
23841
 
23790
23842
  // src/react-client.ts
23791
23843
  var useCommittedLayoutEffect = typeof window === "undefined" ? import_react.useEffect : import_react.useLayoutEffect;