omp-fabric 1.2.0 → 1.3.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 (59) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/actors/global-registry.d.ts.map +1 -1
  3. package/dist/actors/manager.d.ts.map +1 -1
  4. package/dist/actors/types.d.ts +1 -0
  5. package/dist/actors/types.d.ts.map +1 -1
  6. package/dist/agents/manager.d.ts.map +1 -1
  7. package/dist/agents/types.d.ts +1 -0
  8. package/dist/agents/types.d.ts.map +1 -1
  9. package/dist/chunks/{chunk-3TWC6XOS.js → chunk-2WDZT27Q.js} +36 -13
  10. package/dist/chunks/chunk-2WDZT27Q.js.map +7 -0
  11. package/dist/chunks/{chunk-UOSJZXJV.js → chunk-3LI7YO4M.js} +1 -1
  12. package/dist/chunks/chunk-3LI7YO4M.js.map +7 -0
  13. package/dist/chunks/{chunk-TQL7FKMG.js → chunk-7MFYALJI.js} +14 -14
  14. package/dist/chunks/chunk-7MFYALJI.js.map +7 -0
  15. package/dist/chunks/{chunk-B2SQR2JY.js → chunk-BMIE4PIL.js} +2 -2
  16. package/dist/chunks/{chunk-NX4SNIMR.js → chunk-FX3XLQYI.js} +36 -7
  17. package/dist/chunks/chunk-FX3XLQYI.js.map +7 -0
  18. package/dist/chunks/{chunk-EQNNENN6.js → chunk-GDZDWKJS.js} +2 -2
  19. package/dist/chunks/{chunk-2GQC324T.js → chunk-TSU4AEPZ.js} +2 -2
  20. package/dist/chunks/{chunk-5YGOVBOZ.js → chunk-VSSC4IDU.js} +2 -2
  21. package/dist/chunks/{chunk-HDJBUXDX.js → chunk-WQUMHDOS.js} +2 -2
  22. package/dist/chunks/{chunk-WGFHMECI.js → chunk-Z5AP4M6K.js} +24 -6
  23. package/dist/chunks/chunk-Z5AP4M6K.js.map +7 -0
  24. package/dist/entropy/index.js +2 -2
  25. package/dist/fabric-runtime-state.js +275 -108
  26. package/dist/fabric-runtime-state.js.map +3 -3
  27. package/dist/index.js +7 -7
  28. package/dist/memory/discovery.d.ts +10 -0
  29. package/dist/memory/discovery.d.ts.map +1 -1
  30. package/dist/memory/discovery.js +3 -1
  31. package/dist/providers/agents-actions.d.ts.map +1 -1
  32. package/dist/providers/agents-provider.d.ts.map +1 -1
  33. package/dist/providers/codemap-provider.d.ts.map +1 -1
  34. package/dist/providers/mcp-provider.d.ts.map +1 -1
  35. package/dist/providers/memory-provider.d.ts.map +1 -1
  36. package/dist/providers/memory-provider.js +2 -2
  37. package/dist/providers/mesh-provider.d.ts.map +1 -1
  38. package/dist/providers/omp-tools-provider.d.ts.map +1 -1
  39. package/dist/providers/write-preview.d.ts.map +1 -1
  40. package/dist/residency/host.js +3 -3
  41. package/dist/residency/omp-entry.js +3 -3
  42. package/dist/runtime/core-override-guest-types.js +1 -1
  43. package/dist/runtime/guest-types.d.ts +1 -1
  44. package/dist/runtime/guest-types.d.ts.map +1 -1
  45. package/dist/runtime/guest-types.js +1 -1
  46. package/dist/ui/dashboard.js +3 -3
  47. package/docs/codemap.md +6 -0
  48. package/docs/configuration.md +1 -1
  49. package/package.json +1 -1
  50. package/dist/chunks/chunk-3TWC6XOS.js.map +0 -7
  51. package/dist/chunks/chunk-NX4SNIMR.js.map +0 -7
  52. package/dist/chunks/chunk-TQL7FKMG.js.map +0 -7
  53. package/dist/chunks/chunk-UOSJZXJV.js.map +0 -7
  54. package/dist/chunks/chunk-WGFHMECI.js.map +0 -7
  55. /package/dist/chunks/{chunk-B2SQR2JY.js.map → chunk-BMIE4PIL.js.map} +0 -0
  56. /package/dist/chunks/{chunk-EQNNENN6.js.map → chunk-GDZDWKJS.js.map} +0 -0
  57. /package/dist/chunks/{chunk-2GQC324T.js.map → chunk-TSU4AEPZ.js.map} +0 -0
  58. /package/dist/chunks/{chunk-5YGOVBOZ.js.map → chunk-VSSC4IDU.js.map} +0 -0
  59. /package/dist/chunks/{chunk-HDJBUXDX.js.map → chunk-WQUMHDOS.js.map} +0 -0
@@ -11,7 +11,7 @@ import {
11
11
  MemoryProvider,
12
12
  actionArgNormalizer,
13
13
  uniqueDeclaredKeyForSpelling
14
- } from "./chunks/chunk-3TWC6XOS.js";
14
+ } from "./chunks/chunk-2WDZT27Q.js";
15
15
  import "./chunks/chunk-2KEWFW56.js";
16
16
  import "./chunks/chunk-U5FYOMG5.js";
17
17
  import {
@@ -33,7 +33,7 @@ import {
33
33
  repairFabricGuestCode,
34
34
  resolveFabricIdentity,
35
35
  runFabricHandoffAtBoundary
36
- } from "./chunks/chunk-5YGOVBOZ.js";
36
+ } from "./chunks/chunk-VSSC4IDU.js";
37
37
  import "./chunks/chunk-7VIQNUPS.js";
38
38
  import {
39
39
  AgentTranscriptReader,
@@ -41,7 +41,7 @@ import {
41
41
  countContentLines,
42
42
  recentTranscriptTools,
43
43
  writeContentForPreview
44
- } from "./chunks/chunk-HDJBUXDX.js";
44
+ } from "./chunks/chunk-WQUMHDOS.js";
45
45
  import "./chunks/chunk-DLXPTBPL.js";
