@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.
@@ -8104,6 +8104,12 @@ var AssistantChatStateStore = class {
8104
8104
  case "interaction_started":
8105
8105
  this.#beginInteraction(event.data.id);
8106
8106
  return;
8107
+ case "resume_started":
8108
+ this.#status = "submitted";
8109
+ this.#error = void 0;
8110
+ this.#startOperation();
8111
+ this.#notify();
8112
+ return;
8107
8113
  case "content":
8108
8114
  this.#writeText(event.data.delta);
8109
8115
  return;
@@ -8359,6 +8365,78 @@ function isRecord(value) {
8359
8365
  return typeof value === "object" && value !== null && !Array.isArray(value);
8360
8366
  }
8361
8367
 
8368
+ // src/client-errors.ts
8369
+ async function refusalCode(response) {
8370
+ try {
8371
+ const body = await response.clone().json();
8372
+ const code = body.code;
8373
+ return typeof code === "string" ? code : void 0;
8374
+ } catch {
8375
+ return void 0;
8376
+ }
8377
+ }
8378
+ var UNRETRYABLE_SERVICE_CODES = /* @__PURE__ */ new Set([
8379
+ "daily_turn_budget_exhausted",
8380
+ "daily_session_budget_exhausted"
8381
+ ]);
8382
+ var AssistantClientError = class extends Error {
8383
+ detail;
8384
+ constructor(detail, message, options) {
8385
+ super(message, options);
8386
+ this.name = "AssistantClientError";
8387
+ this.detail = detail;
8388
+ }
8389
+ };
8390
+ function parseSession(value) {
8391
+ if (!isRecord2(value) || !isRecord2(value.endpoints)) {
8392
+ throw clientError("session_failed", "Assistant session response is invalid", true);
8393
+ }
8394
+ const interactions = value.endpoints.interactions;
8395
+ const apps = value.endpoints.apps;
8396
+ const sandbox = value.endpoints.sandbox;
8397
+ 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") {
8398
+ throw clientError("session_failed", "Assistant session response is invalid", true);
8399
+ }
8400
+ return {
8401
+ token: value.token,
8402
+ expiresAt: value.expiresAt,
8403
+ endpoints: {
8404
+ turns: value.endpoints.turns,
8405
+ toolConfirmations: value.endpoints.toolConfirmations,
8406
+ ...typeof interactions === "string" ? { interactions } : {},
8407
+ ...typeof apps === "string" ? { apps } : {},
8408
+ ...typeof sandbox === "string" ? { sandbox } : {}
8409
+ },
8410
+ ...isRecord2(value.configuration) ? { configuration: value.configuration } : {},
8411
+ ...isRecord2(value.resume) && typeof value.resume.tool === "string" ? { resume: { tool: value.resume.tool } } : {}
8412
+ };
8413
+ }
8414
+ function isRecord2(value) {
8415
+ return typeof value === "object" && value !== null && !Array.isArray(value);
8416
+ }
8417
+ async function readStableErrorCode(response) {
8418
+ let value;
8419
+ try {
8420
+ value = await response.json();
8421
+ } catch {
8422
+ return void 0;
8423
+ }
8424
+ if (!isRecord2(value) || typeof value.code !== "string") return void 0;
8425
+ return /^[A-Za-z0-9_.-]{1,64}$/.test(value.code) ? value.code : void 0;
8426
+ }
8427
+ function clientError(code, message, retryable, status, options, serviceCode) {
8428
+ return new AssistantClientError(
8429
+ {
8430
+ code,
8431
+ ...status === void 0 ? {} : { status },
8432
+ retryable,
8433
+ ...serviceCode === void 0 ? {} : { serviceCode }
8434
+ },
8435
+ message,
8436
+ options
8437
+ );
8438
+ }
8439
+
8362
8440
  // src/events.ts
8363
8441
  function toAssistantClientEvent(event) {
8364
8442
  const value = event.data;
@@ -8374,20 +8452,25 @@ function toAssistantClientEvent(event) {
8374
8452
  }
8375
8453
  break;
8376
8454
  case "tool_proposed":
8377
- 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)) {
8455
+ 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)) {
8378
8456
  return event;
8379
8457
  }
8380
8458
  break;
8381
8459
  case "input_requested":
