oh-my-opencode 4.6.0 → 4.7.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 (75) hide show
  1. package/bin/version-mismatch.js +47 -0
  2. package/bin/version-mismatch.test.ts +120 -0
  3. package/dist/cli/codex-ulw-loop.d.ts +12 -0
  4. package/dist/cli/doctor/checks/tui-plugin-config.d.ts +2 -0
  5. package/dist/cli/index.js +577 -304
  6. package/dist/cli/install-codex/codex-config-reasoning.d.ts +2 -1
  7. package/dist/cli/install-codex/codex-model-catalog.d.ts +13 -0
  8. package/dist/features/background-agent/concurrency.d.ts +1 -0
  9. package/dist/features/background-agent/process-cleanup.d.ts +6 -0
  10. package/dist/features/claude-code-session-state/state.d.ts +1 -0
  11. package/dist/features/opencode-skill-loader/index.d.ts +1 -0
  12. package/dist/features/opencode-skill-loader/opencode-config-skills-reader.d.ts +5 -0
  13. package/dist/features/tmux-subagent/attachable-session-status.d.ts +1 -1
  14. package/dist/features/tmux-subagent/session-status-parser.d.ts +1 -0
  15. package/dist/hooks/comment-checker/cli.d.ts +1 -0
  16. package/dist/hooks/tasks-todowrite-disabler/constants.d.ts +1 -1
  17. package/dist/index.js +811 -450
  18. package/dist/shared/command-executor/execute-hook-command.d.ts +2 -0
  19. package/dist/tools/skill/description-formatter.d.ts +5 -1
  20. package/dist/tools/skill/types.d.ts +1 -0
  21. package/package.json +12 -13
  22. package/packages/ast-grep-mcp/dist/cli.js +53 -9
  23. package/packages/lsp-tools-mcp/dist/lsp/process.js +1 -1
  24. package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus.md +6 -4
  25. package/packages/omo-codex/plugin/components/rules/src/post-compact-budget.ts +0 -2
  26. package/packages/omo-codex/plugin/components/start-work-continuation/directive.md +1 -1
  27. package/packages/omo-codex/plugin/components/ultrawork/CHANGELOG.md +1 -1
  28. package/packages/omo-codex/plugin/components/ultrawork/README.md +1 -1
  29. package/packages/omo-codex/plugin/components/ultrawork/agents/codex-ultrawork-reviewer.toml +3 -1
  30. package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +7 -7
  31. package/packages/omo-codex/plugin/components/ultrawork/directive.md +1 -1
  32. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +5 -4
  33. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +4 -3
  34. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +12 -1
  35. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint.test.ts +19 -1
  36. package/packages/omo-codex/plugin/hooks/hooks.json +11 -0
  37. package/packages/omo-codex/plugin/model-catalog.json +49 -0
  38. package/packages/omo-codex/plugin/scripts/auto-update.mjs +159 -0
  39. package/packages/omo-codex/plugin/scripts/migrate-codex-config.mjs +269 -0
  40. package/packages/omo-codex/plugin/scripts/sync-hook-status-messages.mjs +3 -1
  41. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +6 -6
  42. package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +6 -6
  43. package/packages/omo-codex/plugin/skills/lcx-report-bug/SKILL.md +127 -0
  44. package/packages/omo-codex/plugin/skills/lcx-report-bug/agents/openai.yaml +9 -0
  45. package/packages/omo-codex/plugin/skills/refactor/SKILL.md +6 -6
  46. package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +6 -6
  47. package/packages/omo-codex/plugin/skills/review-work/SKILL.md +7 -7
  48. package/packages/omo-codex/plugin/skills/start-work/SKILL.md +6 -6
  49. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +5 -4
  50. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +4 -3
  51. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +17 -17
  52. package/packages/omo-codex/plugin/test/aggregate.test.mjs +172 -19
  53. package/packages/omo-codex/plugin/test/auto-update.test.mjs +129 -0
  54. package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +2 -0
  55. package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +146 -0
  56. package/packages/omo-codex/plugin/test/sync-hook-status-messages.test.mjs +1 -0
  57. package/packages/omo-codex/plugin/test/sync-skills.test.mjs +22 -0
  58. package/packages/omo-codex/scripts/install/cli-args.mjs +1 -1
  59. package/packages/omo-codex/scripts/install/config.mjs +2 -15
  60. package/packages/omo-codex/scripts/install/delegated-command.mjs +1 -1
  61. package/packages/omo-codex/scripts/install/legacy-bins.mjs +1 -0
  62. package/packages/omo-codex/scripts/install/model-catalog.mjs +66 -0
  63. package/packages/omo-codex/scripts/install/reasoning-config.mjs +65 -7
  64. package/packages/omo-codex/scripts/install-bin-links.test.mjs +23 -0
  65. package/packages/omo-codex/scripts/install-config-reasoning.test.mjs +82 -3
  66. package/packages/omo-codex/scripts/install-config.test.mjs +5 -6
  67. package/packages/omo-codex/scripts/install-local-entrypoint.test.mjs +30 -2
  68. package/packages/omo-codex/scripts/install-local.mjs +1 -1
  69. package/packages/shared-skills/skills/lcx-report-bug/SKILL.md +127 -0
  70. package/packages/shared-skills/skills/lcx-report-bug/agents/openai.yaml +9 -0
  71. package/packages/shared-skills/skills/review-work/SKILL.md +7 -7
  72. package/packages/shared-skills/skills/start-work/SKILL.md +6 -6
  73. package/packages/shared-skills/skills/ulw-plan/SKILL.md +11 -11
  74. package/postinstall.mjs +36 -3
  75. package/dist/cli/install-codex/codex-config-mcp.d.ts +0 -1
