oh-my-opencode 3.17.15 → 4.1.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 (232) hide show
  1. package/README.ja.md +178 -113
  2. package/README.ko.md +221 -149
  3. package/README.md +79 -51
  4. package/README.ru.md +118 -71
  5. package/README.zh-cn.md +139 -73
  6. package/dist/agents/agent-skill-resolution.d.ts +1 -0
  7. package/dist/agents/atlas/agent.d.ts +7 -12
  8. package/dist/agents/atlas/default-prompt-sections.d.ts +5 -5
  9. package/dist/agents/atlas/gemini-prompt-sections.d.ts +4 -4
  10. package/dist/agents/atlas/gpt-prompt-sections.d.ts +5 -5
  11. package/dist/agents/atlas/kimi-prompt-sections.d.ts +6 -0
  12. package/dist/agents/atlas/kimi.d.ts +2 -0
  13. package/dist/agents/atlas/opus-4-7-prompt-sections.d.ts +6 -0
  14. package/dist/agents/atlas/opus-4-7.d.ts +2 -0
  15. package/dist/agents/atlas/shared-prompt.d.ts +1 -1
  16. package/dist/agents/builtin-agents/available-skills.d.ts +1 -1
  17. package/dist/agents/builtin-agents/general-agents.d.ts +1 -0
  18. package/dist/agents/builtin-agents.d.ts +1 -1
  19. package/dist/agents/dynamic-agent-core-sections.d.ts +1 -0
  20. package/dist/agents/dynamic-agent-prompt-builder.d.ts +1 -1
  21. package/dist/agents/hephaestus/gpt-5-5.d.ts +0 -4
  22. package/dist/agents/prometheus/plan-generation.d.ts +1 -1
  23. package/dist/agents/types.d.ts +1 -0
  24. package/dist/cli/boulder/boulder.d.ts +2 -0
  25. package/dist/cli/boulder/formatter.d.ts +5 -0
  26. package/dist/cli/boulder/index.d.ts +1 -0
  27. package/dist/cli/boulder/types.d.ts +30 -0
  28. package/dist/cli/doctor/checks/system-binary.d.ts +2 -0
  29. package/dist/cli/doctor/checks/team-mode.d.ts +2 -0
  30. package/dist/cli/doctor/constants.d.ts +1 -0
  31. package/dist/cli/index.js +1469 -554
  32. package/dist/config/index.d.ts +1 -1
  33. package/dist/config/schema/agent-names.d.ts +1 -0
  34. package/dist/config/schema/agent-overrides.d.ts +45 -0
  35. package/dist/config/schema/categories.d.ts +7 -1
  36. package/dist/config/schema/commands.d.ts +1 -0
  37. package/dist/config/schema/fallback-models.d.ts +5 -0
  38. package/dist/config/schema/hooks.d.ts +2 -0
  39. package/dist/config/schema/keyword-detector.d.ts +21 -0
  40. package/dist/config/schema/oh-my-opencode-config.d.ts +71 -0
  41. package/dist/config/schema/team-mode.d.ts +16 -0
  42. package/dist/config/schema.d.ts +2 -0
  43. package/dist/create-hooks.d.ts +4 -0
  44. package/dist/create-managers.d.ts +2 -0
  45. package/dist/features/background-agent/manager.d.ts +6 -0
  46. package/dist/features/background-agent/spawner.d.ts +4 -2
  47. package/dist/features/background-agent/task-poller.d.ts +1 -0
  48. package/dist/features/background-agent/types.d.ts +5 -0
  49. package/dist/features/boulder-state/format-duration.d.ts +1 -0
  50. package/dist/features/boulder-state/index.d.ts +1 -0
  51. package/dist/features/boulder-state/storage.d.ts +40 -1
  52. package/dist/features/boulder-state/types.d.ts +43 -0
  53. package/dist/features/builtin-commands/commands.d.ts +1 -0
  54. package/dist/features/builtin-commands/templates/hyperplan.d.ts +1 -0
  55. package/dist/features/builtin-commands/templates/refactor.d.ts +1 -0
  56. package/dist/features/builtin-commands/templates/remove-ai-slops.d.ts +1 -0
  57. package/dist/features/builtin-commands/templates/start-work.d.ts +1 -1
  58. package/dist/features/builtin-commands/types.d.ts +1 -1
  59. package/dist/features/builtin-skills/skills/git-master-sections/commit-workflow.d.ts +1 -1
  60. package/dist/features/builtin-skills/skills/git-master-sections/history-search-workflow.d.ts +1 -1
  61. package/dist/features/builtin-skills/skills/git-master-sections/overview.d.ts +1 -1
  62. package/dist/features/builtin-skills/skills/git-master-sections/quick-reference.d.ts +1 -1
  63. package/dist/features/builtin-skills/skills/git-master-sections/rebase-workflow.d.ts +1 -1
  64. package/dist/features/builtin-skills/skills/index.d.ts +1 -0
  65. package/dist/features/builtin-skills/skills/team-mode.d.ts +2 -0
  66. package/dist/features/builtin-skills/skills.d.ts +1 -0
  67. package/dist/features/claude-code-plugin-loader/discovery.d.ts +1 -0
  68. package/dist/features/hook-message-injector/injector.d.ts +2 -2
  69. package/dist/features/opencode-skill-loader/loader.d.ts +2 -2
  70. package/dist/features/opencode-skill-loader/skill-resolution-options.d.ts +1 -0
  71. package/dist/features/team-mode/deps.d.ts +6 -0
  72. package/dist/features/team-mode/member-guidance.d.ts +2 -0
  73. package/dist/features/team-mode/member-parser.d.ts +16 -0
  74. package/dist/features/team-mode/member-session-resolution.d.ts +6 -0
  75. package/dist/features/team-mode/member-session-routing.d.ts +19 -0
  76. package/dist/features/team-mode/team-layout-tmux/close-team-member-pane.d.ts +4 -0
  77. package/dist/features/team-mode/team-layout-tmux/layout.d.ts +26 -6
  78. package/dist/features/team-mode/team-layout-tmux/rebalance-team-window.d.ts +9 -0
  79. package/dist/features/team-mode/team-layout-tmux/resolve-caller-tmux-session.d.ts +7 -0
  80. package/dist/features/team-mode/team-layout-tmux/sweep-stale-team-sessions.d.ts +8 -0
  81. package/dist/features/team-mode/team-mailbox/ack.d.ts +2 -0
  82. package/dist/features/team-mode/team-mailbox/inbox.d.ts +3 -0
  83. package/dist/features/team-mode/team-mailbox/index.d.ts +7 -0
  84. package/dist/features/team-mode/team-mailbox/poll.d.ts +10 -0
  85. package/dist/features/team-mode/team-mailbox/reservation.d.ts +11 -0
  86. package/dist/features/team-mode/team-mailbox/send.d.ts +27 -0
  87. package/dist/features/team-mode/team-registry/index.d.ts +3 -0
  88. package/dist/features/team-mode/team-registry/loader.d.ts +12 -0
  89. package/dist/features/team-mode/team-registry/paths.d.ts +13 -0
  90. package/dist/features/team-mode/team-registry/team-spec-input-normalizer.d.ts +6 -0
  91. package/dist/features/team-mode/team-registry/validator.d.ts +10 -0
  92. package/dist/features/team-mode/team-runtime/activate-team-layout.d.ts +4 -0
  93. package/dist/features/team-mode/team-runtime/cleanup-team-run-resources.d.ts +17 -0
  94. package/dist/features/team-mode/team-runtime/create.d.ts +25 -0
  95. package/dist/features/team-mode/team-runtime/delete-team.d.ts +16 -0
  96. package/dist/features/team-mode/team-runtime/index.d.ts +2 -0
  97. package/dist/features/team-mode/team-runtime/resolve-member-dependencies.d.ts +3 -0
  98. package/dist/features/team-mode/team-runtime/resolve-member.d.ts +17 -0
  99. package/dist/features/team-mode/team-runtime/session-cleanup.d.ts +21 -0
  100. package/dist/features/team-mode/team-runtime/session-team-run-registry.d.ts +4 -0
  101. package/dist/features/team-mode/team-runtime/shutdown-helpers.d.ts +11 -0
  102. package/dist/features/team-mode/team-runtime/shutdown-test-fixtures.d.ts +46 -0
  103. package/dist/features/team-mode/team-runtime/shutdown.d.ts +5 -0
  104. package/dist/features/team-mode/team-runtime/status.d.ts +36 -0
  105. package/dist/features/team-mode/team-session-registry.d.ts +11 -0
  106. package/dist/features/team-mode/team-state-store/index.d.ts +1 -0
  107. package/dist/features/team-mode/team-state-store/locks.d.ts +12 -0
  108. package/dist/features/team-mode/team-state-store/resume.d.ts +10 -0
  109. package/dist/features/team-mode/team-state-store/store.d.ts +21 -0
  110. package/dist/features/team-mode/team-tasklist/claim.d.ts +10 -0
  111. package/dist/features/team-mode/team-tasklist/dependencies.d.ts +2 -0
  112. package/dist/features/team-mode/team-tasklist/get.d.ts +3 -0
  113. package/dist/features/team-mode/team-tasklist/index.d.ts +6 -0
  114. package/dist/features/team-mode/team-tasklist/list.d.ts +8 -0
  115. package/dist/features/team-mode/team-tasklist/store.d.ts +3 -0
  116. package/dist/features/team-mode/team-tasklist/test-support.d.ts +9 -0
  117. package/dist/features/team-mode/team-tasklist/update.d.ts +9 -0
  118. package/dist/features/team-mode/tools/index.d.ts +1 -0
  119. package/dist/features/team-mode/tools/lifecycle-test-fixture.d.ts +188 -0
  120. package/dist/features/team-mode/tools/lifecycle.d.ts +37 -0
  121. package/dist/features/team-mode/tools/messaging.d.ts +31 -0
  122. package/dist/features/team-mode/tools/query.d.ts +16 -0
  123. package/dist/features/team-mode/tools/tasks.d.ts +18 -0
  124. package/dist/features/team-mode/types.d.ts +138 -6
  125. package/dist/features/tmux-subagent/action-executor-core.d.ts +1 -0
  126. package/dist/features/tmux-subagent/action-executor.d.ts +1 -0
  127. package/dist/features/tmux-subagent/attachable-session-status.d.ts +4 -0
  128. package/dist/features/tmux-subagent/cleanup.d.ts +10 -0
  129. package/dist/features/tmux-subagent/manager.d.ts +32 -3
  130. package/dist/features/tmux-subagent/pane-state-querier.d.ts +10 -0
  131. package/dist/features/tmux-subagent/polling.d.ts +1 -0
  132. package/dist/features/tmux-subagent/session-created-handler.d.ts +23 -0
  133. package/dist/features/tmux-subagent/session-deleted-handler.d.ts +16 -0
  134. package/dist/hooks/atlas/atlas-hook.d.ts +1 -1
  135. package/dist/hooks/atlas/boulder-continuation-injector.d.ts +2 -3
  136. package/dist/hooks/atlas/recent-model-resolver.d.ts +9 -1
  137. package/dist/hooks/atlas/system-reminder-templates.d.ts +1 -0
  138. package/dist/hooks/atlas/tool-execute-after.d.ts +3 -1
  139. package/dist/hooks/atlas/tool-execute-before.d.ts +2 -0
  140. package/dist/hooks/atlas/types.d.ts +10 -2
  141. package/dist/hooks/compaction-context-injector/recovery.d.ts +1 -1
  142. package/dist/hooks/compaction-context-injector/types.d.ts +1 -0
  143. package/dist/hooks/compaction-todo-preserver/hook.d.ts +11 -0
  144. package/dist/hooks/fsync-skip-warning/index.d.ts +18 -0
  145. package/dist/hooks/index.d.ts +4 -0
  146. package/dist/hooks/keyword-detector/constants.d.ts +6 -0
  147. package/dist/hooks/keyword-detector/detector.d.ts +5 -3
  148. package/dist/hooks/keyword-detector/hook.d.ts +2 -1
  149. package/dist/hooks/keyword-detector/hyperplan/default.d.ts +13 -0
  150. package/dist/hooks/keyword-detector/hyperplan/index.d.ts +1 -0
  151. package/dist/hooks/keyword-detector/team/default.d.ts +13 -0
  152. package/dist/hooks/keyword-detector/team/index.d.ts +1 -0
  153. package/dist/hooks/ralph-loop/continuation-prompt-injector.d.ts +7 -1
  154. package/dist/hooks/ralph-loop/iteration-continuation.d.ts +9 -1
  155. package/dist/hooks/ralph-loop/loop-state-controller.d.ts +1 -0
  156. package/dist/hooks/ralph-loop/pending-verification-handler.d.ts +3 -0
  157. package/dist/hooks/ralph-loop/ralph-loop-event-handler.d.ts +2 -0
  158. package/dist/hooks/ralph-loop/types.d.ts +1 -0
  159. package/dist/hooks/ralph-loop/verification-failure-handler.d.ts +3 -1
  160. package/dist/hooks/session-recovery/recover-tool-result-missing.d.ts +2 -2
  161. package/dist/hooks/shared/session-idle-settle.d.ts +2 -0
  162. package/dist/hooks/team-mailbox-injector/hook.d.ts +31 -0
  163. package/dist/hooks/team-mailbox-injector/index.d.ts +2 -0
  164. package/dist/hooks/team-mode-status-injector/hook.d.ts +28 -0
  165. package/dist/hooks/team-mode-status-injector/index.d.ts +1 -0
  166. package/dist/hooks/team-session-events/team-idle-wake-hint.d.ts +41 -0
  167. package/dist/hooks/team-session-events/team-lead-orphan-handler.d.ts +12 -0
  168. package/dist/hooks/team-session-events/team-member-error-handler.d.ts +10 -0
  169. package/dist/hooks/team-session-events/team-member-status-handler.d.ts +10 -0
  170. package/dist/hooks/team-tool-gating/hook.d.ts +3 -0
  171. package/dist/hooks/team-tool-gating/index.d.ts +1 -0
  172. package/dist/hooks/todo-description-override/description.d.ts +1 -1
  173. package/dist/hooks/unstable-agent-babysitter/unstable-agent-babysitter-hook.d.ts +1 -0
  174. package/dist/hooks/write-existing-file-guard/hook.d.ts +6 -1
  175. package/dist/hooks/write-existing-file-guard/tool-execute-before-handler.d.ts +1 -0
  176. package/dist/index.js +78761 -73089
  177. package/dist/oh-my-opencode.schema.json +199 -47
  178. package/dist/plugin/hooks/create-core-hooks.d.ts +4 -0
  179. package/dist/plugin/hooks/create-tool-guard-hooks.d.ts +3 -1
  180. package/dist/plugin/hooks/create-transform-hooks.d.ts +3 -1
  181. package/dist/plugin/recent-synthetic-idles.d.ts +1 -0
  182. package/dist/plugin/session-compacting.d.ts +31 -0
  183. package/dist/plugin/tool-registry.d.ts +16 -0
  184. package/dist/plugin-dispose.d.ts +13 -0
  185. package/dist/plugin-handlers/agent-priority-order.d.ts +6 -6
  186. package/dist/shared/agent-ordering.d.ts +8 -0
  187. package/dist/shared/agent-sort-shim.d.ts +8 -8
  188. package/dist/shared/agent-tool-restrictions.d.ts +5 -1
  189. package/dist/shared/bun-file-shim.d.ts +8 -0
  190. package/dist/shared/bun-hash-shim.d.ts +1 -0
  191. package/dist/shared/bun-spawn-shim.d.ts +1 -0
  192. package/dist/shared/bun-which-shim.d.ts +1 -0
  193. package/dist/shared/classify-path-environment.d.ts +3 -0
  194. package/dist/shared/event-session-id.d.ts +2 -0
  195. package/dist/shared/extract-semver.d.ts +1 -0
  196. package/dist/shared/fsync-skip-tracker.d.ts +12 -0
  197. package/dist/shared/fsync-skip-warning-formatter.d.ts +2 -0
  198. package/dist/shared/index.d.ts +3 -0
  199. package/dist/shared/model-capability-heuristics.d.ts +1 -0
  200. package/dist/shared/opencode-version.d.ts +14 -1
  201. package/dist/shared/posthog.d.ts +7 -1
  202. package/dist/shared/project-discovery-dirs.d.ts +1 -0
  203. package/dist/shared/session-route.d.ts +18 -0
  204. package/dist/shared/shell-env.d.ts +1 -0
  205. package/dist/shared/tmux/cmux-detect.d.ts +8 -0
  206. package/dist/shared/tmux/constants.d.ts +1 -1
  207. package/dist/shared/tmux/index.d.ts +2 -0
  208. package/dist/shared/tmux/runner.d.ts +13 -0
  209. package/dist/shared/tmux/tmux-utils/pane-replace.d.ts +1 -1
  210. package/dist/shared/tmux/tmux-utils/pane-spawn.d.ts +13 -1
  211. package/dist/shared/tmux/tmux-utils/session-spawn.d.ts +13 -1
  212. package/dist/shared/tmux/tmux-utils/stale-session-sweep.d.ts +9 -2
  213. package/dist/shared/tmux/tmux-utils/window-spawn.d.ts +13 -1
  214. package/dist/shared/tmux/tmux-utils.d.ts +1 -1
  215. package/dist/shared/tolerant-fsync.d.ts +5 -0
  216. package/dist/shared/write-file-atomically.d.ts +4 -1
  217. package/dist/tools/call-omo-agent/agent-resolver.d.ts +5 -12
  218. package/dist/tools/call-omo-agent/constants.d.ts +2 -2
  219. package/dist/tools/delegate-task/model-string-parser.d.ts +9 -0
  220. package/dist/tools/delegate-task/openai-categories.d.ts +1 -0
  221. package/dist/tools/delegate-task/resolve-call-id.d.ts +2 -0
  222. package/dist/tools/delegate-task/skill-resolver.d.ts +1 -0
  223. package/dist/tools/delegate-task/subagent-resolver.d.ts +5 -1
  224. package/dist/tools/delegate-task/sync-prompt-sender.d.ts +1 -0
  225. package/dist/tools/delegate-task/sync-result-fetcher.d.ts +3 -1
  226. package/dist/tools/delegate-task/types.d.ts +1 -0
  227. package/dist/tools/index.d.ts +1 -0
  228. package/dist/tools/interactive-bash/tmux-path-resolver.d.ts +1 -0
  229. package/dist/tools/look-at/missing-file-error.d.ts +2 -0
  230. package/dist/tools/skill/types.d.ts +2 -0
  231. package/package.json +21 -15
  232. package/dist/hooks/ralph-loop/completion-promise-detector-test-input.d.ts +0 -11
