omp-fabric 1.11.0 → 1.13.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 (82) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/chunks/{chunk-IGD65D4I.js → chunk-2NTQAH6X.js} +76 -52
  3. package/dist/chunks/chunk-2NTQAH6X.js.map +7 -0
  4. package/dist/chunks/chunk-3XPR2AZL.js +74 -0
  5. package/dist/chunks/chunk-3XPR2AZL.js.map +7 -0
  6. package/dist/chunks/{chunk-Z7HQ6FYW.js → chunk-ANAXFBUE.js} +233 -13
  7. package/dist/chunks/chunk-ANAXFBUE.js.map +7 -0
  8. package/dist/chunks/{chunk-KHQJKGBC.js → chunk-AOXYDBXC.js} +473 -133
  9. package/dist/chunks/chunk-AOXYDBXC.js.map +7 -0
  10. package/dist/chunks/{chunk-TIYERND7.js → chunk-DTXCVXXF.js} +4 -4
  11. package/dist/chunks/{chunk-KTB4R3E3.js → chunk-GZQVYRM3.js} +34 -2
  12. package/dist/chunks/chunk-GZQVYRM3.js.map +7 -0
  13. package/dist/chunks/{chunk-BUV2RSRP.js → chunk-IIX4W4N4.js} +4 -4
  14. package/dist/chunks/{chunk-IT2XOTTB.js → chunk-KJKO6KGW.js} +6 -4
  15. package/dist/chunks/chunk-KJKO6KGW.js.map +7 -0
  16. package/dist/chunks/{chunk-U4KYMAJJ.js → chunk-NIWOSO22.js} +6 -71
  17. package/dist/chunks/chunk-NIWOSO22.js.map +7 -0
  18. package/dist/chunks/{chunk-FG55L44G.js → chunk-R6QAXATY.js} +3 -3
  19. package/dist/chunks/{chunk-JSBTB3P6.js → chunk-SKYNDRW5.js} +24 -1
  20. package/dist/chunks/{chunk-JSBTB3P6.js.map → chunk-SKYNDRW5.js.map} +3 -3
  21. package/dist/chunks/{chunk-LVMIIY3Q.js → chunk-U5QWDSIL.js} +3 -3
  22. package/dist/chunks/{chunk-TSU4AEPZ.js → chunk-XH6SP6UI.js} +30 -37
  23. package/dist/chunks/chunk-XH6SP6UI.js.map +7 -0
  24. package/dist/compaction/hook.js +3 -2
  25. package/dist/compaction/lcm-addresses.d.ts +10 -0
  26. package/dist/compaction/lcm-addresses.d.ts.map +1 -0
  27. package/dist/compaction/lcm-maintenance.d.ts +11 -1
  28. package/dist/compaction/lcm-maintenance.d.ts.map +1 -1
  29. package/dist/compaction/lcm-model.d.ts +2 -1
  30. package/dist/compaction/lcm-model.d.ts.map +1 -1
  31. package/dist/compaction/lcm-runtime.d.ts +22 -0
  32. package/dist/compaction/lcm-runtime.d.ts.map +1 -1
  33. package/dist/compaction/lcm-runtime.js +555 -44
  34. package/dist/compaction/lcm-runtime.js.map +3 -3
  35. package/dist/compaction/threshold.d.ts.map +1 -1
  36. package/dist/config.d.ts +4 -0
  37. package/dist/config.d.ts.map +1 -1
  38. package/dist/fabric-runtime-state.d.ts +3 -34
  39. package/dist/fabric-runtime-state.d.ts.map +1 -1
  40. package/dist/fabric-runtime-state.js +11 -10
  41. package/dist/fabric-runtime-state.js.map +2 -2
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +41 -72
  44. package/dist/index.js.map +4 -4
  45. package/dist/memory/lcm-adapter.d.ts +12 -0
  46. package/dist/memory/lcm-adapter.d.ts.map +1 -1
  47. package/dist/output-budget.d.ts +34 -0
  48. package/dist/output-budget.d.ts.map +1 -1
  49. package/dist/providers/memory-provider.d.ts +2 -0
  50. package/dist/providers/memory-provider.d.ts.map +1 -1
  51. package/dist/providers/memory-provider.js +3 -2
  52. package/dist/residency/host.js +10 -9
  53. package/dist/residency/omp-entry.js +10 -9
  54. package/dist/residency/omp-entry.js.map +1 -1
  55. package/dist/storage/lcm-ledger.d.ts +50 -1
  56. package/dist/storage/lcm-ledger.d.ts.map +1 -1
  57. package/dist/storage/lcm-migration.d.ts +12 -0
  58. package/dist/storage/lcm-migration.d.ts.map +1 -1
  59. package/dist/ui/dashboard.js +4 -3
  60. package/dist/ui/dashboard.js.map +2 -2
  61. package/dist/ui/fabric-render.d.ts +1 -1
  62. package/dist/ui/fabric-render.d.ts.map +1 -1
  63. package/dist/ui/lcm-panel.d.ts.map +1 -1
  64. package/dist/ui/settings.d.ts +5 -0
  65. package/dist/ui/settings.d.ts.map +1 -1
  66. package/dist/ui/settings.js +558 -18
  67. package/dist/ui/settings.js.map +2 -2
  68. package/docs/compaction.md +16 -2
  69. package/docs/configuration.md +55 -6
  70. package/docs/memory-recall.md +18 -7
  71. package/package.json +1 -1
  72. package/dist/chunks/chunk-IGD65D4I.js.map +0 -7
  73. package/dist/chunks/chunk-IT2XOTTB.js.map +0 -7
  74. package/dist/chunks/chunk-KHQJKGBC.js.map +0 -7
  75. package/dist/chunks/chunk-KTB4R3E3.js.map +0 -7
  76. package/dist/chunks/chunk-TSU4AEPZ.js.map +0 -7
  77. package/dist/chunks/chunk-U4KYMAJJ.js.map +0 -7
  78. package/dist/chunks/chunk-Z7HQ6FYW.js.map +0 -7
  79. /package/dist/chunks/{chunk-TIYERND7.js.map → chunk-DTXCVXXF.js.map} +0 -0
  80. /package/dist/chunks/{chunk-BUV2RSRP.js.map → chunk-IIX4W4N4.js.map} +0 -0
  81. /package/dist/chunks/{chunk-FG55L44G.js.map → chunk-R6QAXATY.js.map} +0 -0
  82. /package/dist/chunks/{chunk-LVMIIY3Q.js.map → chunk-U5QWDSIL.js.map} +0 -0
