oh-my-opencode 3.14.0 → 3.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) 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 +715 -429
  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/hook/background-update-check.d.ts +29 -1
  97. package/dist/hooks/bash-file-read-guard.d.ts +2 -0
  98. package/dist/hooks/claude-code-hooks/claude-code-hooks-hook.d.ts +1 -0
  99. package/dist/hooks/claude-code-hooks/config-loader.d.ts +1 -0
  100. package/dist/hooks/claude-code-hooks/config.d.ts +1 -0
  101. package/dist/hooks/claude-code-hooks/handlers/session-event-handler.d.ts +3 -1
  102. package/dist/hooks/claude-code-hooks/session-hook-state.d.ts +1 -0
  103. package/dist/hooks/claude-code-hooks/tool-input-cache.d.ts +2 -0
  104. package/dist/hooks/claude-code-hooks/transcript.d.ts +1 -3
  105. package/dist/hooks/comment-checker/hook.d.ts +1 -0
  106. package/dist/hooks/comment-checker/pending-calls.d.ts +1 -0
  107. package/dist/hooks/index.d.ts +3 -0
  108. package/dist/hooks/keyword-detector/ultrawork/default.d.ts +1 -1
  109. package/dist/hooks/keyword-detector/ultrawork/gemini.d.ts +1 -1
  110. package/dist/hooks/keyword-detector/ultrawork/gpt.d.ts +1 -1
  111. package/dist/hooks/legacy-plugin-toast/auto-migrate-runner.d.ts +2 -0
  112. package/dist/hooks/legacy-plugin-toast/auto-migrate.d.ts +7 -0
  113. package/dist/hooks/legacy-plugin-toast/hook.d.ts +18 -0
  114. package/dist/hooks/legacy-plugin-toast/index.d.ts +1 -0
  115. package/dist/hooks/legacy-plugin-toast/plugin-entry-migrator.d.ts +1 -0
  116. package/dist/hooks/model-fallback/chat-message-fallback-handler.d.ts +23 -0
  117. package/dist/hooks/model-fallback/next-fallback.d.ts +6 -0
  118. package/dist/hooks/ralph-loop/completion-promise-detector-test-input.d.ts +11 -0
  119. package/dist/hooks/rules-injector/constants.d.ts +1 -0
  120. package/dist/hooks/rules-injector/finder.d.ts +1 -1
  121. package/dist/hooks/rules-injector/hook.d.ts +2 -0
  122. package/dist/hooks/rules-injector/injector.d.ts +2 -0
  123. package/dist/hooks/rules-injector/rule-file-finder.d.ts +9 -1
  124. package/dist/hooks/runtime-fallback/fallback-models.d.ts +1 -1
  125. package/dist/hooks/runtime-fallback/retry-model-payload.d.ts +5 -1
  126. package/dist/hooks/start-work/context-info-builder.d.ts +12 -0
  127. package/dist/hooks/start-work/start-work-hook.d.ts +6 -0
  128. package/dist/hooks/start-work/worktree-block.d.ts +1 -0
  129. package/dist/hooks/todo-continuation-enforcer/resolve-message-info.d.ts +2 -2
  130. package/dist/hooks/todo-continuation-enforcer/types.d.ts +4 -0
  131. package/dist/hooks/todo-description-override/description.d.ts +1 -1
  132. package/dist/hooks/tool-pair-validator/hook.d.ts +28 -0
  133. package/dist/hooks/tool-pair-validator/index.d.ts +1 -0
  134. package/dist/hooks/write-existing-file-guard/hook.d.ts +12 -0
  135. package/dist/hooks/write-existing-file-guard/session-read-permissions.d.ts +3 -0
  136. package/dist/hooks/write-existing-file-guard/tool-execute-before-handler.d.ts +15 -0
  137. package/dist/index.js +9525 -5020
  138. package/dist/mcp/websearch.d.ts +2 -2
  139. package/dist/oh-my-opencode.schema.json +1052 -3
  140. package/dist/openclaw/dispatcher.d.ts +6 -0
  141. package/dist/plugin/command-execute-before.d.ts +17 -0
  142. package/dist/plugin/hooks/create-core-hooks.d.ts +3 -0
  143. package/dist/plugin/hooks/create-session-hooks.d.ts +2 -1
  144. package/dist/plugin/hooks/create-tool-guard-hooks.d.ts +2 -1
  145. package/dist/plugin/hooks/create-transform-hooks.d.ts +2 -1
  146. package/dist/plugin/tool-registry.d.ts +1 -0
  147. package/dist/plugin/types.d.ts +1 -0
  148. package/dist/plugin-dispose.d.ts +3 -0
  149. package/dist/shared/agent-display-names.d.ts +8 -0
  150. package/dist/shared/archive-entry-validator.d.ts +6 -0
  151. package/dist/shared/background-output-consumption.d.ts +5 -0
  152. package/dist/shared/connected-providers-cache.d.ts +2 -1
  153. package/dist/shared/contains-path.d.ts +2 -0
  154. package/dist/shared/external-plugin-detector.d.ts +14 -0
  155. package/dist/shared/index.d.ts +3 -0
  156. package/dist/shared/is-abort-error.d.ts +1 -0
  157. package/dist/shared/json-file-cache-store.d.ts +16 -0
  158. package/dist/shared/jsonc-parser.d.ts +1 -0
  159. package/dist/shared/legacy-plugin-warning.d.ts +1 -0
  160. package/dist/shared/load-opencode-plugins.d.ts +1 -0
  161. package/dist/shared/log-legacy-plugin-startup-warning.d.ts +10 -1
  162. package/dist/shared/migrate-legacy-config-file.d.ts +1 -0
  163. package/dist/shared/migrate-legacy-plugin-entry.d.ts +1 -0
  164. package/dist/shared/model-capabilities/bundled-snapshot.d.ts +2 -0
  165. package/dist/shared/model-capabilities/get-model-capabilities.d.ts +2 -0
  166. package/dist/shared/model-capabilities/index.d.ts +3 -0
  167. package/dist/shared/model-capabilities/runtime-model-readers.d.ts +11 -0
  168. package/dist/shared/{model-capabilities.d.ts → model-capabilities/types.d.ts} +35 -32
  169. package/dist/shared/model-suggestion-retry.d.ts +0 -9
  170. package/dist/shared/plugin-entry-migrator.d.ts +3 -0
  171. package/dist/shared/session-category-registry.d.ts +0 -24
  172. package/dist/shared/session-cursor.d.ts +6 -0
  173. package/dist/shared/skill-path-resolver.d.ts +0 -8
  174. package/dist/shared/task-system-enabled.d.ts +6 -0
  175. package/dist/shared/tmux/tmux-utils/server-health.d.ts +1 -0
  176. package/dist/shared/tmux/tmux-utils/session-spawn.d.ts +3 -0
  177. package/dist/shared/tmux/tmux-utils/window-spawn.d.ts +3 -0
  178. package/dist/shared/tmux/tmux-utils.d.ts +3 -1
  179. package/dist/shared/write-file-atomically.d.ts +1 -0
  180. package/dist/shared/zip-entry-listing/powershell-zip-entry-listing.d.ts +4 -0
  181. package/dist/shared/zip-entry-listing/python-zip-entry-listing.d.ts +3 -0
  182. package/dist/shared/zip-entry-listing/read-zip-symlink-target.d.ts +1 -0
  183. package/dist/shared/zip-entry-listing/tar-zip-entry-listing.d.ts +3 -0
  184. package/dist/shared/zip-entry-listing/zipinfo-zip-entry-listing.d.ts +4 -0
  185. package/dist/shared/zip-entry-listing.d.ts +4 -0
  186. package/dist/tools/call-omo-agent/background-executor.d.ts +2 -1
  187. package/dist/tools/call-omo-agent/sync-executor.d.ts +2 -1
  188. package/dist/tools/delegate-task/anthropic-categories.d.ts +2 -0
  189. package/dist/tools/delegate-task/builtin-categories.d.ts +4 -0
  190. package/dist/tools/delegate-task/builtin-category-definition.d.ts +7 -0
  191. package/dist/tools/delegate-task/constants.d.ts +1 -12
  192. package/dist/tools/delegate-task/executor-types.d.ts +2 -1
  193. package/dist/tools/delegate-task/google-categories.d.ts +2 -0
  194. package/dist/tools/delegate-task/kimi-categories.d.ts +2 -0
  195. package/dist/tools/delegate-task/openai-categories.d.ts +2 -0
  196. package/dist/tools/delegate-task/prompt-builder.d.ts +1 -1
  197. package/dist/tools/delegate-task/sync-prompt-sender.d.ts +2 -0
  198. package/dist/tools/delegate-task/types.d.ts +2 -1
  199. package/dist/tools/grep/cli.d.ts +3 -2
  200. package/dist/tools/grep/constants.d.ts +1 -2
  201. package/dist/tools/hashline-edit/tool-description.d.ts +1 -1
  202. package/dist/tools/look-at/constants.d.ts +1 -1
  203. package/dist/tools/lsp/infer-extension.d.ts +1 -0
  204. package/dist/tools/session-manager/file-storage.d.ts +8 -0
  205. package/dist/tools/session-manager/sdk-storage.d.ts +8 -0
  206. package/dist/tools/session-manager/sdk-unavailable.d.ts +1 -0
  207. package/dist/tools/session-manager/storage.d.ts +1 -1
  208. package/dist/tools/skill/description-formatter.d.ts +3 -0
  209. package/dist/tools/skill/mcp-capability-formatter.d.ts +3 -0
  210. package/dist/tools/skill/native-skills.d.ts +12 -0
  211. package/dist/tools/skill/scope-priority.d.ts +4 -0
  212. package/dist/tools/skill/skill-body.d.ts +2 -0
  213. package/dist/tools/skill/skill-matcher.d.ts +5 -0
  214. package/dist/tools/skill/types.d.ts +30 -2
  215. package/dist/tools/skill-mcp/tools.d.ts +1 -1
  216. package/package.json +14 -14
  217. package/postinstall.mjs +12 -0
  218. 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
