@threadbase-sh/streamer 1.29.2 → 1.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -26158,7 +26158,7 @@ var require_thread_stream = __commonJS({
26158
26158
  var { version: version2 } = require_package();
26159
26159
  var { EventEmitter: EventEmitter6 } = require("events");
26160
26160
  var { Worker } = require("worker_threads");
26161
- var { join: join26 } = require("path");
26161
+ var { join: join28 } = require("path");
26162
26162
  var { pathToFileURL } = require("url");
26163
26163
  var { wait } = require_wait();
26164
26164
  var {
@@ -26209,7 +26209,7 @@ var require_thread_stream = __commonJS({
26209
26209
  function createWorker(stream, opts) {
26210
26210
  const { filename, workerData } = opts;
26211
26211
  const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
26212
- const toExecute = bundlerOverrides["thread-stream-worker"] || join26(__dirname, "lib", "worker.js");
26212
+ const toExecute = bundlerOverrides["thread-stream-worker"] || join28(__dirname, "lib", "worker.js");
26213
26213
  const worker = new Worker(toExecute, {
26214
26214
  ...opts.workerOpts,
26215
26215
  name: opts.workerOpts?.name || "thread-stream",
@@ -26675,9 +26675,9 @@ var require_transport = __commonJS({
26675
26675
  "node_modules/pino/lib/transport.js"(exports2, module2) {
26676
26676
  "use strict";
26677
26677
  var { createRequire } = require("module");
26678
- var { existsSync: existsSync12 } = require("fs");
26678
+ var { existsSync: existsSync13 } = require("fs");
26679
26679
  var getCallers = require_caller();
26680
- var { join: join26, isAbsolute: isAbsolute3, sep: sep2 } = require("path");
26680
+ var { join: join28, isAbsolute: isAbsolute3, sep: sep2 } = require("path");
26681
26681
  var { fileURLToPath: fileURLToPath3 } = require("url");
26682
26682
  var sleep = require_atomic_sleep();
26683
26683
  var onExit = require_on_exit_leak_free();
@@ -26749,7 +26749,7 @@ var require_transport = __commonJS({
26749
26749
  return false;
26750
26750
  }
26751
26751
  }
26752
- return isAbsolute3(path2) && !existsSync12(path2);
26752
+ return isAbsolute3(path2) && !existsSync13(path2);
26753
26753
  }
26754
26754
  function stripQuotes(value) {
26755
26755
  const first = value[0];
@@ -26830,7 +26830,7 @@ var require_transport = __commonJS({
26830
26830
  throw new Error("only one of target or targets can be specified");
26831
26831
  }
26832
26832
  if (targets) {
26833
- target = bundlerOverrides["pino-worker"] || join26(__dirname, "worker.js");
26833
+ target = bundlerOverrides["pino-worker"] || join28(__dirname, "worker.js");
26834
26834
  options.targets = targets.filter((dest) => dest.target).map((dest) => {
26835
26835
  return {
26836
26836
  ...dest,
@@ -26848,7 +26848,7 @@ var require_transport = __commonJS({
26848
26848
  });
26849
26849
  });
26850
26850
  } else if (pipeline2) {
26851
- target = bundlerOverrides["pino-worker"] || join26(__dirname, "worker.js");
26851
+ target = bundlerOverrides["pino-worker"] || join28(__dirname, "worker.js");
26852
26852
  options.pipelines = [pipeline2.map((dest) => {
26853
26853
  return {
26854
26854
  ...dest,
@@ -26871,7 +26871,7 @@ var require_transport = __commonJS({
26871
26871
  return origin;
26872
26872
  }
26873
26873
  if (origin === "pino/file") {
26874
- return join26(__dirname, "..", "file.js");
26874
+ return join28(__dirname, "..", "file.js");
26875
26875
  }
26876
26876
  let fixTarget2;
26877
26877
  for (const filePath of callers) {
@@ -27852,7 +27852,7 @@ var require_safe_stable_stringify = __commonJS({
27852
27852
  return circularValue;
27853
27853
  }
27854
27854
  let res = "";
27855
- let join26 = ",";
27855
+ let join28 = ",";
27856
27856
  const originalIndentation = indentation;
27857
27857
  if (Array.isArray(value)) {
27858
27858
  if (value.length === 0) {
@@ -27866,7 +27866,7 @@ var require_safe_stable_stringify = __commonJS({
27866
27866
  indentation += spacer;
27867
27867
  res += `
27868
27868
  ${indentation}`;
27869
- join26 = `,
27869
+ join28 = `,
27870
27870
  ${indentation}`;
27871
27871
  }
27872
27872
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -27874,13 +27874,13 @@ ${indentation}`;
27874
27874
  for (; i < maximumValuesToStringify - 1; i++) {
27875
27875
  const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
27876
27876
  res += tmp2 !== void 0 ? tmp2 : "null";
27877
- res += join26;
27877
+ res += join28;
27878
27878
  }
27879
27879
  const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
27880
27880
  res += tmp !== void 0 ? tmp : "null";
27881
27881
  if (value.length - 1 > maximumBreadth) {
27882
27882
  const removedKeys = value.length - maximumBreadth - 1;
27883
- res += `${join26}"... ${getItemCount(removedKeys)} not stringified"`;
27883
+ res += `${join28}"... ${getItemCount(removedKeys)} not stringified"`;
27884
27884
  }
27885
27885
  if (spacer !== "") {
27886
27886
  res += `
@@ -27901,7 +27901,7 @@ ${originalIndentation}`;
27901
27901
  let separator = "";
27902
27902
  if (spacer !== "") {
27903
27903
  indentation += spacer;
27904
- join26 = `,
27904
+ join28 = `,
27905
27905
  ${indentation}`;
27906
27906
  whitespace = " ";
27907
27907
  }
@@ -27915,13 +27915,13 @@ ${indentation}`;
27915
27915
  const tmp = stringifyFnReplacer(key2, value, stack, replacer, spacer, indentation);
27916
27916
  if (tmp !== void 0) {
27917
27917
  res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
27918
- separator = join26;
27918
+ separator = join28;
27919
27919
  }
27920
27920
  }
27921
27921
  if (keyLength > maximumBreadth) {
27922
27922
  const removedKeys = keyLength - maximumBreadth;
27923
27923
  res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
27924
- separator = join26;
27924
+ separator = join28;
27925
27925
  }
27926
27926
  if (spacer !== "" && separator.length > 1) {
27927
27927
  res = `
@@ -27962,7 +27962,7 @@ ${originalIndentation}`;
27962
27962
  }
27963
27963
  const originalIndentation = indentation;
27964
27964
  let res = "";
27965
- let join26 = ",";
27965
+ let join28 = ",";
27966
27966
  if (Array.isArray(value)) {
27967
27967
  if (value.length === 0) {
27968
27968
  return "[]";
@@ -27975,7 +27975,7 @@ ${originalIndentation}`;
27975
27975
  indentation += spacer;
27976
27976
  res += `
27977
27977
  ${indentation}`;
27978
- join26 = `,
27978
+ join28 = `,
27979
27979
  ${indentation}`;
27980
27980
  }
27981
27981
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -27983,13 +27983,13 @@ ${indentation}`;
27983
27983
  for (; i < maximumValuesToStringify - 1; i++) {
27984
27984
  const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
27985
27985
  res += tmp2 !== void 0 ? tmp2 : "null";
27986
- res += join26;
27986
+ res += join28;
27987
27987
  }
27988
27988
  const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
27989
27989
  res += tmp !== void 0 ? tmp : "null";
27990
27990
  if (value.length - 1 > maximumBreadth) {
27991
27991
  const removedKeys = value.length - maximumBreadth - 1;
27992
- res += `${join26}"... ${getItemCount(removedKeys)} not stringified"`;
27992
+ res += `${join28}"... ${getItemCount(removedKeys)} not stringified"`;
27993
27993
  }
27994
27994
  if (spacer !== "") {
27995
27995
  res += `
@@ -28002,7 +28002,7 @@ ${originalIndentation}`;
28002
28002
  let whitespace = "";
28003
28003
  if (spacer !== "") {
28004
28004
  indentation += spacer;
28005
- join26 = `,
28005
+ join28 = `,
28006
28006
  ${indentation}`;
28007
28007
  whitespace = " ";
28008
28008
  }
@@ -28011,7 +28011,7 @@ ${indentation}`;
28011
28011
  const tmp = stringifyArrayReplacer(key2, value[key2], stack, replacer, spacer, indentation);
28012
28012
  if (tmp !== void 0) {
28013
28013
  res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
28014
- separator = join26;
28014
+ separator = join28;
28015
28015
  }
28016
28016
  }
28017
28017
  if (spacer !== "" && separator.length > 1) {
@@ -28069,20 +28069,20 @@ ${originalIndentation}`;
28069
28069
  indentation += spacer;
28070
28070
  let res2 = `
28071
28071
  ${indentation}`;
28072
- const join27 = `,
28072
+ const join29 = `,
28073
28073
  ${indentation}`;
28074
28074
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
28075
28075
  let i = 0;
28076
28076
  for (; i < maximumValuesToStringify - 1; i++) {
28077
28077
  const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
28078
28078
  res2 += tmp2 !== void 0 ? tmp2 : "null";
28079
- res2 += join27;
28079
+ res2 += join29;
28080
28080
  }
28081
28081
  const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
28082
28082
  res2 += tmp !== void 0 ? tmp : "null";
28083
28083
  if (value.length - 1 > maximumBreadth) {
28084
28084
  const removedKeys = value.length - maximumBreadth - 1;
28085
- res2 += `${join27}"... ${getItemCount(removedKeys)} not stringified"`;
28085
+ res2 += `${join29}"... ${getItemCount(removedKeys)} not stringified"`;
28086
28086
  }
28087
28087
  res2 += `
28088
28088
  ${originalIndentation}`;
@@ -28098,16 +28098,16 @@ ${originalIndentation}`;
28098
28098
  return '"[Object]"';
28099
28099
  }
28100
28100
  indentation += spacer;
28101
- const join26 = `,
28101
+ const join28 = `,
28102
28102
  ${indentation}`;
28103
28103
  let res = "";
28104
28104
  let separator = "";
28105
28105
  let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
28106
28106
  if (isTypedArrayWithEntries(value)) {
28107
- res += stringifyTypedArray(value, join26, maximumBreadth);
28107
+ res += stringifyTypedArray(value, join28, maximumBreadth);
28108
28108
  keys = keys.slice(value.length);
28109
28109
  maximumPropertiesToStringify -= value.length;
28110
- separator = join26;
28110
+ separator = join28;
28111
28111
  }
28112
28112
  if (deterministic) {
28113
28113
  keys = sort(keys, comparator);
@@ -28118,13 +28118,13 @@ ${indentation}`;
28118
28118
  const tmp = stringifyIndent(key2, value[key2], stack, spacer, indentation);
28119
28119
  if (tmp !== void 0) {
28120
28120
  res += `${separator}${strEscape(key2)}: ${tmp}`;
28121
- separator = join26;
28121
+ separator = join28;
28122
28122
  }
28123
28123
  }
28124
28124
  if (keyLength > maximumBreadth) {
28125
28125
  const removedKeys = keyLength - maximumBreadth;
28126
28126
  res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
28127
- separator = join26;
28127
+ separator = join28;
28128
28128
  }
28129
28129
  if (separator !== "") {
28130
28130
  res = `
@@ -35847,17 +35847,17 @@ var require_logger = __commonJS({
35847
35847
  * Some optimizations are performed to avoid creating unnecessary objects and to keep runtime
35848
35848
  * overhead associated with resolving metadata as low as possible.
35849
35849
  */
35850
- static compose(logger2, metaOrFunc) {
35851
- if (logger2 instanceof _LoggerWithComposedMetadata) {
35852
- const contributors = appendToChain(logger2.contributors, metaOrFunc);
35850
+ static compose(logger3, metaOrFunc) {
35851
+ if (logger3 instanceof _LoggerWithComposedMetadata) {
35852
+ const contributors = appendToChain(logger3.contributors, metaOrFunc);
35853
35853
  if (contributors === void 0)
35854
- return logger2;
35855
- return new _LoggerWithComposedMetadata(logger2.parentLogger, contributors);
35854
+ return logger3;
35855
+ return new _LoggerWithComposedMetadata(logger3.parentLogger, contributors);
35856
35856
  } else {
35857
35857
  const contributors = appendToChain(void 0, metaOrFunc);
35858
35858
  if (contributors === void 0)
35859
- return logger2;
35860
- return new _LoggerWithComposedMetadata(logger2, contributors);
35859
+ return logger3;
35860
+ return new _LoggerWithComposedMetadata(logger3, contributors);
35861
35861
  }
35862
35862
  }
35863
35863
  constructor(parentLogger, contributors) {
@@ -36938,8 +36938,8 @@ var require_logging = __commonJS({
36938
36938
  return _logger;
36939
36939
  };
36940
36940
  exports2.getLogger = getLogger3;
36941
- var setLogger = (logger2) => {
36942
- _logger = logger2;
36941
+ var setLogger = (logger3) => {
36942
+ _logger = logger3;
36943
36943
  };
36944
36944
  exports2.setLogger = setLogger;
36945
36945
  var setLoggerVerbosity = (verbosity) => {
@@ -60048,8 +60048,8 @@ var require_src3 = __commonJS({
60048
60048
  throw new Error("Not available in this library. Use @grpc/proto-loader and loadPackageDefinition instead");
60049
60049
  };
60050
60050
  exports2.load = load;
60051
- var setLogger = (logger2) => {
60052
- logging.setLogger(logger2);
60051
+ var setLogger = (logger3) => {
60052
+ logging.setLogger(logger3);
60053
60053
  };
60054
60054
  exports2.setLogger = setLogger;
60055
60055
  var setLogVerbosity = (verbosity) => {
@@ -100406,11 +100406,11 @@ var require_out = __commonJS({
100406
100406
  async.read(path2, getSettings(optionsOrSettingsOrCallback), callback);
100407
100407
  }
100408
100408
  exports2.stat = stat10;
100409
- function statSync10(path2, optionsOrSettings) {
100409
+ function statSync11(path2, optionsOrSettings) {
100410
100410
  const settings = getSettings(optionsOrSettings);
100411
100411
  return sync.read(path2, settings);
100412
100412
  }
100413
- exports2.statSync = statSync10;
100413
+ exports2.statSync = statSync11;
100414
100414
  function getSettings(settingsOrOptions = {}) {
100415
100415
  if (settingsOrOptions instanceof settings_1.default) {
100416
100416
  return settingsOrOptions;
@@ -123538,8 +123538,8 @@ function darwinPlistPath() {
123538
123538
  return `${process.env.HOME}/Library/LaunchAgents/${resolveLoadedLabel()}.plist`;
123539
123539
  }
123540
123540
  function getLogPaths() {
123541
- const dir = (0, import_node_path24.join)(installDir(), "logs");
123542
- return { stdout: (0, import_node_path24.join)(dir, "stdout.log"), stderr: (0, import_node_path24.join)(dir, "stderr.log") };
123541
+ const dir = (0, import_node_path25.join)(installDir(), "logs");
123542
+ return { stdout: (0, import_node_path25.join)(dir, "stdout.log"), stderr: (0, import_node_path25.join)(dir, "stderr.log") };
123543
123543
  }
123544
123544
  function getAgentPid() {
123545
123545
  try {
@@ -123559,12 +123559,12 @@ function getAgentPid() {
123559
123559
  return null;
123560
123560
  }
123561
123561
  }
123562
- var import_node_child_process4, import_node_path24, BREW_LAUNCHD_LABEL2;
123562
+ var import_node_child_process4, import_node_path25, BREW_LAUNCHD_LABEL2;
123563
123563
  var init_launchd = __esm({
123564
123564
  "src/lifecycle/launchd.ts"() {
123565
123565
  "use strict";
123566
123566
  import_node_child_process4 = require("child_process");
123567
- import_node_path24 = require("path");
123567
+ import_node_path25 = require("path");
123568
123568
  init_constants();
123569
123569
  BREW_LAUNCHD_LABEL2 = "homebrew.mxcl.tb-streamer";
123570
123570
  }
@@ -123589,9 +123589,9 @@ var init_marker_schema = __esm({
123589
123589
 
123590
123590
  // src/lifecycle/marker.ts
123591
123591
  function readMarker() {
123592
- if (!(0, import_node_fs20.existsSync)(markerPath())) return null;
123592
+ if (!(0, import_node_fs21.existsSync)(markerPath())) return null;
123593
123593
  try {
123594
- const raw2 = (0, import_node_fs20.readFileSync)(markerPath(), "utf8");
123594
+ const raw2 = (0, import_node_fs21.readFileSync)(markerPath(), "utf8");
123595
123595
  const parsed = JSON.parse(raw2);
123596
123596
  return MarkerSchema.parse(parsed);
123597
123597
  } catch (err) {
@@ -123603,21 +123603,21 @@ function readMarker() {
123603
123603
  }
123604
123604
  function writeMarker(marker) {
123605
123605
  MarkerSchema.parse(marker);
123606
- (0, import_node_fs20.mkdirSync)((0, import_node_path25.dirname)(markerPath()), { recursive: true });
123606
+ (0, import_node_fs21.mkdirSync)((0, import_node_path26.dirname)(markerPath()), { recursive: true });
123607
123607
  const tmp = `${markerPath()}.tmp`;
123608
- (0, import_node_fs20.writeFileSync)(tmp, `${JSON.stringify(marker, null, 2)}
123608
+ (0, import_node_fs21.writeFileSync)(tmp, `${JSON.stringify(marker, null, 2)}
123609
123609
  `, { mode: 384 });
123610
- (0, import_node_fs20.renameSync)(tmp, markerPath());
123610
+ (0, import_node_fs21.renameSync)(tmp, markerPath());
123611
123611
  }
123612
123612
  function clearMarker() {
123613
- if ((0, import_node_fs20.existsSync)(markerPath())) (0, import_node_fs20.rmSync)(markerPath());
123613
+ if ((0, import_node_fs21.existsSync)(markerPath())) (0, import_node_fs21.rmSync)(markerPath());
123614
123614
  }
123615
- var import_node_fs20, import_node_path25, log3;
123615
+ var import_node_fs21, import_node_path26, log3;
123616
123616
  var init_marker = __esm({
123617
123617
  "src/lifecycle/marker.ts"() {
123618
123618
  "use strict";
123619
- import_node_fs20 = require("fs");
123620
- import_node_path25 = require("path");
123619
+ import_node_fs21 = require("fs");
123620
+ import_node_path26 = require("path");
123621
123621
  init_logger();
123622
123622
  init_constants();
123623
123623
  init_marker_schema();
@@ -123818,9 +123818,9 @@ The supervised prod streamer is already holding port ${prodPort}.
123818
123818
  // src/lifecycle/prefs.ts
123819
123819
  function readPrefs() {
123820
123820
  const path2 = prefsPath();
123821
- if (!(0, import_node_fs22.existsSync)(path2)) return { repos: {} };
123821
+ if (!(0, import_node_fs23.existsSync)(path2)) return { repos: {} };
123822
123822
  try {
123823
- return PrefsSchema.parse(JSON.parse((0, import_node_fs22.readFileSync)(path2, "utf8")));
123823
+ return PrefsSchema.parse(JSON.parse((0, import_node_fs23.readFileSync)(path2, "utf8")));
123824
123824
  } catch (err) {
123825
123825
  log5.warn(`prefs at ${path2} are malformed; treating as empty`, {
123826
123826
  error: err instanceof Error ? err.message : String(err)
@@ -123830,11 +123830,11 @@ function readPrefs() {
123830
123830
  }
123831
123831
  function savePrefs(p2) {
123832
123832
  const path2 = prefsPath();
123833
- (0, import_node_fs22.mkdirSync)((0, import_node_path26.dirname)(path2), { recursive: true });
123833
+ (0, import_node_fs23.mkdirSync)((0, import_node_path27.dirname)(path2), { recursive: true });
123834
123834
  const tmp = `${path2}.tmp`;
123835
- (0, import_node_fs22.writeFileSync)(tmp, `${JSON.stringify(p2, null, 2)}
123835
+ (0, import_node_fs23.writeFileSync)(tmp, `${JSON.stringify(p2, null, 2)}
123836
123836
  `, { mode: 384 });
123837
- (0, import_node_fs22.renameSync)(tmp, path2);
123837
+ (0, import_node_fs23.renameSync)(tmp, path2);
123838
123838
  }
123839
123839
  function writePrefForRepo(repoToplevel, choice) {
123840
123840
  const p2 = readPrefs();
@@ -123855,14 +123855,14 @@ function forgetRepo(repoToplevel) {
123855
123855
  }
123856
123856
  function forgetAll() {
123857
123857
  const path2 = prefsPath();
123858
- if ((0, import_node_fs22.existsSync)(path2)) (0, import_node_fs22.rmSync)(path2);
123858
+ if ((0, import_node_fs23.existsSync)(path2)) (0, import_node_fs23.rmSync)(path2);
123859
123859
  }
123860
- var import_node_fs22, import_node_path26, log5, PrefsSchema;
123860
+ var import_node_fs23, import_node_path27, log5, PrefsSchema;
123861
123861
  var init_prefs = __esm({
123862
123862
  "src/lifecycle/prefs.ts"() {
123863
123863
  "use strict";
123864
- import_node_fs22 = require("fs");
123865
- import_node_path26 = require("path");
123864
+ import_node_fs23 = require("fs");
123865
+ import_node_path27 = require("path");
123866
123866
  init_zod();
123867
123867
  init_logger();
123868
123868
  init_constants();
@@ -130754,9 +130754,9 @@ var NodeFsHandler = class {
130754
130754
  if (this.fsw.closed) {
130755
130755
  return;
130756
130756
  }
130757
- const dirname17 = sysPath.dirname(file2);
130757
+ const dirname18 = sysPath.dirname(file2);
130758
130758
  const basename12 = sysPath.basename(file2);
130759
- const parent = this.fsw._getWatchedDir(dirname17);
130759
+ const parent = this.fsw._getWatchedDir(dirname18);
130760
130760
  let prevStats = stats;
130761
130761
  if (parent.has(basename12))
130762
130762
  return;
@@ -130783,7 +130783,7 @@ var NodeFsHandler = class {
130783
130783
  prevStats = newStats2;
130784
130784
  }
130785
130785
  } catch (error51) {
130786
- this.fsw._remove(dirname17, basename12);
130786
+ this.fsw._remove(dirname18, basename12);
130787
130787
  }
130788
130788
  } else if (parent.has(basename12)) {
130789
130789
  const at2 = newStats.atimeMs;
@@ -134993,11 +134993,11 @@ async function search(query, options, scanner) {
134993
134993
 
134994
134994
  // src/server.ts
134995
134995
  var import_events3 = require("events");
134996
- var import_fs25 = require("fs");
134996
+ var import_fs26 = require("fs");
134997
134997
  var import_promises19 = require("fs/promises");
134998
134998
  var import_http = require("http");
134999
- var import_os10 = require("os");
135000
- var import_path22 = require("path");
134999
+ var import_os11 = require("os");
135000
+ var import_path23 = require("path");
135001
135001
  var import_readline4 = require("readline");
135002
135002
 
135003
135003
  // src/agent/agent-client.ts
@@ -137480,7 +137480,8 @@ function isLocalRequest(remoteAddr) {
137480
137480
  const addr = remoteAddr ?? "";
137481
137481
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
137482
137482
  }
137483
- var PUBLIC_PATHS = /* @__PURE__ */ new Set(["/healthz", "/ws"]);
137483
+ var PUBLIC_PATHS = /* @__PURE__ */ new Set(["/healthz"]);
137484
+ var LOCAL_ONLY_PATHS = /* @__PURE__ */ new Set(["/api/logs", "/api/logs/meta"]);
137484
137485
  var PUBLIC_POST_PATHS = /* @__PURE__ */ new Set(["/api/pair/exchange", "/api/__update"]);
137485
137486
  var PUBLIC_POST_PREFIXES = ["/internal/sessions/"];
137486
137487
  var authMiddleware = (deps) => async (c, next) => {
@@ -137491,8 +137492,12 @@ var authMiddleware = (deps) => async (c, next) => {
137491
137492
  await next();
137492
137493
  return;
137493
137494
  }
137495
+ const remoteAddr = c.env.incoming?.socket?.remoteAddress;
137496
+ if (LOCAL_ONLY_PATHS.has(path2) && isLocalRequest(remoteAddr)) {
137497
+ await next();
137498
+ return;
137499
+ }
137494
137500
  if (deps.localNoAuth) {
137495
- const remoteAddr = c.env.incoming?.socket?.remoteAddress;
137496
137501
  if (isLocalRequest(remoteAddr)) {
137497
137502
  await next();
137498
137503
  return;
@@ -137659,6 +137664,126 @@ var createHealthRoutes = () => {
137659
137664
  return app;
137660
137665
  };
137661
137666
 
137667
+ // src/api/routes/logs.routes.ts
137668
+ var import_node_fs6 = require("fs");
137669
+ var import_node_path9 = require("path");
137670
+ init_constants();
137671
+ init_logger();
137672
+ var logger2 = getLogger("logs-api");
137673
+ function resolveLogPath(source) {
137674
+ return (0, import_node_path9.join)(installDir(), "logs", `${source}.log`);
137675
+ }
137676
+ function pickDefaultSource() {
137677
+ for (const source of ["stdout", "stderr", "dev"]) {
137678
+ const p2 = resolveLogPath(source);
137679
+ if ((0, import_node_fs6.existsSync)(p2) && (0, import_node_fs6.statSync)(p2).size > 0) return source;
137680
+ }
137681
+ return "stdout";
137682
+ }
137683
+ function readLogLines(filePath, sinceOffset, limit) {
137684
+ if (!(0, import_node_fs6.existsSync)(filePath)) {
137685
+ return { lines: [], offset: 0, total: 0 };
137686
+ }
137687
+ const fd = (0, import_node_fs6.openSync)(filePath, "r");
137688
+ try {
137689
+ const { size } = (0, import_node_fs6.fstatSync)(fd);
137690
+ if (size === 0) return { lines: [], offset: 0, total: 0 };
137691
+ const maxBytes = Math.min(size, 2 * 1024 * 1024);
137692
+ const start = size - maxBytes;
137693
+ const buf = Buffer.alloc(maxBytes);
137694
+ (0, import_node_fs6.readSync)(fd, buf, 0, maxBytes, start);
137695
+ let text = buf.toString("utf8");
137696
+ if (start > 0) {
137697
+ const firstNl = text.indexOf("\n");
137698
+ if (firstNl >= 0) text = text.slice(firstNl + 1);
137699
+ }
137700
+ const allLines = text.split("\n").filter((line) => line.trim() && !line.startsWith("==="));
137701
+ let lines;
137702
+ let newOffset;
137703
+ if (sinceOffset > 0 && sinceOffset < allLines.length) {
137704
+ lines = allLines.slice(sinceOffset, sinceOffset + limit);
137705
+ newOffset = sinceOffset + lines.length;
137706
+ } else if (sinceOffset >= allLines.length && sinceOffset > 0) {
137707
+ lines = [];
137708
+ newOffset = allLines.length;
137709
+ } else {
137710
+ lines = allLines.slice(-limit);
137711
+ newOffset = allLines.length;
137712
+ }
137713
+ return { lines, offset: newOffset, total: allLines.length };
137714
+ } finally {
137715
+ (0, import_node_fs6.closeSync)(fd);
137716
+ }
137717
+ }
137718
+ function createLogsRoutes() {
137719
+ const app = new Hono2();
137720
+ app.get("/", (c) => {
137721
+ try {
137722
+ const sourceParam = (c.req.query("source") || "").toLowerCase();
137723
+ const source = sourceParam === "stdout" || sourceParam === "stderr" || sourceParam === "dev" ? sourceParam : pickDefaultSource();
137724
+ const logPath = resolveLogPath(source);
137725
+ const sinceOffset = parseInt(c.req.query("since") || "0", 10);
137726
+ const limit = Math.min(parseInt(c.req.query("limit") || "100", 10) || 100, 1e3);
137727
+ if (!(0, import_node_fs6.existsSync)(logPath)) {
137728
+ return c.json({
137729
+ logs: [],
137730
+ message: `No log file found for source=${source}`,
137731
+ offset: 0,
137732
+ total: 0,
137733
+ source
137734
+ });
137735
+ }
137736
+ const { lines, offset, total } = readLogLines(logPath, sinceOffset, limit);
137737
+ const stats = (0, import_node_fs6.statSync)(logPath);
137738
+ return c.json({
137739
+ logs: lines,
137740
+ offset,
137741
+ total,
137742
+ hasMore: offset < total,
137743
+ source,
137744
+ fileSize: stats.size,
137745
+ fileModified: stats.mtime.toISOString()
137746
+ });
137747
+ } catch (error51) {
137748
+ logger2.error("Failed to read logs", { error: String(error51) });
137749
+ return c.json(
137750
+ {
137751
+ error: "Failed to read logs",
137752
+ logs: [],
137753
+ offset: 0,
137754
+ total: 0
137755
+ },
137756
+ 500
137757
+ );
137758
+ }
137759
+ });
137760
+ app.get("/meta", (c) => {
137761
+ try {
137762
+ const sources = ["stdout", "stderr", "dev"].map((source) => {
137763
+ const logPath = resolveLogPath(source);
137764
+ if (!(0, import_node_fs6.existsSync)(logPath)) {
137765
+ return { source, exists: false, total: 0, fileSize: 0 };
137766
+ }
137767
+ const stats = (0, import_node_fs6.statSync)(logPath);
137768
+ return {
137769
+ source,
137770
+ exists: true,
137771
+ fileSize: stats.size,
137772
+ fileModified: stats.mtime.toISOString()
137773
+ };
137774
+ });
137775
+ return c.json({
137776
+ defaultSource: pickDefaultSource(),
137777
+ sources
137778
+ });
137779
+ } catch (error51) {
137780
+ logger2.error("Failed to read log metadata", { error: String(error51) });
137781
+ return c.json({ error: "Failed to read log metadata", exists: false }, 500);
137782
+ }
137783
+ });
137784
+ return app;
137785
+ }
137786
+
137662
137787
  // src/api/routes/misc.routes.ts
137663
137788
  var import_node_child_process2 = require("child_process");
137664
137789
  var import_node_crypto = require("crypto");
@@ -137810,7 +137935,7 @@ function verifySignature(rawBody, signature, secret) {
137810
137935
  }
137811
137936
  }
137812
137937
  function isWithinSkew(timestampHeader, skewSeconds) {
137813
- if (!timestampHeader) return false;
137938
+ if (!timestampHeader) return true;
137814
137939
  const t = Number(timestampHeader);
137815
137940
  if (!Number.isFinite(t)) return false;
137816
137941
  const now = Math.floor(Date.now() / 1e3);
@@ -138021,21 +138146,18 @@ var createSessionRoutes = (deps) => {
138021
138146
  };
138022
138147
 
138023
138148
  // src/api/routes/ws.routes.ts
138024
- init_auth();
138025
138149
  var createWsRoutes = (deps, upgradeWebSocket) => {
138026
138150
  const app = new Hono2();
138027
138151
  app.get(
138028
138152
  "/ws",
138029
- upgradeWebSocket((c) => {
138030
- const key = c.req.query("key");
138031
- const preAuthed = typeof key === "string" && validateApiKey(key, deps.apiKey);
138153
+ upgradeWebSocket(() => {
138032
138154
  let openWs = null;
138033
138155
  return {
138034
138156
  onOpen(_evt, ws2) {
138035
138157
  const raw2 = ws2.raw;
138036
138158
  if (!raw2) return;
138037
138159
  openWs = raw2;
138038
- deps.handleWsOpen(raw2, preAuthed);
138160
+ deps.handleWsOpen(raw2);
138039
138161
  },
138040
138162
  onMessage(evt, _ws) {
138041
138163
  if (openWs) deps.handleWsMessage(openWs, evt.data);
@@ -138080,6 +138202,7 @@ var createHonoApp = (deps, upgradeWebSocket) => {
138080
138202
  app.route("/api", createBrowseRoutes(deps));
138081
138203
  app.route("/", createScannerRoutes(deps));
138082
138204
  app.route("/internal", createProgressRoutes(deps));
138205
+ app.route("/api/logs", createLogsRoutes());
138083
138206
  if (upgradeWebSocket) {
138084
138207
  app.route("/", createWsRoutes(deps, upgradeWebSocket));
138085
138208
  }
@@ -139741,13 +139864,13 @@ function handleListProjects(url2, res) {
139741
139864
  }
139742
139865
 
139743
139866
  // src/live-session-manager.ts
139744
- var import_path19 = require("path");
139867
+ var import_path20 = require("path");
139745
139868
 
139746
139869
  // src/codex-pty-runner.ts
139747
139870
  var import_headless = __toESM(require_xterm_headless(), 1);
139748
139871
  var import_crypto7 = require("crypto");
139749
- var import_fs21 = require("fs");
139750
- var import_path17 = require("path");
139872
+ var import_fs22 = require("fs");
139873
+ var import_path18 = require("path");
139751
139874
  init_logger();
139752
139875
 
139753
139876
  // src/platform.ts
@@ -139873,13 +139996,80 @@ function resolveCodexExe() {
139873
139996
  return _codexExe;
139874
139997
  }
139875
139998
 
139999
+ // src/services/questions/codexGateAnswers.ts
140000
+ var import_fs21 = require("fs");
140001
+ var import_os9 = require("os");
140002
+ var import_path17 = require("path");
140003
+ function gateAnswersPath() {
140004
+ const dir = process.env.THREADBASE_CONFIG_DIR ?? (0, import_path17.join)((0, import_os9.homedir)(), ".threadbase");
140005
+ return (0, import_path17.join)(dir, "gate-answers.json");
140006
+ }
140007
+ function loadGateAnswers() {
140008
+ try {
140009
+ const parsed = JSON.parse((0, import_fs21.readFileSync)(gateAnswersPath(), "utf-8"));
140010
+ return parsed && typeof parsed === "object" ? parsed : {};
140011
+ } catch {
140012
+ return {};
140013
+ }
140014
+ }
140015
+ function saveGateAnswer(key, value) {
140016
+ const path2 = gateAnswersPath();
140017
+ (0, import_fs21.mkdirSync)((0, import_path17.dirname)(path2), { recursive: true });
140018
+ (0, import_fs21.writeFileSync)(path2, `${JSON.stringify({ ...loadGateAnswers(), [key]: value }, null, 2)}
140019
+ `);
140020
+ }
140021
+ function rememberedGateDigit(gate) {
140022
+ const answers = loadGateAnswers();
140023
+ if (gate === "hooks") {
140024
+ if (answers.codexHooksGate === "trust_all") return "2";
140025
+ if (answers.codexHooksGate === "continue_untrusted") return "3";
140026
+ return null;
140027
+ }
140028
+ return answers.codexTrustGate === "yes" ? "1" : null;
140029
+ }
140030
+
140031
+ // src/utils/debounce.ts
140032
+ function debounce(fn, waitMs) {
140033
+ let timer = null;
140034
+ let lastArgs = null;
140035
+ const run2 = () => {
140036
+ timer = null;
140037
+ if (lastArgs) {
140038
+ const args = lastArgs;
140039
+ lastArgs = null;
140040
+ fn(...args);
140041
+ }
140042
+ };
140043
+ const debounced = (...args) => {
140044
+ lastArgs = args;
140045
+ if (timer) clearTimeout(timer);
140046
+ timer = setTimeout(run2, waitMs);
140047
+ };
140048
+ debounced.cancel = () => {
140049
+ if (timer) clearTimeout(timer);
140050
+ timer = null;
140051
+ lastArgs = null;
140052
+ };
140053
+ debounced.flush = () => {
140054
+ if (timer) {
140055
+ clearTimeout(timer);
140056
+ run2();
140057
+ }
140058
+ };
140059
+ return debounced;
140060
+ }
140061
+
139876
140062
  // src/codex-pty-runner.ts
139877
140063
  var OUTPUT_BUFFER_MAX = 65536;
140064
+ var INPUT_HISTORY_MAX = 50;
139878
140065
  var PTY_COLS = 120;
139879
140066
  var PTY_ROWS = 40;
139880
140067
  var SCREEN_SCROLLBACK = 1e3;
139881
140068
  var CODEX_PROMPT_READY_TEXT = "Ready";
139882
140069
  var CODEX_TRUST_GATE_REGEX = /trust the contents/i;
140070
+ var CODEX_HOOKS_GATE_REGEX = /hooks need review/i;
140071
+ var QUIET_DETECT_MS = 500;
140072
+ var CODEX_READY_FALLBACK_MS = 8e3;
139883
140073
  var SUBMIT_BYTES = "\r";
139884
140074
  var CODEX_SUBMIT_DELAY_MS = 16;
139885
140075
  function digestBytes(s3) {
@@ -139887,6 +140077,40 @@ function digestBytes(s3) {
139887
140077
  if (escaped.length <= 200) return escaped;
139888
140078
  return `${escaped.slice(0, 100)}\u2026[${escaped.length - 200}B omitted]\u2026${escaped.slice(-100)}`;
139889
140079
  }
140080
+ function gateCard(gate, lines) {
140081
+ if (gate === "hooks") {
140082
+ const countLine = lines.find((l) => /new or changed/i.test(l))?.trim();
140083
+ return {
140084
+ prompt: [
140085
+ "Hooks need review",
140086
+ countLine,
140087
+ "Hooks can run outside the sandbox after you trust them."
140088
+ ].filter(Boolean).join(" \u2014 "),
140089
+ options: [
140090
+ { index: 2, label: "Trust all and continue", answerKeys: "2\r" },
140091
+ { index: 3, label: "Continue without trusting (hooks won't run)", answerKeys: "3\r" },
140092
+ {
140093
+ index: 4,
140094
+ label: "Trust all and continue (remember for all projects)",
140095
+ answerKeys: "4\r"
140096
+ },
140097
+ {
140098
+ index: 5,
140099
+ label: "Continue without trusting (remember for all projects)",
140100
+ answerKeys: "5\r"
140101
+ }
140102
+ ]
140103
+ };
140104
+ }
140105
+ return {
140106
+ prompt: lines.find((l) => CODEX_TRUST_GATE_REGEX.test(l))?.trim() ?? "Do you trust the contents of this directory?",
140107
+ options: [
140108
+ { index: 1, label: "Yes, continue", answerKeys: "1\r" },
140109
+ { index: 2, label: "No, quit", answerKeys: "2\r" },
140110
+ { index: 3, label: "Yes, continue (remember for all projects)", answerKeys: "3\r" }
140111
+ ]
140112
+ };
140113
+ }
139890
140114
  var pty = null;
139891
140115
  async function loadPty() {
139892
140116
  if (pty) return pty;
@@ -139913,11 +140137,12 @@ var CodexPtyRunner = class {
139913
140137
  onOutput;
139914
140138
  onStatusChange;
139915
140139
  onReady;
139916
- // Accepted for shape-compatibility with PTYManagerOptions; Codex has no
139917
- // detected equivalent yet (Phase 0) never invoked.
140140
+ // Broadcasts Codex's blocking startup gates (directory trust, hooks review)
140141
+ // as question cards; null dismisses the card once the gate leaves the screen.
139918
140142
  onPermissionChange;
139919
140143
  onLiveQuestion;
139920
140144
  onLiveQuestionGone;
140145
+ onUserMessage;
139921
140146
  log;
139922
140147
  // Tracks sessions whose PTY has spawned but Codex hasn't yet reached its
139923
140148
  // "Ready" status bar — i.e. onReady hasn't fired.
@@ -139925,8 +140150,18 @@ var CodexPtyRunner = class {
139925
140150
  // Inputs received via sendInput() while the session was still pendingReady.
139926
140151
  // Flushed in arrival order once Codex reaches Ready.
139927
140152
  queuedInputs = /* @__PURE__ */ new Map();
139928
- // Per-session debounce so the directory-trust gate's \r is only written once.
139929
- trustGateAnswered = /* @__PURE__ */ new Set();
140153
+ // Gate currently on a session's screen (card broadcast, unanswered). While
140154
+ // set, queued-input flushes are held — a flushed digit would CONFIRM a
140155
+ // dialog option — and sendKeys() intercepts remember-variant digits.
140156
+ openGate = /* @__PURE__ */ new Map();
140157
+ // `${sessionId}:${gate}` once a gate has been actioned (auto-answered or
140158
+ // card broadcast) — dedupes repaints of the same dialog.
140159
+ gateActioned = /* @__PURE__ */ new Set();
140160
+ // Per-session trailing debounce re-armed on every chunk; on quiet, re-runs
140161
+ // screen detection so a blocked/truncated boot still reaches ready.
140162
+ quietCheckers = /* @__PURE__ */ new Map();
140163
+ // Per-session flat backstop from spawn (CODEX_READY_FALLBACK_MS).
140164
+ readyFallbackTimers = /* @__PURE__ */ new Map();
139930
140165
  // In-flight start()/startFresh() calls keyed by sessionId. A second
139931
140166
  // concurrent resume for the same session (double-tap, client retry) awaits
139932
140167
  // the first call's promise instead of spawning a duplicate PTY (CRITICAL #3).
@@ -139938,6 +140173,7 @@ var CodexPtyRunner = class {
139938
140173
  this.onPermissionChange = options.onPermissionChange;
139939
140174
  this.onLiveQuestion = options.onLiveQuestion;
139940
140175
  this.onLiveQuestionGone = options.onLiveQuestionGone;
140176
+ this.onUserMessage = options.onUserMessage;
139941
140177
  this.log = options.logger ?? getLogger("codex-pty");
139942
140178
  }
139943
140179
  // Resume an existing Codex session. sessionId is the Codex-persisted
@@ -139956,7 +140192,7 @@ var CodexPtyRunner = class {
139956
140192
  }
139957
140193
  async doStart(sessionId, options) {
139958
140194
  const nodePty = await loadPty();
139959
- const projectName = options.projectName ?? (0, import_path17.basename)(options.projectPath);
140195
+ const projectName = options.projectName ?? (0, import_path18.basename)(options.projectPath);
139960
140196
  const proc = nodePty.spawn(
139961
140197
  resolveCodexExe(),
139962
140198
  ["resume", sessionId, "--cd", options.projectPath, "--no-alt-screen"],
@@ -139981,10 +140217,12 @@ var CodexPtyRunner = class {
139981
140217
  lastOutput: "",
139982
140218
  process: proc,
139983
140219
  outputBuffer: Buffer.alloc(0),
139984
- screen: createScreen()
140220
+ screen: createScreen(),
140221
+ inputHistory: []
139985
140222
  };
139986
140223
  this.sessions.set(sessionId, session);
139987
140224
  this.pendingReady.add(sessionId);
140225
+ this.armReadyFallback(sessionId);
139988
140226
  proc.onData((data) => {
139989
140227
  this.handleOutput(sessionId, data);
139990
140228
  });
@@ -140001,7 +140239,7 @@ var CodexPtyRunner = class {
140001
140239
  async startFresh(options) {
140002
140240
  const nodePty = await loadPty();
140003
140241
  const sessionId = (0, import_crypto7.randomUUID)();
140004
- const projectName = options.projectName ?? (0, import_path17.basename)(options.projectPath);
140242
+ const projectName = options.projectName ?? (0, import_path18.basename)(options.projectPath);
140005
140243
  const args = ["--cd", options.projectPath, "--no-alt-screen"];
140006
140244
  if (options.systemPrompt) {
140007
140245
  args.push(options.systemPrompt);
@@ -140026,10 +140264,12 @@ var CodexPtyRunner = class {
140026
140264
  lastOutput: "",
140027
140265
  process: proc,
140028
140266
  outputBuffer: Buffer.alloc(0),
140029
- screen: createScreen()
140267
+ screen: createScreen(),
140268
+ inputHistory: []
140030
140269
  };
140031
140270
  this.sessions.set(sessionId, session);
140032
140271
  this.pendingReady.add(sessionId);
140272
+ this.armReadyFallback(sessionId);
140033
140273
  proc.onData((data) => {
140034
140274
  this.handleOutput(sessionId, data);
140035
140275
  });
@@ -140039,6 +140279,21 @@ var CodexPtyRunner = class {
140039
140279
  });
140040
140280
  return toPublicSession(session);
140041
140281
  }
140282
+ // Flat backstop: if neither the "Ready" marker nor the quiet-checker settled
140283
+ // the session within CODEX_READY_FALLBACK_MS of spawn, mark it ready anyway
140284
+ // so start requests resolve and mobile can watch the boot live. unref() so a
140285
+ // pending timer never holds the process open.
140286
+ armReadyFallback(sessionId) {
140287
+ const timer = setTimeout(() => {
140288
+ this.readyFallbackTimers.delete(sessionId);
140289
+ const session = this.sessions.get(sessionId);
140290
+ if (session?.status === "running" && this.pendingReady.has(sessionId)) {
140291
+ this.markReady(sessionId, session, "fallback:timeout");
140292
+ }
140293
+ }, CODEX_READY_FALLBACK_MS);
140294
+ timer.unref?.();
140295
+ this.readyFallbackTimers.set(sessionId, timer);
140296
+ }
140042
140297
  // Write raw key bytes directly to the PTY, same as PTYManager.sendKeys.
140043
140298
  sendKeys(sessionId, keys) {
140044
140299
  const session = this.sessions.get(sessionId);
@@ -140050,13 +140305,47 @@ var CodexPtyRunner = class {
140050
140305
  session.status = "running";
140051
140306
  this.onStatusChange?.(toPublicSession(session));
140052
140307
  }
140308
+ const gate = this.openGate.get(sessionId);
140309
+ const digit = gate ? /^([0-9])\r?$/.exec(keys)?.[1] : void 0;
140310
+ const out = gate && digit ? this.resolveGateAnswer(sessionId, gate, digit) : keys;
140053
140311
  this.log.info(
140054
- `[codex.keys.write] ${sessionId.slice(0, 8)} bytes=${keys.length} digest=${digestBytes(keys)}`,
140055
- { event: "codex.keys_write", sessionId, byteLen: keys.length }
140312
+ `[codex.keys.write] ${sessionId.slice(0, 8)} bytes=${out.length} digest=${digestBytes(out)}`,
140313
+ { event: "codex.keys_write", sessionId, byteLen: out.length }
140056
140314
  );
140057
- session.process.write(keys);
140315
+ session.process.write(out);
140058
140316
  session.lastActivityAt = /* @__PURE__ */ new Date();
140059
140317
  }
140318
+ // Map a gate-card digit to the PTY bytes that answer the real dialog,
140319
+ // persisting the choice when the digit was a synthetic "remember for all
140320
+ // projects" option (those numbers don't exist on the actual dialog and must
140321
+ // never reach codex). The trailing \r mobile sends is dropped: a digit alone
140322
+ // selects AND confirms (live-probe verified), and a stray Enter would land
140323
+ // on whatever screen follows.
140324
+ resolveGateAnswer(sessionId, gate, digit) {
140325
+ let real = digit;
140326
+ let remembered = false;
140327
+ if (gate === "hooks" && digit === "4") {
140328
+ saveGateAnswer("codexHooksGate", "trust_all");
140329
+ real = "2";
140330
+ remembered = true;
140331
+ } else if (gate === "hooks" && digit === "5") {
140332
+ saveGateAnswer("codexHooksGate", "continue_untrusted");
140333
+ real = "3";
140334
+ remembered = true;
140335
+ } else if (gate === "trust" && digit === "3") {
140336
+ saveGateAnswer("codexTrustGate", "yes");
140337
+ real = "1";
140338
+ remembered = true;
140339
+ }
140340
+ this.log.info(`[codex.gate_answer] ${sessionId.slice(0, 8)} ${gate} digit=${real}`, {
140341
+ event: "codex.gate_answer",
140342
+ sessionId,
140343
+ gate,
140344
+ digit: real,
140345
+ remembered
140346
+ });
140347
+ return real;
140348
+ }
140060
140349
  sendInput(sessionId, input) {
140061
140350
  const session = this.sessions.get(sessionId);
140062
140351
  if (!session) throw new Error(`Session not found: ${sessionId}`);
@@ -140094,6 +140383,7 @@ var CodexPtyRunner = class {
140094
140383
  // confirmed Codex accepts plain keystrokes), then submit \r after a short
140095
140384
  // delay so Codex's TUI gets an event-loop tick to process the input first.
140096
140385
  writeSubmit(sessionId, session, input, path2, promptCount) {
140386
+ this.recordUserMessage(session, input);
140097
140387
  this.log.info(
140098
140388
  `[codex.input.write] ${sessionId.slice(0, 8)} promptCount=${promptCount} bytes=${input.length} digest=${digestBytes(input)}`,
140099
140389
  {
@@ -140126,8 +140416,12 @@ var CodexPtyRunner = class {
140126
140416
  }, CODEX_SUBMIT_DELAY_MS);
140127
140417
  }
140128
140418
  // Drain any inputs sent while the session was still pendingReady, writing
140129
- // them in arrival order now that Codex is Ready.
140419
+ // them in arrival order now that Codex is Ready. No-op while a gate dialog
140420
+ // is open (a flushed digit would confirm a dialog option) or while still
140421
+ // pendingReady (markReady drains it) — the gate-close path re-drives it for
140422
+ // the ready-with-gate-open case.
140130
140423
  flushQueuedInputs(sessionId) {
140424
+ if (this.openGate.has(sessionId) || this.pendingReady.has(sessionId)) return;
140131
140425
  const queue = this.queuedInputs.get(sessionId);
140132
140426
  if (!queue || queue.length === 0) return;
140133
140427
  this.queuedInputs.delete(sessionId);
@@ -140172,7 +140466,7 @@ var CodexPtyRunner = class {
140172
140466
  if (!session) return;
140173
140467
  this.pendingReady.delete(sessionId);
140174
140468
  this.queuedInputs.delete(sessionId);
140175
- this.trustGateAnswered.delete(sessionId);
140469
+ this.clearSessionDetectors(sessionId);
140176
140470
  try {
140177
140471
  session.process.kill("SIGINT");
140178
140472
  } catch {
@@ -140183,6 +140477,21 @@ var CodexPtyRunner = class {
140183
140477
  this.sessions.delete(sessionId);
140184
140478
  this.onStatusChange?.(toPublicSession(session));
140185
140479
  }
140480
+ // Drop a session's detection state: quiet-checker, ready-fallback timer,
140481
+ // gate bookkeeping — and dismiss a still-open gate card so mobile doesn't
140482
+ // keep rendering a question for a dead PTY.
140483
+ clearSessionDetectors(sessionId) {
140484
+ this.quietCheckers.get(sessionId)?.cancel();
140485
+ this.quietCheckers.delete(sessionId);
140486
+ const timer = this.readyFallbackTimers.get(sessionId);
140487
+ if (timer) clearTimeout(timer);
140488
+ this.readyFallbackTimers.delete(sessionId);
140489
+ if (this.openGate.delete(sessionId)) {
140490
+ this.onPermissionChange?.(sessionId, null);
140491
+ }
140492
+ this.gateActioned.delete(`${sessionId}:hooks`);
140493
+ this.gateActioned.delete(`${sessionId}:trust`);
140494
+ }
140186
140495
  getOutput(sessionId) {
140187
140496
  const session = this.sessions.get(sessionId);
140188
140497
  if (!session) throw new Error(`Session not found: ${sessionId}`);
@@ -140204,6 +140513,19 @@ var CodexPtyRunner = class {
140204
140513
  }
140205
140514
  return lines.slice(-maxLines);
140206
140515
  }
140516
+ getInputHistory(sessionId) {
140517
+ return this.sessions.get(sessionId)?.inputHistory ?? [];
140518
+ }
140519
+ // Record a submitted user message as ground truth and fire onUserMessage.
140520
+ // Called from writeSubmit (direct and flush paths) — never from sendKeys.
140521
+ recordUserMessage(session, text) {
140522
+ const ts2 = Date.now();
140523
+ session.inputHistory.push({ text, ts: ts2 });
140524
+ if (session.inputHistory.length > INPUT_HISTORY_MAX) {
140525
+ session.inputHistory.shift();
140526
+ }
140527
+ this.onUserMessage?.(session.id, text, ts2);
140528
+ }
140207
140529
  getSession(sessionId) {
140208
140530
  const session = this.sessions.get(sessionId);
140209
140531
  return session ? toPublicSession(session) : null;
@@ -140222,10 +140544,19 @@ var CodexPtyRunner = class {
140222
140544
  }
140223
140545
  session.screen.dispose();
140224
140546
  }
140547
+ for (const sessionId of Array.from(this.quietCheckers.keys())) {
140548
+ this.clearSessionDetectors(sessionId);
140549
+ }
140550
+ for (const timer of this.readyFallbackTimers.values()) {
140551
+ clearTimeout(timer);
140552
+ }
140225
140553
  this.sessions.clear();
140226
140554
  this.pendingReady.clear();
140227
140555
  this.queuedInputs.clear();
140228
- this.trustGateAnswered.clear();
140556
+ this.openGate.clear();
140557
+ this.gateActioned.clear();
140558
+ this.quietCheckers.clear();
140559
+ this.readyFallbackTimers.clear();
140229
140560
  }
140230
140561
  handleOutput(sessionId, data) {
140231
140562
  const session = this.sessions.get(sessionId);
@@ -140240,44 +140571,92 @@ var CodexPtyRunner = class {
140240
140571
  session.screen.write(data);
140241
140572
  session.lastOutput = stripAnsi(data);
140242
140573
  this.onOutput?.(sessionId, data);
140243
- this.detectReady(sessionId, session).catch((err) => {
140574
+ this.detectScreenState(sessionId, "chunk").catch((err) => {
140244
140575
  this.log.warn("[codex.ready_detect] failed", {
140245
140576
  event: "codex.ready_detect_failed",
140246
140577
  sessionId,
140247
140578
  err
140248
140579
  });
140249
140580
  });
140581
+ let quiet = this.quietCheckers.get(sessionId);
140582
+ if (!quiet) {
140583
+ quiet = debounce(() => {
140584
+ this.detectScreenState(sessionId, "quiet").catch((err) => {
140585
+ this.log.warn("[codex.ready_detect] failed", {
140586
+ event: "codex.ready_detect_failed",
140587
+ sessionId,
140588
+ err
140589
+ });
140590
+ });
140591
+ }, QUIET_DETECT_MS);
140592
+ this.quietCheckers.set(sessionId, quiet);
140593
+ }
140594
+ quiet();
140250
140595
  }
140251
- // Renders the session's headless screen and checks for the directory-trust
140252
- // gate (answered once, debounced) and the "Ready" status-bar text. Only
140253
- // transitions to waiting_input / fires onReady when the rendered status
140254
- // line literally contains "Ready" `›` alone (visible during "Starting")
140255
- // is NOT a valid readiness signal (Phase 0).
140256
- async detectReady(sessionId, session) {
140257
- if (session.status !== "running" || !this.pendingReady.has(sessionId)) return;
140596
+ // Renders the session's headless screen and drives both detections:
140597
+ // - Gates (directory trust, hooks review) checked on EVERY pass,
140598
+ // independent of pendingReady, so a gate appearing after ready is still
140599
+ // surfaced and a gate leaving the screen closes its card.
140600
+ // - Readiness the "Ready" status-bar marker while pendingReady, plus the
140601
+ // quiet path: after QUIET_DETECT_MS of PTY silence a still-pending
140602
+ // session is marked ready anyway (`›` alone is NOT a marker — Phase 0 —
140603
+ // but a quiet boot screen is more useful to the user live than a
140604
+ // spinner, and "Ready" may be truncated off the 120-col status bar).
140605
+ async detectScreenState(sessionId, trigger) {
140606
+ const session = this.sessions.get(sessionId);
140607
+ if (!session || session.status === "idle") return;
140258
140608
  const lines = await this.getOutputLines(sessionId, PTY_ROWS);
140259
140609
  const screenText = lines.join("\n");
140260
- if (CODEX_TRUST_GATE_REGEX.test(screenText)) {
140261
- if (!this.trustGateAnswered.has(sessionId)) {
140262
- this.trustGateAnswered.add(sessionId);
140263
- this.log.info(`[codex.trust_gate] ${sessionId.slice(0, 8)} auto-answering`, {
140264
- event: "codex.trust_gate",
140265
- sessionId
140266
- });
140267
- session.process.write("\r");
140268
- }
140269
- return;
140610
+ const gate = CODEX_HOOKS_GATE_REGEX.test(screenText) ? "hooks" : CODEX_TRUST_GATE_REGEX.test(screenText) ? "trust" : null;
140611
+ if (gate) {
140612
+ this.handleGate(sessionId, session, gate, lines);
140613
+ } else if (this.openGate.delete(sessionId)) {
140614
+ this.onPermissionChange?.(sessionId, null);
140615
+ this.flushQueuedInputs(sessionId);
140270
140616
  }
140617
+ if (session.status !== "running" || !this.pendingReady.has(sessionId)) return;
140271
140618
  const lastNonBlank2 = [...lines].reverse().find((l) => l.trim() !== "") ?? "";
140272
- if (!lastNonBlank2.includes(CODEX_PROMPT_READY_TEXT)) return;
140273
- this.markReady(sessionId, session);
140619
+ if (lastNonBlank2.includes(CODEX_PROMPT_READY_TEXT)) {
140620
+ this.markReady(sessionId, session, `marker:${CODEX_PROMPT_READY_TEXT}`);
140621
+ } else if (trigger === "quiet") {
140622
+ this.markReady(sessionId, session, "quiet:timeout");
140623
+ }
140274
140624
  }
140275
- markReady(sessionId, session) {
140625
+ // Answer a gate from the persisted remember-store, or surface it as a
140626
+ // question card over the permission transport. Actioned once per session and
140627
+ // gate type — repaints of the same dialog neither re-write nor re-broadcast.
140628
+ handleGate(sessionId, session, gate, lines) {
140629
+ const key = `${sessionId}:${gate}`;
140630
+ if (this.gateActioned.has(key)) return;
140631
+ this.gateActioned.add(key);
140632
+ const remembered = rememberedGateDigit(gate);
140633
+ if (remembered) {
140634
+ this.log.info(`[codex.gate_auto_answer] ${sessionId.slice(0, 8)} ${gate} \u2192 ${remembered}`, {
140635
+ event: "codex.gate_auto_answer",
140636
+ sessionId,
140637
+ gate,
140638
+ digit: remembered
140639
+ });
140640
+ session.process.write(remembered);
140641
+ return;
140642
+ }
140643
+ this.openGate.set(sessionId, gate);
140644
+ const card = gateCard(gate, lines);
140645
+ this.log.info(`[codex.gate_prompt] ${sessionId.slice(0, 8)} ${gate}`, {
140646
+ event: "codex.gate_prompt",
140647
+ sessionId,
140648
+ gate,
140649
+ prompt: card.prompt
140650
+ });
140651
+ this.onPermissionChange?.(sessionId, card);
140652
+ }
140653
+ markReady(sessionId, session, reason) {
140276
140654
  session.lastActivityAt = /* @__PURE__ */ new Date();
140277
140655
  session.status = "waiting_input";
140278
- this.log.info(`[codex.ready] ${sessionId.slice(0, 8)}`, {
140656
+ this.log.info(`[codex.ready] ${sessionId.slice(0, 8)} ${reason}`, {
140279
140657
  event: "codex.ready",
140280
- sessionId
140658
+ sessionId,
140659
+ reason
140281
140660
  });
140282
140661
  this.onStatusChange?.(toPublicSession(session));
140283
140662
  if (this.pendingReady.has(sessionId)) {
@@ -140293,7 +140672,7 @@ var CodexPtyRunner = class {
140293
140672
  session.status = "idle";
140294
140673
  const elapsedMs = session.completedAt.getTime() - session.startedAt.getTime();
140295
140674
  if (exitCode !== 0 && elapsedMs < 2e3 && session.lastOutput === "") {
140296
- if (!(0, import_fs21.existsSync)(session.projectPath)) {
140675
+ if (!(0, import_fs22.existsSync)(session.projectPath)) {
140297
140676
  session.failureReason = `Project directory not found: ${session.projectPath}`;
140298
140677
  } else {
140299
140678
  session.failureReason = `Codex process exited immediately (code ${exitCode}).`;
@@ -140303,7 +140682,7 @@ var CodexPtyRunner = class {
140303
140682
  session.screen.dispose();
140304
140683
  this.sessions.delete(sessionId);
140305
140684
  this.queuedInputs.delete(sessionId);
140306
- this.trustGateAnswered.delete(sessionId);
140685
+ this.clearSessionDetectors(sessionId);
140307
140686
  }
140308
140687
  };
140309
140688
  function toPublicSession(s3) {
@@ -140330,8 +140709,8 @@ function stripAnsi(str) {
140330
140709
  // src/pty-manager.ts
140331
140710
  var import_headless2 = __toESM(require_xterm_headless(), 1);
140332
140711
  var import_crypto8 = require("crypto");
140333
- var import_fs22 = require("fs");
140334
- var import_path18 = require("path");
140712
+ var import_fs23 = require("fs");
140713
+ var import_path19 = require("path");
140335
140714
  init_logger();
140336
140715
 
140337
140716
  // src/services/questions/detectPermissionGate.ts
@@ -140487,9 +140866,15 @@ function detectShellPrompt(lines) {
140487
140866
  ]
140488
140867
  };
140489
140868
  }
140490
- if (NUMBERED_RE.test(last.text)) {
140869
+ const lastNumberedIdx = (() => {
140870
+ for (let i = last.idx; i >= 0; i--) {
140871
+ if (NUMBERED_RE.test(lines[i])) return i;
140872
+ }
140873
+ return -1;
140874
+ })();
140875
+ if (lastNumberedIdx >= 0) {
140491
140876
  const options = [];
140492
- for (let i = 0; i <= last.idx; i++) {
140877
+ for (let i = 0; i <= lastNumberedIdx; i++) {
140493
140878
  const m2 = NUMBERED_RE.exec(lines[i]);
140494
140879
  if (!m2) continue;
140495
140880
  const num = Number.parseInt(m2[1], 10);
@@ -140517,45 +140902,15 @@ function detectShellPrompt(lines) {
140517
140902
  return null;
140518
140903
  }
140519
140904
 
140520
- // src/utils/debounce.ts
140521
- function debounce(fn, waitMs) {
140522
- let timer = null;
140523
- let lastArgs = null;
140524
- const run2 = () => {
140525
- timer = null;
140526
- if (lastArgs) {
140527
- const args = lastArgs;
140528
- lastArgs = null;
140529
- fn(...args);
140530
- }
140531
- };
140532
- const debounced = (...args) => {
140533
- lastArgs = args;
140534
- if (timer) clearTimeout(timer);
140535
- timer = setTimeout(run2, waitMs);
140536
- };
140537
- debounced.cancel = () => {
140538
- if (timer) clearTimeout(timer);
140539
- timer = null;
140540
- lastArgs = null;
140541
- };
140542
- debounced.flush = () => {
140543
- if (timer) {
140544
- clearTimeout(timer);
140545
- run2();
140546
- }
140547
- };
140548
- return debounced;
140549
- }
140550
-
140551
140905
  // src/pty-manager.ts
140552
140906
  var OUTPUT_BUFFER_MAX2 = 65536;
140907
+ var INPUT_HISTORY_MAX2 = 50;
140553
140908
  var PTY_COLS2 = 120;
140554
140909
  var PTY_ROWS2 = 40;
140555
140910
  var SCREEN_SCROLLBACK2 = 1e3;
140556
140911
  var CLAUDE_PROMPT_MARKERS = ["\u256D", "\u276F"];
140557
140912
  var PROMPT_MARKER_FALLBACK_MS = 1e4;
140558
- var QUIET_DETECT_MS = 500;
140913
+ var QUIET_DETECT_MS2 = 500;
140559
140914
  function buildPasteBytes(input) {
140560
140915
  return `\x1B[200~${input}\x1B[201~`;
140561
140916
  }
@@ -140608,6 +140963,7 @@ var PTYManager = class {
140608
140963
  onPermissionChange;
140609
140964
  onLiveQuestion;
140610
140965
  onLiveQuestionGone;
140966
+ onUserMessage;
140611
140967
  // Per-session permission-gate state. True between an OSC 777 (gate open) and
140612
140968
  // the next prompt-ready without a fresh 777 (gate closed). Prevents
140613
140969
  // re-broadcasting open/close on every chunk.
@@ -140653,6 +141009,7 @@ var PTYManager = class {
140653
141009
  this.onPermissionChange = options.onPermissionChange;
140654
141010
  this.onLiveQuestion = options.onLiveQuestion;
140655
141011
  this.onLiveQuestionGone = options.onLiveQuestionGone;
141012
+ this.onUserMessage = options.onUserMessage;
140656
141013
  this.log = options.logger ?? getLogger("pty");
140657
141014
  }
140658
141015
  // Resume an existing Claude conversation. sessionId is the JSONL UUID.
@@ -140683,7 +141040,7 @@ var PTYManager = class {
140683
141040
  }
140684
141041
  async doStart(sessionId, options) {
140685
141042
  const nodePty = await loadPty2();
140686
- const projectName = options.projectName ?? (0, import_path18.basename)(options.projectPath);
141043
+ const projectName = options.projectName ?? (0, import_path19.basename)(options.projectPath);
140687
141044
  const proc = nodePty.spawn(
140688
141045
  resolveClaudeExe(),
140689
141046
  [
@@ -140715,7 +141072,8 @@ var PTYManager = class {
140715
141072
  lastOutput: "",
140716
141073
  process: proc,
140717
141074
  outputBuffer: Buffer.alloc(0),
140718
- screen: createScreen2()
141075
+ screen: createScreen2(),
141076
+ inputHistory: []
140719
141077
  };
140720
141078
  this.sessions.set(sessionId, session);
140721
141079
  this.pendingReady.add(sessionId);
@@ -140734,7 +141092,7 @@ var PTYManager = class {
140734
141092
  async startFresh(options) {
140735
141093
  const nodePty = await loadPty2();
140736
141094
  const sessionId = (0, import_crypto8.randomUUID)();
140737
- const projectName = options.projectName ?? (0, import_path18.basename)(options.projectPath);
141095
+ const projectName = options.projectName ?? (0, import_path19.basename)(options.projectPath);
140738
141096
  const args = [
140739
141097
  "--permission-mode",
140740
141098
  options.permissionMode ?? "acceptEdits",
@@ -140766,7 +141124,8 @@ var PTYManager = class {
140766
141124
  lastOutput: "",
140767
141125
  process: proc,
140768
141126
  outputBuffer: Buffer.alloc(0),
140769
- screen: createScreen2()
141127
+ screen: createScreen2(),
141128
+ inputHistory: []
140770
141129
  };
140771
141130
  this.sessions.set(sessionId, session);
140772
141131
  this.pendingReady.add(sessionId);
@@ -140846,6 +141205,7 @@ var PTYManager = class {
140846
141205
  // step gives the TUI as many extra ticks as it needs, capped at
140847
141206
  // SUBMIT_MAX_WAIT_MS so a silent/wedged PTY still gets its \r eventually.
140848
141207
  writeSubmit(sessionId, session, input, path2, promptCount) {
141208
+ this.recordUserMessage(session, input);
140849
141209
  const pasteBytes = buildPasteBytes(input);
140850
141210
  this.log.info(
140851
141211
  `[pty.input.write] ${sessionId.slice(0, 8)} promptCount=${promptCount} bytes=${pasteBytes.length} digest=${digestBytes2(pasteBytes)}`,
@@ -140976,6 +141336,20 @@ var PTYManager = class {
140976
141336
  }
140977
141337
  return lines.slice(-maxLines);
140978
141338
  }
141339
+ getInputHistory(sessionId) {
141340
+ return this.sessions.get(sessionId)?.inputHistory ?? [];
141341
+ }
141342
+ // Record a submitted user message as ground truth and fire onUserMessage.
141343
+ // Called from writeSubmit (both direct and flush paths) — never from
141344
+ // sendKeys, so raw keystrokes aren't logged as messages.
141345
+ recordUserMessage(session, text) {
141346
+ const ts2 = Date.now();
141347
+ session.inputHistory.push({ text, ts: ts2 });
141348
+ if (session.inputHistory.length > INPUT_HISTORY_MAX2) {
141349
+ session.inputHistory.shift();
141350
+ }
141351
+ this.onUserMessage?.(session.id, text, ts2);
141352
+ }
140979
141353
  getSession(sessionId) {
140980
141354
  const session = this.sessions.get(sessionId);
140981
141355
  return session ? toPublicSession2(session) : null;
@@ -141055,7 +141429,7 @@ var PTYManager = class {
141055
141429
  });
141056
141430
  let quiet = this.quietCheckers.get(sessionId);
141057
141431
  if (!quiet) {
141058
- quiet = debounce(() => this.handleQuiet(sessionId), QUIET_DETECT_MS);
141432
+ quiet = debounce(() => this.handleQuiet(sessionId), QUIET_DETECT_MS2);
141059
141433
  this.quietCheckers.set(sessionId, quiet);
141060
141434
  }
141061
141435
  quiet();
@@ -141178,7 +141552,7 @@ var PTYManager = class {
141178
141552
  session.status = "idle";
141179
141553
  const elapsedMs = session.completedAt.getTime() - session.startedAt.getTime();
141180
141554
  if (exitCode !== 0 && elapsedMs < 2e3 && session.lastOutput === "") {
141181
- if (!(0, import_fs22.existsSync)(session.projectPath)) {
141555
+ if (!(0, import_fs23.existsSync)(session.projectPath)) {
141182
141556
  session.failureReason = `Project directory not found: ${session.projectPath}`;
141183
141557
  } else {
141184
141558
  session.failureReason = `Process exited immediately (code ${exitCode}). Check that the Claude binary is installed and accessible.`;
@@ -141272,6 +141646,9 @@ var LiveSessionManager = class {
141272
141646
  getOutputLines(sessionId, maxLines) {
141273
141647
  return this.runnerFor(sessionId).getOutputLines(sessionId, maxLines);
141274
141648
  }
141649
+ getInputHistory(sessionId) {
141650
+ return this.runnerFor(sessionId).getInputHistory(sessionId);
141651
+ }
141275
141652
  getSession(sessionId) {
141276
141653
  for (const runner of this.runners.values()) {
141277
141654
  const session = runner.getSession(sessionId);
@@ -141306,7 +141683,7 @@ var LiveSessionManager = class {
141306
141683
  const runner = this.runners.get(provider);
141307
141684
  if (runner) return runner;
141308
141685
  const err = new Error(
141309
- `Live ${provider} sessions are not implemented yet for ${(0, import_path19.basename)(projectPath)}`
141686
+ `Live ${provider} sessions are not implemented yet for ${(0, import_path20.basename)(projectPath)}`
141310
141687
  );
141311
141688
  err.statusCode = 501;
141312
141689
  throw err;
@@ -141372,10 +141749,10 @@ var PairTokenStore = class {
141372
141749
 
141373
141750
  // src/process-discovery.ts
141374
141751
  var import_child_process2 = require("child_process");
141375
- var import_os9 = require("os");
141376
- var import_path20 = require("path");
141752
+ var import_os10 = require("os");
141753
+ var import_path21 = require("path");
141377
141754
  async function discoverClaudeProcesses() {
141378
- if ((0, import_os9.platform)() === "win32") return discoverWindows();
141755
+ if ((0, import_os10.platform)() === "win32") return discoverWindows();
141379
141756
  return discoverUnix();
141380
141757
  }
141381
141758
  async function discoverUnix() {
@@ -141392,7 +141769,7 @@ async function discoverUnix() {
141392
141769
  return {
141393
141770
  pid,
141394
141771
  projectPath: cwd,
141395
- projectName: (0, import_path20.basename)(cwd),
141772
+ projectName: (0, import_path21.basename)(cwd),
141396
141773
  branch: await readGitBranch2(cwd),
141397
141774
  conversationId,
141398
141775
  startedAt
@@ -141414,7 +141791,7 @@ async function discoverWindows() {
141414
141791
  return {
141415
141792
  pid,
141416
141793
  projectPath: info.cwd,
141417
- projectName: (0, import_path20.basename)(info.cwd),
141794
+ projectName: (0, import_path21.basename)(info.cwd),
141418
141795
  branch: await readGitBranch2(info.cwd),
141419
141796
  conversationId: extractResumeId(info.args),
141420
141797
  startedAt: info.startedAt
@@ -141495,7 +141872,7 @@ async function getProcessInfoWindows(pid) {
141495
141872
  const startedAt = /* @__PURE__ */ new Date(`${year}-${month}-${day}T${hour}:${min}:${sec}`);
141496
141873
  if (Number.isNaN(startedAt.getTime())) return null;
141497
141874
  const exePath = parts[3] ?? "";
141498
- const cwd = exePath ? (0, import_path20.dirname)(exePath) : "";
141875
+ const cwd = exePath ? (0, import_path21.dirname)(exePath) : "";
141499
141876
  return { cwd, args, startedAt };
141500
141877
  } catch {
141501
141878
  return null;
@@ -141536,13 +141913,13 @@ function seal(plaintext, recipientPublicKeyBase64) {
141536
141913
 
141537
141914
  // node_modules/chokidar/index.js
141538
141915
  var import_node_events2 = require("events");
141539
- var import_node_fs7 = require("fs");
141916
+ var import_node_fs8 = require("fs");
141540
141917
  var import_promises16 = require("fs/promises");
141541
141918
  var sp2 = __toESM(require("path"), 1);
141542
141919
 
141543
141920
  // node_modules/readdirp/index.js
141544
141921
  var import_promises14 = require("fs/promises");
141545
- var import_node_path9 = require("path");
141922
+ var import_node_path10 = require("path");
141546
141923
  var import_node_stream2 = require("stream");
141547
141924
  var EntryTypes2 = {
141548
141925
  FILE_TYPE: "files",
@@ -141632,7 +142009,7 @@ var ReaddirpStream2 = class extends import_node_stream2.Readable {
141632
142009
  this._wantsDir = type ? DIR_TYPES2.has(type) : false;
141633
142010
  this._wantsFile = type ? FILE_TYPES2.has(type) : false;
141634
142011
  this._wantsEverything = type === EntryTypes2.EVERYTHING_TYPE;
141635
- this._root = (0, import_node_path9.resolve)(root);
142012
+ this._root = (0, import_node_path10.resolve)(root);
141636
142013
  this._isDirent = !opts.alwaysStat;
141637
142014
  this._statsProp = this._isDirent ? "dirent" : "stats";
141638
142015
  this._rdOptions = { encoding: "utf8", withFileTypes: this._isDirent };
@@ -141703,8 +142080,8 @@ var ReaddirpStream2 = class extends import_node_stream2.Readable {
141703
142080
  let entry;
141704
142081
  const basename12 = this._isDirent ? dirent.name : dirent;
141705
142082
  try {
141706
- const fullPath = (0, import_node_path9.resolve)((0, import_node_path9.join)(path2, basename12));
141707
- entry = { path: (0, import_node_path9.relative)(this._root, fullPath), fullPath, basename: basename12 };
142083
+ const fullPath = (0, import_node_path10.resolve)((0, import_node_path10.join)(path2, basename12));
142084
+ entry = { path: (0, import_node_path10.relative)(this._root, fullPath), fullPath, basename: basename12 };
141708
142085
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
141709
142086
  } catch (err) {
141710
142087
  this._onError(err);
@@ -141738,7 +142115,7 @@ var ReaddirpStream2 = class extends import_node_stream2.Readable {
141738
142115
  }
141739
142116
  if (entryRealPathStats.isDirectory()) {
141740
142117
  const len = entryRealPath.length;
141741
- if (full.startsWith(entryRealPath) && full.substr(len, 1) === import_node_path9.sep) {
142118
+ if (full.startsWith(entryRealPath) && full.substr(len, 1) === import_node_path10.sep) {
141742
142119
  const recursiveError = new Error(`Circular symlink detected: "${full}" points to "${entryRealPath}"`);
141743
142120
  recursiveError.code = RECURSIVE_ERROR_CODE2;
141744
142121
  return this._onError(recursiveError);
@@ -141774,7 +142151,7 @@ function readdirp2(root, options = {}) {
141774
142151
  }
141775
142152
 
141776
142153
  // node_modules/chokidar/handler.js
141777
- var import_node_fs6 = require("fs");
142154
+ var import_node_fs7 = require("fs");
141778
142155
  var import_promises15 = require("fs/promises");
141779
142156
  var import_node_os3 = require("os");
141780
142157
  var sp = __toESM(require("path"), 1);
@@ -142112,7 +142489,7 @@ function createFsWatchInstance2(path2, options, listener, errHandler, emitRaw) {
142112
142489
  }
142113
142490
  };
142114
142491
  try {
142115
- return (0, import_node_fs6.watch)(path2, {
142492
+ return (0, import_node_fs7.watch)(path2, {
142116
142493
  persistent: options.persistent
142117
142494
  }, handleEvent);
142118
142495
  } catch (error51) {
@@ -142195,7 +142572,7 @@ var setFsWatchFileListener2 = (path2, fullPath, options, handlers) => {
142195
142572
  let cont = FsWatchFileInstances2.get(fullPath);
142196
142573
  const copts = cont && cont.options;
142197
142574
  if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {
142198
- (0, import_node_fs6.unwatchFile)(fullPath);
142575
+ (0, import_node_fs7.unwatchFile)(fullPath);
142199
142576
  cont = void 0;
142200
142577
  }
142201
142578
  if (cont) {
@@ -142206,7 +142583,7 @@ var setFsWatchFileListener2 = (path2, fullPath, options, handlers) => {
142206
142583
  listeners: listener,
142207
142584
  rawEmitters: rawEmitter,
142208
142585
  options,
142209
- watcher: (0, import_node_fs6.watchFile)(fullPath, options, (curr, prev) => {
142586
+ watcher: (0, import_node_fs7.watchFile)(fullPath, options, (curr, prev) => {
142210
142587
  foreach2(cont.rawEmitters, (rawEmitter2) => {
142211
142588
  rawEmitter2(EV2.CHANGE, fullPath, { curr, prev });
142212
142589
  });
@@ -142223,7 +142600,7 @@ var setFsWatchFileListener2 = (path2, fullPath, options, handlers) => {
142223
142600
  delFromSet2(cont, KEY_RAW2, rawEmitter);
142224
142601
  if (isEmptySet2(cont.listeners)) {
142225
142602
  FsWatchFileInstances2.delete(fullPath);
142226
- (0, import_node_fs6.unwatchFile)(fullPath);
142603
+ (0, import_node_fs7.unwatchFile)(fullPath);
142227
142604
  cont.options = cont.watcher = void 0;
142228
142605
  Object.freeze(cont);
142229
142606
  }
@@ -142279,9 +142656,9 @@ var NodeFsHandler2 = class {
142279
142656
  if (this.fsw.closed) {
142280
142657
  return;
142281
142658
  }
142282
- const dirname17 = sp.dirname(file2);
142659
+ const dirname18 = sp.dirname(file2);
142283
142660
  const basename12 = sp.basename(file2);
142284
- const parent = this.fsw._getWatchedDir(dirname17);
142661
+ const parent = this.fsw._getWatchedDir(dirname18);
142285
142662
  let prevStats = stats;
142286
142663
  if (parent.has(basename12))
142287
142664
  return;
@@ -142308,7 +142685,7 @@ var NodeFsHandler2 = class {
142308
142685
  prevStats = newStats2;
142309
142686
  }
142310
142687
  } catch (error51) {
142311
- this.fsw._remove(dirname17, basename12);
142688
+ this.fsw._remove(dirname18, basename12);
142312
142689
  }
142313
142690
  } else if (parent.has(basename12)) {
142314
142691
  const at2 = newStats.atimeMs;
@@ -143093,7 +143470,7 @@ var FSWatcher2 = class extends import_node_events2.EventEmitter {
143093
143470
  const now = /* @__PURE__ */ new Date();
143094
143471
  const writes = this._pendingWrites;
143095
143472
  function awaitWriteFinishFn(prevStat) {
143096
- (0, import_node_fs7.stat)(fullPath, (err, curStat) => {
143473
+ (0, import_node_fs8.stat)(fullPath, (err, curStat) => {
143097
143474
  if (err || !writes.has(path2)) {
143098
143475
  if (err && err.code !== "ENOENT")
143099
143476
  awfEmit(err);
@@ -143267,7 +143644,7 @@ function watch2(paths, options = {}) {
143267
143644
  var chokidar_default = { watch: watch2, FSWatcher: FSWatcher2 };
143268
143645
 
143269
143646
  // src/services/conversations/conversationWatcher.ts
143270
- var import_fs23 = require("fs");
143647
+ var import_fs24 = require("fs");
143271
143648
  var import_promises17 = require("fs/promises");
143272
143649
  var ConversationWatcher = class {
143273
143650
  files = /* @__PURE__ */ new Map();
@@ -143290,7 +143667,7 @@ var ConversationWatcher = class {
143290
143667
  if (this.files.has(filePath)) return;
143291
143668
  let offset;
143292
143669
  try {
143293
- offset = (0, import_fs23.statSync)(filePath).size;
143670
+ offset = (0, import_fs24.statSync)(filePath).size;
143294
143671
  } catch {
143295
143672
  offset = 0;
143296
143673
  }
@@ -143465,14 +143842,14 @@ function findSearchTarget(messages, query) {
143465
143842
  }
143466
143843
 
143467
143844
  // src/services/conversations/pruneAgentConversations.ts
143468
- var import_fs24 = require("fs");
143845
+ var import_fs25 = require("fs");
143469
143846
  function pruneAgentConversations(cache) {
143470
143847
  const db = cache.getDatabase();
143471
143848
  const rows = db.prepare("SELECT id, file_path FROM conversation_meta").all();
143472
143849
  let pruned = 0;
143473
143850
  let missing = 0;
143474
143851
  for (const row of rows) {
143475
- if (!(0, import_fs24.existsSync)(row.file_path)) {
143852
+ if (!(0, import_fs25.existsSync)(row.file_path)) {
143476
143853
  missing += 1;
143477
143854
  continue;
143478
143855
  }
@@ -143495,13 +143872,6 @@ function deriveProjectChatTitle(input) {
143495
143872
  return `Untitled \xB7 ${input.id.slice(0, 8)}`;
143496
143873
  }
143497
143874
 
143498
- // src/services/questions/permissionAnswerKeys.ts
143499
- var ANSWER_KEYS_ALLOWLIST = /^(?:\r|[yn]\r|\x03|\d+\r)$/;
143500
- function sanitizeAnswerKeys(keys) {
143501
- if (keys === void 0) return void 0;
143502
- return ANSWER_KEYS_ALLOWLIST.test(keys) ? keys : void 0;
143503
- }
143504
-
143505
143875
  // src/services/questions/detectAskUserQuestion.ts
143506
143876
  function normalizeContent2(raw2) {
143507
143877
  if (Array.isArray(raw2)) return raw2;
@@ -143841,7 +144211,7 @@ function discoveredToResponse(d, conversationId) {
143841
144211
  var import_crypto10 = require("crypto");
143842
144212
  var import_promises18 = require("fs/promises");
143843
144213
  var import_heic_convert = __toESM(require_heic_convert(), 1);
143844
- var import_path21 = require("path");
144214
+ var import_path22 = require("path");
143845
144215
  var UPLOAD_DIR_NAME = ".threadbase-uploads";
143846
144216
  var MAX_BYTES = 25 * 1024 * 1024;
143847
144217
  var HEIC_MIMES = /* @__PURE__ */ new Set(["image/heic", "image/heif"]);
@@ -143874,9 +144244,9 @@ async function saveUploadFile(input) {
143874
144244
  }
143875
144245
  const id = `up_${(0, import_crypto10.randomBytes)(8).toString("hex")}`;
143876
144246
  const safeName = sanitizeFilename(originalName) || `file${MIME_TO_EXT[mimeType] ?? ""}`;
143877
- const dir = (0, import_path21.join)(input.projectPath, UPLOAD_DIR_NAME, input.sessionId);
144247
+ const dir = (0, import_path22.join)(input.projectPath, UPLOAD_DIR_NAME, input.sessionId);
143878
144248
  await (0, import_promises18.mkdir)(dir, { recursive: true });
143879
- const filePath = (0, import_path21.join)(dir, `${Date.now()}-${id}-${safeName}`);
144249
+ const filePath = (0, import_path22.join)(dir, `${Date.now()}-${id}-${safeName}`);
143880
144250
  await (0, import_promises18.writeFile)(filePath, buffer);
143881
144251
  return {
143882
144252
  id,
@@ -144344,10 +144714,8 @@ var WSHub = class {
144344
144714
  var BROWSE_SYSTEM_PROMPT = (browseRoot) => `You are working within the project boundary: ${browseRoot}. Do not read, write, or execute commands that access files or directories outside this boundary.`;
144345
144715
  var DEFAULT_SYSTEM_PROMPT = "When presenting options or choices to the user, limit the options to at most 3.";
144346
144716
  var DEFAULT_PTY_GRACE_PERIOD_MS = 27e4;
144347
- var DEFAULT_WS_AUTH_TIMEOUT_MS = 5e3;
144348
- var WS_CLOSE_UNAUTHORIZED = 4401;
144349
144717
  var REFRESH_TTL_MS = 2e3;
144350
- var START_READY_TIMEOUT_MS = 15e3;
144718
+ var START_READY_TIMEOUT_MS = 1e4;
144351
144719
  function parseIncludeAgentsEnv(raw2) {
144352
144720
  if (raw2 === void 0) return false;
144353
144721
  const v2 = raw2.trim().toLowerCase();
@@ -144436,14 +144804,6 @@ var StreamerServer = class {
144436
144804
  clientIdToWs = /* @__PURE__ */ new Map();
144437
144805
  // Reverse map for cleanup on close
144438
144806
  wsToClientId = /* @__PURE__ */ new Map();
144439
- // M1 — WS auth. Sockets that have authenticated (via ?key= at upgrade OR a
144440
- // { type: "auth", token } first message). Only authed sockets are added to
144441
- // the hub and receive broadcasts.
144442
- // Plan: https://github.com/RonenMars/threadbase-streamer/blob/a251353bfa417bd48ce3f15086bc336a2c622629/docs/plans/2026-06-24-security-hardening.md#L40
144443
- wsAuthed = /* @__PURE__ */ new Set();
144444
- // Keyless sockets awaiting their first-message auth handshake → close timer.
144445
- wsAuthPending = /* @__PURE__ */ new Map();
144446
- wsAuthTimeoutMs;
144447
144807
  cache = null;
144448
144808
  projectsRepo = null;
144449
144809
  conversationsRepo = null;
@@ -144481,12 +144841,11 @@ var StreamerServer = class {
144481
144841
  this.disableDb = config2.disableDb ?? false;
144482
144842
  this.scannerPersistenceDisabled = config2.scannerPersistent === false;
144483
144843
  this.scanProfiles = config2.scanProfiles;
144484
- this.codexRoots = config2.codexRoots ?? [(0, import_path22.join)((0, import_os10.homedir)(), ".codex", "sessions")];
144844
+ this.codexRoots = config2.codexRoots ?? [(0, import_path23.join)((0, import_os11.homedir)(), ".codex", "sessions")];
144485
144845
  this.ptyGracePeriodMs = config2.ptyGracePeriodMs ?? DEFAULT_PTY_GRACE_PERIOD_MS;
144486
- this.wsAuthTimeoutMs = config2.wsAuthTimeoutMs ?? DEFAULT_WS_AUTH_TIMEOUT_MS;
144487
144846
  this.defaultSystemPrompt = config2.defaultSystemPrompt ?? DEFAULT_SYSTEM_PROMPT;
144488
144847
  this.defaultPermissionMode = config2.defaultPermissionMode ?? loadDefaultPermissionMode() ?? "acceptEdits";
144489
- this.cacheDir = config2.cacheDir ?? loadCacheDir() ?? (0, import_path22.join)((0, import_os10.homedir)(), ".threadbase", "cache");
144848
+ this.cacheDir = config2.cacheDir ?? loadCacheDir() ?? (0, import_path23.join)((0, import_os11.homedir)(), ".threadbase", "cache");
144490
144849
  this.tailSize = config2.tailSize ?? loadTailSize() ?? 10;
144491
144850
  this.directoryDebounceMs = parseDirScanDebounceEnv(process.env.THREADBASE_DIR_SCAN_DEBOUNCE_MS) ?? config2.directoryScanDebounceMs ?? 1e3;
144492
144851
  this.markScannerStaleDebounced = debounce(() => {
@@ -144527,7 +144886,7 @@ var StreamerServer = class {
144527
144886
  const seqs = cache.extendMessageIndex(
144528
144887
  filePath,
144529
144888
  spans,
144530
- (0, import_fs25.statSync)(filePath),
144889
+ (0, import_fs26.statSync)(filePath),
144531
144890
  readFrom,
144532
144891
  endOffset
144533
144892
  );
@@ -144612,6 +144971,9 @@ var StreamerServer = class {
144612
144971
  onOutput: (sessionId, data) => {
144613
144972
  this.wsHub.broadcast({ type: "terminal_output", sessionId, data });
144614
144973
  },
144974
+ onUserMessage: (sessionId, text, ts2) => {
144975
+ this.wsHub.broadcast({ type: "user_message", sessionId, text, ts: ts2 });
144976
+ },
144615
144977
  onPermissionChange: (sessionId, gate) => {
144616
144978
  this.handlePermissionChange(sessionId, gate);
144617
144979
  },
@@ -144688,7 +145050,7 @@ var StreamerServer = class {
144688
145050
  temporalClient,
144689
145051
  taskQueue: agentConfig.temporal.taskQueue
144690
145052
  });
144691
- const conversationsBaseDir = agentConfig.conversationsDir || (0, import_path22.join)((0, import_path22.dirname)(this.cacheDir), "conversations");
145053
+ const conversationsBaseDir = agentConfig.conversationsDir || (0, import_path23.join)((0, import_path23.dirname)(this.cacheDir), "conversations");
144692
145054
  conversationWriter = createConversationWriter({
144693
145055
  baseDir: conversationsBaseDir
144694
145056
  });
@@ -144741,39 +145103,17 @@ var StreamerServer = class {
144741
145103
  handlePairExchange: (req, res) => this.handlePairExchange(req, res),
144742
145104
  handleBrowse: (url2, res) => this.handleBrowse(url2, res),
144743
145105
  handleMkdir: (req, res) => this.handleMkdir(req, res),
144744
- handleWsOpen: (ws2, preAuthed) => {
144745
- if (preAuthed) {
144746
- this.completeWsAuth(ws2);
144747
- return;
145106
+ handleWsOpen: (ws2) => {
145107
+ this.wsHub.addClient(ws2);
145108
+ const sessions = this.sessionStore.list(this.ptyAttachedIds());
145109
+ ws2.send(JSON.stringify({ type: "session_list", sessions }));
145110
+ if (this.cacheReady) {
145111
+ ws2.send(JSON.stringify({ type: "cache_ready" }));
144748
145112
  }
144749
- const timer = setTimeout(() => {
144750
- this.wsAuthPending.delete(ws2);
144751
- try {
144752
- ws2.close(WS_CLOSE_UNAUTHORIZED, "auth timeout");
144753
- } catch {
144754
- }
144755
- }, this.wsAuthTimeoutMs);
144756
- this.wsAuthPending.set(ws2, timer);
144757
145113
  },
144758
145114
  handleWsMessage: async (ws2, raw2) => {
144759
145115
  try {
144760
145116
  const msg = JSON.parse(String(raw2));
144761
- if (!this.wsAuthed.has(ws2)) {
144762
- if (msg.type === "auth" && typeof msg.token === "string") {
144763
- const t = this.wsAuthPending.get(ws2);
144764
- if (t) clearTimeout(t);
144765
- this.wsAuthPending.delete(ws2);
144766
- if (validateApiKey(msg.token, this.apiKey)) {
144767
- this.completeWsAuth(ws2);
144768
- } else {
144769
- try {
144770
- ws2.close(WS_CLOSE_UNAUTHORIZED, "unauthorized");
144771
- } catch {
144772
- }
144773
- }
144774
- }
144775
- return;
144776
- }
144777
145117
  if (msg.type === "register" && typeof msg.clientId === "string") {
144778
145118
  const oldClientId = this.wsToClientId.get(ws2);
144779
145119
  if (oldClientId) this.clientIdToWs.delete(oldClientId);
@@ -144784,24 +145124,56 @@ var StreamerServer = class {
144784
145124
  this.addSessionSubscriber(msg.sessionId, ws2);
144785
145125
  if (this.ptyManager.hasSession(msg.sessionId)) {
144786
145126
  const lines = await this.ptyManager.getOutputLines(msg.sessionId, 200);
144787
- ws2.send(JSON.stringify({ type: "terminal_replay", sessionId: msg.sessionId, lines }));
145127
+ const userMessages = this.ptyManager.getInputHistory(msg.sessionId);
145128
+ ws2.send(
145129
+ JSON.stringify({
145130
+ type: "terminal_replay",
145131
+ sessionId: msg.sessionId,
145132
+ lines,
145133
+ userMessages
145134
+ })
145135
+ );
145136
+ }
145137
+ const pendingGate = this.pendingPermission.get(msg.sessionId);
145138
+ if (pendingGate) {
145139
+ this.log.info(`[ws.replay_permission] ${msg.sessionId.slice(0, 8)}`, {
145140
+ event: "ws.replay_permission",
145141
+ sessionId: msg.sessionId
145142
+ });
145143
+ ws2.send(
145144
+ JSON.stringify({
145145
+ type: "permission",
145146
+ sessionId: msg.sessionId,
145147
+ ...pendingGate.prompt ? { prompt: pendingGate.prompt } : {},
145148
+ ...pendingGate.detail ? { detail: pendingGate.detail } : {},
145149
+ options: pendingGate.options,
145150
+ ...pendingGate.cursor !== void 0 ? { cursor: pendingGate.cursor } : {}
145151
+ })
145152
+ );
145153
+ }
145154
+ const pendingQuestion = this.pendingQuestions.get(msg.sessionId);
145155
+ if (pendingQuestion) {
145156
+ this.log.info(`[ws.replay_question] ${msg.sessionId.slice(0, 8)}`, {
145157
+ event: "ws.replay_question",
145158
+ sessionId: msg.sessionId
145159
+ });
145160
+ ws2.send(
145161
+ JSON.stringify({
145162
+ type: "question",
145163
+ sessionId: msg.sessionId,
145164
+ toolUseId: pendingQuestion.toolUseId,
145165
+ questions: pendingQuestion.questions
145166
+ })
145167
+ );
144788
145168
  }
144789
145169
  }
144790
145170
  if (msg.type === "hold_session" && typeof msg.sessionId === "string") {
144791
- if (this.sessionSubscribers.get(msg.sessionId)?.has(ws2)) {
144792
- this.startGraceTimer(msg.sessionId, 0);
144793
- }
145171
+ this.startGraceTimer(msg.sessionId, 0);
144794
145172
  }
144795
145173
  } catch {
144796
145174
  }
144797
145175
  },
144798
145176
  handleWsClose: (ws2) => {
144799
- const pendingTimer = this.wsAuthPending.get(ws2);
144800
- if (pendingTimer) {
144801
- clearTimeout(pendingTimer);
144802
- this.wsAuthPending.delete(ws2);
144803
- }
144804
- this.wsAuthed.delete(ws2);
144805
145177
  const clientId = this.wsToClientId.get(ws2);
144806
145178
  if (clientId) {
144807
145179
  this.clientIdToWs.delete(clientId);
@@ -144871,20 +145243,6 @@ var StreamerServer = class {
144871
145243
  this.wsHub.broadcast(payload);
144872
145244
  }
144873
145245
  }
144874
- // M1: finalize a WebSocket auth (via ?key= at upgrade or a first-message
144875
- // handshake) — register it with the hub and send the initial snapshot. Only
144876
- // authed sockets reach this, so no unauthenticated client ever receives a
144877
- // broadcast.
144878
- // Plan: https://github.com/RonenMars/threadbase-streamer/blob/a251353bfa417bd48ce3f15086bc336a2c622629/docs/plans/2026-06-24-security-hardening.md#L40
144879
- completeWsAuth(ws2) {
144880
- this.wsAuthed.add(ws2);
144881
- this.wsHub.addClient(ws2);
144882
- const sessions = this.sessionStore.list(this.ptyAttachedIds());
144883
- ws2.send(JSON.stringify({ type: "session_list", sessions }));
144884
- if (this.cacheReady) {
144885
- ws2.send(JSON.stringify({ type: "cache_ready" }));
144886
- }
144887
- }
144888
145246
  addSessionSubscriber(sessionId, ws2) {
144889
145247
  let subs = this.sessionSubscribers.get(sessionId);
144890
145248
  if (!subs) {
@@ -144956,7 +145314,7 @@ var StreamerServer = class {
144956
145314
  });
144957
145315
  try {
144958
145316
  this.cache = ConversationCache.open(
144959
- (0, import_path22.join)(this.cacheDir, "cache.db"),
145317
+ (0, import_path23.join)(this.cacheDir, "cache.db"),
144960
145318
  this.tailSize,
144961
145319
  void 0,
144962
145320
  {
@@ -144982,11 +145340,11 @@ var StreamerServer = class {
144982
145340
  if (this.scanProfiles && this.scanProfiles.length > 0) {
144983
145341
  for (const profile of this.scanProfiles) {
144984
145342
  if (profile.enabled) {
144985
- this.fileWatcher.watchDirectory((0, import_path22.join)(profile.configDir, "projects"));
145343
+ this.fileWatcher.watchDirectory((0, import_path23.join)(profile.configDir, "projects"));
144986
145344
  }
144987
145345
  }
144988
145346
  } else {
144989
- this.fileWatcher.watchDirectory((0, import_path22.join)((0, import_os10.homedir)(), ".claude", "projects"));
145347
+ this.fileWatcher.watchDirectory((0, import_path23.join)((0, import_os11.homedir)(), ".claude", "projects"));
144990
145348
  }
144991
145349
  } catch (err) {
144992
145350
  const message = err instanceof Error ? err.message : String(err);
@@ -145171,9 +145529,6 @@ var StreamerServer = class {
145171
145529
  this.ptyManager.dispose();
145172
145530
  this.fileWatcher.dispose();
145173
145531
  this.wsHub.dispose();
145174
- for (const timer of this.wsAuthPending.values()) clearTimeout(timer);
145175
- this.wsAuthPending.clear();
145176
- this.wsAuthed.clear();
145177
145532
  this.pairTokens.dispose();
145178
145533
  if (this.dbPool) {
145179
145534
  await this.dbPool.end();
@@ -145571,17 +145926,17 @@ var StreamerServer = class {
145571
145926
  return scanner;
145572
145927
  }
145573
145928
  findJsonlPath(uuid3) {
145574
- const projectsDir = (0, import_path22.join)((0, import_os10.homedir)(), ".claude", "projects");
145575
- if (!(0, import_fs25.existsSync)(projectsDir)) return null;
145929
+ const projectsDir = (0, import_path23.join)((0, import_os11.homedir)(), ".claude", "projects");
145930
+ if (!(0, import_fs26.existsSync)(projectsDir)) return null;
145576
145931
  const filename = `${uuid3}.jsonl`;
145577
- for (const dir of (0, import_fs25.readdirSync)(projectsDir)) {
145578
- const fp = (0, import_path22.join)(projectsDir, dir, filename);
145579
- if ((0, import_fs25.existsSync)(fp)) return fp;
145580
- const projectDir = (0, import_path22.join)(projectsDir, dir);
145932
+ for (const dir of (0, import_fs26.readdirSync)(projectsDir)) {
145933
+ const fp = (0, import_path23.join)(projectsDir, dir, filename);
145934
+ if ((0, import_fs26.existsSync)(fp)) return fp;
145935
+ const projectDir = (0, import_path23.join)(projectsDir, dir);
145581
145936
  try {
145582
- for (const sub of (0, import_fs25.readdirSync)(projectDir)) {
145583
- const subagentPath = (0, import_path22.join)(projectDir, sub, "subagents", filename);
145584
- if ((0, import_fs25.existsSync)(subagentPath)) return subagentPath;
145937
+ for (const sub of (0, import_fs26.readdirSync)(projectDir)) {
145938
+ const subagentPath = (0, import_path23.join)(projectDir, sub, "subagents", filename);
145939
+ if ((0, import_fs26.existsSync)(subagentPath)) return subagentPath;
145585
145940
  }
145586
145941
  } catch {
145587
145942
  }
@@ -145590,7 +145945,7 @@ var StreamerServer = class {
145590
145945
  }
145591
145946
  async readCwdFromJsonl(filePath) {
145592
145947
  return new Promise((resolve6) => {
145593
- const rl = (0, import_readline4.createInterface)({ input: (0, import_fs25.createReadStream)(filePath), crlfDelay: Infinity });
145948
+ const rl = (0, import_readline4.createInterface)({ input: (0, import_fs26.createReadStream)(filePath), crlfDelay: Infinity });
145594
145949
  let found = false;
145595
145950
  rl.on("line", (line) => {
145596
145951
  if (found) return;
@@ -145728,7 +146083,7 @@ var StreamerServer = class {
145728
146083
  if (!conv.filePath) return false;
145729
146084
  let mtimeMs = null;
145730
146085
  try {
145731
- mtimeMs = (0, import_fs25.statSync)(conv.filePath).mtimeMs;
146086
+ mtimeMs = (0, import_fs26.statSync)(conv.filePath).mtimeMs;
145732
146087
  } catch {
145733
146088
  return false;
145734
146089
  }
@@ -146096,7 +146451,7 @@ var StreamerServer = class {
146096
146451
  handleGetSession(sessionId, res) {
146097
146452
  const session = this.sessionStore.get(sessionId, this.ptyAttachedIds());
146098
146453
  if (session) {
146099
- if (!(0, import_fs25.existsSync)(session.projectPath)) {
146454
+ if (!(0, import_fs26.existsSync)(session.projectPath)) {
146100
146455
  session.failureReason = `Project directory not found: ${session.projectPath}`;
146101
146456
  }
146102
146457
  json2(res, 200, session);
@@ -146300,16 +146655,17 @@ var StreamerServer = class {
146300
146655
  return;
146301
146656
  }
146302
146657
  this.pendingPermission.set(sessionId, gate);
146303
- const safeOptions = gate.options.map((o) => {
146304
- const answerKeys = sanitizeAnswerKeys(o.answerKeys);
146305
- return answerKeys === void 0 ? { index: o.index, label: o.label } : { ...o, answerKeys };
146306
- });
146658
+ const subscriberCount = this.sessionSubscribers.get(sessionId)?.size ?? 0;
146659
+ this.log.info(
146660
+ `[ws.broadcast_permission] ${sessionId.slice(0, 8)} subscribers=${subscriberCount}`,
146661
+ { event: "ws.broadcast_permission", sessionId, subscriberCount }
146662
+ );
146307
146663
  this.wsHub.broadcast({
146308
146664
  type: "permission",
146309
146665
  sessionId,
146310
146666
  ...gate.prompt ? { prompt: gate.prompt } : {},
146311
146667
  ...gate.detail ? { detail: gate.detail } : {},
146312
- options: safeOptions,
146668
+ options: gate.options,
146313
146669
  ...gate.cursor !== void 0 ? { cursor: gate.cursor } : {}
146314
146670
  });
146315
146671
  }
@@ -146496,7 +146852,7 @@ var StreamerServer = class {
146496
146852
  sessionStore: this.sessionStore,
146497
146853
  // biome-ignore lint/style/noNonNullAssertion: agentClient is set when agentConfig.enabled is true
146498
146854
  agentClient: this.agentClient,
146499
- conversationsDir: this.cacheDir ? (0, import_path22.join)((0, import_path22.dirname)(this.cacheDir), "conversations") : "",
146855
+ conversationsDir: this.cacheDir ? (0, import_path23.join)((0, import_path23.dirname)(this.cacheDir), "conversations") : "",
146500
146856
  agentConfig: this.agentConfig
146501
146857
  });
146502
146858
  json2(res, result.status, result.body);
@@ -146637,9 +146993,9 @@ var StreamerServer = class {
146637
146993
  // was passed to Claude via --session-id so the filename matches from the start.
146638
146994
  watchForJsonl(sessionId, projectPath) {
146639
146995
  const encoded = projectPath.replace(/[/\\:.]/g, "-");
146640
- const projectsDir = (0, import_path22.join)((0, import_os10.homedir)(), ".claude", "projects", encoded);
146996
+ const projectsDir = (0, import_path23.join)((0, import_os11.homedir)(), ".claude", "projects", encoded);
146641
146997
  const expectedFile = `${sessionId}.jsonl`;
146642
- const filePath = (0, import_path22.join)(projectsDir, expectedFile);
146998
+ const filePath = (0, import_path23.join)(projectsDir, expectedFile);
146643
146999
  const deadline = Date.now() + 12e4;
146644
147000
  let watcher = null;
146645
147001
  const cleanup = () => {
@@ -146657,12 +147013,12 @@ var StreamerServer = class {
146657
147013
  cleanup();
146658
147014
  return;
146659
147015
  }
146660
- let resolvedFilePath = (0, import_fs25.existsSync)(filePath) ? filePath : null;
146661
- if (!resolvedFilePath && (0, import_fs25.existsSync)(projectsDir)) {
147016
+ let resolvedFilePath = (0, import_fs26.existsSync)(filePath) ? filePath : null;
147017
+ if (!resolvedFilePath && (0, import_fs26.existsSync)(projectsDir)) {
146662
147018
  try {
146663
147019
  const now = Date.now();
146664
- const recent = (0, import_fs25.readdirSync)(projectsDir).filter((f2) => f2.endsWith(".jsonl")).map((f2) => ({ f: f2, mtime: (0, import_fs25.statSync)((0, import_path22.join)(projectsDir, f2)).mtimeMs })).filter(({ mtime }) => now - mtime < 5e3).sort((a, b2) => b2.mtime - a.mtime)[0];
146665
- if (recent) resolvedFilePath = (0, import_path22.join)(projectsDir, recent.f);
147020
+ const recent = (0, import_fs26.readdirSync)(projectsDir).filter((f2) => f2.endsWith(".jsonl")).map((f2) => ({ f: f2, mtime: (0, import_fs26.statSync)((0, import_path23.join)(projectsDir, f2)).mtimeMs })).filter(({ mtime }) => now - mtime < 5e3).sort((a, b2) => b2.mtime - a.mtime)[0];
147021
+ if (recent) resolvedFilePath = (0, import_path23.join)(projectsDir, recent.f);
146666
147022
  } catch {
146667
147023
  }
146668
147024
  }
@@ -146671,7 +147027,7 @@ var StreamerServer = class {
146671
147027
  this.sessionFileMap.set(sessionId, resolvedFilePath);
146672
147028
  this.fileWatcher.watch(resolvedFilePath);
146673
147029
  try {
146674
- const existing = (0, import_fs25.readFileSync)(resolvedFilePath, "utf8").split("\n").filter(Boolean);
147030
+ const existing = (0, import_fs26.readFileSync)(resolvedFilePath, "utf8").split("\n").filter(Boolean);
146675
147031
  if (existing.length > 0) {
146676
147032
  this.broadcastConversationLines(sessionId, existing);
146677
147033
  }
@@ -146694,7 +147050,7 @@ var StreamerServer = class {
146694
147050
  if (this.sessionFileMap.has(sessionId)) return;
146695
147051
  try {
146696
147052
  require("fs").mkdirSync(projectsDir, { recursive: true });
146697
- watcher = (0, import_fs25.watch)(projectsDir, tryWire);
147053
+ watcher = (0, import_fs26.watch)(projectsDir, tryWire);
146698
147054
  watcher.on("error", cleanup);
146699
147055
  } catch {
146700
147056
  }
@@ -146710,7 +147066,7 @@ var StreamerServer = class {
146710
147066
  watchForCodexRollout(sessionId, projectPath) {
146711
147067
  const deadline = Date.now() + 12e4;
146712
147068
  const now = /* @__PURE__ */ new Date();
146713
- const dateDir = (0, import_path22.join)(
147069
+ const dateDir = (0, import_path23.join)(
146714
147070
  String(now.getFullYear()),
146715
147071
  String(now.getMonth() + 1).padStart(2, "0"),
146716
147072
  String(now.getDate()).padStart(2, "0")
@@ -146723,7 +147079,7 @@ var StreamerServer = class {
146723
147079
  };
146724
147080
  const matchesProjectPath = (candidatePath) => {
146725
147081
  try {
146726
- const firstLine = (0, import_fs25.readFileSync)(candidatePath, "utf8").split("\n", 1)[0];
147082
+ const firstLine = (0, import_fs26.readFileSync)(candidatePath, "utf8").split("\n", 1)[0];
146727
147083
  if (!firstLine) return null;
146728
147084
  const parsed = JSON.parse(firstLine);
146729
147085
  if (parsed?.type !== "session_meta") return null;
@@ -146751,18 +147107,18 @@ var StreamerServer = class {
146751
147107
  this.sessionStore.listManaged().filter((s3) => s3.id !== sessionId && s3.boundConversationId != null).map((s3) => s3.boundConversationId)
146752
147108
  );
146753
147109
  for (const root of this.codexRoots) {
146754
- const sessionsDir = (0, import_path22.join)(root, dateDir);
146755
- if (!(0, import_fs25.existsSync)(sessionsDir)) continue;
147110
+ const sessionsDir = (0, import_path23.join)(root, dateDir);
147111
+ if (!(0, import_fs26.existsSync)(sessionsDir)) continue;
146756
147112
  let candidateFiles;
146757
147113
  try {
146758
- candidateFiles = (0, import_fs25.readdirSync)(sessionsDir).filter((f2) => f2.endsWith(".jsonl"));
147114
+ candidateFiles = (0, import_fs26.readdirSync)(sessionsDir).filter((f2) => f2.endsWith(".jsonl"));
146759
147115
  } catch {
146760
147116
  continue;
146761
147117
  }
146762
147118
  const nowMs = Date.now();
146763
- const recentCandidates = candidateFiles.map((f2) => ({ f: f2, mtime: (0, import_fs25.statSync)((0, import_path22.join)(sessionsDir, f2)).mtimeMs })).filter(({ mtime }) => nowMs - mtime < 1e4).sort((a, b2) => b2.mtime - a.mtime);
147119
+ const recentCandidates = candidateFiles.map((f2) => ({ f: f2, mtime: (0, import_fs26.statSync)((0, import_path23.join)(sessionsDir, f2)).mtimeMs })).filter(({ mtime }) => nowMs - mtime < 1e4).sort((a, b2) => b2.mtime - a.mtime);
146764
147120
  for (const { f: f2 } of recentCandidates) {
146765
- const candidatePath = (0, import_path22.join)(sessionsDir, f2);
147121
+ const candidatePath = (0, import_path23.join)(sessionsDir, f2);
146766
147122
  const match2 = matchesProjectPath(candidatePath);
146767
147123
  if (!match2) continue;
146768
147124
  if (boundElsewhere.has(match2.id)) continue;
@@ -146772,7 +147128,7 @@ var StreamerServer = class {
146772
147128
  this.sessionFileMap.set(sessionId, candidatePath);
146773
147129
  this.fileWatcher.watch(candidatePath);
146774
147130
  try {
146775
- const existing = (0, import_fs25.readFileSync)(candidatePath, "utf8").split("\n").filter(Boolean);
147131
+ const existing = (0, import_fs26.readFileSync)(candidatePath, "utf8").split("\n").filter(Boolean);
146776
147132
  if (existing.length > 0) {
146777
147133
  this.broadcastConversationLines(sessionId, existing);
146778
147134
  }
@@ -146894,7 +147250,7 @@ var StreamerServer = class {
146894
147250
  };
146895
147251
  function classifyResumability(cwd) {
146896
147252
  if (!cwd) return { resumable: true };
146897
- if ((0, import_fs25.existsSync)(cwd)) return { resumable: true };
147253
+ if ((0, import_fs26.existsSync)(cwd)) return { resumable: true };
146898
147254
  const ranInWorktree = /\/\.worktrees\//.test(cwd) || /\/\.claude\/worktrees\//.test(cwd);
146899
147255
  return {
146900
147256
  resumable: false,
@@ -147158,7 +147514,7 @@ async function checkForUpdate(opts) {
147158
147514
  }
147159
147515
 
147160
147516
  // src/updater/install.ts
147161
- var import_node_fs19 = require("fs");
147517
+ var import_node_fs20 = require("fs");
147162
147518
 
147163
147519
  // src/updater/active-sessions.ts
147164
147520
  async function countActiveSessions(opts) {
@@ -147211,8 +147567,8 @@ function isBrewInstall(scriptPath = process.argv[1] ?? "") {
147211
147567
 
147212
147568
  // src/updater/download.ts
147213
147569
  var import_node_crypto4 = require("crypto");
147214
- var import_node_fs8 = require("fs");
147215
- var import_node_path10 = require("path");
147570
+ var import_node_fs9 = require("fs");
147571
+ var import_node_path11 = require("path");
147216
147572
  var import_promises20 = require("stream/promises");
147217
147573
 
147218
147574
  // src/updater/manifest.ts
@@ -147272,13 +147628,13 @@ async function downloadAndVerify(opts) {
147272
147628
  `Manifest references ${artifact.filename} but it is not attached to the release`
147273
147629
  );
147274
147630
  }
147275
- (0, import_node_fs8.mkdirSync)((0, import_node_path10.dirname)(targetPath), { recursive: true });
147631
+ (0, import_node_fs9.mkdirSync)((0, import_node_path11.dirname)(targetPath), { recursive: true });
147276
147632
  const res = await fetch(asset.browserDownloadUrl);
147277
147633
  if (!res.ok || !res.body) {
147278
147634
  throw new Error(`Failed to download ${artifact.filename}: ${res.status} ${res.statusText}`);
147279
147635
  }
147280
147636
  const hash2 = (0, import_node_crypto4.createHash)("sha256");
147281
- const out = (0, import_node_fs8.createWriteStream)(targetPath);
147637
+ const out = (0, import_node_fs9.createWriteStream)(targetPath);
147282
147638
  let bytes = 0;
147283
147639
  const measured = new TransformStream({
147284
147640
  transform(chunk, controller) {
@@ -147290,19 +147646,19 @@ async function downloadAndVerify(opts) {
147290
147646
  try {
147291
147647
  await (0, import_promises20.pipeline)(res.body.pipeThrough(measured), out);
147292
147648
  } catch (err) {
147293
- (0, import_node_fs8.rmSync)(targetPath, { force: true });
147649
+ (0, import_node_fs9.rmSync)(targetPath, { force: true });
147294
147650
  throw err;
147295
147651
  }
147296
147652
  const actual = hash2.digest("hex");
147297
147653
  if (actual !== artifact.sha256) {
147298
- (0, import_node_fs8.rmSync)(targetPath, { force: true });
147654
+ (0, import_node_fs9.rmSync)(targetPath, { force: true });
147299
147655
  throw new Error(
147300
147656
  `sha256 mismatch for ${artifact.filename}: expected ${artifact.sha256}, got ${actual}`
147301
147657
  );
147302
147658
  }
147303
- const stat10 = (0, import_node_fs8.statSync)(targetPath);
147659
+ const stat10 = (0, import_node_fs9.statSync)(targetPath);
147304
147660
  if (stat10.size !== artifact.size) {
147305
- (0, import_node_fs8.rmSync)(targetPath, { force: true });
147661
+ (0, import_node_fs9.rmSync)(targetPath, { force: true });
147306
147662
  throw new Error(
147307
147663
  `size mismatch for ${artifact.filename}: expected ${artifact.size}, got ${stat10.size}`
147308
147664
  );
@@ -147312,16 +147668,16 @@ async function downloadAndVerify(opts) {
147312
147668
 
147313
147669
  // src/updater/paths.ts
147314
147670
  var import_node_os4 = require("os");
147315
- var import_node_path11 = require("path");
147316
- var THREADBASE_ROOT = (0, import_node_path11.join)((0, import_node_os4.homedir)(), ".threadbase");
147317
- var RELEASES_DIR = (0, import_node_path11.join)(THREADBASE_ROOT, "releases");
147318
- var CURRENT_SYMLINK = (0, import_node_path11.join)(THREADBASE_ROOT, "current");
147319
- var DOWNLOAD_DIR = (0, import_node_path11.join)(THREADBASE_ROOT, "releases", ".tmp");
147671
+ var import_node_path12 = require("path");
147672
+ var THREADBASE_ROOT = (0, import_node_path12.join)((0, import_node_os4.homedir)(), ".threadbase");
147673
+ var RELEASES_DIR = (0, import_node_path12.join)(THREADBASE_ROOT, "releases");
147674
+ var CURRENT_SYMLINK = (0, import_node_path12.join)(THREADBASE_ROOT, "current");
147675
+ var DOWNLOAD_DIR = (0, import_node_path12.join)(THREADBASE_ROOT, "releases", ".tmp");
147320
147676
  function releaseDir(version2) {
147321
- return (0, import_node_path11.join)(RELEASES_DIR, version2);
147677
+ return (0, import_node_path12.join)(RELEASES_DIR, version2);
147322
147678
  }
147323
147679
  function downloadPath(version2, filename) {
147324
- return (0, import_node_path11.join)(DOWNLOAD_DIR, `${version2}-${filename}`);
147680
+ return (0, import_node_path12.join)(DOWNLOAD_DIR, `${version2}-${filename}`);
147325
147681
  }
147326
147682
 
147327
147683
  // src/updater/restart.ts
@@ -147402,111 +147758,124 @@ async function stopService(opts = {}) {
147402
147758
  }
147403
147759
 
147404
147760
  // src/updater/stamp-version.ts
147405
- var import_node_fs9 = require("fs");
147406
- var import_node_path12 = require("path");
147761
+ var import_node_fs10 = require("fs");
147762
+ var import_node_path13 = require("path");
147407
147763
  function stampVersionTxt(destDir, version2) {
147408
- const distDir = (0, import_node_path12.join)(destDir, "dist");
147409
- (0, import_node_fs9.mkdirSync)(distDir, { recursive: true });
147410
- (0, import_node_fs9.writeFileSync)((0, import_node_path12.join)(distDir, "version.txt"), `${version2}+update
147411
- `);
147764
+ const distDir = (0, import_node_path13.join)(destDir, "dist");
147765
+ (0, import_node_fs10.mkdirSync)(distDir, { recursive: true });
147766
+ (0, import_node_fs10.writeFileSync)((0, import_node_path13.join)(distDir, "version.txt"), versionStamp(version2));
147767
+ }
147768
+ function versionStamp(version2) {
147769
+ return `${version2}+update
147770
+ `;
147412
147771
  }
147413
147772
 
147414
147773
  // src/updater/swap.ts
147415
- var import_node_fs10 = require("fs");
147416
- var import_node_path13 = require("path");
147774
+ var import_node_fs11 = require("fs");
147775
+ var import_node_path14 = require("path");
147417
147776
  var import_semver2 = __toESM(require_semver2(), 1);
147418
147777
  var KEEP_LAST_N = 2;
147419
147778
  function swapCurrent(version2) {
147420
147779
  const target = releaseDir(version2);
147421
- if (!(0, import_node_fs10.existsSync)(target)) {
147780
+ if (!(0, import_node_fs11.existsSync)(target)) {
147422
147781
  throw new Error(`Cannot swap to ${version2}: ${target} does not exist`);
147423
147782
  }
147424
147783
  if (process.platform === "win32") {
147425
147784
  const tmp = `${CURRENT_SYMLINK}.new`;
147426
- (0, import_node_fs10.rmSync)(tmp, { recursive: true, force: true });
147427
- (0, import_node_fs10.cpSync)(target, tmp, { recursive: true });
147428
- if ((0, import_node_fs10.existsSync)(CURRENT_SYMLINK)) {
147429
- (0, import_node_fs10.rmSync)(CURRENT_SYMLINK, { recursive: true, force: true });
147430
- }
147431
- (0, import_node_fs10.renameSync)(tmp, CURRENT_SYMLINK);
147432
- (0, import_node_fs10.copyFileSync)((0, import_node_path13.join)(CURRENT_SYMLINK, "dist", "cli.cjs"), (0, import_node_path13.join)(THREADBASE_ROOT, "cli.js"));
147785
+ (0, import_node_fs11.rmSync)(tmp, { recursive: true, force: true });
147786
+ (0, import_node_fs11.cpSync)(target, tmp, { recursive: true });
147787
+ if ((0, import_node_fs11.existsSync)(CURRENT_SYMLINK)) {
147788
+ (0, import_node_fs11.rmSync)(CURRENT_SYMLINK, { recursive: true, force: true });
147789
+ }
147790
+ (0, import_node_fs11.renameSync)(tmp, CURRENT_SYMLINK);
147791
+ (0, import_node_fs11.copyFileSync)((0, import_node_path14.join)(CURRENT_SYMLINK, "dist", "cli.cjs"), (0, import_node_path14.join)(THREADBASE_ROOT, "cli.js"));
147792
+ publishVersionTxt(target, version2);
147433
147793
  return;
147434
147794
  }
147435
147795
  const tmpLink = `${CURRENT_SYMLINK}.new`;
147436
- if ((0, import_node_fs10.existsSync)(tmpLink) || lstatSafeIsSymlink(tmpLink)) {
147437
- (0, import_node_fs10.unlinkSync)(tmpLink);
147796
+ if ((0, import_node_fs11.existsSync)(tmpLink) || lstatSafeIsSymlink(tmpLink)) {
147797
+ (0, import_node_fs11.unlinkSync)(tmpLink);
147438
147798
  }
147439
- (0, import_node_fs10.symlinkSync)(target, tmpLink);
147440
- (0, import_node_fs10.renameSync)(tmpLink, CURRENT_SYMLINK);
147441
- const cliJs = (0, import_node_path13.join)(THREADBASE_ROOT, "cli.js");
147799
+ (0, import_node_fs11.symlinkSync)(target, tmpLink);
147800
+ (0, import_node_fs11.renameSync)(tmpLink, CURRENT_SYMLINK);
147801
+ const cliJs = (0, import_node_path14.join)(THREADBASE_ROOT, "cli.js");
147442
147802
  const tmpCliJs = `${cliJs}.new`;
147443
- if ((0, import_node_fs10.existsSync)(tmpCliJs) || lstatSafeIsSymlink(tmpCliJs)) (0, import_node_fs10.unlinkSync)(tmpCliJs);
147444
- (0, import_node_fs10.symlinkSync)((0, import_node_path13.join)(target, "dist", "cli.cjs"), tmpCliJs);
147445
- (0, import_node_fs10.renameSync)(tmpCliJs, cliJs);
147803
+ if ((0, import_node_fs11.existsSync)(tmpCliJs) || lstatSafeIsSymlink(tmpCliJs)) (0, import_node_fs11.unlinkSync)(tmpCliJs);
147804
+ (0, import_node_fs11.symlinkSync)((0, import_node_path14.join)(target, "dist", "cli.cjs"), tmpCliJs);
147805
+ (0, import_node_fs11.renameSync)(tmpCliJs, cliJs);
147806
+ publishVersionTxt(target, version2);
147807
+ }
147808
+ function publishVersionTxt(target, version2) {
147809
+ const dest = (0, import_node_path14.join)(THREADBASE_ROOT, "version.txt");
147810
+ try {
147811
+ (0, import_node_fs11.copyFileSync)((0, import_node_path14.join)(target, "dist", "version.txt"), dest);
147812
+ } catch {
147813
+ (0, import_node_fs11.writeFileSync)(dest, versionStamp(version2));
147814
+ }
147446
147815
  }
147447
147816
  function lstatSafeIsSymlink(path2) {
147448
147817
  try {
147449
- return (0, import_node_fs10.lstatSync)(path2).isSymbolicLink();
147818
+ return (0, import_node_fs11.lstatSync)(path2).isSymbolicLink();
147450
147819
  } catch {
147451
147820
  return false;
147452
147821
  }
147453
147822
  }
147454
147823
  function pruneOldReleases(activeVersion, keep = KEEP_LAST_N) {
147455
- if (!(0, import_node_fs10.existsSync)(RELEASES_DIR)) return [];
147456
- const entries = (0, import_node_fs10.readdirSync)(RELEASES_DIR, { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => e.name).filter((name) => import_semver2.default.valid(name) !== null);
147824
+ if (!(0, import_node_fs11.existsSync)(RELEASES_DIR)) return [];
147825
+ const entries = (0, import_node_fs11.readdirSync)(RELEASES_DIR, { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => e.name).filter((name) => import_semver2.default.valid(name) !== null);
147457
147826
  const sorted = entries.sort((a, b2) => import_semver2.default.rcompare(a, b2));
147458
147827
  const toKeep = new Set(sorted.slice(0, keep));
147459
147828
  toKeep.add(activeVersion);
147460
147829
  const removed = [];
147461
147830
  for (const name of sorted) {
147462
147831
  if (toKeep.has(name)) continue;
147463
- (0, import_node_fs10.rmSync)(releaseDir(name), { recursive: true, force: true });
147832
+ (0, import_node_fs11.rmSync)(releaseDir(name), { recursive: true, force: true });
147464
147833
  removed.push(name);
147465
147834
  }
147466
147835
  return removed;
147467
147836
  }
147468
147837
  function ensureReleasesDir() {
147469
- (0, import_node_fs10.mkdirSync)(RELEASES_DIR, { recursive: true });
147838
+ (0, import_node_fs11.mkdirSync)(RELEASES_DIR, { recursive: true });
147470
147839
  }
147471
147840
 
147472
147841
  // src/updater/unpack.ts
147473
- var import_node_fs17 = require("fs");
147842
+ var import_node_fs18 = require("fs");
147474
147843
 
147475
147844
  // node_modules/tar/dist/esm/index.min.js
147476
147845
  var import_events4 = __toESM(require("events"), 1);
147477
- var import_fs26 = __toESM(require("fs"), 1);
147846
+ var import_fs27 = __toESM(require("fs"), 1);
147478
147847
  var import_node_events3 = require("events");
147479
147848
  var import_node_stream3 = __toESM(require("stream"), 1);
147480
147849
  var import_node_string_decoder = require("string_decoder");
147481
- var import_node_path14 = __toESM(require("path"), 1);
147482
- var import_node_fs11 = __toESM(require("fs"), 1);
147483
- var import_path23 = require("path");
147850
+ var import_node_path15 = __toESM(require("path"), 1);
147851
+ var import_node_fs12 = __toESM(require("fs"), 1);
147852
+ var import_path24 = require("path");
147484
147853
  var import_events5 = require("events");
147485
147854
  var import_assert = __toESM(require("assert"), 1);
147486
147855
  var import_buffer2 = require("buffer");
147487
147856
  var Ps = __toESM(require("zlib"), 1);
147488
147857
  var import_zlib = __toESM(require("zlib"), 1);
147489
- var import_node_path15 = require("path");
147490
147858
  var import_node_path16 = require("path");
147491
- var import_fs27 = __toESM(require("fs"), 1);
147492
- var import_fs28 = __toESM(require("fs"), 1);
147493
- var import_path24 = __toESM(require("path"), 1);
147494
147859
  var import_node_path17 = require("path");
147860
+ var import_fs28 = __toESM(require("fs"), 1);
147861
+ var import_fs29 = __toESM(require("fs"), 1);
147495
147862
  var import_path25 = __toESM(require("path"), 1);
147496
- var import_node_fs12 = __toESM(require("fs"), 1);
147863
+ var import_node_path18 = require("path");
147864
+ var import_path26 = __toESM(require("path"), 1);
147865
+ var import_node_fs13 = __toESM(require("fs"), 1);
147497
147866
  var import_node_assert = __toESM(require("assert"), 1);
147498
147867
  var import_node_crypto5 = require("crypto");
147499
- var import_node_fs13 = __toESM(require("fs"), 1);
147500
- var import_node_path18 = __toESM(require("path"), 1);
147501
- var import_fs29 = __toESM(require("fs"), 1);
147502
147868
  var import_node_fs14 = __toESM(require("fs"), 1);
147503
147869
  var import_node_path19 = __toESM(require("path"), 1);
147870
+ var import_fs30 = __toESM(require("fs"), 1);
147504
147871
  var import_node_fs15 = __toESM(require("fs"), 1);
147505
- var import_promises21 = __toESM(require("fs/promises"), 1);
147506
147872
  var import_node_path20 = __toESM(require("path"), 1);
147507
- var import_node_path21 = require("path");
147508
147873
  var import_node_fs16 = __toESM(require("fs"), 1);
147509
- var import_node_path22 = __toESM(require("path"), 1);
147874
+ var import_promises21 = __toESM(require("fs/promises"), 1);
147875
+ var import_node_path21 = __toESM(require("path"), 1);
147876
+ var import_node_path22 = require("path");
147877
+ var import_node_fs17 = __toESM(require("fs"), 1);
147878
+ var import_node_path23 = __toESM(require("path"), 1);
147510
147879
  var zr = Object.defineProperty;
147511
147880
  var Ur = (s3, t) => {
147512
147881
  for (var e in t) zr(s3, e, { get: t[e], enumerable: true });
@@ -147850,7 +148219,7 @@ var A = class extends import_node_events3.EventEmitter {
147850
148219
  return Wr;
147851
148220
  }
147852
148221
  };
147853
- var Jr = import_fs26.default.writev;
148222
+ var Jr = import_fs27.default.writev;
147854
148223
  var ht = /* @__PURE__ */ Symbol("_autoClose");
147855
148224
  var H2 = /* @__PURE__ */ Symbol("_close");
147856
148225
  var te = /* @__PURE__ */ Symbol("_ended");
@@ -147905,7 +148274,7 @@ var _t = class extends A {
147905
148274
  throw new TypeError("this is a readable stream");
147906
148275
  }
147907
148276
  [at]() {
147908
- import_fs26.default.open(this[U], "r", (t, e) => this[Ht](t, e));
148277
+ import_fs27.default.open(this[U], "r", (t, e) => this[Ht](t, e));
147909
148278
  }
147910
148279
  [Ht](t, e) {
147911
148280
  t ? this[Ut](t) : (this[u] = e, this.emit("open", e), this[zt]());
@@ -147918,7 +148287,7 @@ var _t = class extends A {
147918
148287
  this[j] = true;
147919
148288
  let t = this[vi]();
147920
148289
  if (t.length === 0) return process.nextTick(() => this[Ii](null, 0, t));
147921
- import_fs26.default.read(this[u], t, 0, t.length, null, (e, i, r) => this[Ii](e, i, r));
148290
+ import_fs27.default.read(this[u], t, 0, t.length, null, (e, i, r) => this[Ii](e, i, r));
147922
148291
  }
147923
148292
  }
147924
148293
  [Ii](t, e, i) {
@@ -147927,7 +148296,7 @@ var _t = class extends A {
147927
148296
  [H2]() {
147928
148297
  if (this[ht] && typeof this[u] == "number") {
147929
148298
  let t = this[u];
147930
- this[u] = void 0, import_fs26.default.close(t, (e) => e ? this.emit("error", e) : this.emit("close"));
148299
+ this[u] = void 0, import_fs27.default.close(t, (e) => e ? this.emit("error", e) : this.emit("close"));
147931
148300
  }
147932
148301
  }
147933
148302
  [Ut](t) {
@@ -147955,7 +148324,7 @@ var Be = class extends _t {
147955
148324
  [at]() {
147956
148325
  let t = true;
147957
148326
  try {
147958
- this[Ht](null, import_fs26.default.openSync(this[U], "r")), t = false;
148327
+ this[Ht](null, import_fs27.default.openSync(this[U], "r")), t = false;
147959
148328
  } finally {
147960
148329
  t && this[H2]();
147961
148330
  }
@@ -147966,7 +148335,7 @@ var Be = class extends _t {
147966
148335
  if (!this[j]) {
147967
148336
  this[j] = true;
147968
148337
  do {
147969
- let e = this[vi](), i = e.length === 0 ? 0 : import_fs26.default.readSync(this[u], e, 0, e.length, null);
148338
+ let e = this[vi](), i = e.length === 0 ? 0 : import_fs27.default.readSync(this[u], e, 0, e.length, null);
147970
148339
  if (!this[ki](i, e)) break;
147971
148340
  } while (true);
147972
148341
  this[j] = false;
@@ -147979,7 +148348,7 @@ var Be = class extends _t {
147979
148348
  [H2]() {
147980
148349
  if (this[ht] && typeof this[u] == "number") {
147981
148350
  let t = this[u];
147982
- this[u] = void 0, import_fs26.default.closeSync(t), this.emit("close");
148351
+ this[u] = void 0, import_fs27.default.closeSync(t), this.emit("close");
147983
148352
  }
147984
148353
  }
147985
148354
  };
@@ -148021,7 +148390,7 @@ var et = class extends import_events4.default {
148021
148390
  this[H2](), this[gt] = true, this.emit("error", t);
148022
148391
  }
148023
148392
  [at]() {
148024
- import_fs26.default.open(this[U], this[tt], this[ie], (t, e) => this[Ht](t, e));
148393
+ import_fs27.default.open(this[U], this[tt], this[ie], (t, e) => this[Ht](t, e));
148025
148394
  }
148026
148395
  [Ht](t, e) {
148027
148396
  this[Me] && this[tt] === "r+" && t && t.code === "ENOENT" ? (this[tt] = "w", this[at]()) : t ? this[Ut](t) : (this[u] = e, this.emit("open", e), this[gt] || this[Ai]());
@@ -148033,7 +148402,7 @@ var et = class extends import_events4.default {
148033
148402
  return typeof t == "string" && (t = Buffer.from(t, e)), this[te] ? (this.emit("error", new Error("write() after end()")), false) : this[u] === void 0 || this[gt] || this[Y2].length ? (this[Y2].push(t), this[ke] = true, false) : (this[gt] = true, this[ve](t), true);
148034
148403
  }
148035
148404
  [ve](t) {
148036
- import_fs26.default.write(this[u], t, 0, t.length, this[ot], (e, i) => this[Pt](e, i));
148405
+ import_fs27.default.write(this[u], t, 0, t.length, this[ot], (e, i) => this[Pt](e, i));
148037
148406
  }
148038
148407
  [Pt](t, e) {
148039
148408
  t ? this[Ut](t) : (this[ot] !== void 0 && typeof e == "number" && (this[ot] += e), this[Y2].length ? this[Ai]() : (this[gt] = false, this[te] && !this[Ni] ? (this[Ni] = true, this[H2](), this.emit("finish")) : this[ke] && (this[ke] = false, this.emit("drain"))));
@@ -148049,7 +148418,7 @@ var et = class extends import_events4.default {
148049
148418
  [H2]() {
148050
148419
  if (this[ht] && typeof this[u] == "number") {
148051
148420
  let t = this[u];
148052
- this[u] = void 0, import_fs26.default.close(t, (e) => e ? this.emit("error", e) : this.emit("close"));
148421
+ this[u] = void 0, import_fs27.default.close(t, (e) => e ? this.emit("error", e) : this.emit("close"));
148053
148422
  }
148054
148423
  }
148055
148424
  };
@@ -148057,24 +148426,24 @@ var Wt = class extends et {
148057
148426
  [at]() {
148058
148427
  let t;
148059
148428
  if (this[Me] && this[tt] === "r+") try {
148060
- t = import_fs26.default.openSync(this[U], this[tt], this[ie]);
148429
+ t = import_fs27.default.openSync(this[U], this[tt], this[ie]);
148061
148430
  } catch (e) {
148062
148431
  if (e?.code === "ENOENT") return this[tt] = "w", this[at]();
148063
148432
  throw e;
148064
148433
  }
148065
- else t = import_fs26.default.openSync(this[U], this[tt], this[ie]);
148434
+ else t = import_fs27.default.openSync(this[U], this[tt], this[ie]);
148066
148435
  this[Ht](null, t);
148067
148436
  }
148068
148437
  [H2]() {
148069
148438
  if (this[ht] && typeof this[u] == "number") {
148070
148439
  let t = this[u];
148071
- this[u] = void 0, import_fs26.default.closeSync(t), this.emit("close");
148440
+ this[u] = void 0, import_fs27.default.closeSync(t), this.emit("close");
148072
148441
  }
148073
148442
  }
148074
148443
  [ve](t) {
148075
148444
  let e = true;
148076
148445
  try {
148077
- this[Pt](null, import_fs26.default.writeSync(this[u], t, 0, t.length, this[ot])), e = false;
148446
+ this[Pt](null, import_fs27.default.writeSync(this[u], t, 0, t.length, this[ot])), e = false;
148078
148447
  } finally {
148079
148448
  if (e) try {
148080
148449
  this[H2]();
@@ -148400,12 +148769,12 @@ var F = class {
148400
148769
  }
148401
148770
  };
148402
148771
  var un = (s3, t) => {
148403
- let i = s3, r = "", n, o = import_node_path15.posix.parse(s3).root || ".";
148772
+ let i = s3, r = "", n, o = import_node_path16.posix.parse(s3).root || ".";
148404
148773
  if (Buffer.byteLength(i) < 100) n = [i, r, false];
148405
148774
  else {
148406
- r = import_node_path15.posix.dirname(i), i = import_node_path15.posix.basename(i);
148775
+ r = import_node_path16.posix.dirname(i), i = import_node_path16.posix.basename(i);
148407
148776
  do
148408
- Buffer.byteLength(i) <= 100 && Buffer.byteLength(r) <= t ? n = [i, r, false] : Buffer.byteLength(i) > 100 && Buffer.byteLength(r) <= t ? n = [i.slice(0, 99), r, true] : (i = import_node_path15.posix.join(import_node_path15.posix.basename(r), i), r = import_node_path15.posix.dirname(r));
148777
+ Buffer.byteLength(i) <= 100 && Buffer.byteLength(r) <= t ? n = [i, r, false] : Buffer.byteLength(i) > 100 && Buffer.byteLength(r) <= t ? n = [i.slice(0, 99), r, true] : (i = import_node_path16.posix.join(import_node_path16.posix.basename(r), i), r = import_node_path16.posix.dirname(r));
148409
148778
  while (r !== o && n === void 0);
148410
148779
  n || (n = [s3.slice(0, 99), "", true]);
148411
148780
  }
@@ -148451,7 +148820,7 @@ var ft = class s {
148451
148820
  if (t === "") return Buffer.allocUnsafe(0);
148452
148821
  let e = Buffer.byteLength(t), i = 512 * Math.ceil(1 + e / 512), r = Buffer.allocUnsafe(i);
148453
148822
  for (let n = 0; n < 512; n++) r[n] = 0;
148454
- new F({ path: ("PaxHeader/" + (0, import_node_path16.basename)(this.path ?? "")).slice(0, 99), mode: this.mode || 420, uid: this.uid, gid: this.gid, size: e, mtime: this.mtime, type: this.global ? "GlobalExtendedHeader" : "ExtendedHeader", linkpath: "", uname: this.uname || "", gname: this.gname || "", devmaj: 0, devmin: 0, atime: this.atime, ctime: this.ctime }).encode(r), r.write(t, 512, e, "utf8");
148823
+ new F({ path: ("PaxHeader/" + (0, import_node_path17.basename)(this.path ?? "")).slice(0, 99), mode: this.mode || 420, uid: this.uid, gid: this.gid, size: e, mtime: this.mtime, type: this.global ? "GlobalExtendedHeader" : "ExtendedHeader", linkpath: "", uname: this.uname || "", gname: this.gname || "", devmaj: 0, devmin: 0, atime: this.atime, ctime: this.ctime }).encode(r), r.write(t, 512, e, "utf8");
148455
148824
  for (let n = e + 512; n < r.length; n++) r[n] = 0;
148456
148825
  return r;
148457
148826
  }
@@ -148857,11 +149226,11 @@ var vn = (s3) => {
148857
149226
  };
148858
149227
  var Qi = (s3, t) => {
148859
149228
  let e = new Map(t.map((n) => [ut(n), true])), i = s3.filter, r = (n, o = "") => {
148860
- let h = o || (0, import_path23.parse)(n).root || ".", a;
149229
+ let h = o || (0, import_path24.parse)(n).root || ".", a;
148861
149230
  if (n === h) a = false;
148862
149231
  else {
148863
149232
  let l = e.get(n);
148864
- a = l !== void 0 ? l : r((0, import_path23.dirname)(n), h);
149233
+ a = l !== void 0 ? l : r((0, import_path24.dirname)(n), h);
148865
149234
  }
148866
149235
  return e.set(n, a), a;
148867
149236
  };
@@ -148870,15 +149239,15 @@ var Qi = (s3, t) => {
148870
149239
  var Mn = (s3) => {
148871
149240
  let t = new rt(s3), e = s3.file, i;
148872
149241
  try {
148873
- i = import_node_fs11.default.openSync(e, "r");
148874
- let r = import_node_fs11.default.fstatSync(i), n = s3.maxReadSize || 16 * 1024 * 1024;
149242
+ i = import_node_fs12.default.openSync(e, "r");
149243
+ let r = import_node_fs12.default.fstatSync(i), n = s3.maxReadSize || 16 * 1024 * 1024;
148875
149244
  if (r.size < n) {
148876
- let o = Buffer.allocUnsafe(r.size), h = import_node_fs11.default.readSync(i, o, 0, r.size, 0);
149245
+ let o = Buffer.allocUnsafe(r.size), h = import_node_fs12.default.readSync(i, o, 0, r.size, 0);
148877
149246
  t.end(h === o.byteLength ? o : o.subarray(0, h));
148878
149247
  } else {
148879
149248
  let o = 0, h = Buffer.allocUnsafe(n);
148880
149249
  for (; o < r.size; ) {
148881
- let a = import_node_fs11.default.readSync(i, h, 0, n, o);
149250
+ let a = import_node_fs12.default.readSync(i, h, 0, n, o);
148882
149251
  if (a === 0) break;
148883
149252
  o += a, t.write(h.subarray(0, a));
148884
149253
  }
@@ -148886,7 +149255,7 @@ var Mn = (s3) => {
148886
149255
  }
148887
149256
  } finally {
148888
149257
  if (typeof i == "number") try {
148889
- import_node_fs11.default.closeSync(i);
149258
+ import_node_fs12.default.closeSync(i);
148890
149259
  } catch {
148891
149260
  }
148892
149261
  }
@@ -148894,7 +149263,7 @@ var Mn = (s3) => {
148894
149263
  var Bn = (s3, t) => {
148895
149264
  let e = new rt(s3), i = s3.maxReadSize || 16 * 1024 * 1024, r = s3.file;
148896
149265
  return new Promise((o, h) => {
148897
- e.on("error", h), e.on("end", o), import_node_fs11.default.stat(r, (a, l) => {
149266
+ e.on("error", h), e.on("end", o), import_node_fs12.default.stat(r, (a, l) => {
148898
149267
  if (a) h(a);
148899
149268
  else {
148900
149269
  let c = new _t(r, { readSize: i, size: l.size });
@@ -148907,7 +149276,7 @@ var Ct = K(Mn, Bn, (s3) => new rt(s3), (s3) => new rt(s3), (s3, t) => {
148907
149276
  t?.length && Qi(s3, t), s3.noResume || vn(s3);
148908
149277
  });
148909
149278
  var Ji = (s3, t, e) => (s3 &= 4095, e && (s3 = (s3 | 384) & -19), t && (s3 & 256 && (s3 |= 64), s3 & 32 && (s3 |= 8), s3 & 4 && (s3 |= 1)), s3);
148910
- var { isAbsolute: zn, parse: qs } = import_node_path17.win32;
149279
+ var { isAbsolute: zn, parse: qs } = import_node_path18.win32;
148911
149280
  var ce = (s3) => {
148912
149281
  let t = "", e = qs(s3);
148913
149282
  for (; zn(s3) || e.root; ) {
@@ -148981,7 +149350,7 @@ var de = class extends A {
148981
149350
  let [o, h] = ce(this.path);
148982
149351
  o && typeof h == "string" && (this.path = h, r = o);
148983
149352
  }
148984
- this.win32 = !!i.win32 || process.platform === "win32", this.win32 && (this.path = Qs(this.path.replaceAll(/\\/g, "/")), t = t.replaceAll(/\\/g, "/")), this.absolute = f(i.absolute || import_path24.default.resolve(this.cwd, t)), this.path === "" && (this.path = "./"), r && this.warn("TAR_ENTRY_INFO", `stripping ${r} from absolute path`, { entry: this, path: r + this.path });
149353
+ this.win32 = !!i.win32 || process.platform === "win32", this.win32 && (this.path = Qs(this.path.replaceAll(/\\/g, "/")), t = t.replaceAll(/\\/g, "/")), this.absolute = f(i.absolute || import_path25.default.resolve(this.cwd, t)), this.path === "" && (this.path = "./"), r && this.warn("TAR_ENTRY_INFO", `stripping ${r} from absolute path`, { entry: this, path: r + this.path });
148985
149354
  let n = this.statCache.get(this.absolute);
148986
149355
  n ? this[si](n) : this[ss]();
148987
149356
  }
@@ -148992,7 +149361,7 @@ var de = class extends A {
148992
149361
  return t === "error" && (this.#t = true), super.emit(t, ...e);
148993
149362
  }
148994
149363
  [ss]() {
148995
- import_fs28.default.lstat(this.absolute, (t, e) => {
149364
+ import_fs29.default.lstat(this.absolute, (t, e) => {
148996
149365
  if (t) return this.emit("error", t);
148997
149366
  this[si](e);
148998
149367
  });
@@ -149030,7 +149399,7 @@ var de = class extends A {
149030
149399
  this.path.slice(-1) !== "/" && (this.path += "/"), this.stat.size = 0, this[fe](), this.end();
149031
149400
  }
149032
149401
  [is]() {
149033
- import_fs28.default.readlink(this.absolute, (t, e) => {
149402
+ import_fs29.default.readlink(this.absolute, (t, e) => {
149034
149403
  if (t) return this.emit("error", t);
149035
149404
  this[ns](e);
149036
149405
  });
@@ -149040,7 +149409,7 @@ var de = class extends A {
149040
149409
  }
149041
149410
  [sr](t) {
149042
149411
  if (!this.stat) throw new Error("cannot create link entry without stat");
149043
- this.type = "Link", this.linkpath = f(import_path24.default.relative(this.cwd, t)), this.stat.size = 0, this[fe](), this.end();
149412
+ this.type = "Link", this.linkpath = f(import_path25.default.relative(this.cwd, t)), this.stat.size = 0, this[fe](), this.end();
149044
149413
  }
149045
149414
  [er]() {
149046
149415
  if (!this.stat) throw new Error("cannot create file entry without stat");
@@ -149053,7 +149422,7 @@ var de = class extends A {
149053
149422
  this[os]();
149054
149423
  }
149055
149424
  [os]() {
149056
- import_fs28.default.open(this.absolute, "r", (t, e) => {
149425
+ import_fs29.default.open(this.absolute, "r", (t, e) => {
149057
149426
  if (t) return this.emit("error", t);
149058
149427
  this[hs](e);
149059
149428
  });
@@ -149068,14 +149437,14 @@ var de = class extends A {
149068
149437
  [ii]() {
149069
149438
  let { fd: t, buf: e, offset: i, length: r, pos: n } = this;
149070
149439
  if (t === void 0 || e === void 0) throw new Error("cannot read file without first opening");
149071
- import_fs28.default.read(t, e, i, r, n, (o, h) => {
149440
+ import_fs29.default.read(t, e, i, r, n, (o, h) => {
149072
149441
  if (o) return this[pt](() => this.emit("error", o));
149073
149442
  this[rs](h);
149074
149443
  });
149075
149444
  }
149076
149445
  [pt](t = () => {
149077
149446
  }) {
149078
- this.fd !== void 0 && import_fs28.default.close(this.fd, t);
149447
+ this.fd !== void 0 && import_fs29.default.close(this.fd, t);
149079
149448
  }
149080
149449
  [rs](t) {
149081
149450
  if (t <= 0 && this.remain > 0) {
@@ -149110,20 +149479,20 @@ var de = class extends A {
149110
149479
  var ni = class extends de {
149111
149480
  sync = true;
149112
149481
  [ss]() {
149113
- this[si](import_fs28.default.lstatSync(this.absolute));
149482
+ this[si](import_fs29.default.lstatSync(this.absolute));
149114
149483
  }
149115
149484
  [is]() {
149116
- this[ns](import_fs28.default.readlinkSync(this.absolute));
149485
+ this[ns](import_fs29.default.readlinkSync(this.absolute));
149117
149486
  }
149118
149487
  [os]() {
149119
- this[hs](import_fs28.default.openSync(this.absolute, "r"));
149488
+ this[hs](import_fs29.default.openSync(this.absolute, "r"));
149120
149489
  }
149121
149490
  [ii]() {
149122
149491
  let t = true;
149123
149492
  try {
149124
149493
  let { fd: e, buf: i, offset: r, length: n, pos: o } = this;
149125
149494
  if (e === void 0 || i === void 0) throw new Error("fd and buf must be set in READ method");
149126
- let h = import_fs28.default.readSync(e, i, r, n, o);
149495
+ let h = import_fs29.default.readSync(e, i, r, n, o);
149127
149496
  this[rs](h), t = false;
149128
149497
  } finally {
149129
149498
  if (t) try {
@@ -149138,7 +149507,7 @@ var ni = class extends de {
149138
149507
  }
149139
149508
  [pt](t = () => {
149140
149509
  }) {
149141
- this.fd !== void 0 && import_fs28.default.closeSync(this.fd), t();
149510
+ this.fd !== void 0 && import_fs29.default.closeSync(this.fd), t();
149142
149511
  }
149143
149512
  };
149144
149513
  var oi = class extends A {
@@ -149454,7 +149823,7 @@ var wt = class extends A {
149454
149823
  return typeof t == "string" ? this[ci](t) : this[or](t), this.flowing;
149455
149824
  }
149456
149825
  [or](t) {
149457
- let e = f(import_path25.default.resolve(this.cwd, t.path));
149826
+ let e = f(import_path26.default.resolve(this.cwd, t.path));
149458
149827
  if (!this.filter(t.path, t)) t.resume();
149459
149828
  else {
149460
149829
  let i = new pi(t.path, e);
@@ -149463,13 +149832,13 @@ var wt = class extends A {
149463
149832
  this[Ft]();
149464
149833
  }
149465
149834
  [ci](t) {
149466
- let e = f(import_path25.default.resolve(this.cwd, t));
149835
+ let e = f(import_path26.default.resolve(this.cwd, t));
149467
149836
  this[W2].push(new pi(t, e)), this[Ft]();
149468
149837
  }
149469
149838
  [ds](t) {
149470
149839
  t.pending = true, this[G] += 1;
149471
149840
  let e = this.follow ? "stat" : "lstat";
149472
- import_fs27.default[e](t.absolute, (i, r) => {
149841
+ import_fs28.default[e](t.absolute, (i, r) => {
149473
149842
  t.pending = false, this[G] -= 1, i ? this.emit("error", i) : this[li](t, r);
149474
149843
  });
149475
149844
  }
@@ -149483,7 +149852,7 @@ var wt = class extends A {
149483
149852
  this[Ft]();
149484
149853
  }
149485
149854
  [ms](t) {
149486
- t.pending = true, this[G] += 1, import_fs27.default.readdir(t.absolute, (e, i) => {
149855
+ t.pending = true, this[G] += 1, import_fs28.default.readdir(t.absolute, (e, i) => {
149487
149856
  if (t.pending = false, this[G] -= 1, e) return this.emit("error", e);
149488
149857
  this[fi](t, i);
149489
149858
  });
@@ -149584,10 +149953,10 @@ var kt = class extends wt {
149584
149953
  }
149585
149954
  [ds](t) {
149586
149955
  let e = this.follow ? "statSync" : "lstatSync";
149587
- this[li](t, import_fs27.default[e](t.absolute));
149956
+ this[li](t, import_fs28.default[e](t.absolute));
149588
149957
  }
149589
149958
  [ms](t) {
149590
- this[fi](t, import_fs27.default.readdirSync(t.absolute));
149959
+ this[fi](t, import_fs28.default.readdirSync(t.absolute));
149591
149960
  }
149592
149961
  [di](t) {
149593
149962
  let e = t.entry, i = this.zip;
@@ -149616,11 +149985,11 @@ var $n = (s3, t) => {
149616
149985
  };
149617
149986
  var fr = (s3, t) => {
149618
149987
  t.forEach((e) => {
149619
- e.charAt(0) === "@" ? Ct({ file: import_node_path14.default.resolve(s3.cwd, e.slice(1)), sync: true, noResume: true, onReadEntry: (i) => s3.add(i) }) : s3.add(e);
149988
+ e.charAt(0) === "@" ? Ct({ file: import_node_path15.default.resolve(s3.cwd, e.slice(1)), sync: true, noResume: true, onReadEntry: (i) => s3.add(i) }) : s3.add(e);
149620
149989
  }), s3.end();
149621
149990
  };
149622
149991
  var dr = async (s3, t) => {
149623
- for (let e of t) e.charAt(0) === "@" ? await Ct({ file: import_node_path14.default.resolve(String(s3.cwd), e.slice(1)), noResume: true, onReadEntry: (i) => {
149992
+ for (let e of t) e.charAt(0) === "@" ? await Ct({ file: import_node_path15.default.resolve(String(s3.cwd), e.slice(1)), noResume: true, onReadEntry: (i) => {
149624
149993
  s3.add(i);
149625
149994
  } }) : s3.add(e);
149626
149995
  s3.end();
@@ -149638,8 +150007,8 @@ var Qn = K(Vn, $n, Xn, qn, (s3, t) => {
149638
150007
  });
149639
150008
  var Jn = process.env.__FAKE_PLATFORM__ || process.platform;
149640
150009
  var Er = Jn === "win32";
149641
- var { O_CREAT: wr, O_NOFOLLOW: mr, O_TRUNC: Sr, O_WRONLY: yr } = import_fs29.default.constants;
149642
- var Rr = Number(process.env.__FAKE_FS_O_FILENAME__) || import_fs29.default.constants.UV_FS_O_FILEMAP || 0;
150010
+ var { O_CREAT: wr, O_NOFOLLOW: mr, O_TRUNC: Sr, O_WRONLY: yr } = import_fs30.default.constants;
150011
+ var Rr = Number(process.env.__FAKE_FS_O_FILENAME__) || import_fs30.default.constants.UV_FS_O_FILEMAP || 0;
149643
150012
  var jn = Er && !!Rr;
149644
150013
  var to = 512 * 1024;
149645
150014
  var eo = Rr | Sr | wr | yr;
@@ -149647,29 +150016,29 @@ var ur = !Er && typeof mr == "number" ? mr | Sr | wr | yr : null;
149647
150016
  var us = ur !== null ? () => ur : jn ? (s3) => s3 < to ? eo : "w" : () => "w";
149648
150017
  var ps = (s3, t, e) => {
149649
150018
  try {
149650
- return import_node_fs14.default.lchownSync(s3, t, e);
150019
+ return import_node_fs15.default.lchownSync(s3, t, e);
149651
150020
  } catch (i) {
149652
150021
  if (i?.code !== "ENOENT") throw i;
149653
150022
  }
149654
150023
  };
149655
150024
  var Ei = (s3, t, e, i) => {
149656
- import_node_fs14.default.lchown(s3, t, e, (r) => {
150025
+ import_node_fs15.default.lchown(s3, t, e, (r) => {
149657
150026
  i(r && r?.code !== "ENOENT" ? r : null);
149658
150027
  });
149659
150028
  };
149660
150029
  var io = (s3, t, e, i, r) => {
149661
- if (t.isDirectory()) Es(import_node_path19.default.resolve(s3, t.name), e, i, (n) => {
150030
+ if (t.isDirectory()) Es(import_node_path20.default.resolve(s3, t.name), e, i, (n) => {
149662
150031
  if (n) return r(n);
149663
- let o = import_node_path19.default.resolve(s3, t.name);
150032
+ let o = import_node_path20.default.resolve(s3, t.name);
149664
150033
  Ei(o, e, i, r);
149665
150034
  });
149666
150035
  else {
149667
- let n = import_node_path19.default.resolve(s3, t.name);
150036
+ let n = import_node_path20.default.resolve(s3, t.name);
149668
150037
  Ei(n, e, i, r);
149669
150038
  }
149670
150039
  };
149671
150040
  var Es = (s3, t, e, i) => {
149672
- import_node_fs14.default.readdir(s3, { withFileTypes: true }, (r, n) => {
150041
+ import_node_fs15.default.readdir(s3, { withFileTypes: true }, (r, n) => {
149673
150042
  if (r) {
149674
150043
  if (r.code === "ENOENT") return i();
149675
150044
  if (r.code !== "ENOTDIR" && r.code !== "ENOTSUP") return i(r);
@@ -149685,12 +150054,12 @@ var Es = (s3, t, e, i) => {
149685
150054
  });
149686
150055
  };
149687
150056
  var so = (s3, t, e, i) => {
149688
- t.isDirectory() && ws(import_node_path19.default.resolve(s3, t.name), e, i), ps(import_node_path19.default.resolve(s3, t.name), e, i);
150057
+ t.isDirectory() && ws(import_node_path20.default.resolve(s3, t.name), e, i), ps(import_node_path20.default.resolve(s3, t.name), e, i);
149689
150058
  };
149690
150059
  var ws = (s3, t, e) => {
149691
150060
  let i;
149692
150061
  try {
149693
- i = import_node_fs14.default.readdirSync(s3, { withFileTypes: true });
150062
+ i = import_node_fs15.default.readdirSync(s3, { withFileTypes: true });
149694
150063
  } catch (r) {
149695
150064
  let n = r;
149696
150065
  if (n?.code === "ENOENT") return;
@@ -149724,32 +150093,32 @@ var St = class extends Error {
149724
150093
  }
149725
150094
  };
149726
150095
  var no = (s3, t) => {
149727
- import_node_fs15.default.stat(s3, (e, i) => {
150096
+ import_node_fs16.default.stat(s3, (e, i) => {
149728
150097
  (e || !i.isDirectory()) && (e = new Se(s3, e?.code || "ENOTDIR")), t(e);
149729
150098
  });
149730
150099
  };
149731
150100
  var gr = (s3, t, e) => {
149732
150101
  s3 = f(s3);
149733
150102
  let i = t.umask ?? 18, r = t.mode | 448, n = (r & i) !== 0, o = t.uid, h = t.gid, a = typeof o == "number" && typeof h == "number" && (o !== t.processUid || h !== t.processGid), l = t.preserve, c = t.unlink, d = f(t.cwd), S2 = (E, x) => {
149734
- E ? e(E) : x && a ? Es(x, o, h, (Le) => S2(Le)) : n ? import_node_fs15.default.chmod(s3, r, e) : e();
150103
+ E ? e(E) : x && a ? Es(x, o, h, (Le) => S2(Le)) : n ? import_node_fs16.default.chmod(s3, r, e) : e();
149735
150104
  };
149736
150105
  if (s3 === d) return no(s3, S2);
149737
150106
  if (l) return import_promises21.default.mkdir(s3, { mode: r, recursive: true }).then((E) => S2(null, E ?? void 0), S2);
149738
- let D = f(import_node_path20.default.relative(d, s3)).split("/");
150107
+ let D = f(import_node_path21.default.relative(d, s3)).split("/");
149739
150108
  Ss(d, D, r, c, d, void 0, S2);
149740
150109
  };
149741
150110
  var Ss = (s3, t, e, i, r, n, o) => {
149742
150111
  if (t.length === 0) return o(null, n);
149743
- let h = t.shift(), a = f(import_node_path20.default.resolve(s3 + "/" + h));
149744
- import_node_fs15.default.mkdir(a, e, br(a, t, e, i, r, n, o));
150112
+ let h = t.shift(), a = f(import_node_path21.default.resolve(s3 + "/" + h));
150113
+ import_node_fs16.default.mkdir(a, e, br(a, t, e, i, r, n, o));
149745
150114
  };
149746
150115
  var br = (s3, t, e, i, r, n, o) => (h) => {
149747
- h ? import_node_fs15.default.lstat(s3, (a, l) => {
150116
+ h ? import_node_fs16.default.lstat(s3, (a, l) => {
149748
150117
  if (a) a.path = a.path && f(a.path), o(a);
149749
150118
  else if (l.isDirectory()) Ss(s3, t, e, i, r, n, o);
149750
- else if (i) import_node_fs15.default.unlink(s3, (c) => {
150119
+ else if (i) import_node_fs16.default.unlink(s3, (c) => {
149751
150120
  if (c) return o(c);
149752
- import_node_fs15.default.mkdir(s3, e, br(s3, t, e, i, r, n, o));
150121
+ import_node_fs16.default.mkdir(s3, e, br(s3, t, e, i, r, n, o));
149753
150122
  });
149754
150123
  else {
149755
150124
  if (l.isSymbolicLink()) return o(new St(s3, s3 + "/" + t.join("/")));
@@ -149760,7 +150129,7 @@ var br = (s3, t, e, i, r, n, o) => (h) => {
149760
150129
  var oo = (s3) => {
149761
150130
  let t = false, e;
149762
150131
  try {
149763
- t = import_node_fs15.default.statSync(s3).isDirectory();
150132
+ t = import_node_fs16.default.statSync(s3).isDirectory();
149764
150133
  } catch (i) {
149765
150134
  e = i?.code;
149766
150135
  } finally {
@@ -149770,20 +150139,20 @@ var oo = (s3) => {
149770
150139
  var _r = (s3, t) => {
149771
150140
  s3 = f(s3);
149772
150141
  let e = t.umask ?? 18, i = t.mode | 448, r = (i & e) !== 0, n = t.uid, o = t.gid, h = typeof n == "number" && typeof o == "number" && (n !== t.processUid || o !== t.processGid), a = t.preserve, l = t.unlink, c = f(t.cwd), d = (E) => {
149773
- E && h && ws(E, n, o), r && import_node_fs15.default.chmodSync(s3, i);
150142
+ E && h && ws(E, n, o), r && import_node_fs16.default.chmodSync(s3, i);
149774
150143
  };
149775
150144
  if (s3 === c) return oo(c), d();
149776
- if (a) return d(import_node_fs15.default.mkdirSync(s3, { mode: i, recursive: true }) ?? void 0);
149777
- let T2 = f(import_node_path20.default.relative(c, s3)).split("/"), D;
150145
+ if (a) return d(import_node_fs16.default.mkdirSync(s3, { mode: i, recursive: true }) ?? void 0);
150146
+ let T2 = f(import_node_path21.default.relative(c, s3)).split("/"), D;
149778
150147
  for (let E = T2.shift(), x = c; E && (x += "/" + E); E = T2.shift()) {
149779
- x = f(import_node_path20.default.resolve(x));
150148
+ x = f(import_node_path21.default.resolve(x));
149780
150149
  try {
149781
- import_node_fs15.default.mkdirSync(x, i), D = D || x;
150150
+ import_node_fs16.default.mkdirSync(x, i), D = D || x;
149782
150151
  } catch {
149783
- let Le = import_node_fs15.default.lstatSync(x);
150152
+ let Le = import_node_fs16.default.lstatSync(x);
149784
150153
  if (Le.isDirectory()) continue;
149785
150154
  if (l) {
149786
- import_node_fs15.default.unlinkSync(x), import_node_fs15.default.mkdirSync(x, i), D = D || x;
150155
+ import_node_fs16.default.unlinkSync(x), import_node_fs16.default.mkdirSync(x, i), D = D || x;
149787
150156
  continue;
149788
150157
  } else if (Le.isSymbolicLink()) return new St(x, x + "/" + T2.join("/"));
149789
150158
  }
@@ -149805,14 +150174,14 @@ var ho = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform;
149805
150174
  var ao = ho === "win32";
149806
150175
  var lo = (s3) => s3.split("/").slice(0, -1).reduce((e, i) => {
149807
150176
  let r = e.at(-1);
149808
- return r !== void 0 && (i = (0, import_node_path21.join)(r, i)), e.push(i || "/"), e;
150177
+ return r !== void 0 && (i = (0, import_node_path22.join)(r, i)), e.push(i || "/"), e;
149809
150178
  }, []);
149810
150179
  var yi = class {
149811
150180
  #t = /* @__PURE__ */ new Map();
149812
150181
  #i = /* @__PURE__ */ new Map();
149813
150182
  #s = /* @__PURE__ */ new Set();
149814
150183
  reserve(t, e) {
149815
- t = ao ? ["win32 parallelization disabled"] : t.map((r) => ut((0, import_node_path21.join)(Tr(r))));
150184
+ t = ao ? ["win32 parallelization disabled"] : t.map((r) => ut((0, import_node_path22.join)(Tr(r))));
149816
150185
  let i = new Set(t.map((r) => lo(r)).reduce((r, n) => r.concat(n)));
149817
150186
  this.#i.set(e, { dirs: i, paths: t });
149818
150187
  for (let r of t) {
@@ -149902,17 +150271,17 @@ var fo = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform;
149902
150271
  var Te = fo === "win32";
149903
150272
  var mo = 1024;
149904
150273
  var uo = (s3, t) => {
149905
- if (!Te) return import_node_fs13.default.unlink(s3, t);
150274
+ if (!Te) return import_node_fs14.default.unlink(s3, t);
149906
150275
  let e = s3 + ".DELETE." + (0, import_node_crypto5.randomBytes)(16).toString("hex");
149907
- import_node_fs13.default.rename(s3, e, (i) => {
150276
+ import_node_fs14.default.rename(s3, e, (i) => {
149908
150277
  if (i) return t(i);
149909
- import_node_fs13.default.unlink(e, t);
150278
+ import_node_fs14.default.unlink(e, t);
149910
150279
  });
149911
150280
  };
149912
150281
  var po = (s3) => {
149913
- if (!Te) return import_node_fs13.default.unlinkSync(s3);
150282
+ if (!Te) return import_node_fs14.default.unlinkSync(s3);
149914
150283
  let t = s3 + ".DELETE." + (0, import_node_crypto5.randomBytes)(16).toString("hex");
149915
- import_node_fs13.default.renameSync(s3, t), import_node_fs13.default.unlinkSync(t);
150284
+ import_node_fs14.default.renameSync(s3, t), import_node_fs14.default.unlinkSync(t);
149916
150285
  };
149917
150286
  var vr = (s3, t, e) => s3 !== void 0 && s3 === s3 >>> 0 ? s3 : t !== void 0 && t === t >>> 0 ? t : e;
149918
150287
  var Xt = class extends rt {
@@ -149952,7 +150321,7 @@ var Xt = class extends rt {
149952
150321
  if (t.preserveOwner) throw new TypeError("cannot preserve owner in archive and also set owner explicitly");
149953
150322
  this.uid = t.uid, this.gid = t.gid, this.setOwner = true;
149954
150323
  } else this.uid = void 0, this.gid = void 0, this.setOwner = false;
149955
- this.preserveOwner = t.preserveOwner === void 0 && typeof t.uid != "number" ? process.getuid?.() === 0 : !!t.preserveOwner, this.processUid = (this.preserveOwner || this.setOwner) && process.getuid ? process.getuid() : void 0, this.processGid = (this.preserveOwner || this.setOwner) && process.getgid ? process.getgid() : void 0, this.maxDepth = typeof t.maxDepth == "number" ? t.maxDepth : mo, this.forceChown = t.forceChown === true, this.win32 = !!t.win32 || Te, this.newer = !!t.newer, this.keep = !!t.keep, this.noMtime = !!t.noMtime, this.preservePaths = !!t.preservePaths, this.unlink = !!t.unlink, this.cwd = f(import_node_path18.default.resolve(t.cwd || process.cwd())), this.strip = Number(t.strip) || 0, this.processUmask = this.chmod ? typeof t.processUmask == "number" ? t.processUmask : Lr() : 0, this.umask = typeof t.umask == "number" ? t.umask : this.processUmask, this.dmode = t.dmode || 511 & ~this.umask, this.fmode = t.fmode || 438 & ~this.umask, this.on("entry", (e) => this[Dr](e));
150324
+ this.preserveOwner = t.preserveOwner === void 0 && typeof t.uid != "number" ? process.getuid?.() === 0 : !!t.preserveOwner, this.processUid = (this.preserveOwner || this.setOwner) && process.getuid ? process.getuid() : void 0, this.processGid = (this.preserveOwner || this.setOwner) && process.getgid ? process.getgid() : void 0, this.maxDepth = typeof t.maxDepth == "number" ? t.maxDepth : mo, this.forceChown = t.forceChown === true, this.win32 = !!t.win32 || Te, this.newer = !!t.newer, this.keep = !!t.keep, this.noMtime = !!t.noMtime, this.preservePaths = !!t.preservePaths, this.unlink = !!t.unlink, this.cwd = f(import_node_path19.default.resolve(t.cwd || process.cwd())), this.strip = Number(t.strip) || 0, this.processUmask = this.chmod ? typeof t.processUmask == "number" ? t.processUmask : Lr() : 0, this.umask = typeof t.umask == "number" ? t.umask : this.processUmask, this.dmode = t.dmode || 511 & ~this.umask, this.fmode = t.fmode || 438 & ~this.umask, this.on("entry", (e) => this[Dr](e));
149956
150325
  }
149957
150326
  warn(t, e, i = {}) {
149958
150327
  return (t === "TAR_BAD_ARCHIVE" || t === "TAR_ABORT") && (i.recoverable = false), super.warn(t, e, i);
@@ -149966,7 +150335,7 @@ var Xt = class extends rt {
149966
150335
  let [n, o] = ce(i), h = o.replaceAll(/\\/g, "/").split("/");
149967
150336
  if (h.includes("..") || Te && /^[a-z]:\.\.$/i.test(h[0] ?? "")) {
149968
150337
  if (e === "path" || r === "Link") return this.warn("TAR_ENTRY_ERROR", `${e} contains '..'`, { entry: t, [e]: i }), false;
149969
- let a = import_node_path18.default.posix.dirname(t.path), l = import_node_path18.default.posix.normalize(import_node_path18.default.posix.join(a, h.join("/")));
150338
+ let a = import_node_path19.default.posix.dirname(t.path), l = import_node_path19.default.posix.normalize(import_node_path19.default.posix.join(a, h.join("/")));
149970
150339
  if (l.startsWith("../") || l === "..") return this.warn("TAR_ENTRY_ERROR", `${e} escapes extraction directory`, { entry: t, [e]: i }), false;
149971
150340
  }
149972
150341
  return n && (t[e] = String(o), this.warn("TAR_ENTRY_INFO", `stripping ${n} from absolute ${e}`, { entry: t, [e]: i })), true;
@@ -149984,12 +150353,12 @@ var Xt = class extends rt {
149984
150353
  }
149985
150354
  if (isFinite(this.maxDepth) && i.length > this.maxDepth) return this.warn("TAR_ENTRY_ERROR", "path excessively deep", { entry: t, path: e, depth: i.length, maxDepth: this.maxDepth }), false;
149986
150355
  if (!this[Rs](t, "path") || !this[Rs](t, "linkpath")) return false;
149987
- if (t.absolute = import_node_path18.default.isAbsolute(t.path) ? f(import_node_path18.default.resolve(t.path)) : f(import_node_path18.default.resolve(this.cwd, t.path)), !this.preservePaths && typeof t.absolute == "string" && t.absolute.indexOf(this.cwd + "/") !== 0 && t.absolute !== this.cwd) return this.warn("TAR_ENTRY_ERROR", "path escaped extraction target", { entry: t, path: f(t.path), resolvedPath: t.absolute, cwd: this.cwd }), false;
150356
+ if (t.absolute = import_node_path19.default.isAbsolute(t.path) ? f(import_node_path19.default.resolve(t.path)) : f(import_node_path19.default.resolve(this.cwd, t.path)), !this.preservePaths && typeof t.absolute == "string" && t.absolute.indexOf(this.cwd + "/") !== 0 && t.absolute !== this.cwd) return this.warn("TAR_ENTRY_ERROR", "path escaped extraction target", { entry: t, path: f(t.path), resolvedPath: t.absolute, cwd: this.cwd }), false;
149988
150357
  if (t.absolute === this.cwd && t.type !== "Directory" && t.type !== "GNUDumpDir") return false;
149989
150358
  if (this.win32) {
149990
- let { root: r } = import_node_path18.default.win32.parse(String(t.absolute));
150359
+ let { root: r } = import_node_path19.default.win32.parse(String(t.absolute));
149991
150360
  t.absolute = r + ts(String(t.absolute).slice(r.length));
149992
- let { root: n } = import_node_path18.default.win32.parse(t.path);
150361
+ let { root: n } = import_node_path19.default.win32.parse(t.path);
149993
150362
  t.path = n + ts(t.path.slice(n.length));
149994
150363
  }
149995
150364
  return true;
@@ -150028,16 +150397,16 @@ var Xt = class extends rt {
150028
150397
  [Ts](t, e) {
150029
150398
  let i = typeof t.mode == "number" ? t.mode & 4095 : this.fmode, r = new et(String(t.absolute), { flags: us(t.size), mode: i, autoClose: false });
150030
150399
  r.on("error", (a) => {
150031
- r.fd && import_node_fs13.default.close(r.fd, () => {
150400
+ r.fd && import_node_fs14.default.close(r.fd, () => {
150032
150401
  }), r.write = () => true, this[O](a, t), e();
150033
150402
  });
150034
150403
  let n = 1, o = (a) => {
150035
150404
  if (a) {
150036
- r.fd && import_node_fs13.default.close(r.fd, () => {
150405
+ r.fd && import_node_fs14.default.close(r.fd, () => {
150037
150406
  }), this[O](a, t), e();
150038
150407
  return;
150039
150408
  }
150040
- --n === 0 && r.fd !== void 0 && import_node_fs13.default.close(r.fd, (l) => {
150409
+ --n === 0 && r.fd !== void 0 && import_node_fs14.default.close(r.fd, (l) => {
150041
150410
  l ? this[O](l, t) : this[$t](), e();
150042
150411
  });
150043
150412
  };
@@ -150046,12 +150415,12 @@ var Xt = class extends rt {
150046
150415
  if (typeof l == "number" && t.mtime && !this.noMtime) {
150047
150416
  n++;
150048
150417
  let c = t.atime || /* @__PURE__ */ new Date(), d = t.mtime;
150049
- import_node_fs13.default.futimes(l, c, d, (S2) => S2 ? import_node_fs13.default.utimes(a, c, d, (T2) => o(T2 && S2)) : o());
150418
+ import_node_fs14.default.futimes(l, c, d, (S2) => S2 ? import_node_fs14.default.utimes(a, c, d, (T2) => o(T2 && S2)) : o());
150050
150419
  }
150051
150420
  if (typeof l == "number" && this[ge](t)) {
150052
150421
  n++;
150053
150422
  let c = this[be](t), d = this[_e](t);
150054
- typeof c == "number" && typeof d == "number" && import_node_fs13.default.fchown(l, c, d, (S2) => S2 ? import_node_fs13.default.chown(a, c, d, (T2) => o(T2 && S2)) : o());
150423
+ typeof c == "number" && typeof d == "number" && import_node_fs14.default.fchown(l, c, d, (S2) => S2 ? import_node_fs14.default.chown(a, c, d, (T2) => o(T2 && S2)) : o());
150055
150424
  }
150056
150425
  o();
150057
150426
  });
@@ -150070,20 +150439,20 @@ var Xt = class extends rt {
150070
150439
  let n = 1, o = () => {
150071
150440
  --n === 0 && (e(), this[$t](), t.resume());
150072
150441
  };
150073
- t.mtime && !this.noMtime && (n++, import_node_fs13.default.utimes(String(t.absolute), t.atime || /* @__PURE__ */ new Date(), t.mtime, o)), this[ge](t) && (n++, import_node_fs13.default.chown(String(t.absolute), Number(this[be](t)), Number(this[_e](t)), o)), o();
150442
+ t.mtime && !this.noMtime && (n++, import_node_fs14.default.utimes(String(t.absolute), t.atime || /* @__PURE__ */ new Date(), t.mtime, o)), this[ge](t) && (n++, import_node_fs14.default.chown(String(t.absolute), Number(this[be](t)), Number(this[_e](t)), o)), o();
150074
150443
  });
150075
150444
  }
150076
150445
  [Cr](t) {
150077
150446
  t.unsupported = true, this.warn("TAR_ENTRY_UNSUPPORTED", `unsupported entry type: ${t.type}`, { entry: t }), t.resume();
150078
150447
  }
150079
150448
  [Ar](t, e) {
150080
- let i = f(import_node_path18.default.relative(this.cwd, import_node_path18.default.resolve(import_node_path18.default.dirname(String(t.absolute)), String(t.linkpath)))).split("/");
150449
+ let i = f(import_node_path19.default.relative(this.cwd, import_node_path19.default.resolve(import_node_path19.default.dirname(String(t.absolute)), String(t.linkpath)))).split("/");
150081
150450
  this[Re](t, this.cwd, i, () => this[gi](t, String(t.linkpath), "symlink", e), (r) => {
150082
150451
  this[O](r, t), e();
150083
150452
  });
150084
150453
  }
150085
150454
  [Ir](t, e) {
150086
- let i = f(import_node_path18.default.resolve(this.cwd, String(t.linkpath))), r = f(String(t.linkpath)).split("/");
150455
+ let i = f(import_node_path19.default.resolve(this.cwd, String(t.linkpath))), r = f(String(t.linkpath)).split("/");
150087
150456
  this[Re](t, this.cwd, r, () => this[gi](t, i, "link", e), (n) => {
150088
150457
  this[O](n, t), e();
150089
150458
  });
@@ -150091,10 +150460,10 @@ var Xt = class extends rt {
150091
150460
  [Re](t, e, i, r, n) {
150092
150461
  let o = i.shift();
150093
150462
  if (this.preservePaths || o === void 0) return r();
150094
- let h = import_node_path18.default.resolve(e, o);
150095
- import_node_fs13.default.lstat(h, (a, l) => {
150463
+ let h = import_node_path19.default.resolve(e, o);
150464
+ import_node_fs14.default.lstat(h, (a, l) => {
150096
150465
  if (a) return r();
150097
- if (l?.isSymbolicLink()) return n(new St(h, import_node_path18.default.resolve(h, i.join("/"))));
150466
+ if (l?.isSymbolicLink()) return n(new St(h, import_node_path19.default.resolve(h, i.join("/"))));
150098
150467
  this[Re](t, h, i, r, n);
150099
150468
  });
150100
150469
  }
@@ -150128,7 +150497,7 @@ var Xt = class extends rt {
150128
150497
  });
150129
150498
  }, n = () => {
150130
150499
  if (t.absolute !== this.cwd) {
150131
- let h = f(import_node_path18.default.dirname(String(t.absolute)));
150500
+ let h = f(import_node_path19.default.dirname(String(t.absolute)));
150132
150501
  if (h !== this.cwd) return this[yt](h, this.dmode, (a) => {
150133
150502
  if (a) {
150134
150503
  this[O](a, t), i();
@@ -150139,7 +150508,7 @@ var Xt = class extends rt {
150139
150508
  }
150140
150509
  o();
150141
150510
  }, o = () => {
150142
- import_node_fs13.default.lstat(String(t.absolute), (h, a) => {
150511
+ import_node_fs14.default.lstat(String(t.absolute), (h, a) => {
150143
150512
  if (a && (this.keep || this.newer && a.mtime > (t.mtime ?? a.mtime))) {
150144
150513
  this[Ls](t), i();
150145
150514
  return;
@@ -150148,9 +150517,9 @@ var Xt = class extends rt {
150148
150517
  if (a.isDirectory()) {
150149
150518
  if (t.type === "Directory") {
150150
150519
  let l = this.chmod && t.mode && (a.mode & 4095) !== t.mode, c = (d) => this[P](d ?? null, t, i);
150151
- return l ? import_node_fs13.default.chmod(String(t.absolute), Number(t.mode), c) : c();
150520
+ return l ? import_node_fs14.default.chmod(String(t.absolute), Number(t.mode), c) : c();
150152
150521
  }
150153
- if (t.absolute !== this.cwd) return import_node_fs13.default.rmdir(String(t.absolute), (l) => this[P](l ?? null, t, i));
150522
+ if (t.absolute !== this.cwd) return import_node_fs14.default.rmdir(String(t.absolute), (l) => this[P](l ?? null, t, i));
150154
150523
  }
150155
150524
  if (t.absolute === this.cwd) return this[P](null, t, i);
150156
150525
  uo(String(t.absolute), (l) => this[P](l ?? null, t, i));
@@ -150178,7 +150547,7 @@ var Xt = class extends rt {
150178
150547
  }
150179
150548
  }
150180
150549
  [gi](t, e, i, r) {
150181
- import_node_fs13.default[i](e, String(t.absolute), (n) => {
150550
+ import_node_fs14.default[i](e, String(t.absolute), (n) => {
150182
150551
  n ? this[O](n, t) : (this[$t](), t.resume()), r();
150183
150552
  });
150184
150553
  }
@@ -150203,23 +150572,23 @@ var xe = class extends Xt {
150203
150572
  this[Oe] = true;
150204
150573
  }
150205
150574
  if (t.absolute !== this.cwd) {
150206
- let n = f(import_node_path18.default.dirname(String(t.absolute)));
150575
+ let n = f(import_node_path19.default.dirname(String(t.absolute)));
150207
150576
  if (n !== this.cwd) {
150208
150577
  let o = this[yt](n, this.dmode);
150209
150578
  if (o) return this[O](o, t);
150210
150579
  }
150211
150580
  }
150212
- let [e, i] = ye(() => import_node_fs13.default.lstatSync(String(t.absolute)));
150581
+ let [e, i] = ye(() => import_node_fs14.default.lstatSync(String(t.absolute)));
150213
150582
  if (i && (this.keep || this.newer && i.mtime > (t.mtime ?? i.mtime))) return this[Ls](t);
150214
150583
  if (e || this[Os](t, i)) return this[P](null, t);
150215
150584
  if (i.isDirectory()) {
150216
150585
  if (t.type === "Directory") {
150217
150586
  let o = this.chmod && t.mode && (i.mode & 4095) !== t.mode, [h] = o ? ye(() => {
150218
- import_node_fs13.default.chmodSync(String(t.absolute), Number(t.mode));
150587
+ import_node_fs14.default.chmodSync(String(t.absolute), Number(t.mode));
150219
150588
  }) : [];
150220
150589
  return this[P](h, t);
150221
150590
  }
150222
- let [n] = ye(() => import_node_fs13.default.rmdirSync(String(t.absolute)));
150591
+ let [n] = ye(() => import_node_fs14.default.rmdirSync(String(t.absolute)));
150223
150592
  this[P](n, t);
150224
150593
  }
150225
150594
  let [r] = t.absolute === this.cwd ? [] : ye(() => po(String(t.absolute)));
@@ -150229,21 +150598,21 @@ var xe = class extends Xt {
150229
150598
  let i = typeof t.mode == "number" ? t.mode & 4095 : this.fmode, r = (h) => {
150230
150599
  let a;
150231
150600
  try {
150232
- import_node_fs13.default.closeSync(n);
150601
+ import_node_fs14.default.closeSync(n);
150233
150602
  } catch (l) {
150234
150603
  a = l;
150235
150604
  }
150236
150605
  (h || a) && this[O](h || a, t), e();
150237
150606
  }, n;
150238
150607
  try {
150239
- n = import_node_fs13.default.openSync(String(t.absolute), us(t.size), i);
150608
+ n = import_node_fs14.default.openSync(String(t.absolute), us(t.size), i);
150240
150609
  } catch (h) {
150241
150610
  return r(h);
150242
150611
  }
150243
150612
  let o = this.transform && this.transform(t) || t;
150244
150613
  o !== t && (o.on("error", (h) => this[O](h, t)), t.pipe(o)), o.on("data", (h) => {
150245
150614
  try {
150246
- import_node_fs13.default.writeSync(n, h, 0, h.length);
150615
+ import_node_fs14.default.writeSync(n, h, 0, h.length);
150247
150616
  } catch (a) {
150248
150617
  r(a);
150249
150618
  }
@@ -150252,10 +150621,10 @@ var xe = class extends Xt {
150252
150621
  if (t.mtime && !this.noMtime) {
150253
150622
  let a = t.atime || /* @__PURE__ */ new Date(), l = t.mtime;
150254
150623
  try {
150255
- import_node_fs13.default.futimesSync(n, a, l);
150624
+ import_node_fs14.default.futimesSync(n, a, l);
150256
150625
  } catch (c) {
150257
150626
  try {
150258
- import_node_fs13.default.utimesSync(String(t.absolute), a, l);
150627
+ import_node_fs14.default.utimesSync(String(t.absolute), a, l);
150259
150628
  } catch {
150260
150629
  h = c;
150261
150630
  }
@@ -150264,10 +150633,10 @@ var xe = class extends Xt {
150264
150633
  if (this[ge](t)) {
150265
150634
  let a = this[be](t), l = this[_e](t);
150266
150635
  try {
150267
- import_node_fs13.default.fchownSync(n, Number(a), Number(l));
150636
+ import_node_fs14.default.fchownSync(n, Number(a), Number(l));
150268
150637
  } catch (c) {
150269
150638
  try {
150270
- import_node_fs13.default.chownSync(String(t.absolute), Number(a), Number(l));
150639
+ import_node_fs14.default.chownSync(String(t.absolute), Number(a), Number(l));
150271
150640
  } catch {
150272
150641
  h = h || c;
150273
150642
  }
@@ -150283,11 +150652,11 @@ var xe = class extends Xt {
150283
150652
  return;
150284
150653
  }
150285
150654
  if (t.mtime && !this.noMtime) try {
150286
- import_node_fs13.default.utimesSync(String(t.absolute), t.atime || /* @__PURE__ */ new Date(), t.mtime);
150655
+ import_node_fs14.default.utimesSync(String(t.absolute), t.atime || /* @__PURE__ */ new Date(), t.mtime);
150287
150656
  } catch {
150288
150657
  }
150289
150658
  if (this[ge](t)) try {
150290
- import_node_fs13.default.chownSync(String(t.absolute), Number(this[be](t)), Number(this[_e](t)));
150659
+ import_node_fs14.default.chownSync(String(t.absolute), Number(this[be](t)), Number(this[_e](t)));
150291
150660
  } catch {
150292
150661
  }
150293
150662
  e(), t.resume();
@@ -150303,30 +150672,30 @@ var xe = class extends Xt {
150303
150672
  if (this.preservePaths || i.length === 0) return r();
150304
150673
  let o = e;
150305
150674
  for (let h of i) {
150306
- o = import_node_path18.default.resolve(o, h);
150307
- let [a, l] = ye(() => import_node_fs13.default.lstatSync(o));
150675
+ o = import_node_path19.default.resolve(o, h);
150676
+ let [a, l] = ye(() => import_node_fs14.default.lstatSync(o));
150308
150677
  if (a) return r();
150309
- if (l.isSymbolicLink()) return n(new St(o, import_node_path18.default.resolve(e, i.join("/"))));
150678
+ if (l.isSymbolicLink()) return n(new St(o, import_node_path19.default.resolve(e, i.join("/"))));
150310
150679
  }
150311
150680
  r();
150312
150681
  }
150313
150682
  [gi](t, e, i, r) {
150314
150683
  let n = `${i}Sync`;
150315
150684
  try {
150316
- import_node_fs13.default[n](e, String(t.absolute)), r(), t.resume();
150685
+ import_node_fs14.default[n](e, String(t.absolute)), r(), t.resume();
150317
150686
  } catch (o) {
150318
150687
  return this[O](o, t);
150319
150688
  }
150320
150689
  }
150321
150690
  };
150322
150691
  var Eo = (s3) => {
150323
- let t = new xe(s3), e = s3.file, i = import_node_fs12.default.statSync(e), r = s3.maxReadSize || 16 * 1024 * 1024;
150692
+ let t = new xe(s3), e = s3.file, i = import_node_fs13.default.statSync(e), r = s3.maxReadSize || 16 * 1024 * 1024;
150324
150693
  new Be(e, { readSize: r, size: i.size }).pipe(t);
150325
150694
  };
150326
150695
  var wo = (s3, t) => {
150327
150696
  let e = new Xt(s3), i = s3.maxReadSize || 16 * 1024 * 1024, r = s3.file;
150328
150697
  return new Promise((o, h) => {
150329
- e.on("error", h), e.on("close", o), import_node_fs12.default.stat(r, (a, l) => {
150698
+ e.on("error", h), e.on("close", o), import_node_fs13.default.stat(r, (a, l) => {
150330
150699
  if (a) h(a);
150331
150700
  else {
150332
150701
  let c = new _t(r, { readSize: i, size: l.size });
@@ -150342,15 +150711,15 @@ var yo = (s3, t) => {
150342
150711
  let e = new kt(s3), i = true, r, n;
150343
150712
  try {
150344
150713
  try {
150345
- r = import_node_fs16.default.openSync(s3.file, "r+");
150714
+ r = import_node_fs17.default.openSync(s3.file, "r+");
150346
150715
  } catch (a) {
150347
- if (a?.code === "ENOENT") r = import_node_fs16.default.openSync(s3.file, "w+");
150716
+ if (a?.code === "ENOENT") r = import_node_fs17.default.openSync(s3.file, "w+");
150348
150717
  else throw a;
150349
150718
  }
150350
- let o = import_node_fs16.default.fstatSync(r), h = Buffer.alloc(512);
150719
+ let o = import_node_fs17.default.fstatSync(r), h = Buffer.alloc(512);
150351
150720
  t: for (n = 0; n < o.size; n += 512) {
150352
150721
  for (let c = 0, d = 0; c < 512; c += d) {
150353
- if (d = import_node_fs16.default.readSync(r, h, c, h.length - c, n + c), n === 0 && h[0] === 31 && h[1] === 139) throw new Error("cannot append to compressed archives");
150722
+ if (d = import_node_fs17.default.readSync(r, h, c, h.length - c, n + c), n === 0 && h[0] === 31 && h[1] === 139) throw new Error("cannot append to compressed archives");
150354
150723
  if (!d) break t;
150355
150724
  }
150356
150725
  let a = new F(h);
@@ -150362,7 +150731,7 @@ var yo = (s3, t) => {
150362
150731
  i = false, Ro(s3, e, n, r, t);
150363
150732
  } finally {
150364
150733
  if (i) try {
150365
- import_node_fs16.default.closeSync(r);
150734
+ import_node_fs17.default.closeSync(r);
150366
150735
  } catch {
150367
150736
  }
150368
150737
  }
@@ -150375,29 +150744,29 @@ var go = (s3, t) => {
150375
150744
  t = Array.from(t);
150376
150745
  let e = new wt(s3), i = (n, o, h) => {
150377
150746
  let a = (T2, D) => {
150378
- T2 ? import_node_fs16.default.close(n, (E) => h(T2)) : h(null, D);
150747
+ T2 ? import_node_fs17.default.close(n, (E) => h(T2)) : h(null, D);
150379
150748
  }, l = 0;
150380
150749
  if (o === 0) return a(null, 0);
150381
150750
  let c = 0, d = Buffer.alloc(512), S2 = (T2, D) => {
150382
150751
  if (T2 || D === void 0) return a(T2);
150383
- if (c += D, c < 512 && D) return import_node_fs16.default.read(n, d, c, d.length - c, l + c, S2);
150752
+ if (c += D, c < 512 && D) return import_node_fs17.default.read(n, d, c, d.length - c, l + c, S2);
150384
150753
  if (l === 0 && d[0] === 31 && d[1] === 139) return a(new Error("cannot append to compressed archives"));
150385
150754
  if (c < 512) return a(null, l);
150386
150755
  let E = new F(d);
150387
150756
  if (!E.cksumValid) return a(null, l);
150388
150757
  let x = 512 * Math.ceil((E.size ?? 0) / 512);
150389
150758
  if (l + x + 512 > o || (l += x + 512, l >= o)) return a(null, l);
150390
- s3.mtimeCache && E.mtime && s3.mtimeCache.set(String(E.path), E.mtime), c = 0, import_node_fs16.default.read(n, d, 0, 512, l, S2);
150759
+ s3.mtimeCache && E.mtime && s3.mtimeCache.set(String(E.path), E.mtime), c = 0, import_node_fs17.default.read(n, d, 0, 512, l, S2);
150391
150760
  };
150392
- import_node_fs16.default.read(n, d, 0, 512, l, S2);
150761
+ import_node_fs17.default.read(n, d, 0, 512, l, S2);
150393
150762
  };
150394
150763
  return new Promise((n, o) => {
150395
150764
  e.on("error", o);
150396
150765
  let h = "r+", a = (l, c) => {
150397
- if (l && l.code === "ENOENT" && h === "r+") return h = "w+", import_node_fs16.default.open(s3.file, h, a);
150766
+ if (l && l.code === "ENOENT" && h === "r+") return h = "w+", import_node_fs17.default.open(s3.file, h, a);
150398
150767
  if (l || !c) return o(l);
150399
- import_node_fs16.default.fstat(c, (d, S2) => {
150400
- if (d) return import_node_fs16.default.close(c, () => o(d));
150768
+ import_node_fs17.default.fstat(c, (d, S2) => {
150769
+ if (d) return import_node_fs17.default.close(c, () => o(d));
150401
150770
  i(c, S2.size, (T2, D) => {
150402
150771
  if (T2) return o(T2);
150403
150772
  let E = new et(s3.file, { fd: c, start: D });
@@ -150405,16 +150774,16 @@ var go = (s3, t) => {
150405
150774
  });
150406
150775
  });
150407
150776
  };
150408
- import_node_fs16.default.open(s3.file, h, a);
150777
+ import_node_fs17.default.open(s3.file, h, a);
150409
150778
  });
150410
150779
  };
150411
150780
  var bo = (s3, t) => {
150412
150781
  t.forEach((e) => {
150413
- e.charAt(0) === "@" ? Ct({ file: import_node_path22.default.resolve(s3.cwd, e.slice(1)), sync: true, noResume: true, onReadEntry: (i) => s3.add(i) }) : s3.add(e);
150782
+ e.charAt(0) === "@" ? Ct({ file: import_node_path23.default.resolve(s3.cwd, e.slice(1)), sync: true, noResume: true, onReadEntry: (i) => s3.add(i) }) : s3.add(e);
150414
150783
  }), s3.end();
150415
150784
  };
150416
150785
  var _o = async (s3, t) => {
150417
- for (let e of t) e.charAt(0) === "@" ? await Ct({ file: import_node_path22.default.resolve(String(s3.cwd), e.slice(1)), noResume: true, onReadEntry: (i) => s3.add(i) }) : s3.add(e);
150786
+ for (let e of t) e.charAt(0) === "@" ? await Ct({ file: import_node_path23.default.resolve(String(s3.cwd), e.slice(1)), noResume: true, onReadEntry: (i) => s3.add(i) }) : s3.add(e);
150418
150787
  s3.end();
150419
150788
  };
150420
150789
  var vt = K(yo, go, () => {
@@ -150437,19 +150806,19 @@ var To = (s3) => {
150437
150806
  // src/updater/unpack.ts
150438
150807
  async function unpackTarball(opts) {
150439
150808
  const { tarballPath, destDir } = opts;
150440
- (0, import_node_fs17.rmSync)(destDir, { recursive: true, force: true });
150441
- (0, import_node_fs17.mkdirSync)(destDir, { recursive: true });
150809
+ (0, import_node_fs18.rmSync)(destDir, { recursive: true, force: true });
150810
+ (0, import_node_fs18.mkdirSync)(destDir, { recursive: true });
150442
150811
  await So({ file: tarballPath, cwd: destDir });
150443
150812
  }
150444
150813
 
150445
150814
  // src/updater/update-log.ts
150446
- var import_node_fs18 = require("fs");
150447
- var import_node_path23 = require("path");
150448
- var LOG_PATH = (0, import_node_path23.join)(THREADBASE_ROOT, "update.log");
150815
+ var import_node_fs19 = require("fs");
150816
+ var import_node_path24 = require("path");
150817
+ var LOG_PATH = (0, import_node_path24.join)(THREADBASE_ROOT, "update.log");
150449
150818
  function appendUpdateLog(line) {
150450
150819
  try {
150451
- (0, import_node_fs18.mkdirSync)(THREADBASE_ROOT, { recursive: true });
150452
- (0, import_node_fs18.appendFileSync)(LOG_PATH, `${(/* @__PURE__ */ new Date()).toISOString()} ${line}
150820
+ (0, import_node_fs19.mkdirSync)(THREADBASE_ROOT, { recursive: true });
150821
+ (0, import_node_fs19.appendFileSync)(LOG_PATH, `${(/* @__PURE__ */ new Date()).toISOString()} ${line}
150453
150822
  `, "utf8");
150454
150823
  } catch {
150455
150824
  }
@@ -150520,7 +150889,7 @@ async function runInstall(opts) {
150520
150889
  }
150521
150890
  }
150522
150891
  ensureReleasesDir();
150523
- (0, import_node_fs19.mkdirSync)(DOWNLOAD_DIR, { recursive: true });
150892
+ (0, import_node_fs20.mkdirSync)(DOWNLOAD_DIR, { recursive: true });
150524
150893
  const tarballPath = downloadPath(targetVersion, artifact.filename);
150525
150894
  await downloadAndVerify({ manifest, assets: target.assets, targetPath: tarballPath });
150526
150895
  const destDir = releaseDir(targetVersion);
@@ -150554,7 +150923,7 @@ async function runInstall(opts) {
150554
150923
 
150555
150924
  // cli/prod.ts
150556
150925
  var import_node_child_process6 = require("child_process");
150557
- var import_node_fs21 = require("fs");
150926
+ var import_node_fs22 = require("fs");
150558
150927
  init_constants();
150559
150928
  init_launchd();
150560
150929
  init_marker();
@@ -150640,7 +151009,7 @@ async function runProdDoctor(opts) {
150640
151009
  return { findings, repairs };
150641
151010
  }
150642
151011
  var defaultSpawnTail = ({ files, lines, follow }) => {
150643
- const existing = files.filter((f2) => (0, import_node_fs21.existsSync)(f2));
151012
+ const existing = files.filter((f2) => (0, import_node_fs22.existsSync)(f2));
150644
151013
  if (existing.length === 0) {
150645
151014
  return Promise.resolve({
150646
151015
  ok: false,
@@ -150912,12 +151281,12 @@ program2.command("cache").description("Manage the local SQLite conversation cach
150912
151281
  "Cache directory (default: ~/.threadbase/cache)",
150913
151282
  `${process.env.HOME}/.threadbase/cache`
150914
151283
  ).action((opts) => {
150915
- const { rmSync: rmSync6, existsSync: existsSync12 } = require("fs");
150916
- const { join: join26 } = require("path");
150917
- const dbPath = join26(opts.cacheDir, "cache.db");
151284
+ const { rmSync: rmSync6, existsSync: existsSync13 } = require("fs");
151285
+ const { join: join28 } = require("path");
151286
+ const dbPath = join28(opts.cacheDir, "cache.db");
150918
151287
  for (const suffix of ["", "-shm", "-wal"]) {
150919
151288
  const f2 = dbPath + suffix;
150920
- if (existsSync12(f2)) {
151289
+ if (existsSync13(f2)) {
150921
151290
  rmSync6(f2);
150922
151291
  log7.info(`Deleted ${f2}`, { path: f2 }, "console");
150923
151292
  }