@@ -2,8 +2,9 @@ import {
2
2
  DEFAULT_FABRIC_THINKING,
3
3
  defaultCodePreviewSettings,
4
4
  isFabricThinking,
5
- normalizeCodePreviewSettings
6
- } from "./chunk-JSBTB3P6.js";
5
+ normalizeCodePreviewSettings,
6
+ truncateMiddle
7
+ } from "./chunk-SKYNDRW5.js";
7
8
  import {
8
9
  renameAtomic
9
10
  } from "./chunk-KAD7UWT2.js";
@@ -206,7 +207,7 @@ var resolveAvailableOmpModel = (selector, options) => {
206
207
  // src/config.ts
207
208
  import fs from "node:fs";
208
209
  import os from "node:os";
209
- import path from "node:path";
210
+ import path2 from "node:path";
210
211
 
211
212
  // src/config-migrations.ts
212
213
  var CURRENT_FABRIC_CONFIG_VERSION = 5;
@@ -347,6 +348,175 @@ var migrateFabricConfigDocument = (input) => {
347
348
  };
348
349
  };
349
350
 
351
+ // src/output-budget.ts
352
+ import { mkdir, readdir, rm, stat, writeFile } from "node:fs/promises";
353
+ import { randomBytes } from "node:crypto";
354
+ import path from "node:path";
355
+ var MAX_FAILURE_MODEL_OUTPUT_CHARS = 2e4;
356
+ var modelOutputBudget = (configuredMaxChars, success) => success ? configuredMaxChars : Math.min(configuredMaxChars, MAX_FAILURE_MODEL_OUTPUT_CHARS);
357
+ var fabricStateDir = (env = process.env) => path.join(
358
+ env.XDG_STATE_HOME || path.join(env.HOME || ".", ".local", "state"),
359
+ "omp-fabric"
360
+ );
361
+ var outputArtifactDir = (env = process.env) => path.join(fabricStateDir(env), "output");
362
+ var DEFAULT_OUTPUT_ARTIFACT_RETENTION = {
363
+ maxAgeMs: 7 * 24 * 60 * 60 * 1e3,
364
+ maxBytes: 256 * 1024 * 1024
365
+ };
366
+ var OUTPUT_ARTIFACT_SWEEP_INTERVAL_MS = 5 * 60 * 1e3;
367
+ var sweptAt;
368
+ var lastSweep;
369
+ var resetOutputArtifactSweepSchedule = () => {
370
+ sweptAt = void 0;
371
+ lastSweep = void 0;
372
+ };
373
+ var activeRetention = DEFAULT_OUTPUT_ARTIFACT_RETENTION;
374
+ var configureOutputArtifactRetention = (retention) => {
375
+ const changed = retention.maxAgeMs !== activeRetention.maxAgeMs || retention.maxBytes !== activeRetention.maxBytes;
376
+ activeRetention = { maxAgeMs: retention.maxAgeMs, maxBytes: retention.maxBytes };
377
+ if (changed) resetOutputArtifactSweepSchedule();
378
+ };
379
+ var ARTIFACT_FILE = /^output-[0-9a-z]+-(?:p([0-9a-z]+)-)?[0-9a-f]+\.txt$/;
380
+ var ownerAlive = (pid) => {
381
+ try {
382
+ process.kill(pid, 0);
383
+ return true;
384
+ } catch (error) {
385
+ return !(error instanceof Error && "code" in error && error.code === "ESRCH");
386
+ }
387
+ };
388
+ var sweepOutputArtifacts = async (options = {}) => {
389
+ const directory = options.directory ?? outputArtifactDir();
390
+ const retention = options.retention ?? activeRetention;
391
+ const now = options.now ?? Date.now();
392
+ const alive = options.isOwnerAlive ?? ownerAlive;
393
+ let names;
394
+ try {
395
+ names = await readdir(directory);
396
+ } catch {
397
+ return { removed: [], keptBytes: 0, heldBytes: 0, overBudgetBytes: 0 };
398
+ }
399
+ const candidates = [];
400
+ for (const name of names) {
401
+ const match = ARTIFACT_FILE.exec(name);
402
+ if (!match) continue;
403
+ const artifactPath = path.join(directory, name);
404
+ let info;
405
+ try {
406
+ info = await stat(artifactPath);
407
+ } catch {
408
+ continue;
409
+ }
410
+ if (!info.isFile()) continue;
411
+ const pid = match[1] === void 0 ? Number.NaN : Number.parseInt(match[1], 36);
412
+ candidates.push({
413
+ path: artifactPath,
414
+ bytes: info.size,
415
+ mtimeMs: info.mtimeMs,
416
+ held: Number.isInteger(pid) && pid > 0 && alive(pid)
417
+ });
418
+ }
419
+ candidates.sort((left, right) => left.mtimeMs - right.mtimeMs || left.path.localeCompare(right.path));
420
+ const removed = [];
421
+ const survivors = [];
422
+ let keptBytes = 0;
423
+ for (const candidate of candidates) {
424
+ if (!candidate.held && now - candidate.mtimeMs >= retention.maxAgeMs) {
425
+ try {
426
+ await rm(candidate.path, { force: true });
427
+ removed.push(candidate.path);
428
+ continue;
429
+ } catch {
430
+ }
431
+ }
432
+ survivors.push(candidate);
433
+ keptBytes += candidate.bytes;
434
+ }
435
+ for (const candidate of survivors) {
436
+ if (keptBytes <= retention.maxBytes) break;
437
+ if (candidate.held) continue;
438
+ try {
439
+ await rm(candidate.path, { force: true });
440
+ } catch {
441
+ continue;
442
+ }
443
+ removed.push(candidate.path);
444
+ keptBytes -= candidate.bytes;
445
+ }
446
+ let heldBytes = 0;
447
+ for (const candidate of survivors) {
448
+ if (candidate.held) heldBytes += candidate.bytes;
449
+ }
450
+ return {
451
+ removed,
452
+ keptBytes,
453
+ heldBytes,
454
+ overBudgetBytes: Math.max(0, keptBytes - retention.maxBytes)
455
+ };
456
+ };
457
+ var sweepOutputArtifactsIfDue = async (options = {}) => {
458
+ const now = options.now ?? Date.now();
459
+ const interval = options.intervalMs ?? OUTPUT_ARTIFACT_SWEEP_INTERVAL_MS;
460
+ if (sweptAt !== void 0 && now - sweptAt < interval) return void 0;
461
+ sweptAt = now;
462
+ const sweep = await sweepOutputArtifacts(options);
463
+ lastSweep = { ...sweep, at: now };
464
+ if (sweep.overBudgetBytes > 0) {
465
+ const cap = (options.retention ?? activeRetention).maxBytes;
466
+ console.warn(
467
+ `[omp-fabric] output artifacts keep ${sweep.keptBytes} bytes against a ${cap} byte cap; ${sweep.overBudgetBytes} bytes stay because ${sweep.heldBytes} bytes belong to running sessions`
468
+ );
469
+ }
470
+ return sweep;
471
+ };
472
+ var writeOutputArtifact = async (content) => {
473
+ const directory = outputArtifactDir();
474
+ await mkdir(directory, { recursive: true, mode: 448 });
475
+ const artifactPath = path.join(
476
+ directory,
477
+ `output-${Date.now().toString(36)}-p${process.pid.toString(36)}-${randomBytes(6).toString("hex")}.txt`
478
+ );
479
+ await writeFile(artifactPath, content, { encoding: "utf8", mode: 384 });
480
+ try {
481
+ await sweepOutputArtifactsIfDue({ directory });
482
+ } catch {
483
+ }
484
+ return artifactPath;
485
+ };
486
+ var MAX_ARTIFACT_FAILURE_REASON_CHARS = 160;
487
+ var artifactFailureReason = (error) => {
488
+ const raw = error instanceof Error ? error.message : String(error);
489
+ const flattened = raw.replace(/\s+/g, " ").trim();
490
+ if (!flattened) return "unknown error";
491
+ return flattened.length <= MAX_ARTIFACT_FAILURE_REASON_CHARS ? flattened : `${flattened.slice(0, MAX_ARTIFACT_FAILURE_REASON_CHARS - 1)}\u2026`;
492
+ };
493
+ var boundModelOutput = async (visible, maxChars, fullOutput = visible, writeArtifact = writeOutputArtifact) => {
494
+ if (visible.length <= maxChars && fullOutput.length <= maxChars) {
495
+ return { text: visible, originalChars: fullOutput.length, omittedChars: 0 };
496
+ }
497
+ let artifactPath;
498
+ let failureReason;
499
+ try {
500
+ artifactPath = await writeArtifact(fullOutput);
501
+ } catch (error) {
502
+ failureReason = artifactFailureReason(error);
503
+ }
504
+ const suffix = artifactPath ? `
505
+
506
+ [Full output (${fullOutput.length} chars) saved to: ${artifactPath}]` : `
507
+
508
+ [full output ${fullOutput.length} chars; overflow could not be saved: ${failureReason}]`;
509
+ const bodyBudget = Math.max(1, maxChars - suffix.length);
510
+ const body = truncateMiddle(visible, bodyBudget);
511
+ const combined = `${body}${suffix}`;
512
+ return {
513
+ text: combined.length <= maxChars ? combined : truncateMiddle(combined, maxChars),
514
+ ...artifactPath ? { artifactPath } : {},
515
+ originalChars: fullOutput.length,
516
+ omittedChars: Math.max(0, fullOutput.length - Math.min(fullOutput.length, body.length))
517
+ };
518
+ };
519
+
350
520
  // src/config.ts