package/dist/index.js CHANGED
@@ -4503,6 +4503,7 @@ import { spawn } from "child_process";
4503
4503
  async function executeHookCommand(command, stdin, cwd, options) {
4504
4504
  const home = getHomeDirectory();
4505
4505
  const timeoutMs = options?.timeoutMs ?? DEFAULT_HOOK_TIMEOUT_MS;
4506
+ const killGraceMs = options?.killGraceMs ?? SIGKILL_GRACE_MS;
4506
4507
  const expandedCommand = command.replace(/^~(?=\/|$)/g, home).replace(/\s~(?=\/)/g, ` ${home}`).replace(/\$CLAUDE_PROJECT_DIR/g, cwd).replace(/\$\{CLAUDE_PROJECT_DIR\}/g, cwd);
4507
4508
  let finalCommand = expandedCommand;
4508
4509
  if (options?.forceZsh) {
@@ -4519,6 +4520,7 @@ async function executeHookCommand(command, stdin, cwd, options) {
4519
4520
  }
4520
4521
  return new Promise((resolve2) => {
4521
4522
  let settled = false;
4523
+ let timedOut = false;
4522
4524
  let killTimer = null;
4523
4525
  const isWin32 = process.platform === "win32";
4524
4526
  const PROTECTED_ENV_KEYS = new Set(["HOME", "CLAUDE_PROJECT_DIR"]);
@@ -4566,6 +4568,15 @@ async function executeHookCommand(command, stdin, cwd, options) {
4566
4568
  resolve2(result);
4567
4569
  };
4568
4570
  proc.on("close", (code) => {
4571
+ if (timedOut) {
4572
+ appendTimeoutNotice();
4573
+ settle({
4574
+ exitCode: 124,
4575
+ stdout: stdout.trim(),
4576
+ stderr: stderr.trim()
4577
+ });
4578
+ return;
4579
+ }
4569
4580
  settle({
4570
4581
  exitCode: code ?? 1,
4571
4582
  stdout: stdout.trim(),
@@ -4575,6 +4586,19 @@ async function executeHookCommand(command, stdin, cwd, options) {
4575
4586
  proc.on("error", (err) => {
4576
4587
  settle({ exitCode: 1, stderr: err.message });
4577
4588
  });
4589
+ const killWindowsProcessTree = (onComplete) => {
4590
+ if (!proc.pid) {
4591
+ onComplete?.();
4592
+ return;
4593
+ }
4594
+ const killer = spawn("taskkill", ["/PID", String(proc.pid), "/T", "/F"], {
4595
+ windowsHide: true,
4596
+ stdio: "ignore"
4597
+ });
4598
+ const finish = () => onComplete?.();
4599
+ killer.on("error", finish);
4600
+ killer.on("close", finish);
4601
+ };
4578
4602
  const killProcessGroup = (signal) => {
4579
4603
  try {
4580
4604
  if (!isWin32 && proc.pid) {
@@ -4585,20 +4609,57 @@ async function executeHookCommand(command, stdin, cwd, options) {
4585
4609
  }
4586
4610
  } else {
4587
4611
  proc.kill(signal);
4612
+ if (signal === "SIGKILL") {
4613
+ killWindowsProcessTree();
4614
+ }
4588
4615
  }
4589
4616
  } catch {}
4590
4617
  };
4618
+ const appendTimeoutNotice = () => {
4619
+ if (!stderr.includes("Hook command timed out after")) {
4620
+ stderr += `
4621
+ Hook command timed out after ${timeoutMs}ms`;
4622
+ }
4623
+ };
4591
4624
  const timeoutTimer = setTimeout(() => {
4592
4625
  if (settled)
4593
4626
  return;
4627
+ timedOut = true;
4628
+ appendTimeoutNotice();
4629
+ if (isWin32) {
4630
+ killWindowsProcessTree(() => {
4631
+ settle({
4632
+ exitCode: 124,
4633
+ stdout: stdout.trim(),
4634
+ stderr: stderr.trim()
4635
+ });
4636
+ });
4637
+ return;
4638
+ }
4594
4639
  killProcessGroup("SIGTERM");
4595
4640
  killTimer = setTimeout(() => {
4596
4641
  if (settled)
4597
4642
  return;
4643
+ if (isWin32) {
4644
+ killWindowsProcessTree(() => {
4645
+ settle({
4646
+ exitCode: 124,
4647
+ stdout: stdout.trim(),
4648
+ stderr: stderr.trim()
4649
+ });
4650
+ });
4651
+ return;
4652
+ }
4598
4653
  killProcessGroup("SIGKILL");
4599
- }, SIGKILL_GRACE_MS);
4600
- stderr += `
4601
- Hook command timed out after ${timeoutMs}ms`;
4654
+ settle({
4655
+ exitCode: 124,
4656
+ stdout: stdout.trim(),
4657
+ stderr: stderr.trim()
4658
+ });
4659
+ }, killGraceMs);
4660
+ if (killTimer && typeof killTimer === "object" && "unref" in killTimer) {
4661
+ killTimer.unref();
4662
+ }
4602
4663
  }, timeoutMs);
4603
4664
  if (timeoutTimer && typeof timeoutTimer === "object" && "unref" in timeoutTimer) {
4604
4665
  timeoutTimer.unref();
@@ -4965,8 +5026,8 @@ var init_model_requirements = __esm(() => {
4965
5026
  { providers: ["opencode-go"], model: "qwen3.5-plus" },
4966
5027
  { providers: ["vercel"], model: "minimax-m2.7-highspeed" },
4967
5028
  { providers: ["opencode-go", "vercel"], model: "minimax-m2.7" },
4968
- { providers: ["anthropic", "opencode", "vercel"], model: "claude-haiku-4-5" },
4969
- { providers: ["openai", "opencode", "vercel"], model: "gpt-5.4-nano" }
5029
+ { providers: ["anthropic", "vercel"], model: "claude-haiku-4-5" },
5030
+ { providers: ["openai", "vercel"], model: "gpt-5.4-nano" }
4970
5031
  ]
4971
5032
  },
4972
5033
  explore: {
@@ -4975,8 +5036,8 @@ var init_model_requirements = __esm(() => {
4975
5036
  { providers: ["opencode-go"], model: "qwen3.5-plus" },
4976
5037
  { providers: ["vercel"], model: "minimax-m2.7-highspeed" },
4977
5038
  { providers: ["opencode-go", "vercel"], model: "minimax-m2.7" },
4978
- { providers: ["anthropic", "opencode", "vercel"], model: "claude-haiku-4-5" },
4979
- { providers: ["openai", "opencode", "vercel"], model: "gpt-5.4-nano" }
5039
+ { providers: ["anthropic", "vercel"], model: "claude-haiku-4-5" },
5040
+ { providers: ["openai", "vercel"], model: "gpt-5.4-nano" }
4980
5041
  ]
4981
5042
  },
4982
5043
  "multimodal-looker": {
@@ -5155,7 +5216,7 @@ var init_model_requirements = __esm(() => {
5155
5216
  model: "gpt-5.4-mini"
5156
5217
  },
5157
5218
  {
5158
- providers: ["anthropic", "github-copilot", "opencode", "vercel"],
5219
+ providers: ["anthropic", "github-copilot", "vercel"],
5159
5220
  model: "claude-haiku-4-5"
5160
5221
  },
5161
5222
  {
@@ -5432,7 +5493,7 @@ var init_model_capability_heuristics = __esm(() => {
5432
5493
  },
5433
5494
  {
5434
5495
  family: "kimi",
5435
- includes: ["kimi", "k2"],
5496
+ pattern: /(?:kimi|k2(?![-.]?p\d))/,
5436
5497
  variants: ["low", "medium", "high"],
5437
5498
  supportsThinking: false
5438
5499
  },
@@ -5673,7 +5734,7 @@ function claudeVersionDot(model) {
5673
5734
  function applyGatewayTransforms(model) {
5674
5735
  return claudeVersionDot(model).replace(GEMINI_31_PRO_PREVIEW, "gemini-3.1-pro-preview");
5675
5736
  }
5676
- function transformModelForProviderUsingAnthropicBehavior(provider, model, directAnthropicTransform) {
5737
+ function transformModelForProviderUsingAnthropicBehavior(provider, model) {
5677
5738
  if (provider === "vercel") {
5678
5739
  const slashIndex = model.indexOf("/");
5679
5740
  if (slashIndex !== -1) {
@@ -5694,12 +5755,12 @@ function transformModelForProviderUsingAnthropicBehavior(provider, model, direct
5694
5755
  return model.replace(GEMINI_31_PRO_PREVIEW, "gemini-3.1-pro-preview").replace(GEMINI_3_FLASH_PREVIEW, "gemini-3-flash-preview");
5695
5756
  }
5696
5757
  if (provider === "anthropic") {
5697
- return directAnthropicTransform(model);
5758
+ return model;
5698
5759
  }
5699
5760
  return model;
5700
5761
  }
5701
5762
  function transformModelForProvider(provider, model) {
5702
- return transformModelForProviderUsingAnthropicBehavior(provider, model, claudeVersionDot);
5763
+ return transformModelForProviderUsingAnthropicBehavior(provider, model);
5703
5764
  }
5704
5765
  var CLAUDE_VERSION_DOT, GEMINI_31_PRO_PREVIEW, GEMINI_3_FLASH_PREVIEW;
5705
5766
  var init_provider_model_id_transform = __esm(() => {
@@ -8736,8 +8797,30 @@ function resolveConfigPath(pathValue) {
8736
8797
  return resolvedPath;
8737
8798
  }
8738
8799
  }
8800
+ function isWslEnvironment() {
8801
+ return process.platform === "linux" && (Boolean(process.env.WSL_DISTRO_NAME?.trim()) || Boolean(process.env.WSL_INTEROP?.trim()));
8802
+ }
8803
+ function isWindowsUserConfigRoot(pathValue) {
8804
+ const normalizedPath = pathValue.replaceAll("\\", "/").toLowerCase();
8805
+ return /^[a-z]:\/users\//.test(normalizedPath) || /^\/mnt\/[a-z]\/users\//.test(normalizedPath);
8806
+ }
8807
+ function getWindowsUserFromConfigRoot(pathValue) {
8808
+ const normalizedPath = pathValue.replaceAll("\\", "/");
8809
+ const match = /^(?:[a-z]:|\/mnt\/[a-z])\/Users\/([^/]+)/i.exec(normalizedPath);
8810
+ return match?.[1] ?? null;
8811
+ }
8812
+ function getWslLinuxHomeDir(windowsConfigRoot) {
8813
+ const envHome = process.env.HOME?.trim();
8814
+ if (envHome && envHome.startsWith("/") && !isWindowsUserConfigRoot(envHome)) {
8815
+ return envHome;
8816
+ }
8817
+ const user = process.env.USER?.trim() || process.env.LOGNAME?.trim() || process.env.SUDO_USER?.trim() || (windowsConfigRoot ? getWindowsUserFromConfigRoot(windowsConfigRoot) : undefined);
8818
+ return user ? join6("/home", user) : null;
8819
+ }
8739
8820
  function getCliDefaultConfigDir() {
8740
- const xdgConfig = process.env.XDG_CONFIG_HOME || join6(homedir5(), ".config");
8821
+ const envXdgConfig = process.env.XDG_CONFIG_HOME?.trim();
8822
+ const shouldIgnoreWindowsXdg = envXdgConfig !== undefined && envXdgConfig.length > 0 && isWslEnvironment() && isWindowsUserConfigRoot(envXdgConfig);
8823
+ const xdgConfig = shouldIgnoreWindowsXdg ? join6(getWslLinuxHomeDir(envXdgConfig) ?? "/home", ".config") : envXdgConfig || join6(homedir5(), ".config");
8741
8824
  return resolveConfigPath(join6(xdgConfig, "opencode"));
8742
8825
  }
8743
8826
  function getCliCustomConfigDir() {
@@ -54030,7 +54113,7 @@ function buildTmuxAttachCommand(serverUrl, sessionId, directory = process.cwd())
54030
54113
  }
54031
54114
  function buildTmuxPlaceholderCommand(description) {
54032
54115
  const escapedDescription = shellEscapeForDoubleQuotedCommand(description);
54033
- return `${TMUX_COMMAND_SHELL} -c "printf '%s\\n%s\\n' "OMO subagent pane ready: ${escapedDescription}" "Focus this pane to attach."; while :; do sleep 86400; done"`;
54116
+ return `${TMUX_COMMAND_SHELL} -c "printf '%s\\n%s\\n' \\"OMO subagent pane ready: ${escapedDescription}\\" \\"Focus this pane to attach.\\"; while :; do sleep 86400; done"`;
54034
54117
  }
54035
54118
  var TMUX_COMMAND_SHELL = "/bin/sh";
54036
54119
  var init_pane_command = () => {};
@@ -64082,8 +64165,8 @@ var require_utils2 = __commonJS((exports, module) => {
64082
64165
  }
64083
64166
  return ind;
64084
64167
  }
64085
- function removeDotSegments(path21) {
64086
- let input = path21;
64168
+ function removeDotSegments(path22) {
64169
+ let input = path22;
64087
64170
  const output = [];
64088
64171
  let nextSlash = -1;
64089
64172
  let len = 0;
@@ -64326,8 +64409,8 @@ var require_schemes = __commonJS((exports, module) => {
64326
64409
  wsComponent.secure = undefined;
64327
64410
  }
64328
64411
  if (wsComponent.resourceName) {
64329
- const [path21, query] = wsComponent.resourceName.split("?");
64330
- wsComponent.path = path21 && path21 !== "/" ? path21 : undefined;
64412
+ const [path22, query] = wsComponent.resourceName.split("?");
64413
+ wsComponent.path = path22 && path22 !== "/" ? path22 : undefined;
64331
64414
  wsComponent.query = query;
64332
64415
  wsComponent.resourceName = undefined;
64333
64416
  }
@@ -67502,12 +67585,12 @@ var require_dist = __commonJS((exports, module) => {
67502
67585
  throw new Error(`Unknown format "${name}"`);
67503
67586
  return f;
67504
67587
  };
67505
- function addFormats(ajv, list, fs22, exportName) {
67588
+ function addFormats(ajv, list, fs23, exportName) {
67506
67589
  var _a;
67507
67590
  var _b;
67508
67591
  (_a = (_b = ajv.opts.code).formats) !== null && _a !== undefined || (_b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`);
67509
67592
  for (const f of list)
67510
- ajv.addFormat(f, fs22[f]);
67593
+ ajv.addFormat(f, fs23[f]);
67511
67594
  }
67512
67595
  module.exports = exports = formatsPlugin;
67513
67596
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -67518,8 +67601,8 @@ var require_dist = __commonJS((exports, module) => {
67518
67601
  var require_windows = __commonJS((exports, module) => {
67519
67602
  module.exports = isexe;
67520
67603
  isexe.sync = sync;
67521
- var fs22 = __require("fs");
67522
- function checkPathExt(path21, options) {
67604
+ var fs23 = __require("fs");
67605
+ function checkPathExt(path22, options) {
67523
67606
  var pathext = options.pathExt !== undefined ? options.pathExt : process.env.PATHEXT;
67524
67607
  if (!pathext) {
67525
67608
  return true;
@@ -67530,25 +67613,25 @@ var require_windows = __commonJS((exports, module) => {
67530
67613
  }
67531
67614
  for (var i2 = 0;i2 < pathext.length; i2++) {
67532
67615
  var p = pathext[i2].toLowerCase();
67533
- if (p && path21.substr(-p.length).toLowerCase() === p) {
67616
+ if (p && path22.substr(-p.length).toLowerCase() === p) {
67534
67617
  return true;
67535
67618
  }
67536
67619
  }
67537
67620
  return false;
67538
67621
  }
67539
- function checkStat(stat7, path21, options) {
67622
+ function checkStat(stat7, path22, options) {
67540
67623
  if (!stat7.isSymbolicLink() && !stat7.isFile()) {
67541
67624
  return false;
67542
67625
  }
67543
- return checkPathExt(path21, options);
67626
+ return checkPathExt(path22, options);
67544
67627
  }
67545
- function isexe(path21, options, cb) {
67546
- fs22.stat(path21, function(er, stat7) {
67547
- cb(er, er ? false : checkStat(stat7, path21, options));
67628
+ function isexe(path22, options, cb) {
67629
+ fs23.stat(path22, function(er, stat7) {
67630
+ cb(er, er ? false : checkStat(stat7, path22, options));
67548
67631
  });
67549
67632
  }
67550
- function sync(path21, options) {
67551
- return checkStat(fs22.statSync(path21), path21, options);
67633
+ function sync(path22, options) {
67634
+ return checkStat(fs23.statSync(path22), path22, options);
67552
67635
  }
67553
67636
  });
67554
67637
 
@@ -67556,14 +67639,14 @@ var require_windows = __commonJS((exports, module) => {
67556
67639
  var require_mode = __commonJS((exports, module) => {
67557
67640
  module.exports = isexe;
67558
67641
  isexe.sync = sync;
67559
- var fs22 = __require("fs");
67560
- function isexe(path21, options, cb) {
67561
- fs22.stat(path21, function(er, stat7) {
67642
+ var fs23 = __require("fs");
67643
+ function isexe(path22, options, cb) {
67644
+ fs23.stat(path22, function(er, stat7) {
67562
67645
  cb(er, er ? false : checkStat(stat7, options));
67563
67646
  });
67564
67647
  }
67565
- function sync(path21, options) {
67566
- return checkStat(fs22.statSync(path21), options);
67648
+ function sync(path22, options) {
67649
+ return checkStat(fs23.statSync(path22), options);
67567
67650
  }
67568
67651
  function checkStat(stat7, options) {
67569
67652
  return stat7.isFile() && checkMode(stat7, options);
@@ -67585,7 +67668,7 @@ var require_mode = __commonJS((exports, module) => {
67585
67668
 
67586
67669
  // node_modules/.bun/isexe@2.0.0/node_modules/isexe/index.js
67587
67670
  var require_isexe = __commonJS((exports, module) => {
67588
- var fs22 = __require("fs");
67671
+ var fs23 = __require("fs");
67589
67672
  var core2;
67590
67673
  if (process.platform === "win32" || global.TESTING_WINDOWS) {
67591
67674
  core2 = require_windows();
@@ -67594,7 +67677,7 @@ var require_isexe = __commonJS((exports, module) => {
67594
67677
  }
67595
67678
  module.exports = isexe;
67596
67679
  isexe.sync = sync;
67597
- function isexe(path21, options, cb) {
67680
+ function isexe(path22, options, cb) {
67598
67681
  if (typeof options === "function") {
67599
67682
  cb = options;
67600
67683
  options = {};
@@ -67604,7 +67687,7 @@ var require_isexe = __commonJS((exports, module) => {
67604
67687
  throw new TypeError("callback not provided");
67605
67688
  }
67606
67689
  return new Promise(function(resolve25, reject) {
67607
- isexe(path21, options || {}, function(er, is) {
67690
+ isexe(path22, options || {}, function(er, is) {
67608
67691
  if (er) {
67609
67692
  reject(er);
67610
67693
  } else {
@@ -67613,7 +67696,7 @@ var require_isexe = __commonJS((exports, module) => {
67613
67696
  });
67614
67697
  });
67615
67698
  }
67616
- core2(path21, options || {}, function(er, is) {
67699
+ core2(path22, options || {}, function(er, is) {
67617
67700
  if (er) {
67618
67701
  if (er.code === "EACCES" || options && options.ignoreErrors) {
67619
67702
  er = null;
@@ -67623,9 +67706,9 @@ var require_isexe = __commonJS((exports, module) => {
67623
67706
  cb(er, is);
67624
67707
  });
67625
67708
  }
67626
- function sync(path21, options) {
67709
+ function sync(path22, options) {
67627
67710
  try {
67628
- return core2.sync(path21, options || {});
67711
+ return core2.sync(path22, options || {});
67629
67712
  } catch (er) {
67630
67713
  if (options && options.ignoreErrors || er.code === "EACCES") {
67631
67714
  return false;
@@ -67639,7 +67722,7 @@ var require_isexe = __commonJS((exports, module) => {
67639
67722
  // node_modules/.bun/which@2.0.2/node_modules/which/which.js
67640
67723
  var require_which = __commonJS((exports, module) => {
67641
67724
  var isWindows2 = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
67642
- var path21 = __require("path");
67725
+ var path22 = __require("path");
67643
67726
  var COLON = isWindows2 ? ";" : ":";
67644
67727
  var isexe = require_isexe();
67645
67728
  var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
@@ -67675,7 +67758,7 @@ var require_which = __commonJS((exports, module) => {
67675
67758
  return opt.all && found.length ? resolve25(found) : reject(getNotFoundError(cmd));
67676
67759
  const ppRaw = pathEnv[i2];
67677
67760
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
67678
- const pCmd = path21.join(pathPart, cmd);
67761
+ const pCmd = path22.join(pathPart, cmd);
67679
67762
  const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
67680
67763
  resolve25(subStep(p, i2, 0));
67681
67764
  });
@@ -67702,7 +67785,7 @@ var require_which = __commonJS((exports, module) => {
67702
67785
  for (let i2 = 0;i2 < pathEnv.length; i2++) {
67703
67786
  const ppRaw = pathEnv[i2];
67704
67787
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
67705
- const pCmd = path21.join(pathPart, cmd);
67788
+ const pCmd = path22.join(pathPart, cmd);
67706
67789
  const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
67707
67790
  for (let j = 0;j < pathExt.length; j++) {
67708
67791
  const cur = p + pathExt[j];
@@ -67743,7 +67826,7 @@ var require_path_key = __commonJS((exports, module) => {
67743
67826
 
67744
67827
  // node_modules/.bun/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/resolveCommand.js
67745
67828
  var require_resolveCommand = __commonJS((exports, module) => {
67746
- var path21 = __require("path");
67829
+ var path22 = __require("path");
67747
67830
  var which = require_which();
67748
67831
  var getPathKey = require_path_key();
67749
67832
  function resolveCommandAttempt(parsed, withoutPathExt) {
@@ -67760,7 +67843,7 @@ var require_resolveCommand = __commonJS((exports, module) => {
67760
67843
  try {
67761
67844
  resolved = which.sync(parsed.command, {
67762
67845
  path: env[getPathKey({ env })],
67763
- pathExt: withoutPathExt ? path21.delimiter : undefined
67846
+ pathExt: withoutPathExt ? path22.delimiter : undefined
67764
67847
  });
67765
67848
  } catch (e) {} finally {
67766
67849
  if (shouldSwitchCwd) {
@@ -67768,7 +67851,7 @@ var require_resolveCommand = __commonJS((exports, module) => {
67768
67851
  }
67769
67852
  }
67770
67853
  if (resolved) {
67771
- resolved = path21.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
67854
+ resolved = path22.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
67772
67855
  }
67773
67856
  return resolved;
67774
67857
  }
@@ -67813,8 +67896,8 @@ var require_shebang_command = __commonJS((exports, module) => {
67813
67896
  if (!match) {
67814
67897
  return null;
67815
67898
  }
67816
- const [path21, argument] = match[0].replace(/#! ?/, "").split(" ");
67817
- const binary2 = path21.split("/").pop();
67899
+ const [path22, argument] = match[0].replace(/#! ?/, "").split(" ");
67900
+ const binary2 = path22.split("/").pop();
67818
67901
  if (binary2 === "env") {
67819
67902
  return argument;
67820
67903
  }
@@ -67824,16 +67907,16 @@ var require_shebang_command = __commonJS((exports, module) => {
67824
67907
 
67825
67908
  // node_modules/.bun/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/readShebang.js
67826
67909
  var require_readShebang = __commonJS((exports, module) => {
67827
- var fs22 = __require("fs");
67910
+ var fs23 = __require("fs");
67828
67911
  var shebangCommand = require_shebang_command();
67829
67912
  function readShebang(command) {
67830
67913
  const size = 150;
67831
67914
  const buffer2 = Buffer.alloc(size);
67832
67915
  let fd;
67833
67916
  try {
67834
- fd = fs22.openSync(command, "r");
67835
- fs22.readSync(fd, buffer2, 0, size, 0);
67836
- fs22.closeSync(fd);
67917
+ fd = fs23.openSync(command, "r");
67918
+ fs23.readSync(fd, buffer2, 0, size, 0);
67919
+ fs23.closeSync(fd);
67837
67920
  } catch (e) {}
67838
67921
  return shebangCommand(buffer2.toString());
67839
67922
  }
@@ -67842,7 +67925,7 @@ var require_readShebang = __commonJS((exports, module) => {
67842
67925
 
67843
67926
  // node_modules/.bun/cross-spawn@7.0.6/node_modules/cross-spawn/lib/parse.js
67844
67927
  var require_parse2 = __commonJS((exports, module) => {
67845
- var path21 = __require("path");
67928
+ var path22 = __require("path");
67846
67929
  var resolveCommand2 = require_resolveCommand();
67847
67930
  var escape2 = require_escape();
67848
67931
  var readShebang = require_readShebang();
@@ -67867,7 +67950,7 @@ var require_parse2 = __commonJS((exports, module) => {
67867
67950
  const needsShell = !isExecutableRegExp.test(commandFile);
67868
67951
  if (parsed.options.forceShell || needsShell) {
67869
67952
  const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
67870
- parsed.command = path21.normalize(parsed.command);
67953
+ parsed.command = path22.normalize(parsed.command);
67871
67954
  parsed.command = escape2.command(parsed.command);
67872
67955
  parsed.args = parsed.args.map((arg) => escape2.argument(arg, needsDoubleEscapeMetaChars));
67873
67956
  const shellCommand = [parsed.command].concat(parsed.args).join(" ");
@@ -68574,6 +68657,10 @@ function registerAgentName(name) {
68574
68657
  }
68575
68658
  }
68576
68659
  }
68660
+ function clearRegisteredAgentNames() {
68661
+ registeredAgentNames.clear();
68662
+ registeredAgentAliases.clear();
68663
+ }
68577
68664
  function isAgentRegistered(name) {
68578
68665
  return registeredAgentNames.has(normalizeRegisteredAgentName(name));
68579
68666
  }
@@ -72094,9 +72181,18 @@ function debugLog2(...args) {
72094
72181
  function getBinaryName2() {
72095
72182
  return process.platform === "win32" ? "comment-checker.exe" : "comment-checker";
72096
72183
  }
72184
+ function resolveCommentCheckerPathFromPath(binaryName, which = Bun.which) {
72185
+ try {
72186
+ return which(binaryName);
72187
+ } catch (error) {
72188
+ debugLog2("PATH lookup failed:", error);
72189
+ return null;
72190
+ }
72191
+ }
72097
72192
  function findCommentCheckerPathSync() {
72193
+ const binaryName = getBinaryName2();
72098
72194
  const resolvedPath = resolveCommentCheckerBinary({
72099
- binaryName: getBinaryName2(),
72195
+ binaryName,
72100
72196
  cachedBinaryPath: getCachedBinaryPath2(),
72101
72197
  existsSync: existsSync35,
72102
72198
  importMetaUrl: import.meta.url
@@ -72105,6 +72201,11 @@ function findCommentCheckerPathSync() {
72105
72201
  debugLog2("resolved binary path:", resolvedPath);
72106
72202
  return resolvedPath;
72107
72203
  }
72204
+ const pathBinary = resolveCommentCheckerPathFromPath(binaryName);
72205
+ if (pathBinary !== null && existsSync35(pathBinary)) {
72206
+ debugLog2("resolved PATH binary:", pathBinary);
72207
+ return pathBinary;
72208
+ }
72108
72209
  debugLog2("no binary found in known locations");
72109
72210
  return null;
72110
72211
  }
@@ -76432,9 +76533,7 @@ async function buildTranscriptFromSession(client, sessionId, directory, currentT
76432
76533
  `);
76433
76534
  const cacheEntry = transcriptCache.get(sessionId);
76434
76535
  if (cacheEntry) {
76435
- cacheEntry.baseEntries = allEntries;
76436
76536
  cacheEntry.tempPath = tempPath;
76437
- cacheEntry.createdAt = Date.now();
76438
76537
  }
76439
76538
  return tempPath;
76440
76539
  } catch (error) {
@@ -85356,6 +85455,9 @@ function suppressComboStandalones(detected) {
85356
85455
  return detected;
85357
85456
  return detected.filter((k) => k.type !== "ultrawork" && k.type !== "hyperplan");
85358
85457
  }
85458
+ function filterAlreadyInjectedKeywords(detected, text) {
85459
+ return detected.filter((keyword) => !text.includes(keyword.message));
85460
+ }
85359
85461
  function createKeywordDetectorHook(ctx, _collector, _ralphLoop, config, defaultMode) {
85360
85462
  const disabledKeywords = config?.disabled_keywords;
85361
85463
  const enabledExpansions = config?.enabled_expansions;
@@ -85433,6 +85535,11 @@ function createKeywordDetectorHook(ctx, _collector, _ralphLoop, config, defaultM
85433
85535
  return;
85434
85536
  }
85435
85537
  }
85538
+ detectedKeywords = filterAlreadyInjectedKeywords(detectedKeywords, cleanText);
85539
+ if (detectedKeywords.length === 0) {
85540
+ log(`[keyword-detector] Skipping already injected keyword messages`, { sessionID: input.sessionID });
85541
+ return;
85542
+ }
85436
85543
  const hasUltrawork = detectedKeywords.some((k) => k.type === "ultrawork");
85437
85544
  if (hasUltrawork) {
85438
85545
  const runtimeVariant = getRuntimeVariant(input, output.message);
@@ -87607,9 +87714,10 @@ function collectAssistantText(message) {
87607
87714
  if (!Array.isArray(message.parts)) {
87608
87715
  return "";
87609
87716
  }
87717
+ const allowTextParts = message.info?.role === "assistant";
87610
87718
  let text = "";
87611
87719
  for (const part of message.parts) {
87612
- if (part.type !== "text" && part.type !== "tool_result") {
87720
+ if (part.type !== "tool_result" && !(allowTextParts && part.type === "text")) {
87613
87721
  continue;
87614
87722
  }
87615
87723
  text += `${text ? `
@@ -87628,9 +87736,6 @@ async function detectOracleVerificationFromParentSession(ctx, parentSessionID, d
87628
87736
  const messageArray = Array.isArray(messagesResponse) ? messagesResponse : Array.isArray(responseData) ? responseData : [];
87629
87737
  for (let index = messageArray.length - 1;index >= 0; index -= 1) {
87630
87738
  const message = messageArray[index];
87631
- if (message.info?.role !== "assistant") {
87632
- continue;
87633
- }
87634
87739
  const assistantText = collectAssistantText(message);
87635
87740
  if (!isOracleVerified(assistantText)) {
87636
87741
  continue;
@@ -87649,6 +87754,30 @@ async function detectOracleVerificationFromParentSession(ctx, parentSessionID, d
87649
87754
  return;
87650
87755
  }
87651
87756
  }
87757
+ function showCompletionToastBestEffort(ctx, state3) {
87758
+ const showToast = ctx.client.tui?.showToast;
87759
+ if (!showToast) {
87760
+ return;
87761
+ }
87762
+ const toastBody = {
87763
+ body: {
87764
+ title: "ULTRAWORK LOOP COMPLETE!",
87765
+ message: `JUST ULW ULW! Task completed after ${state3.iteration} iteration(s)`,
87766
+ variant: "success",
87767
+ duration: 5000
87768
+ }
87769
+ };
87770
+ const logToastError = (error) => {
87771
+ log(`[${HOOK_NAME3}] Failed to show ulw completion toast`, {
87772
+ error: String(error)
87773
+ });
87774
+ };
87775
+ try {
87776
+ Promise.resolve(showToast(toastBody)).catch(logToastError);
87777
+ } catch (error) {
87778
+ logToastError(error);
87779
+ }
87780
+ }
87652
87781
  async function handlePendingVerification(ctx, input) {
87653
87782
  const {
87654
87783
  sessionID,
@@ -87664,6 +87793,15 @@ async function handlePendingVerification(ctx, input) {
87664
87793
  if (!verificationSessionID && state3.session_id) {
87665
87794
  const recoveredVerificationSessionID = await detectOracleVerificationFromParentSession(ctx, state3.session_id, directory, apiTimeoutMs);
87666
87795
  if (recoveredVerificationSessionID) {
87796
+ if (state3.completion_promise === ULTRAWORK_VERIFICATION_PROMISE) {
87797
+ log(`[${HOOK_NAME3}] Oracle verification evidence found in parent session, completing ultrawork loop`, {
87798
+ parentSessionID: state3.session_id,
87799
+ recoveredVerificationSessionID
87800
+ });
87801
+ loopState.clear();
87802
+ showCompletionToastBestEffort(ctx, state3);
87803
+ return;
87804
+ }
87667
87805
  const updatedState = loopState.setVerificationSessionID(state3.session_id, recoveredVerificationSessionID);
87668
87806
  if (updatedState) {
87669
87807
  log(`[${HOOK_NAME3}] Recovered missing verification session from parent evidence`, {
@@ -87751,8 +87889,8 @@ var USER_MESSAGE_IN_PROGRESS_WINDOW_MS = 2000;
87751
87889
  function sleep(ms) {
87752
87890
  return ms > 0 ? new Promise((resolve14) => setTimeout(resolve14, ms)) : Promise.resolve();
87753
87891
  }
87754
- function hasRunningBackgroundTasks(backgroundManager, sessionID) {
87755
- return backgroundManager ? backgroundManager.getTasksByParentSession(sessionID).some((task) => task.status === "running") : false;
87892
+ function hasActiveBackgroundTasks(backgroundManager, sessionID) {
87893
+ return backgroundManager ? backgroundManager.getTasksByParentSession(sessionID).some((task) => task.status === "pending" || task.status === "running") : false;
87756
87894
  }
87757
87895
  function getRuntimeRetryActivitySessionID(eventType, props) {
87758
87896
  if (eventType === "message.updated") {
@@ -87935,8 +88073,8 @@ function createRalphLoopEventHandler(ctx, options) {
87935
88073
  if (!state3 || !state3.active) {
87936
88074
  return;
87937
88075
  }
87938
- if (hasRunningBackgroundTasks(options.backgroundManager, sessionID)) {
87939
- log(`[${HOOK_NAME3}] Skipped: background tasks running`, { sessionID });
88076
+ if (hasActiveBackgroundTasks(options.backgroundManager, sessionID)) {
88077
+ log(`[${HOOK_NAME3}] Skipped: background tasks active`, { sessionID });
87940
88078
  return;
87941
88079
  }
87942
88080
  const verificationSessionID = state3.verification_pending ? state3.verification_session_id : undefined;
@@ -88170,8 +88308,8 @@ function createRalphLoopEventHandler(ctx, options) {
88170
88308
  handleErroredLoopSession(props, options.loopState);
88171
88309
  return;
88172
88310
  }
88173
- if (hasRunningBackgroundTasks(options.backgroundManager, sessionID)) {
88174
- log(`[${HOOK_NAME3}] Skipped runtime error retry: background tasks running`, { sessionID });
88311
+ if (hasActiveBackgroundTasks(options.backgroundManager, sessionID)) {
88312
+ log(`[${HOOK_NAME3}] Skipped runtime error retry: background tasks active`, { sessionID });
88175
88313
  return;
88176
88314
  }
88177
88315
  log(`[${HOOK_NAME3}] Retrying after runtime session error`, {
@@ -92667,9 +92805,55 @@ async function discoverConfigSourceSkills(options) {
92667
92805
  }));
92668
92806
  return deduplicateSkillsByName(loadedBySource.flat());
92669
92807
  }
92808
+ // src/features/opencode-skill-loader/opencode-config-skills-reader.ts
92809
+ init_jsonc_parser2();
92810
+ init_opencode_config_dir();
92811
+ import * as fs21 from "fs";
92812
+ import * as path17 from "path";
92813
+ function getConfigPaths3(directory) {
92814
+ const globalConfigDir = getOpenCodeConfigDir({ binary: "opencode" });
92815
+ return [
92816
+ path17.join(directory, ".opencode", "opencode.json"),
92817
+ path17.join(directory, ".opencode", "opencode.jsonc"),
92818
+ path17.join(globalConfigDir, "opencode.json"),
92819
+ path17.join(globalConfigDir, "opencode.jsonc")
92820
+ ];
92821
+ }
92822
+ function toStringArray(value) {
92823
+ if (!Array.isArray(value))
92824
+ return [];
92825
+ return value.filter((item) => typeof item === "string").map((item) => item.trim()).filter((item) => item.length > 0);
92826
+ }
92827
+ function readOpencodeConfigSkills(directory) {
92828
+ const paths = [];
92829
+ const urls = [];
92830
+ for (const configPath of getConfigPaths3(directory)) {
92831
+ try {
92832
+ if (!fs21.existsSync(configPath))
92833
+ continue;
92834
+ const content = fs21.readFileSync(configPath, "utf-8");
92835
+ const parseResult = parseJsoncSafe(content);
92836
+ if (!parseResult.data?.skills)
92837
+ continue;
92838
+ for (const p of toStringArray(parseResult.data.skills.paths)) {
92839
+ if (!paths.includes(p))
92840
+ paths.push(p);
92841
+ }
92842
+ for (const u of toStringArray(parseResult.data.skills.urls)) {
92843
+ if (!urls.includes(u))
92844
+ urls.push(u);
92845
+ }
92846
+ } catch {
92847
+ continue;
92848
+ }
92849
+ }
92850
+ if (paths.length === 0 && urls.length === 0)
92851
+ return;
92852
+ return { paths, urls };
92853
+ }
92670
92854
  // src/tools/slashcommand/command-discovery.ts
92671
- import { existsSync as existsSync63, readdirSync as readdirSync19, readFileSync as readFileSync46, statSync as statSync9 } from "fs";
92672
- import { basename as basename9, join as join75 } from "path";
92855
+ import { existsSync as existsSync64, readdirSync as readdirSync19, readFileSync as readFileSync47, statSync as statSync9 } from "fs";
92856
+ import { basename as basename9, join as join76 } from "path";
92673
92857
 
92674
92858
  // src/tools/slashcommand/command-discovery-deps.ts
92675
92859
  init_excluded_dirs();
@@ -94212,7 +94396,7 @@ function loadBuiltinCommands(disabledCommands, options) {
94212
94396
  // src/tools/slashcommand/command-discovery.ts
94213
94397
  var NESTED_COMMAND_SEPARATOR = "/";
94214
94398
  function discoverCommandsFromDir(commandsDir, scope, prefix = "") {
94215
- if (!existsSync63(commandsDir))
94399
+ if (!existsSync64(commandsDir))
94216
94400
  return [];
94217
94401
  if (!statSync9(commandsDir).isDirectory()) {
94218
94402
  log(`[command-discovery] Skipping non-directory path: ${commandsDir}`);
@@ -94227,16 +94411,16 @@ function discoverCommandsFromDir(commandsDir, scope, prefix = "") {
94227
94411
  if (entry.name.startsWith("."))
94228
94412
  continue;
94229
94413
  const nestedPrefix = prefix ? `${prefix}${NESTED_COMMAND_SEPARATOR}${entry.name}` : entry.name;
94230
- commands2.push(...discoverCommandsFromDir(join75(commandsDir, entry.name), scope, nestedPrefix));
94414
+ commands2.push(...discoverCommandsFromDir(join76(commandsDir, entry.name), scope, nestedPrefix));
94231
94415
  continue;
94232
94416
  }
94233
94417
  if (!isMarkdownFile(entry))
94234
94418
  continue;
94235
- const commandPath = join75(commandsDir, entry.name);
94419
+ const commandPath = join76(commandsDir, entry.name);
94236
94420
  const baseCommandName = basename9(entry.name, ".md");
94237
94421
  const commandName = prefix ? `${prefix}${NESTED_COMMAND_SEPARATOR}${baseCommandName}` : baseCommandName;
94238
94422
  try {
94239
- const content = readFileSync46(commandPath, "utf-8");
94423
+ const content = readFileSync47(commandPath, "utf-8");
94240
94424
  const { data, body } = parseFrontmatter(content);
94241
94425
  const isOpencodeSource = scope === "opencode" || scope === "opencode-project";
94242
94426
  const metadata = {
@@ -94288,8 +94472,8 @@ function deduplicateCommandInfosByName(commands2) {
94288
94472
  return deduplicatedCommands;
94289
94473
  }
94290
94474
  function discoverCommandsSync(directory, options) {
94291
- const userCommandsDir = join75(getClaudeConfigDir(), "commands");
94292
- const projectCommandsDir = join75(directory ?? process.cwd(), ".claude", "commands");
94475
+ const userCommandsDir = join76(getClaudeConfigDir(), "commands");
94476
+ const projectCommandsDir = join76(directory ?? process.cwd(), ".claude", "commands");
94293
94477
  const opencodeGlobalDirs = getOpenCodeCommandDirs({ binary: "opencode" });
94294
94478
  const opencodeProjectDirs = findProjectOpencodeCommandDirs(directory ?? process.cwd());
94295
94479
  const userCommands = discoverCommandsFromDir(userCommandsDir, "user");
@@ -94789,7 +94973,7 @@ var NOTEPAD_DIR = "notepads";
94789
94973
  var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
94790
94974
  var PROMETHEUS_PLANS_DIR = ".omo/plans";
94791
94975
  // packages/boulder-state/src/top-level-task.ts
94792
- import { existsSync as existsSync64, readFileSync as readFileSync47 } from "fs";
94976
+ import { existsSync as existsSync65, readFileSync as readFileSync48 } from "fs";
94793
94977
  var TODO_HEADING_PATTERN = /^##\s+TODOs\b/i;
94794
94978
  var FINAL_VERIFICATION_HEADING_PATTERN = /^##\s+Final Verification Wave\b/i;
94795
94979
  var SECOND_LEVEL_HEADING_PATTERN = /^##\s+/;
@@ -94812,11 +94996,11 @@ function buildTaskRef(section, taskLabel) {
94812
94996
  };
94813
94997
  }
94814
94998
  function readCurrentTopLevelTask(planPath) {
94815
- if (!existsSync64(planPath)) {
94999
+ if (!existsSync65(planPath)) {
94816
95000
  return null;
94817
95001
  }
94818
95002
  try {
94819
- const content = readFileSync47(planPath, "utf-8");
95003
+ const content = readFileSync48(planPath, "utf-8");
94820
95004
  const lines = content.split(/\r?\n/);
94821
95005
  let section = "other";
94822
95006
  for (const line of lines) {
@@ -94841,10 +95025,10 @@ function readCurrentTopLevelTask(planPath) {
94841
95025
  }
94842
95026
  }
94843
95027
  // packages/boulder-state/src/storage/path.ts
94844
- import { existsSync as existsSync65 } from "fs";
94845
- import { isAbsolute as isAbsolute13, join as join76, relative as relative11, resolve as resolve15 } from "path";
95028
+ import { existsSync as existsSync66 } from "fs";
95029
+ import { isAbsolute as isAbsolute13, join as join77, relative as relative11, resolve as resolve15 } from "path";
94846
95030
  function getBoulderFilePath(directory) {
94847
- return join76(directory, BOULDER_DIR, BOULDER_FILE);
95031
+ return join77(directory, BOULDER_DIR, BOULDER_FILE);
94848
95032
  }
94849
95033
  function resolveTrackedPath(baseDirectory, trackedPath) {
94850
95034
  return isAbsolute13(trackedPath) ? resolve15(trackedPath) : resolve15(baseDirectory, trackedPath);
@@ -94862,14 +95046,14 @@ function resolveBoulderPlanPath(directory, state3) {
94862
95046
  }
94863
95047
  const absoluteWorktreePath = resolveTrackedPath(directory, worktreePath);
94864
95048
  const worktreePlanPath = resolve15(absoluteWorktreePath, relativePlanPath);
94865
- return existsSync65(worktreePlanPath) ? worktreePlanPath : absolutePlanPath;
95049
+ return existsSync66(worktreePlanPath) ? worktreePlanPath : absolutePlanPath;
94866
95050
  }
94867
95051
  function resolveBoulderPlanPathForWork(directory, work) {
94868
95052
  return resolveBoulderPlanPath(directory, work);
94869
95053
  }
94870
95054
  // packages/boulder-state/src/storage/plan-progress.ts
94871
- import { existsSync as existsSync66, readFileSync as readFileSync48, readdirSync as readdirSync20, statSync as statSync10 } from "fs";
94872
- import { basename as basename10, join as join77 } from "path";
95055
+ import { existsSync as existsSync67, readFileSync as readFileSync49, readdirSync as readdirSync20, statSync as statSync10 } from "fs";
95056
+ import { basename as basename10, join as join78 } from "path";
94873
95057
  var TODO_HEADING_PATTERN2 = /^##\s+TODOs\b/i;
94874
95058
  var FINAL_VERIFICATION_HEADING_PATTERN2 = /^##\s+Final Verification Wave\b/i;
94875
95059
  var SECOND_LEVEL_HEADING_PATTERN2 = /^##\s+/;
@@ -94882,11 +95066,11 @@ var PROMETHEUS_PLAN_DIRS = [PROMETHEUS_PLANS_DIR, LEGACY_PROMETHEUS_PLANS_DIR];
94882
95066
  function findPrometheusPlans(directory) {
94883
95067
  try {
94884
95068
  return PROMETHEUS_PLAN_DIRS.flatMap((planDir) => {
94885
- const plansDir = join77(directory, planDir);
94886
- if (!existsSync66(plansDir)) {
95069
+ const plansDir = join78(directory, planDir);
95070
+ if (!existsSync67(plansDir)) {
94887
95071
  return [];
94888
95072
  }
94889
- return readdirSync20(plansDir).filter((file) => file.endsWith(".md")).map((file) => join77(plansDir, file));
95073
+ return readdirSync20(plansDir).filter((file) => file.endsWith(".md")).map((file) => join78(plansDir, file));
94890
95074
  }).sort((left, right) => statSync10(right).mtimeMs - statSync10(left).mtimeMs);
94891
95075
  } catch {
94892
95076
  return [];
@@ -94896,11 +95080,11 @@ function getPlanName(planPath) {
94896
95080
  return basename10(planPath, ".md");
94897
95081
  }
94898
95082
  function getPlanProgress(planPath) {
94899
- if (!existsSync66(planPath)) {
95083
+ if (!existsSync67(planPath)) {
94900
95084
  return { total: 0, completed: 0, isComplete: false };
94901
95085
  }
94902
95086
  try {
94903
- const content = readFileSync48(planPath, "utf-8");
95087
+ const content = readFileSync49(planPath, "utf-8");
94904
95088
  const lines = content.split(/\r?\n/);
94905
95089
  const hasStructuredSections = lines.some((line) => TODO_HEADING_PATTERN2.test(line) || FINAL_VERIFICATION_HEADING_PATTERN2.test(line));
94906
95090
  if (hasStructuredSections) {
@@ -95030,14 +95214,14 @@ function selectMirrorWork(state3) {
95030
95214
  return sorted[0] ?? null;
95031
95215
  }
95032
95216
  // packages/boulder-state/src/storage/read-state.ts
95033
- import { existsSync as existsSync67, readFileSync as readFileSync49 } from "fs";
95217
+ import { existsSync as existsSync68, readFileSync as readFileSync50 } from "fs";
95034
95218
  function readBoulderState(directory) {
95035
95219
  const filePath = getBoulderFilePath(directory);
95036
- if (!existsSync67(filePath)) {
95220
+ if (!existsSync68(filePath)) {
95037
95221
  return null;
95038
95222
  }
95039
95223
  try {
95040
- const content = readFileSync49(filePath, "utf-8");
95224
+ const content = readFileSync50(filePath, "utf-8");
95041
95225
  const parsed = JSON.parse(content);
95042
95226
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
95043
95227
  return null;
@@ -95168,13 +95352,13 @@ function getTaskSessionState(directory, taskKey) {
95168
95352
  return state3.task_sessions[taskKey] ?? null;
95169
95353
  }
95170
95354
  // packages/boulder-state/src/storage/write-state.ts
95171
- import { existsSync as existsSync68, mkdirSync as mkdirSync17, unlinkSync as unlinkSync13, writeFileSync as writeFileSync18 } from "fs";
95355
+ import { existsSync as existsSync69, mkdirSync as mkdirSync17, unlinkSync as unlinkSync13, writeFileSync as writeFileSync18 } from "fs";
95172
95356
  import { dirname as dirname25 } from "path";
95173
95357
  function writeBoulderState(directory, state3) {
95174
95358
  const filePath = getBoulderFilePath(directory);
95175
95359
  try {
95176
95360
  const dir = dirname25(filePath);
95177
- if (!existsSync68(dir)) {
95361
+ if (!existsSync69(dir)) {
95178
95362
  mkdirSync17(dir, { recursive: true });
95179
95363
  }
95180
95364
  const stateToWrite = { ...state3 };
@@ -95210,7 +95394,7 @@ function writeBoulderState(directory, state3) {
95210
95394
  function clearBoulderState(directory) {
95211
95395
  const filePath = getBoulderFilePath(directory);
95212
95396
  try {
95213
- if (existsSync68(filePath)) {
95397
+ if (existsSync69(filePath)) {
95214
95398
  unlinkSync13(filePath);
95215
95399
  }
95216
95400
  return true;
@@ -95915,6 +96099,23 @@ function buildExplicitPlanContext(params) {
95915
96099
  const allPlans = findPrometheusPlans(directory);
95916
96100
  const matchedPlan = findPlanByName(allPlans, explicitPlanName);
95917
96101
  if (!matchedPlan) {
96102
+ const incompletePlans = allPlans.filter((planPath) => !getPlanProgress(planPath).isComplete);
96103
+ if (incompletePlans.length === 1) {
96104
+ createNewWorkOrInitialize({
96105
+ directory,
96106
+ planPath: incompletePlans[0],
96107
+ sessionId,
96108
+ activeAgent,
96109
+ worktreePath
96110
+ });
96111
+ return buildAutoSelectedPlanContextInfoOnly({
96112
+ planPath: incompletePlans[0],
96113
+ sessionId,
96114
+ timestamp: timestamp2,
96115
+ worktreeBlock,
96116
+ reason: `Only incomplete plan available after "${explicitPlanName}" did not match any plan`
96117
+ });
96118
+ }
95918
96119
  return buildMissingPlanContext(explicitPlanName, allPlans);
95919
96120
  }
95920
96121
  const progress = getPlanProgress(matchedPlan);
@@ -96321,8 +96522,8 @@ function isAbortError2(error) {
96321
96522
  // src/hooks/atlas/session-last-agent.ts
96322
96523
  init_shared();
96323
96524
  init_compaction_marker();
96324
- import { readFileSync as readFileSync50, readdirSync as readdirSync21 } from "fs";
96325
- import { join as join78 } from "path";
96525
+ import { readFileSync as readFileSync51, readdirSync as readdirSync21 } from "fs";
96526
+ import { join as join79 } from "path";
96326
96527
  var defaultSessionLastAgentDeps = {
96327
96528
  getMessageDir,
96328
96529
  isSqliteBackend,
@@ -96376,7 +96577,7 @@ async function getLastAgentFromSession(sessionID, client, deps = {}) {
96376
96577
  try {
96377
96578
  const messages = readdirSync21(messageDir).filter((fileName) => fileName.endsWith(".json")).map((fileName) => {
96378
96579
  try {
96379
- const content = readFileSync50(join78(messageDir, fileName), "utf-8");
96580
+ const content = readFileSync51(join79(messageDir, fileName), "utf-8");
96380
96581
  const parsed = JSON.parse(content);
96381
96582
  return {
96382
96583
  fileName,
@@ -96896,7 +97097,7 @@ function getTaskLabelSortValue(taskLabel) {
96896
97097
  const parsed = Number.parseInt(taskLabel.replace(/[^0-9]/g, ""), 10);
96897
97098
  return Number.isNaN(parsed) ? Number.POSITIVE_INFINITY : parsed;
96898
97099
  }
96899
- function hasRunningBackgroundTasks2(sessionID, options) {
97100
+ function hasRunningBackgroundTasks(sessionID, options) {
96900
97101
  const backgroundManager = options?.backgroundManager;
96901
97102
  return backgroundManager ? backgroundManager.getTasksByParentSession(sessionID).some((task) => task.status === "running") : false;
96902
97103
  }
@@ -97025,7 +97226,7 @@ function scheduleRetry(input) {
97025
97226
  });
97026
97227
  if (!canContinueSession)
97027
97228
  return;
97028
- if (hasRunningBackgroundTasks2(sessionID, options)) {
97229
+ if (hasRunningBackgroundTasks(sessionID, options)) {
97029
97230
  scheduleRetry({ ctx, sessionID, sessionState, options });
97030
97231
  return;
97031
97232
  }
@@ -97211,7 +97412,7 @@ async function handleAtlasSessionIdle(input) {
97211
97412
  sessionState.promptFailureCount = 0;
97212
97413
  sessionState.lastFailureAt = undefined;
97213
97414
  }
97214
- if (hasRunningBackgroundTasks2(sessionID, options)) {
97415
+ if (hasRunningBackgroundTasks(sessionID, options)) {
97215
97416
  scheduleRetry({ ctx, sessionID, sessionState, options });
97216
97417
  log(`[${HOOK_NAME7}] Skipped: background tasks running`, { sessionID });
97217
97418
  return;
@@ -97371,7 +97572,7 @@ function createAtlasEventHandler(input) {
97371
97572
  // src/hooks/atlas/tool-execute-after.ts
97372
97573
  init_logger();
97373
97574
  init_session_utils();
97374
- import { existsSync as existsSync70, readFileSync as readFileSync52 } from "fs";
97575
+ import { existsSync as existsSync71, readFileSync as readFileSync53 } from "fs";
97375
97576
  import { resolve as resolve18 } from "path";
97376
97577
 
97377
97578
  // src/hooks/atlas/background-launch-session-tracking.ts
@@ -97519,7 +97720,7 @@ async function resolveFallbackTrackedSessionId(input) {
97519
97720
  init_git_worktree();
97520
97721
 
97521
97722
  // src/hooks/atlas/final-wave-plan-state.ts
97522
- import { existsSync as existsSync69, readFileSync as readFileSync51 } from "fs";
97723
+ import { existsSync as existsSync70, readFileSync as readFileSync52 } from "fs";
97523
97724
  var TODO_HEADING_PATTERN3 = /^##\s+TODOs\b/i;
97524
97725
  var FINAL_VERIFICATION_HEADING_PATTERN3 = /^##\s+Final Verification Wave\b/i;
97525
97726
  var SECOND_LEVEL_HEADING_PATTERN3 = /^##\s+/;
@@ -97527,11 +97728,11 @@ var UNCHECKED_CHECKBOX_PATTERN3 = /^\s*[-*]\s*\[\s*\]\s*(.+)$/;
97527
97728
  var TODO_TASK_PATTERN3 = /^\d+\./;
97528
97729
  var FINAL_WAVE_TASK_PATTERN3 = /^F\d+\./i;
97529
97730
  function readFinalWavePlanState(planPath) {
97530
- if (!existsSync69(planPath)) {
97731
+ if (!existsSync70(planPath)) {
97531
97732
  return null;
97532
97733
  }
97533
97734
  try {
97534
- const content = readFileSync51(planPath, "utf-8");
97735
+ const content = readFileSync52(planPath, "utf-8");
97535
97736
  const lines = content.split(/\r?\n/);
97536
97737
  let section = "other";
97537
97738
  let pendingImplementationTaskCount = 0;
@@ -97781,7 +97982,7 @@ function isWriteOrEditToolName(toolName) {
97781
97982
 
97782
97983
  // src/hooks/atlas/tool-execute-after.ts
97783
97984
  function isTrackedTaskChecked(planPath, taskKey) {
97784
- if (!existsSync70(planPath)) {
97985
+ if (!existsSync71(planPath)) {
97785
97986
  return false;
97786
97987
  }
97787
97988
  const [section, label] = taskKey.split(":");
@@ -97794,7 +97995,7 @@ function isTrackedTaskChecked(planPath, taskKey) {
97794
97995
  return false;
97795
97996
  }
97796
97997
  try {
97797
- const content = readFileSync52(planPath, "utf-8");
97998
+ const content = readFileSync53(planPath, "utf-8");
97798
97999
  return matcher.test(content);
97799
98000
  } catch {
97800
98001
  return false;
@@ -97838,11 +98039,11 @@ function parseCheckedTopLevelTaskKeys(planContent) {
97838
98039
  return checkedKeys;
97839
98040
  }
97840
98041
  function readCheckedTaskKeysFromPlan(planPath) {
97841
- if (!existsSync70(planPath)) {
98042
+ if (!existsSync71(planPath)) {
97842
98043
  return new Set;
97843
98044
  }
97844
98045
  try {
97845
- return parseCheckedTopLevelTaskKeys(readFileSync52(planPath, "utf-8"));
98046
+ return parseCheckedTopLevelTaskKeys(readFileSync53(planPath, "utf-8"));
97846
98047
  } catch {
97847
98048
  return new Set;
97848
98049
  }
@@ -98049,7 +98250,7 @@ init_logger();
98049
98250
  init_replace_tool_args();
98050
98251
  init_system_directive();
98051
98252
  init_session_utils();
98052
- import { existsSync as existsSync71, readFileSync as readFileSync53 } from "fs";
98253
+ import { existsSync as existsSync72, readFileSync as readFileSync54 } from "fs";
98053
98254
  import { resolve as resolve19 } from "path";
98054
98255
  var TASK_SECTION_HEADER_PATTERN = /^##\s*1\.\s*TASK\s*$/i;
98055
98256
  var TODO_TASK_LINE_PATTERN = /^(?:[-*]\s*\[\s*\]\s*)?(\d+)\.\s+(.+)$/;
@@ -98110,8 +98311,8 @@ function createToolExecuteBeforeHandler2(input) {
98110
98311
  const planPath = sessionWork ? resolveBoulderPlanPathForWork(ctx.directory, sessionWork) : state3 ? resolveBoulderPlanPath(ctx.directory, state3) : null;
98111
98312
  if (planPath && resolve19(filePath) === resolve19(planPath) && pendingPlanSnapshots) {
98112
98313
  try {
98113
- if (existsSync71(planPath)) {
98114
- pendingPlanSnapshots.set(toolInput.callID, readFileSync53(planPath, "utf-8"));
98314
+ if (existsSync72(planPath)) {
98315
+ pendingPlanSnapshots.set(toolInput.callID, readFileSync54(planPath, "utf-8"));
98115
98316
  }
98116
98317
  } catch {
98117
98318
  pendingPlanSnapshots.delete(toolInput.callID);
@@ -99971,16 +100172,16 @@ function createPreemptiveCompactionHook(ctx, pluginConfig, modelCacheState) {
99971
100172
  init_shared();
99972
100173
 
99973
100174
  // src/hooks/tasks-todowrite-disabler/constants.ts
99974
- var BLOCKED_TOOLS2 = ["TodoWrite", "TodoRead"];
99975
- var REPLACEMENT_MESSAGE = `TodoRead/TodoWrite are DISABLED because experimental.task_system is enabled.
100175
+ var BLOCKED_TOOLS2 = ["TodoRead"];
100176
+ var REPLACEMENT_MESSAGE = `TodoRead is DISABLED because experimental.task_system is enabled.
99976
100177
 
99977
- **ACTION REQUIRED**: RE-REGISTER what you were about to write as Todo using Task tools NOW. Then ASSIGN yourself and START WORKING immediately.
100178
+ **ACTION REQUIRED**: Use Task tools to inspect work state. TodoWrite is still allowed so the live todo panel keeps updating, but reads belong to the task system.
99978
100179
 
99979
- **Use these tools instead:**
99980
- - TaskCreate: Create new task with auto-generated ID
99981
- - TaskUpdate: Update status, assign owner, add dependencies
100180
+ **Use these tools instead of TodoRead:**
99982
100181
  - TaskList: List active tasks with dependency info
99983
100182
  - TaskGet: Get full task details
100183
+ - TaskCreate: Create new task with auto-generated ID
100184
+ - TaskUpdate: Update status, assign owner, add dependencies
99984
100185
 
99985
100186
  **Workflow:**
99986
100187
  1. TaskCreate({ subject: "your task description" })
@@ -99999,7 +100200,7 @@ Even if the task seems trivial (1 line fix, simple edit, quick change), you MUST
99999
100200
 
100000
100201
  **WHY?** Task tracking = visibility = accountability. Skipping registration = invisible work = chaos.
100001
100202
 
100002
- DO NOT retry TodoWrite. Convert to TaskCreate NOW.`;
100203
+ DO NOT retry TodoRead. Use TaskList or TaskGet NOW.`;
100003
100204
 
100004
100205
  // src/hooks/tasks-todowrite-disabler/hook.ts
100005
100206
  function createTasksTodowriteDisablerHook(config) {
@@ -100445,6 +100646,7 @@ function getLastUserRetryPayload(messagesResponse, sessionID) {
100445
100646
  }
100446
100647
 
100447
100648
  // src/hooks/runtime-fallback/auto-retry.ts
100649
+ init_internal_initiator_marker();
100448
100650
  var SESSION_TTL_MS = 30 * 60 * 1000;
100449
100651
  function createAutoRetryHelpers(deps) {
100450
100652
  const {
@@ -100557,7 +100759,7 @@ function createAutoRetryHelpers(deps) {
100557
100759
  sessionID,
100558
100760
  hint: "This can occur when the working directory contains .git and messages are not yet persisted"
100559
100761
  });
100560
- return [{ type: "text", text: "continue" }];
100762
+ return [createInternalAgentContinuationTextPart("continue")];
100561
100763
  })();
100562
100764
  log(`[${HOOK_NAME11}] Auto-retrying with fallback model (${source})`, {
100563
100765
  sessionID,
@@ -101851,12 +102053,12 @@ function createRuntimeFallbackHook(ctx, options, factoryOverrides = {}) {
101851
102053
  };
101852
102054
  }
101853
102055
  // src/hooks/write-existing-file-guard/hook.ts
101854
- import { existsSync as existsSync73, realpathSync as realpathSync8 } from "fs";
101855
- import { basename as basename11, dirname as dirname26, isAbsolute as isAbsolute16, join as join79, normalize as normalize2, relative as relative13, resolve as resolve20 } from "path";
102056
+ import { existsSync as existsSync74, realpathSync as realpathSync8 } from "fs";
102057
+ import { basename as basename11, dirname as dirname26, isAbsolute as isAbsolute16, join as join80, normalize as normalize2, relative as relative13, resolve as resolve20 } from "path";
101856
102058
 
101857
102059
  // src/hooks/write-existing-file-guard/tool-execute-before-handler.ts
101858
102060
  init_shared();
101859
- import { existsSync as existsSync72 } from "fs";
102061
+ import { existsSync as existsSync73 } from "fs";
101860
102062
 
101861
102063
  // src/hooks/write-existing-file-guard/session-read-permissions.ts
101862
102064
  function touchSession(sessionLastAccess, sessionID) {
@@ -101957,7 +102159,7 @@ async function handleWriteExistingFileGuardToolExecuteBefore(params) {
101957
102159
  return;
101958
102160
  }
101959
102161
  if (toolName === "read") {
101960
- if (!existsSync72(resolvedPath) || !input.sessionID) {
102162
+ if (!existsSync73(resolvedPath) || !input.sessionID) {
101961
102163
  return;
101962
102164
  }
101963
102165
  registerReadPermission({
@@ -101974,7 +102176,7 @@ async function handleWriteExistingFileGuardToolExecuteBefore(params) {
101974
102176
  if (argsRecord && "overwrite" in argsRecord) {
101975
102177
  delete argsRecord.overwrite;
101976
102178
  }
101977
- if (!existsSync72(resolvedPath)) {
102179
+ if (!existsSync73(resolvedPath)) {
101978
102180
  return;
101979
102181
  }
101980
102182
  if (isOmoWorkspacePath(canonicalPath)) {
@@ -102033,7 +102235,7 @@ function isPathInsideDirectory(pathToCheck, directory) {
102033
102235
  }
102034
102236
  function toCanonicalPath2(absolutePath) {
102035
102237
  let canonicalPath = absolutePath;
102036
- if (existsSync73(absolutePath)) {
102238
+ if (existsSync74(absolutePath)) {
102037
102239
  try {
102038
102240
  canonicalPath = realpathSync8.native(absolutePath);
102039
102241
  } catch {
@@ -102041,8 +102243,8 @@ function toCanonicalPath2(absolutePath) {
102041
102243
  }
102042
102244
  } else {
102043
102245
  const absoluteDir = dirname26(absolutePath);
102044
- const resolvedDir = existsSync73(absoluteDir) ? realpathSync8.native(absoluteDir) : absoluteDir;
102045
- canonicalPath = join79(resolvedDir, basename11(absolutePath));
102246
+ const resolvedDir = existsSync74(absoluteDir) ? realpathSync8.native(absoluteDir) : absoluteDir;
102247
+ canonicalPath = join80(resolvedDir, basename11(absolutePath));
102046
102248
  }
102047
102249
  return normalize2(canonicalPath);
102048
102250
  }
@@ -103086,16 +103288,16 @@ class Diff {
103086
103288
  }
103087
103289
  }
103088
103290
  }
103089
- addToPath(path17, added, removed, oldPosInc, options) {
103090
- const last = path17.lastComponent;
103291
+ addToPath(path18, added, removed, oldPosInc, options) {
103292
+ const last = path18.lastComponent;
103091
103293
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
103092
103294
  return {
103093
- oldPos: path17.oldPos + oldPosInc,
103295
+ oldPos: path18.oldPos + oldPosInc,
103094
103296
  lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
103095
103297
  };
103096
103298
  } else {
103097
103299
  return {
103098
- oldPos: path17.oldPos + oldPosInc,
103300
+ oldPos: path18.oldPos + oldPosInc,
103099
103301
  lastComponent: { count: 1, added, removed, previousComponent: last }
103100
103302
  };
103101
103303
  }
@@ -104757,8 +104959,8 @@ init_jsonc_parser2();
104757
104959
  init_opencode_config_dir();
104758
104960
  init_plugin_identity();
104759
104961
  init_plugin_entry_migrator();
104760
- import { existsSync as existsSync74, readFileSync as readFileSync54 } from "fs";
104761
- import { join as join80 } from "path";
104962
+ import { existsSync as existsSync75, readFileSync as readFileSync55 } from "fs";
104963
+ import { join as join81 } from "path";
104762
104964
 
104763
104965
  // src/hooks/legacy-plugin-toast/plugin-entry-migrator.ts
104764
104966
  init_migrate_legacy_plugin_entry();
@@ -104766,18 +104968,18 @@ init_migrate_legacy_plugin_entry();
104766
104968
  // src/hooks/legacy-plugin-toast/auto-migrate.ts
104767
104969
  function detectOpenCodeConfigPath(overrideConfigDir) {
104768
104970
  if (overrideConfigDir) {
104769
- const jsoncPath = join80(overrideConfigDir, "opencode.jsonc");
104770
- const jsonPath = join80(overrideConfigDir, "opencode.json");
104771
- if (existsSync74(jsoncPath))
104971
+ const jsoncPath = join81(overrideConfigDir, "opencode.jsonc");
104972
+ const jsonPath = join81(overrideConfigDir, "opencode.json");
104973
+ if (existsSync75(jsoncPath))
104772
104974
  return jsoncPath;
104773
- if (existsSync74(jsonPath))
104975
+ if (existsSync75(jsonPath))
104774
104976
  return jsonPath;
104775
104977
  return null;
104776
104978
  }
104777
104979
  const paths = getOpenCodeConfigPaths({ binary: "opencode", version: null });
104778
- if (existsSync74(paths.configJsonc))
104980
+ if (existsSync75(paths.configJsonc))
104779
104981
  return paths.configJsonc;
104780
- if (existsSync74(paths.configJson))
104982
+ if (existsSync75(paths.configJson))
104781
104983
  return paths.configJson;
104782
104984
  return null;
104783
104985
  }
@@ -104786,7 +104988,7 @@ function autoMigrateLegacyPluginEntry(overrideConfigDir) {
104786
104988
  if (!configPath)
104787
104989
  return { migrated: false, from: null, to: null, configPath: null };
104788
104990
  try {
104789
- const content = readFileSync54(configPath, "utf-8");
104991
+ const content = readFileSync55(configPath, "utf-8");
104790
104992
  const parseResult = parseJsoncSafe(content);
104791
104993
  if (!parseResult.data?.plugin)
104792
104994
  return { migrated: false, from: null, to: null, configPath };
@@ -104970,7 +105172,7 @@ function createNotepadWriteGuardHook() {
104970
105172
  };
104971
105173
  }
104972
105174
  // src/hooks/plan-format-validator/hook.ts
104973
- import { existsSync as existsSync75, readFileSync as readFileSync55 } from "fs";
105175
+ import { existsSync as existsSync76, readFileSync as readFileSync56 } from "fs";
104974
105176
  import { resolve as resolve21 } from "path";
104975
105177
  init_logger();
104976
105178
  var WRITE_TOOLS = new Set(["Write", "Edit", "write", "edit"]);
@@ -105054,9 +105256,9 @@ function createPlanFormatValidatorHook(_ctx) {
105054
105256
  if (!isPlanFilePath(filePath))
105055
105257
  return;
105056
105258
  const resolvedPath = resolve21(_ctx.directory, filePath);
105057
- if (!existsSync75(resolvedPath))
105259
+ if (!existsSync76(resolvedPath))
105058
105260
  return;
105059
- const content = readFileSync55(resolvedPath, "utf-8");
105261
+ const content = readFileSync56(resolvedPath, "utf-8");
105060
105262
  if (!CHECKBOX_PATTERN.test(content))
105061
105263
  return;
105062
105264
  const rawCount = countRawTopLevelCheckboxes(content);
@@ -105186,21 +105388,21 @@ tool.schema = z36;
105186
105388
 
105187
105389
  // src/shared/ripgrep-cli.ts
105188
105390
  import { spawnSync as spawnSync2 } from "child_process";
105189
- import { existsSync as existsSync77 } from "fs";
105190
- import { dirname as dirname27, join as join82 } from "path";
105391
+ import { existsSync as existsSync78 } from "fs";
105392
+ import { dirname as dirname27, join as join83 } from "path";
105191
105393
 
105192
105394
  // src/tools/grep/downloader.ts
105193
105395
  init_shared();
105194
105396
  init_plugin_identity();
105195
105397
  init_binary_downloader();
105196
- import { existsSync as existsSync76, readdirSync as readdirSync22 } from "fs";
105197
- import { join as join81 } from "path";
105398
+ import { existsSync as existsSync77, readdirSync as readdirSync22 } from "fs";
105399
+ import { join as join82 } from "path";
105198
105400
  function findFileRecursive(dir, filename) {
105199
105401
  try {
105200
105402
  const entries = readdirSync22(dir, { withFileTypes: true, recursive: true });
105201
105403
  for (const entry of entries) {
105202
105404
  if (entry.isFile() && entry.name === filename) {
105203
- return join81(entry.parentPath ?? dir, entry.name);
105405
+ return join82(entry.parentPath ?? dir, entry.name);
105204
105406
  }
105205
105407
  }
105206
105408
  } catch {
@@ -105221,11 +105423,11 @@ function getPlatformKey() {
105221
105423
  }
105222
105424
  function getInstallDir() {
105223
105425
  const homeDir = process.env.HOME || process.env.USERPROFILE || ".";
105224
- return join81(homeDir, ".cache", CACHE_DIR_NAME, "bin");
105426
+ return join82(homeDir, ".cache", CACHE_DIR_NAME, "bin");
105225
105427
  }
105226
105428
  function getRgPath() {
105227
105429
  const isWindows2 = process.platform === "win32";
105228
- return join81(getInstallDir(), isWindows2 ? "rg.exe" : "rg");
105430
+ return join82(getInstallDir(), isWindows2 ? "rg.exe" : "rg");
105229
105431
  }
105230
105432
  async function extractTarGz2(archivePath, destDir) {
105231
105433
  const platformKey = getPlatformKey();
@@ -105242,7 +105444,7 @@ async function extractZip2(archivePath, destDir) {
105242
105444
  const binaryName = process.platform === "win32" ? "rg.exe" : "rg";
105243
105445
  const foundPath = findFileRecursive(destDir, binaryName);
105244
105446
  if (foundPath) {
105245
- const destPath = join81(destDir, binaryName);
105447
+ const destPath = join82(destDir, binaryName);
105246
105448
  if (foundPath !== destPath) {
105247
105449
  const { renameSync: renameSync6 } = await import("fs");
105248
105450
  renameSync6(foundPath, destPath);
@@ -105257,13 +105459,13 @@ async function downloadAndInstallRipgrep() {
105257
105459
  }
105258
105460
  const installDir = getInstallDir();
105259
105461
  const rgPath = getRgPath();
105260
- if (existsSync76(rgPath)) {
105462
+ if (existsSync77(rgPath)) {
105261
105463
  return rgPath;
105262
105464
  }
105263
105465
  ensureCacheDir(installDir);
105264
105466
  const filename = `ripgrep-${RG_VERSION}-${config.platform}.${config.extension}`;
105265
105467
  const url = `https://github.com/BurntSushi/ripgrep/releases/download/${RG_VERSION}/${filename}`;
105266
- const archivePath = join81(installDir, filename);
105468
+ const archivePath = join82(installDir, filename);
105267
105469
  try {
105268
105470
  await downloadArchive(url, archivePath);
105269
105471
  if (config.extension === "tar.gz") {
@@ -105272,7 +105474,7 @@ async function downloadAndInstallRipgrep() {
105272
105474
  await extractZip2(archivePath, installDir);
105273
105475
  }
105274
105476
  ensureExecutable(rgPath);
105275
- if (!existsSync76(rgPath)) {
105477
+ if (!existsSync77(rgPath)) {
105276
105478
  throw new Error("ripgrep binary not found after extraction");
105277
105479
  }
105278
105480
  return rgPath;
@@ -105284,7 +105486,7 @@ async function downloadAndInstallRipgrep() {
105284
105486
  }
105285
105487
  function getInstalledRipgrepPath() {
105286
105488
  const rgPath = getRgPath();
105287
- return existsSync76(rgPath) ? rgPath : null;
105489
+ return existsSync77(rgPath) ? rgPath : null;
105288
105490
  }
105289
105491
 
105290
105492
  // src/shared/ripgrep-cli.ts
@@ -105320,15 +105522,15 @@ function getOpenCodeBundledRg() {
105320
105522
  const isWindows2 = process.platform === "win32";
105321
105523
  const rgName = isWindows2 ? "rg.exe" : "rg";
105322
105524
  const candidates = [
105323
- join82(getOpenCodeCacheDir(), "bin", rgName),
105324
- join82(getDataDir(), "opencode", "bin", rgName),
105325
- join82(execDir, rgName),
105326
- join82(execDir, "bin", rgName),
105327
- join82(execDir, "..", "bin", rgName),
105328
- join82(execDir, "..", "libexec", rgName)
105525
+ join83(getOpenCodeCacheDir(), "bin", rgName),
105526
+ join83(getDataDir(), "opencode", "bin", rgName),
105527
+ join83(execDir, rgName),
105528
+ join83(execDir, "bin", rgName),
105529
+ join83(execDir, "..", "bin", rgName),
105530
+ join83(execDir, "..", "libexec", rgName)
105329
105531
  ];
105330
105532
  for (const candidate of candidates) {
105331
- if (existsSync77(candidate)) {
105533
+ if (existsSync78(candidate)) {
105332
105534
  return candidate;
105333
105535
  }
105334
105536
  }
@@ -106071,10 +106273,13 @@ function formatSlashCommand(command) {
106071
106273
  return lines.join(`
106072
106274
  `);
106073
106275
  }
106074
- function formatCombinedDescription(skills2, commands2) {
106075
- const availableSkills = skills2 ?? [];
106276
+ function formatCombinedDescription(skills2, commands2, options = {}) {
106277
+ const availableSkills = options.includeSkills ? skills2 ?? [] : [];
106076
106278
  const availableCommands = commands2 ?? [];
106077
106279
  if (availableSkills.length === 0 && availableCommands.length === 0) {
106280
+ if ((skills2?.length ?? 0) > 0) {
106281
+ return TOOL_DESCRIPTION_PREFIX;
106282
+ }
106078
106283
  return TOOL_DESCRIPTION_NO_SKILLS;
106079
106284
  }
106080
106285
  const availableItems = [
@@ -106086,7 +106291,7 @@ function formatCombinedDescription(skills2, commands2) {
106086
106291
  }
106087
106292
  return `${TOOL_DESCRIPTION_PREFIX}
106088
106293
  <available_items>
106089
- Priority: project > user > opencode > builtin/plugin | Skills listed before commands
106294
+ Priority: project > user > opencode > builtin/plugin${options.includeSkills ? " | Skills listed before commands" : ""}
106090
106295
  Invoke via: skill(name="item-name") - omit leading slash for commands.
106091
106296
  ${availableItems.join(`
106092
106297
  `)}
@@ -106328,7 +106533,9 @@ function createSkillTool(options) {
106328
106533
  const commands2 = getCommands();
106329
106534
  const publicSkills = skills2.filter((s) => !s.definition.agent);
106330
106535
  const skillInfos = publicSkills.map(loadedSkillToInfo);
106331
- cachedDescription = formatCombinedDescription(skillInfos, commands2);
106536
+ cachedDescription = formatCombinedDescription(skillInfos, commands2, {
106537
+ includeSkills: options.includeSkillsInDescription
106538
+ });
106332
106539
  return cachedDescription;
106333
106540
  };
106334
106541
  if (options.skills !== undefined) {
@@ -106346,12 +106553,16 @@ function createSkillTool(options) {
106346
106553
  }
106347
106554
  } catch {}
106348
106555
  }
106349
- cachedDescription = formatCombinedDescription(skillInfos, commandsForDescription);
106556
+ cachedDescription = formatCombinedDescription(skillInfos, commandsForDescription, {
106557
+ includeSkills: options.includeSkillsInDescription
106558
+ });
106350
106559
  if (needsAsyncRefresh) {
106351
106560
  buildDescription(true);
106352
106561
  }
106353
106562
  } else if (options.commands !== undefined) {
106354
- cachedDescription = formatCombinedDescription([], options.commands);
106563
+ cachedDescription = formatCombinedDescription([], options.commands, {
106564
+ includeSkills: options.includeSkillsInDescription
106565
+ });
106355
106566
  }
106356
106567
  return tool({
106357
106568
  get description() {
@@ -106367,7 +106578,9 @@ function createSkillTool(options) {
106367
106578
  async execute(args, ctx) {
106368
106579
  const skills2 = await getSkills(ctx);
106369
106580
  const commands2 = getCommands();
106370
- cachedDescription = formatCombinedDescription(skills2.map(loadedSkillToInfo), commands2);
106581
+ cachedDescription = formatCombinedDescription(skills2.map(loadedSkillToInfo), commands2, {
106582
+ includeSkills: options.includeSkillsInDescription
106583
+ });
106371
106584
  const requestedName = args.name.replace(/^\//, "");
106372
106585
  const matchedSkill = matchSkillByName(skills2, requestedName);
106373
106586
  if (matchedSkill) {
@@ -106428,9 +106641,9 @@ var skill = createSkillTool({ directory: process.cwd() });
106428
106641
  // src/tools/session-manager/constants.ts
106429
106642
  init_shared();
106430
106643
  init_shared();
106431
- import { join as join83 } from "path";
106432
- var TODO_DIR2 = join83(getClaudeConfigDir(), "todos");
106433
- var TRANSCRIPT_DIR2 = join83(getClaudeConfigDir(), "transcripts");
106644
+ import { join as join84 } from "path";
106645
+ var TODO_DIR2 = join84(getClaudeConfigDir(), "todos");
106646
+ var TRANSCRIPT_DIR2 = join84(getClaudeConfigDir(), "transcripts");
106434
106647
  var SESSION_LIST_DESCRIPTION = `List all OpenCode sessions with optional filtering.
106435
106648
 
106436
106649
  Returns a list of available session IDs with metadata including message count, date range, and agents used.
@@ -106507,12 +106720,12 @@ init_opencode_storage_detection();
106507
106720
  init_shared();
106508
106721
 
106509
106722
  // src/tools/session-manager/file-storage.ts
106510
- import { existsSync as existsSync78 } from "fs";
106723
+ import { existsSync as existsSync79 } from "fs";
106511
106724
  import { readdir as readdir5, readFile as readFile8 } from "fs/promises";
106512
- import { join as join84 } from "path";
106725
+ import { join as join85 } from "path";
106513
106726
  init_opencode_message_dir();
106514
106727
  async function getFileMainSessions(directory) {
106515
- if (!existsSync78(SESSION_STORAGE))
106728
+ if (!existsSync79(SESSION_STORAGE))
106516
106729
  return [];
106517
106730
  const sessions = [];
106518
106731
  try {
@@ -106520,13 +106733,13 @@ async function getFileMainSessions(directory) {
106520
106733
  for (const projectDir of projectDirs) {
106521
106734
  if (!projectDir.isDirectory())
106522
106735
  continue;
106523
- const projectPath = join84(SESSION_STORAGE, projectDir.name);
106736
+ const projectPath = join85(SESSION_STORAGE, projectDir.name);
106524
106737
  const sessionFiles = await readdir5(projectPath);
106525
106738
  for (const file of sessionFiles) {
106526
106739
  if (!file.endsWith(".json"))
106527
106740
  continue;
106528
106741
  try {
106529
- const content = await readFile8(join84(projectPath, file), "utf-8");
106742
+ const content = await readFile8(join85(projectPath, file), "utf-8");
106530
106743
  const meta = JSON.parse(content);
106531
106744
  if (meta.parentID)
106532
106745
  continue;
@@ -106544,7 +106757,7 @@ async function getFileMainSessions(directory) {
106544
106757
  return sessions.sort((a, b) => b.time.updated - a.time.updated);
106545
106758
  }
106546
106759
  async function getFileAllSessions() {
106547
- if (!existsSync78(MESSAGE_STORAGE))
106760
+ if (!existsSync79(MESSAGE_STORAGE))
106548
106761
  return [];
106549
106762
  const sessions = [];
106550
106763
  async function scanDirectory(dir) {
@@ -106553,7 +106766,7 @@ async function getFileAllSessions() {
106553
106766
  for (const entry of entries) {
106554
106767
  if (!entry.isDirectory())
106555
106768
  continue;
106556
- const sessionPath = join84(dir, entry.name);
106769
+ const sessionPath = join85(dir, entry.name);
106557
106770
  const files = await readdir5(sessionPath);
106558
106771
  if (files.some((file) => file.endsWith(".json"))) {
106559
106772
  sessions.push(entry.name);
@@ -106573,7 +106786,7 @@ async function fileSessionExists(sessionID) {
106573
106786
  }
106574
106787
  async function getFileSessionMessages(sessionID) {
106575
106788
  const messageDir = getMessageDir(sessionID);
106576
- if (!messageDir || !existsSync78(messageDir))
106789
+ if (!messageDir || !existsSync79(messageDir))
106577
106790
  return [];
106578
106791
  const messages = [];
106579
106792
  try {
@@ -106582,7 +106795,7 @@ async function getFileSessionMessages(sessionID) {
106582
106795
  if (!file.endsWith(".json"))
106583
106796
  continue;
106584
106797
  try {
106585
- const content = await readFile8(join84(messageDir, file), "utf-8");
106798
+ const content = await readFile8(join85(messageDir, file), "utf-8");
106586
106799
  const meta = JSON.parse(content);
106587
106800
  const parts = await readParts2(meta.id);
106588
106801
  messages.push({
@@ -106608,8 +106821,8 @@ async function getFileSessionMessages(sessionID) {
106608
106821
  });
106609
106822
  }
106610
106823
  async function readParts2(messageID) {
106611
- const partDir = join84(PART_STORAGE, messageID);
106612
- if (!existsSync78(partDir))
106824
+ const partDir = join85(PART_STORAGE, messageID);
106825
+ if (!existsSync79(partDir))
106613
106826
  return [];
106614
106827
  const parts = [];
106615
106828
  try {
@@ -106618,7 +106831,7 @@ async function readParts2(messageID) {
106618
106831
  if (!file.endsWith(".json"))
106619
106832
  continue;
106620
106833
  try {
106621
- const content = await readFile8(join84(partDir, file), "utf-8");
106834
+ const content = await readFile8(join85(partDir, file), "utf-8");
106622
106835
  parts.push(JSON.parse(content));
106623
106836
  } catch {
106624
106837
  continue;
@@ -106630,14 +106843,14 @@ async function readParts2(messageID) {
106630
106843
  return parts.sort((a, b) => a.id.localeCompare(b.id));
106631
106844
  }
106632
106845
  async function getFileSessionTodos(sessionID) {
106633
- if (!existsSync78(TODO_DIR2))
106846
+ if (!existsSync79(TODO_DIR2))
106634
106847
  return [];
106635
106848
  try {
106636
106849
  const allFiles = await readdir5(TODO_DIR2);
106637
106850
  const todoFiles = allFiles.filter((file) => file === `${sessionID}.json`);
106638
106851
  for (const file of todoFiles) {
106639
106852
  try {
106640
- const content = await readFile8(join84(TODO_DIR2, file), "utf-8");
106853
+ const content = await readFile8(join85(TODO_DIR2, file), "utf-8");
106641
106854
  const data = JSON.parse(content);
106642
106855
  if (!Array.isArray(data))
106643
106856
  continue;
@@ -106657,10 +106870,10 @@ async function getFileSessionTodos(sessionID) {
106657
106870
  return [];
106658
106871
  }
106659
106872
  async function getFileSessionTranscript(sessionID) {
106660
- if (!existsSync78(TRANSCRIPT_DIR2))
106873
+ if (!existsSync79(TRANSCRIPT_DIR2))
106661
106874
  return 0;
106662
- const transcriptFile = join84(TRANSCRIPT_DIR2, `${sessionID}.jsonl`);
106663
- if (!existsSync78(transcriptFile))
106875
+ const transcriptFile = join85(TRANSCRIPT_DIR2, `${sessionID}.jsonl`);
106876
+ if (!existsSync79(transcriptFile))
106664
106877
  return 0;
106665
106878
  try {
106666
106879
  const content = await readFile8(transcriptFile, "utf-8");
@@ -108465,25 +108678,25 @@ init_session_tools_store();
108465
108678
  init_file_utils2();
108466
108679
  init_shared();
108467
108680
  init_opencode_config_dir();
108468
- import { existsSync as existsSync81, readdirSync as readdirSync23 } from "fs";
108469
- import { join as join85 } from "path";
108681
+ import { existsSync as existsSync82, readdirSync as readdirSync23 } from "fs";
108682
+ import { join as join86 } from "path";
108470
108683
 
108471
108684
  // src/features/claude-code-agent-loader/agent-definitions-loader.ts
108472
108685
  init_frontmatter2();
108473
108686
  init_logger();
108474
- import { existsSync as existsSync80, readFileSync as readFileSync57 } from "fs";
108687
+ import { existsSync as existsSync81, readFileSync as readFileSync58 } from "fs";
108475
108688
  import { basename as basename12, extname as extname3 } from "path";
108476
108689
 
108477
108690
  // src/features/claude-code-agent-loader/json-agent-loader.ts
108478
108691
  init_jsonc_parser2();
108479
108692
  init_claude_model_mapper();
108480
- import { existsSync as existsSync79, readFileSync as readFileSync56 } from "fs";
108693
+ import { existsSync as existsSync80, readFileSync as readFileSync57 } from "fs";
108481
108694
  function parseJsonAgentFile(filePath, scope) {
108482
108695
  try {
108483
- if (!existsSync79(filePath)) {
108696
+ if (!existsSync80(filePath)) {
108484
108697
  return null;
108485
108698
  }
108486
- const content = readFileSync56(filePath, "utf-8");
108699
+ const content = readFileSync57(filePath, "utf-8");
108487
108700
  const { data } = parseJsoncSafe(content);
108488
108701
  if (!data) {
108489
108702
  return null;
@@ -108520,10 +108733,10 @@ function parseJsonAgentFile(filePath, scope) {
108520
108733
  init_claude_model_mapper();
108521
108734
  function parseMarkdownAgentFile(filePath, scope) {
108522
108735
  try {
108523
- if (!existsSync80(filePath)) {
108736
+ if (!existsSync81(filePath)) {
108524
108737
  return null;
108525
108738
  }
108526
- const content = readFileSync57(filePath, "utf-8");
108739
+ const content = readFileSync58(filePath, "utf-8");
108527
108740
  const { data, body } = parseFrontmatter(content);
108528
108741
  const fileName = basename12(filePath);
108529
108742
  const agentName = fileName.replace(/\.md$/i, "");
@@ -108555,7 +108768,7 @@ function parseMarkdownAgentFile(filePath, scope) {
108555
108768
  function loadAgentDefinitions(paths, scope) {
108556
108769
  const result = Object.create(null);
108557
108770
  for (const filePath of paths) {
108558
- if (!existsSync80(filePath)) {
108771
+ if (!existsSync81(filePath)) {
108559
108772
  log(`[agent-definitions-loader] File not found, skipping: ${filePath}`);
108560
108773
  continue;
108561
108774
  }
@@ -108580,7 +108793,7 @@ function loadAgentDefinitions(paths, scope) {
108580
108793
 
108581
108794
  // src/features/claude-code-agent-loader/loader.ts
108582
108795
  function loadAgentsFromDir(agentsDir, scope) {
108583
- if (!existsSync81(agentsDir)) {
108796
+ if (!existsSync82(agentsDir)) {
108584
108797
  return [];
108585
108798
  }
108586
108799
  const entries = readdirSync23(agentsDir, { withFileTypes: true });
@@ -108588,7 +108801,7 @@ function loadAgentsFromDir(agentsDir, scope) {
108588
108801
  for (const entry of entries) {
108589
108802
  if (!isMarkdownFile(entry))
108590
108803
  continue;
108591
- const agentPath = join85(agentsDir, entry.name);
108804
+ const agentPath = join86(agentsDir, entry.name);
108592
108805
  const agent = parseMarkdownAgentFile(agentPath, scope);
108593
108806
  if (agent) {
108594
108807
  agents.push(agent);
@@ -108597,7 +108810,7 @@ function loadAgentsFromDir(agentsDir, scope) {
108597
108810
  return agents;
108598
108811
  }
108599
108812
  function loadUserAgents() {
108600
- const userAgentsDir = join85(getClaudeConfigDir(), "agents");
108813
+ const userAgentsDir = join86(getClaudeConfigDir(), "agents");
108601
108814
  const agents = loadAgentsFromDir(userAgentsDir, "user");
108602
108815
  const result = Object.create(null);
108603
108816
  for (const agent of agents) {
@@ -108606,7 +108819,7 @@ function loadUserAgents() {
108606
108819
  return result;
108607
108820
  }
108608
108821
  function loadProjectAgents(directory) {
108609
- const projectAgentsDir = join85(directory ?? process.cwd(), ".claude", "agents");
108822
+ const projectAgentsDir = join86(directory ?? process.cwd(), ".claude", "agents");
108610
108823
  const agents = loadAgentsFromDir(projectAgentsDir, "project");
108611
108824
  const result = Object.create(null);
108612
108825
  for (const agent of agents) {
@@ -108618,7 +108831,7 @@ function loadOpencodeGlobalAgents() {
108618
108831
  const result = Object.create(null);
108619
108832
  const configDirs = getOpenCodeConfigDirs({ binary: "opencode" });
108620
108833
  for (const configDir of configDirs) {
108621
- const opencodeAgentsDir = join85(configDir, "agents");
108834
+ const opencodeAgentsDir = join86(configDir, "agents");
108622
108835
  const agents = loadAgentsFromDir(opencodeAgentsDir, "opencode");
108623
108836
  for (const agent of agents) {
108624
108837
  if (!(agent.name in result)) {
@@ -108629,7 +108842,7 @@ function loadOpencodeGlobalAgents() {
108629
108842
  return result;
108630
108843
  }
108631
108844
  function loadOpencodeProjectAgents(directory) {
108632
- const opencodeProjectDir = join85(directory ?? process.cwd(), ".opencode", "agents");
108845
+ const opencodeProjectDir = join86(directory ?? process.cwd(), ".opencode", "agents");
108633
108846
  const agents = loadAgentsFromDir(opencodeProjectDir, "opencode-project");
108634
108847
  const result = Object.create(null);
108635
108848
  for (const agent of agents) {
@@ -108641,16 +108854,16 @@ function loadOpencodeProjectAgents(directory) {
108641
108854
  init_opencode_config_dir();
108642
108855
  init_jsonc_parser2();
108643
108856
  init_resolve_agent_definition_paths();
108644
- import * as fs21 from "fs";
108645
- import * as path17 from "path";
108857
+ import * as fs22 from "fs";
108858
+ import * as path18 from "path";
108646
108859
  init_claude_model_mapper();
108647
- function getConfigPaths3(directory) {
108860
+ function getConfigPaths4(directory) {
108648
108861
  const globalConfigDir = getOpenCodeConfigDir({ binary: "opencode" });
108649
108862
  const paths = [
108650
- path17.join(directory, ".opencode", "opencode.json"),
108651
- path17.join(directory, ".opencode", "opencode.jsonc"),
108652
- path17.join(globalConfigDir, "opencode.json"),
108653
- path17.join(globalConfigDir, "opencode.jsonc")
108863
+ path18.join(directory, ".opencode", "opencode.json"),
108864
+ path18.join(directory, ".opencode", "opencode.jsonc"),
108865
+ path18.join(globalConfigDir, "opencode.json"),
108866
+ path18.join(globalConfigDir, "opencode.jsonc")
108654
108867
  ];
108655
108868
  return paths;
108656
108869
  }
@@ -108679,15 +108892,15 @@ function convertInlineAgent(agentData) {
108679
108892
  }
108680
108893
  function readOpencodeConfigAgents(directory) {
108681
108894
  const result = Object.create(null);
108682
- for (const configPath of getConfigPaths3(directory)) {
108895
+ for (const configPath of getConfigPaths4(directory)) {
108683
108896
  try {
108684
- if (!fs21.existsSync(configPath))
108897
+ if (!fs22.existsSync(configPath))
108685
108898
  continue;
108686
- const content = fs21.readFileSync(configPath, "utf-8");
108899
+ const content = fs22.readFileSync(configPath, "utf-8");
108687
108900
  const parseResult = parseJsoncSafe(content);
108688
108901
  if (!parseResult.data)
108689
108902
  continue;
108690
- const configDir = path17.dirname(configPath);
108903
+ const configDir = path18.dirname(configPath);
108691
108904
  const agentsToLoad = parseResult.data.agents || parseResult.data.agent;
108692
108905
  if (agentsToLoad && typeof agentsToLoad === "object") {
108693
108906
  for (const [agentName, agentData] of Object.entries(agentsToLoad)) {
@@ -109383,9 +109596,9 @@ import { pathToFileURL } from "url";
109383
109596
  // src/tools/look-at/image-converter.ts
109384
109597
  init_shared();
109385
109598
  import * as childProcess2 from "child_process";
109386
- import { existsSync as existsSync83, mkdtempSync, readFileSync as readFileSync59, rmSync as rmSync4, unlinkSync as unlinkSync14, writeFileSync as writeFileSync19 } from "fs";
109599
+ import { existsSync as existsSync84, mkdtempSync, readFileSync as readFileSync60, rmSync as rmSync4, unlinkSync as unlinkSync14, writeFileSync as writeFileSync19 } from "fs";
109387
109600
  import { tmpdir as tmpdir7 } from "os";
109388
- import { dirname as dirname31, join as join87 } from "path";
109601
+ import { dirname as dirname31, join as join88 } from "path";
109389
109602
  var SUPPORTED_FORMATS = new Set([
109390
109603
  "image/jpeg",
109391
109604
  "image/png",
@@ -109423,11 +109636,11 @@ function needsConversion(mimeType) {
109423
109636
  return mimeType.startsWith("image/");
109424
109637
  }
109425
109638
  function convertImageToJpeg(inputPath, mimeType) {
109426
- if (!existsSync83(inputPath)) {
109639
+ if (!existsSync84(inputPath)) {
109427
109640
  throw new Error(`File not found: ${inputPath}`);
109428
109641
  }
109429
- const tempDir = mkdtempSync(join87(tmpdir7(), "opencode-img-"));
109430
- const outputPath = join87(tempDir, "converted.jpg");
109642
+ const tempDir = mkdtempSync(join88(tmpdir7(), "opencode-img-"));
109643
+ const outputPath = join88(tempDir, "converted.jpg");
109431
109644
  log(`[image-converter] Converting ${mimeType} to JPEG: ${inputPath}`);
109432
109645
  try {
109433
109646
  if (process.platform === "darwin") {
@@ -109437,7 +109650,7 @@ function convertImageToJpeg(inputPath, mimeType) {
109437
109650
  encoding: "utf-8",
109438
109651
  timeout: CONVERSION_TIMEOUT_MS
109439
109652
  });
109440
- if (existsSync83(outputPath)) {
109653
+ if (existsSync84(outputPath)) {
109441
109654
  log(`[image-converter] Converted using sips: ${outputPath}`);
109442
109655
  return outputPath;
109443
109656
  }
@@ -109452,7 +109665,7 @@ function convertImageToJpeg(inputPath, mimeType) {
109452
109665
  encoding: "utf-8",
109453
109666
  timeout: CONVERSION_TIMEOUT_MS
109454
109667
  });
109455
- if (existsSync83(outputPath)) {
109668
+ if (existsSync84(outputPath)) {
109456
109669
  log(`[image-converter] Converted using ImageMagick: ${outputPath}`);
109457
109670
  return outputPath;
109458
109671
  }
@@ -109465,7 +109678,7 @@ function convertImageToJpeg(inputPath, mimeType) {
109465
109678
  ` + ` RHEL/CentOS: sudo yum install ImageMagick`);
109466
109679
  } catch (error) {
109467
109680
  try {
109468
- if (existsSync83(outputPath)) {
109681
+ if (existsSync84(outputPath)) {
109469
109682
  unlinkSync14(outputPath);
109470
109683
  }
109471
109684
  } catch {}
@@ -109479,11 +109692,11 @@ function convertImageToJpeg(inputPath, mimeType) {
109479
109692
  function cleanupConvertedImage(filePath) {
109480
109693
  try {
109481
109694
  const tempDirectory = dirname31(filePath);
109482
- if (existsSync83(filePath)) {
109695
+ if (existsSync84(filePath)) {
109483
109696
  unlinkSync14(filePath);
109484
109697
  log(`[image-converter] Cleaned up temporary file: ${filePath}`);
109485
109698
  }
109486
- if (existsSync83(tempDirectory)) {
109699
+ if (existsSync84(tempDirectory)) {
109487
109700
  rmSync4(tempDirectory, { recursive: true, force: true });
109488
109701
  log(`[image-converter] Cleaned up temporary directory: ${tempDirectory}`);
109489
109702
  }
@@ -109492,9 +109705,9 @@ function cleanupConvertedImage(filePath) {
109492
109705
  }
109493
109706
  }
109494
109707
  function convertBase64ImageToJpeg(base64Data, mimeType) {
109495
- const tempDir = mkdtempSync(join87(tmpdir7(), "opencode-b64-"));
109708
+ const tempDir = mkdtempSync(join88(tmpdir7(), "opencode-b64-"));
109496
109709
  const inputExt = mimeType.split("/")[1] || "bin";
109497
- const inputPath = join87(tempDir, `input.${inputExt}`);
109710
+ const inputPath = join88(tempDir, `input.${inputExt}`);
109498
109711
  const tempFiles = [inputPath];
109499
109712
  try {
109500
109713
  const cleanBase64 = base64Data.replace(/^data:[^;]+;base64,/, "");
@@ -109503,14 +109716,14 @@ function convertBase64ImageToJpeg(base64Data, mimeType) {
109503
109716
  log(`[image-converter] Converting Base64 ${mimeType} to JPEG`);
109504
109717
  const outputPath = convertImageToJpeg(inputPath, mimeType);
109505
109718
  tempFiles.push(outputPath);
109506
- const convertedBuffer = readFileSync59(outputPath);
109719
+ const convertedBuffer = readFileSync60(outputPath);
109507
109720
  const convertedBase64 = convertedBuffer.toString("base64");
109508
109721
  log(`[image-converter] Base64 conversion successful`);
109509
109722
  return { base64: convertedBase64, tempFiles };
109510
109723
  } catch (error) {
109511
109724
  tempFiles.forEach((file) => {
109512
109725
  try {
109513
- if (existsSync83(file))
109726
+ if (existsSync84(file))
109514
109727
  unlinkSync14(file);
109515
109728
  } catch {}
109516
109729
  });
@@ -109649,13 +109862,68 @@ function asSessionMessage(value) {
109649
109862
  function getCreatedTime(message) {
109650
109863
  return message.info?.time?.created ?? 0;
109651
109864
  }
109865
+ function asText(value) {
109866
+ return typeof value === "string" && value.trim().length > 0 ? value : undefined;
109867
+ }
109868
+ function collectContentText(value) {
109869
+ const directText = asText(value);
109870
+ if (directText)
109871
+ return [directText];
109872
+ if (!Array.isArray(value))
109873
+ return [];
109874
+ const texts = [];
109875
+ for (const block of value) {
109876
+ if (!isObject2(block))
109877
+ continue;
109878
+ const text = asText(block["text"]) ?? asText(block["content"]);
109879
+ if (text)
109880
+ texts.push(text);
109881
+ }
109882
+ return texts;
109883
+ }
109884
+ function normalizeThinkingText(text) {
109885
+ const answerMatches = [...text.matchAll(/<answer\b[^>]*>([\s\S]*?)<\/answer>/gi)].map((match) => match[1]?.trim()).filter((value) => Boolean(value));
109886
+ const withoutThinking = text.replace(/<think\b[^>]*>[\s\S]*?<\/think>/gi, "").trim();
109887
+ const normalized = answerMatches.length > 0 ? answerMatches.join(`
109888
+ `) : withoutThinking;
109889
+ return normalized.length > 0 ? normalized : null;
109890
+ }
109652
109891
  function getTextParts(message) {
109653
109892
  if (!Array.isArray(message.parts))
109654
109893
  return [];
109655
109894
  return message.parts.filter((part) => isObject2(part)).map((part) => ({
109656
109895
  type: typeof part["type"] === "string" ? part["type"] : undefined,
109657
- text: typeof part["text"] === "string" ? part["text"] : undefined
109658
- })).filter((part) => part.type === "text" && Boolean(part.text));
109896
+ text: typeof part["text"] === "string" ? part["text"] : undefined,
109897
+ content: part["content"],
109898
+ reasoning: typeof part["reasoning"] === "string" ? part["reasoning"] : undefined,
109899
+ reasoningContent: typeof part["reasoning_content"] === "string" ? part["reasoning_content"] : undefined
109900
+ }));
109901
+ }
109902
+ function extractTextFromParts(parts) {
109903
+ const textCandidates = [];
109904
+ const reasoningCandidates = [];
109905
+ for (const part of parts) {
109906
+ const contentTexts = collectContentText(part.content);
109907
+ const directText = asText(part.text);
109908
+ if (part.type === "text") {
109909
+ if (directText)
109910
+ textCandidates.push(directText);
109911
+ textCandidates.push(...contentTexts);
109912
+ } else if (part.type === "reasoning" || part.type === "thinking") {
109913
+ if (directText)
109914
+ reasoningCandidates.push(directText);
109915
+ textCandidates.push(...contentTexts);
109916
+ }
109917
+ const reasoningText = asText(part.reasoningContent) ?? asText(part.reasoning);
109918
+ if (reasoningText)
109919
+ reasoningCandidates.push(reasoningText);
109920
+ }
109921
+ const primaryText = textCandidates.map(normalizeThinkingText).filter((text) => text !== null).join(`
109922
+ `);
109923
+ if (primaryText)
109924
+ return primaryText;
109925
+ return reasoningCandidates.map(normalizeThinkingText).filter((text) => text !== null).join(`
109926
+ `) || null;
109659
109927
  }
109660
109928
  function extractLatestAssistantText(messages) {
109661
109929
  return extractLatestAssistantOutcome(messages).text;
@@ -109671,9 +109939,7 @@ function extractLatestAssistantOutcome(messages) {
109671
109939
  if (!lastAssistantMessage) {
109672
109940
  return { text: null, errorName: null, hasAssistant, completed: false };
109673
109941
  }
109674
- const textParts = getTextParts(lastAssistantMessage);
109675
- const text = textParts.map((part) => part.text).join(`
109676
- `) || null;
109942
+ const text = extractTextFromParts(getTextParts(lastAssistantMessage));
109677
109943
  const allParts = Array.isArray(lastAssistantMessage.parts) ? lastAssistantMessage.parts : [];
109678
109944
  const errorPart = allParts.find((part) => isObject2(part) && typeof part["type"] === "string" && part["type"] === "error");
109679
109945
  const errorName = errorPart && typeof errorPart["error"] === "string" ? errorPart["error"] : null;
@@ -110071,9 +110337,9 @@ function getMissingFilePathFromError(error) {
110071
110337
  if (!(error instanceof Error)) {
110072
110338
  return null;
110073
110339
  }
110074
- const path18 = Reflect.get(error, "path");
110075
- if (typeof path18 === "string" && path18.length > 0) {
110076
- return path18;
110340
+ const path19 = Reflect.get(error, "path");
110341
+ if (typeof path19 === "string" && path19.length > 0) {
110342
+ return path19;
110077
110343
  }
110078
110344
  if (error instanceof Error) {
110079
110345
  const match = /open '([^']+)'/.exec(error.message);
@@ -113048,7 +113314,7 @@ function isExplicitSyncRun(runInBackground) {
113048
113314
  // src/tools/delegate-task/index.ts
113049
113315
  init_constants();
113050
113316
  // src/tools/task/task-create.ts
113051
- import { join as join89 } from "path";
113317
+ import { join as join90 } from "path";
113052
113318
 
113053
113319
  // src/tools/task/types.ts
113054
113320
  import { z as z37 } from "zod";
@@ -113104,18 +113370,18 @@ var TaskDeleteInputSchema = z37.object({
113104
113370
 
113105
113371
  // src/features/claude-tasks/storage.ts
113106
113372
  init_opencode_config_dir();
113107
- import { join as join88, dirname as dirname32, basename as basename14, isAbsolute as isAbsolute17 } from "path";
113108
- import { existsSync as existsSync84, mkdirSync as mkdirSync18, readFileSync as readFileSync60, writeFileSync as writeFileSync20, renameSync as renameSync6, unlinkSync as unlinkSync15, readdirSync as readdirSync24 } from "fs";
113373
+ import { join as join89, dirname as dirname32, basename as basename14, isAbsolute as isAbsolute17 } from "path";
113374
+ import { existsSync as existsSync85, mkdirSync as mkdirSync18, readFileSync as readFileSync61, writeFileSync as writeFileSync20, renameSync as renameSync6, unlinkSync as unlinkSync15, readdirSync as readdirSync24 } from "fs";
113109
113375
  import { randomUUID as randomUUID5 } from "crypto";
113110
113376
  function getTaskDir(config = {}) {
113111
113377
  const tasksConfig = config.sisyphus?.tasks;
113112
113378
  const storagePath = tasksConfig?.storage_path;
113113
113379
  if (storagePath) {
113114
- return isAbsolute17(storagePath) ? storagePath : join88(process.cwd(), storagePath);
113380
+ return isAbsolute17(storagePath) ? storagePath : join89(process.cwd(), storagePath);
113115
113381
  }
113116
113382
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
113117
113383
  const listId = resolveTaskListId(config);
113118
- return join88(configDir, "tasks", listId);
113384
+ return join89(configDir, "tasks", listId);
113119
113385
  }
113120
113386
  function sanitizePathSegment(value) {
113121
113387
  return value.replace(/[^a-zA-Z0-9_-]/g, "-") || "default";
@@ -113133,16 +113399,16 @@ function resolveTaskListId(config = {}) {
113133
113399
  return sanitizePathSegment(basename14(process.cwd()));
113134
113400
  }
113135
113401
  function ensureDir(dirPath) {
113136
- if (!existsSync84(dirPath)) {
113402
+ if (!existsSync85(dirPath)) {
113137
113403
  mkdirSync18(dirPath, { recursive: true });
113138
113404
  }
113139
113405
  }
113140
113406
  function readJsonSafe(filePath, schema2) {
113141
113407
  try {
113142
- if (!existsSync84(filePath)) {
113408
+ if (!existsSync85(filePath)) {
113143
113409
  return null;
113144
113410
  }
113145
- const content = readFileSync60(filePath, "utf-8");
113411
+ const content = readFileSync61(filePath, "utf-8");
113146
113412
  const parsed = JSON.parse(content);
113147
113413
  const result = schema2.safeParse(parsed);
113148
113414
  if (!result.success) {
@@ -113162,7 +113428,7 @@ function writeJsonAtomic(filePath, data) {
113162
113428
  renameSync6(tempPath, filePath);
113163
113429
  } catch (error) {
113164
113430
  try {
113165
- if (existsSync84(tempPath)) {
113431
+ if (existsSync85(tempPath)) {
113166
113432
  unlinkSync15(tempPath);
113167
113433
  }
113168
113434
  } catch {}
@@ -113174,7 +113440,7 @@ function generateTaskId() {
113174
113440
  return `T-${randomUUID5()}`;
113175
113441
  }
113176
113442
  function acquireLock2(dirPath) {
113177
- const lockPath = join88(dirPath, ".lock");
113443
+ const lockPath = join89(dirPath, ".lock");
113178
113444
  const lockId = randomUUID5();
113179
113445
  const createLock = (timestamp2) => {
113180
113446
  writeFileSync20(lockPath, JSON.stringify({ id: lockId, timestamp: timestamp2 }), {
@@ -113184,7 +113450,7 @@ function acquireLock2(dirPath) {
113184
113450
  };
113185
113451
  const isStale = () => {
113186
113452
  try {
113187
- const lockContent = readFileSync60(lockPath, "utf-8");
113453
+ const lockContent = readFileSync61(lockPath, "utf-8");
113188
113454
  const lockData = JSON.parse(lockContent);
113189
113455
  const lockAge = Date.now() - lockData.timestamp;
113190
113456
  return lockAge > STALE_LOCK_THRESHOLD_MS;
@@ -113222,9 +113488,9 @@ function acquireLock2(dirPath) {
113222
113488
  acquired: true,
113223
113489
  release: () => {
113224
113490
  try {
113225
- if (!existsSync84(lockPath))
113491
+ if (!existsSync85(lockPath))
113226
113492
  return;
113227
- const lockContent = readFileSync60(lockPath, "utf-8");
113493
+ const lockContent = readFileSync61(lockPath, "utf-8");
113228
113494
  const lockData = JSON.parse(lockContent);
113229
113495
  if (lockData.id !== lockId)
113230
113496
  return;
@@ -113387,7 +113653,7 @@ async function handleCreate(args, config, ctx, context) {
113387
113653
  threadID: context.sessionID
113388
113654
  };
113389
113655
  const validatedTask = TaskObjectSchema.parse(task);
113390
- writeJsonAtomic(join89(taskDir, `${taskId}.json`), validatedTask);
113656
+ writeJsonAtomic(join90(taskDir, `${taskId}.json`), validatedTask);
113391
113657
  await syncTaskTodoUpdate(ctx, validatedTask, context.sessionID);
113392
113658
  return JSON.stringify({
113393
113659
  task: {
@@ -113409,7 +113675,7 @@ async function handleCreate(args, config, ctx, context) {
113409
113675
  }
113410
113676
  }
113411
113677
  // src/tools/task/task-get.ts
113412
- import { join as join90 } from "path";
113678
+ import { join as join91 } from "path";
113413
113679
  var TASK_ID_PATTERN = /^T-[A-Za-z0-9-]+$/;
113414
113680
  function parseTaskId(id) {
113415
113681
  if (!TASK_ID_PATTERN.test(id))
@@ -113434,7 +113700,7 @@ Returns null if the task does not exist or the file is invalid.`,
113434
113700
  return JSON.stringify({ error: "invalid_task_id" });
113435
113701
  }
113436
113702
  const taskDir = getTaskDir(config);
113437
- const taskPath = join90(taskDir, `${taskId}.json`);
113703
+ const taskPath = join91(taskDir, `${taskId}.json`);
113438
113704
  const task = readJsonSafe(taskPath, TaskObjectSchema);
113439
113705
  return JSON.stringify({ task: task ?? null });
113440
113706
  } catch (error) {
@@ -113447,8 +113713,8 @@ Returns null if the task does not exist or the file is invalid.`,
113447
113713
  });
113448
113714
  }
113449
113715
  // src/tools/task/task-list.ts
113450
- import { join as join91 } from "path";
113451
- import { existsSync as existsSync85, readdirSync as readdirSync25 } from "fs";
113716
+ import { join as join92 } from "path";
113717
+ import { existsSync as existsSync86, readdirSync as readdirSync25 } from "fs";
113452
113718
  function createTaskList(config) {
113453
113719
  return tool({
113454
113720
  description: `List all active tasks with summary information.
@@ -113459,7 +113725,7 @@ Returns summary format: id, subject, status, owner, blockedBy (not full descript
113459
113725
  args: {},
113460
113726
  execute: async () => {
113461
113727
  const taskDir = getTaskDir(config);
113462
- if (!existsSync85(taskDir)) {
113728
+ if (!existsSync86(taskDir)) {
113463
113729
  return JSON.stringify({ tasks: [] });
113464
113730
  }
113465
113731
  const files = readdirSync25(taskDir).filter((f) => f.endsWith(".json") && f.startsWith("T-")).map((f) => f.replace(".json", ""));
@@ -113468,7 +113734,7 @@ Returns summary format: id, subject, status, owner, blockedBy (not full descript
113468
113734
  }
113469
113735
  const allTasks = [];
113470
113736
  for (const fileId of files) {
113471
- const task = readJsonSafe(join91(taskDir, `${fileId}.json`), TaskObjectSchema);
113737
+ const task = readJsonSafe(join92(taskDir, `${fileId}.json`), TaskObjectSchema);
113472
113738
  if (task) {
113473
113739
  allTasks.push(task);
113474
113740
  }
@@ -113496,7 +113762,7 @@ Returns summary format: id, subject, status, owner, blockedBy (not full descript
113496
113762
  });
113497
113763
  }
113498
113764
  // src/tools/task/task-update.ts
113499
- import { join as join92 } from "path";
113765
+ import { join as join93 } from "path";
113500
113766
  var TASK_ID_PATTERN2 = /^T-[A-Za-z0-9-]+$/;
113501
113767
  function parseTaskId2(id) {
113502
113768
  if (!TASK_ID_PATTERN2.test(id))
@@ -113544,7 +113810,7 @@ async function handleUpdate(args, config, ctx, context) {
113544
113810
  return JSON.stringify({ error: "task_lock_unavailable" });
113545
113811
  }
113546
113812
  try {
113547
- const taskPath = join92(taskDir, `${taskId}.json`);
113813
+ const taskPath = join93(taskDir, `${taskId}.json`);
113548
113814
  const task = readJsonSafe(taskPath, TaskObjectSchema);
113549
113815
  if (!task) {
113550
113816
  return JSON.stringify({ error: "task_not_found" });
@@ -113602,10 +113868,10 @@ init_bun_file_shim();
113602
113868
  // src/tools/hashline-edit/formatter-trigger.ts
113603
113869
  init_shared();
113604
113870
  init_bun_spawn_shim();
113605
- import path18 from "path";
113871
+ import path19 from "path";
113606
113872
  var cachedFormattersByDirectory = new Map;
113607
113873
  function getFormatterCacheKey(directory) {
113608
- return path18.resolve(directory);
113874
+ return path19.resolve(directory);
113609
113875
  }
113610
113876
  async function resolveFormatters(client, directory) {
113611
113877
  const cacheKey = getFormatterCacheKey(directory);
@@ -113656,7 +113922,7 @@ function buildFormatterCommand(command, filePath) {
113656
113922
  return command.map((arg) => arg.replace(/\$FILE/g, filePath));
113657
113923
  }
113658
113924
  async function runFormattersForFile(client, directory, filePath) {
113659
- const ext = path18.extname(filePath);
113925
+ const ext = path19.extname(filePath);
113660
113926
  if (!ext)
113661
113927
  return;
113662
113928
  const formatters = await resolveFormatters(client, directory);
@@ -113976,17 +114242,17 @@ function buildMemberPromptBody(member, text) {
113976
114242
  // src/features/team-mode/team-mailbox/reservation.ts
113977
114243
  init_paths();
113978
114244
  import { mkdir as mkdir3, readdir as readdir6, rename as rename2, stat as stat5 } from "fs/promises";
113979
- import path19 from "path";
114245
+ import path20 from "path";
113980
114246
  var RESERVED_PREFIX = ".delivering-";
113981
114247
  var RESERVED_SUFFIX = ".json";
113982
114248
  function isMissingPathError(error) {
113983
114249
  return error instanceof Error && "code" in error && error.code === "ENOENT";
113984
114250
  }
113985
114251
  function buildReservation(inboxDir, messageId) {
113986
- const inboxPath = path19.join(inboxDir, `${messageId}.json`);
113987
- const reservedPath = path19.join(inboxDir, `${RESERVED_PREFIX}${messageId}${RESERVED_SUFFIX}`);
113988
- const processedDir = path19.join(inboxDir, "processed");
113989
- const processedPath = path19.join(processedDir, `${messageId}.json`);
114252
+ const inboxPath = path20.join(inboxDir, `${messageId}.json`);
114253
+ const reservedPath = path20.join(inboxDir, `${RESERVED_PREFIX}${messageId}${RESERVED_SUFFIX}`);
114254
+ const processedDir = path20.join(inboxDir, "processed");
114255
+ const processedPath = path20.join(processedDir, `${messageId}.json`);
113990
114256
  return { reservedPath, inboxPath, processedPath, processedDir };
113991
114257
  }
113992
114258
  async function reserveMessageForDelivery(teamRunId, recipientName, messageId, config) {
@@ -114022,7 +114288,7 @@ init_store();
114022
114288
  init_locks();
114023
114289
  import { Buffer as Buffer2 } from "buffer";
114024
114290
  import { mkdir as mkdir4, readdir as readdir7, stat as stat6 } from "fs/promises";
114025
- import path20 from "path";
114291
+ import path21 from "path";
114026
114292
 
114027
114293
  class BroadcastNotPermittedError extends Error {
114028
114294
  constructor(message = "broadcast requires lead role") {
@@ -114091,7 +114357,7 @@ async function getUnreadSizeBytes(inboxDir) {
114091
114357
  return !entry.name.startsWith(".");
114092
114358
  });
114093
114359
  const sizes = await Promise.all(unreadEntries.map(async (entry) => {
114094
- const fileStats = await stat6(path20.join(inboxDir, entry.name));
114360
+ const fileStats = await stat6(path21.join(inboxDir, entry.name));
114095
114361
  return fileStats.size;
114096
114362
  }));
114097
114363
  return sizes.reduce((totalBytes, fileSize) => totalBytes + fileSize, 0);
@@ -114137,8 +114403,8 @@ async function sendMessage(message, teamRunId, config, context) {
114137
114403
  if (nextUnreadSizeBytes > config.recipient_unread_max_bytes) {
114138
114404
  throw new RecipientBackpressureError;
114139
114405
  }
114140
- const unreservedPath = path20.join(inboxDir, `${message.messageId}.json`);
114141
- const reservedPath = path20.join(inboxDir, `.delivering-${message.messageId}.json`);
114406
+ const unreservedPath = path21.join(inboxDir, `${message.messageId}.json`);
114407
+ const reservedPath = path21.join(inboxDir, `.delivering-${message.messageId}.json`);
114142
114408
  if (await fileExists(unreservedPath) || await fileExists(reservedPath)) {
114143
114409
  throw new DuplicateMessageIdError;
114144
114410
  }
@@ -114892,8 +115158,8 @@ function createUnstableAgentBabysitter(args) {
114892
115158
  directory: ctx.directory,
114893
115159
  client: {
114894
115160
  session: {
114895
- messages: async ({ path: path21 }) => {
114896
- const result = await ctx.client.session.messages({ path: path21 });
115161
+ messages: async ({ path: path22 }) => {
115162
+ const result = await ctx.client.session.messages({ path: path22 });
114897
115163
  if (Array.isArray(result))
114898
115164
  return result;
114899
115165
  if (typeof result === "object" && result !== null) {
@@ -115052,7 +115318,7 @@ function createHooks(args) {
115052
115318
  };
115053
115319
  }
115054
115320
  // src/features/background-agent/manager.ts
115055
- import { join as join94 } from "path";
115321
+ import { join as join95 } from "path";
115056
115322
  init_shared();
115057
115323
  init_event_session_id();
115058
115324
  init_session_category_registry();
@@ -115332,8 +115598,8 @@ Use \`background_output(task_id="${task.id}")\` to retrieve this result when rea
115332
115598
  }
115333
115599
 
115334
115600
  // src/features/background-agent/compaction-aware-message-resolver.ts
115335
- import { readdirSync as readdirSync26, readFileSync as readFileSync61 } from "fs";
115336
- import { join as join93 } from "path";
115601
+ import { readdirSync as readdirSync26, readFileSync as readFileSync62 } from "fs";
115602
+ import { join as join94 } from "path";
115337
115603
  init_compaction_marker();
115338
115604
  init_compaction_marker();
115339
115605
  function hasFullAgentAndModel(message) {
@@ -115414,7 +115680,7 @@ function findNearestMessageExcludingCompaction(messageDir, sessionID) {
115414
115680
  const messages = [];
115415
115681
  for (const file of files) {
115416
115682
  try {
115417
- const content = readFileSync61(join93(messageDir, file), "utf-8");
115683
+ const content = readFileSync62(join94(messageDir, file), "utf-8");
115418
115684
  const parsed = JSON.parse(content);
115419
115685
  if (hasCompactionPartInStorage(parsed.id) || isCompactionAgent(parsed.agent)) {
115420
115686
  continue;
@@ -115454,6 +115720,16 @@ class ConcurrencyManager {
115454
115720
  }
115455
115721
  return 5;
115456
115722
  }
115723
+ getConcurrencyKey(model) {
115724
+ if (this.config?.modelConcurrency?.[model] !== undefined) {
115725
+ return model;
115726
+ }
115727
+ const provider = model.split("/")[0];
115728
+ if (provider && this.config?.providerConcurrency?.[provider] !== undefined) {
115729
+ return provider;
115730
+ }
115731
+ return model;
115732
+ }
115457
115733
  async acquire(model) {
115458
115734
  const limit = this.getConcurrencyLimit(model);
115459
115735
  if (limit === Infinity) {
@@ -115488,6 +115764,9 @@ class ConcurrencyManager {
115488
115764
  const queue = this.queues.get(model);
115489
115765
  while (queue && queue.length > 0) {
115490
115766
  const next = queue.shift();
115767
+ if (!next) {
115768
+ continue;
115769
+ }
115491
115770
  if (!next.settled) {
115492
115771
  next.resolve();
115493
115772
  return;
@@ -115681,7 +115960,8 @@ async function tryFallbackRetry(args) {
115681
115960
  });
115682
115961
  throw new TeamModeFallbackError(`team-mode fallback denied: cannot preserve team context for task ${task.id} (teamRunId=${task.teamRunId})`);
115683
115962
  }
115684
- const key = task.model ? `${task.model.providerID}/${task.model.modelID}` : task.agent;
115963
+ const rawKey = task.model ? `${task.model.providerID}/${task.model.modelID}` : task.agent;
115964
+ const key = concurrencyManager.getConcurrencyKey(rawKey);
115685
115965
  const queue = queuesByKey.get(key) ?? [];
115686
115966
  const retryInput = {
115687
115967
  description: task.description,
@@ -116337,8 +116617,13 @@ function scheduleForcedExit(cleanupResult, exitCode, exitAfterCleanup = false) {
116337
116617
  }
116338
116618
  });
116339
116619
  }
116620
+ var _shutdownInProgress = false;
116621
+ function markShutdownStarted() {
116622
+ _shutdownInProgress = true;
116623
+ }
116340
116624
  function registerProcessSignal(signal, handler, exitAfter) {
116341
116625
  const listener = () => {
116626
+ markShutdownStarted();
116342
116627
  const cleanupResult = handler();
116343
116628
  if (exitAfter) {
116344
116629
  scheduleForcedExit(cleanupResult, 0, true);
@@ -116365,11 +116650,32 @@ function describeProcessCleanupError(error) {
116365
116650
  }
116366
116651
  return { raw: String(error) };
116367
116652
  }
116653
+ var HARMLESS_SHUTDOWN_ERRNO_CODES = new Set(["EPIPE", "ECONNRESET"]);
116654
+ var STDIO_WRITE_FDS = new Set([1, 2]);
116655
+ function isStdioWriteError(error) {
116656
+ const syscall = error.syscall;
116657
+ const fd = error.fd;
116658
+ return syscall === "write" && typeof fd === "number" && STDIO_WRITE_FDS.has(fd);
116659
+ }
116660
+ function isHarmlessShutdownError(error) {
116661
+ if (!error || typeof error !== "object")
116662
+ return false;
116663
+ const code = error.code;
116664
+ if (typeof code !== "string")
116665
+ return false;
116666
+ if (!HARMLESS_SHUTDOWN_ERRNO_CODES.has(code))
116667
+ return false;
116668
+ if (isStdioWriteError(error))
116669
+ return true;
116670
+ return _shutdownInProgress;
116671
+ }
116368
116672
  function registerErrorEvent(signal) {
116369
116673
  let logging = false;
116370
116674
  const listener = (error) => {
116371
116675
  if (logging)
116372
116676
  return;
116677
+ if (isHarmlessShutdownError(error))
116678
+ return;
116373
116679
  logging = true;
116374
116680
  log(`[background-agent] ${signal} observed; keeping host alive and skipping cleanup (signal handlers run on real shutdown)`, describeProcessCleanupError(error));
116375
116681
  logging = false;
@@ -116394,9 +116700,13 @@ function registerManagerForCleanup(manager) {
116394
116700
  for (const m of cleanupManagers) {
116395
116701
  try {
116396
116702
  promises.push(Promise.resolve(m.shutdown()).catch((error) => {
116703
+ if (isHarmlessShutdownError(error))
116704
+ return;
116397
116705
  log("[background-agent] Error during async shutdown cleanup:", error);
116398
116706
  }));
116399
116707
  } catch (error) {
116708
+ if (isHarmlessShutdownError(error))
116709
+ continue;
116400
116710
  log("[background-agent] Error during shutdown cleanup:", error);
116401
116711
  }
116402
116712
  }
@@ -118089,10 +118399,8 @@ The fallback retry session is now created and can be inspected directly.
118089
118399
  };
118090
118400
  }
118091
118401
  getConcurrencyKeyFromInput(input) {
118092
- if (input.model) {
118093
- return `${input.model.providerID}/${input.model.modelID}`;
118094
- }
118095
- return input.agent;
118402
+ const modelKey = input.model ? `${input.model.providerID}/${input.model.modelID}` : input.agent;
118403
+ return this.concurrencyManager.getConcurrencyKey(modelKey);
118096
118404
  }
118097
118405
  async trackTask(input) {
118098
118406
  const existingTask = this.tasks.get(input.taskId);
@@ -118106,7 +118414,7 @@ The fallback retry session is now created and can be inspected directly.
118106
118414
  existingTask.parentAgent = input.parentAgent;
118107
118415
  }
118108
118416
  if (!existingTask.concurrencyGroup) {
118109
- existingTask.concurrencyGroup = input.concurrencyKey ?? existingTask.agent;
118417
+ existingTask.concurrencyGroup = input.concurrencyKey ? this.concurrencyManager.getConcurrencyKey(input.concurrencyKey) : existingTask.agent;
118110
118418
  }
118111
118419
  if (existingTask.sessionId) {
118112
118420
  subagentSessions.add(existingTask.sessionId);
@@ -118122,9 +118430,10 @@ The fallback retry session is now created and can be inspected directly.
118122
118430
  log("[background-agent] External task already registered:", { taskId: existingTask.id, sessionID: existingTask.sessionId, status: existingTask.status });
118123
118431
  return existingTask;
118124
118432
  }
118125
- const concurrencyGroup = input.concurrencyKey ?? input.agent ?? "task";
118126
- if (input.concurrencyKey) {
118127
- await this.concurrencyManager.acquire(input.concurrencyKey);
118433
+ const concurrencyKey = input.concurrencyKey ? this.concurrencyManager.getConcurrencyKey(input.concurrencyKey) : undefined;
118434
+ const concurrencyGroup = concurrencyKey ?? input.agent ?? "task";
118435
+ if (concurrencyKey) {
118436
+ await this.concurrencyManager.acquire(concurrencyKey);
118128
118437
  }
118129
118438
  const task = {
118130
118439
  id: input.taskId,
@@ -118141,7 +118450,7 @@ The fallback retry session is now created and can be inspected directly.
118141
118450
  lastUpdate: new Date
118142
118451
  },
118143
118452
  parentAgent: input.parentAgent,
118144
- concurrencyKey: input.concurrencyKey,
118453
+ concurrencyKey,
118145
118454
  concurrencyGroup
118146
118455
  };
118147
118456
  this.addTask(task);
@@ -118177,7 +118486,7 @@ The fallback retry session is now created and can be inspected directly.
118177
118486
  clearTimeout(completionTimer);
118178
118487
  this.completionTimers.delete(existingTask.id);
118179
118488
  }
118180
- const concurrencyKey = existingTask.concurrencyGroup ?? existingTask.agent;
118489
+ const concurrencyKey = this.concurrencyManager.getConcurrencyKey(existingTask.concurrencyGroup ?? existingTask.agent);
118181
118490
  await this.concurrencyManager.acquire(concurrencyKey);
118182
118491
  existingTask.concurrencyKey = concurrencyKey;
118183
118492
  existingTask.concurrencyGroup = concurrencyKey;
@@ -119203,7 +119512,7 @@ The task was re-queued on a fallback model after a retryable failure.
119203
119512
  parentSessionID: task.parentSessionId
119204
119513
  });
119205
119514
  }
119206
- const messageDir = join94(MESSAGE_STORAGE, task.parentSessionId);
119515
+ const messageDir = join95(MESSAGE_STORAGE, task.parentSessionId);
119207
119516
  const currentMessage = messageDir ? findNearestMessageExcludingCompaction(messageDir, task.parentSessionId) : null;
119208
119517
  agent = currentMessage?.agent ?? task.parentAgent;
119209
119518
  model = currentMessage?.model?.providerID && currentMessage?.model?.modelID ? { providerID: currentMessage.model.providerID, modelID: currentMessage.model.modelID } : undefined;
@@ -119546,11 +119855,11 @@ The task was re-queued on a fallback model after a retryable failure.
119546
119855
  }
119547
119856
  // src/features/mcp-oauth/storage.ts
119548
119857
  init_shared();
119549
- import { chmodSync as chmodSync2, existsSync as existsSync86, mkdirSync as mkdirSync19, readFileSync as readFileSync62, renameSync as renameSync7, unlinkSync as unlinkSync16, writeFileSync as writeFileSync21 } from "fs";
119550
- import { dirname as dirname33, join as join95 } from "path";
119858
+ import { chmodSync as chmodSync2, existsSync as existsSync87, mkdirSync as mkdirSync19, readFileSync as readFileSync63, renameSync as renameSync7, unlinkSync as unlinkSync16, writeFileSync as writeFileSync21 } from "fs";
119859
+ import { dirname as dirname33, join as join96 } from "path";
119551
119860
  var STORAGE_FILE_NAME = "mcp-oauth.json";
119552
119861
  function getMcpOauthStoragePath() {
119553
- return join95(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
119862
+ return join96(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
119554
119863
  }
119555
119864
  function normalizeHost(serverHost) {
119556
119865
  let host = serverHost.trim();
@@ -119587,11 +119896,11 @@ function buildKey(serverHost, resource) {
119587
119896
  }
119588
119897
  function readStore() {
119589
119898
  const filePath = getMcpOauthStoragePath();
119590
- if (!existsSync86(filePath)) {
119899
+ if (!existsSync87(filePath)) {
119591
119900
  return null;
119592
119901
  }
119593
119902
  try {
119594
- const content = readFileSync62(filePath, "utf-8");
119903
+ const content = readFileSync63(filePath, "utf-8");
119595
119904
  return JSON.parse(content);
119596
119905
  } catch {
119597
119906
  return null;
@@ -119601,7 +119910,7 @@ function writeStore(store2) {
119601
119910
  const filePath = getMcpOauthStoragePath();
119602
119911
  try {
119603
119912
  const dir = dirname33(filePath);
119604
- if (!existsSync86(dir)) {
119913
+ if (!existsSync87(dir)) {
119605
119914
  mkdirSync19(dir, { recursive: true });
119606
119915
  }
119607
119916
  const tempPath = `${filePath}.tmp.${Date.now()}`;
@@ -125490,8 +125799,33 @@ async function executeActions(actions, ctx) {
125490
125799
  // src/features/tmux-subagent/polling-manager.ts
125491
125800
  init_tmux();
125492
125801
  init_shared();
125493
- init_shared();
125494
125802
  init_event_session_id();
125803
+
125804
+ // src/features/tmux-subagent/session-status-parser.ts
125805
+ function parseSessionStatusResponse(response) {
125806
+ if (typeof response === "object" && response !== null && "data" in response) {
125807
+ return parseSessionStatusMap(response.data);
125808
+ }
125809
+ return parseSessionStatusMap(response);
125810
+ }
125811
+ function parseSessionStatusMap(data) {
125812
+ if (typeof data !== "object" || data === null)
125813
+ return {};
125814
+ const record3 = data;
125815
+ const result = {};
125816
+ for (const [sessionId, value] of Object.entries(record3)) {
125817
+ if (typeof value !== "object" || value === null)
125818
+ continue;
125819
+ const valueRecord = value;
125820
+ const type2 = valueRecord["type"];
125821
+ if (typeof type2 !== "string")
125822
+ continue;
125823
+ result[sessionId] = { type: type2 };
125824
+ }
125825
+ return result;
125826
+ }
125827
+
125828
+ // src/features/tmux-subagent/polling-manager.ts
125495
125829
  var MIN_STABILITY_TIME_MS3 = 10 * 1000;
125496
125830
  var STABLE_POLLS_REQUIRED = 3;
125497
125831
 
@@ -125547,7 +125881,7 @@ class TmuxPollingManager {
125547
125881
  }
125548
125882
  await this.activateFocusedPanes();
125549
125883
  const statusResult = await this.client.session.status({ path: undefined });
125550
- const allStatuses = normalizeSDKResponse(statusResult, {});
125884
+ const allStatuses = parseSessionStatusResponse(statusResult);
125551
125885
  log("[tmux-session-manager] pollSessions", {
125552
125886
  trackedSessions: Array.from(this.sessions.keys()),
125553
125887
  allStatusKeys: Object.keys(allStatuses)
@@ -125594,7 +125928,7 @@ class TmuxPollingManager {
125594
125928
  if ((tracked.stableIdlePolls ?? 0) >= STABLE_POLLS_REQUIRED) {
125595
125929
  const stableWindowActivityVersion = tracked.observedIdleActivityVersion ?? activityVersion;
125596
125930
  const recheckResult = await this.client.session.status({ path: undefined });
125597
- const recheckStatuses = normalizeSDKResponse(recheckResult, {});
125931
+ const recheckStatuses = parseSessionStatusResponse(recheckResult);
125598
125932
  const recheckStatus = recheckStatuses[sessionId];
125599
125933
  const latestTracked = this.sessions.get(sessionId) ?? tracked;
125600
125934
  const recheckActivityVersion = latestTracked.activityVersion ?? 0;
@@ -125735,36 +126069,18 @@ init_tmux();
125735
126069
  init_shared();
125736
126070
 
125737
126071
  // src/features/tmux-subagent/attachable-session-status.ts
125738
- var ATTACHABLE_SESSION_STATUSES = ["idle", "running", "busy"];
126072
+ var ATTACHABLE_SESSION_STATUSES = ["idle", "running", "busy", "retry"];
125739
126073
  function isAttachableSessionStatus(status) {
125740
126074
  return ATTACHABLE_SESSION_STATUSES.some((attachableSessionStatus) => attachableSessionStatus === status);
125741
126075
  }
125742
126076
 
125743
- // src/features/tmux-subagent/session-status-parser.ts
125744
- function parseSessionStatusMap(data) {
125745
- if (typeof data !== "object" || data === null)
125746
- return {};
125747
- const record3 = data;
125748
- const result = {};
125749
- for (const [sessionId, value] of Object.entries(record3)) {
125750
- if (typeof value !== "object" || value === null)
125751
- continue;
125752
- const valueRecord = value;
125753
- const type2 = valueRecord["type"];
125754
- if (typeof type2 !== "string")
125755
- continue;
125756
- result[sessionId] = { type: type2 };
125757
- }
125758
- return result;
125759
- }
125760
-
125761
126077
  // src/features/tmux-subagent/session-ready-waiter.ts
125762
126078
  async function waitForSessionReady(params) {
125763
126079
  const startTime = Date.now();
125764
126080
  while (Date.now() - startTime < SESSION_READY_TIMEOUT_MS) {
125765
126081
  try {
125766
126082
  const statusResult = await params.client.session.status({ path: undefined });
125767
- const allStatuses = parseSessionStatusMap(statusResult.data);
126083
+ const allStatuses = parseSessionStatusResponse(statusResult);
125768
126084
  const sessionStatus = allStatuses[params.sessionId]?.type;
125769
126085
  if (isAttachableSessionStatus(sessionStatus)) {
125770
126086
  log("[tmux-session-manager] session ready", {
@@ -126273,7 +126589,7 @@ class TmuxSessionManager {
126273
126589
  async getSessionStatusType(sessionId) {
126274
126590
  try {
126275
126591
  const statusResult = await this.client.session.status({ path: undefined });
126276
- const allStatuses = parseSessionStatusMap(statusResult.data);
126592
+ const allStatuses = parseSessionStatusResponse(statusResult);
126277
126593
  return allStatuses[sessionId]?.type;
126278
126594
  } catch (error) {
126279
126595
  this.deps.log("[tmux-session-manager] failed to read session status before spawn", {
@@ -127179,14 +127495,14 @@ async function isTmuxAvailable() {
127179
127495
  }
127180
127496
 
127181
127497
  // src/openclaw/reply-listener.ts
127182
- import { dirname as dirname35, join as join98 } from "path";
127498
+ import { dirname as dirname35, join as join99 } from "path";
127183
127499
 
127184
127500
  // src/openclaw/session-registry.ts
127185
127501
  init_data_path();
127186
127502
  import {
127187
- existsSync as existsSync87,
127503
+ existsSync as existsSync88,
127188
127504
  mkdirSync as mkdirSync20,
127189
- readFileSync as readFileSync63,
127505
+ readFileSync as readFileSync64,
127190
127506
  writeFileSync as writeFileSync22,
127191
127507
  openSync as openSync3,
127192
127508
  closeSync as closeSync3,
@@ -127195,11 +127511,11 @@ import {
127195
127511
  statSync as statSync12,
127196
127512
  constants as constants20
127197
127513
  } from "fs";
127198
- import { join as join96, dirname as dirname34 } from "path";
127514
+ import { join as join97, dirname as dirname34 } from "path";
127199
127515
  import { randomUUID as randomUUID8 } from "crypto";
127200
- var OPENCLAW_STORAGE_DIR = join96(getOpenCodeStorageDir(), "openclaw");
127201
- var REGISTRY_PATH = join96(OPENCLAW_STORAGE_DIR, "reply-session-registry.jsonl");
127202
- var REGISTRY_LOCK_PATH = join96(OPENCLAW_STORAGE_DIR, "reply-session-registry.lock");
127516
+ var OPENCLAW_STORAGE_DIR = join97(getOpenCodeStorageDir(), "openclaw");
127517
+ var REGISTRY_PATH = join97(OPENCLAW_STORAGE_DIR, "reply-session-registry.jsonl");
127518
+ var REGISTRY_LOCK_PATH = join97(OPENCLAW_STORAGE_DIR, "reply-session-registry.lock");
127203
127519
  var SECURE_FILE_MODE = 384;
127204
127520
  var MAX_AGE_MS = 24 * 60 * 60 * 1000;
127205
127521
  var LOCK_TIMEOUT_MS = 2000;
@@ -127208,7 +127524,7 @@ var LOCK_RETRY_MS2 = 20;
127208
127524
  var LOCK_STALE_MS = 1e4;
127209
127525
  function ensureRegistryDir() {
127210
127526
  const registryDir = dirname34(REGISTRY_PATH);
127211
- if (!existsSync87(registryDir)) {
127527
+ if (!existsSync88(registryDir)) {
127212
127528
  mkdirSync20(registryDir, { recursive: true, mode: 448 });
127213
127529
  }
127214
127530
  }
@@ -127227,9 +127543,9 @@ function isPidAlive2(pid) {
127227
127543
  }
127228
127544
  function readLockSnapshot() {
127229
127545
  try {
127230
- if (!existsSync87(REGISTRY_LOCK_PATH))
127546
+ if (!existsSync88(REGISTRY_LOCK_PATH))
127231
127547
  return null;
127232
- const raw = readFileSync63(REGISTRY_LOCK_PATH, "utf-8");
127548
+ const raw = readFileSync64(REGISTRY_LOCK_PATH, "utf-8");
127233
127549
  const trimmed = raw.trim();
127234
127550
  if (!trimmed)
127235
127551
  return { raw, pid: null, token: null };
@@ -127253,9 +127569,9 @@ function readLockSnapshot() {
127253
127569
  }
127254
127570
  function removeLockIfUnchanged(snapshot) {
127255
127571
  try {
127256
- if (!existsSync87(REGISTRY_LOCK_PATH))
127572
+ if (!existsSync88(REGISTRY_LOCK_PATH))
127257
127573
  return false;
127258
- const currentRaw = readFileSync63(REGISTRY_LOCK_PATH, "utf-8");
127574
+ const currentRaw = readFileSync64(REGISTRY_LOCK_PATH, "utf-8");
127259
127575
  if (currentRaw !== snapshot.raw)
127260
127576
  return false;
127261
127577
  unlinkSync17(REGISTRY_LOCK_PATH);
@@ -127359,10 +127675,10 @@ function withRegistryLock(onLocked, onLockUnavailable) {
127359
127675
  }
127360
127676
  }
127361
127677
  function readAllMappingsUnsafe() {
127362
- if (!existsSync87(REGISTRY_PATH))
127678
+ if (!existsSync88(REGISTRY_PATH))
127363
127679
  return [];
127364
127680
  try {
127365
- const content = readFileSync63(REGISTRY_PATH, "utf-8");
127681
+ const content = readFileSync64(REGISTRY_PATH, "utf-8");
127366
127682
  return content.split(`
127367
127683
  `).filter((line) => line.trim()).map((line) => {
127368
127684
  try {
@@ -127417,7 +127733,7 @@ function removeSession(sessionId) {
127417
127733
  import {
127418
127734
  appendFileSync as appendFileSync6,
127419
127735
  chmodSync as chmodSync3,
127420
- existsSync as existsSync89,
127736
+ existsSync as existsSync90,
127421
127737
  renameSync as renameSync8,
127422
127738
  statSync as statSync13,
127423
127739
  unlinkSync as unlinkSync18,
@@ -127425,31 +127741,31 @@ import {
127425
127741
  } from "fs";
127426
127742
 
127427
127743
  // src/openclaw/reply-listener-paths.ts
127428
- import { existsSync as existsSync88, mkdirSync as mkdirSync21 } from "fs";
127744
+ import { existsSync as existsSync89, mkdirSync as mkdirSync21 } from "fs";
127429
127745
  import { homedir as homedir19 } from "os";
127430
- import { join as join97 } from "path";
127746
+ import { join as join98 } from "path";
127431
127747
  var REPLY_LISTENER_SECURE_FILE_MODE = 384;
127432
127748
  function resolveReplyListenerHomeDir() {
127433
127749
  return process.env.HOME ?? process.env.USERPROFILE ?? homedir19();
127434
127750
  }
127435
127751
  function getReplyListenerStateDir() {
127436
- return join97(resolveReplyListenerHomeDir(), ".omo", "openclaw", "state");
127752
+ return join98(resolveReplyListenerHomeDir(), ".omo", "openclaw", "state");
127437
127753
  }
127438
127754
  function getReplyListenerPidFilePath() {
127439
- return join97(getReplyListenerStateDir(), "reply-listener.pid");
127755
+ return join98(getReplyListenerStateDir(), "reply-listener.pid");
127440
127756
  }
127441
127757
  function getReplyListenerStateFilePath() {
127442
- return join97(getReplyListenerStateDir(), "reply-listener-state.json");
127758
+ return join98(getReplyListenerStateDir(), "reply-listener-state.json");
127443
127759
  }
127444
127760
  function getReplyListenerConfigFilePath() {
127445
- return join97(getReplyListenerStateDir(), "reply-listener-config.json");
127761
+ return join98(getReplyListenerStateDir(), "reply-listener-config.json");
127446
127762
  }
127447
127763
  function getReplyListenerLogFilePath() {
127448
- return join97(getReplyListenerStateDir(), "reply-listener.log");
127764
+ return join98(getReplyListenerStateDir(), "reply-listener.log");
127449
127765
  }
127450
127766
  function ensureReplyListenerStateDir() {
127451
127767
  const stateDir = getReplyListenerStateDir();
127452
- if (!existsSync88(stateDir)) {
127768
+ if (!existsSync89(stateDir)) {
127453
127769
  mkdirSync21(stateDir, { recursive: true, mode: 448 });
127454
127770
  }
127455
127771
  }
@@ -127465,13 +127781,13 @@ function writeSecureReplyListenerFile(filePath, content) {
127465
127781
  }
127466
127782
  function rotateReplyListenerLogIfNeeded(logPath) {
127467
127783
  try {
127468
- if (!existsSync89(logPath))
127784
+ if (!existsSync90(logPath))
127469
127785
  return;
127470
127786
  const stats = statSync13(logPath);
127471
127787
  if (stats.size <= MAX_REPLY_LISTENER_LOG_SIZE_BYTES)
127472
127788
  return;
127473
127789
  const backupPath = `${logPath}.old`;
127474
- if (existsSync89(backupPath)) {
127790
+ if (existsSync90(backupPath)) {
127475
127791
  unlinkSync18(backupPath);
127476
127792
  }
127477
127793
  renameSync8(logPath, backupPath);
@@ -127512,7 +127828,7 @@ class ReplyListenerRateLimiter {
127512
127828
  }
127513
127829
 
127514
127830
  // src/openclaw/reply-listener-state.ts
127515
- import { existsSync as existsSync90, readFileSync as readFileSync64, unlinkSync as unlinkSync19 } from "fs";
127831
+ import { existsSync as existsSync91, readFileSync as readFileSync65, unlinkSync as unlinkSync19 } from "fs";
127516
127832
  var REPLY_LISTENER_STARTUP_TOKEN_ENV = "OMO_OPENCLAW_REPLY_LISTENER_STARTUP_TOKEN";
127517
127833
  function createDefaultReplyListenerState() {
127518
127834
  return {
@@ -127574,9 +127890,9 @@ function createPendingReplyListenerState(startupToken) {
127574
127890
  function readReplyListenerDaemonState() {
127575
127891
  try {
127576
127892
  const stateFilePath = getReplyListenerStateFilePath();
127577
- if (!existsSync90(stateFilePath))
127893
+ if (!existsSync91(stateFilePath))
127578
127894
  return null;
127579
- return normalizeReplyListenerState(JSON.parse(readFileSync64(stateFilePath, "utf-8")));
127895
+ return normalizeReplyListenerState(JSON.parse(readFileSync65(stateFilePath, "utf-8")));
127580
127896
  } catch {
127581
127897
  return null;
127582
127898
  }
@@ -127591,9 +127907,9 @@ function writeReplyListenerDaemonState(state3) {
127591
127907
  function readReplyListenerDaemonConfig() {
127592
127908
  try {
127593
127909
  const configFilePath = getReplyListenerConfigFilePath();
127594
- if (!existsSync90(configFilePath))
127910
+ if (!existsSync91(configFilePath))
127595
127911
  return null;
127596
- return JSON.parse(readFileSync64(configFilePath, "utf-8"));
127912
+ return JSON.parse(readFileSync65(configFilePath, "utf-8"));
127597
127913
  } catch {
127598
127914
  return null;
127599
127915
  }
@@ -127604,9 +127920,9 @@ function writeReplyListenerDaemonConfig(config) {
127604
127920
  function readReplyListenerPid() {
127605
127921
  try {
127606
127922
  const pidFilePath = getReplyListenerPidFilePath();
127607
- if (!existsSync90(pidFilePath))
127923
+ if (!existsSync91(pidFilePath))
127608
127924
  return null;
127609
- const pid = Number.parseInt(readFileSync64(pidFilePath, "utf-8").trim(), 10);
127925
+ const pid = Number.parseInt(readFileSync65(pidFilePath, "utf-8").trim(), 10);
127610
127926
  return Number.isNaN(pid) ? null : pid;
127611
127927
  } catch {
127612
127928
  return null;
@@ -127617,7 +127933,7 @@ function writeReplyListenerPid(pid) {
127617
127933
  }
127618
127934
  function removeReplyListenerPid() {
127619
127935
  const pidFilePath = getReplyListenerPidFilePath();
127620
- if (existsSync90(pidFilePath)) {
127936
+ if (existsSync91(pidFilePath)) {
127621
127937
  unlinkSync19(pidFilePath);
127622
127938
  }
127623
127939
  }
@@ -127634,7 +127950,7 @@ function markReplyListenerStopped(state3, error) {
127634
127950
 
127635
127951
  // src/openclaw/reply-listener-process.ts
127636
127952
  init_bun_spawn_shim();
127637
- import { readFileSync as readFileSync65 } from "fs";
127953
+ import { readFileSync as readFileSync66 } from "fs";
127638
127954
  var REPLY_LISTENER_DAEMON_IDENTITY_MARKER = "--openclaw-reply-listener-daemon";
127639
127955
  var REPLY_LISTENER_DAEMON_ENV_ALLOWLIST = [
127640
127956
  "PATH",
@@ -127689,7 +128005,7 @@ function isReplyListenerProcessRunning(pid) {
127689
128005
  async function isReplyListenerDaemonProcess(pid) {
127690
128006
  try {
127691
128007
  if (process.platform === "linux") {
127692
- const cmdline = readFileSync65(`/proc/${pid}/cmdline`, "utf-8");
128008
+ const cmdline = readFileSync66(`/proc/${pid}/cmdline`, "utf-8");
127693
128009
  return cmdline.includes(REPLY_LISTENER_DAEMON_IDENTITY_MARKER);
127694
128010
  }
127695
128011
  const processInfo = spawn2(["ps", "-p", String(pid), "-o", "args="], {
@@ -127851,7 +128167,7 @@ async function startReplyListener(config) {
127851
128167
  pendingState.configSignature = getReplyListenerRuntimeSignature(normalizedConfig);
127852
128168
  writeReplyListenerDaemonState(pendingState);
127853
128169
  const currentFile = import.meta.url;
127854
- const daemonScript = currentFile.endsWith(".ts") ? join98(dirname35(new URL(currentFile).pathname), "daemon.ts") : join98(dirname35(new URL(currentFile).pathname), "daemon.js");
128170
+ const daemonScript = currentFile.endsWith(".ts") ? join99(dirname35(new URL(currentFile).pathname), "daemon.ts") : join99(dirname35(new URL(currentFile).pathname), "daemon.js");
127855
128171
  try {
127856
128172
  const processInfo = spawnReplyListenerDaemon(daemonScript, startupToken);
127857
128173
  processInfo.unref();
@@ -128235,21 +128551,21 @@ init_transformer();
128235
128551
  init_logger();
128236
128552
  init_scope_filter2();
128237
128553
  init_bun_file_shim();
128238
- import { existsSync as existsSync91, readFileSync as readFileSync66 } from "fs";
128239
- import { join as join99 } from "path";
128554
+ import { existsSync as existsSync92, readFileSync as readFileSync67 } from "fs";
128555
+ import { join as join100 } from "path";
128240
128556
  import { homedir as homedir20 } from "os";
128241
128557
  function getMcpConfigPaths() {
128242
128558
  const claudeConfigDir = getClaudeConfigDir();
128243
128559
  const cwd = process.cwd();
128244
128560
  return [
128245
- { path: join99(homedir20(), ".claude.json"), scope: "user" },
128246
- { path: join99(claudeConfigDir, ".mcp.json"), scope: "user" },
128247
- { path: join99(cwd, ".mcp.json"), scope: "project" },
128248
- { path: join99(cwd, ".claude", ".mcp.json"), scope: "local" }
128561
+ { path: join100(homedir20(), ".claude.json"), scope: "user" },
128562
+ { path: join100(claudeConfigDir, ".mcp.json"), scope: "user" },
128563
+ { path: join100(cwd, ".mcp.json"), scope: "project" },
128564
+ { path: join100(cwd, ".claude", ".mcp.json"), scope: "local" }
128249
128565
  ];
128250
128566
  }
128251
128567
  async function loadMcpConfigFile(filePath) {
128252
- if (!existsSync91(filePath)) {
128568
+ if (!existsSync92(filePath)) {
128253
128569
  return null;
128254
128570
  }
128255
128571
  try {
@@ -128264,11 +128580,11 @@ function getSystemMcpServerNames() {
128264
128580
  const names = new Set;
128265
128581
  const paths = getMcpConfigPaths();
128266
128582
  const cwd = process.cwd();
128267
- for (const { path: path21 } of paths) {
128268
- if (!existsSync91(path21))
128583
+ for (const { path: path22 } of paths) {
128584
+ if (!existsSync92(path22))
128269
128585
  continue;
128270
128586
  try {
128271
- const content = readFileSync66(path21, "utf-8");
128587
+ const content = readFileSync67(path22, "utf-8");
128272
128588
  const config = JSON.parse(content);
128273
128589
  if (!config?.mcpServers)
128274
128590
  continue;
@@ -128293,30 +128609,30 @@ async function loadMcpConfigs(disabledMcps = []) {
128293
128609
  const paths = getMcpConfigPaths();
128294
128610
  const disabledSet = new Set(disabledMcps);
128295
128611
  const cwd = process.cwd();
128296
- for (const { path: path21, scope } of paths) {
128297
- const config = await loadMcpConfigFile(path21);
128612
+ for (const { path: path22, scope } of paths) {
128613
+ const config = await loadMcpConfigFile(path22);
128298
128614
  if (!config?.mcpServers)
128299
128615
  continue;
128300
128616
  for (const [name, serverConfig] of Object.entries(config.mcpServers)) {
128301
128617
  if (disabledSet.has(name)) {
128302
- log(`Skipping MCP "${name}" (in disabled_mcps)`, { path: path21 });
128618
+ log(`Skipping MCP "${name}" (in disabled_mcps)`, { path: path22 });
128303
128619
  continue;
128304
128620
  }
128305
128621
  if (!shouldLoadMcpServer(serverConfig, cwd)) {
128306
128622
  log(`Skipping MCP server "${name}" because local scope does not match cwd`, {
128307
- path: path21,
128623
+ path: path22,
128308
128624
  projectPath: serverConfig.projectPath,
128309
128625
  cwd
128310
128626
  });
128311
128627
  continue;
128312
128628
  }
128313
128629
  if (serverConfig.disabled) {
128314
- log(`Disabling MCP server "${name}"`, { path: path21 });
128630
+ log(`Disabling MCP server "${name}"`, { path: path22 });
128315
128631
  delete servers[name];
128316
128632
  const existingIndex = loadedServers.findIndex((s) => s.name === name);
128317
128633
  if (existingIndex !== -1) {
128318
128634
  loadedServers.splice(existingIndex, 1);
128319
- log(`Removed previously loaded MCP server "${name}"`, { path: path21 });
128635
+ log(`Removed previously loaded MCP server "${name}"`, { path: path22 });
128320
128636
  }
128321
128637
  continue;
128322
128638
  }
@@ -128328,7 +128644,7 @@ async function loadMcpConfigs(disabledMcps = []) {
128328
128644
  loadedServers.splice(existingIndex, 1);
128329
128645
  }
128330
128646
  loadedServers.push({ name, scope, config: transformed });
128331
- log(`Loaded MCP server "${name}" from ${scope}`, { path: path21 });
128647
+ log(`Loaded MCP server "${name}" from ${scope}`, { path: path22 });
128332
128648
  } catch (error) {
128333
128649
  log(`Failed to transform MCP server "${name}"`, error);
128334
128650
  }
@@ -130108,6 +130424,8 @@ Each exploration prompt should include four fields: **CONTEXT** (what task, whic
130108
130424
 
130109
130425
  After firing exploration agents, keep the returned background task IDs (\`bg_...\`) for result collection and continuation session IDs (\`ses_...\`) for follow-ups. Continue only with non-overlapping preparation: setting up files, reading known-path files, drafting questions. If no non-overlapping work exists, end your response and wait for the completion notification; then use \`background_output(task_id="bg_...")\`, not \`task(task_id="ses_...")\`, to collect results.
130110
130426
 
130427
+ System reminders are input-only signals from the harness. Never write, quote, simulate, or pre-emptively emit \`<system-reminder>\` blocks yourself, and never call \`background_output\` merely because you imagined such a reminder. Only collect a background task after an actual harness-provided completion notification arrives.
130428
+
130111
130429
  Stop searching when you have enough context to proceed confidently, when the same information keeps appearing across sources, when two iterations yield no new useful data, or when you found a direct answer.
130112
130430
 
130113
130431
  ### Tool persistence
@@ -134617,7 +134935,7 @@ createHephaestusAgent2.mode = MODE10;
134617
134935
  // src/agents/builtin-agents/resolve-file-uri.ts
134618
134936
  init_contains_path2();
134619
134937
  init_logger();
134620
- import { existsSync as existsSync92, readFileSync as readFileSync67 } from "fs";
134938
+ import { existsSync as existsSync93, readFileSync as readFileSync68 } from "fs";
134621
134939
  import { homedir as homedir21 } from "os";
134622
134940
  import { isAbsolute as isAbsolute18, resolve as resolve25 } from "path";
134623
134941
  function resolvePromptAppend(promptAppend, configDir) {
@@ -134641,11 +134959,11 @@ function resolvePromptAppend(promptAppend, configDir) {
134641
134959
  });
134642
134960
  return `[WARNING: Path rejected: ${promptAppend} (resolved outside project root ${projectRoot}; file:// prompts must reside within the project boundary)]`;
134643
134961
  }
134644
- if (!existsSync92(filePath)) {
134962
+ if (!existsSync93(filePath)) {
134645
134963
  return `[WARNING: Could not resolve file URI: ${promptAppend}]`;
134646
134964
  }
134647
134965
  try {
134648
- return readFileSync67(filePath, "utf8");
134966
+ return readFileSync68(filePath, "utf8");
134649
134967
  } catch {
134650
134968
  return `[WARNING: Could not read file: ${promptAppend}]`;
134651
134969
  }
@@ -135921,7 +136239,7 @@ function buildAvailableSkills(discoveredSkills, browserProvider, disabledSkills,
135921
136239
  location: "plugin"
135922
136240
  }));
135923
136241
  const discoveredAvailable = discoveredSkills.filter((s) => {
135924
- if (builtinSkillNames.has(s.name) || disabledSkills?.has(s.name))
136242
+ if (disabledSkills?.has(s.name))
135925
136243
  return false;
135926
136244
  if (agentName && s.definition.agent && s.definition.agent !== agentName)
135927
136245
  return false;
@@ -135931,7 +136249,10 @@ function buildAvailableSkills(discoveredSkills, browserProvider, disabledSkills,
135931
136249
  description: skill2.definition.description ?? "",
135932
136250
  location: mapScopeToLocation(skill2.scope)
135933
136251
  }));
135934
- return [...builtinAvailable, ...discoveredAvailable];
136252
+ const skillMap = new Map;
136253
+ builtinAvailable.forEach((skill2) => skillMap.set(skill2.name, skill2));
136254
+ discoveredAvailable.forEach((skill2) => skillMap.set(skill2.name, skill2));
136255
+ return Array.from(skillMap.values());
135935
136256
  }
135936
136257
 
135937
136258
  // src/agents/builtin-agents/general-agents.ts
@@ -136806,7 +137127,7 @@ function buildPlanDemoteConfig(prometheusConfig, planOverride) {
136806
137127
  }
136807
137128
 
136808
137129
  // src/shared/host-skill-config.ts
136809
- function toStringArray(value) {
137130
+ function toStringArray2(value) {
136810
137131
  if (!Array.isArray(value))
136811
137132
  return [];
136812
137133
  return value.filter((item) => typeof item === "string").map((item) => item.trim()).filter((item) => item.length > 0);
@@ -136815,10 +137136,7 @@ function adaptHostSkillConfig(value) {
136815
137136
  if (!value || typeof value !== "object")
136816
137137
  return;
136817
137138
  const hostSkillConfig = value;
136818
- const sources = [
136819
- ...toStringArray(hostSkillConfig.paths),
136820
- ...toStringArray(hostSkillConfig.urls)
136821
- ];
137139
+ const sources = toStringArray2(hostSkillConfig.paths);
136822
137140
  if (sources.length === 0)
136823
137141
  return;
136824
137142
  return { sources };
@@ -136863,7 +137181,7 @@ async function applyAgentConfig(params) {
136863
137181
  discoverOpencodeProjectSkills(params.ctx.directory),
136864
137182
  includeClaudeSkillsForAwareness ? discoverGlobalAgentsSkills() : Promise.resolve([])
136865
137183
  ]);
136866
- const allDiscoveredSkills = [
137184
+ const allDiscoveredSkills = deduplicateSkillsByName([
136867
137185
  ...discoveredConfigSourceSkills,
136868
137186
  ...discoveredHostConfigSkills,
136869
137187
  ...discoveredOpencodeProjectSkills,
@@ -136872,7 +137190,7 @@ async function applyAgentConfig(params) {
136872
137190
  ...discoveredOpencodeGlobalSkills,
136873
137191
  ...discoveredUserSkills,
136874
137192
  ...discoveredGlobalAgentsSkills
136875
- ];
137193
+ ]);
136876
137194
  const browserProvider = params.pluginConfig.browser_automation_engine?.provider ?? "playwright";
136877
137195
  const currentModel = params.config.model;
136878
137196
  const disabledSkills = new Set(params.pluginConfig.disabled_skills ?? []);
@@ -137045,6 +137363,7 @@ async function applyAgentConfig(params) {
137045
137363
  setDefaultAgentForSort(params.config.default_agent ?? configuredDefaultAgent);
137046
137364
  }
137047
137365
  const agentResult = params.config.agent;
137366
+ clearRegisteredAgentNames();
137048
137367
  for (const name of Object.keys(agentResult)) {
137049
137368
  registerAgentName(name);
137050
137369
  }
@@ -137060,8 +137379,8 @@ init_model_sanitizer();
137060
137379
  init_file_utils2();
137061
137380
  init_shared();
137062
137381
  init_logger();
137063
- import { promises as fs22 } from "fs";
137064
- import { join as join100, basename as basename16 } from "path";
137382
+ import { promises as fs23 } from "fs";
137383
+ import { join as join101, basename as basename16 } from "path";
137065
137384
 
137066
137385
  // src/features/claude-code-command-loader/loader-cache.ts
137067
137386
  var commandLoaderCache = new Map;
@@ -137069,13 +137388,13 @@ var commandLoaderCache = new Map;
137069
137388
  // src/features/claude-code-command-loader/loader.ts
137070
137389
  async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix = "") {
137071
137390
  try {
137072
- await fs22.access(commandsDir);
137391
+ await fs23.access(commandsDir);
137073
137392
  } catch {
137074
137393
  return [];
137075
137394
  }
137076
137395
  let realPath;
137077
137396
  try {
137078
- realPath = await fs22.realpath(commandsDir);
137397
+ realPath = await fs23.realpath(commandsDir);
137079
137398
  } catch (error) {
137080
137399
  log(`Failed to resolve command directory: ${commandsDir}`, error);
137081
137400
  return [];
@@ -137086,7 +137405,7 @@ async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix
137086
137405
  visited.add(realPath);
137087
137406
  let entries;
137088
137407
  try {
137089
- entries = await fs22.readdir(commandsDir, { withFileTypes: true });
137408
+ entries = await fs23.readdir(commandsDir, { withFileTypes: true });
137090
137409
  } catch (error) {
137091
137410
  log(`Failed to read command directory: ${commandsDir}`, error);
137092
137411
  return [];
@@ -137098,7 +137417,7 @@ async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix
137098
137417
  continue;
137099
137418
  if (entry.name.startsWith("."))
137100
137419
  continue;
137101
- const subDirPath = join100(commandsDir, entry.name);
137420
+ const subDirPath = join101(commandsDir, entry.name);
137102
137421
  const subPrefix = prefix ? `${prefix}/${entry.name}` : entry.name;
137103
137422
  const subCommands = await loadCommandsFromDir(subDirPath, scope, visited, subPrefix);
137104
137423
  commands2.push(...subCommands);
@@ -137106,11 +137425,11 @@ async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix
137106
137425
  }
137107
137426
  if (!isMarkdownFile(entry))
137108
137427
  continue;
137109
- const commandPath = join100(commandsDir, entry.name);
137428
+ const commandPath = join101(commandsDir, entry.name);
137110
137429
  const baseCommandName = basename16(entry.name, ".md");
137111
137430
  const commandName = prefix ? `${prefix}/${baseCommandName}` : baseCommandName;
137112
137431
  try {
137113
- const content = await fs22.readFile(commandPath, "utf-8");
137432
+ const content = await fs23.readFile(commandPath, "utf-8");
137114
137433
  const { data, body } = parseFrontmatter(content);
137115
137434
  const wrappedTemplate = `<command-instruction>
137116
137435
  ${body.trim()}
@@ -137165,12 +137484,12 @@ function commandsToRecord(commands2) {
137165
137484
  return result;
137166
137485
  }
137167
137486
  async function loadUserCommands() {
137168
- const userCommandsDir = join100(getClaudeConfigDir(), "commands");
137487
+ const userCommandsDir = join101(getClaudeConfigDir(), "commands");
137169
137488
  const commands2 = await loadCommandsFromDir(userCommandsDir, "user");
137170
137489
  return commandsToRecord(commands2);
137171
137490
  }
137172
137491
  async function loadProjectCommands(directory) {
137173
- const projectCommandsDir = join100(directory ?? process.cwd(), ".claude", "commands");
137492
+ const projectCommandsDir = join101(directory ?? process.cwd(), ".claude", "commands");
137174
137493
  const commands2 = await loadCommandsFromDir(projectCommandsDir, "project");
137175
137494
  return commandsToRecord(commands2);
137176
137495
  }
@@ -137321,13 +137640,13 @@ var grep_app = {
137321
137640
  };
137322
137641
 
137323
137642
  // src/mcp/ast-grep.ts
137324
- import { existsSync as existsSync93 } from "fs";
137643
+ import { existsSync as existsSync94 } from "fs";
137325
137644
  import { dirname as dirname36, resolve as resolve26 } from "path";
137326
137645
  import { fileURLToPath as fileURLToPath5 } from "url";
137327
137646
 
137328
137647
  // src/mcp/cli-suffix.ts
137329
- function normalizeCliPath(path21) {
137330
- return path21.replaceAll("\\", "/");
137648
+ function normalizeCliPath(path22) {
137649
+ return path22.replaceAll("\\", "/");
137331
137650
  }
137332
137651
  function hasCliSuffix(candidatePath, suffix) {
137333
137652
  return normalizeCliPath(candidatePath).endsWith(normalizeCliPath(suffix));
@@ -137421,11 +137740,11 @@ function getModuleDirectory(moduleUrl) {
137421
137740
  }
137422
137741
  function createFallbackCandidate(resolveExecutable) {
137423
137742
  const runtime6 = resolveJavaScriptRuntime(resolveExecutable);
137424
- const path21 = resolve26(PACKAGE_REL, DIST_CLI_REL);
137425
- return { command: [runtime6.command, path21, "mcp"], path: path21, exists: runtime6.available, runtimeAvailable: runtime6.available };
137743
+ const path22 = resolve26(PACKAGE_REL, DIST_CLI_REL);
137744
+ return { command: [runtime6.command, path22, "mcp"], path: path22, exists: runtime6.available, runtimeAvailable: runtime6.available };
137426
137745
  }
137427
137746
  function resolveAstGrepCommand(options = {}) {
137428
- const pathExists = options.exists ?? existsSync93;
137747
+ const pathExists = options.exists ?? existsSync94;
137429
137748
  const resolveExecutable = options.resolveExecutable ?? resolveRuntimeExecutable;
137430
137749
  const candidates = [];
137431
137750
  const seenPaths = new Set;
@@ -137461,7 +137780,7 @@ function createAstGrepMcpConfig(options = {}) {
137461
137780
  }
137462
137781
 
137463
137782
  // src/mcp/lsp.ts
137464
- import { existsSync as existsSync94 } from "fs";
137783
+ import { existsSync as existsSync95 } from "fs";
137465
137784
  import { dirname as dirname37, resolve as resolve27 } from "path";
137466
137785
  import { fileURLToPath as fileURLToPath6 } from "url";
137467
137786
  var SUBMODULE_REL = "packages/lsp-tools-mcp";
@@ -137550,7 +137869,7 @@ function createBootstrapCandidate(root, resolveExecutable) {
137550
137869
  };
137551
137870
  }
137552
137871
  function resolveLspCommand(options = {}) {
137553
- const pathExists = options.exists ?? existsSync94;
137872
+ const pathExists = options.exists ?? existsSync95;
137554
137873
  const resolveExecutable = options.resolveExecutable ?? resolveRuntimeExecutable;
137555
137874
  const candidates = [];
137556
137875
  const seenPaths = new Set;
@@ -138082,11 +138401,25 @@ async function createSkillContext(args) {
138082
138401
  return true;
138083
138402
  });
138084
138403
  const includeClaudeSkills = pluginConfig.claude_code?.skills !== false;
138085
- const [configSourceSkills, userSkills, globalSkills, projectSkills, opencodeProjectSkills, agentsProjectSkills, agentsGlobalSkills] = await Promise.all([
138404
+ const hostSkillConfig = adaptHostSkillConfig(readOpencodeConfigSkills(directory));
138405
+ const [
138406
+ configSourceSkills,
138407
+ hostConfigSkills,
138408
+ userSkills,
138409
+ globalSkills,
138410
+ projectSkills,
138411
+ opencodeProjectSkills,
138412
+ agentsProjectSkills,
138413
+ agentsGlobalSkills
138414
+ ] = await Promise.all([
138086
138415
  discoverConfigSourceSkills({
138087
138416
  config: pluginConfig.skills,
138088
138417
  configDir: directory
138089
138418
  }),
138419
+ discoverConfigSourceSkills({
138420
+ config: hostSkillConfig,
138421
+ configDir: directory
138422
+ }),
138090
138423
  includeClaudeSkills ? discoverUserClaudeSkills() : Promise.resolve([]),
138091
138424
  discoverOpencodeGlobalSkills(),
138092
138425
  includeClaudeSkills ? discoverProjectClaudeSkills(directory) : Promise.resolve([]),
@@ -138094,7 +138427,12 @@ async function createSkillContext(args) {
138094
138427
  discoverProjectAgentsSkills(directory),
138095
138428
  discoverGlobalAgentsSkills()
138096
138429
  ]);
138097
- const filteredConfigSourceSkills = filterProviderGatedSkills(configSourceSkills, browserProvider);
138430
+ const configSkillsHostWins = new Map;
138431
+ for (const skill2 of configSourceSkills)
138432
+ configSkillsHostWins.set(skill2.name, skill2);
138433
+ for (const skill2 of hostConfigSkills)
138434
+ configSkillsHostWins.set(skill2.name, skill2);
138435
+ const filteredConfigSourceSkills = filterProviderGatedSkills(Array.from(configSkillsHostWins.values()), browserProvider);
138098
138436
  const filteredUserSkills = filterProviderGatedSkills(userSkills, browserProvider);
138099
138437
  const filteredGlobalSkills = filterProviderGatedSkills(globalSkills, browserProvider);
138100
138438
  const filteredProjectSkills = filterProviderGatedSkills(projectSkills, browserProvider);
@@ -138535,7 +138873,7 @@ async function loadTeamSpec(teamName, config, projectRoot, options) {
138535
138873
 
138536
138874
  // src/features/team-mode/team-runtime/create.ts
138537
138875
  import { access as access4, mkdir as mkdir5 } from "fs/promises";
138538
- import path21 from "path";
138876
+ import path22 from "path";
138539
138877
  init_paths();
138540
138878
  init_store();
138541
138879
  init_team_session_registry();
@@ -138809,7 +139147,7 @@ async function findExistingRuntime(spec, leadSessionId, config) {
138809
139147
  }
138810
139148
  }
138811
139149
  async function createMemberWorktree(memberWorktreePath, projectRoot) {
138812
- const absolutePath = path21.isAbsolute(memberWorktreePath) ? memberWorktreePath : path21.resolve(projectRoot, memberWorktreePath);
139150
+ const absolutePath = path22.isAbsolute(memberWorktreePath) ? memberWorktreePath : path22.resolve(projectRoot, memberWorktreePath);
138813
139151
  await mkdir5(absolutePath, { recursive: true });
138814
139152
  return absolutePath;
138815
139153
  }
@@ -139080,6 +139418,29 @@ var TeamCreateArgsSchema = z41.object({
139080
139418
  ctx.addIssue({ code: "custom", message: "Provide exactly one of teamName or inline_spec." });
139081
139419
  }
139082
139420
  });
139421
+ var TeamCreateInlineMemberToolSchema = tool.schema.object({
139422
+ name: tool.schema.string().optional().describe("Member name, kebab-case or natural text; normalized before team creation."),
139423
+ kind: tool.schema.enum(["category", "subagent_type"]).optional().describe("Member kind. Use category for category-routed workers, or subagent_type for a specific eligible agent."),
139424
+ category: tool.schema.string().optional().describe("Required for category members unless a fallback category can be inferred. Examples: quick, unspecified-low, unspecified-high, deep, ultrabrain, visual-engineering, writing, artistry, git, data-analysis."),
139425
+ subagent_type: tool.schema.string().optional().describe("Required for subagent_type members. Eligible examples: sisyphus, atlas, sisyphus-junior."),
139426
+ prompt: tool.schema.string().optional().describe("Task prompt for this member. Category members need a concrete work prompt."),
139427
+ systemPrompt: tool.schema.string().optional().describe("Legacy alias for prompt; normalized before team creation."),
139428
+ loadSkills: tool.schema.array(tool.schema.string()).optional().describe("Optional skills to load for this member."),
139429
+ role: tool.schema.string().optional().describe("Optional natural-language role used to build a prompt when prompt is omitted."),
139430
+ description: tool.schema.string().optional().describe("Optional natural-language description used to build a prompt when prompt is omitted.")
139431
+ });
139432
+ var TeamCreateInlineSpecToolSchema = tool.schema.union([
139433
+ tool.schema.object({
139434
+ name: tool.schema.string().describe("Team name, kebab-case or natural text; normalized before team creation."),
139435
+ description: tool.schema.string().optional().describe("Optional team description."),
139436
+ leadAgentId: tool.schema.string().optional().describe("Optional member name to use as team lead."),
139437
+ lead: TeamCreateInlineMemberToolSchema.optional().describe("Optional explicit lead member."),
139438
+ members: tool.schema.array(TeamCreateInlineMemberToolSchema).describe("Team members; members must be a flat array, not an object or nested groups. Provide 1-8 members."),
139439
+ teamAllowedPaths: tool.schema.array(tool.schema.string()).optional().describe("Optional paths the team may access."),
139440
+ sessionPermission: tool.schema.string().optional().describe("Optional session permission policy.")
139441
+ }),
139442
+ tool.schema.string().describe("JSON string containing the same inline team spec object.")
139443
+ ]);
139083
139444
  var TeamDeleteArgsSchema = z41.object({ teamRunId: z41.string().min(1), force: z41.boolean().optional() });
139084
139445
  var TeamShutdownRequestArgsSchema = z41.object({ teamRunId: z41.string().min(1), targetMemberName: z41.string().min(1) });
139085
139446
  var TeamApproveShutdownArgsSchema = z41.object({ teamRunId: z41.string().min(1), memberName: z41.string().min(1) });
@@ -139114,8 +139475,8 @@ function parseTeamCreateArgs(rawArgs) {
139114
139475
  }
139115
139476
  return result.data;
139116
139477
  }
139117
- function formatZodIssuePath(path22) {
139118
- return path22.length > 0 ? path22.join(".") : "<root>";
139478
+ function formatZodIssuePath(path23) {
139479
+ return path23.length > 0 ? path23.join(".") : "<root>";
139119
139480
  }
139120
139481
  function formatTeamSpecIssues(error) {
139121
139482
  return error.issues.slice(0, 5).map((issue) => `${formatZodIssuePath(issue.path)}: ${issue.message}`).join("; ");
@@ -139178,7 +139539,7 @@ function createTeamCreateTool(config, client, bgMgr, tmuxMgr, executorConfig, de
139178
139539
  description: "Create a team run from a named or inline team spec.",
139179
139540
  args: {
139180
139541
  teamName: tool.schema.string().optional().describe("Named team spec to load. Provide exactly one of teamName or inline_spec."),
139181
- inline_spec: tool.schema.unknown().optional().describe("Inline team spec object or JSON string. Provide exactly one of teamName or inline_spec."),
139542
+ inline_spec: TeamCreateInlineSpecToolSchema.optional().describe('Inline team spec object or JSON string. Provide exactly one of teamName or inline_spec; members must be a flat array, e.g. { name: "project-analysis-team", members: [{ name: "structure-analyst", category: "quick", prompt: "Analyze project structure." }] }.'),
139182
139543
  leadSessionId: tool.schema.string().optional().describe("Optional non-empty session ID override. Usually omit this and let team_create use the current session.")
139183
139544
  },
139184
139545
  async execute(rawArgs, toolContext) {
@@ -139288,7 +139649,7 @@ init_store();
139288
139649
  // src/features/team-mode/team-tasklist/list.ts
139289
139650
  init_logger();
139290
139651
  import { readdir as readdir8, readFile as readFile10 } from "fs/promises";
139291
- import path22 from "path";
139652
+ import path23 from "path";
139292
139653
 
139293
139654
  // src/features/team-mode/team-registry/index.ts
139294
139655
  init_paths();
@@ -139307,7 +139668,7 @@ async function listTasks(teamRunId, config, filter) {
139307
139668
  for (const entry of entries) {
139308
139669
  if (entry.isDirectory() || entry.name.startsWith(".") || !entry.name.endsWith(".json"))
139309
139670
  continue;
139310
- const taskPath = path22.join(tasksDirectory, entry.name);
139671
+ const taskPath = path23.join(tasksDirectory, entry.name);
139311
139672
  try {
139312
139673
  const taskContent = await readFile10(taskPath, "utf8");
139313
139674
  const parsedTask = TaskSchema.safeParse(JSON.parse(taskContent));
@@ -139339,7 +139700,7 @@ async function listTasks(teamRunId, config, filter) {
139339
139700
  // src/features/team-mode/team-runtime/status.ts
139340
139701
  init_paths();
139341
139702
  import { readdir as readdir9 } from "fs/promises";
139342
- import path23 from "path";
139703
+ import path24 from "path";
139343
139704
  function getPrimaryModelKey(bgMgr, leadSessionId) {
139344
139705
  if (!bgMgr || !leadSessionId)
139345
139706
  return;
@@ -139390,10 +139751,10 @@ async function aggregateStatus(teamRunId, config, bgMgr) {
139390
139751
  const concurrencyCounts = resolveConcurrencyCounts(teamBackgroundManager, runtimeState.leadSessionId);
139391
139752
  const teamRunIdSpecific = teamBackgroundManager?.listTasksByParentSession?.(runtimeState.leadSessionId ?? teamRunId)?.length;
139392
139753
  const baseDir = resolveBaseDir(config);
139393
- const claimsDir = path23.join(getTasksDir(baseDir, teamRunId), "claims");
139754
+ const claimsDir = path24.join(getTasksDir(baseDir, teamRunId), "claims");
139394
139755
  const staleLockEntries = await readdir9(claimsDir, { withFileTypes: true }).catch(() => []);
139395
139756
  const staleLockPaths = await Promise.all(staleLockEntries.filter((entry) => entry.isFile() && entry.name.endsWith(".lock")).map(async (entry) => {
139396
- const lockPath = path23.join(claimsDir, entry.name);
139757
+ const lockPath = path24.join(claimsDir, entry.name);
139397
139758
  return await detectStaleLock(lockPath, 300000) ? lockPath : undefined;
139398
139759
  }));
139399
139760
  return {
@@ -139492,7 +139853,7 @@ function createTeamListTool(config, client, deps = defaultDeps7) {
139492
139853
 
139493
139854
  // src/features/team-mode/team-tasklist/claim.ts
139494
139855
  import { access as access5, mkdir as mkdir6 } from "fs/promises";
139495
- import path25 from "path";
139856
+ import path26 from "path";
139496
139857
  init_locks();
139497
139858
  init_types2();
139498
139859
 
@@ -139506,11 +139867,11 @@ function canClaim(task, allTasks) {
139506
139867
 
139507
139868
  // src/features/team-mode/team-tasklist/get.ts
139508
139869
  import { readFile as readFile11 } from "fs/promises";
139509
- import path24 from "path";
139870
+ import path25 from "path";
139510
139871
  init_types2();
139511
139872
  async function getTask(teamRunId, taskId, config) {
139512
139873
  const tasksDirectory = getTasksDir(resolveBaseDir(config), teamRunId);
139513
- const taskContent = await readFile11(path24.join(tasksDirectory, `${taskId}.json`), "utf8");
139874
+ const taskContent = await readFile11(path25.join(tasksDirectory, `${taskId}.json`), "utf8");
139514
139875
  return TaskSchema.parse(JSON.parse(taskContent));
139515
139876
  }
139516
139877
 
@@ -139549,9 +139910,9 @@ class BlockedByError extends Error {
139549
139910
  async function claimTask(teamRunId, taskId, memberName, config) {
139550
139911
  const baseDirectory = resolveBaseDir(config);
139551
139912
  const tasksDirectory = getTasksDir(baseDirectory, teamRunId);
139552
- const claimsDirectory = path25.join(tasksDirectory, "claims");
139553
- const taskPath = path25.join(tasksDirectory, `${taskId}.json`);
139554
- const claimLockPath = path25.join(claimsDirectory, `${taskId}.lock`);
139913
+ const claimsDirectory = path26.join(tasksDirectory, "claims");
139914
+ const taskPath = path26.join(tasksDirectory, `${taskId}.json`);
139915
+ const claimLockPath = path26.join(claimsDirectory, `${taskId}.lock`);
139555
139916
  await mkdir6(claimsDirectory, { recursive: true, mode: 448 });
139556
139917
  const task = await getTask(teamRunId, taskId, config);
139557
139918
  if (task.status !== "pending") {
@@ -139590,7 +139951,7 @@ async function claimTask(teamRunId, taskId, memberName, config) {
139590
139951
  }
139591
139952
  // src/features/team-mode/team-tasklist/store.ts
139592
139953
  import { mkdir as mkdir7, readFile as readFile12 } from "fs/promises";
139593
- import path26 from "path";
139954
+ import path27 from "path";
139594
139955
  init_locks();
139595
139956
  init_types2();
139596
139957
  var HIGH_WATERMARK_FILE = ".highwatermark";
@@ -139607,9 +139968,9 @@ async function readHighWatermark(watermarkPath) {
139607
139968
  async function createTask(teamRunId, taskInput, config) {
139608
139969
  const tasksDirectory = getTasksDir(resolveBaseDir(config), teamRunId);
139609
139970
  await mkdir7(tasksDirectory, { recursive: true, mode: 448 });
139610
- await mkdir7(path26.join(tasksDirectory, "claims"), { recursive: true, mode: 448 });
139611
- return withLock(path26.join(tasksDirectory, ".lock"), async () => {
139612
- const watermarkPath = path26.join(tasksDirectory, HIGH_WATERMARK_FILE);
139971
+ await mkdir7(path27.join(tasksDirectory, "claims"), { recursive: true, mode: 448 });
139972
+ return withLock(path27.join(tasksDirectory, ".lock"), async () => {
139973
+ const watermarkPath = path27.join(tasksDirectory, HIGH_WATERMARK_FILE);
139613
139974
  const nextTaskId = await readHighWatermark(watermarkPath) + 1;
139614
139975
  await atomicWrite(watermarkPath, String(nextTaskId));
139615
139976
  const now = Date.now();
@@ -139620,13 +139981,13 @@ async function createTask(teamRunId, taskInput, config) {
139620
139981
  createdAt: now,
139621
139982
  updatedAt: now
139622
139983
  });
139623
- await atomicWrite(path26.join(tasksDirectory, `${task.id}.json`), `${JSON.stringify(task, null, 2)}
139984
+ await atomicWrite(path27.join(tasksDirectory, `${task.id}.json`), `${JSON.stringify(task, null, 2)}
139624
139985
  `);
139625
139986
  return task;
139626
139987
  }, { ownerTag: `create-task:${teamRunId}` });
139627
139988
  }
139628
139989
  // src/features/team-mode/team-tasklist/update.ts
139629
- import path27 from "path";
139990
+ import path28 from "path";
139630
139991
  init_locks();
139631
139992
  init_types2();
139632
139993
  var ALLOWED_TRANSITIONS = {
@@ -139675,7 +140036,7 @@ async function updateTaskStatus(teamRunId, taskId, newStatus, memberName, config
139675
140036
  updatedAt: Date.now()
139676
140037
  });
139677
140038
  const tasksDirectory = getTasksDir(resolveBaseDir(config), teamRunId);
139678
- await atomicWrite(path27.join(tasksDirectory, `${taskId}.json`), `${JSON.stringify(updatedTask, null, 2)}
140039
+ await atomicWrite(path28.join(tasksDirectory, `${taskId}.json`), `${JSON.stringify(updatedTask, null, 2)}
139679
140040
  `);
139680
140041
  return updatedTask;
139681
140042
  }
@@ -140407,8 +140768,8 @@ init_agent_display_names();
140407
140768
  // src/plugin/ultrawork-db-model-override.ts
140408
140769
  init_data_path();
140409
140770
  init_shared();
140410
- import { join as join101 } from "path";
140411
- import { existsSync as existsSync95 } from "fs";
140771
+ import { join as join102 } from "path";
140772
+ import { existsSync as existsSync96 } from "fs";
140412
140773
  async function importBunSqlite() {
140413
140774
  if (typeof globalThis.Bun === "undefined") {
140414
140775
  return null;
@@ -140421,7 +140782,7 @@ async function importBunSqlite() {
140421
140782
  }
140422
140783
  }
140423
140784
  function getDbPath() {
140424
- return join101(getDataDir(), "opencode", "opencode.db");
140785
+ return join102(getDataDir(), "opencode", "opencode.db");
140425
140786
  }
140426
140787
  var MAX_MICROTASK_RETRIES = 10;
140427
140788
  function tryUpdateMessageModel(db, messageId, targetModel, variant) {
@@ -140504,7 +140865,7 @@ function scheduleDeferredModelOverride(messageId, targetModel, variant) {
140504
140865
  return;
140505
140866
  }
140506
140867
  const dbPath = getDbPath();
140507
- if (!existsSync95(dbPath)) {
140868
+ if (!existsSync96(dbPath)) {
140508
140869
  log("[ultrawork-db-override] DB not found, skipping deferred override");
140509
140870
  return;
140510
140871
  }
@@ -141049,19 +141410,19 @@ init_session_tools_store();
141049
141410
  // src/features/team-mode/team-mailbox/ack.ts
141050
141411
  init_paths();
141051
141412
  import { mkdir as mkdir8, rename as rename3 } from "fs/promises";
141052
- import path28 from "path";
141413
+ import path29 from "path";
141053
141414
  async function ackMessages(teamRunId, memberName, messageIds, config) {
141054
141415
  const baseDir = resolveBaseDir(config);
141055
141416
  const inboxDir = getInboxDir(baseDir, teamRunId, memberName);
141056
- const processedDir = path28.join(inboxDir, "processed");
141417
+ const processedDir = path29.join(inboxDir, "processed");
141057
141418
  await mkdir8(processedDir, { recursive: true, mode: 448 });
141058
141419
  for (const messageId of messageIds) {
141059
141420
  const messageFileName = `${messageId}.json`;
141060
141421
  const sourcePaths = [
141061
- path28.join(inboxDir, messageFileName),
141062
- path28.join(inboxDir, `.delivering-${messageFileName}`)
141422
+ path29.join(inboxDir, messageFileName),
141423
+ path29.join(inboxDir, `.delivering-${messageFileName}`)
141063
141424
  ];
141064
- const targetPath = path28.join(processedDir, messageFileName);
141425
+ const targetPath = path29.join(processedDir, messageFileName);
141065
141426
  for (const sourcePath of sourcePaths) {
141066
141427
  try {
141067
141428
  await rename3(sourcePath, targetPath);
@@ -142809,9 +143170,9 @@ function createPluginInterface(args) {
142809
143170
  }
142810
143171
 
142811
143172
  // src/plugin-config.ts
142812
- import * as fs23 from "fs";
143173
+ import * as fs24 from "fs";
142813
143174
  import { homedir as homedir22 } from "os";
142814
- import * as path29 from "path";
143175
+ import * as path30 from "path";
142815
143176
  init_shared();
142816
143177
  init_plugin_identity();
142817
143178
 
@@ -142941,22 +143302,22 @@ function resolveHomeDirectory() {
142941
143302
  return process.env.HOME ?? process.env.USERPROFILE ?? homedir22();
142942
143303
  }
142943
143304
  function resolveConfigPathAfterLegacyMigration(detectedPath) {
142944
- if (!path29.basename(detectedPath).startsWith(LEGACY_CONFIG_BASENAME)) {
143305
+ if (!path30.basename(detectedPath).startsWith(LEGACY_CONFIG_BASENAME)) {
142945
143306
  return detectedPath;
142946
143307
  }
142947
143308
  const migrated = migrateLegacyConfigFile(detectedPath);
142948
- const canonicalPath = path29.join(path29.dirname(detectedPath), `${CONFIG_BASENAME}${path29.extname(detectedPath)}`);
142949
- if (migrated || fs23.existsSync(canonicalPath)) {
143309
+ const canonicalPath = path30.join(path30.dirname(detectedPath), `${CONFIG_BASENAME}${path30.extname(detectedPath)}`);
143310
+ if (migrated || fs24.existsSync(canonicalPath)) {
142950
143311
  return canonicalPath;
142951
143312
  }
142952
143313
  return detectedPath;
142953
143314
  }
142954
143315
  function loadExplicitGitMasterOverrides(configPath) {
142955
143316
  try {
142956
- if (!fs23.existsSync(configPath)) {
143317
+ if (!fs24.existsSync(configPath)) {
142957
143318
  return;
142958
143319
  }
142959
- const content = fs23.readFileSync(configPath, "utf-8");
143320
+ const content = fs24.readFileSync(configPath, "utf-8");
142960
143321
  const rawConfig = parseJsonc(content);
142961
143322
  const gitMaster = rawConfig.git_master;
142962
143323
  if (gitMaster && typeof gitMaster === "object" && !Array.isArray(gitMaster)) {
@@ -143013,8 +143374,8 @@ function parseConfigPartially(rawConfig) {
143013
143374
  }
143014
143375
  function loadConfigFromPath2(configPath, _ctx) {
143015
143376
  try {
143016
- if (fs23.existsSync(configPath)) {
143017
- const content = fs23.readFileSync(configPath, "utf-8");
143377
+ if (fs24.existsSync(configPath)) {
143378
+ const content = fs24.readFileSync(configPath, "utf-8");
143018
143379
  const rawConfig = parseJsonc(content);
143019
143380
  migrateConfigFile(configPath, rawConfig);
143020
143381
  const result = OhMyOpenCodeConfigSchema.safeParse(rawConfig);
@@ -143149,7 +143510,7 @@ function loadPluginConfig(directory, ctx) {
143149
143510
  stopDirectory
143150
143511
  });
143151
143512
  const canonicalAncestorPathsNearestFirst = ancestorConfigPathsNearestFirst.map((ancestorPath) => {
143152
- const opencodeDir = path29.dirname(ancestorPath);
143513
+ const opencodeDir = path30.dirname(ancestorPath);
143153
143514
  const ancestorDetected = detectPluginConfigFile(opencodeDir, {
143154
143515
  basenames: [CONFIG_BASENAME],
143155
143516
  legacyBasenames: [LEGACY_CONFIG_BASENAME]
@@ -143190,8 +143551,8 @@ function loadPluginConfig(directory, ctx) {
143190
143551
  const ancestorConfig = loadConfigFromPath2(ancestorPath, ctx);
143191
143552
  const ancestorOverrides = loadExplicitGitMasterOverrides(ancestorPath);
143192
143553
  if (ancestorConfig?.agent_definitions) {
143193
- const ancestorBasePath = path29.dirname(ancestorPath);
143194
- const ancestorDir = path29.dirname(ancestorBasePath);
143554
+ const ancestorBasePath = path30.dirname(ancestorPath);
143555
+ const ancestorDir = path30.dirname(ancestorBasePath);
143195
143556
  ancestorConfig.agent_definitions = resolveAgentDefinitionPaths(ancestorConfig.agent_definitions, ancestorBasePath, ancestorDir);
143196
143557
  }
143197
143558
  if (ancestorConfig) {