46
46
  import {
47
47
  ActionRegistry,
@@ -63,7 +63,7 @@ import {
63
63
  withExclusiveFileLockAsync
64
64
  } from "./chunks/chunk-YWEXP724.js";
65
65
  import "./chunks/chunk-4A4MVZQW.js";
66
- import "./chunks/chunk-NX4SNIMR.js";
66
+ import "./chunks/chunk-FX3XLQYI.js";
67
67
  import "./chunks/chunk-6QBPSZJ5.js";
68
68
  import {
69
69
  FABRIC_COMPONENT_DISCOVER_EVENT,
@@ -94,7 +94,7 @@ import {
94
94
  resolveAgentCwd,
95
95
  resolveOmpBinary,
96
96
  validateAgentCwdRequest
97
- } from "./chunks/chunk-TQL7FKMG.js";
97
+ } from "./chunks/chunk-7MFYALJI.js";
98
98
  import "./chunks/chunk-VPPIJRNZ.js";
99
99
  import {
100
100
  executeFile,
@@ -119,7 +119,7 @@ import {
119
119
  FABRIC_ACTOR_HOST_EVENTS,
120
120
  isFabricActorHostEvent,
121
121
  readJsonlPage
122
- } from "./chunks/chunk-UOSJZXJV.js";
122
+ } from "./chunks/chunk-3LI7YO4M.js";
123
123
  import {
124
124
  isFabricThinking
125
125
  } from "./chunks/chunk-JSBTB3P6.js";
@@ -172,7 +172,7 @@ import {
172
172
  } from "./chunks/chunk-6N4XGAZY.js";
173
173
 
174
174
  // src/fabric-runtime-state.ts
175
- import path18 from "node:path";
175
+ import path19 from "node:path";
176
176
  import { fileURLToPath as fileURLToPath2 } from "node:url";
177
177
 
178
178
  // src/actors/global-registry.ts
@@ -294,6 +294,7 @@ var GlobalActorRegistry = class {
294
294
  ...patch.thinking !== void 0 ? { thinking: patch.thinking } : existing.thinking ? { thinking: existing.thinking } : {},
295
295
  ...patch.tools !== void 0 ? { tools: patch.tools } : existing.tools ? { tools: existing.tools } : {},
296
296
  ...patch.transport !== void 0 ? { transport: patch.transport } : existing.transport ? { transport: existing.transport } : {},
297
+ ...patch.cwd !== void 0 ? { cwd: patch.cwd } : existing.cwd ? { cwd: existing.cwd } : {},
297
298
  ...patch.timeoutMs !== void 0 ? { timeoutMs: patch.timeoutMs } : existing.timeoutMs ? { timeoutMs: existing.timeoutMs } : {},
298
299
  ...patch.extensions !== void 0 ? { extensions: patch.extensions } : typeof existing.extensions === "boolean" ? { extensions: existing.extensions } : {},
299
300
  ...patch.validWhile !== void 0 ? { validWhile: patch.validWhile } : existing.validWhile ? { validWhile: existing.validWhile } : {}
@@ -347,6 +348,7 @@ var GlobalActorRegistry = class {
347
348
  ...def.thinking ? { thinking: def.thinking } : {},
348
349
  ...def.tools ? { tools: [...def.tools] } : {},
349
350
  ...def.transport ? { transport: def.transport } : {},
351
+ ...def.cwd ? { cwd: def.cwd } : {},
350
352
  ...def.timeoutMs ? { timeoutMs: def.timeoutMs } : {},
351
353
  ...typeof def.extensions === "boolean" ? { extensions: def.extensions } : {},
352
354
  ...def.validWhile ? { validWhile: clone(def.validWhile) } : {}
@@ -387,6 +389,7 @@ var GlobalActorRegistry = class {
387
389
  const thinking = def.thinking !== void 0 && isFabricThinking(def.thinking) ? def.thinking : void 0;
388
390
  const tools = Array.isArray(def.tools) ? [...new Set(def.tools.filter((tool) => typeof tool === "string"))] : void 0;
389
391
  const transport = def.transport !== void 0 && TRANSPORTS.has(def.transport) ? def.transport : void 0;
392
+ const cwd = typeof def.cwd === "string" && def.cwd.trim().length > 0 ? def.cwd : void 0;
390
393
  const timeoutMs = typeof def.timeoutMs === "number" ? def.timeoutMs : void 0;
391
394
  const extensions = typeof def.extensions === "boolean" ? def.extensions : void 0;
392
395
  const requires = normalizeRequirements(def.requires);
@@ -407,6 +410,7 @@ var GlobalActorRegistry = class {
407
410
  ...thinking ? { thinking } : {},
408
411
  ...tools ? { tools } : {},
409
412
  ...transport ? { transport } : {},
413
+ ...cwd ? { cwd } : {},
410
414
  ...timeoutMs ? { timeoutMs } : {},
411
415
  ...extensions !== void 0 ? { extensions } : {},
412
416
  ...requires && requires.length > 0 ? { requires } : {},
@@ -443,6 +447,7 @@ var GlobalActorRegistry = class {
443
447
  const thinking = isFabricThinking(record2.thinking) ? record2.thinking : void 0;
444
448
  const tools = Array.isArray(record2.tools) ? record2.tools.filter((tool) => typeof tool === "string") : void 0;
445
449
  const transport = record2.transport !== void 0 && TRANSPORTS.has(record2.transport) ? record2.transport : void 0;
450
+ const cwd = typeof record2.cwd === "string" && record2.cwd.trim().length > 0 ? record2.cwd : void 0;
446
451
  const timeoutMs = typeof record2.timeoutMs === "number" ? record2.timeoutMs : void 0;
447
452
  const extensions = typeof record2.extensions === "boolean" ? record2.extensions : void 0;
448
453
  let requires;
@@ -470,6 +475,7 @@ var GlobalActorRegistry = class {
470
475
  ...thinking ? { thinking } : {},
471
476
  ...tools ? { tools } : {},
472
477
  ...transport ? { transport } : {},
478
+ ...cwd ? { cwd } : {},
473
479
  ...timeoutMs ? { timeoutMs } : {},
474
480
  ...extensions !== void 0 ? { extensions } : {},
475
481
  ...requires && requires.length > 0 ? { requires } : {},
@@ -2219,10 +2225,10 @@ var FabricComponentSupervisor = class {
2219
2225
  adjacent.set(edge.from, targets);
2220
2226
  }
2221
2227
  const cycles = /* @__PURE__ */ new Map();
2222
- const visit = (node, path19, positions) => {
2228
+ const visit = (node, path20, positions) => {
2223
2229
  const position = positions.get(node);
2224
2230
  if (position !== void 0) {
2225
- const cycle = path19.slice(position);
2231
+ const cycle = path20.slice(position);
2226
2232
  const rotations = cycle.map((_, index) => [
2227
2233
  ...cycle.slice(index),
2228
2234
  ...cycle.slice(0, index)
@@ -2232,10 +2238,10 @@ var FabricComponentSupervisor = class {
2232
2238
  cycles.set(canonical.join("\0"), canonical);
2233
2239
  return;
2234
2240
  }
2235
- if (path19.length > this.#components.size) return;
2236
- const nextPositions = new Map(positions).set(node, path19.length);
2241
+ if (path20.length > this.#components.size) return;
2242
+ const nextPositions = new Map(positions).set(node, path20.length);
2237
2243
  for (const target of adjacent.get(node) ?? []) {
2238
- visit(target, [...path19, node], nextPositions);
2244
+ visit(target, [...path20, node], nextPositions);
2239
2245
  }
2240
2246
  };
2241
2247
  for (const id of this.#components.keys()) visit(id, [], /* @__PURE__ */ new Map());
@@ -4198,9 +4204,28 @@ var runProperties = {
4198
4204
  enum: ["off", "minimal", "low", "medium", "high", "xhigh", "max"]
4199
4205
  },
4200
4206
  tools: { type: "array", items: { type: "string" } },
4207
+ addTools: {
4208
+ type: "array",
4209
+ items: { type: "string" },
4210
+ description: "Extra tools merged onto the resolved tool list instead of replacing it; use with or without tools."
4211
+ },
4212
+ images: {
4213
+ type: "array",
4214
+ description: "Image blocks delivered with the task on the child agent's first turn.",
4215
+ items: {
4216
+ type: "object",
4217
+ properties: {
4218
+ type: { const: "image" },
4219
+ data: { type: "string", description: "Base64-encoded image bytes." },
4220
+ mimeType: { type: "string" }
4221
+ },
4222
+ required: ["type", "data", "mimeType"],
4223
+ additionalProperties: false
4224
+ }
4225
+ },
4201
4226
  timeoutMs: {
4202
4227
  type: "number",
4203
- description: "Optional longer wall-clock limit in milliseconds. Omit to use agents.timeoutMs (60 minutes by default); values below the configured default are ignored."
4228
+ description: "Optional wall-clock limit in milliseconds, raising or lowering agents.timeoutMs (60 minutes by default). Clamped to the supported range of 1 second to 24 hours."
4204
4229
  },
4205
4230
  extensions: { type: "boolean" },
4206
4231
  recursive: { type: "boolean" },
@@ -4493,6 +4518,10 @@ var AGENTS_ACTION_DESCRIPTORS = [
4493
4518
  thinking: runProperties.thinking,
4494
4519
  tools: runProperties.tools,
4495
4520
  transport: runProperties.transport,
4521
+ cwd: {
4522
+ ...runProperties.cwd,
4523
+ description: "Filesystem execution directory for every activation; relative paths resolve from the host cwd. An OMP actor must also pass extensions: false, because recursive Fabric activations do not support cwd."
4524
+ },
4496
4525
  timeoutMs: runProperties.timeoutMs,
4497
4526
  extensions: runProperties.extensions,
4498
4527
  requires: {
@@ -5287,27 +5316,37 @@ var actorRunBinding = (args) => ({
5287
5316
  ...typeof args.model === "string" && args.model.trim() ? { model: args.model.trim() } : {},
5288
5317
  ...isFabricThinking(args.thinking) ? { thinking: args.thinking } : {}
5289
5318
  });
5290
- var longerTimeoutOverride = (value, manager) => {
5319
+ var imageContents = (value) => {
5320
+ if (!Array.isArray(value)) return void 0;
5321
+ const images = value.filter(
5322
+ (entry) => typeof entry === "object" && entry !== null && !Array.isArray(entry) && entry.type === "image" && typeof entry.data === "string" && typeof entry.mimeType === "string"
5323
+ );
5324
+ return images.length > 0 ? images : void 0;
5325
+ };
5326
+ var boundedTimeoutOverride = (value, manager) => {
5291
5327
  if (typeof value !== "number" || !Number.isFinite(value)) return void 0;
5292
- const effective = effectiveAgentTimeoutMs(manager.config.timeoutMs, value);
5293
- return effective > manager.config.timeoutMs ? effective : void 0;
5328
+ return effectiveAgentTimeoutMs(manager.config.timeoutMs, value);
5294
5329
  };
5295
5330
  var runRequest = (args, context, manager, options = {}) => {
5296
5331
  const transport = args.transport === "auto" || args.transport === "process" || args.transport === "tmux" || args.transport === "screen" || args.transport === "localterm" || args.transport === "herdr" ? args.transport : void 0;
5297
5332
  const thinking = isFabricThinking(args.thinking) ? args.thinking : void 0;
5298
5333
  const tools = stringArray(args.tools);
5299
- const timeoutMs = longerTimeoutOverride(args.timeoutMs, manager);
5334
+ const addTools = stringArray(args.addTools);
5335
+ const images = imageContents(args.images);
5336
+ const timeoutMs = boundedTimeoutOverride(args.timeoutMs, manager);
5300
5337
  const runner = args.runner === "omp" || args.runner === "claude" || args.runner === "veda" ? args.runner : manager.config.runner;
5301
5338
  const inheritedModel = runner === "omp" && !manager.config.model && context.extensionContext.model ? `${context.extensionContext.model.provider}/${context.extensionContext.model.id}` : void 0;
5302
5339
  return {
5303
5340
  task: String(args.task),
5304
5341
  runner,
5342
+ ...images ? { images } : {},
5305
5343
  ...typeof args.name === "string" ? { name: args.name } : {},
5306
5344
  ...transport ? { transport } : {},
5307
5345
  ...typeof args.model === "string" ? { model: args.model } : inheritedModel ? { model: inheritedModel } : {},
5308
5346
  ...typeof args.persona === "string" && args.persona.trim() ? { persona: args.persona.trim() } : {},
5309
5347
  ...thinking ? { thinking } : {},
5310
5348
  ...tools ? { tools } : {},
5349
+ ...addTools ? { addTools } : {},
5311
5350
  ...timeoutMs !== void 0 ? { timeoutMs } : {},
5312
5351
  ...typeof args.extensions === "boolean" ? { extensions: args.extensions } : {},
5313
5352
  ...typeof args.recursive === "boolean" ? { recursive: args.recursive } : {},
@@ -5365,7 +5404,7 @@ var actorRequest = (args, context, manager, inheritModel = true) => {
5365
5404
  },
5366
5405
  []
5367
5406
  ) : void 0;
5368
- const timeoutMs = longerTimeoutOverride(args.timeoutMs, manager);
5407
+ const timeoutMs = boundedTimeoutOverride(args.timeoutMs, manager);
5369
5408
  const validWhile = typeof args.validWhile === "object" && args.validWhile !== null && !Array.isArray(args.validWhile) && args.validWhile.version === 1 && typeof args.validWhile.source === "string" ? { version: 1, source: args.validWhile.source } : void 0;
5370
5409
  const runner = args.runner === "omp" || args.runner === "claude" || args.runner === "veda" ? args.runner : manager.config.runner;
5371
5410
  if (runner === "veda") {
@@ -5373,6 +5412,12 @@ var actorRequest = (args, context, manager, inheritModel = true) => {
5373
5412
  'The Veda runner does not support persistent actors: Veda executes one headless prompt per invocation. Use an OMP or Claude actor, or agents.run({ runner: "veda" }).'
5374
5413
  );
5375
5414
  }
5415
+ const requestedCwd = typeof args.cwd === "string" ? args.cwd : void 0;
5416
+ validateAgentCwdRequest({
5417
+ ...requestedCwd === void 0 ? {} : { cwd: requestedCwd },
5418
+ recursive: (typeof args.extensions === "boolean" ? args.extensions : true) && runner === "omp"
5419
+ });
5420
+ const cwd = requestedCwd === void 0 ? void 0 : manager.resolveCwd(requestedCwd);
5376
5421
  const inheritedModel = inheritModel && runner === "omp" && !manager.config.model && context.extensionContext.model ? `${context.extensionContext.model.provider}/${context.extensionContext.model.id}` : void 0;
5377
5422
  return {
5378
5423
  ...args.scope === "session" || args.scope === "project" ? { scope: args.scope } : {},
@@ -5390,6 +5435,7 @@ var actorRequest = (args, context, manager, inheritModel = true) => {
5390
5435
  ...isFabricThinking(args.thinking) ? { thinking: args.thinking } : {},
5391
5436
  ...tools ? { tools } : {},
5392
5437
  ...args.transport === "auto" || args.transport === "process" || args.transport === "tmux" || args.transport === "screen" || args.transport === "localterm" || args.transport === "herdr" ? { transport: args.transport } : {},
5438
+ ...cwd ? { cwd } : {},
5393
5439
  ...timeoutMs !== void 0 ? { timeoutMs } : {},
5394
5440
  ...typeof args.extensions === "boolean" ? { extensions: args.extensions } : {},
5395
5441
  ...requires ? { requires } : {},
@@ -6764,6 +6810,8 @@ var CapturedToolsProvider = class {
6764
6810
  };
6765
6811
 
6766
6812
  // src/providers/codemap-provider.ts
6813
+ import { statSync as statSync2 } from "node:fs";
6814
+ import path9 from "node:path";
6767
6815
  import { Type } from "@oh-my-pi/pi-coding-agent/extensibility/legacy-typebox";
6768
6816
  import { validateJsonSchemaValue } from "@oh-my-pi/pi-ai/utils/schema";
6769
6817
 
@@ -7861,7 +7909,12 @@ async function buildSymbolIndex(request) {
7861
7909
 
7862
7910
  // src/providers/codemap-provider.ts
7863
7911
  var INDEX_TTL_MS = 3e4;
7912
+ var pathField = Type.Optional(Type.String({
7913
+ maxLength: 4096,
7914
+ description: "Directory to index. Relative paths resolve against the session directory; defaults to it. Point this at a project root when the session runs elsewhere."
7915
+ }));
7864
7916
  var mapSchema = Type.Object({
7917
+ path: pathField,
7865
7918
  maxTokens: Type.Optional(Type.Number({
7866
7919
  minimum: 200,
7867
7920
  maximum: 2e5,
@@ -7884,6 +7937,7 @@ var mapSchema = Type.Object({
7884
7937
  }))
7885
7938
  }, { additionalProperties: false });
7886
7939
  var cascadeSchema = Type.Object({
7940
+ path: pathField,
7887
7941
  seeds: Type.Array(Type.String({ maxLength: 1024 }), {
7888
7942
  minItems: 1,
7889
7943
  maxItems: 32,
@@ -7900,6 +7954,24 @@ var checked = (action, schema, args) => {
7900
7954
  }
7901
7955
  return args;
7902
7956
  };
7957
+ var resolveRoot = (requested, cwd) => {
7958
+ if (requested === void 0) return cwd;
7959
+ const trimmed = requested.trim();
7960
+ if (trimmed.length === 0) {
7961
+ throw new Error("Invalid codemap path: expected a non-empty directory");
7962
+ }
7963
+ const resolved = path9.isAbsolute(trimmed) ? trimmed : path9.resolve(cwd, trimmed);
7964
+ let stats;
7965
+ try {
7966
+ stats = statSync2(resolved);
7967
+ } catch {
7968
+ throw new Error(`Invalid codemap path: ${resolved} does not exist`);
7969
+ }
7970
+ if (!stats.isDirectory()) {
7971
+ throw new Error(`Invalid codemap path: ${resolved} is not a directory`);
7972
+ }
7973
+ return resolved;
7974
+ };
7903
7975
  var descriptors = [
7904
7976
  {
7905
7977
  name: "map",
@@ -7952,11 +8024,12 @@ var CodemapProvider = class {
7952
8024
  switch (actionName) {
7953
8025
  case "map": {
7954
8026
  const input = checked("map", mapSchema, args);
7955
- const index = await this.#index(context.cwd, input.glob, input.refresh === true, context.signal);
8027
+ const target = resolveRoot(input.path, context.cwd);
8028
+ const index = await this.#index(target, input.glob, input.refresh === true, context.signal);
7956
8029
  let cascade;
7957
8030
  if (input.seeds && input.seeds.length > 0) {
7958
8031
  cascade = await coChange({
7959
- root: context.cwd,
8032
+ root: target,
7960
8033
  seeds: input.seeds,
7961
8034
  maxCommits: this.config.cascadeCommits,
7962
8035
  limit: this.config.cascadeLimit
@@ -7974,6 +8047,7 @@ var CodemapProvider = class {
7974
8047
  });
7975
8048
  return {
7976
8049
  ...budgeted,
8050
+ root: index.root,
7977
8051
  indexed: {
7978
8052
  files: index.files.length,
7979
8053
  symbols: index.symbols.length,
@@ -7988,7 +8062,7 @@ var CodemapProvider = class {
7988
8062
  case "cascade": {
7989
8063
  const input = checked("cascade", cascadeSchema, args);
7990
8064
  const graph = await coChange({
7991
- root: context.cwd,
8065
+ root: resolveRoot(input.path, context.cwd),
7992
8066
  seeds: input.seeds,
7993
8067
  maxCommits: input.maxCommits ?? this.config.cascadeCommits,
7994
8068
  limit: input.limit ?? this.config.cascadeLimit
@@ -8219,7 +8293,7 @@ var ComponentsProvider = class {
8219
8293
  import fs5 from "node:fs/promises";
8220
8294
  import fsSync from "node:fs";
8221
8295
  import os from "node:os";
8222
- import path9 from "node:path";
8296
+ import path10 from "node:path";
8223
8297
  var MCP_DESCRIPTOR_CACHE_VERSION = 1;
8224
8298
  var homeDir = () => {
8225
8299
  const home = process.env.HOME;
@@ -8230,25 +8304,25 @@ var expandHome = (input) => {
8230
8304
  const home = homeDir();
8231
8305
  if (input === "~") return home;
8232
8306
  if (input.startsWith("~/") || input.startsWith("~\\")) {
8233
- return path9.join(home, input.slice(2));
8307
+ return path10.join(home, input.slice(2));
8234
8308
  }
8235
8309
  return input;
8236
8310
  };
8237
- var legacyMcporterDir = () => path9.join(homeDir(), ".mcporter");
8311
+ var legacyMcporterDir = () => path10.join(homeDir(), ".mcporter");
8238
8312
  var mcporterConfigDir = () => {
8239
8313
  const raw = process.env.XDG_CONFIG_HOME;
8240
8314
  if (raw && raw.trim().length > 0) {
8241
8315
  const resolved = expandHome(raw.trim());
8242
- if (path9.isAbsolute(resolved)) return path9.join(resolved, "mcporter");
8316
+ if (path10.isAbsolute(resolved)) return path10.join(resolved, "mcporter");
8243
8317
  }
8244
8318
  return legacyMcporterDir();
8245
8319
  };
8246
8320
  var mcporterConfigCandidates = () => {
8247
8321
  const base = mcporterConfigDir();
8248
- const candidates = [path9.join(base, "mcporter.json"), path9.join(base, "mcporter.jsonc")];
8322
+ const candidates = [path10.join(base, "mcporter.json"), path10.join(base, "mcporter.jsonc")];
8249
8323
  const legacy = legacyMcporterDir();
8250
8324
  if (base !== legacy) {
8251
- candidates.push(path9.join(legacy, "mcporter.json"), path9.join(legacy, "mcporter.jsonc"));
8325
+ candidates.push(path10.join(legacy, "mcporter.json"), path10.join(legacy, "mcporter.jsonc"));
8252
8326
  }
8253
8327
  return candidates;
8254
8328
  };
@@ -8263,12 +8337,12 @@ var pathExists = (filePath) => {
8263
8337
  var mcpConfigLayerPaths = (rootDir, configPath) => {
8264
8338
  const explicitRaw = configPath ?? process.env.MCPORTER_CONFIG;
8265
8339
  if (explicitRaw && explicitRaw.trim().length > 0) {
8266
- return [path9.resolve(expandHome(explicitRaw.trim()))];
8340
+ return [path10.resolve(expandHome(explicitRaw.trim()))];
8267
8341
  }
8268
8342
  const paths = [];
8269
8343
  const home = mcporterConfigCandidates().find(pathExists);
8270
8344
  if (home) paths.push(home);
8271
- const projectPath = path9.resolve(rootDir, "config", "mcporter.json");
8345
+ const projectPath = path10.resolve(rootDir, "config", "mcporter.json");
8272
8346
  if (pathExists(projectPath)) paths.push(projectPath);
8273
8347
  return paths;
8274
8348
  };
@@ -8319,8 +8393,8 @@ var parseCacheFile = (value) => {
8319
8393
  servers: value.servers
8320
8394
  };
8321
8395
  };
8322
- var projectMcpCachePath = (projectRoot) => path9.join(projectRoot, ".omp", "fabric", "mcp-cache.json");
8323
- var globalMcpCachePath = (agentDir) => path9.join(agentDir, "fabric", "mcp-descriptors.json");
8396
+ var projectMcpCachePath = (projectRoot) => path10.join(projectRoot, ".omp", "fabric", "mcp-cache.json");
8397
+ var globalMcpCachePath = (agentDir) => path10.join(agentDir, "fabric", "mcp-descriptors.json");
8324
8398
  var tempCounter = 0;
8325
8399
  var McpDescriptorCacheStore = class {
8326
8400
  constructor(filePath) {
@@ -8337,9 +8411,9 @@ var McpDescriptorCacheStore = class {
8337
8411
  // Atomic-ish write: temp file then rename, so a concurrent reader either
8338
8412
  // sees the previous cache or the next one, never a torn document.
8339
8413
  async save(file) {
8340
- const directory = path9.dirname(this.filePath);
8414
+ const directory = path10.dirname(this.filePath);
8341
8415
  await fs5.mkdir(directory, { recursive: true });
8342
- const tempPath = path9.join(
8416
+ const tempPath = path10.join(
8343
8417
  directory,
8344
8418
  `.mcp-cache-${process.pid}-${Date.now()}-${tempCounter++}.tmp`
8345
8419
  );
@@ -8354,7 +8428,7 @@ var McpDescriptorCacheStore = class {
8354
8428
  };
8355
8429
 
8356
8430
  // src/providers/mcp-provider.ts
8357
- import path10 from "node:path";
8431
+ import path11 from "node:path";
8358
8432
  var TOOL_METADATA_TTL_MS = 6e4;
8359
8433
  var REVALIDATE_CONCURRENCY = 3;
8360
8434
  var REVALIDATE_SERVER_TIMEOUT_MS = 2e4;
@@ -8362,6 +8436,7 @@ var MIN_REVALIDATE_SERVER_TIMEOUT_MS = 5e3;
8362
8436
  var NOTIFY_DEBOUNCE_MS = 100;
8363
8437
  var PERSIST_DEBOUNCE_MS = 150;
8364
8438
  var COLD_LIST_WAIT_MS = 2500;
8439
+ var MAX_CALL_TIMEOUT_MS = 9e5;
8365
8440
  var emptyObjectSchema = {
8366
8441
  type: "object",
8367
8442
  properties: {},
@@ -8412,7 +8487,12 @@ var managementDescriptors = [
8412
8487
  properties: {
8413
8488
  server: { type: "string" },
8414
8489
  tool: { type: "string" },
8415
- args: { type: "object", additionalProperties: true }
8490
+ args: { type: "object", additionalProperties: true },
8491
+ timeoutMs: {
8492
+ type: "number",
8493
+ minimum: 1,
8494
+ description: `Per-call timeout overriding mcp.callTimeoutMs, clamped to ${MAX_CALL_TIMEOUT_MS}ms.`
8495
+ }
8416
8496
  },
8417
8497
  required: ["server", "tool"],
8418
8498
  additionalProperties: false
@@ -8421,6 +8501,7 @@ var managementDescriptors = [
8421
8501
  namespace: "management"
8422
8502
  }
8423
8503
  ];
8504
+ var resolveMcpCallTimeoutMs = (value, fallback) => typeof value === "number" && Number.isFinite(value) && value >= 1 ? Math.min(Math.floor(value), MAX_CALL_TIMEOUT_MS) : fallback;
8424
8505
  var normalizeSchema = (schema) => typeof schema === "object" && schema !== null && !Array.isArray(schema) ? schema : emptyObjectSchema;
8425
8506
  var normalizeMcpResult = (result) => {
8426
8507
  if (typeof result !== "object" || result === null || Array.isArray(result)) return result;
@@ -8608,7 +8689,13 @@ var McpProvider = class {
8608
8689
  const server = String(args.server);
8609
8690
  const tool = String(args.tool);
8610
8691
  const toolArgs = typeof args.args === "object" && args.args !== null && !Array.isArray(args.args) ? args.args : {};
8611
- return this.#call(server, tool, toolArgs, context.signal);
8692
+ return this.#call(
8693
+ server,
8694
+ tool,
8695
+ toolArgs,
8696
+ context.signal,
8697
+ resolveMcpCallTimeoutMs(args.timeoutMs, this.config.callTimeoutMs)
8698
+ );
8612
8699
  }
8613
8700
  const parsed = this.#parseToolName(actionName);
8614
8701
  if (!parsed) throw new Error(`Invalid MCP action: ${actionName}`);
@@ -8681,8 +8768,8 @@ var McpProvider = class {
8681
8768
  }
8682
8769
  if (this.#dirtyPersist) await this.#persistNow().catch(() => void 0);
8683
8770
  }
8684
- async #call(serverName, toolName, args, signal) {
8685
- if (!this.#cacheOn) return this.#callLegacy(serverName, toolName, args, signal);
8771
+ async #call(serverName, toolName, args, signal, timeoutMs) {
8772
+ if (!this.#cacheOn) return this.#callLegacy(serverName, toolName, args, signal, timeoutMs);
8686
8773
  if (signal?.aborted) throw new Error("MCP call cancelled");
8687
8774
  await this.#hydrate();
8688
8775
  const server = await this.#resolveKnownServer(serverName);
@@ -8700,7 +8787,7 @@ var McpProvider = class {
8700
8787
  if (firstContact) this.#recontacted.add(server);
8701
8788
  const operation = runtime.callTool(server, tool.name, {
8702
8789
  args,
8703
- timeoutMs: this.config.callTimeoutMs,
8790
+ timeoutMs: timeoutMs ?? this.config.callTimeoutMs,
8704
8791
  disableOAuth: this.config.disableOAuth
8705
8792
  });
8706
8793
  try {
@@ -9065,7 +9152,7 @@ var McpProvider = class {
9065
9152
  kind: "stdio",
9066
9153
  command: args.command,
9067
9154
  args: commandArgs,
9068
- cwd: path10.resolve(this.cwd, typeof args.cwd === "string" ? args.cwd : ".")
9155
+ cwd: path11.resolve(this.cwd, typeof args.cwd === "string" ? args.cwd : ".")
9069
9156
  },
9070
9157
  ...env ? { env } : {}
9071
9158
  };
@@ -9148,7 +9235,7 @@ var McpProvider = class {
9148
9235
  const tool = await this.#findToolLegacy(runtime, server, parsed.tool);
9149
9236
  return tool ? this.#toolDescriptor(server, tool) : void 0;
9150
9237
  }
9151
- async #callLegacy(serverName, toolName, args, signal) {
9238
+ async #callLegacy(serverName, toolName, args, signal, timeoutMs) {
9152
9239
  if (signal?.aborted) throw new Error("MCP call cancelled");
9153
9240
  const runtime = await this.#getRuntime();
9154
9241
  const server = this.#resolveServerName(runtime, serverName);
@@ -9158,7 +9245,7 @@ var McpProvider = class {
9158
9245
  if (!tool) throw new Error(`Unknown MCP tool: ${serverName}.${toolName}`);
9159
9246
  const operation = runtime.callTool(server, tool.name, {
9160
9247
  args,
9161
- timeoutMs: this.config.callTimeoutMs,
9248
+ timeoutMs: timeoutMs ?? this.config.callTimeoutMs,
9162
9249
  disableOAuth: this.config.disableOAuth
9163
9250
  });
9164
9251
  try {
@@ -9262,7 +9349,11 @@ var descriptors4 = [
9262
9349
  items: { type: "string", enum: ["root", "agent", "actor"] }
9263
9350
  },
9264
9351
  includeStale: { type: "boolean" },
9265
- limit: { type: "number", minimum: 1 }
9352
+ limit: { type: "number", minimum: 1 },
9353
+ withTotal: {
9354
+ type: "boolean",
9355
+ description: "Return { members, total, truncated } instead of a bare array, so a clipped page is distinguishable from a complete one."
9356
+ }
9266
9357
  },
9267
9358
  additionalProperties: false
9268
9359
  },
@@ -9288,7 +9379,11 @@ var descriptors4 = [
9288
9379
  type: "object",
9289
9380
  properties: {
9290
9381
  prefix: { type: "string" },
9291
- limit: { type: "number", minimum: 1 }
9382
+ limit: { type: "number", minimum: 1 },
9383
+ withTotal: {
9384
+ type: "boolean",
9385
+ description: "Return { entries, total, truncated } instead of a bare array, so a clipped page is distinguishable from a complete one."
9386
+ }
9292
9387
  },
9293
9388
  additionalProperties: false
9294
9389
  },
@@ -9379,11 +9474,13 @@ var MeshProvider = class {
9379
9474
  ) : void 0;
9380
9475
  const scope = args.scope === "local" || args.scope === "lineage" || args.scope === "project" ? args.scope : "project";
9381
9476
  const limit = Math.max(1, Math.floor(typeof args.limit === "number" ? args.limit : 100));
9382
- return this.participants.list({
9477
+ const matched = this.participants.list({
9383
9478
  scope,
9384
9479
  ...kinds ? { kinds } : {},
9385
9480
  ...args.includeStale === true ? { includeStale: true } : {}
9386
- }).slice(0, limit);
9481
+ });
9482
+ const members = matched.slice(0, limit);
9483
+ return args.withTotal === true ? { members, total: matched.length, truncated: matched.length > members.length } : members;
9387
9484
  }
9388
9485
  case "get": {
9389
9486
  const key = String(args.key);
@@ -9400,11 +9497,13 @@ var MeshProvider = class {
9400
9497
  this.store.maxReadEvents
9401
9498
  )
9402
9499
  );
9403
- return this.store.listAll(prefix).filter(
9500
+ const matched = this.store.listAll(prefix).filter(
9404
9501
  (entry) => !PRIVATE_STATE_PREFIXES.some(
9405
9502
  (privatePrefix) => entry.key.startsWith(privatePrefix)
9406
9503
  )
9407
- ).slice(0, limit);
9504
+ );
9505
+ const entries = matched.slice(0, limit);
9506
+ return args.withTotal === true ? { entries, total: matched.length, truncated: matched.length > entries.length } : entries;
9408
9507
  }
9409
9508
  case "put": {
9410
9509
  const key = String(args.key);
@@ -9431,13 +9530,14 @@ var MeshProvider = class {
9431
9530
  };
9432
9531
 
9433
9532
  // src/providers/omp-tools-provider.ts
9434
- import { mkdirSync as mkdirSync2, mkdtempSync, readFileSync as readFileSync2, statSync as statSync3, writeFileSync as writeFileSync2 } from "node:fs";
9533
+ import { mkdirSync as mkdirSync2, mkdtempSync, readFileSync as readFileSync2, statSync as statSync4, writeFileSync as writeFileSync2 } from "node:fs";
9435
9534
  import { AsyncLocalStorage } from "node:async_hooks";
9436
9535
  import os2 from "node:os";
9437
- import path13 from "node:path";
9536
+ import path14 from "node:path";
9438
9537
  import { randomUUID as randomUUID3 } from "node:crypto";
9439
9538
  import { BashTool } from "@oh-my-pi/pi-coding-agent/tools/bash";
9440
9539
  import { EditTool } from "@oh-my-pi/pi-coding-agent/edit";
9540
+ import { GlobTool } from "@oh-my-pi/pi-coding-agent/tools/glob";
9441
9541
  import { GrepTool, MULTI_FILE_PER_FILE_MATCHES, SINGLE_FILE_MATCHES } from "@oh-my-pi/pi-coding-agent/tools/grep";
9442
9542
  import { ReadTool } from "@oh-my-pi/pi-coding-agent/tools/read";
9443
9543
  import { piEscapeRegexLiteral, piJoinPath } from "@oh-my-pi/pi-ai/providers/cursor-pi-args";
@@ -9450,7 +9550,7 @@ import {
9450
9550
 
9451
9551
  // src/agents/bash-worktree-add.ts
9452
9552
  import fs6 from "node:fs";
9453
- import path11 from "node:path";
9553
+ import path12 from "node:path";
9454
9554
  var BARE_SAFE = /^[A-Za-z0-9_./:@%+=,-]+$/;
9455
9555
  var parseGitWorktreeAdd = (command) => {
9456
9556
  const trimmed = command.trim();
@@ -9513,8 +9613,8 @@ var tryExecuteGitWorktreeAdd = async (args, sessionCwd) => {
9513
9613
  if (typeof command !== "string") return void 0;
9514
9614
  const parsed = parseGitWorktreeAdd(command);
9515
9615
  if (!parsed) return void 0;
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);
9616
+ const gitCwd = parsed.gitCwd ? path12.resolve(sessionCwd, parsed.gitCwd) : typeof args.cwd === "string" ? args.cwd : sessionCwd;
9617
+ const dest = path12.resolve(gitCwd, parsed.dest);
9518
9618
  let gitRoot;
9519
9619
  try {
9520
9620
  const root = await executeFile("git", ["rev-parse", "--show-toplevel"], {
@@ -9542,8 +9642,8 @@ var tryExecuteGitWorktreeAdd = async (args, sessionCwd) => {
9542
9642
  };
9543
9643
 
9544
9644
  // src/providers/omp-bash-cwd.ts
9545
- import { accessSync, constants, statSync as statSync2 } from "node:fs";
9546
- import path12 from "node:path";
9645
+ import { accessSync, constants, statSync as statSync3 } from "node:fs";
9646
+ import path13 from "node:path";
9547
9647
  import { createBashToolDefinition } from "@oh-my-pi/pi-coding-agent/extensibility/legacy-pi-coding-agent-shim";
9548
9648
  import { Type as Type3 } from "@oh-my-pi/pi-coding-agent/extensibility/legacy-typebox";
9549
9649
  var OMP_BASH_CWD_KEY = "cwd";
@@ -9553,9 +9653,9 @@ var resolveOmpShellCwd = (toolName, sessionCwd, requested) => {
9553
9653
  `Invalid omp.${toolName} cwd ${JSON.stringify(requested)}: path must be a non-empty string`
9554
9654
  );
9555
9655
  }
9556
- const resolved = path12.isAbsolute(requested) ? path12.resolve(requested) : path12.resolve(sessionCwd, requested);
9656
+ const resolved = path13.isAbsolute(requested) ? path13.resolve(requested) : path13.resolve(sessionCwd, requested);
9557
9657
  try {
9558
- if (!statSync2(resolved).isDirectory()) throw new Error("path is not a directory");
9658
+ if (!statSync3(resolved).isDirectory()) throw new Error("path is not a directory");
9559
9659
  accessSync(resolved, constants.R_OK | constants.X_OK);
9560
9660
  } catch (error) {
9561
9661
  const reason = error instanceof Error ? error.message : String(error);
@@ -9628,28 +9728,49 @@ var BashCwdDefinitions = class extends ShellCwdDefinitions {
9628
9728
 
9629
9729
  // src/providers/write-preview.ts
9630
9730
  import { homedir } from "node:os";
9631
- import { dirname, isAbsolute, resolve } from "node:path";
9731
+ import { dirname, isAbsolute, resolve, win32 } from "node:path";
9632
9732
  import { mkdir, readFile as readFile2, stat, writeFile } from "node:fs/promises";
9633
9733
  import { Type as Type4 } from "@oh-my-pi/pi-coding-agent/extensibility/legacy-typebox";
9634
9734
  var mutationQueues = /* @__PURE__ */ new Map();
9635
- var withFileMutationQueue = async (path19, operation) => {
9636
- const previous = mutationQueues.get(path19) ?? Promise.resolve();
9735
+ var withFileMutationQueue = async (path20, operation) => {
9736
+ const previous = mutationQueues.get(path20) ?? Promise.resolve();
9637
9737
  let release;
9638
9738
  const current = new Promise((resolve2) => {
9639
9739
  release = resolve2;
9640
9740
  });
9641
- mutationQueues.set(path19, current);
9741
+ mutationQueues.set(path20, current);
9642
9742
  await previous;
9643
9743
  try {
9644
9744
  return await operation();
9645
9745
  } finally {
9646
9746
  release();
9647
- if (mutationQueues.get(path19) === current) mutationQueues.delete(path19);
9747
+ if (mutationQueues.get(path20) === current) mutationQueues.delete(path20);
9648
9748
  }
9649
9749
  };
9750
+ var URI_LIKE_WRITE_TARGET_RE = /^([a-z][a-z0-9+.-]*):\/{1,2}/i;
9751
+ var OmpWriteUriTargetError = class extends Error {
9752
+ path;
9753
+ constructor(message2, path20) {
9754
+ super(message2);
9755
+ this.name = "OmpWriteUriTargetError";
9756
+ this.path = path20;
9757
+ }
9758
+ };
9759
+ var assertFilesystemWriteTarget = (candidate, reported) => {
9760
+ const trimmed = candidate.trim();
9761
+ if (win32.isAbsolute(trimmed)) return;
9762
+ const scheme = URI_LIKE_WRITE_TARGET_RE.exec(trimmed)?.[1]?.toLowerCase();
9763
+ if (scheme === void 0) return;
9764
+ const guidance = scheme === "xd" ? "Tool devices are dispatched by the top-level `write` tool, which carries the xd:// transport; omp.write writes files." : "omp.write resolves filesystem paths only.";
9765
+ throw new OmpWriteUriTargetError(
9766
+ `Refusing to write '${reported}': '${scheme}://' is a URI scheme, not a directory. ${guidance} Prefix the path with './' to create a literal file by that name.`,
9767
+ reported
9768
+ );
9769
+ };
9650
9770
  var resolvePreviewPath = (filePath, cwd) => {
9651
9771
  let expanded = filePath.startsWith("@") ? filePath.slice(1) : filePath;
9652
9772
  expanded = expanded.replace(/[\u00a0\u2000-\u200a\u202f\u205f\u3000]/g, " ");
9773
+ assertFilesystemWriteTarget(expanded, filePath);
9653
9774
  if (expanded === "~") expanded = homedir();
9654
9775
  else if (expanded.startsWith("~/")) expanded = homedir() + expanded.slice(1);
9655
9776
  return isAbsolute(expanded) ? expanded : resolve(cwd, expanded);
@@ -9697,14 +9818,14 @@ var createPreviewWriteToolDefinition = (cwd) => {
9697
9818
  return {
9698
9819
  ...original,
9699
9820
  async execute(_toolCallId, params, signal) {
9700
- const { path: path19, content } = params;
9701
- const absolutePath = resolvePreviewPath(path19, cwd);
9821
+ const { path: path20, content } = params;
9822
+ const absolutePath = resolvePreviewPath(path20, cwd);
9702
9823
  return withFileMutationQueue(absolutePath, async () => {
9703
9824
  const throwIfAborted2 = () => {
9704
9825
  if (signal?.aborted) throw new Error("Operation aborted");
9705
9826
  };
9706
9827
  throwIfAborted2();
9707
- const before = await readExistingFileForPreview(path19, cwd, content);
9828
+ const before = await readExistingFileForPreview(path20, cwd, content);
9708
9829
  throwIfAborted2();
9709
9830
  await mkdir(dirname(absolutePath), { recursive: true });
9710
9831
  throwIfAborted2();
@@ -9714,7 +9835,7 @@ var createPreviewWriteToolDefinition = (cwd) => {
9714
9835
  content: [
9715
9836
  {
9716
9837
  type: "text",
9717
- text: `Successfully wrote ${Buffer.byteLength(content, "utf8")} bytes to ${path19}`
9838
+ text: `Successfully wrote ${Buffer.byteLength(content, "utf8")} bytes to ${path20}`
9718
9839
  }
9719
9840
  ],
9720
9841
  details: { codePreviewBeforeWrite: before }
@@ -9729,7 +9850,7 @@ var MAX_RENDERER_ARGUMENT_CHARS = 2e5;
9729
9850
  var GUEST_READ_LINE_LIMIT = 1e5;
9730
9851
  var MAX_REPLACE_ALL_FILE_CHARS = 2e6;
9731
9852
  var createNativeSession = (cwd, artifactPaths) => {
9732
- const artifactRoot = artifactPaths ? mkdtempSync(path13.join(os2.tmpdir(), "omp-fabric-bash-")) : void 0;
9853
+ const artifactRoot = artifactPaths ? mkdtempSync(path14.join(os2.tmpdir(), "omp-fabric-bash-")) : void 0;
9733
9854
  return {
9734
9855
  cwd,
9735
9856
  hasUI: false,
@@ -9746,7 +9867,7 @@ var createNativeSession = (cwd, artifactPaths) => {
9746
9867
  try {
9747
9868
  mkdirSync2(artifactRoot, { recursive: true, mode: 448 });
9748
9869
  const id = randomUUID3();
9749
- const artifactPath = path13.join(artifactRoot, `${toolType}-${id}.log`);
9870
+ const artifactPath = path14.join(artifactRoot, `${toolType}-${id}.log`);
9750
9871
  writeFileSync2(artifactPath, "", { mode: 384 });
9751
9872
  artifactPaths.set(id, artifactPath);
9752
9873
  artifactAllocations.getStore()?.push(artifactPath);
@@ -9787,12 +9908,28 @@ var GREP_SKIP_PROPERTY = {
9787
9908
  type: "number",
9788
9909
  description: "Files to skip before collecting results \u2014 paginate when a search hit the file limit"
9789
9910
  };
9790
- var withGrepSkipSchema = (document) => {
9791
- const schema = asRecord(document);
9911
+ var GITIGNORE_PROPERTY = {
9912
+ type: "boolean",
9913
+ description: "Respect gitignore rules; pass false to search ignored files such as build output or .env"
9914
+ };
9915
+ var HIDDEN_PROPERTY = {
9916
+ type: "boolean",
9917
+ description: "Include dotfiles and hidden directories"
9918
+ };
9919
+ var withExtraProperties = (document, extras) => {
9920
+ const source = typeof document === "function" && "toJsonSchema" in document ? document.toJsonSchema() : document;
9921
+ const schema = asRecord(source);
9792
9922
  const properties = asRecord(schema?.properties);
9793
- if (!schema || !properties || Object.hasOwn(properties, "skip")) return document;
9794
- return { ...schema, properties: { ...properties, skip: GREP_SKIP_PROPERTY } };
9923
+ if (!schema || !properties) return document;
9924
+ const additions = {};
9925
+ for (const [name, property] of Object.entries(extras)) {
9926
+ if (!Object.hasOwn(properties, name)) additions[name] = property;
9927
+ }
9928
+ if (Object.keys(additions).length === 0) return document;
9929
+ return { ...schema, properties: { ...properties, ...additions } };
9795
9930
  };
9931
+ var withGrepSkipSchema = (document) => withExtraProperties(document, { skip: GREP_SKIP_PROPERTY, gitignore: GITIGNORE_PROPERTY });
9932
+ var withFindFilterSchema = (document) => withExtraProperties(document, { gitignore: GITIGNORE_PROPERTY, hidden: HIDDEN_PROPERTY });
9796
9933
  var grepSession = (cwd, context) => ({
9797
9934
  cwd,
9798
9935
  hasUI: false,
@@ -9822,7 +9959,37 @@ var createGrepDefinitionWithSkip = (cwd) => {
9822
9959
  pattern: record2.literal === true ? piEscapeRegexLiteral(rawPattern) : rawPattern,
9823
9960
  path: glob ? piJoinPath(searchPath, glob) : searchPath,
9824
9961
  case: record2.ignoreCase === true ? false : void 0,
9825
- ...skip === void 0 ? {} : { skip }
9962
+ ...skip === void 0 ? {} : { skip },
9963
+ ...typeof record2.gitignore === "boolean" ? { gitignore: record2.gitignore } : {}
9964
+ },
9965
+ signal,
9966
+ onUpdate,
9967
+ context
9968
+ );
9969
+ }
9970
+ };
9971
+ };
9972
+ var createFindDefinitionWithFilters = (cwd) => {
9973
+ const legacy = createFindToolDefinition(cwd);
9974
+ const tool = new GlobTool(grepSession(cwd));
9975
+ return {
9976
+ ...legacy,
9977
+ parameters: withFindFilterSchema(legacy.parameters),
9978
+ execute: (toolCallId, params, signal, onUpdate, context) => {
9979
+ const record2 = asRecord(params) ?? {};
9980
+ if (typeof record2.gitignore !== "boolean" && typeof record2.hidden !== "boolean") {
9981
+ return legacy.execute(toolCallId, params, signal, onUpdate, context);
9982
+ }
9983
+ const pattern = typeof record2.pattern === "string" ? record2.pattern : void 0;
9984
+ const searchPath = typeof record2.path === "string" ? record2.path : void 0;
9985
+ const limit = typeof record2.limit === "number" ? record2.limit : void 0;
9986
+ return tool.execute(
9987
+ toolCallId,
9988
+ {
9989
+ path: piJoinPath(searchPath ?? ".", pattern ?? "*"),
9990
+ ...limit === void 0 ? {} : { limit },
9991
+ ...typeof record2.gitignore === "boolean" ? { gitignore: record2.gitignore } : {},
9992
+ ...typeof record2.hidden === "boolean" ? { hidden: record2.hidden } : {}
9826
9993
  },
9827
9994
  signal,
9828
9995
  onUpdate,
@@ -9853,7 +10020,7 @@ var normalizeEditArguments = (args, replaceAll, cwd) => {
9853
10020
  ...replaceAll || record2.all === true || record2.replace_all === true ? { replace_all: true } : {}
9854
10021
  };
9855
10022
  });
9856
- const resolvedPath = path13.resolve(cwd, filePath.startsWith("@") ? filePath.slice(1) : filePath);
10023
+ const resolvedPath = path14.resolve(cwd, filePath.startsWith("@") ? filePath.slice(1) : filePath);
9857
10024
  const current = readFileSync2(resolvedPath, "utf8");
9858
10025
  if (current.length > MAX_REPLACE_ALL_FILE_CHARS) {
9859
10026
  throw new Error(`omp.edit refuses files over ${MAX_REPLACE_ALL_FILE_CHARS} characters`);
@@ -10007,7 +10174,7 @@ var restoreBashOutput = (artifactPath, maxChars, delivered) => {
10007
10174
  if (!artifactPath || maxChars <= 0) return void 0;
10008
10175
  let size;
10009
10176
  try {
10010
- size = statSync3(artifactPath).size;
10177
+ size = statSync4(artifactPath).size;
10011
10178
  } catch {
10012
10179
  return void 0;
10013
10180
  }
@@ -10249,7 +10416,7 @@ var OmpToolsProvider = class _OmpToolsProvider {
10249
10416
  edit: createNativeReplaceEditToolDefinition(cwd),
10250
10417
  write: createPreviewWriteToolDefinition(cwd),
10251
10418
  grep: createGrepDefinitionWithSkip(cwd),
10252
- find: createFindToolDefinition(cwd),
10419
+ find: createFindDefinitionWithFilters(cwd),
10253
10420
  ls: createLsToolDefinition(cwd)
10254
10421
  };
10255
10422
  this.#catalog = catalog;
@@ -10654,7 +10821,7 @@ var OmpToolsProvider = class _OmpToolsProvider {
10654
10821
  import { spawn } from "node:child_process";
10655
10822
  import { createHash as createHash3, randomBytes, randomUUID as randomUUID4 } from "node:crypto";
10656
10823
  import fs8 from "node:fs";
10657
- import path15 from "node:path";
10824
+ import path16 from "node:path";
10658
10825
 
10659
10826
  // src/schema/types.ts
10660
10827
  var stateBinding = (head) => head ? { transitionId: head.transitionId, version: head.version, to: head.to } : null;
@@ -10663,7 +10830,7 @@ var stateBinding = (head) => head ? { transitionId: head.transitionId, version:
10663
10830
  import { execFileSync } from "node:child_process";
10664
10831
  import { createHash as createHash2 } from "node:crypto";
10665
10832
  import fs7 from "node:fs";
10666
- import path14 from "node:path";
10833
+ import path15 from "node:path";
10667
10834
  var SNAPSHOT_MAX_FILES = 2e4;
10668
10835
  var SNAPSHOT_MAX_BYTES = 512 * 1024 * 1024;
10669
10836
  var FALLBACK_SKIPPED_DIRECTORIES = /* @__PURE__ */ new Set([
@@ -10681,10 +10848,10 @@ var git = (cwd, args) => execFileSync("git", ["-C", cwd, ...args], {
10681
10848
  stdio: ["ignore", "pipe", "ignore"]
10682
10849
  });
10683
10850
  var nulPaths = (buffer) => buffer.toString("utf8").split("\0").filter((item) => item.length > 0);
10684
- var normalizeRelative = (value) => value.split(path14.sep).join("/");
10851
+ var normalizeRelative = (value) => value.split(path15.sep).join("/");
10685
10852
  var isInside = (root, candidate) => {
10686
- const relative = path14.relative(root, candidate);
10687
- return relative === "" || !path14.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path14.sep}`);
10853
+ const relative = path15.relative(root, candidate);
10854
+ return relative === "" || !path15.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path15.sep}`);
10688
10855
  };
10689
10856
  var excluded = (absolute, exclusions) => exclusions.some((root) => isInside(root, absolute));
10690
10857
  var entryDigest = (absolute) => {
@@ -10710,12 +10877,12 @@ var buildSnapshot = (cwd, paths, metadata, exclusions) => {
10710
10877
  let bytes = 0;
10711
10878
  const unique = [...new Set(paths)].sort((left, right) => left.localeCompare(right));
10712
10879
  for (const relativeInput of unique) {
10713
- const absolute = path14.resolve(cwd, relativeInput);
10880
+ const absolute = path15.resolve(cwd, relativeInput);
10714
10881
  if (!isInside(cwd, absolute) || excluded(absolute, exclusions)) continue;
10715
10882
  if (Object.keys(entries).length >= SNAPSHOT_MAX_FILES) {
10716
10883
  throw new Error(`Schema workspace snapshot exceeds ${SNAPSHOT_MAX_FILES} files`);
10717
10884
  }
10718
- const relative = normalizeRelative(path14.relative(cwd, absolute));
10885
+ const relative = normalizeRelative(path15.relative(cwd, absolute));
10719
10886
  const entry = entryDigest(absolute);
10720
10887
  bytes += entry.bytes;
10721
10888
  if (bytes > SNAPSHOT_MAX_BYTES) {
@@ -10744,9 +10911,9 @@ var fallbackPaths = (cwd, exclusions) => {
10744
10911
  const entries = fs7.readdirSync(directory, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
10745
10912
  for (const entry of entries) {
10746
10913
  if (FALLBACK_SKIPPED_DIRECTORIES.has(entry.name)) continue;
10747
- const absolute = path14.join(directory, entry.name);
10914
+ const absolute = path15.join(directory, entry.name);
10748
10915
  if (excluded(absolute, exclusions)) continue;
10749
- const relative = normalizeRelative(path14.relative(cwd, absolute));
10916
+ const relative = normalizeRelative(path15.relative(cwd, absolute));
10750
10917
  if (entry.isDirectory()) visit(absolute);
10751
10918
  else paths.push(relative);
10752
10919
  if (paths.length > SNAPSHOT_MAX_FILES) {
@@ -10760,7 +10927,7 @@ var fallbackPaths = (cwd, exclusions) => {
10760
10927
  var snapshotWorkspace = (cwdInput, excludedRoots = []) => {
10761
10928
  const cwd = fs7.realpathSync(cwdInput);
10762
10929
  const exclusions = excludedRoots.map((root) => {
10763
- const absolute = path14.resolve(root);
10930
+ const absolute = path15.resolve(root);
10764
10931
  try {
10765
10932
  return fs7.realpathSync(absolute);
10766
10933
  } catch {
@@ -10798,18 +10965,18 @@ var snapshotWorkspace = (cwdInput, excludedRoots = []) => {
10798
10965
  );
10799
10966
  };
10800
10967
  var resolveWorkspaceFile = (cwdInput, requestedPath, options) => {
10801
- if (!requestedPath.trim() || path14.isAbsolute(requestedPath)) {
10968
+ if (!requestedPath.trim() || path15.isAbsolute(requestedPath)) {
10802
10969
  throw new Error(`Schema paths must be non-empty project-relative paths: ${requestedPath}`);
10803
10970
  }
10804
10971
  const cwd = fs7.realpathSync(cwdInput);
10805
- const absolute = path14.resolve(cwd, requestedPath);
10972
+ const absolute = path15.resolve(cwd, requestedPath);
10806
10973
  if (!isInside(cwd, absolute) || absolute === cwd) {
10807
10974
  throw new Error(`Schema path escapes the project workspace: ${requestedPath}`);
10808
10975
  }
10809
- const relativeParts = path14.relative(cwd, absolute).split(path14.sep);
10976
+ const relativeParts = path15.relative(cwd, absolute).split(path15.sep);
10810
10977
  let cursor = cwd;
10811
10978
  for (let index = 0; index < relativeParts.length; index++) {
10812
- cursor = path14.join(cursor, relativeParts[index]);
10979
+ cursor = path15.join(cursor, relativeParts[index]);
10813
10980
  let stat2;
10814
10981
  try {
10815
10982
  stat2 = fs7.lstatSync(cursor);
@@ -10818,9 +10985,9 @@ var resolveWorkspaceFile = (cwdInput, requestedPath, options) => {
10818
10985
  if (index !== relativeParts.length - 1 || !options.allowAbsent) {
10819
10986
  throw new Error(`Schema path does not exist: ${requestedPath}`);
10820
10987
  }
10821
- const parentReal = fs7.realpathSync(path14.dirname(cursor));
10988
+ const parentReal = fs7.realpathSync(path15.dirname(cursor));
10822
10989
  if (!isInside(cwd, parentReal)) throw new Error(`Schema path parent escapes the workspace: ${requestedPath}`);
10823
- return { absolute, relative: normalizeRelative(path14.relative(cwd, absolute)), exists: false };
10990
+ return { absolute, relative: normalizeRelative(path15.relative(cwd, absolute)), exists: false };
10824
10991
  }
10825
10992
  throw error;
10826
10993
  }
@@ -10832,7 +10999,7 @@ var resolveWorkspaceFile = (cwdInput, requestedPath, options) => {
10832
10999
  throw new Error(`Schema transaction paths must name regular files: ${requestedPath}`);
10833
11000
  }
10834
11001
  }
10835
- return { absolute, relative: normalizeRelative(path14.relative(cwd, absolute)), exists: true };
11002
+ return { absolute, relative: normalizeRelative(path15.relative(cwd, absolute)), exists: true };
10836
11003
  };
10837
11004
  var sha256File = (absolute) => `sha256:${digest(fs7.readFileSync(absolute))}`;
10838
11005
 
@@ -10883,8 +11050,8 @@ var SchemaController = class {
10883
11050
  this.identity = identity;
10884
11051
  this.state = state;
10885
11052
  this.cwd = fs8.realpathSync(cwd);
10886
- this.#journalRoot = path15.join(mesh.root, "schema-transactions");
10887
- this.#lockPath = path15.join(this.#journalRoot, ".commit.lock");
11053
+ this.#journalRoot = path16.join(mesh.root, "schema-transactions");
11054
+ this.#lockPath = path16.join(this.#journalRoot, ".commit.lock");
10888
11055
  this.#recoverJournals();
10889
11056
  }
10890
11057
  #activeHypotheses = /* @__PURE__ */ new Map();
@@ -11083,7 +11250,7 @@ var SchemaController = class {
11083
11250
  this.#assertPayloadBound(input);
11084
11251
  const release = this.#acquireCommitLock();
11085
11252
  const transactionId = randomUUID4();
11086
- const journalPath = path15.join(this.#journalRoot, `${transactionId}.json`);
11253
+ const journalPath = path16.join(this.#journalRoot, `${transactionId}.json`);
11087
11254
  let journal;
11088
11255
  let consumed = false;
11089
11256
  let committed = false;
@@ -11564,7 +11731,7 @@ ${Date.now()}
11564
11731
  }
11565
11732
  for (const name of fs8.readdirSync(this.#journalRoot)) {
11566
11733
  if (!name.endsWith(".json")) continue;
11567
- const filePath = path15.join(this.#journalRoot, name);
11734
+ const filePath = path16.join(this.#journalRoot, name);
11568
11735
  try {
11569
11736
  const journal = JSON.parse(fs8.readFileSync(filePath, "utf8"));
11570
11737
  if (journal.format !== 1 || journal.status !== "applying" || !Array.isArray(journal.before)) continue;
@@ -11818,11 +11985,11 @@ var SchemaProvider = class {
11818
11985
 
11819
11986
  // src/state/store.ts
11820
11987
  import { createHash as createHash5 } from "node:crypto";
11821
- import path17 from "node:path";
11988
+ import path18 from "node:path";
11822
11989
 
11823
11990
  // src/state/complexity.ts
11824
11991
  import fs9 from "node:fs";
11825
- import path16 from "node:path";
11992
+ import path17 from "node:path";
11826
11993
  var isWordStart = (character) => character !== void 0 && (character >= "a" && character <= "z" || character >= "A" && character <= "Z" || character === "_" || character === "$");
11827
11994
  var isWordPart = (character) => isWordStart(character) || character !== void 0 && character >= "0" && character <= "9";
11828
11995
  var regularExpressionPrefixWords = /* @__PURE__ */ new Set([
@@ -12054,7 +12221,7 @@ var languageComplexities = [
12054
12221
  typeScriptJavaScriptComplexity
12055
12222
  ];
12056
12223
  var complexityForFile = (file, languages = languageComplexities) => {
12057
- const extension = path16.extname(file).toLowerCase();
12224
+ const extension = path17.extname(file).toLowerCase();
12058
12225
  return languages.find((language) => language.extensions.includes(extension));
12059
12226
  };
12060
12227
  var countFileComplexity = (file) => {
@@ -12945,7 +13112,7 @@ var StateStore = class {
12945
13112
  const files = [];
12946
13113
  let netDelta = 0;
12947
13114
  for (const file of this.normalizeComplexityFiles(requestedFiles, input.cwd)) {
12948
- const measured = countFileComplexity(path17.resolve(input.cwd, file));
13115
+ const measured = countFileComplexity(path18.resolve(input.cwd, file));
12949
13116
  if (!measured) {
12950
13117
  files.push({ file, supported: false });
12951
13118
  continue;
@@ -12972,7 +13139,7 @@ var StateStore = class {
12972
13139
  const updates = [];
12973
13140
  let netDelta = 0;
12974
13141
  for (const file of this.normalizeComplexityFiles(files, cwd)) {
12975
- const measured = countFileComplexity(path17.resolve(cwd, file));
13142
+ const measured = countFileComplexity(path18.resolve(cwd, file));
12976
13143
  if (!measured) {
12977
13144
  deltas.push({ file, supported: false });
12978
13145
  continue;
@@ -13022,11 +13189,11 @@ var StateStore = class {
13022
13189
  const normalized = /* @__PURE__ */ new Set();
13023
13190
  for (const file of files) {
13024
13191
  if (!file.trim()) continue;
13025
- const relative = path17.relative(cwd, path17.resolve(cwd, file));
13026
- if (relative === ".." || relative.startsWith(`..${path17.sep}`) || path17.isAbsolute(relative)) {
13192
+ const relative = path18.relative(cwd, path18.resolve(cwd, file));
13193
+ if (relative === ".." || relative.startsWith(`..${path18.sep}`) || path18.isAbsolute(relative)) {
13027
13194
  throw new Error(`State complexity file must be inside the project cwd: ${file}`);
13028
13195
  }
13029
- normalized.add(relative.split(path17.sep).join("/"));
13196
+ normalized.add(relative.split(path18.sep).join("/"));
13030
13197
  }
13031
13198
  return [...normalized];
13032
13199
  }
@@ -14020,7 +14187,7 @@ var FabricRuntimeState = class {
14020
14187
  this.#mainAgent = mainAgent;
14021
14188
  const projectRoot = process.env.OMP_FABRIC_PROJECT_ROOT ?? context.cwd;
14022
14189
  const configuredMeshRoot = this.#config.mesh.root;
14023
- const meshRoot = process.env.OMP_FABRIC_MESH_ROOT ?? (configuredMeshRoot ? path18.resolve(projectRoot, configuredMeshRoot) : path18.join(projectRoot, ".omp", "fabric", "mesh"));
14190
+ const meshRoot = process.env.OMP_FABRIC_MESH_ROOT ?? (configuredMeshRoot ? path19.resolve(projectRoot, configuredMeshRoot) : path19.join(projectRoot, ".omp", "fabric", "mesh"));
14024
14191
  this.#mesh = new MeshStore(
14025
14192
  meshRoot,
14026
14193
  this.#config.mesh.maxEventBytes,
@@ -14194,8 +14361,8 @@ var FabricRuntimeState = class {
14194
14361
  };
14195
14362
  const lineageAlive = (rootId) => this.#participants?.get(rootId) !== void 0;
14196
14363
  const actorRoots = {
14197
- project: path18.join(meshRoot, "actors"),
14198
- session: path18.join(meshRoot, "actors", fabricSessionId)
14364
+ project: path19.join(meshRoot, "actors"),
14365
+ session: path19.join(meshRoot, "actors", fabricSessionId)
14199
14366
  };
14200
14367
  const acquireActorCapabilityView = (requirements, signal) => this.#registry.acquireCapabilityView(requirements, {
14201
14368
  cwd: context.cwd,