8382
- if (hasString(value, "id") && hasString(value, "message") && isRecord2(value.requestedSchema) && hasString(value, "expiresAt") && hasOptionalTurnId(value)) {
8460
+ if (hasString(value, "id") && hasString(value, "message") && isRecord3(value.requestedSchema) && hasString(value, "expiresAt") && hasOptionalTurnId(value)) {
8383
8461
  return event;
8384
8462
  }
8385
8463
  break;
8386
- case "auth_requested":
8387
- if (hasString(value, "id") && hasString(value, "tool") && hasString(value, "continuation") && hasString(value, "expiresAt") && hasOptionalTurnId(value)) {
8388
- return event;
8464
+ case "auth_requested": {
8465
+ const signInTicket = typeof value.signInTicket === "string" ? value.signInTicket : typeof value.continuation === "string" ? value.continuation : void 0;
8466
+ if (hasString(value, "id") && hasString(value, "tool") && signInTicket !== void 0 && hasString(value, "expiresAt") && hasOptionalTurnId(value)) {
8467
+ return {
8468
+ event: "auth_requested",
8469
+ data: { ...value, signInTicket }
8470
+ };
8389
8471
  }
8390
8472
  break;
8473
+ }
8391
8474
  case "interaction_resolved":
8392
8475
  if (hasString(value, "id") && (value.action === void 0 || isInteractionAction(value.action)) && hasOptionalTurnId(value)) {
8393
8476
  return event;
@@ -8418,7 +8501,7 @@ function toAssistantClientEvent(event) {
8418
8501
  return { event: "unrecognized", data: { name: event.event, payload: value } };
8419
8502
  }
8420
8503
  function isViewAvailableDetail(value) {
8421
- 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);
8504
+ 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);
8422
8505
  }
8423
8506
  function isHttpsUrl(value) {
8424
8507
  if (typeof value !== "string") return false;
@@ -8451,11 +8534,11 @@ function isJsonValue(value, depth) {
8451
8534
  if (Array.isArray(value)) {
8452
8535
  return value.length <= 256 && value.every((entry) => isJsonValue(entry, depth + 1));
8453
8536
  }
8454
- if (!isRecord2(value)) return false;
8537
+ if (!isRecord3(value)) return false;
8455
8538
  const entries = Object.entries(value);
8456
8539
  return entries.length <= 256 && entries.every(([, entry]) => isJsonValue(entry, depth + 1));
8457
8540
  }
8458
- function isRecord2(value) {
8541
+ function isRecord3(value) {
8459
8542
  return typeof value === "object" && value !== null && !Array.isArray(value);
8460
8543
  }
8461
8544
 
@@ -8698,15 +8781,15 @@ function parseFrame(frame) {
8698
8781
  if (event === "done" && !isValidDonePayload(parsed)) {
8699
8782
  throw invalidStream("assistant event stream contained an invalid done event");
8700
8783
  }
8701
- return { event, data: isRecord3(parsed) ? parsed : { value: parsed } };
8784
+ return { event, data: isRecord4(parsed) ? parsed : { value: parsed } };
8702
8785
  }
8703
8786
  function normalizeLineEndings(input) {
8704
8787
  return input.replaceAll("\r\n", "\n").replaceAll("\r", "\n");
8705
8788
  }
8706
8789
  function isValidDonePayload(value) {
8707
- return isRecord3(value) && (value.turnId === void 0 || typeof value.turnId === "string" && value.turnId.length > 0);
8790
+ return isRecord4(value) && (value.turnId === void 0 || typeof value.turnId === "string" && value.turnId.length > 0);
8708
8791
  }
8709
- function isRecord3(value) {
8792
+ function isRecord4(value) {
8710
8793
  return typeof value === "object" && value !== null && !Array.isArray(value);
8711
8794
  }
8712
8795
  function invalidStream(message, cause) {
@@ -8717,27 +8800,6 @@ function isAbortError2(error) {
8717
8800
  }
8718
8801
 
8719
8802
  // src/client.ts
8720
- async function refusalCode(response) {
8721
- try {
8722
- const body = await response.clone().json();
8723
- const code = body.code;
8724
- return typeof code === "string" ? code : void 0;
8725
- } catch {
8726
- return void 0;
8727
- }
8728
- }
8729
- var UNRETRYABLE_SERVICE_CODES = /* @__PURE__ */ new Set([
8730
- "daily_turn_budget_exhausted",
8731
- "daily_session_budget_exhausted"
8732
- ]);
8733
- var AssistantClientError = class extends Error {
8734
- detail;
8735
- constructor(detail, message, options) {
8736
- super(message, options);
8737
- this.name = "AssistantClientError";
8738
- this.detail = detail;
8739
- }
8740
- };
8741
8803
  var DefaultAssistantClient = class {
8742
8804
  #source;
8743
8805
  #fetch;
@@ -8772,12 +8834,50 @@ var DefaultAssistantClient = class {
8772
8834
  hasSession() {
8773
8835
  return this.#session !== void 0;
8774
8836
  }
8837
+ /** Whether a request holds the single-flight slot, so callers can refuse before mutating UI. */
8838
+ isBusy() {
8839
+ return this.#active !== void 0;
8840
+ }
8775
8841
  async connect() {
8776
8842
  if (this.#session) return;
8777
8843
  await this.#singleFlight(async (signal) => {
8778
- if (!this.#session) await this.#createSession(signal);
8844
+ if (this.#session) return;
8845
+ const session = await this.#createSession(signal);
8846
+ if (session.resume) {
8847
+ try {
8848
+ await this.#runChatOperation(signal, () => this.#resumeTurn(session, signal));
8849
+ } catch {
8850
+ }
8851
+ }
8779
8852
  });
8780
8853
  }
8854
+ /** POST the one-shot resume trigger; a 409 means nothing was pending, which renders as silence. */
8855
+ async #resumeTurn(session, signal) {
8856
+ const response = await this.#request(
8857
+ session.endpoints.turns,
8858
+ {
8859
+ method: "POST",
8860
+ headers: authorizedHeaders(session.token, "text/event-stream"),
8861
+ body: JSON.stringify({ resume: true }),
8862
+ signal
8863
+ },
8864
+ "turn_failed"
8865
+ );
8866
+ if (response.status === 409) return;
8867
+ if (!response.ok) {
8868
+ throw clientError(
8869
+ "turn_failed",
8870
+ `Assistant turn failed (${response.status})`,
8871
+ false,
8872
+ response.status,
8873
+ void 0,
8874
+ await refusalCode(response)
8875
+ );
8876
+ }
8877
+ this.#emit({ event: "resume_started", data: { tool: session.resume?.tool ?? "" } });
8878
+ await this.#consume(response);
8879
+ this.#emit({ event: "message_completed", data: {} });
8880
+ }
8781
8881
  async sendMessage(text2) {
8782
8882
  const message = text2.trim();
8783
8883
  if (!message) return;
@@ -9182,10 +9282,10 @@ function authorizedHeaders(token, accept) {
9182
9282
  };
9183
9283
  }
9184
9284
  function parseAppInteraction(value) {
9185
- if (!isRecord4(value) || !isRecord4(value.interaction)) return void 0;
9285
+ if (!isRecord2(value) || !isRecord2(value.interaction)) return void 0;
9186
9286
  const event = value.interaction.event;
9187
9287
  const data = value.interaction.data;
9188
- if (event !== "tool_proposed" && event !== "input_requested" || !isRecord4(data)) {
9288
+ if (event !== "tool_proposed" && event !== "input_requested" || !isRecord2(data)) {
9189
9289
  return void 0;
9190
9290
  }
9191
9291
  const parsed = toAssistantClientEvent({ event, data });
@@ -9205,60 +9305,12 @@ function appInteractionStopped(action) {
9205
9305
  isError: true
9206
9306
  };
9207
9307
  }
9208
- function parseSession(value) {
9209
- if (!isRecord4(value) || !isRecord4(value.endpoints)) {
9210
- throw clientError("session_failed", "Assistant session response is invalid", true);
9211
- }
9212
- const interactions = value.endpoints.interactions;
9213
- const apps = value.endpoints.apps;
9214
- const sandbox = value.endpoints.sandbox;
9215
- 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") {
9216
- throw clientError("session_failed", "Assistant session response is invalid", true);
9217
- }
9218
- return {
9219
- token: value.token,
9220
- expiresAt: value.expiresAt,
9221
- endpoints: {
9222
- turns: value.endpoints.turns,
9223
- toolConfirmations: value.endpoints.toolConfirmations,
9224
- ...typeof interactions === "string" ? { interactions } : {},
9225
- ...typeof apps === "string" ? { apps } : {},
9226
- ...typeof sandbox === "string" ? { sandbox } : {}
9227
- },
9228
- ...isRecord4(value.configuration) ? { configuration: value.configuration } : {}
9229
- };
9230
- }
9231
- function isRecord4(value) {
9232
- return typeof value === "object" && value !== null && !Array.isArray(value);
9233
- }
9234
- async function readStableErrorCode(response) {
9235
- let value;
9236
- try {
9237
- value = await response.json();
9238
- } catch {
9239
- return void 0;
9240
- }
9241
- if (!isRecord4(value) || typeof value.code !== "string") return void 0;
9242
- return /^[A-Za-z0-9_.-]{1,64}$/.test(value.code) ? value.code : void 0;
9243
- }
9244
- function clientError(code, message, retryable, status, options, serviceCode) {
9245
- return new AssistantClientError(
9246
- {
9247
- code,
9248
- ...status === void 0 ? {} : { status },
9249
- retryable,
9250
- ...serviceCode === void 0 ? {} : { serviceCode }
9251
- },
9252
- message,
9253
- options
9254
- );
9255
- }
9256
9308
 
9257
9309
  export {
9258
9310
  copyAssistantModelContext,
9259
9311
  copyAssistantPageContext,
9260
- sessionSourceKey,
9261
9312
  AssistantClientError,
9313
+ sessionSourceKey,
9262
9314
  createAssistantClient
9263
9315
  };
9264
- //# sourceMappingURL=chunk-S373FCAI.js.map
9316
+ //# sourceMappingURL=chunk-ZPZHPXIQ.js.map