package/dist/cli/index.js CHANGED
@@ -6214,14 +6214,119 @@ var init_model_versions = __esm(() => {
6214
6214
  // src/shared/migration/agent-category.ts
6215
6215
  var init_agent_category = () => {};
6216
6216
 
6217
+ // src/shared/classify-path-environment.ts
6218
+ import { homedir as homedir2 } from "os";
6219
+ import path3 from "path";
6220
+ function normalizeInputPath(absolutePath) {
6221
+ return absolutePath.replaceAll("\\", "/");
6222
+ }
6223
+ function isUnderPath(normalizedPath, normalizedParentPath) {
6224
+ return normalizedPath === normalizedParentPath || normalizedPath.startsWith(`${normalizedParentPath}/`);
6225
+ }
6226
+ function classifyPathEnvironment(absolutePath) {
6227
+ if (absolutePath.length === 0)
6228
+ return "unknown";
6229
+ const normalizedPath = normalizeInputPath(absolutePath);
6230
+ const lowercasePath = normalizedPath.toLowerCase();
6231
+ if (lowercasePath.includes("/onedrive") || lowercasePath.includes("/onedrive/")) {
6232
+ return "onedrive";
6233
+ }
6234
+ if (normalizedPath.includes("/Library/Mobile Documents/")) {
6235
+ return "icloud";
6236
+ }
6237
+ if (isUnderPath(normalizedPath, "/Volumes")) {
6238
+ return "network-drive";
6239
+ }
6240
+ if (normalizedPath.startsWith("/Users/") && (normalizedPath.includes("/Desktop/") || normalizedPath.endsWith("/Desktop") || normalizedPath.includes("/Documents/") || normalizedPath.endsWith("/Documents"))) {
6241
+ return "desktop-sync";
6242
+ }
6243
+ const normalizedHome = normalizeInputPath(homedir2());
6244
+ const desktopPath = normalizeInputPath(path3.join(normalizedHome, "Desktop"));
6245
+ const documentsPath = normalizeInputPath(path3.join(normalizedHome, "Documents"));
6246
+ if (isUnderPath(normalizedPath, desktopPath) || isUnderPath(normalizedPath, documentsPath)) {
6247
+ return "desktop-sync";
6248
+ }
6249
+ return "unknown";
6250
+ }
6251
+ var init_classify_path_environment = () => {};
6252
+
6253
+ // src/shared/fsync-skip-tracker.ts
6254
+ function recordFsyncSkip(entry) {
6255
+ fsyncSkips.push({ ...entry, timestamp: Date.now() });
6256
+ if (fsyncSkips.length > MAX_SKIPS) {
6257
+ fsyncSkips.splice(0, fsyncSkips.length - MAX_SKIPS);
6258
+ }
6259
+ }
6260
+ var MAX_SKIPS = 200, fsyncSkips;
6261
+ var init_fsync_skip_tracker = __esm(() => {
6262
+ fsyncSkips = [];
6263
+ });
6264
+
6265
+ // src/shared/tolerant-fsync.ts
6266
+ import { fsyncSync } from "fs";
6267
+ function isToleratedFsyncError(error) {
6268
+ if (!(error instanceof Error))
6269
+ return false;
6270
+ const code = error.code;
6271
+ return code !== undefined && TOLERATED_FSYNC_CODES.has(code);
6272
+ }
6273
+ function extractPathFromContextLabel(contextLabel) {
6274
+ const separatorIndex = contextLabel.indexOf(":");
6275
+ if (separatorIndex < 0)
6276
+ return contextLabel;
6277
+ return contextLabel.slice(separatorIndex + 1);
6278
+ }
6279
+ function tolerantFsyncSync(fileDescriptor, contextLabel, fsyncImpl = fsyncSync) {
6280
+ try {
6281
+ fsyncImpl(fileDescriptor);
6282
+ } catch (error) {
6283
+ if (!isToleratedFsyncError(error))
6284
+ throw error;
6285
+ const errorCode = error.code ?? "UNKNOWN";
6286
+ const message = error instanceof Error ? error.message : String(error);
6287
+ const filePath = extractPathFromContextLabel(contextLabel);
6288
+ log("fsync skipped due to filesystem limitation", {
6289
+ event: "fsync-skipped",
6290
+ contextLabel,
6291
+ code: errorCode,
6292
+ message
6293
+ });
6294
+ recordFsyncSkip({
6295
+ filePath,
6296
+ contextLabel,
6297
+ errorCode,
6298
+ message,
6299
+ pathClassification: classifyPathEnvironment(filePath)
6300
+ });
6301
+ }
6302
+ }
6303
+ var TOLERATED_FSYNC_CODES;
6304
+ var init_tolerant_fsync = __esm(() => {
6305
+ init_classify_path_environment();
6306
+ init_fsync_skip_tracker();
6307
+ init_logger();
6308
+ TOLERATED_FSYNC_CODES = new Set([
6309
+ "EPERM",
6310
+ "EACCES",
6311
+ "ENOTSUP",
6312
+ "EINVAL"
6313
+ ]);
6314
+ });
6315
+
6217
6316
  // src/shared/write-file-atomically.ts
6218
- import { closeSync, fsyncSync, openSync, renameSync, unlinkSync, writeFileSync } from "fs";
6219
- function writeFileAtomically(filePath, content) {
6317
+ import {
6318
+ closeSync,
6319
+ openSync,
6320
+ renameSync,
6321
+ unlinkSync,
6322
+ writeFileSync
6323
+ } from "fs";
6324
+ function writeFileAtomically(filePath, content, deps = {}) {
6220
6325
  const tempPath = `${filePath}.tmp`;
6221
6326
  writeFileSync(tempPath, content, "utf-8");
6222
- const tempFileDescriptor = openSync(tempPath, "r");
6327
+ const tempFileDescriptor = openSync(tempPath, "r+");
6223
6328
  try {
6224
- fsyncSync(tempFileDescriptor);
6329
+ tolerantFsyncSync(tempFileDescriptor, `writeFileAtomically:${filePath}`, deps.fsyncSync);
6225
6330
  } finally {
6226
6331
  closeSync(tempFileDescriptor);
6227
6332
  }
@@ -6238,11 +6343,18 @@ function writeFileAtomically(filePath, content) {
6238
6343
  }
6239
6344
  }
6240
6345
  }
6241
- var init_write_file_atomically = () => {};
6346
+ var init_write_file_atomically = __esm(() => {
6347
+ init_tolerant_fsync();
6348
+ });
6349
+
6350
+ // src/shared/record-type-guard.ts
6351
+ function isRecord(value) {
6352
+ return typeof value === "object" && value !== null;
6353
+ }
6242
6354
 
6243
6355
  // src/shared/migration/migrations-sidecar.ts
6244
6356
  import * as fs2 from "fs";
6245
- import * as path3 from "path";
6357
+ import * as path4 from "path";
6246
6358
  function getSidecarPath(configPath) {
6247
6359
  return `${configPath}.migrations.json`;
6248
6360
  }
@@ -6254,8 +6366,8 @@ function readAppliedMigrations(configPath) {
6254
6366
  }
6255
6367
  const content = fs2.readFileSync(sidecarPath, "utf-8");
6256
6368
  const parsed = JSON.parse(content);
6257
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed) && Array.isArray(parsed.appliedMigrations)) {
6258
- return new Set(parsed.appliedMigrations.filter((m) => typeof m === "string"));
6369
+ if (isRecord(parsed) && Array.isArray(parsed.appliedMigrations)) {
6370
+ return new Set(parsed.appliedMigrations.filter((migration) => typeof migration === "string"));
6259
6371
  }
6260
6372
  return new Set;
6261
6373
  } catch (err) {
@@ -6269,7 +6381,7 @@ function writeAppliedMigrations(configPath, migrations) {
6269
6381
  appliedMigrations: Array.from(migrations).sort()
6270
6382
  };
6271
6383
  try {
6272
- const parentDir = path3.dirname(sidecarPath);
6384
+ const parentDir = path4.dirname(sidecarPath);
6273
6385
  if (!fs2.existsSync(parentDir)) {
6274
6386
  fs2.mkdirSync(parentDir, { recursive: true });
6275
6387
  }
@@ -6462,7 +6574,7 @@ var init_migration = __esm(() => {
6462
6574
 
6463
6575
  // src/shared/opencode-config-dir.ts
6464
6576
  import { existsSync as existsSync4, realpathSync as realpathSync3 } from "fs";
6465
- import { homedir as homedir2 } from "os";
6577
+ import { homedir as homedir3 } from "os";
6466
6578
  import { join as join5, resolve as resolve2, win32 } from "path";
6467
6579
  function isDevBuild(version) {
6468
6580
  if (!version)
@@ -6473,14 +6585,14 @@ function getTauriConfigDir(identifier) {
6473
6585
  const platform = process.platform;
6474
6586
  switch (platform) {
6475
6587
  case "darwin":
6476
- return join5(homedir2(), "Library", "Application Support", identifier);
6588
+ return join5(homedir3(), "Library", "Application Support", identifier);
6477
6589
  case "win32": {
6478
- const appData = process.env.APPDATA || join5(homedir2(), "AppData", "Roaming");
6590
+ const appData = process.env.APPDATA || join5(homedir3(), "AppData", "Roaming");
6479
6591
  return win32.join(appData, identifier);
6480
6592
  }
6481
6593
  case "linux":
6482
6594
  default: {
6483
- const xdgConfig = process.env.XDG_CONFIG_HOME || join5(homedir2(), ".config");
6595
+ const xdgConfig = process.env.XDG_CONFIG_HOME || join5(homedir3(), ".config");
6484
6596
  return join5(xdgConfig, identifier);
6485
6597
  }
6486
6598
  }
@@ -6500,7 +6612,7 @@ function getCliConfigDir() {
6500
6612
  if (envConfigDir) {
6501
6613
  return resolveConfigPath(envConfigDir);
6502
6614
  }
6503
- const xdgConfig = process.env.XDG_CONFIG_HOME || join5(homedir2(), ".config");
6615
+ const xdgConfig = process.env.XDG_CONFIG_HOME || join5(homedir3(), ".config");
6504
6616
  return resolveConfigPath(join5(xdgConfig, "opencode"));
6505
6617
  }
6506
6618
  function getOpenCodeConfigDir(options) {
@@ -6537,11 +6649,11 @@ var init_opencode_config_dir = __esm(() => {
6537
6649
  });
6538
6650
 
6539
6651
  // src/shared/resolve-agent-definition-paths.ts
6540
- import { homedir as homedir3 } from "os";
6652
+ import { homedir as homedir4 } from "os";
6541
6653
  import { isAbsolute as isAbsolute2, resolve as resolve3 } from "path";
6542
6654
  function resolveAgentDefinitionPaths(paths, baseDir, containmentDir) {
6543
6655
  return paths.flatMap((p) => {
6544
- const expanded = p.startsWith("~/") ? p.replace(/^~\//, `${homedir3()}/`) : p;
6656
+ const expanded = p.startsWith("~/") ? p.replace(/^~\//, `${homedir4()}/`) : p;
6545
6657
  const resolved = isAbsolute2(expanded) ? expanded : resolve3(baseDir, expanded);
6546
6658
  if (containmentDir !== null && !isWithinProject(resolved, containmentDir)) {
6547
6659
  log(`agent_definitions path rejected (outside project boundary): ${p} -> ${resolved}`);
@@ -6557,6 +6669,8 @@ var init_resolve_agent_definition_paths = __esm(() => {
6557
6669
 
6558
6670
  // src/shared/opencode-version.ts
6559
6671
  import { execSync } from "child_process";
6672
+ import { existsSync as existsSync5, readFileSync as readFileSync4, realpathSync as realpathSync4 } from "fs";
6673
+ import { dirname as dirname3, join as join6 } from "path";
6560
6674
  function parseVersion(version) {
6561
6675
  const cleaned = version.replace(/^v/, "").split("-")[0];
6562
6676
  return cleaned.split(".").map((n) => parseInt(n, 10) || 0);
@@ -6575,12 +6689,51 @@ function compareVersions(a, b) {
6575
6689
  }
6576
6690
  return 0;
6577
6691
  }
6578
- function getOpenCodeVersion() {
6692
+ function isRecord2(value) {
6693
+ return typeof value === "object" && value !== null;
6694
+ }
6695
+ function parsePackageVersion(content) {
6696
+ try {
6697
+ const parsed = JSON.parse(content);
6698
+ if (!isRecord2(parsed))
6699
+ return null;
6700
+ const name = parsed.name;
6701
+ const version = parsed.version;
6702
+ if (typeof name !== "string" || !name.includes("opencode"))
6703
+ return null;
6704
+ if (typeof version !== "string" || version.length === 0)
6705
+ return null;
6706
+ return version;
6707
+ } catch {
6708
+ return null;
6709
+ }
6710
+ }
6711
+ function getPackageVersionFromBinary(binaryPath, deps) {
6712
+ try {
6713
+ const realBinaryPath = deps.realpath(binaryPath);
6714
+ const packagePath = join6(dirname3(dirname3(realBinaryPath)), "package.json");
6715
+ if (!deps.exists(packagePath))
6716
+ return null;
6717
+ return parsePackageVersion(deps.readText(packagePath));
6718
+ } catch {
6719
+ return null;
6720
+ }
6721
+ }
6722
+ function getOpenCodeVersion(deps = {}) {
6579
6723
  if (cachedVersion !== NOT_CACHED) {
6580
6724
  return cachedVersion;
6581
6725
  }
6726
+ const resolvedDeps = { ...defaultDeps, ...deps };
6727
+ const binaryPath = resolvedDeps.getBinaryPath();
6728
+ if (binaryPath) {
6729
+ const packageVersion = getPackageVersionFromBinary(binaryPath, resolvedDeps);
6730
+ if (packageVersion) {
6731
+ cachedVersion = packageVersion;
6732
+ return cachedVersion;
6733
+ }
6734
+ }
6582
6735
  try {
6583
- const result = execSync("opencode --version", {
6736
+ const result = resolvedDeps.execCommand("opencode --version", {
6584
6737
  encoding: "utf-8",
6585
6738
  timeout: 5000,
6586
6739
  stdio: ["pipe", "pipe", "pipe"]
@@ -6599,15 +6752,27 @@ function isOpenCodeVersionAtLeast(version) {
6599
6752
  return true;
6600
6753
  return compareVersions(current, version) >= 0;
6601
6754
  }
6602
- var OPENCODE_SQLITE_VERSION = "1.1.53", NOT_CACHED, cachedVersion;
6755
+ var OPENCODE_SQLITE_VERSION = "1.1.53", NOT_CACHED, cachedVersion, defaultDeps;
6603
6756
  var init_opencode_version = __esm(() => {
6604
6757
  NOT_CACHED = Symbol("NOT_CACHED");
6605
6758
  cachedVersion = NOT_CACHED;
6759
+ defaultDeps = {
6760
+ execCommand: (command, options) => execSync(command, options),
6761
+ getBinaryPath: () => {
6762
+ const envPath = process.env.OPENCODE_BIN_PATH;
6763
+ if (envPath)
6764
+ return envPath;
6765
+ return globalThis.Bun?.which("opencode") ?? null;
6766
+ },
6767
+ exists: existsSync5,
6768
+ realpath: realpathSync4,
6769
+ readText: (filePath) => readFileSync4(filePath, "utf-8")
6770
+ };
6606
6771
  });
6607
6772
 
6608
6773
  // src/shared/opencode-storage-detection.ts
6609
- import { existsSync as existsSync5 } from "fs";
6610
- import { join as join6 } from "path";
6774
+ import { existsSync as existsSync6 } from "fs";
6775
+ import { join as join7 } from "path";
6611
6776
  function isSqliteBackend() {
6612
6777
  if (cachedResult === true)
6613
6778
  return true;
@@ -6615,8 +6780,8 @@ function isSqliteBackend() {
6615
6780
  return false;
6616
6781
  const check = () => {
6617
6782
  const versionOk = isOpenCodeVersionAtLeast(OPENCODE_SQLITE_VERSION);
6618
- const dbPath = join6(getDataDir(), "opencode", "opencode.db");
6619
- return versionOk && existsSync5(dbPath);
6783
+ const dbPath = join7(getDataDir(), "opencode", "opencode.db");
6784
+ return versionOk && existsSync6(dbPath);
6620
6785
  };
6621
6786
  if (cachedResult === FALSE_PENDING_RETRY) {
6622
6787
  const result2 = check();
@@ -6738,7 +6903,8 @@ function spawn(cmdOrOpts, opts) {
6738
6903
  cwd: options.cwd,
6739
6904
  env: options.env,
6740
6905
  stdio: resolveStdio(options),
6741
- detached: options.detached
6906
+ detached: options.detached,
6907
+ signal: options.signal
6742
6908
  });
6743
6909
  return wrapNodeProcess(proc);
6744
6910
  }
@@ -6793,15 +6959,23 @@ var init_zip_extractor = __esm(() => {
6793
6959
  init_zip_entry_listing();
6794
6960
  });
6795
6961
 
6962
+ // src/shared/bun-file-shim.ts
6963
+ var runtime2, IS_BUN2;
6964
+ var init_bun_file_shim = __esm(() => {
6965
+ runtime2 = globalThis;
6966
+ IS_BUN2 = typeof runtime2.Bun !== "undefined";
6967
+ });
6968
+
6796
6969
  // src/shared/binary-downloader.ts
6797
- import { chmodSync, existsSync as existsSync6, mkdirSync as mkdirSync3, unlinkSync as unlinkSync2 } from "fs";
6798
- import * as path4 from "path";
6970
+ import { chmodSync, existsSync as existsSync7, mkdirSync as mkdirSync3, unlinkSync as unlinkSync2 } from "fs";
6971
+ import * as path5 from "path";
6799
6972
  function getCachedBinaryPath(cacheDir, binaryName) {
6800
- const binaryPath = path4.join(cacheDir, binaryName);
6801
- return existsSync6(binaryPath) ? binaryPath : null;
6973
+ const binaryPath = path5.join(cacheDir, binaryName);
6974
+ return existsSync7(binaryPath) ? binaryPath : null;
6802
6975
  }
6803
6976
  var init_binary_downloader = __esm(() => {
6804
6977
  init_bun_spawn_shim();
6978
+ init_bun_file_shim();
6805
6979
  init_archive_entry_validator();
6806
6980
  init_zip_extractor();
6807
6981
  });
@@ -6811,7 +6985,7 @@ function stripInvisibleAgentCharacters(agentName) {
6811
6985
  return agentName.replace(INVISIBLE_AGENT_CHARACTERS_REGEX, "");
6812
6986
  }
6813
6987
  function stripAgentListSortPrefix(agentName) {
6814
- return stripInvisibleAgentCharacters(agentName);
6988
+ return stripInvisibleAgentCharacters(agentName).replace(VISIBLE_AGENT_LIST_SORT_PREFIX_REGEX, "").replace(AGENT_WRAPPER_CHARS_REGEX, "");
6815
6989
  }
6816
6990
  function getAgentDisplayName(configKey) {
6817
6991
  const exactMatch = AGENT_DISPLAY_NAMES[configKey];
@@ -6840,7 +7014,7 @@ function getAgentConfigKey(agentName) {
6840
7014
  const lower = stripAgentListSortPrefix(agentName).trim().toLowerCase();
6841
7015
  return resolveKnownAgentConfigKey(agentName) ?? lower;
6842
7016
  }
6843
- var AGENT_DISPLAY_NAMES, INVISIBLE_AGENT_CHARACTERS_REGEX, REVERSE_DISPLAY_NAMES, LEGACY_DISPLAY_NAMES;
7017
+ var AGENT_DISPLAY_NAMES, INVISIBLE_AGENT_CHARACTERS_REGEX, VISIBLE_AGENT_LIST_SORT_PREFIX_REGEX, AGENT_WRAPPER_CHARS_REGEX, REVERSE_DISPLAY_NAMES, LEGACY_DISPLAY_NAMES;
6844
7018
  var init_agent_display_names = __esm(() => {
6845
7019
  AGENT_DISPLAY_NAMES = {
6846
7020
  sisyphus: "Sisyphus - Ultraworker",
@@ -6859,6 +7033,8 @@ var init_agent_display_names = __esm(() => {
6859
7033
  "council-member": "council-member"
6860
7034
  };
6861
7035
  INVISIBLE_AGENT_CHARACTERS_REGEX = /[\u200B\u200C\u200D\uFEFF]/g;
7036
+ VISIBLE_AGENT_LIST_SORT_PREFIX_REGEX = /^\d+\|/;
7037
+ AGENT_WRAPPER_CHARS_REGEX = /^[\\/"']+|[\\/"']+$/g;
6862
7038
  REVERSE_DISPLAY_NAMES = Object.fromEntries(Object.entries(AGENT_DISPLAY_NAMES).map(([key, displayName]) => [displayName.toLowerCase(), key]));
6863
7039
  LEGACY_DISPLAY_NAMES = {
6864
7040
  "sisyphus (ultraworker)": "sisyphus",
@@ -6883,7 +7059,7 @@ var init_model_requirements = __esm(() => {
6883
7059
  model: "claude-opus-4-7",
6884
7060
  variant: "max"
6885
7061
  },
6886
- { providers: ["opencode-go", "vercel"], model: "kimi-k2.5" },
7062
+ { providers: ["opencode-go", "vercel"], model: "kimi-k2.6" },
6887
7063
  { providers: ["kimi-for-coding"], model: "k2p5" },
6888
7064
  {
6889
7065
  providers: [
@@ -6930,13 +7106,14 @@ var init_model_requirements = __esm(() => {
6930
7106
  model: "claude-opus-4-7",
6931
7107
  variant: "max"
6932
7108
  },
6933
- { providers: ["opencode-go", "vercel"], model: "glm-5" }
7109
+ { providers: ["opencode-go", "vercel"], model: "glm-5.1" }
6934
7110
  ]
6935
7111
  },
6936
7112
  librarian: {
6937
7113
  fallbackChain: [
6938
7114
  { providers: ["openai"], model: "gpt-5.4-mini-fast" },
6939
- { providers: ["opencode-go", "vercel"], model: "minimax-m2.7-highspeed" },
7115
+ { providers: ["opencode-go"], model: "qwen3.5-plus" },
7116
+ { providers: ["vercel"], model: "minimax-m2.7-highspeed" },
6940
7117
  { providers: ["opencode-go", "vercel"], model: "minimax-m2.7" },
6941
7118
  { providers: ["anthropic", "opencode", "vercel"], model: "claude-haiku-4-5" },
6942
7119
  { providers: ["openai", "opencode", "vercel"], model: "gpt-5.4-nano" }
@@ -6945,7 +7122,8 @@ var init_model_requirements = __esm(() => {
6945
7122
  explore: {
6946
7123
  fallbackChain: [
6947
7124
  { providers: ["openai"], model: "gpt-5.4-mini-fast" },
6948
- { providers: ["opencode-go", "vercel"], model: "minimax-m2.7-highspeed" },
7125
+ { providers: ["opencode-go"], model: "qwen3.5-plus" },
7126
+ { providers: ["vercel"], model: "minimax-m2.7-highspeed" },
6949
7127
  { providers: ["opencode-go", "vercel"], model: "minimax-m2.7" },
6950
7128
  { providers: ["anthropic", "opencode", "vercel"], model: "claude-haiku-4-5" },
6951
7129
  { providers: ["openai", "opencode", "vercel"], model: "gpt-5.4-nano" }
@@ -6954,7 +7132,7 @@ var init_model_requirements = __esm(() => {
6954
7132
  "multimodal-looker": {
6955
7133
  fallbackChain: [
6956
7134
  { providers: ["openai", "opencode", "vercel"], model: "gpt-5.5", variant: "medium" },
6957
- { providers: ["opencode-go", "vercel"], model: "kimi-k2.5" },
7135
+ { providers: ["opencode-go", "vercel"], model: "kimi-k2.6" },
6958
7136
  { providers: ["zai-coding-plan", "vercel"], model: "glm-4.6v" },
6959
7137
  { providers: ["openai", "github-copilot", "opencode", "vercel"], model: "gpt-5-nano" }
6960
7138
  ]
@@ -6971,7 +7149,7 @@ var init_model_requirements = __esm(() => {
6971
7149
  model: "gpt-5.5",
6972
7150
  variant: "high"
6973
7151
  },
6974
- { providers: ["opencode-go", "vercel"], model: "glm-5" },
7152
+ { providers: ["opencode-go", "vercel"], model: "glm-5.1" },
6975
7153
  {
6976
7154
  providers: ["google", "github-copilot", "opencode", "vercel"],
6977
7155
  model: "gemini-3.1-pro"
@@ -6980,6 +7158,10 @@ var init_model_requirements = __esm(() => {
6980
7158
  },
6981
7159
  metis: {
6982
7160
  fallbackChain: [
7161
+ {
7162
+ providers: ["anthropic", "github-copilot", "opencode", "vercel"],
7163
+ model: "claude-sonnet-4-6"
7164
+ },
6983
7165
  {
6984
7166
  providers: ["anthropic", "github-copilot", "opencode", "vercel"],
6985
7167
  model: "claude-opus-4-7",
@@ -6990,7 +7172,7 @@ var init_model_requirements = __esm(() => {
6990
7172
  model: "gpt-5.5",
6991
7173
  variant: "high"
6992
7174
  },
6993
- { providers: ["opencode-go", "vercel"], model: "glm-5" },
7175
+ { providers: ["opencode-go", "vercel"], model: "glm-5.1" },
6994
7176
  { providers: ["kimi-for-coding"], model: "k2p5" }
6995
7177
  ]
6996
7178
  },
@@ -7011,13 +7193,13 @@ var init_model_requirements = __esm(() => {
7011
7193
  model: "gemini-3.1-pro",
7012
7194
  variant: "high"
7013
7195
  },
7014
- { providers: ["opencode-go", "vercel"], model: "glm-5" }
7196
+ { providers: ["opencode-go", "vercel"], model: "glm-5.1" }
7015
7197
  ]
7016
7198
  },
7017
7199
  atlas: {
7018
7200
  fallbackChain: [
7019
7201
  { providers: ["anthropic", "github-copilot", "opencode", "vercel"], model: "claude-sonnet-4-6" },
7020
- { providers: ["opencode-go", "vercel"], model: "kimi-k2.5" },
7202
+ { providers: ["opencode-go", "vercel"], model: "kimi-k2.6" },
7021
7203
  {
7022
7204
  providers: ["openai", "github-copilot", "opencode", "vercel"],
7023
7205
  model: "gpt-5.5",
@@ -7029,7 +7211,7 @@ var init_model_requirements = __esm(() => {
7029
7211
  "sisyphus-junior": {
7030
7212
  fallbackChain: [
7031
7213
  { providers: ["anthropic", "github-copilot", "opencode", "vercel"], model: "claude-sonnet-4-6" },
7032
- { providers: ["opencode-go", "vercel"], model: "kimi-k2.5" },
7214
+ { providers: ["opencode-go", "vercel"], model: "kimi-k2.6" },
7033
7215
  {
7034
7216
  providers: ["openai", "github-copilot", "opencode", "vercel"],
7035
7217
  model: "gpt-5.5",
@@ -7054,7 +7236,7 @@ var init_model_requirements = __esm(() => {
7054
7236
  model: "claude-opus-4-7",
7055
7237
  variant: "max"
7056
7238
  },
7057
- { providers: ["opencode-go", "vercel"], model: "glm-5" },
7239
+ { providers: ["opencode-go", "vercel"], model: "glm-5.1" },
7058
7240
  { providers: ["kimi-for-coding"], model: "k2p5" }
7059
7241
  ]
7060
7242
  },
@@ -7075,7 +7257,7 @@ var init_model_requirements = __esm(() => {
7075
7257
  model: "claude-opus-4-7",
7076
7258
  variant: "max"
7077
7259
  },
7078
- { providers: ["opencode-go", "vercel"], model: "glm-5" }
7260
+ { providers: ["opencode-go", "vercel"], model: "glm-5.1" }
7079
7261
  ]
7080
7262
  },
7081
7263
  deep: {
@@ -7094,7 +7276,9 @@ var init_model_requirements = __esm(() => {
7094
7276
  providers: ["google", "github-copilot", "opencode", "vercel"],
7095
7277
  model: "gemini-3.1-pro",
7096
7278
  variant: "high"
7097
- }
7279
+ },
7280
+ { providers: ["opencode-go", "vercel"], model: "kimi-k2.6" },
7281
+ { providers: ["opencode-go", "vercel"], model: "glm-5.1" }
7098
7282
  ]
7099
7283
  },
7100
7284
  artistry: {
@@ -7109,9 +7293,10 @@ var init_model_requirements = __esm(() => {
7109
7293
  model: "claude-opus-4-7",
7110
7294
  variant: "max"
7111
7295
  },
7112
- { providers: ["openai", "github-copilot", "opencode", "vercel"], model: "gpt-5.5" }
7113
- ],
7114
- requiresModel: "gemini-3.1-pro"
7296
+ { providers: ["openai", "github-copilot", "opencode", "vercel"], model: "gpt-5.5" },
7297
+ { providers: ["opencode-go", "vercel"], model: "kimi-k2.6" },
7298
+ { providers: ["opencode-go", "vercel"], model: "glm-5.1" }
7299
+ ]
7115
7300
  },
7116
7301
  quick: {
7117
7302
  fallbackChain: [
@@ -7142,7 +7327,7 @@ var init_model_requirements = __esm(() => {
7142
7327
  model: "gpt-5.3-codex",
7143
7328
  variant: "medium"
7144
7329
  },
7145
- { providers: ["opencode-go", "vercel"], model: "kimi-k2.5" },
7330
+ { providers: ["opencode-go", "vercel"], model: "kimi-k2.6" },
7146
7331
  {
7147
7332
  providers: ["google", "github-copilot", "opencode", "vercel"],
7148
7333
  model: "gemini-3-flash"
@@ -7164,7 +7349,7 @@ var init_model_requirements = __esm(() => {
7164
7349
  },
7165
7350
  { providers: ["zai-coding-plan", "opencode", "vercel"], model: "glm-5" },
7166
7351
  { providers: ["kimi-for-coding"], model: "k2p5" },
7167
- { providers: ["opencode-go", "vercel"], model: "glm-5" },
7352
+ { providers: ["opencode-go", "vercel"], model: "glm-5.1" },
7168
7353
  { providers: ["opencode", "vercel"], model: "kimi-k2.5" },
7169
7354
  {
7170
7355
  providers: [
@@ -7186,7 +7371,7 @@ var init_model_requirements = __esm(() => {
7186
7371
  providers: ["google", "github-copilot", "opencode", "vercel"],
7187
7372
  model: "gemini-3-flash"
7188
7373
  },
7189
- { providers: ["opencode-go", "vercel"], model: "kimi-k2.5" },
7374
+ { providers: ["opencode-go", "vercel"], model: "kimi-k2.6" },
7190
7375
  {
7191
7376
  providers: ["anthropic", "github-copilot", "opencode", "vercel"],
7192
7377
  model: "claude-sonnet-4-6"
@@ -7241,8 +7426,8 @@ function normalizeModelID(modelID) {
7241
7426
  }
7242
7427
 
7243
7428
  // src/shared/json-file-cache-store.ts
7244
- import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
7245
- import { join as join8 } from "path";
7429
+ import { existsSync as existsSync8, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "fs";
7430
+ import { join as join9 } from "path";
7246
7431
  function toLogLabel(cacheLabel) {
7247
7432
  return cacheLabel.toLowerCase();
7248
7433
  }
@@ -7250,11 +7435,11 @@ function createJsonFileCacheStore(options) {
7250
7435
  let memoryValue;
7251
7436
  let writtenInCurrentProcess = false;
7252
7437
  function getCacheFilePath() {
7253
- return join8(options.getCacheDir(), options.filename);
7438
+ return join9(options.getCacheDir(), options.filename);
7254
7439
  }
7255
7440
  function ensureCacheDir() {
7256
7441
  const cacheDir = options.getCacheDir();
7257
- if (!existsSync7(cacheDir)) {
7442
+ if (!existsSync8(cacheDir)) {
7258
7443
  mkdirSync4(cacheDir, { recursive: true });
7259
7444
  }
7260
7445
  }
@@ -7263,13 +7448,13 @@ function createJsonFileCacheStore(options) {
7263
7448
  return memoryValue;
7264
7449
  }
7265
7450
  const cacheFile = getCacheFilePath();
7266
- if (!existsSync7(cacheFile)) {
7451
+ if (!existsSync8(cacheFile)) {
7267
7452
  memoryValue = null;
7268
7453
  log(`[${options.logPrefix}] ${options.cacheLabel} file not found`, { cacheFile });
7269
7454
  return null;
7270
7455
  }
7271
7456
  try {
7272
- const content = readFileSync4(cacheFile, "utf-8");
7457
+ const content = readFileSync5(cacheFile, "utf-8");
7273
7458
  const value = JSON.parse(content);
7274
7459
  memoryValue = value;
7275
7460
  log(`[${options.logPrefix}] Read ${toLogLabel(options.cacheLabel)}`, options.describe(value));
@@ -7289,7 +7474,7 @@ function createJsonFileCacheStore(options) {
7289
7474
  if (writtenInCurrentProcess) {
7290
7475
  return true;
7291
7476
  }
7292
- return existsSync7(getCacheFilePath());
7477
+ return existsSync8(getCacheFilePath());
7293
7478
  }
7294
7479
  function write(value) {
7295
7480
  ensureCacheDir();
@@ -7321,7 +7506,7 @@ var init_json_file_cache_store = __esm(() => {
7321
7506
  });
7322
7507
 
7323
7508
  // src/shared/connected-providers-cache.ts
7324
- function isRecord(value) {
7509
+ function isRecord3(value) {
7325
7510
  return typeof value === "object" && value !== null;
7326
7511
  }
7327
7512
  function createConnectedProvidersCacheStore(getCacheDir2 = getOmoOpenCodeCacheDir) {
@@ -7388,7 +7573,7 @@ function createConnectedProvidersCacheStore(getCacheDir2 = getOmoOpenCodeCacheDi
7388
7573
  for (const provider of allProviders) {
7389
7574
  if (provider.models) {
7390
7575
  const modelMetadata = Object.entries(provider.models).map(([modelID, rawMetadata]) => {
7391
- if (!isRecord(rawMetadata)) {
7576
+ if (!isRecord3(rawMetadata)) {
7392
7577
  return { id: modelID };
7393
7578
  }
7394
7579
  const normalizedID = typeof rawMetadata.id === "string" ? rawMetadata.id : modelID;
@@ -7465,14 +7650,14 @@ var init_connected_providers_cache = __esm(() => {
7465
7650
  });
7466
7651
 
7467
7652
  // src/shared/model-availability.ts
7468
- import { existsSync as existsSync8, readFileSync as readFileSync5 } from "fs";
7469
- import { join as join9 } from "path";
7653
+ import { existsSync as existsSync9, readFileSync as readFileSync6 } from "fs";
7654
+ import { join as join10 } from "path";
7470
7655
  function isModelCacheAvailable() {
7471
7656
  if (hasProviderModelsCache()) {
7472
7657
  return true;
7473
7658
  }
7474
- const cacheFile = join9(getOpenCodeCacheDir(), "models.json");
7475
- return existsSync8(cacheFile);
7659
+ const cacheFile = join10(getOpenCodeCacheDir(), "models.json");
7660
+ return existsSync9(cacheFile);
7476
7661
  }
7477
7662
  var init_model_availability = __esm(() => {
7478
7663
  init_logger();
@@ -50000,20 +50185,19 @@ var init_model_capabilities_generated = __esm(() => {
50000
50185
  var SUPPLEMENTAL_MODEL_CAPABILITIES;
50001
50186
  var init_supplemental_entries = __esm(() => {
50002
50187
  SUPPLEMENTAL_MODEL_CAPABILITIES = {
50003
- "gpt-5.4-mini-fast": {
50004
- id: "gpt-5.4-mini-fast",
50005
- family: "gpt-mini",
50188
+ "kimi-k2.6": {
50189
+ id: "kimi-k2.6",
50190
+ family: "kimi",
50006
50191
  reasoning: true,
50007
- temperature: false,
50192
+ temperature: true,
50008
50193
  toolCall: true,
50009
50194
  modalities: {
50010
- input: ["text", "image"],
50195
+ input: ["text", "image", "video"],
50011
50196
  output: ["text"]
50012
50197
  },
50013
50198
  limit: {
50014
- context: 400000,
50015
- input: 272000,
50016
- output: 128000
50199
+ context: 262144,
50200
+ output: 262144
50017
50201
  }
50018
50202
  },
50019
50203
  "gpt-5.5": {
@@ -50031,6 +50215,22 @@ var init_supplemental_entries = __esm(() => {
50031
50215
  input: 272000,
50032
50216
  output: 128000
50033
50217
  }
50218
+ },
50219
+ "gpt-5.4-mini-fast": {
50220
+ id: "gpt-5.4-mini-fast",
50221
+ family: "gpt-mini",
50222
+ reasoning: true,
50223
+ temperature: false,
50224
+ toolCall: true,
50225
+ modalities: {
50226
+ input: ["text", "image"],
50227
+ output: ["text"]
50228
+ },
50229
+ limit: {
50230
+ context: 400000,
50231
+ input: 272000,
50232
+ output: 128000
50233
+ }
50034
50234
  }
50035
50235
  };
50036
50236
  });
@@ -50128,8 +50328,8 @@ var init_model_capability_aliases = __esm(() => {
50128
50328
  PATTERN_ALIAS_RULES = [
50129
50329
  {
50130
50330
  ruleID: "claude-thinking-legacy-alias",
50131
- description: "Normalizes legacy Claude Opus thinking suffixes (4-6, 4-7) to the canonical snapshot ID.",
50132
- match: (normalizedModelID) => /^claude-opus-4-(?:6|7)-thinking$/.test(normalizedModelID),
50331
+ description: "Normalizes the legacy claude-opus-4-7-thinking id to the canonical snapshot ID.",
50332
+ match: (normalizedModelID) => /^claude-opus-4-7-thinking$/.test(normalizedModelID),
50133
50333
  canonicalize: () => "claude-opus-4-7"
50134
50334
  },
50135
50335
  {
@@ -50179,7 +50379,7 @@ var init_model_capability_heuristics = __esm(() => {
50179
50379
  family: "gpt-5",
50180
50380
  includes: ["gpt-5"],
50181
50381
  variants: ["low", "medium", "high", "xhigh"],
50182
- reasoningEfforts: ["none", "minimal", "low", "medium", "high", "xhigh"]
50382
+ reasoningEfforts: ["none", "minimal", "low", "medium", "high", "xhigh", "max"]
50183
50383
  },
50184
50384
  {
50185
50385
  family: "gpt-legacy",
@@ -50218,7 +50418,13 @@ var init_model_capability_heuristics = __esm(() => {
50218
50418
  {
50219
50419
  family: "deepseek",
50220
50420
  includes: ["deepseek"],
50221
- variants: ["low", "medium", "high"]
50421
+ variants: ["low", "medium", "high"],
50422
+ reasoningEfforts: ["high", "max"],
50423
+ reasoningEffortAliases: {
50424
+ low: "high",
50425
+ medium: "high",
50426
+ xhigh: "max"
50427
+ }
50222
50428
  },
50223
50429
  {
50224
50430
  family: "mistral",
@@ -50234,7 +50440,7 @@ var init_model_capability_heuristics = __esm(() => {
50234
50440
  });
50235
50441
 
50236
50442
  // src/shared/model-capabilities/runtime-model-readers.ts
50237
- function isRecord2(value) {
50443
+ function isRecord4(value) {
50238
50444
  return typeof value === "object" && value !== null && !Array.isArray(value);
50239
50445
  }
50240
50446
  function readNumber(value) {
@@ -50252,7 +50458,7 @@ function normalizeVariantKeys(value) {
50252
50458
  if (arrayVariants) {
50253
50459
  return arrayVariants.map((variant) => variant.toLowerCase());
50254
50460
  }
50255
- if (!isRecord2(value)) {
50461
+ if (!isRecord4(value)) {
50256
50462
  return;
50257
50463
  }
50258
50464
  const variants = Object.keys(value).map((variant) => variant.toLowerCase());
@@ -50263,14 +50469,14 @@ function readModalityKeys(value) {
50263
50469
  if (stringArray) {
50264
50470
  return stringArray.map((entry) => entry.toLowerCase());
50265
50471
  }
50266
- if (!isRecord2(value)) {
50472
+ if (!isRecord4(value)) {
50267
50473
  return;
50268
50474
  }
50269
50475
  const enabled = Object.entries(value).filter(([, supported]) => supported === true).map(([modality]) => modality.toLowerCase());
50270
50476
  return enabled.length > 0 ? enabled : undefined;
50271
50477
  }
50272
50478
  function normalizeModalities(value) {
50273
- if (!isRecord2(value)) {
50479
+ if (!isRecord4(value)) {
50274
50480
  return;
50275
50481
  }
50276
50482
  const input = readModalityKeys(value.input);
@@ -50284,7 +50490,7 @@ function normalizeModalities(value) {
50284
50490
  };
50285
50491
  }
50286
50492
  function readRuntimeModelCapabilities(runtimeModel) {
50287
- return isRecord2(runtimeModel?.capabilities) ? runtimeModel.capabilities : undefined;
50493
+ return isRecord4(runtimeModel?.capabilities) ? runtimeModel.capabilities : undefined;
50288
50494
  }
50289
50495
  function readRuntimeModelBoolean(runtimeModel, keys) {
50290
50496
  const runtimeCapabilities = readRuntimeModelCapabilities(runtimeModel);
@@ -50301,7 +50507,7 @@ function readRuntimeModelBoolean(runtimeModel, keys) {
50301
50507
  return;
50302
50508
  }
50303
50509
  function readRuntimeModel(runtimeModel) {
50304
- return isRecord2(runtimeModel) ? runtimeModel : undefined;
50510
+ return isRecord4(runtimeModel) ? runtimeModel : undefined;
50305
50511
  }
50306
50512
  function readRuntimeModelVariants(runtimeModel) {
50307
50513
  const rootVariants = normalizeVariantKeys(runtimeModel?.variants);
@@ -50349,8 +50555,8 @@ function readRuntimeModelToolCallSupport(runtimeModel) {
50349
50555
  return readRuntimeModelBoolean(runtimeModel, ["toolCall", "tool_call", "toolcall"]);
50350
50556
  }
50351
50557
  function readRuntimeModelLimitOutput(runtimeModel) {
50352
- const limit = isRecord2(runtimeModel?.limit) ? runtimeModel.limit : readRuntimeModelCapabilities(runtimeModel)?.limit;
50353
- if (!isRecord2(limit)) {
50558
+ const limit = isRecord4(runtimeModel?.limit) ? runtimeModel.limit : readRuntimeModelCapabilities(runtimeModel)?.limit;
50559
+ if (!isRecord4(limit)) {
50354
50560
  return;
50355
50561
  }
50356
50562
  return readNumber(limit.output);
@@ -50440,7 +50646,7 @@ var init_model_capabilities = __esm(() => {
50440
50646
  });
50441
50647
 
50442
50648
  // src/shared/model-capabilities-cache.ts
50443
- function isRecord3(value) {
50649
+ function isRecord5(value) {
50444
50650
  return typeof value === "object" && value !== null && !Array.isArray(value);
50445
50651
  }
50446
50652
  function readBoolean(value) {
@@ -50460,7 +50666,7 @@ function readStringArray2(value) {
50460
50666
  return result.length > 0 ? result : undefined;
50461
50667
  }
50462
50668
  function normalizeSnapshotEntry(rawModelID, rawModel) {
50463
- if (!isRecord3(rawModel)) {
50669
+ if (!isRecord5(rawModel)) {
50464
50670
  return;
50465
50671
  }
50466
50672
  const id = readString(rawModel.id) ?? rawModelID;
@@ -50468,14 +50674,14 @@ function normalizeSnapshotEntry(rawModelID, rawModel) {
50468
50674
  const reasoning = readBoolean(rawModel.reasoning);
50469
50675
  const temperature = readBoolean(rawModel.temperature);
50470
50676
  const toolCall = readBoolean(rawModel.tool_call);
50471
- const rawModalities = isRecord3(rawModel.modalities) ? rawModel.modalities : undefined;
50677
+ const rawModalities = isRecord5(rawModel.modalities) ? rawModel.modalities : undefined;
50472
50678
  const modalitiesInput = readStringArray2(rawModalities?.input);
50473
50679
  const modalitiesOutput = readStringArray2(rawModalities?.output);
50474
50680
  const modalities = modalitiesInput || modalitiesOutput ? {
50475
50681
  ...modalitiesInput ? { input: modalitiesInput } : {},
50476
50682
  ...modalitiesOutput ? { output: modalitiesOutput } : {}
50477
50683
  } : undefined;
50478
- const rawLimit = isRecord3(rawModel.limit) ? rawModel.limit : undefined;
50684
+ const rawLimit = isRecord5(rawModel.limit) ? rawModel.limit : undefined;
50479
50685
  const limitContext = readNumber2(rawLimit?.context);
50480
50686
  const limitInput = readNumber2(rawLimit?.input);
50481
50687
  const limitOutput = readNumber2(rawLimit?.output);
@@ -50515,13 +50721,13 @@ function mergeSnapshotEntries(existing, incoming) {
50515
50721
  }
50516
50722
  function buildModelCapabilitiesSnapshotFromModelsDev(raw) {
50517
50723
  const models = {};
50518
- const providers = isRecord3(raw) ? raw : {};
50724
+ const providers = isRecord5(raw) ? raw : {};
50519
50725
  for (const providerValue of Object.values(providers)) {
50520
- if (!isRecord3(providerValue)) {
50726
+ if (!isRecord5(providerValue)) {
50521
50727
  continue;
50522
50728
  }
50523
50729
  const providerModels = providerValue.models;
50524
- if (!isRecord3(providerModels)) {
50730
+ if (!isRecord5(providerModels)) {
50525
50731
  continue;
50526
50732
  }
50527
50733
  for (const [rawModelID, rawModel] of Object.entries(providerModels)) {
@@ -50617,19 +50823,19 @@ var init_constants = __esm(() => {
50617
50823
  });
50618
50824
 
50619
50825
  // src/shared/opencode-storage-paths.ts
50620
- import { join as join10 } from "path";
50826
+ import { join as join11 } from "path";
50621
50827
  var OPENCODE_STORAGE, MESSAGE_STORAGE, PART_STORAGE, SESSION_STORAGE;
50622
50828
  var init_opencode_storage_paths = __esm(() => {
50623
50829
  init_data_path();
50624
50830
  OPENCODE_STORAGE = getOpenCodeStorageDir();
50625
- MESSAGE_STORAGE = join10(OPENCODE_STORAGE, "message");
50626
- PART_STORAGE = join10(OPENCODE_STORAGE, "part");
50627
- SESSION_STORAGE = join10(OPENCODE_STORAGE, "session");
50831
+ MESSAGE_STORAGE = join11(OPENCODE_STORAGE, "message");
50832
+ PART_STORAGE = join11(OPENCODE_STORAGE, "part");
50833
+ SESSION_STORAGE = join11(OPENCODE_STORAGE, "session");
50628
50834
  });
50629
50835
 
50630
50836
  // src/shared/compaction-marker.ts
50631
- import { existsSync as existsSync9, readdirSync, readFileSync as readFileSync6 } from "fs";
50632
- import { join as join11 } from "path";
50837
+ import { existsSync as existsSync10, readdirSync, readFileSync as readFileSync7 } from "fs";
50838
+ import { join as join12 } from "path";
50633
50839
  function isCompactionPart(part) {
50634
50840
  return typeof part === "object" && part !== null && part.type === "compaction";
50635
50841
  }
@@ -50643,20 +50849,20 @@ function isCompactionMessage(message) {
50643
50849
  return isCompactionAgent(message.info?.agent ?? message.agent) || hasCompactionPart(message.parts);
50644
50850
  }
50645
50851
  function getCompactionPartStorageDir(messageID) {
50646
- return join11(PART_STORAGE, messageID);
50852
+ return join12(PART_STORAGE, messageID);
50647
50853
  }
50648
50854
  function hasCompactionPartInStorage(messageID) {
50649
50855
  if (!messageID) {
50650
50856
  return false;
50651
50857
  }
50652
50858
  const partDir = getCompactionPartStorageDir(messageID);
50653
- if (!existsSync9(partDir)) {
50859
+ if (!existsSync10(partDir)) {
50654
50860
  return false;
50655
50861
  }
50656
50862
  try {
50657
50863
  return readdirSync(partDir).filter((fileName) => fileName.endsWith(".json")).some((fileName) => {
50658
50864
  try {
50659
- const content = readFileSync6(join11(partDir, fileName), "utf-8");
50865
+ const content = readFileSync7(join12(partDir, fileName), "utf-8");
50660
50866
  return isCompactionPart(JSON.parse(content));
50661
50867
  } catch {
50662
50868
  return false;
@@ -50689,23 +50895,23 @@ var init_hook_message_injector = __esm(() => {
50689
50895
  });
50690
50896
 
50691
50897
  // src/shared/opencode-message-dir.ts
50692
- import { existsSync as existsSync10, readdirSync as readdirSync2 } from "fs";
50693
- import { join as join12 } from "path";
50898
+ import { existsSync as existsSync11, readdirSync as readdirSync2 } from "fs";
50899
+ import { join as join13 } from "path";
50694
50900
  function getMessageDir(sessionID) {
50695
50901
  if (!sessionID.startsWith("ses_"))
50696
50902
  return null;
50697
50903
  if (/[/\\]|\.\./.test(sessionID))
50698
50904
  return null;
50699
- if (!existsSync10(MESSAGE_STORAGE))
50905
+ if (!existsSync11(MESSAGE_STORAGE))
50700
50906
  return null;
50701
- const directPath = join12(MESSAGE_STORAGE, sessionID);
50702
- if (existsSync10(directPath)) {
50907
+ const directPath = join13(MESSAGE_STORAGE, sessionID);
50908
+ if (existsSync11(directPath)) {
50703
50909
  return directPath;
50704
50910
  }
50705
50911
  try {
50706
50912
  for (const dir of readdirSync2(MESSAGE_STORAGE)) {
50707
- const sessionPath = join12(MESSAGE_STORAGE, dir, sessionID);
50708
- if (existsSync10(sessionPath)) {
50913
+ const sessionPath = join13(MESSAGE_STORAGE, dir, sessionID);
50914
+ if (existsSync11(sessionPath)) {
50709
50915
  return sessionPath;
50710
50916
  }
50711
50917
  }
@@ -50728,10 +50934,18 @@ var init_session_utils = __esm(() => {
50728
50934
  init_logger();
50729
50935
  init_agent_display_names();
50730
50936
  });
50937
+
50938
+ // src/shared/event-session-id.ts
50939
+ var init_event_session_id = () => {};
50731
50940
  // src/shared/tmux/constants.ts
50732
- var SESSION_TIMEOUT_MS;
50941
+ var SESSION_TIMEOUT_MS, SESSION_MISSING_GRACE_MS;
50733
50942
  var init_constants2 = __esm(() => {
50734
- SESSION_TIMEOUT_MS = 10 * 60 * 1000;
50943
+ SESSION_TIMEOUT_MS = 60 * 60 * 1000;
50944
+ SESSION_MISSING_GRACE_MS = 30 * 1000;
50945
+ });
50946
+ // src/shared/tmux/runner.ts
50947
+ var init_runner = __esm(() => {
50948
+ init_bun_spawn_shim();
50735
50949
  });
50736
50950
  // src/shared/tmux/tmux-utils/server-health.ts
50737
50951
  var SERVER_RUNNING_KEY;
@@ -50746,32 +50960,27 @@ var init_tmux_path_resolver = __esm(() => {
50746
50960
 
50747
50961
  // src/shared/tmux/tmux-utils/pane-dimensions.ts
50748
50962
  var init_pane_dimensions = __esm(() => {
50749
- init_bun_spawn_shim();
50750
50963
  init_tmux_path_resolver();
50751
50964
  });
50752
50965
 
50753
50966
  // src/shared/tmux/tmux-utils/pane-spawn.ts
50754
50967
  var init_pane_spawn = __esm(() => {
50755
- init_bun_spawn_shim();
50756
50968
  init_tmux_path_resolver();
50757
50969
  init_server_health();
50758
50970
  });
50759
50971
  // src/shared/tmux/tmux-utils/pane-replace.ts
50760
50972
  var init_pane_replace = __esm(() => {
50761
- init_bun_spawn_shim();
50762
50973
  init_tmux_path_resolver();
50763
50974
  });
50764
50975
 
50765
50976
  // src/shared/tmux/tmux-utils/window-spawn.ts
50766
50977
  var init_window_spawn = __esm(() => {
50767
- init_bun_spawn_shim();
50768
50978
  init_tmux_path_resolver();
50769
50979
  init_server_health();
50770
50980
  });
50771
50981
 
50772
50982
  // src/shared/tmux/tmux-utils/session-spawn.ts
50773
50983
  var init_session_spawn = __esm(() => {
50774
- init_bun_spawn_shim();
50775
50984
  init_tmux_path_resolver();
50776
50985
  init_server_health();
50777
50986
  });
@@ -50780,7 +50989,6 @@ var init_stale_session_sweep = () => {};
50780
50989
 
50781
50990
  // src/shared/tmux/tmux-utils/layout.ts
50782
50991
  var init_layout = __esm(() => {
50783
- init_bun_spawn_shim();
50784
50992
  init_tmux_path_resolver();
50785
50993
  });
50786
50994
 
@@ -50799,6 +51007,7 @@ var init_tmux_utils = __esm(() => {
50799
51007
  // src/shared/tmux/index.ts
50800
51008
  var init_tmux = __esm(() => {
50801
51009
  init_constants2();
51010
+ init_runner();
50802
51011
  init_tmux_utils();
50803
51012
  });
50804
51013
  // src/shared/model-suggestion-retry.ts
@@ -50816,7 +51025,7 @@ function getServerBasicAuthHeader() {
50816
51025
  const token = Buffer.from(`${username}:${password}`, "utf8").toString("base64");
50817
51026
  return `Basic ${token}`;
50818
51027
  }
50819
- function isRecord4(value) {
51028
+ function isRecord6(value) {
50820
51029
  return typeof value === "object" && value !== null;
50821
51030
  }
50822
51031
  function isRequestFetch(value) {
@@ -50830,11 +51039,11 @@ function wrapRequestFetch(baseFetch, auth) {
50830
51039
  };
50831
51040
  }
50832
51041
  function getInternalClient(client) {
50833
- if (!isRecord4(client)) {
51042
+ if (!isRecord6(client)) {
50834
51043
  return null;
50835
51044
  }
50836
51045
  const internal = client["_client"];
50837
- return isRecord4(internal) ? internal : null;
51046
+ return isRecord6(internal) ? internal : null;
50838
51047
  }
50839
51048
  function tryInjectViaSetConfigHeaders(internal, auth) {
50840
51049
  const setConfig = internal["setConfig"];
@@ -50850,11 +51059,11 @@ function tryInjectViaSetConfigHeaders(internal, auth) {
50850
51059
  }
50851
51060
  function tryInjectViaInterceptors(internal, auth) {
50852
51061
  const interceptors = internal["interceptors"];
50853
- if (!isRecord4(interceptors)) {
51062
+ if (!isRecord6(interceptors)) {
50854
51063
  return false;
50855
51064
  }
50856
51065
  const requestInterceptors = interceptors["request"];
50857
- if (!isRecord4(requestInterceptors)) {
51066
+ if (!isRecord6(requestInterceptors)) {
50858
51067
  return false;
50859
51068
  }
50860
51069
  const use = requestInterceptors["use"];
@@ -50876,7 +51085,7 @@ function tryInjectViaFetchWrapper(internal, auth) {
50876
51085
  return false;
50877
51086
  }
50878
51087
  const config = getConfig();
50879
- if (!isRecord4(config)) {
51088
+ if (!isRecord6(config)) {
50880
51089
  return false;
50881
51090
  }
50882
51091
  const fetchValue = config["fetch"];
@@ -50890,7 +51099,7 @@ function tryInjectViaFetchWrapper(internal, auth) {
50890
51099
  }
50891
51100
  function tryInjectViaMutableInternalConfig(internal, auth) {
50892
51101
  const configValue = internal["_config"];
50893
- if (!isRecord4(configValue)) {
51102
+ if (!isRecord6(configValue)) {
50894
51103
  return false;
50895
51104
  }
50896
51105
  const fetchValue = configValue["fetch"];
@@ -50901,7 +51110,7 @@ function tryInjectViaMutableInternalConfig(internal, auth) {
50901
51110
  return true;
50902
51111
  }
50903
51112
  function tryInjectViaTopLevelFetch(client, auth) {
50904
- if (!isRecord4(client)) {
51113
+ if (!isRecord6(client)) {
50905
51114
  return false;
50906
51115
  }
50907
51116
  const fetchValue = client["fetch"];
@@ -50949,6 +51158,7 @@ var init_opencode_provider_auth = __esm(() => {
50949
51158
  init_data_path();
50950
51159
  init_logger();
50951
51160
  });
51161
+
50952
51162
  // src/shared/opencode-http-api.ts
50953
51163
  var init_opencode_http_api = __esm(() => {
50954
51164
  init_opencode_server_auth();
@@ -50956,18 +51166,46 @@ var init_opencode_http_api = __esm(() => {
50956
51166
  });
50957
51167
 
50958
51168
  // src/shared/port-utils.ts
51169
+ import { createServer } from "net";
50959
51170
  async function isPortAvailable(port, hostname = "127.0.0.1") {
50960
- try {
50961
- const server = Bun.serve({
50962
- port,
50963
- hostname,
50964
- fetch: () => new Response
51171
+ return new Promise((resolve4) => {
51172
+ const server = createServer();
51173
+ let timeoutId;
51174
+ let resolved = false;
51175
+ const finish = (isAvailable) => {
51176
+ if (resolved) {
51177
+ return;
51178
+ }
51179
+ resolved = true;
51180
+ if (timeoutId) {
51181
+ clearTimeout(timeoutId);
51182
+ }
51183
+ server.removeAllListeners("error");
51184
+ server.removeAllListeners("listening");
51185
+ resolve4(isAvailable);
51186
+ };
51187
+ const closeThenFinish = (isAvailable) => {
51188
+ try {
51189
+ server.close(() => finish(isAvailable));
51190
+ } catch {
51191
+ finish(isAvailable);
51192
+ }
51193
+ };
51194
+ timeoutId = setTimeout(() => {
51195
+ closeThenFinish(false);
51196
+ }, PORT_CHECK_TIMEOUT_MS);
51197
+ server.once("error", () => {
51198
+ finish(false);
50965
51199
  });
50966
- server.stop(true);
50967
- return true;
50968
- } catch {
50969
- return false;
50970
- }
51200
+ server.once("listening", () => {
51201
+ closeThenFinish(true);
51202
+ });
51203
+ try {
51204
+ server.listen(port, hostname);
51205
+ } catch {
51206
+ finish(false);
51207
+ }
51208
+ });
50971
51209
  }
50972
51210
  async function findAvailablePort(startPort = DEFAULT_SERVER_PORT, hostname = "127.0.0.1") {
50973
51211
  for (let attempt = 0;attempt < MAX_PORT_ATTEMPTS; attempt++) {
@@ -50985,7 +51223,7 @@ async function getAvailableServerPort(preferredPort = DEFAULT_SERVER_PORT, hostn
50985
51223
  const port = await findAvailablePort(preferredPort + 1, hostname);
50986
51224
  return { port, wasAutoSelected: true };
50987
51225
  }
50988
- var DEFAULT_SERVER_PORT = 4096, MAX_PORT_ATTEMPTS = 20;
51226
+ var DEFAULT_SERVER_PORT = 4096, MAX_PORT_ATTEMPTS = 20, PORT_CHECK_TIMEOUT_MS = 2000;
50989
51227
  var init_port_utils = () => {};
50990
51228
  // src/shared/git-worktree/parse-status-porcelain.ts
50991
51229
  var init_parse_status_porcelain = () => {};
@@ -51009,14 +51247,57 @@ var init_opencode_command_dirs = __esm(() => {
51009
51247
  });
51010
51248
 
51011
51249
  // src/shared/project-discovery-dirs.ts
51250
+ import { existsSync as existsSync12, realpathSync as realpathSync5 } from "fs";
51251
+ import { dirname as dirname4, join as join14, resolve as resolve4 } from "path";
51252
+ function normalizePath(path6) {
51253
+ const resolvedPath = resolve4(path6);
51254
+ if (!existsSync12(resolvedPath)) {
51255
+ return resolvedPath;
51256
+ }
51257
+ try {
51258
+ return realpathSync5(resolvedPath);
51259
+ } catch {
51260
+ return resolvedPath;
51261
+ }
51262
+ }
51263
+ function findProjectOpencodePluginConfigFiles(startDirectory, stopDirectory) {
51264
+ const paths = [];
51265
+ const seen = new Set;
51266
+ let currentDirectory = normalizePath(startDirectory);
51267
+ const resolvedStopDirectory = stopDirectory ? normalizePath(stopDirectory) : undefined;
51268
+ while (true) {
51269
+ const opencodeDirectory = join14(currentDirectory, ".opencode");
51270
+ if (existsSync12(opencodeDirectory)) {
51271
+ const detected = detectPluginConfigFile(opencodeDirectory);
51272
+ if (detected.format !== "none" && !seen.has(detected.path)) {
51273
+ seen.add(detected.path);
51274
+ paths.push(detected.path);
51275
+ }
51276
+ }
51277
+ if (resolvedStopDirectory === currentDirectory) {
51278
+ return paths;
51279
+ }
51280
+ const parentDirectory = dirname4(currentDirectory);
51281
+ if (parentDirectory === currentDirectory) {
51282
+ return paths;
51283
+ }
51284
+ currentDirectory = normalizePath(parentDirectory);
51285
+ }
51286
+ }
51012
51287
  var worktreePathCache;
51013
51288
  var init_project_discovery_dirs = __esm(() => {
51289
+ init_jsonc_parser();
51014
51290
  worktreePathCache = new Map;
51015
51291
  });
51016
51292
 
51017
51293
  // src/shared/session-directory-resolver.ts
51018
51294
  var init_session_directory_resolver = () => {};
51019
51295
 
51296
+ // src/shared/session-route.ts
51297
+ var init_session_route = __esm(() => {
51298
+ init_model_suggestion_retry();
51299
+ });
51300
+
51020
51301
  // src/shared/session-tools-store.ts
51021
51302
  var store;
51022
51303
  var init_session_tools_store = __esm(() => {
@@ -51103,6 +51384,7 @@ var init_mcp_server_loader = __esm(() => {
51103
51384
  init_scope_filter2();
51104
51385
  init_transformer();
51105
51386
  init_logger();
51387
+ init_bun_file_shim();
51106
51388
  });
51107
51389
 
51108
51390
  // src/features/claude-code-plugin-loader/hook-loader.ts
@@ -51264,6 +51546,7 @@ var init_shared = __esm(() => {
51264
51546
  init_connected_providers_cache();
51265
51547
  init_context_limit_resolver();
51266
51548
  init_session_utils();
51549
+ init_event_session_id();
51267
51550
  init_tmux();
51268
51551
  init_model_suggestion_retry();
51269
51552
  init_opencode_server_auth();
@@ -51277,6 +51560,7 @@ var init_shared = __esm(() => {
51277
51560
  init_opencode_command_dirs();
51278
51561
  init_project_discovery_dirs();
51279
51562
  init_session_directory_resolver();
51563
+ init_session_route();
51280
51564
  init_prompt_tools();
51281
51565
  init_compaction_marker();
51282
51566
  init_internal_initiator_marker();
@@ -51362,17 +51646,17 @@ var init_plugin_name_with_version = __esm(() => {
51362
51646
  });
51363
51647
 
51364
51648
  // src/cli/config-manager/backup-config.ts
51365
- import { copyFileSync as copyFileSync2, existsSync as existsSync11, mkdirSync as mkdirSync5 } from "fs";
51366
- import { dirname as dirname3 } from "path";
51649
+ import { copyFileSync as copyFileSync2, existsSync as existsSync13, mkdirSync as mkdirSync5 } from "fs";
51650
+ import { dirname as dirname5 } from "path";
51367
51651
  function backupConfigFile(configPath) {
51368
- if (!existsSync11(configPath)) {
51652
+ if (!existsSync13(configPath)) {
51369
51653
  return { success: true };
51370
51654
  }
51371
51655
  const timestamp2 = new Date().toISOString().replace(/[:.]/g, "-");
51372
51656
  const backupPath = `${configPath}.backup-${timestamp2}`;
51373
51657
  try {
51374
- const dir = dirname3(backupPath);
51375
- if (!existsSync11(dir)) {
51658
+ const dir = dirname5(backupPath);
51659
+ if (!existsSync13(dir)) {
51376
51660
  mkdirSync5(dir, { recursive: true });
51377
51661
  }
51378
51662
  copyFileSync2(configPath, backupPath);
@@ -51387,10 +51671,10 @@ function backupConfigFile(configPath) {
51387
51671
  var init_backup_config = () => {};
51388
51672
 
51389
51673
  // src/cli/config-manager/ensure-config-directory-exists.ts
51390
- import { existsSync as existsSync12, mkdirSync as mkdirSync6 } from "fs";
51674
+ import { existsSync as existsSync14, mkdirSync as mkdirSync6 } from "fs";
51391
51675
  function ensureConfigDirectoryExists() {
51392
51676
  const configDir = getConfigDir();
51393
- if (!existsSync12(configDir)) {
51677
+ if (!existsSync14(configDir)) {
51394
51678
  mkdirSync6(configDir, { recursive: true });
51395
51679
  }
51396
51680
  }
@@ -51428,14 +51712,14 @@ function formatErrorWithSuggestion(err, context) {
51428
51712
  }
51429
51713
 
51430
51714
  // src/cli/config-manager/opencode-config-format.ts
51431
- import { existsSync as existsSync13 } from "fs";
51715
+ import { existsSync as existsSync15 } from "fs";
51432
51716
  function detectConfigFormat() {
51433
51717
  const configJsonc = getConfigJsonc();
51434
51718
  const configJson = getConfigJson();
51435
- if (existsSync13(configJsonc)) {
51719
+ if (existsSync15(configJsonc)) {
51436
51720
  return { format: "jsonc", path: configJsonc };
51437
51721
  }
51438
- if (existsSync13(configJson)) {
51722
+ if (existsSync15(configJson)) {
51439
51723
  return { format: "json", path: configJson };
51440
51724
  }
51441
51725
  return { format: "none", path: configJson };
@@ -51445,33 +51729,33 @@ var init_opencode_config_format = __esm(() => {
51445
51729
  });
51446
51730
 
51447
51731
  // src/cli/config-manager/parse-opencode-config-file.ts
51448
- import { readFileSync as readFileSync7, statSync } from "fs";
51732
+ import { readFileSync as readFileSync8, statSync } from "fs";
51449
51733
  function isEmptyOrWhitespace(content) {
51450
51734
  return content.trim().length === 0;
51451
51735
  }
51452
- function parseOpenCodeConfigFileWithError(path5) {
51736
+ function parseOpenCodeConfigFileWithError(path6) {
51453
51737
  try {
51454
- const stat = statSync(path5);
51738
+ const stat = statSync(path6);
51455
51739
  if (stat.size === 0) {
51456
- return { config: null, error: `Config file is empty: ${path5}. Delete it or add valid JSON content.` };
51740
+ return { config: null, error: `Config file is empty: ${path6}. Delete it or add valid JSON content.` };
51457
51741
  }
51458
- const content = readFileSync7(path5, "utf-8");
51742
+ const content = readFileSync8(path6, "utf-8");
51459
51743
  if (isEmptyOrWhitespace(content)) {
51460
- return { config: null, error: `Config file contains only whitespace: ${path5}. Delete it or add valid JSON content.` };
51744
+ return { config: null, error: `Config file contains only whitespace: ${path6}. Delete it or add valid JSON content.` };
51461
51745
  }
51462
51746
  const config = parseJsonc(content);
51463
51747
  if (config == null) {
51464
- return { config: null, error: `Config file parsed to null/undefined: ${path5}. Ensure it contains valid JSON.` };
51748
+ return { config: null, error: `Config file parsed to null/undefined: ${path6}. Ensure it contains valid JSON.` };
51465
51749
  }
51466
51750
  if (typeof config !== "object" || Array.isArray(config)) {
51467
51751
  return {
51468
51752
  config: null,
51469
- error: `Config file must contain a JSON object, not ${Array.isArray(config) ? "an array" : typeof config}: ${path5}`
51753
+ error: `Config file must contain a JSON object, not ${Array.isArray(config) ? "an array" : typeof config}: ${path6}`
51470
51754
  };
51471
51755
  }
51472
51756
  return { config };
51473
51757
  } catch (err) {
51474
- return { config: null, error: formatErrorWithSuggestion(err, `parse config file ${path5}`) };
51758
+ return { config: null, error: formatErrorWithSuggestion(err, `parse config file ${path6}`) };
51475
51759
  }
51476
51760
  }
51477
51761
  var init_parse_opencode_config_file = __esm(() => {
@@ -51561,7 +51845,7 @@ function extractVersionFromPluginEntry(entry) {
51561
51845
  }
51562
51846
 
51563
51847
  // src/cli/config-manager/add-plugin-to-opencode-config.ts
51564
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync3 } from "fs";
51848
+ import { readFileSync as readFileSync9, writeFileSync as writeFileSync3 } from "fs";
51565
51849
  async function addPluginToOpenCodeConfig(currentVersion) {
51566
51850
  try {
51567
51851
  ensureConfigDirectoryExists();
@@ -51572,20 +51856,20 @@ async function addPluginToOpenCodeConfig(currentVersion) {
51572
51856
  error: formatErrorWithSuggestion(err, "create config directory")
51573
51857
  };
51574
51858
  }
51575
- const { format: format2, path: path5 } = detectConfigFormat();
51859
+ const { format: format2, path: path6 } = detectConfigFormat();
51576
51860
  const pluginEntry = await getPluginNameWithVersion(currentVersion, PLUGIN_NAME);
51577
51861
  try {
51578
51862
  if (format2 === "none") {
51579
51863
  const config2 = { plugin: [pluginEntry] };
51580
- writeFileSync3(path5, JSON.stringify(config2, null, 2) + `
51864
+ writeFileSync3(path6, JSON.stringify(config2, null, 2) + `
51581
51865
  `);
51582
- return { success: true, configPath: path5 };
51866
+ return { success: true, configPath: path6 };
51583
51867
  }
51584
- const parseResult = parseOpenCodeConfigFileWithError(path5);
51868
+ const parseResult = parseOpenCodeConfigFileWithError(path6);
51585
51869
  if (!parseResult.config) {
51586
51870
  return {
51587
51871
  success: false,
51588
- configPath: path5,
51872
+ configPath: path6,
51589
51873
  error: parseResult.error ?? "Failed to parse config file"
51590
51874
  };
51591
51875
  }
@@ -51601,15 +51885,15 @@ async function addPluginToOpenCodeConfig(currentVersion) {
51601
51885
  if (!compatibility.canUpgrade) {
51602
51886
  return {
51603
51887
  success: false,
51604
- configPath: path5,
51888
+ configPath: path6,
51605
51889
  error: compatibility.reason ?? "Version compatibility check failed"
51606
51890
  };
51607
51891
  }
51608
- const backupResult = backupConfigFile(path5);
51892
+ const backupResult = backupConfigFile(path6);
51609
51893
  if (!backupResult.success) {
51610
51894
  return {
51611
51895
  success: false,
51612
- configPath: path5,
51896
+ configPath: path6,
51613
51897
  error: `Failed to create backup: ${backupResult.error}`
51614
51898
  };
51615
51899
  }
@@ -51618,7 +51902,7 @@ async function addPluginToOpenCodeConfig(currentVersion) {
51618
51902
  normalizedPlugins.push(pluginEntry);
51619
51903
  config.plugin = normalizedPlugins;
51620
51904
  if (format2 === "jsonc") {
51621
- const content = readFileSync8(path5, "utf-8");
51905
+ const content = readFileSync9(path6, "utf-8");
51622
51906
  const pluginArrayRegex = /((?:"plugin"|plugin)\s*:\s*)\[([\s\S]*?)\]/;
51623
51907
  const match = content.match(pluginArrayRegex);
51624
51908
  if (match) {
@@ -51627,21 +51911,21 @@ async function addPluginToOpenCodeConfig(currentVersion) {
51627
51911
  const newContent = content.replace(pluginArrayRegex, `$1[
51628
51912
  ${formattedPlugins}
51629
51913
  ]`);
51630
- writeFileSync3(path5, newContent);
51914
+ writeFileSync3(path6, newContent);
51631
51915
  } else {
51632
51916
  const newContent = content.replace(/(\{)/, `$1
51633
51917
  "plugin": ["${pluginEntry}"],`);
51634
- writeFileSync3(path5, newContent);
51918
+ writeFileSync3(path6, newContent);
51635
51919
  }
51636
51920
  } else {
51637
- writeFileSync3(path5, JSON.stringify(config, null, 2) + `
51921
+ writeFileSync3(path6, JSON.stringify(config, null, 2) + `
51638
51922
  `);
51639
51923
  }
51640
- return { success: true, configPath: path5 };
51924
+ return { success: true, configPath: path6 };
51641
51925
  } catch (err) {
51642
51926
  return {
51643
51927
  success: false,
51644
- configPath: path5,
51928
+ configPath: path6,
51645
51929
  error: formatErrorWithSuggestion(err, "update opencode config")
51646
51930
  };
51647
51931
  }
@@ -51878,7 +52162,7 @@ function generateModelConfig(config) {
51878
52162
  if (avail.native.openai) {
51879
52163
  agentConfig = { model: "openai/gpt-5.4-mini-fast" };
51880
52164
  } else if (avail.opencodeGo) {
51881
- agentConfig = { model: "opencode-go/minimax-m2.7" };
52165
+ agentConfig = { model: "opencode-go/qwen3.5-plus" };
51882
52166
  } else if (avail.zai) {
51883
52167
  agentConfig = { model: ZAI_MODEL };
51884
52168
  } else if (avail.vercelAiGateway) {
@@ -51898,7 +52182,7 @@ function generateModelConfig(config) {
51898
52182
  } else if (avail.opencodeZen) {
51899
52183
  agentConfig = { model: "opencode/claude-haiku-4-5" };
51900
52184
  } else if (avail.opencodeGo) {
51901
- agentConfig = { model: "opencode-go/minimax-m2.7" };
52185
+ agentConfig = { model: "opencode-go/qwen3.5-plus" };
51902
52186
  } else if (avail.copilot) {
51903
52187
  agentConfig = { model: "github-copilot/gpt-5-mini" };
51904
52188
  } else if (avail.vercelAiGateway) {
@@ -51978,12 +52262,12 @@ var init_generate_omo_config = __esm(() => {
51978
52262
  });
51979
52263
 
51980
52264
  // src/shared/migrate-legacy-config-file.ts
51981
- import { existsSync as existsSync14, readFileSync as readFileSync9, renameSync as renameSync2, rmSync } from "fs";
51982
- import { join as join13, dirname as dirname4, basename as basename2 } from "path";
52265
+ import { existsSync as existsSync16, readFileSync as readFileSync10, renameSync as renameSync2, rmSync } from "fs";
52266
+ import { join as join15, dirname as dirname6, basename as basename2 } from "path";
51983
52267
  function buildCanonicalPath(legacyPath) {
51984
- const dir = dirname4(legacyPath);
52268
+ const dir = dirname6(legacyPath);
51985
52269
  const ext = basename2(legacyPath).includes(".jsonc") ? ".jsonc" : ".json";
51986
- return join13(dir, `${CONFIG_BASENAME}${ext}`);
52270
+ return join15(dir, `${CONFIG_BASENAME}${ext}`);
51987
52271
  }
51988
52272
  function archiveLegacyConfigFile(legacyPath) {
51989
52273
  const backupPath = `${legacyPath}.bak`;
@@ -52016,13 +52300,13 @@ function archiveLegacyConfigFile(legacyPath) {
52016
52300
  }
52017
52301
  function migrateLegacySidecarFile(legacyPath, canonicalPath) {
52018
52302
  const legacySidecarPath = getSidecarPath(legacyPath);
52019
- if (!existsSync14(legacySidecarPath))
52303
+ if (!existsSync16(legacySidecarPath))
52020
52304
  return true;
52021
52305
  const canonicalSidecarPath = getSidecarPath(canonicalPath);
52022
- if (existsSync14(canonicalSidecarPath))
52306
+ if (existsSync16(canonicalSidecarPath))
52023
52307
  return true;
52024
52308
  try {
52025
- const content = readFileSync9(legacySidecarPath, "utf-8");
52309
+ const content = readFileSync10(legacySidecarPath, "utf-8");
52026
52310
  writeFileAtomically(canonicalSidecarPath, content);
52027
52311
  log("[migrateLegacyConfigFile] Migrated legacy migration sidecar to canonical path", {
52028
52312
  from: legacySidecarPath,
@@ -52039,15 +52323,15 @@ function migrateLegacySidecarFile(legacyPath, canonicalPath) {
52039
52323
  }
52040
52324
  }
52041
52325
  function migrateLegacyConfigFile(legacyPath) {
52042
- if (!existsSync14(legacyPath))
52326
+ if (!existsSync16(legacyPath))
52043
52327
  return false;
52044
52328
  if (!basename2(legacyPath).startsWith(LEGACY_CONFIG_BASENAME))
52045
52329
  return false;
52046
52330
  const canonicalPath = buildCanonicalPath(legacyPath);
52047
- if (existsSync14(canonicalPath))
52331
+ if (existsSync16(canonicalPath))
52048
52332
  return false;
52049
52333
  try {
52050
- const content = readFileSync9(legacyPath, "utf-8");
52334
+ const content = readFileSync10(legacyPath, "utf-8");
52051
52335
  writeFileAtomically(canonicalPath, content);
52052
52336
  const migratedSidecar = migrateLegacySidecarFile(legacyPath, canonicalPath);
52053
52337
  const archivedLegacyConfig = archiveLegacyConfigFile(legacyPath);
@@ -52088,8 +52372,8 @@ function deepMergeRecord(target, source) {
52088
52372
  }
52089
52373
 
52090
52374
  // src/cli/config-manager/write-omo-config.ts
52091
- import { existsSync as existsSync15, readFileSync as readFileSync10, statSync as statSync2, writeFileSync as writeFileSync4 } from "fs";
52092
- import { basename as basename3, dirname as dirname5, extname, join as join14 } from "path";
52375
+ import { existsSync as existsSync17, readFileSync as readFileSync11, statSync as statSync2, writeFileSync as writeFileSync4 } from "fs";
52376
+ import { basename as basename3, dirname as dirname7, extname, join as join16 } from "path";
52093
52377
  function isEmptyOrWhitespace2(content) {
52094
52378
  return content.trim().length === 0;
52095
52379
  }
@@ -52104,12 +52388,12 @@ function writeOmoConfig(installConfig) {
52104
52388
  };
52105
52389
  }
52106
52390
  const detectedConfigPath = getOmoConfigPath();
52107
- const canonicalConfigPath = join14(dirname5(detectedConfigPath), `${CONFIG_BASENAME}${extname(detectedConfigPath) || ".json"}`);
52391
+ const canonicalConfigPath = join16(dirname7(detectedConfigPath), `${CONFIG_BASENAME}${extname(detectedConfigPath) || ".json"}`);
52108
52392
  const shouldMigrateLegacyPath = basename3(detectedConfigPath).startsWith(LEGACY_CONFIG_BASENAME);
52109
- const omoConfigPath = shouldMigrateLegacyPath ? migrateLegacyConfigFile(detectedConfigPath) || existsSync15(canonicalConfigPath) ? canonicalConfigPath : detectedConfigPath : detectedConfigPath;
52393
+ const omoConfigPath = shouldMigrateLegacyPath ? migrateLegacyConfigFile(detectedConfigPath) || existsSync17(canonicalConfigPath) ? canonicalConfigPath : detectedConfigPath : detectedConfigPath;
52110
52394
  try {
52111
52395
  const newConfig = generateOmoConfig(installConfig);
52112
- if (existsSync15(omoConfigPath)) {
52396
+ if (existsSync17(omoConfigPath)) {
52113
52397
  const backupResult = backupConfigFile(omoConfigPath);
52114
52398
  if (!backupResult.success) {
52115
52399
  return {
@@ -52120,7 +52404,7 @@ function writeOmoConfig(installConfig) {
52120
52404
  }
52121
52405
  try {
52122
52406
  const stat = statSync2(omoConfigPath);
52123
- const content = readFileSync10(omoConfigPath, "utf-8");
52407
+ const content = readFileSync11(omoConfigPath, "utf-8");
52124
52408
  if (stat.size === 0 || isEmptyOrWhitespace2(content)) {
52125
52409
  writeFileSync4(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
52126
52410
  `);
@@ -52166,6 +52450,16 @@ var init_write_omo_config = __esm(() => {
52166
52450
  init_generate_omo_config();
52167
52451
  });
52168
52452
 
52453
+ // src/shared/extract-semver.ts
52454
+ function extractSemverFromOutput(output) {
52455
+ const trimmed = output.trim();
52456
+ if (!trimmed)
52457
+ return null;
52458
+ const semverPattern = /(?<![\d:])v?(\d+\.\d+\.\d+(?:[-+][\w.]+)*)/;
52459
+ const match = trimmed.match(semverPattern);
52460
+ return match?.[1] ?? null;
52461
+ }
52462
+
52169
52463
  // src/shared/spawn-with-windows-hide.ts
52170
52464
  import { spawn as nodeSpawn2 } from "child_process";
52171
52465
  import { Readable as Readable2 } from "stream";
@@ -52178,8 +52472,8 @@ function toReadableStream2(stream) {
52178
52472
  function wrapNodeProcess2(proc) {
52179
52473
  let resolveExited;
52180
52474
  let exitCode = null;
52181
- const exited = new Promise((resolve4) => {
52182
- resolveExited = resolve4;
52475
+ const exited = new Promise((resolve5) => {
52476
+ resolveExited = resolve5;
52183
52477
  });
52184
52478
  proc.on("exit", (code) => {
52185
52479
  exitCode = code ?? 1;
@@ -52235,10 +52529,52 @@ async function findOpenCodeBinaryWithVersion() {
52235
52529
  stdout: "pipe",
52236
52530
  stderr: "pipe"
52237
52531
  });
52238
- const output = await new Response(proc.stdout).text();
52239
- await proc.exited;
52240
- if (proc.exitCode === 0) {
52241
- const version = output.trim();
52532
+ const outputPromise = new Response(proc.stdout).text();
52533
+ let killTimer = null;
52534
+ let killGraceTimer = null;
52535
+ const timedExitResult = await Promise.race([
52536
+ proc.exited.then((exitCode) => ({ type: "exit", exitCode })),
52537
+ new Promise((resolve5) => {
52538
+ killTimer = setTimeout(() => {
52539
+ proc.kill("SIGTERM");
52540
+ killGraceTimer = setTimeout(() => {
52541
+ proc.kill("SIGKILL");
52542
+ }, OPENCODE_VERSION_KILL_GRACE_MS);
52543
+ resolve5({ type: "timeout" });
52544
+ }, OPENCODE_VERSION_CHECK_TIMEOUT_MS);
52545
+ })
52546
+ ]);
52547
+ if (killTimer) {
52548
+ clearTimeout(killTimer);
52549
+ }
52550
+ if (timedExitResult.type === "timeout") {
52551
+ outputPromise.catch(() => {});
52552
+ continue;
52553
+ }
52554
+ if (killGraceTimer) {
52555
+ clearTimeout(killGraceTimer);
52556
+ }
52557
+ let outputTimer = null;
52558
+ const outputResult = await Promise.race([
52559
+ outputPromise.then((output) => ({ type: "output", output })),
52560
+ new Promise((resolve5) => {
52561
+ outputTimer = setTimeout(() => {
52562
+ resolve5({ type: "timeout" });
52563
+ }, OPENCODE_OUTPUT_WAIT_TIMEOUT_MS);
52564
+ })
52565
+ ]).catch(() => ({ type: "timeout" }));
52566
+ if (outputTimer) {
52567
+ clearTimeout(outputTimer);
52568
+ }
52569
+ if (outputResult.type !== "output") {
52570
+ continue;
52571
+ }
52572
+ if (timedExitResult.exitCode === 0 && proc.exitCode === 0) {
52573
+ const output = outputResult.output;
52574
+ const version = extractSemverFromOutput(output) ?? output.trim();
52575
+ if (version.length === 0) {
52576
+ continue;
52577
+ }
52242
52578
  initConfigContext(binary2, version);
52243
52579
  return { binary: binary2, version };
52244
52580
  }
@@ -52256,7 +52592,7 @@ async function getOpenCodeVersion2() {
52256
52592
  const result = await findOpenCodeBinaryWithVersion();
52257
52593
  return result?.version ?? null;
52258
52594
  }
52259
- var OPENCODE_BINARIES;
52595
+ var OPENCODE_BINARIES, OPENCODE_VERSION_CHECK_TIMEOUT_MS = 1500, OPENCODE_VERSION_KILL_GRACE_MS = 200, OPENCODE_OUTPUT_WAIT_TIMEOUT_MS = 200;
52260
52596
  var init_opencode_binary = __esm(() => {
52261
52597
  init_spawn_with_windows_hide();
52262
52598
  init_config_context();
@@ -52264,10 +52600,10 @@ var init_opencode_binary = __esm(() => {
52264
52600
  });
52265
52601
 
52266
52602
  // src/cli/config-manager/detect-current-config.ts
52267
- import { existsSync as existsSync16, readFileSync as readFileSync11 } from "fs";
52603
+ import { existsSync as existsSync18, readFileSync as readFileSync12 } from "fs";
52268
52604
  function detectProvidersFromOmoConfig() {
52269
52605
  const omoConfigPath = getOmoConfigPath();
52270
- if (!existsSync16(omoConfigPath)) {
52606
+ if (!existsSync18(omoConfigPath)) {
52271
52607
  return {
52272
52608
  hasOpenAI: true,
52273
52609
  hasOpencodeZen: true,
@@ -52278,7 +52614,7 @@ function detectProvidersFromOmoConfig() {
52278
52614
  };
52279
52615
  }
52280
52616
  try {
52281
- const content = readFileSync11(omoConfigPath, "utf-8");
52617
+ const content = readFileSync12(omoConfigPath, "utf-8");
52282
52618
  const omoConfig = parseJsonc(content);
52283
52619
  if (!omoConfig || typeof omoConfig !== "object") {
52284
52620
  return {
@@ -52330,11 +52666,11 @@ function detectCurrentConfig() {
52330
52666
  hasOpencodeGo: false,
52331
52667
  hasVercelAiGateway: false
52332
52668
  };
52333
- const { format: format2, path: path5 } = detectConfigFormat();
52669
+ const { format: format2, path: path6 } = detectConfigFormat();
52334
52670
  if (format2 === "none") {
52335
52671
  return result;
52336
52672
  }
52337
- const parseResult = parseOpenCodeConfigFileWithError(path5);
52673
+ const parseResult = parseOpenCodeConfigFileWithError(path6);
52338
52674
  if (!parseResult.config) {
52339
52675
  return result;
52340
52676
  }
@@ -52367,16 +52703,16 @@ var init_detect_current_config = __esm(() => {
52367
52703
  });
52368
52704
 
52369
52705
  // src/cli/config-manager/bun-install.ts
52370
- import { existsSync as existsSync17 } from "fs";
52371
- import { join as join15 } from "path";
52706
+ import { existsSync as existsSync19 } from "fs";
52707
+ import { join as join17 } from "path";
52372
52708
  function getDefaultWorkspaceDir() {
52373
- return join15(getOpenCodeCacheDir(), "packages");
52709
+ return join17(getOpenCodeCacheDir(), "packages");
52374
52710
  }
52375
52711
  function readProcessOutput(stream) {
52376
52712
  if (!stream) {
52377
52713
  return Promise.resolve("");
52378
52714
  }
52379
- return Bun.readableStreamToText(stream);
52715
+ return new Response(stream).text();
52380
52716
  }
52381
52717
  function logCapturedOutputOnFailure(outputMode, output) {
52382
52718
  if (outputMode !== "pipe") {
@@ -52396,7 +52732,7 @@ async function runBunInstallWithDetails(options) {
52396
52732
  const outputMode = options?.outputMode ?? "pipe";
52397
52733
  const cacheDir = options?.workspaceDir ?? getDefaultWorkspaceDir();
52398
52734
  const packageJsonPath = `${cacheDir}/package.json`;
52399
- if (!existsSync17(packageJsonPath)) {
52735
+ if (!existsSync19(packageJsonPath)) {
52400
52736
  return {
52401
52737
  success: false,
52402
52738
  error: `Workspace not initialized: ${packageJsonPath} not found. OpenCode should create this on first run.`
@@ -52411,8 +52747,8 @@ async function runBunInstallWithDetails(options) {
52411
52747
  });
52412
52748
  const outputPromise = Promise.all([readProcessOutput(proc.stdout), readProcessOutput(proc.stderr)]).then(([stdout, stderr]) => ({ stdout, stderr }));
52413
52749
  let timeoutId;
52414
- const timeoutPromise = new Promise((resolve4) => {
52415
- timeoutId = setTimeout(() => resolve4("timeout"), BUN_INSTALL_TIMEOUT_MS);
52750
+ const timeoutPromise = new Promise((resolve5) => {
52751
+ timeoutId = setTimeout(() => resolve5("timeout"), BUN_INSTALL_TIMEOUT_MS);
52416
52752
  });
52417
52753
  const exitPromise = proc.exited.then(() => "completed");
52418
52754
  const result = await Promise.race([exitPromise, timeoutPromise]);
@@ -52539,7 +52875,7 @@ var require_windows = __commonJS((exports, module) => {
52539
52875
  module.exports = isexe;
52540
52876
  isexe.sync = sync;
52541
52877
  var fs5 = __require("fs");
52542
- function checkPathExt(path6, options) {
52878
+ function checkPathExt(path7, options) {
52543
52879
  var pathext = options.pathExt !== undefined ? options.pathExt : process.env.PATHEXT;
52544
52880
  if (!pathext) {
52545
52881
  return true;
@@ -52550,25 +52886,25 @@ var require_windows = __commonJS((exports, module) => {
52550
52886
  }
52551
52887
  for (var i2 = 0;i2 < pathext.length; i2++) {
52552
52888
  var p2 = pathext[i2].toLowerCase();
52553
- if (p2 && path6.substr(-p2.length).toLowerCase() === p2) {
52889
+ if (p2 && path7.substr(-p2.length).toLowerCase() === p2) {
52554
52890
  return true;
52555
52891
  }
52556
52892
  }
52557
52893
  return false;
52558
52894
  }
52559
- function checkStat(stat, path6, options) {
52895
+ function checkStat(stat, path7, options) {
52560
52896
  if (!stat.isSymbolicLink() && !stat.isFile()) {
52561
52897
  return false;
52562
52898
  }
52563
- return checkPathExt(path6, options);
52899
+ return checkPathExt(path7, options);
52564
52900
  }
52565
- function isexe(path6, options, cb) {
52566
- fs5.stat(path6, function(er, stat) {
52567
- cb(er, er ? false : checkStat(stat, path6, options));
52901
+ function isexe(path7, options, cb) {
52902
+ fs5.stat(path7, function(er, stat) {
52903
+ cb(er, er ? false : checkStat(stat, path7, options));
52568
52904
  });
52569
52905
  }
52570
- function sync(path6, options) {
52571
- return checkStat(fs5.statSync(path6), path6, options);
52906
+ function sync(path7, options) {
52907
+ return checkStat(fs5.statSync(path7), path7, options);
52572
52908
  }
52573
52909
  });
52574
52910
 
@@ -52577,13 +52913,13 @@ var require_mode = __commonJS((exports, module) => {
52577
52913
  module.exports = isexe;
52578
52914
  isexe.sync = sync;
52579
52915
  var fs5 = __require("fs");
52580
- function isexe(path6, options, cb) {
52581
- fs5.stat(path6, function(er, stat) {
52916
+ function isexe(path7, options, cb) {
52917
+ fs5.stat(path7, function(er, stat) {
52582
52918
  cb(er, er ? false : checkStat(stat, options));
52583
52919
  });
52584
52920
  }
52585
- function sync(path6, options) {
52586
- return checkStat(fs5.statSync(path6), options);
52921
+ function sync(path7, options) {
52922
+ return checkStat(fs5.statSync(path7), options);
52587
52923
  }
52588
52924
  function checkStat(stat, options) {
52589
52925
  return stat.isFile() && checkMode(stat, options);
@@ -52614,7 +52950,7 @@ var require_isexe = __commonJS((exports, module) => {
52614
52950
  }
52615
52951
  module.exports = isexe;
52616
52952
  isexe.sync = sync;
52617
- function isexe(path6, options, cb) {
52953
+ function isexe(path7, options, cb) {
52618
52954
  if (typeof options === "function") {
52619
52955
  cb = options;
52620
52956
  options = {};
@@ -52623,17 +52959,17 @@ var require_isexe = __commonJS((exports, module) => {
52623
52959
  if (typeof Promise !== "function") {
52624
52960
  throw new TypeError("callback not provided");
52625
52961
  }
52626
- return new Promise(function(resolve4, reject) {
52627
- isexe(path6, options || {}, function(er, is) {
52962
+ return new Promise(function(resolve5, reject) {
52963
+ isexe(path7, options || {}, function(er, is) {
52628
52964
  if (er) {
52629
52965
  reject(er);
52630
52966
  } else {
52631
- resolve4(is);
52967
+ resolve5(is);
52632
52968
  }
52633
52969
  });
52634
52970
  });
52635
52971
  }
52636
- core3(path6, options || {}, function(er, is) {
52972
+ core3(path7, options || {}, function(er, is) {
52637
52973
  if (er) {
52638
52974
  if (er.code === "EACCES" || options && options.ignoreErrors) {
52639
52975
  er = null;
@@ -52643,9 +52979,9 @@ var require_isexe = __commonJS((exports, module) => {
52643
52979
  cb(er, is);
52644
52980
  });
52645
52981
  }
52646
- function sync(path6, options) {
52982
+ function sync(path7, options) {
52647
52983
  try {
52648
- return core3.sync(path6, options || {});
52984
+ return core3.sync(path7, options || {});
52649
52985
  } catch (er) {
52650
52986
  if (options && options.ignoreErrors || er.code === "EACCES") {
52651
52987
  return false;
@@ -52659,7 +52995,7 @@ var require_isexe = __commonJS((exports, module) => {
52659
52995
  // node_modules/which/which.js
52660
52996
  var require_which = __commonJS((exports, module) => {
52661
52997
  var isWindows = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
52662
- var path6 = __require("path");
52998
+ var path7 = __require("path");
52663
52999
  var COLON = isWindows ? ";" : ":";
52664
53000
  var isexe = require_isexe();
52665
53001
  var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
@@ -52690,27 +53026,27 @@ var require_which = __commonJS((exports, module) => {
52690
53026
  opt = {};
52691
53027
  const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
52692
53028
  const found = [];
52693
- const step = (i2) => new Promise((resolve4, reject) => {
53029
+ const step = (i2) => new Promise((resolve5, reject) => {
52694
53030
  if (i2 === pathEnv.length)
52695
- return opt.all && found.length ? resolve4(found) : reject(getNotFoundError(cmd));
53031
+ return opt.all && found.length ? resolve5(found) : reject(getNotFoundError(cmd));
52696
53032
  const ppRaw = pathEnv[i2];
52697
53033
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
52698
- const pCmd = path6.join(pathPart, cmd);
53034
+ const pCmd = path7.join(pathPart, cmd);
52699
53035
  const p2 = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
52700
- resolve4(subStep(p2, i2, 0));
53036
+ resolve5(subStep(p2, i2, 0));
52701
53037
  });
52702
- const subStep = (p2, i2, ii) => new Promise((resolve4, reject) => {
53038
+ const subStep = (p2, i2, ii) => new Promise((resolve5, reject) => {
52703
53039
  if (ii === pathExt.length)
52704
- return resolve4(step(i2 + 1));
53040
+ return resolve5(step(i2 + 1));
52705
53041
  const ext = pathExt[ii];
52706
53042
  isexe(p2 + ext, { pathExt: pathExtExe }, (er, is) => {
52707
53043
  if (!er && is) {
52708
53044
  if (opt.all)
52709
53045
  found.push(p2 + ext);
52710
53046
  else
52711
- return resolve4(p2 + ext);
53047
+ return resolve5(p2 + ext);
52712
53048
  }
52713
- return resolve4(subStep(p2, i2, ii + 1));
53049
+ return resolve5(subStep(p2, i2, ii + 1));
52714
53050
  });
52715
53051
  });
52716
53052
  return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
@@ -52722,7 +53058,7 @@ var require_which = __commonJS((exports, module) => {
52722
53058
  for (let i2 = 0;i2 < pathEnv.length; i2++) {
52723
53059
  const ppRaw = pathEnv[i2];
52724
53060
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
52725
- const pCmd = path6.join(pathPart, cmd);
53061
+ const pCmd = path7.join(pathPart, cmd);
52726
53062
  const p2 = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
52727
53063
  for (let j2 = 0;j2 < pathExt.length; j2++) {
52728
53064
  const cur = p2 + pathExt[j2];
@@ -52763,7 +53099,7 @@ var require_path_key = __commonJS((exports, module) => {
52763
53099
 
52764
53100
  // node_modules/cross-spawn/lib/util/resolveCommand.js
52765
53101
  var require_resolveCommand = __commonJS((exports, module) => {
52766
- var path6 = __require("path");
53102
+ var path7 = __require("path");
52767
53103
  var which = require_which();
52768
53104
  var getPathKey = require_path_key();
52769
53105
  function resolveCommandAttempt(parsed, withoutPathExt) {
@@ -52780,7 +53116,7 @@ var require_resolveCommand = __commonJS((exports, module) => {
52780
53116
  try {
52781
53117
  resolved = which.sync(parsed.command, {
52782
53118
  path: env[getPathKey({ env })],
52783
- pathExt: withoutPathExt ? path6.delimiter : undefined
53119
+ pathExt: withoutPathExt ? path7.delimiter : undefined
52784
53120
  });
52785
53121
  } catch (e2) {} finally {
52786
53122
  if (shouldSwitchCwd) {
@@ -52788,7 +53124,7 @@ var require_resolveCommand = __commonJS((exports, module) => {
52788
53124
  }
52789
53125
  }
52790
53126
  if (resolved) {
52791
- resolved = path6.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
53127
+ resolved = path7.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
52792
53128
  }
52793
53129
  return resolved;
52794
53130
  }
@@ -52833,8 +53169,8 @@ var require_shebang_command = __commonJS((exports, module) => {
52833
53169
  if (!match) {
52834
53170
  return null;
52835
53171
  }
52836
- const [path6, argument] = match[0].replace(/#! ?/, "").split(" ");
52837
- const binary2 = path6.split("/").pop();
53172
+ const [path7, argument] = match[0].replace(/#! ?/, "").split(" ");
53173
+ const binary2 = path7.split("/").pop();
52838
53174
  if (binary2 === "env") {
52839
53175
  return argument;
52840
53176
  }
@@ -52862,7 +53198,7 @@ var require_readShebang = __commonJS((exports, module) => {
52862
53198
 
52863
53199
  // node_modules/cross-spawn/lib/parse.js
52864
53200
  var require_parse = __commonJS((exports, module) => {
52865
- var path6 = __require("path");
53201
+ var path7 = __require("path");
52866
53202
  var resolveCommand2 = require_resolveCommand();
52867
53203
  var escape = require_escape();
52868
53204
  var readShebang = require_readShebang();
@@ -52887,7 +53223,7 @@ var require_parse = __commonJS((exports, module) => {
52887
53223
  const needsShell = !isExecutableRegExp.test(commandFile);
52888
53224
  if (parsed.options.forceShell || needsShell) {
52889
53225
  const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
52890
- parsed.command = path6.normalize(parsed.command);
53226
+ parsed.command = path7.normalize(parsed.command);
52891
53227
  parsed.command = escape.command(parsed.command);
52892
53228
  parsed.args = parsed.args.map((arg) => escape.argument(arg, needsDoubleEscapeMetaChars));
52893
53229
  const shellCommand = [parsed.command].concat(parsed.args).join(" ");
@@ -52991,21 +53327,21 @@ var require_cross_spawn = __commonJS((exports, module) => {
52991
53327
  });
52992
53328
 
52993
53329
  // src/hooks/auto-update-checker/constants.ts
52994
- import * as path6 from "path";
53330
+ import * as path7 from "path";
52995
53331
  import * as os4 from "os";
52996
53332
  function getWindowsAppdataDir() {
52997
53333
  if (process.platform !== "win32")
52998
53334
  return null;
52999
- return process.env.APPDATA ?? path6.join(os4.homedir(), "AppData", "Roaming");
53335
+ return process.env.APPDATA ?? path7.join(os4.homedir(), "AppData", "Roaming");
53000
53336
  }
53001
53337
  function getUserConfigDir() {
53002
53338
  return getOpenCodeConfigDir({ binary: "opencode" });
53003
53339
  }
53004
53340
  function getUserOpencodeConfig() {
53005
- return path6.join(getUserConfigDir(), "opencode.json");
53341
+ return path7.join(getUserConfigDir(), "opencode.json");
53006
53342
  }
53007
53343
  function getUserOpencodeConfigJsonc() {
53008
- return path6.join(getUserConfigDir(), "opencode.jsonc");
53344
+ return path7.join(getUserConfigDir(), "opencode.jsonc");
53009
53345
  }
53010
53346
  var PACKAGE_NAME2, ACCEPTED_PACKAGE_NAMES2, NPM_REGISTRY_URL, NPM_FETCH_TIMEOUT = 5000, CACHE_ROOT_DIR, CACHE_DIR, VERSION_FILE, INSTALLED_PACKAGE_JSON, INSTALLED_PACKAGE_JSON_CANDIDATES;
53011
53347
  var init_constants3 = __esm(() => {
@@ -53016,30 +53352,30 @@ var init_constants3 = __esm(() => {
53016
53352
  ACCEPTED_PACKAGE_NAMES2 = ACCEPTED_PACKAGE_NAMES;
53017
53353
  NPM_REGISTRY_URL = `https://registry.npmjs.org/-/package/${PACKAGE_NAME2}/dist-tags`;
53018
53354
  CACHE_ROOT_DIR = getOpenCodeCacheDir();
53019
- CACHE_DIR = path6.join(CACHE_ROOT_DIR, "packages");
53020
- VERSION_FILE = path6.join(CACHE_ROOT_DIR, "version");
53021
- INSTALLED_PACKAGE_JSON = path6.join(CACHE_DIR, "node_modules", PACKAGE_NAME2, "package.json");
53022
- INSTALLED_PACKAGE_JSON_CANDIDATES = ACCEPTED_PACKAGE_NAMES2.map((name) => path6.join(CACHE_DIR, "node_modules", name, "package.json"));
53355
+ CACHE_DIR = path7.join(CACHE_ROOT_DIR, "packages");
53356
+ VERSION_FILE = path7.join(CACHE_ROOT_DIR, "version");
53357
+ INSTALLED_PACKAGE_JSON = path7.join(CACHE_DIR, "node_modules", PACKAGE_NAME2, "package.json");
53358
+ INSTALLED_PACKAGE_JSON_CANDIDATES = ACCEPTED_PACKAGE_NAMES2.map((name) => path7.join(CACHE_DIR, "node_modules", name, "package.json"));
53023
53359
  });
53024
53360
 
53025
53361
  // src/hooks/auto-update-checker/checker/config-paths.ts
53026
53362
  import * as os5 from "os";
53027
- import * as path7 from "path";
53363
+ import * as path8 from "path";
53028
53364
  function getConfigPaths(directory) {
53029
53365
  const userConfigDir = getUserConfigDir();
53030
53366
  const paths = [
53031
- path7.join(directory, ".opencode", "opencode.json"),
53032
- path7.join(directory, ".opencode", "opencode.jsonc"),
53367
+ path8.join(directory, ".opencode", "opencode.json"),
53368
+ path8.join(directory, ".opencode", "opencode.jsonc"),
53033
53369
  getUserOpencodeConfig(),
53034
53370
  getUserOpencodeConfigJsonc()
53035
53371
  ];
53036
53372
  if (process.platform === "win32") {
53037
- const crossPlatformDir = path7.join(os5.homedir(), ".config");
53373
+ const crossPlatformDir = path8.join(os5.homedir(), ".config");
53038
53374
  const appdataDir = getWindowsAppdataDir();
53039
53375
  if (appdataDir) {
53040
53376
  const alternateDir = userConfigDir === crossPlatformDir ? appdataDir : crossPlatformDir;
53041
- const alternateConfig = path7.join(alternateDir, "opencode", "opencode.json");
53042
- const alternateConfigJsonc = path7.join(alternateDir, "opencode", "opencode.jsonc");
53377
+ const alternateConfig = path8.join(alternateDir, "opencode", "opencode.json");
53378
+ const alternateConfigJsonc = path8.join(alternateDir, "opencode", "opencode.jsonc");
53043
53379
  if (!paths.includes(alternateConfig)) {
53044
53380
  paths.push(alternateConfig);
53045
53381
  }
@@ -53097,13 +53433,13 @@ var init_local_dev_path = __esm(() => {
53097
53433
 
53098
53434
  // src/hooks/auto-update-checker/checker/package-json-locator.ts
53099
53435
  import * as fs6 from "fs";
53100
- import * as path8 from "path";
53436
+ import * as path9 from "path";
53101
53437
  function findPackageJsonUp(startPath) {
53102
53438
  try {
53103
53439
  const stat = fs6.statSync(startPath);
53104
- let dir = stat.isDirectory() ? startPath : path8.dirname(startPath);
53440
+ let dir = stat.isDirectory() ? startPath : path9.dirname(startPath);
53105
53441
  for (let i2 = 0;i2 < 10; i2++) {
53106
- const pkgPath = path8.join(dir, "package.json");
53442
+ const pkgPath = path9.join(dir, "package.json");
53107
53443
  if (fs6.existsSync(pkgPath)) {
53108
53444
  try {
53109
53445
  const content = fs6.readFileSync(pkgPath, "utf-8");
@@ -53112,7 +53448,7 @@ function findPackageJsonUp(startPath) {
53112
53448
  return pkgPath;
53113
53449
  } catch {}
53114
53450
  }
53115
- const parent = path8.dirname(dir);
53451
+ const parent = path9.dirname(dir);
53116
53452
  if (parent === dir)
53117
53453
  break;
53118
53454
  dir = parent;
@@ -53187,7 +53523,7 @@ var init_plugin_entry = __esm(() => {
53187
53523
 
53188
53524
  // src/hooks/auto-update-checker/checker/cached-version.ts
53189
53525
  import * as fs9 from "fs";
53190
- import * as path9 from "path";
53526
+ import * as path10 from "path";
53191
53527
  import { fileURLToPath as fileURLToPath2 } from "url";
53192
53528
  function readPackageVersion(packageJsonPath) {
53193
53529
  const content = fs9.readFileSync(packageJsonPath, "utf-8");
@@ -53196,7 +53532,7 @@ function readPackageVersion(packageJsonPath) {
53196
53532
  }
53197
53533
  function getCachedVersion() {
53198
53534
  try {
53199
- const currentDir = path9.dirname(fileURLToPath2(import.meta.url));
53535
+ const currentDir = path10.dirname(fileURLToPath2(import.meta.url));
53200
53536
  const pkgPath = findPackageJsonUp(currentDir);
53201
53537
  if (pkgPath) {
53202
53538
  return readPackageVersion(pkgPath);
@@ -53212,7 +53548,7 @@ function getCachedVersion() {
53212
53548
  } catch {}
53213
53549
  }
53214
53550
  try {
53215
- const execDir = path9.dirname(fs9.realpathSync(process.execPath));
53551
+ const execDir = path10.dirname(fs9.realpathSync(process.execPath));
53216
53552
  const pkgPath = findPackageJsonUp(execDir);
53217
53553
  if (pkgPath) {
53218
53554
  return readPackageVersion(pkgPath);
@@ -53356,7 +53692,7 @@ var init_check_for_update = __esm(() => {
53356
53692
  // src/hooks/auto-update-checker/checker/sync-package-json.ts
53357
53693
  import * as crypto from "crypto";
53358
53694
  import * as fs10 from "fs";
53359
- import * as path10 from "path";
53695
+ import * as path11 from "path";
53360
53696
  function safeUnlink(filePath) {
53361
53697
  try {
53362
53698
  fs10.unlinkSync(filePath);
@@ -53373,7 +53709,7 @@ function getIntentVersion(pluginInfo) {
53373
53709
  function writeCachePackageJson(cachePackageJsonPath, pkgJson) {
53374
53710
  const tmpPath = `${cachePackageJsonPath}.${crypto.randomUUID()}`;
53375
53711
  try {
53376
- fs10.mkdirSync(path10.dirname(cachePackageJsonPath), { recursive: true });
53712
+ fs10.mkdirSync(path11.dirname(cachePackageJsonPath), { recursive: true });
53377
53713
  fs10.writeFileSync(tmpPath, JSON.stringify(pkgJson, null, 2));
53378
53714
  fs10.renameSync(tmpPath, cachePackageJsonPath);
53379
53715
  return { synced: true, error: null };
@@ -53384,7 +53720,7 @@ function writeCachePackageJson(cachePackageJsonPath, pkgJson) {
53384
53720
  }
53385
53721
  }
53386
53722
  function syncCachePackageJsonToIntent(pluginInfo) {
53387
- const cachePackageJsonPath = path10.join(CACHE_DIR, "package.json");
53723
+ const cachePackageJsonPath = path11.join(CACHE_DIR, "package.json");
53388
53724
  const intentVersion = getIntentVersion(pluginInfo);
53389
53725
  if (!fs10.existsSync(cachePackageJsonPath)) {
53390
53726
  log("[auto-update-checker] Cache package.json missing, creating workspace package.json", { intentVersion });
@@ -53460,7 +53796,7 @@ var init_checker = __esm(() => {
53460
53796
 
53461
53797
  // src/hooks/auto-update-checker/cache.ts
53462
53798
  import * as fs11 from "fs";
53463
- import * as path11 from "path";
53799
+ import * as path12 from "path";
53464
53800
  function stripTrailingCommas(json3) {
53465
53801
  return json3.replace(/,(\s*[}\]])/g, "$1");
53466
53802
  }
@@ -53489,8 +53825,8 @@ function deleteBinaryBunLock(lockPath) {
53489
53825
  }
53490
53826
  }
53491
53827
  function removeFromBunLock(packageName) {
53492
- const textLockPath = path11.join(CACHE_DIR, "bun.lock");
53493
- const binaryLockPath = path11.join(CACHE_DIR, "bun.lockb");
53828
+ const textLockPath = path12.join(CACHE_DIR, "bun.lock");
53829
+ const binaryLockPath = path12.join(CACHE_DIR, "bun.lockb");
53494
53830
  if (fs11.existsSync(textLockPath)) {
53495
53831
  return removeFromTextBunLock(textLockPath, packageName);
53496
53832
  }
@@ -53503,8 +53839,8 @@ function invalidatePackage(packageName = PACKAGE_NAME2) {
53503
53839
  try {
53504
53840
  const userConfigDir = getUserConfigDir();
53505
53841
  const pkgDirs = [
53506
- path11.join(userConfigDir, "node_modules", packageName),
53507
- path11.join(CACHE_DIR, "node_modules", packageName)
53842
+ path12.join(userConfigDir, "node_modules", packageName),
53843
+ path12.join(CACHE_DIR, "node_modules", packageName)
53508
53844
  ];
53509
53845
  let packageRemoved = false;
53510
53846
  let lockRemoved = false;
@@ -53564,8 +53900,8 @@ var init_update_toasts = __esm(() => {
53564
53900
  });
53565
53901
 
53566
53902
  // src/hooks/auto-update-checker/hook/background-update-check.ts
53567
- import { existsSync as existsSync29 } from "fs";
53568
- import { join as join28 } from "path";
53903
+ import { existsSync as existsSync32 } from "fs";
53904
+ import { join as join30 } from "path";
53569
53905
  function getCacheWorkspaceDir(deps) {
53570
53906
  return deps.join(deps.getOpenCodeCacheDir(), "packages");
53571
53907
  }
@@ -53615,7 +53951,7 @@ async function primeCacheWorkspace(activeWorkspace, deps) {
53615
53951
  return runBunInstallSafe(cacheWorkspace, deps);
53616
53952
  }
53617
53953
  function createBackgroundUpdateCheckRunner(overrides = {}) {
53618
- const deps = { ...defaultDeps, ...overrides };
53954
+ const deps = { ...defaultDeps2, ...overrides };
53619
53955
  return async function runBackgroundUpdateCheck(ctx, autoUpdate, getToastMessage) {
53620
53956
  const pluginInfo = deps.findPluginEntry(ctx.directory);
53621
53957
  if (!pluginInfo) {
@@ -53673,7 +54009,7 @@ function createBackgroundUpdateCheckRunner(overrides = {}) {
53673
54009
  deps.log("[auto-update-checker] bun install failed; update not installed (falling back to notification-only)");
53674
54010
  };
53675
54011
  }
53676
- var defaultDeps, runBackgroundUpdateCheck;
54012
+ var defaultDeps2, runBackgroundUpdateCheck;
53677
54013
  var init_background_update_check = __esm(() => {
53678
54014
  init_config_manager();
53679
54015
  init_logger();
@@ -53682,9 +54018,9 @@ var init_background_update_check = __esm(() => {
53682
54018
  init_constants3();
53683
54019
  init_checker();
53684
54020
  init_update_toasts();
53685
- defaultDeps = {
53686
- existsSync: existsSync29,
53687
- join: join28,
54021
+ defaultDeps2 = {
54022
+ existsSync: existsSync32,
54023
+ join: join30,
53688
54024
  runBunInstallWithDetails,
53689
54025
  log,
53690
54026
  getOpenCodeCacheDir,
@@ -53843,7 +54179,7 @@ async function showSpinnerToast(ctx, version3, message) {
53843
54179
  duration: frameInterval + 50
53844
54180
  }
53845
54181
  }).catch(() => {});
53846
- await new Promise((resolve4) => setTimeout(resolve4, frameInterval));
54182
+ await new Promise((resolve6) => setTimeout(resolve6, frameInterval));
53847
54183
  }
53848
54184
  }
53849
54185
  var SISYPHUS_SPINNER;
@@ -53869,7 +54205,7 @@ var init_startup_toasts = __esm(() => {
53869
54205
  });
53870
54206
 
53871
54207
  // src/hooks/auto-update-checker/hook.ts
53872
- function createAutoUpdateCheckerHook(ctx, options = {}, deps = defaultDeps2) {
54208
+ function createAutoUpdateCheckerHook(ctx, options = {}, deps = defaultDeps3) {
53873
54209
  const {
53874
54210
  showStartupToast = true,
53875
54211
  isSisyphusEnabled = false,
@@ -53926,13 +54262,13 @@ v${latestVersion} available. Restart OpenCode to apply.` : "OpenCode is now on S
53926
54262
  }
53927
54263
  };
53928
54264
  }
53929
- var defaultDeps2, isRecord6 = (value) => {
54265
+ var defaultDeps3, isRecord7 = (value) => {
53930
54266
  return typeof value === "object" && value !== null;
53931
54267
  }, getParentID = (properties) => {
53932
- if (!isRecord6(properties))
54268
+ if (!isRecord7(properties))
53933
54269
  return;
53934
54270
  const { info } = properties;
53935
- if (!isRecord6(info))
54271
+ if (!isRecord7(info))
53936
54272
  return;
53937
54273
  const { parentID } = info;
53938
54274
  return typeof parentID === "string" && parentID.length > 0 ? parentID : undefined;
@@ -53946,7 +54282,7 @@ var init_hook = __esm(() => {
53946
54282
  init_model_capabilities_status();
53947
54283
  init_model_cache_warning();
53948
54284
  init_startup_toasts();
53949
- defaultDeps2 = {
54285
+ defaultDeps3 = {
53950
54286
  getCachedVersion,
53951
54287
  getLocalDevVersion,
53952
54288
  showConfigErrorsIfAny,
@@ -53996,7 +54332,7 @@ var {
53996
54332
  // package.json
53997
54333
  var package_default = {
53998
54334
  name: "oh-my-opencode",
53999
- version: "3.17.15",
54335
+ version: "4.1.0",
54000
54336
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
54001
54337
  main: "./dist/index.js",
54002
54338
  types: "dist/index.d.ts",
@@ -54030,7 +54366,7 @@ var package_default = {
54030
54366
  prepublishOnly: "bun run clean && bun run build",
54031
54367
  "test:model-capabilities": "bun test src/shared/model-capability-aliases.test.ts src/shared/model-capability-guardrails.test.ts src/shared/model-capabilities.test.ts src/cli/doctor/checks/model-resolution.test.ts --bail",
54032
54368
  typecheck: "tsc --noEmit",
54033
- test: "bun test"
54369
+ test: "bun run script/run-ci-tests.ts"
54034
54370
  },
54035
54371
  keywords: [
54036
54372
  "opencode",
@@ -54056,7 +54392,7 @@ var package_default = {
54056
54392
  "@ast-grep/napi": "^0.41.1",
54057
54393
  "@clack/prompts": "^0.11.0",
54058
54394
  "@code-yeongyu/comment-checker": "^0.7.0",
54059
- "@modelcontextprotocol/sdk": "^1.25.2",
54395
+ "@modelcontextprotocol/sdk": "^1.29.0",
54060
54396
  "@opencode-ai/plugin": "^1.4.0",
54061
54397
  "@opencode-ai/sdk": "^1.4.0",
54062
54398
  commander: "^14.0.2",
@@ -54077,19 +54413,25 @@ var package_default = {
54077
54413
  zod: "^4.3.0"
54078
54414
  },
54079
54415
  optionalDependencies: {
54080
- "oh-my-opencode-darwin-arm64": "3.17.15",
54081
- "oh-my-opencode-darwin-x64": "3.17.15",
54082
- "oh-my-opencode-darwin-x64-baseline": "3.17.15",
54083
- "oh-my-opencode-linux-arm64": "3.17.15",
54084
- "oh-my-opencode-linux-arm64-musl": "3.17.15",
54085
- "oh-my-opencode-linux-x64": "3.17.15",
54086
- "oh-my-opencode-linux-x64-baseline": "3.17.15",
54087
- "oh-my-opencode-linux-x64-musl": "3.17.15",
54088
- "oh-my-opencode-linux-x64-musl-baseline": "3.17.15",
54089
- "oh-my-opencode-windows-x64": "3.17.15",
54090
- "oh-my-opencode-windows-x64-baseline": "3.17.15"
54416
+ "oh-my-opencode-darwin-arm64": "4.1.0",
54417
+ "oh-my-opencode-darwin-x64": "4.1.0",
54418
+ "oh-my-opencode-darwin-x64-baseline": "4.1.0",
54419
+ "oh-my-opencode-linux-arm64": "4.1.0",
54420
+ "oh-my-opencode-linux-arm64-musl": "4.1.0",
54421
+ "oh-my-opencode-linux-x64": "4.1.0",
54422
+ "oh-my-opencode-linux-x64-baseline": "4.1.0",
54423
+ "oh-my-opencode-linux-x64-musl": "4.1.0",
54424
+ "oh-my-opencode-linux-x64-musl-baseline": "4.1.0",
54425
+ "oh-my-opencode-windows-x64": "4.1.0",
54426
+ "oh-my-opencode-windows-x64-baseline": "4.1.0"
54427
+ },
54428
+ overrides: {
54429
+ hono: "^4.12.18",
54430
+ "@hono/node-server": "^1.19.13",
54431
+ "express-rate-limit": "^8.5.1",
54432
+ "fast-uri": "^3.1.2",
54433
+ "path-to-regexp": "^8.4.2"
54091
54434
  },
54092
- overrides: {},
54093
54435
  trustedDependencies: [
54094
54436
  "@ast-grep/cli",
54095
54437
  "@ast-grep/napi",
@@ -54278,13 +54620,15 @@ var CHECK_IDS = {
54278
54620
  SYSTEM: "system",
54279
54621
  CONFIG: "config",
54280
54622
  TOOLS: "tools",
54281
- MODELS: "models"
54623
+ MODELS: "models",
54624
+ TEAM_MODE: "team-mode"
54282
54625
  };
54283
54626
  var CHECK_NAMES = {
54284
54627
  [CHECK_IDS.SYSTEM]: "System",
54285
54628
  [CHECK_IDS.CONFIG]: "Configuration",
54286
54629
  [CHECK_IDS.TOOLS]: "Tools",
54287
- [CHECK_IDS.MODELS]: "Models"
54630
+ [CHECK_IDS.MODELS]: "Models",
54631
+ [CHECK_IDS.TEAM_MODE]: "Team Mode"
54288
54632
  };
54289
54633
  var EXIT_CODES = {
54290
54634
  SUCCESS: 0,
@@ -55374,10 +55718,10 @@ function formatToolHeader(toolName, input) {
55374
55718
  };
55375
55719
  }
55376
55720
  if (toolName === "list") {
55377
- const path5 = str2(input.path);
55721
+ const path6 = str2(input.path);
55378
55722
  return {
55379
55723
  icon: "\u2192",
55380
- title: path5 ? `List ${path5}` : "List"
55724
+ title: path6 ? `List ${path6}` : "List"
55381
55725
  };
55382
55726
  }
55383
55727
  if (toolName === "read") {
@@ -55886,7 +56230,8 @@ async function processEvents(ctx, stream, state) {
55886
56230
  }
55887
56231
  // src/plugin-config.ts
55888
56232
  import * as fs4 from "fs";
55889
- import * as path5 from "path";
56233
+ import { homedir as homedir5 } from "os";
56234
+ import * as path6 from "path";
55890
56235
 
55891
56236
  // node_modules/zod/v4/classic/external.js
55892
56237
  var exports_external = {};
@@ -56653,10 +56998,10 @@ function mergeDefs(...defs) {
56653
56998
  function cloneDef(schema2) {
56654
56999
  return mergeDefs(schema2._zod.def);
56655
57000
  }
56656
- function getElementAtPath(obj, path5) {
56657
- if (!path5)
57001
+ function getElementAtPath(obj, path6) {
57002
+ if (!path6)
56658
57003
  return obj;
56659
- return path5.reduce((acc, key) => acc?.[key], obj);
57004
+ return path6.reduce((acc, key) => acc?.[key], obj);
56660
57005
  }
56661
57006
  function promiseAllObject(promisesObj) {
56662
57007
  const keys = Object.keys(promisesObj);
@@ -57037,11 +57382,11 @@ function aborted(x2, startIndex = 0) {
57037
57382
  }
57038
57383
  return false;
57039
57384
  }
57040
- function prefixIssues(path5, issues) {
57385
+ function prefixIssues(path6, issues) {
57041
57386
  return issues.map((iss) => {
57042
57387
  var _a;
57043
57388
  (_a = iss).path ?? (_a.path = []);
57044
- iss.path.unshift(path5);
57389
+ iss.path.unshift(path6);
57045
57390
  return iss;
57046
57391
  });
57047
57392
  }
@@ -57224,7 +57569,7 @@ function formatError2(error, mapper = (issue2) => issue2.message) {
57224
57569
  }
57225
57570
  function treeifyError(error, mapper = (issue2) => issue2.message) {
57226
57571
  const result = { errors: [] };
57227
- const processError = (error2, path5 = []) => {
57572
+ const processError = (error2, path6 = []) => {
57228
57573
  var _a, _b;
57229
57574
  for (const issue2 of error2.issues) {
57230
57575
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -57234,7 +57579,7 @@ function treeifyError(error, mapper = (issue2) => issue2.message) {
57234
57579
  } else if (issue2.code === "invalid_element") {
57235
57580
  processError({ issues: issue2.issues }, issue2.path);
57236
57581
  } else {
57237
- const fullpath = [...path5, ...issue2.path];
57582
+ const fullpath = [...path6, ...issue2.path];
57238
57583
  if (fullpath.length === 0) {
57239
57584
  result.errors.push(mapper(issue2));
57240
57585
  continue;
@@ -57266,8 +57611,8 @@ function treeifyError(error, mapper = (issue2) => issue2.message) {
57266
57611
  }
57267
57612
  function toDotPath(_path) {
57268
57613
  const segs = [];
57269
- const path5 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
57270
- for (const seg of path5) {
57614
+ const path6 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
57615
+ for (const seg of path6) {
57271
57616
  if (typeof seg === "number")
57272
57617
  segs.push(`[${seg}]`);
57273
57618
  else if (typeof seg === "symbol")
@@ -69014,13 +69359,13 @@ function resolveRef(ref, ctx) {
69014
69359
  if (!ref.startsWith("#")) {
69015
69360
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
69016
69361
  }
69017
- const path5 = ref.slice(1).split("/").filter(Boolean);
69018
- if (path5.length === 0) {
69362
+ const path6 = ref.slice(1).split("/").filter(Boolean);
69363
+ if (path6.length === 0) {
69019
69364
  return ctx.rootSchema;
69020
69365
  }
69021
69366
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
69022
- if (path5[0] === defsKey) {
69023
- const key = path5[1];
69367
+ if (path6[0] === defsKey) {
69368
+ const key = path6[1];
69024
69369
  if (!key || !ctx.defs[key]) {
69025
69370
  throw new Error(`Reference not found: ${ref}`);
69026
69371
  }
@@ -69441,7 +69786,8 @@ var BuiltinSkillNameSchema = exports_external.enum([
69441
69786
  "frontend-ui-ux",
69442
69787
  "git-master",
69443
69788
  "review-work",
69444
- "ai-slop-remover"
69789
+ "ai-slop-remover",
69790
+ "team-mode"
69445
69791
  ]);
69446
69792
  var OverridableAgentNameSchema = exports_external.enum([
69447
69793
  "build",
@@ -69463,7 +69809,7 @@ var OverridableAgentNameSchema = exports_external.enum([
69463
69809
  var FallbackModelObjectSchema = exports_external.object({
69464
69810
  model: exports_external.string(),
69465
69811
  variant: exports_external.string().optional(),
69466
- reasoningEffort: exports_external.enum(["none", "minimal", "low", "medium", "high", "xhigh"]).optional(),
69812
+ reasoningEffort: exports_external.enum(["none", "minimal", "low", "medium", "high", "xhigh", "max"]).optional(),
69467
69813
  temperature: exports_external.number().min(0).max(2).optional(),
69468
69814
  top_p: exports_external.number().min(0).max(1).optional(),
69469
69815
  maxTokens: exports_external.number().optional(),
@@ -69519,7 +69865,7 @@ var AgentOverrideConfigSchema = exports_external.object({
69519
69865
  type: exports_external.enum(["enabled", "disabled"]),
69520
69866
  budgetTokens: exports_external.number().optional()
69521
69867
  }).optional(),
69522
- reasoningEffort: exports_external.enum(["none", "minimal", "low", "medium", "high", "xhigh"]).optional(),
69868
+ reasoningEffort: exports_external.enum(["none", "minimal", "low", "medium", "high", "xhigh", "max"]).optional(),
69523
69869
  textVerbosity: exports_external.enum(["low", "medium", "high"]).optional(),
69524
69870
  providerOptions: exports_external.record(exports_external.string(), exports_external.unknown()).optional(),
69525
69871
  ultrawork: exports_external.object({
@@ -69595,7 +69941,7 @@ var CategoryConfigSchema = exports_external.object({
69595
69941
  type: exports_external.enum(["enabled", "disabled"]),
69596
69942
  budgetTokens: exports_external.number().optional()
69597
69943
  }).optional(),
69598
- reasoningEffort: exports_external.enum(["none", "minimal", "low", "medium", "high", "xhigh"]).optional(),
69944
+ reasoningEffort: exports_external.enum(["none", "minimal", "low", "medium", "high", "xhigh", "max"]).optional(),
69599
69945
  textVerbosity: exports_external.enum(["low", "medium", "high"]).optional(),
69600
69946
  tools: exports_external.record(exports_external.string(), exports_external.boolean()).optional(),
69601
69947
  prompt_append: exports_external.string().optional(),
@@ -69637,7 +69983,8 @@ var BuiltinCommandNameSchema = exports_external.enum([
69637
69983
  "refactor",
69638
69984
  "start-work",
69639
69985
  "stop-continuation",
69640
- "remove-ai-slops"
69986
+ "remove-ai-slops",
69987
+ "hyperplan"
69641
69988
  ]);
69642
69989
  // src/config/schema/dynamic-context-pruning.ts
69643
69990
  var DynamicContextPruningConfigSchema = exports_external.object({
@@ -69738,6 +70085,7 @@ var HookNameSchema = exports_external.enum([
69738
70085
  "delegate-task-retry",
69739
70086
  "prometheus-md-only",
69740
70087
  "sisyphus-junior-notepad",
70088
+ "team-tool-gating",
69741
70089
  "no-sisyphus-gpt",
69742
70090
  "no-hephaestus-non-gpt",
69743
70091
  "start-work",
@@ -69754,8 +70102,14 @@ var HookNameSchema = exports_external.enum([
69754
70102
  "read-image-resizer",
69755
70103
  "todo-description-override",
69756
70104
  "webfetch-redirect-guard",
70105
+ "fsync-skip-warning",
69757
70106
  "legacy-plugin-toast"
69758
70107
  ]);
70108
+ // src/config/schema/keyword-detector.ts
70109
+ var KeywordTypeSchema = exports_external.enum(["ultrawork", "search", "analyze", "team", "hyperplan", "hyperplan-ultrawork"]);
70110
+ var KeywordDetectorConfigSchema = exports_external.object({
70111
+ disabled_keywords: exports_external.array(KeywordTypeSchema).optional()
70112
+ });
69759
70113
  // src/config/schema/model-capabilities.ts
69760
70114
  var ModelCapabilitiesConfigSchema = exports_external.object({
69761
70115
  enabled: exports_external.boolean().optional(),
@@ -69826,6 +70180,21 @@ var RuntimeFallbackConfigSchema = exports_external.object({
69826
70180
  notify_on_fallback: exports_external.boolean().optional()
69827
70181
  });
69828
70182
 
70183
+ // src/config/schema/team-mode.ts
70184
+ var TeamModeConfigSchema = exports_external.object({
70185
+ enabled: exports_external.boolean().default(false),
70186
+ tmux_visualization: exports_external.boolean().default(false),
70187
+ max_parallel_members: exports_external.number().int().min(1).max(8).default(4),
70188
+ max_members: exports_external.number().int().min(1).max(8).default(8),
70189
+ max_messages_per_run: exports_external.number().int().min(1).default(1e4),
70190
+ max_wall_clock_minutes: exports_external.number().int().min(1).default(120),
70191
+ max_member_turns: exports_external.number().int().min(1).default(500),
70192
+ base_dir: exports_external.string().optional(),
70193
+ message_payload_max_bytes: exports_external.number().int().min(1024).default(32768),
70194
+ recipient_unread_max_bytes: exports_external.number().int().min(1024).default(262144),
70195
+ mailbox_poll_interval_ms: exports_external.number().int().min(500).default(3000)
70196
+ });
70197
+
69829
70198
  // src/config/schema/skills.ts
69830
70199
  var SkillSourceSchema = exports_external.union([
69831
70200
  exports_external.string(),
@@ -69916,6 +70285,7 @@ var OhMyOpenCodeConfigSchema = exports_external.object({
69916
70285
  $schema: exports_external.string().optional(),
69917
70286
  new_task_system_enabled: exports_external.boolean().optional(),
69918
70287
  default_run_agent: exports_external.string().optional(),
70288
+ agent_order: exports_external.array(exports_external.string().max(128)).max(64).optional(),
69919
70289
  agent_definitions: AgentDefinitionsConfigSchema,
69920
70290
  disabled_mcps: exports_external.array(AnyMcpNameSchema).optional(),
69921
70291
  disabled_agents: exports_external.array(exports_external.string()).optional(),
@@ -69940,6 +70310,8 @@ var OhMyOpenCodeConfigSchema = exports_external.object({
69940
70310
  notification: NotificationConfigSchema.optional(),
69941
70311
  model_capabilities: ModelCapabilitiesConfigSchema.optional(),
69942
70312
  openclaw: OpenClawConfigSchema.optional(),
70313
+ team_mode: TeamModeConfigSchema.optional(),
70314
+ keyword_detector: KeywordDetectorConfigSchema.optional(),
69943
70315
  babysitting: BabysittingConfigSchema.optional(),
69944
70316
  git_master: GitMasterConfigSchema.default({
69945
70317
  commit_footer: true,
@@ -69957,6 +70329,98 @@ var OhMyOpenCodeConfigSchema = exports_external.object({
69957
70329
  init_shared();
69958
70330
  init_migrate_legacy_config_file();
69959
70331
  init_plugin_identity();
70332
+
70333
+ // src/shared/agent-ordering.ts
70334
+ init_agent_display_names();
70335
+ var DEFAULT_AGENT_ORDER = [
70336
+ "sisyphus",
70337
+ "hephaestus",
70338
+ "prometheus",
70339
+ "atlas"
70340
+ ];
70341
+ var KNOWN_AGENT_KEYS = new Set(Object.keys(AGENT_DISPLAY_NAMES));
70342
+ function appendUnique(target, value) {
70343
+ if (!target.includes(value)) {
70344
+ target.push(value);
70345
+ }
70346
+ }
70347
+ function validateAgentOrder(agentOrder) {
70348
+ const order = [];
70349
+ const invalid = [];
70350
+ const duplicates = [];
70351
+ const seen = new Set;
70352
+ for (const rawName of agentOrder ?? []) {
70353
+ const trimmed = rawName.trim();
70354
+ if (trimmed.length === 0) {
70355
+ invalid.push(rawName);
70356
+ continue;
70357
+ }
70358
+ const configKey = getAgentConfigKey(trimmed);
70359
+ if (!KNOWN_AGENT_KEYS.has(configKey)) {
70360
+ invalid.push(rawName);
70361
+ continue;
70362
+ }
70363
+ if (seen.has(configKey)) {
70364
+ duplicates.push(rawName);
70365
+ continue;
70366
+ }
70367
+ seen.add(configKey);
70368
+ order.push(configKey);
70369
+ }
70370
+ for (const configKey of DEFAULT_AGENT_ORDER) {
70371
+ appendUnique(order, configKey);
70372
+ }
70373
+ return { order, invalid, duplicates };
70374
+ }
70375
+
70376
+ // src/plugin-config.ts
70377
+ var CONTROL_CHARACTERS_REGEX = /[\u0000-\u001F\u007F-\u009F\u202A-\u202E\u2066-\u2069]/g;
70378
+ var MAX_AGENT_ORDER_WARNING_VALUES = 10;
70379
+ var MAX_AGENT_ORDER_WARNING_VALUE_LENGTH = 80;
70380
+ function formatAgentOrderWarningValues(values) {
70381
+ const displayedValues = values.slice(0, MAX_AGENT_ORDER_WARNING_VALUES).map((value) => {
70382
+ const sanitized = value.replace(CONTROL_CHARACTERS_REGEX, "");
70383
+ const truncated = sanitized.length > MAX_AGENT_ORDER_WARNING_VALUE_LENGTH ? `${sanitized.slice(0, MAX_AGENT_ORDER_WARNING_VALUE_LENGTH)}...` : sanitized;
70384
+ return JSON.stringify(truncated);
70385
+ });
70386
+ const remaining = values.length - displayedValues.length;
70387
+ if (remaining > 0) {
70388
+ displayedValues.push(`(+${remaining} more)`);
70389
+ }
70390
+ return displayedValues.join(", ");
70391
+ }
70392
+ function addAgentOrderWarnings(configPath, agentOrder) {
70393
+ if (!agentOrder)
70394
+ return;
70395
+ const validation = validateAgentOrder(agentOrder);
70396
+ const messages = [];
70397
+ if (validation.invalid.length > 0) {
70398
+ messages.push(`unknown agent names ignored: ${formatAgentOrderWarningValues(validation.invalid)}`);
70399
+ }
70400
+ if (validation.duplicates.length > 0) {
70401
+ messages.push(`duplicate agent names ignored: ${formatAgentOrderWarningValues(validation.duplicates)}`);
70402
+ }
70403
+ if (messages.length === 0)
70404
+ return;
70405
+ addConfigLoadError({
70406
+ path: configPath,
70407
+ error: `agent_order warning - ${messages.join("; ")}`
70408
+ });
70409
+ }
70410
+ function resolveHomeDirectory() {
70411
+ return process.env.HOME ?? process.env.USERPROFILE ?? homedir5();
70412
+ }
70413
+ function resolveConfigPathAfterLegacyMigration(detectedPath) {
70414
+ if (!path6.basename(detectedPath).startsWith(LEGACY_CONFIG_BASENAME)) {
70415
+ return detectedPath;
70416
+ }
70417
+ const migrated = migrateLegacyConfigFile(detectedPath);
70418
+ const canonicalPath = path6.join(path6.dirname(detectedPath), `${CONFIG_BASENAME}${path6.extname(detectedPath)}`);
70419
+ if (migrated || fs4.existsSync(canonicalPath)) {
70420
+ return canonicalPath;
70421
+ }
70422
+ return detectedPath;
70423
+ }
69960
70424
  function loadExplicitGitMasterOverrides(configPath) {
69961
70425
  try {
69962
70426
  if (!fs4.existsSync(configPath)) {
@@ -70024,6 +70488,7 @@ function loadConfigFromPath(configPath, _ctx) {
70024
70488
  migrateConfigFile(configPath, rawConfig);
70025
70489
  const result = OhMyOpenCodeConfigSchema.safeParse(rawConfig);
70026
70490
  if (result.success) {
70491
+ addAgentOrderWarnings(configPath, result.data.agent_order);
70027
70492
  log(`Config loaded from ${configPath}`, { agents: result.data.agents });
70028
70493
  return result.data;
70029
70494
  }
@@ -70035,6 +70500,7 @@ function loadConfigFromPath(configPath, _ctx) {
70035
70500
  });
70036
70501
  const partialResult = parseConfigPartially(rawConfig);
70037
70502
  if (partialResult) {
70503
+ addAgentOrderWarnings(configPath, partialResult.agent_order);
70038
70504
  log(`Partial config loaded from ${configPath}`, { agents: partialResult.agents });
70039
70505
  return partialResult;
70040
70506
  }
@@ -70053,6 +70519,7 @@ function mergeConfigs(base, override) {
70053
70519
  ...override,
70054
70520
  agents: deepMerge(base.agents, override.agents),
70055
70521
  categories: deepMerge(base.categories, override.categories),
70522
+ team_mode: deepMerge(base.team_mode, override.team_mode),
70056
70523
  agent_definitions: [
70057
70524
  ...new Set([
70058
70525
  ...base.agent_definitions ?? [],
@@ -70107,58 +70574,70 @@ function mergeConfigs(base, override) {
70107
70574
  function loadPluginConfig(directory, ctx) {
70108
70575
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
70109
70576
  const userDetected = detectPluginConfigFile(configDir);
70110
- let userConfigPath = userDetected.format !== "none" ? userDetected.path : path5.join(configDir, `${CONFIG_BASENAME}.json`);
70577
+ let userConfigPath = userDetected.format !== "none" ? userDetected.path : path6.join(configDir, `${CONFIG_BASENAME}.json`);
70111
70578
  if (userDetected.legacyPath) {
70112
70579
  log("Canonical plugin config detected alongside legacy config. Remove the legacy file to avoid confusion.", {
70113
70580
  canonicalPath: userDetected.path,
70114
70581
  legacyPath: userDetected.legacyPath
70115
70582
  });
70116
70583
  }
70117
- if (userDetected.format !== "none" && path5.basename(userDetected.path).startsWith(LEGACY_CONFIG_BASENAME)) {
70118
- const migrated = migrateLegacyConfigFile(userDetected.path);
70119
- const canonicalPath = path5.join(path5.dirname(userDetected.path), `${CONFIG_BASENAME}${path5.extname(userDetected.path)}`);
70120
- if (migrated || fs4.existsSync(canonicalPath)) {
70121
- userConfigPath = canonicalPath;
70122
- }
70123
- }
70124
- const projectBasePath = path5.join(directory, ".opencode");
70125
- const projectDetected = detectPluginConfigFile(projectBasePath);
70126
- let projectConfigPath = projectDetected.format !== "none" ? projectDetected.path : path5.join(projectBasePath, `${CONFIG_BASENAME}.json`);
70127
- if (projectDetected.legacyPath) {
70128
- log("Canonical plugin config detected alongside legacy config. Remove the legacy file to avoid confusion.", {
70129
- canonicalPath: projectDetected.path,
70130
- legacyPath: projectDetected.legacyPath
70131
- });
70132
- }
70133
- if (projectDetected.format !== "none" && path5.basename(projectDetected.path).startsWith(LEGACY_CONFIG_BASENAME)) {
70134
- const projectMigrated = migrateLegacyConfigFile(projectDetected.path);
70135
- const canonicalProjectPath = path5.join(path5.dirname(projectDetected.path), `${CONFIG_BASENAME}${path5.extname(projectDetected.path)}`);
70136
- if (projectMigrated || fs4.existsSync(canonicalProjectPath)) {
70137
- projectConfigPath = canonicalProjectPath;
70584
+ if (userDetected.format !== "none") {
70585
+ userConfigPath = resolveConfigPathAfterLegacyMigration(userConfigPath);
70586
+ }
70587
+ const homeDirectory = resolveHomeDirectory();
70588
+ const stopDirectory = containsPath(homeDirectory, directory) ? homeDirectory : directory;
70589
+ const ancestorConfigPathsNearestFirst = findProjectOpencodePluginConfigFiles(directory, stopDirectory);
70590
+ log("Walked ancestor plugin configs", {
70591
+ paths: ancestorConfigPathsNearestFirst,
70592
+ count: ancestorConfigPathsNearestFirst.length,
70593
+ stopDirectory
70594
+ });
70595
+ const canonicalAncestorPathsNearestFirst = ancestorConfigPathsNearestFirst.map((ancestorPath) => {
70596
+ const opencodeDir = path6.dirname(ancestorPath);
70597
+ const ancestorDetected = detectPluginConfigFile(opencodeDir);
70598
+ if (ancestorDetected.legacyPath) {
70599
+ log("Canonical plugin config detected alongside legacy config. Remove the legacy file to avoid confusion.", {
70600
+ canonicalPath: ancestorDetected.path,
70601
+ legacyPath: ancestorDetected.legacyPath
70602
+ });
70138
70603
  }
70139
- }
70604
+ return resolveConfigPathAfterLegacyMigration(ancestorPath);
70605
+ });
70140
70606
  const userConfig = loadConfigFromPath(userConfigPath, ctx);
70141
70607
  const userGitMasterOverrides = loadExplicitGitMasterOverrides(userConfigPath);
70142
70608
  if (userConfig?.agent_definitions) {
70143
70609
  userConfig.agent_definitions = resolveAgentDefinitionPaths(userConfig.agent_definitions, configDir, null);
70144
70610
  }
70145
70611
  let config2 = userConfig ?? OhMyOpenCodeConfigSchema.parse({});
70612
+ const canonicalAncestorPathsFarthestFirst = [...canonicalAncestorPathsNearestFirst].reverse();
70146
70613
  const defaultGitMaster = OhMyOpenCodeConfigSchema.parse({}).git_master;
70147
- const projectConfig = loadConfigFromPath(projectConfigPath, ctx);
70148
- const projectGitMasterOverrides = loadExplicitGitMasterOverrides(projectConfigPath);
70149
- if (projectConfig?.agent_definitions) {
70150
- projectConfig.agent_definitions = resolveAgentDefinitionPaths(projectConfig.agent_definitions, projectBasePath, directory);
70151
- }
70152
- if (projectConfig) {
70153
- config2 = mergeConfigs(config2, projectConfig);
70614
+ const ancestorGitMasterOverridesFarthestFirst = [];
70615
+ for (const ancestorPath of canonicalAncestorPathsFarthestFirst) {
70616
+ const ancestorConfig = loadConfigFromPath(ancestorPath, ctx);
70617
+ const ancestorOverrides = loadExplicitGitMasterOverrides(ancestorPath);
70618
+ if (ancestorConfig?.agent_definitions) {
70619
+ const ancestorBasePath = path6.dirname(ancestorPath);
70620
+ const ancestorDir = path6.dirname(ancestorBasePath);
70621
+ ancestorConfig.agent_definitions = resolveAgentDefinitionPaths(ancestorConfig.agent_definitions, ancestorBasePath, ancestorDir);
70622
+ }
70623
+ if (ancestorConfig) {
70624
+ config2 = mergeConfigs(config2, ancestorConfig);
70625
+ }
70626
+ if (ancestorOverrides) {
70627
+ ancestorGitMasterOverridesFarthestFirst.push(ancestorOverrides);
70628
+ }
70154
70629
  }
70155
- if (userGitMasterOverrides || projectGitMasterOverrides) {
70630
+ if (userGitMasterOverrides || ancestorGitMasterOverridesFarthestFirst.length > 0) {
70631
+ const mergedAncestorGitMaster = {};
70632
+ for (const override of ancestorGitMasterOverridesFarthestFirst) {
70633
+ Object.assign(mergedAncestorGitMaster, override);
70634
+ }
70156
70635
  config2 = {
70157
70636
  ...config2,
70158
70637
  git_master: {
70159
70638
  ...defaultGitMaster,
70160
70639
  ...userGitMasterOverrides ?? {},
70161
- ...projectGitMasterOverrides ?? {}
70640
+ ...mergedAncestorGitMaster
70162
70641
  }
70163
70642
  };
70164
70643
  }
@@ -70178,7 +70657,7 @@ function loadPluginConfig(directory, ctx) {
70178
70657
  // node_modules/@opencode-ai/sdk/dist/gen/core/serverSentEvents.gen.js
70179
70658
  var createSseClient = ({ onSseError, onSseEvent, responseTransformer, responseValidator, sseDefaultRetryDelay, sseMaxRetryAttempts, sseMaxRetryDelay, sseSleepFn, url: url2, ...options }) => {
70180
70659
  let lastEventId;
70181
- const sleep = sseSleepFn ?? ((ms) => new Promise((resolve4) => setTimeout(resolve4, ms)));
70660
+ const sleep = sseSleepFn ?? ((ms) => new Promise((resolve5) => setTimeout(resolve5, ms)));
70182
70661
  const createStream = async function* () {
70183
70662
  let retryDelay = sseDefaultRetryDelay ?? 3000;
70184
70663
  let attempt = 0;
@@ -70409,7 +70888,7 @@ var serializeObjectParam = ({ allowReserved, explode, name, style, value, valueO
70409
70888
 
70410
70889
  // node_modules/@opencode-ai/sdk/dist/gen/core/utils.gen.js
70411
70890
  var PATH_PARAM_RE = /\{[^{}]+\}/g;
70412
- var defaultPathSerializer = ({ path: path6, url: _url2 }) => {
70891
+ var defaultPathSerializer = ({ path: path7, url: _url2 }) => {
70413
70892
  let url2 = _url2;
70414
70893
  const matches = _url2.match(PATH_PARAM_RE);
70415
70894
  if (matches) {
@@ -70428,7 +70907,7 @@ var defaultPathSerializer = ({ path: path6, url: _url2 }) => {
70428
70907
  name = name.substring(1);
70429
70908
  style = "matrix";
70430
70909
  }
70431
- const value = path6[name];
70910
+ const value = path7[name];
70432
70911
  if (value === undefined || value === null) {
70433
70912
  continue;
70434
70913
  }
@@ -70459,11 +70938,11 @@ var defaultPathSerializer = ({ path: path6, url: _url2 }) => {
70459
70938
  }
70460
70939
  return url2;
70461
70940
  };
70462
- var getUrl = ({ baseUrl, path: path6, query, querySerializer, url: _url2 }) => {
70941
+ var getUrl = ({ baseUrl, path: path7, query, querySerializer, url: _url2 }) => {
70463
70942
  const pathUrl = _url2.startsWith("/") ? _url2 : `/${_url2}`;
70464
70943
  let url2 = (baseUrl ?? "") + pathUrl;
70465
- if (path6) {
70466
- url2 = defaultPathSerializer({ path: path6, url: url2 });
70944
+ if (path7) {
70945
+ url2 = defaultPathSerializer({ path: path7, url: url2 });
70467
70946
  }
70468
70947
  let search = query ? querySerializer(query) : "";
70469
70948
  if (search.startsWith("?")) {
@@ -71613,7 +72092,7 @@ async function createOpencodeServer(options) {
71613
72092
  }
71614
72093
  });
71615
72094
  let clear = () => {};
71616
- const url2 = await new Promise((resolve4, reject) => {
72095
+ const url2 = await new Promise((resolve5, reject) => {
71617
72096
  const id = setTimeout(() => {
71618
72097
  clear();
71619
72098
  stop(proc);
@@ -71639,7 +72118,7 @@ async function createOpencodeServer(options) {
71639
72118
  }
71640
72119
  clearTimeout(id);
71641
72120
  resolved = true;
71642
- resolve4(match[1]);
72121
+ resolve5(match[1]);
71643
72122
  return;
71644
72123
  }
71645
72124
  }
@@ -71694,7 +72173,7 @@ var import_picocolors10 = __toESM(require_picocolors(), 1);
71694
72173
 
71695
72174
  // src/cli/run/opencode-binary-resolver.ts
71696
72175
  init_spawn_with_windows_hide();
71697
- import { delimiter, dirname as dirname7, join as join17 } from "path";
72176
+ import { delimiter, dirname as dirname9, join as join19 } from "path";
71698
72177
  var OPENCODE_COMMANDS = ["opencode", "opencode-desktop"];
71699
72178
  var WINDOWS_SUFFIXES = ["", ".exe", ".cmd", ".bat", ".ps1"];
71700
72179
  function getCommandCandidates(platform) {
@@ -71717,7 +72196,7 @@ function collectCandidateBinaryPaths(pathEnv, which = Bun.which, platform = proc
71717
72196
  }
71718
72197
  for (const entry of (pathEnv ?? "").split(delimiter).filter(Boolean)) {
71719
72198
  for (const command of commandCandidates) {
71720
- addCandidate(join17(entry, command));
72199
+ addCandidate(join19(entry, command));
71721
72200
  }
71722
72201
  }
71723
72202
  return candidates;
@@ -71744,7 +72223,7 @@ async function findWorkingOpencodeBinary(pathEnv = process.env.PATH, probe = can
71744
72223
  return null;
71745
72224
  }
71746
72225
  function buildPathWithBinaryFirst(pathEnv, binaryPath) {
71747
- const preferredDir = dirname7(binaryPath);
72226
+ const preferredDir = dirname9(binaryPath);
71748
72227
  const existing = (pathEnv ?? "").split(delimiter).filter((entry) => entry.length > 0 && entry !== preferredDir);
71749
72228
  return [preferredDir, ...existing].join(delimiter);
71750
72229
  }
@@ -71897,7 +72376,7 @@ async function resolveSession(options) {
71897
72376
  if (attempt < SESSION_CREATE_MAX_RETRIES) {
71898
72377
  const delay = SESSION_CREATE_RETRY_DELAY_MS * attempt;
71899
72378
  console.log(import_picocolors11.default.dim(` Retrying in ${delay}ms...`));
71900
- await new Promise((resolve4) => setTimeout(resolve4, delay));
72379
+ await new Promise((resolve5) => setTimeout(resolve5, delay));
71901
72380
  }
71902
72381
  continue;
71903
72382
  }
@@ -71908,7 +72387,7 @@ async function resolveSession(options) {
71908
72387
  if (attempt < SESSION_CREATE_MAX_RETRIES) {
71909
72388
  const delay = SESSION_CREATE_RETRY_DELAY_MS * attempt;
71910
72389
  console.log(import_picocolors11.default.dim(` Retrying in ${delay}ms...`));
71911
- await new Promise((resolve4) => setTimeout(resolve4, delay));
72390
+ await new Promise((resolve5) => setTimeout(resolve5, delay));
71912
72391
  }
71913
72392
  }
71914
72393
  throw new Error("Failed to create session after all retries");
@@ -72119,19 +72598,95 @@ var BOULDER_STATE_PATH = `${BOULDER_DIR}/${BOULDER_FILE}`;
72119
72598
  var NOTEPAD_DIR = "notepads";
72120
72599
  var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
72121
72600
  // src/features/boulder-state/storage.ts
72122
- import { existsSync as existsSync19, readFileSync as readFileSync13, writeFileSync as writeFileSync5, mkdirSync as mkdirSync7, readdirSync as readdirSync3 } from "fs";
72123
- import { dirname as dirname8, join as join18, basename as basename5 } from "path";
72601
+ import { existsSync as existsSync21, readFileSync as readFileSync14, writeFileSync as writeFileSync5, mkdirSync as mkdirSync7, readdirSync as readdirSync3 } from "fs";
72602
+ import { basename as basename5, dirname as dirname10, isAbsolute as isAbsolute3, join as join20, relative as relative2, resolve as resolve5 } from "path";
72124
72603
  var RESERVED_KEYS = new Set(["__proto__", "prototype", "constructor"]);
72604
+ function parseIsoToMs(value) {
72605
+ if (!value) {
72606
+ return null;
72607
+ }
72608
+ const parsed = Date.parse(value);
72609
+ return Number.isNaN(parsed) ? null : parsed;
72610
+ }
72611
+ function buildWorkFromMirror(state) {
72612
+ const planName = state.plan_name ?? getPlanName(state.active_plan);
72613
+ const workId = `${planName}-legacy`;
72614
+ return {
72615
+ work_id: workId,
72616
+ active_plan: state.active_plan,
72617
+ plan_name: planName,
72618
+ status: state.status,
72619
+ started_at: state.started_at,
72620
+ ended_at: state.ended_at,
72621
+ elapsed_ms: state.elapsed_ms,
72622
+ updated_at: state.updated_at,
72623
+ session_ids: Array.isArray(state.session_ids) ? [...state.session_ids] : [],
72624
+ session_origins: state.session_origins,
72625
+ agent: state.agent,
72626
+ worktree_path: state.worktree_path,
72627
+ task_sessions: state.task_sessions
72628
+ };
72629
+ }
72630
+ function projectWorkToMirror(state, work) {
72631
+ state.active_plan = work.active_plan;
72632
+ state.plan_name = work.plan_name;
72633
+ state.status = work.status;
72634
+ state.started_at = work.started_at;
72635
+ state.ended_at = work.ended_at;
72636
+ state.elapsed_ms = work.elapsed_ms;
72637
+ state.updated_at = work.updated_at;
72638
+ state.session_ids = [...work.session_ids];
72639
+ state.session_origins = work.session_origins ? { ...work.session_origins } : {};
72640
+ state.agent = work.agent;
72641
+ state.worktree_path = work.worktree_path;
72642
+ state.task_sessions = work.task_sessions ? { ...work.task_sessions } : {};
72643
+ }
72644
+ function selectMirrorWork(state) {
72645
+ const works = getBoulderWorks(state);
72646
+ if (works.length === 0) {
72647
+ return null;
72648
+ }
72649
+ if (state.active_work_id) {
72650
+ const matched = works.find((work) => work.work_id === state.active_work_id);
72651
+ if (matched) {
72652
+ return matched;
72653
+ }
72654
+ }
72655
+ const sorted = [...works].sort((left, right) => {
72656
+ const leftMs = parseIsoToMs(left.updated_at ?? left.started_at) ?? 0;
72657
+ const rightMs = parseIsoToMs(right.updated_at ?? right.started_at) ?? 0;
72658
+ return rightMs - leftMs;
72659
+ });
72660
+ return sorted[0] ?? null;
72661
+ }
72125
72662
  function getBoulderFilePath(directory) {
72126
- return join18(directory, BOULDER_DIR, BOULDER_FILE);
72663
+ return join20(directory, BOULDER_DIR, BOULDER_FILE);
72664
+ }
72665
+ function resolveTrackedPath(baseDirectory, trackedPath) {
72666
+ return isAbsolute3(trackedPath) ? resolve5(trackedPath) : resolve5(baseDirectory, trackedPath);
72667
+ }
72668
+ function resolveBoulderPlanPath(directory, state) {
72669
+ const absolutePlanPath = resolveTrackedPath(directory, state.active_plan);
72670
+ const worktreePath = state.worktree_path?.trim();
72671
+ if (!worktreePath) {
72672
+ return absolutePlanPath;
72673
+ }
72674
+ const absoluteDirectory = resolve5(directory);
72675
+ const relativePlanPath = relative2(absoluteDirectory, absolutePlanPath);
72676
+ if (relativePlanPath.length === 0 || relativePlanPath.startsWith("..") || isAbsolute3(relativePlanPath)) {
72677
+ return absolutePlanPath;
72678
+ }
72679
+ const absoluteWorktreePath = resolveTrackedPath(directory, worktreePath);
72680
+ const worktreePlanPath = resolve5(absoluteWorktreePath, relativePlanPath);
72681
+ return existsSync21(worktreePlanPath) ? worktreePlanPath : absolutePlanPath;
72127
72682
  }
72128
72683
  function readBoulderState(directory) {
72129
72684
  const filePath = getBoulderFilePath(directory);
72130
- if (!existsSync19(filePath)) {
72685
+ if (!existsSync21(filePath)) {
72131
72686
  return null;
72132
72687
  }
72133
72688
  try {
72134
- const content = readFileSync13(filePath, "utf-8");
72689
+ const content = readFileSync14(filePath, "utf-8");
72135
72690
  const parsed = JSON.parse(content);
72136
72691
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
72137
72692
  return null;
@@ -72151,7 +72706,13 @@ function readBoulderState(directory) {
72151
72706
  if (!parsed.task_sessions || typeof parsed.task_sessions !== "object" || Array.isArray(parsed.task_sessions)) {
72152
72707
  parsed.task_sessions = {};
72153
72708
  }
72154
- return parsed;
72709
+ const state = parsed;
72710
+ const mirrorWork = selectMirrorWork(state);
72711
+ if (mirrorWork) {
72712
+ state.active_work_id = mirrorWork.work_id;
72713
+ projectWorkToMirror(state, mirrorWork);
72714
+ }
72715
+ return state;
72155
72716
  } catch {
72156
72717
  return null;
72157
72718
  }
@@ -72164,11 +72725,11 @@ var CHECKED_CHECKBOX_PATTERN = /^(\s*)[-*]\s*\[[xX]\]\s*(.+)$/;
72164
72725
  var TODO_TASK_PATTERN = /^\d+\.\s+/;
72165
72726
  var FINAL_WAVE_TASK_PATTERN = /^F\d+\.\s+/i;
72166
72727
  function getPlanProgress(planPath) {
72167
- if (!existsSync19(planPath)) {
72168
- return { total: 0, completed: 0, isComplete: true };
72728
+ if (!existsSync21(planPath)) {
72729
+ return { total: 0, completed: 0, isComplete: false };
72169
72730
  }
72170
72731
  try {
72171
- const content = readFileSync13(planPath, "utf-8");
72732
+ const content = readFileSync14(planPath, "utf-8");
72172
72733
  const lines = content.split(/\r?\n/);
72173
72734
  const hasStructuredSections = lines.some((line) => TODO_HEADING_PATTERN.test(line) || FINAL_VERIFICATION_HEADING_PATTERN.test(line));
72174
72735
  if (hasStructuredSections) {
@@ -72176,7 +72737,7 @@ function getPlanProgress(planPath) {
72176
72737
  }
72177
72738
  return getSimplePlanProgress(content);
72178
72739
  } catch {
72179
- return { total: 0, completed: 0, isComplete: true };
72740
+ return { total: 0, completed: 0, isComplete: false };
72180
72741
  }
72181
72742
  }
72182
72743
  function getStructuredPlanProgress(lines) {
@@ -72227,6 +72788,76 @@ function getSimplePlanProgress(content) {
72227
72788
  isComplete: total > 0 && completed === total
72228
72789
  };
72229
72790
  }
72791
+ function getPlanName(planPath) {
72792
+ return basename5(planPath, ".md");
72793
+ }
72794
+ function getBoulderWorks(state) {
72795
+ if (state.works && typeof state.works === "object") {
72796
+ return Object.values(state.works);
72797
+ }
72798
+ if (!state.active_plan || !state.plan_name || !state.started_at) {
72799
+ return [];
72800
+ }
72801
+ return [buildWorkFromMirror(state)];
72802
+ }
72803
+ function resolveBoulderPlanPathForWork(directory, work) {
72804
+ return resolveBoulderPlanPath(directory, work);
72805
+ }
72806
+ // src/features/boulder-state/top-level-task.ts
72807
+ import { existsSync as existsSync22, readFileSync as readFileSync15 } from "fs";
72808
+ var TODO_HEADING_PATTERN2 = /^##\s+TODOs\b/i;
72809
+ var FINAL_VERIFICATION_HEADING_PATTERN2 = /^##\s+Final Verification Wave\b/i;
72810
+ var SECOND_LEVEL_HEADING_PATTERN2 = /^##\s+/;
72811
+ var UNCHECKED_CHECKBOX_PATTERN2 = /^(\s*)[-*]\s*\[\s*\]\s*(.+)$/;
72812
+ var TODO_TASK_PATTERN2 = /^(\d+)\.\s+(.+)$/;
72813
+ var FINAL_WAVE_TASK_PATTERN2 = /^(F\d+)\.\s+(.+)$/i;
72814
+ function buildTaskRef(section, taskLabel) {
72815
+ const pattern = section === "todo" ? TODO_TASK_PATTERN2 : FINAL_WAVE_TASK_PATTERN2;
72816
+ const match = taskLabel.match(pattern);
72817
+ if (!match) {
72818
+ return null;
72819
+ }
72820
+ const rawLabel = match[1];
72821
+ const title = match[2].trim();
72822
+ return {
72823
+ key: `${section}:${rawLabel.toLowerCase()}`,
72824
+ section,
72825
+ label: rawLabel,
72826
+ title
72827
+ };
72828
+ }
72829
+ function readCurrentTopLevelTask(planPath) {
72830
+ if (!existsSync22(planPath)) {
72831
+ return null;
72832
+ }
72833
+ try {
72834
+ const content = readFileSync15(planPath, "utf-8");
72835
+ const lines = content.split(/\r?\n/);
72836
+ let section = "other";
72837
+ for (const line of lines) {
72838
+ if (SECOND_LEVEL_HEADING_PATTERN2.test(line)) {
72839
+ section = TODO_HEADING_PATTERN2.test(line) ? "todo" : FINAL_VERIFICATION_HEADING_PATTERN2.test(line) ? "final-wave" : "other";
72840
+ }
72841
+ const uncheckedTaskMatch = line.match(UNCHECKED_CHECKBOX_PATTERN2);
72842
+ if (!uncheckedTaskMatch) {
72843
+ continue;
72844
+ }
72845
+ if (uncheckedTaskMatch[1].length > 0) {
72846
+ continue;
72847
+ }
72848
+ if (section !== "todo" && section !== "final-wave") {
72849
+ continue;
72850
+ }
72851
+ const taskRef = buildTaskRef(section, uncheckedTaskMatch[2].trim());
72852
+ if (taskRef) {
72853
+ return taskRef;
72854
+ }
72855
+ }
72856
+ return null;
72857
+ } catch {
72858
+ return null;
72859
+ }
72860
+ }
72230
72861
  // src/features/claude-code-session-state/state.ts
72231
72862
  init_agent_display_names();
72232
72863
  var subagentSessions = new Set;
@@ -72240,17 +72871,17 @@ function getSessionAgent(sessionID) {
72240
72871
  // src/features/run-continuation-state/constants.ts
72241
72872
  var CONTINUATION_MARKER_DIR = ".sisyphus/run-continuation";
72242
72873
  // src/features/run-continuation-state/storage.ts
72243
- import { existsSync as existsSync20, mkdirSync as mkdirSync8, readFileSync as readFileSync14, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "fs";
72244
- import { join as join19 } from "path";
72874
+ import { existsSync as existsSync23, mkdirSync as mkdirSync8, readFileSync as readFileSync16, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "fs";
72875
+ import { join as join21 } from "path";
72245
72876
  function getMarkerPath(directory, sessionID) {
72246
- return join19(directory, CONTINUATION_MARKER_DIR, `${sessionID}.json`);
72877
+ return join21(directory, CONTINUATION_MARKER_DIR, `${sessionID}.json`);
72247
72878
  }
72248
72879
  function readContinuationMarker(directory, sessionID) {
72249
72880
  const markerPath = getMarkerPath(directory, sessionID);
72250
- if (!existsSync20(markerPath))
72881
+ if (!existsSync23(markerPath))
72251
72882
  return null;
72252
72883
  try {
72253
- const raw = readFileSync14(markerPath, "utf-8");
72884
+ const raw = readFileSync16(markerPath, "utf-8");
72254
72885
  const parsed = JSON.parse(raw);
72255
72886
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
72256
72887
  return null;
@@ -72311,8 +72942,8 @@ async function isSessionInBoulderLineage(input) {
72311
72942
  // src/hooks/atlas/session-last-agent.ts
72312
72943
  init_shared();
72313
72944
  init_compaction_marker();
72314
- import { readFileSync as readFileSync15, readdirSync as readdirSync4 } from "fs";
72315
- import { join as join20 } from "path";
72945
+ import { readFileSync as readFileSync17, readdirSync as readdirSync4 } from "fs";
72946
+ import { join as join22 } from "path";
72316
72947
  var defaultSessionLastAgentDeps = {
72317
72948
  getMessageDir,
72318
72949
  isSqliteBackend,
@@ -72360,7 +72991,7 @@ async function getLastAgentFromSession(sessionID, client3, deps = {}) {
72360
72991
  try {
72361
72992
  const messages = readdirSync4(messageDir).filter((fileName) => fileName.endsWith(".json")).map((fileName) => {
72362
72993
  try {
72363
- const content = readFileSync15(join20(messageDir, fileName), "utf-8");
72994
+ const content = readFileSync17(join22(messageDir, fileName), "utf-8");
72364
72995
  const parsed = JSON.parse(content);
72365
72996
  return {
72366
72997
  fileName,
@@ -72393,8 +73024,8 @@ init_agent_display_names();
72393
73024
 
72394
73025
  // src/hooks/ralph-loop/storage.ts
72395
73026
  init_frontmatter();
72396
- import { existsSync as existsSync21, readFileSync as readFileSync16, writeFileSync as writeFileSync7, unlinkSync as unlinkSync3, mkdirSync as mkdirSync9 } from "fs";
72397
- import { dirname as dirname9, join as join21 } from "path";
73027
+ import { existsSync as existsSync24, readFileSync as readFileSync18, writeFileSync as writeFileSync7, unlinkSync as unlinkSync3, mkdirSync as mkdirSync9 } from "fs";
73028
+ import { dirname as dirname11, join as join23 } from "path";
72398
73029
 
72399
73030
  // src/hooks/ralph-loop/constants.ts
72400
73031
  var DEFAULT_STATE_FILE = ".sisyphus/ralph-loop.local.md";
@@ -72403,15 +73034,15 @@ var DEFAULT_COMPLETION_PROMISE = "DONE";
72403
73034
 
72404
73035
  // src/hooks/ralph-loop/storage.ts
72405
73036
  function getStateFilePath(directory, customPath) {
72406
- return customPath ? join21(directory, customPath) : join21(directory, DEFAULT_STATE_FILE);
73037
+ return customPath ? join23(directory, customPath) : join23(directory, DEFAULT_STATE_FILE);
72407
73038
  }
72408
73039
  function readState(directory, customPath) {
72409
73040
  const filePath = getStateFilePath(directory, customPath);
72410
- if (!existsSync21(filePath)) {
73041
+ if (!existsSync24(filePath)) {
72411
73042
  return null;
72412
73043
  }
72413
73044
  try {
72414
- const content = readFileSync16(filePath, "utf-8");
73045
+ const content = readFileSync18(filePath, "utf-8");
72415
73046
  const { data, body } = parseFrontmatter(content);
72416
73047
  const active = data.active;
72417
73048
  const iteration = data.iteration;
@@ -72467,7 +73098,7 @@ async function hasActiveBoulderContinuation(directory, sessionID, client3) {
72467
73098
  const boulder = readBoulderState(directory);
72468
73099
  if (!boulder)
72469
73100
  return false;
72470
- const progress = getPlanProgress(boulder.active_plan);
73101
+ const progress = getPlanProgress(resolveBoulderPlanPath(directory, boulder));
72471
73102
  if (progress.isComplete)
72472
73103
  return false;
72473
73104
  if (!client3)
@@ -72625,7 +73256,7 @@ async function pollForCompletion(ctx, eventState, abortController, options = {})
72625
73256
  let secondaryTimeoutChecked = false;
72626
73257
  const pollStartTimestamp = Date.now();
72627
73258
  while (!abortController.signal.aborted) {
72628
- await new Promise((resolve4) => setTimeout(resolve4, pollIntervalMs));
73259
+ await new Promise((resolve6) => setTimeout(resolve6, pollIntervalMs));
72629
73260
  if (abortController.signal.aborted) {
72630
73261
  return 130;
72631
73262
  }
@@ -72856,7 +73487,7 @@ import os3 from "os";
72856
73487
  import { createHash } from "crypto";
72857
73488
 
72858
73489
  // node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
72859
- import { dirname as dirname10, posix, sep } from "path";
73490
+ import { dirname as dirname12, posix, sep } from "path";
72860
73491
  function createModulerModifier() {
72861
73492
  const getModuleFromFileName = createGetModuleFromFilename();
72862
73493
  return async (frames) => {
@@ -72865,7 +73496,7 @@ function createModulerModifier() {
72865
73496
  return frames;
72866
73497
  };
72867
73498
  }
72868
- function createGetModuleFromFilename(basePath = process.argv[1] ? dirname10(process.argv[1]) : process.cwd(), isWindows = sep === "\\") {
73499
+ function createGetModuleFromFilename(basePath = process.argv[1] ? dirname12(process.argv[1]) : process.cwd(), isWindows = sep === "\\") {
72869
73500
  const normalizedBase = isWindows ? normalizeWindowsPath(basePath) : basePath;
72870
73501
  return (filename) => {
72871
73502
  if (!filename)
@@ -72887,8 +73518,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? dirname10(proc
72887
73518
  return decodedFile;
72888
73519
  };
72889
73520
  }
72890
- function normalizeWindowsPath(path6) {
72891
- return path6.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
73521
+ function normalizeWindowsPath(path7) {
73522
+ return path7.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
72892
73523
  }
72893
73524
 
72894
73525
  // node_modules/@posthog/core/dist/featureFlagUtils.mjs
@@ -75203,15 +75834,15 @@ async function addSourceContext(frames) {
75203
75834
  LRU_FILE_CONTENTS_CACHE.reduce();
75204
75835
  return frames;
75205
75836
  }
75206
- function getContextLinesFromFile(path6, ranges, output) {
75207
- return new Promise((resolve4) => {
75208
- const stream = createReadStream(path6);
75837
+ function getContextLinesFromFile(path7, ranges, output) {
75838
+ return new Promise((resolve6) => {
75839
+ const stream = createReadStream(path7);
75209
75840
  const lineReaded = createInterface2({
75210
75841
  input: stream
75211
75842
  });
75212
75843
  function destroyStreamAndResolve() {
75213
75844
  stream.destroy();
75214
- resolve4();
75845
+ resolve6();
75215
75846
  }
75216
75847
  let lineNumber = 0;
75217
75848
  let currentRangeIndex = 0;
@@ -75221,7 +75852,7 @@ function getContextLinesFromFile(path6, ranges, output) {
75221
75852
  let rangeStart = range[0];
75222
75853
  let rangeEnd = range[1];
75223
75854
  function onStreamError() {
75224
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path6, 1);
75855
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(path7, 1);
75225
75856
  lineReaded.close();
75226
75857
  lineReaded.removeAllListeners();
75227
75858
  destroyStreamAndResolve();
@@ -75289,8 +75920,8 @@ function clearLineContext(frame) {
75289
75920
  delete frame.context_line;
75290
75921
  delete frame.post_context;
75291
75922
  }
75292
- function shouldSkipContextLinesForFile(path6) {
75293
- return path6.startsWith("node:") || path6.endsWith(".min.js") || path6.endsWith(".min.cjs") || path6.endsWith(".min.mjs") || path6.startsWith("data:");
75923
+ function shouldSkipContextLinesForFile(path7) {
75924
+ return path7.startsWith("node:") || path7.endsWith(".min.js") || path7.endsWith(".min.cjs") || path7.endsWith(".min.mjs") || path7.startsWith("data:");
75294
75925
  }
75295
75926
  function shouldSkipContextLinesForFrame(frame) {
75296
75927
  if (frame.lineno !== undefined && frame.lineno > MAX_CONTEXTLINES_LINENO)
@@ -76451,9 +77082,9 @@ class PostHogBackendClient extends PostHogCoreStateless {
76451
77082
  if (this.disabled || this.optedOut)
76452
77083
  return;
76453
77084
  if (!this._waitUntilCycle) {
76454
- let resolve4;
77085
+ let resolve6;
76455
77086
  const promise2 = new Promise((r2) => {
76456
- resolve4 = r2;
77087
+ resolve6 = r2;
76457
77088
  });
76458
77089
  try {
76459
77090
  waitUntil(promise2);
@@ -76461,7 +77092,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
76461
77092
  return;
76462
77093
  }
76463
77094
  this._waitUntilCycle = {
76464
- resolve: resolve4,
77095
+ resolve: resolve6,
76465
77096
  startedAt: Date.now(),
76466
77097
  timer: undefined
76467
77098
  };
@@ -76487,11 +77118,11 @@ class PostHogBackendClient extends PostHogCoreStateless {
76487
77118
  return cycle?.resolve;
76488
77119
  }
76489
77120
  async resolveWaitUntilFlush() {
76490
- const resolve4 = this._consumeWaitUntilCycle();
77121
+ const resolve6 = this._consumeWaitUntilCycle();
76491
77122
  try {
76492
77123
  await super.flush();
76493
77124
  } catch {} finally {
76494
- resolve4?.();
77125
+ resolve6?.();
76495
77126
  }
76496
77127
  }
76497
77128
  getPersistedProperty(key) {
@@ -76591,15 +77222,15 @@ class PostHogBackendClient extends PostHogCoreStateless {
76591
77222
  return true;
76592
77223
  if (this.featureFlagsPoller === undefined)
76593
77224
  return false;
76594
- return new Promise((resolve4) => {
77225
+ return new Promise((resolve6) => {
76595
77226
  const timeout = setTimeout(() => {
76596
77227
  cleanup();
76597
- resolve4(false);
77228
+ resolve6(false);
76598
77229
  }, timeoutMs);
76599
77230
  const cleanup = this._events.on("localEvaluationFlagsLoaded", (count) => {
76600
77231
  clearTimeout(timeout);
76601
77232
  cleanup();
76602
- resolve4(count > 0);
77233
+ resolve6(count > 0);
76603
77234
  });
76604
77235
  });
76605
77236
  }
@@ -76943,13 +77574,13 @@ class PostHogBackendClient extends PostHogCoreStateless {
76943
77574
  this.context?.enter(data, options);
76944
77575
  }
76945
77576
  async _shutdown(shutdownTimeoutMs) {
76946
- const resolve4 = this._consumeWaitUntilCycle();
77577
+ const resolve6 = this._consumeWaitUntilCycle();
76947
77578
  await this.featureFlagsPoller?.stopPoller(shutdownTimeoutMs);
76948
77579
  this.errorTracking.shutdown();
76949
77580
  try {
76950
77581
  return await super._shutdown(shutdownTimeoutMs);
76951
77582
  } finally {
76952
- resolve4?.();
77583
+ resolve6?.();
76953
77584
  }
76954
77585
  }
76955
77586
  async _requestRemoteConfigPayload(flagKey) {
@@ -77303,11 +77934,11 @@ init_data_path();
77303
77934
  init_logger();
77304
77935
  init_plugin_identity();
77305
77936
  init_write_file_atomically();
77306
- import { existsSync as existsSync22, mkdirSync as mkdirSync10, readFileSync as readFileSync17 } from "fs";
77307
- import { join as join22 } from "path";
77937
+ import { existsSync as existsSync25, mkdirSync as mkdirSync10, readFileSync as readFileSync19 } from "fs";
77938
+ import { join as join24 } from "path";
77308
77939
  var POSTHOG_ACTIVITY_STATE_FILE = "posthog-activity.json";
77309
77940
  function getPostHogActivityStateFilePath() {
77310
- return join22(getDataDir(), CACHE_DIR_NAME, POSTHOG_ACTIVITY_STATE_FILE);
77941
+ return join24(getDataDir(), CACHE_DIR_NAME, POSTHOG_ACTIVITY_STATE_FILE);
77311
77942
  }
77312
77943
  function getUtcDayString(date5) {
77313
77944
  return date5.toISOString().slice(0, 10);
@@ -77317,11 +77948,11 @@ function isPostHogActivityState(value) {
77317
77948
  }
77318
77949
  function readPostHogActivityState() {
77319
77950
  const stateFilePath = getPostHogActivityStateFilePath();
77320
- if (!existsSync22(stateFilePath)) {
77951
+ if (!existsSync25(stateFilePath)) {
77321
77952
  return {};
77322
77953
  }
77323
77954
  try {
77324
- const content = readFileSync17(stateFilePath, "utf-8");
77955
+ const content = readFileSync19(stateFilePath, "utf-8");
77325
77956
  const parsed = JSON.parse(content);
77326
77957
  if (!isPostHogActivityState(parsed)) {
77327
77958
  return {};
@@ -77338,7 +77969,7 @@ function readPostHogActivityState() {
77338
77969
  function writePostHogActivityState(nextState) {
77339
77970
  const stateFilePath = getPostHogActivityStateFilePath();
77340
77971
  try {
77341
- mkdirSync10(join22(getDataDir(), CACHE_DIR_NAME), { recursive: true });
77972
+ mkdirSync10(join24(getDataDir(), CACHE_DIR_NAME), { recursive: true });
77342
77973
  writeFileAtomically(stateFilePath, `${JSON.stringify(nextState, null, 2)}
77343
77974
  `);
77344
77975
  } catch (error48) {
@@ -77366,9 +77997,13 @@ function getPostHogActivityCaptureState(now = new Date) {
77366
77997
 
77367
77998
  // src/shared/posthog.ts
77368
77999
  var activityStateProviderOverride = null;
78000
+ var osProviderOverride = null;
77369
78001
  function resolveActivityState() {
77370
78002
  return (activityStateProviderOverride ?? getPostHogActivityCaptureState)();
77371
78003
  }
78004
+ function resolveOsProvider() {
78005
+ return osProviderOverride ?? os3;
78006
+ }
77372
78007
  var DEFAULT_POSTHOG_HOST = "https://us.i.posthog.com";
77373
78008
  var DEFAULT_POSTHOG_API_KEY = "phc_CFJhj5HyvA62QPhvyaUCtaq23aUfznnijg5VaaGkNk74";
77374
78009
  var NO_OP_POSTHOG = {
@@ -77399,7 +78034,7 @@ function getPostHogHost() {
77399
78034
  }
77400
78035
  function safeCpus() {
77401
78036
  try {
77402
- const cpus = os3.cpus();
78037
+ const cpus = resolveOsProvider().cpus();
77403
78038
  return { length: cpus.length, model: cpus[0]?.model };
77404
78039
  } catch {
77405
78040
  return { length: 0, model: undefined };
@@ -77407,6 +78042,7 @@ function safeCpus() {
77407
78042
  }
77408
78043
  function getSharedProperties(source) {
77409
78044
  const cpus = safeCpus();
78045
+ const osProvider = resolveOsProvider();
77410
78046
  return {
77411
78047
  platform: "oh-my-opencode",
77412
78048
  package_name: PUBLISHED_PACKAGE_NAME,
@@ -77415,13 +78051,13 @@ function getSharedProperties(source) {
77415
78051
  runtime: "bun",
77416
78052
  runtime_version: process.versions.bun ?? process.version,
77417
78053
  source,
77418
- $os: os3.platform(),
77419
- $os_version: os3.release(),
77420
- os_arch: os3.arch(),
77421
- os_type: os3.type(),
78054
+ $os: osProvider.platform(),
78055
+ $os_version: osProvider.release(),
78056
+ os_arch: osProvider.arch(),
78057
+ os_type: osProvider.type(),
77422
78058
  cpu_count: cpus.length,
77423
78059
  cpu_model: cpus.model,
77424
- total_memory_gb: Math.round(os3.totalmem() / 1024 / 1024 / 1024),
78060
+ total_memory_gb: Math.round(osProvider.totalmem() / 1024 / 1024 / 1024),
77425
78061
  locale: Intl.DateTimeFormat().resolvedOptions().locale,
77426
78062
  timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
77427
78063
  shell: process.env.SHELL,
@@ -77464,11 +78100,14 @@ function createPostHogClient(source, options) {
77464
78100
  };
77465
78101
  }
77466
78102
  function getPostHogDistinctId() {
77467
- return createHash("sha256").update(`${PUBLISHED_PACKAGE_NAME}:${os3.hostname()}`).digest("hex");
78103
+ return createHash("sha256").update(`${PUBLISHED_PACKAGE_NAME}:${resolveOsProvider().hostname()}`).digest("hex");
77468
78104
  }
77469
78105
  function createCliPostHog() {
77470
78106
  return createPostHogClient("cli", {
77471
78107
  enableExceptionAutocapture: false,
78108
+ enableLocalEvaluation: false,
78109
+ strictLocalEvaluation: true,
78110
+ disableRemoteConfig: true,
77472
78111
  flushAt: 1,
77473
78112
  flushInterval: 0
77474
78113
  });
@@ -77479,7 +78118,7 @@ var EVENT_PROCESSOR_SHUTDOWN_TIMEOUT_MS = 2000;
77479
78118
  async function waitForEventProcessorShutdown(eventProcessor, timeoutMs = EVENT_PROCESSOR_SHUTDOWN_TIMEOUT_MS) {
77480
78119
  const completed = await Promise.race([
77481
78120
  eventProcessor.then(() => true),
77482
- new Promise((resolve4) => setTimeout(() => resolve4(false), timeoutMs))
78121
+ new Promise((resolve6) => setTimeout(() => resolve6(false), timeoutMs))
77483
78122
  ]);
77484
78123
  }
77485
78124
  async function run(options) {
@@ -77753,12 +78392,12 @@ async function getLocalVersion(options = {}) {
77753
78392
  }
77754
78393
  }
77755
78394
  // src/cli/doctor/checks/system.ts
77756
- import { existsSync as existsSync33, readFileSync as readFileSync27 } from "fs";
78395
+ import { existsSync as existsSync36, readFileSync as readFileSync29 } from "fs";
77757
78396
 
77758
78397
  // src/cli/doctor/checks/system-binary.ts
77759
- import { existsSync as existsSync30 } from "fs";
77760
- import { homedir as homedir6 } from "os";
77761
- import { join as join29 } from "path";
78398
+ import { existsSync as existsSync33 } from "fs";
78399
+ import { homedir as homedir8 } from "os";
78400
+ import { join as join31 } from "path";
77762
78401
 
77763
78402
  // src/cli/doctor/spawn-with-timeout.ts
77764
78403
  init_spawn_with_windows_hide();
@@ -77771,8 +78410,8 @@ async function spawnWithTimeout(command, options, timeoutMs = DEFAULT_SPAWN_TIME
77771
78410
  return { stdout: "", stderr: "", exitCode: 1, timedOut: false };
77772
78411
  }
77773
78412
  let timer;
77774
- const timeoutPromise = new Promise((resolve4) => {
77775
- timer = setTimeout(() => resolve4("timeout"), timeoutMs);
78413
+ const timeoutPromise = new Promise((resolve6) => {
78414
+ timer = setTimeout(() => resolve6("timeout"), timeoutMs);
77776
78415
  });
77777
78416
  const processPromise = (async () => {
77778
78417
  await proc.exited;
@@ -77792,22 +78431,22 @@ async function spawnWithTimeout(command, options, timeoutMs = DEFAULT_SPAWN_TIME
77792
78431
 
77793
78432
  // src/cli/doctor/checks/system-binary.ts
77794
78433
  function getDesktopAppPaths(platform) {
77795
- const home = homedir6();
78434
+ const home = homedir8();
77796
78435
  switch (platform) {
77797
78436
  case "darwin":
77798
78437
  return [
77799
78438
  "/Applications/OpenCode.app/Contents/MacOS/OpenCode",
77800
- join29(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
78439
+ join31(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
77801
78440
  ];
77802
78441
  case "win32": {
77803
78442
  const programFiles = process.env.ProgramFiles;
77804
78443
  const localAppData = process.env.LOCALAPPDATA;
77805
78444
  const paths = [];
77806
78445
  if (programFiles) {
77807
- paths.push(join29(programFiles, "OpenCode", "OpenCode.exe"));
78446
+ paths.push(join31(programFiles, "OpenCode", "OpenCode.exe"));
77808
78447
  }
77809
78448
  if (localAppData) {
77810
- paths.push(join29(localAppData, "OpenCode", "OpenCode.exe"));
78449
+ paths.push(join31(localAppData, "OpenCode", "OpenCode.exe"));
77811
78450
  }
77812
78451
  return paths;
77813
78452
  }
@@ -77815,8 +78454,8 @@ function getDesktopAppPaths(platform) {
77815
78454
  return [
77816
78455
  "/usr/bin/opencode",
77817
78456
  "/usr/lib/opencode/opencode",
77818
- join29(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
77819
- join29(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
78457
+ join31(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
78458
+ join31(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
77820
78459
  ];
77821
78460
  default:
77822
78461
  return [];
@@ -77828,7 +78467,7 @@ function buildVersionCommand(binaryPath, platform) {
77828
78467
  }
77829
78468
  return [binaryPath, "--version"];
77830
78469
  }
77831
- function findDesktopBinary(platform = process.platform, checkExists = existsSync30) {
78470
+ function findDesktopBinary(platform = process.platform, checkExists = existsSync33) {
77832
78471
  for (const desktopPath of getDesktopAppPaths(platform)) {
77833
78472
  if (checkExists(desktopPath)) {
77834
78473
  return { binary: "opencode", path: desktopPath };
@@ -77838,9 +78477,9 @@ function findDesktopBinary(platform = process.platform, checkExists = existsSync
77838
78477
  }
77839
78478
  async function findOpenCodeBinary() {
77840
78479
  for (const binary2 of OPENCODE_BINARIES2) {
77841
- const path12 = Bun.which(binary2);
77842
- if (path12) {
77843
- return { binary: binary2, path: path12 };
78480
+ const path13 = Bun.which(binary2);
78481
+ if (path13) {
78482
+ return { binary: binary2, path: path13 };
77844
78483
  }
77845
78484
  }
77846
78485
  return findDesktopBinary();
@@ -77851,7 +78490,7 @@ async function getOpenCodeVersion3(binaryPath, platform = process.platform) {
77851
78490
  const result = await spawnWithTimeout(command, { stdout: "pipe", stderr: "pipe" });
77852
78491
  if (result.timedOut || result.exitCode !== 0)
77853
78492
  return null;
77854
- return result.stdout.trim() || null;
78493
+ return extractSemverFromOutput(result.stdout);
77855
78494
  } catch {
77856
78495
  return null;
77857
78496
  }
@@ -77874,12 +78513,12 @@ function compareVersions3(current, minimum) {
77874
78513
 
77875
78514
  // src/cli/doctor/checks/system-plugin.ts
77876
78515
  init_shared();
77877
- import { existsSync as existsSync31, readFileSync as readFileSync25 } from "fs";
78516
+ import { existsSync as existsSync34, readFileSync as readFileSync27 } from "fs";
77878
78517
  function detectConfigPath() {
77879
78518
  const paths = getOpenCodeConfigPaths({ binary: "opencode", version: null });
77880
- if (existsSync31(paths.configJsonc))
78519
+ if (existsSync34(paths.configJsonc))
77881
78520
  return paths.configJsonc;
77882
- if (existsSync31(paths.configJson))
78521
+ if (existsSync34(paths.configJson))
77883
78522
  return paths.configJson;
77884
78523
  return null;
77885
78524
  }
@@ -77925,7 +78564,7 @@ function getPluginInfo() {
77925
78564
  };
77926
78565
  }
77927
78566
  try {
77928
- const content = readFileSync25(configPath, "utf-8");
78567
+ const content = readFileSync27(configPath, "utf-8");
77929
78568
  const parsedConfig = parseJsonc(content);
77930
78569
  const pluginEntry = findPluginEntry2(parsedConfig.plugin ?? []);
77931
78570
  if (!pluginEntry) {
@@ -77963,37 +78602,37 @@ function getPluginInfo() {
77963
78602
  init_file_utils();
77964
78603
  init_checker();
77965
78604
  init_auto_update_checker();
77966
- import { existsSync as existsSync32, readFileSync as readFileSync26 } from "fs";
77967
- import { homedir as homedir7 } from "os";
77968
- import { join as join30 } from "path";
78605
+ import { existsSync as existsSync35, readFileSync as readFileSync28 } from "fs";
78606
+ import { homedir as homedir9 } from "os";
78607
+ import { join as join32 } from "path";
77969
78608
  init_shared();
77970
78609
  function getPlatformDefaultCacheDir(platform = process.platform) {
77971
78610
  if (platform === "darwin")
77972
- return join30(homedir7(), "Library", "Caches");
78611
+ return join32(homedir9(), "Library", "Caches");
77973
78612
  if (platform === "win32")
77974
- return process.env.LOCALAPPDATA ?? join30(homedir7(), "AppData", "Local");
77975
- return join30(homedir7(), ".cache");
78613
+ return process.env.LOCALAPPDATA ?? join32(homedir9(), "AppData", "Local");
78614
+ return join32(homedir9(), ".cache");
77976
78615
  }
77977
78616
  function resolveOpenCodeCacheDir() {
77978
78617
  const xdgCacheHome = process.env.XDG_CACHE_HOME;
77979
78618
  if (xdgCacheHome)
77980
- return join30(xdgCacheHome, "opencode");
78619
+ return join32(xdgCacheHome, "opencode");
77981
78620
  const fromShared = getOpenCodeCacheDir();
77982
- const platformDefault = join30(getPlatformDefaultCacheDir(), "opencode");
77983
- if (existsSync32(fromShared) || !existsSync32(platformDefault))
78621
+ const platformDefault = join32(getPlatformDefaultCacheDir(), "opencode");
78622
+ if (existsSync35(fromShared) || !existsSync35(platformDefault))
77984
78623
  return fromShared;
77985
78624
  return platformDefault;
77986
78625
  }
77987
78626
  function resolveExistingDir(dirPath) {
77988
- if (!existsSync32(dirPath))
78627
+ if (!existsSync35(dirPath))
77989
78628
  return dirPath;
77990
78629
  return resolveSymlink(dirPath);
77991
78630
  }
77992
78631
  function readPackageJson(filePath) {
77993
- if (!existsSync32(filePath))
78632
+ if (!existsSync35(filePath))
77994
78633
  return null;
77995
78634
  try {
77996
- const content = readFileSync26(filePath, "utf-8");
78635
+ const content = readFileSync28(filePath, "utf-8");
77997
78636
  return parseJsonc(content);
77998
78637
  } catch {
77999
78638
  return null;
@@ -78008,11 +78647,11 @@ function normalizeVersion(value) {
78008
78647
  function createPackageCandidates(rootDir) {
78009
78648
  return ACCEPTED_PACKAGE_NAMES.map((packageName) => ({
78010
78649
  packageName,
78011
- installedPackagePath: join30(rootDir, "node_modules", packageName, "package.json")
78650
+ installedPackagePath: join32(rootDir, "node_modules", packageName, "package.json")
78012
78651
  }));
78013
78652
  }
78014
78653
  function selectInstalledPackage(candidate) {
78015
- return candidate.packageCandidates.find((packageCandidate) => existsSync32(packageCandidate.installedPackagePath)) ?? candidate.packageCandidates[0];
78654
+ return candidate.packageCandidates.find((packageCandidate) => existsSync35(packageCandidate.installedPackagePath)) ?? candidate.packageCandidates[0];
78016
78655
  }
78017
78656
  function getExpectedVersion(cachePackage, packageName) {
78018
78657
  return normalizeVersion(cachePackage?.dependencies?.[packageName]) ?? normalizeVersion(cachePackage?.dependencies?.[PACKAGE_NAME]);
@@ -78024,16 +78663,16 @@ function getLoadedPluginVersion() {
78024
78663
  const candidates = [
78025
78664
  {
78026
78665
  cacheDir: configDir,
78027
- cachePackagePath: join30(configDir, "package.json"),
78666
+ cachePackagePath: join32(configDir, "package.json"),
78028
78667
  packageCandidates: createPackageCandidates(configDir)
78029
78668
  },
78030
78669
  {
78031
78670
  cacheDir,
78032
- cachePackagePath: join30(cacheDir, "package.json"),
78671
+ cachePackagePath: join32(cacheDir, "package.json"),
78033
78672
  packageCandidates: createPackageCandidates(cacheDir)
78034
78673
  }
78035
78674
  ];
78036
- const selectedCandidate = candidates.find((candidate) => candidate.packageCandidates.some((packageCandidate) => existsSync32(packageCandidate.installedPackagePath))) ?? candidates[0];
78675
+ const selectedCandidate = candidates.find((candidate) => candidate.packageCandidates.some((packageCandidate) => existsSync35(packageCandidate.installedPackagePath))) ?? candidates[0];
78037
78676
  const { cacheDir: selectedDir, cachePackagePath } = selectedCandidate;
78038
78677
  const selectedPackage = selectInstalledPackage(selectedCandidate);
78039
78678
  const installedPackagePath = selectedPackage.installedPackagePath;
@@ -78060,7 +78699,7 @@ function getSuggestedInstallTag(currentVersion) {
78060
78699
  // src/cli/doctor/checks/system.ts
78061
78700
  init_shared();
78062
78701
  init_plugin_identity();
78063
- var defaultDeps3 = {
78702
+ var defaultDeps4 = {
78064
78703
  findOpenCodeBinary,
78065
78704
  getOpenCodeVersion: getOpenCodeVersion3,
78066
78705
  compareVersions: compareVersions3,
@@ -78072,10 +78711,10 @@ var defaultDeps3 = {
78072
78711
  function isConfigValid(configPath) {
78073
78712
  if (!configPath)
78074
78713
  return true;
78075
- if (!existsSync33(configPath))
78714
+ if (!existsSync36(configPath))
78076
78715
  return false;
78077
78716
  try {
78078
- parseJsonc(readFileSync27(configPath, "utf-8"));
78717
+ parseJsonc(readFileSync29(configPath, "utf-8"));
78079
78718
  return true;
78080
78719
  } catch {
78081
78720
  return false;
@@ -78095,7 +78734,7 @@ function buildMessage(status, issues) {
78095
78734
  return `${issues.length} system issue(s) detected`;
78096
78735
  return `${issues.length} system warning(s) detected`;
78097
78736
  }
78098
- async function gatherSystemInfo(deps = defaultDeps3) {
78737
+ async function gatherSystemInfo(deps = defaultDeps4) {
78099
78738
  const [binaryInfo, pluginInfo] = await Promise.all([
78100
78739
  deps.findOpenCodeBinary(),
78101
78740
  Promise.resolve(deps.getPluginInfo())
@@ -78114,7 +78753,7 @@ async function gatherSystemInfo(deps = defaultDeps3) {
78114
78753
  isLocalDev: pluginInfo.isLocalDev
78115
78754
  };
78116
78755
  }
78117
- async function checkSystem(deps = defaultDeps3) {
78756
+ async function checkSystem(deps = defaultDeps4) {
78118
78757
  const [systemInfo, pluginInfo] = await Promise.all([
78119
78758
  gatherSystemInfo(deps),
78120
78759
  Promise.resolve(deps.getPluginInfo())
@@ -78197,32 +78836,32 @@ async function checkSystem(deps = defaultDeps3) {
78197
78836
  }
78198
78837
 
78199
78838
  // src/cli/doctor/checks/config.ts
78200
- import { readFileSync as readFileSync30 } from "fs";
78201
- import { join as join34 } from "path";
78839
+ import { readFileSync as readFileSync32 } from "fs";
78840
+ import { join as join36 } from "path";
78202
78841
  init_shared();
78203
78842
 
78204
78843
  // src/cli/doctor/checks/model-resolution-cache.ts
78205
78844
  init_shared();
78206
- import { existsSync as existsSync34, readFileSync as readFileSync28 } from "fs";
78207
- import { homedir as homedir8 } from "os";
78208
- import { join as join31 } from "path";
78845
+ import { existsSync as existsSync37, readFileSync as readFileSync30 } from "fs";
78846
+ import { homedir as homedir10 } from "os";
78847
+ import { join as join33 } from "path";
78209
78848
  function getUserConfigDir2() {
78210
78849
  const xdgConfig = process.env.XDG_CONFIG_HOME;
78211
78850
  if (xdgConfig)
78212
- return join31(xdgConfig, "opencode");
78213
- return join31(homedir8(), ".config", "opencode");
78851
+ return join33(xdgConfig, "opencode");
78852
+ return join33(homedir10(), ".config", "opencode");
78214
78853
  }
78215
78854
  function loadCustomProviderNames() {
78216
78855
  const configDir = getUserConfigDir2();
78217
78856
  const candidatePaths = [
78218
- join31(configDir, "opencode.json"),
78219
- join31(configDir, "opencode.jsonc")
78857
+ join33(configDir, "opencode.json"),
78858
+ join33(configDir, "opencode.jsonc")
78220
78859
  ];
78221
78860
  for (const configPath of candidatePaths) {
78222
- if (!existsSync34(configPath))
78861
+ if (!existsSync37(configPath))
78223
78862
  continue;
78224
78863
  try {
78225
- const content = readFileSync28(configPath, "utf-8");
78864
+ const content = readFileSync30(configPath, "utf-8");
78226
78865
  const data = parseJsonc(content);
78227
78866
  if (data?.provider && typeof data.provider === "object") {
78228
78867
  return Object.keys(data.provider);
@@ -78232,16 +78871,16 @@ function loadCustomProviderNames() {
78232
78871
  return [];
78233
78872
  }
78234
78873
  function loadAvailableModelsFromCache() {
78235
- const cacheFile = join31(getOpenCodeCacheDir(), "models.json");
78874
+ const cacheFile = join33(getOpenCodeCacheDir(), "models.json");
78236
78875
  const customProviders = loadCustomProviderNames();
78237
- if (!existsSync34(cacheFile)) {
78876
+ if (!existsSync37(cacheFile)) {
78238
78877
  if (customProviders.length > 0) {
78239
78878
  return { providers: customProviders, modelCount: 0, cacheExists: true };
78240
78879
  }
78241
78880
  return { providers: [], modelCount: 0, cacheExists: false };
78242
78881
  }
78243
78882
  try {
78244
- const content = readFileSync28(cacheFile, "utf-8");
78883
+ const content = readFileSync30(cacheFile, "utf-8");
78245
78884
  const data = parseJsonc(content);
78246
78885
  const cacheProviders = Object.keys(data);
78247
78886
  let modelCount = 0;
@@ -78264,14 +78903,14 @@ init_model_capabilities();
78264
78903
 
78265
78904
  // src/cli/doctor/checks/model-resolution-config.ts
78266
78905
  init_shared();
78267
- import { readFileSync as readFileSync29 } from "fs";
78268
- import { join as join32 } from "path";
78269
- var PROJECT_CONFIG_DIR = join32(process.cwd(), ".opencode");
78906
+ import { readFileSync as readFileSync31 } from "fs";
78907
+ import { join as join34 } from "path";
78908
+ var PROJECT_CONFIG_DIR = join34(process.cwd(), ".opencode");
78270
78909
  function loadOmoConfig() {
78271
78910
  const projectDetected = detectPluginConfigFile(PROJECT_CONFIG_DIR);
78272
78911
  if (projectDetected.format !== "none") {
78273
78912
  try {
78274
- const content = readFileSync29(projectDetected.path, "utf-8");
78913
+ const content = readFileSync31(projectDetected.path, "utf-8");
78275
78914
  return parseJsonc(content);
78276
78915
  } catch {
78277
78916
  return null;
@@ -78281,7 +78920,7 @@ function loadOmoConfig() {
78281
78920
  const userDetected = detectPluginConfigFile(userConfigDir);
78282
78921
  if (userDetected.format !== "none") {
78283
78922
  try {
78284
- const content = readFileSync29(userDetected.path, "utf-8");
78923
+ const content = readFileSync31(userDetected.path, "utf-8");
78285
78924
  return parseJsonc(content);
78286
78925
  } catch {
78287
78926
  return null;
@@ -78292,7 +78931,7 @@ function loadOmoConfig() {
78292
78931
 
78293
78932
  // src/cli/doctor/checks/model-resolution-details.ts
78294
78933
  init_shared();
78295
- import { join as join33 } from "path";
78934
+ import { join as join35 } from "path";
78296
78935
 
78297
78936
  // src/cli/doctor/checks/model-resolution-variant.ts
78298
78937
  function formatModelWithVariant(model, variant) {
@@ -78334,7 +78973,7 @@ function formatCapabilityResolutionLabel(mode) {
78334
78973
  }
78335
78974
  function buildModelResolutionDetails(options) {
78336
78975
  const details = [];
78337
- const cacheFile = join33(getOpenCodeCacheDir(), "models.json");
78976
+ const cacheFile = join35(getOpenCodeCacheDir(), "models.json");
78338
78977
  details.push("\u2550\u2550\u2550 Available Models (from cache) \u2550\u2550\u2550");
78339
78978
  details.push("");
78340
78979
  if (options.available.cacheExists) {
@@ -78489,7 +79128,7 @@ async function checkModels() {
78489
79128
  }
78490
79129
 
78491
79130
  // src/cli/doctor/checks/config.ts
78492
- var PROJECT_CONFIG_DIR2 = join34(process.cwd(), ".opencode");
79131
+ var PROJECT_CONFIG_DIR2 = join36(process.cwd(), ".opencode");
78493
79132
  function findConfigPath() {
78494
79133
  const projectConfig = detectPluginConfigFile(PROJECT_CONFIG_DIR2);
78495
79134
  if (projectConfig.format !== "none")
@@ -78506,7 +79145,7 @@ function validateConfig() {
78506
79145
  return { exists: false, path: null, valid: true, config: null, errors: [] };
78507
79146
  }
78508
79147
  try {
78509
- const content = readFileSync30(configPath, "utf-8");
79148
+ const content = readFileSync32(configPath, "utf-8");
78510
79149
  const rawConfig = parseJsonc(content);
78511
79150
  const schemaResult = OhMyOpenCodeConfigSchema.safeParse(rawConfig);
78512
79151
  if (!schemaResult.success) {
@@ -78609,27 +79248,27 @@ async function checkConfig() {
78609
79248
  }
78610
79249
 
78611
79250
  // src/cli/doctor/checks/dependencies.ts
78612
- import { existsSync as existsSync35 } from "fs";
79251
+ import { existsSync as existsSync38 } from "fs";
78613
79252
  import { createRequire } from "module";
78614
- import { dirname as dirname14, join as join36 } from "path";
79253
+ import { dirname as dirname16, join as join38 } from "path";
78615
79254
 
78616
79255
  // src/hooks/comment-checker/downloader.ts
78617
- import { join as join35 } from "path";
78618
- import { homedir as homedir9, tmpdir as tmpdir3 } from "os";
79256
+ import { join as join37 } from "path";
79257
+ import { homedir as homedir11, tmpdir as tmpdir3 } from "os";
78619
79258
  init_binary_downloader();
78620
79259
  init_logger();
78621
79260
  init_plugin_identity();
78622
79261
  var DEBUG = process.env.COMMENT_CHECKER_DEBUG === "1";
78623
- var DEBUG_FILE = join35(tmpdir3(), "comment-checker-debug.log");
79262
+ var DEBUG_FILE = join37(tmpdir3(), "comment-checker-debug.log");
78624
79263
  function getCacheDir2() {
78625
79264
  if (process.platform === "win32") {
78626
79265
  const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
78627
- const base2 = localAppData || join35(homedir9(), "AppData", "Local");
78628
- return join35(base2, CACHE_DIR_NAME, "bin");
79266
+ const base2 = localAppData || join37(homedir11(), "AppData", "Local");
79267
+ return join37(base2, CACHE_DIR_NAME, "bin");
78629
79268
  }
78630
79269
  const xdgCache = process.env.XDG_CACHE_HOME;
78631
- const base = xdgCache || join35(homedir9(), ".cache");
78632
- return join35(base, CACHE_DIR_NAME, "bin");
79270
+ const base = xdgCache || join37(homedir11(), ".cache");
79271
+ return join37(base, CACHE_DIR_NAME, "bin");
78633
79272
  }
78634
79273
  function getBinaryName() {
78635
79274
  return process.platform === "win32" ? "comment-checker.exe" : "comment-checker";
@@ -78641,9 +79280,9 @@ function getCachedBinaryPath2() {
78641
79280
  // src/cli/doctor/checks/dependencies.ts
78642
79281
  async function checkBinaryExists(binary2) {
78643
79282
  try {
78644
- const path12 = Bun.which(binary2);
78645
- if (path12) {
78646
- return { exists: true, path: path12 };
79283
+ const path13 = Bun.which(binary2);
79284
+ if (path13) {
79285
+ return { exists: true, path: path13 };
78647
79286
  }
78648
79287
  } catch {}
78649
79288
  return { exists: false, path: null };
@@ -78693,15 +79332,15 @@ async function checkAstGrepNapi() {
78693
79332
  path: null
78694
79333
  };
78695
79334
  } catch {
78696
- const { existsSync: existsSync36 } = await import("fs");
78697
- const { join: join37 } = await import("path");
78698
- const { homedir: homedir10 } = await import("os");
79335
+ const { existsSync: existsSync39 } = await import("fs");
79336
+ const { join: join39 } = await import("path");
79337
+ const { homedir: homedir12 } = await import("os");
78699
79338
  const pathsToCheck = [
78700
- join37(homedir10(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
78701
- join37(process.cwd(), "node_modules", "@ast-grep", "napi")
79339
+ join39(homedir12(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
79340
+ join39(process.cwd(), "node_modules", "@ast-grep", "napi")
78702
79341
  ];
78703
79342
  for (const napiPath of pathsToCheck) {
78704
- if (existsSync36(napiPath)) {
79343
+ if (existsSync39(napiPath)) {
78705
79344
  return {
78706
79345
  name: "AST-Grep NAPI",
78707
79346
  required: false,
@@ -78726,8 +79365,8 @@ function findCommentCheckerPackageBinary() {
78726
79365
  try {
78727
79366
  const require2 = createRequire(import.meta.url);
78728
79367
  const pkgPath = require2.resolve("@code-yeongyu/comment-checker/package.json");
78729
- const binaryPath = join36(dirname14(pkgPath), "bin", binaryName);
78730
- if (existsSync35(binaryPath))
79368
+ const binaryPath = join38(dirname16(pkgPath), "bin", binaryName);
79369
+ if (existsSync38(binaryPath))
78731
79370
  return binaryPath;
78732
79371
  } catch {}
78733
79372
  return null;
@@ -78823,6 +79462,19 @@ async function getGhAuthStatus() {
78823
79462
  async function getGhCliInfo() {
78824
79463
  const binaryStatus = await checkBinaryExists2("gh");
78825
79464
  if (!binaryStatus.exists) {
79465
+ const version4 = await getGhVersion();
79466
+ if (version4) {
79467
+ const authStatus2 = await getGhAuthStatus();
79468
+ return {
79469
+ installed: true,
79470
+ version: version4,
79471
+ path: null,
79472
+ authenticated: authStatus2.authenticated,
79473
+ username: authStatus2.username,
79474
+ scopes: authStatus2.scopes,
79475
+ error: authStatus2.error
79476
+ };
79477
+ }
78826
79478
  return {
78827
79479
  installed: false,
78828
79480
  version: null,
@@ -78888,15 +79540,15 @@ var BUILTIN_SERVERS = {
78888
79540
  "kotlin-ls": { command: ["kotlin-lsp"], extensions: [".kt", ".kts"] }
78889
79541
  };
78890
79542
  // src/tools/lsp/server-config-loader.ts
78891
- import { existsSync as existsSync36, readFileSync as readFileSync31 } from "fs";
78892
- import { join as join37 } from "path";
79543
+ import { existsSync as existsSync39, readFileSync as readFileSync33 } from "fs";
79544
+ import { join as join39 } from "path";
78893
79545
  init_shared();
78894
79546
  init_jsonc_parser();
78895
- function loadJsonFile(path12) {
78896
- if (!existsSync36(path12))
79547
+ function loadJsonFile(path13) {
79548
+ if (!existsSync39(path13))
78897
79549
  return null;
78898
79550
  try {
78899
- return parseJsonc(readFileSync31(path12, "utf-8"));
79551
+ return parseJsonc(readFileSync33(path13, "utf-8"));
78900
79552
  } catch {
78901
79553
  return null;
78902
79554
  }
@@ -78905,9 +79557,9 @@ function getConfigPaths2() {
78905
79557
  const cwd = process.cwd();
78906
79558
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
78907
79559
  return {
78908
- project: detectPluginConfigFile(join37(cwd, ".opencode")).path,
79560
+ project: detectPluginConfigFile(join39(cwd, ".opencode")).path,
78909
79561
  user: detectPluginConfigFile(configDir).path,
78910
- opencode: detectConfigFile(join37(configDir, "opencode")).path
79562
+ opencode: detectConfigFile(join39(configDir, "opencode")).path
78911
79563
  };
78912
79564
  }
78913
79565
  function loadAllConfigs() {
@@ -78976,21 +79628,21 @@ function getMergedServers() {
78976
79628
  }
78977
79629
 
78978
79630
  // src/tools/lsp/server-installation.ts
78979
- import { existsSync as existsSync37 } from "fs";
78980
- import { delimiter as delimiter2, join as join39 } from "path";
79631
+ import { existsSync as existsSync40 } from "fs";
79632
+ import { delimiter as delimiter2, join as join41 } from "path";
78981
79633
 
78982
79634
  // src/tools/lsp/server-path-bases.ts
78983
79635
  init_shared();
78984
- import { join as join38 } from "path";
79636
+ import { join as join40 } from "path";
78985
79637
  function getLspServerAdditionalPathBases(workingDirectory) {
78986
79638
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
78987
- const dataDir = join38(getDataDir(), "opencode");
79639
+ const dataDir = join40(getDataDir(), "opencode");
78988
79640
  return [
78989
- join38(workingDirectory, "node_modules", ".bin"),
78990
- join38(configDir, "bin"),
78991
- join38(configDir, "node_modules", ".bin"),
78992
- join38(dataDir, "bin"),
78993
- join38(dataDir, "bin", "node_modules", ".bin")
79641
+ join40(workingDirectory, "node_modules", ".bin"),
79642
+ join40(configDir, "bin"),
79643
+ join40(configDir, "node_modules", ".bin"),
79644
+ join40(dataDir, "bin"),
79645
+ join40(dataDir, "bin", "node_modules", ".bin")
78994
79646
  ];
78995
79647
  }
78996
79648
 
@@ -79000,7 +79652,7 @@ function isServerInstalled(command) {
79000
79652
  return false;
79001
79653
  const cmd = command[0];
79002
79654
  if (cmd.includes("/") || cmd.includes("\\")) {
79003
- if (existsSync37(cmd))
79655
+ if (existsSync40(cmd))
79004
79656
  return true;
79005
79657
  }
79006
79658
  const isWindows = process.platform === "win32";
@@ -79021,14 +79673,14 @@ function isServerInstalled(command) {
79021
79673
  const paths = pathEnv.split(delimiter2);
79022
79674
  for (const p2 of paths) {
79023
79675
  for (const suffix of exts) {
79024
- if (existsSync37(join39(p2, cmd + suffix))) {
79676
+ if (existsSync40(join41(p2, cmd + suffix))) {
79025
79677
  return true;
79026
79678
  }
79027
79679
  }
79028
79680
  }
79029
79681
  for (const base of getLspServerAdditionalPathBases(process.cwd())) {
79030
79682
  for (const suffix of exts) {
79031
- if (existsSync37(join39(base, cmd + suffix))) {
79683
+ if (existsSync40(join41(base, cmd + suffix))) {
79032
79684
  return true;
79033
79685
  }
79034
79686
  }
@@ -79090,24 +79742,24 @@ function getInstalledLspServers() {
79090
79742
 
79091
79743
  // src/cli/doctor/checks/tools-mcp.ts
79092
79744
  init_shared();
79093
- import { existsSync as existsSync38, readFileSync as readFileSync32 } from "fs";
79094
- import { homedir as homedir10 } from "os";
79095
- import { join as join40 } from "path";
79745
+ import { existsSync as existsSync41, readFileSync as readFileSync34 } from "fs";
79746
+ import { homedir as homedir12 } from "os";
79747
+ import { join as join42 } from "path";
79096
79748
  var BUILTIN_MCP_SERVERS = ["context7", "grep_app"];
79097
79749
  function getMcpConfigPaths() {
79098
79750
  return [
79099
- join40(homedir10(), ".claude", ".mcp.json"),
79100
- join40(process.cwd(), ".mcp.json"),
79101
- join40(process.cwd(), ".claude", ".mcp.json")
79751
+ join42(homedir12(), ".claude", ".mcp.json"),
79752
+ join42(process.cwd(), ".mcp.json"),
79753
+ join42(process.cwd(), ".claude", ".mcp.json")
79102
79754
  ];
79103
79755
  }
79104
79756
  function loadUserMcpConfig() {
79105
79757
  const servers = {};
79106
79758
  for (const configPath of getMcpConfigPaths()) {
79107
- if (!existsSync38(configPath))
79759
+ if (!existsSync41(configPath))
79108
79760
  continue;
79109
79761
  try {
79110
- const content = readFileSync32(configPath, "utf-8");
79762
+ const content = readFileSync34(configPath, "utf-8");
79111
79763
  const config2 = parseJsonc(content);
79112
79764
  if (config2.mcpServers) {
79113
79765
  Object.assign(servers, config2.mcpServers);
@@ -79238,6 +79890,89 @@ async function checkTools() {
79238
79890
  issues
79239
79891
  };
79240
79892
  }
79893
+
79894
+ // src/features/team-mode/deps.ts
79895
+ init_bun_spawn_shim();
79896
+ async function checkTeamModeDependencies(config2) {
79897
+ const tmuxAvailable = Boolean(process.env["TMUX"]) || await probeBinary("tmux", ["-V"]);
79898
+ const gitAvailable = await probeBinary("git", ["--version"]);
79899
+ if (config2.tmux_visualization && !tmuxAvailable) {
79900
+ console.warn("[team-mode] tmux_visualization=true but tmux not available; layout will be skipped at runtime");
79901
+ }
79902
+ return { tmuxAvailable, gitAvailable };
79903
+ }
79904
+ async function probeBinary(cmd, args) {
79905
+ try {
79906
+ const proc = spawn({ cmd: [cmd, ...args], stdout: "pipe", stderr: "pipe" });
79907
+ const code = await proc.exited;
79908
+ return code === 0;
79909
+ } catch {
79910
+ return false;
79911
+ }
79912
+ }
79913
+
79914
+ // src/features/team-mode/team-registry/paths.ts
79915
+ init_logger();
79916
+ import { homedir as homedir13 } from "os";
79917
+ import path13 from "path";
79918
+ function resolveBaseDir(config2) {
79919
+ return config2.base_dir ?? path13.join(homedir13(), ".omo");
79920
+ }
79921
+
79922
+ // src/cli/doctor/checks/team-mode.ts
79923
+ init_shared();
79924
+ import { readFileSync as readFileSync35, promises as fs12 } from "fs";
79925
+ import path14 from "path";
79926
+ async function checkTeamMode() {
79927
+ const config2 = loadTeamModeConfig();
79928
+ const teamModeConfig = TeamModeConfigSchema.parse(config2.team_mode ?? {});
79929
+ if (!teamModeConfig.enabled) {
79930
+ return { name: CHECK_NAMES[CHECK_IDS.TEAM_MODE], status: "skip", message: "team_mode: disabled", issues: [] };
79931
+ }
79932
+ const deps = await checkTeamModeDependencies(teamModeConfig);
79933
+ const baseDir = resolveBaseDir(teamModeConfig);
79934
+ const [baseDirExists, teamCount, runtimeCount] = await Promise.all([
79935
+ pathExists(baseDir),
79936
+ safeCount(path14.join(baseDir, "teams")),
79937
+ safeCount(path14.join(baseDir, "runtime"))
79938
+ ]);
79939
+ const baseDirMessage = baseDirExists ? `base dir: ok` : `base dir: missing (plugin init will create it on first use)`;
79940
+ return {
79941
+ name: CHECK_NAMES[CHECK_IDS.TEAM_MODE],
79942
+ status: deps.tmuxAvailable && deps.gitAvailable ? "pass" : "warn",
79943
+ message: `team_mode: enabled | tmux: ${deps.tmuxAvailable ? "ok" : "missing"} | git: ${deps.gitAvailable ? "ok" : "missing"} | ${baseDirMessage} | declared: ${teamCount} | runtime dirs: ${runtimeCount}`,
79944
+ details: undefined,
79945
+ issues: []
79946
+ };
79947
+ }
79948
+ function loadTeamModeConfig() {
79949
+ const projectConfig = detectPluginConfigFile(path14.join(process.cwd(), ".opencode"));
79950
+ const userConfig = detectPluginConfigFile(getOpenCodeConfigDir({ binary: "opencode" }));
79951
+ const configPath = projectConfig.format !== "none" ? projectConfig.path : userConfig.path;
79952
+ if (!configPath)
79953
+ return { team_mode: undefined };
79954
+ try {
79955
+ return parseJsonc(readFileSync35(configPath, "utf-8"));
79956
+ } catch {
79957
+ return { team_mode: undefined };
79958
+ }
79959
+ }
79960
+ async function safeCount(dir) {
79961
+ try {
79962
+ const entries = await fs12.readdir(dir, { withFileTypes: true });
79963
+ return entries.filter((entry) => entry.isDirectory()).length;
79964
+ } catch {
79965
+ return 0;
79966
+ }
79967
+ }
79968
+ async function pathExists(dir) {
79969
+ try {
79970
+ const stats = await fs12.stat(dir);
79971
+ return stats.isDirectory();
79972
+ } catch {
79973
+ return false;
79974
+ }
79975
+ }
79241
79976
  // src/cli/doctor/checks/index.ts
79242
79977
  function getAllCheckDefinitions() {
79243
79978
  return [
@@ -79261,6 +79996,11 @@ function getAllCheckDefinitions() {
79261
79996
  id: CHECK_IDS.MODELS,
79262
79997
  name: CHECK_NAMES[CHECK_IDS.MODELS],
79263
79998
  check: checkModels
79999
+ },
80000
+ {
80001
+ id: CHECK_IDS.TEAM_MODE,
80002
+ name: CHECK_NAMES[CHECK_IDS.TEAM_MODE],
80003
+ check: checkTeamMode
79264
80004
  }
79265
80005
  ];
79266
80006
  }
@@ -79567,8 +80307,18 @@ async function runDoctor(options) {
79567
80307
 
79568
80308
  // src/cli/doctor/index.ts
79569
80309
  async function doctor(options = { mode: "default" }) {
79570
- const result = await runDoctor(options);
79571
- return result.exitCode;
80310
+ try {
80311
+ const result = await runDoctor(options);
80312
+ return result.exitCode;
80313
+ } catch (error48) {
80314
+ const message = error48 instanceof Error ? error48.message : String(error48);
80315
+ console.error(`
80316
+ Doctor failed unexpectedly:`, message);
80317
+ console.error("This may indicate memory pressure (OOM/SIGKILL) or a corrupted installation.");
80318
+ console.error(`Try: OMO_DISABLE_POSTHOG=1 bunx oh-my-opencode doctor --verbose
80319
+ `);
80320
+ return EXIT_CODES.FAILURE;
80321
+ }
79572
80322
  }
79573
80323
 
79574
80324
  // src/cli/refresh-model-capabilities.ts
@@ -79605,11 +80355,11 @@ async function refreshModelCapabilities(options, deps = {}) {
79605
80355
 
79606
80356
  // src/features/mcp-oauth/storage.ts
79607
80357
  init_shared();
79608
- import { chmodSync as chmodSync2, existsSync as existsSync39, mkdirSync as mkdirSync12, readFileSync as readFileSync33, renameSync as renameSync4, unlinkSync as unlinkSync6, writeFileSync as writeFileSync10 } from "fs";
79609
- import { dirname as dirname15, join as join41 } from "path";
80358
+ import { chmodSync as chmodSync2, existsSync as existsSync42, mkdirSync as mkdirSync12, readFileSync as readFileSync36, renameSync as renameSync4, unlinkSync as unlinkSync6, writeFileSync as writeFileSync10 } from "fs";
80359
+ import { dirname as dirname17, join as join43 } from "path";
79610
80360
  var STORAGE_FILE_NAME = "mcp-oauth.json";
79611
80361
  function getMcpOauthStoragePath() {
79612
- return join41(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
80362
+ return join43(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
79613
80363
  }
79614
80364
  function normalizeHost(serverHost) {
79615
80365
  let host = serverHost.trim();
@@ -79646,11 +80396,11 @@ function buildKey(serverHost, resource) {
79646
80396
  }
79647
80397
  function readStore() {
79648
80398
  const filePath = getMcpOauthStoragePath();
79649
- if (!existsSync39(filePath)) {
80399
+ if (!existsSync42(filePath)) {
79650
80400
  return null;
79651
80401
  }
79652
80402
  try {
79653
- const content = readFileSync33(filePath, "utf-8");
80403
+ const content = readFileSync36(filePath, "utf-8");
79654
80404
  return JSON.parse(content);
79655
80405
  } catch {
79656
80406
  return null;
@@ -79659,8 +80409,8 @@ function readStore() {
79659
80409
  function writeStore(store2) {
79660
80410
  const filePath = getMcpOauthStoragePath();
79661
80411
  try {
79662
- const dir = dirname15(filePath);
79663
- if (!existsSync39(dir)) {
80412
+ const dir = dirname17(filePath);
80413
+ if (!existsSync42(dir)) {
79664
80414
  mkdirSync12(dir, { recursive: true });
79665
80415
  }
79666
80416
  const tempPath = `${filePath}.tmp.${Date.now()}`;
@@ -79697,7 +80447,7 @@ function deleteToken(serverHost, resource) {
79697
80447
  if (Object.keys(store2).length === 0) {
79698
80448
  try {
79699
80449
  const filePath = getMcpOauthStoragePath();
79700
- if (existsSync39(filePath)) {
80450
+ if (existsSync42(filePath)) {
79701
80451
  unlinkSync6(filePath);
79702
80452
  }
79703
80453
  return true;
@@ -79866,7 +80616,7 @@ async function getOrRegisterClient(options) {
79866
80616
  }
79867
80617
  }
79868
80618
  function parseRegistrationResponse(data) {
79869
- if (!isRecord7(data))
80619
+ if (!isRecord8(data))
79870
80620
  return null;
79871
80621
  const clientId = data.client_id;
79872
80622
  if (typeof clientId !== "string" || clientId.length === 0)
@@ -79877,7 +80627,7 @@ function parseRegistrationResponse(data) {
79877
80627
  }
79878
80628
  return { clientId };
79879
80629
  }
79880
- function isRecord7(value) {
80630
+ function isRecord8(value) {
79881
80631
  return typeof value === "object" && value !== null;
79882
80632
  }
79883
80633
 
@@ -79892,7 +80642,7 @@ async function findAvailablePort2(startPort = DEFAULT_PORT) {
79892
80642
  // src/features/mcp-oauth/oauth-authorization-flow.ts
79893
80643
  import { spawn as spawn2 } from "child_process";
79894
80644
  import { createHash as createHash2, randomBytes as randomBytes2 } from "crypto";
79895
- import { createServer } from "http";
80645
+ import { createServer as createServer2 } from "http";
79896
80646
  function generateCodeVerifier() {
79897
80647
  return randomBytes2(32).toString("base64url");
79898
80648
  }
@@ -79917,9 +80667,9 @@ function buildAuthorizationUrl(authorizationEndpoint, options) {
79917
80667
  }
79918
80668
  var CALLBACK_TIMEOUT_MS = 5 * 60 * 1000;
79919
80669
  function startCallbackServer(port) {
79920
- return new Promise((resolve4, reject) => {
80670
+ return new Promise((resolve6, reject) => {
79921
80671
  let timeoutId;
79922
- const server2 = createServer((request, response) => {
80672
+ const server2 = createServer2((request, response) => {
79923
80673
  clearTimeout(timeoutId);
79924
80674
  const requestUrl = new URL(request.url ?? "/", `http://localhost:${port}`);
79925
80675
  const code = requestUrl.searchParams.get("code");
@@ -79943,7 +80693,7 @@ function startCallbackServer(port) {
79943
80693
  response.writeHead(200, { "content-type": "text/html" });
79944
80694
  response.end("<html><body><h1>Authorization successful. You can close this tab.</h1></body></html>");
79945
80695
  server2.close();
79946
- resolve4({ code, state: state2 });
80696
+ resolve6({ code, state: state2 });
79947
80697
  });
79948
80698
  timeoutId = setTimeout(() => {
79949
80699
  server2.close();
@@ -80276,6 +81026,163 @@ function createMcpOAuthCommand() {
80276
81026
  return mcp;
80277
81027
  }
80278
81028
 
81029
+ // src/cli/boulder/boulder.ts
81030
+ import { existsSync as existsSync43 } from "fs";
81031
+
81032
+ // src/cli/boulder/formatter.ts
81033
+ var import_picocolors21 = __toESM(require_picocolors(), 1);
81034
+ function colorizeStatus(status2) {
81035
+ if (status2 === "active") {
81036
+ return import_picocolors21.default.cyan(status2);
81037
+ }
81038
+ if (status2 === "completed") {
81039
+ return import_picocolors21.default.green(status2);
81040
+ }
81041
+ if (status2 === "paused") {
81042
+ return import_picocolors21.default.yellow(status2);
81043
+ }
81044
+ return import_picocolors21.default.red(status2);
81045
+ }
81046
+ function formatCurrentTask(work) {
81047
+ if (!work.current_task) {
81048
+ return "-";
81049
+ }
81050
+ const elapsed = work.current_task.elapsed_human ? ` (${work.current_task.elapsed_human})` : "";
81051
+ return `${work.current_task.task_title}${elapsed}`;
81052
+ }
81053
+ function formatWorkBlock(work) {
81054
+ const elapsed = work.elapsed_human ?? "-";
81055
+ const progress = `${work.percentage}% (${work.completed_tasks}/${work.total_tasks})`;
81056
+ return [
81057
+ `plan: ${work.plan_name}`,
81058
+ `status: ${colorizeStatus(work.status)}`,
81059
+ `progress: ${progress}`,
81060
+ `elapsed: ${elapsed}`,
81061
+ `sessions: ${work.session_count}`,
81062
+ `current task: ${formatCurrentTask(work)}`
81063
+ ].join(`
81064
+ `);
81065
+ }
81066
+ function formatTextOutput(result) {
81067
+ const separator = import_picocolors21.default.dim("----------------------------------------");
81068
+ const blocks = result.works.map((work) => formatWorkBlock(work));
81069
+ return ["boulder progress", ...blocks].join(`
81070
+ ${separator}
81071
+ `);
81072
+ }
81073
+ function formatJsonOutput3(result) {
81074
+ return JSON.stringify(result, null, 2);
81075
+ }
81076
+ function formatNoBoulderMessage(isJson) {
81077
+ if (isJson) {
81078
+ return JSON.stringify({
81079
+ error: "No boulder state found."
81080
+ });
81081
+ }
81082
+ return "No boulder state found.";
81083
+ }
81084
+ function formatReadErrorMessage(isJson) {
81085
+ if (isJson) {
81086
+ return JSON.stringify({
81087
+ error: "Failed to read boulder state."
81088
+ });
81089
+ }
81090
+ return "Failed to read boulder state.";
81091
+ }
81092
+
81093
+ // src/cli/boulder/boulder.ts
81094
+ function formatDurationHuman(durationMs) {
81095
+ if (durationMs < 1000) {
81096
+ return `${durationMs}ms`;
81097
+ }
81098
+ const totalSeconds = Math.floor(durationMs / 1000);
81099
+ const seconds = totalSeconds % 60;
81100
+ const totalMinutes = Math.floor(totalSeconds / 60);
81101
+ const minutes = totalMinutes % 60;
81102
+ const hours = Math.floor(totalMinutes / 60);
81103
+ if (hours > 0) {
81104
+ return `${hours}h ${minutes}m ${seconds}s`;
81105
+ }
81106
+ if (minutes > 0) {
81107
+ return `${minutes}m ${seconds}s`;
81108
+ }
81109
+ return `${seconds}s`;
81110
+ }
81111
+ function getElapsedMs(work) {
81112
+ if (work.elapsed_ms !== undefined) {
81113
+ return work.elapsed_ms;
81114
+ }
81115
+ const startedAtMs = Date.parse(work.started_at);
81116
+ if (Number.isNaN(startedAtMs)) {
81117
+ return;
81118
+ }
81119
+ const endedAtMs = work.ended_at ? Date.parse(work.ended_at) : Date.now();
81120
+ if (Number.isNaN(endedAtMs)) {
81121
+ return;
81122
+ }
81123
+ return Math.max(0, endedAtMs - startedAtMs);
81124
+ }
81125
+ function buildCliWork(directory, work) {
81126
+ const planPath = resolveBoulderPlanPathForWork(directory, work);
81127
+ const progress = getPlanProgress(planPath);
81128
+ const elapsedMs = getElapsedMs(work);
81129
+ const currentTask = readCurrentTopLevelTask(planPath);
81130
+ const taskSession = currentTask ? work.task_sessions?.[currentTask.key] : undefined;
81131
+ let currentTaskElapsedHuman;
81132
+ if (taskSession?.elapsed_ms !== undefined) {
81133
+ currentTaskElapsedHuman = formatDurationHuman(taskSession.elapsed_ms);
81134
+ } else if (taskSession?.started_at) {
81135
+ const startedAtMs = Date.parse(taskSession.started_at);
81136
+ if (!Number.isNaN(startedAtMs)) {
81137
+ currentTaskElapsedHuman = formatDurationHuman(Math.max(0, Date.now() - startedAtMs));
81138
+ }
81139
+ }
81140
+ return {
81141
+ work_id: work.work_id,
81142
+ plan_name: work.plan_name,
81143
+ active_plan: work.active_plan,
81144
+ worktree_path: work.worktree_path,
81145
+ status: work.status ?? "active",
81146
+ started_at: work.started_at,
81147
+ ended_at: work.ended_at,
81148
+ elapsed_ms: elapsedMs,
81149
+ elapsed_human: elapsedMs !== undefined ? formatDurationHuman(elapsedMs) : undefined,
81150
+ total_tasks: progress.total,
81151
+ completed_tasks: progress.completed,
81152
+ remaining_tasks: Math.max(0, progress.total - progress.completed),
81153
+ percentage: progress.total > 0 ? Math.round(progress.completed / progress.total * 100) : 0,
81154
+ session_count: work.session_ids.length,
81155
+ current_task: currentTask ? {
81156
+ task_key: currentTask.key,
81157
+ task_title: currentTask.title,
81158
+ elapsed_human: currentTaskElapsedHuman
81159
+ } : undefined
81160
+ };
81161
+ }
81162
+ async function boulder(options) {
81163
+ const directory = options.directory ?? process.cwd();
81164
+ const boulderFilePath = getBoulderFilePath(directory);
81165
+ const state2 = readBoulderState(directory);
81166
+ if (!state2) {
81167
+ const message = existsSync43(boulderFilePath) ? formatReadErrorMessage(options.json) : formatNoBoulderMessage(options.json);
81168
+ process.stderr.write(`${message}
81169
+ `);
81170
+ return existsSync43(boulderFilePath) ? 2 : 1;
81171
+ }
81172
+ const works = getBoulderWorks(state2);
81173
+ const filteredWorks = options.workId ? works.filter((work) => work.work_id === options.workId) : works;
81174
+ if (filteredWorks.length === 0) {
81175
+ process.stderr.write(`${formatNoBoulderMessage(options.json)}
81176
+ `);
81177
+ return 1;
81178
+ }
81179
+ const cliWorks = filteredWorks.map((work) => buildCliWork(directory, work));
81180
+ const result = { works: cliWorks };
81181
+ const output = options.json ? formatJsonOutput3(result) : formatTextOutput(result);
81182
+ process.stdout.write(`${output}
81183
+ `);
81184
+ return 0;
81185
+ }
80279
81186
  // src/cli/cli-program.ts
80280
81187
  var VERSION2 = package_default.version;
80281
81188
  var program2 = new Command;
@@ -80402,6 +81309,14 @@ program2.command("refresh-model-capabilities").description("Refresh the cached m
80402
81309
  program2.command("version").description("Show version information").action(() => {
80403
81310
  console.log(`oh-my-opencode v${VERSION2}`);
80404
81311
  });
81312
+ program2.command("boulder").description("Show boulder progress, elapsed time, and per-task statistics").option("-d, --directory <path>", "Working directory").option("-w, --work-id <id>", "Filter to a specific work").option("--json", "Output as JSON").action(async (options) => {
81313
+ const exitCode = await boulder({
81314
+ directory: options.directory,
81315
+ workId: options.workId,
81316
+ json: options.json ?? false
81317
+ });
81318
+ process.exit(exitCode);
81319
+ });
80405
81320
  program2.addCommand(createMcpOAuthCommand());
80406
81321
  function runCli() {
80407
81322
  program2.parse();