oh-my-opencode 3.14.0 → 3.15.1

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 (221) hide show
  1. package/README.md +14 -6
  2. package/bin/oh-my-opencode.js +11 -0
  3. package/bin/platform.js +13 -13
  4. package/bin/platform.test.ts +15 -0
  5. package/dist/agents/atlas/agent.d.ts +1 -1
  6. package/dist/agents/atlas/default-prompt-sections.d.ts +6 -0
  7. package/dist/agents/atlas/default.d.ts +0 -9
  8. package/dist/agents/atlas/gemini-prompt-sections.d.ts +6 -0
  9. package/dist/agents/atlas/gemini.d.ts +0 -9
  10. package/dist/agents/atlas/gpt-prompt-sections.d.ts +6 -0
  11. package/dist/agents/atlas/gpt.d.ts +0 -9
  12. package/dist/agents/atlas/shared-prompt.d.ts +9 -0
  13. package/dist/agents/dynamic-agent-category-skills-guide.d.ts +2 -0
  14. package/dist/agents/dynamic-agent-core-sections.d.ts +10 -0
  15. package/dist/agents/dynamic-agent-policy-sections.d.ts +6 -0
  16. package/dist/agents/dynamic-agent-prompt-builder.d.ts +5 -35
  17. package/dist/agents/dynamic-agent-prompt-types.d.ts +20 -0
  18. package/dist/agents/dynamic-agent-tool-categorization.d.ts +3 -0
  19. package/dist/agents/hephaestus/agent.d.ts +1 -1
  20. package/dist/agents/hephaestus/gpt-5-3-codex.d.ts +1 -1
  21. package/dist/agents/hephaestus/gpt.d.ts +1 -1
  22. package/dist/agents/momus.d.ts +2 -2
  23. package/dist/agents/prometheus/behavioral-summary.d.ts +1 -1
  24. package/dist/agents/prometheus/identity-constraints.d.ts +1 -1
  25. package/dist/agents/prometheus/plan-generation.d.ts +1 -1
  26. package/dist/agents/prometheus/plan-template.d.ts +1 -1
  27. package/dist/agents/sisyphus/gpt-5-4.d.ts +14 -14
  28. package/dist/agents/sisyphus/index.d.ts +1 -1
  29. package/dist/agents/sisyphus.d.ts +1 -1
  30. package/dist/agents/types.d.ts +1 -0
  31. package/dist/cli/index.js +832 -500
  32. package/dist/cli/mcp-oauth/login.d.ts +6 -1
  33. package/dist/cli/run/event-state.d.ts +0 -2
  34. package/dist/cli/run/types.d.ts +0 -1
  35. package/dist/config/schema/agent-names.d.ts +2 -0
  36. package/dist/config/schema/agent-overrides.d.ts +330 -15
  37. package/dist/config/schema/background-task.d.ts +2 -0
  38. package/dist/config/schema/categories.d.ts +44 -2
  39. package/dist/config/schema/commands.d.ts +1 -0
  40. package/dist/config/schema/experimental.d.ts +1 -0
  41. package/dist/config/schema/fallback-models.d.ts +67 -1
  42. package/dist/config/schema/hooks.d.ts +3 -0
  43. package/dist/config/schema/oh-my-opencode-config.d.ts +344 -16
  44. package/dist/config/schema/sisyphus-agent.d.ts +1 -0
  45. package/dist/config/schema/tmux.d.ts +11 -0
  46. package/dist/create-hooks.d.ts +6 -0
  47. package/dist/create-runtime-tmux-config.d.ts +9 -0
  48. package/dist/features/background-agent/abort-with-timeout.d.ts +2 -0
  49. package/dist/features/background-agent/background-task-notification-template.d.ts +10 -4
  50. package/dist/features/background-agent/constants.d.ts +1 -0
  51. package/dist/features/background-agent/fallback-retry-handler.d.ts +1 -1
  52. package/dist/features/background-agent/manager.d.ts +10 -0
  53. package/dist/features/background-agent/process-cleanup.d.ts +1 -1
  54. package/dist/features/background-agent/session-existence.d.ts +3 -0
  55. package/dist/features/background-agent/task-poller.d.ts +1 -0
  56. package/dist/features/background-agent/types.d.ts +2 -0
  57. package/dist/features/builtin-commands/commands.d.ts +4 -1
  58. package/dist/features/builtin-commands/templates/handoff.d.ts +1 -1
  59. package/dist/features/builtin-commands/templates/init-deep.d.ts +1 -1
  60. package/dist/features/builtin-commands/templates/remove-ai-slops.d.ts +1 -0
  61. package/dist/features/builtin-commands/templates/start-work.d.ts +1 -1
  62. package/dist/features/builtin-commands/types.d.ts +1 -1
  63. package/dist/features/builtin-skills/skills/ai-slop-remover.d.ts +2 -0
  64. package/dist/features/builtin-skills/skills/git-master-sections/commit-workflow.d.ts +1 -0
  65. package/dist/features/builtin-skills/skills/git-master-sections/history-search-workflow.d.ts +1 -0
  66. package/dist/features/builtin-skills/skills/git-master-sections/overview.d.ts +1 -0
  67. package/dist/features/builtin-skills/skills/git-master-sections/quick-reference.d.ts +1 -0
  68. package/dist/features/builtin-skills/skills/git-master-sections/rebase-workflow.d.ts +1 -0
  69. package/dist/features/builtin-skills/skills/index.d.ts +2 -0
  70. package/dist/features/builtin-skills/skills/playwright-cli.d.ts +1 -1
  71. package/dist/features/builtin-skills/skills/review-work.d.ts +2 -0
  72. package/dist/features/claude-code-mcp-loader/configure-allowed-env-vars.d.ts +5 -0
  73. package/dist/features/claude-code-mcp-loader/index.d.ts +1 -0
  74. package/dist/features/claude-code-mcp-loader/scope-filter.d.ts +2 -0
  75. package/dist/features/claude-code-mcp-loader/types.d.ts +8 -4
  76. package/dist/features/claude-code-session-state/state.d.ts +2 -0
  77. package/dist/features/context-injector/collector.d.ts +1 -0
  78. package/dist/features/opencode-skill-loader/async-loader.d.ts +2 -2
  79. package/dist/features/skill-mcp-manager/manager.d.ts +4 -1
  80. package/dist/features/skill-mcp-manager/oauth-handler.d.ts +5 -4
  81. package/dist/features/skill-mcp-manager/types.d.ts +7 -0
  82. package/dist/features/tmux-subagent/manager.d.ts +15 -13
  83. package/dist/features/tmux-subagent/polling-manager.d.ts +5 -0
  84. package/dist/features/tmux-subagent/types.d.ts +2 -0
  85. package/dist/hooks/agent-usage-reminder/constants.d.ts +1 -1
  86. package/dist/hooks/anthropic-context-window-limit-recovery/message-builder.d.ts +4 -1
  87. package/dist/hooks/anthropic-context-window-limit-recovery/recovery-hook.d.ts +10 -0
  88. package/dist/hooks/anthropic-context-window-limit-recovery/recovery-hook.test-support.d.ts +29 -0
  89. package/dist/hooks/anthropic-context-window-limit-recovery/session-timeout-map.d.ts +2 -0
  90. package/dist/hooks/anthropic-context-window-limit-recovery/state.d.ts +2 -0
  91. package/dist/hooks/anthropic-context-window-limit-recovery/types.d.ts +1 -0
  92. package/dist/hooks/atlas/subagent-session-id.d.ts +1 -0
  93. package/dist/hooks/atlas/system-reminder-templates.d.ts +2 -2
  94. package/dist/hooks/auto-slash-command/executor.d.ts +1 -0
  95. package/dist/hooks/auto-slash-command/hook.d.ts +1 -0
  96. package/dist/hooks/auto-update-checker/checker/sync-package-json.d.ts +1 -1
  97. package/dist/hooks/auto-update-checker/constants.d.ts +3 -2
  98. package/dist/hooks/auto-update-checker/hook/background-update-check.d.ts +29 -1
  99. package/dist/hooks/bash-file-read-guard.d.ts +2 -0
  100. package/dist/hooks/claude-code-hooks/claude-code-hooks-hook.d.ts +1 -0
  101. package/dist/hooks/claude-code-hooks/config-loader.d.ts +1 -0
  102. package/dist/hooks/claude-code-hooks/config.d.ts +1 -0
  103. package/dist/hooks/claude-code-hooks/handlers/session-event-handler.d.ts +3 -1
  104. package/dist/hooks/claude-code-hooks/session-hook-state.d.ts +1 -0
  105. package/dist/hooks/claude-code-hooks/tool-input-cache.d.ts +2 -0
  106. package/dist/hooks/claude-code-hooks/transcript.d.ts +1 -3
  107. package/dist/hooks/comment-checker/hook.d.ts +1 -0
  108. package/dist/hooks/comment-checker/pending-calls.d.ts +1 -0
  109. package/dist/hooks/index.d.ts +3 -0
  110. package/dist/hooks/keyword-detector/ultrawork/default.d.ts +1 -1
  111. package/dist/hooks/keyword-detector/ultrawork/gemini.d.ts +1 -1
  112. package/dist/hooks/keyword-detector/ultrawork/gpt.d.ts +1 -1
  113. package/dist/hooks/legacy-plugin-toast/auto-migrate-runner.d.ts +2 -0
  114. package/dist/hooks/legacy-plugin-toast/auto-migrate.d.ts +7 -0
  115. package/dist/hooks/legacy-plugin-toast/hook.d.ts +18 -0
  116. package/dist/hooks/legacy-plugin-toast/index.d.ts +1 -0
  117. package/dist/hooks/legacy-plugin-toast/plugin-entry-migrator.d.ts +1 -0
  118. package/dist/hooks/model-fallback/chat-message-fallback-handler.d.ts +23 -0
  119. package/dist/hooks/model-fallback/next-fallback.d.ts +6 -0
  120. package/dist/hooks/ralph-loop/completion-promise-detector-test-input.d.ts +11 -0
  121. package/dist/hooks/rules-injector/constants.d.ts +1 -0
  122. package/dist/hooks/rules-injector/finder.d.ts +1 -1
  123. package/dist/hooks/rules-injector/hook.d.ts +2 -0
  124. package/dist/hooks/rules-injector/injector.d.ts +2 -0
  125. package/dist/hooks/rules-injector/rule-file-finder.d.ts +9 -1
  126. package/dist/hooks/runtime-fallback/fallback-models.d.ts +1 -1
  127. package/dist/hooks/runtime-fallback/retry-model-payload.d.ts +5 -1
  128. package/dist/hooks/start-work/context-info-builder.d.ts +12 -0
  129. package/dist/hooks/start-work/start-work-hook.d.ts +6 -0
  130. package/dist/hooks/start-work/worktree-block.d.ts +1 -0
  131. package/dist/hooks/todo-continuation-enforcer/resolve-message-info.d.ts +2 -2
  132. package/dist/hooks/todo-continuation-enforcer/session-state.d.ts +4 -3
  133. package/dist/hooks/todo-continuation-enforcer/types.d.ts +7 -0
  134. package/dist/hooks/todo-description-override/description.d.ts +1 -1
  135. package/dist/hooks/tool-pair-validator/hook.d.ts +28 -0
  136. package/dist/hooks/tool-pair-validator/index.d.ts +1 -0
  137. package/dist/hooks/write-existing-file-guard/hook.d.ts +12 -0
  138. package/dist/hooks/write-existing-file-guard/session-read-permissions.d.ts +3 -0
  139. package/dist/hooks/write-existing-file-guard/tool-execute-before-handler.d.ts +15 -0
  140. package/dist/index.js +9660 -5056
  141. package/dist/mcp/websearch.d.ts +2 -2
  142. package/dist/oh-my-opencode.schema.json +1052 -3
  143. package/dist/openclaw/dispatcher.d.ts +6 -0
  144. package/dist/plugin/command-execute-before.d.ts +17 -0
  145. package/dist/plugin/hooks/create-core-hooks.d.ts +3 -0
  146. package/dist/plugin/hooks/create-session-hooks.d.ts +2 -1
  147. package/dist/plugin/hooks/create-tool-guard-hooks.d.ts +2 -1
  148. package/dist/plugin/hooks/create-transform-hooks.d.ts +2 -1
  149. package/dist/plugin/tool-registry.d.ts +1 -0
  150. package/dist/plugin/types.d.ts +1 -0
  151. package/dist/plugin-dispose.d.ts +3 -0
  152. package/dist/shared/agent-display-names.d.ts +8 -0
  153. package/dist/shared/archive-entry-validator.d.ts +6 -0
  154. package/dist/shared/background-output-consumption.d.ts +5 -0
  155. package/dist/shared/connected-providers-cache.d.ts +2 -1
  156. package/dist/shared/contains-path.d.ts +2 -0
  157. package/dist/shared/external-plugin-detector.d.ts +14 -0
  158. package/dist/shared/index.d.ts +3 -0
  159. package/dist/shared/is-abort-error.d.ts +1 -0
  160. package/dist/shared/json-file-cache-store.d.ts +16 -0
  161. package/dist/shared/jsonc-parser.d.ts +1 -0
  162. package/dist/shared/legacy-plugin-warning.d.ts +1 -0
  163. package/dist/shared/load-opencode-plugins.d.ts +1 -0
  164. package/dist/shared/log-legacy-plugin-startup-warning.d.ts +10 -1
  165. package/dist/shared/migrate-legacy-config-file.d.ts +1 -0
  166. package/dist/shared/migrate-legacy-plugin-entry.d.ts +1 -0
  167. package/dist/shared/model-capabilities/bundled-snapshot.d.ts +2 -0
  168. package/dist/shared/model-capabilities/get-model-capabilities.d.ts +2 -0
  169. package/dist/shared/model-capabilities/index.d.ts +3 -0
  170. package/dist/shared/model-capabilities/runtime-model-readers.d.ts +11 -0
  171. package/dist/shared/{model-capabilities.d.ts → model-capabilities/types.d.ts} +35 -32
  172. package/dist/shared/model-suggestion-retry.d.ts +0 -9
  173. package/dist/shared/plugin-entry-migrator.d.ts +3 -0
  174. package/dist/shared/session-category-registry.d.ts +0 -24
  175. package/dist/shared/session-cursor.d.ts +6 -0
  176. package/dist/shared/skill-path-resolver.d.ts +0 -8
  177. package/dist/shared/task-system-enabled.d.ts +6 -0
  178. package/dist/shared/tmux/tmux-utils/server-health.d.ts +1 -0
  179. package/dist/shared/tmux/tmux-utils/session-spawn.d.ts +3 -0
  180. package/dist/shared/tmux/tmux-utils/window-spawn.d.ts +3 -0
  181. package/dist/shared/tmux/tmux-utils.d.ts +3 -1
  182. package/dist/shared/write-file-atomically.d.ts +1 -0
  183. package/dist/shared/zip-entry-listing/powershell-zip-entry-listing.d.ts +4 -0
  184. package/dist/shared/zip-entry-listing/python-zip-entry-listing.d.ts +3 -0
  185. package/dist/shared/zip-entry-listing/read-zip-symlink-target.d.ts +1 -0
  186. package/dist/shared/zip-entry-listing/tar-zip-entry-listing.d.ts +3 -0
  187. package/dist/shared/zip-entry-listing/zipinfo-zip-entry-listing.d.ts +4 -0
  188. package/dist/shared/zip-entry-listing.d.ts +4 -0
  189. package/dist/tools/call-omo-agent/background-executor.d.ts +2 -1
  190. package/dist/tools/call-omo-agent/sync-executor.d.ts +2 -1
  191. package/dist/tools/delegate-task/anthropic-categories.d.ts +2 -0
  192. package/dist/tools/delegate-task/builtin-categories.d.ts +4 -0
  193. package/dist/tools/delegate-task/builtin-category-definition.d.ts +7 -0
  194. package/dist/tools/delegate-task/constants.d.ts +1 -12
  195. package/dist/tools/delegate-task/executor-types.d.ts +2 -1
  196. package/dist/tools/delegate-task/google-categories.d.ts +2 -0
  197. package/dist/tools/delegate-task/kimi-categories.d.ts +2 -0
  198. package/dist/tools/delegate-task/openai-categories.d.ts +2 -0
  199. package/dist/tools/delegate-task/prompt-builder.d.ts +1 -1
  200. package/dist/tools/delegate-task/sync-prompt-sender.d.ts +2 -0
  201. package/dist/tools/delegate-task/types.d.ts +2 -1
  202. package/dist/tools/grep/cli.d.ts +3 -2
  203. package/dist/tools/grep/constants.d.ts +1 -2
  204. package/dist/tools/hashline-edit/tool-description.d.ts +1 -1
  205. package/dist/tools/look-at/constants.d.ts +1 -1
  206. package/dist/tools/lsp/infer-extension.d.ts +1 -0
  207. package/dist/tools/session-manager/file-storage.d.ts +8 -0
  208. package/dist/tools/session-manager/sdk-storage.d.ts +8 -0
  209. package/dist/tools/session-manager/sdk-unavailable.d.ts +1 -0
  210. package/dist/tools/session-manager/storage.d.ts +1 -1
  211. package/dist/tools/skill/description-formatter.d.ts +3 -0
  212. package/dist/tools/skill/mcp-capability-formatter.d.ts +3 -0
  213. package/dist/tools/skill/native-skills.d.ts +12 -0
  214. package/dist/tools/skill/scope-priority.d.ts +4 -0
  215. package/dist/tools/skill/skill-body.d.ts +2 -0
  216. package/dist/tools/skill/skill-matcher.d.ts +5 -0
  217. package/dist/tools/skill/types.d.ts +30 -2
  218. package/dist/tools/skill-mcp/tools.d.ts +1 -1
  219. package/package.json +14 -14
  220. package/postinstall.mjs +12 -0
  221. package/dist/hooks/openclaw.d.ts +0 -11
package/dist/cli/index.js CHANGED
@@ -4914,8 +4914,9 @@ var init_command_executor = __esm(() => {
4914
4914
  init_resolve_commands_in_text();
4915
4915
  });
4916
4916
 
4917
- // src/shared/file-reference-resolver.ts
4918
- var init_file_reference_resolver = () => {};
4917
+ // src/shared/contains-path.ts
4918
+ var init_contains_path = () => {};
4919
+
4919
4920
  // src/shared/logger.ts
4920
4921
  import * as fs from "fs";
4921
4922
  import * as os from "os";
@@ -4956,6 +4957,11 @@ var init_logger = __esm(() => {
4956
4957
  buffer = [];
4957
4958
  });
4958
4959
 
4960
+ // src/shared/file-reference-resolver.ts
4961
+ var init_file_reference_resolver = __esm(() => {
4962
+ init_contains_path();
4963
+ init_logger();
4964
+ });
4959
4965
  // src/shared/deep-merge.ts
