chat-recall 0.7.21 → 0.7.24

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
@@ -443,30 +443,30 @@ var require_caller = __commonJS({
443
443
  var require_redact = __commonJS({
444
444
  "../../node_modules/@pinojs/redact/index.js"(exports, module) {
445
445
  "use strict";
446
- function deepClone(obj) {
447
- if (obj === null || typeof obj !== "object") {
448
- return obj;
446
+ function deepClone(obj2) {
447
+ if (obj2 === null || typeof obj2 !== "object") {
448
+ return obj2;
449
449
  }
450
- if (obj instanceof Date) {
451
- return new Date(obj.getTime());
450
+ if (obj2 instanceof Date) {
451
+ return new Date(obj2.getTime());
452
452
  }
453
- if (obj instanceof Array) {
453
+ if (obj2 instanceof Array) {
454
454
  const cloned = [];
455
- for (let i = 0; i < obj.length; i++) {
456
- cloned[i] = deepClone(obj[i]);
455
+ for (let i = 0; i < obj2.length; i++) {
456
+ cloned[i] = deepClone(obj2[i]);
457
457
  }
458
458
  return cloned;
459
459
  }
460
- if (typeof obj === "object") {
461
- const cloned = Object.create(Object.getPrototypeOf(obj));
462
- for (const key2 in obj) {
463
- if (Object.prototype.hasOwnProperty.call(obj, key2)) {
464
- cloned[key2] = deepClone(obj[key2]);
460
+ if (typeof obj2 === "object") {
461
+ const cloned = Object.create(Object.getPrototypeOf(obj2));
462
+ for (const key2 in obj2) {
463
+ if (Object.prototype.hasOwnProperty.call(obj2, key2)) {
464
+ cloned[key2] = deepClone(obj2[key2]);
465
465
  }
466
466
  }
467
467
  return cloned;
468
468
  }
469
- return obj;
469
+ return obj2;
470
470
  }
471
471
  function parsePath(path) {
472
472
  const parts = [];
@@ -511,8 +511,8 @@ var require_redact = __commonJS({
511
511
  }
512
512
  return parts;
513
513
  }
514
- function setValue(obj, parts, value) {
515
- let current = obj;
514
+ function setValue(obj2, parts, value) {
515
+ let current = obj2;
516
516
  for (let i = 0; i < parts.length - 1; i++) {
517
517
  const key2 = parts[i];
518
518
  if (typeof current !== "object" || current === null || !(key2 in current)) {
@@ -543,8 +543,8 @@ var require_redact = __commonJS({
543
543
  }
544
544
  return true;
545
545
  }
546
- function removeKey(obj, parts) {
547
- let current = obj;
546
+ function removeKey(obj2, parts) {
547
+ let current = obj2;
548
548
  for (let i = 0; i < parts.length - 1; i++) {
549
549
  const key2 = parts[i];
550
550
  if (typeof current !== "object" || current === null || !(key2 in current)) {
@@ -576,8 +576,8 @@ var require_redact = __commonJS({
576
576
  return true;
577
577
  }
578
578
  var PATH_NOT_FOUND = /* @__PURE__ */ Symbol("PATH_NOT_FOUND");
579
- function getValueIfExists(obj, parts) {
580
- let current = obj;
579
+ function getValueIfExists(obj2, parts) {
580
+ let current = obj2;
581
581
  for (const part of parts) {
582
582
  if (current === null || current === void 0) {
583
583
  return PATH_NOT_FOUND;
@@ -592,8 +592,8 @@ var require_redact = __commonJS({
592
592
  }
593
593
  return current;
594
594
  }
595
- function getValue(obj, parts) {
596
- let current = obj;
595
+ function getValue(obj2, parts) {
596
+ let current = obj2;
597
597
  for (const part of parts) {
598
598
  if (current === null || current === void 0) {
599
599
  return void 0;
@@ -605,30 +605,30 @@ var require_redact = __commonJS({
605
605
  }
606
606
  return current;
607
607
  }
608
- function redactPaths(obj, paths, censor, remove = false) {
608
+ function redactPaths(obj2, paths, censor, remove = false) {
609
609
  for (const path of paths) {
610
610
  const parts = parsePath(path);
611
611
  if (parts.includes("*")) {
612
- redactWildcardPath(obj, parts, censor, path, remove);
612
+ redactWildcardPath(obj2, parts, censor, path, remove);
613
613
  } else {
614
614
  if (remove) {
615
- removeKey(obj, parts);
615
+ removeKey(obj2, parts);
616
616
  } else {
617
- const value = getValueIfExists(obj, parts);
617
+ const value = getValueIfExists(obj2, parts);
618
618
  if (value === PATH_NOT_FOUND) {
619
619
  continue;
620
620
  }
621
621
  const actualCensor = typeof censor === "function" ? censor(value, parts) : censor;
622
- setValue(obj, parts, actualCensor);
622
+ setValue(obj2, parts, actualCensor);
623
623
  }
624
624
  }
625
625
  }
626
626
  }
627
- function redactWildcardPath(obj, parts, censor, originalPath, remove = false) {
627
+ function redactWildcardPath(obj2, parts, censor, originalPath, remove = false) {
628
628
  const wildcardIndex = parts.indexOf("*");
629
629
  if (wildcardIndex === parts.length - 1) {
630
630
  const parentParts = parts.slice(0, -1);
631
- let current = obj;
631
+ let current = obj2;
632
632
  for (const part of parentParts) {
633
633
  if (current === null || current === void 0) return;
634
634
  if (typeof current !== "object" || current === null) return;
@@ -666,10 +666,10 @@ var require_redact = __commonJS({
666
666
  }
667
667
  }
668
668
  } else {
669
- redactIntermediateWildcard(obj, parts, censor, wildcardIndex, originalPath, remove);
669
+ redactIntermediateWildcard(obj2, parts, censor, wildcardIndex, originalPath, remove);
670
670
  }
671
671
  }
672
- function redactIntermediateWildcard(obj, parts, censor, wildcardIndex, originalPath, remove = false) {
672
+ function redactIntermediateWildcard(obj2, parts, censor, wildcardIndex, originalPath, remove = false) {
673
673
  const beforeWildcard = parts.slice(0, wildcardIndex);
674
674
  const afterWildcard = parts.slice(wildcardIndex + 1);
675
675
  const pathArray = [];
@@ -710,9 +710,9 @@ var require_redact = __commonJS({
710
710
  }
711
711
  }
712
712
  if (beforeWildcard.length === 0) {
713
- traverse(obj, 0);
713
+ traverse(obj2, 0);
714
714
  } else {
715
- let current = obj;
715
+ let current = obj2;
716
716
  for (let i = 0; i < beforeWildcard.length; i++) {
717
717
  const part = beforeWildcard[i];
718
718
  if (current === null || current === void 0) return;
@@ -743,9 +743,9 @@ var require_redact = __commonJS({
743
743
  }
744
744
  return pathStructure;
745
745
  }
746
- function selectiveClone(obj, pathStructure) {
746
+ function selectiveClone(obj2, pathStructure) {
747
747
  if (!pathStructure) {
748
- return obj;
748
+ return obj2;
749
749
  }
750
750
  function cloneSelectively(source, pathMap, depth = 0) {
751
751
  if (!pathMap || pathMap.size === 0) {
@@ -781,7 +781,7 @@ var require_redact = __commonJS({
781
781
  }
782
782
  return cloned;
783
783
  }
784
- return cloneSelectively(obj, pathStructure);
784
+ return cloneSelectively(obj2, pathStructure);
785
785
  }
786
786
  function validatePath(path) {
787
787
  if (typeof path !== "string") {
@@ -840,17 +840,17 @@ var require_redact = __commonJS({
840
840
  } = options;
841
841
  validatePaths(paths);
842
842
  const pathStructure = buildPathStructure(paths);
843
- return function redact(obj) {
844
- if (strict && (obj === null || typeof obj !== "object")) {
845
- if (obj === null || obj === void 0) {
846
- return serialize ? serialize(obj) : obj;
843
+ return function redact(obj2) {
844
+ if (strict && (obj2 === null || typeof obj2 !== "object")) {
845
+ if (obj2 === null || obj2 === void 0) {
846
+ return serialize ? serialize(obj2) : obj2;
847
847
  }
848
- if (typeof obj !== "object") {
849
- return serialize ? serialize(obj) : obj;
848
+ if (typeof obj2 !== "object") {
849
+ return serialize ? serialize(obj2) : obj2;
850
850
  }
851
851
  }
852
- const cloned = selectiveClone(obj, pathStructure);
853
- const original = obj;
852
+ const cloned = selectiveClone(obj2, pathStructure);
853
+ const original = obj2;
854
854
  let actualCensor = censor;
855
855
  if (typeof censor === "function") {
856
856
  actualCensor = censor;
@@ -1838,10 +1838,10 @@ var require_on_exit_leak_free = __commonJS({
1838
1838
  }
1839
1839
  function callRefs(event) {
1840
1840
  for (const ref of refs[event]) {
1841
- const obj = ref.deref();
1841
+ const obj2 = ref.deref();
1842
1842
  const fn = ref.fn;
1843
- if (obj !== void 0) {
1844
- fn(obj, event);
1843
+ if (obj2 !== void 0) {
1844
+ fn(obj2, event);
1845
1845
  }
1846
1846
  }
1847
1847
  refs[event] = [];
@@ -1853,32 +1853,32 @@ var require_on_exit_leak_free = __commonJS({
1853
1853
  uninstall(event);
1854
1854
  }
1855
1855
  }
1856
- function _register(event, obj, fn) {
1857
- if (obj === void 0) {
1856
+ function _register(event, obj2, fn) {
1857
+ if (obj2 === void 0) {
1858
1858
  throw new Error("the object can't be undefined");
1859
1859
  }
1860
1860
  install(event);
1861
- const ref = new WeakRef(obj);
1861
+ const ref = new WeakRef(obj2);
1862
1862
  ref.fn = fn;
1863
1863
  ensureRegistry();
1864
- registry.register(obj, ref);
1864
+ registry.register(obj2, ref);
1865
1865
  refs[event].push(ref);
1866
1866
  }
1867
- function register(obj, fn) {
1868
- _register("exit", obj, fn);
1867
+ function register(obj2, fn) {
1868
+ _register("exit", obj2, fn);
1869
1869
  }
1870
- function registerBeforeExit(obj, fn) {
1871
- _register("beforeExit", obj, fn);
1870
+ function registerBeforeExit(obj2, fn) {
1871
+ _register("beforeExit", obj2, fn);
1872
1872
  }
1873
- function unregister(obj) {
1873
+ function unregister(obj2) {
1874
1874
  if (registry === void 0) {
1875
1875
  return;
1876
1876
  }
1877
- registry.unregister(obj);
1877
+ registry.unregister(obj2);
1878
1878
  for (const event of ["exit", "beforeExit"]) {
1879
1879
  refs[event] = refs[event].filter((ref) => {
1880
1880
  const _obj = ref.deref();
1881
- return _obj && _obj !== obj;
1881
+ return _obj && _obj !== obj2;
1882
1882
  });
1883
1883
  uninstall(event);
1884
1884
  }
@@ -2034,7 +2034,7 @@ var require_thread_stream = __commonJS({
2034
2034
  var { version: version2 } = require_package();
2035
2035
  var { EventEmitter } = __require("events");
2036
2036
  var { Worker: Worker2 } = __require("worker_threads");
2037
- var { join: join67 } = __require("path");
2037
+ var { join: join68 } = __require("path");
2038
2038
  var { pathToFileURL } = __require("url");
2039
2039
  var { wait } = require_wait();
2040
2040
  var {
@@ -2077,7 +2077,7 @@ var require_thread_stream = __commonJS({
2077
2077
  function createWorker(stream, opts) {
2078
2078
  const { filename, workerData } = opts;
2079
2079
  const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
2080
- const toExecute = bundlerOverrides["thread-stream-worker"] || join67(__dirname, "lib", "worker.js");
2080
+ const toExecute = bundlerOverrides["thread-stream-worker"] || join68(__dirname, "lib", "worker.js");
2081
2081
  const worker = new Worker2(toExecute, {
2082
2082
  ...opts.workerOpts,
2083
2083
  trackUnmanagedFds: false,
@@ -2480,7 +2480,7 @@ var require_transport = __commonJS({
2480
2480
  "use strict";
2481
2481
  var { createRequire: createRequire3 } = __require("module");
2482
2482
  var getCallers = require_caller();
2483
- var { join: join67, isAbsolute: isAbsolute5, sep: sep4 } = __require("node:path");
2483
+ var { join: join68, isAbsolute: isAbsolute5, sep: sep4 } = __require("node:path");
2484
2484
  var sleep2 = require_atomic_sleep();
2485
2485
  var onExit = require_on_exit_leak_free();
2486
2486
  var ThreadStream = require_thread_stream();
@@ -2543,7 +2543,7 @@ var require_transport = __commonJS({
2543
2543
  throw new Error("only one of target or targets can be specified");
2544
2544
  }
2545
2545
  if (targets) {
2546
- target = bundlerOverrides["pino-worker"] || join67(__dirname, "worker.js");
2546
+ target = bundlerOverrides["pino-worker"] || join68(__dirname, "worker.js");
2547
2547
  options.targets = targets.filter((dest) => dest.target).map((dest) => {
2548
2548
  return {
2549
2549
  ...dest,
@@ -2561,7 +2561,7 @@ var require_transport = __commonJS({
2561
2561
  });
2562
2562
  });
2563
2563
  } else if (pipeline) {
2564
- target = bundlerOverrides["pino-worker"] || join67(__dirname, "worker.js");
2564
+ target = bundlerOverrides["pino-worker"] || join68(__dirname, "worker.js");
2565
2565
  options.pipelines = [pipeline.map((dest) => {
2566
2566
  return {
2567
2567
  ...dest,
@@ -2583,7 +2583,7 @@ var require_transport = __commonJS({
2583
2583
  return origin;
2584
2584
  }
2585
2585
  if (origin === "pino/file") {
2586
- return join67(__dirname, "..", "file.js");
2586
+ return join68(__dirname, "..", "file.js");
2587
2587
  }
2588
2588
  let fixTarget2;
2589
2589
  for (const filePath of callers) {
@@ -2706,14 +2706,14 @@ var require_tools = __commonJS({
2706
2706
  }
2707
2707
  return point < 32 ? JSON.stringify(str) : '"' + result + '"';
2708
2708
  }
2709
- function asJson(obj, msg, num, time) {
2709
+ function asJson(obj2, msg, num, time) {
2710
2710
  if (asJsonChan.hasSubscribers === false) {
2711
- return _asJson.call(this, obj, msg, num, time);
2711
+ return _asJson.call(this, obj2, msg, num, time);
2712
2712
  }
2713
2713
  const store = { instance: this, arguments };
2714
- return asJsonChan.traceSync(_asJson, store, this, obj, msg, num, time);
2714
+ return asJsonChan.traceSync(_asJson, store, this, obj2, msg, num, time);
2715
2715
  }
2716
- function _asJson(obj, msg, num, time) {
2716
+ function _asJson(obj2, msg, num, time) {
2717
2717
  const stringify2 = this[stringifySym];
2718
2718
  const stringifySafe = this[stringifySafeSym];
2719
2719
  const stringifiers = this[stringifiersSym];
@@ -2727,13 +2727,13 @@ var require_tools = __commonJS({
2727
2727
  data = data + chindings;
2728
2728
  let value;
2729
2729
  if (formatters.log) {
2730
- obj = formatters.log(obj);
2730
+ obj2 = formatters.log(obj2);
2731
2731
  }
2732
2732
  const wildcardStringifier = stringifiers[wildcardFirstSym];
2733
2733
  let propStr = "";
2734
- for (const key2 in obj) {
2735
- value = obj[key2];
2736
- if (Object.prototype.hasOwnProperty.call(obj, key2) && value !== void 0) {
2734
+ for (const key2 in obj2) {
2735
+ value = obj2[key2];
2736
+ if (Object.prototype.hasOwnProperty.call(obj2, key2) && value !== void 0) {
2737
2737
  if (serializers[key2]) {
2738
2738
  value = serializers[key2](value);
2739
2739
  } else if (key2 === errorKey && serializers.err) {
@@ -2899,13 +2899,13 @@ var require_tools = __commonJS({
2899
2899
  return { opts, stream };
2900
2900
  };
2901
2901
  }
2902
- function stringify(obj, stringifySafeFn) {
2902
+ function stringify(obj2, stringifySafeFn) {
2903
2903
  try {
2904
- return JSON.stringify(obj);
2904
+ return JSON.stringify(obj2);
2905
2905
  } catch (_) {
2906
2906
  try {
2907
2907
  const stringify2 = stringifySafeFn || this[stringifySafeSym];
2908
- return stringify2(obj);
2908
+ return stringify2(obj2);
2909
2909
  } catch (_2) {
2910
2910
  return '"[unable to serialize, circular reference is too complex to analyze]"';
2911
2911
  }
@@ -3355,29 +3355,29 @@ var require_proto = __commonJS({
3355
3355
  const errorKey = this[errorKeySym];
3356
3356
  const messageKey = this[messageKeySym];
3357
3357
  const mixinMergeStrategy = this[mixinMergeStrategySym] || defaultMixinMergeStrategy;
3358
- let obj;
3358
+ let obj2;
3359
3359
  const streamWriteHook = this[hooksSym].streamWrite;
3360
3360
  if (_obj === void 0 || _obj === null) {
3361
- obj = {};
3361
+ obj2 = {};
3362
3362
  } else if (_obj instanceof Error) {
3363
- obj = { [errorKey]: _obj };
3363
+ obj2 = { [errorKey]: _obj };
3364
3364
  if (msg === void 0) {
3365
3365
  msg = _obj.message;
3366
3366
  }
3367
3367
  } else {
3368
- obj = _obj;
3368
+ obj2 = _obj;
3369
3369
  if (msg === void 0 && _obj[messageKey] === void 0 && _obj[errorKey]) {
3370
3370
  msg = _obj[errorKey].message;
3371
3371
  }
3372
3372
  }
3373
3373
  if (mixin) {
3374
- obj = mixinMergeStrategy(obj, mixin(obj, num, this));
3374
+ obj2 = mixinMergeStrategy(obj2, mixin(obj2, num, this));
3375
3375
  }
3376
- const s = this[asJsonSym](obj, msg, num, t);
3376
+ const s = this[asJsonSym](obj2, msg, num, t);
3377
3377
  const stream = this[streamSym];
3378
3378
  if (stream[needsMetadataGsym] === true) {
3379
3379
  stream.lastLevel = num;
3380
- stream.lastObj = obj;
3380
+ stream.lastObj = obj2;
3381
3381
  stream.lastMsg = msg;
3382
3382
  stream.lastTime = t.slice(this[timeSliceIndexSym]);
3383
3383
  stream.lastLogger = this;
@@ -3572,7 +3572,7 @@ var require_safe_stable_stringify = __commonJS({
3572
3572
  return circularValue;
3573
3573
  }
3574
3574
  let res = "";
3575
- let join67 = ",";
3575
+ let join68 = ",";
3576
3576
  const originalIndentation = indentation;
3577
3577
  if (Array.isArray(value)) {
3578
3578
  if (value.length === 0) {
@@ -3586,7 +3586,7 @@ var require_safe_stable_stringify = __commonJS({
3586
3586
  indentation += spacer;
3587
3587
  res += `
3588
3588
  ${indentation}`;
3589
- join67 = `,
3589
+ join68 = `,
3590
3590
  ${indentation}`;
3591
3591
  }
3592
3592
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -3594,13 +3594,13 @@ ${indentation}`;
3594
3594
  for (; i < maximumValuesToStringify - 1; i++) {
3595
3595
  const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
3596
3596
  res += tmp2 !== void 0 ? tmp2 : "null";
3597
- res += join67;
3597
+ res += join68;
3598
3598
  }
3599
3599
  const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
3600
3600
  res += tmp !== void 0 ? tmp : "null";
3601
3601
  if (value.length - 1 > maximumBreadth) {
3602
3602
  const removedKeys = value.length - maximumBreadth - 1;
3603
- res += `${join67}"... ${getItemCount(removedKeys)} not stringified"`;
3603
+ res += `${join68}"... ${getItemCount(removedKeys)} not stringified"`;
3604
3604
  }
3605
3605
  if (spacer !== "") {
3606
3606
  res += `
@@ -3621,7 +3621,7 @@ ${originalIndentation}`;
3621
3621
  let separator = "";
3622
3622
  if (spacer !== "") {
3623
3623
  indentation += spacer;
3624
- join67 = `,
3624
+ join68 = `,
3625
3625
  ${indentation}`;
3626
3626
  whitespace = " ";
3627
3627
  }
@@ -3635,13 +3635,13 @@ ${indentation}`;
3635
3635
  const tmp = stringifyFnReplacer(key3, value, stack, replacer, spacer, indentation);
3636
3636
  if (tmp !== void 0) {
3637
3637
  res += `${separator}${strEscape(key3)}:${whitespace}${tmp}`;
3638
- separator = join67;
3638
+ separator = join68;
3639
3639
  }
3640
3640
  }
3641
3641
  if (keyLength > maximumBreadth) {
3642
3642
  const removedKeys = keyLength - maximumBreadth;
3643
3643
  res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
3644
- separator = join67;
3644
+ separator = join68;
3645
3645
  }
3646
3646
  if (spacer !== "" && separator.length > 1) {
3647
3647
  res = `
@@ -3682,7 +3682,7 @@ ${originalIndentation}`;
3682
3682
  }
3683
3683
  const originalIndentation = indentation;
3684
3684
  let res = "";
3685
- let join67 = ",";
3685
+ let join68 = ",";
3686
3686
  if (Array.isArray(value)) {
3687
3687
  if (value.length === 0) {
3688
3688
  return "[]";
@@ -3695,7 +3695,7 @@ ${originalIndentation}`;
3695
3695
  indentation += spacer;
3696
3696
  res += `
3697
3697
  ${indentation}`;
3698
- join67 = `,
3698
+ join68 = `,
3699
3699
  ${indentation}`;
3700
3700
  }
3701
3701
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -3703,13 +3703,13 @@ ${indentation}`;
3703
3703
  for (; i < maximumValuesToStringify - 1; i++) {
3704
3704
  const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
3705
3705
  res += tmp2 !== void 0 ? tmp2 : "null";
3706
- res += join67;
3706
+ res += join68;
3707
3707
  }
3708
3708
  const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
3709
3709
  res += tmp !== void 0 ? tmp : "null";
3710
3710
  if (value.length - 1 > maximumBreadth) {
3711
3711
  const removedKeys = value.length - maximumBreadth - 1;
3712
- res += `${join67}"... ${getItemCount(removedKeys)} not stringified"`;
3712
+ res += `${join68}"... ${getItemCount(removedKeys)} not stringified"`;
3713
3713
  }
3714
3714
  if (spacer !== "") {
3715
3715
  res += `
@@ -3722,7 +3722,7 @@ ${originalIndentation}`;
3722
3722
  let whitespace = "";
3723
3723
  if (spacer !== "") {
3724
3724
  indentation += spacer;
3725
- join67 = `,
3725
+ join68 = `,
3726
3726
  ${indentation}`;
3727
3727
  whitespace = " ";
3728
3728
  }
@@ -3731,7 +3731,7 @@ ${indentation}`;
3731
3731
  const tmp = stringifyArrayReplacer(key3, value[key3], stack, replacer, spacer, indentation);
3732
3732
  if (tmp !== void 0) {
3733
3733
  res += `${separator}${strEscape(key3)}:${whitespace}${tmp}`;
3734
- separator = join67;
3734
+ separator = join68;
3735
3735
  }
3736
3736
  }
3737
3737
  if (spacer !== "" && separator.length > 1) {
@@ -3789,20 +3789,20 @@ ${originalIndentation}`;
3789
3789
  indentation += spacer;
3790
3790
  let res2 = `
3791
3791
  ${indentation}`;
3792
- const join68 = `,
3792
+ const join69 = `,
3793
3793
  ${indentation}`;
3794
3794
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
3795
3795
  let i = 0;
3796
3796
  for (; i < maximumValuesToStringify - 1; i++) {
3797
3797
  const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
3798
3798
  res2 += tmp2 !== void 0 ? tmp2 : "null";
3799
- res2 += join68;
3799
+ res2 += join69;
3800
3800
  }
3801
3801
  const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
3802
3802
  res2 += tmp !== void 0 ? tmp : "null";
3803
3803
  if (value.length - 1 > maximumBreadth) {
3804
3804
  const removedKeys = value.length - maximumBreadth - 1;
3805
- res2 += `${join68}"... ${getItemCount(removedKeys)} not stringified"`;
3805
+ res2 += `${join69}"... ${getItemCount(removedKeys)} not stringified"`;
3806
3806
  }
3807
3807
  res2 += `
3808
3808
  ${originalIndentation}`;
@@ -3818,16 +3818,16 @@ ${originalIndentation}`;
3818
3818
  return '"[Object]"';
3819
3819
  }
3820
3820
  indentation += spacer;
3821
- const join67 = `,
3821
+ const join68 = `,
3822
3822
  ${indentation}`;
3823
3823
  let res = "";
3824
3824
  let separator = "";
3825
3825
  let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
3826
3826
  if (isTypedArrayWithEntries(value)) {
3827
- res += stringifyTypedArray(value, join67, maximumBreadth);
3827
+ res += stringifyTypedArray(value, join68, maximumBreadth);
3828
3828
  keys = keys.slice(value.length);
3829
3829
  maximumPropertiesToStringify -= value.length;
3830
- separator = join67;
3830
+ separator = join68;
3831
3831
  }
3832
3832
  if (deterministic) {
3833
3833
  keys = sort(keys, comparator);
@@ -3838,13 +3838,13 @@ ${indentation}`;
3838
3838
  const tmp = stringifyIndent(key3, value[key3], stack, spacer, indentation);
3839
3839
  if (tmp !== void 0) {
3840
3840
  res += `${separator}${strEscape(key3)}: ${tmp}`;
3841
- separator = join67;
3841
+ separator = join68;
3842
3842
  }
3843
3843
  }
3844
3844
  if (keyLength > maximumBreadth) {
3845
3845
  const removedKeys = keyLength - maximumBreadth;
3846
3846
  res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
3847
- separator = join67;
3847
+ separator = join68;
3848
3848
  }
3849
3849
  if (separator !== "") {
3850
3850
  res = `
@@ -4959,30 +4959,30 @@ function declaredOrigin(value) {
4959
4959
  const kind = value.kind;
4960
4960
  return typeof kind === "string" && kind ? kind : void 0;
4961
4961
  }
4962
- function userRecordOrigin(obj, text) {
4963
- if (obj.isSidechain === true)
4962
+ function userRecordOrigin(obj2, text) {
4963
+ if (obj2.isSidechain === true)
4964
4964
  return "subagent";
4965
- if (obj.isCompactSummary === true)
4965
+ if (obj2.isCompactSummary === true)
4966
4966
  return "compact-summary";
4967
- const declared = declaredOrigin(obj.origin);
4967
+ const declared = declaredOrigin(obj2.origin);
4968
4968
  if (declared && declared !== "human")
4969
4969
  return declared;
4970
- if (obj.isMeta === true)
4970
+ if (obj2.isMeta === true)
4971
4971
  return "meta";
4972
4972
  if (declared === "human")
4973
4973
  return "human";
4974
4974
  return originFromText(text);
4975
4975
  }
4976
- function queuedCommandPrompt(obj) {
4977
- if (obj.type !== "attachment")
4976
+ function queuedCommandPrompt(obj2) {
4977
+ if (obj2.type !== "attachment")
4978
4978
  return null;
4979
- const att = obj.attachment;
4979
+ const att = obj2.attachment;
4980
4980
  if (!att || att.type !== "queued_command")
4981
4981
  return null;
4982
4982
  const text = promptText(att.prompt);
4983
4983
  if (!text)
4984
4984
  return null;
4985
- if (obj.isSidechain === true)
4985
+ if (obj2.isSidechain === true)
4986
4986
  return { text, origin: "subagent" };
4987
4987
  const declared = declaredOrigin(att.origin);
4988
4988
  if (declared)
@@ -7254,17 +7254,17 @@ function stripBanners(s) {
7254
7254
  function promptFromLine(raw, maxLength) {
7255
7255
  if (!raw.trim())
7256
7256
  return null;
7257
- let obj;
7257
+ let obj2;
7258
7258
  try {
7259
- obj = JSON.parse(raw);
7259
+ obj2 = JSON.parse(raw);
7260
7260
  } catch {
7261
7261
  return null;
7262
7262
  }
7263
- if (obj.type !== "user")
7263
+ if (obj2.type !== "user")
7264
7264
  return null;
7265
- if (obj.isSidechain === true)
7265
+ if (obj2.isSidechain === true)
7266
7266
  return null;
7267
- const message = obj.message;
7267
+ const message = obj2.message;
7268
7268
  if (!message)
7269
7269
  return null;
7270
7270
  const content = message.content;
@@ -8028,17 +8028,17 @@ var init_claude = __esm({
8028
8028
  lineNum++;
8029
8029
  if (!line.trim())
8030
8030
  continue;
8031
- let obj;
8031
+ let obj2;
8032
8032
  try {
8033
- obj = JSON.parse(line);
8033
+ obj2 = JSON.parse(line);
8034
8034
  } catch {
8035
8035
  continue;
8036
8036
  }
8037
- const tsIso = typeof obj.timestamp === "string" ? obj.timestamp : void 0;
8037
+ const tsIso = typeof obj2.timestamp === "string" ? obj2.timestamp : void 0;
8038
8038
  const ts = tsIso ? Date.parse(tsIso) || mtime : mtime;
8039
- if (obj.type === "queue-operation") {
8040
- if (obj.operation === "enqueue" && typeof obj.content === "string") {
8041
- const text = stripReminders(obj.content);
8039
+ if (obj2.type === "queue-operation") {
8040
+ if (obj2.operation === "enqueue" && typeof obj2.content === "string") {
8041
+ const text = stripReminders(obj2.content);
8042
8042
  if (text && originFromText(text) === "human") {
8043
8043
  const e = { kind: "user", ts, tsIso, line: lineNum, text };
8044
8044
  events.push(e);
@@ -8051,15 +8051,15 @@ var init_claude = __esm({
8051
8051
  }
8052
8052
  continue;
8053
8053
  }
8054
- const delivered = queuedCommandPrompt(obj);
8054
+ const delivered = queuedCommandPrompt(obj2);
8055
8055
  if (delivered) {
8056
8056
  const text = stripReminders(delivered.text);
8057
8057
  if (text && delivered.origin === "human")
8058
8058
  pushPrompt({ kind: "user", ts, tsIso, line: lineNum, text });
8059
8059
  continue;
8060
8060
  }
8061
- if (obj.type === "user") {
8062
- const msg = obj.message;
8061
+ if (obj2.type === "user") {
8062
+ const msg = obj2.message;
8063
8063
  const content = msg?.content;
8064
8064
  let text = "";
8065
8065
  const toolResults = [];
@@ -8092,7 +8092,7 @@ var init_claude = __esm({
8092
8092
  }
8093
8093
  }
8094
8094
  const spoken = stripReminders(text);
8095
- if (spoken && userRecordOrigin(obj, spoken) === "human") {
8095
+ if (spoken && userRecordOrigin(obj2, spoken) === "human") {
8096
8096
  pushPrompt({ kind: "user", ts, tsIso, line: lineNum, text: spoken });
8097
8097
  }
8098
8098
  for (const tr of toolResults) {
@@ -8108,13 +8108,13 @@ var init_claude = __esm({
8108
8108
  resultBytes: tr.body.length
8109
8109
  });
8110
8110
  }
8111
- } else if (obj.type === "summary") {
8112
- const summary = typeof obj.summary === "string" ? obj.summary : "";
8111
+ } else if (obj2.type === "summary") {
8112
+ const summary = typeof obj2.summary === "string" ? obj2.summary : "";
8113
8113
  if (summary) {
8114
8114
  events.push({ kind: "summary", ts, tsIso, line: lineNum, text: summary });
8115
8115
  }
8116
- } else if (obj.type === "assistant") {
8117
- const msg = obj.message;
8116
+ } else if (obj2.type === "assistant") {
8117
+ const msg = obj2.message;
8118
8118
  const content = msg?.content;
8119
8119
  if (!Array.isArray(content))
8120
8120
  continue;
@@ -8592,9 +8592,9 @@ function readCwdFromJsonl(sessionPath) {
8592
8592
  if (!line || !line.includes('"cwd"'))
8593
8593
  continue;
8594
8594
  try {
8595
- const obj = JSON.parse(line);
8596
- if (typeof obj.cwd === "string" && obj.cwd)
8597
- return obj.cwd;
8595
+ const obj2 = JSON.parse(line);
8596
+ if (typeof obj2.cwd === "string" && obj2.cwd)
8597
+ return obj2.cwd;
8598
8598
  } catch {
8599
8599
  }
8600
8600
  }
@@ -8676,25 +8676,25 @@ async function parseSessionFile(sessionPath, maxMessages = 50) {
8676
8676
  lineNum++;
8677
8677
  if (!line.trim())
8678
8678
  continue;
8679
- let obj;
8679
+ let obj2;
8680
8680
  try {
8681
- obj = JSON.parse(line);
8681
+ obj2 = JSON.parse(line);
8682
8682
  } catch {
8683
8683
  continue;
8684
8684
  }
8685
8685
  try {
8686
- const msgType = obj.type;
8687
- if (!content.metadata.gitBranch && obj.gitBranch) {
8688
- content.metadata.gitBranch = obj.gitBranch;
8686
+ const msgType = obj2.type;
8687
+ if (!content.metadata.gitBranch && obj2.gitBranch) {
8688
+ content.metadata.gitBranch = obj2.gitBranch;
8689
8689
  }
8690
- if (!content.metadata.slug && obj.slug) {
8691
- content.metadata.slug = obj.slug;
8690
+ if (!content.metadata.slug && obj2.slug) {
8691
+ content.metadata.slug = obj2.slug;
8692
8692
  }
8693
- if (msgType === "system" && obj.subtype === "turn_duration" && obj.durationMs) {
8694
- content.metadata.durationMs += obj.durationMs;
8693
+ if (msgType === "system" && obj2.subtype === "turn_duration" && obj2.durationMs) {
8694
+ content.metadata.durationMs += obj2.durationMs;
8695
8695
  }
8696
8696
  if (msgType === "file-history-snapshot") {
8697
- const snapshot2 = obj.snapshot;
8697
+ const snapshot2 = obj2.snapshot;
8698
8698
  if (snapshot2 && typeof snapshot2 === "object") {
8699
8699
  const backups = snapshot2.trackedFileBackups;
8700
8700
  if (backups && typeof backups === "object") {
@@ -8705,14 +8705,14 @@ async function parseSessionFile(sessionPath, maxMessages = 50) {
8705
8705
  }
8706
8706
  }
8707
8707
  if (msgType === "summary") {
8708
- const summary = obj.summary;
8708
+ const summary = obj2.summary;
8709
8709
  if (summary) {
8710
8710
  content.summaries.push(summary);
8711
8711
  }
8712
8712
  } else if (msgType === "user") {
8713
8713
  if (userCount >= maxMessages)
8714
8714
  continue;
8715
- const msg = obj.message;
8715
+ const msg = obj2.message;
8716
8716
  let text = "";
8717
8717
  if (msg && typeof msg === "object") {
8718
8718
  const msgContent = msg.content;
@@ -8741,18 +8741,18 @@ async function parseSessionFile(sessionPath, maxMessages = 50) {
8741
8741
  text = textParts.join("\n");
8742
8742
  }
8743
8743
  }
8744
- if (text && userRecordOrigin(obj, text) === "human")
8744
+ if (text && userRecordOrigin(obj2, text) === "human")
8745
8745
  recordPrompt(text, lineNum);
8746
8746
  } else if (msgType === "queue-operation") {
8747
- if (obj.operation === "enqueue" && typeof obj.content === "string" && originFromText(obj.content) === "human") {
8748
- recordPrompt(obj.content, lineNum, "enqueue");
8747
+ if (obj2.operation === "enqueue" && typeof obj2.content === "string" && originFromText(obj2.content) === "human") {
8748
+ recordPrompt(obj2.content, lineNum, "enqueue");
8749
8749
  }
8750
8750
  } else if (msgType === "attachment") {
8751
- const queued = queuedCommandPrompt(obj);
8751
+ const queued = queuedCommandPrompt(obj2);
8752
8752
  if (queued?.origin === "human")
8753
8753
  recordPrompt(queued.text, lineNum, "delivery");
8754
8754
  } else if (msgType === "assistant") {
8755
- const msg = obj.message;
8755
+ const msg = obj2.message;
8756
8756
  if (!msg || typeof msg !== "object")
8757
8757
  continue;
8758
8758
  if (msg.model && typeof msg.model === "string") {
@@ -8818,7 +8818,7 @@ async function parseSessionFile(sessionPath, maxMessages = 50) {
8818
8818
  }
8819
8819
  }
8820
8820
  }
8821
- const toolResult = obj.toolUseResult;
8821
+ const toolResult = obj2.toolUseResult;
8822
8822
  if (toolResult && typeof toolResult === "object" && toolCount < maxMessages) {
8823
8823
  const resultText2 = toolResult.result;
8824
8824
  const query = toolResult.query;
@@ -8910,10 +8910,10 @@ async function parseMessagesFromFile(sessionPath) {
8910
8910
  }
8911
8911
  function messagesFromRawLines(raw) {
8912
8912
  const toolResults = /* @__PURE__ */ new Map();
8913
- for (const { obj } of raw) {
8914
- if (obj?.type !== "user")
8913
+ for (const { obj: obj2 } of raw) {
8914
+ if (obj2?.type !== "user")
8915
8915
  continue;
8916
- const content = obj.message?.content;
8916
+ const content = obj2.message?.content;
8917
8917
  if (!Array.isArray(content))
8918
8918
  continue;
8919
8919
  for (const block of content) {
@@ -8926,12 +8926,12 @@ function messagesFromRawLines(raw) {
8926
8926
  }
8927
8927
  }
8928
8928
  const messages = [];
8929
- for (const { line, obj } of raw) {
8930
- if (!obj || typeof obj !== "object")
8929
+ for (const { line, obj: obj2 } of raw) {
8930
+ if (!obj2 || typeof obj2 !== "object")
8931
8931
  continue;
8932
- const timestamp = typeof obj.timestamp === "string" ? obj.timestamp : void 0;
8933
- if (obj.type === "user") {
8934
- const content = obj.message?.content;
8932
+ const timestamp = typeof obj2.timestamp === "string" ? obj2.timestamp : void 0;
8933
+ if (obj2.type === "user") {
8934
+ const content = obj2.message?.content;
8935
8935
  let text = "";
8936
8936
  if (typeof content === "string") {
8937
8937
  text = content;
@@ -8943,18 +8943,18 @@ function messagesFromRawLines(raw) {
8943
8943
  const cleaned = stripBanners2(text);
8944
8944
  if (!cleaned)
8945
8945
  continue;
8946
- const origin = userRecordOrigin(obj, cleaned);
8946
+ const origin = userRecordOrigin(obj2, cleaned);
8947
8947
  messages.push({ line, role: "user", content: cleaned, timestamp, ...origin === "human" ? {} : { origin } });
8948
- } else if (obj.type === "attachment") {
8949
- const queued = queuedCommandPrompt(obj);
8948
+ } else if (obj2.type === "attachment") {
8949
+ const queued = queuedCommandPrompt(obj2);
8950
8950
  if (!queued)
8951
8951
  continue;
8952
8952
  const cleaned = stripBanners2(queued.text);
8953
8953
  if (!cleaned)
8954
8954
  continue;
8955
8955
  messages.push({ line, role: "user", content: cleaned, timestamp, ...queued.origin === "human" ? {} : { origin: queued.origin } });
8956
- } else if (obj.type === "assistant") {
8957
- const blocks = Array.isArray(obj.message?.content) ? obj.message.content : [];
8956
+ } else if (obj2.type === "assistant") {
8957
+ const blocks = Array.isArray(obj2.message?.content) ? obj2.message.content : [];
8958
8958
  const thinkingBlock = blocks.find((c) => c?.type === "thinking");
8959
8959
  const textBlock = blocks.find((c) => c?.type === "text");
8960
8960
  const toolUses = blocks.filter((c) => c?.type === "tool_use");
@@ -8980,10 +8980,10 @@ function messagesFromRawLines(raw) {
8980
8980
  toolCalls: toolCalls.length > 0 ? toolCalls : void 0,
8981
8981
  timestamp
8982
8982
  });
8983
- } else if (obj.type === "summary" && typeof obj.summary === "string") {
8984
- messages.push({ line, role: "summary", content: obj.summary });
8985
- } else if (obj.type === "system" && obj.subtype === "away_summary") {
8986
- const c = obj.content;
8983
+ } else if (obj2.type === "summary" && typeof obj2.summary === "string") {
8984
+ messages.push({ line, role: "summary", content: obj2.summary });
8985
+ } else if (obj2.type === "system" && obj2.subtype === "away_summary") {
8986
+ const c = obj2.content;
8987
8987
  const text = typeof c === "string" ? c : Array.isArray(c) ? c.filter((b) => b?.type === "text" && typeof b.text === "string").map((b) => b.text).join("\n") : "";
8988
8988
  if (text.trim())
8989
8989
  messages.push({ line, role: "summary", content: stripBanners2(text), timestamp });
@@ -9181,31 +9181,31 @@ function parseCodexTranscriptText(text) {
9181
9181
  if (!line.trim())
9182
9182
  continue;
9183
9183
  try {
9184
- const obj = JSON.parse(line);
9185
- if (obj.type === "event_msg" && obj.payload?.type === "user_message") {
9186
- const text2 = String(obj.payload.message || "").trim();
9184
+ const obj2 = JSON.parse(line);
9185
+ if (obj2.type === "event_msg" && obj2.payload?.type === "user_message") {
9186
+ const text2 = String(obj2.payload.message || "").trim();
9187
9187
  if (!text2 || isCodexInjectedWrapper(text2))
9188
9188
  continue;
9189
9189
  messages.push({
9190
9190
  line: lineNum,
9191
9191
  role: "user",
9192
9192
  content: text2,
9193
- timestamp: obj.timestamp
9193
+ timestamp: obj2.timestamp
9194
9194
  });
9195
- } else if (obj.type === "response_item" && obj.payload?.type === "message") {
9196
- if (obj.payload.role !== "assistant")
9195
+ } else if (obj2.type === "response_item" && obj2.payload?.type === "message") {
9196
+ if (obj2.payload.role !== "assistant")
9197
9197
  continue;
9198
- const text2 = flattenCodexContent(obj.payload.content);
9198
+ const text2 = flattenCodexContent(obj2.payload.content);
9199
9199
  if (!text2.trim())
9200
9200
  continue;
9201
9201
  messages.push({
9202
9202
  line: lineNum,
9203
9203
  role: "assistant",
9204
9204
  content: text2,
9205
- timestamp: obj.timestamp
9205
+ timestamp: obj2.timestamp
9206
9206
  });
9207
- } else if (obj.type === "response_item" && obj.payload?.type === "reasoning") {
9208
- const summary = Array.isArray(obj.payload.summary) ? obj.payload.summary.map((s) => s?.text || "").filter(Boolean).join("\n") : "";
9207
+ } else if (obj2.type === "response_item" && obj2.payload?.type === "reasoning") {
9208
+ const summary = Array.isArray(obj2.payload.summary) ? obj2.payload.summary.map((s) => s?.text || "").filter(Boolean).join("\n") : "";
9209
9209
  if (!summary.trim())
9210
9210
  continue;
9211
9211
  messages.push({
@@ -9213,10 +9213,10 @@ function parseCodexTranscriptText(text) {
9213
9213
  role: "assistant",
9214
9214
  content: "",
9215
9215
  thinking: summary,
9216
- timestamp: obj.timestamp
9216
+ timestamp: obj2.timestamp
9217
9217
  });
9218
- } else if (obj.type === "response_item" && obj.payload?.type === "function_call") {
9219
- let input = obj.payload.arguments || {};
9218
+ } else if (obj2.type === "response_item" && obj2.payload?.type === "function_call") {
9219
+ let input = obj2.payload.arguments || {};
9220
9220
  if (typeof input === "string") {
9221
9221
  try {
9222
9222
  input = JSON.parse(input);
@@ -9227,8 +9227,8 @@ function parseCodexTranscriptText(text) {
9227
9227
  line: lineNum,
9228
9228
  role: "assistant",
9229
9229
  content: "",
9230
- toolCalls: [{ name: obj.payload.name || "", input }],
9231
- timestamp: obj.timestamp
9230
+ toolCalls: [{ name: obj2.payload.name || "", input }],
9231
+ timestamp: obj2.timestamp
9232
9232
  });
9233
9233
  }
9234
9234
  } catch {
@@ -9502,19 +9502,19 @@ function mapJsonStrings(line, fn, escapedOnly) {
9502
9502
  const q = line.indexOf('"', i);
9503
9503
  if (q < 0)
9504
9504
  return out + line.slice(i);
9505
- let j = q + 1;
9506
- while (j < line.length) {
9507
- const c = line.charCodeAt(j);
9505
+ let j2 = q + 1;
9506
+ while (j2 < line.length) {
9507
+ const c = line.charCodeAt(j2);
9508
9508
  if (c === 92)
9509
- j += 2;
9509
+ j2 += 2;
9510
9510
  else if (c === 34)
9511
9511
  break;
9512
9512
  else
9513
- j++;
9513
+ j2++;
9514
9514
  }
9515
- const token = line.slice(q, j + 1);
9515
+ const token = line.slice(q, j2 + 1);
9516
9516
  out += line.slice(i, q);
9517
- i = j + 1;
9517
+ i = j2 + 1;
9518
9518
  const body2 = token.slice(1, -1);
9519
9519
  const escaped = body2.includes("\\");
9520
9520
  if (escapedOnly && !escaped) {
@@ -9673,7 +9673,7 @@ async function archiveRawSession(store, sessionId) {
9673
9673
  }
9674
9674
  function detectForkPredecessor(sessionPath) {
9675
9675
  const { readFileSync: readFileSync54, readdirSync: readdirSync36 } = requireFs();
9676
- const { dirname: dirname30, join: join67, basename: basename30 } = requirePath();
9676
+ const { dirname: dirname30, join: join68, basename: basename30 } = requirePath();
9677
9677
  let text;
9678
9678
  try {
9679
9679
  text = readFileSync54(sessionPath, "utf-8");
@@ -9710,7 +9710,7 @@ function detectForkPredecessor(sessionPath) {
9710
9710
  if (!f.endsWith(".jsonl") || f === self || f === "sessions-index.json")
9711
9711
  continue;
9712
9712
  try {
9713
- if (readFileSync54(join67(dir, f), "utf-8").includes(`"uuid":"${headParent}"`)) {
9713
+ if (readFileSync54(join68(dir, f), "utf-8").includes(`"uuid":"${headParent}"`)) {
9714
9714
  return basename30(f, ".jsonl");
9715
9715
  }
9716
9716
  } catch {
@@ -9785,6 +9785,130 @@ var init_sqlite_reader = __esm({
9785
9785
  }
9786
9786
  });
9787
9787
 
9788
+ // ../engine/dist/core/backends/opencode-v2.js
9789
+ function hasTable(db, name) {
9790
+ return !!db.prepare("SELECT 1 FROM main.sqlite_master WHERE type = 'table' AND name = ?").get(name);
9791
+ }
9792
+ function columnsOf(db, table) {
9793
+ return new Set(db.prepare(`SELECT name FROM pragma_table_info('${table}', 'main')`).all().map((r) => r.name));
9794
+ }
9795
+ function installOpencodeV2Views(db) {
9796
+ if (!hasTable(db, "session_v2") || !hasTable(db, "session_message"))
9797
+ return false;
9798
+ const v2Cols = columnsOf(db, "session_v2");
9799
+ const sessionCols = SESSION_COLUMNS.map((c) => v2Cols.has(c) ? c : `NULL AS ${c}`).join(", ");
9800
+ const hasV1 = hasTable(db, "message") && hasTable(db, "part");
9801
+ const v1Messages = hasV1 ? `SELECT id, session_id, time_created, time_updated, data FROM main.message WHERE session_id NOT IN (${V2_SESSIONS}) UNION ALL ` : "";
9802
+ const v1Parts = hasV1 ? `SELECT id, message_id, session_id, time_created, time_updated, data FROM main.part WHERE session_id NOT IN (${V2_SESSIONS}) UNION ALL ` : "";
9803
+ db.exec(`
9804
+ CREATE TEMP VIEW IF NOT EXISTS session AS SELECT ${sessionCols} FROM main.session_v2;
9805
+
9806
+ CREATE TEMP VIEW IF NOT EXISTS message AS
9807
+ ${v1Messages}
9808
+ SELECT m.id, m.session_id, m.time_created, m.time_updated,
9809
+ CASE m.type
9810
+ WHEN 'user' THEN json_object('role', 'user', 'time', ${j("$.time")})
9811
+ ELSE json_object(
9812
+ 'role', 'assistant',
9813
+ 'agent', json_extract(m.data, '$.agent'),
9814
+ 'modelID', json_extract(m.data, '$.model.id'),
9815
+ 'providerID', json_extract(m.data, '$.model.providerID'),
9816
+ 'cost', coalesce(json_extract(m.data, '$.cost'), 0),
9817
+ 'tokens', ${j("$.tokens")},
9818
+ 'time', ${j("$.time")})
9819
+ END AS data
9820
+ FROM main.session_message m WHERE m.type IN ('user', 'assistant');
9821
+
9822
+ CREATE TEMP VIEW IF NOT EXISTS part AS
9823
+ ${v1Parts}
9824
+ SELECT m.id || ':text', m.id, m.session_id, m.time_created, m.time_updated,
9825
+ json_object('type', 'text', 'text', json_extract(m.data, '$.text'))
9826
+ FROM main.session_message m
9827
+ WHERE m.type = 'user' AND json_extract(m.data, '$.text') IS NOT NULL
9828
+ UNION ALL
9829
+ SELECT m.id || ':' || c.key, m.id, m.session_id, m.time_created + c.key, m.time_updated,
9830
+ CASE json_extract(c.value, '$.type')
9831
+ WHEN 'tool' THEN json_object(
9832
+ 'type', 'tool',
9833
+ 'tool', json_extract(c.value, '$.name'),
9834
+ 'callID', json_extract(c.value, '$.id'),
9835
+ 'state', json_object(
9836
+ 'status', json_extract(c.value, '$.state.status'),
9837
+ 'input', json(coalesce(json_extract(c.value, '$.state.input'), '{}')),
9838
+ 'output', (SELECT group_concat(json_extract(o.value, '$.text'), char(10))
9839
+ FROM json_each(c.value, '$.state.content') o
9840
+ WHERE json_extract(o.value, '$.type') = 'text')))
9841
+ ELSE json_object('type', json_extract(c.value, '$.type'), 'text', json_extract(c.value, '$.text'))
9842
+ END
9843
+ FROM main.session_message m, json_each(m.data, '$.content') c
9844
+ WHERE m.type = 'assistant'
9845
+ UNION ALL
9846
+ SELECT m.id || ':step', m.id, m.session_id,
9847
+ coalesce(json_extract(m.data, '$.time.completed'), m.time_created), m.time_updated,
9848
+ json_object('type', 'step-finish', 'cost', coalesce(json_extract(m.data, '$.cost'), 0), 'tokens', ${j("$.tokens")})
9849
+ FROM main.session_message m WHERE m.type = 'assistant';
9850
+ `);
9851
+ return true;
9852
+ }
9853
+ function openOpencodeDb(path) {
9854
+ const db = openSqliteReadonly(path);
9855
+ if (!db)
9856
+ return null;
9857
+ try {
9858
+ installOpencodeV2Views(db);
9859
+ } catch {
9860
+ }
9861
+ return db;
9862
+ }
9863
+ function openOpencodeDbOrThrow(path) {
9864
+ const db = openSqliteReadonlyOrThrow(path);
9865
+ try {
9866
+ installOpencodeV2Views(db);
9867
+ } catch {
9868
+ }
9869
+ return db;
9870
+ }
9871
+ var SESSION_COLUMNS, j, V2_SESSIONS;
9872
+ var init_opencode_v2 = __esm({
9873
+ "../engine/dist/core/backends/opencode-v2.js"() {
9874
+ "use strict";
9875
+ init_sqlite_reader();
9876
+ SESSION_COLUMNS = [
9877
+ "id",
9878
+ "project_id",
9879
+ "parent_id",
9880
+ "slug",
9881
+ "directory",
9882
+ "title",
9883
+ "version",
9884
+ "share_url",
9885
+ "summary_additions",
9886
+ "summary_deletions",
9887
+ "summary_files",
9888
+ "summary_diffs",
9889
+ "revert",
9890
+ "permission",
9891
+ "time_created",
9892
+ "time_updated",
9893
+ "time_compacting",
9894
+ "time_archived",
9895
+ "workspace_id",
9896
+ "path",
9897
+ "agent",
9898
+ "model",
9899
+ "cost",
9900
+ "tokens_input",
9901
+ "tokens_output",
9902
+ "tokens_reasoning",
9903
+ "tokens_cache_read",
9904
+ "tokens_cache_write",
9905
+ "metadata"
9906
+ ];
9907
+ j = (path, fallback = "'{}'") => `json(coalesce(json_extract(m.data, '${path}'), ${fallback}))`;
9908
+ V2_SESSIONS = "SELECT session_id FROM main.session_message";
9909
+ }
9910
+ });
9911
+
9788
9912
  // ../engine/dist/core/backends/opencode.js
9789
9913
  var opencode_exports = {};
9790
9914
  __export(opencode_exports, {
@@ -9795,13 +9919,13 @@ import { existsSync as existsSync11 } from "fs";
9795
9919
  import { homedir as homedir5 } from "os";
9796
9920
  import { dirname as dirname9, join as join12 } from "path";
9797
9921
  function openReadonly(path) {
9798
- return openSqliteReadonly(path);
9922
+ return openOpencodeDb(path);
9799
9923
  }
9800
9924
  var PREFIX, OpencodeBackend, opencodeBackend;
9801
9925
  var init_opencode = __esm({
9802
9926
  "../engine/dist/core/backends/opencode.js"() {
9803
9927
  "use strict";
9804
- init_sqlite_reader();
9928
+ init_opencode_v2();
9805
9929
  init_tool_paths();
9806
9930
  init_session_outcome();
9807
9931
  init_session_git();
@@ -10092,9 +10216,9 @@ var init_opencode = __esm({
10092
10216
  return [];
10093
10217
  const parts = db.prepare(`
10094
10218
  SELECT p.id, p.message_id, p.time_created, p.data, m.data AS msg_data
10095
- FROM part p JOIN message m ON m.id = p.message_id
10219
+ FROM part p JOIN (SELECT id, data FROM message WHERE session_id = ?) m ON m.id = p.message_id
10096
10220
  WHERE p.session_id = ? ORDER BY p.time_created ASC
10097
- `).all(ocId);
10221
+ `).all(ocId, ocId);
10098
10222
  const events = [];
10099
10223
  let lineNum = 0;
10100
10224
  for (const p of parts) {
@@ -10310,17 +10434,17 @@ var init_opencode = __esm({
10310
10434
  if (!existsSync11(dbPath))
10311
10435
  return null;
10312
10436
  const realId = this.toRawId(id);
10313
- const db = openSqliteReadonlyOrThrow(dbPath);
10437
+ const db = openOpencodeDbOrThrow(dbPath);
10314
10438
  try {
10315
10439
  const session = db.prepare(`SELECT * FROM session WHERE id = ?`).get(realId);
10316
10440
  if (!session)
10317
10441
  return null;
10318
10442
  const rows = db.prepare(`
10319
10443
  SELECT m.id AS message_id, m.data AS message_data, p.id AS part_id, p.data AS part_data, p.time_created
10320
- FROM part p JOIN message m ON p.message_id = m.id
10444
+ FROM part p JOIN (SELECT id, data FROM message WHERE session_id = ?) m ON p.message_id = m.id
10321
10445
  WHERE p.session_id = ?
10322
10446
  ORDER BY p.time_created ASC, p.id ASC
10323
- `).all(realId);
10447
+ `).all(realId, realId);
10324
10448
  const lines = [JSON.stringify({ kind: "session", row: session })];
10325
10449
  for (const r of rows)
10326
10450
  lines.push(JSON.stringify({ kind: "part", row: r }));
@@ -10804,30 +10928,30 @@ var init_codex2 = __esm({
10804
10928
  lineNum++;
10805
10929
  if (!line.trim())
10806
10930
  continue;
10807
- let obj;
10931
+ let obj2;
10808
10932
  try {
10809
- obj = JSON.parse(line);
10933
+ obj2 = JSON.parse(line);
10810
10934
  } catch {
10811
10935
  continue;
10812
10936
  }
10813
- const tsIso = typeof obj.timestamp === "string" ? obj.timestamp : void 0;
10937
+ const tsIso = typeof obj2.timestamp === "string" ? obj2.timestamp : void 0;
10814
10938
  const ts = tsIso ? Date.parse(tsIso) || mtime : mtime;
10815
- const payload = obj.payload || {};
10816
- if (obj.type === "event_msg" && payload.type === "user_message") {
10939
+ const payload = obj2.payload || {};
10940
+ if (obj2.type === "event_msg" && payload.type === "user_message") {
10817
10941
  const text = String(payload.message || "").trim();
10818
10942
  if (text && !isCodexInjectedWrapper2(text)) {
10819
10943
  events.push({ kind: "user", ts, tsIso, line: lineNum, text });
10820
10944
  }
10821
- } else if (obj.type === "response_item" && payload.type === "message" && payload.role === "user") {
10945
+ } else if (obj2.type === "response_item" && payload.type === "message" && payload.role === "user") {
10822
10946
  const text = flattenContent(payload.content).trim();
10823
10947
  if (text && !isCodexInjectedWrapper2(text)) {
10824
10948
  events.push({ kind: "user", ts, tsIso, line: lineNum, text });
10825
10949
  }
10826
- } else if (obj.type === "response_item" && payload.type === "message" && payload.role === "assistant") {
10950
+ } else if (obj2.type === "response_item" && payload.type === "message" && payload.role === "assistant") {
10827
10951
  const text = flattenContent(payload.content).trim();
10828
10952
  if (text)
10829
10953
  events.push({ kind: "assistant_text", ts, tsIso, line: lineNum, text });
10830
- } else if (obj.type === "response_item" && payload.type === "function_call") {
10954
+ } else if (obj2.type === "response_item" && payload.type === "function_call") {
10831
10955
  const toolName = String(payload.name || "");
10832
10956
  const callId = String(payload.call_id || "");
10833
10957
  let args = payload.arguments;
@@ -10851,7 +10975,7 @@ var init_codex2 = __esm({
10851
10975
  toolInput: args,
10852
10976
  command
10853
10977
  });
10854
- } else if (obj.type === "response_item" && payload.type === "function_call_output") {
10978
+ } else if (obj2.type === "response_item" && payload.type === "function_call_output") {
10855
10979
  const callId = String(payload.call_id || "");
10856
10980
  const out = payload.output;
10857
10981
  let body2 = "";
@@ -11111,14 +11235,14 @@ function extractProjectPathFromTranscript(path, homeDir) {
11111
11235
  for (const line of content.split("\n")) {
11112
11236
  if (!line.trim())
11113
11237
  continue;
11114
- let obj;
11238
+ let obj2;
11115
11239
  try {
11116
- obj = JSON.parse(line);
11240
+ obj2 = JSON.parse(line);
11117
11241
  } catch {
11118
11242
  continue;
11119
11243
  }
11120
- if (obj.source === "USER_EXPLICIT" && obj.type === "USER_INPUT" && typeof obj.content === "string") {
11121
- const match = obj.content.match(/format\s+\[URI\]\s*->\s*\[CorpusName\]:\s*\n?\s*([^\s\n]+)\s*->/);
11244
+ if (obj2.source === "USER_EXPLICIT" && obj2.type === "USER_INPUT" && typeof obj2.content === "string") {
11245
+ const match = obj2.content.match(/format\s+\[URI\]\s*->\s*\[CorpusName\]:\s*\n?\s*([^\s\n]+)\s*->/);
11122
11246
  if (match && match[1])
11123
11247
  return match[1].trim();
11124
11248
  }
@@ -11236,6 +11360,10 @@ var init_agy = __esm({
11236
11360
  sharedSettingsFile() {
11237
11361
  return join14(this.sharedRootDir(), "settings.json");
11238
11362
  }
11363
+ /** The global hooks file the CLI reads. It does not read hooks from its own home directory. */
11364
+ sharedHooksFile() {
11365
+ return join14(this.sharedRootDir(), "config", "hooks.json");
11366
+ }
11239
11367
  sharedProjectsJson() {
11240
11368
  return join14(this.sharedRootDir(), "projects.json");
11241
11369
  }
@@ -11332,9 +11460,9 @@ var init_agy = __esm({
11332
11460
  const lines = readFileSync7(filePath, "utf-8").split("\n").filter(Boolean);
11333
11461
  messageCount = lines.length;
11334
11462
  for (const line of lines) {
11335
- const obj = JSON.parse(line);
11336
- if (obj.source === "USER_EXPLICIT" && obj.type === "USER_INPUT" && typeof obj.content === "string") {
11337
- const content = obj.content;
11463
+ const obj2 = JSON.parse(line);
11464
+ if (obj2.source === "USER_EXPLICIT" && obj2.type === "USER_INPUT" && typeof obj2.content === "string") {
11465
+ const content = obj2.content;
11338
11466
  const match = content.match(/<USER_REQUEST>([\s\S]*?)<\/USER_REQUEST>/);
11339
11467
  const rawText = match ? match[1].trim() : content.trim();
11340
11468
  firstPrompt = flatString(rawText.slice(0, 200));
@@ -11443,27 +11571,27 @@ var init_agy = __esm({
11443
11571
  lineNum++;
11444
11572
  if (!line.trim())
11445
11573
  continue;
11446
- let obj;
11574
+ let obj2;
11447
11575
  try {
11448
- obj = JSON.parse(line);
11576
+ obj2 = JSON.parse(line);
11449
11577
  } catch {
11450
11578
  continue;
11451
11579
  }
11452
- const tsIso = typeof obj.created_at === "string" ? obj.created_at : void 0;
11580
+ const tsIso = typeof obj2.created_at === "string" ? obj2.created_at : void 0;
11453
11581
  const ts = tsIso ? Date.parse(tsIso) || mtimeFallback : mtimeFallback;
11454
- if (obj.source === "USER_EXPLICIT" && obj.type === "USER_INPUT") {
11455
- const content = typeof obj.content === "string" ? obj.content : "";
11582
+ if (obj2.source === "USER_EXPLICIT" && obj2.type === "USER_INPUT") {
11583
+ const content = typeof obj2.content === "string" ? obj2.content : "";
11456
11584
  const match = content.match(/<USER_REQUEST>([\s\S]*?)<\/USER_REQUEST>/);
11457
11585
  const text = match ? match[1].trim() : content.trim();
11458
11586
  if (text) {
11459
11587
  events.push({ kind: "user", ts, tsIso, line: lineNum, text });
11460
11588
  }
11461
- } else if (obj.source === "MODEL" && obj.type === "PLANNER_RESPONSE") {
11462
- const content = typeof obj.content === "string" ? obj.content.trim() : "";
11589
+ } else if (obj2.source === "MODEL" && obj2.type === "PLANNER_RESPONSE") {
11590
+ const content = typeof obj2.content === "string" ? obj2.content.trim() : "";
11463
11591
  if (content) {
11464
11592
  events.push({ kind: "assistant_text", ts, tsIso, line: lineNum, text: content });
11465
11593
  }
11466
- const tcs = Array.isArray(obj.tool_calls) ? obj.tool_calls : [];
11594
+ const tcs = Array.isArray(obj2.tool_calls) ? obj2.tool_calls : [];
11467
11595
  for (const tc of tcs) {
11468
11596
  let toolName = String(tc?.name || "");
11469
11597
  if (!toolName)
@@ -11491,12 +11619,12 @@ var init_agy = __esm({
11491
11619
  command
11492
11620
  });
11493
11621
  }
11494
- } else if (obj.source === "MODEL" && obj.type !== "PLANNER_RESPONSE") {
11495
- const resultBody = typeof obj.content === "string" ? obj.content : "";
11496
- const isError = obj.status === "ERROR" || obj.status === "FAILED";
11622
+ } else if (obj2.source === "MODEL" && obj2.type !== "PLANNER_RESPONSE") {
11623
+ const resultBody = typeof obj2.content === "string" ? obj2.content : "";
11624
+ const isError = obj2.status === "ERROR" || obj2.status === "FAILED";
11497
11625
  let matchedIndex = -1;
11498
11626
  for (let i = 0; i < pendingToolCalls.length; i++) {
11499
- if (matchesTool(obj.type, pendingToolCalls[i].name)) {
11627
+ if (matchesTool(obj2.type, pendingToolCalls[i].name)) {
11500
11628
  matchedIndex = i;
11501
11629
  break;
11502
11630
  }
@@ -11514,7 +11642,7 @@ var init_agy = __esm({
11514
11642
  toolName = popped.name;
11515
11643
  } else {
11516
11644
  toolUseId = `agy_tc_orphan_${toolUseCounter++}`;
11517
- toolName = obj.type.toLowerCase();
11645
+ toolName = obj2.type.toLowerCase();
11518
11646
  }
11519
11647
  }
11520
11648
  events.push({
@@ -11985,22 +12113,22 @@ function readTranscriptEvents(rawText, mtimeFallback = 0) {
11985
12113
  lineNum++;
11986
12114
  if (!line.trim())
11987
12115
  continue;
11988
- let obj;
12116
+ let obj2;
11989
12117
  try {
11990
- obj = JSON.parse(line);
12118
+ obj2 = JSON.parse(line);
11991
12119
  } catch {
11992
12120
  continue;
11993
12121
  }
11994
- if (!obj.role)
12122
+ if (!obj2.role)
11995
12123
  continue;
11996
- const message = obj.message;
12124
+ const message = obj2.message;
11997
12125
  const content = Array.isArray(message?.content) ? message.content : [];
11998
12126
  for (const part of content) {
11999
12127
  if (!part || typeof part !== "object")
12000
12128
  continue;
12001
12129
  const p = part;
12002
12130
  if (p.type === "text" && typeof p.text === "string") {
12003
- if (obj.role === "user") {
12131
+ if (obj2.role === "user") {
12004
12132
  const { text, ts } = unwrapUserText(p.text);
12005
12133
  if (ts)
12006
12134
  clock = ts;
@@ -14085,19 +14213,19 @@ function parsePiFile(path) {
14085
14213
  for (const line of raw.split("\n")) {
14086
14214
  if (!line.trim())
14087
14215
  continue;
14088
- let obj;
14216
+ let obj2;
14089
14217
  try {
14090
- obj = JSON.parse(line);
14218
+ obj2 = JSON.parse(line);
14091
14219
  } catch {
14092
14220
  continue;
14093
14221
  }
14094
- if (!obj || typeof obj !== "object")
14222
+ if (!obj2 || typeof obj2 !== "object")
14095
14223
  continue;
14096
- if (obj.type === "session" && !out.header) {
14097
- out.header = obj;
14224
+ if (obj2.type === "session" && !out.header) {
14225
+ out.header = obj2;
14098
14226
  continue;
14099
14227
  }
14100
- out.entries.push(obj);
14228
+ out.entries.push(obj2);
14101
14229
  }
14102
14230
  return out;
14103
14231
  }
@@ -14139,10 +14267,10 @@ function readPiHeader(path) {
14139
14267
  const firstLine = buf.toString("utf-8", 0, n).split("\n", 1)[0];
14140
14268
  if (!firstLine.trim())
14141
14269
  return null;
14142
- const obj = JSON.parse(firstLine);
14143
- if (!obj || typeof obj !== "object" || obj.type !== "session")
14270
+ const obj2 = JSON.parse(firstLine);
14271
+ if (!obj2 || typeof obj2 !== "object" || obj2.type !== "session")
14144
14272
  return null;
14145
- return obj;
14273
+ return obj2;
14146
14274
  } catch {
14147
14275
  return null;
14148
14276
  } finally {
@@ -14480,17 +14608,17 @@ var init_pi = __esm({
14480
14608
  lineNum++;
14481
14609
  if (!line.trim())
14482
14610
  continue;
14483
- let obj;
14611
+ let obj2;
14484
14612
  try {
14485
- obj = JSON.parse(line);
14613
+ obj2 = JSON.parse(line);
14486
14614
  } catch {
14487
14615
  continue;
14488
14616
  }
14489
- const tsIso = typeof obj.timestamp === "string" ? obj.timestamp : void 0;
14490
- const msgTs = typeof obj.message?.timestamp === "number" ? obj.message.timestamp : void 0;
14617
+ const tsIso = typeof obj2.timestamp === "string" ? obj2.timestamp : void 0;
14618
+ const msgTs = typeof obj2.message?.timestamp === "number" ? obj2.message.timestamp : void 0;
14491
14619
  const ts = tsIso ? Date.parse(tsIso) || mtimeFallback : msgTs ?? mtimeFallback;
14492
- if (obj.type === "message") {
14493
- const msg = obj.message || {};
14620
+ if (obj2.type === "message") {
14621
+ const msg = obj2.message || {};
14494
14622
  const role = msg.role;
14495
14623
  if (role === "user") {
14496
14624
  const text = piText(msg.content).trim();
@@ -14569,12 +14697,12 @@ var init_pi = __esm({
14569
14697
  }
14570
14698
  continue;
14571
14699
  }
14572
- if (obj.type === "compaction" && typeof obj.summary === "string" && obj.summary.trim()) {
14573
- events.push({ kind: "summary", ts, tsIso, line: lineNum, text: obj.summary.trim() });
14700
+ if (obj2.type === "compaction" && typeof obj2.summary === "string" && obj2.summary.trim()) {
14701
+ events.push({ kind: "summary", ts, tsIso, line: lineNum, text: obj2.summary.trim() });
14574
14702
  continue;
14575
14703
  }
14576
- if (obj.type === "branch_summary" && typeof obj.summary === "string" && obj.summary.trim()) {
14577
- events.push({ kind: "summary", ts, tsIso, line: lineNum, text: obj.summary.trim() });
14704
+ if (obj2.type === "branch_summary" && typeof obj2.summary === "string" && obj2.summary.trim()) {
14705
+ events.push({ kind: "summary", ts, tsIso, line: lineNum, text: obj2.summary.trim() });
14578
14706
  }
14579
14707
  }
14580
14708
  return events;
@@ -15488,19 +15616,19 @@ function runTrufflehog(binary, filePath, opts = {}) {
15488
15616
  if (!line.trim())
15489
15617
  continue;
15490
15618
  try {
15491
- const j = JSON.parse(line);
15492
- const raw = j.Raw || "";
15619
+ const j2 = JSON.parse(line);
15620
+ const raw = j2.Raw || "";
15493
15621
  if (looksLikeUuid(raw))
15494
15622
  continue;
15495
15623
  out.push({
15496
- rule: j.DetectorName || "unknown",
15497
- line: j.SourceMetadata?.Data?.Filesystem?.line || 0,
15624
+ rule: j2.DetectorName || "unknown",
15625
+ line: j2.SourceMetadata?.Data?.Filesystem?.line || 0,
15498
15626
  preview: mask(raw),
15499
15627
  // trufflehog reports `Verified: true` only when --verification
15500
15628
  // ran AND the call succeeded. With --only-verified set, every
15501
15629
  // returned finding is verified live by definition, so we tag
15502
15630
  // them all true; with --no-verification, leave undefined.
15503
- verified: opts.verifyOnly ? true : j.Verified === true ? true : void 0
15631
+ verified: opts.verifyOnly ? true : j2.Verified === true ? true : void 0
15504
15632
  });
15505
15633
  } catch {
15506
15634
  }
@@ -15553,16 +15681,16 @@ function runTrufflehogDir(binary, dir, opts = {}) {
15553
15681
  if (!line.trim())
15554
15682
  continue;
15555
15683
  try {
15556
- const j = JSON.parse(line);
15557
- const raw = j.Raw || "";
15684
+ const j2 = JSON.parse(line);
15685
+ const raw = j2.Raw || "";
15558
15686
  if (looksLikeUuid(raw))
15559
15687
  continue;
15560
15688
  out.push({
15561
- rule: j.DetectorName || "unknown",
15562
- line: j.SourceMetadata?.Data?.Filesystem?.line || 0,
15689
+ rule: j2.DetectorName || "unknown",
15690
+ line: j2.SourceMetadata?.Data?.Filesystem?.line || 0,
15563
15691
  preview: mask(raw),
15564
- verified: opts.verifyOnly ? true : j.Verified === true ? true : void 0,
15565
- file: j.SourceMetadata?.Data?.Filesystem?.file || ""
15692
+ verified: opts.verifyOnly ? true : j2.Verified === true ? true : void 0,
15693
+ file: j2.SourceMetadata?.Data?.Filesystem?.file || ""
15566
15694
  });
15567
15695
  } catch {
15568
15696
  }
@@ -15791,7 +15919,7 @@ async function parseOpenCodeSubagents(parentSessionId) {
15791
15919
  if (!existsSync61(dbPath))
15792
15920
  return [];
15793
15921
  const realParent = parentSessionId.replace("opencode_", "");
15794
- const db = openSqliteReadonlyOrThrow(dbPath);
15922
+ const db = openOpencodeDbOrThrow(dbPath);
15795
15923
  try {
15796
15924
  const children = db.prepare(`
15797
15925
  SELECT id, title, time_created
@@ -15835,16 +15963,16 @@ async function parseOpenCodeTranscript(sessionId) {
15835
15963
  if (!existsSync61(dbPath))
15836
15964
  return [];
15837
15965
  const realId = sessionId.replace("opencode_", "");
15838
- const db = openSqliteReadonlyOrThrow(dbPath);
15966
+ const db = openOpencodeDbOrThrow(dbPath);
15839
15967
  const messages = [];
15840
15968
  try {
15841
15969
  const parts = db.prepare(`
15842
15970
  SELECT p.data, p.time_created, m.data as msg_data
15843
15971
  FROM part p
15844
- JOIN message m ON p.message_id = m.id
15972
+ JOIN (SELECT id, data FROM message WHERE session_id = ?) m ON p.message_id = m.id
15845
15973
  WHERE p.session_id = ?
15846
15974
  ORDER BY p.time_created ASC
15847
- `).all(realId);
15975
+ `).all(realId, realId);
15848
15976
  let lineNum = 0;
15849
15977
  for (const part of parts) {
15850
15978
  try {
@@ -15875,7 +16003,7 @@ var log5;
15875
16003
  var init_opencode2 = __esm({
15876
16004
  "../engine/dist/transcript/opencode.js"() {
15877
16005
  "use strict";
15878
- init_sqlite_reader();
16006
+ init_opencode_v2();
15879
16007
  init_logger();
15880
16008
  log5 = createLogger("transcript-opencode");
15881
16009
  }
@@ -18205,7 +18333,7 @@ var MAX_CHUNK_CHARS8, OpenCodeSource;
18205
18333
  var init_opencode_source = __esm({
18206
18334
  "../engine/dist/parsers/opencode-source.js"() {
18207
18335
  "use strict";
18208
- init_sqlite_reader();
18336
+ init_opencode_v2();
18209
18337
  init_opencode();
18210
18338
  init_settings();
18211
18339
  MAX_CHUNK_CHARS8 = 2e3;
@@ -18222,7 +18350,7 @@ var init_opencode_source = __esm({
18222
18350
  return;
18223
18351
  let db;
18224
18352
  try {
18225
- db = openSqliteReadonlyOrThrow(this.dbPath);
18353
+ db = openOpencodeDbOrThrow(this.dbPath);
18226
18354
  } catch {
18227
18355
  return;
18228
18356
  }
@@ -18319,17 +18447,17 @@ var init_opencode_source = __esm({
18319
18447
  if (!existsSync30(this.dbPath))
18320
18448
  return [];
18321
18449
  const sessionId = item.id.replace("opencode_", "");
18322
- const db = openSqliteReadonlyOrThrow(this.dbPath);
18450
+ const db = openOpencodeDbOrThrow(this.dbPath);
18323
18451
  const chunks = [];
18324
18452
  try {
18325
18453
  const parts = db.prepare(`
18326
18454
  SELECT p.data, m.data as msg_data
18327
18455
  FROM part p
18328
- JOIN message m ON p.message_id = m.id
18456
+ JOIN (SELECT id, data FROM message WHERE session_id = ?) m ON p.message_id = m.id
18329
18457
  WHERE p.session_id = ?
18330
18458
  AND (p.data LIKE '%"type":"text"%' OR p.data LIKE '%"type":"reasoning"%')
18331
18459
  ORDER BY p.time_created ASC
18332
- `).all(sessionId);
18460
+ `).all(sessionId, sessionId);
18333
18461
  const userTexts = [];
18334
18462
  const assistantTexts = [];
18335
18463
  for (const part of parts) {
@@ -18393,7 +18521,7 @@ var OpenCodeTodoSource;
18393
18521
  var init_opencode_todo_source = __esm({
18394
18522
  "../engine/dist/parsers/opencode-todo-source.js"() {
18395
18523
  "use strict";
18396
- init_sqlite_reader();
18524
+ init_opencode_v2();
18397
18525
  init_opencode();
18398
18526
  init_settings();
18399
18527
  OpenCodeTodoSource = class {
@@ -18409,7 +18537,7 @@ var init_opencode_todo_source = __esm({
18409
18537
  return;
18410
18538
  let db;
18411
18539
  try {
18412
- db = openSqliteReadonlyOrThrow(this.dbPath);
18540
+ db = openOpencodeDbOrThrow(this.dbPath);
18413
18541
  } catch {
18414
18542
  return;
18415
18543
  }
@@ -18457,7 +18585,7 @@ var init_opencode_todo_source = __esm({
18457
18585
  if (!existsSync31(this.dbPath))
18458
18586
  return [];
18459
18587
  const sessionId = item.extra?.sessionId || item.id.replace(`${opencodeBackend.idPrefix}todo_`, "");
18460
- const db = openSqliteReadonlyOrThrow(this.dbPath);
18588
+ const db = openOpencodeDbOrThrow(this.dbPath);
18461
18589
  const chunks = [];
18462
18590
  try {
18463
18591
  const todos = db.prepare(`
@@ -19566,7 +19694,7 @@ var require_anchors = __commonJS({
19566
19694
  var require_applyReviver = __commonJS({
19567
19695
  "../../node_modules/yaml/dist/doc/applyReviver.js"(exports) {
19568
19696
  "use strict";
19569
- function applyReviver(reviver, obj, key2, val) {
19697
+ function applyReviver(reviver, obj2, key2, val) {
19570
19698
  if (val && typeof val === "object") {
19571
19699
  if (Array.isArray(val)) {
19572
19700
  for (let i = 0, len = val.length; i < len; ++i) {
@@ -19606,7 +19734,7 @@ var require_applyReviver = __commonJS({
19606
19734
  }
19607
19735
  }
19608
19736
  }
19609
- return reviver.call(obj, key2, val);
19737
+ return reviver.call(obj2, key2, val);
19610
19738
  }
19611
19739
  exports.applyReviver = applyReviver;
19612
19740
  }
@@ -20141,12 +20269,12 @@ var require_foldFlowLines = __commonJS({
20141
20269
  ch = text[i += 1];
20142
20270
  overflow = true;
20143
20271
  }
20144
- const j = i > escEnd + 1 ? i - 2 : escStart - 1;
20145
- if (escapedFolds[j])
20272
+ const j2 = i > escEnd + 1 ? i - 2 : escStart - 1;
20273
+ if (escapedFolds[j2])
20146
20274
  return text;
20147
- folds.push(j);
20148
- escapedFolds[j] = true;
20149
- end = j + endStep;
20275
+ folds.push(j2);
20276
+ escapedFolds[j2] = true;
20277
+ end = j2 + endStep;
20150
20278
  split = void 0;
20151
20279
  } else {
20152
20280
  overflow = true;
@@ -20542,10 +20670,10 @@ var require_stringify = __commonJS({
20542
20670
  return match.find((t) => t.format === item.format) ?? match[0];
20543
20671
  }
20544
20672
  let tagObj = void 0;
20545
- let obj;
20673
+ let obj2;
20546
20674
  if (identity.isScalar(item)) {
20547
- obj = item.value;
20548
- let match = tags.filter((t) => t.identify?.(obj));
20675
+ obj2 = item.value;
20676
+ let match = tags.filter((t) => t.identify?.(obj2));
20549
20677
  if (match.length > 1) {
20550
20678
  const testMatch = match.filter((t) => t.test);
20551
20679
  if (testMatch.length > 0)
@@ -20553,11 +20681,11 @@ var require_stringify = __commonJS({
20553
20681
  }
20554
20682
  tagObj = match.find((t) => t.format === item.format) ?? match.find((t) => !t.format);
20555
20683
  } else {
20556
- obj = item;
20557
- tagObj = tags.find((t) => t.nodeClass && obj instanceof t.nodeClass);
20684
+ obj2 = item;
20685
+ tagObj = tags.find((t) => t.nodeClass && obj2 instanceof t.nodeClass);
20558
20686
  }
20559
20687
  if (!tagObj) {
20560
- const name = obj?.constructor?.name ?? (obj === null ? "null" : typeof obj);
20688
+ const name = obj2?.constructor?.name ?? (obj2 === null ? "null" : typeof obj2);
20561
20689
  throw new Error(`Tag not resolved for ${name} value`);
20562
20690
  }
20563
20691
  return tagObj;
@@ -21113,23 +21241,23 @@ var require_YAMLMap = __commonJS({
21113
21241
  * A generic collection parsing method that can be extended
21114
21242
  * to other node classes that inherit from YAMLMap
21115
21243
  */
21116
- static from(schema, obj, ctx) {
21244
+ static from(schema, obj2, ctx) {
21117
21245
  const { keepUndefined, replacer } = ctx;
21118
21246
  const map = new this(schema);
21119
21247
  const add = (key2, value) => {
21120
21248
  if (typeof replacer === "function")
21121
- value = replacer.call(obj, key2, value);
21249
+ value = replacer.call(obj2, key2, value);
21122
21250
  else if (Array.isArray(replacer) && !replacer.includes(key2))
21123
21251
  return;
21124
21252
  if (value !== void 0 || keepUndefined)
21125
21253
  map.items.push(Pair.createPair(key2, value, ctx));
21126
21254
  };
21127
- if (obj instanceof Map) {
21128
- for (const [key2, value] of obj)
21255
+ if (obj2 instanceof Map) {
21256
+ for (const [key2, value] of obj2)
21129
21257
  add(key2, value);
21130
- } else if (obj && typeof obj === "object") {
21131
- for (const key2 of Object.keys(obj))
21132
- add(key2, obj[key2]);
21258
+ } else if (obj2 && typeof obj2 === "object") {
21259
+ for (const key2 of Object.keys(obj2))
21260
+ add(key2, obj2[key2]);
21133
21261
  }
21134
21262
  if (typeof schema.sortMapEntries === "function") {
21135
21263
  map.items.sort(schema.sortMapEntries);
@@ -21239,7 +21367,7 @@ var require_map = __commonJS({
21239
21367
  onError("Expected a mapping for this tag");
21240
21368
  return map2;
21241
21369
  },
21242
- createNode: (schema, obj, ctx) => YAMLMap.YAMLMap.from(schema, obj, ctx)
21370
+ createNode: (schema, obj2, ctx) => YAMLMap.YAMLMap.from(schema, obj2, ctx)
21243
21371
  };
21244
21372
  exports.map = map;
21245
21373
  }
@@ -21335,15 +21463,15 @@ var require_YAMLSeq = __commonJS({
21335
21463
  onComment
21336
21464
  });
21337
21465
  }
21338
- static from(schema, obj, ctx) {
21466
+ static from(schema, obj2, ctx) {
21339
21467
  const { replacer } = ctx;
21340
21468
  const seq = new this(schema);
21341
- if (obj && Symbol.iterator in Object(obj)) {
21469
+ if (obj2 && Symbol.iterator in Object(obj2)) {
21342
21470
  let i = 0;
21343
- for (let it of obj) {
21471
+ for (let it of obj2) {
21344
21472
  if (typeof replacer === "function") {
21345
- const key2 = obj instanceof Set ? it : String(i++);
21346
- it = replacer.call(obj, key2, it);
21473
+ const key2 = obj2 instanceof Set ? it : String(i++);
21474
+ it = replacer.call(obj2, key2, it);
21347
21475
  }
21348
21476
  seq.items.push(createNode.createNode(it, void 0, ctx));
21349
21477
  }
@@ -21377,7 +21505,7 @@ var require_seq = __commonJS({
21377
21505
  onError("Expected a sequence for this tag");
21378
21506
  return seq2;
21379
21507
  },
21380
- createNode: (schema, obj, ctx) => YAMLSeq.YAMLSeq.from(schema, obj, ctx)
21508
+ createNode: (schema, obj2, ctx) => YAMLSeq.YAMLSeq.from(schema, obj2, ctx)
21381
21509
  };
21382
21510
  exports.seq = seq;
21383
21511
  }
@@ -26630,15 +26758,15 @@ var init_mcps_source = __esm({
26630
26758
  });
26631
26759
  }
26632
26760
  }
26633
- async *fromObject(obj, ctx) {
26634
- if (!obj || typeof obj !== "object")
26761
+ async *fromObject(obj2, ctx) {
26762
+ if (!obj2 || typeof obj2 !== "object")
26635
26763
  return;
26636
26764
  let mtime = 0;
26637
26765
  try {
26638
26766
  mtime = statSync32(ctx.filePath).mtimeMs;
26639
26767
  } catch {
26640
26768
  }
26641
- for (const [name, cfgRaw] of Object.entries(obj)) {
26769
+ for (const [name, cfgRaw] of Object.entries(obj2)) {
26642
26770
  const cfg = cfgRaw || {};
26643
26771
  const cmd = redactInlineSecrets(commandPreview(cfg)).text;
26644
26772
  const allow = Array.isArray(cfg.alwaysAllow) ? cfg.alwaysAllow.slice(0, 8) : [];
@@ -26836,11 +26964,11 @@ function parseScalarToml(text) {
26836
26964
  }
26837
26965
  return out;
26838
26966
  }
26839
- function stringifyScalarToml(obj) {
26967
+ function stringifyScalarToml(obj2) {
26840
26968
  const esc = (v) => v.includes("\n") ? `"""
26841
26969
  ${v}
26842
26970
  """` : `"${v.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
26843
- return Object.entries(obj).filter(([, v]) => v !== void 0 && v !== "").map(([k, v]) => `${k} = ${esc(v)}`).join("\n") + "\n";
26971
+ return Object.entries(obj2).filter(([, v]) => v !== void 0 && v !== "").map(([k, v]) => `${k} = ${esc(v)}`).join("\n") + "\n";
26844
26972
  }
26845
26973
  var init_toolkit_format = __esm({
26846
26974
  "../engine/dist/core/toolkit-format.js"() {
@@ -28036,7 +28164,7 @@ var init_http = __esm({
28036
28164
  CLI_VERSION = JSON.parse(readFileSync34(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
28037
28165
  } catch {
28038
28166
  try {
28039
- if (true) CLI_VERSION = "0.7.21";
28167
+ if (true) CLI_VERSION = "0.7.24";
28040
28168
  } catch {
28041
28169
  }
28042
28170
  }
@@ -28420,7 +28548,7 @@ function serverAllowsTelemetry(serverUrl) {
28420
28548
  function mayReport(serverUrl) {
28421
28549
  return userConsents() && serverAllowsTelemetry(serverUrl);
28422
28550
  }
28423
- function findSensitiveKeys(obj, where = "") {
28551
+ function findSensitiveKeys(obj2, where = "") {
28424
28552
  const out = [];
28425
28553
  const walk = (v, at) => {
28426
28554
  if (!v || typeof v !== "object") return;
@@ -28433,7 +28561,7 @@ function findSensitiveKeys(obj, where = "") {
28433
28561
  walk(val, at ? `${at}.${k}` : k);
28434
28562
  }
28435
28563
  };
28436
- walk(obj, where);
28564
+ walk(obj2, where);
28437
28565
  return out;
28438
28566
  }
28439
28567
  function assertNoSensitiveKeys(payload) {
@@ -28534,7 +28662,7 @@ var init_telemetry = __esm({
28534
28662
  init_sync_client();
28535
28663
  cliVersion2 = () => {
28536
28664
  try {
28537
- return true ? "0.7.21" : "dev";
28665
+ return true ? "0.7.24" : "dev";
28538
28666
  } catch {
28539
28667
  return "dev";
28540
28668
  }
@@ -31147,7 +31275,7 @@ var init_sync_client = __esm({
31147
31275
  ownVersion = JSON.parse(readFileSync39(join46(dir, "../package.json"), "utf-8")).version || ownVersion;
31148
31276
  } catch {
31149
31277
  try {
31150
- if (true) ownVersion = "0.7.21";
31278
+ if (true) ownVersion = "0.7.24";
31151
31279
  } catch {
31152
31280
  }
31153
31281
  }
@@ -33321,6 +33449,7 @@ __export(guard_registration_exports, {
33321
33449
  guardTargets: () => guardTargets,
33322
33450
  guardWrapperName: () => guardWrapperName,
33323
33451
  guardWrapperSource: () => guardWrapperSource,
33452
+ legacyAgyHooksFile: () => legacyAgyHooksFile,
33324
33453
  opencodeConfigDir: () => opencodeConfigDir,
33325
33454
  opencodePluginDir: () => opencodePluginDir,
33326
33455
  opencodePluginSource: () => opencodePluginSource,
@@ -33329,6 +33458,9 @@ __export(guard_registration_exports, {
33329
33458
  });
33330
33459
  import { homedir as homedir21 } from "os";
33331
33460
  import { join as join57 } from "path";
33461
+ function legacyAgyHooksFile() {
33462
+ return join57(agyBackend.homeDir(), "hooks.json");
33463
+ }
33332
33464
  function opencodeConfigDir() {
33333
33465
  const xdg = process.env.XDG_CONFIG_HOME;
33334
33466
  const base4 = xdg && xdg.trim() ? xdg : join57(homedir21(), ".config");
@@ -33355,7 +33487,7 @@ function guardTargets() {
33355
33487
  {
33356
33488
  tool: "agy",
33357
33489
  label: "Antigravity",
33358
- configPath: join57(agyBackend.homeDir(), "hooks.json"),
33490
+ configPath: agyBackend.sharedHooksFile(),
33359
33491
  homeDir: agyBackend.homeDir()
33360
33492
  },
33361
33493
  {
@@ -33505,14 +33637,24 @@ function ask(payload) {
33505
33637
  });
33506
33638
  }
33507
33639
 
33508
- export const ChatRecallGuard = async () => ({
33509
- "tool.execute.before": async (input, output) => {
33510
- const verdict = await ask({ tool: input?.tool, args: output?.args });
33511
- if (!verdict || !verdict.message) return;
33512
- if (verdict.block) throw new Error(verdict.message);
33513
- console.error(verdict.message);
33514
- },
33515
- });
33640
+ async function check(tool, args) {
33641
+ const verdict = await ask({ tool, args });
33642
+ if (!verdict || !verdict.message) return;
33643
+ if (verdict.block) throw new Error(verdict.message);
33644
+ console.error(verdict.message);
33645
+ }
33646
+
33647
+ async function setup(ctx) {
33648
+ await ctx.tool.hook("execute.before", (event) => check(event?.tool, event?.input));
33649
+ }
33650
+
33651
+ async function server() {
33652
+ return {
33653
+ "tool.execute.before": (input, output) => check(input?.tool, output?.args),
33654
+ };
33655
+ }
33656
+
33657
+ export default { id: "${GUARD_ID}", server, setup };
33516
33658
  `;
33517
33659
  }
33518
33660
  var GUARD_ID, AGY_MATCHER, CODEX_MATCHER, TIMEOUT_SECS, isOurs, asArray2;
@@ -33529,6 +33671,383 @@ var init_guard_registration = __esm({
33529
33671
  }
33530
33672
  });
33531
33673
 
33674
+ // ../engine/dist/core/message-registration.js
33675
+ var message_registration_exports = {};
33676
+ __export(message_registration_exports, {
33677
+ MESSAGES_ID: () => MESSAGES_ID,
33678
+ isOurPluginSource: () => isOurPluginSource,
33679
+ messageCommand: () => messageCommand,
33680
+ messageTargets: () => messageTargets,
33681
+ messageWrapperName: () => messageWrapperName,
33682
+ messageWrapperSource: () => messageWrapperSource,
33683
+ opencodeMessagesSource: () => opencodeMessagesSource,
33684
+ piAgentDir: () => piAgentDir2,
33685
+ piMessagesSource: () => piMessagesSource,
33686
+ registerMessages: () => registerMessages,
33687
+ unregisterMessages: () => unregisterMessages
33688
+ });
33689
+ import { homedir as homedir22 } from "os";
33690
+ import { join as join58 } from "path";
33691
+ function piAgentDir2() {
33692
+ const dir = process.env.PI_CODING_AGENT_DIR;
33693
+ return dir && dir.trim() ? dir : join58(homedir22(), ".pi", "agent");
33694
+ }
33695
+ function messageTargets() {
33696
+ return [
33697
+ {
33698
+ tool: "codex",
33699
+ label: "Codex",
33700
+ configPath: join58(codexBackend.homeDir(), "hooks.json"),
33701
+ homeDir: codexBackend.homeDir(),
33702
+ // Codex binds its approval to the hook's hash, and only a person can give it.
33703
+ note: "Codex asks you to approve a hook before it runs one. Run /hooks in Codex once to approve the message hook."
33704
+ },
33705
+ {
33706
+ tool: "agy",
33707
+ label: "Antigravity",
33708
+ configPath: agyBackend.sharedHooksFile(),
33709
+ homeDir: agyBackend.homeDir()
33710
+ },
33711
+ {
33712
+ tool: "cursor",
33713
+ label: "Cursor",
33714
+ configPath: join58(cursorBackend.homeDir(), "hooks.json"),
33715
+ homeDir: cursorBackend.homeDir(),
33716
+ note: "Cursor delivers a message at the start of a session and when the agent stops, as a follow-up prompt."
33717
+ },
33718
+ {
33719
+ tool: "opencode",
33720
+ label: "OpenCode",
33721
+ configPath: join58(opencodePluginDir(), `${MESSAGES_ID}.js`),
33722
+ homeDir: opencodeConfigDir()
33723
+ },
33724
+ {
33725
+ tool: "pi",
33726
+ label: "pi",
33727
+ configPath: join58(piAgentDir2(), "extensions", `${MESSAGES_ID}.js`),
33728
+ homeDir: piAgentDir2()
33729
+ }
33730
+ ];
33731
+ }
33732
+ function messageWrapperName(tool) {
33733
+ return `chat_recall_messages_${tool}.sh`;
33734
+ }
33735
+ function messageWrapperSource(tool, nodePath, hookEntry) {
33736
+ return `#!/bin/sh
33737
+ # Written by \`chat-recall install-hooks\`. Re-running replaces it.
33738
+ exec ${JSON.stringify(nodePath)} ${JSON.stringify(hookEntry)} --tool ${tool} "$@"
33739
+ `;
33740
+ }
33741
+ function messageCommand(wrapperPath, args = "") {
33742
+ const p = wrapperPath.includes(" ") ? `"${wrapperPath}"` : wrapperPath;
33743
+ return args ? `${p} ${args}` : p;
33744
+ }
33745
+ function mergeCodex2(config2, command) {
33746
+ const c = obj(config2);
33747
+ const hooks = obj(c.hooks);
33748
+ for (const event of CODEX_EVENTS) {
33749
+ const kept = asArray3(hooks[event]).filter((e) => !asArray3(e?.hooks).some((h) => isOurs2(h?.command)));
33750
+ kept.push({ hooks: [{ type: "command", command, timeout: TIMEOUT_SECS2 }] });
33751
+ hooks[event] = kept;
33752
+ }
33753
+ c.hooks = hooks;
33754
+ return c;
33755
+ }
33756
+ function stripCodex2(config2) {
33757
+ const c = obj(config2);
33758
+ const hooks = obj(c.hooks);
33759
+ let removed = 0;
33760
+ for (const event of CODEX_EVENTS) {
33761
+ const before = asArray3(hooks[event]);
33762
+ const kept = before.filter((e) => !asArray3(e?.hooks).some((h) => isOurs2(h?.command)));
33763
+ removed += before.length - kept.length;
33764
+ if (kept.length)
33765
+ hooks[event] = kept;
33766
+ else
33767
+ delete hooks[event];
33768
+ }
33769
+ if (Object.keys(hooks).length)
33770
+ c.hooks = hooks;
33771
+ else
33772
+ delete c.hooks;
33773
+ return { config: c, removed };
33774
+ }
33775
+ function mergeAgy2(config2, command) {
33776
+ const c = obj(config2);
33777
+ const run = (event) => [{ type: "command", command: `${command} --event ${event}`, timeout: TIMEOUT_SECS2 }];
33778
+ c[MESSAGES_ID] = {
33779
+ enabled: true,
33780
+ SessionStart: run("SessionStart"),
33781
+ PreInvocation: run("PreInvocation"),
33782
+ Stop: run("Stop")
33783
+ };
33784
+ return c;
33785
+ }
33786
+ function stripAgy2(config2) {
33787
+ const c = obj(config2);
33788
+ const had = Object.prototype.hasOwnProperty.call(c, MESSAGES_ID) ? 1 : 0;
33789
+ delete c[MESSAGES_ID];
33790
+ return { config: c, removed: had };
33791
+ }
33792
+ function mergeCursor2(config2, command) {
33793
+ const c = obj(config2);
33794
+ c.version = typeof c.version === "number" ? c.version : 1;
33795
+ const hooks = obj(c.hooks);
33796
+ for (const event of CURSOR_EVENTS) {
33797
+ const kept = asArray3(hooks[event]).filter((e) => !isOurs2(e?.command));
33798
+ kept.push({ command, timeout: TIMEOUT_SECS2 });
33799
+ hooks[event] = kept;
33800
+ }
33801
+ c.hooks = hooks;
33802
+ return c;
33803
+ }
33804
+ function stripCursor2(config2) {
33805
+ const c = obj(config2);
33806
+ const hooks = obj(c.hooks);
33807
+ let removed = 0;
33808
+ for (const event of CURSOR_EVENTS) {
33809
+ const before = asArray3(hooks[event]);
33810
+ const kept = before.filter((e) => !isOurs2(e?.command));
33811
+ removed += before.length - kept.length;
33812
+ if (kept.length)
33813
+ hooks[event] = kept;
33814
+ else
33815
+ delete hooks[event];
33816
+ }
33817
+ c.hooks = hooks;
33818
+ return { config: c, removed };
33819
+ }
33820
+ function registerMessages(tool, config2, command) {
33821
+ switch (tool) {
33822
+ case "codex":
33823
+ return mergeCodex2(config2, command);
33824
+ case "agy":
33825
+ return mergeAgy2(config2, command);
33826
+ case "cursor":
33827
+ return mergeCursor2(config2, command);
33828
+ }
33829
+ }
33830
+ function unregisterMessages(tool, config2) {
33831
+ switch (tool) {
33832
+ case "codex":
33833
+ return stripCodex2(config2);
33834
+ case "agy":
33835
+ return stripAgy2(config2);
33836
+ case "cursor":
33837
+ return stripCursor2(config2);
33838
+ }
33839
+ }
33840
+ function isOurPluginSource(source) {
33841
+ return source.includes(`${MESSAGES_ID}: written by`);
33842
+ }
33843
+ function runnerSource(wrapperPath) {
33844
+ return `import { spawn } from "child_process";
33845
+
33846
+ const HOOK = ${JSON.stringify(wrapperPath)};
33847
+
33848
+ function runHook(sessionId, event, cwd) {
33849
+ return new Promise((resolve) => {
33850
+ let out = "";
33851
+ let child;
33852
+ try {
33853
+ child = spawn(HOOK, [], { stdio: ["pipe", "pipe", "ignore"] });
33854
+ } catch {
33855
+ resolve("");
33856
+ return;
33857
+ }
33858
+ const done = setTimeout(() => { child.kill(); resolve(""); }, ${TIMEOUT_SECS2 * 1e3});
33859
+ child.stdout.on("data", (c) => { out += c; });
33860
+ child.on("error", () => { clearTimeout(done); resolve(""); });
33861
+ child.on("close", () => { clearTimeout(done); resolve(out.trim()); });
33862
+ child.stdin.end(JSON.stringify({ session_id: sessionId, hook_event_name: event, cwd }));
33863
+ });
33864
+ }
33865
+
33866
+ /**
33867
+ * Wait for a message to an idle session. The hook long-polls the server and
33868
+ * prints the messages when one arrives; onText gets them. One waiter per
33869
+ * session; stopWaiter ends it when the session gets a prompt.
33870
+ */
33871
+ const waiters = new Map();
33872
+
33873
+ function startWaiter(sessionId, cwd, onText) {
33874
+ if (waiters.has(sessionId)) return;
33875
+ let out = "";
33876
+ let child;
33877
+ try {
33878
+ child = spawn(HOOK, ["--wait"], { stdio: ["pipe", "pipe", "ignore"] });
33879
+ } catch {
33880
+ return;
33881
+ }
33882
+ waiters.set(sessionId, child);
33883
+ child.stdout.on("data", (c) => { out += c; });
33884
+ child.on("error", () => { waiters.delete(sessionId); });
33885
+ child.on("close", () => {
33886
+ if (waiters.get(sessionId) === child) waiters.delete(sessionId);
33887
+ const text = out.trim();
33888
+ if (text) Promise.resolve().then(() => onText(text)).catch(() => {});
33889
+ });
33890
+ child.stdin.end(JSON.stringify({ session_id: sessionId, hook_event_name: "Stop", cwd }));
33891
+ }
33892
+
33893
+ function stopWaiter(sessionId) {
33894
+ const child = waiters.get(sessionId);
33895
+ if (!child) return;
33896
+ waiters.delete(sessionId);
33897
+ try { child.kill(); } catch { /* gone */ }
33898
+ }
33899
+ `;
33900
+ }
33901
+ function opencodeMessagesSource(wrapperPath) {
33902
+ return `// ${MESSAGES_ID}: written by \`chat-recall install-hooks\`. Re-running replaces it.
33903
+ //
33904
+ // Reports each opencode session to chat-recall and adds the messages that
33905
+ // other sessions sent it to the next prompt.
33906
+ ${runnerSource(wrapperPath)}
33907
+ const RUN_END = new Set(["session.execution.succeeded", "session.execution.failed", "session.execution.interrupted", "session.idle"]);
33908
+
33909
+ async function setup(ctx) {
33910
+ const dir = ctx?.location?.directory;
33911
+ const started = new Set();
33912
+ const children = new Set();
33913
+ const isChild = async (id) => {
33914
+ if (children.has(id)) return true;
33915
+ try {
33916
+ const s = await ctx.session.get({ sessionID: id });
33917
+ if (s?.parentID) { children.add(id); return true; }
33918
+ } catch { /* unknown: treat as a main session */ }
33919
+ return false;
33920
+ };
33921
+ await ctx.session.hook("prompt", async (event) => {
33922
+ const id = event?.sessionID;
33923
+ if (!id || !event.prompt || (await isChild(id))) return;
33924
+ stopWaiter("opencode_" + id);
33925
+ const parts = [];
33926
+ if (!started.has(id)) {
33927
+ started.add(id);
33928
+ parts.push(await runHook("opencode_" + id, "SessionStart", dir));
33929
+ }
33930
+ parts.push(await runHook("opencode_" + id, "UserPromptSubmit", dir));
33931
+ const text = parts.filter(Boolean).join("\\n\\n");
33932
+ if (text) event.prompt.text = [event.prompt.text, text].filter(Boolean).join("\\n\\n");
33933
+ });
33934
+ const controller = new AbortController();
33935
+ (async () => {
33936
+ try {
33937
+ for await (const ev of ctx.event.subscribe({ signal: controller.signal })) {
33938
+ const id = ev?.data?.sessionID ?? ev?.properties?.sessionID;
33939
+ if (!id || !started.has(id)) continue;
33940
+ if (RUN_END.has(ev.type)) {
33941
+ await runHook("opencode_" + id, "Stop", dir);
33942
+ // An idle session acts on a message from another session by itself:
33943
+ // the text becomes its next prompt.
33944
+ startWaiter("opencode_" + id, dir, (text) => ctx.session.prompt({ sessionID: id, text }));
33945
+ } else if (ev.type === "session.deleted") {
33946
+ started.delete(id);
33947
+ stopWaiter("opencode_" + id);
33948
+ await runHook("opencode_" + id, "SessionEnd", dir);
33949
+ }
33950
+ }
33951
+ } catch { /* the subscription ends with the plugin */ }
33952
+ })();
33953
+ return () => {
33954
+ controller.abort();
33955
+ for (const id of [...waiters.keys()]) stopWaiter(id);
33956
+ };
33957
+ }
33958
+
33959
+ const pending = new Map();
33960
+ const children = new Set();
33961
+ let seq = 0;
33962
+
33963
+ function partId() {
33964
+ seq += 1;
33965
+ return "prt_" + Date.now().toString(16) + seq.toString(16).padStart(4, "0") + "chatrecall";
33966
+ }
33967
+
33968
+ async function server({ directory }) {
33969
+ return {
33970
+ event: async ({ event }) => {
33971
+ const info = event?.properties?.info;
33972
+ if (event?.type === "session.created" && info?.id) {
33973
+ if (info.parentID) { children.add(info.id); return; }
33974
+ const text = await runHook("opencode_" + info.id, "SessionStart", directory);
33975
+ if (text) pending.set(info.id, text);
33976
+ } else if (event?.type === "session.idle" && event.properties?.sessionID && !children.has(event.properties.sessionID)) {
33977
+ await runHook("opencode_" + event.properties.sessionID, "Stop", directory);
33978
+ } else if (event?.type === "session.deleted" && info?.id) {
33979
+ children.delete(info.id);
33980
+ pending.delete(info.id);
33981
+ await runHook("opencode_" + info.id, "SessionEnd", directory);
33982
+ }
33983
+ },
33984
+ "chat.message": async (input, output) => {
33985
+ const id = input?.sessionID;
33986
+ if (!id || children.has(id) || !output?.message) return;
33987
+ const before = pending.get(id) ?? "";
33988
+ pending.delete(id);
33989
+ const now = await runHook("opencode_" + id, "UserPromptSubmit", directory);
33990
+ const text = [before, now].filter(Boolean).join("\\n\\n");
33991
+ if (!text) return;
33992
+ output.parts.push({ id: partId(), sessionID: id, messageID: output.message.id, type: "text", text, synthetic: true });
33993
+ },
33994
+ };
33995
+ }
33996
+
33997
+ export default { id: "${MESSAGES_ID}", server, setup };
33998
+ `;
33999
+ }
34000
+ function piMessagesSource(wrapperPath) {
34001
+ return `// ${MESSAGES_ID}: written by \`chat-recall install-hooks\`. Re-running replaces it.
34002
+ //
34003
+ // Reports each pi session to chat-recall and adds the messages that other
34004
+ // sessions sent it to the next prompt.
34005
+ ${runnerSource(wrapperPath)}
34006
+ export default function (pi) {
34007
+ let pending = "";
34008
+ const idOf = (ctx) => "pi_" + ctx.sessionManager.getSessionId();
34009
+ const cwdOf = (ctx) => ctx.sessionManager.getCwd();
34010
+
34011
+ pi.on("session_start", async (_event, ctx) => {
34012
+ pending = await runHook(idOf(ctx), "SessionStart", cwdOf(ctx));
34013
+ });
34014
+ pi.on("before_agent_start", async (event, ctx) => {
34015
+ stopWaiter(idOf(ctx));
34016
+ if (event.messageType !== "user") return;
34017
+ const now = await runHook(idOf(ctx), "UserPromptSubmit", cwdOf(ctx));
34018
+ const text = [pending, now].filter(Boolean).join("\\n\\n");
34019
+ pending = "";
34020
+ if (!text) return;
34021
+ return { message: { customType: "${MESSAGES_ID}", content: text, display: true } };
34022
+ });
34023
+ pi.on("agent_end", async (_event, ctx) => {
34024
+ await runHook(idOf(ctx), "Stop", cwdOf(ctx));
34025
+ // An idle session acts on a message from another session by itself.
34026
+ startWaiter(idOf(ctx), cwdOf(ctx), (text) => pi.sendUserMessage(text));
34027
+ });
34028
+ pi.on("session_shutdown", async (_event, ctx) => {
34029
+ stopWaiter(idOf(ctx));
34030
+ await runHook(idOf(ctx), "SessionEnd", cwdOf(ctx));
34031
+ });
34032
+ }
34033
+ `;
34034
+ }
34035
+ var MESSAGES_ID, TIMEOUT_SECS2, isOurs2, asArray3, obj, CODEX_EVENTS, CURSOR_EVENTS;
34036
+ var init_message_registration = __esm({
34037
+ "../engine/dist/core/message-registration.js"() {
34038
+ "use strict";
34039
+ init_backends();
34040
+ init_guard_registration();
34041
+ MESSAGES_ID = "chat-recall-messages";
34042
+ TIMEOUT_SECS2 = 10;
34043
+ isOurs2 = (cmd) => typeof cmd === "string" && cmd.includes("chat_recall_messages_");
34044
+ asArray3 = (v) => Array.isArray(v) ? v : [];
34045
+ obj = (v) => v && typeof v === "object" && !Array.isArray(v) ? { ...v } : {};
34046
+ CODEX_EVENTS = ["SessionStart", "UserPromptSubmit", "Stop", "SessionEnd"];
34047
+ CURSOR_EVENTS = ["sessionStart", "beforeSubmitPrompt", "stop", "sessionEnd"];
34048
+ }
34049
+ });
34050
+
33532
34051
  // src/install-hooks.ts
33533
34052
  var install_hooks_exports = {};
33534
34053
  __export(install_hooks_exports, {
@@ -33544,7 +34063,7 @@ __export(install_hooks_exports, {
33544
34063
  uninstallHooks: () => uninstallHooks
33545
34064
  });
33546
34065
  import { chmodSync as chmodSync5, copyFileSync as copyFileSync3, existsSync as existsSync52, mkdirSync as mkdirSync17, readFileSync as readFileSync46, realpathSync as realpathSync6, renameSync as renameSync6, unlinkSync as unlinkSync4, writeFileSync as writeFileSync17 } from "node:fs";
33547
- import { dirname as dirname24, join as join58 } from "node:path";
34066
+ import { dirname as dirname24, join as join59 } from "node:path";
33548
34067
  function isOurEntry(entry) {
33549
34068
  const cmd = entry?.hooks?.[0]?.command;
33550
34069
  if (typeof cmd !== "string") return false;
@@ -33554,8 +34073,8 @@ function claudeSettingsFiles() {
33554
34073
  const out = [];
33555
34074
  const seen = /* @__PURE__ */ new Set();
33556
34075
  for (const home of claudeHomeDirs()) {
33557
- if (!existsSync52(join58(home, "projects"))) continue;
33558
- const file = join58(home, "settings.json");
34076
+ if (!existsSync52(join59(home, "projects"))) continue;
34077
+ const file = join59(home, "settings.json");
33559
34078
  let key2;
33560
34079
  try {
33561
34080
  key2 = realpathSync6(file);
@@ -33571,9 +34090,9 @@ function claudeSettingsFiles() {
33571
34090
  }
33572
34091
  function findScript(distDir, name) {
33573
34092
  return [
33574
- join58(distDir, "..", "hooks", name),
33575
- join58(distDir, "..", "..", "hooks", name),
33576
- join58(distDir, "..", "..", "..", "hooks", name)
34093
+ join59(distDir, "..", "hooks", name),
34094
+ join59(distDir, "..", "..", "hooks", name),
34095
+ join59(distDir, "..", "..", "..", "hooks", name)
33577
34096
  ].find((p) => existsSync52(p));
33578
34097
  }
33579
34098
  function hookEntries(sel, paths) {
@@ -33638,7 +34157,7 @@ function writeJsonAtomic(file, value) {
33638
34157
  renameSync6(tmp, target);
33639
34158
  }
33640
34159
  function statePath() {
33641
- return join58(getHooksDir(), "install.json");
34160
+ return join59(getHooksDir(), "install.json");
33642
34161
  }
33643
34162
  function readState() {
33644
34163
  try {
@@ -33656,7 +34175,7 @@ async function installHooks(distDir, sel = ALL_HOOKS) {
33656
34175
  if (!sel[key2]) continue;
33657
34176
  const source = findScript(distDir, SCRIPTS[key2]);
33658
34177
  if (!source) continue;
33659
- const target = join58(scriptsDir, SCRIPTS[key2]);
34178
+ const target = join59(scriptsDir, SCRIPTS[key2]);
33660
34179
  copyFileSync3(source, target);
33661
34180
  chmodSync5(target, 493);
33662
34181
  scripts[key2] = target;
@@ -33668,7 +34187,16 @@ async function installHooks(distDir, sel = ALL_HOOKS) {
33668
34187
  cliEntry: resolveCliEntry(distDir),
33669
34188
  messageHookEntry: resolveMessageHookEntry(distDir)
33670
34189
  });
33671
- const report = { written: [], skipped: [], migrated: 0, shellSkipped, scriptsDir, selection: sel, guardTargets: [] };
34190
+ const report = {
34191
+ written: [],
34192
+ skipped: [],
34193
+ migrated: 0,
34194
+ shellSkipped,
34195
+ scriptsDir,
34196
+ selection: sel,
34197
+ guardTargets: [],
34198
+ messageTargets: []
34199
+ };
33672
34200
  for (const settingsFile of claudeSettingsFiles()) {
33673
34201
  const config2 = readJson4(settingsFile);
33674
34202
  if (!config2) {
@@ -33678,9 +34206,12 @@ async function installHooks(distDir, sel = ALL_HOOKS) {
33678
34206
  mergeOurEntries(config2, entries);
33679
34207
  writeJsonAtomic(settingsFile, config2);
33680
34208
  report.written.push(settingsFile);
33681
- report.migrated += migrateHooksJson(join58(dirname24(settingsFile), "hooks.json"));
34209
+ report.migrated += migrateHooksJson(join59(dirname24(settingsFile), "hooks.json"));
33682
34210
  }
33683
34211
  if (sel.guard && scripts.guard) report.guardTargets = await addGuardToOtherTools(scriptsDir, scripts.guard);
34212
+ if (sel.messages && !shellSkipped) {
34213
+ report.messageTargets = await addMessagesToOtherTools(scriptsDir, process.execPath, resolveMessageHookEntry(distDir));
34214
+ }
33684
34215
  writeJsonAtomic(statePath(), { version: cliVersion(), selection: sel });
33685
34216
  return report;
33686
34217
  }
@@ -33695,9 +34226,9 @@ function migrateHooksJson(file) {
33695
34226
  return removed;
33696
34227
  }
33697
34228
  async function uninstallHooks() {
33698
- const report = { removed: 0, files: [], guardRemoved: [] };
34229
+ const report = { removed: 0, files: [], guardRemoved: [], messagesRemoved: [] };
33699
34230
  for (const settingsFile of claudeSettingsFiles()) {
33700
- for (const file of [settingsFile, join58(dirname24(settingsFile), "hooks.json")]) {
34231
+ for (const file of [settingsFile, join59(dirname24(settingsFile), "hooks.json")]) {
33701
34232
  if (!existsSync52(file)) continue;
33702
34233
  const config2 = readJson4(file);
33703
34234
  if (!config2) continue;
@@ -33709,6 +34240,7 @@ async function uninstallHooks() {
33709
34240
  }
33710
34241
  }
33711
34242
  report.guardRemoved = await removeGuardFromOtherTools();
34243
+ report.messagesRemoved = await removeMessagesFromOtherTools();
33712
34244
  writeJsonAtomic(statePath(), { version: cliVersion(), selection: ALL_HOOKS, uninstalled: true });
33713
34245
  return report;
33714
34246
  }
@@ -33732,9 +34264,10 @@ async function ensureHooks(distDir) {
33732
34264
  async function addGuardToOtherTools(scriptsDir, guardScript) {
33733
34265
  const reg = await Promise.resolve().then(() => (init_guard_registration(), guard_registration_exports));
33734
34266
  const out = [];
34267
+ removeLegacyAgyGuard(reg);
33735
34268
  for (const target of reg.guardTargets()) {
33736
34269
  if (!existsSync52(target.homeDir)) continue;
33737
- const wrapper = join58(scriptsDir, reg.guardWrapperName(target.tool));
34270
+ const wrapper = join59(scriptsDir, reg.guardWrapperName(target.tool));
33738
34271
  writeFileSync17(wrapper, reg.guardWrapperSource(target.tool, guardScript));
33739
34272
  chmodSync5(wrapper, 493);
33740
34273
  mkdirSync17(dirname24(target.configPath), { recursive: true });
@@ -33751,6 +34284,7 @@ async function addGuardToOtherTools(scriptsDir, guardScript) {
33751
34284
  async function removeGuardFromOtherTools() {
33752
34285
  const reg = await Promise.resolve().then(() => (init_guard_registration(), guard_registration_exports));
33753
34286
  const out = [];
34287
+ removeLegacyAgyGuard(reg);
33754
34288
  for (const target of reg.guardTargets()) {
33755
34289
  if (!existsSync52(target.configPath)) continue;
33756
34290
  if (target.tool === "opencode") {
@@ -33765,6 +34299,53 @@ async function removeGuardFromOtherTools() {
33765
34299
  }
33766
34300
  return out;
33767
34301
  }
34302
+ function removeLegacyAgyGuard(reg) {
34303
+ const file = reg.legacyAgyHooksFile();
34304
+ if (!existsSync52(file)) return;
34305
+ const r = reg.unregisterGuard("agy", readJson4(file) ?? {});
34306
+ if (r.removed) writeJsonAtomic(file, r.config);
34307
+ }
34308
+ async function addMessagesToOtherTools(scriptsDir, nodePath, hookEntry) {
34309
+ const reg = await Promise.resolve().then(() => (init_message_registration(), message_registration_exports));
34310
+ const out = [];
34311
+ for (const target of reg.messageTargets()) {
34312
+ if (!existsSync52(target.homeDir)) continue;
34313
+ const wrapper = join59(scriptsDir, reg.messageWrapperName(target.tool));
34314
+ writeFileSync17(wrapper, reg.messageWrapperSource(target.tool, nodePath, hookEntry));
34315
+ chmodSync5(wrapper, 493);
34316
+ mkdirSync17(dirname24(target.configPath), { recursive: true });
34317
+ if (target.tool === "opencode") {
34318
+ writeFileSync17(target.configPath, reg.opencodeMessagesSource(wrapper));
34319
+ } else if (target.tool === "pi") {
34320
+ writeFileSync17(target.configPath, reg.piMessagesSource(wrapper));
34321
+ } else {
34322
+ const config2 = readJson4(target.configPath);
34323
+ if (!config2) continue;
34324
+ writeJsonAtomic(target.configPath, reg.registerMessages(target.tool, config2, reg.messageCommand(wrapper)));
34325
+ }
34326
+ out.push({ label: target.label, configPath: target.configPath, note: target.note });
34327
+ }
34328
+ return out;
34329
+ }
34330
+ async function removeMessagesFromOtherTools() {
34331
+ const reg = await Promise.resolve().then(() => (init_message_registration(), message_registration_exports));
34332
+ const out = [];
34333
+ for (const target of reg.messageTargets()) {
34334
+ if (!existsSync52(target.configPath)) continue;
34335
+ if (target.tool === "opencode" || target.tool === "pi") {
34336
+ if (!reg.isOurPluginSource(readFileSync46(target.configPath, "utf-8"))) continue;
34337
+ unlinkSync4(target.configPath);
34338
+ } else {
34339
+ const config2 = readJson4(target.configPath);
34340
+ if (!config2) continue;
34341
+ const r = reg.unregisterMessages(target.tool, config2);
34342
+ if (r.removed === 0) continue;
34343
+ writeJsonAtomic(target.configPath, r.config);
34344
+ }
34345
+ out.push({ label: target.label, configPath: target.configPath });
34346
+ }
34347
+ return out;
34348
+ }
33768
34349
  var ALL_HOOKS, SCRIPTS, HOOK_EVENTS;
33769
34350
  var init_install_hooks = __esm({
33770
34351
  "src/install-hooks.ts"() {
@@ -34432,7 +35013,7 @@ __export(collector_exports, {
34432
35013
  import { spawn as spawn3 } from "node:child_process";
34433
35014
  import { execSync as execSync4 } from "node:child_process";
34434
35015
  import { readFileSync as readFileSync47 } from "node:fs";
34435
- import { join as join59, basename as basename28 } from "node:path";
35016
+ import { join as join60, basename as basename28 } from "node:path";
34436
35017
  async function resolveCodeindexBin(autoInstall = true) {
34437
35018
  let st = checkCodeindexStatus();
34438
35019
  if (!st.installed && autoInstall)
@@ -34614,7 +35195,7 @@ async function collectCode(opts) {
34614
35195
  }
34615
35196
  const complexity = (r) => {
34616
35197
  try {
34617
- const txt = readFileSync47(join59(ws, r), "utf8");
35198
+ const txt = readFileSync47(join60(ws, r), "utf8");
34618
35199
  if (txt.length > 2e6)
34619
35200
  return 1;
34620
35201
  const m = txt.match(CF_RE);
@@ -35046,16 +35627,16 @@ async function collectCode(opts) {
35046
35627
  ...blastTargets.map((f, i) => call(2e3 + i, "plan_change", { file: f, format: "json" }))
35047
35628
  ]);
35048
35629
  blastTargets.forEach((f, i) => {
35049
- const j = parseJson(pc, 2e3 + i, null);
35050
- if (j && typeof j === "object" && typeof j.fan_in === "number") {
35630
+ const j2 = parseJson(pc, 2e3 + i, null);
35631
+ if (j2 && typeof j2 === "object" && typeof j2.fan_in === "number") {
35051
35632
  blast[f] = {
35052
- fileRole: j.file_role ?? "regular",
35053
- fanIn: j.fan_in ?? 0,
35054
- fanOut: j.fan_out ?? 0,
35055
- direct: j.direct ?? 0,
35056
- transitive: j.transitive ?? 0,
35057
- maxDepth: j.max_depth ?? 0,
35058
- directFiles: Array.isArray(j.direct_files) ? j.direct_files.map(rel).slice(0, 20) : void 0
35633
+ fileRole: j2.file_role ?? "regular",
35634
+ fanIn: j2.fan_in ?? 0,
35635
+ fanOut: j2.fan_out ?? 0,
35636
+ direct: j2.direct ?? 0,
35637
+ transitive: j2.transitive ?? 0,
35638
+ maxDepth: j2.max_depth ?? 0,
35639
+ directFiles: Array.isArray(j2.direct_files) ? j2.direct_files.map(rel).slice(0, 20) : void 0
35059
35640
  };
35060
35641
  }
35061
35642
  });
@@ -35399,8 +35980,8 @@ __export(project_tasks_exports, {
35399
35980
  renderTeamTasksMd: () => renderTeamTasksMd
35400
35981
  });
35401
35982
  import { existsSync as existsSync54, readFileSync as readFileSync48, writeFileSync as writeFileSync18, mkdirSync as mkdirSync18, statSync as statSync46 } from "node:fs";
35402
- import { join as join60, dirname as dirname25 } from "node:path";
35403
- import { homedir as homedir22 } from "node:os";
35983
+ import { join as join61, dirname as dirname25 } from "node:path";
35984
+ import { homedir as homedir23 } from "node:os";
35404
35985
  function isTeamTaskStatus(v) {
35405
35986
  return !!v && TEAM_STATUSES.has(v);
35406
35987
  }
@@ -35450,7 +36031,7 @@ function parseTaskFile(content) {
35450
36031
  return out;
35451
36032
  }
35452
36033
  function ledgerPath2() {
35453
- return join60(homedir22(), ".chat-recall", "project-tasks-ledger.json");
36034
+ return join61(homedir23(), ".chat-recall", "project-tasks-ledger.json");
35454
36035
  }
35455
36036
  function readLedger() {
35456
36037
  try {
@@ -35483,7 +36064,7 @@ async function pushProjectTaskStatuses(base4, authHeaders, opts = {}) {
35483
36064
  continue;
35484
36065
  }
35485
36066
  for (const project of projects) {
35486
- const file = join60(project, fk.filename);
36067
+ const file = join61(project, fk.filename);
35487
36068
  if (!existsSync54(file)) continue;
35488
36069
  let mtime;
35489
36070
  try {
@@ -35568,7 +36149,7 @@ __export(intent_drain_exports, {
35568
36149
  runIntent: () => runIntent
35569
36150
  });
35570
36151
  import { existsSync as existsSync55, readFileSync as readFileSync49, writeFileSync as writeFileSync19, appendFileSync, mkdirSync as mkdirSync19 } from "node:fs";
35571
- import { join as join61 } from "node:path";
36152
+ import { join as join62 } from "node:path";
35572
36153
  import { fileURLToPath as fileURLToPath4 } from "node:url";
35573
36154
  import { dirname as dirname26 } from "node:path";
35574
36155
  function instructionTargets(rootPath, isGlobal) {
@@ -35582,16 +36163,16 @@ function instructionTargets(rootPath, isGlobal) {
35582
36163
  const tools = installed.length ? installed : [INSTRUCTION_TOOLS[0]];
35583
36164
  if (isGlobal) return [...new Set(tools.map((t) => instructionsPath(t.id)))];
35584
36165
  if (!rootPath) return [];
35585
- const present = INSTRUCTION_FILENAMES.map((f) => join61(rootPath, f)).filter((p) => existsSync55(p));
36166
+ const present = INSTRUCTION_FILENAMES.map((f) => join62(rootPath, f)).filter((p) => existsSync55(p));
35586
36167
  if (present.length) return present;
35587
- return [...new Set(tools.map((t) => join61(rootPath, instructionsFilename(t.id))))];
36168
+ return [...new Set(tools.map((t) => join62(rootPath, instructionsFilename(t.id))))];
35588
36169
  }
35589
36170
  function applyCodeRecommendation(intent) {
35590
36171
  try {
35591
36172
  const meta = JSON.parse(intent.name || "{}");
35592
36173
  if (intent.artifact_type === "write_tasks_file") {
35593
36174
  if (!meta.rootPath || !meta.content) return { status: "error", result: JSON.stringify({ error: "missing rootPath or content" }) };
35594
- const file = join61(meta.rootPath, meta.filename || "CODE_TASKS.md");
36175
+ const file = join62(meta.rootPath, meta.filename || "CODE_TASKS.md");
35595
36176
  writeFileSync19(file, meta.content);
35596
36177
  return { status: "done", result: JSON.stringify({ wrote: file }) };
35597
36178
  }
@@ -35796,10 +36377,10 @@ var init_intent_drain = __esm({
35796
36377
  ownVersion2 = "0.0.0";
35797
36378
  try {
35798
36379
  const dir = dirname26(fileURLToPath4(import.meta.url));
35799
- ownVersion2 = JSON.parse(readFileSync49(join61(dir, "../package.json"), "utf-8")).version || ownVersion2;
36380
+ ownVersion2 = JSON.parse(readFileSync49(join62(dir, "../package.json"), "utf-8")).version || ownVersion2;
35800
36381
  } catch {
35801
36382
  try {
35802
- if (true) ownVersion2 = "0.7.21";
36383
+ if (true) ownVersion2 = "0.7.24";
35803
36384
  } catch {
35804
36385
  }
35805
36386
  }
@@ -36001,47 +36582,47 @@ __export(team_merge_exports, {
36001
36582
  mergePullResult: () => mergePullResult
36002
36583
  });
36003
36584
  import { existsSync as existsSync56, mkdirSync as mkdirSync20, readFileSync as readFileSync50, rmSync as rmSync10, writeFileSync as writeFileSync20, statSync as statSync47 } from "fs";
36004
- import { dirname as dirname27, join as join62 } from "path";
36585
+ import { dirname as dirname27, join as join63 } from "path";
36005
36586
  import { createHash as createHash15 } from "crypto";
36006
36587
  function installPathFor(art, tool) {
36007
36588
  switch (art.type) {
36008
36589
  case "skill":
36009
36590
  switch (tool) {
36010
36591
  case "claude":
36011
- return join62(claudeBackend.skillsDir(), art.name, "SKILL.md");
36592
+ return join63(claudeBackend.skillsDir(), art.name, "SKILL.md");
36012
36593
  // Antigravity's OWN skills dir. It used to resolve to the shared
36013
36594
  // ~/.gemini/skills while toolkit-sync installed to
36014
36595
  // ~/.gemini/antigravity-cli/skills, so a team skill landed in one place
36015
36596
  // and a synced skill in the other.
36016
36597
  case "agy":
36017
- return join62(agyBackend.homeDir(), "skills", art.name, "SKILL.md");
36598
+ return join63(agyBackend.homeDir(), "skills", art.name, "SKILL.md");
36018
36599
  case "opencode":
36019
- return join62(opencodeBackend.skillsDir(), art.name, "SKILL.md");
36600
+ return join63(opencodeBackend.skillsDir(), art.name, "SKILL.md");
36020
36601
  // User skills go to ~/.codex/skills (NOT .system, which is OpenAI's bundle).
36021
36602
  case "codex":
36022
- return join62(codexBackend.skillsDir(), art.name, "SKILL.md");
36603
+ return join63(codexBackend.skillsDir(), art.name, "SKILL.md");
36023
36604
  case "cursor":
36024
- return join62(cursorHomeDir(), "skills", art.name, "SKILL.md");
36605
+ return join63(cursorHomeDir(), "skills", art.name, "SKILL.md");
36025
36606
  }
36026
36607
  break;
36027
36608
  case "agent":
36028
36609
  if (tool === "claude")
36029
- return join62(claudeBackend.agentsDir(), `${art.name}.md`);
36610
+ return join63(claudeBackend.agentsDir(), `${art.name}.md`);
36030
36611
  return null;
36031
36612
  case "command":
36032
36613
  if (tool === "claude")
36033
- return join62(claudeBackend.commandsDir(), `${art.name}.md`);
36614
+ return join63(claudeBackend.commandsDir(), `${art.name}.md`);
36034
36615
  return null;
36035
36616
  case "hook":
36036
36617
  if (tool === "claude")
36037
- return join62(claudeBackend.homeDir(), "chat-recall-hooks", `${art.name}.json`);
36618
+ return join63(claudeBackend.homeDir(), "chat-recall-hooks", `${art.name}.json`);
36038
36619
  return null;
36039
36620
  case "plan":
36040
36621
  switch (tool) {
36041
36622
  case "claude":
36042
- return join62(claudeBackend.plansDir(), `${art.name}.md`);
36623
+ return join63(claudeBackend.plansDir(), `${art.name}.md`);
36043
36624
  case "opencode":
36044
- return join62(opencodeBackend.plansDir(), `${art.name}.md`);
36625
+ return join63(opencodeBackend.plansDir(), `${art.name}.md`);
36045
36626
  case "agy":
36046
36627
  return null;
36047
36628
  // Antigravity plans live per-session
@@ -36052,11 +36633,11 @@ function installPathFor(art, tool) {
36052
36633
  }
36053
36634
  break;
36054
36635
  case "instructions":
36055
- return join62(getDataDir(), "team-instructions", tool, `${art.name}.md`);
36636
+ return join63(getDataDir(), "team-instructions", tool, `${art.name}.md`);
36056
36637
  case "mcp":
36057
- return join62(getDataDir(), "team-mcps", `${art.name}.json`);
36638
+ return join63(getDataDir(), "team-mcps", `${art.name}.json`);
36058
36639
  case "plugin":
36059
- return join62(getDataDir(), "team-plugins", tool, art.name, "manifest.json");
36640
+ return join63(getDataDir(), "team-plugins", tool, art.name, "manifest.json");
36060
36641
  }
36061
36642
  return null;
36062
36643
  }
@@ -36222,7 +36803,7 @@ var init_vault_crypto = __esm({
36222
36803
 
36223
36804
  // ../engine/dist/core/vault-source.js
36224
36805
  import { existsSync as existsSync57, readdirSync as readdirSync35, statSync as statSync48 } from "fs";
36225
- import { extname, join as join63 } from "path";
36806
+ import { extname, join as join64 } from "path";
36226
36807
  function* walkVaultSources() {
36227
36808
  const t = loadSettings().team.vault;
36228
36809
  const include2 = new Set(t.syncTools);
@@ -36259,7 +36840,7 @@ function* walkClaude() {
36259
36840
  if (proj.startsWith("."))
36260
36841
  continue;
36261
36842
  const projectPath = resolveProjectDirName(proj);
36262
- const projDir = join63(root, proj);
36843
+ const projDir = join64(root, proj);
36263
36844
  let entries = [];
36264
36845
  try {
36265
36846
  entries = readdirSync35(projDir);
@@ -36269,7 +36850,7 @@ function* walkClaude() {
36269
36850
  for (const f of entries) {
36270
36851
  if (extname(f) !== ".jsonl")
36271
36852
  continue;
36272
- const path = join63(projDir, f);
36853
+ const path = join64(projDir, f);
36273
36854
  const s = safeStat(path);
36274
36855
  if (!s)
36275
36856
  continue;
@@ -36299,7 +36880,7 @@ function* walkCursor() {
36299
36880
  }
36300
36881
  }
36301
36882
  function* walkCodex() {
36302
- const sessionsRoot = join63(codexBackend.homeDir(), "sessions");
36883
+ const sessionsRoot = join64(codexBackend.homeDir(), "sessions");
36303
36884
  if (!existsSync57(sessionsRoot))
36304
36885
  return;
36305
36886
  const stack = [sessionsRoot];
@@ -36312,7 +36893,7 @@ function* walkCodex() {
36312
36893
  continue;
36313
36894
  }
36314
36895
  for (const e of entries) {
36315
- const path = join63(dir, e.name);
36896
+ const path = join64(dir, e.name);
36316
36897
  if (e.isDirectory()) {
36317
36898
  stack.push(path);
36318
36899
  continue;
@@ -36328,7 +36909,7 @@ function* walkCodex() {
36328
36909
  }
36329
36910
  }
36330
36911
  function* walkAgy() {
36331
- const brainDir = join63(agyBackend.homeDir(), "brain");
36912
+ const brainDir = join64(agyBackend.homeDir(), "brain");
36332
36913
  if (!existsSync57(brainDir))
36333
36914
  return;
36334
36915
  let sessionDirs = [];
@@ -36338,16 +36919,16 @@ function* walkAgy() {
36338
36919
  return;
36339
36920
  }
36340
36921
  for (const rawId of sessionDirs) {
36341
- const sessionPath = join63(brainDir, rawId);
36922
+ const sessionPath = join64(brainDir, rawId);
36342
36923
  try {
36343
36924
  if (!statSync48(sessionPath).isDirectory())
36344
36925
  continue;
36345
36926
  } catch {
36346
36927
  continue;
36347
36928
  }
36348
- let filePath = join63(sessionPath, ".system_generated", "logs", "transcript.jsonl");
36929
+ let filePath = join64(sessionPath, ".system_generated", "logs", "transcript.jsonl");
36349
36930
  if (!existsSync57(filePath)) {
36350
- filePath = join63(sessionPath, ".system_generated", "logs", "transcript_full.jsonl");
36931
+ filePath = join64(sessionPath, ".system_generated", "logs", "transcript_full.jsonl");
36351
36932
  }
36352
36933
  if (!existsSync57(filePath))
36353
36934
  continue;
@@ -36386,7 +36967,7 @@ __export(vault_client_exports, {
36386
36967
  vaultSync: () => vaultSync
36387
36968
  });
36388
36969
  import { mkdirSync as mkdirSync21, readFileSync as readFileSync51, writeFileSync as writeFileSync21, existsSync as existsSync58 } from "fs";
36389
- import { dirname as dirname28, join as join64 } from "path";
36970
+ import { dirname as dirname28, join as join65 } from "path";
36390
36971
  function context2() {
36391
36972
  const s = loadSettings().team;
36392
36973
  if (!s.enabled)
@@ -36577,7 +37158,7 @@ async function vaultSync(passphrase) {
36577
37158
  }
36578
37159
  function importedPathFor(tool, sessionId) {
36579
37160
  const base4 = sessionId.replace(/^gemini_/, "").replace(/^codex_/, "").replace(/^agy_/, "").replace(/^cursor_/, "").replace(/^opencode_/, "");
36580
- return join64(IMPORTED_ROOT(), tool, `${base4}.jsonl`);
37161
+ return join65(IMPORTED_ROOT(), tool, `${base4}.jsonl`);
36581
37162
  }
36582
37163
  async function vaultRestore(passphrase, opts = {}) {
36583
37164
  const ctx = context2();
@@ -36666,7 +37247,7 @@ var init_vault_client = __esm({
36666
37247
  uploadKey = (sessionId, tool) => `${sessionId}\0${tool}`;
36667
37248
  VaultPassphraseMismatchError = class extends Error {
36668
37249
  };
36669
- IMPORTED_ROOT = () => join64(getDataDir(), "imported");
37250
+ IMPORTED_ROOT = () => join65(getDataDir(), "imported");
36670
37251
  }
36671
37252
  });
36672
37253
 
@@ -37229,14 +37810,14 @@ __export(service_installer_exports, {
37229
37810
  });
37230
37811
  import { execSync as execSync5 } from "child_process";
37231
37812
  import { existsSync as existsSync59, mkdirSync as mkdirSync22, readFileSync as readFileSync52, rmSync as rmSync11, writeFileSync as writeFileSync22 } from "fs";
37232
- import { homedir as homedir23 } from "os";
37233
- import { join as join65 } from "path";
37813
+ import { homedir as homedir24 } from "os";
37814
+ import { join as join66 } from "path";
37234
37815
  import { fileURLToPath as fileURLToPath5 } from "url";
37235
37816
  function resolveDaemonPaths() {
37236
37817
  const watchJs = fileURLToPath5(new URL("./watch.js", import.meta.url));
37237
37818
  const node = process.execPath;
37238
- const dataDir = join65(homedir23(), ".chat-recall");
37239
- const logFile = join65(dataDir, "watch.log");
37819
+ const dataDir = join66(homedir24(), ".chat-recall");
37820
+ const logFile = join66(dataDir, "watch.log");
37240
37821
  return { watchJs, node, logFile, dataDir };
37241
37822
  }
37242
37823
  function tryCmd(cmd) {
@@ -37263,7 +37844,7 @@ function refreshServiceDefinition() {
37263
37844
  if (process.platform !== "linux") return false;
37264
37845
  try {
37265
37846
  const { watchJs, node, logFile } = resolveDaemonPaths();
37266
- const unitPath = join65(homedir23(), ".config", "systemd", "user", "chat-recall-watch.service");
37847
+ const unitPath = join66(homedir24(), ".config", "systemd", "user", "chat-recall-watch.service");
37267
37848
  if (!existsSync59(unitPath)) return false;
37268
37849
  const current = readFileSync52(unitPath, "utf8");
37269
37850
  if (!current.includes(watchJs)) return false;
@@ -37294,8 +37875,8 @@ function installService() {
37294
37875
  );
37295
37876
  }
37296
37877
  function installSystemd(watchJs, node, logFile) {
37297
- const unitDir = join65(homedir23(), ".config", "systemd", "user");
37298
- const unitPath = join65(unitDir, "chat-recall-watch.service");
37878
+ const unitDir = join66(homedir24(), ".config", "systemd", "user");
37879
+ const unitPath = join66(unitDir, "chat-recall-watch.service");
37299
37880
  const unit = renderSystemdUnit(watchJs, node, logFile);
37300
37881
  mkdirSync22(unitDir, { recursive: true });
37301
37882
  writeFileSync22(unitPath, unit);
@@ -37381,8 +37962,8 @@ function renderSystemdUnit(watchJs, node, logFile) {
37381
37962
  }
37382
37963
  function installLaunchd(watchJs, node, logFile) {
37383
37964
  const label = "com.chat-recall.watch";
37384
- const plistDir = join65(homedir23(), "Library", "LaunchAgents");
37385
- const plistPath = join65(plistDir, `${label}.plist`);
37965
+ const plistDir = join66(homedir24(), "Library", "LaunchAgents");
37966
+ const plistPath = join66(plistDir, `${label}.plist`);
37386
37967
  const plist = renderLaunchdPlist(watchJs, node, logFile, label);
37387
37968
  mkdirSync22(plistDir, { recursive: true });
37388
37969
  writeFileSync22(plistPath, plist);
@@ -37438,7 +38019,7 @@ function uninstallService() {
37438
38019
  removed = true;
37439
38020
  } catch {
37440
38021
  }
37441
- const unitPath = join65(homedir23(), ".config", "systemd", "user", "chat-recall-watch.service");
38022
+ const unitPath = join66(homedir24(), ".config", "systemd", "user", "chat-recall-watch.service");
37442
38023
  if (existsSync59(unitPath)) {
37443
38024
  rmSync11(unitPath, { force: true });
37444
38025
  removed = true;
@@ -37450,7 +38031,7 @@ function uninstallService() {
37450
38031
  return removed;
37451
38032
  }
37452
38033
  if (process.platform === "darwin") {
37453
- const plistPath = join65(homedir23(), "Library", "LaunchAgents", "com.chat-recall.watch.plist");
38034
+ const plistPath = join66(homedir24(), "Library", "LaunchAgents", "com.chat-recall.watch.plist");
37454
38035
  try {
37455
38036
  execSync5(`launchctl unload "${plistPath}" 2>/dev/null`, { stdio: "ignore" });
37456
38037
  } catch {
@@ -37987,8 +38568,8 @@ import { config } from "dotenv";
37987
38568
  import { Command } from "commander";
37988
38569
  import chalk2 from "chalk";
37989
38570
  import { existsSync as existsSync60, readFileSync as readFileSync53, writeFileSync as writeFileSync23 } from "fs";
37990
- import { homedir as homedir24 } from "os";
37991
- import { join as join66, resolve as resolve2, dirname as dirname29, basename as basename29 } from "path";
38571
+ import { homedir as homedir25 } from "os";
38572
+ import { join as join67, resolve as resolve2, dirname as dirname29, basename as basename29 } from "path";
37992
38573
 
37993
38574
  // ../engine/dist/core/score-tier.js
37994
38575
  var STRONG_RATIO = 0.85;
@@ -38415,10 +38996,10 @@ program.command("init").description("Set up chat-recall: connect to your server,
38415
38996
  } else if (target) {
38416
38997
  }
38417
38998
  if (!options.skipMcp) {
38418
- const projectRoot = join66(import.meta.dirname, "..");
38999
+ const projectRoot = join67(import.meta.dirname, "..");
38419
39000
  let mcpBinOnPath = false;
38420
39001
  mcpBinOnPath = isOnPath("chat-recall-mcp");
38421
- const launch = mcpBinOnPath ? { command: "chat-recall-mcp" } : { command: "node", args: [join66(projectRoot, "dist", "mcp-relay.js")] };
39002
+ const launch = mcpBinOnPath ? { command: "chat-recall-mcp" } : { command: "node", args: [join67(projectRoot, "dist", "mcp-relay.js")] };
38422
39003
  const MCP_ENV = { NODE_OPTIONS: "--max-old-space-size=1024" };
38423
39004
  const { registerMcpEverywhere: registerMcpEverywhere2 } = await Promise.resolve().then(() => (init_mcp_clients(), mcp_clients_exports));
38424
39005
  const MCP_CLIENT_FOR_BIN = {
@@ -38459,7 +39040,7 @@ program.command("init").description("Set up chat-recall: connect to your server,
38459
39040
  const detected = checkCodeindexStatus2();
38460
39041
  if (detected.installed && !forceInstall) {
38461
39042
  if (!options.skipMcp) {
38462
- const mcpJsonPath = join66(homedir24(), ".mcp.json");
39043
+ const mcpJsonPath = join67(homedir25(), ".mcp.json");
38463
39044
  const reg = registerCodeindexMcp2(mcpJsonPath, detected.path);
38464
39045
  }
38465
39046
  } else if (forceInstall) {
@@ -38468,7 +39049,7 @@ program.command("init").description("Set up chat-recall: connect to your server,
38468
39049
  if (result.installed) {
38469
39050
  const sizeMb = result.size ? `${(result.size / 1024 / 1024).toFixed(1)} MB` : "?";
38470
39051
  if (!options.skipMcp) {
38471
- const mcpJsonPath = join66(homedir24(), ".mcp.json");
39052
+ const mcpJsonPath = join67(homedir25(), ".mcp.json");
38472
39053
  const reg = registerCodeindexMcp2(mcpJsonPath, CODEINDEX_BIN_PATH2);
38473
39054
  }
38474
39055
  } else if (!result.prebuiltAvailable) {
@@ -39088,7 +39669,7 @@ program.command("doctor").description("Quick health check across login, server,
39088
39669
  }
39089
39670
  }
39090
39671
  }
39091
- const credFile = join66(getDataDir(), "credentials.json");
39672
+ const credFile = join67(getDataDir(), "credentials.json");
39092
39673
  if (!existsSync61(credFile)) {
39093
39674
  note(false, "Credentials file", `missing \u2014 run \`chat-recall login <server-url>\``);
39094
39675
  } else {
@@ -39113,7 +39694,7 @@ program.command("doctor").description("Quick health check across login, server,
39113
39694
  note(false, label, `${settingsFile} is not valid JSON, so no hook in it runs`);
39114
39695
  continue;
39115
39696
  }
39116
- const legacy = join66(dirname29(settingsFile), "hooks.json");
39697
+ const legacy = join67(dirname29(settingsFile), "hooks.json");
39117
39698
  try {
39118
39699
  const stranded = existsSync61(legacy) ? Object.values(JSON.parse(readFileSync54(legacy, "utf-8")).hooks || {}).flat().filter(isOurEntry2).length : 0;
39119
39700
  if (stranded) note(false, `Old hook file (${profile})`, `${stranded} chat-recall entr${stranded === 1 ? "y" : "ies"} in ${legacy}, which Claude Code does not read \u2014 run \`chat-recall install-hooks\` to move them`);
@@ -39161,12 +39742,32 @@ program.command("doctor").description("Quick health check across login, server,
39161
39742
  } catch (err) {
39162
39743
  note(false, "Decision guard", `check failed: ${err}`);
39163
39744
  }
39745
+ try {
39746
+ const reg = await Promise.resolve().then(() => (init_message_registration(), message_registration_exports));
39747
+ for (const target2 of reg.messageTargets()) {
39748
+ if (!existsSync61(target2.homeDir)) continue;
39749
+ const label = `Messages \u2014 ${target2.label}`;
39750
+ let registered = existsSync61(target2.configPath);
39751
+ if (registered) {
39752
+ try {
39753
+ const text = readFileSync54(target2.configPath, "utf-8");
39754
+ registered = text.includes("chat_recall_messages_") || reg.isOurPluginSource(text);
39755
+ } catch {
39756
+ registered = false;
39757
+ }
39758
+ }
39759
+ const detail = !registered ? "not registered \u2014 run `chat-recall install-hooks`" : target2.tool === "codex" ? `${target2.configPath} \u2014 approve it in Codex with /hooks` : target2.configPath;
39760
+ note(registered, label, detail);
39761
+ }
39762
+ } catch (err) {
39763
+ note(false, "Messages", `check failed: ${err}`);
39764
+ }
39164
39765
  try {
39165
39766
  const { skillTargets: skillTargets2, bundledSkillNames: bundledSkillNames2 } = await Promise.resolve().then(() => (init_install_skills(), install_skills_exports));
39166
39767
  const want = bundledSkillNames2().length;
39167
39768
  for (const t of skillTargets2()) {
39168
39769
  if (!t.available) continue;
39169
- const have = want === 0 ? 0 : bundledSkillNames2().filter((n) => existsSync61(join66(t.dir, n, ".chat-recall-managed"))).length;
39770
+ const have = want === 0 ? 0 : bundledSkillNames2().filter((n) => existsSync61(join67(t.dir, n, ".chat-recall-managed"))).length;
39170
39771
  note(
39171
39772
  have === want,
39172
39773
  `Skills \u2014 ${t.label}`,
@@ -39241,12 +39842,12 @@ program.command("doctor").description("Quick health check across login, server,
39241
39842
  note(watchRunning, "Watch daemon", watchRunning ? "running" : "not running (run `chat-recall watch --install-service` to keep collection running)");
39242
39843
  const dataDir = getDataDir();
39243
39844
  const legacyPaths = [
39244
- join66(dataDir, "cache.db"),
39245
- join66(dataDir, "cache.db-wal"),
39246
- join66(dataDir, "cache.db-shm"),
39247
- join66(dataDir, "index", "lancedb"),
39248
- join66(dataDir, "index", "knowledge_graph.db"),
39249
- join66(dataDir, "index", "metadata.db")
39845
+ join67(dataDir, "cache.db"),
39846
+ join67(dataDir, "cache.db-wal"),
39847
+ join67(dataDir, "cache.db-shm"),
39848
+ join67(dataDir, "index", "lancedb"),
39849
+ join67(dataDir, "index", "knowledge_graph.db"),
39850
+ join67(dataDir, "index", "metadata.db")
39250
39851
  ];
39251
39852
  const legacyPresent = legacyPaths.filter((p) => existsSync61(p));
39252
39853
  if (opts.purgeLocal) {
@@ -39319,7 +39920,7 @@ companions.command("install").description("Install codeindex (downloads from mun
39319
39920
  if (result.installed) {
39320
39921
  const sizeMb = result.size ? `${(result.size / 1024 / 1024).toFixed(1)} MB` : "?";
39321
39922
  console.log(chalk2.green(`\u2713 codeindex installed (${sizeMb}) \u2192 ${result.path}`));
39322
- const mcpJsonPath = join66(homedir24(), ".mcp.json");
39923
+ const mcpJsonPath = join67(homedir25(), ".mcp.json");
39323
39924
  const reg = registerCodeindexMcp2(mcpJsonPath, CODEINDEX_BIN_PATH2);
39324
39925
  if (reg.added) console.log(chalk2.dim(` Registered as MCP server in ${mcpJsonPath}`));
39325
39926
  else console.log(chalk2.dim(` Already registered as MCP server`));
@@ -39341,7 +39942,7 @@ companions.command("uninstall").description("Remove the codeindex binary chat-re
39341
39942
  const r = uninstallCodeindex2();
39342
39943
  if (r.removed) console.log(chalk2.green(`\u2713 Removed ${r.path}`));
39343
39944
  else console.log(chalk2.dim(` Nothing to remove at ${r.path}`));
39344
- const mcpJsonPath = join66(homedir24(), ".mcp.json");
39945
+ const mcpJsonPath = join67(homedir25(), ".mcp.json");
39345
39946
  const u = unregisterCodeindexMcp2(mcpJsonPath);
39346
39947
  if (u.removed) console.log(chalk2.dim(` Unregistered MCP server from ${mcpJsonPath}`));
39347
39948
  });
@@ -39894,8 +40495,8 @@ tasks.command("pull [dir]").description("Write TEAM_TASKS.md for your tasks in t
39894
40495
  const { resolveProjectId: resolveProjectId2 } = await Promise.resolve().then(() => (init_project_resolver(), project_resolver_exports));
39895
40496
  const { renderTeamTasksMd: renderTeamTasksMd2, parseTeamTasksFile: parseTeamTasksFile2 } = await Promise.resolve().then(() => (init_project_tasks(), project_tasks_exports));
39896
40497
  const { writeFileSync: writeFileSync24, readFileSync: readFileSync54, existsSync: existsSync61 } = await import("node:fs");
39897
- const { join: join67 } = await import("node:path");
39898
- const file = join67(cwd, "TEAM_TASKS.md");
40498
+ const { join: join68 } = await import("node:path");
40499
+ const file = join68(cwd, "TEAM_TASKS.md");
39899
40500
  if (!opts.force && existsSync61(file) && parseTeamTasksFile2(readFileSync54(file, "utf8")).length > 0) {
39900
40501
  console.error(chalk2.red("TEAM_TASKS.md has unpushed edits."), "Run", chalk2.bold("chat-recall tasks push"), "first, or", chalk2.bold("tasks pull --force"), "to discard.");
39901
40502
  process.exit(1);
@@ -39916,8 +40517,8 @@ tasks.command("push [dir]").description("Push TEAM_TASKS.md status edits back to
39916
40517
  try {
39917
40518
  const { parseTeamTasksFile: parseTeamTasksFile2 } = await Promise.resolve().then(() => (init_project_tasks(), project_tasks_exports));
39918
40519
  const { readFileSync: readFileSync54, existsSync: existsSync61 } = await import("node:fs");
39919
- const { join: join67 } = await import("node:path");
39920
- const file = join67(cwd, "TEAM_TASKS.md");
40520
+ const { join: join68 } = await import("node:path");
40521
+ const file = join68(cwd, "TEAM_TASKS.md");
39921
40522
  if (!existsSync61(file)) {
39922
40523
  console.error(chalk2.red("no TEAM_TASKS.md here \u2014"), "run", chalk2.bold("chat-recall tasks pull"), "first");
39923
40524
  process.exit(1);
@@ -40412,7 +41013,8 @@ program.command("install-hooks").description("Install the chat-recall hooks into
40412
41013
  const r2 = await uninstallHooks2();
40413
41014
  for (const f of r2.files) console.log(chalk2.green(`\u2713 Removed chat-recall hooks from ${f}`));
40414
41015
  for (const g of r2.guardRemoved) console.log(chalk2.green(`\u2713 Removed the guard from ${g.label} (${g.configPath})`));
40415
- if (r2.removed === 0 && r2.guardRemoved.length === 0) console.log(chalk2.dim("No chat-recall hooks were registered."));
41016
+ for (const m of r2.messagesRemoved) console.log(chalk2.green(`\u2713 Removed the message hook from ${m.label} (${m.configPath})`));
41017
+ if (r2.removed === 0 && r2.guardRemoved.length === 0 && r2.messagesRemoved.length === 0) console.log(chalk2.dim("No chat-recall hooks were registered."));
40416
41018
  console.log(chalk2.dim("The MCP server will not put them back. Run `chat-recall install-hooks` to install them again."));
40417
41019
  return;
40418
41020
  }
@@ -40432,6 +41034,10 @@ program.command("install-hooks").description("Install the chat-recall hooks into
40432
41034
  console.log(chalk2.green(`\u2713 Registered the guard for ${g.label}`));
40433
41035
  if (g.note) console.log(chalk2.yellow(` ! ${g.note}`));
40434
41036
  }
41037
+ for (const m of r.messageTargets) {
41038
+ console.log(chalk2.green(`\u2713 Registered the message hook for ${m.label} (${m.configPath})`));
41039
+ if (m.note) console.log(chalk2.yellow(` ! ${m.note}`));
41040
+ }
40435
41041
  if (r.shellSkipped) {
40436
41042
  console.log(chalk2.yellow("The five shell hooks are not installed on Windows: Claude Code runs hooks through cmd.exe, which cannot run them."));
40437
41043
  console.log(chalk2.dim(" The task-board and message hooks are installed. Under WSL, run this inside the WSL shell to get all of them."));
@@ -40709,8 +41315,8 @@ include.command("list", { isDefault: true }).description("Show paths opted back
40709
41315
  include.command("project <path>").description("Re-permit a path under a personal folder (substring match; e.g. ~/Documents/code)").action(async (path) => {
40710
41316
  const { loadSettings: loadSettings2, saveSettings: saveSettings2 } = await Promise.resolve().then(() => (init_settings(), settings_exports));
40711
41317
  const { resolve: resolve3 } = await import("node:path");
40712
- const { homedir: homedir25 } = await import("node:os");
40713
- const abs = resolve3(path.replace(/^~(?=\/|$)/, homedir25()));
41318
+ const { homedir: homedir26 } = await import("node:os");
41319
+ const abs = resolve3(path.replace(/^~(?=\/|$)/, homedir26()));
40714
41320
  const s = loadSettings2();
40715
41321
  s.sync.includeProjects = s.sync.includeProjects || [];
40716
41322
  if (s.sync.includeProjects.includes(abs)) {
@@ -40724,8 +41330,8 @@ include.command("project <path>").description("Re-permit a path under a personal
40724
41330
  include.command("remove <path>").description("Undo an opt-in (personal folder goes back to skipped)").action(async (path) => {
40725
41331
  const { loadSettings: loadSettings2, saveSettings: saveSettings2 } = await Promise.resolve().then(() => (init_settings(), settings_exports));
40726
41332
  const { resolve: resolve3 } = await import("node:path");
40727
- const { homedir: homedir25 } = await import("node:os");
40728
- const abs = resolve3(path.replace(/^~(?=\/|$)/, homedir25()));
41333
+ const { homedir: homedir26 } = await import("node:os");
41334
+ const abs = resolve3(path.replace(/^~(?=\/|$)/, homedir26()));
40729
41335
  const s = loadSettings2();
40730
41336
  const before = (s.sync.includeProjects || []).length;
40731
41337
  s.sync.includeProjects = (s.sync.includeProjects || []).filter((p) => p !== path && p !== abs);
@@ -40864,8 +41470,8 @@ program.command("projects").description("List distinct project ids discovered on
40864
41470
  exclude.command("project <path>").description("Exclude a project path from syncing (substring match on the project path; e.g. ~/.claude-pr-bot)").action(async (path) => {
40865
41471
  const { loadSettings: loadSettings2, saveSettings: saveSettings2 } = await Promise.resolve().then(() => (init_settings(), settings_exports));
40866
41472
  const { resolve: resolve3 } = await import("node:path");
40867
- const { homedir: homedir25 } = await import("node:os");
40868
- const abs = resolve3(path.replace(/^~(?=\/|$)/, homedir25()));
41473
+ const { homedir: homedir26 } = await import("node:os");
41474
+ const abs = resolve3(path.replace(/^~(?=\/|$)/, homedir26()));
40869
41475
  const s = loadSettings2();
40870
41476
  if (s.sync.excludeProjects.includes(abs)) {
40871
41477
  console.log(chalk2.dim(`Already excluded: ${abs}`));
@@ -40894,8 +41500,8 @@ exclude.command("tool <tool>").description("Exclude an AI tool entirely (claude
40894
41500
  exclude.command("remove <value>").description("Remove an exclusion (tool name or project path)").action(async (value) => {
40895
41501
  const { loadSettings: loadSettings2, saveSettings: saveSettings2 } = await Promise.resolve().then(() => (init_settings(), settings_exports));
40896
41502
  const { resolve: resolve3 } = await import("node:path");
40897
- const { homedir: homedir25 } = await import("node:os");
40898
- const abs = resolve3(value.replace(/^~(?=\/|$)/, homedir25()));
41503
+ const { homedir: homedir26 } = await import("node:os");
41504
+ const abs = resolve3(value.replace(/^~(?=\/|$)/, homedir26()));
40899
41505
  const s = loadSettings2();
40900
41506
  const beforeTools = s.sync.excludeTools.length;
40901
41507
  const beforeProjects = s.sync.excludeProjects.length;