omp-fabric 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +1 -0
  3. package/dist/agents/handoff.d.ts +1 -1
  4. package/dist/agents/handoff.d.ts.map +1 -1
  5. package/dist/agents/types.d.ts +1 -1
  6. package/dist/agents/types.d.ts.map +1 -1
  7. package/dist/chunks/{chunk-TLSJXU4F.js → chunk-5YGOVBOZ.js} +179 -10
  8. package/dist/chunks/chunk-5YGOVBOZ.js.map +7 -0
  9. package/dist/chunks/{chunk-CVLO4GNW.js → chunk-EQNNENN6.js} +3 -3
  10. package/dist/chunks/{chunk-YPYVUGON.js → chunk-JOWMM3EX.js} +6 -6
  11. package/dist/chunks/chunk-JOWMM3EX.js.map +7 -0
  12. package/dist/chunks/{chunk-L2FNMIOW.js → chunk-QNRGTJGE.js} +2 -1
  13. package/dist/chunks/chunk-QNRGTJGE.js.map +7 -0
  14. package/dist/chunks/{chunk-WXZP5VWP.js → chunk-TQL7FKMG.js} +3 -3
  15. package/dist/chunks/{chunk-Z6HEQPXX.js → chunk-WGFHMECI.js} +47 -1
  16. package/dist/chunks/{chunk-Z6HEQPXX.js.map → chunk-WGFHMECI.js.map} +2 -2
  17. package/dist/chunks/{chunk-EZPERYEG.js → chunk-XRJYPNTI.js} +56 -2
  18. package/dist/chunks/chunk-XRJYPNTI.js.map +7 -0
  19. package/dist/chunks/{chunk-KIREBD2V.js → chunk-ZP3S74LW.js} +2 -1
  20. package/dist/codemap/budget.d.ts +3 -0
  21. package/dist/codemap/budget.d.ts.map +1 -0
  22. package/dist/codemap/cascade.d.ts +3 -0
  23. package/dist/codemap/cascade.d.ts.map +1 -0
  24. package/dist/codemap/symbols.d.ts +3 -0
  25. package/dist/codemap/symbols.d.ts.map +1 -0
  26. package/dist/codemap/types.d.ts +58 -0
  27. package/dist/codemap/types.d.ts.map +1 -0
  28. package/dist/compaction/hook.js +1 -1
  29. package/dist/config.d.ts +11 -0
  30. package/dist/config.d.ts.map +1 -1
  31. package/dist/core/system-guidance.d.ts.map +1 -1
  32. package/dist/fabric-runtime-state.d.ts.map +1 -1
  33. package/dist/fabric-runtime-state.js +1605 -344
  34. package/dist/fabric-runtime-state.js.map +4 -4
  35. package/dist/index.js +7 -7
  36. package/dist/index.js.map +1 -1
  37. package/dist/prewalk/handoff.d.ts +2 -1
  38. package/dist/prewalk/handoff.d.ts.map +1 -1
  39. package/dist/prewalk/retirement.d.ts +35 -0
  40. package/dist/prewalk/retirement.d.ts.map +1 -0
  41. package/dist/providers/codemap-provider.d.ts +14 -0
  42. package/dist/providers/codemap-provider.d.ts.map +1 -0
  43. package/dist/residency/host.js +5 -5
  44. package/dist/residency/omp-entry.js +5 -5
  45. package/dist/runtime/core-override-guest-types.js +1 -1
  46. package/dist/runtime/guest-types.d.ts +1 -1
  47. package/dist/runtime/guest-types.d.ts.map +1 -1
  48. package/dist/runtime/guest-types.js +1 -1
  49. package/dist/runtime/node-process-runtime.js +1 -1
  50. package/dist/runtime/quickjs-runtime.d.ts +1 -1
  51. package/dist/runtime/quickjs-runtime.d.ts.map +1 -1
  52. package/dist/runtime/quickjs-runtime.js +1 -1
  53. package/dist/ui/settings.d.ts.map +1 -1
  54. package/dist/ui/settings.js +90 -1
  55. package/dist/ui/settings.js.map +2 -2
  56. package/docs/architecture.md +1 -1
  57. package/docs/codemap.md +89 -0
  58. package/docs/configuration.md +1 -1
  59. package/package.json +4 -1
  60. package/dist/chunks/chunk-EZPERYEG.js.map +0 -7
  61. package/dist/chunks/chunk-L2FNMIOW.js.map +0 -7
  62. package/dist/chunks/chunk-TLSJXU4F.js.map +0 -7
  63. package/dist/chunks/chunk-YPYVUGON.js.map +0 -7
  64. /package/dist/chunks/{chunk-CVLO4GNW.js.map → chunk-EQNNENN6.js.map} +0 -0
  65. /package/dist/chunks/{chunk-WXZP5VWP.js.map → chunk-TQL7FKMG.js.map} +0 -0
  66. /package/dist/chunks/{chunk-KIREBD2V.js.map → chunk-ZP3S74LW.js.map} +0 -0
@@ -33,7 +33,7 @@ import {
33
33
  repairFabricGuestCode,
34
34
  resolveFabricIdentity,
35
35
  runFabricHandoffAtBoundary
36
- } from "./chunks/chunk-TLSJXU4F.js";
36
+ } from "./chunks/chunk-5YGOVBOZ.js";
37
37
  import "./chunks/chunk-7VIQNUPS.js";
38
38
  import {
39
39
  AgentTranscriptReader,
@@ -94,7 +94,7 @@ import {
94
94
  resolveAgentCwd,
95
95
  resolveOmpBinary,
96
96
  validateAgentCwdRequest
97
- } from "./chunks/chunk-WXZP5VWP.js";
97
+ } from "./chunks/chunk-TQL7FKMG.js";
98
98
  import "./chunks/chunk-VPPIJRNZ.js";
