scream-code 0.10.2 → 0.10.3

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.
@@ -3,25 +3,27 @@ import { fileURLToPath as __cjsShimFileURLToPath } from 'node:url';
3
3
  import { dirname as __cjsShimDirname } from 'node:path';
4
4
  const __filename = __cjsShimFileURLToPath(import.meta.url);
5
5
  const __dirname = __cjsShimDirname(__filename);
6
- import { a as __toESM, i as __require, r as __exportAll, t as __commonJSMin } from "./chunk-apG1qJts.mjs";
6
+ import { i as __require, o as __toESM, r as __exportAll, t as __commonJSMin } from "./chunk-D90kvbyJ.mjs";
7
7
  import "./suppress-sqlite-warning-C2VB0doZ.mjs";
8
8
  import { C as join$1, D as resolve$1, E as relative$1, S as isAbsolute$1, T as parse$7, a as isSupportedFile, b as basename$1, i as ingestFile, r as ingestDirectory, t as multiSearch, w as normalize, x as dirname$2, y as KnowledgeStore } from "./src-oeUnRY3N.mjs";
9
+ import { t as require_base64_js } from "./base64-js-DzVmk6Nb.mjs";
9
10
  import { a as setLocale, i as getLocale, n as assertScreamHostIdentity, o as t, r as createScreamDefaultHeaders, t as TextInputDialogComponent } from "./text-input-dialog-Cj7OClhs.mjs";
10
11
  import { createRequire } from "node:module";
11
12
  import { createHash, randomBytes, randomInt, randomUUID } from "node:crypto";
13
+ import * as fs$1 from "node:fs/promises";
12
14
  import Jn, { access, appendFile, chmod, copyFile, cp, lstat, mkdir, mkdtemp, open, readFile, readdir, realpath, rename, rm, rmdir, stat, unlink, writeFile } from "node:fs/promises";
13
15
  import I, { createWriteStream } from "fs";
14
16
  import Vr, { EventEmitter } from "events";
15
17
  import * as path$1$1 from "path";
16
18
  import Xs, { dirname, parse } from "path";
17
19
  import { Buffer as Buffer$1 } from "buffer";
18
- import * as fs$10 from "fs/promises";
20
+ import * as fs$11 from "fs/promises";
19
21
  import { writeFile as writeFile$1 } from "fs/promises";
20
22
  import Ds, { PassThrough, Readable } from "node:stream";
21
23
  import { finished, pipeline as pipeline$1 } from "node:stream/promises";
22
24
  import * as vs from "zlib";
23
25
  import Qr from "zlib";
24
- import * as fs$9 from "node:fs";
26
+ import * as fs$10 from "node:fs";
25
27
  import Vt, { appendFileSync, chmodSync, closeSync, constants, createReadStream, createWriteStream as createWriteStream$1, existsSync, fsyncSync, mkdirSync, openSync, promises, readFileSync, readSync, realpathSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
26
28
  import * as path$8 from "node:path";
27
29
  import path, { basename, dirname as dirname$1, extname, isAbsolute, join, posix, relative, resolve, sep, win32 } from "node:path";
@@ -684,6 +686,38 @@ var APIProviderRateLimitError = class extends APIStatusError {
684
686
  }
685
687
  };
686
688
  /**
689
+ * HTTP status error meaning the conversation history sent to the provider
690
+ * has orphaned tool calls (an assistant `tool_calls` block whose matching
691
+ * tool results are missing). Recoverable only by rebuilding the history —
692
+ * retrying the same request always fails. Carried as a distinct class so
693
+ * callers can reset the session on THIS kind alone instead of sniffing
694
+ * error message text.
695
+ */
696
+ var APIOrphanedToolCallError = class extends APIStatusError {
697
+ constructor(statusCode, message, requestId) {
698
+ super(statusCode, message, requestId);
699
+ this.name = "APIOrphanedToolCallError";
700
+ }
701
+ };
702
+ /**
703
+ * Message-text parity check shared by normalizeAPIStatusError and
704
+ * isOrphanedToolCallError. Mirrors the historical two-includes semantics:
705
+ * the fragments may appear in any order.
706
+ */
707
+ function isOrphanedToolCallMessage(lowerMessage) {
708
+ return lowerMessage.includes("insufficient tool messages") || lowerMessage.includes("tool_calls") && lowerMessage.includes("followed by tool messages");
709
+ }
710
+ /**
711
+ * True when an error signals orphaned tool calls in the request history.
712
+ * instanceof is checked first (provider threw the typed error); the message
713
+ * patterns are the fallback for errors that crossed wrapping boundaries
714
+ * (session/RPC layers re-wrapping the provider error).
715
+ */
716
+ function isOrphanedToolCallError(error) {
717
+ if (error instanceof APIOrphanedToolCallError) return true;
718
+ return isOrphanedToolCallMessage(errorMessage$5(error).toLowerCase());
719
+ }
720
+ /**
687
721
  * The API returned an empty response (no content, no tool calls).
688
722
  */
