@threadbase-sh/streamer 1.58.0 → 1.58.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -14996,8 +14996,8 @@ var init_regexes = __esm({
14996
14996
  _emoji = `^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$`;
14997
14997
  ipv4 = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/;
14998
14998
  ipv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/;
14999
- mac = (delimiter) => {
15000
- const escapedDelim = escapeRegex(delimiter ?? ":");
14999
+ mac = (delimiter2) => {
15000
+ const escapedDelim = escapeRegex(delimiter2 ?? ":");
15001
15001
  return new RegExp(`^(?:[0-9A-F]{2}${escapedDelim}){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}${escapedDelim}){5}[0-9a-f]{2}$`);
15002
15002
  };
15003
15003
  cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/;
@@ -97168,6 +97168,25 @@ var init_devices_repository = __esm({
97168
97168
  }
97169
97169
  });
97170
97170
 
97171
+ // src/providers.ts
97172
+ function isProviderName(value) {
97173
+ return value === CLAUDE_CODE_PROVIDER || value === CODEX_CLI_PROVIDER;
97174
+ }
97175
+ function coerceProviderForRunner(value) {
97176
+ return isProviderName(value) ? value : CLAUDE_CODE_PROVIDER;
97177
+ }
97178
+ function isProviderResumable(_provider, availabilityResumable) {
97179
+ return availabilityResumable;
97180
+ }
97181
+ var CLAUDE_CODE_PROVIDER, CODEX_CLI_PROVIDER;
97182
+ var init_providers = __esm({
97183
+ "src/providers.ts"() {
97184
+ "use strict";
97185
+ CLAUDE_CODE_PROVIDER = "claude-code";
97186
+ CODEX_CLI_PROVIDER = "codex-cli";
97187
+ }
97188
+ });
97189
+
97171
97190
  // src/platform.ts
97172
97191
  function isWindowsExecutablePath(path2) {
97173
97192
  const dot = path2.lastIndexOf(".");
@@ -97294,6 +97313,39 @@ function resolveCodexExe() {
97294
97313
  _codexExe = "codex";
97295
97314
  return _codexExe;
97296
97315
  }
97316
+ function isExecutableFile(path2) {
97317
+ try {
97318
+ if (!(0, import_fs2.statSync)(path2).isFile()) return false;
97319
+ (0, import_fs2.accessSync)(path2, import_fs2.constants.X_OK);
97320
+ return true;
97321
+ } catch {
97322
+ return false;
97323
+ }
97324
+ }
97325
+ function locateExecutable(exe) {
97326
+ if (/[\\/]/.test(exe)) return isExecutableFile(exe) ? exe : null;
97327
+ const names = isWindows ? [
97328
+ ...isWindowsExecutablePath(exe) ? [exe] : [],
97329
+ ...[...WINDOWS_EXECUTABLE_EXTENSIONS].map((ext) => `${exe}${ext}`)
97330
+ ] : [exe];
97331
+ for (const dir of (process.env.PATH ?? "").split(import_path2.delimiter)) {
97332
+ if (!dir) continue;
97333
+ for (const name of names) {
97334
+ const candidate = (0, import_path2.join)(dir, name);
97335
+ if (isExecutableFile(candidate)) return candidate;
97336
+ }
97337
+ }
97338
+ return null;
97339
+ }
97340
+ function locateProviderExe(provider) {
97341
+ const isCodex = provider === CODEX_CLI_PROVIDER;
97342
+ const found = locateExecutable(isCodex ? resolveCodexExe() : resolveClaudeExe());
97343
+ if (found === null) {
97344
+ if (isCodex) clearCodexExeCache();
97345
+ else clearClaudeExeCache();
97346
+ }
97347
+ return found;
97348
+ }
97297
97349
  var import_child_process, import_fs2, import_os4, import_path2, isWindows, WINDOWS_EXECUTABLE_EXTENSIONS, _claudeExe, _codexExe;
97298
97350
  var init_platform = __esm({
97299
97351
  "src/platform.ts"() {
@@ -97302,30 +97354,12 @@ var init_platform = __esm({
97302
97354
  import_fs2 = require("fs");
97303
97355
  import_os4 = require("os");
97304
97356
  import_path2 = require("path");
97357
+ init_providers();
97305
97358
  isWindows = (0, import_os4.platform)() === "win32";
97306
97359
  WINDOWS_EXECUTABLE_EXTENSIONS = /* @__PURE__ */ new Set([".exe", ".cmd", ".bat"]);
97307
97360
  }
97308
97361
  });
97309
97362
 
97310
- // src/providers.ts
97311
- function isProviderName(value) {
97312
- return value === CLAUDE_CODE_PROVIDER || value === CODEX_CLI_PROVIDER;
97313
- }
97314
- function coerceProviderForRunner(value) {
97315
- return isProviderName(value) ? value : CLAUDE_CODE_PROVIDER;
97316
- }
97317
- function isProviderResumable(_provider, availabilityResumable) {
97318
- return availabilityResumable;
97319
- }
97320
- var CLAUDE_CODE_PROVIDER, CODEX_CLI_PROVIDER;
97321
- var init_providers = __esm({
97322
- "src/providers.ts"() {
97323
- "use strict";
97324
- CLAUDE_CODE_PROVIDER = "claude-code";
97325
- CODEX_CLI_PROVIDER = "codex-cli";
97326
- }
97327
- });
97328
-
97329
97363
  // node_modules/fast-glob/out/utils/array.js
97330
97364
  var require_array = __commonJS({
97331
97365
  "node_modules/fast-glob/out/utils/array.js"(exports2) {
@@ -99301,7 +99335,7 @@ var require_scan = __commonJS({
99301
99335
  var require_parse4 = __commonJS({
99302
99336
  "node_modules/picomatch/lib/parse.js"(exports2, module2) {
99303
99337
  "use strict";
99304
- var constants2 = require_constants5();
99338
+ var constants3 = require_constants5();
99305
99339
  var utils = require_utils2();
99306
99340
  var {
99307
99341
  MAX_LENGTH,
@@ -99309,7 +99343,7 @@ var require_parse4 = __commonJS({
99309
99343
  REGEX_NON_SPECIAL_CHARS,
99310
99344
  REGEX_SPECIAL_CHARS_BACKREF,
99311
99345
  REPLACEMENTS
99312
- } = constants2;
99346
+ } = constants3;
99313
99347
  var expandRange = (args, options) => {
99314
99348
  if (typeof options.expandRange === "function") {
99315
99349
  return options.expandRange(...args, options);
@@ -99515,7 +99549,7 @@ var require_parse4 = __commonJS({
99515
99549
  if (options.maxExtglobRecursion === false) {
99516
99550
  return { risky: false };
99517
99551
  }
99518
- const max = typeof options.maxExtglobRecursion === "number" ? options.maxExtglobRecursion : constants2.DEFAULT_MAX_EXTGLOB_RECURSION;
99552
+ const max = typeof options.maxExtglobRecursion === "number" ? options.maxExtglobRecursion : constants3.DEFAULT_MAX_EXTGLOB_RECURSION;
99519
99553
  const branches = splitTopLevel(body).map((branch) => branch.trim());
99520
99554
  if (branches.length > 1) {
99521
99555
  if (branches.some((branch) => branch === "") || branches.some((branch) => /^[*?]+$/.test(branch)) || hasRepeatedCharPrefixOverlap(branches)) {
@@ -99548,8 +99582,8 @@ var require_parse4 = __commonJS({
99548
99582
  const tokens = [bos];
99549
99583
  const capture = opts.capture ? "" : "?:";
99550
99584
  const win32 = utils.isWindows(options);
99551
- const PLATFORM_CHARS = constants2.globChars(win32);
99552
- const EXTGLOB_CHARS = constants2.extglobChars(PLATFORM_CHARS);
99585
+ const PLATFORM_CHARS = constants3.globChars(win32);
99586
+ const EXTGLOB_CHARS = constants3.extglobChars(PLATFORM_CHARS);
99553
99587
  const {
99554
99588
  DOT_LITERAL,
99555
99589
  PLUS_LITERAL,
@@ -100248,7 +100282,7 @@ var require_parse4 = __commonJS({
100248
100282
  NO_DOTS_SLASH,
100249
100283
  STAR,
100250
100284
  START_ANCHOR
100251
- } = constants2.globChars(win32);
100285
+ } = constants3.globChars(win32);
100252
100286
  const nodot = opts.dot ? NO_DOTS : NO_DOT;
100253
100287
  const slashDot = opts.dot ? NO_DOTS_SLASH : NO_DOT;
100254
100288
  const capture = opts.capture ? "" : "?:";
@@ -100307,7 +100341,7 @@ var require_picomatch = __commonJS({
100307
100341
  var scan = require_scan();
100308
100342
  var parse3 = require_parse4();
100309
100343
  var utils = require_utils2();
100310
- var constants2 = require_constants5();
100344
+ var constants3 = require_constants5();
100311
100345
  var isObject2 = (val) => val && typeof val === "object" && !Array.isArray(val);
100312
100346
  var picomatch = (glob, options, returnState = false) => {
100313
100347
  if (Array.isArray(glob)) {
@@ -100435,7 +100469,7 @@ var require_picomatch = __commonJS({
100435
100469
  return /$^/;
100436
100470
  }
100437
100471
  };
100438
- picomatch.constants = constants2;
100472
+ picomatch.constants = constants3;
100439
100473
  module2.exports = picomatch;
100440
100474
  }
100441
100475
  });
@@ -101185,11 +101219,11 @@ var require_out = __commonJS({
101185
101219
  async.read(path2, getSettings(optionsOrSettingsOrCallback), callback);
101186
101220
  }
101187
101221
  exports2.stat = stat7;
101188
- function statSync17(path2, optionsOrSettings) {
101222
+ function statSync18(path2, optionsOrSettings) {
101189
101223
  const settings = getSettings(optionsOrSettings);
101190
101224
  return sync.read(path2, settings);
101191
101225
  }
101192
- exports2.statSync = statSync17;
101226
+ exports2.statSync = statSync18;
101193
101227
  function getSettings(settingsOrOptions = {}) {
101194
101228
  if (settingsOrOptions instanceof settings_1.default) {
101195
101229
  return settingsOrOptions;
@@ -113552,7 +113586,7 @@ var require_crc = __commonJS({
113552
113586
  var require_parser2 = __commonJS({
113553
113587
  "node_modules/pngjs/lib/parser.js"(exports2, module2) {
113554
113588
  "use strict";
113555
- var constants2 = require_constants7();
113589
+ var constants3 = require_constants7();
113556
113590
  var CrcCalculator = require_crc();
113557
113591
  var Parser = module2.exports = function(options, dependencies) {
113558
113592
  this._options = options;
@@ -113563,12 +113597,12 @@ var require_parser2 = __commonJS({
113563
113597
  this._palette = [];
113564
113598
  this._colorType = 0;
113565
113599
  this._chunks = {};
113566
- this._chunks[constants2.TYPE_IHDR] = this._handleIHDR.bind(this);
113567
- this._chunks[constants2.TYPE_IEND] = this._handleIEND.bind(this);
113568
- this._chunks[constants2.TYPE_IDAT] = this._handleIDAT.bind(this);
113569
- this._chunks[constants2.TYPE_PLTE] = this._handlePLTE.bind(this);
113570
- this._chunks[constants2.TYPE_tRNS] = this._handleTRNS.bind(this);
113571
- this._chunks[constants2.TYPE_gAMA] = this._handleGAMA.bind(this);
113600
+ this._chunks[constants3.TYPE_IHDR] = this._handleIHDR.bind(this);
113601
+ this._chunks[constants3.TYPE_IEND] = this._handleIEND.bind(this);
113602
+ this._chunks[constants3.TYPE_IDAT] = this._handleIDAT.bind(this);
113603
+ this._chunks[constants3.TYPE_PLTE] = this._handlePLTE.bind(this);
113604
+ this._chunks[constants3.TYPE_tRNS] = this._handleTRNS.bind(this);
113605
+ this._chunks[constants3.TYPE_gAMA] = this._handleGAMA.bind(this);
113572
113606
  this.read = dependencies.read;
113573
113607
  this.error = dependencies.error;
113574
113608
  this.metadata = dependencies.metadata;
@@ -113583,10 +113617,10 @@ var require_parser2 = __commonJS({
113583
113617
  };
113584
113618
  };
113585
113619
  Parser.prototype.start = function() {
113586
- this.read(constants2.PNG_SIGNATURE.length, this._parseSignature.bind(this));
113620
+ this.read(constants3.PNG_SIGNATURE.length, this._parseSignature.bind(this));
113587
113621
  };
113588
113622
  Parser.prototype._parseSignature = function(data) {
113589
- let signature = constants2.PNG_SIGNATURE;
113623
+ let signature = constants3.PNG_SIGNATURE;
113590
113624
  for (let i = 0; i < signature.length; i++) {
113591
113625
  if (data[i] !== signature[i]) {
113592
113626
  this.error(new Error("Invalid file signature"));
@@ -113603,7 +113637,7 @@ var require_parser2 = __commonJS({
113603
113637
  name += String.fromCharCode(data[i]);
113604
113638
  }
113605
113639
  let ancillary = Boolean(data[4] & 32);
113606
- if (!this._hasIHDR && type !== constants2.TYPE_IHDR) {
113640
+ if (!this._hasIHDR && type !== constants3.TYPE_IHDR) {
113607
113641
  this.error(new Error("Expected IHDR on beggining"));
113608
113642
  return;
113609
113643
  }
@@ -113651,7 +113685,7 @@ var require_parser2 = __commonJS({
113651
113685
  this.error(new Error("Unsupported bit depth " + depth));
113652
113686
  return;
113653
113687
  }
113654
- if (!(colorType in constants2.COLORTYPE_TO_BPP_MAP)) {
113688
+ if (!(colorType in constants3.COLORTYPE_TO_BPP_MAP)) {
113655
113689
  this.error(new Error("Unsupported color type"));
113656
113690
  return;
113657
113691
  }
@@ -113668,16 +113702,16 @@ var require_parser2 = __commonJS({
113668
113702
  return;
113669
113703
  }
113670
113704
  this._colorType = colorType;
113671
- let bpp = constants2.COLORTYPE_TO_BPP_MAP[this._colorType];
113705
+ let bpp = constants3.COLORTYPE_TO_BPP_MAP[this._colorType];
113672
113706
  this._hasIHDR = true;
113673
113707
  this.metadata({
113674
113708
  width,
113675
113709
  height,
113676
113710
  depth,
113677
113711
  interlace: Boolean(interlace),
113678
- palette: Boolean(colorType & constants2.COLORTYPE_PALETTE),
113679
- color: Boolean(colorType & constants2.COLORTYPE_COLOR),
113680
- alpha: Boolean(colorType & constants2.COLORTYPE_ALPHA),
113712
+ palette: Boolean(colorType & constants3.COLORTYPE_PALETTE),
113713
+ color: Boolean(colorType & constants3.COLORTYPE_COLOR),
113714
+ alpha: Boolean(colorType & constants3.COLORTYPE_ALPHA),
113681
113715
  bpp,
113682
113716
  colorType
113683
113717
  });
@@ -113701,7 +113735,7 @@ var require_parser2 = __commonJS({
113701
113735
  };
113702
113736
  Parser.prototype._parseTRNS = function(data) {
113703
113737
  this._crc.write(data);
113704
- if (this._colorType === constants2.COLORTYPE_PALETTE_COLOR) {
113738
+ if (this._colorType === constants3.COLORTYPE_PALETTE_COLOR) {
113705
113739
  if (this._palette.length === 0) {
113706
113740
  this.error(new Error("Transparency chunk must be after palette"));
113707
113741
  return;
@@ -113715,10 +113749,10 @@ var require_parser2 = __commonJS({
113715
113749
  }
113716
113750
  this.palette(this._palette);
113717
113751
  }
113718
- if (this._colorType === constants2.COLORTYPE_GRAYSCALE) {
113752
+ if (this._colorType === constants3.COLORTYPE_GRAYSCALE) {
113719
113753
  this.transColor([data.readUInt16BE(0)]);
113720
113754
  }
113721
- if (this._colorType === constants2.COLORTYPE_COLOR) {
113755
+ if (this._colorType === constants3.COLORTYPE_COLOR) {
113722
113756
  this.transColor([
113723
113757
  data.readUInt16BE(0),
113724
113758
  data.readUInt16BE(2),
@@ -113732,7 +113766,7 @@ var require_parser2 = __commonJS({
113732
113766
  };
113733
113767
  Parser.prototype._parseGAMA = function(data) {
113734
113768
  this._crc.write(data);
113735
- this.gamma(data.readUInt32BE(0) / constants2.GAMMA_DIVISION);
113769
+ this.gamma(data.readUInt32BE(0) / constants3.GAMMA_DIVISION);
113736
113770
  this._handleChunkEnd();
113737
113771
  };
113738
113772
  Parser.prototype._handleIDAT = function(length) {
@@ -113744,7 +113778,7 @@ var require_parser2 = __commonJS({
113744
113778
  };
113745
113779
  Parser.prototype._parseIDAT = function(length, data) {
113746
113780
  this._crc.write(data);
113747
- if (this._colorType === constants2.COLORTYPE_PALETTE_COLOR && this._palette.length === 0) {
113781
+ if (this._colorType === constants3.COLORTYPE_PALETTE_COLOR && this._palette.length === 0) {
113748
113782
  throw new Error("Expected palette not found");
113749
113783
  }
113750
113784
  this.inflateData(data);
@@ -114232,9 +114266,9 @@ var require_parser_async = __commonJS({
114232
114266
  var require_bitpacker = __commonJS({
114233
114267
  "node_modules/pngjs/lib/bitpacker.js"(exports2, module2) {
114234
114268
  "use strict";
114235
- var constants2 = require_constants7();
114269
+ var constants3 = require_constants7();
114236
114270
  module2.exports = function(dataIn, width, height, options) {
114237
- let outHasAlpha = [constants2.COLORTYPE_COLOR_ALPHA, constants2.COLORTYPE_ALPHA].indexOf(
114271
+ let outHasAlpha = [constants3.COLORTYPE_COLOR_ALPHA, constants3.COLORTYPE_ALPHA].indexOf(
114238
114272
  options.colorType
114239
114273
  ) !== -1;
114240
114274
  if (options.colorType === options.inputColorType) {
@@ -114254,11 +114288,11 @@ var require_bitpacker = __commonJS({
114254
114288
  }
114255
114289
  let data = options.bitDepth !== 16 ? dataIn : new Uint16Array(dataIn.buffer);
114256
114290
  let maxValue = 255;
114257
- let inBpp = constants2.COLORTYPE_TO_BPP_MAP[options.inputColorType];
114291
+ let inBpp = constants3.COLORTYPE_TO_BPP_MAP[options.inputColorType];
114258
114292
  if (inBpp === 4 && !options.inputHasAlpha) {
114259
114293
  inBpp = 3;
114260
114294
  }
114261
- let outBpp = constants2.COLORTYPE_TO_BPP_MAP[options.colorType];
114295
+ let outBpp = constants3.COLORTYPE_TO_BPP_MAP[options.colorType];
114262
114296
  if (options.bitDepth === 16) {
114263
114297
  maxValue = 65535;
114264
114298
  outBpp *= 2;
@@ -114282,24 +114316,24 @@ var require_bitpacker = __commonJS({
114282
114316
  let blue;
114283
114317
  let alpha = maxValue;
114284
114318
  switch (options.inputColorType) {
114285
- case constants2.COLORTYPE_COLOR_ALPHA:
114319
+ case constants3.COLORTYPE_COLOR_ALPHA:
114286
114320
  alpha = data[inIndex + 3];
114287
114321
  red = data[inIndex];
114288
114322
  green = data[inIndex + 1];
114289
114323
  blue = data[inIndex + 2];
114290
114324
  break;
114291
- case constants2.COLORTYPE_COLOR:
114325
+ case constants3.COLORTYPE_COLOR:
114292
114326
  red = data[inIndex];
114293
114327
  green = data[inIndex + 1];
114294
114328
  blue = data[inIndex + 2];
114295
114329
  break;
114296
- case constants2.COLORTYPE_ALPHA:
114330
+ case constants3.COLORTYPE_ALPHA:
114297
114331
  alpha = data[inIndex + 1];
114298
114332
  red = data[inIndex];
114299
114333
  green = red;
114300
114334
  blue = red;
114301
114335
  break;
114302
- case constants2.COLORTYPE_GRAYSCALE:
114336
+ case constants3.COLORTYPE_GRAYSCALE:
114303
114337
  red = data[inIndex];
114304
114338
  green = red;
114305
114339
  blue = red;
@@ -114332,8 +114366,8 @@ var require_bitpacker = __commonJS({
114332
114366
  for (let x = 0; x < width; x++) {
114333
114367
  let rgba = getRGBA(data, inIndex);
114334
114368
  switch (options.colorType) {
114335
- case constants2.COLORTYPE_COLOR_ALPHA:
114336
- case constants2.COLORTYPE_COLOR:
114369
+ case constants3.COLORTYPE_COLOR_ALPHA:
114370
+ case constants3.COLORTYPE_COLOR:
114337
114371
  if (options.bitDepth === 8) {
114338
114372
  outData[outIndex] = rgba.red;
114339
114373
  outData[outIndex + 1] = rgba.green;
@@ -114350,8 +114384,8 @@ var require_bitpacker = __commonJS({
114350
114384
  }
114351
114385
  }
114352
114386
  break;
114353
- case constants2.COLORTYPE_ALPHA:
114354
- case constants2.COLORTYPE_GRAYSCALE: {
114387
+ case constants3.COLORTYPE_ALPHA:
114388
+ case constants3.COLORTYPE_GRAYSCALE: {
114355
114389
  let grayscale = (rgba.red + rgba.green + rgba.blue) / 3;
114356
114390
  if (options.bitDepth === 8) {
114357
114391
  outData[outIndex] = grayscale;
@@ -114524,7 +114558,7 @@ var require_filter_pack = __commonJS({
114524
114558
  var require_packer = __commonJS({
114525
114559
  "node_modules/pngjs/lib/packer.js"(exports2, module2) {
114526
114560
  "use strict";
114527
- var constants2 = require_constants7();
114561
+ var constants3 = require_constants7();
114528
114562
  var CrcStream = require_crc();
114529
114563
  var bitPacker = require_bitpacker();
114530
114564
  var filter = require_filter_pack();
@@ -114537,23 +114571,23 @@ var require_packer = __commonJS({
114537
114571
  options.inputHasAlpha = options.inputHasAlpha != null ? options.inputHasAlpha : true;
114538
114572
  options.deflateFactory = options.deflateFactory || zlib.createDeflate;
114539
114573
  options.bitDepth = options.bitDepth || 8;
114540
- options.colorType = typeof options.colorType === "number" ? options.colorType : constants2.COLORTYPE_COLOR_ALPHA;
114541
- options.inputColorType = typeof options.inputColorType === "number" ? options.inputColorType : constants2.COLORTYPE_COLOR_ALPHA;
114574
+ options.colorType = typeof options.colorType === "number" ? options.colorType : constants3.COLORTYPE_COLOR_ALPHA;
114575
+ options.inputColorType = typeof options.inputColorType === "number" ? options.inputColorType : constants3.COLORTYPE_COLOR_ALPHA;
114542
114576
  if ([
114543
- constants2.COLORTYPE_GRAYSCALE,
114544
- constants2.COLORTYPE_COLOR,
114545
- constants2.COLORTYPE_COLOR_ALPHA,
114546
- constants2.COLORTYPE_ALPHA
114577
+ constants3.COLORTYPE_GRAYSCALE,
114578
+ constants3.COLORTYPE_COLOR,
114579
+ constants3.COLORTYPE_COLOR_ALPHA,
114580
+ constants3.COLORTYPE_ALPHA
114547
114581
  ].indexOf(options.colorType) === -1) {
114548
114582
  throw new Error(
114549
114583
  "option color type:" + options.colorType + " is not supported at present"
114550
114584
  );
114551
114585
  }
114552
114586
  if ([
114553
- constants2.COLORTYPE_GRAYSCALE,
114554
- constants2.COLORTYPE_COLOR,
114555
- constants2.COLORTYPE_COLOR_ALPHA,
114556
- constants2.COLORTYPE_ALPHA
114587
+ constants3.COLORTYPE_GRAYSCALE,
114588
+ constants3.COLORTYPE_COLOR,
114589
+ constants3.COLORTYPE_COLOR_ALPHA,
114590
+ constants3.COLORTYPE_ALPHA
114557
114591
  ].indexOf(options.inputColorType) === -1) {
114558
114592
  throw new Error(
114559
114593
  "option input color type:" + options.inputColorType + " is not supported at present"
@@ -114577,7 +114611,7 @@ var require_packer = __commonJS({
114577
114611
  };
114578
114612
  Packer.prototype.filterData = function(data, width, height) {
114579
114613
  let packedData = bitPacker(data, width, height, this._options);
114580
- let bpp = constants2.COLORTYPE_TO_BPP_MAP[this._options.colorType];
114614
+ let bpp = constants3.COLORTYPE_TO_BPP_MAP[this._options.colorType];
114581
114615
  let filteredData = filter(packedData, width, height, this._options, bpp);
114582
114616
  return filteredData;
114583
114617
  };
@@ -114597,8 +114631,8 @@ var require_packer = __commonJS({
114597
114631
  };
114598
114632
  Packer.prototype.packGAMA = function(gamma) {
114599
114633
  let buf = Buffer.alloc(4);
114600
- buf.writeUInt32BE(Math.floor(gamma * constants2.GAMMA_DIVISION), 0);
114601
- return this._packChunk(constants2.TYPE_gAMA, buf);
114634
+ buf.writeUInt32BE(Math.floor(gamma * constants3.GAMMA_DIVISION), 0);
114635
+ return this._packChunk(constants3.TYPE_gAMA, buf);
114602
114636
  };
114603
114637
  Packer.prototype.packIHDR = function(width, height) {
114604
114638
  let buf = Buffer.alloc(13);
@@ -114609,13 +114643,13 @@ var require_packer = __commonJS({
114609
114643
  buf[10] = 0;
114610
114644
  buf[11] = 0;
114611
114645
  buf[12] = 0;
114612
- return this._packChunk(constants2.TYPE_IHDR, buf);
114646
+ return this._packChunk(constants3.TYPE_IHDR, buf);
114613
114647
  };
114614
114648
  Packer.prototype.packIDAT = function(data) {
114615
- return this._packChunk(constants2.TYPE_IDAT, data);
114649
+ return this._packChunk(constants3.TYPE_IDAT, data);
114616
114650
  };
114617
114651
  Packer.prototype.packIEND = function() {
114618
- return this._packChunk(constants2.TYPE_IEND, null);
114652
+ return this._packChunk(constants3.TYPE_IEND, null);
114619
114653
  };
114620
114654
  }
114621
114655
  });
@@ -114626,7 +114660,7 @@ var require_packer_async = __commonJS({
114626
114660
  "use strict";
114627
114661
  var util = require("util");
114628
114662
  var Stream = require("stream");
114629
- var constants2 = require_constants7();
114663
+ var constants3 = require_constants7();
114630
114664
  var Packer = require_packer();
114631
114665
  var PackerAsync = module2.exports = function(opt) {
114632
114666
  Stream.call(this);
@@ -114637,7 +114671,7 @@ var require_packer_async = __commonJS({
114637
114671
  };
114638
114672
  util.inherits(PackerAsync, Stream);
114639
114673
  PackerAsync.prototype.pack = function(data, width, height, gamma) {
114640
- this.emit("data", Buffer.from(constants2.PNG_SIGNATURE));
114674
+ this.emit("data", Buffer.from(constants3.PNG_SIGNATURE));
114641
114675
  this.emit("data", this._packer.packIHDR(width, height));
114642
114676
  if (gamma) {
114643
114677
  this.emit("data", this._packer.packGAMA(gamma));
@@ -114965,7 +114999,7 @@ var require_packer_sync = __commonJS({
114965
114999
  if (!zlib.deflateSync) {
114966
115000
  hasSyncZlib = false;
114967
115001
  }
114968
- var constants2 = require_constants7();
115002
+ var constants3 = require_constants7();
114969
115003
  var Packer = require_packer();
114970
115004
  module2.exports = function(metaData, opt) {
114971
115005
  if (!hasSyncZlib) {
@@ -114976,7 +115010,7 @@ var require_packer_sync = __commonJS({
114976
115010
  let options = opt || {};
114977
115011
  let packer = new Packer(options);
114978
115012
  let chunks = [];
114979
- chunks.push(Buffer.from(constants2.PNG_SIGNATURE));
115013
+ chunks.push(Buffer.from(constants3.PNG_SIGNATURE));
114980
115014
  chunks.push(packer.packIHDR(metaData.width, metaData.height));
114981
115015
  if (metaData.gamma) {
114982
115016
  chunks.push(packer.packGAMA(metaData.gamma));
@@ -120682,11 +120716,19 @@ var init_codex_pty_runner = __esm({
120682
120716
  onStatusChange;
120683
120717
  onPhaseChange;
120684
120718
  onReady;
120685
- // Broadcasts Codex's blocking startup gates (directory trust, hooks review)
120686
- // as question cards; null dismisses the card once the gate leaves the screen.
120719
+ // Every Codex prompt the client can answer — startup gates (directory trust,
120720
+ // hooks review), command approvals, and the rate-limit model picker is
120721
+ // broadcast through this one channel; null dismisses the card once the prompt
120722
+ // leaves the screen.
120723
+ //
120724
+ // Deliberately NOT onLiveQuestion/onLiveQuestionGone, which is Claude's
120725
+ // AskUserQuestion transport. Both channels land on the same mobile
120726
+ // QuestionCard, and the permission one is the correct fit for Codex: its menus
120727
+ // are answered by the option's real on-screen number (parseCodexNumberedOptions
120728
+ // emits `answerKeys: "2\r"`), which is exactly what `permissionIndices` carries
120729
+ // and what AskUserQuestion's down-arrow-count model cannot express. Wiring the
120730
+ // question channel as well would be a second path to the same card.
120687
120731
  onPermissionChange;
120688
- onLiveQuestion;
120689
- onLiveQuestionGone;
120690
120732
  onUserMessage;
120691
120733
  log;
120692
120734
  // Tracks sessions whose PTY has spawned but Codex hasn't yet reached its
@@ -120736,8 +120778,6 @@ var init_codex_pty_runner = __esm({
120736
120778
  this.onPhaseChange = options.onPhaseChange;
120737
120779
  this.onReady = options.onReady;
120738
120780
  this.onPermissionChange = options.onPermissionChange;
120739
- this.onLiveQuestion = options.onLiveQuestion;
120740
- this.onLiveQuestionGone = options.onLiveQuestionGone;
120741
120781
  this.onUserMessage = options.onUserMessage;
120742
120782
  this.log = options.logger ?? getLogger("codex-pty");
120743
120783
  }
@@ -122888,6 +122928,7 @@ var init_live_session_manager = __esm({
122888
122928
  "use strict";
122889
122929
  import_path28 = require("path");
122890
122930
  init_codex_pty_runner();
122931
+ init_platform();
122891
122932
  init_providers();
122892
122933
  init_remote_session_runner();
122893
122934
  init_pty_manager();
@@ -122920,11 +122961,13 @@ var init_live_session_manager = __esm({
122920
122961
  async start(sessionId, options) {
122921
122962
  const provider = options.provider ?? CLAUDE_CODE_PROVIDER;
122922
122963
  const runner = this.assertSupportedProvider(provider, options.projectPath);
122964
+ this.assertProviderInstalled(provider);
122923
122965
  return runner.start(sessionId, options);
122924
122966
  }
122925
122967
  async startFresh(options) {
122926
122968
  const provider = options.provider ?? CLAUDE_CODE_PROVIDER;
122927
122969
  const runner = this.assertSupportedProvider(provider, options.projectPath);
122970
+ this.assertProviderInstalled(provider);
122928
122971
  return runner.startFresh(options);
122929
122972
  }
122930
122973
  /**
@@ -122943,6 +122986,7 @@ var init_live_session_manager = __esm({
122943
122986
  err.statusCode = 501;
122944
122987
  throw err;
122945
122988
  }
122989
+ this.assertProviderInstalled(provider);
122946
122990
  return runner.startFork(options);
122947
122991
  }
122948
122992
  sendInput(sessionId, input) {
@@ -123024,6 +123068,30 @@ var init_live_session_manager = __esm({
123024
123068
  }
123025
123069
  throw new Error(`Session not found: ${sessionId}`);
123026
123070
  }
123071
+ /**
123072
+ * Refuse before spawning when the provider's CLI is not on this machine.
123073
+ *
123074
+ * Without this the spawn "succeeds": on POSIX execvp fails inside the forked
123075
+ * child, so a session appears, exits ~12ms later with code 1 and no output,
123076
+ * and the caller is told only that it "exited before becoming ready" — or,
123077
+ * on the Claude resume path, is told nothing at all, since that path answers
123078
+ * 200 before the process has had a chance to die. Every start route funnels
123079
+ * through here, so one check covers start, resume, adopt and fork.
123080
+ *
123081
+ * 503, not 500: the request was well-formed and the fault is this machine's
123082
+ * environment. `code` is what mobile branches on (it reads `errBody.code`),
123083
+ * and `PROVIDER_NOT_INSTALLED` is a remediation string it already knows.
123084
+ */
123085
+ assertProviderInstalled(provider) {
123086
+ if (locateProviderExe(provider) !== null) return;
123087
+ const command = provider === CODEX_CLI_PROVIDER ? "codex" : "claude";
123088
+ const err = new Error(
123089
+ `The ${command} command was not found on this server. Install the ${provider} CLI, or make sure it is on the PATH the streamer runs with.`
123090
+ );
123091
+ err.statusCode = 503;
123092
+ err.code = "PROVIDER_NOT_INSTALLED";
123093
+ throw err;
123094
+ }
123027
123095
  assertSupportedProvider(provider, projectPath) {
123028
123096
  if (this.remoteRunner) return this.remoteRunner;
123029
123097
  const runner = this.runners.get(provider);
@@ -126357,10 +126425,10 @@ var require_truncate = __commonJS({
126357
126425
  "node_modules/semver/functions/truncate.js"(exports2, module2) {
126358
126426
  "use strict";
126359
126427
  var parse3 = require_parse5();
126360
- var constants2 = require_constants8();
126428
+ var constants3 = require_constants8();
126361
126429
  var SemVer = require_semver();
126362
126430
  var truncate = (version2, truncation, options) => {
126363
- if (!constants2.RELEASE_TYPES.includes(truncation)) {
126431
+ if (!constants3.RELEASE_TYPES.includes(truncation)) {
126364
126432
  return null;
126365
126433
  }
126366
126434
  const clonedVersion = cloneInputVersion(version2, options);
@@ -127409,7 +127477,7 @@ var require_semver2 = __commonJS({
127409
127477
  "node_modules/semver/index.js"(exports2, module2) {
127410
127478
  "use strict";
127411
127479
  var internalRe = require_re();
127412
- var constants2 = require_constants8();
127480
+ var constants3 = require_constants8();
127413
127481
  var SemVer = require_semver();
127414
127482
  var identifiers = require_identifiers();
127415
127483
  var parse3 = require_parse5();
@@ -127493,8 +127561,8 @@ var require_semver2 = __commonJS({
127493
127561
  re: internalRe.re,
127494
127562
  src: internalRe.src,
127495
127563
  tokens: internalRe.t,
127496
- SEMVER_SPEC_VERSION: constants2.SEMVER_SPEC_VERSION,
127497
- RELEASE_TYPES: constants2.RELEASE_TYPES,
127564
+ SEMVER_SPEC_VERSION: constants3.SEMVER_SPEC_VERSION,
127565
+ RELEASE_TYPES: constants3.RELEASE_TYPES,
127498
127566
  compareIdentifiers: identifiers.compareIdentifiers,
127499
127567
  rcompareIdentifiers: identifiers.rcompareIdentifiers
127500
127568
  };
@@ -134493,7 +134561,9 @@ var corsMiddleware = (configValue) => {
134493
134561
  // src/api/middleware/error.middleware.ts
134494
134562
  var errorMiddleware = (err, c) => {
134495
134563
  const message = err instanceof Error ? err.message : "Internal server error";
134496
- return c.json({ error: message }, 500);
134564
+ const { statusCode, code } = err;
134565
+ const status = typeof statusCode === "number" && statusCode >= 400 && statusCode <= 599 ? statusCode : 500;
134566
+ return c.json(typeof code === "string" ? { error: message, code } : { error: message }, status);
134497
134567
  };
134498
134568
 
134499
134569
  // src/api/routes/backup.routes.ts
@@ -134918,6 +134988,7 @@ var createDeviceRoutes = (deps) => {
134918
134988
  // src/api/routes/diagnostics.routes.ts
134919
134989
  var import_fs3 = require("fs");
134920
134990
  init_platform();
134991
+ init_providers();
134921
134992
 
134922
134993
  // src/services/diagnostics/diagnostics.ts
134923
134994
  var DIAGNOSTICS_CONTRACT_VERSION = 1;
@@ -135039,24 +135110,26 @@ function computeBootToken() {
135039
135110
  }
135040
135111
 
135041
135112
  // src/api/routes/diagnostics.routes.ts
135042
- function providerCheck(name, resolve4) {
135113
+ function providerCheck(name) {
135043
135114
  try {
135044
- const exe = resolve4();
135045
- return {
135046
- id: `provider:${name}`,
135047
- status: "ok",
135048
- summary: `${name} CLI is installed.`,
135049
- remediation: "NONE",
135050
- detail: { location: redactPath(exe) }
135051
- };
135115
+ const exe = locateProviderExe(name);
135116
+ if (exe !== null) {
135117
+ return {
135118
+ id: `provider:${name}`,
135119
+ status: "ok",
135120
+ summary: `${name} CLI is installed.`,
135121
+ remediation: "NONE",
135122
+ detail: { location: redactPath(exe) }
135123
+ };
135124
+ }
135052
135125
  } catch {
135053
- return {
135054
- id: `provider:${name}`,
135055
- status: "failed",
135056
- summary: `${name} CLI could not be located. Sessions for this provider cannot start.`,
135057
- remediation: "PROVIDER_NOT_INSTALLED"
135058
- };
135059
135126
  }
135127
+ return {
135128
+ id: `provider:${name}`,
135129
+ status: "failed",
135130
+ summary: `${name} CLI could not be located. Sessions for this provider cannot start.`,
135131
+ remediation: "PROVIDER_NOT_INSTALLED"
135132
+ };
135060
135133
  }
135061
135134
  var createDiagnosticsRoutes = (deps) => {
135062
135135
  const app = new Hono2();
@@ -135069,8 +135142,8 @@ var createDiagnosticsRoutes = (deps) => {
135069
135142
  remediation: "NONE",
135070
135143
  detail: { version: getVersion(), uptimeSeconds: Math.floor(process.uptime()) }
135071
135144
  });
135072
- checks.push(providerCheck("claude-code", resolveClaudeExe));
135073
- checks.push(providerCheck("codex-cli", resolveCodexExe));
135145
+ checks.push(providerCheck(CLAUDE_CODE_PROVIDER));
135146
+ checks.push(providerCheck(CODEX_CLI_PROVIDER));
135074
135147
  const cacheAlert = deps.cacheMonitor()?.healthzField();
135075
135148
  checks.push(
135076
135149
  cacheAlert ? {
@@ -136187,7 +136260,6 @@ var createProjectRoutes = (deps) => {
136187
136260
  };
136188
136261
 
136189
136262
  // src/api/routes/providers.routes.ts
136190
- init_platform();
136191
136263
  init_providers();
136192
136264
 
136193
136265
  // src/services/providers/providerHealth.ts
@@ -136232,7 +136304,10 @@ function parseVersionOutput(output) {
136232
136304
  const match2 = output.match(/\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?/);
136233
136305
  return match2 ? match2[0] : null;
136234
136306
  }
136307
+ var versionByExe = /* @__PURE__ */ new Map();
136235
136308
  function runVersion(exe) {
136309
+ const cached4 = versionByExe.get(exe);
136310
+ if (cached4 !== void 0) return Promise.resolve(cached4);
136236
136311
  const viaShell = isWindows && /\.(?:cmd|bat)$/i.test(exe);
136237
136312
  const file2 = viaShell ? `"${exe}"` : exe;
136238
136313
  return new Promise((resolve4) => {
@@ -136242,7 +136317,9 @@ function runVersion(exe) {
136242
136317
  { timeout: VERSION_TIMEOUT_MS, shell: viaShell, windowsHide: true },
136243
136318
  (err, stdout2, stderr) => {
136244
136319
  if (err && !stdout2 && !stderr) return resolve4(null);
136245
- resolve4(parseVersionOutput(`${stdout2}${stderr}`));
136320
+ const version2 = parseVersionOutput(`${stdout2}${stderr}`);
136321
+ if (version2 !== null) versionByExe.set(exe, version2);
136322
+ resolve4(version2);
136246
136323
  }
136247
136324
  );
136248
136325
  });
@@ -136286,13 +136363,16 @@ function compareSemver(a, b2) {
136286
136363
  if (pb2.pre === null) return -1;
136287
136364
  return pa.pre < pb2.pre ? -1 : 1;
136288
136365
  }
136289
- async function providerHealth(name, resolveExe, detect = runVersion) {
136366
+ async function providerHealth(name, locateExe = () => locateProviderExe(name), detect = runVersion) {
136290
136367
  const verifiedAgainst = VERIFIED_AGAINST[name];
136291
136368
  const capabilities = capabilitiesFor(name);
136292
- let exe;
136369
+ let exe = null;
136293
136370
  try {
136294
- exe = resolveExe();
136371
+ exe = locateExe();
136295
136372
  } catch {
136373
+ exe = null;
136374
+ }
136375
+ if (exe === null) {
136296
136376
  return {
136297
136377
  name,
136298
136378
  available: false,
@@ -136329,8 +136409,8 @@ var createProviderRoutes = () => {
136329
136409
  const app = new Hono2();
136330
136410
  app.get("/", async (c) => {
136331
136411
  const providers = await Promise.all([
136332
- providerHealth(CLAUDE_CODE_PROVIDER, resolveClaudeExe),
136333
- providerHealth(CODEX_CLI_PROVIDER, resolveCodexExe)
136412
+ providerHealth(CLAUDE_CODE_PROVIDER),
136413
+ providerHealth(CODEX_CLI_PROVIDER)
136334
136414
  ]);
136335
136415
  return c.json({ providers });
136336
136416
  });
@@ -148301,7 +148381,10 @@ var SessionHandlers = class {
148301
148381
  });
148302
148382
  this.sessionStore.addManaged(session);
148303
148383
  this.registryBoot.recordSessionSpawn(session);
148304
- const { outcome } = await this.deps.waitForStartupOutcome(session.id, START_READY_TIMEOUT_MS);
148384
+ const { outcome, session: settled } = await this.deps.waitForStartupOutcome(
148385
+ session.id,
148386
+ START_READY_TIMEOUT_MS
148387
+ );
148305
148388
  const current = this.sessionStore.get(session.id, this.deps.ptyAttachedIds());
148306
148389
  if (outcome === "ready" && current) {
148307
148390
  json2(res, 200, { session: current });
@@ -148309,7 +148392,7 @@ var SessionHandlers = class {
148309
148392
  json2(res, 502, {
148310
148393
  id: session.id,
148311
148394
  status: "idle",
148312
- error: current.failureReason ?? "Session exited before becoming ready"
148395
+ error: settled?.failureReason ?? "Session exited before becoming ready"
148313
148396
  });
148314
148397
  } else {
148315
148398
  json2(res, 202, { id: session.id, status: "pending" });
@@ -148323,11 +148406,16 @@ var SessionHandlers = class {
148323
148406
  } catch (err) {
148324
148407
  const message = err instanceof Error ? err.message : "Failed to start session";
148325
148408
  const statusCode = typeof err.statusCode === "number" ? err.statusCode : 500;
148409
+ const code = err.code;
148326
148410
  this.log.error(`[start] failed to start session: ${message}`, {
148327
148411
  event: "session.start_failed",
148328
148412
  error: message
148329
148413
  });
148330
- json2(res, statusCode, { error: message });
148414
+ json2(
148415
+ res,
148416
+ statusCode,
148417
+ typeof code === "string" ? { error: message, code } : { error: message }
148418
+ );
148331
148419
  }
148332
148420
  }
148333
148421
  async handleSetSessionName(sessionId, req, res) {
@@ -149023,7 +149111,37 @@ var PairTokenStore = class {
149023
149111
  expiresInSeconds: Math.floor(this.ttlMs / 1e3)
149024
149112
  };
149025
149113
  }
149114
+ /**
149115
+ * Whether `consume` would succeed right now, WITHOUT spending the token.
149116
+ *
149117
+ * Exists so a caller can reject a bad token before doing any work, and still
149118
+ * spend the token only once the work has succeeded. A pair token is
149119
+ * single-use and lives 180 seconds, so spending it on a request that then
149120
+ * fails costs the user a whole new QR — and, worse, makes their retry
149121
+ * indistinguishable from an attacker replaying a photographed code, which is
149122
+ * the one signal `design.md` §2.6 designates as replay detection.
149123
+ *
149124
+ * Advisory, not a reservation: it takes no lock and holds nothing. The
149125
+ * authoritative answer is still `consume`'s.
149126
+ */
149127
+ verify(token) {
149128
+ const result = this.check(token);
149129
+ return result.ok ? { ok: true } : result;
149130
+ }
149026
149131
  consume(token) {
149132
+ const result = this.check(token);
149133
+ if (!result.ok) return result;
149134
+ result.record.used = true;
149135
+ return { ok: true };
149136
+ }
149137
+ /**
149138
+ * The shared predicate behind `verify` and `consume`.
149139
+ *
149140
+ * One implementation on purpose: two copies of "is this token usable" is two
149141
+ * places for the expiry or single-use rule to drift, and a drift in this
149142
+ * direction fails open.
149143
+ */
149144
+ check(token) {
149027
149145
  const record3 = this.current;
149028
149146
  if (!record3 || record3.token !== token) return { ok: false, reason: "unknown" };
149029
149147
  if (Date.now() > record3.expiresAt) {
@@ -149031,8 +149149,7 @@ var PairTokenStore = class {
149031
149149
  return { ok: false, reason: "expired" };
149032
149150
  }
149033
149151
  if (record3.used) return { ok: false, reason: "used" };
149034
- record3.used = true;
149035
- return { ok: true };
149152
+ return { ok: true, record: record3 };
149036
149153
  }
149037
149154
  peek() {
149038
149155
  return this.current;
@@ -149053,6 +149170,7 @@ var PairTokenStore = class {
149053
149170
  };
149054
149171
 
149055
149172
  // src/server.ts
149173
+ init_platform();
149056
149174
  init_providers();
149057
149175
  init_remote_session_runner();
149058
149176
 
@@ -150115,7 +150233,15 @@ function createLiveSessionOptions(deps) {
150115
150233
  // grace-timer/idle-reaper hold (statusSource "shutdown") apart from a
150116
150234
  // genuine process exit ("process-exit"), and reports both as
150117
150235
  // `lifecycle: "completed"`. See managedToResponse in session-store.ts.
150118
- ...session.statusSource != null && { statusSource: session.statusSource }
150236
+ ...session.statusSource != null && { statusSource: session.statusSource },
150237
+ // Why a session died, not just that it did. Without this the store's
150238
+ // copy has no failureReason, so managedToResponse falls through to
150239
+ // `lifecycle: "completed"` (see session-store.ts) and a session that
150240
+ // never started — missing CLI, missing project dir — is reported to
150241
+ // every client as one that finished normally. Guarded like its
150242
+ // neighbours: a later transition must not blank a recorded failure.
150243
+ ...session.failureReason != null && { failureReason: session.failureReason },
150244
+ ...session.failureCode != null && { failureCode: session.failureCode }
150119
150245
  });
150120
150246
  deps.managedSessionsRepo()?.recordStatus(
150121
150247
  session.id,
@@ -153614,6 +153740,41 @@ var StreamerServer = class {
153614
153740
  json2(res, 503, body);
153615
153741
  return true;
153616
153742
  }
153743
+ /**
153744
+ * Say which provider CLIs this machine can actually launch.
153745
+ *
153746
+ * The operator cannot discover this case unaided: under launchd/Task
153747
+ * Scheduler the service inherits a stripped PATH, so a CLI that works
153748
+ * perfectly in their terminal is invisible to the service, and every session
153749
+ * start dies milliseconds in. `/api/diagnostics` answers it too, but only for
153750
+ * someone who already suspects it.
153751
+ *
153752
+ * Availability only, never a version — `--version` costs a process spawn per
153753
+ * provider (85ms for claude here) and belongs on the first request that wants
153754
+ * it, not on boot.
153755
+ *
153756
+ * Called AFTER the port is bound, which is not cosmetic. This is the first
153757
+ * caller of the exe resolvers in the process, so the memo is cold by
153758
+ * definition and each provider pays one synchronous `which` / `where.exe`
153759
+ * (platform.ts) with a 3s timeout. On POSIX that is 3ms found, 7ms missing.
153760
+ * Windows is the risk — `where.exe` is slower, `execFileSync` blocks the
153761
+ * event loop, and Task Scheduler's stripped PATH is exactly where a miss
153762
+ * pays the full timeout — so the worst case is ~6s of two blocking lookups.
153763
+ * After `listen()` that delays the first requests on a box that cannot start
153764
+ * a session anyway; before it, it would have delayed binding the port.
153765
+ */
153766
+ logProviderAvailability() {
153767
+ for (const provider of [CLAUDE_CODE_PROVIDER, CODEX_CLI_PROVIDER]) {
153768
+ if (locateProviderExe(provider)) {
153769
+ this.log.info(`Provider ${provider}: found`, { event: "config.provider", provider });
153770
+ } else {
153771
+ this.log.warn(`Provider ${provider}: not found on PATH \u2014 sessions cannot start`, {
153772
+ event: "config.provider_missing",
153773
+ provider
153774
+ });
153775
+ }
153776
+ }
153777
+ }
153617
153778
  async listen(port, opts) {
153618
153779
  if (this.featureFlags.ptyHost) {
153619
153780
  try {
@@ -153674,6 +153835,7 @@ var StreamerServer = class {
153674
153835
  event: "server.listening",
153675
153836
  ...this.host !== void 0 && { host: this.host }
153676
153837
  });
153838
+ this.logProviderAvailability();
153677
153839
  try {
153678
153840
  this.runtimeStore = RuntimeStore.open(this.runtimeDbPath);
153679
153841
  this.managedSessionsRepo = new ManagedSessionsRepository(this.runtimeStore.getDatabase());
@@ -154050,9 +154212,9 @@ var StreamerServer = class {
154050
154212
  json2(res, 400, { error: "Missing token or clientPublicKey" });
154051
154213
  return;
154052
154214
  }
154053
- const result = this.pairTokens.consume(token);
154054
- if (!result.ok) {
154055
- json2(res, 401, { error: `Pair token ${result.reason}` });
154215
+ const precheck = this.pairTokens.verify(token);
154216
+ if (!precheck.ok) {
154217
+ json2(res, 401, { error: `Pair token ${precheck.reason}` });
154056
154218
  return;
154057
154219
  }
154058
154220
  let sealed;
@@ -154063,6 +154225,11 @@ var StreamerServer = class {
154063
154225
  json2(res, 400, { error: message });
154064
154226
  return;
154065
154227
  }
154228
+ const result = this.pairTokens.consume(token);
154229
+ if (!result.ok) {
154230
+ json2(res, 401, { error: `Pair token ${result.reason}` });
154231
+ return;
154232
+ }
154066
154233
  const ts2 = (/* @__PURE__ */ new Date()).toISOString();
154067
154234
  this.log.info(`[pair] token exchanged from ${ip} at ${ts2}`, {
154068
154235
  event: "pair.token_exchanged",