99
99
  import {
100
100
  executeFile,
@@ -104,7 +104,7 @@ import {
104
104
  import "./chunks/chunk-CT2AJ2UI.js";
105
105
  import {
106
106
  checkedHandoffCompaction
107
- } from "./chunks/chunk-YPYVUGON.js";
107
+ } from "./chunks/chunk-JOWMM3EX.js";
108
108
  import {
109
109
  DEFAULT_FABRIC_CONFIG,
110
110
  FUZZY_RESOLUTION_MARKERS,
@@ -114,7 +114,7 @@ import {
114
114
  resolveAgentDir,
115
115
  resolveAvailableOmpModel,
116
116
  resolveFabricModel
117
- } from "./chunks/chunk-EZPERYEG.js";
117
+ } from "./chunks/chunk-XRJYPNTI.js";
118
118
  import {
119
119
  FABRIC_ACTOR_HOST_EVENTS,
120
120
  isFabricActorHostEvent,
@@ -155,8 +155,9 @@ import {
155
155
  MAX_PRESERVE_ITEM_CHARS,
156
156
  compactionRequestBoundsError,
157
157
  encodeCompactionRequest,
158
+ estimateTokens,
158
159
  fabricExecTitleHintCached
159
- } from "./chunks/chunk-KIREBD2V.js";
160
+ } from "./chunks/chunk-ZP3S74LW.js";
160
161
  import "./chunks/chunk-3J7BKUNG.js";
161
162
  import "./chunks/chunk-4HQDSTHN.js";
162
163
  import {
@@ -171,7 +172,7 @@ import {
171
172
  } from "./chunks/chunk-6N4XGAZY.js";
172
173
 
173
174
  // src/fabric-runtime-state.ts
174
- import path16 from "node:path";
175
+ import path18 from "node:path";
175
176
  import { fileURLToPath as fileURLToPath2 } from "node:url";
176
177
 
177
178
  // src/actors/global-registry.ts
@@ -425,36 +426,36 @@ var GlobalActorRegistry = class {
425
426
  if (!Array.isArray(records)) return;
426
427
  for (const value of records) {
427
428
  if (typeof value !== "object" || value === null || Array.isArray(value)) continue;
428
- const record = value;
429
- if (typeof record.id !== "string" || !/^[a-f0-9]{32}$/.test(record.id) || typeof record.name !== "string" || !ACTOR_NAME_PATTERN.test(record.name) || typeof record.instructions !== "string" || Buffer.byteLength(record.instructions, "utf8") > this.#maxBytes || typeof record.createdAt !== "number") {
429
+ const record2 = value;
430
+ if (typeof record2.id !== "string" || !/^[a-f0-9]{32}$/.test(record2.id) || typeof record2.name !== "string" || !ACTOR_NAME_PATTERN.test(record2.name) || typeof record2.instructions !== "string" || Buffer.byteLength(record2.instructions, "utf8") > this.#maxBytes || typeof record2.createdAt !== "number") {
430
431
  continue;
431
432
  }
432
- const events = Array.isArray(record.events) ? record.events.filter((event) => HOST_EVENTS.has(event)) : [];
433
- const topics = Array.isArray(record.topics) ? record.topics.filter(
433
+ const events = Array.isArray(record2.events) ? record2.events.filter((event) => HOST_EVENTS.has(event)) : [];
434
+ const topics = Array.isArray(record2.topics) ? record2.topics.filter(
434
435
  (topic) => typeof topic === "string" && TOPIC_PATTERN.test(topic)
435
436
  ) : [];
436
- const delivery = record.delivery === "steer" || record.delivery === "followUp" || record.delivery === "nextTurn" ? record.delivery : "mailbox";
437
- const responseMode = record.responseMode === "directive" ? "directive" : "text";
438
- const triggerTurn = (delivery === "steer" || delivery === "followUp") && record.triggerTurn === true;
439
- const coalesce = record.coalesce !== false;
440
- const residency = record.residency === "durable" ? "durable" : "session";
441
- const runner = record.runner === "claude" ? "claude" : "omp";
442
- const thinking = isFabricThinking(record.thinking) ? record.thinking : void 0;
443
- const tools = Array.isArray(record.tools) ? record.tools.filter((tool) => typeof tool === "string") : void 0;
444
- const transport = record.transport !== void 0 && TRANSPORTS.has(record.transport) ? record.transport : void 0;
445
- const timeoutMs = typeof record.timeoutMs === "number" ? record.timeoutMs : void 0;
446
- const extensions = typeof record.extensions === "boolean" ? record.extensions : void 0;
437
+ const delivery = record2.delivery === "steer" || record2.delivery === "followUp" || record2.delivery === "nextTurn" ? record2.delivery : "mailbox";
438
+ const responseMode = record2.responseMode === "directive" ? "directive" : "text";
439
+ const triggerTurn = (delivery === "steer" || delivery === "followUp") && record2.triggerTurn === true;
440
+ const coalesce = record2.coalesce !== false;
441
+ const residency = record2.residency === "durable" ? "durable" : "session";
442
+ const runner = record2.runner === "claude" ? "claude" : "omp";
443
+ const thinking = isFabricThinking(record2.thinking) ? record2.thinking : void 0;
444
+ const tools = Array.isArray(record2.tools) ? record2.tools.filter((tool) => typeof tool === "string") : void 0;
445
+ const transport = record2.transport !== void 0 && TRANSPORTS.has(record2.transport) ? record2.transport : void 0;
446
+ const timeoutMs = typeof record2.timeoutMs === "number" ? record2.timeoutMs : void 0;
447
+ const extensions = typeof record2.extensions === "boolean" ? record2.extensions : void 0;
447
448
  let requires;
448
449
  try {
449
- requires = normalizeRequirements(record.requires);
450
+ requires = normalizeRequirements(record2.requires);
450
451
  } catch {
451
452
  continue;
452
453
  }
453
- const validWhile = record.validWhile?.version === 1 && typeof record.validWhile.source === "string" && record.validWhile.source.length <= 16e3 ? clone(record.validWhile) : void 0;
454
+ const validWhile = record2.validWhile?.version === 1 && typeof record2.validWhile.source === "string" && record2.validWhile.source.length <= 16e3 ? clone(record2.validWhile) : void 0;
454
455
  const def = {
455
- id: record.id,
456
- name: record.name,
457
- instructions: record.instructions,
456
+ id: record2.id,
457
+ name: record2.name,
458
+ instructions: record2.instructions,
458
459
  events,
459
460
  topics,
460
461
  delivery,
@@ -463,9 +464,9 @@ var GlobalActorRegistry = class {
463
464
  coalesce,
464
465
  residency,
465
466
  runner,
466
- createdAt: record.createdAt,
467
- updatedAt: typeof record.updatedAt === "number" ? record.updatedAt : record.createdAt,
468
- ...typeof record.model === "string" && record.model ? { model: record.model } : {},
467
+ createdAt: record2.createdAt,
468
+ updatedAt: typeof record2.updatedAt === "number" ? record2.updatedAt : record2.createdAt,
469
+ ...typeof record2.model === "string" && record2.model ? { model: record2.model } : {},
469
470
  ...thinking ? { thinking } : {},
470
471
  ...tools ? { tools } : {},
471
472
  ...transport ? { transport } : {},
@@ -793,10 +794,10 @@ var normalizeRegistration = (registration, fallbackLabel) => {
793
794
  }
794
795
  };
795
796
  };
796
- var beginCleanup = (record) => {
797
- if (record.cleanupStarted) return;
798
- record.cleanupStarted = true;
799
- record.beforeCleanup?.();
797
+ var beginCleanup = (record2) => {
798
+ if (record2.cleanupStarted) return;
799
+ record2.cleanupStarted = true;
800
+ record2.beforeCleanup?.();
800
801
  };
801
802
  var closeIterator = async (iterator, disposers) => {
802
803
  if (!iterator.return) return;
@@ -809,20 +810,20 @@ var closeIterator = async (iterator, disposers) => {
809
810
  var checkTarget = async (guard) => {
810
811
  if (guard && !await guard()) throw new FabricEffectDivertedError();
811
812
  };
812
- var driveIterator = async (iterator, record, guard) => {
813
+ var driveIterator = async (iterator, record2, guard) => {
813
814
  try {
814
815
  for (; ; ) {
815
- if (!record.armed) {
816
- beginCleanup(record);
817
- await closeIterator(iterator, record.disposers);
816
+ if (!record2.armed) {
817
+ beginCleanup(record2);
818
+ await closeIterator(iterator, record2.disposers);
818
819
  return;
819
820
  }
820
821
  await checkTarget(guard);
821
822
  const step = await iterator.next();
822
- if (!step.done) collectDisposer(step.value, record.disposers);
823
- if (!record.armed) {
824
- beginCleanup(record);
825
- await closeIterator(iterator, record.disposers);
823
+ if (!step.done) collectDisposer(step.value, record2.disposers);
824
+ if (!record2.armed) {
825
+ beginCleanup(record2);
826
+ await closeIterator(iterator, record2.disposers);
826
827
  return;
827
828
  }
828
829
  if (step.done) {
@@ -833,8 +834,8 @@ var driveIterator = async (iterator, record, guard) => {
833
834
  } catch (error) {
834
835
  if (error instanceof FabricEffectDivertedError) {
835
836
  try {
836
- beginCleanup(record);
837
- await closeIterator(iterator, record.disposers);
837
+ beginCleanup(record2);
838
+ await closeIterator(iterator, record2.disposers);
838
839
  } catch (closeError) {
839
840
  throw new FabricEffectDivertedError(
840
841
  "Fabric effect target changed and iterator close failed",
@@ -845,19 +846,19 @@ var driveIterator = async (iterator, record, guard) => {
845
846
  throw error;
846
847
  }
847
848
  };
848
- var collectEffect = async (effect, record, guard) => {
849
+ var collectEffect = async (effect, record2, guard) => {
849
850
  const resolved = isPromiseLike(effect) ? await effect : effect;
850
851
  if (resolved === void 0 || resolved === null || typeof resolved === "function") {
851
- collectDisposer(resolved, record.disposers);
852
- if (record.armed) await checkTarget(guard);
852
+ collectDisposer(resolved, record2.disposers);
853
+ if (record2.armed) await checkTarget(guard);
853
854
  return;
854
855
  }
855
856
  if (isAsyncIterable(resolved)) {
856
- await driveIterator(resolved[Symbol.asyncIterator](), record, guard);
857
+ await driveIterator(resolved[Symbol.asyncIterator](), record2, guard);
857
858
  return;
858
859
  }
859
860
  if (isIterable(resolved)) {
860
- await driveIterator(resolved[Symbol.iterator](), record, guard);
861
+ await driveIterator(resolved[Symbol.iterator](), record2, guard);
861
862
  return;
862
863
  }
863
864
  throw new TypeError("Fabric effect returned an unsupported value");
@@ -876,10 +877,10 @@ var FabricEffectScope = class {
876
877
  }
877
878
  footprint(limit = Number.POSITIVE_INFINITY) {
878
879
  const effects = [];
879
- for (const record of this.#records) {
880
+ for (const record2 of this.#records) {
880
881
  if (effects.length >= limit) break;
881
- if (!record.disposed && record.effect) {
882
- effects.push({ ...record.effect, resources: [...record.effect.resources] });
882
+ if (!record2.disposed && record2.effect) {
883
+ effects.push({ ...record2.effect, resources: [...record2.effect.resources] });
883
884
  }
884
885
  }
885
886
  return effects;
@@ -889,7 +890,7 @@ var FabricEffectScope = class {
889
890
  throw new Error("Cannot create an effect on a disposing Fabric scope");
890
891
  }
891
892
  const normalized = normalizeRegistration(registration, "anonymous");
892
- const record = {
893
+ const record2 = {
893
894
  label: normalized.label,
894
895
  ...normalized.effect ? { effect: normalized.effect } : {},
895
896
  disposers: [],
@@ -902,9 +903,9 @@ var FabricEffectScope = class {
902
903
  ...hooks.beforeCleanup ? { beforeCleanup: hooks.beforeCleanup } : {}
903
904
  };
904
905
  const cleanupDisposers = async () => {
905
- beginCleanup(record);
906
+ beginCleanup(record2);
906
907
  const failures = [];
907
- for (const disposer of record.disposers.splice(0).reverse()) {
908
+ for (const disposer of record2.disposers.splice(0).reverse()) {
908
909
  try {
909
910
  await disposer();
910
911
  } catch (error) {
@@ -912,64 +913,64 @@ var FabricEffectScope = class {
912
913
  }
913
914
  }
914
915
  if (failures.length > 0) {
915
- throw new AggregateError(failures, `Fabric effect cleanup failed: ${record.label}`);
916
+ throw new AggregateError(failures, `Fabric effect cleanup failed: ${record2.label}`);
916
917
  }
917
918
  };
918
919
  let disposal;
919
- record.dispose = async () => {
920
- if (record.disposed) return disposal;
921
- record.disposed = true;
922
- record.armed = false;
920
+ record2.dispose = async () => {
921
+ if (record2.disposed) return disposal;
922
+ record2.disposed = true;
923
+ record2.armed = false;
923
924
  disposal = (async () => {
924
- await record.setup.catch(() => void 0);
925
+ await record2.setup.catch(() => void 0);
925
926
  await cleanupDisposers();
926
927
  })();
927
928
  return disposal;
928
929
  };
929
- this.#records.push(record);
930
- record.setup = (async () => {
930
+ this.#records.push(record2);
931
+ record2.setup = (async () => {
931
932
  try {
932
933
  if (this.#guard) await checkTarget(this.#guard);
933
- if (!record.armed) return;
934
- await collectEffect(setup(), record, this.#guard);
934
+ if (!record2.armed) return;
935
+ await collectEffect(setup(), record2, this.#guard);
935
936
  } catch (error) {
936
937
  try {
937
938
  await cleanupDisposers();
938
939
  } catch (cleanupError) {
939
940
  const failures = cleanupError instanceof AggregateError ? cleanupError.errors : [cleanupError];
940
941
  for (const failure of failures) {
941
- this.#setupCleanupFailures.push({ label: record.label, error: errorMessage(failure) });
942
+ this.#setupCleanupFailures.push({ label: record2.label, error: errorMessage(failure) });
942
943
  }
943
944
  throw new AggregateError(
944
945
  [error, cleanupError],
945
- `Fabric effect setup and rollback failed: ${record.label}`
946
+ `Fabric effect setup and rollback failed: ${record2.label}`
946
947
  );
947
948
  }
948
949
  throw error;
949
950
  }
950
951
  })();
951
952
  try {
952
- await record.setup;
953
+ await record2.setup;
953
954
  if (this.#state === "open") {
954
- const index = this.#records.indexOf(record);
955
+ const index = this.#records.indexOf(record2);
955
956
  if (index >= 0 && index !== this.#records.length - 1) {
956
957
  this.#records.splice(index, 1);
957
- this.#records.push(record);
958
+ this.#records.push(record2);
958
959
  }
959
960
  }
960
961
  } catch (error) {
961
- const index = this.#records.indexOf(record);
962
+ const index = this.#records.indexOf(record2);
962
963
  if (index >= 0) this.#records.splice(index, 1);
963
964
  throw error;
964
965
  }
965
- return record.dispose;
966
+ return record2.dispose;
966
967
  }
967
968
  defer(disposer, registration = "deferred") {
968
969
  if (this.#state !== "open") {
969
970
  throw new Error("Cannot defer cleanup on a disposing Fabric scope");
970
971
  }
971
972
  const normalized = normalizeRegistration(registration, "deferred");
972
- const record = {
973
+ const record2 = {
973
974
  label: normalized.label,
974
975
  ...normalized.effect ? { effect: normalized.effect } : {},
975
976
  disposers: [disposer],
@@ -981,13 +982,13 @@ var FabricEffectScope = class {
981
982
  cleanupStarted: false
982
983
  };
983
984
  let disposal;
984
- record.dispose = async () => {
985
- if (record.disposed) return disposal;
986
- record.disposed = true;
987
- record.armed = false;
985
+ record2.dispose = async () => {
986
+ if (record2.disposed) return disposal;
987
+ record2.disposed = true;
988
+ record2.armed = false;
988
989
  disposal = (async () => {
989
990
  const failures = [];
990
- for (const cleanup of record.disposers.splice(0).reverse()) {
991
+ for (const cleanup of record2.disposers.splice(0).reverse()) {
991
992
  try {
992
993
  await cleanup();
993
994
  } catch (error) {
@@ -995,29 +996,29 @@ var FabricEffectScope = class {
995
996
  }
996
997
  }
997
998
  if (failures.length > 0) {
998
- throw new AggregateError(failures, `Fabric effect cleanup failed: ${record.label}`);
999
+ throw new AggregateError(failures, `Fabric effect cleanup failed: ${record2.label}`);
999
1000
  }
1000
1001
  })();
1001
1002
  return disposal;
1002
1003
  };
1003
- this.#records.push(record);
1004
- return record.dispose;
1004
+ this.#records.push(record2);
1005
+ return record2.dispose;
1005
1006
  }
1006
1007
  dispose() {
1007
1008
  if (this.#cleanup) return this.#cleanup;
1008
1009
  this.#state = "disposing";
1009
1010
  this.#cleanup = (async () => {
1010
1011
  const failures = this.#setupCleanupFailures.splice(0);
1011
- for (const record of this.#records.splice(0).reverse()) {
1012
+ for (const record2 of this.#records.splice(0).reverse()) {
1012
1013
  try {
1013
- await record.dispose();
1014
+ await record2.dispose();
1014
1015
  } catch (error) {
1015
1016
  if (error instanceof AggregateError) {
1016
1017
  for (const nested of error.errors) {
1017
- failures.push({ label: record.label, error: errorMessage(nested) });
1018
+ failures.push({ label: record2.label, error: errorMessage(nested) });
1018
1019
  }
1019
1020
  } else {
1020
- failures.push({ label: record.label, error: errorMessage(error) });
1021
+ failures.push({ label: record2.label, error: errorMessage(error) });
1021
1022
  }
1022
1023
  }
1023
1024
  }
@@ -2218,10 +2219,10 @@ var FabricComponentSupervisor = class {
2218
2219
  adjacent.set(edge.from, targets);
2219
2220
  }
2220
2221
  const cycles = /* @__PURE__ */ new Map();
2221
- const visit = (node, path17, positions) => {
2222
+ const visit = (node, path19, positions) => {
2222
2223
  const position = positions.get(node);
2223
2224
  if (position !== void 0) {
2224
- const cycle = path17.slice(position);
2225
+ const cycle = path19.slice(position);
2225
2226
  const rotations = cycle.map((_, index) => [
2226
2227
  ...cycle.slice(index),
2227
2228
  ...cycle.slice(0, index)
@@ -2231,10 +2232,10 @@ var FabricComponentSupervisor = class {
2231
2232
  cycles.set(canonical.join("\0"), canonical);
2232
2233
  return;
2233
2234
  }
2234
- if (path17.length > this.#components.size) return;
2235
- const nextPositions = new Map(positions).set(node, path17.length);
2235
+ if (path19.length > this.#components.size) return;
2236
+ const nextPositions = new Map(positions).set(node, path19.length);
2236
2237
  for (const target of adjacent.get(node) ?? []) {
2237
- visit(target, [...path17, node], nextPositions);
2238
+ visit(target, [...path19, node], nextPositions);
2238
2239
  }
2239
2240
  };
2240
2241
  for (const id of this.#components.keys()) visit(id, [], /* @__PURE__ */ new Map());
@@ -2736,18 +2737,18 @@ var finiteNumber = (value) => typeof value === "number" && Number.isFinite(value
2736
2737
  var nonEmptyString = (value) => typeof value === "string" && value.length > 0 ? value : void 0;
2737
2738
  var decodeOutcome = (raw) => {
2738
2739
  if (typeof raw !== "object" || raw === null) return void 0;
2739
- const record = raw;
2740
- const at = finiteNumber(record.at);
2741
- const requestedBy = nonEmptyString(record.requestedBy);
2742
- const status = record.status;
2740
+ const record2 = raw;
2741
+ const at = finiteNumber(record2.at);
2742
+ const requestedBy = nonEmptyString(record2.requestedBy);
2743
+ const status = record2.status;
2743
2744
  if (at === void 0 || requestedBy === void 0) return void 0;
2744
2745
  if (status !== "committed" && status !== "cancelled" && status !== "failed" && status !== "skipped") {
2745
2746
  return void 0;
2746
2747
  }
2747
- const summary = nonEmptyString(record.summary);
2748
- const error = nonEmptyString(record.error);
2749
- const tokensBefore = finiteNumber(record.tokensBefore);
2750
- const estimatedTokensAfter = finiteNumber(record.estimatedTokensAfter);
2748
+ const summary = nonEmptyString(record2.summary);
2749
+ const error = nonEmptyString(record2.error);
2750
+ const tokensBefore = finiteNumber(record2.tokensBefore);
2751
+ const estimatedTokensAfter = finiteNumber(record2.estimatedTokensAfter);
2751
2752
  return {
2752
2753
  at,
2753
2754
  requestedBy,
@@ -2964,7 +2965,7 @@ var FabricExecutionService = class {
2964
2965
  })) ?? []
2965
2966
  ) : void 0;
2966
2967
  const code = repairFabricGuestCode(options.code);
2967
- const checked = dependencies.typeCheckFabricCode(
2968
+ const checked2 = dependencies.typeCheckFabricCode(
2968
2969
  code,
2969
2970
  dependencies.guestTypeDeclarations(effectiveFullCodeMode, {
2970
2971
  excludeGlobals: [...unavailable.keys()],
@@ -2972,8 +2973,8 @@ var FabricExecutionService = class {
2972
2973
  ...coreOverrideDeclarations ? { coreOverrides: coreOverrideDeclarations } : {}
2973
2974
  })
2974
2975
  );
2975
- if (checked.errors.length > 0) {
2976
- for (const error of checked.errors) {
2976
+ if (checked2.errors.length > 0) {
2977
+ for (const error of checked2.errors) {
2977
2978
  const missing = /^Cannot find name '([^']+)'/.exec(error.message);
2978
2979
  const reason = missing?.[1] ? unavailable.get(missing[1]) : void 0;
2979
2980
  if (missing && reason) {
@@ -2990,10 +2991,10 @@ var FabricExecutionService = class {
2990
2991
  trace: traceRecorder.seal(
2991
2992
  "failed",
2992
2993
  [],
2993
- `Type checking failed (${checked.errors.length} ${checked.errors.length === 1 ? "error" : "errors"})`
2994
+ `Type checking failed (${checked2.errors.length} ${checked2.errors.length === 1 ? "error" : "errors"})`
2994
2995
  ),
2995
2996
  elapsedMs: performance.now() - startedAt,
2996
- typeErrors: checked.errors
2997
+ typeErrors: checked2.errors
2997
2998
  };
2998
2999
  }
2999
3000
  const classifierUsages = [];
@@ -3424,8 +3425,8 @@ var FabricExecutionService = class {
3424
3425
  memoryLimitBytes: this.config.executor.memoryLimitBytes,
3425
3426
  maxLogChars: this.config.executor.maxOutputChars,
3426
3427
  minimumTimeoutMsForHostCall,
3427
- ...checked.javascript ? { transpiledCode: checked.javascript } : {},
3428
- ...checked.sourceMap ? { transpiledSourceMap: checked.sourceMap } : {},
3428
+ ...checked2.javascript ? { transpiledCode: checked2.javascript } : {},
3429
+ ...checked2.sourceMap ? { transpiledSourceMap: checked2.sourceMap } : {},
3429
3430
  ...options.payloads ? { payloads: options.payloads } : {},
3430
3431
  ...Object.keys(proxyNames).length > 0 ? { proxyNames } : {},
3431
3432
  ...options.tokenBudget !== void 0 ? { tokenBudget: options.tokenBudget } : {},
@@ -5032,10 +5033,10 @@ var ResidencyClient = class {
5032
5033
  statusAgent(id) {
5033
5034
  const metadata = this.#metadata(id);
5034
5035
  if (!metadata) throw new Error(`Unknown durable Fabric agent: ${id}`);
5035
- const record = readJson(path5.join(metadata.runDirectory, "status.json"));
5036
- if (!record || record.id !== metadata.id) return structuredClone(metadata.handle);
5036
+ const record2 = readJson(path5.join(metadata.runDirectory, "status.json"));
5037
+ if (!record2 || record2.id !== metadata.id) return structuredClone(metadata.handle);
5037
5038
  return {
5038
- ...record,
5039
+ ...record2,
5039
5040
  cwd: metadata.handle.cwd,
5040
5041
  residency: "durable",
5041
5042
  logFile: path5.join(metadata.runDirectory, "events.jsonl"),
@@ -5398,20 +5399,20 @@ var actorRequest = (args, context, manager, inheritModel = true) => {
5398
5399
  var collectAgentToolPreviewNodes = (records, options, depth = 0, budget = { remaining: options.maxNodes ?? AGENT_PREVIEW_TREE_MAX_NODES }) => {
5399
5400
  const maxDepth = options.maxDepth ?? AGENT_PREVIEW_TREE_MAX_DEPTH;
5400
5401
  const nodes = [];
5401
- for (const record of records) {
5402
+ for (const record2 of records) {
5402
5403
  if (budget.remaining <= 0) break;
5403
5404
  budget.remaining -= 1;
5404
- const descendants = Array.isArray(record.nestedAgents) ? record.nestedAgents : [];
5405
+ const descendants = Array.isArray(record2.nestedAgents) ? record2.nestedAgents : [];
5405
5406
  const agents = depth + 1 < maxDepth && descendants.length > 0 && budget.remaining > 0 ? collectAgentToolPreviewNodes(descendants, options, depth + 1, budget) : [];
5406
5407
  nodes.push({
5407
- id: record.id,
5408
- name: record.actorName ?? record.name,
5409
- status: record.status,
5410
- ...record.runner === "omp" || record.runner === "claude" || record.runner === "veda" ? { runner: record.runner } : {},
5411
- owner: record.actorId ? "actor" : "agent",
5412
- ...record.currentTool ? { currentTool: record.currentTool } : {},
5413
- ...record.text ? { text: tailCodePoints(record.text, AGENT_PREVIEW_TEXT_CODE_POINTS) } : {},
5414
- tools: options.tools(record),
5408
+ id: record2.id,
5409
+ name: record2.actorName ?? record2.name,
5410
+ status: record2.status,
5411
+ ...record2.runner === "omp" || record2.runner === "claude" || record2.runner === "veda" ? { runner: record2.runner } : {},
5412
+ owner: record2.actorId ? "actor" : "agent",
5413
+ ...record2.currentTool ? { currentTool: record2.currentTool } : {},
5414
+ ...record2.text ? { text: tailCodePoints(record2.text, AGENT_PREVIEW_TEXT_CODE_POINTS) } : {},
5415
+ tools: options.tools(record2),
5415
5416
  ...agents.length > 0 ? { agents } : {},
5416
5417
  ...descendants.length > agents.length ? { agentsTruncated: true } : {}
5417
5418
  });
@@ -6457,18 +6458,18 @@ var AgentsProvider = class {
6457
6458
  const scope = this.#participantScope(scopeValue, "local");
6458
6459
  if (scope === "local") return this.manager.list();
6459
6460
  const local = /* @__PURE__ */ new Map();
6460
- const append = (record) => {
6461
- local.set(record.id, record);
6462
- if ("nestedAgents" in record) {
6463
- for (const nested of record.nestedAgents ?? []) append(nested);
6461
+ const append = (record2) => {
6462
+ local.set(record2.id, record2);
6463
+ if ("nestedAgents" in record2) {
6464
+ for (const nested of record2.nestedAgents ?? []) append(nested);
6464
6465
  }
6465
6466
  };
6466
- for (const record of this.manager.list()) append(record);
6467
- for (const record of this.residency?.listAgents() ?? []) append(record);
6467
+ for (const record2 of this.manager.list()) append(record2);
6468
+ for (const record2 of this.residency?.listAgents() ?? []) append(record2);
6468
6469
  const listed = this.participants.list({ scope, kinds: ["agent"] }).map((participant) => local.get(participant.id) ?? participant);
6469
- const seen = new Set(listed.map((record) => record.id));
6470
- for (const record of this.residency?.listAgents() ?? []) {
6471
- if (!seen.has(record.id)) listed.push(record);
6470
+ const seen = new Set(listed.map((record2) => record2.id));
6471
+ for (const record2 of this.residency?.listAgents() ?? []) {
6472
+ if (!seen.has(record2.id)) listed.push(record2);
6472
6473
  }
6473
6474
  return listed;
6474
6475
  }
@@ -6624,9 +6625,9 @@ var CapturedToolsProvider = class {
6624
6625
  #allowedTools = readChildToolAllowlist();
6625
6626
  async list(request, _context) {
6626
6627
  const query = request.query?.trim().toLowerCase();
6627
- const descriptors6 = this.catalog.list().filter((entry) => !this.#allowedTools || this.#allowedTools.has(entry.name)).map(descriptorFrom);
6628
- if (!query) return descriptors6;
6629
- return descriptors6.filter(
6628
+ const descriptors7 = this.catalog.list().filter((entry) => !this.#allowedTools || this.#allowedTools.has(entry.name)).map(descriptorFrom);
6629
+ if (!query) return descriptors7;
6630
+ return descriptors7.filter(
6630
6631
  (descriptor) => `${descriptor.name} ${descriptor.description} ${descriptor.namespace ?? ""}`.toLowerCase().includes(query)
6631
6632
  );
6632
6633
  }
@@ -6762,32 +6763,1274 @@ var CapturedToolsProvider = class {
6762
6763
  }
6763
6764
  };
6764
6765
 
6765
- // src/providers/compact-provider.ts
6766
+ // src/providers/codemap-provider.ts
6766
6767
  import { Type } from "@oh-my-pi/pi-coding-agent/extensibility/legacy-typebox";
6767
6768
  import { validateJsonSchemaValue } from "@oh-my-pi/pi-ai/utils/schema";
6768
- var requestSchema = Type.Object({
6769
- reason: Type.Optional(Type.String({
6769
+
6770
+ // src/codemap/budget.ts
6771
+ var KIND_LETTERS = {
6772
+ fn: "f",
6773
+ class: "c",
6774
+ iface: "i",
6775
+ type: "t",
6776
+ const: "v",
6777
+ enum: "e",
6778
+ method: "m"
6779
+ };
6780
+ var LEGEND = "# f=fn c=class i=iface t=type v=const e=enum m=method";
6781
+ var MIN_FILE_ENTRY = 8;
6782
+ var FOCUS_WEIGHT = 1;
6783
+ var CASCADE_WEIGHT = 0.6;
6784
+ var NAME_EXACT_SCORE = 6;
6785
+ var NAME_WORD_SCORE = 3;
6786
+ var PATH_WORD_SCORE = 4;
6787
+ var SUBSTRING_SCORE = 1;
6788
+ var MIN_SUBSTRING_LENGTH = 3;
6789
+ var EXPORT_PASSES = [true, false];
6790
+ var isUpper = (code) => code >= 65 && code <= 90;
6791
+ var isLower = (code) => code >= 97 && code <= 122;
6792
+ var isDigit = (code) => code >= 48 && code <= 57;
6793
+ var isWordChar = (code) => isUpper(code) || isLower(code) || isDigit(code);
6794
+ var compareText = (left, right) => left < right ? -1 : left > right ? 1 : 0;
6795
+ var collectWords = (value, sink) => {
6796
+ let start = -1;
6797
+ for (let index = 0; index < value.length; index++) {
6798
+ const code = value.charCodeAt(index);
6799
+ if (!isWordChar(code)) {
6800
+ if (start >= 0) sink.add(value.slice(start, index).toLowerCase());
6801
+ start = -1;
6802
+ continue;
6803
+ }
6804
+ if (start < 0) {
6805
+ start = index;
6806
+ continue;
6807
+ }
6808
+ const previous = value.charCodeAt(index - 1);
6809
+ const next = index + 1 < value.length ? value.charCodeAt(index + 1) : 0;
6810
+ if (isUpper(code) && (!isUpper(previous) || isLower(next))) {
6811
+ sink.add(value.slice(start, index).toLowerCase());
6812
+ start = index;
6813
+ }
6814
+ }
6815
+ if (start >= 0) sink.add(value.slice(start).toLowerCase());
6816
+ };
6817
+ var focusTerms = (focus) => {
6818
+ if (focus === void 0 || focus.length === 0) return [];
6819
+ const words = /* @__PURE__ */ new Set();
6820
+ collectWords(focus, words);
6821
+ return [...words];
6822
+ };
6823
+ var lexiconFor = (group) => {
6824
+ const pathWords = /* @__PURE__ */ new Set();
6825
+ collectWords(group.file, pathWords);
6826
+ const names = /* @__PURE__ */ new Set();
6827
+ const nameWords = /* @__PURE__ */ new Set();
6828
+ const distinct = [];
6829
+ for (const symbol of group.symbols) {
6830
+ const lowered = symbol.name.toLowerCase();
6831
+ if (names.has(lowered)) continue;
6832
+ names.add(lowered);
6833
+ distinct.push(lowered);
6834
+ collectWords(symbol.name, nameWords);
6835
+ }
6836
+ return {
6837
+ pathWords,
6838
+ pathLower: group.file.toLowerCase(),
6839
+ names,
6840
+ nameWords,
6841
+ namesBlob: distinct.join("\n")
6842
+ };
6843
+ };
6844
+ var termScore = (term, lexicon) => {
6845
+ const wideEnough = term.length >= MIN_SUBSTRING_LENGTH;
6846
+ let score = 0;
6847
+ if (lexicon.names.has(term)) score += NAME_EXACT_SCORE;
6848
+ else if (lexicon.nameWords.has(term)) score += NAME_WORD_SCORE;
6849
+ else if (wideEnough && lexicon.namesBlob.includes(term)) score += SUBSTRING_SCORE;
6850
+ if (lexicon.pathWords.has(term)) score += PATH_WORD_SCORE;
6851
+ else if (wideEnough && lexicon.pathLower.includes(term)) score += SUBSTRING_SCORE;
6852
+ return score;
6853
+ };
6854
+ var groupByFile = (symbols) => {
6855
+ const byFile = /* @__PURE__ */ new Map();
6856
+ for (const symbol of symbols) {
6857
+ let group = byFile.get(symbol.file);
6858
+ if (group === void 0) {
6859
+ group = { file: symbol.file, symbols: [], score: 0 };
6860
+ byFile.set(symbol.file, group);
6861
+ }
6862
+ group.symbols.push(symbol);
6863
+ }
6864
+ for (const group of byFile.values()) {
6865
+ group.symbols.sort((left, right) => left.line - right.line || compareText(left.name, right.name) || compareText(left.kind, right.kind));
6866
+ }
6867
+ return [...byFile.values()];
6868
+ };
6869
+ var applyFocus = (groups, focus) => {
6870
+ const terms = focusTerms(focus);
6871
+ if (terms.length === 0) return;
6872
+ let peak = 0;
6873
+ for (const group of groups) {
6874
+ const lexicon = lexiconFor(group);
6875
+ let raw = 0;
6876
+ for (const term of terms) raw += termScore(term, lexicon);
6877
+ group.score = raw;
6878
+ if (raw > peak) peak = raw;
6879
+ }
6880
+ for (const group of groups) group.score = peak > 0 ? group.score / peak * FOCUS_WEIGHT : 0;
6881
+ };
6882
+ var applyCascade = (groups, request) => {
6883
+ const edges = request.cascade?.edges;
6884
+ if (edges === void 0 || edges.length === 0) return;
6885
+ const best = /* @__PURE__ */ new Map();
6886
+ let peak = 0;
6887
+ for (const edge of edges) {
6888
+ if (edge.score > peak) peak = edge.score;
6889
+ const previous = best.get(edge.file);
6890
+ if (previous === void 0 || edge.score > previous) best.set(edge.file, edge.score);
6891
+ }
6892
+ if (peak <= 0) return;
6893
+ for (const group of groups) {
6894
+ const edgeScore = best.get(group.file);
6895
+ if (edgeScore !== void 0 && edgeScore > 0) {
6896
+ group.score += edgeScore / peak * CASCADE_WEIGHT;
6897
+ }
6898
+ }
6899
+ };
6900
+ var rankGroups = (groups, request) => {
6901
+ applyFocus(groups, request.focus);
6902
+ applyCascade(groups, request);
6903
+ groups.sort((left, right) => right.score - left.score || right.symbols.length - left.symbols.length || compareText(left.file, right.file));
6904
+ };
6905
+ var spend = (groups, charBudget, reserved) => {
6906
+ const lines = [];
6907
+ let used = reserved;
6908
+ let filesShown = 0;
6909
+ let symbolsShown = 0;
6910
+ let omittedFiles = 0;
6911
+ let omittedSymbols = 0;
6912
+ for (const group of groups) {
6913
+ const headerCost = group.file.length + 1;
6914
+ if (used + headerCost >= charBudget) {
6915
+ omittedFiles++;
6916
+ omittedSymbols += group.symbols.length;
6917
+ continue;
6918
+ }
6919
+ const rendered = new Array(group.symbols.length);
6920
+ const picked = [];
6921
+ let cost = headerCost;
6922
+ for (const exported of EXPORT_PASSES) {
6923
+ for (let index = 0; index < group.symbols.length; index++) {
6924
+ const symbol = group.symbols[index];
6925
+ if (symbol.exported !== exported) continue;
6926
+ let line = rendered[index];
6927
+ if (line === void 0) {
6928
+ line = `${symbol.line} ${KIND_LETTERS[symbol.kind]} ${symbol.name}`;
6929
+ rendered[index] = line;
6930
+ }
6931
+ const lineCost = line.length + 1;
6932
+ if (used + cost + lineCost > charBudget) continue;
6933
+ cost += lineCost;
6934
+ picked.push(index);
6935
+ }
6936
+ }
6937
+ if (picked.length === 0) {
6938
+ omittedFiles++;
6939
+ omittedSymbols += group.symbols.length;
6940
+ continue;
6941
+ }
6942
+ picked.sort((left, right) => left - right);
6943
+ lines.push(group.file);
6944
+ for (const index of picked) lines.push(rendered[index]);
6945
+ used += cost;
6946
+ filesShown++;
6947
+ symbolsShown += picked.length;
6948
+ omittedSymbols += group.symbols.length - picked.length;
6949
+ }
6950
+ return { lines, filesShown, symbolsShown, omittedFiles, omittedSymbols };
6951
+ };
6952
+ function assembleMap(request) {
6953
+ const groups = groupByFile(request.index.symbols);
6954
+ rankGroups(groups, request);
6955
+ const charBudget = request.maxTokens > 0 ? Math.floor(request.maxTokens) * 4 : 0;
6956
+ const legendCost = LEGEND.length + 1;
6957
+ const reserved = charBudget >= legendCost + MIN_FILE_ENTRY ? legendCost : 0;
6958
+ let plan = spend(groups, charBudget, reserved);
6959
+ let legendShown = reserved > 0;
6960
+ if (plan.filesShown === 0 && reserved > 0) {
6961
+ plan = spend(groups, charBudget, 0);
6962
+ legendShown = false;
6963
+ }
6964
+ const body = plan.lines.join("\n");
6965
+ const text = plan.lines.length === 0 ? "" : legendShown ? `${LEGEND}
6966
+ ${body}
6967
+ ` : `${body}
6968
+ `;
6969
+ return {
6970
+ text,
6971
+ tokensEstimated: estimateTokens({ role: "user", content: text }),
6972
+ filesShown: plan.filesShown,
6973
+ symbolsShown: plan.symbolsShown,
6974
+ omittedFiles: plan.omittedFiles,
6975
+ omittedSymbols: plan.omittedSymbols,
6976
+ truncated: plan.omittedFiles > 0 || plan.omittedSymbols > 0
6977
+ };
6978
+ }
6979
+
6980
+ // src/codemap/cascade.ts
6981
+ import { execFile } from "node:child_process";
6982
+ import { existsSync, realpathSync } from "node:fs";
6983
+ import path7 from "node:path";
6984
+ import { promisify } from "node:util";
6985
+ var execFileAsync = promisify(execFile);
6986
+ var BULK_COMMIT_FILE_CEILING = 100;
6987
+ var GIT_TIMEOUT_MS = 2e4;
6988
+ var GIT_MAX_BUFFER = 64 << 20;
6989
+ var COMMIT_MARKER_CODE = 1;
6990
+ var QUOTE_CODE = 34;
6991
+ var ESCAPE_BYTES = /* @__PURE__ */ new Map([
6992
+ ["a", 7],
6993
+ ["b", 8],
6994
+ ["t", 9],
6995
+ ["n", 10],
6996
+ ["v", 11],
6997
+ ["f", 12],
6998
+ ["r", 13],
6999
+ ['"', 34],
7000
+ ["\\", 92]
7001
+ ]);
7002
+ var toPosix = (value) => path7.sep === "/" ? value : value.replaceAll(path7.sep, "/");
7003
+ var unquoteGitPath = (raw) => {
7004
+ if (raw.length < 2 || raw.charCodeAt(raw.length - 1) !== QUOTE_CODE) return raw;
7005
+ const bytes = [];
7006
+ for (let index = 1; index < raw.length - 1; index += 1) {
7007
+ const char = raw[index];
7008
+ if (char !== "\\") {
7009
+ const code = char.charCodeAt(0);
7010
+ if (code < 128) bytes.push(code);
7011
+ else for (const byte of Buffer.from(char, "utf8")) bytes.push(byte);
7012
+ continue;
7013
+ }
7014
+ const next = raw[index + 1];
7015
+ if (next === void 0) break;
7016
+ const mapped = ESCAPE_BYTES.get(next);
7017
+ if (mapped !== void 0) {
7018
+ bytes.push(mapped);
7019
+ index += 1;
7020
+ continue;
7021
+ }
7022
+ if (next >= "0" && next <= "7") {
7023
+ let value = 0;
7024
+ let digits = 0;
7025
+ while (digits < 3) {
7026
+ const digit = raw[index + 1 + digits];
7027
+ if (digit === void 0 || digit < "0" || digit > "7") break;
7028
+ value = value * 8 + (digit.charCodeAt(0) - 48);
7029
+ digits += 1;
7030
+ }
7031
+ bytes.push(value & 255);
7032
+ index += digits;
7033
+ continue;
7034
+ }
7035
+ bytes.push(next.charCodeAt(0));
7036
+ index += 1;
7037
+ }
7038
+ return Buffer.from(bytes).toString("utf8");
7039
+ };
7040
+ var realPath = (value) => {
7041
+ try {
7042
+ return realpathSync.native(value);
7043
+ } catch {
7044
+ return value;
7045
+ }
7046
+ };
7047
+ var relativeSeed = (root, top, seed) => {
7048
+ const absolute = path7.isAbsolute(seed) ? seed : path7.resolve(root, seed);
7049
+ for (const base of /* @__PURE__ */ new Set([top, realPath(top)])) {
7050
+ for (const candidate of /* @__PURE__ */ new Set([absolute, realPath(absolute), path7.resolve(realPath(root), seed)])) {
7051
+ const relative = path7.relative(base, candidate);
7052
+ if (!relative || relative === ".." || relative.startsWith(`..${path7.sep}`) || path7.isAbsolute(relative)) {
7053
+ continue;
7054
+ }
7055
+ return toPosix(relative);
7056
+ }
7057
+ }
7058
+ return void 0;
7059
+ };
7060
+ var emptyGraph = (seeds, unavailable) => ({
7061
+ seeds,
7062
+ edges: [],
7063
+ commitsScanned: 0,
7064
+ truncated: false,
7065
+ unavailable
7066
+ });
7067
+ async function coChange(request) {
7068
+ const requestedSeeds = request.seeds.filter((seed) => seed.length > 0);
7069
+ if (requestedSeeds.length === 0) return emptyGraph([], "no seed files were provided");
7070
+ if (!existsSync(request.root)) return emptyGraph(requestedSeeds, "root directory does not exist");
7071
+ const maxCommits = Math.max(1, Math.floor(request.maxCommits) || 1);
7072
+ const limit = Math.max(1, Math.floor(request.limit) || 1);
7073
+ let top;
7074
+ try {
7075
+ const revParse = await execFileAsync("git", ["rev-parse", "--show-toplevel"], {
7076
+ cwd: request.root,
7077
+ timeout: GIT_TIMEOUT_MS,
7078
+ encoding: "utf8"
7079
+ });
7080
+ top = revParse.stdout.trim();
7081
+ } catch (error) {
7082
+ const code = error.code;
7083
+ if (code === "ENOENT") return emptyGraph(requestedSeeds, "git is not available");
7084
+ return emptyGraph(requestedSeeds, "not a git repository");
7085
+ }
7086
+ if (!top) return emptyGraph(requestedSeeds, "not a git repository");
7087
+ const seedSet = /* @__PURE__ */ new Set();
7088
+ for (const seed of requestedSeeds) {
7089
+ const normalized = relativeSeed(request.root, top, seed);
7090
+ if (normalized) seedSet.add(normalized);
7091
+ }
7092
+ const seeds = [...seedSet];
7093
+ if (seeds.length === 0) return emptyGraph(requestedSeeds, "seed files are outside the repository");
7094
+ let stdout;
7095
+ try {
7096
+ const log = await execFileAsync(
7097
+ "git",
7098
+ [
7099
+ "log",
7100
+ `--max-count=${maxCommits}`,
7101
+ "--no-merges",
7102
+ "--name-only",
7103
+ `--pretty=format:%H`
7104
+ ],
7105
+ {
7106
+ cwd: top,
7107
+ timeout: GIT_TIMEOUT_MS,
7108
+ maxBuffer: GIT_MAX_BUFFER,
7109
+ encoding: "utf8"
7110
+ }
7111
+ );
7112
+ stdout = log.stdout;
7113
+ } catch (error) {
7114
+ const code = error.code;
7115
+ if (code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER") {
7116
+ return emptyGraph(seeds, "commit history exceeded the read budget");
7117
+ }
7118
+ return emptyGraph(seeds, "no commit history");
7119
+ }
7120
+ const fileCommits = /* @__PURE__ */ new Map();
7121
+ const sharedCommits = /* @__PURE__ */ new Map();
7122
+ const current = [];
7123
+ let commitsScanned = 0;
7124
+ let seedCommits = 0;
7125
+ let inCommit = false;
7126
+ let bulk = false;
7127
+ const settle = () => {
7128
+ if (!inCommit) return;
7129
+ inCommit = false;
7130
+ if (bulk) {
7131
+ bulk = false;
7132
+ current.length = 0;
7133
+ return;
7134
+ }
7135
+ commitsScanned += 1;
7136
+ let touchesSeed = false;
7137
+ for (const file of current) {
7138
+ if (seedSet.has(file)) {
7139
+ touchesSeed = true;
7140
+ break;
7141
+ }
7142
+ }
7143
+ if (touchesSeed) seedCommits += 1;
7144
+ for (const file of current) {
7145
+ fileCommits.set(file, (fileCommits.get(file) ?? 0) + 1);
7146
+ if (touchesSeed && !seedSet.has(file)) {
7147
+ sharedCommits.set(file, (sharedCommits.get(file) ?? 0) + 1);
7148
+ }
7149
+ }
7150
+ current.length = 0;
7151
+ };
7152
+ let cursor = 0;
7153
+ while (cursor <= stdout.length) {
7154
+ let end = stdout.indexOf("\n", cursor);
7155
+ if (end < 0) end = stdout.length;
7156
+ const line = stdout.slice(cursor, end);
7157
+ cursor = end + 1;
7158
+ if (line.length === 0) continue;
7159
+ if (line.charCodeAt(0) === COMMIT_MARKER_CODE) {
7160
+ settle();
7161
+ inCommit = true;
7162
+ continue;
7163
+ }
7164
+ if (!inCommit || bulk) continue;
7165
+ if (current.length >= BULK_COMMIT_FILE_CEILING) {
7166
+ bulk = true;
7167
+ current.length = 0;
7168
+ continue;
7169
+ }
7170
+ current.push(line.charCodeAt(0) === QUOTE_CODE ? unquoteGitPath(line) : line);
7171
+ }
7172
+ settle();
7173
+ if (commitsScanned === 0) return emptyGraph(seeds, "no commit history");
7174
+ const edges = [];
7175
+ if (seedCommits > 0) {
7176
+ const seedRoot = Math.sqrt(seedCommits);
7177
+ for (const [file, shared] of sharedCommits) {
7178
+ const total = fileCommits.get(file) ?? shared;
7179
+ edges.push({ file, score: shared / (seedRoot * Math.sqrt(total)), commits: shared });
7180
+ }
7181
+ }
7182
+ edges.sort((left, right) => {
7183
+ if (right.score !== left.score) return right.score - left.score;
7184
+ if (right.commits !== left.commits) return right.commits - left.commits;
7185
+ return left.file < right.file ? -1 : left.file > right.file ? 1 : 0;
7186
+ });
7187
+ const truncated = edges.length > limit;
7188
+ if (truncated) edges.length = limit;
7189
+ if (seedCommits === 0) {
7190
+ return { seeds, edges, commitsScanned, truncated, unavailable: "seed files do not appear in the scanned history" };
7191
+ }
7192
+ return { seeds, edges, commitsScanned, truncated };
7193
+ }
7194
+
7195
+ // src/codemap/symbols.ts
7196
+ import { execFile as execFile2 } from "node:child_process";
7197
+ import { readFile, readdir } from "node:fs/promises";
7198
+ import { createRequire } from "node:module";
7199
+ import path8 from "node:path";
7200
+ import { promisify as promisify2 } from "node:util";
7201
+ var execFileAsync2 = promisify2(execFile2);
7202
+ var commonDirectory = (files) => {
7203
+ let prefix;
7204
+ for (const file of files) {
7205
+ const parts = file.split("/");
7206
+ parts.pop();
7207
+ if (prefix === void 0) {
7208
+ prefix = parts;
7209
+ continue;
7210
+ }
7211
+ let shared = 0;
7212
+ while (shared < prefix.length && shared < parts.length && prefix[shared] === parts[shared]) shared++;
7213
+ prefix.length = shared;
7214
+ if (shared === 0) return "";
7215
+ }
7216
+ return prefix === void 0 ? "" : prefix.join("/");
7217
+ };
7218
+ var importBundledNatives = async () => {
7219
+ try {
7220
+ const bundled = await import("@oh-my-pi/pi-natives");
7221
+ return typeof bundled.astGrep === "function" ? bundled : void 0;
7222
+ } catch {
7223
+ return void 0;
7224
+ }
7225
+ };
7226
+ var importPlatformNatives = () => {
7227
+ const load = createRequire(import.meta.url);
7228
+ return load(`@oh-my-pi/pi-natives-${process.platform}-${process.arch}`);
7229
+ };
7230
+ var nativesOnce;
7231
+ var codeNatives = () => {
7232
+ nativesOnce ??= importBundledNatives().then((bundled) => bundled ?? importPlatformNatives());
7233
+ return nativesOnce;
7234
+ };
7235
+ var SCRIPT_DECLARATION = /^(?:export\s+)?(?:default\s+)?(?:declare\s+)?(?:abstract\s+)?(?:async\s+)?(function|class|interface|type|enum|const|let|var)\b/;
7236
+ var ARROW_VALUE = /^(?:async\s*)?[(<]/;
7237
+ var classifyScript = (text, meta) => {
7238
+ const exported = text.startsWith("export");
7239
+ const declaration = SCRIPT_DECLARATION.exec(text);
7240
+ switch (declaration?.[1]) {
7241
+ case "function":
7242
+ return { kind: "fn", exported };
7243
+ case "class":
7244
+ return { kind: "class", exported };
7245
+ case "interface":
7246
+ return { kind: "iface", exported };
7247
+ case "type":
7248
+ return { kind: "type", exported };
7249
+ case "enum":
7250
+ return { kind: "enum", exported };
7251
+ default: {
7252
+ const value = meta?.V;
7253
+ if (value === void 0) return { kind: "fn", exported };
7254
+ const arrow = ARROW_VALUE.test(value) && value.includes("=>");
7255
+ return { kind: arrow ? "fn" : "const", exported };
7256
+ }
7257
+ }
7258
+ };
7259
+ var SCRIPT_VALUE_PATTERNS = [
7260
+ "function $NAME($$$A) { $$$B }",
7261
+ "export function $NAME($$$A) { $$$B }",
7262
+ "export default function $NAME($$$A) { $$$B }",
7263
+ "class $NAME { $$$B }",
7264
+ "export class $NAME { $$$B }",
7265
+ "export default class $NAME { $$$B }",
7266
+ "const $NAME = ($$$A) => $B",
7267
+ "const $NAME = $V",
7268
+ "export const $NAME = $V"
7269
+ ];
7270
+ var TYPED_SCRIPT_PATTERNS = [
7271
+ ...SCRIPT_VALUE_PATTERNS,
7272
+ "interface $NAME { $$$B }",
7273
+ "export interface $NAME { $$$B }",
7274
+ "type $NAME = $V",
7275
+ "export type $NAME = $V",
7276
+ "enum $NAME { $$$B }",
7277
+ "export enum $NAME { $$$B }"
7278
+ ];
7279
+ var PYTHON_DEFINITION = /^(?:async\s+)?def\b/;
7280
+ var PYTHON_CLASS = /^class\b/;
7281
+ var classifyPython = (text) => {
7282
+ if (PYTHON_DEFINITION.test(text)) return { kind: "fn", exported: true };
7283
+ if (PYTHON_CLASS.test(text)) return { kind: "class", exported: true };
7284
+ return { kind: "const", exported: true };
7285
+ };
7286
+ var GO_METHOD = /^func\s*\(/;
7287
+ var GO_FUNCTION = /^func\b/;
7288
+ var GO_STRUCT = /^type\s+\w+\s+struct\b/;
7289
+ var GO_INTERFACE = /^type\s+\w+\s+interface\b/;
7290
+ var GO_TYPE = /^type\b/;
7291
+ var classifyGo = (text) => {
7292
+ if (GO_METHOD.test(text)) return { kind: "method", exported: true };
7293
+ if (GO_FUNCTION.test(text)) return { kind: "fn", exported: true };
7294
+ if (GO_STRUCT.test(text)) return { kind: "class", exported: true };
7295
+ if (GO_INTERFACE.test(text)) return { kind: "iface", exported: true };
7296
+ if (GO_TYPE.test(text)) return { kind: "type", exported: true };
7297
+ return { kind: "const", exported: true };
7298
+ };
7299
+ var RUST_KEYWORD = /^(?:pub(?:\([^)]*\))?\s+)?(fn|struct|enum|trait|type|const|static)\b/;
7300
+ var classifyRust = (text) => {
7301
+ const exported = text.startsWith("pub");
7302
+ switch (RUST_KEYWORD.exec(text)?.[1]) {
7303
+ case "fn":
7304
+ return { kind: "fn", exported };
7305
+ case "struct":
7306
+ return { kind: "class", exported };
7307
+ case "enum":
7308
+ return { kind: "enum", exported };
7309
+ case "trait":
7310
+ return { kind: "iface", exported };
7311
+ case "type":
7312
+ return { kind: "type", exported };
7313
+ default:
7314
+ return { kind: "const", exported };
7315
+ }
7316
+ };
7317
+ var JAVA_KEYWORD = /^(?:(?:public|private|protected|static|final|abstract|synchronized|native|strictfp)\s+)*(class|interface|enum|record)\b/;
7318
+ var classifyJava = (text) => {
7319
+ const exported = text.startsWith("public");
7320
+ switch (JAVA_KEYWORD.exec(text)?.[1]) {
7321
+ case "class":
7322
+ case "record":
7323
+ return { kind: "class", exported };
7324
+ case "interface":
7325
+ return { kind: "iface", exported };
7326
+ case "enum":
7327
+ return { kind: "enum", exported };
7328
+ default:
7329
+ return { kind: "method", exported };
7330
+ }
7331
+ };
7332
+ var globFor = (extensions) => extensions.length === 1 ? `**/*.${extensions[0]}` : `**/*.{${extensions.join(",")}}`;
7333
+ var defineSpec = (id, lang, extensions, patterns, classify) => ({ id, lang, extensions, glob: globFor(extensions), patterns, classify });
7334
+ var LANGUAGE_SPECS = [
7335
+ defineSpec("ts", "ts", ["ts", "mts", "cts"], TYPED_SCRIPT_PATTERNS, classifyScript),
7336
+ defineSpec("tsx", "tsx", ["tsx"], TYPED_SCRIPT_PATTERNS, classifyScript),
7337
+ defineSpec("js", "js", ["js", "mjs", "cjs", "jsx"], SCRIPT_VALUE_PATTERNS, classifyScript),
7338
+ defineSpec(
7339
+ "python",
7340
+ "python",
7341
+ ["py", "pyi"],
7342
+ [
7343
+ "def $NAME($$$A): $$$B",
7344
+ "class $NAME($$$A): $$$B",
7345
+ "class $NAME: $$$B",
7346
+ "$NAME = $V"
7347
+ ],
7348
+ classifyPython
7349
+ ),
7350
+ defineSpec(
7351
+ "go",
7352
+ "go",
7353
+ ["go"],
7354
+ [
7355
+ "func $NAME($$$A) $$$R { $$$B }",
7356
+ "func ($$$RECV) $NAME($$$A) $$$R { $$$B }",
7357
+ "type $NAME struct { $$$B }",
7358
+ "type $NAME interface { $$$B }",
7359
+ "type $NAME = $V",
7360
+ "const $NAME = $V",
7361
+ "var $NAME = $V"
7362
+ ],
7363
+ classifyGo
7364
+ ),
7365
+ defineSpec(
7366
+ "rust",
7367
+ "rust",
7368
+ ["rs"],
7369
+ [
7370
+ "fn $NAME($$$A) { $$$B }",
7371
+ "fn $NAME($$$A) -> $R { $$$B }",
7372
+ "pub fn $NAME($$$A) { $$$B }",
7373
+ "pub fn $NAME($$$A) -> $R { $$$B }",
7374
+ "struct $NAME { $$$B }",
7375
+ "pub struct $NAME { $$$B }",
7376
+ "enum $NAME { $$$B }",
7377
+ "pub enum $NAME { $$$B }",
7378
+ "trait $NAME { $$$B }",
7379
+ "pub trait $NAME { $$$B }",
7380
+ "type $NAME = $V;",
7381
+ "pub type $NAME = $V;",
7382
+ "const $NAME: $T = $V;",
7383
+ "pub const $NAME: $T = $V;",
7384
+ "static $NAME: $T = $V;",
7385
+ "pub static $NAME: $T = $V;"
7386
+ ],
7387
+ classifyRust
7388
+ ),
7389
+ defineSpec(
7390
+ "java",
7391
+ "java",
7392
+ ["java"],
7393
+ [
7394
+ "class $NAME { $$$B }",
7395
+ "public class $NAME { $$$B }",
7396
+ "interface $NAME { $$$B }",
7397
+ "public interface $NAME { $$$B }",
7398
+ "enum $NAME { $$$B }",
7399
+ "public enum $NAME { $$$B }",
7400
+ "$RET $NAME($$$A) { $$$B }",
7401
+ "public $RET $NAME($$$A) { $$$B }",
7402
+ "private $RET $NAME($$$A) { $$$B }",
7403
+ "protected $RET $NAME($$$A) { $$$B }",
7404
+ "public static $RET $NAME($$$A) { $$$B }",
7405
+ "static $RET $NAME($$$A) { $$$B }"
7406
+ ],
7407
+ classifyJava
7408
+ )
7409
+ ];
7410
+ var EXTENSION_SPECS = /* @__PURE__ */ new Map();
7411
+ for (const spec of LANGUAGE_SPECS) {
7412
+ for (const extension of spec.extensions) EXTENSION_SPECS.set(extension, spec);
7413
+ }
7414
+ var FALLBACK_EXTENSIONS = /* @__PURE__ */ new Set([
7415
+ "c",
7416
+ "cc",
7417
+ "cpp",
7418
+ "cs",
7419
+ "cxx",
7420
+ "dart",
7421
+ "elm",
7422
+ "erl",
7423
+ "ex",
7424
+ "exs",
7425
+ "groovy",
7426
+ "h",
7427
+ "hh",
7428
+ "hpp",
7429
+ "hs",
7430
+ "jl",
7431
+ "kt",
7432
+ "kts",
7433
+ "lua",
7434
+ "nim",
7435
+ "php",
7436
+ "pl",
7437
+ "pm",
7438
+ "proto",
7439
+ "rb",
7440
+ "scala",
7441
+ "sh",
7442
+ "sql",
7443
+ "svelte",
7444
+ "swift",
7445
+ "vue",
7446
+ "zig"
7447
+ ]);
7448
+ var SKIP_DIRECTORIES = /* @__PURE__ */ new Set(["node_modules", "dist"]);
7449
+ var IDENTIFIER = /^[A-Za-z_$][\w$]*$/;
7450
+ var KIND_RANK = {
7451
+ method: 5,
7452
+ fn: 4,
7453
+ class: 3,
7454
+ iface: 3,
7455
+ enum: 3,
7456
+ type: 2,
7457
+ const: 1
7458
+ };
7459
+ var MATCH_TIMEOUT_MS = 12e4;
7460
+ var MAX_FALLBACK_BYTES = 2e6;
7461
+ var extensionOf = (file) => {
7462
+ const slash = file.lastIndexOf("/");
7463
+ const dot = file.lastIndexOf(".");
7464
+ if (dot <= slash + 1) return void 0;
7465
+ return file.slice(dot + 1).toLowerCase();
7466
+ };
7467
+ var indexableExtension = (file) => {
7468
+ const extension = extensionOf(file);
7469
+ if (extension === void 0) return void 0;
7470
+ if (EXTENSION_SPECS.has(extension) || FALLBACK_EXTENSIONS.has(extension)) return extension;
7471
+ return void 0;
7472
+ };
7473
+ var GLOB_ESCAPE = /[.+^$()|[\]\\]/g;
7474
+ var globToRegExp = (pattern) => {
7475
+ let source = "";
7476
+ let braces = 0;
7477
+ for (let i = 0; i < pattern.length; i += 1) {
7478
+ const character = pattern[i];
7479
+ if (character === "*") {
7480
+ if (pattern[i + 1] === "*") {
7481
+ i += 1;
7482
+ if (pattern[i + 1] === "/") {
7483
+ i += 1;
7484
+ source += "(?:[^/]*/)*";
7485
+ } else {
7486
+ source += ".*";
7487
+ }
7488
+ continue;
7489
+ }
7490
+ source += "[^/]*";
7491
+ continue;
7492
+ }
7493
+ if (character === "?") {
7494
+ source += "[^/]";
7495
+ continue;
7496
+ }
7497
+ if (character === "{") {
7498
+ braces += 1;
7499
+ source += "(?:";
7500
+ continue;
7501
+ }
7502
+ if (character === "}" && braces > 0) {
7503
+ braces -= 1;
7504
+ source += ")";
7505
+ continue;
7506
+ }
7507
+ if (character === "," && braces > 0) {
7508
+ source += "|";
7509
+ continue;
7510
+ }
7511
+ source += character?.replace(GLOB_ESCAPE, "\\$&") ?? "";
7512
+ }
7513
+ return new RegExp(`^${source}$`);
7514
+ };
7515
+ var GIT_LIST_TIMEOUT_MS = 2e4;
7516
+ var GIT_LIST_MAX_BUFFER = 64 * 1024 * 1024;
7517
+ var gitTrackedFiles = async (root, matcher, signal) => {
7518
+ let stdout;
7519
+ try {
7520
+ const result = await execFileAsync2(
7521
+ "git",
7522
+ ["-C", root, "ls-files", "--cached", "--others", "--exclude-standard", "-z"],
7523
+ {
7524
+ maxBuffer: GIT_LIST_MAX_BUFFER,
7525
+ timeout: GIT_LIST_TIMEOUT_MS,
7526
+ ...signal ? { signal } : {}
7527
+ }
7528
+ );
7529
+ stdout = result.stdout;
7530
+ } catch {
7531
+ return void 0;
7532
+ }
7533
+ const found = [];
7534
+ let cursor = 0;
7535
+ while (cursor < stdout.length) {
7536
+ let end = stdout.indexOf("\0", cursor);
7537
+ if (end === -1) end = stdout.length;
7538
+ const relative = stdout.slice(cursor, end);
7539
+ cursor = end + 1;
7540
+ if (relative.length === 0) continue;
7541
+ if (relative.charCodeAt(0) === 46) continue;
7542
+ if (indexableExtension(relative) === void 0) continue;
7543
+ if (matcher !== void 0 && !matcher.test(relative)) continue;
7544
+ let skipped2 = false;
7545
+ let segmentStart = 0;
7546
+ while (segmentStart < relative.length) {
7547
+ let segmentEnd = relative.indexOf("/", segmentStart);
7548
+ if (segmentEnd === -1) break;
7549
+ const segment = relative.slice(segmentStart, segmentEnd);
7550
+ if (segment.charCodeAt(0) === 46 || SKIP_DIRECTORIES.has(segment)) {
7551
+ skipped2 = true;
7552
+ break;
7553
+ }
7554
+ segmentStart = segmentEnd + 1;
7555
+ }
7556
+ if (!skipped2) found.push(relative);
7557
+ }
7558
+ return found;
7559
+ };
7560
+ var walkFiles = async (root, matcher, signal) => {
7561
+ const found = [];
7562
+ const pending = [""];
7563
+ while (pending.length > 0) {
7564
+ const directory = pending.pop() ?? "";
7565
+ throwIfAborted(signal);
7566
+ let entries;
7567
+ try {
7568
+ entries = await readdir(directory === "" ? root : path8.join(root, directory), {
7569
+ withFileTypes: true
7570
+ });
7571
+ } catch {
7572
+ continue;
7573
+ }
7574
+ for (const entry of entries) {
7575
+ const name = entry.name;
7576
+ if (name.charCodeAt(0) === 46) continue;
7577
+ const relative = directory === "" ? name : `${directory}/${name}`;
7578
+ if (entry.isDirectory()) {
7579
+ if (!SKIP_DIRECTORIES.has(name)) pending.push(relative);
7580
+ continue;
7581
+ }
7582
+ if (!entry.isFile()) continue;
7583
+ if (indexableExtension(relative) === void 0) continue;
7584
+ if (matcher !== void 0 && !matcher.test(relative)) continue;
7585
+ found.push(relative);
7586
+ }
7587
+ }
7588
+ return found;
7589
+ };
7590
+ var discoverFiles = async (root, matcher, signal) => await gitTrackedFiles(root, matcher, signal) ?? await walkFiles(root, matcher, signal);
7591
+ var COMMENT_HEAD = /^(?:\/\/|\/\*|\*|#|--|<!--|;|%)/;
7592
+ var IMPORT_HEAD = /^(?:import|from|require|include|use|using|package|open|load|source)\b/;
7593
+ var DECLARATION_HEAD = /^(?:export|pub|public|private|protected|internal|static|final|abstract|override|virtual|inline|async|unsafe|extern|shared|readonly|declare|local|def|defp|defmodule|defstruct|defmacro|class|module|namespace|record|object|data|struct|enum|union|interface|trait|protocol|actor|impl|extension|fn|func|function|sub|procedure|method|const|let|var|val|type|typedef|typealias|template|operator|constructor|init|property|event|signal|macro|task)\b/;
7594
+ var ASSIGNMENT_HEAD = /^[A-Za-z_$][\w$]*\s*(?::[^=]*)?=[^=]/;
7595
+ var EXPORTED_HEAD = /^(?:export|pub|public)\b/;
7596
+ var IDENTIFIERS = /[A-Za-z_$][\w$]*/g;
7597
+ var FALLBACK_KINDS = /* @__PURE__ */ new Map([
7598
+ ["class", "class"],
7599
+ ["module", "class"],
7600
+ ["namespace", "class"],
7601
+ ["record", "class"],
7602
+ ["object", "class"],
7603
+ ["struct", "class"],
7604
+ ["impl", "class"],
7605
+ ["actor", "class"],
7606
+ ["defmodule", "class"],
7607
+ ["defstruct", "class"],
7608
+ ["interface", "iface"],
7609
+ ["trait", "iface"],
7610
+ ["protocol", "iface"],
7611
+ ["enum", "enum"],
7612
+ ["union", "enum"],
7613
+ ["def", "fn"],
7614
+ ["defp", "fn"],
7615
+ ["defmacro", "fn"],
7616
+ ["fn", "fn"],
7617
+ ["func", "fn"],
7618
+ ["function", "fn"],
7619
+ ["sub", "fn"],
7620
+ ["procedure", "fn"],
7621
+ ["method", "method"],
7622
+ ["constructor", "method"],
7623
+ ["init", "method"],
7624
+ ["type", "type"],
7625
+ ["typedef", "type"],
7626
+ ["typealias", "type"]
7627
+ ]);
7628
+ var FALLBACK_SKIP = /* @__PURE__ */ new Set([
7629
+ ...FALLBACK_KINDS.keys(),
7630
+ "export",
7631
+ "pub",
7632
+ "public",
7633
+ "private",
7634
+ "protected",
7635
+ "internal",
7636
+ "static",
7637
+ "final",
7638
+ "abstract",
7639
+ "override",
7640
+ "virtual",
7641
+ "inline",
7642
+ "async",
7643
+ "unsafe",
7644
+ "extern",
7645
+ "shared",
7646
+ "readonly",
7647
+ "declare",
7648
+ "local",
7649
+ "extension",
7650
+ "template",
7651
+ "operator",
7652
+ "property",
7653
+ "event",
7654
+ "signal",
7655
+ "macro",
7656
+ "task",
7657
+ "const",
7658
+ "let",
7659
+ "var",
7660
+ "val",
7661
+ "auto",
7662
+ "new",
7663
+ "return",
7664
+ "self",
7665
+ "this",
7666
+ "void",
7667
+ "int",
7668
+ "long",
7669
+ "short",
7670
+ "byte",
7671
+ "char",
7672
+ "bool",
7673
+ "boolean",
7674
+ "float",
7675
+ "double",
7676
+ "string",
7677
+ "str",
7678
+ "unsigned",
7679
+ "signed",
7680
+ "size_t",
7681
+ "mut",
7682
+ "end",
7683
+ "do",
7684
+ "then",
7685
+ "begin",
7686
+ "where",
7687
+ "with",
7688
+ "as",
7689
+ "in",
7690
+ "of",
7691
+ "is",
7692
+ "not",
7693
+ "and",
7694
+ "or",
7695
+ "if",
7696
+ "else",
7697
+ "for",
7698
+ "while",
7699
+ "switch",
7700
+ "match",
7701
+ "try",
7702
+ "catch",
7703
+ "throw",
7704
+ "throws",
7705
+ "extends",
7706
+ "implements"
7707
+ ]);
7708
+ var fallbackSymbol = (file, line, lineNumber) => {
7709
+ const trimmed = line.trim();
7710
+ if (trimmed.length === 0) return void 0;
7711
+ if (COMMENT_HEAD.test(trimmed) || IMPORT_HEAD.test(trimmed)) return void 0;
7712
+ if (!DECLARATION_HEAD.test(trimmed) && !ASSIGNMENT_HEAD.test(trimmed)) return void 0;
7713
+ IDENTIFIERS.lastIndex = 0;
7714
+ let kind = "const";
7715
+ let name;
7716
+ for (let token = IDENTIFIERS.exec(trimmed); token !== null; token = IDENTIFIERS.exec(trimmed)) {
7717
+ const word = token[0];
7718
+ if (!FALLBACK_SKIP.has(word)) {
7719
+ name = word;
7720
+ break;
7721
+ }
7722
+ const mapped = FALLBACK_KINDS.get(word);
7723
+ if (mapped !== void 0 && kind === "const") kind = mapped;
7724
+ }
7725
+ if (name === void 0 || !IDENTIFIER.test(name)) return void 0;
7726
+ const exported = EXPORTED_HEAD.test(trimmed) || name.charCodeAt(0) !== 95;
7727
+ return { file, line: lineNumber, kind, name, exported };
7728
+ };
7729
+ var countLines = (code) => {
7730
+ let lines = 1;
7731
+ for (let at = code.indexOf("\n"); at >= 0; at = code.indexOf("\n", at + 1)) lines += 1;
7732
+ return lines;
7733
+ };
7734
+ var record = (into, symbol) => {
7735
+ const key = `${symbol.file}\0${symbol.line}\0${symbol.name}`;
7736
+ const existing = into.get(key);
7737
+ if (existing === void 0) {
7738
+ into.set(key, symbol);
7739
+ return;
7740
+ }
7741
+ if (symbol.exported) existing.exported = true;
7742
+ if (KIND_RANK[symbol.kind] > KIND_RANK[existing.kind]) existing.kind = symbol.kind;
7743
+ };
7744
+ var toPosix2 = (value) => path8.sep === "/" ? value : value.split(path8.sep).join("/");
7745
+ var compareSymbols = (left, right) => {
7746
+ if (left.file !== right.file) return left.file < right.file ? -1 : 1;
7747
+ if (left.line !== right.line) return left.line - right.line;
7748
+ return left.name < right.name ? -1 : left.name > right.name ? 1 : 0;
7749
+ };
7750
+ async function buildSymbolIndex(request) {
7751
+ const startedAt = Date.now();
7752
+ const signal = request.signal;
7753
+ throwIfAborted(signal);
7754
+ const root = path8.resolve(request.root);
7755
+ const matcher = request.glob === void 0 ? void 0 : globToRegExp(request.glob);
7756
+ const discovered = await discoverFiles(root, matcher, signal);
7757
+ discovered.sort();
7758
+ let truncated = false;
7759
+ let files = discovered;
7760
+ if (files.length > request.maxFiles) {
7761
+ files = discovered.slice(0, request.maxFiles);
7762
+ truncated = true;
7763
+ }
7764
+ const languages = {};
7765
+ const assigned = /* @__PURE__ */ new Map();
7766
+ const activeSpecs = /* @__PURE__ */ new Set();
7767
+ const fallbackFiles = [];
7768
+ for (const file of files) {
7769
+ const extension = indexableExtension(file);
7770
+ if (extension === void 0) continue;
7771
+ const spec = EXTENSION_SPECS.get(extension);
7772
+ const label = spec?.id ?? extension;
7773
+ languages[label] = (languages[label] ?? 0) + 1;
7774
+ if (spec === void 0) {
7775
+ fallbackFiles.push(file);
7776
+ continue;
7777
+ }
7778
+ assigned.set(file, spec.id);
7779
+ activeSpecs.add(spec.id);
7780
+ }
7781
+ const natives = await codeNatives();
7782
+ const collected = /* @__PURE__ */ new Map();
7783
+ const matchLimit = Math.max(4096, request.maxSymbols * 2);
7784
+ for (const spec of LANGUAGE_SPECS) {
7785
+ if (!activeSpecs.has(spec.id)) continue;
7786
+ throwIfAborted(signal);
7787
+ const scoped = [];
7788
+ for (const [file, id] of assigned) if (id === spec.id) scoped.push(file);
7789
+ const prefix = commonDirectory(scoped);
7790
+ const result = await natives.astGrep({
7791
+ patterns: spec.patterns,
7792
+ lang: spec.lang,
7793
+ path: prefix === "" ? root : path8.join(root, prefix),
7794
+ glob: spec.glob,
7795
+ includeMeta: true,
7796
+ limit: matchLimit,
7797
+ timeoutMs: MATCH_TIMEOUT_MS,
7798
+ ...signal ? { signal } : {}
7799
+ });
7800
+ if (result.limitReached) truncated = true;
7801
+ for (const match of result.matches) {
7802
+ const relative = toPosix2(match.path);
7803
+ const file = prefix === "" ? relative : `${prefix}/${relative}`;
7804
+ if (assigned.get(file) !== spec.id) continue;
7805
+ const name = match.metaVariables?.NAME;
7806
+ if (name === void 0 || !IDENTIFIER.test(name)) continue;
7807
+ const classification = spec.classify(match.text, match.metaVariables);
7808
+ record(collected, {
7809
+ file,
7810
+ line: match.startLine,
7811
+ kind: classification.kind,
7812
+ name,
7813
+ exported: classification.exported
7814
+ });
7815
+ }
7816
+ }
7817
+ for (const file of fallbackFiles) {
7818
+ throwIfAborted(signal);
7819
+ let code;
7820
+ try {
7821
+ code = await readFile(path8.join(root, file), "utf8");
7822
+ } catch {
7823
+ continue;
7824
+ }
7825
+ if (code.length === 0 || code.length > MAX_FALLBACK_BYTES) continue;
7826
+ let summary;
7827
+ try {
7828
+ summary = natives.summarizeCode({
7829
+ code,
7830
+ path: file,
7831
+ unfoldUntilLines: Math.max(64, countLines(code) >> 2)
7832
+ });
7833
+ } catch {
7834
+ continue;
7835
+ }
7836
+ for (const segment of summary.segments) {
7837
+ if (segment.kind !== "kept" || segment.text === void 0) continue;
7838
+ const lines = segment.text.split("\n");
7839
+ for (let offset = 0; offset < lines.length; offset += 1) {
7840
+ const symbol = fallbackSymbol(file, lines[offset] ?? "", segment.startLine + offset);
7841
+ if (symbol !== void 0) record(collected, symbol);
7842
+ }
7843
+ }
7844
+ }
7845
+ const symbols = [...collected.values()];
7846
+ symbols.sort(compareSymbols);
7847
+ if (symbols.length > request.maxSymbols) {
7848
+ symbols.length = request.maxSymbols;
7849
+ truncated = true;
7850
+ }
7851
+ return {
7852
+ root,
7853
+ symbols,
7854
+ files,
7855
+ languages,
7856
+ fallbackFiles,
7857
+ truncated,
7858
+ elapsedMs: Date.now() - startedAt
7859
+ };
7860
+ }
7861
+
7862
+ // src/providers/codemap-provider.ts
7863
+ var INDEX_TTL_MS = 3e4;
7864
+ var mapSchema = Type.Object({
7865
+ maxTokens: Type.Optional(Type.Number({
7866
+ minimum: 200,
7867
+ maximum: 2e5,
7868
+ description: "Token ceiling for the rendered map"
7869
+ })),
7870
+ glob: Type.Optional(Type.String({
7871
+ maxLength: 512,
7872
+ description: "Glob filter relative to the workspace root"
7873
+ })),
7874
+ focus: Type.Optional(Type.String({
7875
+ maxLength: 512,
7876
+ description: "Task description or symbol name the map should centre on"
7877
+ })),
7878
+ seeds: Type.Optional(Type.Array(Type.String({ maxLength: 1024 }), {
7879
+ maxItems: 32,
7880
+ description: "Files whose git co-change history should raise related files in the ranking"
7881
+ })),
7882
+ refresh: Type.Optional(Type.Boolean({
7883
+ description: "Rebuild the symbol index instead of reusing the cached one"
7884
+ }))
7885
+ }, { additionalProperties: false });
7886
+ var cascadeSchema = Type.Object({
7887
+ seeds: Type.Array(Type.String({ maxLength: 1024 }), {
7888
+ minItems: 1,
7889
+ maxItems: 32,
7890
+ description: "Files to rank co-change against"
7891
+ }),
7892
+ limit: Type.Optional(Type.Number({ minimum: 1, maximum: 200 })),
7893
+ maxCommits: Type.Optional(Type.Number({ minimum: 10, maximum: 2e4 }))
7894
+ }, { additionalProperties: false });
7895
+ var checked = (action, schema, args) => {
7896
+ const validation = validateJsonSchemaValue(schema.toJsonSchema(), args);
7897
+ if (!validation.success) {
7898
+ const message2 = validation.issues.slice(0, 5).map((issue) => issue.message).join("; ");
7899
+ throw new Error(`Invalid codemap.${action} arguments: ${message2}`);
7900
+ }
7901
+ return args;
7902
+ };
7903
+ var descriptors = [
7904
+ {
7905
+ name: "map",
7906
+ description: "Repo-wide symbol map under an explicit token budget. Returns one line per symbol (line, kind, name) grouped by file, ranked by focus relevance and optional git co-change, with omission counts when the budget bites. Answers which files and symbols a task touches; use omp.grep for text and omp.read for source.",
7907
+ inputSchema: mapSchema.toJsonSchema(),
7908
+ risk: "read"
7909
+ },
7910
+ {
7911
+ name: "cascade",
7912
+ description: "Rank files by how often they historically changed in the same commits as the seed files, normalised so ubiquitous files (lockfiles, changelogs) do not dominate. Answers which files a change will drag along, which text search cannot.",
7913
+ inputSchema: cascadeSchema.toJsonSchema(),
7914
+ risk: "read"
7915
+ }
7916
+ ];
7917
+ var normalizeCodemapArgs = actionArgNormalizer(() => descriptors);
7918
+ var CodemapProvider = class {
7919
+ constructor(config) {
7920
+ this.config = config;
7921
+ }
7922
+ name = "codemap";
7923
+ description = "Structural repo map: budgeted symbol disclosure and git co-change ranking";
7924
+ #cache = /* @__PURE__ */ new Map();
7925
+ async list(request, _context) {
7926
+ const query = request.query?.toLowerCase();
7927
+ return query ? descriptors.filter(
7928
+ (descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
7929
+ ) : descriptors;
7930
+ }
7931
+ async describe(actionName, _context) {
7932
+ return descriptors.find((descriptor) => descriptor.name === actionName);
7933
+ }
7934
+ prepareArguments(actionName, args) {
7935
+ return normalizeCodemapArgs(actionName, args);
7936
+ }
7937
+ async #index(root, glob, refresh, signal) {
7938
+ const key = `${root}\0${glob ?? ""}`;
7939
+ const cached = this.#cache.get(key);
7940
+ if (!refresh && cached && Date.now() - cached.at < INDEX_TTL_MS) return cached.index;
7941
+ const index = await buildSymbolIndex({
7942
+ root,
7943
+ ...glob !== void 0 ? { glob } : {},
7944
+ maxFiles: this.config.maxFiles,
7945
+ maxSymbols: this.config.maxSymbols,
7946
+ ...signal !== void 0 ? { signal } : {}
7947
+ });
7948
+ this.#cache.set(key, { index, at: Date.now() });
7949
+ return index;
7950
+ }
7951
+ async invoke(actionName, args, context) {
7952
+ switch (actionName) {
7953
+ case "map": {
7954
+ const input = checked("map", mapSchema, args);
7955
+ const index = await this.#index(context.cwd, input.glob, input.refresh === true, context.signal);
7956
+ let cascade;
7957
+ if (input.seeds && input.seeds.length > 0) {
7958
+ cascade = await coChange({
7959
+ root: context.cwd,
7960
+ seeds: input.seeds,
7961
+ maxCommits: this.config.cascadeCommits,
7962
+ limit: this.config.cascadeLimit
7963
+ });
7964
+ }
7965
+ const budgeted = assembleMap({
7966
+ index,
7967
+ maxTokens: input.maxTokens ?? this.config.defaultMaxTokens,
7968
+ ...input.focus !== void 0 ? { focus: input.focus } : {},
7969
+ ...cascade !== void 0 ? { cascade } : {}
7970
+ });
7971
+ context.activity?.({
7972
+ type: "progress",
7973
+ message: `Code map: ${budgeted.symbolsShown} symbols across ${budgeted.filesShown} files${budgeted.truncated ? ` (${budgeted.omittedSymbols} omitted)` : ""}`
7974
+ });
7975
+ return {
7976
+ ...budgeted,
7977
+ indexed: {
7978
+ files: index.files.length,
7979
+ symbols: index.symbols.length,
7980
+ languages: index.languages,
7981
+ fallbackFiles: index.fallbackFiles.length,
7982
+ truncated: index.truncated,
7983
+ elapsedMs: index.elapsedMs
7984
+ },
7985
+ ...cascade !== void 0 ? { cascade } : {}
7986
+ };
7987
+ }
7988
+ case "cascade": {
7989
+ const input = checked("cascade", cascadeSchema, args);
7990
+ const graph = await coChange({
7991
+ root: context.cwd,
7992
+ seeds: input.seeds,
7993
+ maxCommits: input.maxCommits ?? this.config.cascadeCommits,
7994
+ limit: input.limit ?? this.config.cascadeLimit
7995
+ });
7996
+ context.activity?.({
7997
+ type: "progress",
7998
+ message: graph.unavailable ? `Co-change unavailable: ${graph.unavailable}` : `Co-change: ${graph.edges.length} related files from ${graph.commitsScanned} commits`
7999
+ });
8000
+ return graph;
8001
+ }
8002
+ default:
8003
+ throw new Error(`Unknown codemap action: ${actionName}`);
8004
+ }
8005
+ }
8006
+ };
8007
+
8008
+ // src/providers/compact-provider.ts
8009
+ import { Type as Type2 } from "@oh-my-pi/pi-coding-agent/extensibility/legacy-typebox";
8010
+ import { validateJsonSchemaValue as validateJsonSchemaValue2 } from "@oh-my-pi/pi-ai/utils/schema";
8011
+ var requestSchema = Type2.Object({
8012
+ reason: Type2.Optional(Type2.String({
6770
8013
  maxLength: 1024,
6771
8014
  description: "Short human-readable reason for the compaction"
6772
8015
  })),
6773
- instructions: Type.Optional(Type.String({
8016
+ instructions: Type2.Optional(Type2.String({
6774
8017
  maxLength: MAX_COMPACTION_INSTRUCTIONS_CHARS,
6775
8018
  description: "Custom compaction instructions forwarded to OMP core"
6776
8019
  })),
6777
- preserve: Type.Optional(Type.Array(
6778
- Type.String({ maxLength: MAX_PRESERVE_ITEM_CHARS }),
8020
+ preserve: Type2.Optional(Type2.Array(
8021
+ Type2.String({ maxLength: MAX_PRESERVE_ITEM_CHARS }),
6779
8022
  {
6780
8023
  maxItems: MAX_PRESERVE_ITEMS,
6781
8024
  description: "Explicit bounded facts to preserve, encoded as a typed Fabric compaction request"
6782
8025
  }
6783
8026
  )),
6784
- requestedBy: Type.Optional(Type.String({
8027
+ requestedBy: Type2.Optional(Type2.String({
6785
8028
  maxLength: 256,
6786
8029
  description: "Who requested the compaction (default: model)"
6787
8030
  }))
6788
8031
  }, { additionalProperties: false });
6789
8032
  var checkedRequestArguments = (args) => {
6790
- const validation = validateJsonSchemaValue(requestSchema.toJsonSchema(), args);
8033
+ const validation = validateJsonSchemaValue2(requestSchema.toJsonSchema(), args);
6791
8034
  if (!validation.success) {
6792
8035
  const message2 = validation.issues.slice(0, 5).map((error) => error.message).join("; ");
6793
8036
  throw new Error(`Invalid compact.request arguments: ${message2}`);
@@ -6811,7 +8054,7 @@ var emptySchema = {
6811
8054
  properties: {},
6812
8055
  additionalProperties: false
6813
8056
  };
6814
- var descriptors = [
8057
+ var descriptors2 = [
6815
8058
  {
6816
8059
  name: "request",
6817
8060
  description: "Request an advisory compaction of the host session's context at the next safe boundary (agent_end). The host commits it only between turns, never mid-turn. A new request replaces any pending one.",
@@ -6834,7 +8077,7 @@ var descriptors = [
6834
8077
  risk: "write"
6835
8078
  }
6836
8079
  ];
6837
- var normalizeCompactArgs = actionArgNormalizer(() => descriptors);
8080
+ var normalizeCompactArgs = actionArgNormalizer(() => descriptors2);
6838
8081
  var CompactProvider = class {
6839
8082
  constructor(controller) {
6840
8083
  this.controller = controller;
@@ -6843,12 +8086,12 @@ var CompactProvider = class {
6843
8086
  description = "Programmatic, advisory-then-committed context compaction for the host OMP session";
6844
8087
  async list(request, _context) {
6845
8088
  const query = request.query?.toLowerCase();
6846
- return query ? descriptors.filter(
8089
+ return query ? descriptors2.filter(
6847
8090
  (descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
6848
- ) : descriptors;
8091
+ ) : descriptors2;
6849
8092
  }
6850
8093
  async describe(actionName, _context) {
6851
- return descriptors.find((descriptor) => descriptor.name === actionName);
8094
+ return descriptors2.find((descriptor) => descriptor.name === actionName);
6852
8095
  }
6853
8096
  prepareArguments(actionName, args) {
6854
8097
  return normalizeCompactArgs(actionName, args);
@@ -6888,7 +8131,7 @@ var CompactProvider = class {
6888
8131
  };
6889
8132
 
6890
8133
  // src/providers/components-provider.ts
6891
- var descriptors2 = [
8134
+ var descriptors3 = [
6892
8135
  {
6893
8136
  name: "list",
6894
8137
  description: "List registered component definitions and configured component instances.",
@@ -6935,13 +8178,13 @@ var ComponentsProvider = class {
6935
8178
  description = "Supervised component lifecycle, exact capability dependencies, effect cleanup, and reload diagnostics.";
6936
8179
  async list(request, _context) {
6937
8180
  const query = request.query?.normalize("NFKC").trim().toLowerCase();
6938
- const filtered = query ? descriptors2.filter(
8181
+ const filtered = query ? descriptors3.filter(
6939
8182
  (descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
6940
- ) : descriptors2;
8183
+ ) : descriptors3;
6941
8184
  return filtered.slice(0, Math.max(1, Math.min(request.limit ?? 100, 100)));
6942
8185
  }
6943
8186
  async describe(actionName, _context) {
6944
- return descriptors2.find((descriptor) => descriptor.name === actionName);
8187
+ return descriptors3.find((descriptor) => descriptor.name === actionName);
6945
8188
  }
6946
8189
  async invoke(actionName, args, _context) {
6947
8190
  switch (actionName) {
@@ -6976,7 +8219,7 @@ var ComponentsProvider = class {
6976
8219
  import fs5 from "node:fs/promises";
6977
8220
  import fsSync from "node:fs";
6978
8221
  import os from "node:os";
6979
- import path7 from "node:path";
8222
+ import path9 from "node:path";
6980
8223
  var MCP_DESCRIPTOR_CACHE_VERSION = 1;
6981
8224
  var homeDir = () => {
6982
8225
  const home = process.env.HOME;
@@ -6987,25 +8230,25 @@ var expandHome = (input) => {
6987
8230
  const home = homeDir();
6988
8231
  if (input === "~") return home;
6989
8232
  if (input.startsWith("~/") || input.startsWith("~\\")) {
6990
- return path7.join(home, input.slice(2));
8233
+ return path9.join(home, input.slice(2));
6991
8234
  }
6992
8235
  return input;
6993
8236
  };
6994
- var legacyMcporterDir = () => path7.join(homeDir(), ".mcporter");
8237
+ var legacyMcporterDir = () => path9.join(homeDir(), ".mcporter");
6995
8238
  var mcporterConfigDir = () => {
6996
8239
  const raw = process.env.XDG_CONFIG_HOME;
6997
8240
  if (raw && raw.trim().length > 0) {
6998
8241
  const resolved = expandHome(raw.trim());
6999
- if (path7.isAbsolute(resolved)) return path7.join(resolved, "mcporter");
8242
+ if (path9.isAbsolute(resolved)) return path9.join(resolved, "mcporter");
7000
8243
  }
7001
8244
  return legacyMcporterDir();
7002
8245
  };
7003
8246
  var mcporterConfigCandidates = () => {
7004
8247
  const base = mcporterConfigDir();
7005
- const candidates = [path7.join(base, "mcporter.json"), path7.join(base, "mcporter.jsonc")];
8248
+ const candidates = [path9.join(base, "mcporter.json"), path9.join(base, "mcporter.jsonc")];
7006
8249
  const legacy = legacyMcporterDir();
7007
8250
  if (base !== legacy) {
7008
- candidates.push(path7.join(legacy, "mcporter.json"), path7.join(legacy, "mcporter.jsonc"));
8251
+ candidates.push(path9.join(legacy, "mcporter.json"), path9.join(legacy, "mcporter.jsonc"));
7009
8252
  }
7010
8253
  return candidates;
7011
8254
  };
@@ -7020,12 +8263,12 @@ var pathExists = (filePath) => {
7020
8263
  var mcpConfigLayerPaths = (rootDir, configPath) => {
7021
8264
  const explicitRaw = configPath ?? process.env.MCPORTER_CONFIG;
7022
8265
  if (explicitRaw && explicitRaw.trim().length > 0) {
7023
- return [path7.resolve(expandHome(explicitRaw.trim()))];
8266
+ return [path9.resolve(expandHome(explicitRaw.trim()))];
7024
8267
  }
7025
8268
  const paths = [];
7026
8269
  const home = mcporterConfigCandidates().find(pathExists);
7027
8270
  if (home) paths.push(home);
7028
- const projectPath = path7.resolve(rootDir, "config", "mcporter.json");
8271
+ const projectPath = path9.resolve(rootDir, "config", "mcporter.json");
7029
8272
  if (pathExists(projectPath)) paths.push(projectPath);
7030
8273
  return paths;
7031
8274
  };
@@ -7076,8 +8319,8 @@ var parseCacheFile = (value) => {
7076
8319
  servers: value.servers
7077
8320
  };
7078
8321
  };
7079
- var projectMcpCachePath = (projectRoot) => path7.join(projectRoot, ".omp", "fabric", "mcp-cache.json");
7080
- var globalMcpCachePath = (agentDir) => path7.join(agentDir, "fabric", "mcp-descriptors.json");
8322
+ var projectMcpCachePath = (projectRoot) => path9.join(projectRoot, ".omp", "fabric", "mcp-cache.json");
8323
+ var globalMcpCachePath = (agentDir) => path9.join(agentDir, "fabric", "mcp-descriptors.json");
7081
8324
  var tempCounter = 0;
7082
8325
  var McpDescriptorCacheStore = class {
7083
8326
  constructor(filePath) {
@@ -7094,9 +8337,9 @@ var McpDescriptorCacheStore = class {
7094
8337
  // Atomic-ish write: temp file then rename, so a concurrent reader either
7095
8338
  // sees the previous cache or the next one, never a torn document.
7096
8339
  async save(file) {
7097
- const directory = path7.dirname(this.filePath);
8340
+ const directory = path9.dirname(this.filePath);
7098
8341
  await fs5.mkdir(directory, { recursive: true });
7099
- const tempPath = path7.join(
8342
+ const tempPath = path9.join(
7100
8343
  directory,
7101
8344
  `.mcp-cache-${process.pid}-${Date.now()}-${tempCounter++}.tmp`
7102
8345
  );
@@ -7111,7 +8354,7 @@ var McpDescriptorCacheStore = class {
7111
8354
  };
7112
8355
 
7113
8356
  // src/providers/mcp-provider.ts
7114
- import path8 from "node:path";
8357
+ import path10 from "node:path";
7115
8358
  var TOOL_METADATA_TTL_MS = 6e4;
7116
8359
  var REVALIDATE_CONCURRENCY = 3;
7117
8360
  var REVALIDATE_SERVER_TIMEOUT_MS = 2e4;
@@ -7181,16 +8424,16 @@ var managementDescriptors = [
7181
8424
  var normalizeSchema = (schema) => typeof schema === "object" && schema !== null && !Array.isArray(schema) ? schema : emptyObjectSchema;
7182
8425
  var normalizeMcpResult = (result) => {
7183
8426
  if (typeof result !== "object" || result === null || Array.isArray(result)) return result;
7184
- const record = result;
7185
- if (!Array.isArray(record.content)) return result;
7186
- const text = record.content.filter(
8427
+ const record2 = result;
8428
+ if (!Array.isArray(record2.content)) return result;
8429
+ const text = record2.content.filter(
7187
8430
  (part) => typeof part === "object" && part !== null && part.type === "text" && typeof part.text === "string"
7188
8431
  ).map((part) => part.text).join("\n");
7189
- if (record.isError === true) throw new Error(text || "MCP tool returned an error");
8432
+ if (record2.isError === true) throw new Error(text || "MCP tool returned an error");
7190
8433
  return {
7191
8434
  text,
7192
- content: record.content,
7193
- structuredContent: record.structuredContent ?? null
8435
+ content: record2.content,
8436
+ structuredContent: record2.structuredContent ?? null
7194
8437
  };
7195
8438
  };
7196
8439
  var delay2 = (ms, signal) => new Promise((resolve2) => {
@@ -7265,9 +8508,9 @@ var McpProvider = class {
7265
8508
  this.#kickRevalidation();
7266
8509
  if (!request.namespace) await this.#awaitColdEnumeration(context.signal);
7267
8510
  const query = request.query?.toLowerCase();
7268
- const filterQuery = (descriptors6) => query ? descriptors6.filter(
8511
+ const filterQuery = (descriptors7) => query ? descriptors7.filter(
7269
8512
  (descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
7270
- ) : descriptors6;
8513
+ ) : descriptors7;
7271
8514
  if (request.namespace) {
7272
8515
  const server = await this.#resolveKnownServer(request.namespace);
7273
8516
  if (!server) return [];
@@ -7416,11 +8659,11 @@ var McpProvider = class {
7416
8659
  // Provider-fidelity descriptors for everything currently known, cached or
7417
8660
  // ephemeral.
7418
8661
  sliceDescriptors() {
7419
- const descriptors6 = [];
8662
+ const descriptors7 = [];
7420
8663
  for (const [server, entry] of this.#servers) {
7421
- for (const tool of entry.tools) descriptors6.push(this.#toolDescriptor(server, tool));
8664
+ for (const tool of entry.tools) descriptors7.push(this.#toolDescriptor(server, tool));
7422
8665
  }
7423
- return descriptors6;
8666
+ return descriptors7;
7424
8667
  }
7425
8668
  // Test/ops hook: await hydration and any in-flight background revalidation,
7426
8669
  // then flush pending persistence and notifications.
@@ -7822,7 +9065,7 @@ var McpProvider = class {
7822
9065
  kind: "stdio",
7823
9066
  command: args.command,
7824
9067
  args: commandArgs,
7825
- cwd: path8.resolve(this.cwd, typeof args.cwd === "string" ? args.cwd : ".")
9068
+ cwd: path10.resolve(this.cwd, typeof args.cwd === "string" ? args.cwd : ".")
7826
9069
  },
7827
9070
  ...env ? { env } : {}
7828
9071
  };
@@ -7887,13 +9130,13 @@ var McpProvider = class {
7887
9130
  return tools.map((tool) => this.#toolDescriptor(server, tool));
7888
9131
  })
7889
9132
  );
7890
- const descriptors6 = settled.flatMap(
9133
+ const descriptors7 = settled.flatMap(
7891
9134
  (entry) => entry.status === "fulfilled" ? entry.value : []
7892
9135
  );
7893
9136
  const query = request.query?.toLowerCase();
7894
- const filtered = query ? descriptors6.filter(
9137
+ const filtered = query ? descriptors7.filter(
7895
9138
  (descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
7896
- ) : descriptors6;
9139
+ ) : descriptors7;
7897
9140
  return request.namespace ? filtered : [...managementDescriptors, ...filtered];
7898
9141
  }
7899
9142
  async #describeLegacy(actionName, _context) {
@@ -7965,7 +9208,7 @@ var assertReadableStateKey = (key) => {
7965
9208
  throw new Error(`Fabric mesh key is private host state: ${key}`);
7966
9209
  }
7967
9210
  };
7968
- var descriptors3 = [
9211
+ var descriptors4 = [
7969
9212
  {
7970
9213
  name: "self",
7971
9214
  description: "Return this Fabric participant's mesh identity",
@@ -8084,7 +9327,7 @@ var descriptors3 = [
8084
9327
  namespace: "coordination"
8085
9328
  }
8086
9329
  ];
8087
- var normalizeMeshArgs = actionArgNormalizer(() => descriptors3);
9330
+ var normalizeMeshArgs = actionArgNormalizer(() => descriptors4);
8088
9331
  var MeshProvider = class {
8089
9332
  constructor(store, identity, participants) {
8090
9333
  this.store = store;
@@ -8095,12 +9338,12 @@ var MeshProvider = class {
8095
9338
  description = "Durable topics and compare-and-swap shared state for emergent agent coordination";
8096
9339
  async list(request, _context) {
8097
9340
  const query = request.query?.toLowerCase();
8098
- return query ? descriptors3.filter(
9341
+ return query ? descriptors4.filter(
8099
9342
  (descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
8100
- ) : descriptors3;
9343
+ ) : descriptors4;
8101
9344
  }
8102
9345
  async describe(actionName, _context) {
8103
- return descriptors3.find((descriptor) => descriptor.name === actionName);
9346
+ return descriptors4.find((descriptor) => descriptor.name === actionName);
8104
9347
  }
8105
9348
  prepareArguments(actionName, args) {
8106
9349
  return normalizeMeshArgs(actionName, args);
@@ -8191,7 +9434,7 @@ var MeshProvider = class {
8191
9434
  import { mkdirSync as mkdirSync2, mkdtempSync, readFileSync as readFileSync2, statSync as statSync3, writeFileSync as writeFileSync2 } from "node:fs";
8192
9435
  import { AsyncLocalStorage } from "node:async_hooks";
8193
9436
  import os2 from "node:os";
8194
- import path11 from "node:path";
9437
+ import path13 from "node:path";
8195
9438
  import { randomUUID as randomUUID3 } from "node:crypto";
8196
9439
  import { BashTool } from "@oh-my-pi/pi-coding-agent/tools/bash";
8197
9440
  import { EditTool } from "@oh-my-pi/pi-coding-agent/edit";
@@ -8207,7 +9450,7 @@ import {
8207
9450
 
8208
9451
  // src/agents/bash-worktree-add.ts
8209
9452
  import fs6 from "node:fs";
8210
- import path9 from "node:path";
9453
+ import path11 from "node:path";
8211
9454
  var BARE_SAFE = /^[A-Za-z0-9_./:@%+=,-]+$/;
8212
9455
  var parseGitWorktreeAdd = (command) => {
8213
9456
  const trimmed = command.trim();
@@ -8270,8 +9513,8 @@ var tryExecuteGitWorktreeAdd = async (args, sessionCwd) => {
8270
9513
  if (typeof command !== "string") return void 0;
8271
9514
  const parsed = parseGitWorktreeAdd(command);
8272
9515
  if (!parsed) return void 0;
8273
- const gitCwd = parsed.gitCwd ? path9.resolve(sessionCwd, parsed.gitCwd) : typeof args.cwd === "string" ? args.cwd : sessionCwd;
8274
- const dest = path9.resolve(gitCwd, parsed.dest);
9516
+ const gitCwd = parsed.gitCwd ? path11.resolve(sessionCwd, parsed.gitCwd) : typeof args.cwd === "string" ? args.cwd : sessionCwd;
9517
+ const dest = path11.resolve(gitCwd, parsed.dest);
8275
9518
  let gitRoot;
8276
9519
  try {
8277
9520
  const root = await executeFile("git", ["rev-parse", "--show-toplevel"], {
@@ -8300,9 +9543,9 @@ var tryExecuteGitWorktreeAdd = async (args, sessionCwd) => {
8300
9543
 
8301
9544
  // src/providers/omp-bash-cwd.ts
8302
9545
  import { accessSync, constants, statSync as statSync2 } from "node:fs";
8303
- import path10 from "node:path";
9546
+ import path12 from "node:path";
8304
9547
  import { createBashToolDefinition } from "@oh-my-pi/pi-coding-agent/extensibility/legacy-pi-coding-agent-shim";
8305
- import { Type as Type2 } from "@oh-my-pi/pi-coding-agent/extensibility/legacy-typebox";
9548
+ import { Type as Type3 } from "@oh-my-pi/pi-coding-agent/extensibility/legacy-typebox";
8306
9549
  var OMP_BASH_CWD_KEY = "cwd";
8307
9550
  var resolveOmpShellCwd = (toolName, sessionCwd, requested) => {
8308
9551
  if (typeof requested !== "string" || requested.trim().length === 0) {
@@ -8310,7 +9553,7 @@ var resolveOmpShellCwd = (toolName, sessionCwd, requested) => {
8310
9553
  `Invalid omp.${toolName} cwd ${JSON.stringify(requested)}: path must be a non-empty string`
8311
9554
  );
8312
9555
  }
8313
- const resolved = path10.isAbsolute(requested) ? path10.resolve(requested) : path10.resolve(sessionCwd, requested);
9556
+ const resolved = path12.isAbsolute(requested) ? path12.resolve(requested) : path12.resolve(sessionCwd, requested);
8314
9557
  try {
8315
9558
  if (!statSync2(resolved).isDirectory()) throw new Error("path is not a directory");
8316
9559
  accessSync(resolved, constants.R_OK | constants.X_OK);
@@ -8330,8 +9573,8 @@ var resolveShellCwdArgument = (toolName, sessionCwd, args) => Object.hasOwn(args
8330
9573
  args[OMP_BASH_CWD_KEY]
8331
9574
  )
8332
9575
  } : args;
8333
- var CWD_PROPERTY = Type2.Optional(
8334
- Type2.String({
9576
+ var CWD_PROPERTY = Type3.Optional(
9577
+ Type3.String({
8335
9578
  description: "Execution directory for this command; relative paths resolve from the session cwd."
8336
9579
  })
8337
9580
  );
@@ -8350,7 +9593,7 @@ var withShellCwdSchema = (schema) => {
8350
9593
  if (Object.hasOwn(document.properties, OMP_BASH_CWD_KEY)) return schema;
8351
9594
  const cwdSchema = schemaDocument2(CWD_PROPERTY);
8352
9595
  if (!cwdSchema) return schema;
8353
- return Type2.Unsafe({
9596
+ return Type3.Unsafe({
8354
9597
  ...document,
8355
9598
  properties: { ...document.properties, [OMP_BASH_CWD_KEY]: cwdSchema }
8356
9599
  });
@@ -8386,22 +9629,22 @@ var BashCwdDefinitions = class extends ShellCwdDefinitions {
8386
9629
  // src/providers/write-preview.ts
8387
9630
  import { homedir } from "node:os";
8388
9631
  import { dirname, isAbsolute, resolve } from "node:path";
8389
- import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
8390
- import { Type as Type3 } from "@oh-my-pi/pi-coding-agent/extensibility/legacy-typebox";
9632
+ import { mkdir, readFile as readFile2, stat, writeFile } from "node:fs/promises";
9633
+ import { Type as Type4 } from "@oh-my-pi/pi-coding-agent/extensibility/legacy-typebox";
8391
9634
  var mutationQueues = /* @__PURE__ */ new Map();
8392
- var withFileMutationQueue = async (path17, operation) => {
8393
- const previous = mutationQueues.get(path17) ?? Promise.resolve();
9635
+ var withFileMutationQueue = async (path19, operation) => {
9636
+ const previous = mutationQueues.get(path19) ?? Promise.resolve();
8394
9637
  let release;
8395
9638
  const current = new Promise((resolve2) => {
8396
9639
  release = resolve2;
8397
9640
  });
8398
- mutationQueues.set(path17, current);
9641
+ mutationQueues.set(path19, current);
8399
9642
  await previous;
8400
9643
  try {
8401
9644
  return await operation();
8402
9645
  } finally {
8403
9646
  release();
8404
- if (mutationQueues.get(path17) === current) mutationQueues.delete(path17);
9647
+ if (mutationQueues.get(path19) === current) mutationQueues.delete(path19);
8405
9648
  }
8406
9649
  };
8407
9650
  var resolvePreviewPath = (filePath, cwd) => {
@@ -8436,7 +9679,7 @@ var readExistingFileForPreview = async (filePath, cwd, nextContent) => {
8436
9679
  return skipped("previous file too large", fileStat.size, true);
8437
9680
  }
8438
9681
  try {
8439
- const content = await readFile(absolutePath, "utf8");
9682
+ const content = await readFile2(absolutePath, "utf8");
8440
9683
  const bytes = Buffer.byteLength(content, "utf8");
8441
9684
  return bytes > MAX_WRITE_DIFF_BYTES ? skipped("previous file too large", bytes, true) : { kind: "content", content };
8442
9685
  } catch {
@@ -8448,20 +9691,20 @@ var createPreviewWriteToolDefinition = (cwd) => {
8448
9691
  name: "write",
8449
9692
  label: "Write",
8450
9693
  description: "Write a file",
8451
- parameters: Type3.Object({ path: Type3.String(), content: Type3.String() }),
9694
+ parameters: Type4.Object({ path: Type4.String(), content: Type4.String() }),
8452
9695
  execute: async () => ({ content: [{ type: "text", text: "" }] })
8453
9696
  };
8454
9697
  return {
8455
9698
  ...original,
8456
9699
  async execute(_toolCallId, params, signal) {
8457
- const { path: path17, content } = params;
8458
- const absolutePath = resolvePreviewPath(path17, cwd);
9700
+ const { path: path19, content } = params;
9701
+ const absolutePath = resolvePreviewPath(path19, cwd);
8459
9702
  return withFileMutationQueue(absolutePath, async () => {
8460
9703
  const throwIfAborted2 = () => {
8461
9704
  if (signal?.aborted) throw new Error("Operation aborted");
8462
9705
  };
8463
9706
  throwIfAborted2();
8464
- const before = await readExistingFileForPreview(path17, cwd, content);
9707
+ const before = await readExistingFileForPreview(path19, cwd, content);
8465
9708
  throwIfAborted2();
8466
9709
  await mkdir(dirname(absolutePath), { recursive: true });
8467
9710
  throwIfAborted2();
@@ -8471,7 +9714,7 @@ var createPreviewWriteToolDefinition = (cwd) => {
8471
9714
  content: [
8472
9715
  {
8473
9716
  type: "text",
8474
- text: `Successfully wrote ${Buffer.byteLength(content, "utf8")} bytes to ${path17}`
9717
+ text: `Successfully wrote ${Buffer.byteLength(content, "utf8")} bytes to ${path19}`
8475
9718
  }
8476
9719
  ],
8477
9720
  details: { codePreviewBeforeWrite: before }
@@ -8486,7 +9729,7 @@ var MAX_RENDERER_ARGUMENT_CHARS = 2e5;
8486
9729
  var GUEST_READ_LINE_LIMIT = 1e5;
8487
9730
  var MAX_REPLACE_ALL_FILE_CHARS = 2e6;
8488
9731
  var createNativeSession = (cwd, artifactPaths) => {
8489
- const artifactRoot = artifactPaths ? mkdtempSync(path11.join(os2.tmpdir(), "omp-fabric-bash-")) : void 0;
9732
+ const artifactRoot = artifactPaths ? mkdtempSync(path13.join(os2.tmpdir(), "omp-fabric-bash-")) : void 0;
8490
9733
  return {
8491
9734
  cwd,
8492
9735
  hasUI: false,
@@ -8503,7 +9746,7 @@ var createNativeSession = (cwd, artifactPaths) => {
8503
9746
  try {
8504
9747
  mkdirSync2(artifactRoot, { recursive: true, mode: 448 });
8505
9748
  const id = randomUUID3();
8506
- const artifactPath = path11.join(artifactRoot, `${toolType}-${id}.log`);
9749
+ const artifactPath = path13.join(artifactRoot, `${toolType}-${id}.log`);
8507
9750
  writeFileSync2(artifactPath, "", { mode: 384 });
8508
9751
  artifactPaths.set(id, artifactPath);
8509
9752
  artifactAllocations.getStore()?.push(artifactPath);
@@ -8566,19 +9809,19 @@ var createGrepDefinitionWithSkip = (cwd) => {
8566
9809
  ...legacy,
8567
9810
  parameters: withGrepSkipSchema(legacy.parameters),
8568
9811
  execute: (toolCallId, params, signal, onUpdate, context) => {
8569
- const record = asRecord(params) ?? {};
8570
- const rawPattern = typeof record.pattern === "string" ? record.pattern : "";
8571
- const searchPath = typeof record.path === "string" ? record.path : ".";
8572
- const glob = typeof record.glob === "string" ? record.glob : void 0;
8573
- const contextLines = typeof record.context === "number" ? record.context : void 0;
8574
- const skip = typeof record.skip === "number" ? record.skip : void 0;
9812
+ const record2 = asRecord(params) ?? {};
9813
+ const rawPattern = typeof record2.pattern === "string" ? record2.pattern : "";
9814
+ const searchPath = typeof record2.path === "string" ? record2.path : ".";
9815
+ const glob = typeof record2.glob === "string" ? record2.glob : void 0;
9816
+ const contextLines = typeof record2.context === "number" ? record2.context : void 0;
9817
+ const skip = typeof record2.skip === "number" ? record2.skip : void 0;
8575
9818
  const tool = contextLines === void 0 ? defaultTool : new GrepTool(grepSession(cwd, contextLines));
8576
9819
  return tool.execute(
8577
9820
  toolCallId,
8578
9821
  {
8579
- pattern: record.literal === true ? piEscapeRegexLiteral(rawPattern) : rawPattern,
9822
+ pattern: record2.literal === true ? piEscapeRegexLiteral(rawPattern) : rawPattern,
8580
9823
  path: glob ? piJoinPath(searchPath, glob) : searchPath,
8581
- case: record.ignoreCase === true ? false : void 0,
9824
+ case: record2.ignoreCase === true ? false : void 0,
8582
9825
  ...skip === void 0 ? {} : { skip }
8583
9826
  },
8584
9827
  signal,
@@ -8598,19 +9841,19 @@ var normalizeEditArguments = (args, replaceAll, cwd) => {
8598
9841
  if (typeof edit !== "object" || edit === null || Array.isArray(edit)) {
8599
9842
  throw new Error(`omp.edit edits[${index}] must be an object`);
8600
9843
  }
8601
- const record = edit;
8602
- const oldString = record.old_string ?? record.oldText ?? record.old;
8603
- const newString = record.new_string ?? record.newText ?? record.new ?? record.replacement;
9844
+ const record2 = edit;
9845
+ const oldString = record2.old_string ?? record2.oldText ?? record2.old;
9846
+ const newString = record2.new_string ?? record2.newText ?? record2.new ?? record2.replacement;
8604
9847
  if (typeof oldString !== "string" || typeof newString !== "string") {
8605
9848
  throw new Error(`omp.edit edits[${index}] requires old and new text strings`);
8606
9849
  }
8607
9850
  return {
8608
9851
  old_string: oldString,
8609
9852
  new_string: newString,
8610
- ...replaceAll || record.all === true || record.replace_all === true ? { replace_all: true } : {}
9853
+ ...replaceAll || record2.all === true || record2.replace_all === true ? { replace_all: true } : {}
8611
9854
  };
8612
9855
  });
8613
- const resolvedPath = path11.resolve(cwd, filePath.startsWith("@") ? filePath.slice(1) : filePath);
9856
+ const resolvedPath = path13.resolve(cwd, filePath.startsWith("@") ? filePath.slice(1) : filePath);
8614
9857
  const current = readFileSync2(resolvedPath, "utf8");
8615
9858
  if (current.length > MAX_REPLACE_ALL_FILE_CHARS) {
8616
9859
  throw new Error(`omp.edit refuses files over ${MAX_REPLACE_ALL_FILE_CHARS} characters`);
@@ -8722,7 +9965,7 @@ var keepLeadingLines = (text, count) => {
8722
9965
  }
8723
9966
  return text.slice(0, index - 1);
8724
9967
  };
8725
- var countLines = (text) => {
9968
+ var countLines2 = (text) => {
8726
9969
  if (text.length === 0) return 0;
8727
9970
  let lines = 1;
8728
9971
  for (let index = text.indexOf("\n"); index !== -1; index = text.indexOf("\n", index + 1)) lines++;
@@ -8791,11 +10034,11 @@ var withoutColumnLimit = (detailRecord, metaRecord) => {
8791
10034
  return remainingDetails;
8792
10035
  };
8793
10036
  var grepTruncationSignal = (details) => {
8794
- const record = asRecord(details);
8795
- if (!record || record.truncated !== true) return void 0;
8796
- const perFile = finiteNumber2(record.perFileLimitReached);
8797
- const maxColumn = finiteNumber2(asRecord(asRecord(asRecord(record.meta)?.limits)?.columnTruncated)?.maxColumn);
8798
- const fileCount = finiteNumber2(record.fileCount);
10037
+ const record2 = asRecord(details);
10038
+ if (!record2 || record2.truncated !== true) return void 0;
10039
+ const perFile = finiteNumber2(record2.perFileLimitReached);
10040
+ const maxColumn = finiteNumber2(asRecord(asRecord(asRecord(record2.meta)?.limits)?.columnTruncated)?.maxColumn);
10041
+ const fileCount = finiteNumber2(record2.fileCount);
8799
10042
  const reasons = [];
8800
10043
  const notes = [];
8801
10044
  let continuation = null;
@@ -8822,7 +10065,7 @@ var grepTruncationSignal = (details) => {
8822
10065
  tool: "grep",
8823
10066
  partial: true,
8824
10067
  reasons,
8825
- ...finiteNumber2(record.matchCount) === void 0 ? {} : { matchCount: record.matchCount },
10068
+ ...finiteNumber2(record2.matchCount) === void 0 ? {} : { matchCount: record2.matchCount },
8826
10069
  ...fileCount === void 0 ? {} : { fileCount },
8827
10070
  ...perFile === void 0 ? {} : { perFileMatchLimit: perFile },
8828
10071
  ...maxColumn === void 0 ? {} : { maxColumn },
@@ -8859,9 +10102,9 @@ var lineBudgetSignal = (meta, target, progress) => {
8859
10102
  };
8860
10103
  };
8861
10104
  var findTruncationSignal = (details) => {
8862
- const record = asRecord(details);
8863
- if (!record || record.truncated !== true) return void 0;
8864
- const reached = finiteNumber2(record.resultLimitReached) ?? finiteNumber2(record.fileCount);
10105
+ const record2 = asRecord(details);
10106
+ if (!record2 || record2.truncated !== true) return void 0;
10107
+ const reached = finiteNumber2(record2.resultLimitReached) ?? finiteNumber2(record2.fileCount);
8865
10108
  return {
8866
10109
  tool: "find",
8867
10110
  partial: true,
@@ -9014,10 +10257,10 @@ var OmpToolsProvider = class _OmpToolsProvider {
9014
10257
  }
9015
10258
  async list(request, _context) {
9016
10259
  const query = request.query?.toLowerCase();
9017
- const descriptors6 = await Promise.all(
10260
+ const descriptors7 = await Promise.all(
9018
10261
  OMP_CORE_TOOL_NAMES.map((name) => this.describe(name, _context))
9019
10262
  );
9020
- return descriptors6.filter((descriptor) => descriptor !== void 0).filter(
10263
+ return descriptors7.filter((descriptor) => descriptor !== void 0).filter(
9021
10264
  (descriptor) => query ? `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query) : true
9022
10265
  );
9023
10266
  }
@@ -9041,13 +10284,13 @@ var OmpToolsProvider = class _OmpToolsProvider {
9041
10284
  if (typeof prepared !== "object" || prepared === null || Array.isArray(prepared)) {
9042
10285
  throw new Error(`OMP tool ${actionName} prepared non-object arguments`);
9043
10286
  }
9044
- const record = prepared;
10287
+ const record2 = prepared;
9045
10288
  if (isOmpShellToolName(actionName)) {
9046
- const shellArgs = Object.hasOwn(args, OMP_BASH_CWD_KEY) ? { ...record, [OMP_BASH_CWD_KEY]: args[OMP_BASH_CWD_KEY] } : record;
10289
+ const shellArgs = Object.hasOwn(args, OMP_BASH_CWD_KEY) ? { ...record2, [OMP_BASH_CWD_KEY]: args[OMP_BASH_CWD_KEY] } : record2;
9047
10290
  return resolveShellCwdArgument(actionName, this.#cwd, shellArgs);
9048
10291
  }
9049
- if (actionName === "read") return normalizeReadArguments(record);
9050
- return actionName === "edit" ? normalizeEditArguments(record, args.all === true, this.#cwd) : record;
10292
+ if (actionName === "read") return normalizeReadArguments(record2);
10293
+ return actionName === "edit" ? normalizeEditArguments(record2, args.all === true, this.#cwd) : record2;
9051
10294
  }
9052
10295
  #assertAllowed(name) {
9053
10296
  if (this.#allowedTools && !this.#allowedTools.has(name)) {
@@ -9257,7 +10500,7 @@ var OmpToolsProvider = class _OmpToolsProvider {
9257
10500
  }
9258
10501
  const budget = resultCharBound(context) - READ_MARKER_RESERVE_CHARS;
9259
10502
  let text = stripRepeatReadHint(textContent(result.content));
9260
- let covered = meta.shownEnd ?? countLines(text);
10503
+ let covered = meta.shownEnd ?? countLines2(text);
9261
10504
  let nextOffset = meta.nextOffset;
9262
10505
  let stopped;
9263
10506
  while (nextOffset !== void 0 && covered < target.endLimit) {
@@ -9281,7 +10524,7 @@ var OmpToolsProvider = class _OmpToolsProvider {
9281
10524
  const pageText = stripRepeatReadHint(textContent(page.content));
9282
10525
  const start = pageMeta?.shownStart ?? nextOffset;
9283
10526
  const body = dropLeadingLines(pageText, Math.max(0, covered - start + 1));
9284
- const pageEnd = pageMeta?.shownEnd ?? start + countLines(pageText) - 1;
10527
+ const pageEnd = pageMeta?.shownEnd ?? start + countLines2(pageText) - 1;
9285
10528
  if (body.length === 0 || pageEnd <= covered) {
9286
10529
  nextOffset = void 0;
9287
10530
  break;
@@ -9411,7 +10654,7 @@ var OmpToolsProvider = class _OmpToolsProvider {
9411
10654
  import { spawn } from "node:child_process";
9412
10655
  import { createHash as createHash3, randomBytes, randomUUID as randomUUID4 } from "node:crypto";
9413
10656
  import fs8 from "node:fs";
9414
- import path13 from "node:path";
10657
+ import path15 from "node:path";
9415
10658
 
9416
10659
  // src/schema/types.ts
9417
10660
  var stateBinding = (head) => head ? { transitionId: head.transitionId, version: head.version, to: head.to } : null;
@@ -9420,7 +10663,7 @@ var stateBinding = (head) => head ? { transitionId: head.transitionId, version:
9420
10663
  import { execFileSync } from "node:child_process";
9421
10664
  import { createHash as createHash2 } from "node:crypto";
9422
10665
  import fs7 from "node:fs";
9423
- import path12 from "node:path";
10666
+ import path14 from "node:path";
9424
10667
  var SNAPSHOT_MAX_FILES = 2e4;
9425
10668
  var SNAPSHOT_MAX_BYTES = 512 * 1024 * 1024;
9426
10669
  var FALLBACK_SKIPPED_DIRECTORIES = /* @__PURE__ */ new Set([
@@ -9438,10 +10681,10 @@ var git = (cwd, args) => execFileSync("git", ["-C", cwd, ...args], {
9438
10681
  stdio: ["ignore", "pipe", "ignore"]
9439
10682
  });
9440
10683
  var nulPaths = (buffer) => buffer.toString("utf8").split("\0").filter((item) => item.length > 0);
9441
- var normalizeRelative = (value) => value.split(path12.sep).join("/");
10684
+ var normalizeRelative = (value) => value.split(path14.sep).join("/");
9442
10685
  var isInside = (root, candidate) => {
9443
- const relative = path12.relative(root, candidate);
9444
- return relative === "" || !path12.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path12.sep}`);
10686
+ const relative = path14.relative(root, candidate);
10687
+ return relative === "" || !path14.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path14.sep}`);
9445
10688
  };
9446
10689
  var excluded = (absolute, exclusions) => exclusions.some((root) => isInside(root, absolute));
9447
10690
  var entryDigest = (absolute) => {
@@ -9467,12 +10710,12 @@ var buildSnapshot = (cwd, paths, metadata, exclusions) => {
9467
10710
  let bytes = 0;
9468
10711
  const unique = [...new Set(paths)].sort((left, right) => left.localeCompare(right));
9469
10712
  for (const relativeInput of unique) {
9470
- const absolute = path12.resolve(cwd, relativeInput);
10713
+ const absolute = path14.resolve(cwd, relativeInput);
9471
10714
  if (!isInside(cwd, absolute) || excluded(absolute, exclusions)) continue;
9472
10715
  if (Object.keys(entries).length >= SNAPSHOT_MAX_FILES) {
9473
10716
  throw new Error(`Schema workspace snapshot exceeds ${SNAPSHOT_MAX_FILES} files`);
9474
10717
  }
9475
- const relative = normalizeRelative(path12.relative(cwd, absolute));
10718
+ const relative = normalizeRelative(path14.relative(cwd, absolute));
9476
10719
  const entry = entryDigest(absolute);
9477
10720
  bytes += entry.bytes;
9478
10721
  if (bytes > SNAPSHOT_MAX_BYTES) {
@@ -9501,9 +10744,9 @@ var fallbackPaths = (cwd, exclusions) => {
9501
10744
  const entries = fs7.readdirSync(directory, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
9502
10745
  for (const entry of entries) {
9503
10746
  if (FALLBACK_SKIPPED_DIRECTORIES.has(entry.name)) continue;
9504
- const absolute = path12.join(directory, entry.name);
10747
+ const absolute = path14.join(directory, entry.name);
9505
10748
  if (excluded(absolute, exclusions)) continue;
9506
- const relative = normalizeRelative(path12.relative(cwd, absolute));
10749
+ const relative = normalizeRelative(path14.relative(cwd, absolute));
9507
10750
  if (entry.isDirectory()) visit(absolute);
9508
10751
  else paths.push(relative);
9509
10752
  if (paths.length > SNAPSHOT_MAX_FILES) {
@@ -9517,7 +10760,7 @@ var fallbackPaths = (cwd, exclusions) => {
9517
10760
  var snapshotWorkspace = (cwdInput, excludedRoots = []) => {
9518
10761
  const cwd = fs7.realpathSync(cwdInput);
9519
10762
  const exclusions = excludedRoots.map((root) => {
9520
- const absolute = path12.resolve(root);
10763
+ const absolute = path14.resolve(root);
9521
10764
  try {
9522
10765
  return fs7.realpathSync(absolute);
9523
10766
  } catch {
@@ -9555,18 +10798,18 @@ var snapshotWorkspace = (cwdInput, excludedRoots = []) => {
9555
10798
  );
9556
10799
  };
9557
10800
  var resolveWorkspaceFile = (cwdInput, requestedPath, options) => {
9558
- if (!requestedPath.trim() || path12.isAbsolute(requestedPath)) {
10801
+ if (!requestedPath.trim() || path14.isAbsolute(requestedPath)) {
9559
10802
  throw new Error(`Schema paths must be non-empty project-relative paths: ${requestedPath}`);
9560
10803
  }
9561
10804
  const cwd = fs7.realpathSync(cwdInput);
9562
- const absolute = path12.resolve(cwd, requestedPath);
10805
+ const absolute = path14.resolve(cwd, requestedPath);
9563
10806
  if (!isInside(cwd, absolute) || absolute === cwd) {
9564
10807
  throw new Error(`Schema path escapes the project workspace: ${requestedPath}`);
9565
10808
  }
9566
- const relativeParts = path12.relative(cwd, absolute).split(path12.sep);
10809
+ const relativeParts = path14.relative(cwd, absolute).split(path14.sep);
9567
10810
  let cursor = cwd;
9568
10811
  for (let index = 0; index < relativeParts.length; index++) {
9569
- cursor = path12.join(cursor, relativeParts[index]);
10812
+ cursor = path14.join(cursor, relativeParts[index]);
9570
10813
  let stat2;
9571
10814
  try {
9572
10815
  stat2 = fs7.lstatSync(cursor);
@@ -9575,9 +10818,9 @@ var resolveWorkspaceFile = (cwdInput, requestedPath, options) => {
9575
10818
  if (index !== relativeParts.length - 1 || !options.allowAbsent) {
9576
10819
  throw new Error(`Schema path does not exist: ${requestedPath}`);
9577
10820
  }
9578
- const parentReal = fs7.realpathSync(path12.dirname(cursor));
10821
+ const parentReal = fs7.realpathSync(path14.dirname(cursor));
9579
10822
  if (!isInside(cwd, parentReal)) throw new Error(`Schema path parent escapes the workspace: ${requestedPath}`);
9580
- return { absolute, relative: normalizeRelative(path12.relative(cwd, absolute)), exists: false };
10823
+ return { absolute, relative: normalizeRelative(path14.relative(cwd, absolute)), exists: false };
9581
10824
  }
9582
10825
  throw error;
9583
10826
  }
@@ -9589,7 +10832,7 @@ var resolveWorkspaceFile = (cwdInput, requestedPath, options) => {
9589
10832
  throw new Error(`Schema transaction paths must name regular files: ${requestedPath}`);
9590
10833
  }
9591
10834
  }
9592
- return { absolute, relative: normalizeRelative(path12.relative(cwd, absolute)), exists: true };
10835
+ return { absolute, relative: normalizeRelative(path14.relative(cwd, absolute)), exists: true };
9593
10836
  };
9594
10837
  var sha256File = (absolute) => `sha256:${digest(fs7.readFileSync(absolute))}`;
9595
10838
 
@@ -9640,8 +10883,8 @@ var SchemaController = class {
9640
10883
  this.identity = identity;
9641
10884
  this.state = state;
9642
10885
  this.cwd = fs8.realpathSync(cwd);
9643
- this.#journalRoot = path13.join(mesh.root, "schema-transactions");
9644
- this.#lockPath = path13.join(this.#journalRoot, ".commit.lock");
10886
+ this.#journalRoot = path15.join(mesh.root, "schema-transactions");
10887
+ this.#lockPath = path15.join(this.#journalRoot, ".commit.lock");
9645
10888
  this.#recoverJournals();
9646
10889
  }
9647
10890
  #activeHypotheses = /* @__PURE__ */ new Map();
@@ -9666,12 +10909,12 @@ var SchemaController = class {
9666
10909
  }
9667
10910
  status(parentToolCallId) {
9668
10911
  const workspace = this.#workspaceEntry();
9669
- const hypotheses = this.mesh.list(HYPOTHESIS_PREFIX, this.mesh.maxReadEvents).map((entry) => entry.value).filter((record) => !parentToolCallId || record.parentToolCallId === parentToolCallId).map((record) => ({
9670
- id: record.id,
9671
- label: record.label,
9672
- status: record.status,
9673
- generation: record.generation,
9674
- updatedAt: record.updatedAt
10912
+ const hypotheses = this.mesh.list(HYPOTHESIS_PREFIX, this.mesh.maxReadEvents).map((entry) => entry.value).filter((record2) => !parentToolCallId || record2.parentToolCallId === parentToolCallId).map((record2) => ({
10913
+ id: record2.id,
10914
+ label: record2.label,
10915
+ status: record2.status,
10916
+ generation: record2.generation,
10917
+ updatedAt: record2.updatedAt
9675
10918
  }));
9676
10919
  return {
9677
10920
  mode: this.config.mode,
@@ -9696,7 +10939,7 @@ var SchemaController = class {
9696
10939
  const snapshot = snapshotWorkspace(this.cwd, [this.mesh.root]);
9697
10940
  const generation = this.#generation();
9698
10941
  const now = Date.now();
9699
- const record = {
10942
+ const record2 = {
9700
10943
  id: randomUUID4(),
9701
10944
  label: input.label,
9702
10945
  summary: input.summary,
@@ -9710,66 +10953,66 @@ var SchemaController = class {
9710
10953
  createdAt: now,
9711
10954
  updatedAt: now
9712
10955
  };
9713
- await this.#publish("hypothesized", record);
10956
+ await this.#publish("hypothesized", record2);
9714
10957
  await this.mesh.put({
9715
- key: `${HYPOTHESIS_PREFIX}${record.id}`,
9716
- value: record,
10958
+ key: `${HYPOTHESIS_PREFIX}${record2.id}`,
10959
+ value: record2,
9717
10960
  ifVersion: 0,
9718
10961
  identity: this.identity
9719
10962
  });
9720
- this.#activeHypotheses.set(record.id, context.parentToolCallId);
9721
- context.update(`Schema hypothesis recorded: ${record.label}`);
10963
+ this.#activeHypotheses.set(record2.id, context.parentToolCallId);
10964
+ context.update(`Schema hypothesis recorded: ${record2.label}`);
9722
10965
  return {
9723
- hypothesisId: record.id,
9724
- status: record.status,
9725
- state: record.state,
9726
- fingerprint: record.fingerprint,
10966
+ hypothesisId: record2.id,
10967
+ status: record2.status,
10968
+ state: record2.state,
10969
+ fingerprint: record2.fingerprint,
9727
10970
  generation
9728
10971
  };
9729
10972
  }
9730
10973
  async verify(hypothesisId, context) {
9731
10974
  const entry = this.#requireHypothesis(hypothesisId);
9732
- const record = entry.value;
9733
- this.#assertInvocation(record.parentToolCallId, context.parentToolCallId);
9734
- if (record.status !== "active") throw new Error(`Schema hypothesis is not active: ${record.status}`);
9735
- if (record.evidence.length === 0) return this.#failedVerification(record, [], "missing evidence");
10975
+ const record2 = entry.value;
10976
+ this.#assertInvocation(record2.parentToolCallId, context.parentToolCallId);
10977
+ if (record2.status !== "active") throw new Error(`Schema hypothesis is not active: ${record2.status}`);
10978
+ if (record2.evidence.length === 0) return this.#failedVerification(record2, [], "missing evidence");
9736
10979
  let before;
9737
10980
  try {
9738
10981
  before = snapshotWorkspace(this.cwd, [this.mesh.root]);
9739
10982
  } catch (error) {
9740
- return this.#failedVerification(record, [], `workspace snapshot failed: ${errorMessage4(error)}`);
10983
+ return this.#failedVerification(record2, [], `workspace snapshot failed: ${errorMessage4(error)}`);
9741
10984
  }
9742
10985
  const currentState = stateBinding(this.state?.getHead() ?? null);
9743
- if (!sameBinding(record.state, currentState)) {
9744
- return this.#failedVerification(record, [], "state head changed since hypothesis");
10986
+ if (!sameBinding(record2.state, currentState)) {
10987
+ return this.#failedVerification(record2, [], "state head changed since hypothesis");
9745
10988
  }
9746
- if (record.generation !== this.#generation()) {
9747
- return this.#failedVerification(record, [], "workspace generation changed since hypothesis");
10989
+ if (record2.generation !== this.#generation()) {
10990
+ return this.#failedVerification(record2, [], "workspace generation changed since hypothesis");
9748
10991
  }
9749
- if (record.fingerprint !== before.fingerprint) {
9750
- return this.#failedVerification(record, [], "workspace fingerprint changed since hypothesis");
10992
+ if (record2.fingerprint !== before.fingerprint) {
10993
+ return this.#failedVerification(record2, [], "workspace fingerprint changed since hypothesis");
9751
10994
  }
9752
- const results = await this.#verifyEvidence(record.evidence, context);
10995
+ const results = await this.#verifyEvidence(record2.evidence, context);
9753
10996
  let after;
9754
10997
  try {
9755
10998
  after = snapshotWorkspace(this.cwd, [this.mesh.root]);
9756
10999
  } catch (error) {
9757
- return this.#failedVerification(record, results, `post-evidence snapshot failed: ${errorMessage4(error)}`);
11000
+ return this.#failedVerification(record2, results, `post-evidence snapshot failed: ${errorMessage4(error)}`);
9758
11001
  }
9759
11002
  const allConfirmed = results.length > 0 && results.every((result) => result.status === "confirmed");
9760
11003
  if (!allConfirmed || before.fingerprint !== after.fingerprint) {
9761
11004
  const reason = before.fingerprint !== after.fingerprint ? "workspace fingerprint changed while evidence ran" : "one or more evidence items were not confirmed";
9762
- return this.#failedVerification(record, results, reason);
11005
+ return this.#failedVerification(record2, results, reason);
9763
11006
  }
9764
11007
  const certificate = randomBytes(32).toString("hex");
9765
11008
  const issuedAt = Date.now();
9766
11009
  const certificateRecord = {
9767
11010
  tokenHash: hashToken(certificate),
9768
- hypothesisId: record.id,
11011
+ hypothesisId: record2.id,
9769
11012
  parentToolCallId: context.parentToolCallId,
9770
- state: record.state,
9771
- fingerprint: record.fingerprint,
9772
- generation: record.generation,
11013
+ state: record2.state,
11014
+ fingerprint: record2.fingerprint,
11015
+ generation: record2.generation,
9773
11016
  issuedAt,
9774
11017
  expiresAt: issuedAt + this.config.certificateTtlMs,
9775
11018
  status: "active"
@@ -9784,7 +11027,7 @@ var SchemaController = class {
9784
11027
  try {
9785
11028
  await this.mesh.put({
9786
11029
  key: entry.key,
9787
- value: { ...record, status: "verified", updatedAt: Date.now() },
11030
+ value: { ...record2, status: "verified", updatedAt: Date.now() },
9788
11031
  ifVersion: entry.version,
9789
11032
  identity: this.identity
9790
11033
  });
@@ -9803,16 +11046,16 @@ var SchemaController = class {
9803
11046
  this.#activeCertificates.set(certificateRecord.tokenHash, context.parentToolCallId);
9804
11047
  try {
9805
11048
  await this.#publish("verified", {
9806
- hypothesisId: record.id,
11049
+ hypothesisId: record2.id,
9807
11050
  tokenHash: certificateRecord.tokenHash,
9808
11051
  results: results.map((result) => ({
9809
11052
  kind: result.evidence.kind,
9810
11053
  status: result.status,
9811
11054
  detail: result.detail
9812
11055
  })),
9813
- state: record.state,
9814
- fingerprint: record.fingerprint,
9815
- generation: record.generation,
11056
+ state: record2.state,
11057
+ fingerprint: record2.fingerprint,
11058
+ generation: record2.generation,
9816
11059
  issuedAt,
9817
11060
  expiresAt: certificateRecord.expiresAt
9818
11061
  });
@@ -9821,7 +11064,7 @@ var SchemaController = class {
9821
11064
  context.update(`Schema evidence confirmed; certificate expires in ${this.config.certificateTtlMs}ms`);
9822
11065
  return {
9823
11066
  verified: true,
9824
- hypothesisId: record.id,
11067
+ hypothesisId: record2.id,
9825
11068
  certificate,
9826
11069
  issuedAt,
9827
11070
  expiresAt: certificateRecord.expiresAt,
@@ -9840,7 +11083,7 @@ var SchemaController = class {
9840
11083
  this.#assertPayloadBound(input);
9841
11084
  const release = this.#acquireCommitLock();
9842
11085
  const transactionId = randomUUID4();
9843
- const journalPath = path13.join(this.#journalRoot, `${transactionId}.json`);
11086
+ const journalPath = path15.join(this.#journalRoot, `${transactionId}.json`);
9844
11087
  let journal;
9845
11088
  let consumed = false;
9846
11089
  let committed = false;
@@ -10050,12 +11293,12 @@ var SchemaController = class {
10050
11293
  if (invocation !== parentToolCallId) continue;
10051
11294
  const entry = this.mesh.get(`${CERTIFICATE_PREFIX}${tokenHash}`);
10052
11295
  if (entry) {
10053
- const record = entry.value;
10054
- if (record.status === "active") {
11296
+ const record2 = entry.value;
11297
+ if (record2.status === "active") {
10055
11298
  try {
10056
11299
  await this.mesh.put({
10057
11300
  key: entry.key,
10058
- value: { ...record, status: "abandoned" },
11301
+ value: { ...record2, status: "abandoned" },
10059
11302
  ifVersion: entry.version,
10060
11303
  identity: this.identity
10061
11304
  });
@@ -10069,12 +11312,12 @@ var SchemaController = class {
10069
11312
  if (invocation !== parentToolCallId) continue;
10070
11313
  const entry = this.mesh.get(`${HYPOTHESIS_PREFIX}${hypothesisId}`);
10071
11314
  if (entry) {
10072
- const record = entry.value;
10073
- if (record.status === "active" || record.status === "verified") {
11315
+ const record2 = entry.value;
11316
+ if (record2.status === "active" || record2.status === "verified") {
10074
11317
  try {
10075
11318
  await this.mesh.put({
10076
11319
  key: entry.key,
10077
- value: { ...record, status: "abandoned", updatedAt: Date.now() },
11320
+ value: { ...record2, status: "abandoned", updatedAt: Date.now() },
10078
11321
  ifVersion: entry.version,
10079
11322
  identity: this.identity
10080
11323
  });
@@ -10085,16 +11328,16 @@ var SchemaController = class {
10085
11328
  this.#activeHypotheses.delete(hypothesisId);
10086
11329
  }
10087
11330
  }
10088
- async #failedVerification(record, results, reason) {
11331
+ async #failedVerification(record2, results, reason) {
10089
11332
  try {
10090
11333
  await this.#publish("verification_failed", {
10091
- hypothesisId: record.id,
11334
+ hypothesisId: record2.id,
10092
11335
  reason,
10093
11336
  results: results.map((result) => ({ kind: result.evidence.kind, status: result.status, detail: result.detail }))
10094
11337
  });
10095
11338
  } catch {
10096
11339
  }
10097
- return { verified: false, hypothesisId: record.id, reason, results };
11340
+ return { verified: false, hypothesisId: record2.id, reason, results };
10098
11341
  }
10099
11342
  async #verifyEvidence(evidence, context) {
10100
11343
  if (evidence.length === 0) return [];
@@ -10321,7 +11564,7 @@ ${Date.now()}
10321
11564
  }
10322
11565
  for (const name of fs8.readdirSync(this.#journalRoot)) {
10323
11566
  if (!name.endsWith(".json")) continue;
10324
- const filePath = path13.join(this.#journalRoot, name);
11567
+ const filePath = path15.join(this.#journalRoot, name);
10325
11568
  try {
10326
11569
  const journal = JSON.parse(fs8.readFileSync(filePath, "utf8"));
10327
11570
  if (journal.format !== 1 || journal.status !== "applying" || !Array.isArray(journal.before)) continue;
@@ -10441,7 +11684,7 @@ var operationSchema = {
10441
11684
  }
10442
11685
  ]
10443
11686
  };
10444
- var descriptors4 = [
11687
+ var descriptors5 = [
10445
11688
  {
10446
11689
  name: "status",
10447
11690
  description: "Read the fixed session Schema mode, transaction bounds, generation, and invocation hypotheses",
@@ -10511,7 +11754,7 @@ var descriptors4 = [
10511
11754
  namespace: "schema"
10512
11755
  }
10513
11756
  ];
10514
- var normalizeSchemaArgs = actionArgNormalizer(() => descriptors4);
11757
+ var normalizeSchemaArgs = actionArgNormalizer(() => descriptors5);
10515
11758
  var SchemaProvider = class {
10516
11759
  constructor(controller) {
10517
11760
  this.controller = controller;
@@ -10520,12 +11763,12 @@ var SchemaProvider = class {
10520
11763
  description = "Host-owned, opt-in Schema verification and bounded local-file transaction control plane";
10521
11764
  async list(request, _context) {
10522
11765
  const query = request.query?.toLowerCase();
10523
- return query ? descriptors4.filter(
11766
+ return query ? descriptors5.filter(
10524
11767
  (descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
10525
- ) : descriptors4;
11768
+ ) : descriptors5;
10526
11769
  }
10527
11770
  async describe(actionName, _context) {
10528
- return descriptors4.find((descriptor) => descriptor.name === actionName);
11771
+ return descriptors5.find((descriptor) => descriptor.name === actionName);
10529
11772
  }
10530
11773
  prepareArguments(actionName, args) {
10531
11774
  return normalizeSchemaArgs(actionName, args);
@@ -10575,11 +11818,11 @@ var SchemaProvider = class {
10575
11818
 
10576
11819
  // src/state/store.ts
10577
11820
  import { createHash as createHash5 } from "node:crypto";
10578
- import path15 from "node:path";
11821
+ import path17 from "node:path";
10579
11822
 
10580
11823
  // src/state/complexity.ts
10581
11824
  import fs9 from "node:fs";
10582
- import path14 from "node:path";
11825
+ import path16 from "node:path";
10583
11826
  var isWordStart = (character) => character !== void 0 && (character >= "a" && character <= "z" || character >= "A" && character <= "Z" || character === "_" || character === "$");
10584
11827
  var isWordPart = (character) => isWordStart(character) || character !== void 0 && character >= "0" && character <= "9";
10585
11828
  var regularExpressionPrefixWords = /* @__PURE__ */ new Set([
@@ -10811,7 +12054,7 @@ var languageComplexities = [
10811
12054
  typeScriptJavaScriptComplexity
10812
12055
  ];
10813
12056
  var complexityForFile = (file, languages = languageComplexities) => {
10814
- const extension = path14.extname(file).toLowerCase();
12057
+ const extension = path16.extname(file).toLowerCase();
10815
12058
  return languages.find((language) => language.extensions.includes(extension));
10816
12059
  };
10817
12060
  var countFileComplexity = (file) => {
@@ -11630,10 +12873,10 @@ var StateStore = class {
11630
12873
  const currentHead = this.getHead();
11631
12874
  const records = [];
11632
12875
  for (const event of events) {
11633
- const record = toRecord(event, committedIds);
11634
- if (record) records.push(record);
12876
+ const record2 = toRecord(event, committedIds);
12877
+ if (record2) records.push(record2);
11635
12878
  }
11636
- if (currentHead && !records.some((record) => record.transitionId === currentHead.transitionId)) {
12879
+ if (currentHead && !records.some((record2) => record2.transitionId === currentHead.transitionId)) {
11637
12880
  const currentRecord = toHeadRecord(currentHead);
11638
12881
  if (currentRecord) records.push(currentRecord);
11639
12882
  }
@@ -11646,7 +12889,7 @@ var StateStore = class {
11646
12889
  }
11647
12890
  }
11648
12891
  const visibleRecords = input.includeArchived || lastRepresentation < 0 ? records : records.slice(lastRepresentation);
11649
- const visibleIds = new Set(visibleRecords.map((record) => record.transitionId));
12892
+ const visibleIds = new Set(visibleRecords.map((record2) => record2.transitionId));
11650
12893
  const latestOutcomes = latestTransitionOutcomes(events);
11651
12894
  const eventCertifications = events.map((event) => toCertificate(event, currentHead, latestOutcomes)).filter((certificate) => certificate !== void 0).filter(
11652
12895
  (certificate) => certificate.targets.every((target) => visibleIds.has(target.transitionId))
@@ -11662,32 +12905,32 @@ var StateStore = class {
11662
12905
  certifications.map((certificate) => [certificate.sequence, certificate])
11663
12906
  );
11664
12907
  const latestCertificate = /* @__PURE__ */ new Map();
11665
- for (const record of visibleRecords) {
11666
- const outcome = latestOutcomes.get(record.transitionId);
12908
+ for (const record2 of visibleRecords) {
12909
+ const outcome = latestOutcomes.get(record2.transitionId);
11667
12910
  if (outcome?.phase !== "certified") continue;
11668
12911
  const certificate = certificatesBySequence.get(outcome.event.sequence);
11669
- if (certificate) latestCertificate.set(record.transitionId, certificate);
12912
+ if (certificate) latestCertificate.set(record2.transitionId, certificate);
11670
12913
  }
11671
12914
  if (durableCertificate) {
11672
12915
  latestCertificate.set(currentHead.transitionId, durableCertificate);
11673
12916
  }
11674
12917
  const archiveBoundaryId = input.includeArchived !== true && lastRepresentation > 0 ? records[lastRepresentation]?.transitionId : void 0;
11675
12918
  const filtered = (input.label ? visibleRecords.filter(
11676
- (record) => record.label === input.label || record.to === input.label || record.from === input.label && record.transitionId !== archiveBoundaryId
11677
- ) : visibleRecords).map((record) => {
11678
- const certificate = latestCertificate.get(record.transitionId);
11679
- return certificate ? { ...record, certificationStatus: "certified", certificate } : record;
12919
+ (record2) => record2.label === input.label || record2.to === input.label || record2.from === input.label && record2.transitionId !== archiveBoundaryId
12920
+ ) : visibleRecords).map((record2) => {
12921
+ const certificate = latestCertificate.get(record2.transitionId);
12922
+ return certificate ? { ...record2, certificationStatus: "certified", certificate } : record2;
11680
12923
  });
11681
12924
  const limited = input.limit !== void 0 && input.limit > 0 ? filtered.slice(0, input.limit) : filtered;
11682
12925
  const labelSet = /* @__PURE__ */ new Set();
11683
12926
  const limitedIds = /* @__PURE__ */ new Set();
11684
- for (const record of limited) {
11685
- limitedIds.add(record.transitionId);
11686
- if (record.from && record.transitionId !== archiveBoundaryId) {
11687
- labelSet.add(record.from);
12927
+ for (const record2 of limited) {
12928
+ limitedIds.add(record2.transitionId);
12929
+ if (record2.from && record2.transitionId !== archiveBoundaryId) {
12930
+ labelSet.add(record2.from);
11688
12931
  }
11689
- labelSet.add(record.to);
11690
- labelSet.add(record.label);
12932
+ labelSet.add(record2.to);
12933
+ labelSet.add(record2.label);
11691
12934
  }
11692
12935
  return {
11693
12936
  transitions: limited,
@@ -11702,7 +12945,7 @@ var StateStore = class {
11702
12945
  const files = [];
11703
12946
  let netDelta = 0;
11704
12947
  for (const file of this.normalizeComplexityFiles(requestedFiles, input.cwd)) {
11705
- const measured = countFileComplexity(path15.resolve(input.cwd, file));
12948
+ const measured = countFileComplexity(path17.resolve(input.cwd, file));
11706
12949
  if (!measured) {
11707
12950
  files.push({ file, supported: false });
11708
12951
  continue;
@@ -11729,7 +12972,7 @@ var StateStore = class {
11729
12972
  const updates = [];
11730
12973
  let netDelta = 0;
11731
12974
  for (const file of this.normalizeComplexityFiles(files, cwd)) {
11732
- const measured = countFileComplexity(path15.resolve(cwd, file));
12975
+ const measured = countFileComplexity(path17.resolve(cwd, file));
11733
12976
  if (!measured) {
11734
12977
  deltas.push({ file, supported: false });
11735
12978
  continue;
@@ -11779,11 +13022,11 @@ var StateStore = class {
11779
13022
  const normalized = /* @__PURE__ */ new Set();
11780
13023
  for (const file of files) {
11781
13024
  if (!file.trim()) continue;
11782
- const relative = path15.relative(cwd, path15.resolve(cwd, file));
11783
- if (relative === ".." || relative.startsWith(`..${path15.sep}`) || path15.isAbsolute(relative)) {
13025
+ const relative = path17.relative(cwd, path17.resolve(cwd, file));
13026
+ if (relative === ".." || relative.startsWith(`..${path17.sep}`) || path17.isAbsolute(relative)) {
11784
13027
  throw new Error(`State complexity file must be inside the project cwd: ${file}`);
11785
13028
  }
11786
- normalized.add(relative.split(path15.sep).join("/"));
13029
+ normalized.add(relative.split(path17.sep).join("/"));
11787
13030
  }
11788
13031
  return [...normalized];
11789
13032
  }
@@ -11917,7 +13160,7 @@ var StateStore = class {
11917
13160
  includeArchived: input.includeArchived === true
11918
13161
  });
11919
13162
  const match = transitions.find(
11920
- (record) => record.transitionId === verificationHead.transitionId
13163
+ (record2) => record2.transitionId === verificationHead.transitionId
11921
13164
  );
11922
13165
  targets = match ? [match] : [];
11923
13166
  } else {
@@ -12225,7 +13468,7 @@ var checkGoalSchema = {
12225
13468
  additionalProperties: false
12226
13469
  };
12227
13470
  var emptySchema3 = { type: "object", properties: {}, additionalProperties: false };
12228
- var descriptors5 = [
13471
+ var descriptors6 = [
12229
13472
  {
12230
13473
  name: "transition",
12231
13474
  description: "Append a labeled, validated state transition and compare-and-swap advance the head",
@@ -12276,7 +13519,7 @@ var descriptors5 = [
12276
13519
  namespace: "state"
12277
13520
  }
12278
13521
  ];
12279
- var normalizeStateArgs = actionArgNormalizer(() => descriptors5);
13522
+ var normalizeStateArgs = actionArgNormalizer(() => descriptors6);
12280
13523
  var StateProvider = class {
12281
13524
  name = "state";
12282
13525
  description = "Schema-style labeled transition layer: an append-only timeline of validated transitions with a compare-and-swap head and evidence-based certification over mesh storage";
@@ -12291,12 +13534,12 @@ var StateProvider = class {
12291
13534
  }
12292
13535
  async list(request, _context) {
12293
13536
  const query = request.query?.toLowerCase();
12294
- return query ? descriptors5.filter(
13537
+ return query ? descriptors6.filter(
12295
13538
  (descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
12296
- ) : descriptors5;
13539
+ ) : descriptors6;
12297
13540
  }
12298
13541
  async describe(actionName, _context) {
12299
- return descriptors5.find((descriptor) => descriptor.name === actionName);
13542
+ return descriptors6.find((descriptor) => descriptor.name === actionName);
12300
13543
  }
12301
13544
  prepareArguments(actionName, args) {
12302
13545
  return normalizeStateArgs(actionName, args);
@@ -12777,7 +14020,7 @@ var FabricRuntimeState = class {
12777
14020
  this.#mainAgent = mainAgent;
12778
14021
  const projectRoot = process.env.OMP_FABRIC_PROJECT_ROOT ?? context.cwd;
12779
14022
  const configuredMeshRoot = this.#config.mesh.root;
12780
- const meshRoot = process.env.OMP_FABRIC_MESH_ROOT ?? (configuredMeshRoot ? path16.resolve(projectRoot, configuredMeshRoot) : path16.join(projectRoot, ".omp", "fabric", "mesh"));
14023
+ const meshRoot = process.env.OMP_FABRIC_MESH_ROOT ?? (configuredMeshRoot ? path18.resolve(projectRoot, configuredMeshRoot) : path18.join(projectRoot, ".omp", "fabric", "mesh"));
12781
14024
  this.#mesh = new MeshStore(
12782
14025
  meshRoot,
12783
14026
  this.#config.mesh.maxEventBytes,
@@ -12842,6 +14085,19 @@ var FabricRuntimeState = class {
12842
14085
  description: "Host context compaction controller",
12843
14086
  create: () => new CompactProvider(this.#compact)
12844
14087
  }));
14088
+ if (this.#config.codemap.enabled) {
14089
+ const codemapConfig = this.#config.codemap;
14090
+ await installBuiltin(createProviderComponent({
14091
+ provider: "codemap",
14092
+ description: "Structural repo map and git co-change ranking",
14093
+ create: () => new CodemapProvider(codemapConfig)
14094
+ }));
14095
+ } else {
14096
+ this.#registry.markUnavailable(
14097
+ "codemap",
14098
+ 'disabled by configuration (codemap.enabled=false); set "codemap": { "enabled": true } in .omp/fabric.json or the agent fabric.json to enable codemap.* actions'
14099
+ );
14100
+ }
12845
14101
  const agentConfig = enforceSchema ? { ...this.#config.agents, enabled: false } : this.#config.agents;
12846
14102
  const modelsConfig = this.#config.models;
12847
14103
  const visibleOmpModels = () => {
@@ -12938,8 +14194,8 @@ var FabricRuntimeState = class {
12938
14194
  };
12939
14195
  const lineageAlive = (rootId) => this.#participants?.get(rootId) !== void 0;
12940
14196
  const actorRoots = {
12941
- project: path16.join(meshRoot, "actors"),
12942
- session: path16.join(meshRoot, "actors", fabricSessionId)
14197
+ project: path18.join(meshRoot, "actors"),
14198
+ session: path18.join(meshRoot, "actors", fabricSessionId)
12943
14199
  };
12944
14200
  const acquireActorCapabilityView = (requirements, signal) => this.#registry.acquireCapabilityView(requirements, {
12945
14201
  cwd: context.cwd,
@@ -13139,6 +14395,7 @@ ${escapeXmlText(text)}
13139
14395
  ...this.#config.mesh.enabled ? ["mesh", "state"] : [],
13140
14396
  "schema",
13141
14397
  "compact",
14398
+ ...this.#config.codemap.enabled ? ["codemap"] : [],
13142
14399
  "agents",
13143
14400
  ...this.#config.memory.enabled ? ["memory"] : []
13144
14401
  ]);
@@ -13279,7 +14536,11 @@ ${escapeXmlText(text)}
13279
14536
  pending,
13280
14537
  outerToolResult,
13281
14538
  context,
13282
- (update) => this.activity.updateCall(runId, callId, update)
14539
+ (update) => this.activity.updateCall(runId, callId, update),
14540
+ {
14541
+ handoffRetirement: this.#config?.prewalk.handoffRetirement ?? DEFAULT_FABRIC_CONFIG.prewalk.handoffRetirement,
14542
+ handoffRetirementKeep: this.#config?.prewalk.handoffRetirementKeep ?? DEFAULT_FABRIC_CONFIG.prewalk.handoffRetirementKeep
14543
+ }
13283
14544
  );
13284
14545
  const succeeded = result.completed === true || result.continued === true;
13285
14546
  const error = typeof result.error === "string" ? result.error : void 0;