351
521
  var MIN_COMPACTION_TOKEN_THRESHOLD = 1e3;
352
522
  var MAX_COMPACTION_TOKEN_THRESHOLD = 1e8;
@@ -360,6 +530,28 @@ var clampCompactionRatioThreshold = (value) => Math.min(
360
530
  MAX_COMPACTION_RATIO_THRESHOLD,
361
531
  Math.max(MIN_COMPACTION_RATIO_THRESHOLD, value)
362
532
  );
533
+ var MIN_SOFT_THRESHOLD_RATIO = 0.1;
534
+ var MAX_SOFT_THRESHOLD_RATIO = 0.95;
535
+ var MIN_HARD_THRESHOLD_RATIO = 0.2;
536
+ var MAX_HARD_THRESHOLD_RATIO = 0.98;
537
+ var SOFT_BELOW_HARD_MARGIN = 0.05;
538
+ var clampSoftThresholdRatio = (value) => value <= 0 ? 0 : Math.min(MAX_SOFT_THRESHOLD_RATIO, Math.max(MIN_SOFT_THRESHOLD_RATIO, value));
539
+ var THRESHOLD_RATIO_STEPS_PER_UNIT = 20;
540
+ var roundThresholdRatio = (value) => Math.round(value * THRESHOLD_RATIO_STEPS_PER_UNIT) / THRESHOLD_RATIO_STEPS_PER_UNIT;
541
+ var clampHardThresholdRatio = (value) => value <= 0 ? 0 : Math.min(MAX_HARD_THRESHOLD_RATIO, Math.max(MIN_HARD_THRESHOLD_RATIO, value));
542
+ var reconcileThresholdRatios = (soft, hard) => {
543
+ const clampedHard = clampHardThresholdRatio(hard);
544
+ const clampedSoft = clampSoftThresholdRatio(soft);
545
+ if (clampedHard > 0 && clampedSoft > 0 && clampedSoft >= clampedHard) {
546
+ return {
547
+ soft: clampSoftThresholdRatio(
548
+ roundThresholdRatio(clampedHard - SOFT_BELOW_HARD_MARGIN)
549
+ ),
550
+ hard: clampedHard
551
+ };
552
+ }
553
+ return { soft: clampedSoft, hard: clampedHard };
554
+ };
363
555
  var MAX_EXECUTOR_TIMEOUT_MS = 24 * 36e5;