4960
4966
  function isPlainObject(value) {
4961
4967
  return typeof value === "object" && value !== null && !Array.isArray(value) && Object.prototype.toString.call(value) === "[object Object]";
@@ -5018,15 +5024,7 @@ function resolveSymlink(filePath) {
5018
5024
  var init_file_utils = () => {};
5019
5025
 
5020
5026
  // src/shared/context-limit-resolver.ts
5021
- var ANTHROPIC_NO_HEADER_GA_MODEL_IDS;
5022
- var init_context_limit_resolver = __esm(() => {
5023
- ANTHROPIC_NO_HEADER_GA_MODEL_IDS = new Set([
5024
- "claude-opus-4-6",
5025
- "claude-opus-4.6",
5026
- "claude-sonnet-4-6",
5027
- "claude-sonnet-4.6"
5028
- ]);
5029
- });
5027
+ var init_context_limit_resolver = () => {};
5030
5028
 
5031
5029
  // src/shared/normalize-sdk-response.ts
5032
5030
  function normalizeSDKResponse(response, fallback, options) {
@@ -5973,6 +5971,9 @@ var init_main = __esm(() => {
5973
5971
  })(ParseErrorCode || (ParseErrorCode = {}));
5974
5972
  });
5975
5973
 
5974
+ // src/shared/plugin-identity.ts
5975
+ var PLUGIN_NAME = "oh-my-openagent", LEGACY_PLUGIN_NAME = "oh-my-opencode", CONFIG_BASENAME = "oh-my-openagent", LEGACY_CONFIG_BASENAME = "oh-my-opencode";
5976
+
5976
5977
  // src/shared/jsonc-parser.ts
5977
5978
  import { existsSync, readFileSync } from "fs";
5978
5979
  import { join as join3 } from "path";
@@ -6000,17 +6001,21 @@ function detectConfigFile(basePath) {
6000
6001
  return { format: "none", path: jsonPath };
6001
6002
  }
6002
6003
  function detectPluginConfigFile(dir) {
6003
- for (const name of PLUGIN_CONFIG_NAMES) {
6004
- const result = detectConfigFile(join3(dir, name));
6005
- if (result.format !== "none")
6006
- return result;
6004
+ const canonicalResult = detectConfigFile(join3(dir, CONFIG_BASENAME));
6005
+ const legacyResult = detectConfigFile(join3(dir, LEGACY_CONFIG_BASENAME));
6006
+ if (canonicalResult.format !== "none") {
6007
+ return {
6008
+ ...canonicalResult,
6009
+ legacyPath: legacyResult.format !== "none" ? legacyResult.path : undefined
6010
+ };
6011
+ }
6012
+ if (legacyResult.format !== "none") {
6013
+ return legacyResult;
6007
6014
  }
6008
- return { format: "none", path: join3(dir, PLUGIN_CONFIG_NAMES[0] + ".json") };
6015
+ return { format: "none", path: join3(dir, `${CONFIG_BASENAME}.json`) };
6009
6016
  }
6010
- var PLUGIN_CONFIG_NAMES;
6011
6017
  var init_jsonc_parser = __esm(() => {
6012
6018
  init_main();
6013
- PLUGIN_CONFIG_NAMES = ["oh-my-opencode", "oh-my-openagent"];
6014
6019
  });
6015
6020
 
6016
6021
  // src/shared/migration/agent-names.ts
@@ -6134,13 +6139,29 @@ var MODEL_VERSION_MAP;
6134
6139
  var init_model_versions = __esm(() => {
6135
6140
  MODEL_VERSION_MAP = {
6136
6141
  "anthropic/claude-opus-4-5": "anthropic/claude-opus-4-6",
6137
- "anthropic/claude-sonnet-4-5": "anthropic/claude-sonnet-4-6"
6142
+ "anthropic/claude-sonnet-4-5": "anthropic/claude-sonnet-4-6",
6143
+ "openai/gpt-5.3-codex": "openai/gpt-5.4"
6138
6144
  };
6139
6145
  });
6140
6146
 
6141
6147
  // src/shared/migration/agent-category.ts
6142
6148
  var init_agent_category = () => {};
6143
6149
 
6150
+ // src/shared/write-file-atomically.ts
6151
+ import { closeSync, fsyncSync, openSync, renameSync, writeFileSync } from "fs";
6152
+ function writeFileAtomically(filePath, content) {
6153
+ const tempPath = `${filePath}.tmp`;
6154
+ writeFileSync(tempPath, content, "utf-8");
6155
+ const tempFileDescriptor = openSync(tempPath, "r");
6156
+ try {
6157
+ fsyncSync(tempFileDescriptor);
6158
+ } finally {
6159
+ closeSync(tempFileDescriptor);
6160
+ }
6161
+ renameSync(tempPath, filePath);
6162
+ }
6163
+ var init_write_file_atomically = () => {};
6164
+
6144
6165
  // src/shared/migration/config-migration.ts
6145
6166
  import * as fs2 from "fs";
6146
6167
  function migrateConfigFile(configPath, rawConfig) {
@@ -6229,11 +6250,13 @@ function migrateConfigFile(configPath, rawConfig) {
6229
6250
  try {
6230
6251
  fs2.copyFileSync(configPath, backupPath);
6231
6252
  backupSucceeded = true;
6232
- } catch {}
6253
+ } catch {
6254
+ backupSucceeded = false;
6255
+ }
6233
6256
  let writeSucceeded = false;
6234
6257
  try {
6235
- fs2.writeFileSync(configPath, JSON.stringify(copy, null, 2) + `
6236
- `, "utf-8");
6258
+ writeFileAtomically(configPath, JSON.stringify(copy, null, 2) + `
6259
+ `);
6237
6260
  writeSucceeded = true;
6238
6261
  } catch (err) {
6239
6262
  log(`Failed to write migrated config to ${configPath}:`, err);
@@ -6254,6 +6277,7 @@ function migrateConfigFile(configPath, rawConfig) {
6254
6277
  }
6255
6278
  var init_config_migration = __esm(() => {
6256
6279
  init_logger();
6280
+ init_write_file_atomically();
6257
6281
  init_agent_names();
6258
6282
  init_hook_names();
6259
6283
  init_model_versions();
@@ -6356,17 +6380,56 @@ var init_opencode_storage_detection = __esm(() => {
6356
6380
  NOT_CACHED2 = Symbol("NOT_CACHED");
6357
6381
  FALSE_PENDING_RETRY = Symbol("FALSE_PENDING_RETRY");
6358
6382
  });
6383
+ // src/shared/load-opencode-plugins.ts
6384
+ var init_load_opencode_plugins = __esm(() => {
6385
+ init_jsonc_parser();
6386
+ });
6387
+
6359
6388
  // src/shared/external-plugin-detector.ts
6360
6389
  var init_external_plugin_detector = __esm(() => {
6390
+ init_load_opencode_plugins();
6361
6391
  init_logger();
6362
- init_jsonc_parser();
6392
+ });
6393
+
6394
+ // src/shared/archive-entry-validator.ts
6395
+ var init_archive_entry_validator = () => {};
6396
+
6397
+ // src/shared/zip-entry-listing/python-zip-entry-listing.ts
6398
+ var init_python_zip_entry_listing = () => {};
6399
+
6400
+ // src/shared/zip-entry-listing/powershell-zip-entry-listing.ts
6401
+ var init_powershell_zip_entry_listing = () => {};
6402
+
6403
+ // src/shared/zip-entry-listing/tar-zip-entry-listing.ts
6404
+ var init_tar_zip_entry_listing = __esm(() => {
6405
+ init_logger();
6406
+ });
6407
+
6408
+ // src/shared/zip-entry-listing/read-zip-symlink-target.ts
6409
+ var init_read_zip_symlink_target = () => {};
6410
+
6411
+ // src/shared/zip-entry-listing/zipinfo-zip-entry-listing.ts
6412
+ var init_zipinfo_zip_entry_listing = __esm(() => {
6413
+ init_read_zip_symlink_target();
6414
+ });
6415
+
6416
+ // src/shared/zip-entry-listing.ts
6417
+ var init_zip_entry_listing = __esm(() => {
6418
+ init_python_zip_entry_listing();
6419
+ init_powershell_zip_entry_listing();
6420
+ init_tar_zip_entry_listing();
6421
+ init_zipinfo_zip_entry_listing();
6363
6422
  });
6364
6423
 
6365
6424
  // src/shared/zip-extractor.ts
6366
- var init_zip_extractor = () => {};
6425
+ var init_zip_extractor = __esm(() => {
6426
+ init_archive_entry_validator();
6427
+ init_zip_entry_listing();
6428
+ });
6367
6429
 
6368
6430
  // src/shared/binary-downloader.ts
6369
6431
  var init_binary_downloader = __esm(() => {
6432
+ init_archive_entry_validator();
6370
6433
  init_zip_extractor();
6371
6434
  });
6372
6435
 
@@ -6433,7 +6496,7 @@ var init_model_requirements = __esm(() => {
6433
6496
  librarian: {
6434
6497
  fallbackChain: [
6435
6498
  { providers: ["opencode-go"], model: "minimax-m2.7" },
6436
- { providers: ["opencode"], model: "minimax-m2.5" },
6499
+ { providers: ["opencode"], model: "minimax-m2.7-highspeed" },
6437
6500
  { providers: ["anthropic", "opencode"], model: "claude-haiku-4-5" },
6438
6501
  { providers: ["opencode"], model: "gpt-5-nano" }
6439
6502
  ]
@@ -6441,8 +6504,8 @@ var init_model_requirements = __esm(() => {
6441
6504
  explore: {
6442
6505
  fallbackChain: [
6443
6506
  { providers: ["github-copilot", "xai"], model: "grok-code-fast-1" },
6444
- { providers: ["opencode-go"], model: "minimax-m2.7" },
6445
- { providers: ["opencode"], model: "minimax-m2.5" },
6507
+ { providers: ["opencode-go"], model: "minimax-m2.7-highspeed" },
6508
+ { providers: ["opencode"], model: "minimax-m2.7" },
6446
6509
  { providers: ["anthropic", "opencode"], model: "claude-haiku-4-5" },
6447
6510
  { providers: ["opencode"], model: "gpt-5-nano" }
6448
6511
  ]
@@ -6577,8 +6640,8 @@ var init_model_requirements = __esm(() => {
6577
6640
  deep: {
6578
6641
  fallbackChain: [
6579
6642
  {
6580
- providers: ["openai", "opencode"],
6581
- model: "gpt-5.3-codex",
6643
+ providers: ["openai", "github-copilot", "venice", "opencode"],
6644
+ model: "gpt-5.4",
6582
6645
  variant: "medium"
6583
6646
  },
6584
6647
  {
@@ -6591,8 +6654,7 @@ var init_model_requirements = __esm(() => {
6591
6654
  model: "gemini-3.1-pro",
6592
6655
  variant: "high"
6593
6656
  }
6594
- ],
6595
- requiresModel: "gpt-5.3-codex"
6657
+ ]
6596
6658
  },
6597
6659
  artistry: {
6598
6660
  fallbackChain: [
@@ -6703,6 +6765,22 @@ var sessionCursors;
6703
6765
  var init_session_cursor = __esm(() => {
6704
6766
  sessionCursors = new Map;
6705
6767
  });
6768
+
6769
+ // src/shared/shell-env.ts
6770
+ function detectShellType() {
6771
+ if (process.env.PSModulePath) {
6772
+ return "powershell";
6773
+ }
6774
+ if (process.env.SHELL) {
6775
+ const shell = process.env.SHELL;
6776
+ if (shell.includes("csh") || shell.includes("tcsh")) {
6777
+ return "csh";
6778
+ }
6779
+ return "unix";
6780
+ }
6781
+ return process.platform === "win32" ? "cmd" : "unix";
6782
+ }
6783
+
6706
6784
  // src/shared/system-directive.ts
6707
6785
  var init_system_directive = () => {};
6708
6786
 
@@ -6714,108 +6792,122 @@ function normalizeModelID(modelID) {
6714
6792
  return modelID.replace(/\.(\d+)/g, "-$1");
6715
6793
  }
6716
6794
 
6717
- // src/shared/connected-providers-cache.ts
6718
- import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
6795
+ // src/shared/json-file-cache-store.ts
6796
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
6719
6797
  import { join as join5 } from "path";
6720
- function isRecord(value) {
6721
- return typeof value === "object" && value !== null;
6798
+ function toLogLabel(cacheLabel) {
6799
+ return cacheLabel.toLowerCase();
6722
6800
  }
6723
- function createConnectedProvidersCacheStore(getCacheDir2 = getOmoOpenCodeCacheDir) {
6724
- function getCacheFilePath(filename) {
6725
- return join5(getCacheDir2(), filename);
6801
+ function createJsonFileCacheStore(options) {
6802
+ let memoryValue;
6803
+ function getCacheFilePath() {
6804
+ return join5(options.getCacheDir(), options.filename);
6726
6805
  }
6727
- let memConnected;
6728
- let memProviderModels;
6729
6806
  function ensureCacheDir() {
6730
- const cacheDir = getCacheDir2();
6807
+ const cacheDir = options.getCacheDir();
6731
6808
  if (!existsSync3(cacheDir)) {
6732
6809
  mkdirSync2(cacheDir, { recursive: true });
6733
6810
  }
6734
6811
  }
6735
- function readConnectedProvidersCache() {
6736
- if (memConnected !== undefined)
6737
- return memConnected;
6738
- const cacheFile = getCacheFilePath(CONNECTED_PROVIDERS_CACHE_FILE);
6812
+ function read() {
6813
+ if (memoryValue !== undefined) {
6814
+ return memoryValue;
6815
+ }
6816
+ const cacheFile = getCacheFilePath();
6739
6817
  if (!existsSync3(cacheFile)) {
6740
- log("[connected-providers-cache] Cache file not found", { cacheFile });
6741
- memConnected = null;
6818
+ memoryValue = null;
6819
+ log(`[${options.logPrefix}] ${options.cacheLabel} file not found`, { cacheFile });
6742
6820
  return null;
6743
6821
  }
6744
6822
  try {
6745
6823
  const content = readFileSync2(cacheFile, "utf-8");
6746
- const data = JSON.parse(content);
6747
- log("[connected-providers-cache] Read cache", { count: data.connected.length, updatedAt: data.updatedAt });
6748
- memConnected = data.connected;
6749
- return data.connected;
6750
- } catch (err) {
6751
- log("[connected-providers-cache] Error reading cache", { error: String(err) });
6752
- memConnected = null;
6824
+ const value = JSON.parse(content);
6825
+ memoryValue = value;
6826
+ log(`[${options.logPrefix}] Read ${toLogLabel(options.cacheLabel)}`, options.describe(value));
6827
+ return value;
6828
+ } catch (error) {
6829
+ memoryValue = null;
6830
+ log(`[${options.logPrefix}] Error reading ${toLogLabel(options.cacheLabel)}`, {
6831
+ error: String(error)
6832
+ });
6753
6833
  return null;
6754
6834
  }
6755
6835
  }
6836
+ function has() {
6837
+ return existsSync3(getCacheFilePath());
6838
+ }
6839
+ function write(value) {
6840
+ ensureCacheDir();
6841
+ const cacheFile = getCacheFilePath();
6842
+ try {
6843
+ writeFileSync2(cacheFile, options.serialize?.(value) ?? JSON.stringify(value, null, 2));
6844
+ memoryValue = value;
6845
+ log(`[${options.logPrefix}] ${options.cacheLabel} written`, options.describe(value));
6846
+ } catch (error) {
6847
+ log(`[${options.logPrefix}] Error writing ${toLogLabel(options.cacheLabel)}`, {
6848
+ error: String(error)
6849
+ });
6850
+ }
6851
+ }
6852
+ function resetMemory() {
6853
+ memoryValue = undefined;
6854
+ }
6855
+ return {
6856
+ read,
6857
+ has,
6858
+ write,
6859
+ resetMemory
6860
+ };
6861
+ }
6862
+ var init_json_file_cache_store = __esm(() => {
6863
+ init_logger();
6864
+ });
6865
+
6866
+ // src/shared/connected-providers-cache.ts
6867
+ function isRecord(value) {
6868
+ return typeof value === "object" && value !== null;
6869
+ }
6870
+ function createConnectedProvidersCacheStore(getCacheDir2 = getOmoOpenCodeCacheDir) {
6871
+ const connectedProvidersCacheStore = createJsonFileCacheStore({
6872
+ getCacheDir: getCacheDir2,
6873
+ filename: CONNECTED_PROVIDERS_CACHE_FILE,
6874
+ logPrefix: "connected-providers-cache",
6875
+ cacheLabel: "Cache",
6876
+ describe: (value) => ({ count: value.connected.length, updatedAt: value.updatedAt })
6877
+ });
6878
+ const providerModelsCacheStore = createJsonFileCacheStore({
6879
+ getCacheDir: getCacheDir2,
6880
+ filename: PROVIDER_MODELS_CACHE_FILE,
6881
+ logPrefix: "connected-providers-cache",
6882
+ cacheLabel: "Provider-models cache",
6883
+ describe: (value) => ({
6884
+ providerCount: Object.keys(value.models).length,
6885
+ updatedAt: value.updatedAt
6886
+ })
6887
+ });
6888
+ function readConnectedProvidersCache() {
6889
+ return connectedProvidersCacheStore.read()?.connected ?? null;
6890
+ }
6756
6891
  function hasConnectedProvidersCache() {
6757
- const cacheFile = getCacheFilePath(CONNECTED_PROVIDERS_CACHE_FILE);
6758
- return existsSync3(cacheFile);
6892
+ return connectedProvidersCacheStore.has();
6759
6893
  }
6760
6894
  function writeConnectedProvidersCache(connected) {
6761
- ensureCacheDir();
6762
- const cacheFile = getCacheFilePath(CONNECTED_PROVIDERS_CACHE_FILE);
6763
- const data = {
6895
+ connectedProvidersCacheStore.write({
6764
6896
  connected,
6765
6897
  updatedAt: new Date().toISOString()
6766
- };
6767
- try {
6768
- writeFileSync2(cacheFile, JSON.stringify(data, null, 2));
6769
- memConnected = connected;
6770
- log("[connected-providers-cache] Cache written", { count: connected.length });
6771
- } catch (err) {
6772
- log("[connected-providers-cache] Error writing cache", { error: String(err) });
6773
- }
6898
+ });
6774
6899
  }
6775
6900
  function readProviderModelsCache() {
6776
- if (memProviderModels !== undefined)
6777
- return memProviderModels;
6778
- const cacheFile = getCacheFilePath(PROVIDER_MODELS_CACHE_FILE);
6779
- if (!existsSync3(cacheFile)) {
6780
- log("[connected-providers-cache] Provider-models cache file not found", { cacheFile });
6781
- memProviderModels = null;
6782
- return null;
6783
- }
6784
- try {
6785
- const content = readFileSync2(cacheFile, "utf-8");
6786
- const data = JSON.parse(content);
6787
- log("[connected-providers-cache] Read provider-models cache", {
6788
- providerCount: Object.keys(data.models).length,
6789
- updatedAt: data.updatedAt
6790
- });
6791
- memProviderModels = data;
6792
- return data;
6793
- } catch (err) {
6794
- log("[connected-providers-cache] Error reading provider-models cache", { error: String(err) });
6795
- memProviderModels = null;
6796
- return null;
6797
- }
6901
+ return providerModelsCacheStore.read();
6798
6902
  }
6799
6903
  function hasProviderModelsCache() {
6800
- const cacheFile = getCacheFilePath(PROVIDER_MODELS_CACHE_FILE);
6801
- return existsSync3(cacheFile);
6904
+ return providerModelsCacheStore.has();
6802
6905
  }
6803
6906
  function writeProviderModelsCache(data) {
6804
- ensureCacheDir();
6805
- const cacheFile = getCacheFilePath(PROVIDER_MODELS_CACHE_FILE);
6806
- const cacheData = {
6907
+ providerModelsCacheStore.write({
6807
6908
  ...data,
6808
6909
  updatedAt: new Date().toISOString()
6809
- };
6810
- try {
6811
- writeFileSync2(cacheFile, JSON.stringify(cacheData, null, 2));
6812
- memProviderModels = cacheData;
6813
- log("[connected-providers-cache] Provider-models cache written", {
6814
- providerCount: Object.keys(data.models).length
6815
- });
6816
- } catch (err) {
6817
- log("[connected-providers-cache] Error writing provider-models cache", { error: String(err) });
6818
- }
6910
+ });
6819
6911
  }
6820
6912
  async function updateConnectedProvidersCache(client) {
6821
6913
  if (!client?.provider?.list) {
@@ -6861,13 +6953,18 @@ function createConnectedProvidersCacheStore(getCacheDir2 = getOmoOpenCodeCacheDi
6861
6953
  log("[connected-providers-cache] Error updating cache", { error: String(err) });
6862
6954
  }
6863
6955
  }
6956
+ function _resetMemCacheForTesting() {
6957
+ connectedProvidersCacheStore.resetMemory();
6958
+ providerModelsCacheStore.resetMemory();
6959
+ }
6864
6960
  return {
6865
6961
  readConnectedProvidersCache,
6866
6962
  hasConnectedProvidersCache,
6867
6963
  readProviderModelsCache,
6868
6964
  hasProviderModelsCache,
6869
6965
  writeProviderModelsCache,
6870
- updateConnectedProvidersCache
6966
+ updateConnectedProvidersCache,
6967
+ _resetMemCacheForTesting
6871
6968
  };
6872
6969
  }
6873
6970
  function findProviderModelMetadata(providerID, modelID, cache = defaultConnectedProvidersCacheStore.readProviderModelsCache()) {
@@ -6882,16 +6979,17 @@ function findProviderModelMetadata(providerID, modelID, cache = defaultConnected
6882
6979
  }
6883
6980
  continue;
6884
6981
  }
6885
- if (entry?.id === modelID) {
6982
+ if (entry.id === modelID) {
6886
6983
  return entry;
6887
6984
  }
6888
6985
  }
6889
6986
  return;
6890
6987
  }
6891
- var CONNECTED_PROVIDERS_CACHE_FILE = "connected-providers.json", PROVIDER_MODELS_CACHE_FILE = "provider-models.json", defaultConnectedProvidersCacheStore, readConnectedProvidersCache, hasConnectedProvidersCache, readProviderModelsCache, hasProviderModelsCache, writeProviderModelsCache, updateConnectedProvidersCache;
6988
+ var CONNECTED_PROVIDERS_CACHE_FILE = "connected-providers.json", PROVIDER_MODELS_CACHE_FILE = "provider-models.json", defaultConnectedProvidersCacheStore, readConnectedProvidersCache, hasConnectedProvidersCache, readProviderModelsCache, hasProviderModelsCache, writeProviderModelsCache, updateConnectedProvidersCache, _resetMemCacheForTesting;
6892
6989
  var init_connected_providers_cache = __esm(() => {
6893
6990
  init_logger();
6894
6991
  init_data_path();
6992
+ init_json_file_cache_store();
6895
6993
  defaultConnectedProvidersCacheStore = createConnectedProvidersCacheStore(() => getOmoOpenCodeCacheDir());
6896
6994
  ({
6897
6995
  readConnectedProvidersCache,
@@ -6899,7 +6997,8 @@ var init_connected_providers_cache = __esm(() => {
6899
6997
  readProviderModelsCache,
6900
6998
  hasProviderModelsCache,
6901
6999
  writeProviderModelsCache,
6902
- updateConnectedProvidersCache
7000
+ updateConnectedProvidersCache,
7001
+ _resetMemCacheForTesting
6903
7002
  } = defaultConnectedProvidersCacheStore);
6904
7003
  });
6905
7004
 
@@ -19077,7 +19176,7 @@ var init_model_capabilities_generated = __esm(() => {
19077
19176
  family: "gpt-nano",
19078
19177
  reasoning: false,
19079
19178
  temperature: true,
19080
- toolCall: false,
19179
+ toolCall: true,
19081
19180
  modalities: {
19082
19181
  input: [
19083
19182
  "text",
@@ -19238,7 +19337,7 @@ var init_model_capabilities_generated = __esm(() => {
19238
19337
  family: "gpt-mini",
19239
19338
  reasoning: false,
19240
19339
  temperature: true,
19241
- toolCall: false,
19340
+ toolCall: true,
19242
19341
  modalities: {
19243
19342
  input: [
19244
19343
  "text",
@@ -47654,53 +47753,62 @@ var init_model_capabilities_generated = __esm(() => {
47654
47753
  };
47655
47754
  });
47656
47755
 
47756
+ // src/shared/model-capabilities/bundled-snapshot.ts
47757
+ function normalizeSnapshot(snapshot) {
47758
+ return snapshot;
47759
+ }
47760
+ function getBundledModelCapabilitiesSnapshot() {
47761
+ return bundledModelCapabilitiesSnapshot;
47762
+ }
47763
+ var bundledModelCapabilitiesSnapshot;
47764
+ var init_bundled_snapshot = __esm(() => {
47765
+ init_model_capabilities_generated();
47766
+ bundledModelCapabilitiesSnapshot = normalizeSnapshot(model_capabilities_generated_default);
47767
+ });
47768
+
47657
47769
  // src/shared/model-capability-aliases.ts
47658
47770
  function normalizeLookupModelID(modelID) {
47659
47771
  return modelID.trim().toLowerCase();
47660
47772
  }
47773
+ function stripProviderPrefixForAliasLookup(normalizedModelID) {
47774
+ const slashIndex = normalizedModelID.indexOf("/");
47775
+ if (slashIndex <= 0 || slashIndex === normalizedModelID.length - 1) {
47776
+ return normalizedModelID;
47777
+ }
47778
+ return normalizedModelID.slice(slashIndex + 1);
47779
+ }
47661
47780
  function resolveModelIDAlias(modelID) {
47662
- const normalizedModelID = normalizeLookupModelID(modelID);
47663
- const exactRule = EXACT_ALIAS_RULES_BY_MODEL.get(normalizedModelID);
47781
+ const requestedModelID = normalizeLookupModelID(modelID);
47782
+ const aliasLookupModelID = stripProviderPrefixForAliasLookup(requestedModelID);
47783
+ const exactRule = EXACT_ALIAS_RULES_BY_MODEL.get(aliasLookupModelID);
47664
47784
  if (exactRule) {
47665
47785
  return {
47666
- requestedModelID: normalizedModelID,
47786
+ requestedModelID,
47667
47787
  canonicalModelID: exactRule.canonicalModelID,
47668
47788
  source: "exact-alias",
47669
47789
  ruleID: exactRule.ruleID
47670
47790
  };
47671
47791
  }
47672
47792
  for (const rule of PATTERN_ALIAS_RULES) {
47673
- if (!rule.match(normalizedModelID)) {
47793
+ if (!rule.match(aliasLookupModelID)) {
47674
47794
  continue;
47675
47795
  }
47676
47796
  return {
47677
- requestedModelID: normalizedModelID,
47678
- canonicalModelID: rule.canonicalize(normalizedModelID),
47797
+ requestedModelID,
47798
+ canonicalModelID: rule.canonicalize(aliasLookupModelID),
47679
47799
  source: "pattern-alias",
47680
47800
  ruleID: rule.ruleID
47681
47801
  };
47682
47802
  }
47683
47803
  return {
47684
- requestedModelID: normalizedModelID,
47685
- canonicalModelID: normalizedModelID,
47804
+ requestedModelID,
47805
+ canonicalModelID: aliasLookupModelID,
47686
47806
  source: "canonical"
47687
47807
  };
47688
47808
  }
47689
47809
  var EXACT_ALIAS_RULES, EXACT_ALIAS_RULES_BY_MODEL, PATTERN_ALIAS_RULES;
47690
47810
  var init_model_capability_aliases = __esm(() => {
47691
47811
  EXACT_ALIAS_RULES = [
47692
- {
47693
- aliasModelID: "gemini-3.1-pro-high",
47694
- ruleID: "gemini-3.1-pro-tier-alias",
47695
- canonicalModelID: "gemini-3.1-pro",
47696
- rationale: "OmO historically encoded Gemini tier selection in the model name instead of variant metadata."
47697
- },
47698
- {
47699
- aliasModelID: "gemini-3.1-pro-low",
47700
- ruleID: "gemini-3.1-pro-tier-alias",
47701
- canonicalModelID: "gemini-3.1-pro",
47702
- rationale: "OmO historically encoded Gemini tier selection in the model name instead of variant metadata."
47703
- },
47704
47812
  {
47705
47813
  aliasModelID: "gemini-3-pro-high",
47706
47814
  ruleID: "gemini-3-pro-tier-alias",
@@ -47712,16 +47820,23 @@ var init_model_capability_aliases = __esm(() => {
47712
47820
  ruleID: "gemini-3-pro-tier-alias",
47713
47821
  canonicalModelID: "gemini-3-pro-preview",
47714
47822
  rationale: "Legacy Gemini 3 tier suffixes still need to land on the canonical preview model."
47823
+ }
47824
+ ];
47825
+ EXACT_ALIAS_RULES_BY_MODEL = new Map(EXACT_ALIAS_RULES.map((rule) => [rule.aliasModelID, rule]));
47826
+ PATTERN_ALIAS_RULES = [
47827
+ {
47828
+ ruleID: "claude-thinking-legacy-alias",
47829
+ description: "Normalizes the legacy Claude Opus 4.6 thinking suffix to the canonical snapshot ID.",
47830
+ match: (normalizedModelID) => /^claude-opus-4-6-thinking$/.test(normalizedModelID),
47831
+ canonicalize: () => "claude-opus-4-6"
47715
47832
  },
47716
47833
  {
47717
- aliasModelID: "claude-opus-4-6-thinking",
47718
- ruleID: "claude-opus-4-6-thinking-legacy-alias",
47719
- canonicalModelID: "claude-opus-4-6",
47720
- rationale: "OmO historically used a legacy compatibility suffix before models.dev shipped canonical thinking variants for newer Claude families."
47834
+ ruleID: "gemini-3.1-pro-tier-alias",
47835
+ description: "Normalizes Gemini 3.1 Pro tier suffixes to the canonical snapshot ID.",
47836
+ match: (normalizedModelID) => /^gemini-3\.1-pro-(?:high|low)$/.test(normalizedModelID),
47837
+ canonicalize: () => "gemini-3.1-pro"
47721
47838
  }
47722
47839
  ];
47723
- EXACT_ALIAS_RULES_BY_MODEL = new Map(EXACT_ALIAS_RULES.map((rule) => [rule.aliasModelID, rule]));
47724
- PATTERN_ALIAS_RULES = [];
47725
47840
  });
47726
47841
 
47727
47842
  // src/shared/model-capability-heuristics.ts
@@ -47807,13 +47922,10 @@ var init_model_capability_heuristics = __esm(() => {
47807
47922
  ];
47808
47923
  });
47809
47924
 
47810
- // src/shared/model-capabilities.ts
47925
+ // src/shared/model-capabilities/runtime-model-readers.ts
47811
47926
  function isRecord2(value) {
47812
47927
  return typeof value === "object" && value !== null && !Array.isArray(value);
47813
47928
  }
47814
- function normalizeLookupModelID2(modelID) {
47815
- return modelID.trim().toLowerCase();
47816
- }
47817
47929
  function readNumber(value) {
47818
47930
  return typeof value === "number" ? value : undefined;
47819
47931
  }
@@ -47860,32 +47972,13 @@ function normalizeModalities(value) {
47860
47972
  ...output ? { output } : {}
47861
47973
  };
47862
47974
  }
47863
- function normalizeSnapshot(snapshot) {
47864
- return snapshot;
47865
- }
47866
- function getOverride(modelID) {
47867
- return MODEL_ID_OVERRIDES[normalizeLookupModelID2(modelID)];
47868
- }
47869
47975
  function readRuntimeModelCapabilities(runtimeModel) {
47870
47976
  return isRecord2(runtimeModel?.capabilities) ? runtimeModel.capabilities : undefined;
47871
47977
  }
47872
- function readRuntimeModelLimitOutput(runtimeModel) {
47873
- if (!runtimeModel) {
47874
- return;
47875
- }
47876
- const limit = isRecord2(runtimeModel.limit) ? runtimeModel.limit : readRuntimeModelCapabilities(runtimeModel)?.limit;
47877
- if (!isRecord2(limit)) {
47878
- return;
47879
- }
47880
- return readNumber(limit.output);
47881
- }
47882
47978
  function readRuntimeModelBoolean(runtimeModel, keys) {
47883
- if (!runtimeModel) {
47884
- return;
47885
- }
47886
47979
  const runtimeCapabilities = readRuntimeModelCapabilities(runtimeModel);
47887
47980
  for (const key of keys) {
47888
- const value = runtimeModel[key];
47981
+ const value = runtimeModel?.[key];
47889
47982
  if (typeof value === "boolean") {
47890
47983
  return value;
47891
47984
  }
@@ -47896,114 +47989,110 @@ function readRuntimeModelBoolean(runtimeModel, keys) {
47896
47989
  }
47897
47990
  return;
47898
47991
  }
47899
- function readRuntimeModelModalities(runtimeModel) {
47900
- if (!runtimeModel) {
47901
- return;
47902
- }
47903
- const rootModalities = normalizeModalities(runtimeModel.modalities);
47904
- if (rootModalities) {
47905
- return rootModalities;
47906
- }
47907
- const runtimeCapabilities = readRuntimeModelCapabilities(runtimeModel);
47908
- if (!runtimeCapabilities) {
47909
- return;
47910
- }
47911
- const nestedModalities = normalizeModalities(runtimeCapabilities.modalities);
47912
- if (nestedModalities) {
47913
- return nestedModalities;
47914
- }
47915
- const capabilityModalities = normalizeModalities(runtimeCapabilities);
47916
- if (capabilityModalities) {
47917
- return capabilityModalities;
47918
- }
47919
- return;
47992
+ function readRuntimeModel(runtimeModel) {
47993
+ return isRecord2(runtimeModel) ? runtimeModel : undefined;
47920
47994
  }
47921
47995
  function readRuntimeModelVariants(runtimeModel) {
47922
- if (!runtimeModel) {
47923
- return;
47924
- }
47925
- const rootVariants = normalizeVariantKeys(runtimeModel.variants);
47996
+ const rootVariants = normalizeVariantKeys(runtimeModel?.variants);
47926
47997
  if (rootVariants) {
47927
47998
  return rootVariants;
47928
47999
  }
47929
- const runtimeCapabilities = readRuntimeModelCapabilities(runtimeModel);
47930
- if (!runtimeCapabilities) {
47931
- return;
47932
- }
47933
- return normalizeVariantKeys(runtimeCapabilities.variants);
47934
- }
47935
- function readRuntimeModelTopPSupport(runtimeModel) {
47936
- return readRuntimeModelBoolean(runtimeModel, ["topP", "top_p"]);
48000
+ return normalizeVariantKeys(readRuntimeModelCapabilities(runtimeModel)?.variants);
47937
48001
  }
47938
- function readRuntimeModelToolCallSupport(runtimeModel) {
47939
- return readRuntimeModelBoolean(runtimeModel, ["toolCall", "tool_call", "toolcall"]);
48002
+ function readRuntimeModelModalities(runtimeModel) {
48003
+ const rootModalities = normalizeModalities(runtimeModel?.modalities);
48004
+ if (rootModalities) {
48005
+ return rootModalities;
48006
+ }
48007
+ const runtimeCapabilities = readRuntimeModelCapabilities(runtimeModel);
48008
+ return normalizeModalities(runtimeCapabilities?.modalities) ?? normalizeModalities(runtimeCapabilities);
47940
48009
  }
47941
48010
  function readRuntimeModelReasoningSupport(runtimeModel) {
47942
48011
  return readRuntimeModelBoolean(runtimeModel, ["reasoning"]);
47943
48012
  }
47944
- function readRuntimeModelTemperatureSupport(runtimeModel) {
47945
- return readRuntimeModelBoolean(runtimeModel, ["temperature"]);
47946
- }
47947
48013
  function readRuntimeModelThinkingSupport(runtimeModel) {
47948
48014
  const capabilityValue = readRuntimeModelReasoningSupport(runtimeModel);
47949
48015
  if (capabilityValue !== undefined) {
47950
48016
  return capabilityValue;
47951
48017
  }
47952
- const rootThinkingSupport = readRuntimeModelBoolean(runtimeModel, ["thinking", "supportsThinking"]);
47953
- if (rootThinkingSupport !== undefined) {
47954
- return rootThinkingSupport;
48018
+ const thinkingSupport = readRuntimeModelBoolean(runtimeModel, ["thinking", "supportsThinking"]);
48019
+ if (thinkingSupport !== undefined) {
48020
+ return thinkingSupport;
47955
48021
  }
47956
48022
  const runtimeCapabilities = readRuntimeModelCapabilities(runtimeModel);
47957
- if (!runtimeCapabilities) {
47958
- return;
47959
- }
47960
48023
  for (const key of ["thinking", "supportsThinking"]) {
47961
- const value = runtimeCapabilities[key];
48024
+ const value = runtimeCapabilities?.[key];
47962
48025
  if (typeof value === "boolean") {
47963
48026
  return value;
47964
48027
  }
47965
48028
  }
47966
48029
  return;
47967
48030
  }
47968
- function readRuntimeModel(runtimeModel) {
47969
- return isRecord2(runtimeModel) ? runtimeModel : undefined;
48031
+ function readRuntimeModelTemperatureSupport(runtimeModel) {
48032
+ return readRuntimeModelBoolean(runtimeModel, ["temperature"]);
48033
+ }
48034
+ function readRuntimeModelTopPSupport(runtimeModel) {
48035
+ return readRuntimeModelBoolean(runtimeModel, ["topP", "top_p"]);
48036
+ }
48037
+ function readRuntimeModelToolCallSupport(runtimeModel) {
48038
+ return readRuntimeModelBoolean(runtimeModel, ["toolCall", "tool_call", "toolcall"]);
48039
+ }
48040
+ function readRuntimeModelLimitOutput(runtimeModel) {
48041
+ const limit = isRecord2(runtimeModel?.limit) ? runtimeModel.limit : readRuntimeModelCapabilities(runtimeModel)?.limit;
48042
+ if (!isRecord2(limit)) {
48043
+ return;
48044
+ }
48045
+ return readNumber(limit.output);
48046
+ }
48047
+
48048
+ // src/shared/model-capabilities/get-model-capabilities.ts
48049
+ function normalizeLookupModelID2(modelID) {
48050
+ return modelID.trim().toLowerCase();
48051
+ }
48052
+ function getOverride(modelID) {
48053
+ return MODEL_ID_OVERRIDES[normalizeLookupModelID2(modelID)];
47970
48054
  }
47971
48055
  function getModelCapabilities(input) {
47972
48056
  const canonicalization = resolveModelIDAlias(input.modelID);
47973
- const requestedModelID = canonicalization.requestedModelID;
47974
- const canonicalModelID = canonicalization.canonicalModelID;
47975
48057
  const override = getOverride(input.modelID);
47976
48058
  const runtimeModel = readRuntimeModel(input.runtimeModel ?? findProviderModelMetadata(input.providerID, input.modelID));
47977
48059
  const runtimeSnapshot = input.runtimeSnapshot;
47978
- const bundledSnapshot = input.bundledSnapshot ?? bundledModelCapabilitiesSnapshot;
47979
- const snapshotEntry = runtimeSnapshot?.models?.[canonicalModelID] ?? bundledSnapshot.models[canonicalModelID];
47980
- const heuristicFamily = detectHeuristicModelFamily(canonicalModelID);
48060
+ const bundledSnapshot = input.bundledSnapshot ?? getBundledModelCapabilitiesSnapshot();
48061
+ const snapshotEntry = runtimeSnapshot?.models?.[canonicalization.canonicalModelID] ?? bundledSnapshot.models[canonicalization.canonicalModelID];
48062
+ const heuristicFamily = detectHeuristicModelFamily(canonicalization.canonicalModelID);
47981
48063
  const runtimeVariants = readRuntimeModelVariants(runtimeModel);
47982
- const snapshotSource = runtimeSnapshot?.models?.[canonicalModelID] ? "runtime-snapshot" : bundledSnapshot.models[canonicalModelID] ? "bundled-snapshot" : "none";
48064
+ const runtimeReasoning = readRuntimeModelReasoningSupport(runtimeModel);
48065
+ const runtimeThinking = readRuntimeModelThinkingSupport(runtimeModel);
48066
+ const runtimeTemperature = readRuntimeModelTemperatureSupport(runtimeModel);
48067
+ const runtimeTopP = readRuntimeModelTopPSupport(runtimeModel);
48068
+ const runtimeMaxOutputTokens = readRuntimeModelLimitOutput(runtimeModel);
48069
+ const runtimeToolCall = readRuntimeModelToolCallSupport(runtimeModel);
48070
+ const runtimeModalities = readRuntimeModelModalities(runtimeModel);
48071
+ const snapshotSource = runtimeSnapshot?.models?.[canonicalization.canonicalModelID] ? "runtime-snapshot" : bundledSnapshot.models[canonicalization.canonicalModelID] ? "bundled-snapshot" : "none";
47983
48072
  const familySource = snapshotEntry?.family ? "snapshot" : heuristicFamily?.family ? "heuristic" : "none";
47984
48073
  const variantsSource = runtimeVariants ? "runtime" : override?.variants ? "override" : heuristicFamily?.variants ? "heuristic" : "none";
47985
48074
  const reasoningEffortsSource = override?.reasoningEfforts ? "override" : heuristicFamily?.reasoningEfforts ? "heuristic" : "none";
47986
- const reasoningSource = readRuntimeModelReasoningSupport(runtimeModel) !== undefined ? "runtime" : snapshotEntry?.reasoning !== undefined ? snapshotSource : "none";
47987
- const supportsThinkingSource = override?.supportsThinking !== undefined ? "override" : heuristicFamily?.supportsThinking !== undefined ? "heuristic" : readRuntimeModelThinkingSupport(runtimeModel) !== undefined ? "runtime" : snapshotEntry?.reasoning !== undefined ? snapshotSource : "none";
47988
- const supportsTemperatureSource = readRuntimeModelTemperatureSupport(runtimeModel) !== undefined ? "runtime" : override?.supportsTemperature !== undefined ? "override" : snapshotEntry?.temperature !== undefined ? snapshotSource : "none";
47989
- const supportsTopPSource = readRuntimeModelTopPSupport(runtimeModel) !== undefined ? "runtime" : override?.supportsTopP !== undefined ? "override" : "none";
47990
- const maxOutputTokensSource = readRuntimeModelLimitOutput(runtimeModel) !== undefined ? "runtime" : snapshotEntry?.limit?.output !== undefined ? snapshotSource : "none";
47991
- const toolCallSource = readRuntimeModelToolCallSupport(runtimeModel) !== undefined ? "runtime" : snapshotEntry?.toolCall !== undefined ? snapshotSource : "none";
47992
- const modalitiesSource = readRuntimeModelModalities(runtimeModel) !== undefined ? "runtime" : snapshotEntry?.modalities !== undefined ? snapshotSource : "none";
48075
+ const reasoningSource = runtimeReasoning === undefined ? snapshotEntry?.reasoning === undefined ? "none" : snapshotSource : "runtime";
48076
+ const supportsThinkingSource = override?.supportsThinking !== undefined ? "override" : heuristicFamily?.supportsThinking !== undefined ? "heuristic" : runtimeThinking !== undefined ? "runtime" : snapshotEntry?.reasoning !== undefined ? snapshotSource : "none";
48077
+ const supportsTemperatureSource = runtimeTemperature !== undefined ? "runtime" : override?.supportsTemperature !== undefined ? "override" : snapshotEntry?.temperature !== undefined ? snapshotSource : "none";
48078
+ const supportsTopPSource = runtimeTopP !== undefined ? "runtime" : override?.supportsTopP !== undefined ? "override" : "none";
48079
+ const maxOutputTokensSource = runtimeMaxOutputTokens !== undefined ? "runtime" : snapshotEntry?.limit?.output !== undefined ? snapshotSource : "none";
48080
+ const toolCallSource = runtimeToolCall !== undefined ? "runtime" : snapshotEntry?.toolCall !== undefined ? snapshotSource : "none";
48081
+ const modalitiesSource = runtimeModalities !== undefined ? "runtime" : snapshotEntry?.modalities !== undefined ? snapshotSource : "none";
47993
48082
  const resolutionMode = snapshotSource !== "none" && canonicalization.source === "canonical" ? "snapshot-backed" : snapshotSource !== "none" ? "alias-backed" : familySource === "heuristic" || variantsSource === "heuristic" || reasoningEffortsSource === "heuristic" ? "heuristic-backed" : "unknown";
47994
48083
  return {
47995
- requestedModelID,
47996
- canonicalModelID,
48084
+ requestedModelID: canonicalization.requestedModelID,
48085
+ canonicalModelID: canonicalization.canonicalModelID,
47997
48086
  family: snapshotEntry?.family ?? heuristicFamily?.family,
47998
48087
  variants: runtimeVariants ?? override?.variants ?? heuristicFamily?.variants,
47999
48088
  reasoningEfforts: override?.reasoningEfforts ?? heuristicFamily?.reasoningEfforts,
48000
- reasoning: readRuntimeModelReasoningSupport(runtimeModel) ?? snapshotEntry?.reasoning,
48001
- supportsThinking: override?.supportsThinking ?? heuristicFamily?.supportsThinking ?? readRuntimeModelThinkingSupport(runtimeModel) ?? snapshotEntry?.reasoning,
48002
- supportsTemperature: readRuntimeModelTemperatureSupport(runtimeModel) ?? override?.supportsTemperature ?? snapshotEntry?.temperature,
48003
- supportsTopP: readRuntimeModelTopPSupport(runtimeModel) ?? override?.supportsTopP,
48004
- maxOutputTokens: readRuntimeModelLimitOutput(runtimeModel) ?? snapshotEntry?.limit?.output,
48005
- toolCall: readRuntimeModelToolCallSupport(runtimeModel) ?? snapshotEntry?.toolCall,
48006
- modalities: readRuntimeModelModalities(runtimeModel) ?? snapshotEntry?.modalities,
48089
+ reasoning: runtimeReasoning ?? snapshotEntry?.reasoning,
48090
+ supportsThinking: override?.supportsThinking ?? heuristicFamily?.supportsThinking ?? runtimeThinking ?? snapshotEntry?.reasoning,
48091
+ supportsTemperature: runtimeTemperature ?? override?.supportsTemperature ?? snapshotEntry?.temperature,
48092
+ supportsTopP: runtimeTopP ?? override?.supportsTopP,
48093
+ maxOutputTokens: runtimeMaxOutputTokens ?? snapshotEntry?.limit?.output,
48094
+ toolCall: runtimeToolCall ?? snapshotEntry?.toolCall,
48095
+ modalities: runtimeModalities ?? snapshotEntry?.modalities,
48007
48096
  diagnostics: {
48008
48097
  resolutionMode,
48009
48098
  canonicalization: {
@@ -48024,19 +48113,22 @@ function getModelCapabilities(input) {
48024
48113
  }
48025
48114
  };
48026
48115
  }
48027
- var MODEL_ID_OVERRIDES, bundledModelCapabilitiesSnapshot;
48028
- var init_model_capabilities = __esm(() => {
48029
- init_model_capabilities_generated();
48116
+ var MODEL_ID_OVERRIDES;
48117
+ var init_get_model_capabilities = __esm(() => {
48030
48118
  init_connected_providers_cache();
48031
48119
  init_model_capability_aliases();
48032
48120
  init_model_capability_heuristics();
48121
+ init_bundled_snapshot();
48033
48122
  MODEL_ID_OVERRIDES = {};
48034
- bundledModelCapabilitiesSnapshot = normalizeSnapshot(model_capabilities_generated_default);
48123
+ });
48124
+
48125
+ // src/shared/model-capabilities/index.ts
48126
+ var init_model_capabilities = __esm(() => {
48127
+ init_bundled_snapshot();
48128
+ init_get_model_capabilities();
48035
48129
  });
48036
48130
 
48037
48131
  // src/shared/model-capabilities-cache.ts
48038
- import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
48039
- import { join as join7 } from "path";
48040
48132
  function isRecord3(value) {
48041
48133
  return typeof value === "object" && value !== null && !Array.isArray(value);
48042
48134
  }
@@ -48150,54 +48242,26 @@ async function fetchModelCapabilitiesSnapshot(args = {}) {
48150
48242
  };
48151
48243
  }
48152
48244
  function createModelCapabilitiesCacheStore(getCacheDir2 = getOmoOpenCodeCacheDir) {
48153
- let memSnapshot;
48154
- function getCacheFilePath() {
48155
- return join7(getCacheDir2(), MODEL_CAPABILITIES_CACHE_FILE);
48156
- }
48157
- function ensureCacheDir() {
48158
- const cacheDir = getCacheDir2();
48159
- if (!existsSync5(cacheDir)) {
48160
- mkdirSync3(cacheDir, { recursive: true });
48161
- }
48162
- }
48245
+ const snapshotCacheStore = createJsonFileCacheStore({
48246
+ getCacheDir: getCacheDir2,
48247
+ filename: MODEL_CAPABILITIES_CACHE_FILE,
48248
+ logPrefix: "model-capabilities-cache",
48249
+ cacheLabel: "Cache",
48250
+ describe: (snapshot) => ({
48251
+ modelCount: Object.keys(snapshot.models).length,
48252
+ generatedAt: snapshot.generatedAt
48253
+ }),
48254
+ serialize: (snapshot) => `${JSON.stringify(snapshot, null, 2)}
48255
+ `
48256
+ });
48163
48257
  function readModelCapabilitiesCache() {
48164
- if (memSnapshot !== undefined) {
48165
- return memSnapshot;
48166
- }
48167
- const cacheFile = getCacheFilePath();
48168
- if (!existsSync5(cacheFile)) {
48169
- memSnapshot = null;
48170
- log("[model-capabilities-cache] Cache file not found", { cacheFile });
48171
- return null;
48172
- }
48173
- try {
48174
- const content = readFileSync4(cacheFile, "utf-8");
48175
- const snapshot = JSON.parse(content);
48176
- memSnapshot = snapshot;
48177
- log("[model-capabilities-cache] Read cache", {
48178
- modelCount: Object.keys(snapshot.models).length,
48179
- generatedAt: snapshot.generatedAt
48180
- });
48181
- return snapshot;
48182
- } catch (error) {
48183
- memSnapshot = null;
48184
- log("[model-capabilities-cache] Error reading cache", { error: String(error) });
48185
- return null;
48186
- }
48258
+ return snapshotCacheStore.read();
48187
48259
  }
48188
48260
  function hasModelCapabilitiesCache() {
48189
- return existsSync5(getCacheFilePath());
48261
+ return snapshotCacheStore.has();
48190
48262
  }
48191
48263
  function writeModelCapabilitiesCache(snapshot) {
48192
- ensureCacheDir();
48193
- const cacheFile = getCacheFilePath();
48194
- writeFileSync3(cacheFile, JSON.stringify(snapshot, null, 2) + `
48195
- `);
48196
- memSnapshot = snapshot;
48197
- log("[model-capabilities-cache] Cache written", {
48198
- modelCount: Object.keys(snapshot.models).length,
48199
- generatedAt: snapshot.generatedAt
48200
- });
48264
+ snapshotCacheStore.write(snapshot);
48201
48265
  }
48202
48266
  async function refreshModelCapabilitiesCache(args = {}) {
48203
48267
  const snapshot = await fetchModelCapabilitiesSnapshot(args);
@@ -48214,7 +48278,7 @@ function createModelCapabilitiesCacheStore(getCacheDir2 = getOmoOpenCodeCacheDir
48214
48278
  var MODELS_DEV_SOURCE_URL = "https://models.dev/api.json", MODEL_CAPABILITIES_CACHE_FILE = "model-capabilities.json", defaultModelCapabilitiesCacheStore, readModelCapabilitiesCache, hasModelCapabilitiesCache, writeModelCapabilitiesCache, refreshModelCapabilitiesCache;
48215
48279
  var init_model_capabilities_cache = __esm(() => {
48216
48280
  init_data_path();
48217
- init_logger();
48281
+ init_json_file_cache_store();
48218
48282
  defaultModelCapabilitiesCacheStore = createModelCapabilitiesCacheStore(() => getOmoOpenCodeCacheDir());
48219
48283
  ({
48220
48284
  readModelCapabilitiesCache,
@@ -48259,24 +48323,26 @@ var init_hook_message_injector = __esm(() => {
48259
48323
  });
48260
48324
 
48261
48325
  // src/shared/opencode-storage-paths.ts
48262
- import { join as join8 } from "path";
48326
+ import { join as join7 } from "path";
48263
48327
  var OPENCODE_STORAGE, MESSAGE_STORAGE, PART_STORAGE, SESSION_STORAGE;
48264
48328
  var init_opencode_storage_paths = __esm(() => {
48265
48329
  init_data_path();
48266
48330
  OPENCODE_STORAGE = getOpenCodeStorageDir();
48267
- MESSAGE_STORAGE = join8(OPENCODE_STORAGE, "message");
48268
- PART_STORAGE = join8(OPENCODE_STORAGE, "part");
48269
- SESSION_STORAGE = join8(OPENCODE_STORAGE, "session");
48331
+ MESSAGE_STORAGE = join7(OPENCODE_STORAGE, "message");
48332
+ PART_STORAGE = join7(OPENCODE_STORAGE, "part");
48333
+ SESSION_STORAGE = join7(OPENCODE_STORAGE, "session");
48270
48334
  });
48271
48335
 
48272
48336
  // src/shared/opencode-message-dir.ts
48273
48337
  var init_opencode_message_dir = __esm(() => {
48274
48338
  init_opencode_storage_paths();
48275
- init_opencode_storage_detection();
48276
48339
  init_logger();
48277
48340
  });
48278
48341
 
48279
48342
  // src/shared/agent-display-names.ts
48343
+ function stripAgentListSortPrefix(agentName) {
48344
+ return agentName.replace(/^\u200B+/, "");
48345
+ }
48280
48346
  function getAgentDisplayName(configKey) {
48281
48347
  const exactMatch = AGENT_DISPLAY_NAMES[configKey];
48282
48348
  if (exactMatch !== undefined)
@@ -48289,7 +48355,7 @@ function getAgentDisplayName(configKey) {
48289
48355
  return configKey;
48290
48356
  }
48291
48357
  function getAgentConfigKey(agentName) {
48292
- const lower = agentName.toLowerCase();
48358
+ const lower = stripAgentListSortPrefix(agentName).toLowerCase();
48293
48359
  const reversed = REVERSE_DISPLAY_NAMES[lower];
48294
48360
  if (reversed !== undefined)
48295
48361
  return reversed;
@@ -48307,10 +48373,13 @@ var init_agent_display_names = __esm(() => {
48307
48373
  "sisyphus-junior": "Sisyphus-Junior",
48308
48374
  metis: "Metis (Plan Consultant)",
48309
48375
  momus: "Momus (Plan Critic)",
48376
+ athena: "Athena (Council)",
48377
+ "athena-junior": "Athena-Junior (Council)",
48310
48378
  oracle: "oracle",
48311
48379
  librarian: "librarian",
48312
48380
  explore: "explore",
48313
- "multimodal-looker": "multimodal-looker"
48381
+ "multimodal-looker": "multimodal-looker",
48382
+ "council-member": "council-member"
48314
48383
  };
48315
48384
  REVERSE_DISPLAY_NAMES = Object.fromEntries(Object.entries(AGENT_DISPLAY_NAMES).map(([key, displayName]) => [displayName.toLowerCase(), key]));
48316
48385
  });
@@ -48328,6 +48397,12 @@ var SESSION_TIMEOUT_MS;
48328
48397
  var init_constants2 = __esm(() => {
48329
48398
  SESSION_TIMEOUT_MS = 10 * 60 * 1000;
48330
48399
  });
48400
+ // src/shared/tmux/tmux-utils/server-health.ts
48401
+ var SERVER_RUNNING_KEY;
48402
+ var init_server_health = __esm(() => {
48403
+ SERVER_RUNNING_KEY = Symbol.for("oh-my-opencode:server-running-in-process");
48404
+ });
48405
+
48331
48406
  // src/tools/interactive-bash/tmux-path-resolver.ts
48332
48407
  var init_tmux_path_resolver = () => {};
48333
48408
 
@@ -48339,6 +48414,7 @@ var init_pane_dimensions = __esm(() => {
48339
48414
  // src/shared/tmux/tmux-utils/pane-spawn.ts
48340
48415
  var init_pane_spawn = __esm(() => {
48341
48416
  init_tmux_path_resolver();
48417
+ init_server_health();
48342
48418
  });
48343
48419
 
48344
48420
  // src/shared/tmux/tmux-utils/pane-close.ts
@@ -48351,6 +48427,18 @@ var init_pane_replace = __esm(() => {
48351
48427
  init_tmux_path_resolver();
48352
48428
  });
48353
48429
 
48430
+ // src/shared/tmux/tmux-utils/window-spawn.ts
48431
+ var init_window_spawn = __esm(() => {
48432
+ init_tmux_path_resolver();
48433
+ init_server_health();
48434
+ });
48435
+
48436
+ // src/shared/tmux/tmux-utils/session-spawn.ts
48437
+ var init_session_spawn = __esm(() => {
48438
+ init_tmux_path_resolver();
48439
+ init_server_health();
48440
+ });
48441
+
48354
48442
  // src/shared/tmux/tmux-utils/layout.ts
48355
48443
  var init_layout = __esm(() => {
48356
48444
  init_tmux_path_resolver();
@@ -48358,10 +48446,13 @@ var init_layout = __esm(() => {
48358
48446
 
48359
48447
  // src/shared/tmux/tmux-utils.ts
48360
48448
  var init_tmux_utils = __esm(() => {
48449
+ init_server_health();
48361
48450
  init_pane_dimensions();
48362
48451
  init_pane_spawn();
48363
48452
  init_pane_close();
48364
48453
  init_pane_replace();
48454
+ init_window_spawn();
48455
+ init_session_spawn();
48365
48456
  init_layout();
48366
48457
  });
48367
48458
 
@@ -48493,10 +48584,32 @@ var init_agent_loader = __esm(() => {
48493
48584
  init_logger();
48494
48585
  init_claude_model_mapper();
48495
48586
  });
48587
+
48588
+ // src/features/claude-code-mcp-loader/configure-allowed-env-vars.ts
48589
+ var additionalAllowedMcpEnvVars;
48590
+ var init_configure_allowed_env_vars = __esm(() => {
48591
+ additionalAllowedMcpEnvVars = new Set;
48592
+ });
48593
+
48594
+ // src/features/claude-code-mcp-loader/env-expander.ts
48595
+ var init_env_expander = __esm(() => {
48596
+ init_logger();
48597
+ init_configure_allowed_env_vars();
48598
+ });
48599
+
48600
+ // src/features/claude-code-mcp-loader/scope-filter.ts
48601
+ var init_scope_filter = __esm(() => {
48602
+ init_contains_path();
48603
+ });
48604
+
48496
48605
  // src/features/claude-code-mcp-loader/transformer.ts
48497
- var init_transformer = () => {};
48606
+ var init_transformer = __esm(() => {
48607
+ init_env_expander();
48608
+ });
48498
48609
  // src/features/claude-code-plugin-loader/mcp-server-loader.ts
48499
48610
  var init_mcp_server_loader = __esm(() => {
48611
+ init_env_expander();
48612
+ init_scope_filter();
48500
48613
  init_transformer();
48501
48614
  init_logger();
48502
48615
  });
@@ -48545,21 +48658,30 @@ var init_session_category_registry = __esm(() => {
48545
48658
  sessionCategoryMap = new Map;
48546
48659
  });
48547
48660
 
48548
- // src/shared/plugin-identity.ts
48549
- var PLUGIN_NAME = "oh-my-openagent", LEGACY_PLUGIN_NAME = "oh-my-opencode";
48550
-
48551
48661
  // src/shared/legacy-plugin-warning.ts
48552
48662
  var init_legacy_plugin_warning = __esm(() => {
48553
48663
  init_jsonc_parser();
48554
48664
  init_opencode_config_dir();
48555
48665
  });
48556
48666
 
48667
+ // src/shared/plugin-entry-migrator.ts
48668
+ var init_plugin_entry_migrator = () => {};
48669
+
48670
+ // src/shared/migrate-legacy-plugin-entry.ts
48671
+ var init_migrate_legacy_plugin_entry = __esm(() => {
48672
+ init_main();
48673
+ init_jsonc_parser();
48674
+ init_logger();
48675
+ init_plugin_entry_migrator();
48676
+ });
48677
+
48557
48678
  // src/shared/log-legacy-plugin-startup-warning.ts
48558
48679
  var init_log_legacy_plugin_startup_warning = __esm(() => {
48559
48680
  init_legacy_plugin_warning();
48560
48681
  init_logger();
48682
+ init_migrate_legacy_plugin_entry();
48683
+ init_plugin_entry_migrator();
48561
48684
  });
48562
-
48563
48685
  // src/shared/index.ts
48564
48686
  var init_shared = __esm(() => {
48565
48687
  init_model_resolver();
@@ -48567,6 +48689,7 @@ var init_shared = __esm(() => {
48567
48689
  init_session_category_registry();
48568
48690
  init_frontmatter();
48569
48691
  init_command_executor();
48692
+ init_contains_path();
48570
48693
  init_file_reference_resolver();
48571
48694
  init_logger();
48572
48695
  init_snake_case();
@@ -48586,6 +48709,7 @@ var init_shared = __esm(() => {
48586
48709
  init_external_plugin_detector();
48587
48710
  init_zip_extractor();
48588
48711
  init_binary_downloader();
48712
+ init_write_file_atomically();
48589
48713
  init_agent_variant();
48590
48714
  init_session_cursor();
48591
48715
  init_system_directive();
@@ -48691,11 +48815,11 @@ var init_plugin_name_with_version = __esm(() => {
48691
48815
  });
48692
48816
 
48693
48817
  // src/cli/config-manager/ensure-config-directory-exists.ts
48694
- import { existsSync as existsSync6, mkdirSync as mkdirSync4 } from "fs";
48818
+ import { existsSync as existsSync5, mkdirSync as mkdirSync3 } from "fs";
48695
48819
  function ensureConfigDirectoryExists() {
48696
48820
  const configDir = getConfigDir();
48697
- if (!existsSync6(configDir)) {
48698
- mkdirSync4(configDir, { recursive: true });
48821
+ if (!existsSync5(configDir)) {
48822
+ mkdirSync3(configDir, { recursive: true });
48699
48823
  }
48700
48824
  }
48701
48825
  var init_ensure_config_directory_exists = __esm(() => {
@@ -48732,14 +48856,14 @@ function formatErrorWithSuggestion(err, context) {
48732
48856
  }
48733
48857
 
48734
48858
  // src/cli/config-manager/opencode-config-format.ts
48735
- import { existsSync as existsSync7 } from "fs";
48859
+ import { existsSync as existsSync6 } from "fs";
48736
48860
  function detectConfigFormat() {
48737
48861
  const configJsonc = getConfigJsonc();
48738
48862
  const configJson = getConfigJson();
48739
- if (existsSync7(configJsonc)) {
48863
+ if (existsSync6(configJsonc)) {
48740
48864
  return { format: "jsonc", path: configJsonc };
48741
48865
  }
48742
- if (existsSync7(configJson)) {
48866
+ if (existsSync6(configJson)) {
48743
48867
  return { format: "json", path: configJson };
48744
48868
  }
48745
48869
  return { format: "none", path: configJson };
@@ -48749,7 +48873,7 @@ var init_opencode_config_format = __esm(() => {
48749
48873
  });
48750
48874
 
48751
48875
  // src/cli/config-manager/parse-opencode-config-file.ts
48752
- import { readFileSync as readFileSync5, statSync } from "fs";
48876
+ import { readFileSync as readFileSync4, statSync } from "fs";
48753
48877
  function isEmptyOrWhitespace(content) {
48754
48878
  return content.trim().length === 0;
48755
48879
  }
@@ -48759,7 +48883,7 @@ function parseOpenCodeConfigFileWithError(path3) {
48759
48883
  if (stat.size === 0) {
48760
48884
  return { config: null, error: `Config file is empty: ${path3}. Delete it or add valid JSON content.` };
48761
48885
  }
48762
- const content = readFileSync5(path3, "utf-8");
48886
+ const content = readFileSync4(path3, "utf-8");
48763
48887
  if (isEmptyOrWhitespace(content)) {
48764
48888
  return { config: null, error: `Config file contains only whitespace: ${path3}. Delete it or add valid JSON content.` };
48765
48889
  }
@@ -48783,7 +48907,7 @@ var init_parse_opencode_config_file = __esm(() => {
48783
48907
  });
48784
48908
 
48785
48909
  // src/cli/config-manager/add-plugin-to-opencode-config.ts
48786
- import { readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
48910
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
48787
48911
  async function addPluginToOpenCodeConfig(currentVersion) {
48788
48912
  try {
48789
48913
  ensureConfigDirectoryExists();
@@ -48799,7 +48923,7 @@ async function addPluginToOpenCodeConfig(currentVersion) {
48799
48923
  try {
48800
48924
  if (format2 === "none") {
48801
48925
  const config2 = { plugin: [pluginEntry] };
48802
- writeFileSync4(path3, JSON.stringify(config2, null, 2) + `
48926
+ writeFileSync3(path3, JSON.stringify(config2, null, 2) + `
48803
48927
  `);
48804
48928
  return { success: true, configPath: path3 };
48805
48929
  }
@@ -48828,7 +48952,7 @@ async function addPluginToOpenCodeConfig(currentVersion) {
48828
48952
  }
48829
48953
  config.plugin = normalizedPlugins;
48830
48954
  if (format2 === "jsonc") {
48831
- const content = readFileSync6(path3, "utf-8");
48955
+ const content = readFileSync5(path3, "utf-8");
48832
48956
  const pluginArrayRegex = /((?:"plugin"|plugin)\s*:\s*)\[([\s\S]*?)\]/;
48833
48957
  const match = content.match(pluginArrayRegex);
48834
48958
  if (match) {
@@ -48837,14 +48961,14 @@ async function addPluginToOpenCodeConfig(currentVersion) {
48837
48961
  const newContent = content.replace(pluginArrayRegex, `$1[
48838
48962
  ${formattedPlugins}
48839
48963
  ]`);
48840
- writeFileSync4(path3, newContent);
48964
+ writeFileSync3(path3, newContent);
48841
48965
  } else {
48842
48966
  const newContent = content.replace(/(\{)/, `$1
48843
48967
  "plugin": ["${pluginEntry}"],`);
48844
- writeFileSync4(path3, newContent);
48968
+ writeFileSync3(path3, newContent);
48845
48969
  }
48846
48970
  } else {
48847
- writeFileSync4(path3, JSON.stringify(config, null, 2) + `
48971
+ writeFileSync3(path3, JSON.stringify(config, null, 2) + `
48848
48972
  `);
48849
48973
  }
48850
48974
  return { success: true, configPath: path3 };
@@ -49090,7 +49214,7 @@ function deepMergeRecord(target, source) {
49090
49214
  }
49091
49215
 
49092
49216
  // src/cli/config-manager/write-omo-config.ts
49093
- import { existsSync as existsSync8, readFileSync as readFileSync7, statSync as statSync2, writeFileSync as writeFileSync5 } from "fs";
49217
+ import { existsSync as existsSync7, readFileSync as readFileSync6, statSync as statSync2, writeFileSync as writeFileSync4 } from "fs";
49094
49218
  function isEmptyOrWhitespace2(content) {
49095
49219
  return content.trim().length === 0;
49096
49220
  }
@@ -49107,34 +49231,34 @@ function writeOmoConfig(installConfig) {
49107
49231
  const omoConfigPath = getOmoConfigPath();
49108
49232
  try {
49109
49233
  const newConfig = generateOmoConfig(installConfig);
49110
- if (existsSync8(omoConfigPath)) {
49234
+ if (existsSync7(omoConfigPath)) {
49111
49235
  try {
49112
49236
  const stat = statSync2(omoConfigPath);
49113
- const content = readFileSync7(omoConfigPath, "utf-8");
49237
+ const content = readFileSync6(omoConfigPath, "utf-8");
49114
49238
  if (stat.size === 0 || isEmptyOrWhitespace2(content)) {
49115
- writeFileSync5(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
49239
+ writeFileSync4(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
49116
49240
  `);
49117
49241
  return { success: true, configPath: omoConfigPath };
49118
49242
  }
49119
49243
  const existing = parseJsonc(content);
49120
49244
  if (!existing || typeof existing !== "object" || Array.isArray(existing)) {
49121
- writeFileSync5(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
49245
+ writeFileSync4(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
49122
49246
  `);
49123
49247
  return { success: true, configPath: omoConfigPath };
49124
49248
  }
49125
49249
  const merged = deepMergeRecord(newConfig, existing);
49126
- writeFileSync5(omoConfigPath, JSON.stringify(merged, null, 2) + `
49250
+ writeFileSync4(omoConfigPath, JSON.stringify(merged, null, 2) + `
49127
49251
  `);
49128
49252
  } catch (parseErr) {
49129
49253
  if (parseErr instanceof SyntaxError) {
49130
- writeFileSync5(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
49254
+ writeFileSync4(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
49131
49255
  `);
49132
49256
  return { success: true, configPath: omoConfigPath };
49133
49257
  }
49134
49258
  throw parseErr;
49135
49259
  }
49136
49260
  } else {
49137
- writeFileSync5(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
49261
+ writeFileSync4(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
49138
49262
  `);
49139
49263
  }
49140
49264
  return { success: true, configPath: omoConfigPath };
@@ -49250,10 +49374,10 @@ var init_opencode_binary = __esm(() => {
49250
49374
  });
49251
49375
 
49252
49376
  // src/cli/config-manager/detect-current-config.ts
49253
- import { existsSync as existsSync9, readFileSync as readFileSync8 } from "fs";
49377
+ import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
49254
49378
  function detectProvidersFromOmoConfig() {
49255
49379
  const omoConfigPath = getOmoConfigPath();
49256
- if (!existsSync9(omoConfigPath)) {
49380
+ if (!existsSync8(omoConfigPath)) {
49257
49381
  return {
49258
49382
  hasOpenAI: true,
49259
49383
  hasOpencodeZen: true,
@@ -49263,7 +49387,7 @@ function detectProvidersFromOmoConfig() {
49263
49387
  };
49264
49388
  }
49265
49389
  try {
49266
- const content = readFileSync8(omoConfigPath, "utf-8");
49390
+ const content = readFileSync7(omoConfigPath, "utf-8");
49267
49391
  const omoConfig = parseJsonc(content);
49268
49392
  if (!omoConfig || typeof omoConfig !== "object") {
49269
49393
  return {
@@ -49339,7 +49463,11 @@ var init_detect_current_config = __esm(() => {
49339
49463
  });
49340
49464
 
49341
49465
  // src/cli/config-manager/bun-install.ts
49342
- import { existsSync as existsSync10 } from "fs";
49466
+ import { existsSync as existsSync9 } from "fs";
49467
+ import { join as join8 } from "path";
49468
+ function getDefaultWorkspaceDir() {
49469
+ return join8(getOpenCodeCacheDir(), "packages");
49470
+ }
49343
49471
  function readProcessOutput(stream) {
49344
49472
  if (!stream) {
49345
49473
  return Promise.resolve("");
@@ -49362,9 +49490,9 @@ function logCapturedOutputOnFailure(outputMode, output) {
49362
49490
  }
49363
49491
  async function runBunInstallWithDetails(options) {
49364
49492
  const outputMode = options?.outputMode ?? "pipe";
49365
- const cacheDir = options?.workspaceDir ?? getOpenCodeCacheDir();
49493
+ const cacheDir = options?.workspaceDir ?? getDefaultWorkspaceDir();
49366
49494
  const packageJsonPath = `${cacheDir}/package.json`;
49367
- if (!existsSync10(packageJsonPath)) {
49495
+ if (!existsSync9(packageJsonPath)) {
49368
49496
  return {
49369
49497
  success: false,
49370
49498
  error: `Workspace not initialized: ${packageJsonPath} not found. OpenCode should create this on first run.`
@@ -49508,13 +49636,14 @@ function getWindowsAppdataDir() {
49508
49636
  return null;
49509
49637
  return process.env.APPDATA ?? path4.join(os3.homedir(), "AppData", "Roaming");
49510
49638
  }
49511
- var PACKAGE_NAME = "oh-my-opencode", NPM_REGISTRY_URL, NPM_FETCH_TIMEOUT = 5000, CACHE_DIR, VERSION_FILE, USER_CONFIG_DIR, USER_OPENCODE_CONFIG, USER_OPENCODE_CONFIG_JSONC, INSTALLED_PACKAGE_JSON;
49639
+ var PACKAGE_NAME = "oh-my-openagent", NPM_REGISTRY_URL, NPM_FETCH_TIMEOUT = 5000, CACHE_ROOT_DIR, CACHE_DIR, VERSION_FILE, USER_CONFIG_DIR, USER_OPENCODE_CONFIG, USER_OPENCODE_CONFIG_JSONC, INSTALLED_PACKAGE_JSON;
49512
49640
  var init_constants3 = __esm(() => {
49513
49641
  init_data_path();
49514
49642
  init_opencode_config_dir();
49515
49643
  NPM_REGISTRY_URL = `https://registry.npmjs.org/-/package/${PACKAGE_NAME}/dist-tags`;
49516
- CACHE_DIR = getOpenCodeCacheDir();
49517
- VERSION_FILE = path4.join(CACHE_DIR, "version");
49644
+ CACHE_ROOT_DIR = getOpenCodeCacheDir();
49645
+ CACHE_DIR = path4.join(CACHE_ROOT_DIR, "packages");
49646
+ VERSION_FILE = path4.join(CACHE_ROOT_DIR, "version");
49518
49647
  USER_CONFIG_DIR = getOpenCodeConfigDir({ binary: "opencode" });
49519
49648
  USER_OPENCODE_CONFIG = path4.join(USER_CONFIG_DIR, "opencode.json");
49520
49649
  USER_OPENCODE_CONFIG_JSONC = path4.join(USER_CONFIG_DIR, "opencode.jsonc");
@@ -49861,11 +49990,28 @@ function getIntentVersion(pluginInfo) {
49861
49990
  }
49862
49991
  return pluginInfo.pinnedVersion;
49863
49992
  }
49993
+ function writeCachePackageJson(cachePackageJsonPath, pkgJson) {
49994
+ const tmpPath = `${cachePackageJsonPath}.${crypto.randomUUID()}`;
49995
+ try {
49996
+ fs9.mkdirSync(path8.dirname(cachePackageJsonPath), { recursive: true });
49997
+ fs9.writeFileSync(tmpPath, JSON.stringify(pkgJson, null, 2));
49998
+ fs9.renameSync(tmpPath, cachePackageJsonPath);
49999
+ return { synced: true, error: null };
50000
+ } catch (err) {
50001
+ log("[auto-update-checker] Failed to write cache package.json:", err);
50002
+ safeUnlink(tmpPath);
50003
+ return { synced: false, error: "write_error", message: "Failed to write cache package.json" };
50004
+ }
50005
+ }
49864
50006
  function syncCachePackageJsonToIntent(pluginInfo) {
49865
50007
  const cachePackageJsonPath = path8.join(CACHE_DIR, "package.json");
50008
+ const intentVersion = getIntentVersion(pluginInfo);
49866
50009
  if (!fs9.existsSync(cachePackageJsonPath)) {
49867
- log("[auto-update-checker] Cache package.json not found, nothing to sync");
49868
- return { synced: false, error: "file_not_found", message: "Cache package.json not found" };
50010
+ log("[auto-update-checker] Cache package.json missing, creating workspace package.json", { intentVersion });
50011
+ return {
50012
+ ...writeCachePackageJson(cachePackageJsonPath, { dependencies: { [PACKAGE_NAME]: intentVersion } }),
50013
+ message: `Created cache package.json with: ${intentVersion}`
50014
+ };
49869
50015
  }
49870
50016
  let content;
49871
50017
  let pkgJson;
@@ -49882,11 +50028,20 @@ function syncCachePackageJsonToIntent(pluginInfo) {
49882
50028
  return { synced: false, error: "parse_error", message: "Failed to parse cache package.json (malformed JSON)" };
49883
50029
  }
49884
50030
  if (!pkgJson || !pkgJson.dependencies?.[PACKAGE_NAME]) {
49885
- log("[auto-update-checker] Plugin not in cache package.json dependencies, nothing to sync");
49886
- return { synced: false, error: "plugin_not_in_deps", message: "Plugin not in cache package.json dependencies" };
50031
+ log("[auto-update-checker] Plugin missing from cache package.json dependencies, adding dependency", { intentVersion });
50032
+ const nextPkgJson = {
50033
+ ...pkgJson ?? {},
50034
+ dependencies: {
50035
+ ...pkgJson?.dependencies ?? {},
50036
+ [PACKAGE_NAME]: intentVersion
50037
+ }
50038
+ };
50039
+ return {
50040
+ ...writeCachePackageJson(cachePackageJsonPath, nextPkgJson),
50041
+ message: `Added ${PACKAGE_NAME}: ${intentVersion}`
50042
+ };
49887
50043
  }
49888
50044
  const currentVersion = pkgJson.dependencies[PACKAGE_NAME];
49889
- const intentVersion = getIntentVersion(pluginInfo);
49890
50045
  if (currentVersion === intentVersion) {
49891
50046
  log("[auto-update-checker] Cache package.json already matches intent:", intentVersion);
49892
50047
  return { synced: false, error: null, message: `Already matches intent: ${intentVersion}` };
@@ -49899,16 +50054,10 @@ function syncCachePackageJsonToIntent(pluginInfo) {
49899
50054
  log(`[auto-update-checker] Updating cache package.json: "${currentVersion}" \u2192 "${intentVersion}"`);
49900
50055
  }
49901
50056
  pkgJson.dependencies[PACKAGE_NAME] = intentVersion;
49902
- const tmpPath = `${cachePackageJsonPath}.${crypto.randomUUID()}`;
49903
- try {
49904
- fs9.writeFileSync(tmpPath, JSON.stringify(pkgJson, null, 2));
49905
- fs9.renameSync(tmpPath, cachePackageJsonPath);
49906
- return { synced: true, error: null, message: `Updated: "${currentVersion}" \u2192 "${intentVersion}"` };
49907
- } catch (err) {
49908
- log("[auto-update-checker] Failed to write cache package.json:", err);
49909
- safeUnlink(tmpPath);
49910
- return { synced: false, error: "write_error", message: "Failed to write cache package.json" };
49911
- }
50057
+ return {
50058
+ ...writeCachePackageJson(cachePackageJsonPath, pkgJson),
50059
+ message: `Updated: "${currentVersion}" \u2192 "${intentVersion}"`
50060
+ };
49912
50061
  }
49913
50062
  var EXACT_SEMVER_REGEX2;
49914
50063
  var init_sync_package_json = __esm(() => {
@@ -50035,89 +50184,115 @@ var init_update_toasts = __esm(() => {
50035
50184
 
50036
50185
  // src/hooks/auto-update-checker/hook/background-update-check.ts
50037
50186
  import { existsSync as existsSync21 } from "fs";
50038
- import { join as join19 } from "path";
50187
+ import { join as join20 } from "path";
50188
+ function getCacheWorkspaceDir(deps) {
50189
+ return deps.join(deps.getOpenCodeCacheDir(), "packages");
50190
+ }
50039
50191
  function getPinnedVersionToastMessage(latestVersion) {
50040
50192
  return `Update available: ${latestVersion} (version pinned, update manually)`;
50041
50193
  }
50042
- function resolveActiveInstallWorkspace() {
50043
- const configPaths = getOpenCodeConfigPaths({ binary: "opencode" });
50044
- const cacheDir = getOpenCodeCacheDir();
50045
- const configInstallPath = join19(configPaths.configDir, "node_modules", PACKAGE_NAME, "package.json");
50046
- const cacheInstallPath = join19(cacheDir, "node_modules", PACKAGE_NAME, "package.json");
50047
- if (existsSync21(configInstallPath)) {
50048
- log(`[auto-update-checker] Active workspace: config-dir (${configPaths.configDir})`);
50194
+ function resolveActiveInstallWorkspace(deps) {
50195
+ const configPaths = deps.getOpenCodeConfigPaths({ binary: "opencode" });
50196
+ const cacheDir = getCacheWorkspaceDir(deps);
50197
+ const configInstallPath = deps.join(configPaths.configDir, "node_modules", PACKAGE_NAME, "package.json");
50198
+ const cacheInstallPath = deps.join(cacheDir, "node_modules", PACKAGE_NAME, "package.json");
50199
+ if (deps.existsSync(configInstallPath)) {
50200
+ deps.log(`[auto-update-checker] Active workspace: config-dir (${configPaths.configDir})`);
50049
50201
  return configPaths.configDir;
50050
50202
  }
50051
- if (existsSync21(cacheInstallPath)) {
50052
- log(`[auto-update-checker] Active workspace: cache-dir (${cacheDir})`);
50203
+ if (deps.existsSync(cacheInstallPath)) {
50204
+ deps.log(`[auto-update-checker] Active workspace: cache-dir (${cacheDir})`);
50053
50205
  return cacheDir;
50054
50206
  }
50055
- log(`[auto-update-checker] Active workspace: config-dir (default, no install detected)`);
50207
+ const cachePackageJsonPath = deps.join(cacheDir, "package.json");
50208
+ if (deps.existsSync(cachePackageJsonPath)) {
50209
+ deps.log(`[auto-update-checker] Active workspace: cache-dir (${cacheDir}, package.json present)`);
50210
+ return cacheDir;
50211
+ }
50212
+ deps.log(`[auto-update-checker] Active workspace: config-dir (default, no install detected)`);
50056
50213
  return configPaths.configDir;
50057
50214
  }
50058
- async function runBunInstallSafe(workspaceDir) {
50215
+ async function runBunInstallSafe(workspaceDir, deps) {
50059
50216
  try {
50060
- const result = await runBunInstallWithDetails({ outputMode: "pipe", workspaceDir });
50217
+ const result = await deps.runBunInstallWithDetails({ outputMode: "pipe", workspaceDir });
50061
50218
  if (!result.success && result.error) {
50062
- log("[auto-update-checker] bun install error:", result.error);
50219
+ deps.log("[auto-update-checker] bun install error:", result.error);
50063
50220
  }
50064
50221
  return result.success;
50065
50222
  } catch (err) {
50066
50223
  const errorMessage = err instanceof Error ? err.message : String(err);
50067
- log("[auto-update-checker] bun install error:", errorMessage);
50224
+ deps.log("[auto-update-checker] bun install error:", errorMessage);
50068
50225
  return false;
50069
50226
  }
50070
50227
  }
50071
- async function runBackgroundUpdateCheck(ctx, autoUpdate, getToastMessage) {
50072
- const pluginInfo = findPluginEntry(ctx.directory);
50073
- if (!pluginInfo) {
50074
- log("[auto-update-checker] Plugin not found in config");
50075
- return;
50076
- }
50077
- const cachedVersion = getCachedVersion();
50078
- const currentVersion = cachedVersion ?? pluginInfo.pinnedVersion;
50079
- if (!currentVersion) {
50080
- log("[auto-update-checker] No version found (cached or pinned)");
50081
- return;
50082
- }
50083
- const channel = extractChannel(pluginInfo.pinnedVersion ?? currentVersion);
50084
- const latestVersion = await getLatestVersion(channel);
50085
- if (!latestVersion) {
50086
- log("[auto-update-checker] Failed to fetch latest version for channel:", channel);
50087
- return;
50088
- }
50089
- if (currentVersion === latestVersion) {
50090
- log("[auto-update-checker] Already on latest version for channel:", channel);
50091
- return;
50092
- }
50093
- log(`[auto-update-checker] Update available (${channel}): ${currentVersion} \u2192 ${latestVersion}`);
50094
- if (!autoUpdate) {
50095
- await showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
50096
- log("[auto-update-checker] Auto-update disabled, notification only");
50097
- return;
50098
- }
50099
- if (pluginInfo.isPinned) {
50100
- await showUpdateAvailableToast(ctx, latestVersion, () => getPinnedVersionToastMessage(latestVersion));
50101
- log(`[auto-update-checker] User-pinned version detected (${pluginInfo.entry}), skipping auto-update. Notification only.`);
50102
- return;
50103
- }
50104
- const syncResult = syncCachePackageJsonToIntent(pluginInfo);
50105
- if (syncResult.error) {
50106
- log(`[auto-update-checker] Sync failed with error: ${syncResult.error}`, syncResult.message);
50107
- await showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
50108
- return;
50109
- }
50110
- invalidatePackage(PACKAGE_NAME);
50111
- const activeWorkspace = resolveActiveInstallWorkspace();
50112
- const installSuccess = await runBunInstallSafe(activeWorkspace);
50113
- if (installSuccess) {
50114
- await showAutoUpdatedToast(ctx, currentVersion, latestVersion);
50115
- log(`[auto-update-checker] Update installed: ${currentVersion} \u2192 ${latestVersion}`);
50116
- return;
50228
+ async function primeCacheWorkspace(activeWorkspace, deps) {
50229
+ const cacheWorkspace = getCacheWorkspaceDir(deps);
50230
+ if (activeWorkspace === cacheWorkspace) {
50231
+ return true;
50117
50232
  }
50118
- await showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
50119
- log("[auto-update-checker] bun install failed; update not installed (falling back to notification-only)");
50233
+ deps.log(`[auto-update-checker] Priming cache workspace after install: ${cacheWorkspace}`);
50234
+ return runBunInstallSafe(cacheWorkspace, deps);
50120
50235
  }
50236
+ function createBackgroundUpdateCheckRunner(overrides = {}) {
50237
+ const deps = { ...defaultDeps, ...overrides };
50238
+ return async function runBackgroundUpdateCheck(ctx, autoUpdate, getToastMessage) {
50239
+ const pluginInfo = deps.findPluginEntry(ctx.directory);
50240
+ if (!pluginInfo) {
50241
+ deps.log("[auto-update-checker] Plugin not found in config");
50242
+ return;
50243
+ }
50244
+ const cachedVersion = deps.getCachedVersion();
50245
+ const currentVersion = cachedVersion ?? pluginInfo.pinnedVersion;
50246
+ if (!currentVersion) {
50247
+ deps.log("[auto-update-checker] No version found (cached or pinned)");
50248
+ return;
50249
+ }
50250
+ const channel = deps.extractChannel(pluginInfo.pinnedVersion ?? currentVersion);
50251
+ const latestVersion = await deps.getLatestVersion(channel);
50252
+ if (!latestVersion) {
50253
+ deps.log("[auto-update-checker] Failed to fetch latest version for channel:", channel);
50254
+ return;
50255
+ }
50256
+ if (currentVersion === latestVersion) {
50257
+ deps.log("[auto-update-checker] Already on latest version for channel:", channel);
50258
+ return;
50259
+ }
50260
+ deps.log(`[auto-update-checker] Update available (${channel}): ${currentVersion} \u2192 ${latestVersion}`);
50261
+ if (!autoUpdate) {
50262
+ await deps.showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
50263
+ deps.log("[auto-update-checker] Auto-update disabled, notification only");
50264
+ return;
50265
+ }
50266
+ if (pluginInfo.isPinned) {
50267
+ await deps.showUpdateAvailableToast(ctx, latestVersion, () => getPinnedVersionToastMessage(latestVersion));
50268
+ deps.log(`[auto-update-checker] User-pinned version detected (${pluginInfo.entry}), skipping auto-update. Notification only.`);
50269
+ return;
50270
+ }
50271
+ const syncResult = deps.syncCachePackageJsonToIntent(pluginInfo);
50272
+ if (syncResult.error) {
50273
+ deps.log(`[auto-update-checker] Sync failed with error: ${syncResult.error}`, syncResult.message);
50274
+ await deps.showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
50275
+ return;
50276
+ }
50277
+ deps.invalidatePackage(PACKAGE_NAME);
50278
+ const activeWorkspace = resolveActiveInstallWorkspace(deps);
50279
+ const installSuccess = await runBunInstallSafe(activeWorkspace, deps);
50280
+ if (installSuccess) {
50281
+ const cachePrimed = await primeCacheWorkspace(activeWorkspace, deps);
50282
+ if (!cachePrimed) {
50283
+ await deps.showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
50284
+ deps.log("[auto-update-checker] cache workspace priming failed after install");
50285
+ return;
50286
+ }
50287
+ await deps.showAutoUpdatedToast(ctx, currentVersion, latestVersion);
50288
+ deps.log(`[auto-update-checker] Update installed: ${currentVersion} \u2192 ${latestVersion}`);
50289
+ return;
50290
+ }
50291
+ await deps.showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
50292
+ deps.log("[auto-update-checker] bun install failed; update not installed (falling back to notification-only)");
50293
+ };
50294
+ }
50295
+ var defaultDeps, runBackgroundUpdateCheck;
50121
50296
  var init_background_update_check = __esm(() => {
50122
50297
  init_config_manager();
50123
50298
  init_logger();
@@ -50126,6 +50301,23 @@ var init_background_update_check = __esm(() => {
50126
50301
  init_constants3();
50127
50302
  init_checker();
50128
50303
  init_update_toasts();
50304
+ defaultDeps = {
50305
+ existsSync: existsSync21,
50306
+ join: join20,
50307
+ runBunInstallWithDetails,
50308
+ log,
50309
+ getOpenCodeCacheDir,
50310
+ getOpenCodeConfigPaths,
50311
+ invalidatePackage,
50312
+ extractChannel,
50313
+ findPluginEntry,
50314
+ getCachedVersion,
50315
+ getLatestVersion,
50316
+ syncCachePackageJsonToIntent,
50317
+ showUpdateAvailableToast,
50318
+ showAutoUpdatedToast
50319
+ };
50320
+ runBackgroundUpdateCheck = createBackgroundUpdateCheckRunner();
50129
50321
  });
50130
50322
 
50131
50323
  // src/hooks/auto-update-checker/hook/config-errors-toast.ts
@@ -50391,9 +50583,9 @@ var {
50391
50583
  // package.json
50392
50584
  var package_default = {
50393
50585
  name: "oh-my-opencode",
50394
- version: "3.14.0",
50586
+ version: "3.15.1",
50395
50587
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
50396
- main: "dist/index.js",
50588
+ main: "./dist/index.js",
50397
50589
  types: "dist/index.d.ts",
50398
50590
  type: "module",
50399
50591
  bin: {
@@ -50465,21 +50657,21 @@ var package_default = {
50465
50657
  devDependencies: {
50466
50658
  "@types/js-yaml": "^4.0.9",
50467
50659
  "@types/picomatch": "^3.0.2",
50468
- "bun-types": "1.3.10",
50660
+ "bun-types": "1.3.11",
50469
50661
  typescript: "^5.7.3"
50470
50662
  },
50471
50663
  optionalDependencies: {
50472
- "oh-my-opencode-darwin-arm64": "3.14.0",
50473
- "oh-my-opencode-darwin-x64": "3.14.0",
50474
- "oh-my-opencode-darwin-x64-baseline": "3.14.0",
50475
- "oh-my-opencode-linux-arm64": "3.14.0",
50476
- "oh-my-opencode-linux-arm64-musl": "3.14.0",
50477
- "oh-my-opencode-linux-x64": "3.14.0",
50478
- "oh-my-opencode-linux-x64-baseline": "3.14.0",
50479
- "oh-my-opencode-linux-x64-musl": "3.14.0",
50480
- "oh-my-opencode-linux-x64-musl-baseline": "3.14.0",
50481
- "oh-my-opencode-windows-x64": "3.14.0",
50482
- "oh-my-opencode-windows-x64-baseline": "3.14.0"
50664
+ "oh-my-opencode-darwin-arm64": "3.15.1",
50665
+ "oh-my-opencode-darwin-x64": "3.15.1",
50666
+ "oh-my-opencode-darwin-x64-baseline": "3.15.1",
50667
+ "oh-my-opencode-linux-arm64": "3.15.1",
50668
+ "oh-my-opencode-linux-arm64-musl": "3.15.1",
50669
+ "oh-my-opencode-linux-x64": "3.15.1",
50670
+ "oh-my-opencode-linux-x64-baseline": "3.15.1",
50671
+ "oh-my-opencode-linux-x64-musl": "3.15.1",
50672
+ "oh-my-opencode-linux-x64-musl-baseline": "3.15.1",
50673
+ "oh-my-opencode-windows-x64": "3.15.1",
50674
+ "oh-my-opencode-windows-x64-baseline": "3.15.1"
50483
50675
  },
50484
50676
  overrides: {
50485
50677
  "@opencode-ai/sdk": "^1.2.24"
@@ -50709,7 +50901,7 @@ async function runCliInstaller(args, version) {
50709
50901
  console.log(` Run ${import_picocolors2.default.cyan("opencode")} to start!`);
50710
50902
  console.log();
50711
50903
  printBox(`${import_picocolors2.default.bold("Pro Tip:")} Include ${import_picocolors2.default.cyan("ultrawork")} (or ${import_picocolors2.default.cyan("ulw")}) in your prompt.
50712
- ` + `All features work like magic\u2014parallel agents, background tasks,
50904
+ ` + `All features work like magic-parallel agents, background tasks,
50713
50905
  ` + `deep exploration, and relentless execution until completion.`, "The Magic Word");
50714
50906
  console.log(`${SYMBOLS.star} ${import_picocolors2.default.yellow("If you found this helpful, consider starring the repo!")}`);
50715
50907
  console.log(` ${import_picocolors2.default.dim("gh api --silent --method PUT /user/starred/code-yeongyu/oh-my-openagent >/dev/null 2>&1 || true")}`);
@@ -51484,7 +51676,7 @@ async function runTuiInstaller(args, version) {
51484
51676
  M2.success(import_picocolors4.default.bold(isUpdate ? "Configuration updated!" : "Installation complete!"));
51485
51677
  M2.message(`Run ${import_picocolors4.default.cyan("opencode")} to start!`);
51486
51678
  Me(`Include ${import_picocolors4.default.cyan("ultrawork")} (or ${import_picocolors4.default.cyan("ulw")}) in your prompt.
51487
- ` + `All features work like magic\u2014parallel agents, background tasks,
51679
+ ` + `All features work like magic-parallel agents, background tasks,
51488
51680
  ` + `deep exploration, and relentless execution until completion.`, "The Magic Word");
51489
51681
  M2.message(`${import_picocolors4.default.yellow("\u2605")} If you found this helpful, consider starring the repo!`);
51490
51682
  M2.message(` ${import_picocolors4.default.dim("gh api --silent --method PUT /user/starred/code-yeongyu/oh-my-openagent >/dev/null 2>&1 || true")}`);
@@ -65766,7 +65958,9 @@ var BuiltinSkillNameSchema = exports_external.enum([
65766
65958
  "agent-browser",
65767
65959
  "dev-browser",
65768
65960
  "frontend-ui-ux",
65769
- "git-master"
65961
+ "git-master",
65962
+ "review-work",
65963
+ "ai-slop-remover"
65770
65964
  ]);
65771
65965
  var OverridableAgentNameSchema = exports_external.enum([
65772
65966
  "build",
@@ -65797,9 +65991,14 @@ var FallbackModelObjectSchema = exports_external.object({
65797
65991
  budgetTokens: exports_external.number().optional()
65798
65992
  }).optional()
65799
65993
  });
65994
+ var FallbackModelStringArraySchema = exports_external.array(exports_external.string());
65995
+ var FallbackModelObjectArraySchema = exports_external.array(FallbackModelObjectSchema);
65996
+ var FallbackModelMixedArraySchema = exports_external.array(exports_external.union([exports_external.string(), FallbackModelObjectSchema]));
65800
65997
  var FallbackModelsSchema = exports_external.union([
65801
65998
  exports_external.string(),
65802
- exports_external.array(exports_external.union([exports_external.string(), FallbackModelObjectSchema]))
65999
+ FallbackModelStringArraySchema,
66000
+ FallbackModelObjectArraySchema,
66001
+ FallbackModelMixedArraySchema
65803
66002
  ]);
65804
66003
 
65805
66004
  // src/config/schema/internal/permission.ts
@@ -65887,6 +66086,8 @@ var BackgroundTaskConfigSchema = exports_external.object({
65887
66086
  maxDescendants: exports_external.number().int().min(1).optional(),
65888
66087
  staleTimeoutMs: exports_external.number().min(60000).optional(),
65889
66088
  messageStalenessTimeoutMs: exports_external.number().min(60000).optional(),
66089
+ taskTtlMs: exports_external.number().min(300000).optional(),
66090
+ sessionGoneTimeoutMs: exports_external.number().min(1e4).optional(),
65890
66091
  syncPollTimeoutMs: exports_external.number().min(60000).optional(),
65891
66092
  maxToolCalls: exports_external.number().int().min(10).optional(),
65892
66093
  circuitBreaker: CircuitBreakerConfigSchema.optional()
@@ -65955,7 +66156,8 @@ var BuiltinCommandNameSchema = exports_external.enum([
65955
66156
  "cancel-ralph",
65956
66157
  "refactor",
65957
66158
  "start-work",
65958
- "stop-continuation"
66159
+ "stop-continuation",
66160
+ "remove-ai-slops"
65959
66161
  ]);
65960
66162
  // src/config/schema/dynamic-context-pruning.ts
65961
66163
  var DynamicContextPruningConfigSchema = exports_external.object({
@@ -66000,7 +66202,8 @@ var ExperimentalConfigSchema = exports_external.object({
66000
66202
  safe_hook_creation: exports_external.boolean().optional(),
66001
66203
  disable_omo_env: exports_external.boolean().optional(),
66002
66204
  hashline_edit: exports_external.boolean().optional(),
66003
- model_fallback_title: exports_external.boolean().optional()
66205
+ model_fallback_title: exports_external.boolean().optional(),
66206
+ max_tools: exports_external.number().int().min(1).optional()
66004
66207
  });
66005
66208
  // src/config/schema/git-env-prefix.ts
66006
66209
  var GIT_ENV_ASSIGNMENT_PATTERN = /^(?:[A-Za-z_][A-Za-z0-9_]*=[A-Za-z0-9_-]*)(?: [A-Za-z_][A-Za-z0-9_]*=[A-Za-z0-9_-]*)*$/;
@@ -66043,6 +66246,7 @@ var HookNameSchema = exports_external.enum([
66043
66246
  "non-interactive-env",
66044
66247
  "interactive-bash-session",
66045
66248
  "thinking-block-validator",
66249
+ "tool-pair-validator",
66046
66250
  "ralph-loop",
66047
66251
  "category-skill-reminder",
66048
66252
  "compaction-context-injector",
@@ -66064,11 +66268,13 @@ var HookNameSchema = exports_external.enum([
66064
66268
  "tasks-todowrite-disabler",
66065
66269
  "runtime-fallback",
66066
66270
  "write-existing-file-guard",
66271
+ "bash-file-read-guard",
66067
66272
  "anthropic-effort",
66068
66273
  "hashline-read-enhancer",
66069
66274
  "read-image-resizer",
66070
66275
  "todo-description-override",
66071
- "webfetch-redirect-guard"
66276
+ "webfetch-redirect-guard",
66277
+ "legacy-plugin-toast"
66072
66278
  ]);
66073
66279
  // src/config/schema/model-capabilities.ts
66074
66280
  var ModelCapabilitiesConfigSchema = exports_external.object({
@@ -66184,7 +66390,8 @@ var SisyphusAgentConfigSchema = exports_external.object({
66184
66390
  disabled: exports_external.boolean().optional(),
66185
66391
  default_builder_enabled: exports_external.boolean().optional(),
66186
66392
  planner_enabled: exports_external.boolean().optional(),
66187
- replace_plan: exports_external.boolean().optional()
66393
+ replace_plan: exports_external.boolean().optional(),
66394
+ tdd: exports_external.boolean().default(true).optional()
66188
66395
  });
66189
66396
 
66190
66397
  // src/config/schema/tmux.ts
@@ -66195,12 +66402,18 @@ var TmuxLayoutSchema = exports_external.enum([
66195
66402
  "even-horizontal",
66196
66403
  "even-vertical"
66197
66404
  ]);
66405
+ var TmuxIsolationSchema = exports_external.enum([
66406
+ "inline",
66407
+ "window",
66408
+ "session"
66409
+ ]);
66198
66410
  var TmuxConfigSchema = exports_external.object({
66199
66411
  enabled: exports_external.boolean().default(false),
66200
66412
  layout: TmuxLayoutSchema.default("main-vertical"),
66201
66413
  main_pane_size: exports_external.number().min(20).max(80).default(60),
66202
66414
  main_pane_min_width: exports_external.number().min(40).default(120),
66203
- agent_pane_min_width: exports_external.number().min(20).default(40)
66415
+ agent_pane_min_width: exports_external.number().min(20).default(40),
66416
+ isolation: TmuxIsolationSchema.default("inline")
66204
66417
  });
66205
66418
 
66206
66419
  // src/config/schema/start-work.ts
@@ -66225,6 +66438,7 @@ var OhMyOpenCodeConfigSchema = exports_external.object({
66225
66438
  disabled_hooks: exports_external.array(exports_external.string()).optional(),
66226
66439
  disabled_commands: exports_external.array(BuiltinCommandNameSchema).optional(),
66227
66440
  disabled_tools: exports_external.array(exports_external.string()).optional(),
66441
+ mcp_env_allowlist: exports_external.array(exports_external.string()).optional(),
66228
66442
  hashline_edit: exports_external.boolean().optional(),
66229
66443
  model_fallback: exports_external.boolean().optional(),
66230
66444
  agents: AgentOverridesSchema.optional(),
@@ -66242,7 +66456,11 @@ var OhMyOpenCodeConfigSchema = exports_external.object({
66242
66456
  model_capabilities: ModelCapabilitiesConfigSchema.optional(),
66243
66457
  openclaw: OpenClawConfigSchema.optional(),
66244
66458
  babysitting: BabysittingConfigSchema.optional(),
66245
- git_master: GitMasterConfigSchema.optional(),
66459
+ git_master: GitMasterConfigSchema.default({
66460
+ commit_footer: true,
66461
+ include_co_authored_by: true,
66462
+ git_env_prefix: "GIT_MASTER=1"
66463
+ }),
66246
66464
  browser_automation_engine: BrowserAutomationConfigSchema.optional(),
66247
66465
  websearch: WebsearchConfigSchema.optional(),
66248
66466
  tmux: TmuxConfigSchema.optional(),
@@ -66252,13 +66470,79 @@ var OhMyOpenCodeConfigSchema = exports_external.object({
66252
66470
  });
66253
66471
  // src/plugin-config.ts
66254
66472
  init_shared();
66473
+
66474
+ // src/shared/migrate-legacy-config-file.ts
66475
+ init_logger();
66476
+ init_write_file_atomically();
66477
+ import { existsSync as existsSync10, readFileSync as readFileSync8, renameSync as renameSync2, rmSync } from "fs";
66478
+ import { join as join9, dirname, basename } from "path";
66479
+ function buildCanonicalPath(legacyPath) {
66480
+ const dir = dirname(legacyPath);
66481
+ const ext = basename(legacyPath).includes(".jsonc") ? ".jsonc" : ".json";
66482
+ return join9(dir, `${CONFIG_BASENAME}${ext}`);
66483
+ }
66484
+ function archiveLegacyConfigFile(legacyPath) {
66485
+ const backupPath = `${legacyPath}.bak`;
66486
+ try {
66487
+ renameSync2(legacyPath, backupPath);
66488
+ log("[migrateLegacyConfigFile] Legacy config was migrated and renamed to backup. Update the canonical file only.", {
66489
+ legacyPath,
66490
+ backupPath
66491
+ });
66492
+ return true;
66493
+ } catch (renameError) {
66494
+ try {
66495
+ rmSync(legacyPath);
66496
+ log("[migrateLegacyConfigFile] Legacy config was migrated and removed after backup rename failed. Update the canonical file only.", {
66497
+ legacyPath,
66498
+ backupPath,
66499
+ renameError
66500
+ });
66501
+ return true;
66502
+ } catch (removeError) {
66503
+ log("[migrateLegacyConfigFile] WARNING: canonical config was written but the legacy file still exists and will be ignored. Remove or rename it manually.", {
66504
+ legacyPath,
66505
+ backupPath,
66506
+ renameError,
66507
+ removeError
66508
+ });
66509
+ return false;
66510
+ }
66511
+ }
66512
+ }
66513
+ function migrateLegacyConfigFile(legacyPath) {
66514
+ if (!existsSync10(legacyPath))
66515
+ return false;
66516
+ if (!basename(legacyPath).startsWith(LEGACY_CONFIG_BASENAME))
66517
+ return false;
66518
+ const canonicalPath = buildCanonicalPath(legacyPath);
66519
+ if (existsSync10(canonicalPath))
66520
+ return false;
66521
+ try {
66522
+ const content = readFileSync8(legacyPath, "utf-8");
66523
+ writeFileAtomically(canonicalPath, content);
66524
+ const archivedLegacyConfig = archiveLegacyConfigFile(legacyPath);
66525
+ log("[migrateLegacyConfigFile] Migrated legacy config to canonical path", {
66526
+ from: legacyPath,
66527
+ to: canonicalPath,
66528
+ archivedLegacyConfig
66529
+ });
66530
+ return archivedLegacyConfig;
66531
+ } catch (error48) {
66532
+ log("[migrateLegacyConfigFile] Failed to migrate legacy config file", { legacyPath, error: error48 });
66533
+ return false;
66534
+ }
66535
+ }
66536
+
66537
+ // src/plugin-config.ts
66255
66538
  var PARTIAL_STRING_ARRAY_KEYS = new Set([
66256
66539
  "disabled_mcps",
66257
66540
  "disabled_agents",
66258
66541
  "disabled_skills",
66259
66542
  "disabled_hooks",
66260
66543
  "disabled_commands",
66261
- "disabled_tools"
66544
+ "disabled_tools",
66545
+ "mcp_env_allowlist"
66262
66546
  ]);
66263
66547
  function parseConfigPartially(rawConfig) {
66264
66548
  const fullResult = OhMyOpenCodeConfigSchema.safeParse(rawConfig);
@@ -66289,7 +66573,7 @@ function parseConfigPartially(rawConfig) {
66289
66573
  }
66290
66574
  }
66291
66575
  if (invalidSections.length > 0) {
66292
- log("Partial config loaded \u2014 invalid sections skipped:", invalidSections);
66576
+ log("Partial config loaded - invalid sections skipped:", invalidSections);
66293
66577
  }
66294
66578
  return partialConfig;
66295
66579
  }
@@ -66308,7 +66592,7 @@ function loadConfigFromPath(configPath, _ctx) {
66308
66592
  log(`Config validation error in ${configPath}:`, result.error.issues);
66309
66593
  addConfigLoadError({
66310
66594
  path: configPath,
66311
- error: `Partial config loaded \u2014 invalid sections skipped: ${errorMsg}`
66595
+ error: `Partial config loaded - invalid sections skipped: ${errorMsg}`
66312
66596
  });
66313
66597
  const partialResult = parseConfigPartially(rawConfig);
66314
66598
  if (partialResult) {
@@ -66366,23 +66650,51 @@ function mergeConfigs(base, override) {
66366
66650
  ...override.disabled_tools ?? []
66367
66651
  ])
66368
66652
  ],
66653
+ mcp_env_allowlist: [
66654
+ ...new Set([
66655
+ ...base.mcp_env_allowlist ?? [],
66656
+ ...override.mcp_env_allowlist ?? []
66657
+ ])
66658
+ ],
66369
66659
  claude_code: deepMerge(base.claude_code, override.claude_code)
66370
66660
  };
66371
66661
  }
66372
66662
  function loadPluginConfig(directory, ctx) {
66373
66663
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
66374
66664
  const userDetected = detectPluginConfigFile(configDir);
66375
- const userConfigPath = userDetected.format !== "none" ? userDetected.path : path3.join(configDir, "oh-my-opencode.json");
66665
+ let userConfigPath = userDetected.format !== "none" ? userDetected.path : path3.join(configDir, "oh-my-opencode.json");
66666
+ if (userDetected.legacyPath) {
66667
+ log("Canonical plugin config detected alongside legacy config. Remove the legacy file to avoid confusion.", {
66668
+ canonicalPath: userDetected.path,
66669
+ legacyPath: userDetected.legacyPath
66670
+ });
66671
+ }
66672
+ if (userDetected.format !== "none" && path3.basename(userDetected.path).startsWith(LEGACY_CONFIG_BASENAME)) {
66673
+ migrateLegacyConfigFile(userDetected.path);
66674
+ userConfigPath = path3.join(path3.dirname(userDetected.path), `${CONFIG_BASENAME}${path3.extname(userDetected.path)}`);
66675
+ }
66376
66676
  const projectBasePath = path3.join(directory, ".opencode");
66377
66677
  const projectDetected = detectPluginConfigFile(projectBasePath);
66378
- const projectConfigPath = projectDetected.format !== "none" ? projectDetected.path : path3.join(projectBasePath, "oh-my-opencode.json");
66379
- let config2 = loadConfigFromPath(userConfigPath, ctx) ?? {};
66678
+ let projectConfigPath = projectDetected.format !== "none" ? projectDetected.path : path3.join(projectBasePath, "oh-my-opencode.json");
66679
+ if (projectDetected.legacyPath) {
66680
+ log("Canonical plugin config detected alongside legacy config. Remove the legacy file to avoid confusion.", {
66681
+ canonicalPath: projectDetected.path,
66682
+ legacyPath: projectDetected.legacyPath
66683
+ });
66684
+ }
66685
+ if (projectDetected.format !== "none" && path3.basename(projectDetected.path).startsWith(LEGACY_CONFIG_BASENAME)) {
66686
+ migrateLegacyConfigFile(projectDetected.path);
66687
+ projectConfigPath = path3.join(path3.dirname(projectDetected.path), `${CONFIG_BASENAME}${path3.extname(projectDetected.path)}`);
66688
+ }
66689
+ const userConfig = loadConfigFromPath(userConfigPath, ctx);
66690
+ let config2 = userConfig ?? OhMyOpenCodeConfigSchema.parse({});
66380
66691
  const projectConfig = loadConfigFromPath(projectConfigPath, ctx);
66381
66692
  if (projectConfig) {
66382
66693
  config2 = mergeConfigs(config2, projectConfig);
66383
66694
  }
66384
66695
  config2 = {
66385
- ...config2
66696
+ ...config2,
66697
+ mcp_env_allowlist: userConfig?.mcp_env_allowlist ?? []
66386
66698
  };
66387
66699
  log("Final merged config", {
66388
66700
  agents: config2.agents,
@@ -67841,7 +68153,7 @@ var import_picocolors9 = __toESM(require_picocolors(), 1);
67841
68153
 
67842
68154
  // src/cli/run/opencode-binary-resolver.ts
67843
68155
  init_spawn_with_windows_hide();
67844
- import { delimiter, dirname, join as join10 } from "path";
68156
+ import { delimiter, dirname as dirname3, join as join11 } from "path";
67845
68157
  var OPENCODE_COMMANDS = ["opencode", "opencode-desktop"];
67846
68158
  var WINDOWS_SUFFIXES = ["", ".exe", ".cmd", ".bat", ".ps1"];
67847
68159
  function getCommandCandidates(platform) {
@@ -67864,7 +68176,7 @@ function collectCandidateBinaryPaths(pathEnv, which = Bun.which, platform = proc
67864
68176
  }
67865
68177
  for (const entry of (pathEnv ?? "").split(delimiter).filter(Boolean)) {
67866
68178
  for (const command of commandCandidates) {
67867
- addCandidate(join10(entry, command));
68179
+ addCandidate(join11(entry, command));
67868
68180
  }
67869
68181
  }
67870
68182
  return candidates;
@@ -67891,7 +68203,7 @@ async function findWorkingOpencodeBinary(pathEnv = process.env.PATH, probe = can
67891
68203
  return null;
67892
68204
  }
67893
68205
  function buildPathWithBinaryFirst(pathEnv, binaryPath) {
67894
- const preferredDir = dirname(binaryPath);
68206
+ const preferredDir = dirname3(binaryPath);
67895
68207
  const existing = (pathEnv ?? "").split(delimiter).filter((entry) => entry.length > 0 && entry !== preferredDir);
67896
68208
  return [preferredDir, ...existing].join(delimiter);
67897
68209
  }
@@ -68093,6 +68405,22 @@ async function readOutput(stream, streamName) {
68093
68405
  return "";
68094
68406
  }
68095
68407
  }
68408
+ function resolveHookShellCommand(command) {
68409
+ const shellType = detectShellType();
68410
+ switch (shellType) {
68411
+ case "powershell": {
68412
+ const powershellExecutable = process.platform === "win32" ? "powershell.exe" : "pwsh";
68413
+ return [powershellExecutable, "-NoProfile", "-Command", command];
68414
+ }
68415
+ case "cmd":
68416
+ return [process.env.ComSpec || "cmd.exe", "/d", "/s", "/c", command];
68417
+ case "csh":
68418
+ return ["csh", "-c", command];
68419
+ case "unix":
68420
+ default:
68421
+ return ["sh", "-c", command];
68422
+ }
68423
+ }
68096
68424
  async function executeOnCompleteHook(options) {
68097
68425
  const { command, sessionId, exitCode, durationMs, messageCount } = options;
68098
68426
  const trimmedCommand = command.trim();
@@ -68101,7 +68429,8 @@ async function executeOnCompleteHook(options) {
68101
68429
  }
68102
68430
  log("Running on-complete hook", { command: trimmedCommand });
68103
68431
  try {
68104
- const proc = spawnWithWindowsHide(["sh", "-c", trimmedCommand], {
68432
+ const shellCommand = resolveHookShellCommand(trimmedCommand);
68433
+ const proc = spawnWithWindowsHide(shellCommand, {
68105
68434
  env: {
68106
68435
  ...process.env,
68107
68436
  SESSION_ID: sessionId,
@@ -68230,11 +68559,11 @@ var BOULDER_STATE_PATH = `${BOULDER_DIR}/${BOULDER_FILE}`;
68230
68559
  var NOTEPAD_DIR = "notepads";
68231
68560
  var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
68232
68561
  // src/features/boulder-state/storage.ts
68233
- import { existsSync as existsSync12, readFileSync as readFileSync10, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, readdirSync } from "fs";
68234
- import { dirname as dirname2, join as join11, basename } from "path";
68562
+ import { existsSync as existsSync12, readFileSync as readFileSync10, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, readdirSync } from "fs";
68563
+ import { dirname as dirname4, join as join12, basename as basename3 } from "path";
68235
68564
  var RESERVED_KEYS = new Set(["__proto__", "prototype", "constructor"]);
68236
68565
  function getBoulderFilePath(directory) {
68237
- return join11(directory, BOULDER_DIR, BOULDER_FILE);
68566
+ return join12(directory, BOULDER_DIR, BOULDER_FILE);
68238
68567
  }
68239
68568
  function readBoulderState(directory) {
68240
68569
  const filePath = getBoulderFilePath(directory);
@@ -68280,10 +68609,10 @@ function getPlanProgress(planPath) {
68280
68609
  // src/features/run-continuation-state/constants.ts
68281
68610
  var CONTINUATION_MARKER_DIR = ".sisyphus/run-continuation";
68282
68611
  // src/features/run-continuation-state/storage.ts
68283
- import { existsSync as existsSync13, mkdirSync as mkdirSync6, readFileSync as readFileSync11, rmSync, writeFileSync as writeFileSync7 } from "fs";
68284
- import { join as join12 } from "path";
68612
+ import { existsSync as existsSync13, mkdirSync as mkdirSync5, readFileSync as readFileSync11, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "fs";
68613
+ import { join as join13 } from "path";
68285
68614
  function getMarkerPath(directory, sessionID) {
68286
- return join12(directory, CONTINUATION_MARKER_DIR, `${sessionID}.json`);
68615
+ return join13(directory, CONTINUATION_MARKER_DIR, `${sessionID}.json`);
68287
68616
  }
68288
68617
  function readContinuationMarker(directory, sessionID) {
68289
68618
  const markerPath = getMarkerPath(directory, sessionID);
@@ -68315,8 +68644,8 @@ function getActiveContinuationMarkerReason(marker) {
68315
68644
  }
68316
68645
  // src/hooks/ralph-loop/storage.ts
68317
68646
  init_frontmatter();
68318
- import { existsSync as existsSync14, readFileSync as readFileSync12, writeFileSync as writeFileSync8, unlinkSync, mkdirSync as mkdirSync7 } from "fs";
68319
- import { dirname as dirname3, join as join13 } from "path";
68647
+ import { existsSync as existsSync14, readFileSync as readFileSync12, writeFileSync as writeFileSync7, unlinkSync, mkdirSync as mkdirSync6 } from "fs";
68648
+ import { dirname as dirname5, join as join14 } from "path";
68320
68649
 
68321
68650
  // src/hooks/ralph-loop/constants.ts
68322
68651
  var DEFAULT_STATE_FILE = ".sisyphus/ralph-loop.local.md";
@@ -68325,7 +68654,7 @@ var DEFAULT_COMPLETION_PROMISE = "DONE";
68325
68654
 
68326
68655
  // src/hooks/ralph-loop/storage.ts
68327
68656
  function getStateFilePath(directory, customPath) {
68328
- return customPath ? join13(directory, customPath) : join13(directory, DEFAULT_STATE_FILE);
68657
+ return customPath ? join14(directory, customPath) : join14(directory, DEFAULT_STATE_FILE);
68329
68658
  }
68330
68659
  function readState(directory, customPath) {
68331
68660
  const filePath = getStateFilePath(directory, customPath);
@@ -69045,24 +69374,24 @@ import { existsSync as existsSync25, readFileSync as readFileSync22 } from "fs";
69045
69374
  init_spawn_with_windows_hide();
69046
69375
  import { existsSync as existsSync22 } from "fs";
69047
69376
  import { homedir as homedir5 } from "os";
69048
- import { join as join20 } from "path";
69377
+ import { join as join21 } from "path";
69049
69378
  function getDesktopAppPaths(platform) {
69050
69379
  const home = homedir5();
69051
69380
  switch (platform) {
69052
69381
  case "darwin":
69053
69382
  return [
69054
69383
  "/Applications/OpenCode.app/Contents/MacOS/OpenCode",
69055
- join20(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
69384
+ join21(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
69056
69385
  ];
69057
69386
  case "win32": {
69058
69387
  const programFiles = process.env.ProgramFiles;
69059
69388
  const localAppData = process.env.LOCALAPPDATA;
69060
69389
  const paths = [];
69061
69390
  if (programFiles) {
69062
- paths.push(join20(programFiles, "OpenCode", "OpenCode.exe"));
69391
+ paths.push(join21(programFiles, "OpenCode", "OpenCode.exe"));
69063
69392
  }
69064
69393
  if (localAppData) {
69065
- paths.push(join20(localAppData, "OpenCode", "OpenCode.exe"));
69394
+ paths.push(join21(localAppData, "OpenCode", "OpenCode.exe"));
69066
69395
  }
69067
69396
  return paths;
69068
69397
  }
@@ -69070,8 +69399,8 @@ function getDesktopAppPaths(platform) {
69070
69399
  return [
69071
69400
  "/usr/bin/opencode",
69072
69401
  "/usr/lib/opencode/opencode",
69073
- join20(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
69074
- join20(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
69402
+ join21(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
69403
+ join21(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
69075
69404
  ];
69076
69405
  default:
69077
69406
  return [];
@@ -69222,21 +69551,21 @@ init_checker();
69222
69551
  init_auto_update_checker();
69223
69552
  import { existsSync as existsSync24, readFileSync as readFileSync21 } from "fs";
69224
69553
  import { homedir as homedir6 } from "os";
69225
- import { join as join21 } from "path";
69554
+ import { join as join22 } from "path";
69226
69555
  init_shared();
69227
69556
  function getPlatformDefaultCacheDir(platform = process.platform) {
69228
69557
  if (platform === "darwin")
69229
- return join21(homedir6(), "Library", "Caches");
69558
+ return join22(homedir6(), "Library", "Caches");
69230
69559
  if (platform === "win32")
69231
- return process.env.LOCALAPPDATA ?? join21(homedir6(), "AppData", "Local");
69232
- return join21(homedir6(), ".cache");
69560
+ return process.env.LOCALAPPDATA ?? join22(homedir6(), "AppData", "Local");
69561
+ return join22(homedir6(), ".cache");
69233
69562
  }
69234
69563
  function resolveOpenCodeCacheDir() {
69235
69564
  const xdgCacheHome = process.env.XDG_CACHE_HOME;
69236
69565
  if (xdgCacheHome)
69237
- return join21(xdgCacheHome, "opencode");
69566
+ return join22(xdgCacheHome, "opencode");
69238
69567
  const fromShared = getOpenCodeCacheDir();
69239
- const platformDefault = join21(getPlatformDefaultCacheDir(), "opencode");
69568
+ const platformDefault = join22(getPlatformDefaultCacheDir(), "opencode");
69240
69569
  if (existsSync24(fromShared) || !existsSync24(platformDefault))
69241
69570
  return fromShared;
69242
69571
  return platformDefault;
@@ -69269,13 +69598,13 @@ function getLoadedPluginVersion() {
69269
69598
  const candidates = [
69270
69599
  {
69271
69600
  cacheDir: configDir,
69272
- cachePackagePath: join21(configDir, "package.json"),
69273
- installedPackagePath: join21(configDir, "node_modules", PACKAGE_NAME2, "package.json")
69601
+ cachePackagePath: join22(configDir, "package.json"),
69602
+ installedPackagePath: join22(configDir, "node_modules", PACKAGE_NAME2, "package.json")
69274
69603
  },
69275
69604
  {
69276
69605
  cacheDir,
69277
- cachePackagePath: join21(cacheDir, "package.json"),
69278
- installedPackagePath: join21(cacheDir, "node_modules", PACKAGE_NAME2, "package.json")
69606
+ cachePackagePath: join22(cacheDir, "package.json"),
69607
+ installedPackagePath: join22(cacheDir, "node_modules", PACKAGE_NAME2, "package.json")
69279
69608
  }
69280
69609
  ];
69281
69610
  const selectedCandidate = candidates.find((candidate) => existsSync24(candidate.installedPackagePath)) ?? candidates[0];
@@ -69425,22 +69754,22 @@ async function checkSystem() {
69425
69754
 
69426
69755
  // src/cli/doctor/checks/config.ts
69427
69756
  import { readFileSync as readFileSync25 } from "fs";
69428
- import { join as join25 } from "path";
69757
+ import { join as join26 } from "path";
69429
69758
  init_shared();
69430
69759
 
69431
69760
  // src/cli/doctor/checks/model-resolution-cache.ts
69432
69761
  init_shared();
69433
69762
  import { existsSync as existsSync26, readFileSync as readFileSync23 } from "fs";
69434
69763
  import { homedir as homedir7 } from "os";
69435
- import { join as join22 } from "path";
69764
+ import { join as join23 } from "path";
69436
69765
  function getOpenCodeCacheDir2() {
69437
69766
  const xdgCache = process.env.XDG_CACHE_HOME;
69438
69767
  if (xdgCache)
69439
- return join22(xdgCache, "opencode");
69440
- return join22(homedir7(), ".cache", "opencode");
69768
+ return join23(xdgCache, "opencode");
69769
+ return join23(homedir7(), ".cache", "opencode");
69441
69770
  }
69442
69771
  function loadAvailableModelsFromCache() {
69443
- const cacheFile = join22(getOpenCodeCacheDir2(), "models.json");
69772
+ const cacheFile = join23(getOpenCodeCacheDir2(), "models.json");
69444
69773
  if (!existsSync26(cacheFile)) {
69445
69774
  return { providers: [], modelCount: 0, cacheExists: false };
69446
69775
  }
@@ -69468,9 +69797,9 @@ init_model_capabilities();
69468
69797
  // src/cli/doctor/checks/model-resolution-config.ts
69469
69798
  init_shared();
69470
69799
  import { readFileSync as readFileSync24 } from "fs";
69471
- import { join as join23 } from "path";
69800
+ import { join as join24 } from "path";
69472
69801
  var USER_CONFIG_DIR2 = getOpenCodeConfigPaths({ binary: "opencode", version: null }).configDir;
69473
- var PROJECT_CONFIG_DIR = join23(process.cwd(), ".opencode");
69802
+ var PROJECT_CONFIG_DIR = join24(process.cwd(), ".opencode");
69474
69803
  function loadOmoConfig() {
69475
69804
  const projectDetected = detectPluginConfigFile(PROJECT_CONFIG_DIR);
69476
69805
  if (projectDetected.format !== "none") {
@@ -69495,7 +69824,7 @@ function loadOmoConfig() {
69495
69824
 
69496
69825
  // src/cli/doctor/checks/model-resolution-details.ts
69497
69826
  init_shared();
69498
- import { join as join24 } from "path";
69827
+ import { join as join25 } from "path";
69499
69828
 
69500
69829
  // src/cli/doctor/checks/model-resolution-variant.ts
69501
69830
  function formatModelWithVariant(model, variant) {
@@ -69537,7 +69866,7 @@ function formatCapabilityResolutionLabel(mode) {
69537
69866
  }
69538
69867
  function buildModelResolutionDetails(options) {
69539
69868
  const details = [];
69540
- const cacheFile = join24(getOpenCodeCacheDir(), "models.json");
69869
+ const cacheFile = join25(getOpenCodeCacheDir(), "models.json");
69541
69870
  details.push("\u2550\u2550\u2550 Available Models (from cache) \u2550\u2550\u2550");
69542
69871
  details.push("");
69543
69872
  if (options.available.cacheExists) {
@@ -69598,7 +69927,7 @@ function buildEffectiveResolution(requirement, userOverride) {
69598
69927
 
69599
69928
  // src/cli/doctor/checks/model-resolution.ts
69600
69929
  function parseProviderModel(value) {
69601
- const slashIndex = value.indexOf("/");
69930
+ const slashIndex = value.lastIndexOf("/");
69602
69931
  if (slashIndex <= 0 || slashIndex === value.length - 1) {
69603
69932
  return null;
69604
69933
  }
@@ -69693,7 +70022,7 @@ async function checkModels() {
69693
70022
 
69694
70023
  // src/cli/doctor/checks/config.ts
69695
70024
  var USER_CONFIG_DIR3 = getOpenCodeConfigDir({ binary: "opencode" });
69696
- var PROJECT_CONFIG_DIR2 = join25(process.cwd(), ".opencode");
70025
+ var PROJECT_CONFIG_DIR2 = join26(process.cwd(), ".opencode");
69697
70026
  function findConfigPath() {
69698
70027
  const projectConfig = detectPluginConfigFile(PROJECT_CONFIG_DIR2);
69699
70028
  if (projectConfig.format !== "none")
@@ -69815,7 +70144,7 @@ async function checkConfig() {
69815
70144
  init_spawn_with_windows_hide();
69816
70145
  import { existsSync as existsSync27 } from "fs";
69817
70146
  import { createRequire } from "module";
69818
- import { dirname as dirname6, join as join26 } from "path";
70147
+ import { dirname as dirname9, join as join27 } from "path";
69819
70148
  async function checkBinaryExists(binary2) {
69820
70149
  try {
69821
70150
  const path10 = Bun.which(binary2);
@@ -69872,11 +70201,11 @@ async function checkAstGrepNapi() {
69872
70201
  };
69873
70202
  } catch {
69874
70203
  const { existsSync: existsSync28 } = await import("fs");
69875
- const { join: join27 } = await import("path");
70204
+ const { join: join28 } = await import("path");
69876
70205
  const { homedir: homedir8 } = await import("os");
69877
70206
  const pathsToCheck = [
69878
- join27(homedir8(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
69879
- join27(process.cwd(), "node_modules", "@ast-grep", "napi")
70207
+ join28(homedir8(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
70208
+ join28(process.cwd(), "node_modules", "@ast-grep", "napi")
69880
70209
  ];
69881
70210
  for (const napiPath of pathsToCheck) {
69882
70211
  if (existsSync28(napiPath)) {
@@ -69904,7 +70233,7 @@ function findCommentCheckerPackageBinary() {
69904
70233
  try {
69905
70234
  const require2 = createRequire(import.meta.url);
69906
70235
  const pkgPath = require2.resolve("@code-yeongyu/comment-checker/package.json");
69907
- const binaryPath = join26(dirname6(pkgPath), "bin", binaryName);
70236
+ const binaryPath = join27(dirname9(pkgPath), "bin", binaryName);
69908
70237
  if (existsSync27(binaryPath))
69909
70238
  return binaryPath;
69910
70239
  } catch {}
@@ -70063,7 +70392,7 @@ var BUILTIN_SERVERS = {
70063
70392
  };
70064
70393
  // src/tools/lsp/server-config-loader.ts
70065
70394
  import { existsSync as existsSync28, readFileSync as readFileSync26 } from "fs";
70066
- import { join as join27 } from "path";
70395
+ import { join as join28 } from "path";
70067
70396
  init_shared();
70068
70397
  init_jsonc_parser();
70069
70398
  function loadJsonFile(path10) {
@@ -70079,9 +70408,9 @@ function getConfigPaths2() {
70079
70408
  const cwd = process.cwd();
70080
70409
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
70081
70410
  return {
70082
- project: detectPluginConfigFile(join27(cwd, ".opencode")).path,
70411
+ project: detectPluginConfigFile(join28(cwd, ".opencode")).path,
70083
70412
  user: detectPluginConfigFile(configDir).path,
70084
- opencode: detectConfigFile(join27(configDir, "opencode")).path
70413
+ opencode: detectConfigFile(join28(configDir, "opencode")).path
70085
70414
  };
70086
70415
  }
70087
70416
  function loadAllConfigs() {
@@ -70151,20 +70480,20 @@ function getMergedServers() {
70151
70480
 
70152
70481
  // src/tools/lsp/server-installation.ts
70153
70482
  import { existsSync as existsSync29 } from "fs";
70154
- import { delimiter as delimiter2, join as join29 } from "path";
70483
+ import { delimiter as delimiter2, join as join30 } from "path";
70155
70484
 
70156
70485
  // src/tools/lsp/server-path-bases.ts
70157
70486
  init_shared();
70158
- import { join as join28 } from "path";
70487
+ import { join as join29 } from "path";
70159
70488
  function getLspServerAdditionalPathBases(workingDirectory) {
70160
70489
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
70161
- const dataDir = join28(getDataDir(), "opencode");
70490
+ const dataDir = join29(getDataDir(), "opencode");
70162
70491
  return [
70163
- join28(workingDirectory, "node_modules", ".bin"),
70164
- join28(configDir, "bin"),
70165
- join28(configDir, "node_modules", ".bin"),
70166
- join28(dataDir, "bin"),
70167
- join28(dataDir, "bin", "node_modules", ".bin")
70492
+ join29(workingDirectory, "node_modules", ".bin"),
70493
+ join29(configDir, "bin"),
70494
+ join29(configDir, "node_modules", ".bin"),
70495
+ join29(dataDir, "bin"),
70496
+ join29(dataDir, "bin", "node_modules", ".bin")
70168
70497
  ];
70169
70498
  }
70170
70499
 
@@ -70195,14 +70524,14 @@ function isServerInstalled(command) {
70195
70524
  const paths = pathEnv.split(delimiter2);
70196
70525
  for (const p2 of paths) {
70197
70526
  for (const suffix of exts) {
70198
- if (existsSync29(join29(p2, cmd + suffix))) {
70527
+ if (existsSync29(join30(p2, cmd + suffix))) {
70199
70528
  return true;
70200
70529
  }
70201
70530
  }
70202
70531
  }
70203
70532
  for (const base of getLspServerAdditionalPathBases(process.cwd())) {
70204
70533
  for (const suffix of exts) {
70205
- if (existsSync29(join29(base, cmd + suffix))) {
70534
+ if (existsSync29(join30(base, cmd + suffix))) {
70206
70535
  return true;
70207
70536
  }
70208
70537
  }
@@ -70266,13 +70595,13 @@ function getInstalledLspServers() {
70266
70595
  init_shared();
70267
70596
  import { existsSync as existsSync30, readFileSync as readFileSync27 } from "fs";
70268
70597
  import { homedir as homedir8 } from "os";
70269
- import { join as join30 } from "path";
70598
+ import { join as join31 } from "path";
70270
70599
  var BUILTIN_MCP_SERVERS = ["context7", "grep_app"];
70271
70600
  function getMcpConfigPaths() {
70272
70601
  return [
70273
- join30(homedir8(), ".claude", ".mcp.json"),
70274
- join30(process.cwd(), ".mcp.json"),
70275
- join30(process.cwd(), ".claude", ".mcp.json")
70602
+ join31(homedir8(), ".claude", ".mcp.json"),
70603
+ join31(process.cwd(), ".mcp.json"),
70604
+ join31(process.cwd(), ".claude", ".mcp.json")
70276
70605
  ];
70277
70606
  }
70278
70607
  function loadUserMcpConfig() {
@@ -70734,11 +71063,11 @@ async function refreshModelCapabilities(options, deps = {}) {
70734
71063
 
70735
71064
  // src/features/mcp-oauth/storage.ts
70736
71065
  init_shared();
70737
- import { chmodSync, existsSync as existsSync31, mkdirSync as mkdirSync8, readFileSync as readFileSync28, unlinkSync as unlinkSync4, writeFileSync as writeFileSync11 } from "fs";
70738
- import { dirname as dirname7, join as join31 } from "path";
71066
+ import { chmodSync, existsSync as existsSync31, mkdirSync as mkdirSync8, readFileSync as readFileSync28, unlinkSync as unlinkSync4, writeFileSync as writeFileSync10 } from "fs";
71067
+ import { dirname as dirname10, join as join32 } from "path";
70739
71068
  var STORAGE_FILE_NAME = "mcp-oauth.json";
70740
71069
  function getMcpOauthStoragePath() {
70741
- return join31(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
71070
+ return join32(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
70742
71071
  }
70743
71072
  function normalizeHost(serverHost) {
70744
71073
  let host = serverHost.trim();
@@ -70788,11 +71117,11 @@ function readStore() {
70788
71117
  function writeStore(store2) {
70789
71118
  const filePath = getMcpOauthStoragePath();
70790
71119
  try {
70791
- const dir = dirname7(filePath);
71120
+ const dir = dirname10(filePath);
70792
71121
  if (!existsSync31(dir)) {
70793
71122
  mkdirSync8(dir, { recursive: true });
70794
71123
  }
70795
- writeFileSync11(filePath, JSON.stringify(store2, null, 2), { encoding: "utf-8", mode: 384 });
71124
+ writeFileSync10(filePath, JSON.stringify(store2, null, 2), { encoding: "utf-8", mode: 384 });
70796
71125
  chmodSync(filePath, 384);
70797
71126
  return true;
70798
71127
  } catch {
@@ -71249,14 +71578,17 @@ class McpOAuthProvider {
71249
71578
  }
71250
71579
 
71251
71580
  // src/cli/mcp-oauth/login.ts
71252
- async function login(serverName, options) {
71581
+ var defaultLoginDependencies = {
71582
+ createProvider: (options) => new McpOAuthProvider(options)
71583
+ };
71584
+ async function login(serverName, options, deps = defaultLoginDependencies) {
71253
71585
  try {
71254
71586
  const serverUrl = options.serverUrl;
71255
71587
  if (!serverUrl) {
71256
71588
  console.error(`Error: --server-url is required for server "${serverName}"`);
71257
71589
  return 1;
71258
71590
  }
71259
- const provider = new McpOAuthProvider({
71591
+ const provider = deps.createProvider({
71260
71592
  serverUrl,
71261
71593
  clientId: options.clientId,
71262
71594
  scopes: options.scopes