opencode-repos 0.1.0 → 0.3.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 (477) hide show
  1. package/AGENTS.md +180 -0
  2. package/README.md +103 -3
  3. package/TODO.md +3 -0
  4. package/bun.lock +0 -85
  5. package/index.ts +1585 -153
  6. package/oh-my-opencode/.github/FUNDING.yml +15 -0
  7. package/oh-my-opencode/.github/ISSUE_TEMPLATE/bug_report.yml +129 -0
  8. package/oh-my-opencode/.github/ISSUE_TEMPLATE/config.yml +8 -0
  9. package/oh-my-opencode/.github/ISSUE_TEMPLATE/feature_request.yml +100 -0
  10. package/oh-my-opencode/.github/ISSUE_TEMPLATE/general.yml +83 -0
  11. package/oh-my-opencode/.github/assets/google.jpg +0 -0
  12. package/oh-my-opencode/.github/assets/hero.jpg +0 -0
  13. package/oh-my-opencode/.github/assets/indent.jpg +0 -0
  14. package/oh-my-opencode/.github/assets/microsoft.jpg +0 -0
  15. package/oh-my-opencode/.github/assets/omo.png +0 -0
  16. package/oh-my-opencode/.github/assets/orchestrator-atlas.png +0 -0
  17. package/oh-my-opencode/.github/assets/sisyphus.png +0 -0
  18. package/oh-my-opencode/.github/assets/sisyphuslabs.png +0 -0
  19. package/oh-my-opencode/.github/pull_request_template.md +34 -0
  20. package/oh-my-opencode/.github/workflows/ci.yml +138 -0
  21. package/oh-my-opencode/.github/workflows/cla.yml +41 -0
  22. package/oh-my-opencode/.github/workflows/lint-workflows.yml +22 -0
  23. package/oh-my-opencode/.github/workflows/publish.yml +165 -0
  24. package/oh-my-opencode/.github/workflows/sisyphus-agent.yml +500 -0
  25. package/oh-my-opencode/.opencode/background-tasks.json +27 -0
  26. package/oh-my-opencode/.opencode/command/get-unpublished-changes.md +84 -0
  27. package/oh-my-opencode/.opencode/command/omomomo.md +37 -0
  28. package/oh-my-opencode/.opencode/command/publish.md +257 -0
  29. package/oh-my-opencode/AGENTS.md +179 -0
  30. package/oh-my-opencode/CLA.md +58 -0
  31. package/oh-my-opencode/CONTRIBUTING.md +268 -0
  32. package/oh-my-opencode/LICENSE.md +82 -0
  33. package/oh-my-opencode/README.ja.md +370 -0
  34. package/oh-my-opencode/README.md +376 -0
  35. package/oh-my-opencode/README.zh-cn.md +380 -0
  36. package/oh-my-opencode/assets/oh-my-opencode.schema.json +2171 -0
  37. package/oh-my-opencode/bin/oh-my-opencode.js +80 -0
  38. package/oh-my-opencode/bin/platform.js +38 -0
  39. package/oh-my-opencode/bin/platform.test.ts +148 -0
  40. package/oh-my-opencode/bun.lock +314 -0
  41. package/oh-my-opencode/bunfig.toml +2 -0
  42. package/oh-my-opencode/docs/category-skill-guide.md +200 -0
  43. package/oh-my-opencode/docs/cli-guide.md +272 -0
  44. package/oh-my-opencode/docs/configurations.md +654 -0
  45. package/oh-my-opencode/docs/features.md +550 -0
  46. package/oh-my-opencode/docs/guide/installation.md +288 -0
  47. package/oh-my-opencode/docs/guide/overview.md +97 -0
  48. package/oh-my-opencode/docs/guide/understanding-orchestration-system.md +445 -0
  49. package/oh-my-opencode/docs/orchestration-guide.md +152 -0
  50. package/oh-my-opencode/docs/ultrawork-manifesto.md +197 -0
  51. package/oh-my-opencode/package.json +89 -0
  52. package/oh-my-opencode/packages/darwin-arm64/bin/.gitkeep +0 -0
  53. package/oh-my-opencode/packages/darwin-arm64/package.json +22 -0
  54. package/oh-my-opencode/packages/darwin-x64/bin/.gitkeep +0 -0
  55. package/oh-my-opencode/packages/darwin-x64/package.json +22 -0
  56. package/oh-my-opencode/packages/linux-arm64/bin/.gitkeep +0 -0
  57. package/oh-my-opencode/packages/linux-arm64/package.json +25 -0
  58. package/oh-my-opencode/packages/linux-arm64-musl/bin/.gitkeep +0 -0
  59. package/oh-my-opencode/packages/linux-arm64-musl/package.json +25 -0
  60. package/oh-my-opencode/packages/linux-x64/bin/.gitkeep +0 -0
  61. package/oh-my-opencode/packages/linux-x64/package.json +25 -0
  62. package/oh-my-opencode/packages/linux-x64-musl/bin/.gitkeep +0 -0
  63. package/oh-my-opencode/packages/linux-x64-musl/package.json +25 -0
  64. package/oh-my-opencode/packages/windows-x64/bin/.gitkeep +0 -0
  65. package/oh-my-opencode/packages/windows-x64/package.json +22 -0
  66. package/oh-my-opencode/postinstall.mjs +43 -0
  67. package/oh-my-opencode/script/build-binaries.ts +103 -0
  68. package/oh-my-opencode/script/build-schema.ts +28 -0
  69. package/oh-my-opencode/script/generate-changelog.ts +92 -0
  70. package/oh-my-opencode/script/publish.ts +344 -0
  71. package/oh-my-opencode/signatures/cla.json +676 -0
  72. package/oh-my-opencode/src/agents/AGENTS.md +67 -0
  73. package/oh-my-opencode/src/agents/atlas.ts +1383 -0
  74. package/oh-my-opencode/src/agents/dynamic-agent-prompt-builder.ts +400 -0
  75. package/oh-my-opencode/src/agents/explore.ts +122 -0
  76. package/oh-my-opencode/src/agents/index.ts +13 -0
  77. package/oh-my-opencode/src/agents/librarian.ts +326 -0
  78. package/oh-my-opencode/src/agents/metis.ts +315 -0
  79. package/oh-my-opencode/src/agents/momus.test.ts +57 -0
  80. package/oh-my-opencode/src/agents/momus.ts +444 -0
  81. package/oh-my-opencode/src/agents/multimodal-looker.ts +56 -0
  82. package/oh-my-opencode/src/agents/oracle.ts +122 -0
  83. package/oh-my-opencode/src/agents/prometheus-prompt.test.ts +22 -0
  84. package/oh-my-opencode/src/agents/prometheus-prompt.ts +1196 -0
  85. package/oh-my-opencode/src/agents/sisyphus-junior.test.ts +232 -0
  86. package/oh-my-opencode/src/agents/sisyphus-junior.ts +134 -0
  87. package/oh-my-opencode/src/agents/sisyphus.ts +633 -0
  88. package/oh-my-opencode/src/agents/types.ts +80 -0
  89. package/oh-my-opencode/src/agents/utils.test.ts +311 -0
  90. package/oh-my-opencode/src/agents/utils.ts +240 -0
  91. package/oh-my-opencode/src/cli/AGENTS.md +91 -0
  92. package/oh-my-opencode/src/cli/config-manager.test.ts +364 -0
  93. package/oh-my-opencode/src/cli/config-manager.ts +641 -0
  94. package/oh-my-opencode/src/cli/doctor/checks/auth.test.ts +114 -0
  95. package/oh-my-opencode/src/cli/doctor/checks/auth.ts +115 -0
  96. package/oh-my-opencode/src/cli/doctor/checks/config.test.ts +103 -0
  97. package/oh-my-opencode/src/cli/doctor/checks/config.ts +123 -0
  98. package/oh-my-opencode/src/cli/doctor/checks/dependencies.test.ts +152 -0
  99. package/oh-my-opencode/src/cli/doctor/checks/dependencies.ts +163 -0
  100. package/oh-my-opencode/src/cli/doctor/checks/gh.test.ts +151 -0
  101. package/oh-my-opencode/src/cli/doctor/checks/gh.ts +171 -0
  102. package/oh-my-opencode/src/cli/doctor/checks/index.ts +34 -0
  103. package/oh-my-opencode/src/cli/doctor/checks/lsp.test.ts +134 -0
  104. package/oh-my-opencode/src/cli/doctor/checks/lsp.ts +77 -0
  105. package/oh-my-opencode/src/cli/doctor/checks/mcp.test.ts +115 -0
  106. package/oh-my-opencode/src/cli/doctor/checks/mcp.ts +128 -0
  107. package/oh-my-opencode/src/cli/doctor/checks/opencode.test.ts +227 -0
  108. package/oh-my-opencode/src/cli/doctor/checks/opencode.ts +178 -0
  109. package/oh-my-opencode/src/cli/doctor/checks/plugin.test.ts +109 -0
  110. package/oh-my-opencode/src/cli/doctor/checks/plugin.ts +124 -0
  111. package/oh-my-opencode/src/cli/doctor/checks/version.test.ts +148 -0
  112. package/oh-my-opencode/src/cli/doctor/checks/version.ts +135 -0
  113. package/oh-my-opencode/src/cli/doctor/constants.ts +72 -0
  114. package/oh-my-opencode/src/cli/doctor/formatter.test.ts +218 -0
  115. package/oh-my-opencode/src/cli/doctor/formatter.ts +140 -0
  116. package/oh-my-opencode/src/cli/doctor/index.ts +11 -0
  117. package/oh-my-opencode/src/cli/doctor/runner.test.ts +153 -0
  118. package/oh-my-opencode/src/cli/doctor/runner.ts +132 -0
  119. package/oh-my-opencode/src/cli/doctor/types.ts +113 -0
  120. package/oh-my-opencode/src/cli/get-local-version/formatter.ts +66 -0
  121. package/oh-my-opencode/src/cli/get-local-version/index.ts +106 -0
  122. package/oh-my-opencode/src/cli/get-local-version/types.ts +14 -0
  123. package/oh-my-opencode/src/cli/index.ts +153 -0
  124. package/oh-my-opencode/src/cli/install.ts +523 -0
  125. package/oh-my-opencode/src/cli/model-fallback.ts +246 -0
  126. package/oh-my-opencode/src/cli/run/completion.test.ts +170 -0
  127. package/oh-my-opencode/src/cli/run/completion.ts +79 -0
  128. package/oh-my-opencode/src/cli/run/events.test.ts +155 -0
  129. package/oh-my-opencode/src/cli/run/events.ts +325 -0
  130. package/oh-my-opencode/src/cli/run/index.ts +2 -0
  131. package/oh-my-opencode/src/cli/run/runner.ts +159 -0
  132. package/oh-my-opencode/src/cli/run/types.ts +76 -0
  133. package/oh-my-opencode/src/cli/types.ts +40 -0
  134. package/oh-my-opencode/src/config/index.ts +26 -0
  135. package/oh-my-opencode/src/config/schema.test.ts +444 -0
  136. package/oh-my-opencode/src/config/schema.ts +339 -0
  137. package/oh-my-opencode/src/features/AGENTS.md +77 -0
  138. package/oh-my-opencode/src/features/background-agent/concurrency.test.ts +418 -0
  139. package/oh-my-opencode/src/features/background-agent/concurrency.ts +137 -0
  140. package/oh-my-opencode/src/features/background-agent/index.ts +3 -0
  141. package/oh-my-opencode/src/features/background-agent/manager.test.ts +1928 -0
  142. package/oh-my-opencode/src/features/background-agent/manager.ts +1335 -0
  143. package/oh-my-opencode/src/features/background-agent/types.ts +66 -0
  144. package/oh-my-opencode/src/features/boulder-state/constants.ts +13 -0
  145. package/oh-my-opencode/src/features/boulder-state/index.ts +3 -0
  146. package/oh-my-opencode/src/features/boulder-state/storage.test.ts +250 -0
  147. package/oh-my-opencode/src/features/boulder-state/storage.ts +150 -0
  148. package/oh-my-opencode/src/features/boulder-state/types.ts +26 -0
  149. package/oh-my-opencode/src/features/builtin-commands/commands.ts +89 -0
  150. package/oh-my-opencode/src/features/builtin-commands/index.ts +2 -0
  151. package/oh-my-opencode/src/features/builtin-commands/templates/init-deep.ts +300 -0
  152. package/oh-my-opencode/src/features/builtin-commands/templates/ralph-loop.ts +38 -0
  153. package/oh-my-opencode/src/features/builtin-commands/templates/refactor.ts +619 -0
  154. package/oh-my-opencode/src/features/builtin-commands/templates/start-work.ts +72 -0
  155. package/oh-my-opencode/src/features/builtin-commands/types.ts +9 -0
  156. package/oh-my-opencode/src/features/builtin-skills/frontend-ui-ux/SKILL.md +78 -0
  157. package/oh-my-opencode/src/features/builtin-skills/git-master/SKILL.md +1105 -0
  158. package/oh-my-opencode/src/features/builtin-skills/index.ts +2 -0
  159. package/oh-my-opencode/src/features/builtin-skills/skills.ts +1203 -0
  160. package/oh-my-opencode/src/features/builtin-skills/types.ts +16 -0
  161. package/oh-my-opencode/src/features/claude-code-agent-loader/index.ts +2 -0
  162. package/oh-my-opencode/src/features/claude-code-agent-loader/loader.ts +90 -0
  163. package/oh-my-opencode/src/features/claude-code-agent-loader/types.ts +17 -0
  164. package/oh-my-opencode/src/features/claude-code-command-loader/index.ts +2 -0
  165. package/oh-my-opencode/src/features/claude-code-command-loader/loader.ts +144 -0
  166. package/oh-my-opencode/src/features/claude-code-command-loader/types.ts +46 -0
  167. package/oh-my-opencode/src/features/claude-code-mcp-loader/env-expander.ts +27 -0
  168. package/oh-my-opencode/src/features/claude-code-mcp-loader/index.ts +11 -0
  169. package/oh-my-opencode/src/features/claude-code-mcp-loader/loader.test.ts +162 -0
  170. package/oh-my-opencode/src/features/claude-code-mcp-loader/loader.ts +113 -0
  171. package/oh-my-opencode/src/features/claude-code-mcp-loader/transformer.ts +53 -0
  172. package/oh-my-opencode/src/features/claude-code-mcp-loader/types.ts +42 -0
  173. package/oh-my-opencode/src/features/claude-code-plugin-loader/index.ts +3 -0
  174. package/oh-my-opencode/src/features/claude-code-plugin-loader/loader.ts +486 -0
  175. package/oh-my-opencode/src/features/claude-code-plugin-loader/types.ts +210 -0
  176. package/oh-my-opencode/src/features/claude-code-session-state/index.ts +1 -0
  177. package/oh-my-opencode/src/features/claude-code-session-state/state.test.ts +126 -0
  178. package/oh-my-opencode/src/features/claude-code-session-state/state.ts +37 -0
  179. package/oh-my-opencode/src/features/context-injector/collector.test.ts +330 -0
  180. package/oh-my-opencode/src/features/context-injector/collector.ts +85 -0
  181. package/oh-my-opencode/src/features/context-injector/index.ts +14 -0
  182. package/oh-my-opencode/src/features/context-injector/injector.test.ts +122 -0
  183. package/oh-my-opencode/src/features/context-injector/injector.ts +167 -0
  184. package/oh-my-opencode/src/features/context-injector/types.ts +91 -0
  185. package/oh-my-opencode/src/features/hook-message-injector/constants.ts +6 -0
  186. package/oh-my-opencode/src/features/hook-message-injector/index.ts +4 -0
  187. package/oh-my-opencode/src/features/hook-message-injector/injector.ts +195 -0
  188. package/oh-my-opencode/src/features/hook-message-injector/types.ts +47 -0
  189. package/oh-my-opencode/src/features/opencode-skill-loader/async-loader.test.ts +448 -0
  190. package/oh-my-opencode/src/features/opencode-skill-loader/async-loader.ts +180 -0
  191. package/oh-my-opencode/src/features/opencode-skill-loader/blocking.test.ts +210 -0
  192. package/oh-my-opencode/src/features/opencode-skill-loader/blocking.ts +62 -0
  193. package/oh-my-opencode/src/features/opencode-skill-loader/discover-worker.ts +59 -0
  194. package/oh-my-opencode/src/features/opencode-skill-loader/index.ts +4 -0
  195. package/oh-my-opencode/src/features/opencode-skill-loader/loader.test.ts +273 -0
  196. package/oh-my-opencode/src/features/opencode-skill-loader/loader.ts +259 -0
  197. package/oh-my-opencode/src/features/opencode-skill-loader/merger.ts +267 -0
  198. package/oh-my-opencode/src/features/opencode-skill-loader/skill-content.test.ts +267 -0
  199. package/oh-my-opencode/src/features/opencode-skill-loader/skill-content.ts +206 -0
  200. package/oh-my-opencode/src/features/opencode-skill-loader/types.ts +38 -0
  201. package/oh-my-opencode/src/features/skill-mcp-manager/env-cleaner.test.ts +201 -0
  202. package/oh-my-opencode/src/features/skill-mcp-manager/env-cleaner.ts +27 -0
  203. package/oh-my-opencode/src/features/skill-mcp-manager/index.ts +2 -0
  204. package/oh-my-opencode/src/features/skill-mcp-manager/manager.test.ts +611 -0
  205. package/oh-my-opencode/src/features/skill-mcp-manager/manager.ts +520 -0
  206. package/oh-my-opencode/src/features/skill-mcp-manager/types.ts +14 -0
  207. package/oh-my-opencode/src/features/task-toast-manager/index.ts +2 -0
  208. package/oh-my-opencode/src/features/task-toast-manager/manager.test.ts +249 -0
  209. package/oh-my-opencode/src/features/task-toast-manager/manager.ts +215 -0
  210. package/oh-my-opencode/src/features/task-toast-manager/types.ts +24 -0
  211. package/oh-my-opencode/src/hooks/AGENTS.md +73 -0
  212. package/oh-my-opencode/src/hooks/agent-usage-reminder/constants.ts +54 -0
  213. package/oh-my-opencode/src/hooks/agent-usage-reminder/index.ts +109 -0
  214. package/oh-my-opencode/src/hooks/agent-usage-reminder/storage.ts +42 -0
  215. package/oh-my-opencode/src/hooks/agent-usage-reminder/types.ts +6 -0
  216. package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/executor.test.ts +307 -0
  217. package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/executor.ts +485 -0
  218. package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/index.ts +151 -0
  219. package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/parser.ts +201 -0
  220. package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/pruning-deduplication.test.ts +33 -0
  221. package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/pruning-deduplication.ts +184 -0
  222. package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/pruning-types.ts +44 -0
  223. package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/storage.test.ts +77 -0
  224. package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/storage.ts +250 -0
  225. package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/types.ts +42 -0
  226. package/oh-my-opencode/src/hooks/atlas/index.test.ts +953 -0
  227. package/oh-my-opencode/src/hooks/atlas/index.ts +771 -0
  228. package/oh-my-opencode/src/hooks/auto-slash-command/constants.ts +12 -0
  229. package/oh-my-opencode/src/hooks/auto-slash-command/detector.test.ts +296 -0
  230. package/oh-my-opencode/src/hooks/auto-slash-command/detector.ts +65 -0
  231. package/oh-my-opencode/src/hooks/auto-slash-command/executor.ts +205 -0
  232. package/oh-my-opencode/src/hooks/auto-slash-command/index.test.ts +254 -0
  233. package/oh-my-opencode/src/hooks/auto-slash-command/index.ts +89 -0
  234. package/oh-my-opencode/src/hooks/auto-slash-command/types.ts +23 -0
  235. package/oh-my-opencode/src/hooks/auto-update-checker/cache.ts +93 -0
  236. package/oh-my-opencode/src/hooks/auto-update-checker/checker.test.ts +24 -0
  237. package/oh-my-opencode/src/hooks/auto-update-checker/checker.ts +284 -0
  238. package/oh-my-opencode/src/hooks/auto-update-checker/constants.ts +64 -0
  239. package/oh-my-opencode/src/hooks/auto-update-checker/index.test.ts +254 -0
  240. package/oh-my-opencode/src/hooks/auto-update-checker/index.ts +260 -0
  241. package/oh-my-opencode/src/hooks/auto-update-checker/types.ts +29 -0
  242. package/oh-my-opencode/src/hooks/background-compaction/index.ts +87 -0
  243. package/oh-my-opencode/src/hooks/background-notification/index.ts +28 -0
  244. package/oh-my-opencode/src/hooks/background-notification/types.ts +5 -0
  245. package/oh-my-opencode/src/hooks/claude-code-hooks/AGENTS.md +70 -0
  246. package/oh-my-opencode/src/hooks/claude-code-hooks/config-loader.ts +107 -0
  247. package/oh-my-opencode/src/hooks/claude-code-hooks/config.ts +103 -0
  248. package/oh-my-opencode/src/hooks/claude-code-hooks/index.ts +401 -0
  249. package/oh-my-opencode/src/hooks/claude-code-hooks/plugin-config.ts +12 -0
  250. package/oh-my-opencode/src/hooks/claude-code-hooks/post-tool-use.ts +199 -0
  251. package/oh-my-opencode/src/hooks/claude-code-hooks/pre-compact.ts +109 -0
  252. package/oh-my-opencode/src/hooks/claude-code-hooks/pre-tool-use.ts +172 -0
  253. package/oh-my-opencode/src/hooks/claude-code-hooks/stop.ts +118 -0
  254. package/oh-my-opencode/src/hooks/claude-code-hooks/todo.ts +76 -0
  255. package/oh-my-opencode/src/hooks/claude-code-hooks/tool-input-cache.ts +47 -0
  256. package/oh-my-opencode/src/hooks/claude-code-hooks/transcript.ts +252 -0
  257. package/oh-my-opencode/src/hooks/claude-code-hooks/types.ts +204 -0
  258. package/oh-my-opencode/src/hooks/claude-code-hooks/user-prompt-submit.ts +117 -0
  259. package/oh-my-opencode/src/hooks/comment-checker/cli.test.ts +68 -0
  260. package/oh-my-opencode/src/hooks/comment-checker/cli.ts +221 -0
  261. package/oh-my-opencode/src/hooks/comment-checker/downloader.ts +196 -0
  262. package/oh-my-opencode/src/hooks/comment-checker/index.ts +171 -0
  263. package/oh-my-opencode/src/hooks/comment-checker/types.ts +33 -0
  264. package/oh-my-opencode/src/hooks/compaction-context-injector/index.ts +61 -0
  265. package/oh-my-opencode/src/hooks/context-window-monitor.ts +99 -0
  266. package/oh-my-opencode/src/hooks/delegate-task-retry/index.test.ts +119 -0
  267. package/oh-my-opencode/src/hooks/delegate-task-retry/index.ts +136 -0
  268. package/oh-my-opencode/src/hooks/directory-agents-injector/constants.ts +9 -0
  269. package/oh-my-opencode/src/hooks/directory-agents-injector/index.ts +182 -0
  270. package/oh-my-opencode/src/hooks/directory-agents-injector/storage.ts +48 -0
  271. package/oh-my-opencode/src/hooks/directory-agents-injector/types.ts +5 -0
  272. package/oh-my-opencode/src/hooks/directory-readme-injector/constants.ts +9 -0
  273. package/oh-my-opencode/src/hooks/directory-readme-injector/index.ts +177 -0
  274. package/oh-my-opencode/src/hooks/directory-readme-injector/storage.ts +48 -0
  275. package/oh-my-opencode/src/hooks/directory-readme-injector/types.ts +5 -0
  276. package/oh-my-opencode/src/hooks/edit-error-recovery/index.test.ts +126 -0
  277. package/oh-my-opencode/src/hooks/edit-error-recovery/index.ts +57 -0
  278. package/oh-my-opencode/src/hooks/empty-task-response-detector.ts +27 -0
  279. package/oh-my-opencode/src/hooks/index.ts +32 -0
  280. package/oh-my-opencode/src/hooks/interactive-bash-session/constants.ts +15 -0
  281. package/oh-my-opencode/src/hooks/interactive-bash-session/index.ts +262 -0
  282. package/oh-my-opencode/src/hooks/interactive-bash-session/storage.ts +59 -0
  283. package/oh-my-opencode/src/hooks/interactive-bash-session/types.ts +11 -0
  284. package/oh-my-opencode/src/hooks/keyword-detector/constants.ts +300 -0
  285. package/oh-my-opencode/src/hooks/keyword-detector/detector.ts +52 -0
  286. package/oh-my-opencode/src/hooks/keyword-detector/index.test.ts +529 -0
  287. package/oh-my-opencode/src/hooks/keyword-detector/index.ts +100 -0
  288. package/oh-my-opencode/src/hooks/keyword-detector/types.ts +4 -0
  289. package/oh-my-opencode/src/hooks/non-interactive-env/constants.ts +70 -0
  290. package/oh-my-opencode/src/hooks/non-interactive-env/detector.ts +19 -0
  291. package/oh-my-opencode/src/hooks/non-interactive-env/index.test.ts +323 -0
  292. package/oh-my-opencode/src/hooks/non-interactive-env/index.ts +63 -0
  293. package/oh-my-opencode/src/hooks/non-interactive-env/types.ts +3 -0
  294. package/oh-my-opencode/src/hooks/prometheus-md-only/constants.ts +32 -0
  295. package/oh-my-opencode/src/hooks/prometheus-md-only/index.test.ts +488 -0
  296. package/oh-my-opencode/src/hooks/prometheus-md-only/index.ts +136 -0
  297. package/oh-my-opencode/src/hooks/ralph-loop/constants.ts +5 -0
  298. package/oh-my-opencode/src/hooks/ralph-loop/index.test.ts +835 -0
  299. package/oh-my-opencode/src/hooks/ralph-loop/index.ts +417 -0
  300. package/oh-my-opencode/src/hooks/ralph-loop/storage.ts +115 -0
  301. package/oh-my-opencode/src/hooks/ralph-loop/types.ts +19 -0
  302. package/oh-my-opencode/src/hooks/rules-injector/constants.ts +30 -0
  303. package/oh-my-opencode/src/hooks/rules-injector/finder.test.ts +381 -0
  304. package/oh-my-opencode/src/hooks/rules-injector/finder.ts +263 -0
  305. package/oh-my-opencode/src/hooks/rules-injector/index.ts +223 -0
  306. package/oh-my-opencode/src/hooks/rules-injector/matcher.ts +63 -0
  307. package/oh-my-opencode/src/hooks/rules-injector/parser.test.ts +226 -0
  308. package/oh-my-opencode/src/hooks/rules-injector/parser.ts +211 -0
  309. package/oh-my-opencode/src/hooks/rules-injector/storage.ts +59 -0
  310. package/oh-my-opencode/src/hooks/rules-injector/types.ts +57 -0
  311. package/oh-my-opencode/src/hooks/session-notification-utils.ts +140 -0
  312. package/oh-my-opencode/src/hooks/session-notification.test.ts +361 -0
  313. package/oh-my-opencode/src/hooks/session-notification.ts +330 -0
  314. package/oh-my-opencode/src/hooks/session-recovery/constants.ts +10 -0
  315. package/oh-my-opencode/src/hooks/session-recovery/index.test.ts +223 -0
  316. package/oh-my-opencode/src/hooks/session-recovery/index.ts +435 -0
  317. package/oh-my-opencode/src/hooks/session-recovery/storage.ts +390 -0
  318. package/oh-my-opencode/src/hooks/session-recovery/types.ts +98 -0
  319. package/oh-my-opencode/src/hooks/start-work/index.test.ts +402 -0
  320. package/oh-my-opencode/src/hooks/start-work/index.ts +242 -0
  321. package/oh-my-opencode/src/hooks/task-resume-info/index.ts +36 -0
  322. package/oh-my-opencode/src/hooks/think-mode/detector.ts +57 -0
  323. package/oh-my-opencode/src/hooks/think-mode/index.test.ts +353 -0
  324. package/oh-my-opencode/src/hooks/think-mode/index.ts +89 -0
  325. package/oh-my-opencode/src/hooks/think-mode/switcher.test.ts +461 -0
  326. package/oh-my-opencode/src/hooks/think-mode/switcher.ts +222 -0
  327. package/oh-my-opencode/src/hooks/think-mode/types.ts +21 -0
  328. package/oh-my-opencode/src/hooks/thinking-block-validator/index.ts +171 -0
  329. package/oh-my-opencode/src/hooks/todo-continuation-enforcer.test.ts +876 -0
  330. package/oh-my-opencode/src/hooks/todo-continuation-enforcer.ts +480 -0
  331. package/oh-my-opencode/src/hooks/tool-output-truncator.test.ts +168 -0
  332. package/oh-my-opencode/src/hooks/tool-output-truncator.ts +61 -0
  333. package/oh-my-opencode/src/index.ts +589 -0
  334. package/oh-my-opencode/src/mcp/AGENTS.md +70 -0
  335. package/oh-my-opencode/src/mcp/context7.ts +6 -0
  336. package/oh-my-opencode/src/mcp/grep-app.ts +6 -0
  337. package/oh-my-opencode/src/mcp/index.test.ts +86 -0
  338. package/oh-my-opencode/src/mcp/index.ts +32 -0
  339. package/oh-my-opencode/src/mcp/types.ts +9 -0
  340. package/oh-my-opencode/src/mcp/websearch.ts +10 -0
  341. package/oh-my-opencode/src/plugin-config.test.ts +119 -0
  342. package/oh-my-opencode/src/plugin-config.ts +135 -0
  343. package/oh-my-opencode/src/plugin-handlers/config-handler.test.ts +103 -0
  344. package/oh-my-opencode/src/plugin-handlers/config-handler.ts +399 -0
  345. package/oh-my-opencode/src/plugin-handlers/index.ts +1 -0
  346. package/oh-my-opencode/src/plugin-state.ts +30 -0
  347. package/oh-my-opencode/src/shared/AGENTS.md +63 -0
  348. package/oh-my-opencode/src/shared/agent-tool-restrictions.ts +44 -0
  349. package/oh-my-opencode/src/shared/agent-variant.test.ts +83 -0
  350. package/oh-my-opencode/src/shared/agent-variant.ts +40 -0
  351. package/oh-my-opencode/src/shared/claude-config-dir.test.ts +60 -0
  352. package/oh-my-opencode/src/shared/claude-config-dir.ts +11 -0
  353. package/oh-my-opencode/src/shared/command-executor.ts +225 -0
  354. package/oh-my-opencode/src/shared/config-errors.ts +18 -0
  355. package/oh-my-opencode/src/shared/config-path.ts +47 -0
  356. package/oh-my-opencode/src/shared/data-path.ts +22 -0
  357. package/oh-my-opencode/src/shared/deep-merge.test.ts +336 -0
  358. package/oh-my-opencode/src/shared/deep-merge.ts +53 -0
  359. package/oh-my-opencode/src/shared/dynamic-truncator.ts +193 -0
  360. package/oh-my-opencode/src/shared/external-plugin-detector.test.ts +133 -0
  361. package/oh-my-opencode/src/shared/external-plugin-detector.ts +132 -0
  362. package/oh-my-opencode/src/shared/file-reference-resolver.ts +85 -0
  363. package/oh-my-opencode/src/shared/file-utils.ts +40 -0
  364. package/oh-my-opencode/src/shared/first-message-variant.test.ts +32 -0
  365. package/oh-my-opencode/src/shared/first-message-variant.ts +28 -0
  366. package/oh-my-opencode/src/shared/frontmatter.test.ts +262 -0
  367. package/oh-my-opencode/src/shared/frontmatter.ts +31 -0
  368. package/oh-my-opencode/src/shared/hook-disabled.ts +22 -0
  369. package/oh-my-opencode/src/shared/index.ts +29 -0
  370. package/oh-my-opencode/src/shared/jsonc-parser.test.ts +266 -0
  371. package/oh-my-opencode/src/shared/jsonc-parser.ts +66 -0
  372. package/oh-my-opencode/src/shared/logger.ts +20 -0
  373. package/oh-my-opencode/src/shared/migration.test.ts +602 -0
  374. package/oh-my-opencode/src/shared/migration.ts +191 -0
  375. package/oh-my-opencode/src/shared/model-resolver.test.ts +101 -0
  376. package/oh-my-opencode/src/shared/model-resolver.ts +35 -0
  377. package/oh-my-opencode/src/shared/model-sanitizer.ts +12 -0
  378. package/oh-my-opencode/src/shared/opencode-config-dir.test.ts +318 -0
  379. package/oh-my-opencode/src/shared/opencode-config-dir.ts +142 -0
  380. package/oh-my-opencode/src/shared/opencode-version.test.ts +223 -0
  381. package/oh-my-opencode/src/shared/opencode-version.ts +72 -0
  382. package/oh-my-opencode/src/shared/pattern-matcher.ts +29 -0
  383. package/oh-my-opencode/src/shared/permission-compat.test.ts +134 -0
  384. package/oh-my-opencode/src/shared/permission-compat.ts +77 -0
  385. package/oh-my-opencode/src/shared/session-cursor.test.ts +66 -0
  386. package/oh-my-opencode/src/shared/session-cursor.ts +85 -0
  387. package/oh-my-opencode/src/shared/shell-env.test.ts +278 -0
  388. package/oh-my-opencode/src/shared/shell-env.ts +111 -0
  389. package/oh-my-opencode/src/shared/snake-case.ts +49 -0
  390. package/oh-my-opencode/src/shared/system-directive.ts +40 -0
  391. package/oh-my-opencode/src/shared/tool-name.ts +26 -0
  392. package/oh-my-opencode/src/shared/zip-extractor.ts +83 -0
  393. package/oh-my-opencode/src/tools/AGENTS.md +74 -0
  394. package/oh-my-opencode/src/tools/ast-grep/cli.ts +230 -0
  395. package/oh-my-opencode/src/tools/ast-grep/constants.ts +261 -0
  396. package/oh-my-opencode/src/tools/ast-grep/downloader.ts +128 -0
  397. package/oh-my-opencode/src/tools/ast-grep/index.ts +13 -0
  398. package/oh-my-opencode/src/tools/ast-grep/tools.ts +112 -0
  399. package/oh-my-opencode/src/tools/ast-grep/types.ts +61 -0
  400. package/oh-my-opencode/src/tools/ast-grep/utils.ts +102 -0
  401. package/oh-my-opencode/src/tools/background-task/constants.ts +7 -0
  402. package/oh-my-opencode/src/tools/background-task/index.ts +7 -0
  403. package/oh-my-opencode/src/tools/background-task/tools.ts +479 -0
  404. package/oh-my-opencode/src/tools/background-task/types.ts +16 -0
  405. package/oh-my-opencode/src/tools/call-omo-agent/constants.ts +7 -0
  406. package/oh-my-opencode/src/tools/call-omo-agent/index.ts +3 -0
  407. package/oh-my-opencode/src/tools/call-omo-agent/tools.ts +338 -0
  408. package/oh-my-opencode/src/tools/call-omo-agent/types.ts +27 -0
  409. package/oh-my-opencode/src/tools/delegate-task/constants.ts +205 -0
  410. package/oh-my-opencode/src/tools/delegate-task/index.ts +3 -0
  411. package/oh-my-opencode/src/tools/delegate-task/tools.test.ts +1575 -0
  412. package/oh-my-opencode/src/tools/delegate-task/tools.ts +885 -0
  413. package/oh-my-opencode/src/tools/delegate-task/types.ts +9 -0
  414. package/oh-my-opencode/src/tools/glob/cli.test.ts +158 -0
  415. package/oh-my-opencode/src/tools/glob/cli.ts +191 -0
  416. package/oh-my-opencode/src/tools/glob/constants.ts +12 -0
  417. package/oh-my-opencode/src/tools/glob/index.ts +3 -0
  418. package/oh-my-opencode/src/tools/glob/tools.ts +41 -0
  419. package/oh-my-opencode/src/tools/glob/types.ts +22 -0
  420. package/oh-my-opencode/src/tools/glob/utils.ts +26 -0
  421. package/oh-my-opencode/src/tools/grep/cli.ts +229 -0
  422. package/oh-my-opencode/src/tools/grep/constants.ts +127 -0
  423. package/oh-my-opencode/src/tools/grep/downloader.test.ts +103 -0
  424. package/oh-my-opencode/src/tools/grep/downloader.ts +145 -0
  425. package/oh-my-opencode/src/tools/grep/index.ts +3 -0
  426. package/oh-my-opencode/src/tools/grep/tools.ts +40 -0
  427. package/oh-my-opencode/src/tools/grep/types.ts +39 -0
  428. package/oh-my-opencode/src/tools/grep/utils.ts +53 -0
  429. package/oh-my-opencode/src/tools/index.ts +72 -0
  430. package/oh-my-opencode/src/tools/interactive-bash/constants.ts +18 -0
  431. package/oh-my-opencode/src/tools/interactive-bash/index.ts +4 -0
  432. package/oh-my-opencode/src/tools/interactive-bash/tools.ts +126 -0
  433. package/oh-my-opencode/src/tools/interactive-bash/utils.ts +71 -0
  434. package/oh-my-opencode/src/tools/look-at/constants.ts +3 -0
  435. package/oh-my-opencode/src/tools/look-at/index.ts +3 -0
  436. package/oh-my-opencode/src/tools/look-at/tools.test.ts +73 -0
  437. package/oh-my-opencode/src/tools/look-at/tools.ts +173 -0
  438. package/oh-my-opencode/src/tools/look-at/types.ts +4 -0
  439. package/oh-my-opencode/src/tools/lsp/client.ts +596 -0
  440. package/oh-my-opencode/src/tools/lsp/config.test.ts +130 -0
  441. package/oh-my-opencode/src/tools/lsp/config.ts +285 -0
  442. package/oh-my-opencode/src/tools/lsp/constants.ts +390 -0
  443. package/oh-my-opencode/src/tools/lsp/index.ts +7 -0
  444. package/oh-my-opencode/src/tools/lsp/tools.ts +261 -0
  445. package/oh-my-opencode/src/tools/lsp/types.ts +124 -0
  446. package/oh-my-opencode/src/tools/lsp/utils.ts +406 -0
  447. package/oh-my-opencode/src/tools/session-manager/constants.ts +97 -0
  448. package/oh-my-opencode/src/tools/session-manager/index.ts +3 -0
  449. package/oh-my-opencode/src/tools/session-manager/storage.test.ts +315 -0
  450. package/oh-my-opencode/src/tools/session-manager/storage.ts +238 -0
  451. package/oh-my-opencode/src/tools/session-manager/tools.test.ts +124 -0
  452. package/oh-my-opencode/src/tools/session-manager/tools.ts +146 -0
  453. package/oh-my-opencode/src/tools/session-manager/types.ts +99 -0
  454. package/oh-my-opencode/src/tools/session-manager/utils.test.ts +160 -0
  455. package/oh-my-opencode/src/tools/session-manager/utils.ts +199 -0
  456. package/oh-my-opencode/src/tools/skill/constants.ts +8 -0
  457. package/oh-my-opencode/src/tools/skill/index.ts +3 -0
  458. package/oh-my-opencode/src/tools/skill/tools.test.ts +239 -0
  459. package/oh-my-opencode/src/tools/skill/tools.ts +200 -0
  460. package/oh-my-opencode/src/tools/skill/types.ts +31 -0
  461. package/oh-my-opencode/src/tools/skill-mcp/constants.ts +3 -0
  462. package/oh-my-opencode/src/tools/skill-mcp/index.ts +3 -0
  463. package/oh-my-opencode/src/tools/skill-mcp/tools.test.ts +215 -0
  464. package/oh-my-opencode/src/tools/skill-mcp/tools.ts +172 -0
  465. package/oh-my-opencode/src/tools/skill-mcp/types.ts +8 -0
  466. package/oh-my-opencode/src/tools/slashcommand/index.ts +2 -0
  467. package/oh-my-opencode/src/tools/slashcommand/tools.ts +252 -0
  468. package/oh-my-opencode/src/tools/slashcommand/types.ts +28 -0
  469. package/oh-my-opencode/test-setup.ts +6 -0
  470. package/oh-my-opencode/tsconfig.json +20 -0
  471. package/package.json +1 -4
  472. package/src/__tests__/git.test.ts +7 -2
  473. package/src/__tests__/manifest.test.ts +5 -5
  474. package/src/agents/repo-explorer.ts +2 -1
  475. package/src/git.ts +18 -3
  476. package/src/manifest.ts +22 -15
  477. package/src/scanner.ts +41 -32
