chat-recall 0.7.19 → 0.7.20

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.
@@ -2040,7 +2040,7 @@ var require_thread_stream = __commonJS({
2040
2040
  var { version } = require_package();
2041
2041
  var { EventEmitter } = __require("events");
2042
2042
  var { Worker } = __require("worker_threads");
2043
- var { join: join14 } = __require("path");
2043
+ var { join: join15 } = __require("path");
2044
2044
  var { pathToFileURL } = __require("url");
2045
2045
  var { wait } = require_wait();
2046
2046
  var {
@@ -2083,7 +2083,7 @@ var require_thread_stream = __commonJS({
2083
2083
  function createWorker(stream, opts) {
2084
2084
  const { filename, workerData } = opts;
2085
2085
  const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
2086
- const toExecute = bundlerOverrides["thread-stream-worker"] || join14(__dirname, "lib", "worker.js");
2086
+ const toExecute = bundlerOverrides["thread-stream-worker"] || join15(__dirname, "lib", "worker.js");
2087
2087
  const worker = new Worker(toExecute, {
2088
2088
  ...opts.workerOpts,
2089
2089
  trackUnmanagedFds: false,
@@ -2486,7 +2486,7 @@ var require_transport = __commonJS({
2486
2486
  "use strict";
2487
2487
  var { createRequire: createRequire3 } = __require("module");
2488
2488
  var getCallers = require_caller();
2489
- var { join: join14, isAbsolute, sep } = __require("node:path");
2489
+ var { join: join15, isAbsolute: isAbsolute2, sep } = __require("node:path");
2490
2490
  var sleep = require_atomic_sleep();
2491
2491
  var onExit = require_on_exit_leak_free();
2492
2492
  var ThreadStream = require_thread_stream();
@@ -2549,7 +2549,7 @@ var require_transport = __commonJS({
2549
2549
  throw new Error("only one of target or targets can be specified");
2550
2550
  }
2551
2551
  if (targets) {
2552
- target = bundlerOverrides["pino-worker"] || join14(__dirname, "worker.js");
2552
+ target = bundlerOverrides["pino-worker"] || join15(__dirname, "worker.js");
2553
2553
  options.targets = targets.filter((dest) => dest.target).map((dest) => {
2554
2554
  return {
2555
2555
  ...dest,
@@ -2567,7 +2567,7 @@ var require_transport = __commonJS({
2567
2567
  });
2568
2568
  });
2569
2569
  } else if (pipeline) {
2570
- target = bundlerOverrides["pino-worker"] || join14(__dirname, "worker.js");
2570
+ target = bundlerOverrides["pino-worker"] || join15(__dirname, "worker.js");
2571
2571
  options.pipelines = [pipeline.map((dest) => {
2572
2572
  return {
2573
2573
  ...dest,
@@ -2585,11 +2585,11 @@ var require_transport = __commonJS({
2585
2585
  return buildStream(fixTarget(target), options, worker, sync);
2586
2586
  function fixTarget(origin) {
2587
2587
  origin = bundlerOverrides[origin] || origin;
2588
- if (isAbsolute(origin) || origin.indexOf("file://") === 0) {
2588
+ if (isAbsolute2(origin) || origin.indexOf("file://") === 0) {
2589
2589
  return origin;
2590
2590
  }
2591
2591
  if (origin === "pino/file") {
2592
- return join14(__dirname, "..", "file.js");
2592
+ return join15(__dirname, "..", "file.js");
2593
2593
  }
2594
2594
  let fixTarget2;
2595
2595
  for (const filePath of callers) {
@@ -3578,7 +3578,7 @@ var require_safe_stable_stringify = __commonJS({
3578
3578
  return circularValue;
3579
3579
  }
3580
3580
  let res = "";
3581
- let join14 = ",";
3581
+ let join15 = ",";
3582
3582
  const originalIndentation = indentation;
3583
3583
  if (Array.isArray(value)) {
3584
3584
  if (value.length === 0) {
@@ -3592,7 +3592,7 @@ var require_safe_stable_stringify = __commonJS({
3592
3592
  indentation += spacer;
3593
3593
  res += `
3594
3594
  ${indentation}`;
3595
- join14 = `,
3595
+ join15 = `,
3596
3596
  ${indentation}`;
3597
3597
  }
3598
3598
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -3600,13 +3600,13 @@ ${indentation}`;
3600
3600
  for (; i < maximumValuesToStringify - 1; i++) {
3601
3601
  const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
3602
3602
  res += tmp2 !== void 0 ? tmp2 : "null";
3603
- res += join14;
3603
+ res += join15;
3604
3604
  }
3605
3605
  const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
3606
3606
  res += tmp !== void 0 ? tmp : "null";
3607
3607
  if (value.length - 1 > maximumBreadth) {
3608
3608
  const removedKeys = value.length - maximumBreadth - 1;
3609
- res += `${join14}"... ${getItemCount(removedKeys)} not stringified"`;
3609
+ res += `${join15}"... ${getItemCount(removedKeys)} not stringified"`;
3610
3610
  }
3611
3611
  if (spacer !== "") {
3612
3612
  res += `
@@ -3627,7 +3627,7 @@ ${originalIndentation}`;
3627
3627
  let separator = "";
3628
3628
  if (spacer !== "") {
3629
3629
  indentation += spacer;
3630
- join14 = `,
3630
+ join15 = `,
3631
3631
  ${indentation}`;
3632
3632
  whitespace = " ";
3633
3633
  }
@@ -3641,13 +3641,13 @@ ${indentation}`;
3641
3641
  const tmp = stringifyFnReplacer(key2, value, stack, replacer, spacer, indentation);
3642
3642
  if (tmp !== void 0) {
3643
3643
  res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
3644
- separator = join14;
3644
+ separator = join15;
3645
3645
  }
3646
3646
  }
3647
3647
  if (keyLength > maximumBreadth) {
3648
3648
  const removedKeys = keyLength - maximumBreadth;
3649
3649
  res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
3650
- separator = join14;
3650
+ separator = join15;
3651
3651
  }
3652
3652
  if (spacer !== "" && separator.length > 1) {
3653
3653
  res = `
@@ -3688,7 +3688,7 @@ ${originalIndentation}`;
3688
3688
  }
3689
3689
  const originalIndentation = indentation;
3690
3690
  let res = "";
3691
- let join14 = ",";
3691
+ let join15 = ",";
3692
3692
  if (Array.isArray(value)) {
3693
3693
  if (value.length === 0) {
3694
3694
  return "[]";
@@ -3701,7 +3701,7 @@ ${originalIndentation}`;
3701
3701
  indentation += spacer;
3702
3702
  res += `
3703
3703
  ${indentation}`;
3704
- join14 = `,
3704
+ join15 = `,
3705
3705
  ${indentation}`;
3706
3706
  }
3707
3707
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -3709,13 +3709,13 @@ ${indentation}`;
3709
3709
  for (; i < maximumValuesToStringify - 1; i++) {
3710
3710
  const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
3711
3711
  res += tmp2 !== void 0 ? tmp2 : "null";
3712
- res += join14;
3712
+ res += join15;
3713
3713
  }
3714
3714
  const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
3715
3715
  res += tmp !== void 0 ? tmp : "null";
3716
3716
  if (value.length - 1 > maximumBreadth) {
3717
3717
  const removedKeys = value.length - maximumBreadth - 1;
3718
- res += `${join14}"... ${getItemCount(removedKeys)} not stringified"`;
3718
+ res += `${join15}"... ${getItemCount(removedKeys)} not stringified"`;
3719
3719
  }
3720
3720
  if (spacer !== "") {
3721
3721
  res += `
@@ -3728,7 +3728,7 @@ ${originalIndentation}`;
3728
3728
  let whitespace = "";
3729
3729
  if (spacer !== "") {
3730
3730
  indentation += spacer;
3731
- join14 = `,
3731
+ join15 = `,
3732
3732
  ${indentation}`;
3733
3733
  whitespace = " ";
3734
3734
  }
@@ -3737,7 +3737,7 @@ ${indentation}`;
3737
3737
  const tmp = stringifyArrayReplacer(key2, value[key2], stack, replacer, spacer, indentation);
3738
3738
  if (tmp !== void 0) {
3739
3739
  res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
3740
- separator = join14;
3740
+ separator = join15;
3741
3741
  }
3742
3742
  }
3743
3743
  if (spacer !== "" && separator.length > 1) {
@@ -3795,20 +3795,20 @@ ${originalIndentation}`;
3795
3795
  indentation += spacer;
3796
3796
  let res2 = `
3797
3797
  ${indentation}`;
3798
- const join15 = `,
3798
+ const join16 = `,
3799
3799
  ${indentation}`;
3800
3800
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
3801
3801
  let i = 0;
3802
3802
  for (; i < maximumValuesToStringify - 1; i++) {
3803
3803
  const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
3804
3804
  res2 += tmp2 !== void 0 ? tmp2 : "null";
3805
- res2 += join15;
3805
+ res2 += join16;
3806
3806
  }
3807
3807
  const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
3808
3808
  res2 += tmp !== void 0 ? tmp : "null";
3809
3809
  if (value.length - 1 > maximumBreadth) {
3810
3810
  const removedKeys = value.length - maximumBreadth - 1;
3811
- res2 += `${join15}"... ${getItemCount(removedKeys)} not stringified"`;
3811
+ res2 += `${join16}"... ${getItemCount(removedKeys)} not stringified"`;
3812
3812
  }
3813
3813
  res2 += `
3814
3814
  ${originalIndentation}`;
@@ -3824,16 +3824,16 @@ ${originalIndentation}`;
3824
3824
  return '"[Object]"';
3825
3825
  }
3826
3826
  indentation += spacer;
3827
- const join14 = `,
3827
+ const join15 = `,
3828
3828
  ${indentation}`;
3829
3829
  let res = "";
3830
3830
  let separator = "";
3831
3831
  let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
3832
3832
  if (isTypedArrayWithEntries(value)) {
3833
- res += stringifyTypedArray(value, join14, maximumBreadth);
3833
+ res += stringifyTypedArray(value, join15, maximumBreadth);
3834
3834
  keys = keys.slice(value.length);
3835
3835
  maximumPropertiesToStringify -= value.length;
3836
- separator = join14;
3836
+ separator = join15;
3837
3837
  }
3838
3838
  if (deterministic) {
3839
3839
  keys = sort(keys, comparator);
@@ -3844,13 +3844,13 @@ ${indentation}`;
3844
3844
  const tmp = stringifyIndent(key2, value[key2], stack, spacer, indentation);
3845
3845
  if (tmp !== void 0) {
3846
3846
  res += `${separator}${strEscape(key2)}: ${tmp}`;
3847
- separator = join14;
3847
+ separator = join15;
3848
3848
  }
3849
3849
  }
3850
3850
  if (keyLength > maximumBreadth) {
3851
3851
  const removedKeys = keyLength - maximumBreadth;
3852
3852
  res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
3853
- separator = join14;
3853
+ separator = join15;
3854
3854
  }
3855
3855
  if (separator !== "") {
3856
3856
  res = `
@@ -4524,7 +4524,8 @@ function defaultSourcesEnabled() {
4524
4524
  commands: true
4525
4525
  },
4526
4526
  cursor: { sessions: true, skills: true, agents: true, commands: true },
4527
- hermes: { sessions: true },
4527
+ hermes: { sessions: true, skills: true },
4528
+ pi: { sessions: true, skills: true, commands: true },
4528
4529
  shared: { skills: true },
4529
4530
  common: { mcps: true, agentMd: true }
4530
4531
  };
@@ -4596,6 +4597,7 @@ function mergeSources(base, partial) {
4596
4597
  agy: { ...base.enabled.agy, ...inherited, ...partial.enabled?.agy ?? {} },
4597
4598
  cursor: { ...base.enabled.cursor, ...partial.enabled?.cursor ?? {} },
4598
4599
  hermes: { ...base.enabled.hermes, ...partial.enabled?.hermes ?? {} },
4600
+ pi: { ...base.enabled.pi, ...partial.enabled?.pi ?? {} },
4599
4601
  shared: { ...base.enabled.shared, ...partial.enabled?.shared ?? {} },
4600
4602
  common: { ...base.enabled.common, ...partial.enabled?.common ?? {} }
4601
4603
  };
@@ -4608,6 +4610,7 @@ function mergeSources(base, partial) {
4608
4610
  cursorHome: partial.cursorHome ?? base.cursorHome,
4609
4611
  cursorIdeHome: partial.cursorIdeHome ?? base.cursorIdeHome,
4610
4612
  hermesHome: partial.hermesHome ?? base.hermesHome,
4613
+ piHome: partial.piHome ?? base.piHome,
4611
4614
  extraClaudeHomes: partial.extraClaudeHomes ?? base.extraClaudeHomes,
4612
4615
  approvedHomes: partial.approvedHomes ?? base.approvedHomes,
4613
4616
  declinedHomes: partial.declinedHomes ?? base.declinedHomes,
@@ -5370,6 +5373,10 @@ var init_from_events = __esm({
5370
5373
  });
5371
5374
 
5372
5375
  // ../engine/dist/transcript/raw.js
5376
+ import { getHeapStatistics } from "v8";
5377
+ function rawParseMaxBytes(heapLimit) {
5378
+ return Math.max(0, Math.min(RAW_PARSE_CEILING, Math.floor((heapLimit - RAW_PARSE_HEAP_RESERVE) / RAW_PARSE_HEAP_PER_BYTE)));
5379
+ }
5373
5380
  function redactJsonLine(line, redact) {
5374
5381
  if (!line.includes('"'))
5375
5382
  return redact(line);
@@ -5435,7 +5442,7 @@ function redactContainer(c, redact) {
5435
5442
  }))
5436
5443
  };
5437
5444
  }
5438
- var RAW_PARSE_MAX_BYTES;
5445
+ var STREAM_PIECE_CHARS, RAW_PARSE_HEAP_PER_BYTE, RAW_PARSE_HEAP_RESERVE, RAW_PARSE_CEILING, RAW_PARSE_MAX_BYTES;
5439
5446
  var init_raw = __esm({
5440
5447
  "../engine/dist/transcript/raw.js"() {
5441
5448
  "use strict";
@@ -5443,7 +5450,11 @@ var init_raw = __esm({
5443
5450
  init_claude();
5444
5451
  init_codex();
5445
5452
  init_from_events();
5446
- RAW_PARSE_MAX_BYTES = 40 * 1024 * 1024;
5453
+ STREAM_PIECE_CHARS = 1 << 20;
5454
+ RAW_PARSE_HEAP_PER_BYTE = 6;
5455
+ RAW_PARSE_HEAP_RESERVE = 128 * 1024 * 1024;
5456
+ RAW_PARSE_CEILING = 40 * 1024 * 1024;
5457
+ RAW_PARSE_MAX_BYTES = rawParseMaxBytes(getHeapStatistics().heap_size_limit);
5447
5458
  }
5448
5459
  });
5449
5460
 
@@ -5531,6 +5542,9 @@ function grandfatherLegacyHomes() {
5531
5542
  }
5532
5543
  return { seeded };
5533
5544
  }
5545
+ function defaultPiHome() {
5546
+ return join3(homedir2(), ".pi", "agent");
5547
+ }
5534
5548
  function defaultHermesHome() {
5535
5549
  if (process.platform === "win32") {
5536
5550
  const local = process.env.LOCALAPPDATA?.trim() || join3(homedir2(), "AppData", "Local");
@@ -5555,7 +5569,8 @@ function primaryHomes() {
5555
5569
  env.CHAT_RECALL_AGY_HOME || s?.agyHome || join3(home, ".gemini", "antigravity-cli"),
5556
5570
  env.CHAT_RECALL_CURSOR_HOME || s?.cursorHome || join3(home, ".cursor"),
5557
5571
  dirOf(opencodeDb),
5558
- env.CHAT_RECALL_HERMES_HOME || s?.hermesHome || env.HERMES_HOME?.trim() || defaultHermesHome()
5572
+ env.CHAT_RECALL_HERMES_HOME || s?.hermesHome || env.HERMES_HOME?.trim() || defaultHermesHome(),
5573
+ env.CHAT_RECALL_PI_HOME || s?.piHome || env.PI_CODING_AGENT_DIR?.trim() || defaultPiHome()
5559
5574
  ];
5560
5575
  return candidates.map(normalizeHomePath);
5561
5576
  }
@@ -5591,9 +5606,9 @@ var init_home_approval = __esm({
5591
5606
  });
5592
5607
 
5593
5608
  // ../engine/dist/core/tool-paths.js
5594
- import { existsSync as existsSync3, readdirSync as readdirSync2 } from "fs";
5609
+ import { existsSync as existsSync3, readdirSync as readdirSync2, readFileSync as readFileSync2, statSync as statSync3, realpathSync as realpathSync2 } from "fs";
5595
5610
  import { homedir as homedir3 } from "os";
5596
- import { join as join4, dirname as dirname4, basename } from "path";
5611
+ import { join as join4, dirname as dirname4, basename, isAbsolute } from "path";
5597
5612
  function claudeHomeDir() {
5598
5613
  return process.env.CHAT_RECALL_CLAUDE_HOME || sources().claudeHome || join4(homedir3(), ".claude");
5599
5614
  }
@@ -5649,6 +5664,98 @@ function cursorHomeDir() {
5649
5664
  function cursorIdeHomeDir() {
5650
5665
  return process.env.CHAT_RECALL_CURSOR_IDE_HOME || sources().cursorIdeHome || (process.platform === "darwin" ? join4(homedir3(), "Library", "Application Support", "Cursor") : join4(homedir3(), ".config", "Cursor"));
5651
5666
  }
5667
+ function piHomeDir() {
5668
+ const raw = process.env.CHAT_RECALL_PI_HOME || sources().piHome || process.env.PI_CODING_AGENT_DIR?.trim();
5669
+ return raw ? expandTildePath(raw) : join4(homedir3(), ".pi", "agent");
5670
+ }
5671
+ function expandTildePath(value) {
5672
+ const t = value.trim();
5673
+ if (t === "~")
5674
+ return homedir3();
5675
+ if (t.startsWith("~/") || t.startsWith("~\\"))
5676
+ return join4(homedir3(), t.slice(2));
5677
+ return t;
5678
+ }
5679
+ function piSessionDir() {
5680
+ const override = piSessionDirEnv();
5681
+ if (override)
5682
+ return override;
5683
+ return piSessionDirForHome(piHomeDir());
5684
+ }
5685
+ function piSessionDirEnv() {
5686
+ const raw = process.env.CHAT_RECALL_PI_SESSION_DIR || process.env.PI_CODING_AGENT_SESSION_DIR?.trim();
5687
+ return raw && raw.trim() ? expandTildePath(raw) : null;
5688
+ }
5689
+ function piSessionDirForHome(home) {
5690
+ const env = piSessionDirEnv();
5691
+ if (env && sameDir(home, piHomeDir()))
5692
+ return env;
5693
+ return piSessionDirFromSettings(join4(home, "settings.json")) || join4(home, "sessions");
5694
+ }
5695
+ function sameDir(a, b) {
5696
+ if (a === b)
5697
+ return true;
5698
+ try {
5699
+ return realpathSync2(a) === realpathSync2(b);
5700
+ } catch {
5701
+ return false;
5702
+ }
5703
+ }
5704
+ function piSessionDirFromSettings(file) {
5705
+ let sig;
5706
+ try {
5707
+ sig = statSync3(file).mtimeMs;
5708
+ } catch {
5709
+ return null;
5710
+ }
5711
+ if (piSettingsCache && piSettingsCache.path === file && piSettingsCache.sig === sig) {
5712
+ return piSettingsCache.dir;
5713
+ }
5714
+ let dir = null;
5715
+ try {
5716
+ const parsed = JSON.parse(readFileSync2(file, "utf-8"));
5717
+ const value = typeof parsed.sessionDir === "string" ? parsed.sessionDir.trim() : "";
5718
+ const expanded = value ? expandTildePath(value) : "";
5719
+ dir = expanded && isAbsolute(expanded) ? expanded : null;
5720
+ } catch {
5721
+ }
5722
+ piSettingsCache = { path: file, sig, dir };
5723
+ return dir;
5724
+ }
5725
+ function piSessionDirs(opts = {}) {
5726
+ const home = piHomeDir();
5727
+ const dir = piSessionDir();
5728
+ if (!existsSync3(dir))
5729
+ return [];
5730
+ if (opts.includeExcluded)
5731
+ return [dir];
5732
+ try {
5733
+ grandfatherLegacyHomes();
5734
+ } catch {
5735
+ }
5736
+ try {
5737
+ if (!isHomeSynced(home))
5738
+ return [];
5739
+ } catch {
5740
+ }
5741
+ try {
5742
+ if (homeDecision(dir) === "declined")
5743
+ return [];
5744
+ } catch {
5745
+ }
5746
+ if (_sourceExclusionFilter && _sourceExclusionFilter(dir))
5747
+ return [];
5748
+ return [dir];
5749
+ }
5750
+ function piSkillsDir() {
5751
+ return join4(piHomeDir(), "skills");
5752
+ }
5753
+ function piPromptsDir() {
5754
+ return join4(piHomeDir(), "prompts");
5755
+ }
5756
+ function piMcpConfigPath() {
5757
+ return join4(piHomeDir(), "mcp.json");
5758
+ }
5652
5759
  function siblingHomes(base, overridden, suffix) {
5653
5760
  const roots = [];
5654
5761
  const add = (home) => {
@@ -5758,7 +5865,7 @@ function hermesDbPaths(opts = {}) {
5758
5865
  }
5759
5866
  return applyExclusions(dbs, opts.includeExcluded);
5760
5867
  }
5761
- var sources, _sourceExclusionFilter;
5868
+ var sources, _sourceExclusionFilter, piSettingsCache;
5762
5869
  var init_tool_paths = __esm({
5763
5870
  "../engine/dist/core/tool-paths.js"() {
5764
5871
  "use strict";
@@ -5766,6 +5873,7 @@ var init_tool_paths = __esm({
5766
5873
  init_settings();
5767
5874
  sources = loadSourceSettings;
5768
5875
  _sourceExclusionFilter = null;
5876
+ piSettingsCache = null;
5769
5877
  }
5770
5878
  });
5771
5879
 
@@ -6931,7 +7039,7 @@ var init_opencode = __esm({
6931
7039
  });
6932
7040
 
6933
7041
  // ../engine/dist/core/backends/tail-read.js
6934
- import { openSync, readSync, closeSync, statSync as statSync3, fstatSync } from "node:fs";
7042
+ import { openSync, readSync, closeSync, statSync as statSync4, fstatSync } from "node:fs";
6935
7043
  function readAt(fd, pos, len) {
6936
7044
  const buf = Buffer.alloc(len);
6937
7045
  let got = 0;
@@ -6992,7 +7100,7 @@ function linesBeforeOffset(path, offset) {
6992
7100
  function readTailFromOffset(path, offset, maxBytes = TAIL_READ_MAX_BYTES) {
6993
7101
  let size = 0;
6994
7102
  try {
6995
- size = statSync3(path).size;
7103
+ size = statSync4(path).size;
6996
7104
  } catch {
6997
7105
  return { text: "", newOffset: offset };
6998
7106
  }
@@ -7042,7 +7150,7 @@ function readSourcesFromOffset(paths, offset, maxBytes = TAIL_READ_MAX_BYTES) {
7042
7150
  const path = paths[i];
7043
7151
  let size = 0;
7044
7152
  try {
7045
- size = statSync3(path).size;
7153
+ size = statSync4(path).size;
7046
7154
  } catch {
7047
7155
  size = 0;
7048
7156
  }
@@ -7127,7 +7235,7 @@ var init_tail_read = __esm({
7127
7235
  });
7128
7236
 
7129
7237
  // ../engine/dist/core/backends/codex.js
7130
- import { readdirSync as readdirSync3, readFileSync as readFileSync2, statSync as statSync4, openSync as openSync2, readSync as readSync2, closeSync as closeSync2 } from "fs";
7238
+ import { readdirSync as readdirSync3, readFileSync as readFileSync3, statSync as statSync5, openSync as openSync2, readSync as readSync2, closeSync as closeSync2 } from "fs";
7131
7239
  import { basename as basename4, dirname as dirname7, join as join6 } from "path";
7132
7240
  function parseShellWrites(cmd) {
7133
7241
  const out = [];
@@ -7256,7 +7364,7 @@ function flattenContent(content) {
7256
7364
  }
7257
7365
  function readFirstLine(path) {
7258
7366
  try {
7259
- const head = readFileSync2(path, "utf-8").split("\n", 1)[0] || "";
7367
+ const head = readFileSync3(path, "utf-8").split("\n", 1)[0] || "";
7260
7368
  if (!head)
7261
7369
  return null;
7262
7370
  return JSON.parse(head);
@@ -7362,7 +7470,7 @@ var init_codex2 = __esm({
7362
7470
  return null;
7363
7471
  let mtime = 0;
7364
7472
  try {
7365
- mtime = statSync4(located.path).mtimeMs;
7473
+ mtime = statSync5(located.path).mtimeMs;
7366
7474
  } catch {
7367
7475
  }
7368
7476
  return {
@@ -7382,7 +7490,7 @@ var init_codex2 = __esm({
7382
7490
  for (const filePath of walkRollouts(root)) {
7383
7491
  let stat;
7384
7492
  try {
7385
- stat = statSync4(filePath);
7493
+ stat = statSync5(filePath);
7386
7494
  } catch {
7387
7495
  continue;
7388
7496
  }
@@ -7402,7 +7510,7 @@ var init_codex2 = __esm({
7402
7510
  let messageCount = 0;
7403
7511
  if (opts.previews !== false)
7404
7512
  try {
7405
- const lines = readFileSync2(filePath, "utf-8").split("\n");
7513
+ const lines = readFileSync3(filePath, "utf-8").split("\n");
7406
7514
  for (const line of lines) {
7407
7515
  if (!line.trim())
7408
7516
  continue;
@@ -7554,7 +7662,7 @@ var init_codex2 = __esm({
7554
7662
  continue;
7555
7663
  let firstLine = "";
7556
7664
  try {
7557
- firstLine = readFileSync2(path, "utf-8").split("\n", 1)[0] || "";
7665
+ firstLine = readFileSync3(path, "utf-8").split("\n", 1)[0] || "";
7558
7666
  } catch {
7559
7667
  continue;
7560
7668
  }
@@ -7578,8 +7686,8 @@ var init_codex2 = __esm({
7578
7686
  let raw = "";
7579
7687
  let mtime = 0;
7580
7688
  try {
7581
- raw = readFileSync2(path, "utf-8");
7582
- mtime = statSync4(path).mtimeMs;
7689
+ raw = readFileSync3(path, "utf-8");
7690
+ mtime = statSync5(path).mtimeMs;
7583
7691
  } catch {
7584
7692
  return [];
7585
7693
  }
@@ -7679,7 +7787,7 @@ var init_codex2 = __esm({
7679
7787
  const events = this.readEvents(this.toRawId(id));
7680
7788
  let fileMtime = 0;
7681
7789
  try {
7682
- fileMtime = statSync4(located.path).mtimeMs;
7790
+ fileMtime = statSync5(located.path).mtimeMs;
7683
7791
  } catch {
7684
7792
  }
7685
7793
  return liveScanEditsFromEvents(events, this.fileToolMap, {
@@ -7743,7 +7851,7 @@ var init_codex2 = __esm({
7743
7851
  const p = join6(dir, entry.name);
7744
7852
  let st;
7745
7853
  try {
7746
- st = statSync4(p);
7854
+ st = statSync5(p);
7747
7855
  } catch {
7748
7856
  continue;
7749
7857
  }
@@ -7755,7 +7863,7 @@ var init_codex2 = __esm({
7755
7863
  let parentId = null;
7756
7864
  let isSubagent = false;
7757
7865
  try {
7758
- const first = readFileSync2(p, "utf-8").split("\n")[0];
7866
+ const first = readFileSync3(p, "utf-8").split("\n")[0];
7759
7867
  if (first) {
7760
7868
  const meta = JSON.parse(first);
7761
7869
  const payload = meta?.payload || {};
@@ -7810,8 +7918,8 @@ var init_codex2 = __esm({
7810
7918
  let mtime = 0;
7811
7919
  const push = (path, name) => {
7812
7920
  try {
7813
- const st = statSync4(path);
7814
- files.push({ name, bytes: readFileSync2(path) });
7921
+ const st = statSync5(path);
7922
+ files.push({ name, bytes: readFileSync3(path) });
7815
7923
  if (st.mtimeMs > mtime)
7816
7924
  mtime = st.mtimeMs;
7817
7925
  } catch {
@@ -7852,7 +7960,7 @@ var init_codex2 = __esm({
7852
7960
  if (!loc)
7853
7961
  return 0;
7854
7962
  try {
7855
- return statSync4(loc.path).size;
7963
+ return statSync5(loc.path).size;
7856
7964
  } catch {
7857
7965
  return 0;
7858
7966
  }
@@ -7869,7 +7977,7 @@ var init_codex2 = __esm({
7869
7977
  });
7870
7978
 
7871
7979
  // ../engine/dist/core/backends/agy.js
7872
- import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as readFileSync3, statSync as statSync5 } from "fs";
7980
+ import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as readFileSync4, statSync as statSync6 } from "fs";
7873
7981
  import { basename as basename5, dirname as dirname8, join as join7 } from "path";
7874
7982
  function agyTranscriptPath(logsDir) {
7875
7983
  const full = join7(logsDir, "transcript_full.jsonl");
@@ -7889,7 +7997,7 @@ function resolveAgyProject(logsDir, homeDir) {
7889
7997
  function extractProjectPathFromTranscript(path, homeDir) {
7890
7998
  let content;
7891
7999
  try {
7892
- content = readFileSync3(path, "utf-8");
8000
+ content = readFileSync4(path, "utf-8");
7893
8001
  } catch {
7894
8002
  return "";
7895
8003
  }
@@ -8062,7 +8170,7 @@ var init_agy = __esm({
8062
8170
  return null;
8063
8171
  let mtime = 0;
8064
8172
  try {
8065
- mtime = statSync5(path).mtimeMs;
8173
+ mtime = statSync6(path).mtimeMs;
8066
8174
  } catch {
8067
8175
  }
8068
8176
  const projectPath = resolveAgyProject(dirname8(path), this.homeDir());
@@ -8090,7 +8198,7 @@ var init_agy = __esm({
8090
8198
  for (const rawId of sessionDirs) {
8091
8199
  const sessionPath = join7(brainDir, rawId);
8092
8200
  try {
8093
- if (!statSync5(sessionPath).isDirectory())
8201
+ if (!statSync6(sessionPath).isDirectory())
8094
8202
  continue;
8095
8203
  } catch {
8096
8204
  continue;
@@ -8100,7 +8208,7 @@ var init_agy = __esm({
8100
8208
  continue;
8101
8209
  let stat;
8102
8210
  try {
8103
- stat = statSync5(filePath);
8211
+ stat = statSync6(filePath);
8104
8212
  } catch {
8105
8213
  continue;
8106
8214
  }
@@ -8114,7 +8222,7 @@ var init_agy = __esm({
8114
8222
  let messageCount = 0;
8115
8223
  if (opts.previews !== false)
8116
8224
  try {
8117
- const lines = readFileSync3(filePath, "utf-8").split("\n").filter(Boolean);
8225
+ const lines = readFileSync4(filePath, "utf-8").split("\n").filter(Boolean);
8118
8226
  messageCount = lines.length;
8119
8227
  for (const line of lines) {
8120
8228
  const obj = JSON.parse(line);
@@ -8204,7 +8312,7 @@ var init_agy = __esm({
8204
8312
  return [];
8205
8313
  let rawText;
8206
8314
  try {
8207
- rawText = readFileSync3(located.path, "utf-8");
8315
+ rawText = readFileSync4(located.path, "utf-8");
8208
8316
  } catch {
8209
8317
  return [];
8210
8318
  }
@@ -8366,7 +8474,7 @@ var init_agy = __esm({
8366
8474
  for (const rawId of sessionDirs) {
8367
8475
  const sessionPath = join7(brainDir, rawId);
8368
8476
  try {
8369
- if (!statSync5(sessionPath).isDirectory())
8477
+ if (!statSync6(sessionPath).isDirectory())
8370
8478
  continue;
8371
8479
  } catch {
8372
8480
  continue;
@@ -8375,7 +8483,7 @@ var init_agy = __esm({
8375
8483
  if (!filePath)
8376
8484
  continue;
8377
8485
  try {
8378
- const st = statSync5(filePath);
8486
+ const st = statSync6(filePath);
8379
8487
  if (st.mtimeMs < opts.sinceMs)
8380
8488
  continue;
8381
8489
  candidates.push({ rawId, mtime: st.mtimeMs });
@@ -8403,8 +8511,8 @@ var init_agy = __esm({
8403
8511
  try {
8404
8512
  return {
8405
8513
  tool: "agy",
8406
- mtime: statSync5(loc.path).mtimeMs,
8407
- files: [{ name: basename5(loc.path), bytes: readFileSync3(loc.path) }]
8514
+ mtime: statSync6(loc.path).mtimeMs,
8515
+ files: [{ name: basename5(loc.path), bytes: readFileSync4(loc.path) }]
8408
8516
  };
8409
8517
  } catch {
8410
8518
  return null;
@@ -8418,7 +8526,7 @@ var init_agy = __esm({
8418
8526
  if (!loc)
8419
8527
  return 0;
8420
8528
  try {
8421
- return statSync5(loc.path).size;
8529
+ return statSync6(loc.path).size;
8422
8530
  } catch {
8423
8531
  return 0;
8424
8532
  }
@@ -8435,7 +8543,7 @@ var init_agy = __esm({
8435
8543
  });
8436
8544
 
8437
8545
  // ../engine/dist/core/backends/cursor-store.js
8438
- import { existsSync as existsSync7, readdirSync as readdirSync5, readFileSync as readFileSync4, statSync as statSync6 } from "fs";
8546
+ import { existsSync as existsSync7, readdirSync as readdirSync5, readFileSync as readFileSync5, statSync as statSync7 } from "fs";
8439
8547
  import { join as join8 } from "path";
8440
8548
  function cursorProjectSlug(absPath) {
8441
8549
  return absPath.replace(/[^a-zA-Z0-9]/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
@@ -8452,7 +8560,7 @@ function listChatsIn(chatsRoot) {
8452
8560
  const hashPath = join8(chatsRoot, workspaceHash);
8453
8561
  let chatIds;
8454
8562
  try {
8455
- if (!statSync6(hashPath).isDirectory())
8563
+ if (!statSync7(hashPath).isDirectory())
8456
8564
  continue;
8457
8565
  chatIds = readdirSync5(hashPath);
8458
8566
  } catch {
@@ -8465,7 +8573,7 @@ function listChatsIn(chatsRoot) {
8465
8573
  continue;
8466
8574
  let meta = {};
8467
8575
  try {
8468
- meta = JSON.parse(readFileSync4(join8(dir, "meta.json"), "utf-8"));
8576
+ meta = JSON.parse(readFileSync5(join8(dir, "meta.json"), "utf-8"));
8469
8577
  } catch {
8470
8578
  }
8471
8579
  if (meta.hasConversation === false)
@@ -8474,7 +8582,7 @@ function listChatsIn(chatsRoot) {
8474
8582
  let created = meta.createdAtMs ?? 0;
8475
8583
  if (!mtime || !created) {
8476
8584
  try {
8477
- const st = statSync6(dbPath);
8585
+ const st = statSync7(dbPath);
8478
8586
  mtime = mtime || st.mtimeMs;
8479
8587
  created = created || st.birthtimeMs || st.mtimeMs;
8480
8588
  } catch {
@@ -8510,14 +8618,14 @@ function findChat(chatsRoots, chatId) {
8510
8618
  continue;
8511
8619
  let meta = {};
8512
8620
  try {
8513
- meta = JSON.parse(readFileSync4(join8(dir, "meta.json"), "utf-8"));
8621
+ meta = JSON.parse(readFileSync5(join8(dir, "meta.json"), "utf-8"));
8514
8622
  } catch {
8515
8623
  }
8516
8624
  let mtime = meta.updatedAtMs ?? 0;
8517
8625
  let created = meta.createdAtMs ?? 0;
8518
8626
  if (!mtime || !created) {
8519
8627
  try {
8520
- const st = statSync6(dbPath);
8628
+ const st = statSync7(dbPath);
8521
8629
  mtime = mtime || st.mtimeMs;
8522
8630
  created = created || st.birthtimeMs || st.mtimeMs;
8523
8631
  } catch {
@@ -8820,7 +8928,7 @@ var init_cursor_store = __esm({
8820
8928
  });
8821
8929
 
8822
8930
  // ../engine/dist/core/backends/cursor-ide.js
8823
- import { existsSync as existsSync8, readFileSync as readFileSync5, readdirSync as readdirSync6, statSync as statSync7 } from "fs";
8931
+ import { existsSync as existsSync8, readFileSync as readFileSync6, readdirSync as readdirSync6, statSync as statSync8 } from "fs";
8824
8932
  import { dirname as dirname9, join as join9 } from "path";
8825
8933
  function jsonOf(value) {
8826
8934
  if (value == null)
@@ -8873,7 +8981,7 @@ function projectPathForWorkspace(workspaceDir) {
8873
8981
  }
8874
8982
  function safeRead(path) {
8875
8983
  try {
8876
- return readFileSync5(path, "utf-8");
8984
+ return readFileSync6(path, "utf-8");
8877
8985
  } catch {
8878
8986
  return null;
8879
8987
  }
@@ -8890,7 +8998,7 @@ function workspaceIndex(workspaceRoots) {
8890
8998
  for (const id of entries) {
8891
8999
  const dir = join9(root, id);
8892
9000
  try {
8893
- if (!statSync7(dir).isDirectory())
9001
+ if (!statSync8(dir).isDirectory())
8894
9002
  continue;
8895
9003
  } catch {
8896
9004
  continue;
@@ -9236,7 +9344,7 @@ var init_cursor_ide = __esm({
9236
9344
  });
9237
9345
 
9238
9346
  // ../engine/dist/core/backends/cursor.js
9239
- import { existsSync as existsSync9, readFileSync as readFileSync6, statSync as statSync8 } from "fs";
9347
+ import { existsSync as existsSync9, readFileSync as readFileSync7, statSync as statSync9 } from "fs";
9240
9348
  import { join as join10 } from "path";
9241
9349
  var PREFIX4, CursorBackend, cursorBackend;
9242
9350
  var init_cursor = __esm({
@@ -9289,7 +9397,7 @@ var init_cursor = __esm({
9289
9397
  if (r.surface === "cli") {
9290
9398
  let mtime2 = r.chat.updatedAtMs;
9291
9399
  try {
9292
- mtime2 = statSync8(r.chat.dbPath).mtimeMs || mtime2;
9400
+ mtime2 = statSync9(r.chat.dbPath).mtimeMs || mtime2;
9293
9401
  } catch {
9294
9402
  }
9295
9403
  return {
@@ -9302,7 +9410,7 @@ var init_cursor = __esm({
9302
9410
  }
9303
9411
  let mtime = r.composer.updatedAtMs;
9304
9412
  try {
9305
- mtime = statSync8(r.composer.globalDbPath).mtimeMs || mtime;
9413
+ mtime = statSync9(r.composer.globalDbPath).mtimeMs || mtime;
9306
9414
  } catch {
9307
9415
  }
9308
9416
  return {
@@ -9460,7 +9568,7 @@ var init_cursor = __esm({
9460
9568
  if (!jsonl)
9461
9569
  return [];
9462
9570
  try {
9463
- return readTranscriptEvents(readFileSync6(jsonl, "utf-8"), chat.updatedAtMs);
9571
+ return readTranscriptEvents(readFileSync7(jsonl, "utf-8"), chat.updatedAtMs);
9464
9572
  } catch {
9465
9573
  return [];
9466
9574
  }
@@ -9546,9 +9654,9 @@ var init_cursor = __esm({
9546
9654
  const files = [{ name: `${r.chat.chatId}.jsonl`, bytes: Buffer.from(lines, "utf8") }];
9547
9655
  const metaPath = join10(r.chat.dir, "meta.json");
9548
9656
  if (existsSync9(metaPath)) {
9549
- files.push({ name: "meta.json", bytes: readFileSync6(metaPath) });
9657
+ files.push({ name: "meta.json", bytes: readFileSync7(metaPath) });
9550
9658
  }
9551
- return { tool: "cursor", mtime: statSync8(r.chat.dbPath).mtimeMs, files };
9659
+ return { tool: "cursor", mtime: statSync9(r.chat.dbPath).mtimeMs, files };
9552
9660
  }
9553
9661
  const events = readComposerEvents(r.composer);
9554
9662
  if (events.length === 0)
@@ -9556,7 +9664,7 @@ var init_cursor = __esm({
9556
9664
  const body = events.map((e) => JSON.stringify(e)).join("\n") + "\n";
9557
9665
  return {
9558
9666
  tool: "cursor",
9559
- mtime: statSync8(r.composer.globalDbPath).mtimeMs,
9667
+ mtime: statSync9(r.composer.globalDbPath).mtimeMs,
9560
9668
  files: [{ name: `${r.composer.composerId}.jsonl`, bytes: Buffer.from(body, "utf8") }]
9561
9669
  };
9562
9670
  } catch {
@@ -9568,7 +9676,7 @@ var init_cursor = __esm({
9568
9676
  if (!p)
9569
9677
  return "";
9570
9678
  try {
9571
- return readFileSync6(p, "utf-8");
9679
+ return readFileSync7(p, "utf-8");
9572
9680
  } catch {
9573
9681
  return "";
9574
9682
  }
@@ -10045,6 +10153,623 @@ var init_hermes = __esm({
10045
10153
  }
10046
10154
  });
10047
10155
 
10156
+ // ../engine/dist/core/backends/pi.js
10157
+ import { readdirSync as readdirSync7, readFileSync as readFileSync8, statSync as statSync10, openSync as openSync3, readSync as readSync3, closeSync as closeSync3 } from "fs";
10158
+ import { createHash } from "crypto";
10159
+ import { basename as basename6, join as join11 } from "path";
10160
+ function parsePiFile(path) {
10161
+ let raw;
10162
+ try {
10163
+ raw = readFileSync8(path, "utf-8");
10164
+ } catch {
10165
+ return { header: null, entries: [] };
10166
+ }
10167
+ const out = { header: null, entries: [] };
10168
+ for (const line of raw.split("\n")) {
10169
+ if (!line.trim())
10170
+ continue;
10171
+ let obj;
10172
+ try {
10173
+ obj = JSON.parse(line);
10174
+ } catch {
10175
+ continue;
10176
+ }
10177
+ if (!obj || typeof obj !== "object")
10178
+ continue;
10179
+ if (obj.type === "session" && !out.header) {
10180
+ out.header = obj;
10181
+ continue;
10182
+ }
10183
+ out.entries.push(obj);
10184
+ }
10185
+ return out;
10186
+ }
10187
+ function idFromFilename(file) {
10188
+ if (!file.endsWith(".jsonl"))
10189
+ return null;
10190
+ const stem = file.slice(0, -".jsonl".length);
10191
+ const at = stem.indexOf("_");
10192
+ const id = at === -1 ? stem : stem.slice(at + 1);
10193
+ return id || null;
10194
+ }
10195
+ function* walkSessionFiles(root, depth = 2) {
10196
+ if (depth < 0)
10197
+ return;
10198
+ let entries;
10199
+ try {
10200
+ entries = readdirSync7(root, { withFileTypes: true });
10201
+ } catch {
10202
+ return;
10203
+ }
10204
+ for (const entry of entries) {
10205
+ if (entry.name.startsWith("."))
10206
+ continue;
10207
+ const path = join11(root, entry.name);
10208
+ if (entry.isDirectory()) {
10209
+ yield* walkSessionFiles(path, depth - 1);
10210
+ continue;
10211
+ }
10212
+ if (entry.isFile() && entry.name.endsWith(".jsonl"))
10213
+ yield path;
10214
+ }
10215
+ }
10216
+ function readPiHeader(path) {
10217
+ let fd = null;
10218
+ try {
10219
+ fd = openSync3(path, "r");
10220
+ const buf = Buffer.alloc(8192);
10221
+ const n = readSync3(fd, buf, 0, buf.length, 0);
10222
+ const firstLine = buf.toString("utf-8", 0, n).split("\n", 1)[0];
10223
+ if (!firstLine.trim())
10224
+ return null;
10225
+ const obj = JSON.parse(firstLine);
10226
+ if (!obj || typeof obj !== "object" || obj.type !== "session")
10227
+ return null;
10228
+ return obj;
10229
+ } catch {
10230
+ return null;
10231
+ } finally {
10232
+ if (fd !== null) {
10233
+ try {
10234
+ closeSync3(fd);
10235
+ } catch {
10236
+ }
10237
+ }
10238
+ }
10239
+ }
10240
+ function dirSignature(root) {
10241
+ const parts = [];
10242
+ try {
10243
+ parts.push(String(statSync10(root).mtimeMs));
10244
+ } catch {
10245
+ return "missing";
10246
+ }
10247
+ let entries = [];
10248
+ try {
10249
+ entries = readdirSync7(root, { withFileTypes: true });
10250
+ } catch {
10251
+ return parts.join(",");
10252
+ }
10253
+ for (const entry of entries) {
10254
+ if (!entry.isDirectory())
10255
+ continue;
10256
+ try {
10257
+ parts.push(`${entry.name}:${statSync10(join11(root, entry.name)).mtimeMs}`);
10258
+ } catch {
10259
+ }
10260
+ }
10261
+ parts.sort();
10262
+ return parts.join(",");
10263
+ }
10264
+ function piSessionKey(file) {
10265
+ return `${file.id}~${projectSuffix(file.projectPath || file.projectDir)}`;
10266
+ }
10267
+ function projectSuffix(projectDir) {
10268
+ return createHash("sha256").update(projectDir).digest("hex").slice(0, 8);
10269
+ }
10270
+ function mtimeOf(path, fallback) {
10271
+ try {
10272
+ return statSync10(path).mtimeMs;
10273
+ } catch {
10274
+ return fallback;
10275
+ }
10276
+ }
10277
+ function piText(content) {
10278
+ if (typeof content === "string")
10279
+ return content;
10280
+ if (!Array.isArray(content))
10281
+ return "";
10282
+ const parts = [];
10283
+ for (const block of content) {
10284
+ if (!block || typeof block !== "object")
10285
+ continue;
10286
+ const b = block;
10287
+ if (b.type === "text" && typeof b.text === "string")
10288
+ parts.push(b.text);
10289
+ }
10290
+ return parts.join("\n");
10291
+ }
10292
+ function piToolInput(args) {
10293
+ return args && typeof args === "object" && !Array.isArray(args) ? { ...args } : {};
10294
+ }
10295
+ var PREFIX6, PiBackend, piBackend;
10296
+ var init_pi = __esm({
10297
+ "../engine/dist/core/backends/pi.js"() {
10298
+ "use strict";
10299
+ init_tail_read();
10300
+ init_tool_paths();
10301
+ init_session_outcome();
10302
+ init_session_git();
10303
+ init_generic_engine();
10304
+ init_flat_string();
10305
+ PREFIX6 = "pi_";
10306
+ PiBackend = class {
10307
+ id = "pi";
10308
+ idPrefix = PREFIX6;
10309
+ displayName = "Pi";
10310
+ homeDir() {
10311
+ return piHomeDir();
10312
+ }
10313
+ /** Session root(s) — Pi has a single agent dir, so this is one entry. */
10314
+ sessionDirs() {
10315
+ return piSessionDirs();
10316
+ }
10317
+ skillsDir() {
10318
+ return piSkillsDir();
10319
+ }
10320
+ promptsDir() {
10321
+ return piPromptsDir();
10322
+ }
10323
+ mcpConfigPath() {
10324
+ return piMcpConfigPath();
10325
+ }
10326
+ isAvailable() {
10327
+ return this.sessionDirs().length > 0;
10328
+ }
10329
+ // ── ID handling ────────────────────────────────────────────────
10330
+ matchesId(id) {
10331
+ return id.startsWith(PREFIX6);
10332
+ }
10333
+ /**
10334
+ * A Pi id can itself start with `<prefix>` (`--session-id` allows `_`), so the
10335
+ * bare prefix does not identify a stored id. The index does.
10336
+ */
10337
+ toRawId(id) {
10338
+ if (!id.startsWith(PREFIX6))
10339
+ return id;
10340
+ if (this.fileIndex().has(id))
10341
+ return id;
10342
+ return id.slice(PREFIX6.length);
10343
+ }
10344
+ toPrefixedId(rawId) {
10345
+ if (!rawId.startsWith(PREFIX6))
10346
+ return PREFIX6 + rawId;
10347
+ return this.fileIndex().has(rawId) ? PREFIX6 + rawId : rawId;
10348
+ }
10349
+ // ── Location ───────────────────────────────────────────────────
10350
+ /**
10351
+ * Session key → file path for every session on this machine.
10352
+ *
10353
+ * The entry list is cached on the project dirs. When two files carry one key
10354
+ * — a copy of a session — this stats them on every call, because an append to
10355
+ * the live file changes its mtime and not its folder.
10356
+ */
10357
+ fileIndex() {
10358
+ const roots = this.sessionDirs();
10359
+ const signature = roots.map(dirSignature).join("|");
10360
+ if (this._index?.signature !== signature) {
10361
+ const entries2 = [];
10362
+ for (const root of roots) {
10363
+ for (const path of walkSessionFiles(root)) {
10364
+ let mtime = 0;
10365
+ try {
10366
+ mtime = statSync10(path).mtimeMs;
10367
+ } catch {
10368
+ continue;
10369
+ }
10370
+ const header = readPiHeader(path);
10371
+ const id = header ? header.id || idFromFilename(basename6(path)) : "";
10372
+ entries2.push({
10373
+ id: id || "",
10374
+ projectPath: header?.cwd || "",
10375
+ projectDir: basename6(join11(path, "..")),
10376
+ mtime,
10377
+ path
10378
+ });
10379
+ }
10380
+ }
10381
+ this._index = { signature, entries: entries2 };
10382
+ }
10383
+ const entries = this._index.entries;
10384
+ const seen = /* @__PURE__ */ new Map();
10385
+ for (const entry of entries) {
10386
+ if (!entry.id) {
10387
+ const header = readPiHeader(entry.path);
10388
+ if (!header)
10389
+ continue;
10390
+ entry.id = header.id || idFromFilename(basename6(entry.path)) || "";
10391
+ entry.projectPath = header.cwd || "";
10392
+ if (!entry.id)
10393
+ continue;
10394
+ }
10395
+ const key = piSessionKey(entry);
10396
+ const prior = seen.get(key);
10397
+ if (!prior) {
10398
+ seen.set(key, entry);
10399
+ continue;
10400
+ }
10401
+ const priorMtime = mtimeOf(prior.path, prior.mtime);
10402
+ const entryMtime = mtimeOf(entry.path, entry.mtime);
10403
+ if (entryMtime > priorMtime)
10404
+ seen.set(key, entry);
10405
+ }
10406
+ const files = /* @__PURE__ */ new Map();
10407
+ for (const [key, file] of seen)
10408
+ files.set(key, file.path);
10409
+ return files;
10410
+ }
10411
+ _index = null;
10412
+ findSession(id) {
10413
+ const rawId = this.toRawId(id);
10414
+ const path = this.fileIndex().get(rawId);
10415
+ if (!path)
10416
+ return null;
10417
+ const header = readPiHeader(path);
10418
+ if (!header)
10419
+ return null;
10420
+ let mtime = 0;
10421
+ try {
10422
+ mtime = statSync10(path).mtimeMs;
10423
+ } catch {
10424
+ }
10425
+ return {
10426
+ path,
10427
+ format: "jsonl",
10428
+ projectDir: basename6(join11(path, "..")),
10429
+ projectPath: header.cwd || "",
10430
+ mtime
10431
+ };
10432
+ }
10433
+ listSessions(opts = {}) {
10434
+ const cutoff = opts.sinceMs ?? 0;
10435
+ const filter = opts.projectFilter?.toLowerCase();
10436
+ const out = [];
10437
+ for (const [rawId, path] of this.fileIndex()) {
10438
+ let stat;
10439
+ try {
10440
+ stat = statSync10(path);
10441
+ } catch {
10442
+ continue;
10443
+ }
10444
+ if (stat.mtimeMs < cutoff)
10445
+ continue;
10446
+ const header = readPiHeader(path);
10447
+ if (!header)
10448
+ continue;
10449
+ const projectPath = header.cwd || "";
10450
+ if (filter && !projectPath.toLowerCase().includes(filter))
10451
+ continue;
10452
+ let firstPrompt = "";
10453
+ let messageCount = 0;
10454
+ if (opts.previews !== false) {
10455
+ const parsed = parsePiFile(path);
10456
+ for (const entry of parsed.entries) {
10457
+ if (entry.type !== "message")
10458
+ continue;
10459
+ const role = entry.message?.role;
10460
+ if (role !== "user" && role !== "assistant")
10461
+ continue;
10462
+ messageCount++;
10463
+ if (!firstPrompt && role === "user") {
10464
+ const text = piText(entry.message?.content).trim();
10465
+ if (text)
10466
+ firstPrompt = flatString(text.slice(0, 200));
10467
+ }
10468
+ }
10469
+ }
10470
+ out.push({
10471
+ toolId: "pi",
10472
+ rawId,
10473
+ prefixedId: this.toPrefixedId(rawId),
10474
+ projectPath,
10475
+ projectDir: basename6(join11(path, "..")),
10476
+ fullPath: path,
10477
+ created: header.timestamp || stat.birthtime.toISOString(),
10478
+ modified: stat.mtime.toISOString(),
10479
+ mtime: stat.mtimeMs,
10480
+ firstPrompt,
10481
+ messageCount
10482
+ });
10483
+ }
10484
+ out.sort((a, b) => b.mtime - a.mtime);
10485
+ return opts.limit ? out.slice(0, opts.limit) : out;
10486
+ }
10487
+ // ── Generic-engine inputs ───────────────────────────────────────
10488
+ /**
10489
+ * The file tools and their EditOp. A shell command carries no path, so it
10490
+ * produces no file entry.
10491
+ */
10492
+ fileToolMap = {
10493
+ write: "write",
10494
+ edit: "edit",
10495
+ read: "read"
10496
+ };
10497
+ /**
10498
+ * The inline diff of a file tool.
10499
+ * - write: { path, content }.
10500
+ * - edit: { path, edits: [{ oldText, newText }] }.
10501
+ *
10502
+ * An edit holds several disjoint replacements. Join them into one pair.
10503
+ */
10504
+ extractEditDelta(toolName, input) {
10505
+ if (input == null || typeof input !== "object")
10506
+ return null;
10507
+ const inp = input;
10508
+ if (toolName === "write") {
10509
+ const after = typeof inp.content === "string" ? inp.content : null;
10510
+ if (after === null)
10511
+ return null;
10512
+ return { before: "", after };
10513
+ }
10514
+ if (toolName === "edit") {
10515
+ const edits = Array.isArray(inp.edits) ? inp.edits : [];
10516
+ let before = "";
10517
+ let after = "";
10518
+ for (const raw of edits) {
10519
+ if (!raw || typeof raw !== "object")
10520
+ continue;
10521
+ const e = raw;
10522
+ if (typeof e.oldText === "string")
10523
+ before += (before ? "\n" : "") + e.oldText;
10524
+ if (typeof e.newText === "string")
10525
+ after += (after ? "\n" : "") + e.newText;
10526
+ }
10527
+ if (!before && !after)
10528
+ return null;
10529
+ return { before: before || null, after: after || null };
10530
+ }
10531
+ return null;
10532
+ }
10533
+ readEvents(rawId) {
10534
+ const located = this.findSession(rawId);
10535
+ if (!located)
10536
+ return [];
10537
+ let rawText;
10538
+ try {
10539
+ rawText = readFileSync8(located.path, "utf-8");
10540
+ } catch {
10541
+ return [];
10542
+ }
10543
+ return this.readEventsFromText(rawText, located.mtime);
10544
+ }
10545
+ /**
10546
+ * Parse Pi session text into canonical events. Split out from readEvents so
10547
+ * the same parser runs on archived/shadow container bytes.
10548
+ */
10549
+ readEventsFromText(rawText, mtimeFallback = 0) {
10550
+ const events = [];
10551
+ let lineNum = 0;
10552
+ for (const line of rawText.split("\n")) {
10553
+ lineNum++;
10554
+ if (!line.trim())
10555
+ continue;
10556
+ let obj;
10557
+ try {
10558
+ obj = JSON.parse(line);
10559
+ } catch {
10560
+ continue;
10561
+ }
10562
+ const tsIso = typeof obj.timestamp === "string" ? obj.timestamp : void 0;
10563
+ const msgTs = typeof obj.message?.timestamp === "number" ? obj.message.timestamp : void 0;
10564
+ const ts = tsIso ? Date.parse(tsIso) || mtimeFallback : msgTs ?? mtimeFallback;
10565
+ if (obj.type === "message") {
10566
+ const msg = obj.message || {};
10567
+ const role = msg.role;
10568
+ if (role === "user") {
10569
+ const text = piText(msg.content).trim();
10570
+ if (text)
10571
+ events.push({ kind: "user", ts, tsIso, line: lineNum, text });
10572
+ continue;
10573
+ }
10574
+ if (role === "assistant") {
10575
+ const text = piText(msg.content).trim();
10576
+ if (text)
10577
+ events.push({ kind: "assistant_text", ts, tsIso, line: lineNum, text });
10578
+ const blocks = Array.isArray(msg.content) ? msg.content : [];
10579
+ for (const block of blocks) {
10580
+ if (!block || typeof block !== "object" || block.type !== "toolCall")
10581
+ continue;
10582
+ const toolName = String(block.name || "");
10583
+ if (!toolName)
10584
+ continue;
10585
+ const input = piToolInput(block.arguments);
10586
+ const command = toolName === "bash" || toolName === "powershell" ? typeof input.command === "string" ? input.command : void 0 : void 0;
10587
+ events.push({
10588
+ kind: "tool_use",
10589
+ ts,
10590
+ tsIso,
10591
+ line: lineNum,
10592
+ toolName,
10593
+ toolUseId: typeof block.id === "string" ? block.id : "",
10594
+ toolInput: input,
10595
+ command
10596
+ });
10597
+ }
10598
+ continue;
10599
+ }
10600
+ if (role === "toolResult") {
10601
+ const body = piText(msg.content);
10602
+ events.push({
10603
+ kind: "tool_result",
10604
+ ts,
10605
+ tsIso,
10606
+ line: lineNum,
10607
+ toolName: typeof msg.toolName === "string" ? msg.toolName : void 0,
10608
+ toolUseId: typeof msg.toolCallId === "string" ? msg.toolCallId : "",
10609
+ resultBody: body,
10610
+ resultIsError: msg.isError === true,
10611
+ resultBytes: body.length
10612
+ });
10613
+ continue;
10614
+ }
10615
+ if (role === "bashExecution") {
10616
+ const command = typeof msg.command === "string" ? msg.command : "";
10617
+ const output = typeof msg.output === "string" ? msg.output : "";
10618
+ const toolUseId = `pi_bash_${lineNum}`;
10619
+ events.push({
10620
+ kind: "tool_use",
10621
+ ts,
10622
+ tsIso,
10623
+ line: lineNum,
10624
+ toolName: "bash",
10625
+ toolUseId,
10626
+ toolInput: { command },
10627
+ command
10628
+ });
10629
+ events.push({
10630
+ kind: "tool_result",
10631
+ ts,
10632
+ tsIso,
10633
+ line: lineNum,
10634
+ toolUseId,
10635
+ toolName: "bash",
10636
+ resultBody: output,
10637
+ resultIsError: typeof msg.exitCode === "number" && msg.exitCode !== 0,
10638
+ resultExitCode: typeof msg.exitCode === "number" ? msg.exitCode : void 0,
10639
+ resultBytes: output.length
10640
+ });
10641
+ continue;
10642
+ }
10643
+ continue;
10644
+ }
10645
+ if (obj.type === "compaction" && typeof obj.summary === "string" && obj.summary.trim()) {
10646
+ events.push({ kind: "summary", ts, tsIso, line: lineNum, text: obj.summary.trim() });
10647
+ continue;
10648
+ }
10649
+ if (obj.type === "branch_summary" && typeof obj.summary === "string" && obj.summary.trim()) {
10650
+ events.push({ kind: "summary", ts, tsIso, line: lineNum, text: obj.summary.trim() });
10651
+ }
10652
+ }
10653
+ return events;
10654
+ }
10655
+ // ── Per-session operations — all delegate to the generic engine ─
10656
+ extractTurns(id, opts = {}) {
10657
+ const events = this.readEvents(this.toRawId(id));
10658
+ return extractTurnsFromEvents(this.toPrefixedId(id), events, opts);
10659
+ }
10660
+ liveScanEdits(id) {
10661
+ const located = this.findSession(this.toRawId(id));
10662
+ if (!located) {
10663
+ return { found: false, projectPath: "", projectDir: "", edits: [], fileMtime: 0, tool: "pi" };
10664
+ }
10665
+ const events = this.readEvents(this.toRawId(id));
10666
+ return liveScanEditsFromEvents(events, this.fileToolMap, {
10667
+ sessionId: this.toPrefixedId(id),
10668
+ tool: "pi",
10669
+ projectPath: located.projectPath,
10670
+ projectDir: located.projectDir,
10671
+ fileMtime: located.mtime,
10672
+ found: true
10673
+ }, this.extractEditDelta.bind(this));
10674
+ }
10675
+ replay(id) {
10676
+ const located = this.findSession(this.toRawId(id));
10677
+ if (!located) {
10678
+ return { sessionId: this.toPrefixedId(id), found: false, projectPath: "", files: [], totalLinesAdded: 0, totalLinesRemoved: 0 };
10679
+ }
10680
+ const events = this.readEvents(this.toRawId(id));
10681
+ return replayFromEvents(this.toPrefixedId(id), events, this.fileToolMap, this.extractEditDelta.bind(this), { projectPath: located.projectPath, found: true });
10682
+ }
10683
+ computeOutcome(id, opts) {
10684
+ return computeOutcome(this.toPrefixedId(id), opts);
10685
+ }
10686
+ collectRecentEdits(opts) {
10687
+ const candidates = [];
10688
+ for (const [rawId, path] of this.fileIndex()) {
10689
+ let stat;
10690
+ try {
10691
+ stat = statSync10(path);
10692
+ } catch {
10693
+ continue;
10694
+ }
10695
+ if (stat.mtimeMs < opts.sinceMs)
10696
+ continue;
10697
+ if (opts.projectFilter) {
10698
+ const header = readPiHeader(path);
10699
+ const projectPath = header?.cwd || "";
10700
+ if (!projectPath.toLowerCase().includes(opts.projectFilter.toLowerCase()))
10701
+ continue;
10702
+ }
10703
+ candidates.push({ rawId, mtime: stat.mtimeMs });
10704
+ }
10705
+ candidates.sort((a, b) => b.mtime - a.mtime);
10706
+ const limited = opts.limitSessions ? candidates.slice(0, opts.limitSessions) : candidates;
10707
+ const edits = [];
10708
+ for (const c of limited)
10709
+ edits.push(...this.liveScanEdits(c.rawId).edits);
10710
+ return edits;
10711
+ }
10712
+ getCommits(id, files, startMs, endMs, bufferMinutes) {
10713
+ return getSessionCommits(this.toPrefixedId(id), files, startMs, endMs, bufferMinutes);
10714
+ }
10715
+ /**
10716
+ * Pi's user-assigned session name (`/name`, `--name`), from the newest
10717
+ * `session_info` entry. Null when the session was never named.
10718
+ */
10719
+ getNativeTitle(rawId) {
10720
+ const located = this.findSession(rawId);
10721
+ if (!located)
10722
+ return null;
10723
+ const parsed = parsePiFile(located.path);
10724
+ for (let i = parsed.entries.length - 1; i >= 0; i--) {
10725
+ const entry = parsed.entries[i];
10726
+ if (entry.type !== "session_info")
10727
+ continue;
10728
+ const name = typeof entry.name === "string" ? entry.name.trim() : "";
10729
+ if (name)
10730
+ return name;
10731
+ }
10732
+ return null;
10733
+ }
10734
+ exportRawSession(id) {
10735
+ const located = this.findSession(id);
10736
+ if (!located)
10737
+ return null;
10738
+ try {
10739
+ const st = statSync10(located.path);
10740
+ return {
10741
+ tool: "pi",
10742
+ mtime: st.mtimeMs,
10743
+ files: [{ name: basename6(located.path), bytes: readFileSync8(located.path) }]
10744
+ };
10745
+ } catch {
10746
+ return null;
10747
+ }
10748
+ }
10749
+ isAppendOnly() {
10750
+ return true;
10751
+ }
10752
+ fileSize(prefixedId) {
10753
+ const located = this.findSession(prefixedId);
10754
+ if (!located)
10755
+ return 0;
10756
+ try {
10757
+ return statSync10(located.path).size;
10758
+ } catch {
10759
+ return 0;
10760
+ }
10761
+ }
10762
+ async readFromOffset(prefixedId, offset, maxBytes) {
10763
+ const located = this.findSession(prefixedId);
10764
+ if (!located)
10765
+ return { text: "", newOffset: offset };
10766
+ return readTailFromOffset(located.path, offset, maxBytes);
10767
+ }
10768
+ };
10769
+ piBackend = new PiBackend();
10770
+ }
10771
+ });
10772
+
10048
10773
  // ../engine/dist/core/backends/index.js
10049
10774
  function bootstrapBackends() {
10050
10775
  registerBackend(claudeBackend);
@@ -10053,6 +10778,7 @@ function bootstrapBackends() {
10053
10778
  registerBackend(agyBackend);
10054
10779
  registerBackend(cursorBackend);
10055
10780
  registerBackend(hermesBackend);
10781
+ registerBackend(piBackend);
10056
10782
  }
10057
10783
  var init_backends = __esm({
10058
10784
  "../engine/dist/core/backends/index.js"() {
@@ -10064,6 +10790,7 @@ var init_backends = __esm({
10064
10790
  init_agy();
10065
10791
  init_cursor();
10066
10792
  init_hermes();
10793
+ init_pi();
10067
10794
  init_tool_backend();
10068
10795
  _setRegistryBootstrapper(bootstrapBackends);
10069
10796
  }
@@ -10276,7 +11003,7 @@ var init_session_outcome = __esm({
10276
11003
  });
10277
11004
 
10278
11005
  // ../engine/dist/core/first-prompt.js
10279
- import { createReadStream, existsSync as existsSync11, openSync as openSync3, readSync as readSync3, closeSync as closeSync3 } from "fs";
11006
+ import { createReadStream, existsSync as existsSync11, openSync as openSync4, readSync as readSync4, closeSync as closeSync4 } from "fs";
10280
11007
  import { StringDecoder } from "string_decoder";
10281
11008
  function stripBanners(s) {
10282
11009
  let out = s;
@@ -10330,7 +11057,7 @@ function extractFirstUserPromptSync(filePath, options = {}) {
10330
11057
  const maxBytes = options.maxBytes ?? 4 * 1024 * 1024;
10331
11058
  let fd;
10332
11059
  try {
10333
- fd = openSync3(filePath, "r");
11060
+ fd = openSync4(filePath, "r");
10334
11061
  } catch {
10335
11062
  return "";
10336
11063
  }
@@ -10342,7 +11069,7 @@ function extractFirstUserPromptSync(filePath, options = {}) {
10342
11069
  let pos = 0;
10343
11070
  let lineNo = 0;
10344
11071
  for (; ; ) {
10345
- const n = readSync3(fd, buf, 0, CHUNK, pos);
11072
+ const n = readSync4(fd, buf, 0, CHUNK, pos);
10346
11073
  if (n <= 0)
10347
11074
  break;
10348
11075
  pos += n;
@@ -10368,7 +11095,7 @@ function extractFirstUserPromptSync(filePath, options = {}) {
10368
11095
  return "";
10369
11096
  } finally {
10370
11097
  try {
10371
- closeSync3(fd);
11098
+ closeSync4(fd);
10372
11099
  } catch {
10373
11100
  }
10374
11101
  }
@@ -10387,7 +11114,7 @@ var init_first_prompt = __esm({
10387
11114
  });
10388
11115
 
10389
11116
  // ../engine/dist/core/project-dir-name.js
10390
- import { readdirSync as readdirSync7 } from "node:fs";
11117
+ import { readdirSync as readdirSync8 } from "node:fs";
10391
11118
  function looksWindowsEncoded(dirName) {
10392
11119
  return /^[A-Za-z]--/.test(dirName);
10393
11120
  }
@@ -10407,7 +11134,7 @@ function resolveProjectDirName(dirName, deps = {}) {
10407
11134
  return structural;
10408
11135
  if (looksWindowsEncoded(dirName))
10409
11136
  return structural;
10410
- const readdir = deps.readdir ?? ((p) => readdirSync7(p, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name));
11137
+ const readdir = deps.readdir ?? ((p) => readdirSync8(p, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name));
10411
11138
  const encodeName = (name) => name.replace(/[-_.]/g, "-");
10412
11139
  let remaining = dirName.replace(/^-/, "");
10413
11140
  let current = "/";
@@ -10445,8 +11172,8 @@ var init_project_dir_name = __esm({
10445
11172
  });
10446
11173
 
10447
11174
  // ../engine/dist/core/backends/claude.js
10448
- import { existsSync as existsSync12, readdirSync as readdirSync8, readFileSync as readFileSync7, statSync as statSync9, openSync as openSync4, readSync as readSync4, closeSync as closeSync4 } from "fs";
10449
- import { join as join11, basename as basename6 } from "path";
11175
+ import { existsSync as existsSync12, readdirSync as readdirSync9, readFileSync as readFileSync9, statSync as statSync11, openSync as openSync5, readSync as readSync5, closeSync as closeSync5 } from "fs";
11176
+ import { join as join12, basename as basename7 } from "path";
10450
11177
  function stripReminders(text) {
10451
11178
  return text.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/g, "").trim();
10452
11179
  }
@@ -10478,41 +11205,41 @@ var init_claude2 = __esm({
10478
11205
  }
10479
11206
  // ── Subpath helpers used by the parser/source layer ─────────────
10480
11207
  projectsDir() {
10481
- return join11(this.homeDir(), "projects");
11208
+ return join12(this.homeDir(), "projects");
10482
11209
  }
10483
11210
  plansDir() {
10484
- return join11(this.homeDir(), "plans");
11211
+ return join12(this.homeDir(), "plans");
10485
11212
  }
10486
11213
  todosDir() {
10487
- return join11(this.homeDir(), "todos");
11214
+ return join12(this.homeDir(), "todos");
10488
11215
  }
10489
11216
  /** Legacy task-list directory still used by older Claude Code releases. */
10490
11217
  tasksDir() {
10491
- return join11(this.homeDir(), "tasks");
11218
+ return join12(this.homeDir(), "tasks");
10492
11219
  }
10493
11220
  pasteCacheDir() {
10494
- return join11(this.homeDir(), "paste-cache");
11221
+ return join12(this.homeDir(), "paste-cache");
10495
11222
  }
10496
11223
  skillsDir() {
10497
- return join11(this.homeDir(), "skills");
11224
+ return join12(this.homeDir(), "skills");
10498
11225
  }
10499
11226
  agentsDir() {
10500
- return join11(this.homeDir(), "agents");
11227
+ return join12(this.homeDir(), "agents");
10501
11228
  }
10502
11229
  commandsDir() {
10503
- return join11(this.homeDir(), "commands");
11230
+ return join12(this.homeDir(), "commands");
10504
11231
  }
10505
11232
  pluginsManifestPath() {
10506
- return join11(this.homeDir(), "plugins", "installed_plugins.json");
11233
+ return join12(this.homeDir(), "plugins", "installed_plugins.json");
10507
11234
  }
10508
11235
  hooksFile() {
10509
- return join11(this.homeDir(), "hooks.json");
11236
+ return join12(this.homeDir(), "hooks.json");
10510
11237
  }
10511
11238
  settingsFile() {
10512
- return join11(this.homeDir(), "settings.json");
11239
+ return join12(this.homeDir(), "settings.json");
10513
11240
  }
10514
11241
  historyFile() {
10515
- return join11(this.homeDir(), "history.jsonl");
11242
+ return join12(this.homeDir(), "history.jsonl");
10516
11243
  }
10517
11244
  isAvailable() {
10518
11245
  return existsSync12(this.projectsDir());
@@ -10543,13 +11270,13 @@ var init_claude2 = __esm({
10543
11270
  return null;
10544
11271
  let head;
10545
11272
  try {
10546
- const fd = openSync4(located.path, "r");
11273
+ const fd = openSync5(located.path, "r");
10547
11274
  try {
10548
11275
  const buf = Buffer.alloc(65536);
10549
- const n = readSync4(fd, buf, 0, buf.length, 0);
11276
+ const n = readSync5(fd, buf, 0, buf.length, 0);
10550
11277
  head = buf.toString("utf-8", 0, n);
10551
11278
  } finally {
10552
- closeSync4(fd);
11279
+ closeSync5(fd);
10553
11280
  }
10554
11281
  } catch {
10555
11282
  return null;
@@ -10576,7 +11303,7 @@ var init_claude2 = __esm({
10576
11303
  let mtime = 0;
10577
11304
  for (const c of copies) {
10578
11305
  try {
10579
- mtime = Math.max(mtime, statSync9(c.path).mtimeMs);
11306
+ mtime = Math.max(mtime, statSync11(c.path).mtimeMs);
10580
11307
  } catch {
10581
11308
  }
10582
11309
  }
@@ -10623,18 +11350,18 @@ var init_claude2 = __esm({
10623
11350
  };
10624
11351
  if (!existsSync12(root))
10625
11352
  return;
10626
- for (const proj of readdirSync8(root, { withFileTypes: true })) {
11353
+ for (const proj of readdirSync9(root, { withFileTypes: true })) {
10627
11354
  if (!proj.isDirectory())
10628
11355
  continue;
10629
11356
  if (filter && !proj.name.toLowerCase().includes(filter))
10630
11357
  continue;
10631
- const projPath = join11(root, proj.name);
11358
+ const projPath = join12(root, proj.name);
10632
11359
  const projectPath = resolveProjectDirName(proj.name);
10633
- const indexPath = join11(projPath, "sessions-index.json");
11360
+ const indexPath = join12(projPath, "sessions-index.json");
10634
11361
  const indexed = /* @__PURE__ */ new Set();
10635
11362
  if (existsSync12(indexPath)) {
10636
11363
  try {
10637
- const indexData = JSON.parse(readFileSync7(indexPath, "utf-8"));
11364
+ const indexData = JSON.parse(readFileSync9(indexPath, "utf-8"));
10638
11365
  const entries = indexData.entries || [];
10639
11366
  for (const entry of entries) {
10640
11367
  if (!entry.fullPath || !existsSync12(entry.fullPath))
@@ -10659,20 +11386,20 @@ var init_claude2 = __esm({
10659
11386
  }
10660
11387
  let files;
10661
11388
  try {
10662
- files = readdirSync8(projPath);
11389
+ files = readdirSync9(projPath);
10663
11390
  } catch {
10664
11391
  continue;
10665
11392
  }
10666
11393
  for (const f of files) {
10667
11394
  if (!f.endsWith(".jsonl") || f === "sessions-index.json")
10668
11395
  continue;
10669
- const sessionId = basename6(f, ".jsonl");
11396
+ const sessionId = basename7(f, ".jsonl");
10670
11397
  if (indexed.has(sessionId))
10671
11398
  continue;
10672
- const fullPath = join11(projPath, f);
11399
+ const fullPath = join12(projPath, f);
10673
11400
  let stat;
10674
11401
  try {
10675
- stat = statSync9(fullPath);
11402
+ stat = statSync11(fullPath);
10676
11403
  } catch {
10677
11404
  continue;
10678
11405
  }
@@ -10926,7 +11653,7 @@ var init_claude2 = __esm({
10926
11653
  const events = this.readEvents(rawId);
10927
11654
  let fileMtime = 0;
10928
11655
  try {
10929
- fileMtime = statSync9(located.path).mtimeMs;
11656
+ fileMtime = statSync11(located.path).mtimeMs;
10930
11657
  } catch {
10931
11658
  }
10932
11659
  return liveScanEditsFromEvents(events, this.fileToolMap, {
@@ -10964,30 +11691,30 @@ var init_claude2 = __esm({
10964
11691
  for (const root of claudeProjectDirs()) {
10965
11692
  if (!existsSync12(root))
10966
11693
  continue;
10967
- for (const projEntry of readdirSync8(root, { withFileTypes: true })) {
11694
+ for (const projEntry of readdirSync9(root, { withFileTypes: true })) {
10968
11695
  if (!projEntry.isDirectory())
10969
11696
  continue;
10970
11697
  if (opts.projectFilter && !projEntry.name.toLowerCase().includes(opts.projectFilter.toLowerCase()))
10971
11698
  continue;
10972
- const projPath = join11(root, projEntry.name);
11699
+ const projPath = join12(root, projEntry.name);
10973
11700
  let files;
10974
11701
  try {
10975
- files = readdirSync8(projPath);
11702
+ files = readdirSync9(projPath);
10976
11703
  } catch {
10977
11704
  continue;
10978
11705
  }
10979
11706
  for (const f of files) {
10980
11707
  if (!f.endsWith(".jsonl") || f === "sessions-index.json")
10981
11708
  continue;
10982
- const fp = join11(projPath, f);
11709
+ const fp = join12(projPath, f);
10983
11710
  try {
10984
- const st = statSync9(fp);
11711
+ const st = statSync11(fp);
10985
11712
  let mtime = st.mtimeMs;
10986
- const subDir = join11(projPath, f.slice(0, -6), "subagents");
11713
+ const subDir = join12(projPath, f.slice(0, -6), "subagents");
10987
11714
  if (existsSync12(subDir)) {
10988
- for (const sub of readdirSync8(subDir)) {
11715
+ for (const sub of readdirSync9(subDir)) {
10989
11716
  try {
10990
- const subSt = statSync9(join11(subDir, sub));
11717
+ const subSt = statSync11(join12(subDir, sub));
10991
11718
  if (subSt.mtimeMs > mtime)
10992
11719
  mtime = subSt.mtimeMs;
10993
11720
  } catch {
@@ -10996,7 +11723,7 @@ var init_claude2 = __esm({
10996
11723
  }
10997
11724
  if (mtime < opts.sinceMs)
10998
11725
  continue;
10999
- candidates.push({ rawId: basename6(f, ".jsonl"), mtime });
11726
+ candidates.push({ rawId: basename7(f, ".jsonl"), mtime });
11000
11727
  } catch {
11001
11728
  }
11002
11729
  }
@@ -11052,7 +11779,7 @@ var init_claude2 = __esm({
11052
11779
  let total = 0;
11053
11780
  for (const located of findSessionFiles(this.toRawId(prefixedId))) {
11054
11781
  try {
11055
- total += statSync9(located.path).size;
11782
+ total += statSync11(located.path).size;
11056
11783
  } catch {
11057
11784
  }
11058
11785
  }
@@ -11081,7 +11808,7 @@ var init_claude2 = __esm({
11081
11808
  return copies.slice(0, -1).map((c) => {
11082
11809
  let size = -1;
11083
11810
  try {
11084
- size = statSync9(c.path).size;
11811
+ size = statSync11(c.path).size;
11085
11812
  } catch {
11086
11813
  }
11087
11814
  return `${c.path}:${size}`;
@@ -11114,11 +11841,11 @@ var init_model_pricing = __esm({
11114
11841
  });
11115
11842
 
11116
11843
  // ../engine/dist/parsers/session.js
11117
- import { createReadStream as createReadStream2, existsSync as existsSync13, readdirSync as readdirSync9, readFileSync as readFileSync8, statSync as statSync10, openSync as openSync5, readSync as readSync5, closeSync as closeSync5 } from "fs";
11118
- import { join as join12, basename as basename7 } from "path";
11844
+ import { createReadStream as createReadStream2, existsSync as existsSync13, readdirSync as readdirSync10, readFileSync as readFileSync10, statSync as statSync12, openSync as openSync6, readSync as readSync6, closeSync as closeSync6 } from "fs";
11845
+ import { join as join13, basename as basename8 } from "path";
11119
11846
  function hasSubagentsDir(sessionPath) {
11120
11847
  const dir = sessionPath.slice(0, -6);
11121
- return existsSync13(join12(dir, "subagents"));
11848
+ return existsSync13(join13(dir, "subagents"));
11122
11849
  }
11123
11850
  var init_session = __esm({
11124
11851
  "../engine/dist/parsers/session.js"() {
@@ -11133,9 +11860,9 @@ var init_session = __esm({
11133
11860
  });
11134
11861
 
11135
11862
  // ../engine/dist/transcript/shadow.js
11136
- import { createHash } from "crypto";
11863
+ import { createHash as createHash2 } from "crypto";
11137
11864
  function sha1(s) {
11138
- return createHash("sha1").update(s).digest("hex");
11865
+ return createHash2("sha1").update(s).digest("hex");
11139
11866
  }
11140
11867
  function lineKey(line) {
11141
11868
  try {
@@ -11217,11 +11944,11 @@ __export(live_session_scan_exports, {
11217
11944
  withSessionReadCache: () => withSessionReadCache,
11218
11945
  withSessionScanScope: () => withSessionScanScope
11219
11946
  });
11220
- import { existsSync as existsSync14, readdirSync as readdirSync10, readFileSync as readFileSync9, statSync as statSync11, openSync as openSync6, readSync as readSync6, closeSync as closeSync6 } from "fs";
11221
- import { join as join13, basename as basename8 } from "path";
11222
- import { createHash as createHash2 } from "crypto";
11947
+ import { existsSync as existsSync14, readdirSync as readdirSync11, readFileSync as readFileSync11, statSync as statSync13, openSync as openSync7, readSync as readSync7, closeSync as closeSync7 } from "fs";
11948
+ import { join as join14, basename as basename9 } from "path";
11949
+ import { createHash as createHash3 } from "crypto";
11223
11950
  function lazyGeminiProjectsJson() {
11224
- return join13(geminiHomeDir(), "projects.json");
11951
+ return join14(geminiHomeDir(), "projects.json");
11225
11952
  }
11226
11953
  function detectTool(sessionId) {
11227
11954
  return getBackendForId(sessionId)?.id ?? "claude";
@@ -11284,18 +12011,18 @@ function sessionFileIndex() {
11284
12011
  dirs.set(root, dirMtime(root));
11285
12012
  let entries;
11286
12013
  try {
11287
- entries = readdirSync10(root, { withFileTypes: true });
12014
+ entries = readdirSync11(root, { withFileTypes: true });
11288
12015
  } catch {
11289
12016
  continue;
11290
12017
  }
11291
12018
  for (const entry of entries) {
11292
12019
  if (!entry.isDirectory())
11293
12020
  continue;
11294
- const dir = join13(root, entry.name);
12021
+ const dir = join14(root, entry.name);
11295
12022
  dirs.set(dir, dirMtime(dir));
11296
12023
  let names;
11297
12024
  try {
11298
- names = readdirSync10(dir);
12025
+ names = readdirSync11(dir);
11299
12026
  } catch {
11300
12027
  continue;
11301
12028
  }
@@ -11304,7 +12031,7 @@ function sessionFileIndex() {
11304
12031
  continue;
11305
12032
  const id = name.slice(0, -".jsonl".length);
11306
12033
  const located = {
11307
- path: join13(dir, name),
12034
+ path: join14(dir, name),
11308
12035
  projectDir: entry.name,
11309
12036
  projectPath: projectPathOf(entry.name)
11310
12037
  };
@@ -11336,7 +12063,7 @@ function resolveSessionContentGroups(sessionId) {
11336
12063
  };
11337
12064
  for (const located of findSessionFiles(sessionId)) {
11338
12065
  for (const p of resolveSessionContentPaths(located.path)) {
11339
- add(p === located.path ? "main" : `subagents/${basename8(p)}`, p);
12066
+ add(p === located.path ? "main" : `subagents/${basename9(p)}`, p);
11340
12067
  }
11341
12068
  }
11342
12069
  const names = [...groups.keys()].sort((a, b) => a === "main" ? -1 : b === "main" ? 1 : a.localeCompare(b));
@@ -11370,7 +12097,7 @@ function readSessionGroupText(group) {
11370
12097
  const parts = [];
11371
12098
  for (const p of group.paths) {
11372
12099
  try {
11373
- const st = statSync11(p);
12100
+ const st = statSync13(p);
11374
12101
  parts.push(`${p}:${st.mtimeMs}:${st.size}`);
11375
12102
  } catch {
11376
12103
  parts.push(`${p}:missing`);
@@ -11385,12 +12112,12 @@ function readSessionGroupText(group) {
11385
12112
  for (const p of group.paths) {
11386
12113
  let raw;
11387
12114
  try {
11388
- raw = readFileSync9(p, "utf-8");
12115
+ raw = readFileSync11(p, "utf-8");
11389
12116
  } catch {
11390
12117
  continue;
11391
12118
  }
11392
12119
  try {
11393
- mtime = Math.max(mtime, statSync11(p).mtimeMs);
12120
+ mtime = Math.max(mtime, statSync13(p).mtimeMs);
11394
12121
  } catch {
11395
12122
  }
11396
12123
  text = text ? mergeLineText(text, raw).text : raw;
@@ -11403,10 +12130,10 @@ function readSessionGroupText(group) {
11403
12130
  function resolveSessionContentPaths(sessionFile) {
11404
12131
  if (!hasSubagentsDir(sessionFile))
11405
12132
  return [sessionFile];
11406
- const subDir = join13(sessionFile.slice(0, -6), "subagents");
12133
+ const subDir = join14(sessionFile.slice(0, -6), "subagents");
11407
12134
  if (!existsSync14(subDir))
11408
12135
  return [sessionFile];
11409
- const subPaths = readdirSync10(subDir).filter((f) => f.endsWith(".jsonl")).sort().map((f) => join13(subDir, f));
12136
+ const subPaths = readdirSync11(subDir).filter((f) => f.endsWith(".jsonl")).sort().map((f) => join14(subDir, f));
11410
12137
  return [sessionFile, ...subPaths];
11411
12138
  }
11412
12139
  function liveScanSessionEdits(sessionId) {
@@ -11423,9 +12150,9 @@ function loadGeminiProjectMap() {
11423
12150
  const projectsPath = lazyGeminiProjectsJson();
11424
12151
  if (existsSync14(projectsPath)) {
11425
12152
  try {
11426
- const data = JSON.parse(readFileSync9(projectsPath, "utf-8"));
12153
+ const data = JSON.parse(readFileSync11(projectsPath, "utf-8"));
11427
12154
  for (const path of Object.keys(data.projects || {})) {
11428
- map.set(createHash2("sha256").update(path).digest("hex"), path);
12155
+ map.set(createHash3("sha256").update(path).digest("hex"), path);
11429
12156
  }
11430
12157
  } catch {
11431
12158
  }
@@ -11461,19 +12188,19 @@ function geminiIndex() {
11461
12188
  continue;
11462
12189
  let projs;
11463
12190
  try {
11464
- projs = readdirSync10(tmpRoot, { withFileTypes: true });
12191
+ projs = readdirSync11(tmpRoot, { withFileTypes: true });
11465
12192
  } catch {
11466
12193
  continue;
11467
12194
  }
11468
12195
  for (const proj of projs) {
11469
12196
  if (!proj.isDirectory())
11470
12197
  continue;
11471
- const chats = join13(tmpRoot, proj.name, "chats");
12198
+ const chats = join14(tmpRoot, proj.name, "chats");
11472
12199
  if (!existsSync14(chats))
11473
12200
  continue;
11474
12201
  let files;
11475
12202
  try {
11476
- files = readdirSync10(chats);
12203
+ files = readdirSync11(chats);
11477
12204
  } catch {
11478
12205
  continue;
11479
12206
  }
@@ -11482,7 +12209,7 @@ function geminiIndex() {
11482
12209
  continue;
11483
12210
  const base = f.replace(/\.jsonl?$/, "");
11484
12211
  const located = {
11485
- path: join13(chats, f),
12212
+ path: join14(chats, f),
11486
12213
  projectDir: proj.name,
11487
12214
  projectPath: projMap.get(proj.name) || "",
11488
12215
  format: f.endsWith(".jsonl") ? "jsonl" : "json"
@@ -11517,19 +12244,19 @@ function geminiInnerIdIndex(idx) {
11517
12244
  return byInnerId;
11518
12245
  }
11519
12246
  function readHeadSync(path, bytes = 65536) {
11520
- const fd = openSync6(path, "r");
12247
+ const fd = openSync7(path, "r");
11521
12248
  try {
11522
12249
  const buf = Buffer.alloc(bytes);
11523
- const n = readSync6(fd, buf, 0, buf.length, 0);
12250
+ const n = readSync7(fd, buf, 0, buf.length, 0);
11524
12251
  return buf.toString("utf-8", 0, n);
11525
12252
  } finally {
11526
- closeSync6(fd);
12253
+ closeSync7(fd);
11527
12254
  }
11528
12255
  }
11529
12256
  function readGeminiSessionIdFromFile(path, format) {
11530
12257
  if (format === "json") {
11531
12258
  try {
11532
- return JSON.parse(readFileSync9(path, "utf-8"))?.sessionId ?? null;
12259
+ return JSON.parse(readFileSync11(path, "utf-8"))?.sessionId ?? null;
11533
12260
  } catch {
11534
12261
  return null;
11535
12262
  }
@@ -11544,7 +12271,7 @@ function readGeminiSessionIdFromFile(path, format) {
11544
12271
  function readGeminiMessages(path, format) {
11545
12272
  if (format === "json") {
11546
12273
  try {
11547
- const json = JSON.parse(readFileSync9(path, "utf-8"));
12274
+ const json = JSON.parse(readFileSync11(path, "utf-8"));
11548
12275
  return Array.isArray(json.messages) ? json.messages : [];
11549
12276
  } catch {
11550
12277
  return [];
@@ -11553,7 +12280,7 @@ function readGeminiMessages(path, format) {
11553
12280
  const out = [];
11554
12281
  let raw;
11555
12282
  try {
11556
- raw = readFileSync9(path, "utf-8");
12283
+ raw = readFileSync11(path, "utf-8");
11557
12284
  } catch {
11558
12285
  return out;
11559
12286
  }
@@ -11592,21 +12319,21 @@ function findCodexSessionFile(sessionId) {
11592
12319
  function findCodexSessionFileIn(root, sessionId) {
11593
12320
  if (!existsSync14(root))
11594
12321
  return null;
11595
- for (const year of readdirSync10(root, { withFileTypes: true })) {
12322
+ for (const year of readdirSync11(root, { withFileTypes: true })) {
11596
12323
  if (!year.isDirectory())
11597
12324
  continue;
11598
- const yearPath = join13(root, year.name);
11599
- for (const month of readdirSync10(yearPath, { withFileTypes: true })) {
12325
+ const yearPath = join14(root, year.name);
12326
+ for (const month of readdirSync11(yearPath, { withFileTypes: true })) {
11600
12327
  if (!month.isDirectory())
11601
12328
  continue;
11602
- const monthPath = join13(yearPath, month.name);
11603
- for (const day of readdirSync10(monthPath, { withFileTypes: true })) {
12329
+ const monthPath = join14(yearPath, month.name);
12330
+ for (const day of readdirSync11(monthPath, { withFileTypes: true })) {
11604
12331
  if (!day.isDirectory())
11605
12332
  continue;
11606
- const dayPath = join13(monthPath, day.name);
12333
+ const dayPath = join14(monthPath, day.name);
11607
12334
  let files;
11608
12335
  try {
11609
- files = readdirSync10(dayPath);
12336
+ files = readdirSync11(dayPath);
11610
12337
  } catch {
11611
12338
  continue;
11612
12339
  }
@@ -11614,22 +12341,22 @@ function findCodexSessionFileIn(root, sessionId) {
11614
12341
  if (!f.endsWith(".jsonl"))
11615
12342
  continue;
11616
12343
  if (f.includes(sessionId)) {
11617
- return { path: join13(dayPath, f), projectPath: "" };
12344
+ return { path: join14(dayPath, f), projectPath: "" };
11618
12345
  }
11619
12346
  }
11620
12347
  }
11621
12348
  }
11622
12349
  }
11623
12350
  function scanDir(dir) {
11624
- for (const entry of readdirSync10(dir, { withFileTypes: true })) {
12351
+ for (const entry of readdirSync11(dir, { withFileTypes: true })) {
11625
12352
  if (entry.isDirectory()) {
11626
- const found = scanDir(join13(dir, entry.name));
12353
+ const found = scanDir(join14(dir, entry.name));
11627
12354
  if (found)
11628
12355
  return found;
11629
12356
  } else if (entry.name.endsWith(".jsonl")) {
11630
- const p = join13(dir, entry.name);
12357
+ const p = join14(dir, entry.name);
11631
12358
  try {
11632
- const first = readFileSync9(p, "utf-8").split("\n")[0];
12359
+ const first = readFileSync11(p, "utf-8").split("\n")[0];
11633
12360
  if (!first)
11634
12361
  continue;
11635
12362
  const meta = JSON.parse(first);
@@ -11705,7 +12432,7 @@ var init_live_session_scan = __esm({
11705
12432
  INDEX_RECHECK_MS = 1e3;
11706
12433
  dirMtime = (p) => {
11707
12434
  try {
11708
- return statSync11(p).mtimeMs;
12435
+ return statSync13(p).mtimeMs;
11709
12436
  } catch {
11710
12437
  return -1;
11711
12438
  }