364
556
  var MIN_AGENT_TIMEOUT_MS = 1e3;
365
557
  var DEFAULT_AGENT_TIMEOUT_MS = 36e5;
@@ -473,6 +665,8 @@ var DEFAULT_FABRIC_CONFIG = {
473
665
  compaction: {
474
666
  engine: "lcm",
475
667
  targetContextRatio: 0.75,
668
+ softThresholdRatio: 0.55,
669
+ hardThresholdRatio: 0,
476
670
  thresholds: {},
477
671
  tokenThresholds: {},
478
672
  lcmMaxInputChars: 2e5,
@@ -490,7 +684,9 @@ var DEFAULT_FABRIC_CONFIG = {
490
684
  retention: {
491
685
  orphanedTempRunMs: 6 * 60 * 60 * 1e3,
492
686
  oneShotRunMs: 24 * 60 * 60 * 1e3,
493
- actorRunArchiveMs: 7 * 24 * 60 * 60 * 1e3
687
+ actorRunArchiveMs: 7 * 24 * 60 * 60 * 1e3,
688
+ outputArtifactMs: DEFAULT_OUTPUT_ARTIFACT_RETENTION.maxAgeMs,
689
+ outputArtifactMaxBytes: DEFAULT_OUTPUT_ARTIFACT_RETENTION.maxBytes
494
690
  },
495
691
  mesh: {
496
692
  enabled: true,
@@ -656,6 +852,10 @@ var normalizeFabricConfig = (input) => {
656
852
  clampCompactionTokenThreshold(tokens)
657
853
  ])
658
854
  );
855
+ const thresholdRatios = reconcileThresholdRatios(
856
+ typeof compaction.softThresholdRatio === "number" && Number.isFinite(compaction.softThresholdRatio) ? compaction.softThresholdRatio : DEFAULT_FABRIC_CONFIG.compaction.softThresholdRatio,
857
+ typeof compaction.hardThresholdRatio === "number" && Number.isFinite(compaction.hardThresholdRatio) ? compaction.hardThresholdRatio : DEFAULT_FABRIC_CONFIG.compaction.hardThresholdRatio
858
+ );
659
859
  const prewalkModel = stringValue(prewalk.model);
660
860
  const prewalkThinking = isFabricThinking(prewalk.thinking) ? prewalk.thinking : void 0;
661
861
  const agentModel = stringValue(agents.model);
@@ -975,6 +1175,8 @@ var normalizeFabricConfig = (input) => {
975
1175
  0.25,
976
1176
  0.85
977
1177
  ),
1178
+ softThresholdRatio: thresholdRatios.soft,
1179
+ hardThresholdRatio: thresholdRatios.hard,
978
1180
  thresholds: compactionThresholds,
979
1181
  tokenThresholds: compactionTokenThresholds,
980
1182
  lcmMaxInputChars: boundedInteger(compaction.lcmMaxInputChars, DEFAULT_FABRIC_CONFIG.compaction.lcmMaxInputChars, 1024, 1e6),
@@ -1007,6 +1209,18 @@ var normalizeFabricConfig = (input) => {
1007
1209
  DEFAULT_FABRIC_CONFIG.retention.actorRunArchiveMs,
1008
1210
  60 * 60 * 1e3,
1009
1211
  365 * 24 * 60 * 60 * 1e3
1212
+ ),
1213
+ outputArtifactMs: boundedInteger(
1214
+ retention.outputArtifactMs,
1215
+ DEFAULT_FABRIC_CONFIG.retention.outputArtifactMs,
1216
+ 60 * 60 * 1e3,
1217
+ 365 * 24 * 60 * 60 * 1e3
1218
+ ),
1219
+ outputArtifactMaxBytes: boundedInteger(
1220
+ retention.outputArtifactMaxBytes,
1221
+ DEFAULT_FABRIC_CONFIG.retention.outputArtifactMaxBytes,
1222
+ 1024 * 1024,
1223
+ 64 * 1024 * 1024 * 1024
1010
1224
  )
1011
1225
  },
1012
1226
  mesh: {
@@ -1246,12 +1460,12 @@ var planConfigFile = (filePath) => {
1246
1460
  };
1247
1461
  var writeJsonAtomic = (filePath, document, expectedSource) => {
1248
1462
  const resolvedPath = fs.existsSync(filePath) ? fs.realpathSync(filePath) : filePath;
1249
- const directory = path.dirname(resolvedPath);
1463
+ const directory = path2.dirname(resolvedPath);
1250
1464
  if (!fs.existsSync(directory)) fs.mkdirSync(directory, { recursive: true });
1251
1465
  const mode = fs.existsSync(resolvedPath) ? fs.statSync(resolvedPath).mode & 511 : 384;
1252
- const temporaryPath = path.join(
1466
+ const temporaryPath = path2.join(
1253
1467
  directory,
1254
- `.${path.basename(resolvedPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`
1468
+ `.${path2.basename(resolvedPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`
1255
1469
  );
1256
1470
  let descriptor;
1257
1471
  try {
@@ -1297,8 +1511,8 @@ var writeJsonAtomic = (filePath, document, expectedSource) => {
1297
1511
  var resolveFabricConfig = (options, includeProject, applyEnvironmentOverrides) => {
1298
1512
  let merged = structuredClone(DEFAULT_FABRIC_CONFIG);
1299
1513
  const plans = [
1300
- planConfigFile(path.join(options.agentDir, "fabric.json")),
1301
- ...includeProject ? [planConfigFile(path.join(options.cwd, ".omp", "fabric.json"))] : []
1514
+ planConfigFile(path2.join(options.agentDir, "fabric.json")),
1515
+ ...includeProject ? [planConfigFile(path2.join(options.cwd, ".omp", "fabric.json"))] : []
1302
1516
  ].filter((plan) => plan !== void 0);
1303
1517
  for (const plan of plans) {
1304
1518
  if (plan.changed) writeJsonAtomic(plan.path, plan.document, plan.source);
@@ -1318,6 +1532,10 @@ var loadFabricConfigForScope = (options, scope) => {
1318
1532
  };
1319
1533
  var loadFabricConfig = (options) => {
1320
1534
  const config = resolveFabricConfig(options, options.projectTrusted, true);
1535
+ configureOutputArtifactRetention({
1536
+ maxAgeMs: config.retention.outputArtifactMs,
1537
+ maxBytes: config.retention.outputArtifactMaxBytes
1538
+ });
1321
1539
  return config;
1322
1540
  };
1323
1541
  var saveFabricConfig = (options, partial) => {
@@ -1325,7 +1543,7 @@ var saveFabricConfig = (options, partial) => {
1325
1543
  if (scope === "project" && !options.projectTrusted) {
1326
1544
  throw new Error("Cannot save project Fabric configuration for an untrusted project");
1327
1545
  }
1328
- const targetPath = scope === "project" ? path.join(options.cwd, ".omp", "fabric.json") : path.join(options.agentDir, "fabric.json");
1546
+ const targetPath = scope === "project" ? path2.join(options.cwd, ".omp", "fabric.json") : path2.join(options.agentDir, "fabric.json");
1329
1547
  if (Object.hasOwn(partial, "configVersion") || Object.hasOwn(partial, "subagents")) {
1330
1548
  throw new Error("Fabric configuration updates must use the current schema");
1331
1549
  }
@@ -1341,7 +1559,7 @@ var saveFabricConfig = (options, partial) => {
1341
1559
  };
1342
1560
 
1343
1561
  // src/core/agent-dir.ts
1344
- import path2 from "node:path";
1562
+ import path3 from "node:path";
1345
1563
  import { fileURLToPath } from "node:url";
1346
1564
  import { homedir } from "node:os";
1347
1565
  import { getAgentDir } from "@oh-my-pi/pi-utils";
@@ -1349,7 +1567,7 @@ var expandEnvDir = (envDir) => {
1349
1567
  if (/^file:\/\//.test(envDir)) return fileURLToPath(envDir);
1350
1568
  if (envDir === "~") return homedir();
1351
1569
  if (envDir.startsWith("~/") || process.platform === "win32" && envDir.startsWith("~\\")) {
1352
- return path2.join(homedir(), envDir.slice(2));
1570
+ return path3.join(homedir(), envDir.slice(2));
1353
1571
  }
1354
1572
  return envDir;
1355
1573
  };
@@ -1364,6 +1582,8 @@ export {
1364
1582
  normalizeModelAliases,
1365
1583
  resolveFabricModel,
1366
1584
  resolveAvailableOmpModel,
1585
+ modelOutputBudget,
1586
+ boundModelOutput,
1367
1587
  MIN_COMPACTION_TOKEN_THRESHOLD,
1368
1588
  MAX_COMPACTION_TOKEN_THRESHOLD,
1369
1589
  MIN_COMPACTION_RATIO_THRESHOLD,
@@ -1381,4 +1601,4 @@ export {
1381
1601
  saveFabricConfig,
1382
1602
  resolveAgentDir
1383
1603
  };
1384
- //# sourceMappingURL=chunk-Z7HQ6FYW.js.map
1604
+ //# sourceMappingURL=chunk-ANAXFBUE.js.map