+ };
6007
6011
  }
6008
- return { format: "none", path: join3(dir, PLUGIN_CONFIG_NAMES[0] + ".json") };
6012
+ if (legacyResult.format !== "none") {
6013
+ return legacyResult;
6014
+ }
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,14 +48323,14 @@ 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
@@ -48277,6 +48341,9 @@ var init_opencode_message_dir = __esm(() => {
48277
48341
  });
48278
48342
 
48279
48343
  // src/shared/agent-display-names.ts
48344
+ function stripAgentListSortPrefix(agentName) {
48345
+ return agentName.replace(/^\u200B+/, "");
48346
+ }
48280
48347
  function getAgentDisplayName(configKey) {
48281
48348
  const exactMatch = AGENT_DISPLAY_NAMES[configKey];
48282
48349
  if (exactMatch !== undefined)
@@ -48289,7 +48356,7 @@ function getAgentDisplayName(configKey) {
48289
48356
  return configKey;
48290
48357
  }
48291
48358
  function getAgentConfigKey(agentName) {
48292
- const lower = agentName.toLowerCase();
48359
+ const lower = stripAgentListSortPrefix(agentName).toLowerCase();
48293
48360
  const reversed = REVERSE_DISPLAY_NAMES[lower];
48294
48361
  if (reversed !== undefined)
48295
48362
  return reversed;
@@ -48307,10 +48374,13 @@ var init_agent_display_names = __esm(() => {
48307
48374
  "sisyphus-junior": "Sisyphus-Junior",
48308
48375
  metis: "Metis (Plan Consultant)",
48309
48376
  momus: "Momus (Plan Critic)",
48377
+ athena: "Athena (Council)",
48378
+ "athena-junior": "Athena-Junior (Council)",
48310
48379
  oracle: "oracle",
48311
48380
  librarian: "librarian",
48312
48381
  explore: "explore",
48313
- "multimodal-looker": "multimodal-looker"
48382
+ "multimodal-looker": "multimodal-looker",
48383
+ "council-member": "council-member"
48314
48384
  };
48315
48385
  REVERSE_DISPLAY_NAMES = Object.fromEntries(Object.entries(AGENT_DISPLAY_NAMES).map(([key, displayName]) => [displayName.toLowerCase(), key]));
48316
48386
  });
@@ -48328,6 +48398,12 @@ var SESSION_TIMEOUT_MS;
48328
48398
  var init_constants2 = __esm(() => {
48329
48399
  SESSION_TIMEOUT_MS = 10 * 60 * 1000;
48330
48400
  });
48401
+ // src/shared/tmux/tmux-utils/server-health.ts
48402
+ var SERVER_RUNNING_KEY;
48403
+ var init_server_health = __esm(() => {
48404
+ SERVER_RUNNING_KEY = Symbol.for("oh-my-opencode:server-running-in-process");
48405
+ });
48406
+
48331
48407
  // src/tools/interactive-bash/tmux-path-resolver.ts
48332
48408
  var init_tmux_path_resolver = () => {};
48333
48409
 
@@ -48339,6 +48415,7 @@ var init_pane_dimensions = __esm(() => {
48339
48415
  // src/shared/tmux/tmux-utils/pane-spawn.ts
48340
48416
  var init_pane_spawn = __esm(() => {
48341
48417
  init_tmux_path_resolver();
48418
+ init_server_health();
48342
48419
  });
48343
48420
 
48344
48421
  // src/shared/tmux/tmux-utils/pane-close.ts
@@ -48351,6 +48428,18 @@ var init_pane_replace = __esm(() => {
48351
48428
  init_tmux_path_resolver();
48352
48429
  });
48353
48430
 
48431
+ // src/shared/tmux/tmux-utils/window-spawn.ts
48432
+ var init_window_spawn = __esm(() => {
48433
+ init_tmux_path_resolver();
48434
+ init_server_health();
48435
+ });
48436
+
48437
+ // src/shared/tmux/tmux-utils/session-spawn.ts
48438
+ var init_session_spawn = __esm(() => {
48439
+ init_tmux_path_resolver();
48440
+ init_server_health();
48441
+ });
48442
+
48354
48443
  // src/shared/tmux/tmux-utils/layout.ts
48355
48444
  var init_layout = __esm(() => {
48356
48445
  init_tmux_path_resolver();
@@ -48358,10 +48447,13 @@ var init_layout = __esm(() => {
48358
48447
 
48359
48448
  // src/shared/tmux/tmux-utils.ts
48360
48449
  var init_tmux_utils = __esm(() => {
48450
+ init_server_health();
48361
48451
  init_pane_dimensions();
48362
48452
  init_pane_spawn();
48363
48453
  init_pane_close();
48364
48454
  init_pane_replace();
48455
+ init_window_spawn();
48456
+ init_session_spawn();
48365
48457
  init_layout();
48366
48458
  });
48367
48459
 
@@ -48493,10 +48585,32 @@ var init_agent_loader = __esm(() => {
48493
48585
  init_logger();
48494
48586
  init_claude_model_mapper();
48495
48587
  });
48588
+
48589
+ // src/features/claude-code-mcp-loader/configure-allowed-env-vars.ts
48590
+ var additionalAllowedMcpEnvVars;
48591
+ var init_configure_allowed_env_vars = __esm(() => {
48592
+ additionalAllowedMcpEnvVars = new Set;
48593
+ });
48594
+
48595
+ // src/features/claude-code-mcp-loader/env-expander.ts
48596
+ var init_env_expander = __esm(() => {
48597
+ init_logger();
48598
+ init_configure_allowed_env_vars();
48599
+ });
48600
+
48601
+ // src/features/claude-code-mcp-loader/scope-filter.ts
48602
+ var init_scope_filter = __esm(() => {
48603
+ init_contains_path();
48604
+ });
48605
+
48496
48606
  // src/features/claude-code-mcp-loader/transformer.ts
48497
- var init_transformer = () => {};
48607
+ var init_transformer = __esm(() => {
48608
+ init_env_expander();
48609
+ });
48498
48610
  // src/features/claude-code-plugin-loader/mcp-server-loader.ts
48499
48611
  var init_mcp_server_loader = __esm(() => {
48612
+ init_env_expander();
48613
+ init_scope_filter();
48500
48614
  init_transformer();
48501
48615
  init_logger();
48502
48616
  });
@@ -48545,21 +48659,30 @@ var init_session_category_registry = __esm(() => {
48545
48659
  sessionCategoryMap = new Map;
48546
48660
  });
48547
48661
 
48548
- // src/shared/plugin-identity.ts
48549
- var PLUGIN_NAME = "oh-my-openagent", LEGACY_PLUGIN_NAME = "oh-my-opencode";
48550
-
48551
48662
  // src/shared/legacy-plugin-warning.ts
48552
48663
  var init_legacy_plugin_warning = __esm(() => {
48553
48664
  init_jsonc_parser();
48554
48665
  init_opencode_config_dir();
48555
48666
  });
48556
48667
 
48668
+ // src/shared/plugin-entry-migrator.ts
48669
+ var init_plugin_entry_migrator = () => {};
48670
+
48671
+ // src/shared/migrate-legacy-plugin-entry.ts
48672
+ var init_migrate_legacy_plugin_entry = __esm(() => {
48673
+ init_main();
48674
+ init_jsonc_parser();
48675
+ init_logger();
48676
+ init_plugin_entry_migrator();
48677
+ });
48678
+
48557
48679
  // src/shared/log-legacy-plugin-startup-warning.ts
48558
48680
  var init_log_legacy_plugin_startup_warning = __esm(() => {
48559
48681
  init_legacy_plugin_warning();
48560
48682
  init_logger();
48683
+ init_migrate_legacy_plugin_entry();
48684
+ init_plugin_entry_migrator();
48561
48685
  });
48562
-
48563
48686
  // src/shared/index.ts
48564
48687
  var init_shared = __esm(() => {
48565
48688
  init_model_resolver();
@@ -48567,6 +48690,7 @@ var init_shared = __esm(() => {
48567
48690
  init_session_category_registry();
48568
48691
  init_frontmatter();
48569
48692
  init_command_executor();
48693
+ init_contains_path();
48570
48694
  init_file_reference_resolver();
48571
48695
  init_logger();
48572
48696
  init_snake_case();
@@ -48586,6 +48710,7 @@ var init_shared = __esm(() => {
48586
48710
  init_external_plugin_detector();
48587
48711
  init_zip_extractor();
48588
48712
  init_binary_downloader();
48713
+ init_write_file_atomically();
48589
48714
  init_agent_variant();
48590
48715
  init_session_cursor();
48591
48716
  init_system_directive();
@@ -48691,11 +48816,11 @@ var init_plugin_name_with_version = __esm(() => {
48691
48816
  });
48692
48817
 
48693
48818
  // src/cli/config-manager/ensure-config-directory-exists.ts
48694
- import { existsSync as existsSync6, mkdirSync as mkdirSync4 } from "fs";
48819
+ import { existsSync as existsSync5, mkdirSync as mkdirSync3 } from "fs";
48695
48820
  function ensureConfigDirectoryExists() {
48696
48821
  const configDir = getConfigDir();
48697
- if (!existsSync6(configDir)) {
48698
- mkdirSync4(configDir, { recursive: true });
48822
+ if (!existsSync5(configDir)) {
48823
+ mkdirSync3(configDir, { recursive: true });
48699
48824
  }
48700
48825
  }
48701
48826
  var init_ensure_config_directory_exists = __esm(() => {
@@ -48732,14 +48857,14 @@ function formatErrorWithSuggestion(err, context) {
48732
48857
  }
48733
48858
 
48734
48859
  // src/cli/config-manager/opencode-config-format.ts
48735
- import { existsSync as existsSync7 } from "fs";
48860
+ import { existsSync as existsSync6 } from "fs";
48736
48861
  function detectConfigFormat() {
48737
48862
  const configJsonc = getConfigJsonc();
48738
48863
  const configJson = getConfigJson();
48739
- if (existsSync7(configJsonc)) {
48864
+ if (existsSync6(configJsonc)) {
48740
48865
  return { format: "jsonc", path: configJsonc };
48741
48866
  }
48742
- if (existsSync7(configJson)) {
48867
+ if (existsSync6(configJson)) {
48743
48868
  return { format: "json", path: configJson };
48744
48869
  }
48745
48870
  return { format: "none", path: configJson };
@@ -48749,7 +48874,7 @@ var init_opencode_config_format = __esm(() => {
48749
48874
  });
48750
48875
 
48751
48876
  // src/cli/config-manager/parse-opencode-config-file.ts
48752
- import { readFileSync as readFileSync5, statSync } from "fs";
48877
+ import { readFileSync as readFileSync4, statSync } from "fs";
48753
48878
  function isEmptyOrWhitespace(content) {
48754
48879
  return content.trim().length === 0;
48755
48880
  }
@@ -48759,7 +48884,7 @@ function parseOpenCodeConfigFileWithError(path3) {
48759
48884
  if (stat.size === 0) {
48760
48885
  return { config: null, error: `Config file is empty: ${path3}. Delete it or add valid JSON content.` };
48761
48886
  }
48762
- const content = readFileSync5(path3, "utf-8");
48887
+ const content = readFileSync4(path3, "utf-8");
48763
48888
  if (isEmptyOrWhitespace(content)) {
48764
48889
  return { config: null, error: `Config file contains only whitespace: ${path3}. Delete it or add valid JSON content.` };
48765
48890
  }
@@ -48783,7 +48908,7 @@ var init_parse_opencode_config_file = __esm(() => {
48783
48908
  });
48784
48909
 
48785
48910
  // src/cli/config-manager/add-plugin-to-opencode-config.ts
48786
- import { readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
48911
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
48787
48912
  async function addPluginToOpenCodeConfig(currentVersion) {
48788
48913
  try {
48789
48914
  ensureConfigDirectoryExists();
@@ -48799,7 +48924,7 @@ async function addPluginToOpenCodeConfig(currentVersion) {
48799
48924
  try {
48800
48925
  if (format2 === "none") {
48801
48926
  const config2 = { plugin: [pluginEntry] };
48802
- writeFileSync4(path3, JSON.stringify(config2, null, 2) + `
48927
+ writeFileSync3(path3, JSON.stringify(config2, null, 2) + `
48803
48928
  `);
48804
48929
  return { success: true, configPath: path3 };
48805
48930
  }
@@ -48828,7 +48953,7 @@ async function addPluginToOpenCodeConfig(currentVersion) {
48828
48953
  }
48829
48954
  config.plugin = normalizedPlugins;
48830
48955
  if (format2 === "jsonc") {
48831
- const content = readFileSync6(path3, "utf-8");
48956
+ const content = readFileSync5(path3, "utf-8");
48832
48957
  const pluginArrayRegex = /((?:"plugin"|plugin)\s*:\s*)\[([\s\S]*?)\]/;
48833
48958
  const match = content.match(pluginArrayRegex);
48834
48959
  if (match) {
@@ -48837,14 +48962,14 @@ async function addPluginToOpenCodeConfig(currentVersion) {
48837
48962
  const newContent = content.replace(pluginArrayRegex, `$1[
48838
48963
  ${formattedPlugins}
48839
48964
  ]`);
48840
- writeFileSync4(path3, newContent);
48965
+ writeFileSync3(path3, newContent);
48841
48966
  } else {
48842
48967
  const newContent = content.replace(/(\{)/, `$1
48843
48968
  "plugin": ["${pluginEntry}"],`);
48844
- writeFileSync4(path3, newContent);
48969
+ writeFileSync3(path3, newContent);
48845
48970
  }
48846
48971
  } else {
48847
- writeFileSync4(path3, JSON.stringify(config, null, 2) + `
48972
+ writeFileSync3(path3, JSON.stringify(config, null, 2) + `
48848
48973
  `);
48849
48974
  }
48850
48975
  return { success: true, configPath: path3 };
@@ -49090,7 +49215,7 @@ function deepMergeRecord(target, source) {
49090
49215
  }
49091
49216
 
49092
49217
  // src/cli/config-manager/write-omo-config.ts
49093
- import { existsSync as existsSync8, readFileSync as readFileSync7, statSync as statSync2, writeFileSync as writeFileSync5 } from "fs";
49218
+ import { existsSync as existsSync7, readFileSync as readFileSync6, statSync as statSync2, writeFileSync as writeFileSync4 } from "fs";
49094
49219
  function isEmptyOrWhitespace2(content) {
49095
49220
  return content.trim().length === 0;
49096
49221
  }
@@ -49107,34 +49232,34 @@ function writeOmoConfig(installConfig) {
49107
49232
  const omoConfigPath = getOmoConfigPath();
49108
49233
  try {
49109
49234
  const newConfig = generateOmoConfig(installConfig);
49110
- if (existsSync8(omoConfigPath)) {
49235
+ if (existsSync7(omoConfigPath)) {
49111
49236
  try {
49112
49237
  const stat = statSync2(omoConfigPath);
49113
- const content = readFileSync7(omoConfigPath, "utf-8");
49238
+ const content = readFileSync6(omoConfigPath, "utf-8");
49114
49239
  if (stat.size === 0 || isEmptyOrWhitespace2(content)) {
49115
- writeFileSync5(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
49240
+ writeFileSync4(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
49116
49241
  `);
49117
49242
  return { success: true, configPath: omoConfigPath };
49118
49243
  }
49119
49244
  const existing = parseJsonc(content);
49120
49245
  if (!existing || typeof existing !== "object" || Array.isArray(existing)) {
49121
- writeFileSync5(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
49246
+ writeFileSync4(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
49122
49247
  `);
49123
49248
  return { success: true, configPath: omoConfigPath };
49124
49249
  }
49125
49250
  const merged = deepMergeRecord(newConfig, existing);
49126
- writeFileSync5(omoConfigPath, JSON.stringify(merged, null, 2) + `
49251
+ writeFileSync4(omoConfigPath, JSON.stringify(merged, null, 2) + `
49127
49252
  `);
49128
49253
  } catch (parseErr) {
49129
49254
  if (parseErr instanceof SyntaxError) {
49130
- writeFileSync5(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
49255
+ writeFileSync4(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
49131
49256
  `);
49132
49257
  return { success: true, configPath: omoConfigPath };
49133
49258
  }
49134
49259
  throw parseErr;
49135
49260
  }
49136
49261
  } else {
49137
- writeFileSync5(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
49262
+ writeFileSync4(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
49138
49263
  `);
49139
49264
  }
49140
49265
  return { success: true, configPath: omoConfigPath };
@@ -49250,10 +49375,10 @@ var init_opencode_binary = __esm(() => {
49250
49375
  });
49251
49376
 
49252
49377
  // src/cli/config-manager/detect-current-config.ts
49253
- import { existsSync as existsSync9, readFileSync as readFileSync8 } from "fs";
49378
+ import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
49254
49379
  function detectProvidersFromOmoConfig() {
49255
49380
  const omoConfigPath = getOmoConfigPath();
49256
- if (!existsSync9(omoConfigPath)) {
49381
+ if (!existsSync8(omoConfigPath)) {
49257
49382
  return {
49258
49383
  hasOpenAI: true,
49259
49384
  hasOpencodeZen: true,
@@ -49263,7 +49388,7 @@ function detectProvidersFromOmoConfig() {
49263
49388
  };
49264
49389
  }
49265
49390
  try {
49266
- const content = readFileSync8(omoConfigPath, "utf-8");
49391
+ const content = readFileSync7(omoConfigPath, "utf-8");
49267
49392
  const omoConfig = parseJsonc(content);
49268
49393
  if (!omoConfig || typeof omoConfig !== "object") {
49269
49394
  return {
@@ -49339,7 +49464,7 @@ var init_detect_current_config = __esm(() => {
49339
49464
  });
49340
49465
 
49341
49466
  // src/cli/config-manager/bun-install.ts
49342
- import { existsSync as existsSync10 } from "fs";
49467
+ import { existsSync as existsSync9 } from "fs";
49343
49468
  function readProcessOutput(stream) {
49344
49469
  if (!stream) {
49345
49470
  return Promise.resolve("");
@@ -49364,7 +49489,7 @@ async function runBunInstallWithDetails(options) {
49364
49489
  const outputMode = options?.outputMode ?? "pipe";
49365
49490
  const cacheDir = options?.workspaceDir ?? getOpenCodeCacheDir();
49366
49491
  const packageJsonPath = `${cacheDir}/package.json`;
49367
- if (!existsSync10(packageJsonPath)) {
49492
+ if (!existsSync9(packageJsonPath)) {
49368
49493
  return {
49369
49494
  success: false,
49370
49495
  error: `Workspace not initialized: ${packageJsonPath} not found. OpenCode should create this on first run.`
@@ -50039,85 +50164,89 @@ import { join as join19 } from "path";
50039
50164
  function getPinnedVersionToastMessage(latestVersion) {
50040
50165
  return `Update available: ${latestVersion} (version pinned, update manually)`;
50041
50166
  }
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})`);
50167
+ function resolveActiveInstallWorkspace(deps) {
50168
+ const configPaths = deps.getOpenCodeConfigPaths({ binary: "opencode" });
50169
+ const cacheDir = deps.getOpenCodeCacheDir();
50170
+ const configInstallPath = deps.join(configPaths.configDir, "node_modules", PACKAGE_NAME, "package.json");
50171
+ const cacheInstallPath = deps.join(cacheDir, "node_modules", PACKAGE_NAME, "package.json");
50172
+ if (deps.existsSync(configInstallPath)) {
50173
+ deps.log(`[auto-update-checker] Active workspace: config-dir (${configPaths.configDir})`);
50049
50174
  return configPaths.configDir;
50050
50175
  }
50051
- if (existsSync21(cacheInstallPath)) {
50052
- log(`[auto-update-checker] Active workspace: cache-dir (${cacheDir})`);
50176
+ if (deps.existsSync(cacheInstallPath)) {
50177
+ deps.log(`[auto-update-checker] Active workspace: cache-dir (${cacheDir})`);
50053
50178
  return cacheDir;
50054
50179
  }
50055
- log(`[auto-update-checker] Active workspace: config-dir (default, no install detected)`);
50180
+ deps.log(`[auto-update-checker] Active workspace: config-dir (default, no install detected)`);
50056
50181
  return configPaths.configDir;
50057
50182
  }
50058
- async function runBunInstallSafe(workspaceDir) {
50183
+ async function runBunInstallSafe(workspaceDir, deps) {
50059
50184
  try {
50060
- const result = await runBunInstallWithDetails({ outputMode: "pipe", workspaceDir });
50185
+ const result = await deps.runBunInstallWithDetails({ outputMode: "pipe", workspaceDir });
50061
50186
  if (!result.success && result.error) {
50062
- log("[auto-update-checker] bun install error:", result.error);
50187
+ deps.log("[auto-update-checker] bun install error:", result.error);
50063
50188
  }
50064
50189
  return result.success;
50065
50190
  } catch (err) {
50066
50191
  const errorMessage = err instanceof Error ? err.message : String(err);
50067
- log("[auto-update-checker] bun install error:", errorMessage);
50192
+ deps.log("[auto-update-checker] bun install error:", errorMessage);
50068
50193
  return false;
50069
50194
  }
50070
50195
  }
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;
50117
- }
50118
- await showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
50119
- log("[auto-update-checker] bun install failed; update not installed (falling back to notification-only)");
50196
+ function createBackgroundUpdateCheckRunner(overrides = {}) {
50197
+ const deps = { ...defaultDeps, ...overrides };
50198
+ return async function runBackgroundUpdateCheck(ctx, autoUpdate, getToastMessage) {
50199
+ const pluginInfo = deps.findPluginEntry(ctx.directory);
50200
+ if (!pluginInfo) {
50201
+ deps.log("[auto-update-checker] Plugin not found in config");
50202
+ return;
50203
+ }
50204
+ const cachedVersion = deps.getCachedVersion();
50205
+ const currentVersion = cachedVersion ?? pluginInfo.pinnedVersion;
50206
+ if (!currentVersion) {
50207
+ deps.log("[auto-update-checker] No version found (cached or pinned)");
50208
+ return;
50209
+ }
50210
+ const channel = deps.extractChannel(pluginInfo.pinnedVersion ?? currentVersion);
50211
+ const latestVersion = await deps.getLatestVersion(channel);
50212
+ if (!latestVersion) {
50213
+ deps.log("[auto-update-checker] Failed to fetch latest version for channel:", channel);
50214
+ return;
50215
+ }
50216
+ if (currentVersion === latestVersion) {
50217
+ deps.log("[auto-update-checker] Already on latest version for channel:", channel);
50218
+ return;
50219
+ }
50220
+ deps.log(`[auto-update-checker] Update available (${channel}): ${currentVersion} \u2192 ${latestVersion}`);
50221
+ if (!autoUpdate) {
50222
+ await deps.showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
50223
+ deps.log("[auto-update-checker] Auto-update disabled, notification only");
50224
+ return;
50225
+ }
50226
+ if (pluginInfo.isPinned) {
50227
+ await deps.showUpdateAvailableToast(ctx, latestVersion, () => getPinnedVersionToastMessage(latestVersion));
50228
+ deps.log(`[auto-update-checker] User-pinned version detected (${pluginInfo.entry}), skipping auto-update. Notification only.`);
50229
+ return;
50230
+ }
50231
+ const syncResult = deps.syncCachePackageJsonToIntent(pluginInfo);
50232
+ if (syncResult.error) {
50233
+ deps.log(`[auto-update-checker] Sync failed with error: ${syncResult.error}`, syncResult.message);
50234
+ await deps.showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
50235
+ return;
50236
+ }
50237
+ deps.invalidatePackage(PACKAGE_NAME);
50238
+ const activeWorkspace = resolveActiveInstallWorkspace(deps);
50239
+ const installSuccess = await runBunInstallSafe(activeWorkspace, deps);
50240
+ if (installSuccess) {
50241
+ await deps.showAutoUpdatedToast(ctx, currentVersion, latestVersion);
50242
+ deps.log(`[auto-update-checker] Update installed: ${currentVersion} \u2192 ${latestVersion}`);
50243
+ return;
50244
+ }
50245
+ await deps.showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
50246
+ deps.log("[auto-update-checker] bun install failed; update not installed (falling back to notification-only)");
50247
+ };
50120
50248
  }
50249
+ var defaultDeps, runBackgroundUpdateCheck;
50121
50250
  var init_background_update_check = __esm(() => {
50122
50251
  init_config_manager();
50123
50252
  init_logger();
@@ -50126,6 +50255,23 @@ var init_background_update_check = __esm(() => {
50126
50255
  init_constants3();
50127
50256
  init_checker();
50128
50257
  init_update_toasts();
50258
+ defaultDeps = {
50259
+ existsSync: existsSync21,
50260
+ join: join19,
50261
+ runBunInstallWithDetails,
50262
+ log,
50263
+ getOpenCodeCacheDir,
50264
+ getOpenCodeConfigPaths,
50265
+ invalidatePackage,
50266
+ extractChannel,
50267
+ findPluginEntry,
50268
+ getCachedVersion,
50269
+ getLatestVersion,
50270
+ syncCachePackageJsonToIntent,
50271
+ showUpdateAvailableToast,
50272
+ showAutoUpdatedToast
50273
+ };
50274
+ runBackgroundUpdateCheck = createBackgroundUpdateCheckRunner();
50129
50275
  });
50130
50276
 
50131
50277
  // src/hooks/auto-update-checker/hook/config-errors-toast.ts
@@ -50391,9 +50537,9 @@ var {
50391
50537
  // package.json
50392
50538
  var package_default = {
50393
50539
  name: "oh-my-opencode",
50394
- version: "3.14.0",
50540
+ version: "3.15.0",
50395
50541
  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",
50542
+ main: "./dist/index.js",
50397
50543
  types: "dist/index.d.ts",
50398
50544
  type: "module",
50399
50545
  bin: {
@@ -50465,21 +50611,21 @@ var package_default = {
50465
50611
  devDependencies: {
50466
50612
  "@types/js-yaml": "^4.0.9",
50467
50613
  "@types/picomatch": "^3.0.2",
50468
- "bun-types": "1.3.10",
50614
+ "bun-types": "1.3.11",
50469
50615
  typescript: "^5.7.3"
50470
50616
  },
50471
50617
  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"
50618
+ "oh-my-opencode-darwin-arm64": "3.15.0",
50619
+ "oh-my-opencode-darwin-x64": "3.15.0",
50620
+ "oh-my-opencode-darwin-x64-baseline": "3.15.0",
50621
+ "oh-my-opencode-linux-arm64": "3.15.0",
50622
+ "oh-my-opencode-linux-arm64-musl": "3.15.0",
50623
+ "oh-my-opencode-linux-x64": "3.15.0",
50624
+ "oh-my-opencode-linux-x64-baseline": "3.15.0",
50625
+ "oh-my-opencode-linux-x64-musl": "3.15.0",
50626
+ "oh-my-opencode-linux-x64-musl-baseline": "3.15.0",
50627
+ "oh-my-opencode-windows-x64": "3.15.0",
50628
+ "oh-my-opencode-windows-x64-baseline": "3.15.0"
50483
50629
  },
50484
50630
  overrides: {
50485
50631
  "@opencode-ai/sdk": "^1.2.24"
@@ -50709,7 +50855,7 @@ async function runCliInstaller(args, version) {
50709
50855
  console.log(` Run ${import_picocolors2.default.cyan("opencode")} to start!`);
50710
50856
  console.log();
50711
50857
  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,
50858
+ ` + `All features work like magic-parallel agents, background tasks,
50713
50859
  ` + `deep exploration, and relentless execution until completion.`, "The Magic Word");
50714
50860
  console.log(`${SYMBOLS.star} ${import_picocolors2.default.yellow("If you found this helpful, consider starring the repo!")}`);
50715
50861
  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 +51630,7 @@ async function runTuiInstaller(args, version) {
51484
51630
  M2.success(import_picocolors4.default.bold(isUpdate ? "Configuration updated!" : "Installation complete!"));
51485
51631
  M2.message(`Run ${import_picocolors4.default.cyan("opencode")} to start!`);
51486
51632
  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,
51633
+ ` + `All features work like magic-parallel agents, background tasks,
51488
51634
  ` + `deep exploration, and relentless execution until completion.`, "The Magic Word");
51489
51635
  M2.message(`${import_picocolors4.default.yellow("\u2605")} If you found this helpful, consider starring the repo!`);
51490
51636
  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 +65912,9 @@ var BuiltinSkillNameSchema = exports_external.enum([
65766
65912
  "agent-browser",
65767
65913
  "dev-browser",
65768
65914
  "frontend-ui-ux",
65769
- "git-master"
65915
+ "git-master",
65916
+ "review-work",
65917
+ "ai-slop-remover"
65770
65918
  ]);
65771
65919
  var OverridableAgentNameSchema = exports_external.enum([
65772
65920
  "build",
@@ -65797,9 +65945,14 @@ var FallbackModelObjectSchema = exports_external.object({
65797
65945
  budgetTokens: exports_external.number().optional()
65798
65946
  }).optional()
65799
65947
  });
65948
+ var FallbackModelStringArraySchema = exports_external.array(exports_external.string());
65949
+ var FallbackModelObjectArraySchema = exports_external.array(FallbackModelObjectSchema);
65950
+ var FallbackModelMixedArraySchema = exports_external.array(exports_external.union([exports_external.string(), FallbackModelObjectSchema]));
65800
65951
  var FallbackModelsSchema = exports_external.union([
65801
65952
  exports_external.string(),
65802
- exports_external.array(exports_external.union([exports_external.string(), FallbackModelObjectSchema]))
65953
+ FallbackModelStringArraySchema,
65954
+ FallbackModelObjectArraySchema,
65955
+ FallbackModelMixedArraySchema
65803
65956
  ]);
65804
65957
 
65805
65958
  // src/config/schema/internal/permission.ts
@@ -65887,6 +66040,8 @@ var BackgroundTaskConfigSchema = exports_external.object({
65887
66040
  maxDescendants: exports_external.number().int().min(1).optional(),
65888
66041
  staleTimeoutMs: exports_external.number().min(60000).optional(),
65889
66042
  messageStalenessTimeoutMs: exports_external.number().min(60000).optional(),
66043
+ taskTtlMs: exports_external.number().min(300000).optional(),
66044
+ sessionGoneTimeoutMs: exports_external.number().min(1e4).optional(),
65890
66045
  syncPollTimeoutMs: exports_external.number().min(60000).optional(),
65891
66046
  maxToolCalls: exports_external.number().int().min(10).optional(),
65892
66047
  circuitBreaker: CircuitBreakerConfigSchema.optional()
@@ -65955,7 +66110,8 @@ var BuiltinCommandNameSchema = exports_external.enum([
65955
66110
  "cancel-ralph",
65956
66111
  "refactor",
65957
66112
  "start-work",
65958
- "stop-continuation"
66113
+ "stop-continuation",
66114
+ "remove-ai-slops"
65959
66115
  ]);
65960
66116
  // src/config/schema/dynamic-context-pruning.ts
65961
66117
  var DynamicContextPruningConfigSchema = exports_external.object({
@@ -66000,7 +66156,8 @@ var ExperimentalConfigSchema = exports_external.object({
66000
66156
  safe_hook_creation: exports_external.boolean().optional(),
66001
66157
  disable_omo_env: exports_external.boolean().optional(),
66002
66158
  hashline_edit: exports_external.boolean().optional(),
66003
- model_fallback_title: exports_external.boolean().optional()
66159
+ model_fallback_title: exports_external.boolean().optional(),
66160
+ max_tools: exports_external.number().int().min(1).optional()
66004
66161
  });
66005
66162
  // src/config/schema/git-env-prefix.ts
66006
66163
  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 +66200,7 @@ var HookNameSchema = exports_external.enum([
66043
66200
  "non-interactive-env",
66044
66201
  "interactive-bash-session",
66045
66202
  "thinking-block-validator",
66203
+ "tool-pair-validator",
66046
66204
  "ralph-loop",
66047
66205
  "category-skill-reminder",
66048
66206
  "compaction-context-injector",
@@ -66064,11 +66222,13 @@ var HookNameSchema = exports_external.enum([
66064
66222
  "tasks-todowrite-disabler",
66065
66223
  "runtime-fallback",
66066
66224
  "write-existing-file-guard",
66225
+ "bash-file-read-guard",
66067
66226
  "anthropic-effort",
66068
66227
  "hashline-read-enhancer",
66069
66228
  "read-image-resizer",
66070
66229
  "todo-description-override",
66071
- "webfetch-redirect-guard"
66230
+ "webfetch-redirect-guard",
66231
+ "legacy-plugin-toast"
66072
66232
  ]);
66073
66233
  // src/config/schema/model-capabilities.ts
66074
66234
  var ModelCapabilitiesConfigSchema = exports_external.object({
@@ -66184,7 +66344,8 @@ var SisyphusAgentConfigSchema = exports_external.object({
66184
66344
  disabled: exports_external.boolean().optional(),
66185
66345
  default_builder_enabled: exports_external.boolean().optional(),
66186
66346
  planner_enabled: exports_external.boolean().optional(),
66187
- replace_plan: exports_external.boolean().optional()
66347
+ replace_plan: exports_external.boolean().optional(),
66348
+ tdd: exports_external.boolean().default(true).optional()
66188
66349
  });
66189
66350
 
66190
66351
  // src/config/schema/tmux.ts
@@ -66195,12 +66356,18 @@ var TmuxLayoutSchema = exports_external.enum([
66195
66356
  "even-horizontal",
66196
66357
  "even-vertical"
66197
66358
  ]);
66359
+ var TmuxIsolationSchema = exports_external.enum([
66360
+ "inline",
66361
+ "window",
66362
+ "session"
66363
+ ]);
66198
66364
  var TmuxConfigSchema = exports_external.object({
66199
66365
  enabled: exports_external.boolean().default(false),
66200
66366
  layout: TmuxLayoutSchema.default("main-vertical"),
66201
66367
  main_pane_size: exports_external.number().min(20).max(80).default(60),
66202
66368
  main_pane_min_width: exports_external.number().min(40).default(120),
66203
- agent_pane_min_width: exports_external.number().min(20).default(40)
66369
+ agent_pane_min_width: exports_external.number().min(20).default(40),
66370
+ isolation: TmuxIsolationSchema.default("inline")
66204
66371
  });
66205
66372
 
66206
66373
  // src/config/schema/start-work.ts
@@ -66225,6 +66392,7 @@ var OhMyOpenCodeConfigSchema = exports_external.object({
66225
66392
  disabled_hooks: exports_external.array(exports_external.string()).optional(),
66226
66393
  disabled_commands: exports_external.array(BuiltinCommandNameSchema).optional(),
66227
66394
  disabled_tools: exports_external.array(exports_external.string()).optional(),
66395
+ mcp_env_allowlist: exports_external.array(exports_external.string()).optional(),
66228
66396
  hashline_edit: exports_external.boolean().optional(),
66229
66397
  model_fallback: exports_external.boolean().optional(),
66230
66398
  agents: AgentOverridesSchema.optional(),
@@ -66242,7 +66410,11 @@ var OhMyOpenCodeConfigSchema = exports_external.object({
66242
66410
  model_capabilities: ModelCapabilitiesConfigSchema.optional(),
66243
66411
  openclaw: OpenClawConfigSchema.optional(),
66244
66412
  babysitting: BabysittingConfigSchema.optional(),
66245
- git_master: GitMasterConfigSchema.optional(),
66413
+ git_master: GitMasterConfigSchema.default({
66414
+ commit_footer: true,
66415
+ include_co_authored_by: true,
66416
+ git_env_prefix: "GIT_MASTER=1"
66417
+ }),
66246
66418
  browser_automation_engine: BrowserAutomationConfigSchema.optional(),
66247
66419
  websearch: WebsearchConfigSchema.optional(),
66248
66420
  tmux: TmuxConfigSchema.optional(),
@@ -66252,13 +66424,79 @@ var OhMyOpenCodeConfigSchema = exports_external.object({
66252
66424
  });
66253
66425
  // src/plugin-config.ts
66254
66426
  init_shared();
66427
+
66428
+ // src/shared/migrate-legacy-config-file.ts
66429
+ init_logger();
66430
+ init_write_file_atomically();
66431
+ import { existsSync as existsSync10, readFileSync as readFileSync8, renameSync as renameSync2, rmSync } from "fs";
66432
+ import { join as join8, dirname, basename } from "path";
66433
+ function buildCanonicalPath(legacyPath) {
66434
+ const dir = dirname(legacyPath);
66435
+ const ext = basename(legacyPath).includes(".jsonc") ? ".jsonc" : ".json";
66436
+ return join8(dir, `${CONFIG_BASENAME}${ext}`);
66437
+ }
66438
+ function archiveLegacyConfigFile(legacyPath) {
66439
+ const backupPath = `${legacyPath}.bak`;
66440
+ try {
66441
+ renameSync2(legacyPath, backupPath);
66442
+ log("[migrateLegacyConfigFile] Legacy config was migrated and renamed to backup. Update the canonical file only.", {
66443
+ legacyPath,
66444
+ backupPath
66445
+ });
66446
+ return true;
66447
+ } catch (renameError) {
66448
+ try {
66449
+ rmSync(legacyPath);
66450
+ log("[migrateLegacyConfigFile] Legacy config was migrated and removed after backup rename failed. Update the canonical file only.", {
66451
+ legacyPath,
66452
+ backupPath,
66453
+ renameError
66454
+ });
66455
+ return true;
66456
+ } catch (removeError) {
66457
+ log("[migrateLegacyConfigFile] WARNING: canonical config was written but the legacy file still exists and will be ignored. Remove or rename it manually.", {
66458
+ legacyPath,
66459
+ backupPath,
66460
+ renameError,
66461
+ removeError
66462
+ });
66463
+ return false;
66464
+ }
66465
+ }
66466
+ }
66467
+ function migrateLegacyConfigFile(legacyPath) {
66468
+ if (!existsSync10(legacyPath))
66469
+ return false;
66470
+ if (!basename(legacyPath).startsWith(LEGACY_CONFIG_BASENAME))
66471
+ return false;
66472
+ const canonicalPath = buildCanonicalPath(legacyPath);
66473
+ if (existsSync10(canonicalPath))
66474
+ return false;
66475
+ try {
66476
+ const content = readFileSync8(legacyPath, "utf-8");
66477
+ writeFileAtomically(canonicalPath, content);
66478
+ const archivedLegacyConfig = archiveLegacyConfigFile(legacyPath);
66479
+ log("[migrateLegacyConfigFile] Migrated legacy config to canonical path", {
66480
+ from: legacyPath,
66481
+ to: canonicalPath,
66482
+ archivedLegacyConfig
66483
+ });
66484
+ return archivedLegacyConfig;
66485
+ } catch (error48) {
66486
+ log("[migrateLegacyConfigFile] Failed to migrate legacy config file", { legacyPath, error: error48 });
66487
+ return false;
66488
+ }
66489
+ }
66490
+
66491
+ // src/plugin-config.ts
66255
66492
  var PARTIAL_STRING_ARRAY_KEYS = new Set([
66256
66493
  "disabled_mcps",
66257
66494
  "disabled_agents",
66258
66495
  "disabled_skills",
66259
66496
  "disabled_hooks",
66260
66497
  "disabled_commands",
66261
- "disabled_tools"
66498
+ "disabled_tools",
66499
+ "mcp_env_allowlist"
66262
66500
  ]);
66263
66501
  function parseConfigPartially(rawConfig) {
66264
66502
  const fullResult = OhMyOpenCodeConfigSchema.safeParse(rawConfig);
@@ -66289,7 +66527,7 @@ function parseConfigPartially(rawConfig) {
66289
66527
  }
66290
66528
  }
66291
66529
  if (invalidSections.length > 0) {
66292
- log("Partial config loaded \u2014 invalid sections skipped:", invalidSections);
66530
+ log("Partial config loaded - invalid sections skipped:", invalidSections);
66293
66531
  }
66294
66532
  return partialConfig;
66295
66533
  }
@@ -66308,7 +66546,7 @@ function loadConfigFromPath(configPath, _ctx) {
66308
66546
  log(`Config validation error in ${configPath}:`, result.error.issues);
66309
66547
  addConfigLoadError({
66310
66548
  path: configPath,
66311
- error: `Partial config loaded \u2014 invalid sections skipped: ${errorMsg}`
66549
+ error: `Partial config loaded - invalid sections skipped: ${errorMsg}`
66312
66550
  });
66313
66551
  const partialResult = parseConfigPartially(rawConfig);
66314
66552
  if (partialResult) {
@@ -66366,23 +66604,51 @@ function mergeConfigs(base, override) {
66366
66604
  ...override.disabled_tools ?? []
66367
66605
  ])
66368
66606
  ],
66607
+ mcp_env_allowlist: [
66608
+ ...new Set([
66609
+ ...base.mcp_env_allowlist ?? [],
66610
+ ...override.mcp_env_allowlist ?? []
66611
+ ])
66612
+ ],
66369
66613
  claude_code: deepMerge(base.claude_code, override.claude_code)
66370
66614
  };
66371
66615
  }
66372
66616
  function loadPluginConfig(directory, ctx) {
66373
66617
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
66374
66618
  const userDetected = detectPluginConfigFile(configDir);
66375
- const userConfigPath = userDetected.format !== "none" ? userDetected.path : path3.join(configDir, "oh-my-opencode.json");
66619
+ let userConfigPath = userDetected.format !== "none" ? userDetected.path : path3.join(configDir, "oh-my-opencode.json");
66620
+ if (userDetected.legacyPath) {
66621
+ log("Canonical plugin config detected alongside legacy config. Remove the legacy file to avoid confusion.", {
66622
+ canonicalPath: userDetected.path,
66623
+ legacyPath: userDetected.legacyPath
66624
+ });
66625
+ }
66626
+ if (userDetected.format !== "none" && path3.basename(userDetected.path).startsWith(LEGACY_CONFIG_BASENAME)) {
66627
+ migrateLegacyConfigFile(userDetected.path);
66628
+ userConfigPath = path3.join(path3.dirname(userDetected.path), `${CONFIG_BASENAME}${path3.extname(userDetected.path)}`);
66629
+ }
66376
66630
  const projectBasePath = path3.join(directory, ".opencode");
66377
66631
  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) ?? {};
66632
+ let projectConfigPath = projectDetected.format !== "none" ? projectDetected.path : path3.join(projectBasePath, "oh-my-opencode.json");
66633
+ if (projectDetected.legacyPath) {
66634
+ log("Canonical plugin config detected alongside legacy config. Remove the legacy file to avoid confusion.", {
66635
+ canonicalPath: projectDetected.path,
66636
+ legacyPath: projectDetected.legacyPath
66637
+ });
66638
+ }
66639
+ if (projectDetected.format !== "none" && path3.basename(projectDetected.path).startsWith(LEGACY_CONFIG_BASENAME)) {
66640
+ migrateLegacyConfigFile(projectDetected.path);
66641
+ projectConfigPath = path3.join(path3.dirname(projectDetected.path), `${CONFIG_BASENAME}${path3.extname(projectDetected.path)}`);
66642
+ }
66643
+ const userConfig = loadConfigFromPath(userConfigPath, ctx);
66644
+ let config2 = userConfig ?? OhMyOpenCodeConfigSchema.parse({});
66380
66645
  const projectConfig = loadConfigFromPath(projectConfigPath, ctx);
66381
66646
  if (projectConfig) {
66382
66647
  config2 = mergeConfigs(config2, projectConfig);
66383
66648
  }
66384
66649
  config2 = {
66385
- ...config2
66650
+ ...config2,
66651
+ mcp_env_allowlist: userConfig?.mcp_env_allowlist ?? []
66386
66652
  };
66387
66653
  log("Final merged config", {
66388
66654
  agents: config2.agents,
@@ -67841,7 +68107,7 @@ var import_picocolors9 = __toESM(require_picocolors(), 1);
67841
68107
 
67842
68108
  // src/cli/run/opencode-binary-resolver.ts
67843
68109
  init_spawn_with_windows_hide();
67844
- import { delimiter, dirname, join as join10 } from "path";
68110
+ import { delimiter, dirname as dirname3, join as join10 } from "path";
67845
68111
  var OPENCODE_COMMANDS = ["opencode", "opencode-desktop"];
67846
68112
  var WINDOWS_SUFFIXES = ["", ".exe", ".cmd", ".bat", ".ps1"];
67847
68113
  function getCommandCandidates(platform) {
@@ -67891,7 +68157,7 @@ async function findWorkingOpencodeBinary(pathEnv = process.env.PATH, probe = can
67891
68157
  return null;
67892
68158
  }
67893
68159
  function buildPathWithBinaryFirst(pathEnv, binaryPath) {
67894
- const preferredDir = dirname(binaryPath);
68160
+ const preferredDir = dirname3(binaryPath);
67895
68161
  const existing = (pathEnv ?? "").split(delimiter).filter((entry) => entry.length > 0 && entry !== preferredDir);
67896
68162
  return [preferredDir, ...existing].join(delimiter);
67897
68163
  }
@@ -68093,6 +68359,22 @@ async function readOutput(stream, streamName) {
68093
68359
  return "";
68094
68360
  }
68095
68361
  }
68362
+ function resolveHookShellCommand(command) {
68363
+ const shellType = detectShellType();
68364
+ switch (shellType) {
68365
+ case "powershell": {
68366
+ const powershellExecutable = process.platform === "win32" ? "powershell.exe" : "pwsh";
68367
+ return [powershellExecutable, "-NoProfile", "-Command", command];
68368
+ }
68369
+ case "cmd":
68370
+ return [process.env.ComSpec || "cmd.exe", "/d", "/s", "/c", command];
68371
+ case "csh":
68372
+ return ["csh", "-c", command];
68373
+ case "unix":
68374
+ default:
68375
+ return ["sh", "-c", command];
68376
+ }
68377
+ }
68096
68378
  async function executeOnCompleteHook(options) {
68097
68379
  const { command, sessionId, exitCode, durationMs, messageCount } = options;
68098
68380
  const trimmedCommand = command.trim();
@@ -68101,7 +68383,8 @@ async function executeOnCompleteHook(options) {
68101
68383
  }
68102
68384
  log("Running on-complete hook", { command: trimmedCommand });
68103
68385
  try {
68104
- const proc = spawnWithWindowsHide(["sh", "-c", trimmedCommand], {
68386
+ const shellCommand = resolveHookShellCommand(trimmedCommand);
68387
+ const proc = spawnWithWindowsHide(shellCommand, {
68105
68388
  env: {
68106
68389
  ...process.env,
68107
68390
  SESSION_ID: sessionId,
@@ -68230,8 +68513,8 @@ var BOULDER_STATE_PATH = `${BOULDER_DIR}/${BOULDER_FILE}`;
68230
68513
  var NOTEPAD_DIR = "notepads";
68231
68514
  var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
68232
68515
  // 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";
68516
+ import { existsSync as existsSync12, readFileSync as readFileSync10, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, readdirSync } from "fs";
68517
+ import { dirname as dirname4, join as join11, basename as basename3 } from "path";
68235
68518
  var RESERVED_KEYS = new Set(["__proto__", "prototype", "constructor"]);
68236
68519
  function getBoulderFilePath(directory) {
68237
68520
  return join11(directory, BOULDER_DIR, BOULDER_FILE);
@@ -68280,7 +68563,7 @@ function getPlanProgress(planPath) {
68280
68563
  // src/features/run-continuation-state/constants.ts
68281
68564
  var CONTINUATION_MARKER_DIR = ".sisyphus/run-continuation";
68282
68565
  // src/features/run-continuation-state/storage.ts
68283
- import { existsSync as existsSync13, mkdirSync as mkdirSync6, readFileSync as readFileSync11, rmSync, writeFileSync as writeFileSync7 } from "fs";
68566
+ import { existsSync as existsSync13, mkdirSync as mkdirSync5, readFileSync as readFileSync11, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "fs";
68284
68567
  import { join as join12 } from "path";
68285
68568
  function getMarkerPath(directory, sessionID) {
68286
68569
  return join12(directory, CONTINUATION_MARKER_DIR, `${sessionID}.json`);
@@ -68315,8 +68598,8 @@ function getActiveContinuationMarkerReason(marker) {
68315
68598
  }
68316
68599
  // src/hooks/ralph-loop/storage.ts
68317
68600
  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";
68601
+ import { existsSync as existsSync14, readFileSync as readFileSync12, writeFileSync as writeFileSync7, unlinkSync, mkdirSync as mkdirSync6 } from "fs";
68602
+ import { dirname as dirname5, join as join13 } from "path";
68320
68603
 
68321
68604
  // src/hooks/ralph-loop/constants.ts
68322
68605
  var DEFAULT_STATE_FILE = ".sisyphus/ralph-loop.local.md";
@@ -69598,7 +69881,7 @@ function buildEffectiveResolution(requirement, userOverride) {
69598
69881
 
69599
69882
  // src/cli/doctor/checks/model-resolution.ts
69600
69883
  function parseProviderModel(value) {
69601
- const slashIndex = value.indexOf("/");
69884
+ const slashIndex = value.lastIndexOf("/");
69602
69885
  if (slashIndex <= 0 || slashIndex === value.length - 1) {
69603
69886
  return null;
69604
69887
  }
@@ -69815,7 +70098,7 @@ async function checkConfig() {
69815
70098
  init_spawn_with_windows_hide();
69816
70099
  import { existsSync as existsSync27 } from "fs";
69817
70100
  import { createRequire } from "module";
69818
- import { dirname as dirname6, join as join26 } from "path";
70101
+ import { dirname as dirname8, join as join26 } from "path";
69819
70102
  async function checkBinaryExists(binary2) {
69820
70103
  try {
69821
70104
  const path10 = Bun.which(binary2);
@@ -69904,7 +70187,7 @@ function findCommentCheckerPackageBinary() {
69904
70187
  try {
69905
70188
  const require2 = createRequire(import.meta.url);
69906
70189
  const pkgPath = require2.resolve("@code-yeongyu/comment-checker/package.json");
69907
- const binaryPath = join26(dirname6(pkgPath), "bin", binaryName);
70190
+ const binaryPath = join26(dirname8(pkgPath), "bin", binaryName);
69908
70191
  if (existsSync27(binaryPath))
69909
70192
  return binaryPath;
69910
70193
  } catch {}
@@ -70734,8 +71017,8 @@ async function refreshModelCapabilities(options, deps = {}) {
70734
71017
 
70735
71018
  // src/features/mcp-oauth/storage.ts
70736
71019
  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";
71020
+ import { chmodSync, existsSync as existsSync31, mkdirSync as mkdirSync7, readFileSync as readFileSync28, unlinkSync as unlinkSync4, writeFileSync as writeFileSync10 } from "fs";
71021
+ import { dirname as dirname9, join as join31 } from "path";
70739
71022
  var STORAGE_FILE_NAME = "mcp-oauth.json";
70740
71023
  function getMcpOauthStoragePath() {
70741
71024
  return join31(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
@@ -70788,11 +71071,11 @@ function readStore() {
70788
71071
  function writeStore(store2) {
70789
71072
  const filePath = getMcpOauthStoragePath();
70790
71073
  try {
70791
- const dir = dirname7(filePath);
71074
+ const dir = dirname9(filePath);
70792
71075
  if (!existsSync31(dir)) {
70793
- mkdirSync8(dir, { recursive: true });
71076
+ mkdirSync7(dir, { recursive: true });
70794
71077
  }
70795
- writeFileSync11(filePath, JSON.stringify(store2, null, 2), { encoding: "utf-8", mode: 384 });
71078
+ writeFileSync10(filePath, JSON.stringify(store2, null, 2), { encoding: "utf-8", mode: 384 });
70796
71079
  chmodSync(filePath, 384);
70797
71080
  return true;
70798
71081
  } catch {
@@ -71249,14 +71532,17 @@ class McpOAuthProvider {
71249
71532
  }
71250
71533
 
71251
71534
  // src/cli/mcp-oauth/login.ts
71252
- async function login(serverName, options) {
71535
+ var defaultLoginDependencies = {
71536
+ createProvider: (options) => new McpOAuthProvider(options)
71537
+ };
71538
+ async function login(serverName, options, deps = defaultLoginDependencies) {
71253
71539
  try {
71254
71540
  const serverUrl = options.serverUrl;
71255
71541
  if (!serverUrl) {
71256
71542
  console.error(`Error: --server-url is required for server "${serverName}"`);
71257
71543
  return 1;
71258
71544
  }
71259
- const provider = new McpOAuthProvider({
71545
+ const provider = deps.createProvider({
71260
71546
  serverUrl,
71261
71547
  clientId: options.clientId,
71262
71548
  scopes: options.scopes