@@ -0,0 +1,311 @@
1
+ import { describe, test, expect } from "bun:test"
2
+ import { createBuiltinAgents } from "./utils"
3
+ import type { AgentConfig } from "@opencode-ai/sdk"
4
+
5
+ const TEST_DEFAULT_MODEL = "anthropic/claude-opus-4-5"
6
+
7
+ describe("createBuiltinAgents with model overrides", () => {
8
+ test("Sisyphus with default model has thinking config", () => {
9
+ // #given - no overrides, using systemDefaultModel
10
+
11
+ // #when
12
+ const agents = createBuiltinAgents([], {}, undefined, TEST_DEFAULT_MODEL)
13
+
14
+ // #then
15
+ expect(agents.Sisyphus.model).toBe("anthropic/claude-opus-4-5")
16
+ expect(agents.Sisyphus.thinking).toEqual({ type: "enabled", budgetTokens: 32000 })
17
+ expect(agents.Sisyphus.reasoningEffort).toBeUndefined()
18
+ })
19
+
20
+ test("Sisyphus with GPT model override has reasoningEffort, no thinking", () => {
21
+ // #given
22
+ const overrides = {
23
+ Sisyphus: { model: "github-copilot/gpt-5.2" },
24
+ }
25
+
26
+ // #when
27
+ const agents = createBuiltinAgents([], overrides, undefined, TEST_DEFAULT_MODEL)
28
+
29
+ // #then
30
+ expect(agents.Sisyphus.model).toBe("github-copilot/gpt-5.2")
31
+ expect(agents.Sisyphus.reasoningEffort).toBe("medium")
32
+ expect(agents.Sisyphus.thinking).toBeUndefined()
33
+ })
34
+
35
+ test("Sisyphus with systemDefaultModel GPT has reasoningEffort, no thinking", () => {
36
+ // #given
37
+ const systemDefaultModel = "openai/gpt-5.2"
38
+
39
+ // #when
40
+ const agents = createBuiltinAgents([], {}, undefined, systemDefaultModel)
41
+
42
+ // #then
43
+ expect(agents.Sisyphus.model).toBe("openai/gpt-5.2")
44
+ expect(agents.Sisyphus.reasoningEffort).toBe("medium")
45
+ expect(agents.Sisyphus.thinking).toBeUndefined()
46
+ })
47
+
48
+ test("Oracle with default model has reasoningEffort", () => {
49
+ // #given - no overrides, using systemDefaultModel for other agents
50
+ // Oracle uses its own default model (openai/gpt-5.2) from the factory singleton
51
+
52
+ // #when
53
+ const agents = createBuiltinAgents([], {}, undefined, TEST_DEFAULT_MODEL)
54
+
55
+ // #then - Oracle uses systemDefaultModel since model is now required
56
+ expect(agents.oracle.model).toBe("anthropic/claude-opus-4-5")
57
+ expect(agents.oracle.thinking).toEqual({ type: "enabled", budgetTokens: 32000 })
58
+ expect(agents.oracle.reasoningEffort).toBeUndefined()
59
+ })
60
+
61
+ test("Oracle with GPT model override has reasoningEffort, no thinking", () => {
62
+ // #given
63
+ const overrides = {
64
+ oracle: { model: "openai/gpt-5.2" },
65
+ }
66
+
67
+ // #when
68
+ const agents = createBuiltinAgents([], overrides, undefined, TEST_DEFAULT_MODEL)
69
+
70
+ // #then
71
+ expect(agents.oracle.model).toBe("openai/gpt-5.2")
72
+ expect(agents.oracle.reasoningEffort).toBe("medium")
73
+ expect(agents.oracle.textVerbosity).toBe("high")
74
+ expect(agents.oracle.thinking).toBeUndefined()
75
+ })
76
+
77
+ test("Oracle with Claude model override has thinking, no reasoningEffort", () => {
78
+ // #given
79
+ const overrides = {
80
+ oracle: { model: "anthropic/claude-sonnet-4" },
81
+ }
82
+
83
+ // #when
84
+ const agents = createBuiltinAgents([], overrides, undefined, TEST_DEFAULT_MODEL)
85
+
86
+ // #then
87
+ expect(agents.oracle.model).toBe("anthropic/claude-sonnet-4")
88
+ expect(agents.oracle.thinking).toEqual({ type: "enabled", budgetTokens: 32000 })
89
+ expect(agents.oracle.reasoningEffort).toBeUndefined()
90
+ expect(agents.oracle.textVerbosity).toBeUndefined()
91
+ })
92
+
93
+ test("non-model overrides are still applied after factory rebuild", () => {
94
+ // #given
95
+ const overrides = {
96
+ Sisyphus: { model: "github-copilot/gpt-5.2", temperature: 0.5 },
97
+ }
98
+
99
+ // #when
100
+ const agents = createBuiltinAgents([], overrides, undefined, TEST_DEFAULT_MODEL)
101
+
102
+ // #then
103
+ expect(agents.Sisyphus.model).toBe("github-copilot/gpt-5.2")
104
+ expect(agents.Sisyphus.temperature).toBe(0.5)
105
+ })
106
+ })
107
+
108
+ describe("buildAgent with category and skills", () => {
109
+ const { buildAgent } = require("./utils")
110
+ const TEST_MODEL = "anthropic/claude-opus-4-5"
111
+
112
+ test("agent with category inherits category settings", () => {
113
+ // #given - agent factory that sets category but no model
114
+ const source = {
115
+ "test-agent": () =>
116
+ ({
117
+ description: "Test agent",
118
+ category: "visual-engineering",
119
+ }) as AgentConfig,
120
+ }
121
+
122
+ // #when
123
+ const agent = buildAgent(source["test-agent"], TEST_MODEL)
124
+
125
+ // #then - category's built-in model is applied
126
+ expect(agent.model).toBe("google/gemini-3-pro-preview")
127
+ })
128
+
129
+ test("agent with category and existing model keeps existing model", () => {
130
+ // #given
131
+ const source = {
132
+ "test-agent": () =>
133
+ ({
134
+ description: "Test agent",
135
+ category: "visual-engineering",
136
+ model: "custom/model",
137
+ }) as AgentConfig,
138
+ }
139
+
140
+ // #when
141
+ const agent = buildAgent(source["test-agent"], TEST_MODEL)
142
+
143
+ // #then - explicit model takes precedence over category
144
+ expect(agent.model).toBe("custom/model")
145
+ })
146
+
147
+ test("agent with category inherits variant", () => {
148
+ // #given
149
+ const source = {
150
+ "test-agent": () =>
151
+ ({
152
+ description: "Test agent",
153
+ category: "custom-category",
154
+ }) as AgentConfig,
155
+ }
156
+
157
+ const categories = {
158
+ "custom-category": {
159
+ model: "openai/gpt-5.2",
160
+ variant: "xhigh",
161
+ },
162
+ }
163
+
164
+ // #when
165
+ const agent = buildAgent(source["test-agent"], TEST_MODEL, categories)
166
+
167
+ // #then
168
+ expect(agent.model).toBe("openai/gpt-5.2")
169
+ expect(agent.variant).toBe("xhigh")
170
+ })
171
+
172
+ test("agent with skills has content prepended to prompt", () => {
173
+ // #given
174
+ const source = {
175
+ "test-agent": () =>
176
+ ({
177
+ description: "Test agent",
178
+ skills: ["frontend-ui-ux"],
179
+ prompt: "Original prompt content",
180
+ }) as AgentConfig,
181
+ }
182
+
183
+ // #when
184
+ const agent = buildAgent(source["test-agent"], TEST_MODEL)
185
+
186
+ // #then
187
+ expect(agent.prompt).toContain("Role: Designer-Turned-Developer")
188
+ expect(agent.prompt).toContain("Original prompt content")
189
+ expect(agent.prompt).toMatch(/Designer-Turned-Developer[\s\S]*Original prompt content/s)
190
+ })
191
+
192
+ test("agent with multiple skills has all content prepended", () => {
193
+ // #given
194
+ const source = {
195
+ "test-agent": () =>
196
+ ({
197
+ description: "Test agent",
198
+ skills: ["frontend-ui-ux"],
199
+ prompt: "Agent prompt",
200
+ }) as AgentConfig,
201
+ }
202
+
203
+ // #when
204
+ const agent = buildAgent(source["test-agent"], TEST_MODEL)
205
+
206
+ // #then
207
+ expect(agent.prompt).toContain("Role: Designer-Turned-Developer")
208
+ expect(agent.prompt).toContain("Agent prompt")
209
+ })
210
+
211
+ test("agent without category or skills works as before", () => {
212
+ // #given
213
+ const source = {
214
+ "test-agent": () =>
215
+ ({
216
+ description: "Test agent",
217
+ model: "custom/model",
218
+ temperature: 0.5,
219
+ prompt: "Base prompt",
220
+ }) as AgentConfig,
221
+ }
222
+
223
+ // #when
224
+ const agent = buildAgent(source["test-agent"], TEST_MODEL)
225
+
226
+ // #then
227
+ expect(agent.model).toBe("custom/model")
228
+ expect(agent.temperature).toBe(0.5)
229
+ expect(agent.prompt).toBe("Base prompt")
230
+ })
231
+
232
+ test("agent with category and skills applies both", () => {
233
+ // #given
234
+ const source = {
235
+ "test-agent": () =>
236
+ ({
237
+ description: "Test agent",
238
+ category: "ultrabrain",
239
+ skills: ["frontend-ui-ux"],
240
+ prompt: "Task description",
241
+ }) as AgentConfig,
242
+ }
243
+
244
+ // #when
245
+ const agent = buildAgent(source["test-agent"], TEST_MODEL)
246
+
247
+ // #then - category's built-in model and skills are applied
248
+ expect(agent.model).toBe("openai/gpt-5.2-codex")
249
+ expect(agent.variant).toBe("xhigh")
250
+ expect(agent.prompt).toContain("Role: Designer-Turned-Developer")
251
+ expect(agent.prompt).toContain("Task description")
252
+ })
253
+
254
+ test("agent with non-existent category has no effect", () => {
255
+ // #given
256
+ const source = {
257
+ "test-agent": () =>
258
+ ({
259
+ description: "Test agent",
260
+ category: "non-existent",
261
+ prompt: "Base prompt",
262
+ }) as AgentConfig,
263
+ }
264
+
265
+ // #when
266
+ const agent = buildAgent(source["test-agent"], TEST_MODEL)
267
+
268
+ // #then
269
+ // Note: The factory receives model, but if category doesn't exist, it's not applied
270
+ // The agent's model comes from the factory output (which doesn't set model)
271
+ expect(agent.model).toBeUndefined()
272
+ expect(agent.prompt).toBe("Base prompt")
273
+ })
274
+
275
+ test("agent with non-existent skills only prepends found ones", () => {
276
+ // #given
277
+ const source = {
278
+ "test-agent": () =>
279
+ ({
280
+ description: "Test agent",
281
+ skills: ["frontend-ui-ux", "non-existent-skill"],
282
+ prompt: "Base prompt",
283
+ }) as AgentConfig,
284
+ }
285
+
286
+ // #when
287
+ const agent = buildAgent(source["test-agent"], TEST_MODEL)
288
+
289
+ // #then
290
+ expect(agent.prompt).toContain("Role: Designer-Turned-Developer")
291
+ expect(agent.prompt).toContain("Base prompt")
292
+ })
293
+
294
+ test("agent with empty skills array keeps original prompt", () => {
295
+ // #given
296
+ const source = {
297
+ "test-agent": () =>
298
+ ({
299
+ description: "Test agent",
300
+ skills: [],
301
+ prompt: "Base prompt",
302
+ }) as AgentConfig,
303
+ }
304
+
305
+ // #when
306
+ const agent = buildAgent(source["test-agent"], TEST_MODEL)
307
+
308
+ // #then
309
+ expect(agent.prompt).toBe("Base prompt")
310
+ })
311
+ })
@@ -0,0 +1,240 @@
1
+ import type { AgentConfig } from "@opencode-ai/sdk"
2
+ import type { BuiltinAgentName, AgentOverrideConfig, AgentOverrides, AgentFactory, AgentPromptMetadata } from "./types"
3
+ import type { CategoriesConfig, CategoryConfig, GitMasterConfig } from "../config/schema"
4
+ import { createSisyphusAgent } from "./sisyphus"
5
+ import { createOracleAgent, ORACLE_PROMPT_METADATA } from "./oracle"
6
+ import { createLibrarianAgent, LIBRARIAN_PROMPT_METADATA } from "./librarian"
7
+ import { createExploreAgent, EXPLORE_PROMPT_METADATA } from "./explore"
8
+ import { createMultimodalLookerAgent, MULTIMODAL_LOOKER_PROMPT_METADATA } from "./multimodal-looker"
9
+ import { createMetisAgent } from "./metis"
10
+ import { createAtlasAgent } from "./atlas"
11
+ import { createMomusAgent } from "./momus"
12
+ import type { AvailableAgent, AvailableCategory, AvailableSkill } from "./dynamic-agent-prompt-builder"
13
+ import { deepMerge } from "../shared"
14
+ import { DEFAULT_CATEGORIES, CATEGORY_DESCRIPTIONS } from "../tools/delegate-task/constants"
15
+ import { resolveMultipleSkills } from "../features/opencode-skill-loader/skill-content"
16
+ import { createBuiltinSkills } from "../features/builtin-skills"
17
+
18
+ type AgentSource = AgentFactory | AgentConfig
19
+
20
+ const agentSources: Record<BuiltinAgentName, AgentSource> = {
21
+ Sisyphus: createSisyphusAgent,
22
+ oracle: createOracleAgent,
23
+ librarian: createLibrarianAgent,
24
+ explore: createExploreAgent,
25
+ "multimodal-looker": createMultimodalLookerAgent,
26
+ "Metis (Plan Consultant)": createMetisAgent,
27
+ "Momus (Plan Reviewer)": createMomusAgent,
28
+ // Note: Atlas is handled specially in createBuiltinAgents()
29
+ // because it needs OrchestratorContext, not just a model string
30
+ Atlas: createAtlasAgent as unknown as AgentFactory,
31
+ }
32
+
33
+ /**
34
+ * Metadata for each agent, used to build Sisyphus's dynamic prompt sections
35
+ * (Delegation Table, Tool Selection, Key Triggers, etc.)
36
+ */
37
+ const agentMetadata: Partial<Record<BuiltinAgentName, AgentPromptMetadata>> = {
38
+ oracle: ORACLE_PROMPT_METADATA,
39
+ librarian: LIBRARIAN_PROMPT_METADATA,
40
+ explore: EXPLORE_PROMPT_METADATA,
41
+ "multimodal-looker": MULTIMODAL_LOOKER_PROMPT_METADATA,
42
+ }
43
+
44
+ function isFactory(source: AgentSource): source is AgentFactory {
45
+ return typeof source === "function"
46
+ }
47
+
48
+ export function buildAgent(
49
+ source: AgentSource,
50
+ model: string,
51
+ categories?: CategoriesConfig,
52
+ gitMasterConfig?: GitMasterConfig
53
+ ): AgentConfig {
54
+ const base = isFactory(source) ? source(model) : source
55
+ const categoryConfigs: Record<string, CategoryConfig> = categories
56
+ ? { ...DEFAULT_CATEGORIES, ...categories }
57
+ : DEFAULT_CATEGORIES
58
+
59
+ const agentWithCategory = base as AgentConfig & { category?: string; skills?: string[]; variant?: string }
60
+ if (agentWithCategory.category) {
61
+ const categoryConfig = categoryConfigs[agentWithCategory.category]
62
+ if (categoryConfig) {
63
+ if (!base.model) {
64
+ base.model = categoryConfig.model
65
+ }
66
+ if (base.temperature === undefined && categoryConfig.temperature !== undefined) {
67
+ base.temperature = categoryConfig.temperature
68
+ }
69
+ if (base.variant === undefined && categoryConfig.variant !== undefined) {
70
+ base.variant = categoryConfig.variant
71
+ }
72
+ }
73
+ }
74
+
75
+ if (agentWithCategory.skills?.length) {
76
+ const { resolved } = resolveMultipleSkills(agentWithCategory.skills, { gitMasterConfig })
77
+ if (resolved.size > 0) {
78
+ const skillContent = Array.from(resolved.values()).join("\n\n")
79
+ base.prompt = skillContent + (base.prompt ? "\n\n" + base.prompt : "")
80
+ }
81
+ }
82
+
83
+ return base
84
+ }
85
+
86
+ /**
87
+ * Creates OmO-specific environment context (time, timezone, locale).
88
+ * Note: Working directory, platform, and date are already provided by OpenCode's system.ts,
89
+ * so we only include fields that OpenCode doesn't provide to avoid duplication.
90
+ * See: https://github.com/code-yeongyu/oh-my-opencode/issues/379
91
+ */
92
+ export function createEnvContext(): string {
93
+ const now = new Date()
94
+ const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone
95
+ const locale = Intl.DateTimeFormat().resolvedOptions().locale
96
+
97
+ const dateStr = now.toLocaleDateString(locale, {
98
+ weekday: "short",
99
+ year: "numeric",
100
+ month: "short",
101
+ day: "numeric",
102
+ })
103
+
104
+ const timeStr = now.toLocaleTimeString(locale, {
105
+ hour: "2-digit",
106
+ minute: "2-digit",
107
+ second: "2-digit",
108
+ hour12: true,
109
+ })
110
+
111
+ return `
112
+ <omo-env>
113
+ Current date: ${dateStr}
114
+ Current time: ${timeStr}
115
+ Timezone: ${timezone}
116
+ Locale: ${locale}
117
+ </omo-env>`
118
+ }
119
+
120
+ function mergeAgentConfig(
121
+ base: AgentConfig,
122
+ override: AgentOverrideConfig
123
+ ): AgentConfig {
124
+ const { prompt_append, ...rest } = override
125
+ const merged = deepMerge(base, rest as Partial<AgentConfig>)
126
+
127
+ if (prompt_append && merged.prompt) {
128
+ merged.prompt = merged.prompt + "\n" + prompt_append
129
+ }
130
+
131
+ return merged
132
+ }
133
+
134
+ export function createBuiltinAgents(
135
+ disabledAgents: BuiltinAgentName[] = [],
136
+ agentOverrides: AgentOverrides = {},
137
+ directory?: string,
138
+ systemDefaultModel?: string,
139
+ categories?: CategoriesConfig,
140
+ gitMasterConfig?: GitMasterConfig
141
+ ): Record<string, AgentConfig> {
142
+ if (!systemDefaultModel) {
143
+ throw new Error("createBuiltinAgents requires systemDefaultModel")
144
+ }
145
+
146
+ const result: Record<string, AgentConfig> = {}
147
+ const availableAgents: AvailableAgent[] = []
148
+
149
+ const mergedCategories = categories
150
+ ? { ...DEFAULT_CATEGORIES, ...categories }
151
+ : DEFAULT_CATEGORIES
152
+
153
+ const availableCategories: AvailableCategory[] = Object.entries(mergedCategories).map(([name]) => ({
154
+ name,
155
+ description: CATEGORY_DESCRIPTIONS[name] ?? "General tasks",
156
+ }))
157
+
158
+ const builtinSkills = createBuiltinSkills()
159
+ const availableSkills: AvailableSkill[] = builtinSkills.map((skill) => ({
160
+ name: skill.name,
161
+ description: skill.description,
162
+ location: "plugin" as const,
163
+ }))
164
+
165
+ for (const [name, source] of Object.entries(agentSources)) {
166
+ const agentName = name as BuiltinAgentName
167
+
168
+ if (agentName === "Sisyphus") continue
169
+ if (agentName === "Atlas") continue
170
+ if (disabledAgents.includes(agentName)) continue
171
+
172
+ const override = agentOverrides[agentName]
173
+ const model = override?.model ?? systemDefaultModel
174
+
175
+ let config = buildAgent(source, model, mergedCategories, gitMasterConfig)
176
+
177
+ if (agentName === "librarian" && directory && config.prompt) {
178
+ const envContext = createEnvContext()
179
+ config = { ...config, prompt: config.prompt + envContext }
180
+ }
181
+
182
+ if (override) {
183
+ config = mergeAgentConfig(config, override)
184
+ }
185
+
186
+ result[name] = config
187
+
188
+ const metadata = agentMetadata[agentName]
189
+ if (metadata) {
190
+ availableAgents.push({
191
+ name: agentName,
192
+ description: config.description ?? "",
193
+ metadata,
194
+ })
195
+ }
196
+ }
197
+
198
+ if (!disabledAgents.includes("Sisyphus")) {
199
+ const sisyphusOverride = agentOverrides["Sisyphus"]
200
+ const sisyphusModel = sisyphusOverride?.model ?? systemDefaultModel
201
+
202
+ let sisyphusConfig = createSisyphusAgent(
203
+ sisyphusModel,
204
+ availableAgents,
205
+ undefined,
206
+ availableSkills,
207
+ availableCategories
208
+ )
209
+
210
+ if (directory && sisyphusConfig.prompt) {
211
+ const envContext = createEnvContext()
212
+ sisyphusConfig = { ...sisyphusConfig, prompt: sisyphusConfig.prompt + envContext }
213
+ }
214
+
215
+ if (sisyphusOverride) {
216
+ sisyphusConfig = mergeAgentConfig(sisyphusConfig, sisyphusOverride)
217
+ }
218
+
219
+ result["Sisyphus"] = sisyphusConfig
220
+ }
221
+
222
+ if (!disabledAgents.includes("Atlas")) {
223
+ const orchestratorOverride = agentOverrides["Atlas"]
224
+ const orchestratorModel = orchestratorOverride?.model ?? systemDefaultModel
225
+ let orchestratorConfig = createAtlasAgent({
226
+ model: orchestratorModel,
227
+ availableAgents,
228
+ availableSkills,
229
+ userCategories: categories,
230
+ })
231
+
232
+ if (orchestratorOverride) {
233
+ orchestratorConfig = mergeAgentConfig(orchestratorConfig, orchestratorOverride)
234
+ }
235
+
236
+ result["Atlas"] = orchestratorConfig
237
+ }
238
+
239
+ return result
240
+ }
@@ -0,0 +1,91 @@
1
+ # CLI KNOWLEDGE BASE
2
+
3
+ ## OVERVIEW
4
+
5
+ CLI entry point: `bunx oh-my-opencode`. Interactive installer, doctor diagnostics, session runner. Uses Commander.js + @clack/prompts TUI.
6
+
7
+ ## STRUCTURE
8
+
9
+ ```
10
+ cli/
11
+ ├── index.ts # Commander.js entry, 5 subcommands
12
+ ├── install.ts # Interactive TUI installer (462 lines)
13
+ ├── config-manager.ts # JSONC parsing, multi-level merge (730 lines)
14
+ ├── types.ts # InstallArgs, InstallConfig, DetectedConfig
15
+ ├── doctor/
16
+ │ ├── index.ts # Doctor command entry
17
+ │ ├── runner.ts # Check orchestration
18
+ │ ├── formatter.ts # Colored output, symbols
19
+ │ ├── constants.ts # Check IDs, categories, symbols
20
+ │ ├── types.ts # CheckResult, CheckDefinition
21
+ │ └── checks/ # 14 checks across 6 categories
22
+ │ ├── version.ts # OpenCode + plugin version
23
+ │ ├── config.ts # JSONC validity, Zod validation
24
+ │ ├── auth.ts # Anthropic, OpenAI, Google
25
+ │ ├── dependencies.ts # AST-Grep, Comment Checker
26
+ │ ├── lsp.ts # LSP server connectivity
27
+ │ ├── mcp.ts # MCP server validation
28
+ │ └── gh.ts # GitHub CLI availability
29
+ ├── run/
30
+ │ ├── index.ts # Run command entry
31
+ │ └── runner.ts # Session launcher
32
+ └── get-local-version/
33
+ ├── index.ts # Version detection
34
+ └── formatter.ts # Version output
35
+ ```
36
+
37
+ ## CLI COMMANDS
38
+
39
+ | Command | Purpose |
40
+ |---------|---------|
41
+ | `install` | Interactive setup, subscription detection |
42
+ | `doctor` | 14 health checks, `--verbose`, `--json`, `--category` |
43
+ | `run` | Launch OpenCode session with completion enforcement |
44
+ | `get-local-version` | Version detection, update checking |
45
+
46
+ ## DOCTOR CHECK CATEGORIES
47
+
48
+ | Category | Checks |
49
+ |----------|--------|
50
+ | installation | opencode, plugin registration |
51
+ | configuration | config validity, Zod validation |
52
+ | authentication | anthropic, openai, google |
53
+ | dependencies | ast-grep CLI/NAPI, comment-checker |
54
+ | tools | LSP, MCP connectivity |
55
+ | updates | version comparison |
56
+
57
+ ## HOW TO ADD CHECK
58
+
59
+ 1. Create `src/cli/doctor/checks/my-check.ts`:
60
+ ```typescript
61
+ export function getMyCheckDefinition(): CheckDefinition {
62
+ return {
63
+ id: "my-check",
64
+ name: "My Check",
65
+ category: "configuration",
66
+ check: async () => ({ status: "pass", message: "OK" })
67
+ }
68
+ }
69
+ ```
70
+ 2. Export from `checks/index.ts`
71
+ 3. Add to `getAllCheckDefinitions()`
72
+
73
+ ## TUI FRAMEWORK
74
+
75
+ - **@clack/prompts**: `select()`, `spinner()`, `intro()`, `outro()`, `note()`
76
+ - **picocolors**: Colored terminal output
77
+ - **Symbols**: ✓ (pass), ✗ (fail), ⚠ (warn), ○ (skip)
78
+
79
+ ## CONFIG-MANAGER
80
+
81
+ - **JSONC**: Comments (`// ...`), block comments, trailing commas
82
+ - **Multi-source**: User (`~/.config/opencode/`) + Project (`.opencode/`)
83
+ - **Env override**: `OPENCODE_CONFIG_DIR` for profile isolation
84
+ - **Validation**: Zod schema with error aggregation
85
+
86
+ ## ANTI-PATTERNS
87
+
88
+ - **Blocking in non-TTY**: Check `process.stdout.isTTY`
89
+ - **Direct JSON.parse**: Use `parseJsonc()` for config
90
+ - **Silent failures**: Always return warn/fail in doctor
91
+ - **Hardcoded paths**: Use `ConfigManager`