689
723
  var APIEmptyResponseError = class extends ChatProviderError {
@@ -720,6 +754,7 @@ function isContextOverflowErrorCode(code) {
720
754
  function normalizeAPIStatusError(statusCode, message, requestId) {
721
755
  if (statusCode === 429) return new APIProviderRateLimitError(message, requestId, parseRateLimitReason(message));
722
756
  if (isContextOverflowStatusError(statusCode, message)) return new APIContextOverflowError(statusCode, message, requestId);
757
+ if (statusCode === 400 && isOrphanedToolCallMessage(message.toLowerCase())) return new APIOrphanedToolCallError(statusCode, message, requestId);
723
758
  return new APIStatusError(statusCode, message, requestId);
724
759
  }
725
760
  function isContextOverflowStatusError(statusCode, message) {
@@ -727,6 +762,9 @@ function isContextOverflowStatusError(statusCode, message) {
727
762
  const lowerMessage = message.toLowerCase();
728
763
  return CONTEXT_OVERFLOW_MESSAGE_PATTERNS.some((pattern) => pattern.test(lowerMessage));
729
764
  }
765
+ function errorMessage$5(error) {
766
+ return error instanceof Error ? error.message : String(error);
767
+ }
730
768
  //#endregion
731
769
  //#region ../../packages/ltod/src/providers/tool-call-id.ts
732
770
  const EMPTY_TOOL_CALL_ID = "tool_call";
@@ -10293,12 +10331,12 @@ var require_gaxios = /* @__PURE__ */ __commonJSMin(((exports) => {
10293
10331
  * @returns A proxy agent
10294
10332
  */
10295
10333
  static async #getProxyAgent() {
10296
- this.#proxyAgent ||= (await import("./dist-0bMQWc-B.mjs").then((m) => /* @__PURE__ */ __toESM(m.default))).HttpsProxyAgent;
10334
+ this.#proxyAgent ||= (await import("./dist-AcjRoBBn.mjs").then((m) => /* @__PURE__ */ __toESM(m.default))).HttpsProxyAgent;
10297
10335
  return this.#proxyAgent;
10298
10336
  }
10299
10337
  static async #getFetch() {
10300
10338
  const hasWindow = typeof window !== "undefined" && !!window;
10301
- this.#fetch ||= hasWindow ? window.fetch : (await import("./src-Dae4j3bv.mjs")).default;
10339
+ this.#fetch ||= hasWindow ? window.fetch : (await import("./src-BMbOMRuY.mjs")).default;
10302
10340
  return this.#fetch;
10303
10341
  }
10304
10342
  /**
@@ -12752,94 +12790,6 @@ var require_src$1 = /* @__PURE__ */ __commonJSMin(((exports) => {
12752
12790
  __exportStar(require_gcp_residency(), exports);
12753
12791
  }));
12754
12792
  //#endregion
12755
- //#region ../../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js
12756
- var require_base64_js = /* @__PURE__ */ __commonJSMin(((exports) => {
12757
- exports.byteLength = byteLength;
12758
- exports.toByteArray = toByteArray;
12759
- exports.fromByteArray = fromByteArray;
12760
- var lookup = [];
12761
- var revLookup = [];
12762
- var Arr = typeof Uint8Array !== "undefined" ? Uint8Array : Array;
12763
- var code = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
12764
- for (var i = 0, len = code.length; i < len; ++i) {
12765
- lookup[i] = code[i];
12766
- revLookup[code.charCodeAt(i)] = i;
12767
- }
12768
- revLookup["-".charCodeAt(0)] = 62;
12769
- revLookup["_".charCodeAt(0)] = 63;
12770
- function getLens(b64) {
12771
- var len = b64.length;
12772
- if (len % 4 > 0) throw new Error("Invalid string. Length must be a multiple of 4");
12773
- var validLen = b64.indexOf("=");
12774
- if (validLen === -1) validLen = len;
12775
- var placeHoldersLen = validLen === len ? 0 : 4 - validLen % 4;
12776
- return [validLen, placeHoldersLen];
12777
- }
12778
- function byteLength(b64) {
12779
- var lens = getLens(b64);
12780
- var validLen = lens[0];
12781
- var placeHoldersLen = lens[1];
12782
- return (validLen + placeHoldersLen) * 3 / 4 - placeHoldersLen;
12783
- }
12784
- function _byteLength(b64, validLen, placeHoldersLen) {
12785
- return (validLen + placeHoldersLen) * 3 / 4 - placeHoldersLen;
12786
- }
12787
- function toByteArray(b64) {
12788
- var tmp;
12789
- var lens = getLens(b64);
12790
- var validLen = lens[0];
12791
- var placeHoldersLen = lens[1];
12792
- var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen));
12793
- var curByte = 0;
12794
- var len = placeHoldersLen > 0 ? validLen - 4 : validLen;
12795
- var i;
12796
- for (i = 0; i < len; i += 4) {
12797
- tmp = revLookup[b64.charCodeAt(i)] << 18 | revLookup[b64.charCodeAt(i + 1)] << 12 | revLookup[b64.charCodeAt(i + 2)] << 6 | revLookup[b64.charCodeAt(i + 3)];
12798
- arr[curByte++] = tmp >> 16 & 255;
12799
- arr[curByte++] = tmp >> 8 & 255;
12800
- arr[curByte++] = tmp & 255;
12801
- }
12802
- if (placeHoldersLen === 2) {
12803
- tmp = revLookup[b64.charCodeAt(i)] << 2 | revLookup[b64.charCodeAt(i + 1)] >> 4;
12804
- arr[curByte++] = tmp & 255;
12805
- }
12806
- if (placeHoldersLen === 1) {
12807
- tmp = revLookup[b64.charCodeAt(i)] << 10 | revLookup[b64.charCodeAt(i + 1)] << 4 | revLookup[b64.charCodeAt(i + 2)] >> 2;
12808
- arr[curByte++] = tmp >> 8 & 255;
12809
- arr[curByte++] = tmp & 255;
12810
- }
12811
- return arr;
12812
- }
12813
- function tripletToBase64(num) {
12814
- return lookup[num >> 18 & 63] + lookup[num >> 12 & 63] + lookup[num >> 6 & 63] + lookup[num & 63];
12815
- }
12816
- function encodeChunk(uint8, start, end) {
12817
- var tmp;
12818
- var output = [];
12819
- for (var i = start; i < end; i += 3) {
12820
- tmp = (uint8[i] << 16 & 16711680) + (uint8[i + 1] << 8 & 65280) + (uint8[i + 2] & 255);
12821
- output.push(tripletToBase64(tmp));
12822
- }
12823
- return output.join("");
12824
- }
12825
- function fromByteArray(uint8) {
12826
- var tmp;
12827
- var len = uint8.length;
12828
- var extraBytes = len % 3;
12829
- var parts = [];
12830
- var maxChunkLength = 16383;
12831
- for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) parts.push(encodeChunk(uint8, i, i + maxChunkLength > len2 ? len2 : i + maxChunkLength));
12832
- if (extraBytes === 1) {
12833
- tmp = uint8[len - 1];
12834
- parts.push(lookup[tmp >> 2] + lookup[tmp << 4 & 63] + "==");
12835
- } else if (extraBytes === 2) {
12836
- tmp = (uint8[len - 2] << 8) + uint8[len - 1];
12837
- parts.push(lookup[tmp >> 10] + lookup[tmp >> 4 & 63] + lookup[tmp << 2 & 63] + "=");
12838
- }
12839
- return parts.join("");
12840
- }
12841
- }));
12842
- //#endregion
12843
12793
  //#region ../../node_modules/.pnpm/google-auth-library@10.6.2/node_modules/google-auth-library/build/src/crypto/shared.js
12844
12794
  var require_shared$1 = /* @__PURE__ */ __commonJSMin(((exports) => {
12845
12795
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -13207,7 +13157,7 @@ var require_util$1 = /* @__PURE__ */ __commonJSMin(((exports) => {
13207
13157
  exports.removeUndefinedValuesInObject = removeUndefinedValuesInObject;
13208
13158
  exports.isValidFile = isValidFile;
13209
13159
  exports.getWellKnownCertificateConfigFileLocation = getWellKnownCertificateConfigFileLocation;
13210
- const fs$16 = __require("fs");
13160
+ const fs$17 = __require("fs");
13211
13161
  const os$2 = __require("os");
13212
13162
  const path$13 = __require("path");
13213
13163
  const WELL_KNOWN_CERTIFICATE_CONFIG_FILE = "certificate_config.json";
@@ -13327,7 +13277,7 @@ var require_util$1 = /* @__PURE__ */ __commonJSMin(((exports) => {
13327
13277
  */
13328
13278
  async function isValidFile(filePath) {
13329
13279
  try {
13330
- return (await fs$16.promises.lstat(filePath)).isFile();
13280
+ return (await fs$17.promises.lstat(filePath)).isFile();
13331
13281
  } catch (e) {
13332
13282
  return false;
13333
13283
  }
@@ -15041,10 +14991,10 @@ var require_getCredentials = /* @__PURE__ */ __commonJSMin(((exports) => {
15041
14991
  Object.defineProperty(exports, "__esModule", { value: true });
15042
14992
  exports.getCredentials = getCredentials;
15043
14993
  const path$12 = __require("path");
15044
- const fs$15 = __require("fs");
14994
+ const fs$16 = __require("fs");
15045
14995
  const util_1$1 = __require("util");
15046
14996
  const errorWithCode_1 = require_errorWithCode();
15047
- const readFile = fs$15.readFile ? (0, util_1$1.promisify)(fs$15.readFile) : async () => {
14997
+ const readFile = fs$16.readFile ? (0, util_1$1.promisify)(fs$16.readFile) : async () => {
15048
14998
  throw new errorWithCode_1.ErrorWithCode("use key rather than keyFile.", "MISSING_CREDENTIALS");
15049
14999
  };
15050
15000
  var ExtensionFiles;
@@ -16592,10 +16542,10 @@ var require_filesubjecttokensupplier = /* @__PURE__ */ __commonJSMin(((exports)
16592
16542
  Object.defineProperty(exports, "__esModule", { value: true });
16593
16543
  exports.FileSubjectTokenSupplier = void 0;
16594
16544
  const util_1 = __require("util");
16595
- const fs$14 = __require("fs");
16596
- const readFile = (0, util_1.promisify)(fs$14.readFile ?? (() => {}));
16597
- const realpath = (0, util_1.promisify)(fs$14.realpath ?? (() => {}));
16598
- const lstat = (0, util_1.promisify)(fs$14.lstat ?? (() => {}));
16545
+ const fs$15 = __require("fs");
16546
+ const readFile = (0, util_1.promisify)(fs$15.readFile ?? (() => {}));
16547
+ const realpath = (0, util_1.promisify)(fs$15.realpath ?? (() => {}));
16548
+ const lstat = (0, util_1.promisify)(fs$15.lstat ?? (() => {}));
16599
16549
  /**
16600
16550
  * Internal subject token supplier implementation used when a file location
16601
16551
  * is configured in the credential configuration used to build an {@link IdentityPoolClient}
@@ -16697,7 +16647,7 @@ var require_certificatesubjecttokensupplier = /* @__PURE__ */ __commonJSMin(((ex
16697
16647
  Object.defineProperty(exports, "__esModule", { value: true });
16698
16648
  exports.CertificateSubjectTokenSupplier = exports.InvalidConfigurationError = exports.CertificateSourceUnavailableError = exports.CERTIFICATE_CONFIGURATION_ENV_VARIABLE = void 0;
16699
16649
  const util_1 = require_util$1();
16700
- const fs$13 = __require("fs");
16650
+ const fs$14 = __require("fs");
16701
16651
  const crypto_1 = __require("crypto");
16702
16652
  const https$1 = __require("https");
16703
16653
  exports.CERTIFICATE_CONFIGURATION_ENV_VARIABLE = "GOOGLE_API_CERTIFICATE_CONFIG";
@@ -16792,7 +16742,7 @@ var require_certificatesubjecttokensupplier = /* @__PURE__ */ __commonJSMin(((ex
16792
16742
  const configPath = this.certificateConfigPath;
16793
16743
  let fileContents;
16794
16744
  try {
16795
- fileContents = await fs$13.promises.readFile(configPath, "utf8");
16745
+ fileContents = await fs$14.promises.readFile(configPath, "utf8");
16796
16746
  } catch (err) {
16797
16747
  throw new CertificateSourceUnavailableError(`Failed to read certificate config file at: ${configPath}`);
16798
16748
  }
@@ -16817,13 +16767,13 @@ var require_certificatesubjecttokensupplier = /* @__PURE__ */ __commonJSMin(((ex
16817
16767
  async #getKeyAndCert(certPath, keyPath) {
16818
16768
  let cert, key;
16819
16769
  try {
16820
- cert = await fs$13.promises.readFile(certPath);
16770
+ cert = await fs$14.promises.readFile(certPath);
16821
16771
  new crypto_1.X509Certificate(cert);
16822
16772
  } catch (err) {
16823
16773
  throw new CertificateSourceUnavailableError(`Failed to read certificate file at ${certPath}: ${err instanceof Error ? err.message : String(err)}`);
16824
16774
  }
16825
16775
  try {
16826
- key = await fs$13.promises.readFile(keyPath);
16776
+ key = await fs$14.promises.readFile(keyPath);
16827
16777
  (0, crypto_1.createPrivateKey)(key);
16828
16778
  } catch (err) {
16829
16779
  throw new CertificateSourceUnavailableError(`Failed to read private key file at ${keyPath}: ${err instanceof Error ? err.message : String(err)}`);
@@ -16842,7 +16792,7 @@ var require_certificatesubjecttokensupplier = /* @__PURE__ */ __commonJSMin(((ex
16842
16792
  const leafCert = new crypto_1.X509Certificate(leafCertBuffer);
16843
16793
  if (!this.trustChainPath) return JSON.stringify([leafCert.raw.toString("base64")]);
16844
16794
  try {
16845
- const chainCerts = ((await fs$13.promises.readFile(this.trustChainPath, "utf8")).match(/-----BEGIN CERTIFICATE-----[^-]+-----END CERTIFICATE-----/g) ?? []).map((pem, index) => {
16795
+ const chainCerts = ((await fs$14.promises.readFile(this.trustChainPath, "utf8")).match(/-----BEGIN CERTIFICATE-----[^-]+-----END CERTIFICATE-----/g) ?? []).map((pem, index) => {
16846
16796
  try {
16847
16797
  return new crypto_1.X509Certificate(pem);
16848
16798
  } catch (err) {
@@ -17503,7 +17453,7 @@ var require_pluggable_auth_handler = /* @__PURE__ */ __commonJSMin(((exports) =>
17503
17453
  exports.PluggableAuthHandler = exports.ExecutableError = void 0;
17504
17454
  const executable_response_1 = require_executable_response();
17505
17455
  const childProcess = __require("child_process");
17506
- const fs$12 = __require("fs");
17456
+ const fs$13 = __require("fs");
17507
17457
  /**
17508
17458
  * Error thrown from the executable run by PluggableAuthClient.
17509
17459
  */
@@ -17580,12 +17530,12 @@ var require_pluggable_auth_handler = /* @__PURE__ */ __commonJSMin(((exports) =>
17580
17530
  if (!this.outputFile || this.outputFile.length === 0) return;
17581
17531
  let filePath;
17582
17532
  try {
17583
- filePath = await fs$12.promises.realpath(this.outputFile);
17533
+ filePath = await fs$13.promises.realpath(this.outputFile);
17584
17534
  } catch {
17585
17535
  return;
17586
17536
  }
17587
- if (!(await fs$12.promises.lstat(filePath)).isFile()) return;
17588
- const responseString = await fs$12.promises.readFile(filePath, { encoding: "utf8" });
17537
+ if (!(await fs$13.promises.lstat(filePath)).isFile()) return;
17538
+ const responseString = await fs$13.promises.readFile(filePath, { encoding: "utf8" });
17589
17539
  if (responseString === "") return;
17590
17540
  try {
17591
17541
  const responseJson = JSON.parse(responseString);
@@ -18007,7 +17957,7 @@ var require_googleauth = /* @__PURE__ */ __commonJSMin(((exports) => {
18007
17957
  Object.defineProperty(exports, "__esModule", { value: true });
18008
17958
  exports.GoogleAuth = exports.GoogleAuthExceptionMessages = void 0;
18009
17959
  const child_process_1 = __require("child_process");
18010
- const fs$11 = __require("fs");
17960
+ const fs$12 = __require("fs");
18011
17961
  const gaxios_1 = require_src$3();
18012
17962
  const gcpMetadata = require_src$1();
18013
17963
  const os$1 = __require("os");
@@ -18255,7 +18205,7 @@ var require_googleauth = /* @__PURE__ */ __commonJSMin(((exports) => {
18255
18205
  }
18256
18206
  if (location) {
18257
18207
  location = path$11.join(location, "gcloud", "application_default_credentials.json");
18258
- if (!fs$11.existsSync(location)) location = null;
18208
+ if (!fs$12.existsSync(location)) location = null;
18259
18209
  }
18260
18210
  if (!location) return null;
18261
18211
  return await this._getApplicationCredentialsFromFilePath(location, options);
@@ -18269,13 +18219,13 @@ var require_googleauth = /* @__PURE__ */ __commonJSMin(((exports) => {
18269
18219
  async _getApplicationCredentialsFromFilePath(filePath, options = {}) {
18270
18220
  if (!filePath || filePath.length === 0) throw new Error("The file path is invalid.");
18271
18221
  try {
18272
- filePath = fs$11.realpathSync(filePath);
18273
- if (!fs$11.lstatSync(filePath).isFile()) throw new Error();
18222
+ filePath = fs$12.realpathSync(filePath);
18223
+ if (!fs$12.lstatSync(filePath).isFile()) throw new Error();
18274
18224
  } catch (err) {
18275
18225
  if (err instanceof Error) err.message = `The file at ${filePath} does not exist, or it is not a file. ${err.message}`;
18276
18226
  throw err;
18277
18227
  }
18278
- const readStream = fs$11.createReadStream(filePath);
18228
+ const readStream = fs$12.createReadStream(filePath);
18279
18229
  return this.fromStream(readStream, options);
18280
18230
  }
18281
18231
  /**
@@ -18542,7 +18492,7 @@ var require_googleauth = /* @__PURE__ */ __commonJSMin(((exports) => {
18542
18492
  if (this.jsonContent) return this._cacheClientFromJSON(this.jsonContent, this.clientOptions);
18543
18493
  else if (this.keyFilename) {
18544
18494
  const filePath = path$11.resolve(this.keyFilename);
18545
- const stream = fs$11.createReadStream(filePath);
18495
+ const stream = fs$12.createReadStream(filePath);
18546
18496
  return await this.fromStreamAsync(stream, this.clientOptions);
18547
18497
  } else if (this.apiKey) {
18548
18498
  const client = await this.fromAPIKey(this.apiKey, this.clientOptions);
@@ -37287,7 +37237,7 @@ var NodeUploader = class {
37287
37237
  type: void 0
37288
37238
  };
37289
37239
  if (typeof file === "string") {
37290
- fileStat.size = (await fs$10.stat(file)).size;
37240
+ fileStat.size = (await fs$11.stat(file)).size;
37291
37241
  fileStat.type = this.inferMimeType(file);
37292
37242
  return fileStat;
37293
37243
  } else return await getBlobStat(file);
@@ -37419,7 +37369,7 @@ var NodeUploader = class {
37419
37369
  let fileHandle;
37420
37370
  const fileName = path$1$1.basename(file);
37421
37371
  try {
37422
- fileHandle = await fs$10.open(file, "r");
37372
+ fileHandle = await fs$11.open(file, "r");
37423
37373
  if (!fileHandle) throw new Error(`Failed to open file`);
37424
37374
  fileSize = (await fileHandle.stat()).size;
37425
37375
  while (offset < fileSize) {
@@ -48186,11 +48136,11 @@ var ScreamFiles = class {
48186
48136
  async uploadVideo(input, options) {
48187
48137
  let file;
48188
48138
  if (typeof input === "string") {
48189
- if (!fs$9.existsSync(input)) throw new ChatProviderError(`Video file not found: ${input}`);
48139
+ if (!fs$10.existsSync(input)) throw new ChatProviderError(`Video file not found: ${input}`);
48190
48140
  const filename = path$8.basename(input);
48191
48141
  const mimeType = guessMimeTypeFromExt(filename);
48192
48142
  if (mimeType === void 0 || !mimeType.startsWith("video/")) throw new ChatProviderError(`ScreamFiles.uploadVideo: file extension does not indicate a video type: ${filename}`);
48193
- const data = await fs$9.promises.readFile(input);
48143
+ const data = await fs$10.promises.readFile(input);
48194
48144
  const blob = new Blob([new Uint8Array(data)], { type: mimeType });
48195
48145
  file = new File([blob], filename, { type: mimeType });
48196
48146
  } else {
@@ -49877,7 +49827,7 @@ async function generate(provider, systemPrompt, tools, history, callbacks, optio
49877
49827
  if (options?.signal?.aborted) throwAbortError();
49878
49828
  options?.onRequestStart?.();
49879
49829
  const stream = await provider.generate(systemPrompt, tools, history, options);
49880
- await throwIfAborted(options?.signal, stream);
49830
+ await throwIfAborted$1(options?.signal, stream);
49881
49831
  const idleTimeoutMs = getStreamIdleTimeoutMs();
49882
49832
  const firstItemTimeoutMs = getStreamFirstItemTimeoutMs(idleTimeoutMs);
49883
49833
  const watchedStream = iterateWithIdleTimeout(stream, {
@@ -49888,10 +49838,10 @@ async function generate(provider, systemPrompt, tools, history, callbacks, optio
49888
49838
  firstItemErrorMessage: `Stream stalled — no first token within ${firstItemTimeoutMs ?? 0}ms. Provider: ${provider.name}, model: ${provider.modelName}`
49889
49839
  });
49890
49840
  for await (const part of watchedStream) {
49891
- await throwIfAborted(options?.signal, stream);
49841
+ await throwIfAborted$1(options?.signal, stream);
49892
49842
  if (callbacks?.onMessagePart !== void 0) {
49893
49843
  await callbacks.onMessagePart(deepCopyPart(part));
49894
- await throwIfAborted(options?.signal, stream);
49844
+ await throwIfAborted$1(options?.signal, stream);
49895
49845
  }
49896
49846
  if (isToolCallPart(part) && part.index !== void 0 && !isPendingToolCallAtIndex(pendingPart, part.index)) {
49897
49847
  const arrayIdx = toolCallIndexMap.get(part.index);
@@ -49907,7 +49857,7 @@ async function generate(provider, systemPrompt, tools, history, callbacks, optio
49907
49857
  pendingPart = part;
49908
49858
  }
49909
49859
  }
49910
- await throwIfAborted(options?.signal, stream);
49860
+ await throwIfAborted$1(options?.signal, stream);
49911
49861
  options?.onStreamEnd?.();
49912
49862
  if (pendingPart !== null) flushPart(message, pendingPart, toolCallIndexMap);
49913
49863
  if (message.content.length === 0 && message.toolCalls.length === 0) throw new APIEmptyResponseError(`The API returned an empty response (no content, no tool calls). Provider: ${provider.name}, model: ${provider.modelName}. Common causes: the model's max output tokens are set too low, the model does not support this request format, or the provider/proxy returned an empty stream. Try again, switch models, or check provider settings.`);
@@ -49916,7 +49866,7 @@ async function generate(provider, systemPrompt, tools, history, callbacks, optio
49916
49866
  const hasToolCalls = message.toolCalls.length > 0;
49917
49867
  if (hasThink && !hasText && !hasToolCalls) throw new APIEmptyResponseError(`The API returned a response containing only thinking content without any text or tool calls. This usually indicates the stream was interrupted or the output token budget was exhausted during reasoning. Provider: ${provider.name}, model: ${provider.modelName}. If this persists, reduce reasoning effort or switch to a model with a larger output budget.`);
49918
49868
  if (callbacks?.onToolCall !== void 0) for (const toolCall of message.toolCalls) {
49919
- await throwIfAborted(options?.signal, stream);
49869
+ await throwIfAborted$1(options?.signal, stream);
49920
49870
  await callbacks.onToolCall(toolCall);
49921
49871
  }
49922
49872
  return {
@@ -49933,7 +49883,7 @@ function throwAbortError() {
49933
49883
  async function cancelStream(stream) {
49934
49884
  await stream[Symbol.asyncIterator]().return?.();
49935
49885
  }
49936
- async function throwIfAborted(signal, stream) {
49886
+ async function throwIfAborted$1(signal, stream) {
49937
49887
  if (!signal?.aborted) return;
49938
49888
  if (stream !== void 0) await cancelStream(stream);
49939
49889
  throwAbortError();
@@ -50295,7 +50245,7 @@ async function syncDir(dirPath) {
50295
50245
  */
50296
50246
  function syncFd(fd) {
50297
50247
  return new Promise((resolve, reject) => {
50298
- fs$9.fsync(fd, (err) => {
50248
+ fs$10.fsync(fd, (err) => {
50299
50249
  if (err) {
50300
50250
  reject(err);
50301
50251
  return;
@@ -50903,7 +50853,7 @@ function isAbortError$1(err) {
50903
50853
  if (err instanceof Error) return err.name === "AbortError";
50904
50854
  return false;
50905
50855
  }
50906
- function errorMessage$3(err) {
50856
+ function errorMessage$4(err) {
50907
50857
  if (err instanceof Error) return err.message;
50908
50858
  return String(err);
50909
50859
  }
@@ -66860,7 +66810,7 @@ var require_node_loaders = /* @__PURE__ */ __commonJSMin(((exports, module) => {
66860
66810
  };
66861
66811
  return _setPrototypeOf(o, p);
66862
66812
  }
66863
- var fs$8 = __require("fs");
66813
+ var fs$9 = __require("fs");
66864
66814
  var path$6 = __require("path");
66865
66815
  var Loader = require_loader();
66866
66816
  var PrecompiledLoader = require_precompiled_loader().PrecompiledLoader;
@@ -66884,7 +66834,7 @@ var require_node_loaders = /* @__PURE__ */ __commonJSMin(((exports, module) => {
66884
66834
  } catch (e) {
66885
66835
  throw new Error("watch requires chokidar to be installed");
66886
66836
  }
66887
- var paths = _this.searchPaths.filter(fs$8.existsSync);
66837
+ var paths = _this.searchPaths.filter(fs$9.existsSync);
66888
66838
  var watcher = chokidar.watch(paths);
66889
66839
  watcher.on("all", function(event, fullname) {
66890
66840
  fullname = path$6.resolve(fullname);
@@ -66903,7 +66853,7 @@ var require_node_loaders = /* @__PURE__ */ __commonJSMin(((exports, module) => {
66903
66853
  for (var i = 0; i < paths.length; i++) {
66904
66854
  var basePath = path$6.resolve(paths[i]);
66905
66855
  var p = path$6.resolve(paths[i], name);
66906
- if (p.indexOf(basePath) === 0 && fs$8.existsSync(p)) {
66856
+ if (p.indexOf(basePath) === 0 && fs$9.existsSync(p)) {
66907
66857
  fullpath = p;
66908
66858
  break;
66909
66859
  }
@@ -66911,7 +66861,7 @@ var require_node_loaders = /* @__PURE__ */ __commonJSMin(((exports, module) => {
66911
66861
  if (!fullpath) return null;
66912
66862
  this.pathsToNames[fullpath] = name;
66913
66863
  var source = {
66914
- src: fs$8.readFileSync(fullpath, "utf-8"),
66864
+ src: fs$9.readFileSync(fullpath, "utf-8"),
66915
66865
  path: fullpath,
66916
66866
  noCache: this.noCache
66917
66867
  };
@@ -66959,7 +66909,7 @@ var require_node_loaders = /* @__PURE__ */ __commonJSMin(((exports, module) => {
66959
66909
  }
66960
66910
  this.pathsToNames[fullpath] = name;
66961
66911
  var source = {
66962
- src: fs$8.readFileSync(fullpath, "utf-8"),
66912
+ src: fs$9.readFileSync(fullpath, "utf-8"),
66963
66913
  path: fullpath,
66964
66914
  noCache: this.noCache
66965
66915
  };
@@ -67703,7 +67653,7 @@ var require_precompile_global = /* @__PURE__ */ __commonJSMin(((exports, module)
67703
67653
  //#endregion
67704
67654
  //#region ../../node_modules/.pnpm/nunjucks@3.2.4/node_modules/nunjucks/src/precompile.js
67705
67655
  var require_precompile = /* @__PURE__ */ __commonJSMin(((exports, module) => {
67706
- var fs$7 = __require("fs");
67656
+ var fs$8 = __require("fs");
67707
67657
  var path$4 = __require("path");
67708
67658
  var _prettifyError = require_lib$1()._prettifyError;
67709
67659
  var compiler = require_compiler();
@@ -67728,27 +67678,27 @@ var require_precompile = /* @__PURE__ */ __commonJSMin(((exports, module) => {
67728
67678
  var env = opts.env || new Environment([]);
67729
67679
  var wrapper = opts.wrapper || precompileGlobal;
67730
67680
  if (opts.isString) return precompileString(input, opts);
67731
- var pathStats = fs$7.existsSync(input) && fs$7.statSync(input);
67681
+ var pathStats = fs$8.existsSync(input) && fs$8.statSync(input);
67732
67682
  var precompiled = [];
67733
67683
  var templates = [];
67734
67684
  function addTemplates(dir) {
67735
- fs$7.readdirSync(dir).forEach(function(file) {
67685
+ fs$8.readdirSync(dir).forEach(function(file) {
67736
67686
  var filepath = path$4.join(dir, file);
67737
67687
  var subpath = filepath.substr(path$4.join(input, "/").length);
67738
- var stat = fs$7.statSync(filepath);
67688
+ var stat = fs$8.statSync(filepath);
67739
67689
  if (stat && stat.isDirectory()) {
67740
67690
  subpath += "/";
67741
67691
  if (!match(subpath, opts.exclude)) addTemplates(filepath);
67742
67692
  } else if (match(subpath, opts.include)) templates.push(filepath);
67743
67693
  });
67744
67694
  }
67745
- if (pathStats.isFile()) precompiled.push(_precompile(fs$7.readFileSync(input, "utf-8"), opts.name || input, env));
67695
+ if (pathStats.isFile()) precompiled.push(_precompile(fs$8.readFileSync(input, "utf-8"), opts.name || input, env));
67746
67696
  else if (pathStats.isDirectory()) {
67747
67697
  addTemplates(input);
67748
67698
  for (var i = 0; i < templates.length; i++) {
67749
67699
  var name = templates[i].replace(path$4.join(input, "/"), "");
67750
67700
  try {
67751
- precompiled.push(_precompile(fs$7.readFileSync(templates[i], "utf-8"), name, env));
67701
+ precompiled.push(_precompile(fs$8.readFileSync(templates[i], "utf-8"), name, env));
67752
67702
  } catch (e) {
67753
67703
  if (opts.force) console.error(e);
67754
67704
  else throw e;
@@ -68224,7 +68174,7 @@ var require_pend = /* @__PURE__ */ __commonJSMin(((exports, module) => {
68224
68174
  //#endregion
68225
68175
  //#region ../../node_modules/.pnpm/yauzl@3.3.1/node_modules/yauzl/fd-slicer.js
68226
68176
  var require_fd_slicer = /* @__PURE__ */ __commonJSMin(((exports) => {
68227
- var fs$6 = __require("fs");
68177
+ var fs$7 = __require("fs");
68228
68178
  var util$2 = __require("util");
68229
68179
  var stream = __require("stream");
68230
68180
  var Readable = stream.Readable;
@@ -68244,7 +68194,7 @@ var require_fd_slicer = /* @__PURE__ */ __commonJSMin(((exports) => {
68244
68194
  FdSlicer.prototype.read = function(buffer, offset, length, position, callback) {
68245
68195
  var self = this;
68246
68196
  self.pend.go(function(cb) {
68247
- fs$6.read(self.fd, buffer, offset, length, position, function(err, bytesRead, buffer) {
68197
+ fs$7.read(self.fd, buffer, offset, length, position, function(err, bytesRead, buffer) {
68248
68198
  cb();
68249
68199
  callback(err, bytesRead, buffer);
68250
68200
  });
@@ -68261,7 +68211,7 @@ var require_fd_slicer = /* @__PURE__ */ __commonJSMin(((exports) => {
68261
68211
  self.refCount -= 1;
68262
68212
  if (self.refCount < 0) throw new Error("invalid unref");
68263
68213
  if (self.refCount > 0) return;
68264
- fs$6.close(self.fd, onCloseDone);
68214
+ fs$7.close(self.fd, onCloseDone);
68265
68215
  function onCloseDone(err) {
68266
68216
  if (err) self.emit("error", err);
68267
68217
  else self.emit("close");
@@ -68288,7 +68238,7 @@ var require_fd_slicer = /* @__PURE__ */ __commonJSMin(((exports) => {
68288
68238
  }
68289
68239
  self.context.pend.go(function(cb) {
68290
68240
  var buffer = Buffer.allocUnsafe(toRead);
68291
- fs$6.read(self.context.fd, buffer, 0, toRead, self.pos, function(err, bytesRead) {
68241
+ fs$7.read(self.context.fd, buffer, 0, toRead, self.pos, function(err, bytesRead) {
68292
68242
  if (err) self.destroy(err);
68293
68243
  else if (bytesRead === 0) {
68294
68244
  self.push(null);
@@ -74220,7 +74170,7 @@ var mi = class {
74220
74170
  K(Hn, Wn, Gn, Zn, (s, t) => {
74221
74171
  if (!t?.length) throw new TypeError("no paths specified to add to archive");
74222
74172
  });
74223
- var dr = (process.env.__FAKE_PLATFORM__ || process.platform) === "win32", { O_CREAT: ur, O_NOFOLLOW: lr, O_TRUNC: mr, O_WRONLY: pr } = I.constants, Er = Number(process.env.__FAKE_FS_O_FILENAME__) || I.constants.UV_FS_O_FILEMAP || 0, Vn = dr && !!Er, $n = 512 * 1024, Xn = Er | mr | ur | pr, cr = !dr && typeof lr == "number" ? lr | mr | ur | pr : null, fs$4 = cr !== null ? () => cr : Vn ? (s) => s < $n ? Xn : "w" : () => "w";
74173
+ var dr = (process.env.__FAKE_PLATFORM__ || process.platform) === "win32", { O_CREAT: ur, O_NOFOLLOW: lr, O_TRUNC: mr, O_WRONLY: pr } = I.constants, Er = Number(process.env.__FAKE_FS_O_FILENAME__) || I.constants.UV_FS_O_FILEMAP || 0, Vn = dr && !!Er, $n = 512 * 1024, Xn = Er | mr | ur | pr, cr = !dr && typeof lr == "number" ? lr | mr | ur | pr : null, fs$5 = cr !== null ? () => cr : Vn ? (s) => s < $n ? Xn : "w" : () => "w";
74224
74174
  var ds = (s, t, e) => {
74225
74175
  try {
74226
74176
  return Vt.lchownSync(s, t, e);
@@ -74588,7 +74538,7 @@ var Or = Symbol("onEntry"), Rs = Symbol("checkFs"), Tr = Symbol("checkFs2"), gs
74588
74538
  }
74589
74539
  [bs](t, e) {
74590
74540
  let i = typeof t.mode == "number" ? t.mode & 4095 : this.fmode, r = new tt(String(t.absolute), {
74591
- flags: fs$4(t.size),
74541
+ flags: fs$5(t.size),
74592
74542
  mode: i,
74593
74543
  autoClose: !1
74594
74544
  });
@@ -74792,7 +74742,7 @@ var Or = Symbol("onEntry"), Rs = Symbol("checkFs"), Tr = Symbol("checkFs2"), gs
74792
74742
  (h || a) && this[O](h || a, t), e();
74793
74743
  }, n;
74794
74744
  try {
74795
- n = Vt.openSync(String(t.absolute), fs$4(t.size), i);
74745
+ n = Vt.openSync(String(t.absolute), fs$5(t.size), i);
74796
74746
  } catch (h) {
74797
74747
  return r(h);
74798
74748
  }
@@ -76160,7 +76110,7 @@ const FTYP_VIDEO_BRANDS = Object.freeze({
76160
76110
  "3gp7": "video/3gpp",
76161
76111
  "3g2": "video/3gpp2"
76162
76112
  });
76163
- function toBuffer(data) {
76113
+ function toBuffer$1(data) {
76164
76114
  return Buffer.isBuffer(data) ? data : Buffer.from(data.buffer, data.byteOffset, data.byteLength);
76165
76115
  }
76166
76116
  function startsWith(buf, prefix) {
@@ -76175,7 +76125,7 @@ function sniffFtypBrand(header) {
76175
76125
  return header.subarray(8, 12).toString("latin1").toLowerCase().replaceAll(/[\s\u0000]+$/g, "").trim();
76176
76126
  }
76177
76127
  function sniffMediaFromMagic(data) {
76178
- const buf = toBuffer(data);
76128
+ const buf = toBuffer$1(data);
76179
76129
  const header = buf.length > 512 ? buf.subarray(0, 512) : buf;
76180
76130
  if (startsWith(header, [
76181
76131
  137,
@@ -76287,7 +76237,7 @@ function sniffMediaFromMagic(data) {
76287
76237
  * when the supplied buffer is too short to cover it.
76288
76238
  */
76289
76239
  function sniffImageDimensions(data) {
76290
- const buf = toBuffer(data);
76240
+ const buf = toBuffer$1(data);
76291
76241
  if (startsWith(buf, [
76292
76242
  137,
76293
76243
  80,
@@ -76372,7 +76322,7 @@ function detectFileType(path, header) {
76372
76322
  mimeType: VIDEO_MIME_BY_SUFFIX$1[suffix]
76373
76323
  };
76374
76324
  if (header !== void 0) {
76375
- const buf = toBuffer(header);
76325
+ const buf = toBuffer$1(header);
76376
76326
  const sniffed = sniffMediaFromMagic(buf);
76377
76327
  if (sniffed) {
76378
76328
  if (mediaHint) {
@@ -81146,7 +81096,7 @@ async function runHook(command, input, options) {
81146
81096
  detached: process.platform !== "win32"
81147
81097
  });
81148
81098
  } catch (error) {
81149
- return allowResult({ stderr: errorMessage$2(error) });
81099
+ return allowResult({ stderr: errorMessage$3(error) });
81150
81100
  }
81151
81101
  return new Promise((resolve) => {
81152
81102
  let stdout = "";
@@ -81194,7 +81144,7 @@ async function runHook(command, input, options) {
81194
81144
  child.on("error", (error) => {
81195
81145
  settle(allowResult({
81196
81146
  stdout,
81197
- stderr: stderr + errorMessage$2(error)
81147
+ stderr: stderr + errorMessage$3(error)
81198
81148
  }));
81199
81149
  });
81200
81150
  child.on("close", (code) => {
@@ -81290,7 +81240,7 @@ function tryKillProcess(child, signal) {
81290
81240
  function isRecord$5(value) {
81291
81241
  return typeof value === "object" && value !== null && !Array.isArray(value);
81292
81242
  }
81293
- function errorMessage$2(error) {
81243
+ function errorMessage$3(error) {
81294
81244
  return error instanceof Error ? error.message : String(error);
81295
81245
  }
81296
81246
  //#endregion
@@ -92177,6 +92127,7 @@ var ToolScheduler = class {
92177
92127
  //#endregion
92178
92128
  //#region ../../packages/agent-core/src/loop/tool-call.ts
92179
92129
  const GRACE_TIMEOUT_MS = 2e3;
92130
+ const STEER_POLL_INTERVAL_MS = 150;
92180
92131
  const TOOL_OUTPUT_EMPTY = "Tool output is empty.";
92181
92132
  const TOOL_OUTPUT_NON_TEXT = "Tool returned non-text content.";
92182
92133
  const validators = /* @__PURE__ */ new WeakMap();
@@ -92196,15 +92147,29 @@ async function runToolCallBatch(step, response) {
92196
92147
  const scheduler = new ToolScheduler();
92197
92148
  const pendingResults = [];
92198
92149
  let stopTurn = false;
92150
+ const steerController = step.hasPendingSteer !== void 0 ? new AbortController() : void 0;
92151
+ const effectiveStep = steerController === void 0 ? step : {
92152
+ ...step,
92153
+ signal: AbortSignal.any([step.signal, steerController.signal])
92154
+ };
92155
+ const abortOnSteer = () => {
92156
+ if (step.hasPendingSteer?.() === true && steerController !== void 0 && !steerController.signal.aborted) steerController.abort(userCancellationReason());
92157
+ };
92158
+ abortOnSteer();
92159
+ const steerPoll = steerController === void 0 ? void 0 : setInterval(() => {
92160
+ try {
92161
+ abortOnSteer();
92162
+ } catch {}
92163
+ }, STEER_POLL_INTERVAL_MS);
92199
92164
  try {
92200
92165
  for (let index = 0; index < calls.length; index += 1) {
92201
92166
  const call = calls[index];
92202
- if (step.signal.aborted) {
92167
+ if (effectiveStep.signal.aborted) {
92203
92168
  await dispatchToolCall(step, call, call.args);
92204
- pendingResults.push(Promise.resolve(makeErrorToolResult(call, call.args, abortedToolOutput(call.toolName, step.signal))));
92169
+ pendingResults.push(Promise.resolve(makeErrorToolResult(call, call.args, abortedToolOutput(call.toolName, effectiveStep.signal))));
92205
92170
  continue;
92206
92171
  }
92207
- const prepared = await prepareToolCall(step, call);
92172
+ const prepared = await prepareToolCall(effectiveStep, call);
92208
92173
  pendingResults.push(scheduler.add(prepared.task));
92209
92174
  if (prepared.stopBatchAfterThis === true) {
92210
92175
  stopTurn = true;
@@ -92216,7 +92181,7 @@ async function runToolCallBatch(step, response) {
92216
92181
  }
92217
92182
  }
92218
92183
  for (const pendingResult of pendingResults) {
92219
- const result = await finalizePendingToolResult(step, await pendingResult);
92184
+ const result = await finalizePendingToolResult(effectiveStep, await pendingResult);
92220
92185
  if (result.stopTurn === true) stopTurn = true;
92221
92186
  await step.dispatchEvent({
92222
92187
  type: "tool.result",
@@ -92226,6 +92191,7 @@ async function runToolCallBatch(step, response) {
92226
92191
  });
92227
92192
  }
92228
92193
  } finally {
92194
+ if (steerPoll !== void 0) clearInterval(steerPoll);
92229
92195
  await Promise.allSettled(pendingResults);
92230
92196
  }
92231
92197
  return { stopTurn };
@@ -92289,7 +92255,7 @@ function parseToolCallArguments(raw) {
92289
92255
  } catch {
92290
92256
  return {
92291
92257
  success: false,
92292
- error: errorMessage$3(error)
92258
+ error: errorMessage$4(error)
92293
92259
  };
92294
92260
  }
92295
92261
  }
@@ -92369,7 +92335,7 @@ async function prepareToolCall(step, call) {
92369
92335
  toolCallId: call.toolCall.id,
92370
92336
  error
92371
92337
  });
92372
- return settleError(effectiveArgs, error instanceof PathSecurityError ? error.message : `Tool "${call.toolName}" failed to resolve execution: ${errorMessage$3(error)}`);
92338
+ return settleError(effectiveArgs, error instanceof PathSecurityError ? error.message : `Tool "${call.toolName}" failed to resolve execution: ${errorMessage$4(error)}`);
92373
92339
  }
92374
92340
  const displayFields = toolCallDisplayFieldsFromExecution(execution);
92375
92341
  const settleAborted = () => settleError(effectiveArgs, abortedToolOutput(call.toolName, step.signal), displayFields);
@@ -92428,7 +92394,7 @@ async function runPrepareToolExecutionHook(step, call) {
92428
92394
  return {
92429
92395
  kind: "hookFailed",
92430
92396
  args,
92431
- output: `prepareToolExecution hook failed for "${call.toolName}": ${errorMessage$3(error)}`
92397
+ output: `prepareToolExecution hook failed for "${call.toolName}": ${errorMessage$4(error)}`
92432
92398
  };
92433
92399
  }
92434
92400
  const effectiveArgs = hookResult?.updatedArgs ?? args;
@@ -92469,7 +92435,7 @@ async function runAuthorizeToolExecutionHook(step, call, args, execution) {
92469
92435
  };
92470
92436
  return {
92471
92437
  block: true,
92472
- reason: `authorizeToolExecution hook failed for "${call.toolName}": ${errorMessage$3(error)}`
92438
+ reason: `authorizeToolExecution hook failed for "${call.toolName}": ${errorMessage$4(error)}`
92473
92439
  };
92474
92440
  }
92475
92441
  }
@@ -92496,7 +92462,7 @@ async function runRunnableToolCall(step, call, effectiveArgs, metadata, executio
92496
92462
  toolCallId: toolCall.id,
92497
92463
  error
92498
92464
  });
92499
- return makeErrorToolResult(call, effectiveArgs, aborted ? abortedToolOutput(toolName, signal) : `Tool "${toolName}" failed: ${errorMessage$3(error)}`);
92465
+ return makeErrorToolResult(call, effectiveArgs, aborted ? abortedToolOutput(toolName, signal) : `Tool "${toolName}" failed: ${errorMessage$4(error)}`);
92500
92466
  }
92501
92467
  return makeToolResult(call, effectiveArgs, toolResult);
92502
92468
  }
@@ -92528,7 +92494,7 @@ async function finalizePendingToolResult(step, pendingResult) {
92528
92494
  toolCallId: pendingResult.toolCall.id,
92529
92495
  error
92530
92496
  });
92531
- const output = aborted ? `Tool "${pendingResult.toolName}" aborted during finalizeToolResult hook.` : `finalizeToolResult hook failed for "${pendingResult.toolName}": ${errorMessage$3(error)}`;
92497
+ const output = aborted ? `Tool "${pendingResult.toolName}" aborted during finalizeToolResult hook.` : `finalizeToolResult hook failed for "${pendingResult.toolName}": ${errorMessage$4(error)}`;
92532
92498
  return {
92533
92499
  ...pendingResult,
92534
92500
  stopTurn: pendingResult.stopTurn,
@@ -92698,7 +92664,8 @@ async function executeLoopStep(deps) {
92698
92664
  signal,
92699
92665
  turnId,
92700
92666
  currentStep,
92701
- stepUuid
92667
+ stepUuid,
92668
+ hasPendingSteer: deps.hasPendingSteer
92702
92669
  };
92703
92670
  await dispatchEvent({
92704
92671
  type: "step.begin",
@@ -92860,7 +92827,8 @@ async function runTurn(input) {
92860
92827
  log,
92861
92828
  currentStep: steps,
92862
92829
  maxRetryAttempts,
92863
- recordUsage: recordStepUsage
92830
+ recordUsage: recordStepUsage,
92831
+ hasPendingSteer: input.hasPendingSteer
92864
92832
  });
92865
92833
  activeStep = void 0;
92866
92834
  if (stepResult.stopReason === "tool_use") continue;
@@ -92884,7 +92852,7 @@ async function runTurn(input) {
92884
92852
  usage
92885
92853
  };
92886
92854
  }
92887
- dispatchEvent(makeInterruptedEvent(isMaxStepsExceededError(error) ? "max_steps" : "error", steps, activeStep, errorMessage$3(error)));
92855
+ dispatchEvent(makeInterruptedEvent(isMaxStepsExceededError(error) ? "max_steps" : "error", steps, activeStep, errorMessage$4(error)));
92888
92856
  throw error;
92889
92857
  }
92890
92858
  return {
@@ -97914,7 +97882,7 @@ var TurnFlow = class {
97914
97882
  });
97915
97883
  return this.launch(input, origin);
97916
97884
  }
97917
- steer(input, origin = USER_PROMPT_ORIGIN) {
97885
+ steer(input, origin = USER_PROMPT_ORIGIN, opts) {
97918
97886
  this.agent.records.logRecord({
97919
97887
  type: "turn.steer",
97920
97888
  input,
@@ -97923,7 +97891,8 @@ var TurnFlow = class {
97923
97891
  if (this.activeTurn) {
97924
97892
  this.steerBuffer.push({
97925
97893
  input,
97926
- origin
97894
+ origin,
97895
+ interrupt: opts?.interrupt
97927
97896
  });
97928
97897
  return null;
97929
97898
  }
@@ -98245,6 +98214,7 @@ var TurnFlow = class {
98245
98214
  log: this.agent.log,
98246
98215
  maxSteps: loopControl?.maxStepsPerTurn,
98247
98216
  maxRetryAttempts: loopControl?.maxRetriesPerStep,
98217
+ hasPendingSteer: () => this.steerBuffer.some((steer) => steer.origin.kind === "user" && steer.interrupt !== false),
98248
98218
  hooks: {
98249
98219
  beforeStep: async ({ signal: stepSignal, stepNumber }) => {
98250
98220
  this.flushSteerBuffer();
@@ -99236,7 +99206,7 @@ var Agent = class {
99236
99206
  this.turn.prompt(payload.input);
99237
99207
  },
99238
99208
  steer: (payload) => {
99239
- this.turn.steer(payload.input);
99209
+ this.turn.steer(payload.input, USER_PROMPT_ORIGIN, { interrupt: payload.interrupt });
99240
99210
  },
99241
99211
  cancel: (payload) => {
99242
99212
  this.turn.cancel(payload.turnId);
@@ -102426,7 +102396,7 @@ function buildMcpHttpHeaders(config, envLookup) {
102426
102396
  var require_windows = /* @__PURE__ */ __commonJSMin(((exports, module) => {
102427
102397
  module.exports = isexe;
102428
102398
  isexe.sync = sync;
102429
- var fs$3 = __require("fs");
102399
+ var fs$4 = __require("fs");
102430
102400
  function checkPathExt(path, options) {
102431
102401
  var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
102432
102402
  if (!pathext) return true;
@@ -102443,12 +102413,12 @@ var require_windows = /* @__PURE__ */ __commonJSMin(((exports, module) => {
102443
102413
  return checkPathExt(path, options);
102444
102414
  }
102445
102415
  function isexe(path, options, cb) {
102446
- fs$3.stat(path, function(er, stat) {
102416
+ fs$4.stat(path, function(er, stat) {
102447
102417
  cb(er, er ? false : checkStat(stat, path, options));
102448
102418
  });
102449
102419
  }
102450
102420
  function sync(path, options) {
102451
- return checkStat(fs$3.statSync(path), path, options);
102421
+ return checkStat(fs$4.statSync(path), path, options);
102452
102422
  }
102453
102423
  }));
102454
102424
  //#endregion
@@ -102456,14 +102426,14 @@ var require_windows = /* @__PURE__ */ __commonJSMin(((exports, module) => {
102456
102426
  var require_mode = /* @__PURE__ */ __commonJSMin(((exports, module) => {
102457
102427
  module.exports = isexe;
102458
102428
  isexe.sync = sync;
102459
- var fs$2 = __require("fs");
102429
+ var fs$3 = __require("fs");
102460
102430
  function isexe(path, options, cb) {
102461
- fs$2.stat(path, function(er, stat) {
102431
+ fs$3.stat(path, function(er, stat) {
102462
102432
  cb(er, er ? false : checkStat(stat, options));
102463
102433
  });
102464
102434
  }
102465
102435
  function sync(path, options) {
102466
- return checkStat(fs$2.statSync(path), options);
102436
+ return checkStat(fs$3.statSync(path), options);
102467
102437
  }
102468
102438
  function checkStat(stat, options) {
102469
102439
  return stat.isFile() && checkMode(stat, options);
@@ -102678,16 +102648,16 @@ var require_shebang_command = /* @__PURE__ */ __commonJSMin(((exports, module) =
102678
102648
  //#endregion
102679
102649
  //#region ../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/readShebang.js
102680
102650
  var require_readShebang = /* @__PURE__ */ __commonJSMin(((exports, module) => {
102681
- const fs$1 = __require("fs");
102651
+ const fs$2 = __require("fs");
102682
102652
  const shebangCommand = require_shebang_command();
102683
102653
  function readShebang(command) {
102684
102654
  const size = 150;
102685
102655
  const buffer = Buffer.alloc(size);
102686
102656
  let fd;
102687
102657
  try {
102688
- fd = fs$1.openSync(command, "r");
102689
- fs$1.readSync(fd, buffer, 0, size, 0);
102690
- fs$1.closeSync(fd);
102658
+ fd = fs$2.openSync(command, "r");
102659
+ fs$2.readSync(fd, buffer, 0, size, 0);
102660
+ fs$2.closeSync(fd);
102691
102661
  } catch (e) {}
102692
102662
  return shebangCommand(buffer.toString());
102693
102663
  }
@@ -117200,6 +117170,243 @@ function Document() {
117200
117170
  illegalConstructor();
117201
117171
  }
117202
117172
  setPrototypeOf(Document, Document$1).prototype = Document$1.prototype;
117173
+ /** `.tmp` files older than this are treated as orphaned writes and swept. */
117174
+ const TMP_ORPHAN_MAX_AGE_MS = 300 * 1e3;
117175
+ function documentConversionCacheDir() {
117176
+ return path$8.join(resolveScreamHome(), "cache", "document-conversion");
117177
+ }
117178
+ function isEnoent(error) {
117179
+ return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
117180
+ }
117181
+ function markitConversionCacheKey(bytes, extension) {
117182
+ const safeExtension = (extension.trim().toLowerCase().replace(/^\.+/, "") || "bin").replace(/[^a-z0-9]+/g, "_") || "bin";
117183
+ const safeVersion = getCoreVersion().replace(/[^a-z0-9]+/gi, "_");
117184
+ const digest = createHash("sha256").update(bytes).digest("hex");
117185
+ return `v${String(1)}-${safeVersion}-${safeExtension}-${digest}`;
117186
+ }
117187
+ function cacheEntryPath(key) {
117188
+ return path$8.join(documentConversionCacheDir(), `${key}.json`);
117189
+ }
117190
+ function errorMessage$2(error) {
117191
+ return error instanceof Error ? error.message : String(error);
117192
+ }
117193
+ function parseCacheEntry(raw) {
117194
+ const parsed = JSON.parse(raw);
117195
+ if (typeof parsed !== "object" || parsed === null) return null;
117196
+ if (!("version" in parsed) || parsed.version !== 1) return null;
117197
+ if (!("content" in parsed) || typeof parsed.content !== "string" || parsed.content.length === 0) return null;
117198
+ return {
117199
+ version: 1,
117200
+ content: parsed.content
117201
+ };
117202
+ }
117203
+ async function readMarkitConversionCache(key) {
117204
+ const target = cacheEntryPath(key);
117205
+ let raw;
117206
+ try {
117207
+ raw = await fs$1.readFile(target, "utf8");
117208
+ } catch (error) {
117209
+ if (!isEnoent(error)) log.debug("document conversion cache read failed", { error: errorMessage$2(error) });
117210
+ return { status: "miss" };
117211
+ }
117212
+ let entry;
117213
+ try {
117214
+ entry = parseCacheEntry(raw);
117215
+ } catch (error) {
117216
+ log.debug("document conversion cache read failed", { error: errorMessage$2(error) });
117217
+ entry = null;
117218
+ }
117219
+ if (entry === null) {
117220
+ await fs$1.rm(target, { force: true }).catch(() => void 0);
117221
+ return { status: "miss" };
117222
+ }
117223
+ return {
117224
+ status: "hit",
117225
+ content: entry.content
117226
+ };
117227
+ }
117228
+ async function pruneMarkitConversionCache(cacheDir) {
117229
+ let names;
117230
+ try {
117231
+ names = await fs$1.readdir(cacheDir);
117232
+ } catch (error) {
117233
+ if (!isEnoent(error)) log.debug("document conversion cache prune failed", { error: errorMessage$2(error) });
117234
+ return;
117235
+ }
117236
+ const now = Date.now();
117237
+ const entries = [];
117238
+ let totalBytes = 0;
117239
+ for (const name of names) {
117240
+ const entryPath = path$8.join(cacheDir, name);
117241
+ let stat;
117242
+ try {
117243
+ stat = await fs$1.stat(entryPath);
117244
+ } catch (error) {
117245
+ if (!isEnoent(error)) log.debug("document conversion cache prune failed", { error: errorMessage$2(error) });
117246
+ continue;
117247
+ }
117248
+ if (!stat.isFile()) continue;
117249
+ if (name.endsWith(".tmp")) {
117250
+ if (now - stat.mtimeMs > TMP_ORPHAN_MAX_AGE_MS) await fs$1.rm(entryPath, { force: true }).catch(() => void 0);
117251
+ continue;
117252
+ }
117253
+ if (!name.endsWith(".json")) continue;
117254
+ entries.push({
117255
+ path: entryPath,
117256
+ size: stat.size,
117257
+ mtimeMs: stat.mtimeMs
117258
+ });
117259
+ totalBytes += stat.size;
117260
+ }
117261
+ if (totalBytes <= 268435456) return;
117262
+ entries.sort((a, b) => a.mtimeMs - b.mtimeMs);
117263
+ for (const entry of entries) {
117264
+ if (totalBytes <= 268435456) break;
117265
+ try {
117266
+ await fs$1.rm(entry.path, { force: true });
117267
+ totalBytes -= entry.size;
117268
+ } catch (error) {
117269
+ if (!isEnoent(error)) log.debug("document conversion cache prune failed", { error: errorMessage$2(error) });
117270
+ }
117271
+ }
117272
+ }
117273
+ async function writeMarkitConversionCache(key, content) {
117274
+ const cacheDir = documentConversionCacheDir();
117275
+ const target = path$8.join(cacheDir, `${key}.json`);
117276
+ const tempPath = path$8.join(cacheDir, `${key}.${String(process.pid)}.${String(Date.now())}.${randomUUID()}.tmp`);
117277
+ const payload = JSON.stringify({
117278
+ version: 1,
117279
+ content
117280
+ });
117281
+ try {
117282
+ await fs$1.mkdir(cacheDir, { recursive: true });
117283
+ await fs$1.writeFile(tempPath, payload);
117284
+ await fs$1.rename(tempPath, target);
117285
+ } catch (error) {
117286
+ await fs$1.rm(tempPath, { force: true }).catch(() => void 0);
117287
+ log.debug("document conversion cache write failed", { error: errorMessage$2(error) });
117288
+ return;
117289
+ }
117290
+ pruneMarkitConversionCache(cacheDir).catch((error) => {
117291
+ log.debug("document conversion cache prune failed", { error: errorMessage$2(error) });
117292
+ });
117293
+ }
117294
+ //#endregion
117295
+ //#region ../../packages/agent-core/src/utils/markit.ts
117296
+ function logMuPdfWasmOutput(stream, values) {
117297
+ const message = values.length === 1 && typeof values[0] === "string" ? values[0] : values.map(String).join(" ");
117298
+ log.debug("mupdf wasm output", {
117299
+ stream,
117300
+ message
117301
+ });
117302
+ }
117303
+ function installMuPdfWasmLogger() {
117304
+ const globalScope = globalThis;
117305
+ const moduleConfig = globalScope.$libmupdf_wasm_Module ?? {};
117306
+ moduleConfig.print = (...values) => logMuPdfWasmOutput("stdout", values);
117307
+ moduleConfig.printErr = (...values) => logMuPdfWasmOutput("stderr", values);
117308
+ globalScope.$libmupdf_wasm_Module = moduleConfig;
117309
+ }
117310
+ installMuPdfWasmLogger();
117311
+ let markit = async () => {
117312
+ const promise = import("./markit-DG5XsAGz.mjs").then(({ Markit }) => {
117313
+ const instance = new Markit();
117314
+ markit = () => instance;
117315
+ return instance;
117316
+ });
117317
+ markit = () => promise;
117318
+ return promise;
117319
+ };
117320
+ function normalizeExtension(extension) {
117321
+ const trimmed = extension.trim().toLowerCase();
117322
+ if (!trimmed) return ".bin";
117323
+ return trimmed.startsWith(".") ? trimmed : `.${trimmed}`;
117324
+ }
117325
+ function normalizeError(error) {
117326
+ if (error instanceof Error && error.message.trim().length > 0) return error.message.trim();
117327
+ return "Conversion failed";
117328
+ }
117329
+ function isAbort(error) {
117330
+ return error instanceof Error && error.name === "AbortError";
117331
+ }
117332
+ async function untilAborted(signal, task) {
117333
+ if (signal === void 0) return task();
117334
+ signal.throwIfAborted();
117335
+ return new Promise((resolve, reject) => {
117336
+ const onAbort = () => {
117337
+ reject(abortError());
117338
+ };
117339
+ signal.addEventListener("abort", onAbort, { once: true });
117340
+ task().then(resolve, reject).finally(() => {
117341
+ signal.removeEventListener("abort", onAbort);
117342
+ });
117343
+ });
117344
+ }
117345
+ async function runMarkitConversion(task, signal) {
117346
+ try {
117347
+ const instance = await markit();
117348
+ return await untilAborted(signal, () => task(instance));
117349
+ } catch (error) {
117350
+ if (isAbort(error)) throw abortError();
117351
+ throw error;
117352
+ }
117353
+ }
117354
+ function finalizeConversion(markdown) {
117355
+ if (typeof markdown === "string" && markdown.length > 0) return {
117356
+ content: markdown,
117357
+ ok: true
117358
+ };
117359
+ return {
117360
+ content: "",
117361
+ ok: false,
117362
+ error: "Conversion produced no output"
117363
+ };
117364
+ }
117365
+ function toBuffer(bytes) {
117366
+ return Buffer.isBuffer(bytes) ? bytes : Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength);
117367
+ }
117368
+ function throwIfAborted(signal) {
117369
+ if (signal?.aborted) throw abortError();
117370
+ }
117371
+ async function runCachedBufferConversion(bytes, streamInfo, signal, cacheEnabled = true) {
117372
+ const cacheKey = cacheEnabled ? markitConversionCacheKey(bytes, streamInfo.extension ?? streamInfo.mimetype ?? ".bin") : void 0;
117373
+ if (cacheKey !== void 0) {
117374
+ throwIfAborted(signal);
117375
+ const cached = await readMarkitConversionCache(cacheKey);
117376
+ throwIfAborted(signal);
117377
+ if (cached.status === "hit") return {
117378
+ content: cached.content,
117379
+ ok: true,
117380
+ cache: "hit"
117381
+ };
117382
+ }
117383
+ throwIfAborted(signal);
117384
+ let result;
117385
+ try {
117386
+ result = await runMarkitConversion((markitInstance) => markitInstance.convert(toBuffer(bytes), streamInfo), signal);
117387
+ } catch (error) {
117388
+ if (isAbort(error)) throw abortError();
117389
+ return {
117390
+ content: "",
117391
+ ok: false,
117392
+ error: normalizeError(error),
117393
+ cache: cacheEnabled ? "miss" : "skipped"
117394
+ };
117395
+ }
117396
+ const finalized = finalizeConversion(result.markdown);
117397
+ if (finalized.ok && cacheKey !== void 0) await writeMarkitConversionCache(cacheKey, finalized.content);
117398
+ return {
117399
+ ...finalized,
117400
+ cache: cacheEnabled ? "miss" : "skipped"
117401
+ };
117402
+ }
117403
+ async function convertBufferWithMarkit(buffer, extension, signal, options) {
117404
+ const normalizedExtension = normalizeExtension(extension);
117405
+ return runCachedBufferConversion(buffer, {
117406
+ extension: normalizedExtension,
117407
+ filename: `input${normalizedExtension}`
117408
+ }, signal, options?.useCache ?? true);
117409
+ }
117203
117410
  //#endregion
117204
117411
  //#region ../../packages/agent-core/src/tools/providers/local-fetch-url.ts
117205
117412
  /**
@@ -117217,6 +117424,49 @@ setPrototypeOf(Document, Document$1).prototype = Document$1.prototype;
117217
117424
  * common content containers (`<article>` / `<main>` / `<body>`)
117218
117425
  * before throwing a "meaningful content" error.
117219
117426
  */
117427
+ /** Document types the markit engine converts to markdown. */
117428
+ const CONVERTIBLE_EXTENSIONS = new Set([
117429
+ ".pdf",
117430
+ ".docx",
117431
+ ".pptx",
117432
+ ".xlsx",
117433
+ ".epub"
117434
+ ]);
117435
+ const CONVERTIBLE_MIME_PREFIXES = [
117436
+ ["application/pdf", ".pdf"],
117437
+ ["application/x-pdf", ".pdf"],
117438
+ ["application/vnd.openxmlformats-officedocument.wordprocessingml.document", ".docx"],
117439
+ ["application/vnd.openxmlformats-officedocument.presentationml.presentation", ".pptx"],
117440
+ ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", ".xlsx"],
117441
+ ["application/epub+zip", ".epub"]
117442
+ ];
117443
+ /**
117444
+ * Decide whether a response is a convertible document, from Content-Type
117445
+ * first and the URL path extension as fallback. `confident: true` means the
117446
+ * Content-Type itself declared a document type (conversion failure is a real
117447
+ * error); `confident: false` means only the URL extension matched (an HTML
117448
+ * page at a .pdf URL must fall back to normal extraction).
117449
+ */
117450
+ function resolveDocumentExtension(url, contentType) {
117451
+ for (const [prefix, extension] of CONVERTIBLE_MIME_PREFIXES) if (contentType.startsWith(prefix)) return {
117452
+ extension,
117453
+ confident: true
117454
+ };
117455
+ if (contentType.length > 0 && !contentType.startsWith("application/octet-stream") && !contentType.startsWith("binary/octet-stream")) return;
117456
+ try {
117457
+ const pathname = new URL(url).pathname.toLowerCase();
117458
+ const dot = pathname.lastIndexOf(".");
117459
+ if (dot >= 0) {
117460
+ const extension = pathname.slice(dot);
117461
+ if (CONVERTIBLE_EXTENSIONS.has(extension)) return {
117462
+ extension,
117463
+ confident: false
117464
+ };
117465
+ }
117466
+ } catch {}
117467
+ }
117468
+ /** Hard ceiling for one markit conversion (omp uses 20s; allow slow hosts). */
117469
+ const CONVERSION_TIMEOUT_MS = 3e4;
117220
117470
  const DEFAULT_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36";
117221
117471
  const DEFAULT_MAX_BYTES = 10 * 1024 * 1024;
117222
117472
  const FETCH_TIMEOUT_MS = 3e4;
@@ -117330,10 +117580,16 @@ var LocalFetchURLProvider = class {
117330
117580
  throw new Error(`Response body too large: ${String(cl)} bytes exceeds maxBytes (${String(this.maxBytes)}).`);
117331
117581
  }
117332
117582
  }
117583
+ const contentType = (response.headers.get("content-type") ?? "").toLowerCase();
117584
+ const documentExtension = resolveDocumentExtension(url, contentType);
117585
+ if (documentExtension !== void 0) return this.fetchDocument(response, documentExtension.extension, contentType, documentExtension.confident);
117333
117586
  const body = await response.text();
117334
117587
  const actualBytes = Buffer.byteLength(body, "utf8");
117335
117588
  if (actualBytes > this.maxBytes) throw new Error(`Response body too large: ${String(actualBytes)} bytes exceeds maxBytes (${String(this.maxBytes)}).`);
117336
- const contentType = (response.headers.get("content-type") ?? "").toLowerCase();
117589
+ return this.extractTextResponse(body, contentType);
117590
+ }
117591
+ /** Text-path extraction shared by the normal flow and the document fallback. */
117592
+ extractTextResponse(body, contentType) {
117337
117593
  if (contentType.startsWith("text/plain") || contentType.startsWith("text/markdown")) return {
117338
117594
  content: body,
117339
117595
  kind: "passthrough"
@@ -117343,6 +117599,28 @@ var LocalFetchURLProvider = class {
117343
117599
  kind: "extracted"
117344
117600
  };
117345
117601
  }
117602
+ /**
117603
+ * Fetch a convertible document (PDF/Office) as binary and convert it to
117604
+ * markdown via the markit engine (lazy-loaded, cached on disk).
117605
+ *
117606
+ * `confident` distinguishes detection strength: a convertible Content-Type
117607
+ * means conversion failure is a real error (corrupt document), while an
117608
+ * extension-only guess (e.g. an HTML viewer page at a .pdf URL) falls back
117609
+ * to the normal text extraction path instead of erroring (omp's behavior).
117610
+ */
117611
+ async fetchDocument(response, extension, contentType, confident) {
117612
+ const bytes = new Uint8Array(await response.arrayBuffer());
117613
+ if (bytes.byteLength > this.maxBytes) throw new Error(`Response body too large: ${String(bytes.byteLength)} bytes exceeds maxBytes (${String(this.maxBytes)}).`);
117614
+ const converted = await convertBufferWithMarkit(bytes, extension, AbortSignal.timeout(CONVERSION_TIMEOUT_MS));
117615
+ if (!converted.ok) {
117616
+ if (!confident) return this.extractTextResponse(new TextDecoder().decode(bytes), contentType);
117617
+ throw new Error(`Document conversion failed (${extension}): ${converted.error ?? "unknown error"}`);
117618
+ }
117619
+ return {
117620
+ content: converted.content,
117621
+ kind: "extracted"
117622
+ };
117623
+ }
117346
117624
  extractMainContent(html) {
117347
117625
  const primary = parseHTML(html);
117348
117626
  try {
@@ -121127,7 +121405,8 @@ var SDKRpcClient = class {
121127
121405
  return (await this.getRpc()).steer({
121128
121406
  sessionId: input.sessionId,
121129
121407
  agentId: this.interactiveAgentId,
121130
- input: input.input
121408
+ input: input.input,
121409
+ interrupt: input.interrupt
121131
121410
  });
121132
121411
  }
121133
121412
  async generateAgentsMd(input) {
@@ -121619,11 +121898,12 @@ var Session = class {
121619
121898
  input: normalizePromptInput(input)
121620
121899
  });
121621
121900
  }
121622
- async steer(input) {
121901
+ async steer(input, opts) {
121623
121902
  this.ensureOpen();
121624
121903
  await this.rpc.steer({
121625
121904
  sessionId: this.id,
121626
- input: normalizePromptInput(input)
121905
+ input: normalizePromptInput(input),
121906
+ interrupt: opts?.interrupt
121627
121907
  });
121628
121908
  }
121629
121909
  async init(targetDir) {
@@ -122390,7 +122670,7 @@ function optionalBuildString(value) {
122390
122670
  return typeof value === "string" && value.length > 0 ? value : void 0;
122391
122671
  }
122392
122672
  const SCREAM_BUILD_INFO = {
122393
- version: optionalBuildString("0.10.2"),
122673
+ version: optionalBuildString("0.10.3"),
122394
122674
  channel: optionalBuildString(""),
122395
122675
  commit: optionalBuildString(""),
122396
122676
  buildTarget: optionalBuildString("darwin-arm64")
@@ -123297,15 +123577,13 @@ const BRAILLE_SPINNER_FRAMES = [
123297
123577
  "⠇",
123298
123578
  "⠏"
123299
123579
  ];
123300
- const MOON_SPINNER_FRAMES = [
123301
- "💬",
123302
- "🗯️",
123303
- "🫯",
123304
- "💭",
123305
- "💬",
123306
- "🗯️",
123307
- "🫯",
123308
- "💭"
123580
+ const PIXEL_PULSE_FRAMES = [
123581
+ "",
123582
+ "",
123583
+ "",
123584
+ "",
123585
+ "",
123586
+ ""
123309
123587
  ];
123310
123588
  const PULSE_WAVE_FRAMES = [
123311
123589
  {
@@ -126076,6 +126354,21 @@ const lightColors = {
126076
126354
  function getColorPalette(theme) {
126077
126355
  return theme === "dark" ? darkColors : lightColors;
126078
126356
  }
126357
+ /**
126358
+ * True when a hex background is light enough to need dark text on top
126359
+ * (relative luminance above 0.5). Shared by badge/tag renderers so a
126360
+ * fluorescent-green block never gets unreadable white text.
126361
+ */
126362
+ function isLightBgHex(hex) {
126363
+ const r = parseInt(hex.slice(1, 3), 16);
126364
+ const g = parseInt(hex.slice(3, 5), 16);
126365
+ const b = parseInt(hex.slice(5, 7), 16);
126366
+ return (.299 * r + .587 * g + .114 * b) / 255 > .5;
126367
+ }
126368
+ /** Foreground colour with readable contrast on the given hex background. */
126369
+ function contrastTextHex(bgHex) {
126370
+ return isLightBgHex(bgHex) ? "#000000" : "#FFFFFF";
126371
+ }
126079
126372
  //#endregion
126080
126373
  //#region src/tui/theme/styles.ts
126081
126374
  /**
@@ -133099,15 +133392,11 @@ var MoonLoader = class extends Text {
133099
133392
  currentFrame = 0;
133100
133393
  intervalId = null;
133101
133394
  ui;
133102
- frames;
133103
- interval;
133104
133395
  colorFn;
133105
133396
  label;
133106
- constructor(ui, style = "moon", colorFn, label = "") {
133397
+ constructor(ui, colorFn, label = "") {
133107
133398
  super("", 1, 0);
133108
133399
  this.ui = ui;
133109
- this.frames = style === "moon" ? [...MOON_SPINNER_FRAMES] : [...BRAILLE_SPINNER_FRAMES];
133110
- this.interval = style === "moon" ? 120 : 80;
133111
133400
  this.colorFn = colorFn;
133112
133401
  this.label = label;
133113
133402
  this.start();
@@ -133115,9 +133404,9 @@ var MoonLoader = class extends Text {
133115
133404
  start() {
133116
133405
  this.updateDisplay();
133117
133406
  this.intervalId = setInterval(() => {
133118
- this.currentFrame = (this.currentFrame + 1) % this.frames.length;
133407
+ this.currentFrame = (this.currentFrame + 1) % BRAILLE_SPINNER_FRAMES.length;
133119
133408
  this.updateDisplay();
133120
- }, this.interval);
133409
+ }, 80);
133121
133410
  }
133122
133411
  stop() {
133123
133412
  if (this.intervalId) {
@@ -133134,7 +133423,7 @@ var MoonLoader = class extends Text {
133134
133423
  this.updateDisplay();
133135
133424
  }
133136
133425
  updateDisplay() {
133137
- const frame = this.frames[this.currentFrame];
133426
+ const frame = BRAILLE_SPINNER_FRAMES[this.currentFrame];
133138
133427
  const coloredFrame = this.colorFn ? this.colorFn(frame) : frame;
133139
133428
  this.setText(this.label ? `${coloredFrame} ${this.label}` : coloredFrame);
133140
133429
  this.ui.requestComponentRender(this);
@@ -133343,7 +133632,7 @@ var SkillCenterLoadingComponent = class extends Container {
133343
133632
  this.label = label;
133344
133633
  this.host = host;
133345
133634
  const tint = (s) => chalk.hex(host.state.theme.colors.primary)(s);
133346
- this.loader = new MoonLoader(host.state.ui, "braille", tint, this.label);
133635
+ this.loader = new MoonLoader(host.state.ui, tint, this.label);
133347
133636
  this.addChild(new Spacer(1));
133348
133637
  this.addChild(this.loader);
133349
133638
  }
@@ -136928,6 +137217,16 @@ var EditorKeyboardController = class {
136928
137217
  host.restoreEditor();
136929
137218
  return;
136930
137219
  }
137220
+ if (host.state.queuedMessages.length > 0) {
137221
+ const restored = host.state.queuedMessages.map((m) => m.text.trim()).filter((text) => text.length > 0);
137222
+ host.clearQueuedMessages();
137223
+ const existing = host.state.editor.getText();
137224
+ const parts = [...restored, existing].filter((s) => s.trim().length > 0);
137225
+ host.state.editor.setText(parts.join("\n"));
137226
+ host.updateQueueDisplay();
137227
+ host.state.ui.requestRender();
137228
+ return;
137229
+ }
136931
137230
  if (host.state.appState.isCompacting) {
136932
137231
  this.cancelCurrentCompaction();
136933
137232
  return;
@@ -137722,6 +138021,7 @@ var SessionEventHandler = class {
137722
138021
  handleStepCompleted(event) {
137723
138022
  this.host.streamingUI.flushNow();
137724
138023
  this.maybeShowDebugTiming(event);
138024
+ this.drainQueuedMessagesIntoSteer();
137725
138025
  if (event.finishReason !== "max_tokens") return;
137726
138026
  const title = this.host.streamingUI.markStepTruncated(String(event.turnId), event.step) > 0 ? t("handler.max_tokens_truncated") : t("handler.max_tokens_no_tool");
137727
138027
  const detail = this.isAnthropicSessionActive() ? t("handler.max_tokens_hint") : void 0;
@@ -137732,6 +138032,40 @@ var SessionEventHandler = class {
137732
138032
  const text = formatStepDebugTiming(event);
137733
138033
  if (text !== void 0) this.host.showStatus(text);
137734
138034
  }
138035
+ /**
138036
+ * Auto-insert queued messages at the step boundary. The current step has
138037
+ * finished, so queued input is steered in with interrupt: false — it
138038
+ * never kills in-flight tools; it reaches the model at the next call.
138039
+ * Race-safe by design: if the turn already ended between the event and
138040
+ * the steer call, the core launches a fresh turn with the message.
138041
+ * (Ctrl+S remains the immediate-interrupt path.)
138042
+ *
138043
+ * Skipped while `deferUserMessages` is set: /init and make-skill run
138044
+ * system-triggered flows whose steps must not receive user input.
138045
+ */
138046
+ drainQueuedMessagesIntoSteer() {
138047
+ const { state } = this.host;
138048
+ const session = this.host.session;
138049
+ if (session === void 0 || state.appState.isCompacting || this.host.deferUserMessages) return;
138050
+ const items = state.queuedMessages;
138051
+ if (items.length === 0) return;
138052
+ state.queuedMessages = [];
138053
+ this.host.updateQueueDisplay();
138054
+ for (const item of items) {
138055
+ this.host.appendTranscriptEntry({
138056
+ id: nextTranscriptId(),
138057
+ kind: "user",
138058
+ turnId: this.host.streamingUI.getTurnContext().turnId,
138059
+ renderMode: "plain",
138060
+ content: item.text,
138061
+ ...item.imageAttachmentIds !== void 0 && item.imageAttachmentIds.length > 0 ? { imageAttachmentIds: item.imageAttachmentIds } : {}
138062
+ });
138063
+ session.steer(item.parts ?? item.text, { interrupt: false }).catch((error) => {
138064
+ const message = formatErrorMessage(error);
138065
+ this.host.showError(t("input.guide_failed", { message }));
138066
+ });
138067
+ }
138068
+ }
137735
138069
  isAnthropicSessionActive() {
137736
138070
  const { state } = this.host;
137737
138071
  const providerKey = state.appState.availableModels[state.appState.model]?.provider;
@@ -137914,7 +138248,7 @@ var SessionEventHandler = class {
137914
138248
  return;
137915
138249
  }
137916
138250
  const tint = (s) => chalk.hex(state.theme.colors.textMuted)(s);
137917
- const spinner = new MoonLoader(state.ui, "braille", tint, label);
138251
+ const spinner = new MoonLoader(state.ui, tint, label);
137918
138252
  state.transcriptContainer.addChild(spinner);
137919
138253
  this.mcpServerStatusSpinners.set(name, spinner);
137920
138254
  state.ui.requestRender();
@@ -141053,7 +141387,7 @@ var TranscriptController = class TranscriptController {
141053
141387
  }
141054
141388
  showProgressSpinner(label) {
141055
141389
  const tint = (s) => chalk.hex(this.host.state.theme.colors.primary)(s);
141056
- const spinner = new MoonLoader(this.host.state.ui, "braille", tint, label);
141390
+ const spinner = new MoonLoader(this.host.state.ui, tint, label);
141057
141391
  const spacer = new Spacer(1);
141058
141392
  const container = this.host.state.transcriptContainer;
141059
141393
  container.addChild(spacer);
@@ -141668,7 +142002,7 @@ var LifecycleController = class LifecycleController {
141668
142002
  this.stopPulseWave();
141669
142003
  break;
141670
142004
  case "composing": {
141671
- const spinner = this.ensureActivitySpinner("braille", "working...", (s) => chalk.hex(state.theme.colors.primary)(s));
142005
+ const spinner = this.ensureActivitySpinner("working...", (s) => chalk.hex(state.theme.colors.primary)(s));
141672
142006
  state.activityContainer.addChild(new ActivityPaneComponent({
141673
142007
  mode: "composing",
141674
142008
  spinner
@@ -141710,14 +142044,10 @@ var LifecycleController = class LifecycleController {
141710
142044
  this.host.state.terminal.setProgress(active);
141711
142045
  this.host.state.terminalState.progressActive = active;
141712
142046
  }
141713
- ensureActivitySpinner(style, label = "", colorFn) {
141714
- if (this.host.state.activitySpinner?.style !== style) this.stopActivitySpinner();
142047
+ ensureActivitySpinner(label = "", colorFn) {
141715
142048
  if (this.host.state.activitySpinner === null) {
141716
- const instance = new MoonLoader(this.host.state.ui, style, colorFn, label);
141717
- this.host.state.activitySpinner = {
141718
- instance,
141719
- style
141720
- };
142049
+ const instance = new MoonLoader(this.host.state.ui, colorFn, label);
142050
+ this.host.state.activitySpinner = { instance };
141721
142051
  return instance;
141722
142052
  }
141723
142053
  this.host.state.activitySpinner.instance.setLabel(label);
@@ -144333,7 +144663,10 @@ var ApprovalPanelComponent = class extends Container {
144333
144663
  onToggleToolOutput;
144334
144664
  onTogglePlanExpand;
144335
144665
  onOpenPreview;
144336
- constructor(request, onResponse, colors, onToggleToolOutput, onTogglePlanExpand, onOpenPreview) {
144666
+ ui;
144667
+ animFrame = 0;
144668
+ intervalId = null;
144669
+ constructor(request, onResponse, colors, onToggleToolOutput, onTogglePlanExpand, onOpenPreview, ui) {
144337
144670
  super();
144338
144671
  this.request = request;
144339
144672
  this.onResponse = onResponse;
@@ -144341,6 +144674,7 @@ var ApprovalPanelComponent = class extends Container {
144341
144674
  this.onToggleToolOutput = onToggleToolOutput;
144342
144675
  this.onTogglePlanExpand = onTogglePlanExpand;
144343
144676
  this.onOpenPreview = onOpenPreview;
144677
+ this.ui = ui;
144344
144678
  this.feedbackInput.onSubmit = (value) => {
144345
144679
  this.submit(this.selectedIndex, value);
144346
144680
  };
@@ -144348,10 +144682,22 @@ var ApprovalPanelComponent = class extends Container {
144348
144682
  this.feedbackMode = false;
144349
144683
  this.feedbackInput.setValue("");
144350
144684
  };
144685
+ if (this.ui !== void 0) this.intervalId = setInterval(() => {
144686
+ this.animFrame = (this.animFrame + 1) % PIXEL_PULSE_FRAMES.length;
144687
+ this.ui?.requestComponentRender(this);
144688
+ }, 100);
144689
+ }
144690
+ /** Stop the selection pulse. Idempotent; called on submit and on hide. */
144691
+ stop() {
144692
+ if (this.intervalId !== null) {
144693
+ clearInterval(this.intervalId);
144694
+ this.intervalId = null;
144695
+ }
144351
144696
  }
144352
144697
  submit(index, feedback = "") {
144353
144698
  const option = this.choiceAt(index);
144354
144699
  if (!option) return;
144700
+ this.stop();
144355
144701
  this.onResponse({
144356
144702
  response: option.response,
144357
144703
  feedback: feedback || void 0,
@@ -144368,6 +144714,7 @@ var ApprovalPanelComponent = class extends Container {
144368
144714
  }
144369
144715
  handleInput(data) {
144370
144716
  if (matchesKey(data, Key.escape) || matchesKey(data, Key.ctrl("c")) || matchesKey(data, Key.ctrl("d"))) {
144717
+ this.stop();
144371
144718
  this.onResponse({ response: "rejected" });
144372
144719
  return;
144373
144720
  }
@@ -144418,11 +144765,9 @@ var ApprovalPanelComponent = class extends Container {
144418
144765
  this.feedbackInput.focused = this.focused && this.feedbackMode;
144419
144766
  const { data } = this.request;
144420
144767
  const blockStyles = makeBlockStyles(this.colors);
144421
- const borderColor = chalk.hex(this.colors.borderFocus);
144422
- const borderColorBold = chalk.bold.hex(this.colors.borderFocus);
144423
- const selectColorBold = chalk.bold.hex(this.colors.accent);
144768
+ const borderColor = chalk.hex(this.colors.primary);
144769
+ const borderColorBold = chalk.bold.hex(this.colors.primary);
144424
144770
  const dim = chalk.hex(this.colors.textDim);
144425
- const strong = chalk.hex(this.colors.textStrong);
144426
144771
  const horizontalBar = borderColor("─".repeat(width));
144427
144772
  const indent = (s) => ` ${s}`;
144428
144773
  const title = headerFor(data.tool_name);
@@ -144447,8 +144792,11 @@ var ApprovalPanelComponent = class extends Container {
144447
144792
  const num = idx + 1;
144448
144793
  const labelWithNum = `${String(num)}. ${option.label}`;
144449
144794
  if (this.feedbackMode && option.requires_feedback === true && isSelected) lines.push(indent(this.renderInlineFeedbackLine(width - 2, labelWithNum)));
144450
- else if (isSelected) lines.push(indent(`${selectColorBold("▶")} ${selectColorBold(labelWithNum)}`));
144451
- else lines.push(indent(strong(` ${labelWithNum}`)));
144795
+ else if (isSelected) {
144796
+ const indicator = chalk.hex(this.colors.primary)(PIXEL_PULSE_FRAMES[this.animFrame]);
144797
+ const selectedLabel = chalk.bold.hex(this.colors.primary)(labelWithNum);
144798
+ lines.push(indent(`${indicator} ${selectedLabel}`));
144799
+ } else lines.push(indent(dim(` ${labelWithNum}`)));
144452
144800
  }
144453
144801
  lines.push("");
144454
144802
  if (this.feedbackMode) lines.push(indent(dim(t("approval.feedback_hint"))));
@@ -144477,8 +144825,7 @@ var ApprovalPanelComponent = class extends Container {
144477
144825
  if (this.selectedIndex < 0 || this.selectedIndex >= count) this.selectedIndex = Math.max(0, Math.min(this.selectedIndex, count - 1));
144478
144826
  }
144479
144827
  renderInlineFeedbackLine(width, labelWithNum) {
144480
- const selectColorBold = chalk.bold.hex(this.colors.accent);
144481
- const prefix = `${selectColorBold("▶")} ${selectColorBold(labelWithNum)} `;
144828
+ const prefix = `${chalk.hex(this.colors.primary)(PIXEL_PULSE_FRAMES[this.animFrame])} ${chalk.bold.hex(this.colors.primary)(labelWithNum)} `;
144482
144829
  const inputWidth = Math.max(4, width - visibleWidth(prefix) + 2);
144483
144830
  const inputLine = this.feedbackInput.render(inputWidth)[0] ?? "> ";
144484
144831
  return prefix + (inputLine.startsWith("> ") ? inputLine.slice(2) : inputLine);
@@ -145449,7 +145796,10 @@ var QuestionDialogComponent = class extends Container {
145449
145796
  answers;
145450
145797
  onToggleToolOutput;
145451
145798
  onTogglePlanExpand;
145452
- constructor(request, onAnswer, colors, maxVisibleOptions = 6, onToggleToolOutput, onTogglePlanExpand) {
145799
+ ui;
145800
+ animFrame = 0;
145801
+ intervalId = null;
145802
+ constructor(request, onAnswer, colors, maxVisibleOptions = 6, onToggleToolOutput, onTogglePlanExpand, ui) {
145453
145803
  super();
145454
145804
  this.request = request;
145455
145805
  this.onAnswer = onAnswer;
@@ -145457,6 +145807,7 @@ var QuestionDialogComponent = class extends Container {
145457
145807
  this.maxVisibleOptions = maxVisibleOptions;
145458
145808
  this.onToggleToolOutput = onToggleToolOutput;
145459
145809
  this.onTogglePlanExpand = onTogglePlanExpand;
145810
+ this.ui = ui;
145460
145811
  this.otherInput.onSubmit = (value) => {
145461
145812
  this.commitOtherInput(value, "enter");
145462
145813
  };
@@ -145467,14 +145818,33 @@ var QuestionDialogComponent = class extends Container {
145467
145818
  this.otherDrafts = Array.from({ length: total }, () => "");
145468
145819
  this.committedOtherValues = Array.from({ length: total }, () => void 0);
145469
145820
  this.answers = Array.from({ length: total }, () => void 0);
145821
+ if (this.ui !== void 0) this.intervalId = setInterval(() => {
145822
+ this.animFrame = (this.animFrame + 1) % PIXEL_PULSE_FRAMES.length;
145823
+ this.ui?.requestComponentRender(this);
145824
+ }, 100);
145825
+ }
145826
+ /** Stop the wizard pulse. Idempotent; called on respond and on hide. */
145827
+ stop() {
145828
+ if (this.intervalId !== null) {
145829
+ clearInterval(this.intervalId);
145830
+ this.intervalId = null;
145831
+ }
145832
+ }
145833
+ respond(response) {
145834
+ this.stop();
145835
+ this.onAnswer(response);
145836
+ }
145837
+ /** Breathing pixel block in the brand fluorescent green. */
145838
+ pulseBlock() {
145839
+ return chalk.hex(this.colors.primary)(PIXEL_PULSE_FRAMES[this.animFrame]);
145470
145840
  }
145471
145841
  handleInput(data) {
145472
145842
  if (matchesKey(data, Key.escape)) {
145473
- this.onAnswer({ answers: [] });
145843
+ this.respond({ answers: [] });
145474
145844
  return;
145475
145845
  }
145476
145846
  if (matchesKey(data, Key.ctrl("c")) || matchesKey(data, Key.ctrl("d"))) {
145477
- this.onAnswer({ answers: [] });
145847
+ this.respond({ answers: [] });
145478
145848
  return;
145479
145849
  }
145480
145850
  if (matchesKey(data, Key.ctrl("o"))) {
@@ -145699,7 +146069,7 @@ var QuestionDialogComponent = class extends Container {
145699
146069
  }
145700
146070
  executeSubmitAction(actionIdx, method) {
145701
146071
  if (actionIdx === 1) {
145702
- this.onAnswer({ answers: [] });
146072
+ this.respond({ answers: [] });
145703
146073
  return;
145704
146074
  }
145705
146075
  this.reviewMessage = void 0;
@@ -145711,7 +146081,7 @@ var QuestionDialogComponent = class extends Container {
145711
146081
  const answer = this.answers[i];
145712
146082
  if (answer !== void 0 && answer.length > 0) out[i] = answer;
145713
146083
  }
145714
- this.onAnswer({
146084
+ this.respond({
145715
146085
  answers: out,
145716
146086
  method: this.lastAnswerMethod ?? method
145717
146087
  });
@@ -145767,20 +146137,23 @@ var QuestionDialogComponent = class extends Container {
145767
146137
  const label = this.renderOptionLabel(questionIdx, option, isCursor);
145768
146138
  let tone;
145769
146139
  let prefix;
146140
+ const pulse = this.pulseBlock();
146141
+ const primaryBold = chalk.hex(this.colors.primary).bold;
145770
146142
  if (question.multi_select) {
145771
- prefix = ` [${isSelected ? "✓" : " "}] `;
146143
+ const checked = isSelected ? "✓" : " ";
146144
+ prefix = isCursor ? ` ${pulse} [${checked}] ` : ` [${checked}] `;
145772
146145
  if (isSelected && isCursor) tone = (s) => success.bold(s);
145773
146146
  else if (isSelected) tone = success;
145774
- else if (isCursor) tone = accent;
146147
+ else if (isCursor) tone = primaryBold;
145775
146148
  else tone = dim;
145776
146149
  } else if (isSelected && this.isAnswered(questionIdx)) {
145777
- prefix = isCursor ? ` [${String(num)}] ` : ` [${String(num)}] `;
146150
+ prefix = isCursor ? ` ${pulse} ${String(num)}. ` : `${String(num)}. `;
145778
146151
  tone = isCursor ? (s) => success.bold(s) : success;
145779
146152
  } else if (isCursor) {
145780
- prefix = ` [${String(num)}] `;
145781
- tone = accent;
146153
+ prefix = ` ${pulse} ${String(num)}. `;
146154
+ tone = primaryBold;
145782
146155
  } else {
145783
- prefix = ` [${String(num)}] `;
146156
+ prefix = ` ${String(num)}. `;
145784
146157
  tone = dim;
145785
146158
  }
145786
146159
  const continuation = " ".repeat(visibleWidth(prefix));
@@ -145830,8 +146203,8 @@ var QuestionDialogComponent = class extends Container {
145830
146203
  const label = t(SUBMIT_ACTIONS_KEYS[i]);
145831
146204
  if (label === void 0) continue;
145832
146205
  const num = i + 1;
145833
- if (i === this.submitActionIdx) lines.push(accent(` [${String(num)}] ${label}`));
145834
- else lines.push(dim(` [${String(num)}] ${label}`));
146206
+ if (i === this.submitActionIdx) lines.push(chalk.hex(this.colors.primary).bold(` ${this.pulseBlock()} ${String(num)}. ${label}`));
146207
+ else lines.push(dim(` ${String(num)}. ${label}`));
145835
146208
  }
145836
146209
  lines.push("");
145837
146210
  lines.push(this.buildSubmitHint(dim));
@@ -145840,18 +146213,18 @@ var QuestionDialogComponent = class extends Container {
145840
146213
  }
145841
146214
  pushTabs(lines) {
145842
146215
  const dim = chalk.hex(this.colors.textDim);
145843
- const active = chalk.bgHex(this.colors.primary).hex(this.colors.text).bold;
146216
+ const active = chalk.bgHex(this.colors.primary).hex(contrastTextHex(this.colors.primary)).bold;
145844
146217
  const tabs = [];
145845
146218
  for (let i = 0; i < this.request.data.questions.length; i++) {
145846
146219
  const question = this.request.data.questions[i];
145847
146220
  if (question === void 0) continue;
145848
146221
  const label = question.header !== void 0 && question.header.length > 0 ? question.header : `Q${String(i + 1)}`;
145849
- if (i === this.currentTab) tabs.push(active(` ${label} `));
146222
+ if (i === this.currentTab) tabs.push(active(` ${PIXEL_PULSE_FRAMES[this.animFrame]} ${label} `));
145850
146223
  else if (this.isAnswered(i)) tabs.push(chalk.hex(this.colors.success)(`(✓) ${label}`));
145851
146224
  else tabs.push(dim(`(○) ${label}`));
145852
146225
  }
145853
146226
  const submitLabel = t("question.submit");
145854
- if (this.isSubmitTab()) tabs.push(active(` ${submitLabel} `));
146227
+ if (this.isSubmitTab()) tabs.push(active(` ${PIXEL_PULSE_FRAMES[this.animFrame]} ${submitLabel} `));
145855
146228
  else tabs.push(dim(` ${submitLabel} `));
145856
146229
  lines.push(` ${tabs.join(" ")}`);
145857
146230
  }
@@ -145937,12 +146310,13 @@ var QuestionDialogComponent = class extends Container {
145937
146310
  const question = this.request.data.questions[questionIdx];
145938
146311
  if (question === void 0) return option.label;
145939
146312
  let prefix;
146313
+ const pulse = this.pulseBlock();
145940
146314
  if (question.multi_select) {
145941
- const body = ` [${isSelected ? "✓" : " "}] ${option.label}: `;
145942
- prefix = isSelected ? chalk.hex(this.colors.success).bold(body) : chalk.hex(this.colors.primary)(body);
146315
+ const body = ` ${pulse} [${isSelected ? "✓" : " "}] ${option.label}: `;
146316
+ prefix = isSelected ? chalk.hex(this.colors.success).bold(body) : chalk.hex(this.colors.primary).bold(body);
145943
146317
  } else {
145944
- const body = ` [${String(num)}] ${option.label}: `;
145945
- prefix = isSelected && this.isAnswered(questionIdx) ? chalk.hex(this.colors.success).bold(body) : chalk.hex(this.colors.primary)(body);
146318
+ const body = ` ${pulse} ${String(num)}. ${option.label}: `;
146319
+ prefix = isSelected && this.isAnswered(questionIdx) ? chalk.hex(this.colors.success).bold(body) : chalk.hex(this.colors.primary).bold(body);
145946
146320
  }
145947
146321
  const inputWidth = Math.max(4, width - visibleWidth(prefix) + 2);
145948
146322
  const inputLine = this.otherInput.render(inputWidth)[0] ?? "> ";
@@ -145976,6 +146350,7 @@ var QuestionDialogComponent = class extends Container {
145976
146350
  var DialogManager = class {
145977
146351
  host;
145978
146352
  activeApprovalPanel;
146353
+ activeQuestionDialog;
145979
146354
  approvalPreview;
145980
146355
  constructor(host) {
145981
146356
  this.host = host;
@@ -146108,12 +146483,14 @@ var DialogManager = class {
146108
146483
  this.restoreEditor();
146109
146484
  }
146110
146485
  showApprovalPanel(payload) {
146486
+ this.activeApprovalPanel?.stop();
146111
146487
  this.host.patchLivePane({ pendingApproval: { data: payload } });
146112
146488
  notifyTerminalOnce(this.host.state, `approval:${payload.id}`, {
146113
146489
  title: t("dialog.approval_title"),
146114
146490
  body: payload.tool_name
146115
146491
  });
146116
146492
  const panel = new ApprovalPanelComponent({ data: payload }, (response) => {
146493
+ panel.stop();
146117
146494
  this.host.approvalController.respond(adaptPanelResponse(response));
146118
146495
  }, this.host.state.theme.colors, () => {
146119
146496
  this.host.toggleToolOutputExpansion();
@@ -146121,12 +146498,13 @@ var DialogManager = class {
146121
146498
  this.host.togglePlanExpansion();
146122
146499
  }, (block) => {
146123
146500
  this.openApprovalPreview(panel, block);
146124
- });
146501
+ }, this.host.state.ui);
146125
146502
  this.activeApprovalPanel = panel;
146126
146503
  this.mountEditorReplacement(panel);
146127
146504
  }
146128
146505
  hideApprovalPanel() {
146129
146506
  if (this.approvalPreview !== void 0) this.closeApprovalPreview();
146507
+ this.activeApprovalPanel?.stop();
146130
146508
  this.activeApprovalPanel = void 0;
146131
146509
  this.host.patchLivePane({ pendingApproval: null });
146132
146510
  this.restoreEditor();
@@ -146161,21 +146539,26 @@ var DialogManager = class {
146161
146539
  this.host.state.ui.requestRender(true);
146162
146540
  }
146163
146541
  showQuestionDialog(payload) {
146542
+ this.activeQuestionDialog?.stop();
146164
146543
  this.host.patchLivePane({ pendingQuestion: { data: payload } });
146165
146544
  notifyTerminalOnce(this.host.state, `question:${payload.id}`, {
146166
146545
  title: t("dialog.question_title"),
146167
146546
  body: payload.questions[0]?.question
146168
146547
  });
146169
146548
  const dialog = new QuestionDialogComponent({ data: payload }, (response) => {
146549
+ dialog.stop();
146170
146550
  this.host.questionController.respond(response);
146171
146551
  }, this.host.state.theme.colors, void 0, () => {
146172
146552
  this.host.toggleToolOutputExpansion();
146173
146553
  }, () => {
146174
146554
  this.host.togglePlanExpansion();
146175
- });
146555
+ }, this.host.state.ui);
146556
+ this.activeQuestionDialog = dialog;
146176
146557
  this.mountEditorReplacement(dialog);
146177
146558
  }
146178
146559
  hideQuestionDialog() {
146560
+ this.activeQuestionDialog?.stop();
146561
+ this.activeQuestionDialog = void 0;
146179
146562
  this.host.patchLivePane({ pendingQuestion: null });
146180
146563
  this.restoreEditor();
146181
146564
  }
@@ -147983,7 +148366,7 @@ async function runStreamJson(opts) {
147983
148366
  });
147984
148367
  session.prompt(userText).catch((error) => {
147985
148368
  const msg = error instanceof Error ? error.message : String(error);
147986
- if (msg.includes("insufficient tool messages") || msg.includes("tool_calls") && msg.includes("followed by tool messages")) {
148369
+ if (isOrphanedToolCallError(error)) {
147987
148370
  log.warn("stream-json: resetting session after tool call mismatch", {
147988
148371
  sessionId: session?.id,
147989
148372
  error: msg