@usepowerplant/cli 0.4.5 → 0.4.7

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.js CHANGED
@@ -6877,19 +6877,19 @@ var require_module_details_from_path = __commonJS({
6877
6877
  basedir += segments[i] + sep2;
6878
6878
  }
6879
6879
  }
6880
- var path27 = "";
6880
+ var path29 = "";
6881
6881
  var lastSegmentIndex = segments.length - 1;
6882
6882
  for (var i2 = index + offset; i2 <= lastSegmentIndex; i2++) {
6883
6883
  if (i2 === lastSegmentIndex) {
6884
- path27 += segments[i2];
6884
+ path29 += segments[i2];
6885
6885
  } else {
6886
- path27 += segments[i2] + sep2;
6886
+ path29 += segments[i2] + sep2;
6887
6887
  }
6888
6888
  }
6889
6889
  return {
6890
6890
  name,
6891
6891
  basedir,
6892
- path: path27
6892
+ path: path29
6893
6893
  };
6894
6894
  };
6895
6895
  }
@@ -6899,7 +6899,7 @@ var require_module_details_from_path = __commonJS({
6899
6899
  var require_require_in_the_middle = __commonJS({
6900
6900
  "../../node_modules/.pnpm/require-in-the-middle@8.0.1/node_modules/require-in-the-middle/index.js"(exports, module2) {
6901
6901
  "use strict";
6902
- var path27 = __require("path");
6902
+ var path29 = __require("path");
6903
6903
  var Module = __require("module");
6904
6904
  var debug2 = require_src3()("require-in-the-middle");
6905
6905
  var moduleDetailsFromPath = require_module_details_from_path();
@@ -7044,7 +7044,7 @@ var require_require_in_the_middle = __commonJS({
7044
7044
  }
7045
7045
  moduleName = filename;
7046
7046
  } else if (hasWhitelist === true && modules.includes(filename)) {
7047
- const parsedPath = path27.parse(filename);
7047
+ const parsedPath = path29.parse(filename);
7048
7048
  moduleName = parsedPath.name;
7049
7049
  basedir = parsedPath.dir;
7050
7050
  } else {
@@ -7082,7 +7082,7 @@ var require_require_in_the_middle = __commonJS({
7082
7082
  }
7083
7083
  if (res !== filename) {
7084
7084
  if (internals === true) {
7085
- moduleName = moduleName + path27.sep + path27.relative(basedir, filename);
7085
+ moduleName = moduleName + path29.sep + path29.relative(basedir, filename);
7086
7086
  debug2("preparing to process require of internal file: %s", moduleName);
7087
7087
  } else {
7088
7088
  debug2("ignoring require of non-main module file: %s", res);
@@ -7118,8 +7118,8 @@ var require_require_in_the_middle = __commonJS({
7118
7118
  }
7119
7119
  };
7120
7120
  function resolveModuleName(stat) {
7121
- const normalizedPath = path27.sep !== "/" ? stat.path.split(path27.sep).join("/") : stat.path;
7122
- return path27.posix.join(stat.name, normalizedPath).replace(normalize3, "");
7121
+ const normalizedPath = path29.sep !== "/" ? stat.path.split(path29.sep).join("/") : stat.path;
7122
+ return path29.posix.join(stat.name, normalizedPath).replace(normalize3, "");
7123
7123
  }
7124
7124
  }
7125
7125
  });
@@ -7204,7 +7204,7 @@ var require_RequireInTheMiddleSingleton = __commonJS({
7204
7204
  Object.defineProperty(exports, "__esModule", { value: true });
7205
7205
  exports.RequireInTheMiddleSingleton = void 0;
7206
7206
  var require_in_the_middle_1 = require_require_in_the_middle();
7207
- var path27 = __require("path");
7207
+ var path29 = __require("path");
7208
7208
  var ModuleNameTrie_1 = require_ModuleNameTrie();
7209
7209
  var isMocha = [
7210
7210
  "afterEach",
@@ -7268,7 +7268,7 @@ var require_RequireInTheMiddleSingleton = __commonJS({
7268
7268
  };
7269
7269
  exports.RequireInTheMiddleSingleton = RequireInTheMiddleSingleton;
7270
7270
  function normalizePathSeparators(moduleNameOrPath) {
7271
- return path27.sep !== ModuleNameTrie_1.ModuleNameSeparator ? moduleNameOrPath.split(path27.sep).join(ModuleNameTrie_1.ModuleNameSeparator) : moduleNameOrPath;
7271
+ return path29.sep !== ModuleNameTrie_1.ModuleNameSeparator ? moduleNameOrPath.split(path29.sep).join(ModuleNameTrie_1.ModuleNameSeparator) : moduleNameOrPath;
7272
7272
  }
7273
7273
  }
7274
7274
  });
@@ -7434,7 +7434,7 @@ var require_register = __commonJS({
7434
7434
  // ../../node_modules/.pnpm/import-in-the-middle@3.4.0/node_modules/import-in-the-middle/index.js
7435
7435
  var require_import_in_the_middle = __commonJS({
7436
7436
  "../../node_modules/.pnpm/import-in-the-middle@3.4.0/node_modules/import-in-the-middle/index.js"(exports, module2) {
7437
- var path27 = __require("path");
7437
+ var path29 = __require("path");
7438
7438
  var moduleDetailsFromPath = require_module_details_from_path();
7439
7439
  var { fileURLToPath: fileURLToPath3 } = __require("url");
7440
7440
  var { MessageChannel } = __require("worker_threads");
@@ -7553,7 +7553,7 @@ var require_import_in_the_middle = __commonJS({
7553
7553
  } else if (baseDir.endsWith(specifiers.get(loadUrl)) || isTurbopackSpecifier(specifiers.get(loadUrl), baseDir)) {
7554
7554
  callHookFn(hookFn, namespace, name, baseDir);
7555
7555
  } else if (internals) {
7556
- const internalPath = name + path27.sep + path27.relative(baseDir, filePath);
7556
+ const internalPath = name + path29.sep + path29.relative(baseDir, filePath);
7557
7557
  callHookFn(hookFn, namespace, internalPath, baseDir);
7558
7558
  }
7559
7559
  } else if (matchArg === specifier) {
@@ -7628,7 +7628,7 @@ var require_instrumentation2 = __commonJS({
7628
7628
  "use strict";
7629
7629
  Object.defineProperty(exports, "__esModule", { value: true });
7630
7630
  exports.InstrumentationBase = void 0;
7631
- var path27 = __require("path");
7631
+ var path29 = __require("path");
7632
7632
  var util_1 = __require("util");
7633
7633
  var semver_1 = require_semver();
7634
7634
  var shimmer_1 = require_shimmer();
@@ -7729,7 +7729,7 @@ var require_instrumentation2 = __commonJS({
7729
7729
  }
7730
7730
  _extractPackageVersion(baseDir) {
7731
7731
  try {
7732
- const json2 = (0, fs_1.readFileSync)(path27.join(baseDir, "package.json"), {
7732
+ const json2 = (0, fs_1.readFileSync)(path29.join(baseDir, "package.json"), {
7733
7733
  encoding: "utf8"
7734
7734
  });
7735
7735
  const version2 = JSON.parse(json2).version;
@@ -7771,7 +7771,7 @@ var require_instrumentation2 = __commonJS({
7771
7771
  return exports2;
7772
7772
  }
7773
7773
  const files = module3.files ?? [];
7774
- const normalizedName = path27.normalize(name);
7774
+ const normalizedName = path29.normalize(name);
7775
7775
  const supportedFileInstrumentations = files.filter((f) => f.name === normalizedName && isSupported(f.supportedVersions, version2, module3.includePrerelease));
7776
7776
  return supportedFileInstrumentations.reduce((patchedExports, file2) => {
7777
7777
  file2.moduleExports = patchedExports;
@@ -7817,8 +7817,8 @@ var require_instrumentation2 = __commonJS({
7817
7817
  this._warnOnPreloadedModules();
7818
7818
  for (const module3 of this._modules) {
7819
7819
  const hookFn = (exports2, name, baseDir) => {
7820
- if (!baseDir && path27.isAbsolute(name)) {
7821
- const parsedPath = path27.parse(name);
7820
+ if (!baseDir && path29.isAbsolute(name)) {
7821
+ const parsedPath = path29.parse(name);
7822
7822
  name = parsedPath.name;
7823
7823
  baseDir = parsedPath.dir;
7824
7824
  }
@@ -7827,7 +7827,7 @@ var require_instrumentation2 = __commonJS({
7827
7827
  const onRequire = (exports2, name, baseDir) => {
7828
7828
  return this._onRequire(module3, exports2, name, baseDir);
7829
7829
  };
7830
- const hook = path27.isAbsolute(module3.name) ? new require_in_the_middle_1.Hook([module3.name], { internals: true }, onRequire) : this._requireInTheMiddleSingleton.register(module3.name, onRequire);
7830
+ const hook = path29.isAbsolute(module3.name) ? new require_in_the_middle_1.Hook([module3.name], { internals: true }, onRequire) : this._requireInTheMiddleSingleton.register(module3.name, onRequire);
7831
7831
  this._hooks.push(hook);
7832
7832
  const esmHook = new import_in_the_middle_1.Hook([module3.name], { internals: true }, hookFn);
7833
7833
  this._hooks.push(esmHook);
@@ -8435,9 +8435,9 @@ var require_getMachineId_linux = __commonJS({
8435
8435
  var api_1 = (init_esm(), __toCommonJS(esm_exports));
8436
8436
  async function getMachineId() {
8437
8437
  const paths = ["/etc/machine-id", "/var/lib/dbus/machine-id"];
8438
- for (const path27 of paths) {
8438
+ for (const path29 of paths) {
8439
8439
  try {
8440
- const result = await fs_1.promises.readFile(path27, { encoding: "utf8" });
8440
+ const result = await fs_1.promises.readFile(path29, { encoding: "utf8" });
8441
8441
  return result.trim();
8442
8442
  } catch (e) {
8443
8443
  api_1.diag.debug(`error reading machine id: ${e}`);
@@ -8643,7 +8643,7 @@ var require_ProcessDetector = __commonJS({
8643
8643
  exports.processDetector = void 0;
8644
8644
  var api_1 = (init_esm(), __toCommonJS(esm_exports));
8645
8645
  var semconv_1 = require_semconv2();
8646
- var os21 = __require("os");
8646
+ var os22 = __require("os");
8647
8647
  var ProcessDetector = class {
8648
8648
  detect(_config) {
8649
8649
  const attributes = {
@@ -8663,7 +8663,7 @@ var require_ProcessDetector = __commonJS({
8663
8663
  attributes[semconv_1.ATTR_PROCESS_COMMAND] = process.argv[1];
8664
8664
  }
8665
8665
  try {
8666
- const userInfo = os21.userInfo();
8666
+ const userInfo = os22.userInfo();
8667
8667
  attributes[semconv_1.ATTR_PROCESS_OWNER] = userInfo.username;
8668
8668
  } catch (e) {
8669
8669
  api_1.diag.debug(`error obtaining process owner: ${e}`);
@@ -11797,14 +11797,14 @@ var require_util = __commonJS({
11797
11797
  }
11798
11798
  const port = url2.port != null ? url2.port : url2.protocol === "https:" ? 443 : 80;
11799
11799
  let origin = url2.origin != null ? url2.origin : `${url2.protocol || ""}//${url2.hostname || ""}:${port}`;
11800
- let path27 = url2.path != null ? url2.path : `${url2.pathname || ""}${url2.search || ""}`;
11800
+ let path29 = url2.path != null ? url2.path : `${url2.pathname || ""}${url2.search || ""}`;
11801
11801
  if (origin[origin.length - 1] === "/") {
11802
11802
  origin = origin.slice(0, origin.length - 1);
11803
11803
  }
11804
- if (path27 && path27[0] !== "/") {
11805
- path27 = `/${path27}`;
11804
+ if (path29 && path29[0] !== "/") {
11805
+ path29 = `/${path29}`;
11806
11806
  }
11807
- return new URL(`${origin}${path27}`);
11807
+ return new URL(`${origin}${path29}`);
11808
11808
  }
11809
11809
  if (!isHttpOrHttpsPrefixed(url2.origin || url2.protocol)) {
11810
11810
  throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`.");
@@ -12625,9 +12625,9 @@ var require_diagnostics = __commonJS({
12625
12625
  "undici:client:sendHeaders",
12626
12626
  (evt) => {
12627
12627
  const {
12628
- request: { method, path: path27, origin }
12628
+ request: { method, path: path29, origin }
12629
12629
  } = evt;
12630
- debugLog3("sending request to %s %s%s", method, origin, path27);
12630
+ debugLog3("sending request to %s %s%s", method, origin, path29);
12631
12631
  }
12632
12632
  );
12633
12633
  }
@@ -12645,14 +12645,14 @@ var require_diagnostics = __commonJS({
12645
12645
  "undici:request:headers",
12646
12646
  (evt) => {
12647
12647
  const {
12648
- request: { method, path: path27, origin },
12648
+ request: { method, path: path29, origin },
12649
12649
  response: { statusCode }
12650
12650
  } = evt;
12651
12651
  debugLog3(
12652
12652
  "received response to %s %s%s - HTTP %d",
12653
12653
  method,
12654
12654
  origin,
12655
- path27,
12655
+ path29,
12656
12656
  statusCode
12657
12657
  );
12658
12658
  }
@@ -12661,23 +12661,23 @@ var require_diagnostics = __commonJS({
12661
12661
  "undici:request:trailers",
12662
12662
  (evt) => {
12663
12663
  const {
12664
- request: { method, path: path27, origin }
12664
+ request: { method, path: path29, origin }
12665
12665
  } = evt;
12666
- debugLog3("trailers received from %s %s%s", method, origin, path27);
12666
+ debugLog3("trailers received from %s %s%s", method, origin, path29);
12667
12667
  }
12668
12668
  );
12669
12669
  diagnosticsChannel9.subscribe(
12670
12670
  "undici:request:error",
12671
12671
  (evt) => {
12672
12672
  const {
12673
- request: { method, path: path27, origin },
12673
+ request: { method, path: path29, origin },
12674
12674
  error: error62
12675
12675
  } = evt;
12676
12676
  debugLog3(
12677
12677
  "request to %s %s%s errored - %s",
12678
12678
  method,
12679
12679
  origin,
12680
- path27,
12680
+ path29,
12681
12681
  error62.message
12682
12682
  );
12683
12683
  }
@@ -12792,7 +12792,7 @@ var require_request = __commonJS({
12792
12792
  var kHandler = /* @__PURE__ */ Symbol("handler");
12793
12793
  var Request2 = class {
12794
12794
  constructor(origin, {
12795
- path: path27,
12795
+ path: path29,
12796
12796
  method,
12797
12797
  body,
12798
12798
  headers,
@@ -12809,11 +12809,11 @@ var require_request = __commonJS({
12809
12809
  maxRedirections,
12810
12810
  typeOfService
12811
12811
  }, handler) {
12812
- if (typeof path27 !== "string") {
12812
+ if (typeof path29 !== "string") {
12813
12813
  throw new InvalidArgumentError("path must be a string");
12814
- } else if (path27[0] !== "/" && !(path27.startsWith("http://") || path27.startsWith("https://")) && method !== "CONNECT") {
12814
+ } else if (path29[0] !== "/" && !(path29.startsWith("http://") || path29.startsWith("https://")) && method !== "CONNECT") {
12815
12815
  throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
12816
- } else if (invalidPathRegex.test(path27)) {
12816
+ } else if (invalidPathRegex.test(path29)) {
12817
12817
  throw new InvalidArgumentError("invalid request path");
12818
12818
  }
12819
12819
  if (typeof method !== "string") {
@@ -12888,7 +12888,7 @@ var require_request = __commonJS({
12888
12888
  this.completed = false;
12889
12889
  this.aborted = false;
12890
12890
  this.upgrade = upgrade || null;
12891
- this.path = query ? serializePathWithQuery(path27, query) : path27;
12891
+ this.path = query ? serializePathWithQuery(path29, query) : path29;
12892
12892
  this.origin = origin;
12893
12893
  this.protocol = getProtocolFromUrlString(origin);
12894
12894
  this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
@@ -17281,7 +17281,7 @@ var require_client_h1 = __commonJS({
17281
17281
  kHTTPContext,
17282
17282
  kClosed
17283
17283
  } = require_symbols();
17284
- var constants2 = require_constants3();
17284
+ var constants3 = require_constants3();
17285
17285
  var EMPTY_BUF = Buffer.alloc(0);
17286
17286
  var FastBuffer = Buffer[Symbol.species];
17287
17287
  var removeAllListeners = util2.removeAllListeners;
@@ -17410,7 +17410,7 @@ var require_client_h1 = __commonJS({
17410
17410
  */
17411
17411
  constructor(client, socket, { exports: exports2 }) {
17412
17412
  this.llhttp = exports2;
17413
- this.ptr = this.llhttp.llhttp_alloc(constants2.TYPE.RESPONSE);
17413
+ this.ptr = this.llhttp.llhttp_alloc(constants3.TYPE.RESPONSE);
17414
17414
  this.client = client;
17415
17415
  this.socket = socket;
17416
17416
  this.timeout = null;
@@ -17506,11 +17506,11 @@ var require_client_h1 = __commonJS({
17506
17506
  currentParser = null;
17507
17507
  currentBufferRef = null;
17508
17508
  }
17509
- if (ret !== constants2.ERROR.OK) {
17509
+ if (ret !== constants3.ERROR.OK) {
17510
17510
  const data = chunk.subarray(llhttp.llhttp_get_error_pos(this.ptr) - currentBufferPtr);
17511
- if (ret === constants2.ERROR.PAUSED_UPGRADE) {
17511
+ if (ret === constants3.ERROR.PAUSED_UPGRADE) {
17512
17512
  this.onUpgrade(data);
17513
- } else if (ret === constants2.ERROR.PAUSED) {
17513
+ } else if (ret === constants3.ERROR.PAUSED) {
17514
17514
  this.paused = true;
17515
17515
  socket.unshift(data);
17516
17516
  } else {
@@ -17533,10 +17533,10 @@ var require_client_h1 = __commonJS({
17533
17533
  } finally {
17534
17534
  currentParser = null;
17535
17535
  }
17536
- if (ret === constants2.ERROR.OK) {
17536
+ if (ret === constants3.ERROR.OK) {
17537
17537
  return null;
17538
17538
  }
17539
- if (ret === constants2.ERROR.PAUSED || ret === constants2.ERROR.PAUSED_UPGRADE) {
17539
+ if (ret === constants3.ERROR.PAUSED || ret === constants3.ERROR.PAUSED_UPGRADE) {
17540
17540
  this.paused = true;
17541
17541
  return null;
17542
17542
  }
@@ -17553,7 +17553,7 @@ var require_client_h1 = __commonJS({
17553
17553
  const len = new Uint8Array(llhttp.memory.buffer, ptr).indexOf(0);
17554
17554
  message2 = "Response does not match the HTTP/1.1 protocol (" + Buffer.from(llhttp.memory.buffer, ptr, len).toString() + ")";
17555
17555
  }
17556
- return new HTTPParserError(message2, constants2.ERROR[ret], data);
17556
+ return new HTTPParserError(message2, constants3.ERROR[ret], data);
17557
17557
  }
17558
17558
  destroy() {
17559
17559
  assert2(currentParser === null);
@@ -17763,7 +17763,7 @@ var require_client_h1 = __commonJS({
17763
17763
  socket[kBlocking] = false;
17764
17764
  client[kResume]();
17765
17765
  }
17766
- return pause ? constants2.ERROR.PAUSED : 0;
17766
+ return pause ? constants3.ERROR.PAUSED : 0;
17767
17767
  }
17768
17768
  /**
17769
17769
  * @param {Buffer} buf
@@ -17789,7 +17789,7 @@ var require_client_h1 = __commonJS({
17789
17789
  }
17790
17790
  this.bytesRead += buf.length;
17791
17791
  if (request2.onData(buf) === false) {
17792
- return constants2.ERROR.PAUSED;
17792
+ return constants3.ERROR.PAUSED;
17793
17793
  }
17794
17794
  return 0;
17795
17795
  }
@@ -17829,13 +17829,13 @@ var require_client_h1 = __commonJS({
17829
17829
  if (socket[kWriting]) {
17830
17830
  assert2(client[kRunning] === 0);
17831
17831
  util2.destroy(socket, new InformationalError("reset"));
17832
- return constants2.ERROR.PAUSED;
17832
+ return constants3.ERROR.PAUSED;
17833
17833
  } else if (!shouldKeepAlive) {
17834
17834
  util2.destroy(socket, new InformationalError("reset"));
17835
- return constants2.ERROR.PAUSED;
17835
+ return constants3.ERROR.PAUSED;
17836
17836
  } else if (socket[kReset] && client[kRunning] === 0) {
17837
17837
  util2.destroy(socket, new InformationalError("reset"));
17838
- return constants2.ERROR.PAUSED;
17838
+ return constants3.ERROR.PAUSED;
17839
17839
  } else if (client[kPipelining] == null || client[kPipelining] === 1) {
17840
17840
  setImmediate(client[kResume]);
17841
17841
  } else {
@@ -18070,7 +18070,7 @@ var require_client_h1 = __commonJS({
18070
18070
  return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT";
18071
18071
  }
18072
18072
  function writeH1(client, request2) {
18073
- const { method, path: path27, host, upgrade, blocking, reset } = request2;
18073
+ const { method, path: path29, host, upgrade, blocking, reset } = request2;
18074
18074
  let { body, headers, contentLength } = request2;
18075
18075
  const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
18076
18076
  if (util2.isFormDataLike(body)) {
@@ -18148,7 +18148,7 @@ var require_client_h1 = __commonJS({
18148
18148
  if (socket.setTypeOfService) {
18149
18149
  socket.setTypeOfService(request2.typeOfService);
18150
18150
  }
18151
- let header = `${method} ${path27} HTTP/1.1\r
18151
+ let header = `${method} ${path29} HTTP/1.1\r
18152
18152
  `;
18153
18153
  if (typeof host === "string") {
18154
18154
  header += `host: ${host}\r
@@ -18827,7 +18827,7 @@ var require_client_h2 = __commonJS({
18827
18827
  const headersTimeout = request2.headersTimeout ?? client[kHeadersTimeout];
18828
18828
  const bodyTimeout = request2.bodyTimeout ?? client[kBodyTimeout];
18829
18829
  const session = client[kHTTP2Session];
18830
- const { method, path: path27, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request2;
18830
+ const { method, path: path29, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request2;
18831
18831
  let { body } = request2;
18832
18832
  if (upgrade != null && upgrade !== "websocket") {
18833
18833
  util2.errorRequest(client, request2, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`));
@@ -18896,7 +18896,7 @@ var require_client_h2 = __commonJS({
18896
18896
  }
18897
18897
  headers[HTTP2_HEADER_METHOD] = "CONNECT";
18898
18898
  headers[HTTP2_HEADER_PROTOCOL] = "websocket";
18899
- headers[HTTP2_HEADER_PATH] = path27;
18899
+ headers[HTTP2_HEADER_PATH] = path29;
18900
18900
  if (protocol === "ws:" || protocol === "wss:") {
18901
18901
  headers[HTTP2_HEADER_SCHEME] = protocol === "ws:" ? "http" : "https";
18902
18902
  } else {
@@ -18938,7 +18938,7 @@ var require_client_h2 = __commonJS({
18938
18938
  stream.setTimeout(headersTimeout);
18939
18939
  return true;
18940
18940
  }
18941
- headers[HTTP2_HEADER_PATH] = path27;
18941
+ headers[HTTP2_HEADER_PATH] = path29;
18942
18942
  headers[HTTP2_HEADER_SCHEME] = protocol === "http:" ? "http" : "https";
18943
18943
  const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
18944
18944
  if (body && typeof body.read === "function") {
@@ -21290,10 +21290,10 @@ var require_proxy_agent = __commonJS({
21290
21290
  };
21291
21291
  const {
21292
21292
  origin,
21293
- path: path27 = "/",
21293
+ path: path29 = "/",
21294
21294
  headers = {}
21295
21295
  } = opts;
21296
- opts.path = origin + path27;
21296
+ opts.path = origin + path29;
21297
21297
  if (!("host" in headers) && !("Host" in headers)) {
21298
21298
  const { host } = new URL(origin);
21299
21299
  headers.host = host;
@@ -23402,20 +23402,20 @@ var require_mock_utils = __commonJS({
23402
23402
  }
23403
23403
  return normalizedQp;
23404
23404
  }
23405
- function safeUrl(path27) {
23406
- if (typeof path27 !== "string") {
23407
- return path27;
23405
+ function safeUrl(path29) {
23406
+ if (typeof path29 !== "string") {
23407
+ return path29;
23408
23408
  }
23409
- const pathSegments = path27.split("?", 3);
23409
+ const pathSegments = path29.split("?", 3);
23410
23410
  if (pathSegments.length !== 2) {
23411
- return path27;
23411
+ return path29;
23412
23412
  }
23413
23413
  const qp = new URLSearchParams(pathSegments.pop());
23414
23414
  qp.sort();
23415
23415
  return [...pathSegments, qp.toString()].join("?");
23416
23416
  }
23417
- function matchKey(mockDispatch2, { path: path27, method, body, headers }) {
23418
- const pathMatch = matchValue(mockDispatch2.path, path27);
23417
+ function matchKey(mockDispatch2, { path: path29, method, body, headers }) {
23418
+ const pathMatch = matchValue(mockDispatch2.path, path29);
23419
23419
  const methodMatch = matchValue(mockDispatch2.method, method);
23420
23420
  const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
23421
23421
  const headersMatch = matchHeaders(mockDispatch2, headers);
@@ -23440,8 +23440,8 @@ var require_mock_utils = __commonJS({
23440
23440
  const basePath = key.query ? serializePathWithQuery(key.path, key.query) : key.path;
23441
23441
  const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
23442
23442
  const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath);
23443
- let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path27, ignoreTrailingSlash }) => {
23444
- return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path27)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path27), resolvedPath);
23443
+ let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path29, ignoreTrailingSlash }) => {
23444
+ return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path29)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path29), resolvedPath);
23445
23445
  });
23446
23446
  if (matchedMockDispatches.length === 0) {
23447
23447
  throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
@@ -23480,19 +23480,19 @@ var require_mock_utils = __commonJS({
23480
23480
  mockDispatches.splice(index, 1);
23481
23481
  }
23482
23482
  }
23483
- function removeTrailingSlash(path27) {
23484
- while (path27.endsWith("/")) {
23485
- path27 = path27.slice(0, -1);
23483
+ function removeTrailingSlash(path29) {
23484
+ while (path29.endsWith("/")) {
23485
+ path29 = path29.slice(0, -1);
23486
23486
  }
23487
- if (path27.length === 0) {
23488
- path27 = "/";
23487
+ if (path29.length === 0) {
23488
+ path29 = "/";
23489
23489
  }
23490
- return path27;
23490
+ return path29;
23491
23491
  }
23492
23492
  function buildKey(opts) {
23493
- const { path: path27, method, body, headers, query } = opts;
23493
+ const { path: path29, method, body, headers, query } = opts;
23494
23494
  return {
23495
- path: path27,
23495
+ path: path29,
23496
23496
  method,
23497
23497
  body,
23498
23498
  headers,
@@ -24182,10 +24182,10 @@ var require_pending_interceptors_formatter = __commonJS({
24182
24182
  }
24183
24183
  format(pendingInterceptors) {
24184
24184
  const withPrettyHeaders = pendingInterceptors.map(
24185
- ({ method, path: path27, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
24185
+ ({ method, path: path29, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
24186
24186
  Method: method,
24187
24187
  Origin: origin,
24188
- Path: path27,
24188
+ Path: path29,
24189
24189
  "Status code": statusCode,
24190
24190
  Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
24191
24191
  Invocations: timesInvoked,
@@ -24267,9 +24267,9 @@ var require_mock_agent = __commonJS({
24267
24267
  const acceptNonStandardSearchParameters = this[kMockAgentAcceptsNonStandardSearchParameters];
24268
24268
  const dispatchOpts = { ...opts };
24269
24269
  if (acceptNonStandardSearchParameters && dispatchOpts.path) {
24270
- const [path27, searchParams] = dispatchOpts.path.split("?");
24270
+ const [path29, searchParams] = dispatchOpts.path.split("?");
24271
24271
  const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters);
24272
- dispatchOpts.path = `${path27}?${normalizedSearchParams}`;
24272
+ dispatchOpts.path = `${path29}?${normalizedSearchParams}`;
24273
24273
  }
24274
24274
  return this[kAgent].dispatch(dispatchOpts, handler);
24275
24275
  }
@@ -24670,12 +24670,12 @@ var require_snapshot_recorder = __commonJS({
24670
24670
  * @return {Promise<void>} - Resolves when snapshots are loaded
24671
24671
  */
24672
24672
  async loadSnapshots(filePath) {
24673
- const path27 = filePath || this.#snapshotPath;
24674
- if (!path27) {
24673
+ const path29 = filePath || this.#snapshotPath;
24674
+ if (!path29) {
24675
24675
  throw new InvalidArgumentError("Snapshot path is required");
24676
24676
  }
24677
24677
  try {
24678
- const data = await readFile3(resolve2(path27), "utf8");
24678
+ const data = await readFile3(resolve2(path29), "utf8");
24679
24679
  const parsed = JSON.parse(data);
24680
24680
  if (Array.isArray(parsed)) {
24681
24681
  this.#snapshots.clear();
@@ -24689,7 +24689,7 @@ var require_snapshot_recorder = __commonJS({
24689
24689
  if (error62.code === "ENOENT") {
24690
24690
  this.#snapshots.clear();
24691
24691
  } else {
24692
- throw new UndiciError(`Failed to load snapshots from ${path27}`, { cause: error62 });
24692
+ throw new UndiciError(`Failed to load snapshots from ${path29}`, { cause: error62 });
24693
24693
  }
24694
24694
  }
24695
24695
  }
@@ -24700,11 +24700,11 @@ var require_snapshot_recorder = __commonJS({
24700
24700
  * @returns {Promise<void>} - Resolves when snapshots are saved
24701
24701
  */
24702
24702
  async saveSnapshots(filePath) {
24703
- const path27 = filePath || this.#snapshotPath;
24704
- if (!path27) {
24703
+ const path29 = filePath || this.#snapshotPath;
24704
+ if (!path29) {
24705
24705
  throw new InvalidArgumentError("Snapshot path is required");
24706
24706
  }
24707
- const resolvedPath = resolve2(path27);
24707
+ const resolvedPath = resolve2(path29);
24708
24708
  await mkdir(dirname2(resolvedPath), { recursive: true });
24709
24709
  const data = Array.from(this.#snapshots.entries()).map(([hash2, snapshot]) => ({
24710
24710
  hash: hash2,
@@ -25336,15 +25336,15 @@ var require_redirect_handler = __commonJS({
25336
25336
  return;
25337
25337
  }
25338
25338
  const { origin, pathname, search } = util2.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
25339
- const path27 = search ? `${pathname}${search}` : pathname;
25340
- const redirectUrlString = `${origin}${path27}`;
25339
+ const path29 = search ? `${pathname}${search}` : pathname;
25340
+ const redirectUrlString = `${origin}${path29}`;
25341
25341
  for (const historyUrl of this.history) {
25342
25342
  if (historyUrl.toString() === redirectUrlString) {
25343
25343
  throw new InvalidArgumentError(`Redirect loop detected. Cannot redirect to ${origin}. This typically happens when using a Client or Pool with cross-origin redirects. Use an Agent for cross-origin redirects.`);
25344
25344
  }
25345
25345
  }
25346
25346
  this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
25347
- this.opts.path = path27;
25347
+ this.opts.path = path29;
25348
25348
  this.opts.origin = origin;
25349
25349
  this.opts.query = null;
25350
25350
  }
@@ -27104,10 +27104,10 @@ var require_cache_handler = __commonJS({
27104
27104
  }
27105
27105
  return locationUrl.pathname + locationUrl.search;
27106
27106
  }
27107
- function deleteCachedUri(store, cacheKey, path27) {
27107
+ function deleteCachedUri(store, cacheKey, path29) {
27108
27108
  deleteCachedValue(store, {
27109
27109
  ...cacheKey,
27110
- path: path27
27110
+ path: path29
27111
27111
  });
27112
27112
  for (let i = 0; i < util2.safeHTTPMethods.length; i++) {
27113
27113
  const method = util2.safeHTTPMethods[i];
@@ -27115,7 +27115,7 @@ var require_cache_handler = __commonJS({
27115
27115
  deleteCachedValue(store, {
27116
27116
  ...cacheKey,
27117
27117
  method,
27118
- path: path27
27118
+ path: path29
27119
27119
  });
27120
27120
  }
27121
27121
  }
@@ -27126,9 +27126,9 @@ var require_cache_handler = __commonJS({
27126
27126
  }
27127
27127
  const values = Array.isArray(headerValue) ? headerValue : [headerValue];
27128
27128
  for (let i = 0; i < values.length; i++) {
27129
- const path27 = getSameOriginPath(cacheKey, values[i]);
27130
- if (path27 !== void 0) {
27131
- deleteCachedUri(store, cacheKey, path27);
27129
+ const path29 = getSameOriginPath(cacheKey, values[i]);
27130
+ if (path29 !== void 0) {
27131
+ deleteCachedUri(store, cacheKey, path29);
27132
27132
  }
27133
27133
  }
27134
27134
  }
@@ -32128,11 +32128,11 @@ var require_fetch = __commonJS({
32128
32128
  function dispatch({ body }) {
32129
32129
  const url2 = requestCurrentURL(request2);
32130
32130
  const agent = fetchParams.controller.dispatcher;
32131
- const path27 = url2.pathname + url2.search;
32131
+ const path29 = url2.pathname + url2.search;
32132
32132
  const hasTrailingQuestionMark = url2.search.length === 0 && url2.href[url2.href.length - url2.hash.length - 1] === "?";
32133
32133
  return new Promise((resolve2, reject) => agent.dispatch(
32134
32134
  {
32135
- path: hasTrailingQuestionMark ? `${path27}?` : path27,
32135
+ path: hasTrailingQuestionMark ? `${path29}?` : path29,
32136
32136
  origin: url2.origin,
32137
32137
  method: request2.method,
32138
32138
  body: agent.isMockActive ? request2.body && (request2.body.source || request2.body.stream) : body,
@@ -33079,9 +33079,9 @@ var require_util4 = __commonJS({
33079
33079
  }
33080
33080
  }
33081
33081
  }
33082
- function validateCookiePath(path27) {
33083
- for (let i = 0; i < path27.length; ++i) {
33084
- const code = path27.charCodeAt(i);
33082
+ function validateCookiePath(path29) {
33083
+ for (let i = 0; i < path29.length; ++i) {
33084
+ const code = path29.charCodeAt(i);
33085
33085
  if (code < 32 || // exclude CTLs (0-31)
33086
33086
  code > 126 || // exclude DEL and non-ascii
33087
33087
  code === 59) {
@@ -36429,11 +36429,11 @@ var require_undici = __commonJS({
36429
36429
  if (typeof opts.path !== "string") {
36430
36430
  throw new InvalidArgumentError("invalid opts.path");
36431
36431
  }
36432
- let path27 = opts.path;
36432
+ let path29 = opts.path;
36433
36433
  if (!opts.path.startsWith("/")) {
36434
- path27 = `/${path27}`;
36434
+ path29 = `/${path29}`;
36435
36435
  }
36436
- url2 = new URL(util2.parseOrigin(url2).origin + path27);
36436
+ url2 = new URL(util2.parseOrigin(url2).origin + path29);
36437
36437
  } else {
36438
36438
  if (!opts) {
36439
36439
  opts = typeof url2 === "object" ? url2 : {};
@@ -36542,11 +36542,8 @@ ${captureLines}` : capture.stack;
36542
36542
  }
36543
36543
  });
36544
36544
 
36545
- // src/cli.ts
36546
- import { spawn as spawn2, spawnSync as spawnSync5 } from "node:child_process";
36547
- import { existsSync as existsSync12, mkdirSync as mkdirSync11, openSync as openSync5, realpathSync as realpathSync4, rmSync as rmSync6 } from "node:fs";
36548
- import path26 from "node:path";
36549
- import { parseArgs } from "node:util";
36545
+ // src/clientFailure.ts
36546
+ import { constants } from "node:os";
36550
36547
 
36551
36548
  // ../../apps/collector/src/credentials.ts
36552
36549
  import { execFileSync } from "node:child_process";
@@ -37298,10 +37295,10 @@ function mergeDefs(...defs) {
37298
37295
  function cloneDef(schema) {
37299
37296
  return mergeDefs(schema._zod.def);
37300
37297
  }
37301
- function getElementAtPath(obj, path27) {
37302
- if (!path27)
37298
+ function getElementAtPath(obj, path29) {
37299
+ if (!path29)
37303
37300
  return obj;
37304
- return path27.reduce((acc, key) => acc?.[key], obj);
37301
+ return path29.reduce((acc, key) => acc?.[key], obj);
37305
37302
  }
37306
37303
  function promiseAllObject(promisesObj) {
37307
37304
  const keys = Object.keys(promisesObj);
@@ -37713,11 +37710,11 @@ function explicitlyAborted(x, startIndex = 0) {
37713
37710
  }
37714
37711
  return false;
37715
37712
  }
37716
- function prefixIssues(path27, issues) {
37713
+ function prefixIssues(path29, issues) {
37717
37714
  return issues.map((iss) => {
37718
37715
  var _a4;
37719
37716
  (_a4 = iss).path ?? (_a4.path = []);
37720
- iss.path.unshift(path27);
37717
+ iss.path.unshift(path29);
37721
37718
  return iss;
37722
37719
  });
37723
37720
  }
@@ -38150,16 +38147,16 @@ function flattenError(error62, mapper = (issue2) => issue2.message) {
38150
38147
  }
38151
38148
  function formatError(error62, mapper = (issue2) => issue2.message) {
38152
38149
  const fieldErrors = { _errors: [] };
38153
- const processError = (error63, path27 = []) => {
38150
+ const processError = (error63, path29 = []) => {
38154
38151
  for (const issue2 of error63.issues) {
38155
38152
  if (issue2.code === "invalid_union" && issue2.errors.length) {
38156
- issue2.errors.map((issues) => processError({ issues }, [...path27, ...issue2.path]));
38153
+ issue2.errors.map((issues) => processError({ issues }, [...path29, ...issue2.path]));
38157
38154
  } else if (issue2.code === "invalid_key") {
38158
- processError({ issues: issue2.issues }, [...path27, ...issue2.path]);
38155
+ processError({ issues: issue2.issues }, [...path29, ...issue2.path]);
38159
38156
  } else if (issue2.code === "invalid_element") {
38160
- processError({ issues: issue2.issues }, [...path27, ...issue2.path]);
38157
+ processError({ issues: issue2.issues }, [...path29, ...issue2.path]);
38161
38158
  } else {
38162
- const fullpath = [...path27, ...issue2.path];
38159
+ const fullpath = [...path29, ...issue2.path];
38163
38160
  if (fullpath.length === 0) {
38164
38161
  fieldErrors._errors.push(mapper(issue2));
38165
38162
  } else {
@@ -38198,17 +38195,17 @@ function formatError(error62, mapper = (issue2) => issue2.message) {
38198
38195
  }
38199
38196
  function treeifyError(error62, mapper = (issue2) => issue2.message) {
38200
38197
  const result = { errors: [] };
38201
- const processError = (error63, path27 = []) => {
38198
+ const processError = (error63, path29 = []) => {
38202
38199
  var _a4;
38203
38200
  for (const issue2 of error63.issues) {
38204
38201
  if (issue2.code === "invalid_union" && issue2.errors.length) {
38205
- issue2.errors.map((issues) => processError({ issues }, [...path27, ...issue2.path]));
38202
+ issue2.errors.map((issues) => processError({ issues }, [...path29, ...issue2.path]));
38206
38203
  } else if (issue2.code === "invalid_key") {
38207
- processError({ issues: issue2.issues }, [...path27, ...issue2.path]);
38204
+ processError({ issues: issue2.issues }, [...path29, ...issue2.path]);
38208
38205
  } else if (issue2.code === "invalid_element") {
38209
- processError({ issues: issue2.issues }, [...path27, ...issue2.path]);
38206
+ processError({ issues: issue2.issues }, [...path29, ...issue2.path]);
38210
38207
  } else {
38211
- const fullpath = [...path27, ...issue2.path];
38208
+ const fullpath = [...path29, ...issue2.path];
38212
38209
  if (fullpath.length === 0) {
38213
38210
  result.errors.push(mapper(issue2));
38214
38211
  continue;
@@ -38247,8 +38244,8 @@ function treeifyError(error62, mapper = (issue2) => issue2.message) {
38247
38244
  }
38248
38245
  function toDotPath(_path) {
38249
38246
  const segs = [];
38250
- const path27 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
38251
- for (const seg of path27) {
38247
+ const path29 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
38248
+ for (const seg of path29) {
38252
38249
  if (typeof seg === "number")
38253
38250
  segs.push(`[${seg}]`);
38254
38251
  else if (typeof seg === "symbol")
@@ -54758,13 +54755,13 @@ function resolveRef(ref, ctx) {
54758
54755
  if (!ref.startsWith("#")) {
54759
54756
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
54760
54757
  }
54761
- const path27 = ref.slice(1).split("/").filter(Boolean);
54762
- if (path27.length === 0) {
54758
+ const path29 = ref.slice(1).split("/").filter(Boolean);
54759
+ if (path29.length === 0) {
54763
54760
  return ctx.rootSchema;
54764
54761
  }
54765
54762
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
54766
- if (path27[0] === defsKey) {
54767
- const key = path27[1] === void 0 ? void 0 : decodeJSONPointerSegment(path27[1]);
54763
+ if (path29[0] === defsKey) {
54764
+ const key = path29[1] === void 0 ? void 0 : decodeJSONPointerSegment(path29[1]);
54768
54765
  if (!key || !ctx.defs[key]) {
54769
54766
  throw new Error(`Reference not found: ${ref}`);
54770
54767
  }
@@ -55703,10 +55700,21 @@ function createDigestTurnParser(options = {}) {
55703
55700
  const turns = [];
55704
55701
  let pendingTools = [];
55705
55702
  let pendingUsage = null;
55703
+ let pendingAt = null;
55706
55704
  let currentId = null;
55707
55705
  let currentCarrier = null;
55708
55706
  let currentBase = null;
55709
55707
  let currentCounted = false;
55708
+ const envelopes = [];
55709
+ let pendingEnvelopes = [];
55710
+ let currentEnvelope = null;
55711
+ const landPending = (turn) => {
55712
+ for (const envelope of pendingEnvelopes) {
55713
+ envelope.turn = turn;
55714
+ envelopes.push(envelope);
55715
+ }
55716
+ pendingEnvelopes = [];
55717
+ };
55710
55718
  return {
55711
55719
  pushLine(line) {
55712
55720
  const trimmed = line.trim();
@@ -55720,14 +55728,16 @@ function createDigestTurnParser(options = {}) {
55720
55728
  return;
55721
55729
  }
55722
55730
  if (record2.isMeta === true) return;
55731
+ const at = recordTime(record2);
55723
55732
  if (record2.type === "user") {
55724
55733
  const text = userText(record2);
55725
- if (text) turns.push({ kind: "human_prompt", text, toolCalls: [], usage: null });
55734
+ if (text) turns.push({ kind: "human_prompt", text, toolCalls: [], usage: null, at });
55726
55735
  return;
55727
55736
  }
55728
55737
  if (record2.type !== "assistant") return;
55729
55738
  const message2 = record2.message;
55730
55739
  if (!message2 || message2.model === "<synthetic>" || !Array.isArray(message2.content)) return;
55740
+ pendingAt ??= at;
55731
55741
  const id = messageIdOf(record2, message2);
55732
55742
  if (id === null || id !== currentId) {
55733
55743
  currentId = id;
@@ -55741,12 +55751,17 @@ function createDigestTurnParser(options = {}) {
55741
55751
  const updated = mergeUsage(currentBase, parsedUsage);
55742
55752
  if (currentCarrier) currentCarrier.usage = updated;
55743
55753
  else pendingUsage = updated;
55754
+ if (currentEnvelope) currentEnvelope.usage = parsedUsage;
55744
55755
  } else if (currentCarrier) {
55745
55756
  currentCarrier.usage = mergeUsage(currentCarrier.usage, parsedUsage);
55746
55757
  currentCounted = true;
55758
+ currentEnvelope = { turn: turns.indexOf(currentCarrier), at, usage: parsedUsage };
55759
+ envelopes.push(currentEnvelope);
55747
55760
  } else {
55748
55761
  pendingUsage = mergeUsage(pendingUsage, parsedUsage);
55749
55762
  currentCounted = true;
55763
+ currentEnvelope = { turn: -1, at, usage: parsedUsage };
55764
+ pendingEnvelopes.push(currentEnvelope);
55750
55765
  }
55751
55766
  }
55752
55767
  const model = typeof message2.model === "string" ? message2.model : null;
@@ -55761,32 +55776,50 @@ function createDigestTurnParser(options = {}) {
55761
55776
  }
55762
55777
  if (part.type === "text" && typeof part.text === "string" && part.text.trim() !== "") {
55763
55778
  if (currentCarrier === null) {
55764
- const turn = { kind: "agent_text", text: part.text, toolCalls: pendingTools, usage: pendingUsage };
55779
+ const turn = {
55780
+ kind: "agent_text",
55781
+ text: part.text,
55782
+ toolCalls: pendingTools,
55783
+ usage: pendingUsage,
55784
+ at: pendingAt
55785
+ };
55765
55786
  turns.push(turn);
55766
55787
  currentCarrier = turn;
55767
55788
  pendingUsage = null;
55789
+ landPending(turns.length - 1);
55768
55790
  } else {
55769
55791
  turns.push({
55770
55792
  kind: "agent_text",
55771
55793
  text: part.text,
55772
55794
  toolCalls: pendingTools,
55773
- usage: currentCounted ? zeroUsage(model) : null
55795
+ usage: currentCounted ? zeroUsage(model) : null,
55796
+ // A sibling block of the same record began when the record did.
55797
+ at: pendingAt ?? at
55774
55798
  });
55775
55799
  }
55776
55800
  pendingTools = [];
55801
+ pendingAt = null;
55777
55802
  }
55778
55803
  }
55779
55804
  },
55780
55805
  finish() {
55781
55806
  if (pendingTools.length > 0 || pendingUsage !== null) {
55782
- turns.push({ kind: "agent_text", text: "", toolCalls: pendingTools, usage: pendingUsage });
55807
+ turns.push({ kind: "agent_text", text: "", toolCalls: pendingTools, usage: pendingUsage, at: pendingAt });
55808
+ landPending(turns.length - 1);
55783
55809
  pendingTools = [];
55784
55810
  pendingUsage = null;
55811
+ pendingAt = null;
55785
55812
  }
55786
55813
  return turns;
55814
+ },
55815
+ usageEnvelopes() {
55816
+ return envelopes;
55787
55817
  }
55788
55818
  };
55789
55819
  }
55820
+ function recordTime(record2) {
55821
+ return typeof record2.timestamp === "string" && record2.timestamp !== "" ? record2.timestamp : null;
55822
+ }
55790
55823
  function isRecord(value) {
55791
55824
  return value !== null && typeof value === "object" && !Array.isArray(value);
55792
55825
  }
@@ -55923,10 +55956,12 @@ function promptText(content) {
55923
55956
  function createCodexTurnParser(options = {}) {
55924
55957
  const turns = [];
55925
55958
  let pendingTools = [];
55959
+ let pendingAt = null;
55926
55960
  const flushPendingTools = () => {
55927
55961
  if (pendingTools.length === 0) return;
55928
- turns.push({ kind: "agent_text", text: "", toolCalls: pendingTools, usage: null });
55962
+ turns.push({ kind: "agent_text", text: "", toolCalls: pendingTools, usage: null, at: pendingAt });
55929
55963
  pendingTools = [];
55964
+ pendingAt = null;
55930
55965
  };
55931
55966
  return {
55932
55967
  pushLine(line) {
@@ -55941,6 +55976,7 @@ function createCodexTurnParser(options = {}) {
55941
55976
  return;
55942
55977
  }
55943
55978
  if (record2.type !== "response_item") return;
55979
+ const at = typeof record2.timestamp === "string" && record2.timestamp !== "" ? record2.timestamp : null;
55944
55980
  const item = record2.payload;
55945
55981
  if (item === null || typeof item !== "object" || Array.isArray(item)) return;
55946
55982
  const responseItem = item;
@@ -55952,6 +55988,7 @@ function createCodexTurnParser(options = {}) {
55952
55988
  if (args !== null) call.input = boundedToolInput(args);
55953
55989
  }
55954
55990
  pendingTools.push(call);
55991
+ pendingAt ??= at;
55955
55992
  return;
55956
55993
  }
55957
55994
  if (responseItem.type !== "message") return;
@@ -55959,15 +55996,16 @@ function createCodexTurnParser(options = {}) {
55959
55996
  const text2 = promptText(responseItem.content);
55960
55997
  if (text2 !== null) {
55961
55998
  flushPendingTools();
55962
- turns.push({ kind: "human_prompt", text: text2, toolCalls: [], usage: null });
55999
+ turns.push({ kind: "human_prompt", text: text2, toolCalls: [], usage: null, at });
55963
56000
  }
55964
56001
  return;
55965
56002
  }
55966
56003
  if (responseItem.role !== "assistant") return;
55967
56004
  const text = outputTextBlocks(responseItem.content).join("\n");
55968
56005
  if (text.trim() === "") return;
55969
- turns.push({ kind: "agent_text", text, toolCalls: pendingTools, usage: null });
56006
+ turns.push({ kind: "agent_text", text, toolCalls: pendingTools, usage: null, at: pendingAt ?? at });
55970
56007
  pendingTools = [];
56008
+ pendingAt = null;
55971
56009
  },
55972
56010
  finish() {
55973
56011
  flushPendingTools();
@@ -55980,10 +56018,12 @@ function createCodexTurnParser(options = {}) {
55980
56018
  function createCursorTurnParser(options = {}) {
55981
56019
  const turns = [];
55982
56020
  let pendingTools = [];
56021
+ let pendingAt = null;
55983
56022
  const flushPendingTools = () => {
55984
56023
  if (pendingTools.length === 0) return;
55985
- turns.push({ kind: "agent_text", text: "", toolCalls: pendingTools, usage: null });
56024
+ turns.push({ kind: "agent_text", text: "", toolCalls: pendingTools, usage: null, at: pendingAt });
55986
56025
  pendingTools = [];
56026
+ pendingAt = null;
55987
56027
  };
55988
56028
  return {
55989
56029
  pushLine(line) {
@@ -55997,9 +56037,10 @@ function createCursorTurnParser(options = {}) {
55997
56037
  } catch {
55998
56038
  return;
55999
56039
  }
56040
+ const at = typeof record2.createdAt === "string" && record2.createdAt !== "" ? record2.createdAt : null;
56000
56041
  if (record2.type === "user" && typeof record2.text === "string" && record2.text.trim() !== "") {
56001
56042
  flushPendingTools();
56002
- turns.push({ kind: "human_prompt", text: record2.text, toolCalls: [], usage: null });
56043
+ turns.push({ kind: "human_prompt", text: record2.text, toolCalls: [], usage: null, at });
56003
56044
  return;
56004
56045
  }
56005
56046
  if (record2.type === "tool" && typeof record2.name === "string") {
@@ -56009,11 +56050,13 @@ function createCursorTurnParser(options = {}) {
56009
56050
  call.input = boundedToolInput(record2.args);
56010
56051
  }
56011
56052
  pendingTools.push(call);
56053
+ pendingAt ??= at;
56012
56054
  return;
56013
56055
  }
56014
56056
  if (record2.type === "agent" && typeof record2.text === "string" && record2.text.trim() !== "") {
56015
- turns.push({ kind: "agent_text", text: record2.text, toolCalls: pendingTools, usage: null });
56057
+ turns.push({ kind: "agent_text", text: record2.text, toolCalls: pendingTools, usage: null, at: pendingAt ?? at });
56016
56058
  pendingTools = [];
56059
+ pendingAt = null;
56017
56060
  }
56018
56061
  },
56019
56062
  finish() {
@@ -56053,8 +56096,8 @@ function primaryArg(args) {
56053
56096
  function readFilePath(name, primary) {
56054
56097
  if (!primary || !READ_TOOLS.has(name)) return null;
56055
56098
  if (ARTIFACT_PATH_RE.test(primary)) return null;
56056
- const path27 = primary.startsWith("/workspace/") ? primary.slice("/workspace/".length) : primary;
56057
- return path27.length > 0 ? path27 : null;
56099
+ const path29 = primary.startsWith("/workspace/") ? primary.slice("/workspace/".length) : primary;
56100
+ return path29.length > 0 ? path29 : null;
56058
56101
  }
56059
56102
  function asRecord3(value) {
56060
56103
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
@@ -56079,7 +56122,7 @@ function parseCursorRunEventsDetailed(runs, options = {}) {
56079
56122
  let text = "";
56080
56123
  const flush2 = () => {
56081
56124
  if (text !== "" || pendingTools.length > 0 || pendingTokens > 0) {
56082
- turns.push({ kind: "agent_text", text, toolCalls: pendingTools, usage: null });
56125
+ turns.push({ kind: "agent_text", text, toolCalls: pendingTools, usage: null, at: null });
56083
56126
  turnTokens.push(pendingTokens);
56084
56127
  }
56085
56128
  text = "";
@@ -56129,7 +56172,7 @@ function parseCursorRunEventsDetailed(runs, options = {}) {
56129
56172
  const prompt = stringField(asRecord3(data?.userMessage), "text");
56130
56173
  if (!prompt) continue;
56131
56174
  if (text !== "") flush2();
56132
- turns.push({ kind: "human_prompt", text: prompt, toolCalls: [], usage: null });
56175
+ turns.push({ kind: "human_prompt", text: prompt, toolCalls: [], usage: null, at: null });
56133
56176
  turnTokens.push(0);
56134
56177
  continue;
56135
56178
  }
@@ -56186,10 +56229,16 @@ function normalizeUrl(raw) {
56186
56229
 
56187
56230
  // ../core/src/sessionTurns.ts
56188
56231
  function parseSessionTurns(source, transcript, options = {}) {
56189
- if (source === "cursor-cloud") return parseCursorRunEvents(envelopeRuns(transcript), options);
56232
+ return parseSessionTurnsDetailed(source, transcript, options).turns;
56233
+ }
56234
+ function parseSessionTurnsDetailed(source, transcript, options = {}) {
56235
+ if (source === "cursor-cloud") {
56236
+ return { turns: parseCursorRunEvents(envelopeRuns(transcript), options), envelopes: [] };
56237
+ }
56190
56238
  const parser = createSessionTurnParser(source, options);
56191
56239
  for (const line of transcript.split("\n")) parser.pushLine(line);
56192
- return parser.finish();
56240
+ const turns = parser.finish();
56241
+ return { turns, envelopes: parser.usageEnvelopes?.() ?? [] };
56193
56242
  }
56194
56243
  function createSessionTurnParser(source, options = {}) {
56195
56244
  if (source === "codex") return createCodexTurnParser(options);
@@ -56461,6 +56510,21 @@ var HARNESS_SESSION_RULES = {
56461
56510
  evidence: external_exports.object({ thread_source: external_exports.enum(["subagent", "guardian_review"]) })
56462
56511
  },
56463
56512
  { fact: "subagent", evidence: external_exports.object({ source: external_exports.object({ subagent: external_exports.object({}) }) }) },
56513
+ {
56514
+ fact: "standaloneReview",
56515
+ evidence: external_exports.object({
56516
+ source: external_exports.literal("exec"),
56517
+ thread_source: external_exports.literal("user"),
56518
+ // The adapter supplies the record immediately after session_meta.
56519
+ initialEvent: external_exports.object({
56520
+ type: external_exports.literal("event_msg"),
56521
+ payload: external_exports.object({
56522
+ type: external_exports.literal("item_completed"),
56523
+ item: external_exports.object({ type: external_exports.literal("EnteredReviewMode") })
56524
+ })
56525
+ })
56526
+ })
56527
+ },
56464
56528
  { fact: "archived", evidence: external_exports.object({ archived: trueFlag }) }
56465
56529
  ],
56466
56530
  cursor: [
@@ -56668,8 +56732,8 @@ function getFunctionName(fn) {
56668
56732
  return defaultFunctionName;
56669
56733
  }
56670
56734
  }
56671
- function normalizeStackTracePath(path27) {
56672
- let filename = path27?.startsWith("file://") ? path27.slice(7) : path27;
56735
+ function normalizeStackTracePath(path29) {
56736
+ let filename = path29?.startsWith("file://") ? path29.slice(7) : path29;
56673
56737
  if (filename?.match(/\/[A-Z]:/)) {
56674
56738
  filename = filename.slice(1);
56675
56739
  }
@@ -58479,8 +58543,8 @@ function isValidProtocol(protocol) {
58479
58543
  return protocol === "http" || protocol === "https";
58480
58544
  }
58481
58545
  function dsnToString(dsn, withPassword = false) {
58482
- const { host, path: path27, pass, port, projectId, protocol, publicKey } = dsn;
58483
- return `${protocol}://${publicKey}${withPassword && pass ? `:${pass}` : ""}@${host}${port ? `:${port}` : ""}/${path27 ? `${path27}/` : path27}${projectId}`;
58546
+ const { host, path: path29, pass, port, projectId, protocol, publicKey } = dsn;
58547
+ return `${protocol}://${publicKey}${withPassword && pass ? `:${pass}` : ""}@${host}${port ? `:${port}` : ""}/${path29 ? `${path29}/` : path29}${projectId}`;
58484
58548
  }
58485
58549
  function dsnFromString(str) {
58486
58550
  const match = DSN_REGEX.exec(str);
@@ -58491,11 +58555,11 @@ function dsnFromString(str) {
58491
58555
  return void 0;
58492
58556
  }
58493
58557
  const [protocol, publicKey, pass = "", host = "", port = "", lastPath = ""] = match.slice(1);
58494
- let path27 = "";
58558
+ let path29 = "";
58495
58559
  let projectId = lastPath;
58496
58560
  const split = projectId.split("/");
58497
58561
  if (split.length > 1) {
58498
- path27 = split.slice(0, -1).join("/");
58562
+ path29 = split.slice(0, -1).join("/");
58499
58563
  projectId = split.pop();
58500
58564
  }
58501
58565
  if (projectId) {
@@ -58504,7 +58568,7 @@ function dsnFromString(str) {
58504
58568
  projectId = projectMatch[0];
58505
58569
  }
58506
58570
  }
58507
- return dsnFromComponents({ host, pass, path: path27, projectId, port, protocol, publicKey });
58571
+ return dsnFromComponents({ host, pass, path: path29, projectId, port, protocol, publicKey });
58508
58572
  }
58509
58573
  function dsnFromComponents(components) {
58510
58574
  return {
@@ -63038,9 +63102,9 @@ function stripUrlQueryAndFragment(urlPath) {
63038
63102
  return urlPath.split(/[?#]/, 1)[0];
63039
63103
  }
63040
63104
  function getSanitizedUrlString(url2) {
63041
- const { protocol, host, path: path27 } = url2;
63105
+ const { protocol, host, path: path29 } = url2;
63042
63106
  const filteredHost = host?.replace(/^.*@/, "[filtered]:[filtered]@").replace(/(:80)$/, "").replace(/(:443)$/, "") || "";
63043
- return `${protocol ? `${protocol}://` : ""}${filteredHost}${path27}`;
63107
+ return `${protocol ? `${protocol}://` : ""}${filteredHost}${path29}`;
63044
63108
  }
63045
63109
  function stripDataUrlContent(url2, includeDataPrefix = true) {
63046
63110
  if (url2.startsWith("data:")) {
@@ -63983,8 +64047,8 @@ function splitPath(filename) {
63983
64047
  const parts = splitPathRe.exec(truncated);
63984
64048
  return parts ? parts.slice(1) : [];
63985
64049
  }
63986
- function dirname(path27) {
63987
- const result = splitPath(path27);
64050
+ function dirname(path29) {
64051
+ const result = splitPath(path29);
63988
64052
  const root = result[0] || "";
63989
64053
  let dir = result[1];
63990
64054
  if (!root && !dir) {
@@ -67807,15 +67871,15 @@ var getLayerMetadata = (route, layer, layerPath) => {
67807
67871
  };
67808
67872
  }
67809
67873
  };
67810
- var getRouterPath = (path27, layer) => {
67874
+ var getRouterPath = (path29, layer) => {
67811
67875
  const stackLayer = Array.isArray(layer.handle?.stack) ? layer.handle?.stack?.[0] : void 0;
67812
67876
  if (stackLayer?.route?.path) {
67813
- return `${path27}${stackLayer.route.path}`;
67877
+ return `${path29}${stackLayer.route.path}`;
67814
67878
  }
67815
67879
  if (stackLayer && Array.isArray(stackLayer?.handle?.stack)) {
67816
- return getRouterPath(path27, stackLayer);
67880
+ return getRouterPath(path29, stackLayer);
67817
67881
  }
67818
- return path27;
67882
+ return path29;
67819
67883
  };
67820
67884
  var isLayerIgnored = (name, type, config2) => {
67821
67885
  if (Array.isArray(config2?.ignoreLayersType) && config2?.ignoreLayersType?.includes(type)) {
@@ -67835,7 +67899,7 @@ function getActualMatchedRoute(req, constructedRoute) {
67835
67899
  if (layersStore.length === 0) {
67836
67900
  return void 0;
67837
67901
  }
67838
- if (layersStore.every((path27) => path27 === "/")) {
67902
+ if (layersStore.every((path29) => path29 === "/")) {
67839
67903
  return req.originalUrl === "/" ? "/" : void 0;
67840
67904
  }
67841
67905
  if (constructedRoute === "*") {
@@ -67851,11 +67915,11 @@ function getActualMatchedRoute(req, constructedRoute) {
67851
67915
  function getConstructedRoute(req) {
67852
67916
  const layersStore = getStoredLayers(req);
67853
67917
  let constructedRoute = "";
67854
- for (const path27 of layersStore) {
67855
- if (path27 === "/" || path27 === "/*") {
67918
+ for (const path29 of layersStore) {
67919
+ if (path29 === "/" || path29 === "/*") {
67856
67920
  continue;
67857
67921
  }
67858
- constructedRoute += !constructedRoute || constructedRoute.endsWith("/") ? path27 : `/${path27}`;
67922
+ constructedRoute += !constructedRoute || constructedRoute.endsWith("/") ? path29 : `/${path29}`;
67859
67923
  }
67860
67924
  return constructedRoute.replace(/\/{2,}/g, "/");
67861
67925
  }
@@ -68360,9 +68424,9 @@ function getRequestUrlObject(requestOptions) {
68360
68424
  const hostHeader = requestOptions.headers?.host && String(requestOptions.headers?.host);
68361
68425
  const hostname4 = hostHeader || requestOptions.hostname || requestOptions.host || "";
68362
68426
  const port = !requestOptions.port || requestOptions.port === 80 || requestOptions.port === 443 || /^(.*):(\d+)$/.test(hostname4) ? "" : `:${requestOptions.port}`;
68363
- const path27 = requestOptions.path ? requestOptions.path : "/";
68427
+ const path29 = requestOptions.path ? requestOptions.path : "/";
68364
68428
  const base = `${protocol}//${hostname4}${port}`;
68365
- return new URL(path27.startsWith("//") ? `${base}${path27}` : path27, base);
68429
+ return new URL(path29.startsWith("//") ? `${base}${path29}` : path29, base);
68366
68430
  }
68367
68431
  function getRequestUrlFromClientRequest(request2) {
68368
68432
  return String(getRequestUrl(getRequestOptions(request2)));
@@ -69035,11 +69099,11 @@ function shouldIgnoreSpansForIncomingRequest(request2, {
69035
69099
  return false;
69036
69100
  }
69037
69101
  function isStaticAssetRequest(urlPath) {
69038
- const path27 = stripUrlQueryAndFragment(urlPath);
69039
- if (path27.match(/\.(ico|png|jpg|jpeg|gif|svg|css|js|woff|woff2|ttf|eot|webp|avif)$/)) {
69102
+ const path29 = stripUrlQueryAndFragment(urlPath);
69103
+ if (path29.match(/\.(ico|png|jpg|jpeg|gif|svg|css|js|woff|woff2|ttf|eot|webp|avif)$/)) {
69040
69104
  return true;
69041
69105
  }
69042
- if (path27.match(/^\/(robots\.txt|sitemap\.xml|manifest\.json|browserconfig\.xml)$/)) {
69106
+ if (path29.match(/^\/(robots\.txt|sitemap\.xml|manifest\.json|browserconfig\.xml)$/)) {
69043
69107
  return true;
69044
69108
  }
69045
69109
  return false;
@@ -69280,11 +69344,11 @@ function isKnownPrefetchRequest2(req) {
69280
69344
  return req.headers["next-router-prefetch"] === "1";
69281
69345
  }
69282
69346
  function isStaticAssetRequest2(urlPath) {
69283
- const path27 = stripUrlQueryAndFragment(urlPath);
69284
- if (path27.match(/\.(ico|png|jpg|jpeg|gif|svg|css|js|woff|woff2|ttf|eot|webp|avif)$/)) {
69347
+ const path29 = stripUrlQueryAndFragment(urlPath);
69348
+ if (path29.match(/\.(ico|png|jpg|jpeg|gif|svg|css|js|woff|woff2|ttf|eot|webp|avif)$/)) {
69285
69349
  return true;
69286
69350
  }
69287
- if (path27.match(/^\/(robots\.txt|sitemap\.xml|manifest\.json|browserconfig\.xml)$/)) {
69351
+ if (path29.match(/^\/(robots\.txt|sitemap\.xml|manifest\.json|browserconfig\.xml)$/)) {
69288
69352
  return true;
69289
69353
  }
69290
69354
  return false;
@@ -69644,19 +69708,19 @@ function getBreadcrumbData(request2) {
69644
69708
  return {};
69645
69709
  }
69646
69710
  }
69647
- function getAbsoluteUrl2(origin, path27 = "/") {
69711
+ function getAbsoluteUrl2(origin, path29 = "/") {
69648
69712
  try {
69649
- const url2 = new URL(path27, origin);
69713
+ const url2 = new URL(path29, origin);
69650
69714
  return url2.toString();
69651
69715
  } catch {
69652
69716
  const url2 = `${origin}`;
69653
- if (url2.endsWith("/") && path27.startsWith("/")) {
69654
- return `${url2}${path27.slice(1)}`;
69717
+ if (url2.endsWith("/") && path29.startsWith("/")) {
69718
+ return `${url2}${path29.slice(1)}`;
69655
69719
  }
69656
- if (!url2.endsWith("/") && !path27.startsWith("/")) {
69657
- return `${url2}/${path27}`;
69720
+ if (!url2.endsWith("/") && !path29.startsWith("/")) {
69721
+ return `${url2}/${path29}`;
69658
69722
  }
69659
- return `${url2}${path27}`;
69723
+ return `${url2}${path29}`;
69660
69724
  }
69661
69725
  }
69662
69726
 
@@ -69901,15 +69965,15 @@ function getRequestMethod(original) {
69901
69965
  }
69902
69966
  return "_OTHER";
69903
69967
  }
69904
- function getAbsoluteUrl3(origin, path27 = "/") {
69968
+ function getAbsoluteUrl3(origin, path29 = "/") {
69905
69969
  const url2 = `${origin}`;
69906
- if (url2.endsWith("/") && path27.startsWith("/")) {
69907
- return `${url2}${path27.slice(1)}`;
69970
+ if (url2.endsWith("/") && path29.startsWith("/")) {
69971
+ return `${url2}${path29.slice(1)}`;
69908
69972
  }
69909
- if (!url2.endsWith("/") && !path27.startsWith("/")) {
69910
- return `${url2}/${path27}`;
69973
+ if (!url2.endsWith("/") && !path29.startsWith("/")) {
69974
+ return `${url2}/${path29}`;
69911
69975
  }
69912
- return `${url2}${path27}`;
69976
+ return `${url2}${path29}`;
69913
69977
  }
69914
69978
 
69915
69979
  // ../../node_modules/.pnpm/@sentry+node-core@10.73.0_@opentelemetry+api@1.9.1_@opentelemetry+core@2.11.0_@opentele_0c1f249c3fa9afb330ae7de0346c118f/node_modules/@sentry/node-core/build/esm/integrations/node-fetch/index.js
@@ -72395,12 +72459,12 @@ function emplace(map2, key, contents) {
72395
72459
  }
72396
72460
  return value;
72397
72461
  }
72398
- function shouldSkipContextLinesForFile(path27) {
72399
- if (path27.startsWith("node:")) return true;
72400
- if (path27.endsWith(".min.js")) return true;
72401
- if (path27.endsWith(".min.cjs")) return true;
72402
- if (path27.endsWith(".min.mjs")) return true;
72403
- if (path27.startsWith("data:")) return true;
72462
+ function shouldSkipContextLinesForFile(path29) {
72463
+ if (path29.startsWith("node:")) return true;
72464
+ if (path29.endsWith(".min.js")) return true;
72465
+ if (path29.endsWith(".min.cjs")) return true;
72466
+ if (path29.endsWith(".min.mjs")) return true;
72467
+ if (path29.startsWith("data:")) return true;
72404
72468
  return false;
72405
72469
  }
72406
72470
  function shouldSkipContextLinesForFrame(frame) {
@@ -72448,9 +72512,9 @@ function makeLineReaderRanges(lines, linecontext) {
72448
72512
  }
72449
72513
  return out;
72450
72514
  }
72451
- function getContextLinesFromFile(path27, ranges, output2) {
72515
+ function getContextLinesFromFile(path29, ranges, output2) {
72452
72516
  return new Promise((resolve2, _reject) => {
72453
- const stream = createReadStream(path27);
72517
+ const stream = createReadStream(path29);
72454
72518
  const lineReaded = createInterface({
72455
72519
  input: stream
72456
72520
  });
@@ -72468,8 +72532,8 @@ function getContextLinesFromFile(path27, ranges, output2) {
72468
72532
  let rangeStart = range[0];
72469
72533
  let rangeEnd = range[1];
72470
72534
  function onStreamError(e) {
72471
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path27, 1);
72472
- DEBUG_BUILD2 && debug.error(`Failed to read file: ${path27}. Error: ${e}`);
72535
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(path29, 1);
72536
+ DEBUG_BUILD2 && debug.error(`Failed to read file: ${path29}. Error: ${e}`);
72473
72537
  lineReaded.close();
72474
72538
  lineReaded.removeAllListeners();
72475
72539
  destroyStreamAndResolve();
@@ -73908,8 +73972,8 @@ function getSpotlightConfig(optionsSpotlight) {
73908
73972
 
73909
73973
  // ../../node_modules/.pnpm/@sentry+node-core@10.73.0_@opentelemetry+api@1.9.1_@opentelemetry+core@2.11.0_@opentele_0c1f249c3fa9afb330ae7de0346c118f/node_modules/@sentry/node-core/build/esm/utils/module.js
73910
73974
  import { posix, sep } from "node:path";
73911
- function normalizeWindowsPath(path27) {
73912
- return path27.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
73975
+ function normalizeWindowsPath(path29) {
73976
+ return path29.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
73913
73977
  }
73914
73978
  function createGetModuleFromFilename(basePath = process.argv[1] ? dirname(process.argv[1]) : process.cwd(), isWindows = sep === "\\") {
73915
73979
  const normalizedBase = isWindows ? normalizeWindowsPath(basePath) : basePath;
@@ -76785,22 +76849,22 @@ function addSpanSource(span, loc, start, end) {
76785
76849
  span.setAttribute(AttributeNames2.SOURCE, source);
76786
76850
  }
76787
76851
  }
76788
- function createFieldIfNotExists(contextValue, info, path27) {
76789
- let field = getField(contextValue, path27);
76852
+ function createFieldIfNotExists(contextValue, info, path29) {
76853
+ let field = getField(contextValue, path29);
76790
76854
  if (field) {
76791
76855
  return { field, spanAdded: false };
76792
76856
  }
76793
- const parentSpan = getParentFieldSpan(contextValue, path27);
76857
+ const parentSpan = getParentFieldSpan(contextValue, path29);
76794
76858
  field = {
76795
- span: createResolverSpan(contextValue, info, path27, parentSpan)
76859
+ span: createResolverSpan(contextValue, info, path29, parentSpan)
76796
76860
  };
76797
- addField(contextValue, path27, field);
76861
+ addField(contextValue, path29, field);
76798
76862
  return { field, spanAdded: true };
76799
76863
  }
76800
- function createResolverSpan(contextValue, info, path27, parentSpan) {
76864
+ function createResolverSpan(contextValue, info, path29, parentSpan) {
76801
76865
  const attributes = {
76802
76866
  [AttributeNames2.FIELD_NAME]: info.fieldName,
76803
- [AttributeNames2.FIELD_PATH]: path27.join("."),
76867
+ [AttributeNames2.FIELD_PATH]: path29.join("."),
76804
76868
  [AttributeNames2.FIELD_TYPE]: info.returnType.toString(),
76805
76869
  [AttributeNames2.PARENT_NAME]: info.parentType.name
76806
76870
  };
@@ -76832,15 +76896,15 @@ function getOperation(document2, operationName) {
76832
76896
  return document2.definitions.find((definition) => OPERATION_VALUES.indexOf(definition?.operation) !== -1);
76833
76897
  }
76834
76898
  }
76835
- function addField(contextValue, path27, field) {
76836
- return contextValue[OTEL_GRAPHQL_DATA_SYMBOL].fields[path27.join(".")] = field;
76899
+ function addField(contextValue, path29, field) {
76900
+ return contextValue[OTEL_GRAPHQL_DATA_SYMBOL].fields[path29.join(".")] = field;
76837
76901
  }
76838
- function getField(contextValue, path27) {
76839
- return contextValue[OTEL_GRAPHQL_DATA_SYMBOL].fields[path27.join(".")];
76902
+ function getField(contextValue, path29) {
76903
+ return contextValue[OTEL_GRAPHQL_DATA_SYMBOL].fields[path29.join(".")];
76840
76904
  }
76841
- function getParentFieldSpan(contextValue, path27) {
76842
- for (let i = path27.length - 1; i > 0; i--) {
76843
- const field = getField(contextValue, path27.slice(0, i));
76905
+ function getParentFieldSpan(contextValue, path29) {
76906
+ for (let i = path29.length - 1; i > 0; i--) {
76907
+ const field = getField(contextValue, path29.slice(0, i));
76844
76908
  if (field) {
76845
76909
  return field.span;
76846
76910
  }
@@ -76850,9 +76914,9 @@ function getParentFieldSpan(contextValue, path27) {
76850
76914
  function getRootSpan2(contextValue) {
76851
76915
  return contextValue[OTEL_GRAPHQL_DATA_SYMBOL].span;
76852
76916
  }
76853
- function pathToArray(path27) {
76917
+ function pathToArray(path29) {
76854
76918
  const flattened = [];
76855
- let curr = path27;
76919
+ let curr = path29;
76856
76920
  while (curr) {
76857
76921
  flattened.push(String(curr.key));
76858
76922
  curr = curr.prev;
@@ -76993,8 +77057,8 @@ function wrapFieldResolver(getConfig3, fieldResolver, isDefaultResolver = false)
76993
77057
  if (!contextValue[OTEL_GRAPHQL_DATA_SYMBOL]) {
76994
77058
  return fieldResolver.call(this, source, args, contextValue, info);
76995
77059
  }
76996
- const path27 = pathToArray(info?.path);
76997
- const { field, spanAdded } = createFieldIfNotExists(contextValue, info, path27);
77060
+ const path29 = pathToArray(info?.path);
77061
+ const { field, spanAdded } = createFieldIfNotExists(contextValue, info, path29);
76998
77062
  const span = field.span;
76999
77063
  const shouldEndSpan = spanAdded;
77000
77064
  return withActiveSpan(span, () => {
@@ -79977,10 +80041,10 @@ var PostgresJsInstrumentation = class extends import_instrumentation24.Instrumen
79977
80041
  },
79978
80042
  (exports) => exports
79979
80043
  );
79980
- ["src", "cf/src", "cjs/src"].forEach((path27) => {
80044
+ ["src", "cf/src", "cjs/src"].forEach((path29) => {
79981
80045
  module2.files.push(
79982
80046
  new InstrumentationNodeModuleFile(
79983
- `postgres/${path27}/query.js`,
80047
+ `postgres/${path29}/query.js`,
79984
80048
  SUPPORTED_VERSIONS4,
79985
80049
  this._patchQueryPrototype.bind(this),
79986
80050
  this._unpatchQueryPrototype.bind(this)
@@ -80611,13 +80675,13 @@ var HonoInstrumentation = class extends import_instrumentation27.Instrumentation
80611
80675
  return function(original) {
80612
80676
  return function wrappedHandler(...args) {
80613
80677
  if (typeof args[0] === "string") {
80614
- const path27 = args[0];
80678
+ const path29 = args[0];
80615
80679
  if (args.length === 1) {
80616
- return original.apply(this, [path27]);
80680
+ return original.apply(this, [path29]);
80617
80681
  }
80618
80682
  const handlers2 = args.slice(1);
80619
80683
  return original.apply(this, [
80620
- path27,
80684
+ path29,
80621
80685
  ...handlers2.map((handler) => instrumentation._wrapHandler(handler))
80622
80686
  ]);
80623
80687
  }
@@ -80651,13 +80715,13 @@ var HonoInstrumentation = class extends import_instrumentation27.Instrumentation
80651
80715
  return function(original) {
80652
80716
  return function wrappedHandler(...args) {
80653
80717
  if (typeof args[0] === "string") {
80654
- const path27 = args[0];
80718
+ const path29 = args[0];
80655
80719
  if (args.length === 1) {
80656
- return original.apply(this, [path27]);
80720
+ return original.apply(this, [path29]);
80657
80721
  }
80658
80722
  const handlers2 = args.slice(1);
80659
80723
  return original.apply(this, [
80660
- path27,
80724
+ path29,
80661
80725
  ...handlers2.map((handler) => instrumentation._wrapHandler(handler))
80662
80726
  ]);
80663
80727
  }
@@ -80677,8 +80741,8 @@ var HonoInstrumentation = class extends import_instrumentation27.Instrumentation
80677
80741
  if (!instrumentation.isEnabled()) {
80678
80742
  return handler.apply(this, [c, next]);
80679
80743
  }
80680
- const path27 = c.req.path;
80681
- const span = instrumentation.tracer.startSpan(path27);
80744
+ const path29 = c.req.path;
80745
+ const span = instrumentation.tracer.startSpan(path29);
80682
80746
  return context.with(trace.setSpan(context.active(), span), () => {
80683
80747
  return instrumentation._safeExecute(
80684
80748
  () => {
@@ -80688,7 +80752,7 @@ var HonoInstrumentation = class extends import_instrumentation27.Instrumentation
80688
80752
  const type = instrumentation._determineHandlerType(result2);
80689
80753
  span.setAttributes({
80690
80754
  [AttributeNames5.HONO_TYPE]: type,
80691
- [AttributeNames5.HONO_NAME]: type === HonoTypes.REQUEST_HANDLER ? path27 : handler.name || "anonymous"
80755
+ [AttributeNames5.HONO_NAME]: type === HonoTypes.REQUEST_HANDLER ? path29 : handler.name || "anonymous"
80692
80756
  });
80693
80757
  instrumentation.getConfig().responseHook?.(span);
80694
80758
  return result2;
@@ -80697,7 +80761,7 @@ var HonoInstrumentation = class extends import_instrumentation27.Instrumentation
80697
80761
  const type = instrumentation._determineHandlerType(result);
80698
80762
  span.setAttributes({
80699
80763
  [AttributeNames5.HONO_TYPE]: type,
80700
- [AttributeNames5.HONO_NAME]: type === HonoTypes.REQUEST_HANDLER ? path27 : handler.name || "anonymous"
80764
+ [AttributeNames5.HONO_NAME]: type === HonoTypes.REQUEST_HANDLER ? path29 : handler.name || "anonymous"
80701
80765
  });
80702
80766
  instrumentation.getConfig().responseHook?.(span);
80703
80767
  return result;
@@ -80901,11 +80965,11 @@ var KoaInstrumentation = class extends import_instrumentation29.InstrumentationB
80901
80965
  const router = dispatchLayer.router;
80902
80966
  const routesStack = router?.stack ?? [];
80903
80967
  for (const pathLayer of routesStack) {
80904
- const path27 = pathLayer.path;
80968
+ const path29 = pathLayer.path;
80905
80969
  const pathStack = pathLayer.stack;
80906
80970
  for (let j = 0; j < pathStack.length; j++) {
80907
80971
  const routedMiddleware = pathStack[j];
80908
- pathStack[j] = this._patchLayer(routedMiddleware, true, path27);
80972
+ pathStack[j] = this._patchLayer(routedMiddleware, true, path29);
80909
80973
  }
80910
80974
  }
80911
80975
  return dispatchLayer;
@@ -83359,7 +83423,7 @@ import os6 from "node:os";
83359
83423
  // ../../apps/collector/src/http.ts
83360
83424
  var import_undici = __toESM(require_undici(), 1);
83361
83425
  var CLI_VERSION_HEADER = "x-powerplant-cli-version";
83362
- var cliVersion = true ? "0.4.5" : "0.0.0-checkout";
83426
+ var cliVersion = true ? "0.4.7" : "0.0.0-checkout";
83363
83427
  function cliVersionHeaders() {
83364
83428
  return { [CLI_VERSION_HEADER]: cliVersion, "user-agent": `powerplant-cli/${cliVersion}` };
83365
83429
  }
@@ -85059,6 +85123,7 @@ function readCodexTranscriptHints(home, roots) {
85059
85123
  }
85060
85124
 
85061
85125
  // ../../apps/collector/src/codexCli.ts
85126
+ import { closeSync as closeSync3, mkdirSync as mkdirSync2, openSync as openSync3, renameSync, rmSync, utimesSync, writeSync } from "node:fs";
85062
85127
  import os8 from "node:os";
85063
85128
  import path7 from "node:path";
85064
85129
  import { setImmediate as yieldToEventLoop2 } from "node:timers/promises";
@@ -85133,19 +85198,96 @@ function parseCodexRollout(text) {
85133
85198
  ...typeof git?.repository_url === "string" && repoFullNameFrom(git.repository_url)
85134
85199
  };
85135
85200
  }
85136
- function parseRolloutFile(rolloutPath) {
85137
- const text = readIfExists(rolloutPath);
85138
- return text === null ? null : parseCodexRollout(text);
85139
- }
85201
+ function foldRolloutPages(pages) {
85202
+ const first = (key) => pages.find((page) => page[key] !== void 0)?.[key];
85203
+ const last = (key) => [...pages].reverse().find((page) => page[key] !== void 0)?.[key];
85204
+ const sum2 = (measured2) => measured2.length === 0 ? null : measured2.reduce((total, page) => addCodexTotals(total, page));
85205
+ const measured = pages.map((page) => page.totals).filter((totals) => totals !== null);
85206
+ const measuredFast = pages.filter((page) => page.totals !== null).map((page) => page.fastTotals);
85207
+ const sessionId = first("sessionId");
85208
+ const startedAt = first("startedAt");
85209
+ const endedAt = last("endedAt");
85210
+ const model = last("model");
85211
+ const speedMode = last("speedMode");
85212
+ const cwd = first("cwd");
85213
+ const gitBranch = first("gitBranch");
85214
+ const repoName = first("repoName");
85215
+ const repoFullName = first("repoFullName");
85216
+ return {
85217
+ kind: pages[0].kind,
85218
+ ...sessionId !== void 0 && { sessionId },
85219
+ ...startedAt !== void 0 && { startedAt },
85220
+ ...endedAt !== void 0 && { endedAt },
85221
+ ...model !== void 0 && { model },
85222
+ totals: sum2(measured),
85223
+ fastTotals: measuredFast.every((fast) => fast !== null) ? sum2(measuredFast) : null,
85224
+ ...speedMode !== void 0 && { speedMode },
85225
+ ...cwd !== void 0 && { cwd },
85226
+ ...gitBranch !== void 0 && { gitBranch },
85227
+ ...repoName !== void 0 && { repoName },
85228
+ ...repoFullName !== void 0 && { repoFullName }
85229
+ };
85230
+ }
85231
+ function rolloutIdentity(rolloutPath) {
85232
+ const name = path7.basename(rolloutPath, ".jsonl");
85233
+ const [head, pageId, ...rest] = name.split("_");
85234
+ const threadId2 = head.slice(-36);
85235
+ const conventional = rest.length === 0 && head.startsWith("rollout-") && head.at(-37) === "-" && SESSION_UUID.test(threadId2) && (pageId === void 0 || SESSION_UUID.test(pageId));
85236
+ if (!conventional) return { threadId: name, page: false };
85237
+ return { threadId: threadId2.toLowerCase(), page: pageId !== void 0 };
85238
+ }
85239
+ function codexSpoolDir(home) {
85240
+ return path7.join(home, ".config", "powerplant", "codex");
85241
+ }
85242
+ function mergedSpoolIsFresh(spoolPath, mtimeMs) {
85243
+ const existing = statIfExists(spoolPath);
85244
+ return existing !== null && Math.abs(existing.mtimeMs - mtimeMs) < 1;
85245
+ }
85246
+ var MergedSpoolWriter = class {
85247
+ constructor(spoolPath) {
85248
+ this.spoolPath = spoolPath;
85249
+ mkdirSync2(path7.dirname(spoolPath), { recursive: true, mode: 448 });
85250
+ this.tmpPath = `${spoolPath}.${process.pid}.tmp`;
85251
+ this.fd = openSync3(this.tmpPath, "w", 384);
85252
+ }
85253
+ spoolPath;
85254
+ tmpPath;
85255
+ fd;
85256
+ bytes = 0;
85257
+ append(pageText) {
85258
+ if (this.fd === void 0) throw new Error("merged transcript already closed");
85259
+ const text = pageText.endsWith("\n") ? pageText : `${pageText}
85260
+ `;
85261
+ this.bytes += writeSync(this.fd, text);
85262
+ }
85263
+ /** Stamps the newest page's mtime and publishes the file; returns its size. */
85264
+ finish(mtimeMs) {
85265
+ this.close();
85266
+ utimesSync(this.tmpPath, mtimeMs / 1e3, mtimeMs / 1e3);
85267
+ renameSync(this.tmpPath, this.spoolPath);
85268
+ return this.bytes;
85269
+ }
85270
+ abandon() {
85271
+ this.close();
85272
+ rmSync(this.tmpPath, { force: true });
85273
+ }
85274
+ close() {
85275
+ if (this.fd === void 0) return;
85276
+ closeSync3(this.fd);
85277
+ this.fd = void 0;
85278
+ }
85279
+ };
85140
85280
  function rolloutLocation(rolloutPath) {
85141
85281
  const record2 = readFirstRecord(rolloutPath, (candidate) => candidate.type === "session_meta");
85142
85282
  const meta3 = record2?.payload;
85143
85283
  if (!meta3 || typeof meta3 !== "object" || Array.isArray(meta3)) return { kind: "session", totals: null, fastTotals: null };
85144
85284
  const { cwd, id, session_id: fallbackId } = meta3;
85145
85285
  const sessionId = id ?? fallbackId;
85286
+ const startedAt = record2?.timestamp;
85146
85287
  return {
85147
85288
  kind: isSidecarThread(meta3) ? "subagent" : "session",
85148
85289
  ...typeof sessionId === "string" && { sessionId },
85290
+ ...typeof startedAt === "string" && { startedAt },
85149
85291
  totals: null,
85150
85292
  fastTotals: null,
85151
85293
  ...typeof cwd === "string" && cwd !== "" && { cwd }
@@ -85200,89 +85342,128 @@ async function collectCodexSessions(options = {}) {
85200
85342
  const now = options.now ?? Date.now();
85201
85343
  const capture = options.capture ?? captureEverythingUnresolved;
85202
85344
  const maxBytes = options.maxTranscriptBytes ?? MAX_TRANSCRIPT_FILE_BYTES;
85345
+ const spoolDir = options.spoolDir ?? codexSpoolDir(options.homeDir ?? os8.homedir());
85203
85346
  const items = [];
85204
85347
  const candidates = [];
85205
85348
  const unreadable = [];
85206
85349
  const skips = { skippedOutOfScope: 0, skippedNoRepo: 0 };
85207
85350
  let skippedSubagentThreads = 0;
85208
85351
  let skippedTooLarge = 0;
85352
+ let mergedThreads = 0;
85353
+ let largestMergedBytes = 0;
85209
85354
  const externalIdOf = (rolloutPath) => path7.basename(rolloutPath, ".jsonl");
85210
- const seen = /* @__PURE__ */ new Set();
85211
- const admitFrom = async (files, archived, sessionId) => {
85212
- for (const rolloutPath of files) {
85213
- if (seen.has(rolloutPath)) continue;
85355
+ const files = /* @__PURE__ */ new Map();
85356
+ const observe = async (paths, archived, hintSessionId) => {
85357
+ for (const rolloutPath of paths) {
85358
+ const known = files.get(rolloutPath);
85359
+ if (known !== void 0) {
85360
+ if (hintSessionId === void 0) delete known.hintSessionIds;
85361
+ else known.hintSessionIds?.push(hintSessionId);
85362
+ continue;
85363
+ }
85214
85364
  await yieldToEventLoop2();
85215
85365
  const stat = statIfExists(rolloutPath);
85216
85366
  if (!stat) continue;
85217
- seen.add(rolloutPath);
85218
- if (options.sinceMs !== void 0 && Math.max(stat.mtimeMs, stat.ctimeMs) < options.sinceMs)
85219
- continue;
85220
- if (stat.size > maxBytes) {
85367
+ files.set(rolloutPath, {
85368
+ rolloutPath,
85369
+ archived,
85370
+ identity: rolloutIdentity(rolloutPath),
85371
+ mtimeMs: stat.mtimeMs,
85372
+ changedMs: Math.max(stat.mtimeMs, stat.ctimeMs),
85373
+ sizeBytes: stat.size,
85374
+ ...hintSessionId !== void 0 && { hintSessionIds: [hintSessionId] }
85375
+ });
85376
+ }
85377
+ };
85378
+ const archiveDir = codexArchivedSessionsDir(sessionsDir);
85379
+ const hintHome = options.homeDir ?? (options.codexDir === void 0 ? os8.homedir() : void 0);
85380
+ if (hintHome !== void 0) {
85381
+ for (const hint of readCodexTranscriptHints(hintHome, [sessionsDir, archiveDir])) {
85382
+ await observe([hint.rolloutPath], hint.archived, hint.sessionId);
85383
+ }
85384
+ }
85385
+ await observe(rolloutFiles(sessionsDir), false);
85386
+ await observe(rolloutFiles(archiveDir), true);
85387
+ const byThread = /* @__PURE__ */ new Map();
85388
+ for (const file2 of files.values()) {
85389
+ const thread = byThread.get(file2.identity.threadId);
85390
+ if (thread === void 0) byThread.set(file2.identity.threadId, [file2]);
85391
+ else thread.push(file2);
85392
+ }
85393
+ for (const [threadId2, observed] of byThread) {
85394
+ const stored = dedupeStoreCopies(observed);
85395
+ let externalId = externalIdOf((stored.find((file2) => !file2.identity.page) ?? stored[0]).rolloutPath);
85396
+ try {
85397
+ const spoolPath = stored.length > 1 ? path7.join(spoolDir, `${threadId2}.jsonl`) : void 0;
85398
+ const changedMs = Math.max(...stored.map((file2) => file2.changedMs));
85399
+ if (options.sinceMs !== void 0 && changedMs < options.sinceMs) {
85400
+ const neverMerged = spoolPath !== void 0 && !options.locationsOnly && statIfExists(spoolPath) === null;
85401
+ if (!neverMerged) continue;
85402
+ }
85403
+ await yieldToEventLoop2();
85404
+ const named = stored.filter((file2) => {
85405
+ if (file2.hintSessionIds === void 0) return true;
85406
+ const { sessionId } = rolloutLocation(file2.rolloutPath);
85407
+ return sessionId !== void 0 && file2.hintSessionIds.includes(sessionId);
85408
+ });
85409
+ if (named.length === 0) continue;
85410
+ const threadFiles = named.length > 1 ? orderPages(named) : named;
85411
+ const base = threadFiles[0];
85412
+ externalId = externalIdOf(base.rolloutPath);
85413
+ const mtimeMs = Math.max(...threadFiles.map((file2) => file2.mtimeMs));
85414
+ const sizeBytes = threadFiles.reduce((sum2, file2) => sum2 + file2.sizeBytes, 0);
85415
+ if (sizeBytes > maxBytes) {
85221
85416
  skippedTooLarge += 1;
85222
85417
  observeFileDiagnostic(options.onFileDiagnostic, {
85223
- path: rolloutPath,
85418
+ path: base.rolloutPath,
85224
85419
  reason: "too_large",
85225
- sizeBytes: stat.size
85420
+ sizeBytes
85226
85421
  });
85227
85422
  continue;
85228
85423
  }
85229
- try {
85230
- const location = rolloutLocation(rolloutPath);
85231
- if (sessionId !== void 0 && location.sessionId !== sessionId) {
85232
- seen.delete(rolloutPath);
85233
- continue;
85234
- }
85235
- if (location.kind === "subagent") {
85236
- skippedSubagentThreads += 1;
85237
- continue;
85238
- }
85239
- const decision = captureDecision(location.cwd, capture);
85240
- if (!decision.capture) {
85241
- countCaptureSkip(skips, decision.reason);
85242
- continue;
85243
- }
85244
- if (options.locationsOnly) {
85245
- items.push({
85246
- mtimeMs: stat.mtimeMs,
85247
- transcriptPath: rolloutPath,
85248
- ...location.cwd && { cwd: location.cwd },
85249
- item: {
85250
- source: "codex",
85251
- externalId: externalIdOf(rolloutPath),
85252
- status: now - stat.mtimeMs < ACTIVE_GRACE_MS ? "active" : "inactive",
85253
- archived,
85254
- capturedVia: decision.via
85255
- }
85256
- });
85257
- continue;
85258
- }
85259
- candidates.push({
85260
- rolloutPath,
85261
- archived,
85262
- mtimeMs: stat.mtimeMs,
85424
+ const location = rolloutLocation(base.rolloutPath);
85425
+ if (location.kind === "subagent") {
85426
+ skippedSubagentThreads += 1;
85427
+ continue;
85428
+ }
85429
+ const decision = captureDecision(location.cwd, capture);
85430
+ if (!decision.capture) {
85431
+ countCaptureSkip(skips, decision.reason);
85432
+ continue;
85433
+ }
85434
+ const thread = {
85435
+ externalId,
85436
+ files: threadFiles,
85437
+ ...threadFiles.length > 1 && spoolPath !== void 0 && { spoolPath },
85438
+ mtimeMs,
85439
+ archived: threadFiles.every((file2) => file2.archived)
85440
+ };
85441
+ if (options.locationsOnly) {
85442
+ items.push({
85443
+ mtimeMs,
85444
+ transcriptPath: base.rolloutPath,
85263
85445
  ...location.cwd && { cwd: location.cwd },
85264
- decision
85265
- });
85266
- } catch (error62) {
85267
- unreadable.push(`${externalIdOf(rolloutPath)}: ${describeReadError(error62)}`);
85268
- observeFileDiagnostic(options.onFileDiagnostic, {
85269
- path: rolloutPath,
85270
- reason: "unreadable",
85271
- sizeBytes: null,
85272
- errorCode: diagnosticErrorCode(error62)
85446
+ item: {
85447
+ source: "codex",
85448
+ externalId,
85449
+ status: now - mtimeMs < ACTIVE_GRACE_MS ? "active" : "inactive",
85450
+ archived: thread.archived,
85451
+ capturedVia: decision.via
85452
+ }
85273
85453
  });
85454
+ continue;
85274
85455
  }
85275
- }
85276
- };
85277
- const archiveDir = codexArchivedSessionsDir(sessionsDir);
85278
- const hintHome = options.homeDir ?? (options.codexDir === void 0 ? os8.homedir() : void 0);
85279
- if (hintHome !== void 0) {
85280
- for (const hint of readCodexTranscriptHints(hintHome, [sessionsDir, archiveDir])) {
85281
- await admitFrom([hint.rolloutPath], hint.archived, hint.sessionId);
85456
+ candidates.push({ thread, ...location.cwd && { cwd: location.cwd }, decision });
85457
+ } catch (error62) {
85458
+ unreadable.push(`${externalId}: ${describeReadError(error62)}`);
85459
+ observeFileDiagnostic(options.onFileDiagnostic, {
85460
+ path: stored[0].rolloutPath,
85461
+ reason: "unreadable",
85462
+ sizeBytes: null,
85463
+ errorCode: diagnosticErrorCode(error62)
85464
+ });
85282
85465
  }
85283
85466
  }
85284
- await admitFrom(rolloutFiles(sessionsDir), false);
85285
- await admitFrom(rolloutFiles(archiveDir), true);
85286
85467
  if (options.locationsOnly) {
85287
85468
  return {
85288
85469
  sessions: items.sort((a, b2) => b2.mtimeMs - a.mtimeMs),
@@ -85290,30 +85471,59 @@ async function collectCodexSessions(options = {}) {
85290
85471
  skippedSubagentThreads,
85291
85472
  skippedTooLarge,
85292
85473
  unreadable,
85293
- heldBack: 0
85474
+ heldBack: 0,
85475
+ mergedThreads: 0,
85476
+ largestMergedBytes: 0
85294
85477
  };
85295
85478
  }
85296
- candidates.sort((a, b2) => b2.mtimeMs - a.mtimeMs);
85479
+ candidates.sort((a, b2) => b2.thread.mtimeMs - a.thread.mtimeMs);
85297
85480
  const chosen = options.maxSessions === void 0 ? candidates : candidates.slice(0, options.maxSessions);
85298
85481
  const threadNames = chosen.length > 0 ? loadThreadNames(sessionsDir) : /* @__PURE__ */ new Map();
85299
85482
  for (const candidate of chosen) {
85300
85483
  await yieldToEventLoop2();
85301
- const { rolloutPath, archived, mtimeMs, cwd, decision } = candidate;
85484
+ const { thread, cwd, decision } = candidate;
85485
+ let writer;
85302
85486
  try {
85303
- const summary = parseRolloutFile(rolloutPath);
85304
- if (!summary) continue;
85487
+ const rewrite = thread.spoolPath !== void 0 && !mergedSpoolIsFresh(thread.spoolPath, thread.mtimeMs);
85488
+ if (thread.spoolPath !== void 0 && rewrite) writer = new MergedSpoolWriter(thread.spoolPath);
85489
+ const pages = [];
85490
+ let vanished = false;
85491
+ for (const file2 of thread.files) {
85492
+ const text = readIfExists(file2.rolloutPath);
85493
+ if (text === null) {
85494
+ vanished = true;
85495
+ break;
85496
+ }
85497
+ const page = parseCodexRollout(text);
85498
+ if (page === null) continue;
85499
+ pages.push(page);
85500
+ writer?.append(text);
85501
+ }
85502
+ if (vanished || pages.length === 0) {
85503
+ writer?.abandon();
85504
+ continue;
85505
+ }
85506
+ const summary = foldRolloutPages(pages);
85507
+ let transcriptPath = thread.files[0].rolloutPath;
85508
+ if (thread.spoolPath !== void 0) {
85509
+ const mergedBytes = writer ? writer.finish(thread.mtimeMs) : statIfExists(thread.spoolPath)?.size ?? 0;
85510
+ writer = void 0;
85511
+ transcriptPath = thread.spoolPath;
85512
+ mergedThreads += 1;
85513
+ largestMergedBytes = Math.max(largestMergedBytes, mergedBytes);
85514
+ }
85305
85515
  const repoDir = summary.repoName ?? (cwd ? path7.basename(cwd) : void 0);
85306
85516
  const repoFullName = decision.repoFullName ?? summary.repoFullName;
85307
85517
  const title = summary.sessionId ? threadNames.get(summary.sessionId) : void 0;
85308
85518
  items.push({
85309
- mtimeMs,
85310
- transcriptPath: rolloutPath,
85519
+ mtimeMs: thread.mtimeMs,
85520
+ transcriptPath,
85311
85521
  ...cwd && { cwd },
85312
85522
  item: {
85313
85523
  source: "codex",
85314
- externalId: externalIdOf(rolloutPath),
85315
- status: now - mtimeMs < ACTIVE_GRACE_MS ? "active" : "inactive",
85316
- archived,
85524
+ externalId: thread.externalId,
85525
+ status: now - thread.mtimeMs < ACTIVE_GRACE_MS ? "active" : "inactive",
85526
+ archived: thread.archived,
85317
85527
  ...summary.startedAt && { startedAt: summary.startedAt },
85318
85528
  ...summary.endedAt && { endedAt: summary.endedAt },
85319
85529
  ...summary.model && { model: summary.model },
@@ -85338,9 +85548,10 @@ async function collectCodexSessions(options = {}) {
85338
85548
  }
85339
85549
  });
85340
85550
  } catch (error62) {
85341
- unreadable.push(`${externalIdOf(rolloutPath)}: ${describeReadError(error62)}`);
85551
+ writer?.abandon();
85552
+ unreadable.push(`${thread.externalId}: ${describeReadError(error62)}`);
85342
85553
  observeFileDiagnostic(options.onFileDiagnostic, {
85343
- path: rolloutPath,
85554
+ path: thread.files[0].rolloutPath,
85344
85555
  reason: "unreadable",
85345
85556
  sizeBytes: null,
85346
85557
  errorCode: diagnosticErrorCode(error62)
@@ -85353,15 +85564,32 @@ async function collectCodexSessions(options = {}) {
85353
85564
  skippedSubagentThreads,
85354
85565
  skippedTooLarge,
85355
85566
  unreadable,
85356
- heldBack: candidates.length - chosen.length
85567
+ heldBack: candidates.length - chosen.length,
85568
+ mergedThreads,
85569
+ largestMergedBytes
85357
85570
  };
85358
85571
  }
85572
+ function dedupeStoreCopies(threadFiles) {
85573
+ const byName = /* @__PURE__ */ new Map();
85574
+ for (const file2 of threadFiles) {
85575
+ const name = path7.basename(file2.rolloutPath);
85576
+ const known = byName.get(name);
85577
+ if (known === void 0 || file2.archived) byName.set(name, file2);
85578
+ }
85579
+ return [...byName.values()];
85580
+ }
85581
+ function orderPages(threadFiles) {
85582
+ const orderOf = (file2) => rolloutLocation(file2.rolloutPath).startedAt ?? "";
85583
+ return threadFiles.map((file2) => ({ file: file2, order: orderOf(file2) })).sort(
85584
+ (a, b2) => Number(a.file.identity.page) - Number(b2.file.identity.page) || a.order.localeCompare(b2.order) || a.file.rolloutPath.localeCompare(b2.file.rolloutPath)
85585
+ ).map((entry) => entry.file);
85586
+ }
85359
85587
  function codexThreadCwd(threadId2, sessionsDir = path7.join(os8.homedir(), ".codex", "sessions")) {
85360
85588
  if (!SESSION_UUID.test(threadId2)) return void 0;
85361
- const suffix = `-${threadId2.toLowerCase()}.jsonl`;
85589
+ const wanted = threadId2.toLowerCase();
85362
85590
  for (const root of [sessionsDir, codexArchivedSessionsDir(sessionsDir)]) {
85363
85591
  for (const rolloutPath of rolloutFiles(root)) {
85364
- if (!path7.basename(rolloutPath).toLowerCase().endsWith(suffix)) continue;
85592
+ if (rolloutIdentity(rolloutPath).threadId !== wanted) continue;
85365
85593
  const cwd = rolloutLocation(rolloutPath).cwd;
85366
85594
  if (cwd !== void 0) return cwd;
85367
85595
  }
@@ -85375,7 +85603,7 @@ import path10 from "node:path";
85375
85603
 
85376
85604
  // ../../apps/collector/src/cursorLocal.ts
85377
85605
  import { createHash as createHash4 } from "node:crypto";
85378
- import { existsSync as existsSync2, mkdirSync as mkdirSync3, utimesSync as utimesSync2, writeFileSync as writeFileSync3 } from "node:fs";
85606
+ import { existsSync as existsSync2, mkdirSync as mkdirSync4, utimesSync as utimesSync3, writeFileSync as writeFileSync3 } from "node:fs";
85379
85607
  import os10 from "node:os";
85380
85608
  import path9 from "node:path";
85381
85609
  import { fileURLToPath } from "node:url";
@@ -85383,15 +85611,15 @@ import { fileURLToPath } from "node:url";
85383
85611
  // ../../apps/collector/src/cursorTranscriptFile.ts
85384
85612
  import { createHash as createHash3 } from "node:crypto";
85385
85613
  import {
85386
- closeSync as closeSync3,
85614
+ closeSync as closeSync4,
85387
85615
  existsSync,
85388
85616
  lstatSync as lstatSync2,
85389
- mkdirSync as mkdirSync2,
85390
- openSync as openSync3,
85617
+ mkdirSync as mkdirSync3,
85618
+ openSync as openSync4,
85391
85619
  readSync as readSync3,
85392
85620
  readdirSync as readdirSync3,
85393
85621
  realpathSync as realpathSync2,
85394
- utimesSync,
85622
+ utimesSync as utimesSync2,
85395
85623
  writeFileSync as writeFileSync2
85396
85624
  } from "node:fs";
85397
85625
  import os9 from "node:os";
@@ -85460,7 +85688,7 @@ var hintSchema2 = external_exports.object({
85460
85688
  model: external_exports.string().max(256).optional()
85461
85689
  });
85462
85690
  function readBounded(file2, maxBytes) {
85463
- const fd = openSync3(file2, "r");
85691
+ const fd = openSync4(file2, "r");
85464
85692
  try {
85465
85693
  const chunks = [];
85466
85694
  let bytes = 0;
@@ -85473,7 +85701,7 @@ function readBounded(file2, maxBytes) {
85473
85701
  }
85474
85702
  return null;
85475
85703
  } finally {
85476
- closeSync3(fd);
85704
+ closeSync4(fd);
85477
85705
  }
85478
85706
  }
85479
85707
  function collectCursorTranscriptFiles(options, isDatabaseSession, result, databaseSpoolDir, spoolName) {
@@ -85577,9 +85805,9 @@ function collectCursorTranscriptFiles(options, isDatabaseSession, result, databa
85577
85805
  result.skippedTooLarge++;
85578
85806
  continue;
85579
85807
  }
85580
- mkdirSync2(spoolDir, { recursive: true, mode: 448 });
85808
+ mkdirSync3(spoolDir, { recursive: true, mode: 448 });
85581
85809
  writeFileSync2(spool, body, { mode: 384 });
85582
- utimesSync(spool, stat.atime, stat.mtime);
85810
+ utimesSync2(spool, stat.atime, stat.mtime);
85583
85811
  }
85584
85812
  result.sessions.push({
85585
85813
  cwd,
@@ -85930,13 +86158,13 @@ function collectFromStore(db, userDir, options, result, knownIds) {
85930
86158
  ...transcript.bubblesOmitted > 0 && { bubblesOmitted: transcript.bubblesOmitted }
85931
86159
  };
85932
86160
  if (!spoolDirReady) {
85933
- mkdirSync3(spoolDir, { recursive: true });
86161
+ mkdirSync4(spoolDir, { recursive: true });
85934
86162
  spoolDirReady = true;
85935
86163
  }
85936
86164
  const body = [meta3, ...transcript.lines].map((line) => JSON.stringify(line)).join("\n");
85937
86165
  writeFileSync3(spoolPath, `${body}
85938
86166
  `, "utf8");
85939
- utimesSync2(spoolPath, new Date(lastUpdatedAt), new Date(lastUpdatedAt));
86167
+ utimesSync3(spoolPath, new Date(lastUpdatedAt), new Date(lastUpdatedAt));
85940
86168
  }
85941
86169
  const repoSourceDir = facts.repoPath ?? cwd;
85942
86170
  const startBranch = facts.branches[0];
@@ -86109,13 +86337,22 @@ function allowProtectedRepoDiscovery(config2, found, environment = {}, deps = de
86109
86337
  const needsReview = new ProtectedRootTally(environment);
86110
86338
  for (const entry of found) {
86111
86339
  const probes = entry.folders.flatMap(
86112
- (folder) => folder.cwds.map((cwd) => ({ cwd, probe: probeOf(cwd), sessionCount: folder.sessionCount }))
86340
+ (folder) => folder.cwds.map((cwd) => ({ cwd, probe: probeOf(cwd), folder }))
86113
86341
  );
86114
86342
  let unconsented = 0;
86115
- for (const { cwd, probe, sessionCount } of probes) {
86343
+ const countedFolderTargets = /* @__PURE__ */ new Set();
86344
+ for (const { cwd, probe, folder } of probes) {
86116
86345
  if (probe.kind !== "unconsented") continue;
86117
86346
  unconsented += 1;
86118
- needsReview.add(probe.root, checkoutOfGitDir(probe.path), cwd, sessionCount);
86347
+ const checkout = checkoutOfGitDir(probe.path);
86348
+ const target = [folder.path, probe.root, checkout].join("\0");
86349
+ needsReview.add(
86350
+ probe.root,
86351
+ checkout,
86352
+ cwd,
86353
+ countedFolderTargets.has(target) ? 0 : folder.sessionCount
86354
+ );
86355
+ countedFolderTargets.add(target);
86119
86356
  }
86120
86357
  if (probes.some(({ probe }) => probe.kind === "found")) outcome.enabled.push(entry);
86121
86358
  else if (probes.some(({ probe }) => probe.kind === "denied")) outcome.blocked.push(entry);
@@ -86144,7 +86381,7 @@ function allowProtectedRepoDiscovery(config2, found, environment = {}, deps = de
86144
86381
  }
86145
86382
 
86146
86383
  // ../../apps/collector/src/hookInstall.ts
86147
- import { existsSync as existsSync3, mkdirSync as mkdirSync4, readFileSync as readFileSync6, rmSync, writeFileSync as writeFileSync4 } from "node:fs";
86384
+ import { existsSync as existsSync3, mkdirSync as mkdirSync5, readFileSync as readFileSync6, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "node:fs";
86148
86385
  import os12 from "node:os";
86149
86386
  import path11 from "node:path";
86150
86387
  import { fileURLToPath as fileURLToPath2 } from "node:url";
@@ -86212,7 +86449,7 @@ function hookSourcePath(script) {
86212
86449
  }
86213
86450
  function installCollectorHooks(homeDir = os12.homedir()) {
86214
86451
  const hookDir = path11.join(homeDir, ".config", "powerplant", "hooks");
86215
- mkdirSync4(hookDir, { recursive: true });
86452
+ mkdirSync5(hookDir, { recursive: true });
86216
86453
  for (const script of HOOK_SCRIPTS) {
86217
86454
  writeFileSync4(path11.join(hookDir, script), readFileSync6(hookSourcePath(script), "utf8"), {
86218
86455
  mode: 493
@@ -86228,12 +86465,12 @@ function installCollectorHooks(homeDir = os12.homedir()) {
86228
86465
  }
86229
86466
  const merged = mergeCollectorHooks(settingsText, (script) => `node "${path11.join(hookDir, script)}"`);
86230
86467
  if (merged.action === "write") {
86231
- mkdirSync4(settingsDir, { recursive: true });
86468
+ mkdirSync5(settingsDir, { recursive: true });
86232
86469
  writeFileSync4(settingsPath, merged.text);
86233
86470
  }
86234
86471
  if (merged.action !== "skip") {
86235
86472
  for (const retired of RETIRED_HOOK_WIRINGS) {
86236
- rmSync(path11.join(hookDir, retired.script), { force: true });
86473
+ rmSync2(path11.join(hookDir, retired.script), { force: true });
86237
86474
  }
86238
86475
  }
86239
86476
  return {
@@ -86245,7 +86482,7 @@ function installCollectorHooks(homeDir = os12.homedir()) {
86245
86482
 
86246
86483
  // ../../apps/collector/src/service.ts
86247
86484
  import { execFileSync as execFileSync3 } from "node:child_process";
86248
- import { chmodSync as chmodSync2, existsSync as existsSync4, mkdirSync as mkdirSync5, readFileSync as readFileSync7, rmSync as rmSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync5 } from "node:fs";
86485
+ import { chmodSync as chmodSync2, existsSync as existsSync4, mkdirSync as mkdirSync6, readFileSync as readFileSync7, rmSync as rmSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync5 } from "node:fs";
86249
86486
  import os13 from "node:os";
86250
86487
  import path12 from "node:path";
86251
86488
  var RESTART_THROTTLE_SECONDS = 60;
@@ -86325,11 +86562,11 @@ function installService(config2, command) {
86325
86562
  );
86326
86563
  }
86327
86564
  const launcher = launcherPath(config2.appEnv);
86328
- mkdirSync5(path12.dirname(launcher), { recursive: true });
86565
+ mkdirSync6(path12.dirname(launcher), { recursive: true });
86329
86566
  writeFileSync5(launcher, buildLauncherScript(command));
86330
86567
  chmodSync2(launcher, 493);
86331
86568
  const file2 = plistPath(config2.appEnv);
86332
- mkdirSync5(path12.dirname(file2), { recursive: true });
86569
+ mkdirSync6(path12.dirname(file2), { recursive: true });
86333
86570
  writeFileSync5(file2, buildLaunchdPlist(config2.appEnv, installerPathValue()));
86334
86571
  runLaunchctl(["bootstrap", `gui/${uid()}`, file2]);
86335
86572
  return `${file2} (watching for session changes; log: ${logPath(config2.appEnv)})`;
@@ -86367,7 +86604,7 @@ function serviceUpToDate(config2, command) {
86367
86604
  function uninstallService(config2) {
86368
86605
  requireMacos();
86369
86606
  const existed = bootout(config2.appEnv);
86370
- rmSync2(launcherPath(config2.appEnv), { force: true });
86607
+ rmSync3(launcherPath(config2.appEnv), { force: true });
86371
86608
  if (existsSync4(plistPath(config2.appEnv))) {
86372
86609
  unlinkSync2(plistPath(config2.appEnv));
86373
86610
  return true;
@@ -86437,7 +86674,7 @@ function xmlEscape(value) {
86437
86674
  }
86438
86675
 
86439
86676
  // ../../apps/collector/src/status.ts
86440
- import { mkdirSync as mkdirSync6, readFileSync as readFileSync8, renameSync, rmSync as rmSync3, writeFileSync as writeFileSync6 } from "node:fs";
86677
+ import { mkdirSync as mkdirSync7, readFileSync as readFileSync8, renameSync as renameSync2, rmSync as rmSync4, writeFileSync as writeFileSync6 } from "node:fs";
86441
86678
  import os14 from "node:os";
86442
86679
  import path13 from "node:path";
86443
86680
  var HEARTBEAT_INTERVAL_MS = 6e4;
@@ -86503,10 +86740,10 @@ function controlFilePath(appEnv, homeDir) {
86503
86740
  return path13.join(collectorStateDir(homeDir), `collector-control-${appEnv}.json`);
86504
86741
  }
86505
86742
  function writeAtomically(file2, payload) {
86506
- mkdirSync6(path13.dirname(file2), { recursive: true });
86743
+ mkdirSync7(path13.dirname(file2), { recursive: true });
86507
86744
  const tmp = `${file2}.${process.pid}.tmp`;
86508
86745
  writeFileSync6(tmp, payload);
86509
- renameSync(tmp, file2);
86746
+ renameSync2(tmp, file2);
86510
86747
  }
86511
86748
  function writeCollectorStatus(appEnv, status, homeDir) {
86512
86749
  writeAtomically(statusFilePath(appEnv, homeDir), JSON.stringify(status, null, 2));
@@ -86547,10 +86784,10 @@ function writeCollectorControl(appEnv, control, homeDir) {
86547
86784
  writeAtomically(controlFilePath(appEnv, homeDir), JSON.stringify(control, null, 2));
86548
86785
  }
86549
86786
  function clearCollectorControl(appEnv, homeDir) {
86550
- rmSync3(controlFilePath(appEnv, homeDir), { force: true });
86787
+ rmSync4(controlFilePath(appEnv, homeDir), { force: true });
86551
86788
  }
86552
86789
  function clearCollectorStatus(appEnv, homeDir) {
86553
- rmSync3(statusFilePath(appEnv, homeDir), { force: true });
86790
+ rmSync4(statusFilePath(appEnv, homeDir), { force: true });
86554
86791
  }
86555
86792
  function describeDaemonState(read, probes = {}) {
86556
86793
  if (read.file === "invalid") return { state: "unreadable" };
@@ -86923,7 +87160,10 @@ async function runSyncPassInternal(config2, options, diagnostic) {
86923
87160
  const active = items.filter((s) => s.status === "active").length;
86924
87161
  const tooLarge = (count2, what) => count2 > 0 ? ` \xB7 ${count2} ${what} skipped (over ${MAX_TRANSCRIPT_FILE_BYTES / (1024 * 1024)}MB, too large to read)` : "";
86925
87162
  log3(
86926
- `Found ${inWindow.length} local session(s) (${claude.sessions.length} claude, ${codex.sessions.length} codex, ${cursor.sessions.length} cursor) ` + describeScanReach(window2, options.narrowSinceMs) + (active > 0 ? ` (${active} still active)` : "") + (skippedOutOfScope > 0 ? ` \xB7 ${skippedOutOfScope} ${describeSkipReason(capture)}` : "") + (skippedNoRepo > 0 ? ` \xB7 ${skippedNoRepo} ${describeNoRepoSkipReason(capture)}` : "") + (codex.skippedSubagentThreads > 0 ? ` \xB7 ${codex.skippedSubagentThreads} codex subagent thread(s) skipped (spend unmeasured)` : "") + (cursor.skippedSubagentComposers > 0 ? ` \xB7 ${cursor.skippedSubagentComposers} cursor subagent thread(s) skipped` : "") + (cursor.skippedNonLocalComposers > 0 ? ` \xB7 ${cursor.skippedNonLocalComposers} cursor session(s) skipped (not local to this machine)` : "") + (cursor.skippedUnreadable > 0 ? ` \xB7 ${cursor.skippedUnreadable} cursor session(s) unreadable, skipped` : "") + tooLarge(claude.skippedTooLarge, "claude transcript(s)") + (claude.unreadable.length > 0 ? ` \xB7 ${claude.unreadable.length} claude transcript(s) unreadable, skipped` : "") + tooLarge(codex.skippedTooLarge, "codex rollout(s)") + (codex.unreadable.length > 0 ? ` \xB7 ${codex.unreadable.length} codex rollout(s) unreadable, skipped` : "") + tooLarge(cursor.skippedTooLarge, "cursor transcript(s)") + (cursor.truncatedTranscripts > 0 ? ` \xB7 ${cursor.truncatedTranscripts} cursor transcript(s) cut at ${MAX_TRANSCRIPT_FILE_BYTES / (1024 * 1024)}MB (the rest of the conversation stays local)` : "") + (heldBack > 0 ? ` \xB7 ${heldBack} older session(s) held back, the first sync backfills the ${DEEP_FIRST_SYNC_MAX_SESSIONS} most recently active` : "") + "."
87163
+ `Found ${inWindow.length} local session(s) (${claude.sessions.length} claude, ${codex.sessions.length} codex, ${cursor.sessions.length} cursor) ` + describeScanReach(window2, options.narrowSinceMs) + (active > 0 ? ` (${active} still active)` : "") + (skippedOutOfScope > 0 ? ` \xB7 ${skippedOutOfScope} ${describeSkipReason(capture)}` : "") + (skippedNoRepo > 0 ? ` \xB7 ${skippedNoRepo} ${describeNoRepoSkipReason(capture)}` : "") + (codex.skippedSubagentThreads > 0 ? ` \xB7 ${codex.skippedSubagentThreads} codex subagent thread(s) skipped (spend unmeasured)` : "") + (cursor.skippedSubagentComposers > 0 ? ` \xB7 ${cursor.skippedSubagentComposers} cursor subagent thread(s) skipped` : "") + (cursor.skippedNonLocalComposers > 0 ? ` \xB7 ${cursor.skippedNonLocalComposers} cursor session(s) skipped (not local to this machine)` : "") + (cursor.skippedUnreadable > 0 ? ` \xB7 ${cursor.skippedUnreadable} cursor session(s) unreadable, skipped` : "") + tooLarge(claude.skippedTooLarge, "claude transcript(s)") + (claude.unreadable.length > 0 ? ` \xB7 ${claude.unreadable.length} claude transcript(s) unreadable, skipped` : "") + tooLarge(codex.skippedTooLarge, "codex rollout(s)") + (codex.unreadable.length > 0 ? ` \xB7 ${codex.unreadable.length} codex rollout(s) unreadable, skipped` : "") + // The measure for POW-79's follow-up: a merged thread re-uploads whole
87164
+ // on every change, so once the largest nears the cap, per-page upload
87165
+ // is due.
87166
+ (codex.mergedThreads > 0 ? ` \xB7 ${codex.mergedThreads} codex thread(s) merged from split rollouts (largest ${(codex.largestMergedBytes / (1024 * 1024)).toFixed(1)}MB of the ${MAX_TRANSCRIPT_FILE_BYTES / (1024 * 1024)}MB cap)` : "") + tooLarge(cursor.skippedTooLarge, "cursor transcript(s)") + (cursor.truncatedTranscripts > 0 ? ` \xB7 ${cursor.truncatedTranscripts} cursor transcript(s) cut at ${MAX_TRANSCRIPT_FILE_BYTES / (1024 * 1024)}MB (the rest of the conversation stays local)` : "") + (heldBack > 0 ? ` \xB7 ${heldBack} older session(s) held back, the first sync backfills the ${DEEP_FIRST_SYNC_MAX_SESSIONS} most recently active` : "") + "."
86927
87167
  );
86928
87168
  for (const failure of claude.unreadable) log3(` claude transcript skipped, ${failure}`);
86929
87169
  for (const failure of codex.unreadable) log3(` codex rollout skipped, ${failure}`);
@@ -87170,10 +87410,10 @@ import path16 from "node:path";
87170
87410
  import {
87171
87411
  existsSync as existsSync5,
87172
87412
  lstatSync as lstatSync3,
87173
- mkdirSync as mkdirSync7,
87413
+ mkdirSync as mkdirSync8,
87174
87414
  readFileSync as readFileSync10,
87175
- renameSync as renameSync2,
87176
- rmSync as rmSync4,
87415
+ renameSync as renameSync3,
87416
+ rmSync as rmSync5,
87177
87417
  writeFileSync as writeFileSync7
87178
87418
  } from "node:fs";
87179
87419
  import path15 from "node:path";
@@ -87254,7 +87494,7 @@ function installProviderHook(provider, home) {
87254
87494
  `${shellQuote2(process.execPath)} ${shellQuote2(scriptPath)}`
87255
87495
  );
87256
87496
  if (merged.action === "skip") return { provider, settings: "skip", detail: merged.reason };
87257
- mkdirSync7(hookDir, { recursive: true });
87497
+ mkdirSync8(hookDir, { recursive: true });
87258
87498
  writeAtomic(scriptPath, readFileSync10(hookSourcePath(script), "utf8"), 448);
87259
87499
  if (merged.action === "write") {
87260
87500
  const current = existsSync5(configPath) ? readFileSync10(configPath, "utf8") : null;
@@ -87272,9 +87512,9 @@ function writeAtomic(file2, text, mode) {
87272
87512
  const temporary = `${file2}.${randomUUID()}.tmp`;
87273
87513
  try {
87274
87514
  writeFileSync7(temporary, text, { mode, flag: "wx" });
87275
- renameSync2(temporary, file2);
87515
+ renameSync3(temporary, file2);
87276
87516
  } finally {
87277
- rmSync4(temporary, { force: true });
87517
+ rmSync5(temporary, { force: true });
87278
87518
  }
87279
87519
  }
87280
87520
  function installProviderHooks(home) {
@@ -87818,22 +88058,96 @@ function describeDelay(ms) {
87818
88058
  }
87819
88059
 
87820
88060
  // ../../apps/collector/src/localSessionFacts.ts
87821
- import { existsSync as existsSync7, readdirSync as readdirSync4 } from "node:fs";
88061
+ import { existsSync as existsSync7, readdirSync as readdirSync4, statSync as statSync4 } from "node:fs";
87822
88062
  import os16 from "node:os";
88063
+ import path18 from "node:path";
88064
+
88065
+ // ../../apps/collector/src/codexReviewFacts.ts
88066
+ import { closeSync as closeSync5, lstatSync as lstatSync4, openSync as openSync5, readSync as readSync4, realpathSync as realpathSync3 } from "node:fs";
87823
88067
  import path17 from "node:path";
88068
+ var pointerSchema = external_exports.object({
88069
+ source: external_exports.unknown().optional(),
88070
+ rollout_path: external_exports.string().nullish()
88071
+ });
88072
+ var metaSchema = external_exports.object({
88073
+ type: external_exports.literal("session_meta"),
88074
+ payload: external_exports.object({
88075
+ id: external_exports.string(),
88076
+ source: external_exports.unknown().optional(),
88077
+ thread_source: external_exports.string().optional()
88078
+ })
88079
+ });
88080
+ var MAX_PREFIX_BYTES = 256 * 1024;
88081
+ function readCodexReviewFacts(row, id, home) {
88082
+ const pointer = pointerSchema.parse(row);
88083
+ if (pointer.source !== "exec" || !pointer.rollout_path) return {};
88084
+ const file2 = pointer.rollout_path;
88085
+ if (!path17.isAbsolute(file2) || !file2.endsWith(".jsonl")) return {};
88086
+ const root = ["sessions", "archived_sessions"].map((store) => path17.join(home, ".codex", store)).find((store) => {
88087
+ const relative2 = path17.relative(store, file2);
88088
+ return relative2 !== "" && relative2 !== ".." && !relative2.startsWith(`..${path17.sep}`) && !path17.isAbsolute(relative2);
88089
+ });
88090
+ if (!root) return {};
88091
+ try {
88092
+ if (!lstatSync4(file2).isFile() || realpathSync3(file2) !== path17.join(realpathSync3(root), path17.relative(root, file2))) return {};
88093
+ const records = readPrefix(file2);
88094
+ if (records === null) return {};
88095
+ const meta3 = metaSchema.safeParse(records[0]);
88096
+ if (!meta3.success || meta3.data.payload.id !== id) return {};
88097
+ return harnessSessionFacts("codex", { ...meta3.data.payload, initialEvent: records[1] });
88098
+ } catch (error62) {
88099
+ if (error62 instanceof Error && "code" in error62 && error62.code === "ENOENT") return {};
88100
+ throw error62;
88101
+ }
88102
+ }
88103
+ function readPrefix(file2) {
88104
+ const fd = openSync5(file2, "r");
88105
+ const buffer = Buffer.alloc(MAX_PREFIX_BYTES);
88106
+ let used = 0;
88107
+ let first = -1;
88108
+ let second = -1;
88109
+ try {
88110
+ while (used < buffer.length && second < 0) {
88111
+ const bytes = readSync4(fd, buffer, used, Math.min(4096, buffer.length - used), null);
88112
+ if (bytes === 0) break;
88113
+ const end = used + bytes;
88114
+ for (let i = used; i < end; i++) {
88115
+ if (buffer[i] !== 10) continue;
88116
+ if (first < 0) first = i;
88117
+ else {
88118
+ second = i;
88119
+ break;
88120
+ }
88121
+ }
88122
+ used = end;
88123
+ }
88124
+ } finally {
88125
+ closeSync5(fd);
88126
+ }
88127
+ if (first < 0 || second < 0) return null;
88128
+ try {
88129
+ return [JSON.parse(buffer.subarray(0, first).toString("utf8")), JSON.parse(buffer.subarray(first + 1, second).toString("utf8"))];
88130
+ } catch {
88131
+ return null;
88132
+ }
88133
+ }
88134
+
88135
+ // ../../apps/collector/src/localSessionFacts.ts
88136
+ var WORKING_FRESH_MS = 9e4;
87824
88137
  var STORES = [
87825
88138
  {
87826
88139
  source: "codex",
87827
88140
  file: (home) => {
87828
- const directory = path17.join(home, ".codex");
88141
+ const directory = path18.join(home, ".codex");
87829
88142
  if (!existsSync7(directory)) return null;
87830
88143
  const files = readdirSync4(directory).filter((name) => /^state_\d+\.sqlite$/.test(name)).sort((a, b2) => Number(b2.match(/\d+/)?.[0]) - Number(a.match(/\d+/)?.[0]));
87831
- return files[0] ? path17.join(directory, files[0]) : null;
88144
+ return files[0] ? path18.join(directory, files[0]) : null;
87832
88145
  },
87833
88146
  id: (externalId) => /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/i.exec(externalId)?.[1],
87834
88147
  table: "threads",
87835
88148
  key: "id",
87836
- fields: ["source", "thread_source", "archived"],
88149
+ fields: ["source", "thread_source", "archived", "rollout_path"],
88150
+ additionalFacts: readCodexReviewFacts,
87837
88151
  decode: (row) => {
87838
88152
  const parsed = external_exports.object({
87839
88153
  source: external_exports.unknown().optional(),
@@ -87848,20 +88162,29 @@ var STORES = [
87848
88162
  }
87849
88163
  }
87850
88164
  return { ...parsed, source };
88165
+ },
88166
+ written: (row) => {
88167
+ const rollout = external_exports.object({ rollout_path: external_exports.string() }).safeParse(row);
88168
+ return rollout.success ? fileWrittenAt(rollout.data.rollout_path) : null;
87851
88169
  }
87852
88170
  },
87853
88171
  {
87854
88172
  source: "cursor",
87855
- file: (home) => path17.join(defaultCursorUserDir(home), "globalStorage", "state.vscdb"),
88173
+ file: (home) => path18.join(defaultCursorUserDir(home), "globalStorage", "state.vscdb"),
87856
88174
  id: (externalId) => externalId,
87857
88175
  table: "composerHeaders",
87858
88176
  key: "composerId",
87859
- fields: ["isArchived", "isSubagent"],
87860
- decode: (row) => row
88177
+ fields: ["isArchived", "isSubagent", "lastUpdatedAt"],
88178
+ decode: (row) => row,
88179
+ written: (row) => {
88180
+ const stamp = external_exports.object({ lastUpdatedAt: external_exports.number() }).safeParse(row);
88181
+ return stamp.success ? stamp.data.lastUpdatedAt : null;
88182
+ }
87861
88183
  }
87862
88184
  ];
87863
- async function readLocalSessionFacts(sessions, onError2, home = os16.homedir()) {
88185
+ async function readLocalSessionFacts(sessions, onError2, home = os16.homedir(), now = Date.now()) {
87864
88186
  const result = /* @__PURE__ */ new Map();
88187
+ const working = (writtenAt) => writtenAt !== null && now - writtenAt < WORKING_FRESH_MS ? { working: true } : {};
87865
88188
  for (const store of STORES) {
87866
88189
  const wanted = sessions.filter((session) => session.source === store.source);
87867
88190
  if (wanted.length === 0) continue;
@@ -87885,11 +88208,16 @@ async function readLocalSessionFacts(sessions, onError2, home = os16.homedir())
87885
88208
  if (!id) continue;
87886
88209
  try {
87887
88210
  const row = statement.get(id);
87888
- if (row !== void 0)
87889
- result.set(
87890
- localSessionKey(session),
87891
- harnessSessionFacts(store.source, store.decode(row))
87892
- );
88211
+ if (row !== void 0) {
88212
+ const key = localSessionKey(session);
88213
+ const facts = {
88214
+ ...harnessSessionFacts(store.source, store.decode(row)),
88215
+ ...working(store.written(row))
88216
+ };
88217
+ result.set(key, facts);
88218
+ if ("additionalFacts" in store && facts.archived !== true && facts.subagent !== true)
88219
+ result.set(key, { ...facts, ...store.additionalFacts(row, id, home) });
88220
+ }
87893
88221
  } catch (error62) {
87894
88222
  onError2(error62, store.source);
87895
88223
  }
@@ -87901,26 +88229,297 @@ async function readLocalSessionFacts(sessions, onError2, home = os16.homedir())
87901
88229
  onError2(error62, store.source);
87902
88230
  }
87903
88231
  }
88232
+ try {
88233
+ for (const session of sessions.filter((session2) => session2.source === "claude-code")) {
88234
+ const facts = working(claudeTranscriptWrittenAt(session.externalId, home));
88235
+ if (facts.working) result.set(localSessionKey(session), facts);
88236
+ }
88237
+ } catch (error62) {
88238
+ onError2(error62, "claude-code");
88239
+ }
87904
88240
  return result;
87905
88241
  }
88242
+ function claudeTranscriptWrittenAt(sessionId, home) {
88243
+ if (!/^[0-9a-f-]{36}$/i.test(sessionId)) return null;
88244
+ const projects = path18.join(home, ".claude", "projects");
88245
+ if (!existsSync7(projects)) return null;
88246
+ for (const entry of readdirSync4(projects, { withFileTypes: true })) {
88247
+ if (!entry.isDirectory()) continue;
88248
+ const writtenAt = fileWrittenAt(path18.join(projects, entry.name, `${sessionId}.jsonl`));
88249
+ if (writtenAt !== null) return writtenAt;
88250
+ }
88251
+ return null;
88252
+ }
88253
+ function fileWrittenAt(file2) {
88254
+ try {
88255
+ return statSync4(file2).mtimeMs;
88256
+ } catch {
88257
+ return null;
88258
+ }
88259
+ }
87906
88260
  function localSessionKey(session) {
87907
88261
  return JSON.stringify([session.source, session.externalId]);
87908
88262
  }
87909
88263
 
88264
+ // src/clientFailure.ts
88265
+ function clientFailure(error62) {
88266
+ if (error62 instanceof ExpectedCliError) {
88267
+ return { outcome: "failed", domain: "Powerplant", code: "EXPECTED_CLI_OUTCOME" };
88268
+ }
88269
+ const code = error62 instanceof Error && "code" in error62 && typeof error62.code === "string" && /^E[A-Z0-9_]{1,31}$/.test(error62.code) ? error62.code : void 0;
88270
+ return {
88271
+ outcome: code === "ENOENT" ? "missing" : code === "EACCES" || code === "EPERM" ? "denied" : "failed",
88272
+ domain: code ? Object.hasOwn(constants.errno, code) ? "POSIX" : "Node" : "JavaScript",
88273
+ code: code ?? (error62 instanceof TypeError ? "TypeError" : error62 instanceof RangeError ? "RangeError" : "unclassified")
88274
+ };
88275
+ }
88276
+ function nativeFailureRecord(error62) {
88277
+ return `POWERPLANT_DIAGNOSTIC ${JSON.stringify({ version: 1, failure: clientFailure(error62) })}`;
88278
+ }
88279
+
88280
+ // src/desktopDiagnostics.ts
88281
+ import os18 from "node:os";
88282
+ import path20 from "node:path";
88283
+
88284
+ // src/memberSessions.ts
88285
+ import { execFileSync as execFileSync4 } from "node:child_process";
88286
+ import { existsSync as existsSync8 } from "node:fs";
88287
+ import { open as open2, readdir as readdir2 } from "node:fs/promises";
88288
+ import os17 from "node:os";
88289
+ import path19 from "node:path";
88290
+ var memberSessionSchema = external_exports.object({
88291
+ id: external_exports.string().min(1),
88292
+ source: external_exports.string().min(1),
88293
+ externalId: external_exports.string().min(1),
88294
+ title: external_exports.string().nullable(),
88295
+ repoDir: external_exports.string().nullable(),
88296
+ machineId: external_exports.string().nullable(),
88297
+ lastActivityAt: external_exports.string().min(1),
88298
+ providerUrl: external_exports.string().nullable(),
88299
+ archived: external_exports.boolean().optional(),
88300
+ subagent: external_exports.boolean().optional(),
88301
+ standaloneReview: external_exports.boolean().optional(),
88302
+ /** The harness wrote to the session moments ago (this machine only, see
88303
+ * the collector's LocalSessionFacts). Absent is unknown, never idle. */
88304
+ working: external_exports.boolean().optional()
88305
+ });
88306
+ function applyLocalFacts(sessions, machineId, localFacts, localKey, claudeDesktop) {
88307
+ return sessions.map((session) => {
88308
+ if (machineId === null || session.machineId !== machineId) return session;
88309
+ const desktop = session.source === "claude-code" ? claudeDesktop.get(session.externalId) : void 0;
88310
+ return {
88311
+ ...session,
88312
+ ...localFacts.get(localKey(session)),
88313
+ ...desktop?.archived === true && { archived: true }
88314
+ };
88315
+ });
88316
+ }
88317
+ async function fetchMemberSessions(credentials, fetchImpl = fetch, options = { windowHours: RECENT_SESSION_WINDOW_MS / 36e5, limit: RECENT_SESSION_VISIBLE_LIMIT }) {
88318
+ const { windowHours, limit } = recentSessionOptionsSchema.parse(options);
88319
+ try {
88320
+ const query = new URLSearchParams({ view: "recent", windowHours: String(windowHours), limit: String(limit) });
88321
+ const response = await fetchImpl(`${credentials.apiUrl}/api/collector/member-sessions?${query.toString()}`, {
88322
+ headers: { authorization: `Bearer ${credentials.token}`, ...cliVersionHeaders() },
88323
+ signal: AbortSignal.timeout(1e4)
88324
+ });
88325
+ if (!response.ok) throw new Error(`session read returned ${response.status}`);
88326
+ const { data } = external_exports.object({ data: external_exports.object({
88327
+ sessions: external_exports.array(memberSessionSchema).max(50),
88328
+ nextCursor: external_exports.string().max(512).nullable().optional()
88329
+ }) }).parse(await response.json());
88330
+ return {
88331
+ sessions: data.sessions.slice(0, limit),
88332
+ // Older servers ignore the recent window and omit this field.
88333
+ // A cursor on a supported server is an intentional cap, not a failure.
88334
+ incomplete: data.nextCursor === void 0
88335
+ };
88336
+ } catch {
88337
+ return null;
88338
+ }
88339
+ }
88340
+ function resumeCommand(source, sessionId, powerplantUrl) {
88341
+ return ["resume-session", source, sessionId, "--open", powerplantUrl];
88342
+ }
88343
+ function sessionLinks(session, webUrl, options) {
88344
+ const powerplantUrl = `${webUrl}/rooms/${session.id}`;
88345
+ switch (session.source) {
88346
+ case "claude-code":
88347
+ if (!options.localMachine) return { powerplantUrl };
88348
+ if (options.terminalSession !== void 0) {
88349
+ const { tty, appPid, appName } = options.terminalSession;
88350
+ return {
88351
+ powerplantUrl,
88352
+ extra: {
88353
+ label: `Show in ${appName}`,
88354
+ focus: { tty, appPid },
88355
+ terminal: resumeCommand("claude-code", session.externalId, powerplantUrl)
88356
+ }
88357
+ };
88358
+ }
88359
+ if (options.claudeDesktopSessionId !== void 0) {
88360
+ return {
88361
+ powerplantUrl,
88362
+ extra: {
88363
+ label: "Open in Claude",
88364
+ url: `claude://claude.ai/epitaxy/${encodeURIComponent(options.claudeDesktopSessionId)}`
88365
+ }
88366
+ };
88367
+ }
88368
+ return {
88369
+ powerplantUrl,
88370
+ extra: {
88371
+ label: "Resume in terminal",
88372
+ terminal: resumeCommand("claude-code", session.externalId, powerplantUrl)
88373
+ }
88374
+ };
88375
+ case "codex": {
88376
+ const threadId2 = codexThreadId(session.externalId);
88377
+ if (threadId2 === null || !options.localMachine) return { powerplantUrl };
88378
+ return {
88379
+ powerplantUrl,
88380
+ extra: options.codexDesktop ? { label: "Open in Codex", url: `codex://threads/${threadId2}` } : { label: "Resume in terminal", terminal: resumeCommand("codex", threadId2, powerplantUrl) }
88381
+ };
88382
+ }
88383
+ case "claude-cloud":
88384
+ return {
88385
+ powerplantUrl,
88386
+ extra: { label: "Open on claude.ai", url: `https://claude.ai/code/${encodeURIComponent(session.externalId)}` }
88387
+ };
88388
+ default:
88389
+ return session.providerUrl === null ? { powerplantUrl } : { powerplantUrl, extra: { label: "Open in Cursor", url: session.providerUrl } };
88390
+ }
88391
+ }
88392
+ var TRAILING_UUID = /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/i;
88393
+ function codexThreadId(externalId) {
88394
+ return TRAILING_UUID.exec(externalId)?.[1] ?? null;
88395
+ }
88396
+ var CODEX_APP_BUNDLES = ["ChatGPT.app", "Codex.app"];
88397
+ var urlSchemesSchema = external_exports.array(external_exports.object({ CFBundleURLSchemes: external_exports.array(external_exports.string()).optional() }));
88398
+ function detectCodexDesktop(probe) {
88399
+ return detectDesktopScheme(CODEX_APP_BUNDLES, "codex", probe);
88400
+ }
88401
+ function detectClaudeDesktop(probe) {
88402
+ return detectDesktopScheme(["Claude.app"], "claude", probe);
88403
+ }
88404
+ function detectDesktopScheme(bundles, scheme, probe = { exists: existsSync8, readUrlSchemes: realReadUrlSchemes }) {
88405
+ const roots = ["/Applications", path19.join(os17.homedir(), "Applications")];
88406
+ return roots.some(
88407
+ (root) => bundles.some((bundle) => {
88408
+ const bundlePath = path19.join(root, bundle);
88409
+ return probe.exists(bundlePath) && probe.readUrlSchemes(bundlePath).includes(scheme);
88410
+ })
88411
+ );
88412
+ }
88413
+ function realReadUrlSchemes(bundlePath) {
88414
+ if (process.platform !== "darwin") return [];
88415
+ try {
88416
+ const json2 = execFileSync4(
88417
+ "plutil",
88418
+ ["-extract", "CFBundleURLTypes", "json", "-o", "-", path19.join(bundlePath, "Contents", "Info.plist")],
88419
+ { stdio: ["ignore", "pipe", "ignore"] }
88420
+ ).toString();
88421
+ const parsed = urlSchemesSchema.safeParse(JSON.parse(json2));
88422
+ if (!parsed.success) return [];
88423
+ return parsed.data.flatMap((entry) => entry.CFBundleURLSchemes ?? []);
88424
+ } catch {
88425
+ return [];
88426
+ }
88427
+ }
88428
+ var claudeDesktopSessionSchema = external_exports.object({
88429
+ sessionId: external_exports.string().regex(/^local_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i),
88430
+ cliSessionId: external_exports.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i),
88431
+ /** Observed 2026-09-10 on Claude 1.52386.0: the app sets this itself on
88432
+ * older sessions as well as on a user's archive action. A file without
88433
+ * it, or with another shape, is not archived as far as this read knows,
88434
+ * and still links: the flag must never cost the row its desktop link. */
88435
+ isArchived: external_exports.unknown().optional()
88436
+ });
88437
+ async function readClaudeDesktopSessions(wanted, root = path19.join(os17.homedir(), "Library/Application Support/Claude/claude-code-sessions")) {
88438
+ const sessions = /* @__PURE__ */ new Map();
88439
+ const ambiguous = /* @__PURE__ */ new Set();
88440
+ if (wanted.size === 0) return sessions;
88441
+ const buffer = Buffer.alloc(1024 * 1024 + 1);
88442
+ async function visit3(directory, depth) {
88443
+ const entries = await readdir2(directory, { withFileTypes: true }).catch((error62) => {
88444
+ if (depth > 0 && isMissingFile(error62)) return [];
88445
+ throw error62;
88446
+ });
88447
+ for (const entry of entries) {
88448
+ const file2 = path19.join(directory, entry.name);
88449
+ if (entry.isDirectory() && depth < 2) {
88450
+ await visit3(file2, depth + 1);
88451
+ } else if (depth === 2 && entry.isFile() && /^local_.*\.json$/.test(entry.name)) {
88452
+ const handle = await open2(file2, "r").catch((error62) => {
88453
+ if (isMissingFile(error62)) return null;
88454
+ throw error62;
88455
+ });
88456
+ if (handle === null) continue;
88457
+ try {
88458
+ const { bytesRead } = await handle.read(buffer);
88459
+ if (bytesRead > 1024 * 1024) continue;
88460
+ const parsed = claudeDesktopSessionSchema.safeParse(
88461
+ JSON.parse(buffer.subarray(0, bytesRead).toString())
88462
+ );
88463
+ if (!parsed.success || !wanted.has(parsed.data.cliSessionId)) continue;
88464
+ const { cliSessionId, sessionId, isArchived } = parsed.data;
88465
+ if (ambiguous.has(cliSessionId)) continue;
88466
+ if (sessions.has(cliSessionId) && sessions.get(cliSessionId)?.sessionId !== sessionId) {
88467
+ sessions.delete(cliSessionId);
88468
+ ambiguous.add(cliSessionId);
88469
+ } else {
88470
+ sessions.set(cliSessionId, { sessionId, archived: isArchived === true });
88471
+ }
88472
+ } catch (error62) {
88473
+ if (!(error62 instanceof SyntaxError)) throw error62;
88474
+ } finally {
88475
+ await handle.close();
88476
+ }
88477
+ }
88478
+ }
88479
+ }
88480
+ await visit3(root, 0);
88481
+ return sessions;
88482
+ }
88483
+ function isMissingFile(error62) {
88484
+ return error62 instanceof Error && "code" in error62 && error62.code === "ENOENT";
88485
+ }
88486
+
88487
+ // src/desktopDiagnostics.ts
88488
+ async function probeClaudeDesktopSessions(wanted, installed, reportFault, root = path20.join(os18.homedir(), "Library/Application Support/Claude/claude-code-sessions"), read = readClaudeDesktopSessions) {
88489
+ if (!installed || wanted.size === 0) {
88490
+ return { sessions: /* @__PURE__ */ new Map(), diagnostic: { outcome: "not-needed" } };
88491
+ }
88492
+ try {
88493
+ return { sessions: await read(wanted, root), diagnostic: { outcome: "available" } };
88494
+ } catch (error62) {
88495
+ const diagnostic = clientFailure(error62);
88496
+ if (diagnostic.domain === "JavaScript" || diagnostic.domain === "Node") {
88497
+ reportFault(new Error(`Claude desktop registry failed (${diagnostic.domain}:${diagnostic.code})`));
88498
+ }
88499
+ return { sessions: /* @__PURE__ */ new Map(), diagnostic };
88500
+ }
88501
+ }
88502
+
88503
+ // src/cli.ts
88504
+ import { spawn as spawn2, spawnSync as spawnSync5 } from "node:child_process";
88505
+ import { existsSync as existsSync12, mkdirSync as mkdirSync12, openSync as openSync7, realpathSync as realpathSync5, rmSync as rmSync7 } from "node:fs";
88506
+ import path28 from "node:path";
88507
+ import { parseArgs } from "node:util";
88508
+
87910
88509
  // src/connect.ts
87911
- import { execFileSync as execFileSync4, spawnSync } from "node:child_process";
88510
+ import { execFileSync as execFileSync5, spawnSync } from "node:child_process";
87912
88511
  import {
87913
- existsSync as existsSync8,
87914
- mkdirSync as mkdirSync8,
88512
+ existsSync as existsSync9,
88513
+ mkdirSync as mkdirSync9,
87915
88514
  mkdtempSync,
87916
88515
  readdirSync as readdirSync5,
87917
88516
  readFileSync as readFileSync11,
87918
- realpathSync as realpathSync3,
87919
- statSync as statSync4,
88517
+ realpathSync as realpathSync4,
88518
+ statSync as statSync5,
87920
88519
  writeFileSync as writeFileSync8
87921
88520
  } from "node:fs";
87922
- import os17 from "node:os";
87923
- import path18 from "node:path";
88521
+ import os19 from "node:os";
88522
+ import path21 from "node:path";
87924
88523
  import { emitKeypressEvents } from "node:readline";
87925
88524
 
87926
88525
  // src/agentVersions.ts
@@ -87978,6 +88577,11 @@ var officialClientsSchema = external_exports.object({
87978
88577
  cursor: external_exports.object({ clientId: external_exports.string().min(1) })
87979
88578
  }).nullable();
87980
88579
  var officialClientsDocumentSchema = external_exports.object({ clients: officialClientsSchema });
88580
+ function connectExitCode(outcome, background) {
88581
+ if (outcome.failed > 0) return 1;
88582
+ if (background && (outcome.pending > 0 || outcome.connected + outcome.configured === 0)) return 1;
88583
+ return 0;
88584
+ }
87981
88585
  var OPENAI_TEAM_ID = "2DC432GLL2";
87982
88586
  var CURSOR_TEAM_ID = "VDXQ22DGB9";
87983
88587
  var CODEX_BUNDLE_ID = "com.openai.codex";
@@ -87989,10 +88593,10 @@ function startTimeBudget(totalMs, now = Date.now) {
87989
88593
  return { remainingMs: () => Math.max(0, deadline - now()) };
87990
88594
  }
87991
88595
  function defaultApplicationsDirs(homeDir) {
87992
- return process.platform === "darwin" ? ["/Applications", path18.join(homeDir, "Applications")] : [];
88596
+ return process.platform === "darwin" ? ["/Applications", path21.join(homeDir, "Applications")] : [];
87993
88597
  }
87994
88598
  function detectClients(options = {}) {
87995
- const homeDir = options.homeDir ?? os17.homedir();
88599
+ const homeDir = options.homeDir ?? os19.homedir();
87996
88600
  const whichAll = options.whichAll ?? defaultWhichAll;
87997
88601
  const env = options.env ?? process.env;
87998
88602
  const applicationsDirs = options.applicationsDirs ?? defaultApplicationsDirs(homeDir);
@@ -88007,7 +88611,7 @@ function detectClients(options = {}) {
88007
88611
  const add = (client, bin, configDir) => {
88008
88612
  let real;
88009
88613
  try {
88010
- real = realpathSync3(bin);
88614
+ real = realpathSync4(bin);
88011
88615
  } catch {
88012
88616
  return;
88013
88617
  }
@@ -88017,20 +88621,20 @@ function detectClients(options = {}) {
88017
88621
  clients.push({ client, bin, ...configDir !== void 0 && { configDir } });
88018
88622
  };
88019
88623
  for (const bin of whichAll("claude")) add("claude", bin);
88020
- const localClaude = path18.join(homeDir, ".local", "bin", "claude");
88021
- if (existsSync8(localClaude)) add("claude", localClaude);
88624
+ const localClaude = path21.join(homeDir, ".local", "bin", "claude");
88625
+ if (existsSync9(localClaude)) add("claude", localClaude);
88022
88626
  for (const bin of desktopClaudeBinaries(homeDir)) add("claude", bin);
88023
88627
  const claudeBins = clients.filter((client) => client.client === "claude" && client.configDir === void 0).map((client) => client.bin);
88024
88628
  for (const configDir of claudeConfigHomes(homeDir, env)) {
88025
88629
  for (const bin of claudeBins) add("claude", bin, configDir);
88026
88630
  }
88027
88631
  for (const bin of whichAll("codex")) add("codex", bin);
88028
- const localCodex = path18.join(homeDir, ".local", "bin", "codex");
88029
- if (existsSync8(localCodex)) add("codex", localCodex);
88632
+ const localCodex = path21.join(homeDir, ".local", "bin", "codex");
88633
+ if (existsSync9(localCodex)) add("codex", localCodex);
88030
88634
  for (const bin of codexBundleBinaries(applicationsDirs, bundleSeams)) add("codex", bin);
88031
- const cursorDir = path18.join(homeDir, ".cursor");
88032
- if (existsSync8(cursorDir) || cursorAppInstalled(applicationsDirs, bundleSeams)) {
88033
- clients.push({ client: "cursor", bin: path18.join(cursorDir, "mcp.json") });
88635
+ const cursorDir = path21.join(homeDir, ".cursor");
88636
+ if (existsSync9(cursorDir) || cursorAppInstalled(applicationsDirs, bundleSeams)) {
88637
+ clients.push({ client: "cursor", bin: path21.join(cursorDir, "mcp.json") });
88034
88638
  }
88035
88639
  return clients;
88036
88640
  }
@@ -88038,19 +88642,19 @@ function claudeConfigHomes(homeDir, env) {
88038
88642
  const homes = [];
88039
88643
  const seen = /* @__PURE__ */ new Set();
88040
88644
  try {
88041
- seen.add(realpathSync3(path18.join(homeDir, ".claude")));
88645
+ seen.add(realpathSync4(path21.join(homeDir, ".claude")));
88042
88646
  } catch {
88043
88647
  }
88044
88648
  const add = (configDir) => {
88045
88649
  let real;
88046
88650
  try {
88047
- real = realpathSync3(configDir);
88651
+ real = realpathSync4(configDir);
88048
88652
  } catch {
88049
88653
  return;
88050
88654
  }
88051
88655
  if (seen.has(real)) return;
88052
88656
  seen.add(real);
88053
- homes.push(path18.resolve(configDir));
88657
+ homes.push(path21.resolve(configDir));
88054
88658
  };
88055
88659
  let entries = [];
88056
88660
  try {
@@ -88058,8 +88662,8 @@ function claudeConfigHomes(homeDir, env) {
88058
88662
  } catch {
88059
88663
  }
88060
88664
  for (const entry of entries.sort()) {
88061
- if (entry.startsWith(".claude-") && existsSync8(path18.join(homeDir, entry, ".claude.json"))) {
88062
- add(path18.join(homeDir, entry));
88665
+ if (entry.startsWith(".claude-") && existsSync9(path21.join(homeDir, entry, ".claude.json"))) {
88666
+ add(path21.join(homeDir, entry));
88063
88667
  }
88064
88668
  }
88065
88669
  if (env.CLAUDE_CONFIG_DIR) add(env.CLAUDE_CONFIG_DIR);
@@ -88087,7 +88691,7 @@ function appBundles(applicationsDirs, namePrefixes) {
88087
88691
  for (const entry of entries) {
88088
88692
  if (!entry.endsWith(".app")) continue;
88089
88693
  if (!namePrefixes.some((prefix) => entry.startsWith(prefix))) continue;
88090
- bundles.push(path18.join(dir, entry));
88694
+ bundles.push(path21.join(dir, entry));
88091
88695
  }
88092
88696
  }
88093
88697
  return bundles;
@@ -88107,7 +88711,7 @@ function codexBundleBinaries(applicationsDirs, seams) {
88107
88711
  const infoTimeoutMs = budgetedTimeout(BUNDLE_INFO_TIMEOUT_MS, appDir, seams);
88108
88712
  if (infoTimeoutMs === null) continue;
88109
88713
  if (seams.readBundleInfo(appDir, infoTimeoutMs)?.bundleId !== CODEX_BUNDLE_ID) continue;
88110
- const bin = path18.join(appDir, "Contents", "Resources", "codex");
88714
+ const bin = path21.join(appDir, "Contents", "Resources", "codex");
88111
88715
  if (!isExecutableFile(bin)) continue;
88112
88716
  if (!signedByTeam(bin, OPENAI_TEAM_ID, "OpenAI", appDir, seams)) continue;
88113
88717
  found.push(bin);
@@ -88119,7 +88723,7 @@ function trustedCursorBundle(appDir, seams) {
88119
88723
  if (infoTimeoutMs === null) return null;
88120
88724
  const info = seams.readBundleInfo(appDir, infoTimeoutMs);
88121
88725
  if (info?.executable === void 0) return null;
88122
- const bin = path18.join(appDir, "Contents", "MacOS", info.executable);
88726
+ const bin = path21.join(appDir, "Contents", "MacOS", info.executable);
88123
88727
  if (!isExecutableFile(bin)) return null;
88124
88728
  if (!signedByTeam(bin, CURSOR_TEAM_ID, "Cursor", appDir, seams)) return null;
88125
88729
  return info;
@@ -88142,7 +88746,7 @@ function cursorAppVersion(applicationsDirs, seams) {
88142
88746
  }
88143
88747
  function isExecutableFile(filePath) {
88144
88748
  try {
88145
- const stats = statSync4(filePath);
88749
+ const stats = statSync5(filePath);
88146
88750
  return stats.isFile() && (stats.mode & 73) !== 0;
88147
88751
  } catch {
88148
88752
  return false;
@@ -88156,7 +88760,7 @@ var bundleInfoSchema = external_exports.object({
88156
88760
  function realReadBundleInfo(appDir, timeoutMs) {
88157
88761
  const result = spawnSync(
88158
88762
  "plutil",
88159
- ["-convert", "json", "-o", "-", path18.join(appDir, "Contents", "Info.plist")],
88763
+ ["-convert", "json", "-o", "-", path21.join(appDir, "Contents", "Info.plist")],
88160
88764
  { encoding: "utf8", timeout: timeoutMs }
88161
88765
  );
88162
88766
  if (result.status !== 0) return null;
@@ -88178,18 +88782,18 @@ function realVerifySignature(binPath, teamId, timeoutMs) {
88178
88782
  }).status === 0;
88179
88783
  }
88180
88784
  function desktopClaudeBinaries(homeDir) {
88181
- const root = path18.join(homeDir, "Library", "Application Support", "Claude", "claude-code");
88785
+ const root = path21.join(homeDir, "Library", "Application Support", "Claude", "claude-code");
88182
88786
  let versions;
88183
88787
  try {
88184
88788
  versions = readdirSync5(root);
88185
88789
  } catch {
88186
88790
  return [];
88187
88791
  }
88188
- return versions.map((version2) => path18.join(root, version2, "claude.app", "Contents", "MacOS", "claude")).filter((bin) => existsSync8(bin));
88792
+ return versions.map((version2) => path21.join(root, version2, "claude.app", "Contents", "MacOS", "claude")).filter((bin) => existsSync9(bin));
88189
88793
  }
88190
88794
  function defaultWhichAll(name) {
88191
88795
  try {
88192
- return execFileSync4("which", ["-a", name], { encoding: "utf8" }).split("\n").map((line) => line.trim()).filter(Boolean);
88796
+ return execFileSync5("which", ["-a", name], { encoding: "utf8" }).split("\n").map((line) => line.trim()).filter(Boolean);
88193
88797
  } catch {
88194
88798
  return [];
88195
88799
  }
@@ -88284,9 +88888,9 @@ function displayName(client, all) {
88284
88888
  const sameTarget = peers.filter((peer) => peer.configDir === client.configDir);
88285
88889
  const details = [];
88286
88890
  if (profiles.size > 1) {
88287
- details.push(client.configDir?.replace(os17.homedir(), "~") ?? "default profile");
88891
+ details.push(client.configDir?.replace(os19.homedir(), "~") ?? "default profile");
88288
88892
  }
88289
- if (sameTarget.length > 1) details.push(client.bin.replace(os17.homedir(), "~"));
88893
+ if (sameTarget.length > 1) details.push(client.bin.replace(os19.homedir(), "~"));
88290
88894
  return details.length > 0 ? `${product} (${details.join(", ")})` : product;
88291
88895
  }
88292
88896
  function pickerAllowed(options) {
@@ -88736,7 +89340,7 @@ function connectCursor(mcpJsonPath, name, deps) {
88736
89340
  );
88737
89341
  if (patch.error !== void 0 || patch.entry === void 0) {
88738
89342
  return failed(
88739
- `${mcpJsonPath.replace(os17.homedir(), "~")} is ${patch.error}, fix it by hand, then re-run ${deps.connectCommand}.`
89343
+ `${mcpJsonPath.replace(os19.homedir(), "~")} is ${patch.error}, fix it by hand, then re-run ${deps.connectCommand}.`
88740
89344
  );
88741
89345
  }
88742
89346
  if (patch.changed) deps.writeTextFile(mcpJsonPath, patch.content);
@@ -88792,7 +89396,7 @@ function disconnectTarget(agent, candidates, deps) {
88792
89396
  try {
88793
89397
  last = candidate.client === "claude" ? disconnectClaude(candidate, deps) : candidate.client === "codex" ? disconnectCodex(candidate.bin, deps) : disconnectCursor(candidate.bin, deps);
88794
89398
  } catch (error62) {
88795
- const name = candidate.client === "cursor" ? `Cursor (${candidate.bin.replace(os17.homedir(), "~")})` : describeBinary(candidate.bin);
89399
+ const name = candidate.client === "cursor" ? `Cursor (${candidate.bin.replace(os19.homedir(), "~")})` : describeBinary(candidate.bin);
88796
89400
  deps.log(`\u2717 ${name}: ${error62 instanceof Error ? error62.message : String(error62)}`);
88797
89401
  last = "failed";
88798
89402
  }
@@ -88854,7 +89458,7 @@ function disconnectCodex(bin, deps) {
88854
89458
  return "disconnected";
88855
89459
  }
88856
89460
  function disconnectCursor(mcpJsonPath, deps) {
88857
- const name = `Cursor (${mcpJsonPath.replace(os17.homedir(), "~")})`;
89461
+ const name = `Cursor (${mcpJsonPath.replace(os19.homedir(), "~")})`;
88858
89462
  const patch = unpatchCursorMcpJson(deps.readTextFile(mcpJsonPath), MCP_SERVER_NAME);
88859
89463
  if (patch.error !== void 0) {
88860
89464
  deps.log(`\u2717 ${name}: mcp.json is ${patch.error}, fix it by hand, then re-run powerplant disconnect.`);
@@ -88884,11 +89488,11 @@ function anyClientStillConnected(clients, deps) {
88884
89488
  });
88885
89489
  }
88886
89490
  function describeBinary(bin) {
88887
- return `${path18.basename(bin)} (${bin.replace(os17.homedir(), "~")})`;
89491
+ return `${path21.basename(bin)} (${bin.replace(os19.homedir(), "~")})`;
88888
89492
  }
88889
89493
  function describeClaudeTarget(client) {
88890
89494
  if (client.configDir === void 0) return describeBinary(client.bin);
88891
- return `${path18.basename(client.bin)} (${client.configDir.replace(os17.homedir(), "~")})`;
89495
+ return `${path21.basename(client.bin)} (${client.configDir.replace(os19.homedir(), "~")})`;
88892
89496
  }
88893
89497
  var FAILURE_DETAIL_MAX_CHARS = 200;
88894
89498
  function describeFailure(result) {
@@ -88901,7 +89505,7 @@ function describeFailure(result) {
88901
89505
  }
88902
89506
  var neutralDirMemo;
88903
89507
  function neutralWorkdir() {
88904
- neutralDirMemo ??= mkdtempSync(path18.join(os17.tmpdir(), "powerplant-connect-"));
89508
+ neutralDirMemo ??= mkdtempSync(path21.join(os19.tmpdir(), "powerplant-connect-"));
88905
89509
  return neutralDirMemo;
88906
89510
  }
88907
89511
  async function fetchOfficialClients(apiUrl, log3) {
@@ -88945,11 +89549,11 @@ function realReadTextFileStrict(filePath) {
88945
89549
  }
88946
89550
  }
88947
89551
  function realWriteTextFile(filePath, content) {
88948
- mkdirSync8(path18.dirname(filePath), { recursive: true });
89552
+ mkdirSync9(path21.dirname(filePath), { recursive: true });
88949
89553
  writeFileSync8(filePath, content);
88950
89554
  }
88951
- function codexConfigPath(homeDir = os17.homedir()) {
88952
- return path18.join(process.env.CODEX_HOME ?? path18.join(homeDir, ".codex"), "config.toml");
89555
+ function codexConfigPath(homeDir = os19.homedir()) {
89556
+ return path21.join(process.env.CODEX_HOME ?? path21.join(homeDir, ".codex"), "config.toml");
88953
89557
  }
88954
89558
  function realOpenUrl(url2) {
88955
89559
  const bin = process.platform === "darwin" ? "open" : process.platform === "linux" ? "xdg-open" : null;
@@ -88969,7 +89573,7 @@ function commandEnv(overrides) {
88969
89573
  }
88970
89574
  function realAgentVersion(client) {
88971
89575
  if (client.client === "cursor") {
88972
- return cursorAppVersion(defaultApplicationsDirs(os17.homedir()), {
89576
+ return cursorAppVersion(defaultApplicationsDirs(os19.homedir()), {
88973
89577
  readBundleInfo: realReadBundleInfo,
88974
89578
  verifySignature: realVerifySignature,
88975
89579
  budget: UNLIMITED_TIME_BUDGET,
@@ -89009,9 +89613,9 @@ function realRunInteractive(bin, args, env) {
89009
89613
  }
89010
89614
 
89011
89615
  // src/connections.ts
89012
- import { execFileSync as execFileSync5, spawnSync as spawnSync2 } from "node:child_process";
89013
- import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "node:fs";
89014
- import path19 from "node:path";
89616
+ import { execFileSync as execFileSync6, spawnSync as spawnSync2 } from "node:child_process";
89617
+ import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync9 } from "node:fs";
89618
+ import path22 from "node:path";
89015
89619
  function probeConnections(clients, deps) {
89016
89620
  const reports = [];
89017
89621
  for (const kind of ["claude", "codex", "cursor"]) {
@@ -89055,7 +89659,7 @@ function aggregateClaudeTargets(targets) {
89055
89659
  if (targets.length === 1 || worst.report.state === "signed-in") return worst.report;
89056
89660
  return {
89057
89661
  ...worst.report,
89058
- target: worst.configDir === void 0 ? "default profile" : path19.basename(worst.configDir)
89662
+ target: worst.configDir === void 0 ? "default profile" : path22.basename(worst.configDir)
89059
89663
  };
89060
89664
  }
89061
89665
  function probeClient(client, deps) {
@@ -89134,12 +89738,12 @@ var detectedClientsSchema = external_exports.object({
89134
89738
  )
89135
89739
  });
89136
89740
  function detectedClientsPath(homeDir) {
89137
- return path19.join(collectorStateDir(homeDir), "detected-clients.json");
89741
+ return path22.join(collectorStateDir(homeDir), "detected-clients.json");
89138
89742
  }
89139
89743
  function saveDetectedClients(clients, pathValue, homeDir) {
89140
89744
  try {
89141
89745
  const file2 = detectedClientsPath(homeDir);
89142
- mkdirSync9(path19.dirname(file2), { recursive: true });
89746
+ mkdirSync10(path22.dirname(file2), { recursive: true });
89143
89747
  const record2 = {
89144
89748
  detectedAt: (/* @__PURE__ */ new Date()).toISOString(),
89145
89749
  path: pathValue,
@@ -89212,7 +89816,7 @@ function runWithPath(pathValue, budget = UNLIMITED_TIME_BUDGET) {
89212
89816
  function whichAllWith(pathValue) {
89213
89817
  return (name) => {
89214
89818
  try {
89215
- return execFileSync5("which", ["-a", name], {
89819
+ return execFileSync6("which", ["-a", name], {
89216
89820
  encoding: "utf8",
89217
89821
  env: { ...process.env, PATH: pathValue }
89218
89822
  }).split("\n").map((line) => line.trim()).filter(Boolean);
@@ -89223,10 +89827,10 @@ function whichAllWith(pathValue) {
89223
89827
  }
89224
89828
 
89225
89829
  // src/doctor.ts
89226
- import { closeSync as closeSync4, fstatSync, openSync as openSync4, readSync as readSync4 } from "node:fs";
89830
+ import { closeSync as closeSync6, fstatSync, openSync as openSync6, readSync as readSync5 } from "node:fs";
89227
89831
 
89228
89832
  // src/update.ts
89229
- import path21 from "node:path";
89833
+ import path24 from "node:path";
89230
89834
 
89231
89835
  // src/duration.ts
89232
89836
  function duration3(ms) {
@@ -89244,11 +89848,11 @@ function ago(ms) {
89244
89848
  }
89245
89849
 
89246
89850
  // src/installOwner.ts
89247
- import { accessSync, constants } from "node:fs";
89248
- import path20 from "node:path";
89851
+ import { accessSync, constants as constants2 } from "node:fs";
89852
+ import path23 from "node:path";
89249
89853
 
89250
89854
  // src/version.ts
89251
- var CLI_VERSION = true ? "0.4.5" : "0.0.0-checkout";
89855
+ var CLI_VERSION = true ? "0.4.7" : "0.0.0-checkout";
89252
89856
  var CLI_RELEASE_BUILD = true ? true : false;
89253
89857
  var CLI_PACKAGE_NAME = "@usepowerplant/cli";
89254
89858
 
@@ -89272,8 +89876,8 @@ function inspectInstall(entryPath2, env) {
89272
89876
  inPlace: { ok: false, reason: `the install at ${packageDir} isn't a layout this CLI recognises` }
89273
89877
  };
89274
89878
  }
89275
- const modulesDir = path20.dirname(path20.dirname(packageDir));
89276
- const prefix = manager === "npm" ? path20.dirname(path20.dirname(modulesDir)) : null;
89879
+ const modulesDir = path23.dirname(path23.dirname(packageDir));
89880
+ const prefix = manager === "npm" ? path23.dirname(path23.dirname(modulesDir)) : null;
89277
89881
  if (!env.isWritableDirectory(modulesDir)) {
89278
89882
  return { manager, packageDir, prefix, inPlace: { ok: false, reason: `${modulesDir} isn't writable by you` } };
89279
89883
  }
@@ -89312,7 +89916,7 @@ function manualUpdateCommand(manager, version2, prefix = null, channel3 = "lates
89312
89916
  return [bin, ...args].join(" ");
89313
89917
  }
89314
89918
  function installedVersion(packageDir, readTextFile) {
89315
- const raw = readTextFile(path20.join(packageDir, "package.json"));
89919
+ const raw = readTextFile(path23.join(packageDir, "package.json"));
89316
89920
  if (raw === null) return null;
89317
89921
  try {
89318
89922
  const parsed = JSON.parse(raw);
@@ -89329,7 +89933,7 @@ function realInspectEnvironment() {
89329
89933
  pnpmHome: process.env.PNPM_HOME,
89330
89934
  isWritableDirectory: (dir) => {
89331
89935
  try {
89332
- accessSync(dir, constants.W_OK);
89936
+ accessSync(dir, constants2.W_OK);
89333
89937
  return true;
89334
89938
  } catch {
89335
89939
  return false;
@@ -89353,10 +89957,10 @@ var updateProgressSchema = external_exports.object({
89353
89957
  });
89354
89958
  var UPDATE_PROGRESS_STALE_MS = 15 * 6e4;
89355
89959
  function updateProgressPath(homeDir) {
89356
- return path21.join(collectorStateDir(homeDir), "cli-update.json");
89960
+ return path24.join(collectorStateDir(homeDir), "cli-update.json");
89357
89961
  }
89358
89962
  function updateLogPath(homeDir) {
89359
- return path21.join(collectorStateDir(homeDir), "cli-update.log");
89963
+ return path24.join(collectorStateDir(homeDir), "cli-update.log");
89360
89964
  }
89361
89965
  function readUpdateProgress(readTextFile, file2 = updateProgressPath()) {
89362
89966
  const raw = readTextFile(file2);
@@ -89549,26 +90153,26 @@ function redactedLogTail(raw) {
89549
90153
  while (lines.length > 0 && lines[lines.length - 1]?.trim() === "") lines.pop();
89550
90154
  return lines.slice(-DOCTOR_LOG_TAIL_LINES);
89551
90155
  }
89552
- function readDoctorLogTail(path27) {
90156
+ function readDoctorLogTail(path29) {
89553
90157
  let fd;
89554
90158
  try {
89555
- fd = openSync4(path27, "r");
90159
+ fd = openSync6(path29, "r");
89556
90160
  } catch (error62) {
89557
- if (error62.code === "ENOENT") return { path: path27, lines: null };
89558
- return { path: path27, lines: null, readError: error62 instanceof Error ? error62.message : String(error62) };
90161
+ if (error62.code === "ENOENT") return { path: path29, lines: null };
90162
+ return { path: path29, lines: null, readError: error62 instanceof Error ? error62.message : String(error62) };
89559
90163
  }
89560
90164
  try {
89561
90165
  const size = fstatSync(fd).size;
89562
90166
  const offset = Math.max(0, size - LOG_TAIL_READ_BYTES);
89563
90167
  const buffer = Buffer.alloc(Math.min(size, LOG_TAIL_READ_BYTES));
89564
- readSync4(fd, buffer, 0, buffer.length, offset);
90168
+ readSync5(fd, buffer, 0, buffer.length, offset);
89565
90169
  let text = buffer.toString("utf8");
89566
90170
  if (offset > 0) text = text.slice(text.indexOf("\n") + 1);
89567
- return { path: path27, lines: redactedLogTail(text) };
90171
+ return { path: path29, lines: redactedLogTail(text) };
89568
90172
  } catch (error62) {
89569
- return { path: path27, lines: null, readError: error62 instanceof Error ? error62.message : String(error62) };
90173
+ return { path: path29, lines: null, readError: error62 instanceof Error ? error62.message : String(error62) };
89570
90174
  } finally {
89571
- closeSync4(fd);
90175
+ closeSync6(fd);
89572
90176
  }
89573
90177
  }
89574
90178
  function renderDoctorReport(i) {
@@ -90075,191 +90679,8 @@ async function realPromptLine(question) {
90075
90679
  }
90076
90680
  }
90077
90681
 
90078
- // src/memberSessions.ts
90079
- import { execFileSync as execFileSync6 } from "node:child_process";
90080
- import { existsSync as existsSync9 } from "node:fs";
90081
- import { open as open2, readdir as readdir2 } from "node:fs/promises";
90082
- import os18 from "node:os";
90083
- import path22 from "node:path";
90084
- var memberSessionSchema = external_exports.object({
90085
- id: external_exports.string().min(1),
90086
- source: external_exports.string().min(1),
90087
- externalId: external_exports.string().min(1),
90088
- title: external_exports.string().nullable(),
90089
- repoDir: external_exports.string().nullable(),
90090
- machineId: external_exports.string().nullable(),
90091
- lastActivityAt: external_exports.string().min(1),
90092
- providerUrl: external_exports.string().nullable(),
90093
- archived: external_exports.boolean().optional(),
90094
- subagent: external_exports.boolean().optional()
90095
- });
90096
- async function fetchMemberSessions(credentials, fetchImpl = fetch, options = { windowHours: RECENT_SESSION_WINDOW_MS / 36e5, limit: RECENT_SESSION_VISIBLE_LIMIT }) {
90097
- const { windowHours, limit } = recentSessionOptionsSchema.parse(options);
90098
- try {
90099
- const query = new URLSearchParams({ view: "recent", windowHours: String(windowHours), limit: String(limit) });
90100
- const response = await fetchImpl(`${credentials.apiUrl}/api/collector/member-sessions?${query.toString()}`, {
90101
- headers: { authorization: `Bearer ${credentials.token}`, ...cliVersionHeaders() },
90102
- signal: AbortSignal.timeout(1e4)
90103
- });
90104
- if (!response.ok) throw new Error(`session read returned ${response.status}`);
90105
- const { data } = external_exports.object({ data: external_exports.object({
90106
- sessions: external_exports.array(memberSessionSchema).max(50),
90107
- nextCursor: external_exports.string().max(512).nullable().optional()
90108
- }) }).parse(await response.json());
90109
- return {
90110
- sessions: data.sessions.slice(0, limit),
90111
- // Older servers ignore the recent window and omit this field.
90112
- // A cursor on a supported server is an intentional cap, not a failure.
90113
- incomplete: data.nextCursor === void 0
90114
- };
90115
- } catch {
90116
- return null;
90117
- }
90118
- }
90119
- function resumeCommand(source, sessionId, powerplantUrl) {
90120
- return ["resume-session", source, sessionId, "--open", powerplantUrl];
90121
- }
90122
- function sessionLinks(session, webUrl, options) {
90123
- const powerplantUrl = `${webUrl}/rooms/${session.id}`;
90124
- switch (session.source) {
90125
- case "claude-code":
90126
- if (!options.localMachine) return { powerplantUrl };
90127
- if (options.terminalSession !== void 0) {
90128
- const { tty, appPid, appName } = options.terminalSession;
90129
- return {
90130
- powerplantUrl,
90131
- extra: {
90132
- label: `Show in ${appName}`,
90133
- focus: { tty, appPid },
90134
- terminal: resumeCommand("claude-code", session.externalId, powerplantUrl)
90135
- }
90136
- };
90137
- }
90138
- if (options.claudeDesktopSessionId !== void 0) {
90139
- return {
90140
- powerplantUrl,
90141
- extra: {
90142
- label: "Open in Claude",
90143
- url: `claude://claude.ai/epitaxy/${encodeURIComponent(options.claudeDesktopSessionId)}`
90144
- }
90145
- };
90146
- }
90147
- return {
90148
- powerplantUrl,
90149
- extra: {
90150
- label: "Resume in terminal",
90151
- terminal: resumeCommand("claude-code", session.externalId, powerplantUrl)
90152
- }
90153
- };
90154
- case "codex": {
90155
- const threadId2 = codexThreadId(session.externalId);
90156
- if (threadId2 === null || !options.localMachine) return { powerplantUrl };
90157
- return {
90158
- powerplantUrl,
90159
- extra: options.codexDesktop ? { label: "Open in Codex", url: `codex://threads/${threadId2}` } : { label: "Resume in terminal", terminal: resumeCommand("codex", threadId2, powerplantUrl) }
90160
- };
90161
- }
90162
- case "claude-cloud":
90163
- return {
90164
- powerplantUrl,
90165
- extra: { label: "Open on claude.ai", url: `https://claude.ai/code/${encodeURIComponent(session.externalId)}` }
90166
- };
90167
- default:
90168
- return session.providerUrl === null ? { powerplantUrl } : { powerplantUrl, extra: { label: "Open in Cursor", url: session.providerUrl } };
90169
- }
90170
- }
90171
- var TRAILING_UUID = /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/i;
90172
- function codexThreadId(externalId) {
90173
- return TRAILING_UUID.exec(externalId)?.[1] ?? null;
90174
- }
90175
- var CODEX_APP_BUNDLES = ["ChatGPT.app", "Codex.app"];
90176
- var urlSchemesSchema = external_exports.array(external_exports.object({ CFBundleURLSchemes: external_exports.array(external_exports.string()).optional() }));
90177
- function detectCodexDesktop(probe) {
90178
- return detectDesktopScheme(CODEX_APP_BUNDLES, "codex", probe);
90179
- }
90180
- function detectClaudeDesktop(probe) {
90181
- return detectDesktopScheme(["Claude.app"], "claude", probe);
90182
- }
90183
- function detectDesktopScheme(bundles, scheme, probe = { exists: existsSync9, readUrlSchemes: realReadUrlSchemes }) {
90184
- const roots = ["/Applications", path22.join(os18.homedir(), "Applications")];
90185
- return roots.some(
90186
- (root) => bundles.some((bundle) => {
90187
- const bundlePath = path22.join(root, bundle);
90188
- return probe.exists(bundlePath) && probe.readUrlSchemes(bundlePath).includes(scheme);
90189
- })
90190
- );
90191
- }
90192
- function realReadUrlSchemes(bundlePath) {
90193
- if (process.platform !== "darwin") return [];
90194
- try {
90195
- const json2 = execFileSync6(
90196
- "plutil",
90197
- ["-extract", "CFBundleURLTypes", "json", "-o", "-", path22.join(bundlePath, "Contents", "Info.plist")],
90198
- { stdio: ["ignore", "pipe", "ignore"] }
90199
- ).toString();
90200
- const parsed = urlSchemesSchema.safeParse(JSON.parse(json2));
90201
- if (!parsed.success) return [];
90202
- return parsed.data.flatMap((entry) => entry.CFBundleURLSchemes ?? []);
90203
- } catch {
90204
- return [];
90205
- }
90206
- }
90207
- var claudeDesktopSessionSchema = external_exports.object({
90208
- sessionId: external_exports.string().regex(/^local_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i),
90209
- cliSessionId: external_exports.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i)
90210
- });
90211
- async function readClaudeDesktopSessions(wanted, root = path22.join(os18.homedir(), "Library/Application Support/Claude/claude-code-sessions")) {
90212
- const sessions = /* @__PURE__ */ new Map();
90213
- const ambiguous = /* @__PURE__ */ new Set();
90214
- if (wanted.size === 0) return sessions;
90215
- const buffer = Buffer.alloc(1024 * 1024 + 1);
90216
- async function visit3(directory, depth) {
90217
- const entries = await readdir2(directory, { withFileTypes: true }).catch((error62) => {
90218
- if (isMissingFile(error62)) return [];
90219
- throw error62;
90220
- });
90221
- for (const entry of entries) {
90222
- const file2 = path22.join(directory, entry.name);
90223
- if (entry.isDirectory() && depth < 2) {
90224
- await visit3(file2, depth + 1);
90225
- } else if (depth === 2 && entry.isFile() && /^local_.*\.json$/.test(entry.name)) {
90226
- const handle = await open2(file2, "r").catch((error62) => {
90227
- if (isMissingFile(error62)) return null;
90228
- throw error62;
90229
- });
90230
- if (handle === null) continue;
90231
- try {
90232
- const { bytesRead } = await handle.read(buffer);
90233
- if (bytesRead > 1024 * 1024) continue;
90234
- const parsed = claudeDesktopSessionSchema.safeParse(
90235
- JSON.parse(buffer.subarray(0, bytesRead).toString())
90236
- );
90237
- if (!parsed.success || !wanted.has(parsed.data.cliSessionId)) continue;
90238
- const { cliSessionId, sessionId } = parsed.data;
90239
- if (ambiguous.has(cliSessionId)) continue;
90240
- if (sessions.has(cliSessionId) && sessions.get(cliSessionId) !== sessionId) {
90241
- sessions.delete(cliSessionId);
90242
- ambiguous.add(cliSessionId);
90243
- } else {
90244
- sessions.set(cliSessionId, sessionId);
90245
- }
90246
- } catch (error62) {
90247
- if (!(error62 instanceof SyntaxError)) throw error62;
90248
- } finally {
90249
- await handle.close();
90250
- }
90251
- }
90252
- }
90253
- }
90254
- await visit3(root, 0);
90255
- return sessions;
90256
- }
90257
- function isMissingFile(error62) {
90258
- return error62 instanceof Error && "code" in error62 && error62.code === "ENOENT";
90259
- }
90260
-
90261
90682
  // src/menu.ts
90262
- import path23 from "node:path";
90683
+ import path25 from "node:path";
90263
90684
  var MENU_CONTRACT = 1;
90264
90685
  var CLIENT_NAMES = { claude: "Claude Code", codex: "Codex", cursor: "Cursor" };
90265
90686
  function renderMenu(i) {
@@ -90287,6 +90708,8 @@ function renderMenu(i) {
90287
90708
  }
90288
90709
  if (items.length > 0) items.push({ type: "separator" });
90289
90710
  const progress = updateProgressView(i.update.progress, i.cliVersion, i.now);
90711
+ let updateStart;
90712
+ let updateCount = 0;
90290
90713
  const unsupported = isUnsupportedVersion(i.cliVersion, i.oldestSupportedVersion);
90291
90714
  if (unsupported) {
90292
90715
  items.push(
@@ -90295,7 +90718,9 @@ function renderMenu(i) {
90295
90718
  `You have ${i.cliVersion}; the oldest supported is ${i.oldestSupportedVersion}. Update now.`
90296
90719
  )
90297
90720
  );
90721
+ updateStart ??= items.length;
90298
90722
  items.push(...updateItems(i, progress, envArgs, problem));
90723
+ updateCount = items.length - updateStart;
90299
90724
  items.push({ type: "separator" });
90300
90725
  }
90301
90726
  if (i.credentialsError !== void 0) {
@@ -90318,10 +90743,17 @@ function renderMenu(i) {
90318
90743
  if (agents !== null) {
90319
90744
  items.push({ type: "separator" });
90320
90745
  items.push({ type: "section", title: "Recent sessions" });
90746
+ if (i.desktopDiagnostic?.outcome === "denied" || i.desktopDiagnostic?.outcome === "failed") {
90747
+ items.push(problem(
90748
+ i.desktopDiagnostic.outcome === "denied" ? "Claude desktop session access was denied" : "Claude desktop sessions could not be read",
90749
+ "Desktop links are unavailable. Retry by reopening this menu; use Terminal or Powerplant in the meantime."
90750
+ ));
90751
+ }
90321
90752
  items.push(...agents);
90322
90753
  }
90323
90754
  if (!unsupported && (isUpdateAvailable(i.cliVersion, i.latestVersion) || progress.kind !== "none")) {
90324
90755
  items.push({ type: "separator" });
90756
+ updateStart = items.length;
90325
90757
  if (progress.kind === "none") {
90326
90758
  items.push({
90327
90759
  type: "status",
@@ -90331,6 +90763,7 @@ function renderMenu(i) {
90331
90763
  });
90332
90764
  }
90333
90765
  items.push(...updateItems(i, progress, envArgs, problem));
90766
+ updateCount = items.length - updateStart;
90334
90767
  }
90335
90768
  items.push({ type: "separator" });
90336
90769
  items.push({ type: "action", title: "Open Powerplant", url: i.config.webUrl });
@@ -90340,6 +90773,18 @@ function renderMenu(i) {
90340
90773
  const icon = attention ? "attention" : i.control.paused ? "paused" : "running";
90341
90774
  return {
90342
90775
  contract: MENU_CONTRACT,
90776
+ ...i.update.inPlace && updateStart !== void 0 && {
90777
+ cliUpdate: {
90778
+ startIndex: updateStart,
90779
+ itemCount: updateCount,
90780
+ state: progress.kind === "none" ? "available" : progress.kind,
90781
+ target: progress.kind === "none" ? i.latestVersion : progress.target,
90782
+ ...progress.kind === "failed" && { detail: progress.detail },
90783
+ run: ["update", "--background", ...envArgs],
90784
+ logPath: updateLogPath()
90785
+ }
90786
+ },
90787
+ ...i.desktopDiagnostic && { desktopDiagnostic: i.desktopDiagnostic },
90343
90788
  appEnv: i.config.appEnv,
90344
90789
  cliVersion: i.cliVersion,
90345
90790
  icon,
@@ -90456,7 +90901,7 @@ function collectorBlock(i, envArgs, problem) {
90456
90901
  var AGENT_TITLE_MAX = 48;
90457
90902
  function recentAgentItems(i) {
90458
90903
  if (i.memberSessions === null) return null;
90459
- const recent = i.memberSessions.filter((session) => i.now - Date.parse(session.lastActivityAt) < RECENT_SESSION_WINDOW_MS).filter((session) => session.archived !== true && session.subagent !== true).sort((a, b2) => Date.parse(b2.lastActivityAt) - Date.parse(a.lastActivityAt)).map((session) => agentRow(session, i));
90904
+ const recent = i.memberSessions.filter((session) => i.now - Date.parse(session.lastActivityAt) < RECENT_SESSION_WINDOW_MS).filter((session) => session.archived !== true && session.subagent !== true && session.standaloneReview !== true).sort((a, b2) => Date.parse(b2.lastActivityAt) - Date.parse(a.lastActivityAt)).map((session) => agentRow(session, i));
90460
90905
  const rows = recent.length === 0 ? [{ type: "status", mark: "muted", title: i.memberSessionsIncomplete ? "No sessions found in the partial list" : "No eligible sessions in the latest results" }] : groupedAgentRows(recent.slice(0, RECENT_SESSION_VISIBLE_LIMIT));
90461
90906
  if (i.memberSessionsIncomplete) rows.push({
90462
90907
  type: "status",
@@ -90476,7 +90921,7 @@ function agentRow(session, i) {
90476
90921
  const trimmed = name.length > AGENT_TITLE_MAX ? `${name.slice(0, AGENT_TITLE_MAX - 1)}\u2026` : name;
90477
90922
  const when = ago(i.now - Date.parse(session.lastActivityAt));
90478
90923
  const localMachine = i.credentials !== null && session.machineId === i.credentials.machineId;
90479
- const desktopSessionId = localMachine && session.source === "claude-code" ? i.claudeDesktopSessions?.get(session.externalId) : void 0;
90924
+ const desktopSessionId = localMachine && session.source === "claude-code" ? i.claudeDesktopSessions?.get(session.externalId)?.sessionId : void 0;
90480
90925
  const app = desktopSessionId !== void 0 ? "Claude desktop" : isSessionSource(session.source) ? describeSessionSource(session.source) : session.source;
90481
90926
  const links = sessionLinks(session, i.config.webUrl, {
90482
90927
  codexDesktop: i.codexDesktop,
@@ -90485,7 +90930,8 @@ function agentRow(session, i) {
90485
90930
  terminalSession: i.liveTerminalSessions?.get(session.externalId)
90486
90931
  });
90487
90932
  const agent = {
90488
- icon: session.source === "codex" ? "chatgpt" : session.source === "cursor" || session.source === "cursor-cloud" ? "cursor" : session.source === "claude-code" || session.source === "claude-cloud" ? "claude" : "unknown"
90933
+ icon: session.source === "codex" ? "chatgpt" : session.source === "cursor" || session.source === "cursor-cloud" ? "cursor" : session.source === "claude-code" || session.source === "claude-cloud" ? "claude" : "unknown",
90934
+ ...session.working === true && { working: true }
90489
90935
  };
90490
90936
  if (links.extra !== void 0) {
90491
90937
  const envArgs = i.config.appEnv === "production" ? [] : ["--env", i.config.appEnv];
@@ -90515,6 +90961,11 @@ function connectionRow(connection, envArgs) {
90515
90961
  const fix = (title) => ({
90516
90962
  type: "action",
90517
90963
  title,
90964
+ background: {
90965
+ argv: ["connect", "--background", "--client", connection.client, ...envArgs],
90966
+ progress: `Connecting ${name}\u2026`,
90967
+ detail: connection.client === "cursor" ? "Finish setup in Cursor if prompted." : "Complete sign-in in your browser if prompted."
90968
+ },
90518
90969
  terminal: ["connect", "--client", connection.client, ...envArgs]
90519
90970
  });
90520
90971
  const row = (mark, state) => ({
@@ -90603,7 +91054,7 @@ function daemonVersionNote(i) {
90603
91054
  }
90604
91055
  var VERSION_CACHE_TTL_MS = 60 * 6e4;
90605
91056
  function versionCachePath(homeDir, source = "npm") {
90606
- return path23.join(collectorStateDir(homeDir), source === "npm" ? "version-check.json" : "version-check-promoted.json");
91057
+ return path25.join(collectorStateDir(homeDir), source === "npm" ? "version-check.json" : "version-check-promoted.json");
90607
91058
  }
90608
91059
  async function cachedLatestVersion(options) {
90609
91060
  const raw = options.readTextFile(options.cacheFile);
@@ -90631,8 +91082,8 @@ async function cachedLatestVersion(options) {
90631
91082
  // src/liveTerminalSessions.ts
90632
91083
  import { execFileSync as execFileSync7 } from "node:child_process";
90633
91084
  import { readdir as readdir3, readFile as readFile2 } from "node:fs/promises";
90634
- import os19 from "node:os";
90635
- import path24 from "node:path";
91085
+ import os20 from "node:os";
91086
+ import path26 from "node:path";
90636
91087
  var sessionFileAsObserved = external_exports.looseObject({
90637
91088
  pid: external_exports.number().int().positive(),
90638
91089
  sessionId: external_exports.string().min(1),
@@ -90640,8 +91091,8 @@ var sessionFileAsObserved = external_exports.looseObject({
90640
91091
  });
90641
91092
  var START_TIME_TOLERANCE_MS = 3e4;
90642
91093
  var SESSION_FILE = /^(\d+)\.json$/;
90643
- function claudeSessionsDir(homeDir = os19.homedir()) {
90644
- return path24.join(homeDir, ".claude", "sessions");
91094
+ function claudeSessionsDir(homeDir = os20.homedir()) {
91095
+ return path26.join(homeDir, ".claude", "sessions");
90645
91096
  }
90646
91097
  async function readLiveTerminalSessions(wanted, deps = {}) {
90647
91098
  const found = /* @__PURE__ */ new Map();
@@ -90666,7 +91117,7 @@ async function readLiveTerminalSessions(wanted, deps = {}) {
90666
91117
  }
90667
91118
  continue;
90668
91119
  }
90669
- const session = await readSessionFile(path24.join(sessionsDir, entry), report2);
91120
+ const session = await readSessionFile(path26.join(sessionsDir, entry), report2);
90670
91121
  if (session === null) continue;
90671
91122
  if (session.pid !== Number(match[1])) {
90672
91123
  report2({
@@ -90704,7 +91155,7 @@ async function readSessionFile(file2, report2) {
90704
91155
  report2({
90705
91156
  operation: "claude-session-registry-shape",
90706
91157
  message: "A Claude Code session file has a shape this CLI can't read",
90707
- context: { file: path24.basename(file2), shape: describeShape(raw) }
91158
+ context: { file: path26.basename(file2), shape: describeShape(raw) }
90708
91159
  });
90709
91160
  return null;
90710
91161
  }
@@ -91100,9 +91551,9 @@ function createTerminalOutput(options) {
91100
91551
  }
91101
91552
 
91102
91553
  // src/menubarApp.ts
91103
- import { existsSync as existsSync11, mkdirSync as mkdirSync10, renameSync as renameSync3, rmSync as rmSync5 } from "node:fs";
91104
- import os20 from "node:os";
91105
- import path25 from "node:path";
91554
+ import { existsSync as existsSync11, mkdirSync as mkdirSync11, renameSync as renameSync4, rmSync as rmSync6 } from "node:fs";
91555
+ import os21 from "node:os";
91556
+ import path27 from "node:path";
91106
91557
  import { spawnSync as spawnSync4 } from "node:child_process";
91107
91558
  var MENUBAR_APP_ZIP = "dist/menubar/Powerplant.app.zip";
91108
91559
  var MENUBAR_APP_NAME = "Powerplant.app";
@@ -91140,14 +91591,14 @@ async function syncMenubarApp(ops, context2) {
91140
91591
  }
91141
91592
  }
91142
91593
  function realMenubarAppOps(input2) {
91143
- const home = input2.homeDir ?? os20.homedir();
91144
- const userAppPath = path25.join(home, "Applications", MENUBAR_APP_NAME);
91145
- const candidates = [userAppPath, path25.join("/Applications", MENUBAR_APP_NAME)];
91594
+ const home = input2.homeDir ?? os21.homedir();
91595
+ const userAppPath = path27.join(home, "Applications", MENUBAR_APP_NAME);
91596
+ const candidates = [userAppPath, path27.join("/Applications", MENUBAR_APP_NAME)];
91146
91597
  return {
91147
91598
  cliVersion: input2.cliVersion,
91148
91599
  packagedZip: () => {
91149
91600
  if (input2.packageDir === null) return null;
91150
- const zip = path25.join(input2.packageDir, MENUBAR_APP_ZIP);
91601
+ const zip = path27.join(input2.packageDir, MENUBAR_APP_ZIP);
91151
91602
  return existsSync11(zip) ? zip : null;
91152
91603
  },
91153
91604
  installedApp: () => {
@@ -91167,12 +91618,12 @@ function realMenubarAppOps(input2) {
91167
91618
  throw new Error(`the running app at ${appPath} did not quit`);
91168
91619
  },
91169
91620
  replace: (zip, appPath) => {
91170
- const parent = path25.dirname(appPath);
91171
- mkdirSync10(parent, { recursive: true });
91172
- const staging = path25.join(parent, `.${MENUBAR_APP_NAME}.swap-${process.pid}`);
91173
- const retired = path25.join(parent, `.${MENUBAR_APP_NAME}.old-${process.pid}`);
91174
- rmSync5(staging, { recursive: true, force: true });
91175
- rmSync5(retired, { recursive: true, force: true });
91621
+ const parent = path27.dirname(appPath);
91622
+ mkdirSync11(parent, { recursive: true });
91623
+ const staging = path27.join(parent, `.${MENUBAR_APP_NAME}.swap-${process.pid}`);
91624
+ const retired = path27.join(parent, `.${MENUBAR_APP_NAME}.old-${process.pid}`);
91625
+ rmSync6(staging, { recursive: true, force: true });
91626
+ rmSync6(retired, { recursive: true, force: true });
91176
91627
  try {
91177
91628
  const extract = spawnSync4("ditto", ["-xk", zip, staging]);
91178
91629
  if (extract.status !== 0) {
@@ -91180,21 +91631,21 @@ function realMenubarAppOps(input2) {
91180
91631
  `ditto could not extract ${zip} (${extract.stderr?.toString().trim() || `exit ${extract.status}`})`
91181
91632
  );
91182
91633
  }
91183
- const extracted = path25.join(staging, MENUBAR_APP_NAME);
91184
- if (!existsSync11(path25.join(extracted, "Contents", "Info.plist"))) {
91634
+ const extracted = path27.join(staging, MENUBAR_APP_NAME);
91635
+ if (!existsSync11(path27.join(extracted, "Contents", "Info.plist"))) {
91185
91636
  throw new Error(`${zip} does not contain ${MENUBAR_APP_NAME}`);
91186
91637
  }
91187
91638
  const hadOld = existsSync11(appPath);
91188
- if (hadOld) renameSync3(appPath, retired);
91639
+ if (hadOld) renameSync4(appPath, retired);
91189
91640
  try {
91190
- renameSync3(extracted, appPath);
91641
+ renameSync4(extracted, appPath);
91191
91642
  } catch (error62) {
91192
- if (hadOld) renameSync3(retired, appPath);
91643
+ if (hadOld) renameSync4(retired, appPath);
91193
91644
  throw error62;
91194
91645
  }
91195
91646
  } finally {
91196
- rmSync5(staging, { recursive: true, force: true });
91197
- rmSync5(retired, { recursive: true, force: true });
91647
+ rmSync6(staging, { recursive: true, force: true });
91648
+ rmSync6(retired, { recursive: true, force: true });
91198
91649
  }
91199
91650
  },
91200
91651
  launch: (appPath) => {
@@ -91209,7 +91660,7 @@ function realMenubarAppOps(input2) {
91209
91660
  };
91210
91661
  }
91211
91662
  function appProcessIds(appPath) {
91212
- const executable = path25.join(appPath, "Contents", "MacOS", "PowerplantMenubar");
91663
+ const executable = path27.join(appPath, "Contents", "MacOS", "PowerplantMenubar");
91213
91664
  const result = spawnSync4("ps", ["-axo", "pid=,comm="], { encoding: "utf8" });
91214
91665
  if (result.status !== 0) {
91215
91666
  throw new Error(`ps could not list processes (${result.error?.message ?? `exit ${result.status}`})`);
@@ -91238,10 +91689,10 @@ var workspaceSchema = external_exports.object({
91238
91689
  active: external_exports.boolean()
91239
91690
  });
91240
91691
  var FETCH_TIMEOUT_MS2 = 1e4;
91241
- async function callApi(credentials, path27, init3, fetchImpl) {
91692
+ async function callApi(credentials, path29, init3, fetchImpl) {
91242
91693
  let response;
91243
91694
  try {
91244
- response = await fetchImpl(`${credentials.apiUrl}${path27}`, {
91695
+ response = await fetchImpl(`${credentials.apiUrl}${path29}`, {
91245
91696
  ...init3,
91246
91697
  headers: {
91247
91698
  authorization: `Bearer ${credentials.token}`,
@@ -91260,7 +91711,7 @@ async function callApi(credentials, path27, init3, fetchImpl) {
91260
91711
  );
91261
91712
  }
91262
91713
  if (!response.ok) {
91263
- throw new ExpectedCliError(`Powerplant answered ${response.status} for ${path27}.`);
91714
+ throw new ExpectedCliError(`Powerplant answered ${response.status} for ${path29}.`);
91264
91715
  }
91265
91716
  return response.json();
91266
91717
  }
@@ -91404,7 +91855,8 @@ function parseCliArgs() {
91404
91855
  "dry-run": { type: "boolean", default: false },
91405
91856
  json: { type: "boolean", default: false },
91406
91857
  forget: { type: "boolean", default: false },
91407
- // Internal: the menu bar app's update action. Hands the update to a
91858
+ // Internal: connect reports unfinished login as failure to the menu.
91859
+ // For update, hands the update to a
91408
91860
  // detached copy of this command so the app's verb deadline can't kill
91409
91861
  // a package manager mid-install; progress lands in the state file the
91410
91862
  // menu reads (update.ts).
@@ -91579,7 +92031,7 @@ ${USAGE}`);
91579
92031
  if (outcome.pending > 0) {
91580
92032
  console.log(`Some logins are unfinished, re-run \`${connectCommand}\` any time.`);
91581
92033
  }
91582
- if (outcome.failed > 0) process.exitCode = 1;
92034
+ process.exitCode = connectExitCode(outcome, values.background);
91583
92035
  return;
91584
92036
  }
91585
92037
  case "disconnect": {
@@ -91691,17 +92143,15 @@ The access you granted these agents stays on your Powerplant account until you r
91691
92143
  (memberSessions?.sessions ?? []).filter((session) => credentials !== null && session.machineId === credentials.machineId),
91692
92144
  (error62, source) => reportDaily(error62, `powerplant-menu-${source}-metadata`)
91693
92145
  );
91694
- const menuSessions = memberSessions?.sessions.map((session) => ({
91695
- ...session,
91696
- ...session.machineId === credentials?.machineId ? localFacts.get(localSessionKey(session)) : {}
91697
- })) ?? null;
91698
92146
  const localClaudeIds = new Set(
91699
92147
  (memberSessions?.sessions ?? []).filter((session) => credentials !== null && session.machineId === credentials.machineId && session.source === "claude-code").map((session) => session.externalId)
91700
92148
  );
91701
- const claudeDesktopSessions = detectClaudeDesktop() ? await readClaudeDesktopSessions(localClaudeIds).catch((error62) => {
91702
- reportDaily(error62, "powerplant-menu-desktop-sessions");
91703
- return /* @__PURE__ */ new Map();
91704
- }) : /* @__PURE__ */ new Map();
92149
+ const desktopProbe = await probeClaudeDesktopSessions(
92150
+ localClaudeIds,
92151
+ detectClaudeDesktop(),
92152
+ (error62) => reportDaily(error62, "powerplant-menu-desktop-sessions")
92153
+ );
92154
+ const menuSessions = memberSessions === null ? null : applyLocalFacts(memberSessions.sessions, credentials?.machineId ?? null, localFacts, localSessionKey, desktopProbe.sessions);
91705
92155
  const liveTerminalSessions = await readLiveTerminalSessions(localClaudeIds, {
91706
92156
  report: (finding) => reportDaily(
91707
92157
  new Error(finding.message),
@@ -91732,7 +92182,8 @@ The access you granted these agents stays on your Powerplant account until you r
91732
92182
  memberSessions: menuSessions,
91733
92183
  memberSessionsIncomplete: memberSessions?.incomplete,
91734
92184
  codexDesktop: detectCodexDesktop(),
91735
- claudeDesktopSessions,
92185
+ claudeDesktopSessions: desktopProbe.sessions,
92186
+ desktopDiagnostic: desktopProbe.diagnostic,
91736
92187
  liveTerminalSessions,
91737
92188
  update: { inPlace: inspectThisInstall().inPlace.ok, progress: updateProgress.read() },
91738
92189
  now: Date.now()
@@ -91924,8 +92375,8 @@ function startBackgroundUpdate(config2, target) {
91924
92375
  readProgress: updateProgress.read,
91925
92376
  writeProgress: updateProgress.write,
91926
92377
  spawnChild: () => {
91927
- mkdirSync11(path26.dirname(updateLogPath()), { recursive: true });
91928
- const log3 = openSync5(updateLogPath(), "a");
92378
+ mkdirSync12(path28.dirname(updateLogPath()), { recursive: true });
92379
+ const log3 = openSync7(updateLogPath(), "a");
91929
92380
  const child = spawn2(process.execPath, [entryPath(), "update", ...envArgsFor(config2)], {
91930
92381
  detached: true,
91931
92382
  stdio: ["ignore", log3, log3],
@@ -91987,7 +92438,7 @@ function restartSyncOnNewCode(config2) {
91987
92438
  var updateProgress = {
91988
92439
  read: () => readUpdateProgress(realReadTextFile),
91989
92440
  write: (record2) => realWriteTextFile(updateProgressPath(), JSON.stringify(record2, null, 2)),
91990
- clear: () => rmSync6(updateProgressPath(), { force: true })
92441
+ clear: () => rmSync7(updateProgressPath(), { force: true })
91991
92442
  };
91992
92443
  function envArgsFor(config2) {
91993
92444
  return config2.appEnv === "production" ? [] : ["--env", config2.appEnv];
@@ -92004,7 +92455,7 @@ function entryPath() {
92004
92455
  const entry = process.argv[1];
92005
92456
  if (!entry) throw new Error("cannot resolve the CLI entry path from argv");
92006
92457
  try {
92007
- return linkedEntryPath(realpathSync4(entry));
92458
+ return linkedEntryPath(realpathSync5(entry));
92008
92459
  } catch {
92009
92460
  return entry;
92010
92461
  }
@@ -92018,6 +92469,7 @@ main().catch(async (error62) => {
92018
92469
  } else {
92019
92470
  console.error(error62);
92020
92471
  }
92472
+ if (process.env.POWERPLANT_NATIVE_DIAGNOSTICS === "1") console.error(nativeFailureRecord(error62));
92021
92473
  reportCollectorError(error62, `powerplant-cli-${cliCommand}`);
92022
92474
  await flushReporting();
92023
92475
  process.exitCode = 1;