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,260 @@
1
+ import type { PluginInput } from "@opencode-ai/plugin"
2
+ import { getCachedVersion, getLocalDevVersion, findPluginEntry, getLatestVersion, updatePinnedVersion } from "./checker"
3
+ import { invalidatePackage } from "./cache"
4
+ import { PACKAGE_NAME } from "./constants"
5
+ import { log } from "../../shared/logger"
6
+ import { getConfigLoadErrors, clearConfigLoadErrors } from "../../shared/config-errors"
7
+ import { runBunInstall } from "../../cli/config-manager"
8
+ import type { AutoUpdateCheckerOptions } from "./types"
9
+
10
+ const SISYPHUS_SPINNER = ["·", "•", "●", "○", "◌", "◦", " "]
11
+
12
+ export function isPrereleaseVersion(version: string): boolean {
13
+ return version.includes("-")
14
+ }
15
+
16
+ export function isDistTag(version: string): boolean {
17
+ const startsWithDigit = /^\d/.test(version)
18
+ return !startsWithDigit
19
+ }
20
+
21
+ export function isPrereleaseOrDistTag(pinnedVersion: string | null): boolean {
22
+ if (!pinnedVersion) return false
23
+ return isPrereleaseVersion(pinnedVersion) || isDistTag(pinnedVersion)
24
+ }
25
+
26
+ export function extractChannel(version: string | null): string {
27
+ if (!version) return "latest"
28
+
29
+ if (isDistTag(version)) {
30
+ return version
31
+ }
32
+
33
+ if (isPrereleaseVersion(version)) {
34
+ const prereleasePart = version.split("-")[1]
35
+ if (prereleasePart) {
36
+ const channelMatch = prereleasePart.match(/^(alpha|beta|rc|canary|next)/)
37
+ if (channelMatch) {
38
+ return channelMatch[1]
39
+ }
40
+ }
41
+ }
42
+
43
+ return "latest"
44
+ }
45
+
46
+ export function createAutoUpdateCheckerHook(ctx: PluginInput, options: AutoUpdateCheckerOptions = {}) {
47
+ const { showStartupToast = true, isSisyphusEnabled = false, autoUpdate = true } = options
48
+
49
+ const getToastMessage = (isUpdate: boolean, latestVersion?: string): string => {
50
+ if (isSisyphusEnabled) {
51
+ return isUpdate
52
+ ? `Sisyphus on steroids is steering OpenCode.\nv${latestVersion} available. Restart to apply.`
53
+ : `Sisyphus on steroids is steering OpenCode.`
54
+ }
55
+ return isUpdate
56
+ ? `OpenCode is now on Steroids. oMoMoMoMo...\nv${latestVersion} available. Restart OpenCode to apply.`
57
+ : `OpenCode is now on Steroids. oMoMoMoMo...`
58
+ }
59
+
60
+ let hasChecked = false
61
+
62
+ return {
63
+ event: ({ event }: { event: { type: string; properties?: unknown } }) => {
64
+ if (event.type !== "session.created") return
65
+ if (hasChecked) return
66
+
67
+ const props = event.properties as { info?: { parentID?: string } } | undefined
68
+ if (props?.info?.parentID) return
69
+
70
+ hasChecked = true
71
+
72
+ setTimeout(async () => {
73
+ const cachedVersion = getCachedVersion()
74
+ const localDevVersion = getLocalDevVersion(ctx.directory)
75
+ const displayVersion = localDevVersion ?? cachedVersion
76
+
77
+ await showConfigErrorsIfAny(ctx)
78
+
79
+ if (localDevVersion) {
80
+ if (showStartupToast) {
81
+ showLocalDevToast(ctx, displayVersion, isSisyphusEnabled).catch(() => {})
82
+ }
83
+ log("[auto-update-checker] Local development mode")
84
+ return
85
+ }
86
+
87
+ if (showStartupToast) {
88
+ showVersionToast(ctx, displayVersion, getToastMessage(false)).catch(() => {})
89
+ }
90
+
91
+ runBackgroundUpdateCheck(ctx, autoUpdate, getToastMessage).catch(err => {
92
+ log("[auto-update-checker] Background update check failed:", err)
93
+ })
94
+ }, 0)
95
+ },
96
+ }
97
+ }
98
+
99
+ async function runBackgroundUpdateCheck(
100
+ ctx: PluginInput,
101
+ autoUpdate: boolean,
102
+ getToastMessage: (isUpdate: boolean, latestVersion?: string) => string
103
+ ): Promise<void> {
104
+ const pluginInfo = findPluginEntry(ctx.directory)
105
+ if (!pluginInfo) {
106
+ log("[auto-update-checker] Plugin not found in config")
107
+ return
108
+ }
109
+
110
+ const cachedVersion = getCachedVersion()
111
+ const currentVersion = cachedVersion ?? pluginInfo.pinnedVersion
112
+ if (!currentVersion) {
113
+ log("[auto-update-checker] No version found (cached or pinned)")
114
+ return
115
+ }
116
+
117
+ const channel = extractChannel(pluginInfo.pinnedVersion ?? currentVersion)
118
+ const latestVersion = await getLatestVersion(channel)
119
+ if (!latestVersion) {
120
+ log("[auto-update-checker] Failed to fetch latest version for channel:", channel)
121
+ return
122
+ }
123
+
124
+ if (currentVersion === latestVersion) {
125
+ log("[auto-update-checker] Already on latest version for channel:", channel)
126
+ return
127
+ }
128
+
129
+ log(`[auto-update-checker] Update available (${channel}): ${currentVersion} → ${latestVersion}`)
130
+
131
+ if (!autoUpdate) {
132
+ await showUpdateAvailableToast(ctx, latestVersion, getToastMessage)
133
+ log("[auto-update-checker] Auto-update disabled, notification only")
134
+ return
135
+ }
136
+
137
+ if (pluginInfo.isPinned) {
138
+ const updated = updatePinnedVersion(pluginInfo.configPath, pluginInfo.entry, latestVersion)
139
+ if (!updated) {
140
+ await showUpdateAvailableToast(ctx, latestVersion, getToastMessage)
141
+ log("[auto-update-checker] Failed to update pinned version in config")
142
+ return
143
+ }
144
+ log(`[auto-update-checker] Config updated: ${pluginInfo.entry} → ${PACKAGE_NAME}@${latestVersion}`)
145
+ }
146
+
147
+ invalidatePackage(PACKAGE_NAME)
148
+
149
+ const installSuccess = await runBunInstallSafe()
150
+
151
+ if (installSuccess) {
152
+ await showAutoUpdatedToast(ctx, currentVersion, latestVersion)
153
+ log(`[auto-update-checker] Update installed: ${currentVersion} → ${latestVersion}`)
154
+ } else {
155
+ await showUpdateAvailableToast(ctx, latestVersion, getToastMessage)
156
+ log("[auto-update-checker] bun install failed; update not installed (falling back to notification-only)")
157
+ }
158
+ }
159
+
160
+ async function runBunInstallSafe(): Promise<boolean> {
161
+ try {
162
+ return await runBunInstall()
163
+ } catch (err) {
164
+ const errorMessage = err instanceof Error ? err.message : String(err)
165
+ log("[auto-update-checker] bun install error:", errorMessage)
166
+ return false
167
+ }
168
+ }
169
+
170
+ async function showConfigErrorsIfAny(ctx: PluginInput): Promise<void> {
171
+ const errors = getConfigLoadErrors()
172
+ if (errors.length === 0) return
173
+
174
+ const errorMessages = errors.map(e => `${e.path}: ${e.error}`).join("\n")
175
+ await ctx.client.tui
176
+ .showToast({
177
+ body: {
178
+ title: "Config Load Error",
179
+ message: `Failed to load config:\n${errorMessages}`,
180
+ variant: "error" as const,
181
+ duration: 10000,
182
+ },
183
+ })
184
+ .catch(() => {})
185
+
186
+ log(`[auto-update-checker] Config load errors shown: ${errors.length} error(s)`)
187
+ clearConfigLoadErrors()
188
+ }
189
+
190
+ async function showVersionToast(ctx: PluginInput, version: string | null, message: string): Promise<void> {
191
+ const displayVersion = version ?? "unknown"
192
+ await showSpinnerToast(ctx, displayVersion, message)
193
+ log(`[auto-update-checker] Startup toast shown: v${displayVersion}`)
194
+ }
195
+
196
+ async function showSpinnerToast(ctx: PluginInput, version: string, message: string): Promise<void> {
197
+ const totalDuration = 5000
198
+ const frameInterval = 100
199
+ const totalFrames = Math.floor(totalDuration / frameInterval)
200
+
201
+ for (let i = 0; i < totalFrames; i++) {
202
+ const spinner = SISYPHUS_SPINNER[i % SISYPHUS_SPINNER.length]
203
+ await ctx.client.tui
204
+ .showToast({
205
+ body: {
206
+ title: `${spinner} OhMyOpenCode ${version}`,
207
+ message,
208
+ variant: "info" as const,
209
+ duration: frameInterval + 50,
210
+ },
211
+ })
212
+ .catch(() => { })
213
+ await new Promise(resolve => setTimeout(resolve, frameInterval))
214
+ }
215
+ }
216
+
217
+ async function showUpdateAvailableToast(
218
+ ctx: PluginInput,
219
+ latestVersion: string,
220
+ getToastMessage: (isUpdate: boolean, latestVersion?: string) => string
221
+ ): Promise<void> {
222
+ await ctx.client.tui
223
+ .showToast({
224
+ body: {
225
+ title: `OhMyOpenCode ${latestVersion}`,
226
+ message: getToastMessage(true, latestVersion),
227
+ variant: "info" as const,
228
+ duration: 8000,
229
+ },
230
+ })
231
+ .catch(() => {})
232
+ log(`[auto-update-checker] Update available toast shown: v${latestVersion}`)
233
+ }
234
+
235
+ async function showAutoUpdatedToast(ctx: PluginInput, oldVersion: string, newVersion: string): Promise<void> {
236
+ await ctx.client.tui
237
+ .showToast({
238
+ body: {
239
+ title: `OhMyOpenCode Updated!`,
240
+ message: `v${oldVersion} → v${newVersion}\nRestart OpenCode to apply.`,
241
+ variant: "success" as const,
242
+ duration: 8000,
243
+ },
244
+ })
245
+ .catch(() => {})
246
+ log(`[auto-update-checker] Auto-updated toast shown: v${oldVersion} → v${newVersion}`)
247
+ }
248
+
249
+ async function showLocalDevToast(ctx: PluginInput, version: string | null, isSisyphusEnabled: boolean): Promise<void> {
250
+ const displayVersion = version ?? "dev"
251
+ const message = isSisyphusEnabled
252
+ ? "Sisyphus running in local development mode."
253
+ : "Running in local development mode. oMoMoMo..."
254
+ await showSpinnerToast(ctx, `${displayVersion} (dev)`, message)
255
+ log(`[auto-update-checker] Local dev toast shown: v${displayVersion}`)
256
+ }
257
+
258
+ export type { UpdateCheckResult, AutoUpdateCheckerOptions } from "./types"
259
+ export { checkForUpdate } from "./checker"
260
+ export { invalidatePackage, invalidateCache } from "./cache"
@@ -0,0 +1,29 @@
1
+ export interface NpmDistTags {
2
+ latest: string
3
+ [key: string]: string
4
+ }
5
+
6
+ export interface OpencodeConfig {
7
+ plugin?: string[]
8
+ [key: string]: unknown
9
+ }
10
+
11
+ export interface PackageJson {
12
+ version: string
13
+ name?: string
14
+ [key: string]: unknown
15
+ }
16
+
17
+ export interface UpdateCheckResult {
18
+ needsUpdate: boolean
19
+ currentVersion: string | null
20
+ latestVersion: string | null
21
+ isLocalDev: boolean
22
+ isPinned: boolean
23
+ }
24
+
25
+ export interface AutoUpdateCheckerOptions {
26
+ showStartupToast?: boolean
27
+ isSisyphusEnabled?: boolean
28
+ autoUpdate?: boolean
29
+ }
@@ -0,0 +1,87 @@
1
+ import type { BackgroundManager } from "../../features/background-agent"
2
+
3
+ interface CompactingInput {
4
+ sessionID: string
5
+ }
6
+
7
+ interface CompactingOutput {
8
+ context: string[]
9
+ prompt?: string
10
+ }
11
+
12
+ /**
13
+ * Background agent compaction hook - preserves task state during context compaction.
14
+ *
15
+ * When OpenCode compacts session context to save tokens, this hook injects
16
+ * information about running and recently completed background tasks so the
17
+ * agent doesn't lose awareness of delegated work.
18
+ */
19
+ export function createBackgroundCompactionHook(manager: BackgroundManager) {
20
+ return {
21
+ "experimental.session.compacting": async (
22
+ input: CompactingInput,
23
+ output: CompactingOutput
24
+ ): Promise<void> => {
25
+ const { sessionID } = input
26
+
27
+ // Get running tasks for this session
28
+ const running = manager.getRunningTasks()
29
+ .filter(t => t.parentSessionID === sessionID)
30
+ .map(t => ({
31
+ id: t.id,
32
+ agent: t.agent,
33
+ description: t.description,
34
+ startedAt: t.startedAt,
35
+ }))
36
+
37
+ // Get recently completed tasks (still in memory within 5-min retention)
38
+ const completed = manager.getCompletedTasks()
39
+ .filter(t => t.parentSessionID === sessionID)
40
+ .slice(-10) // Last 10 completed
41
+ .map(t => ({
42
+ id: t.id,
43
+ agent: t.agent,
44
+ description: t.description,
45
+ status: t.status,
46
+ }))
47
+
48
+ // Early exit if nothing to preserve
49
+ if (running.length === 0 && completed.length === 0) return
50
+
51
+ const sections: string[] = ["<background-tasks>"]
52
+
53
+ // Running tasks section
54
+ if (running.length > 0) {
55
+ sections.push("## Running Background Tasks")
56
+ sections.push("")
57
+ for (const t of running) {
58
+ const elapsed = t.startedAt
59
+ ? Math.floor((Date.now() - t.startedAt.getTime()) / 1000)
60
+ : 0
61
+ sections.push(`- **\`${t.id}\`** (${t.agent}): ${t.description} [${elapsed}s elapsed]`)
62
+ }
63
+ sections.push("")
64
+ sections.push("> **Note:** You WILL be notified when tasks complete.")
65
+ sections.push("> Do NOT poll - continue productive work.")
66
+ sections.push("")
67
+ }
68
+
69
+ // Completed tasks section
70
+ if (completed.length > 0) {
71
+ sections.push("## Recently Completed Tasks")
72
+ sections.push("")
73
+ for (const t of completed) {
74
+ const statusEmoji = t.status === "completed" ? "✅" : t.status === "error" ? "❌" : "⏱️"
75
+ sections.push(`- ${statusEmoji} **\`${t.id}\`**: ${t.description}`)
76
+ }
77
+ sections.push("")
78
+ }
79
+
80
+ sections.push("## Retrieval")
81
+ sections.push('Use `background_output(task_id="<id>")` to retrieve task results.')
82
+ sections.push("</background-tasks>")
83
+
84
+ output.context.push(sections.join("\n"))
85
+ }
86
+ }
87
+ }
@@ -0,0 +1,28 @@
1
+ import type { BackgroundManager } from "../../features/background-agent"
2
+
3
+ interface Event {
4
+ type: string
5
+ properties?: Record<string, unknown>
6
+ }
7
+
8
+ interface EventInput {
9
+ event: Event
10
+ }
11
+
12
+ /**
13
+ * Background notification hook - handles event routing to BackgroundManager.
14
+ *
15
+ * Notifications are now delivered directly via session.prompt({ noReply })
16
+ * from the manager, so this hook only needs to handle event routing.
17
+ */
18
+ export function createBackgroundNotificationHook(manager: BackgroundManager) {
19
+ const eventHandler = async ({ event }: EventInput) => {
20
+ manager.handleEvent(event)
21
+ }
22
+
23
+ return {
24
+ event: eventHandler,
25
+ }
26
+ }
27
+
28
+ export type { BackgroundNotificationHookConfig } from "./types"
@@ -0,0 +1,5 @@
1
+ import type { BackgroundTask } from "../../features/background-agent"
2
+
3
+ export interface BackgroundNotificationHookConfig {
4
+ formatNotification?: (tasks: BackgroundTask[]) => string
5
+ }
@@ -0,0 +1,70 @@
1
+ # CLAUDE CODE HOOKS COMPATIBILITY LAYER
2
+
3
+ ## OVERVIEW
4
+
5
+ Full Claude Code settings.json hook compatibility. Executes user-defined hooks at 5 lifecycle events: PreToolUse, PostToolUse, UserPromptSubmit, Stop, PreCompact.
6
+
7
+ ## STRUCTURE
8
+
9
+ ```
10
+ claude-code-hooks/
11
+ ├── index.ts # Main factory (401 lines) - createClaudeCodeHooksHook()
12
+ ├── config.ts # Loads ~/.claude/settings.json
13
+ ├── config-loader.ts # Extended config from multiple sources
14
+ ├── pre-tool-use.ts # PreToolUse hook executor (172 lines)
15
+ ├── post-tool-use.ts # PostToolUse hook executor (199 lines)
16
+ ├── user-prompt-submit.ts # UserPromptSubmit hook executor
17
+ ├── stop.ts # Stop hook executor (session idle)
18
+ ├── pre-compact.ts # PreCompact hook executor (context compaction)
19
+ ├── transcript.ts # Tool use recording (252 lines)
20
+ ├── tool-input-cache.ts # Caches tool inputs between pre/post
21
+ ├── types.ts # Hook types, context interfaces
22
+ ├── todo.ts # Todo JSON parsing fix
23
+ └── plugin-config.ts # Plugin config access
24
+ ```
25
+
26
+ ## HOOK LIFECYCLE
27
+
28
+ | Event | When | Can Block | Context Fields |
29
+ |-------|------|-----------|----------------|
30
+ | **PreToolUse** | Before tool | Yes | sessionId, toolName, toolInput, cwd |
31
+ | **PostToolUse** | After tool | Warn only | + toolOutput, transcriptPath |
32
+ | **UserPromptSubmit** | On user message | Yes | sessionId, prompt, parts, cwd |
33
+ | **Stop** | Session idle | inject_prompt | sessionId, parentSessionId |
34
+ | **PreCompact** | Before summarize | No | sessionId, cwd |
35
+
36
+ ## CONFIG SOURCES
37
+
38
+ Priority (highest first):
39
+ 1. `.claude/settings.json` (project)
40
+ 2. `~/.claude/settings.json` (user)
41
+
42
+ ```json
43
+ {
44
+ "hooks": {
45
+ "PreToolUse": [{ "matcher": "Edit", "command": "./check.sh" }],
46
+ "PostToolUse": [{ "command": "post-hook.sh $TOOL_NAME" }]
47
+ }
48
+ }
49
+ ```
50
+
51
+ ## HOOK EXECUTION
52
+
53
+ 1. User-defined hooks loaded from settings.json
54
+ 2. Matchers filter by tool name (supports wildcards)
55
+ 3. Commands executed via subprocess with environment:
56
+ - `$SESSION_ID`, `$TOOL_NAME`, `$TOOL_INPUT`, `$CWD`
57
+ 4. Exit codes: 0=pass, 1=warn, 2=block
58
+
59
+ ## KEY PATTERNS
60
+
61
+ - **Session tracking**: `Map<sessionID, state>` for first-message, error, interrupt
62
+ - **Input caching**: Tool inputs cached pre→post via `tool-input-cache.ts`
63
+ - **Transcript recording**: All tool uses logged for debugging
64
+ - **Todowrite fix**: Parses string todos to array (line 174-196)
65
+
66
+ ## ANTI-PATTERNS
67
+
68
+ - **Heavy PreToolUse logic**: Runs before EVERY tool call
69
+ - **Blocking non-critical**: Use warnings in PostToolUse instead
70
+ - **Missing error handling**: Always wrap subprocess calls
@@ -0,0 +1,107 @@
1
+ import { existsSync } from "fs"
2
+ import { homedir } from "os"
3
+ import { join } from "path"
4
+ import type { ClaudeHookEvent } from "./types"
5
+ import { log } from "../../shared/logger"
6
+
7
+ export interface DisabledHooksConfig {
8
+ Stop?: string[]
9
+ PreToolUse?: string[]
10
+ PostToolUse?: string[]
11
+ UserPromptSubmit?: string[]
12
+ PreCompact?: string[]
13
+ }
14
+
15
+ export interface PluginExtendedConfig {
16
+ disabledHooks?: DisabledHooksConfig
17
+ }
18
+
19
+ const USER_CONFIG_PATH = join(homedir(), ".config", "opencode", "opencode-cc-plugin.json")
20
+
21
+ function getProjectConfigPath(): string {
22
+ return join(process.cwd(), ".opencode", "opencode-cc-plugin.json")
23
+ }
24
+
25
+ async function loadConfigFromPath(path: string): Promise<PluginExtendedConfig | null> {
26
+ if (!existsSync(path)) {
27
+ return null
28
+ }
29
+
30
+ try {
31
+ const content = await Bun.file(path).text()
32
+ return JSON.parse(content) as PluginExtendedConfig
33
+ } catch (error) {
34
+ log("Failed to load config", { path, error })
35
+ return null
36
+ }
37
+ }
38
+
39
+ function mergeDisabledHooks(
40
+ base: DisabledHooksConfig | undefined,
41
+ override: DisabledHooksConfig | undefined
42
+ ): DisabledHooksConfig {
43
+ if (!override) return base ?? {}
44
+ if (!base) return override
45
+
46
+ return {
47
+ Stop: override.Stop ?? base.Stop,
48
+ PreToolUse: override.PreToolUse ?? base.PreToolUse,
49
+ PostToolUse: override.PostToolUse ?? base.PostToolUse,
50
+ UserPromptSubmit: override.UserPromptSubmit ?? base.UserPromptSubmit,
51
+ PreCompact: override.PreCompact ?? base.PreCompact,
52
+ }
53
+ }
54
+
55
+ export async function loadPluginExtendedConfig(): Promise<PluginExtendedConfig> {
56
+ const userConfig = await loadConfigFromPath(USER_CONFIG_PATH)
57
+ const projectConfig = await loadConfigFromPath(getProjectConfigPath())
58
+
59
+ const merged: PluginExtendedConfig = {
60
+ disabledHooks: mergeDisabledHooks(
61
+ userConfig?.disabledHooks,
62
+ projectConfig?.disabledHooks
63
+ ),
64
+ }
65
+
66
+ if (userConfig || projectConfig) {
67
+ log("Plugin extended config loaded", {
68
+ userConfigExists: userConfig !== null,
69
+ projectConfigExists: projectConfig !== null,
70
+ mergedDisabledHooks: merged.disabledHooks,
71
+ })
72
+ }
73
+
74
+ return merged
75
+ }
76
+
77
+ const regexCache = new Map<string, RegExp>()
78
+
79
+ function getRegex(pattern: string): RegExp {
80
+ let regex = regexCache.get(pattern)
81
+ if (!regex) {
82
+ try {
83
+ regex = new RegExp(pattern)
84
+ regexCache.set(pattern, regex)
85
+ } catch {
86
+ regex = new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
87
+ regexCache.set(pattern, regex)
88
+ }
89
+ }
90
+ return regex
91
+ }
92
+
93
+ export function isHookCommandDisabled(
94
+ eventType: ClaudeHookEvent,
95
+ command: string,
96
+ config: PluginExtendedConfig | null
97
+ ): boolean {
98
+ if (!config?.disabledHooks) return false
99
+
100
+ const patterns = config.disabledHooks[eventType]
101
+ if (!patterns || patterns.length === 0) return false
102
+
103
+ return patterns.some((pattern) => {
104
+ const regex = getRegex(pattern)
105
+ return regex.test(command)
106
+ })
107
+ }
@@ -0,0 +1,103 @@
1
+ import { join } from "path"
2
+ import { existsSync } from "fs"
3
+ import { getClaudeConfigDir } from "../../shared"
4
+ import type { ClaudeHooksConfig, HookMatcher, HookCommand } from "./types"
5
+
6
+ interface RawHookMatcher {
7
+ matcher?: string
8
+ pattern?: string
9
+ hooks: HookCommand[]
10
+ }
11
+
12
+ interface RawClaudeHooksConfig {
13
+ PreToolUse?: RawHookMatcher[]
14
+ PostToolUse?: RawHookMatcher[]
15
+ UserPromptSubmit?: RawHookMatcher[]
16
+ Stop?: RawHookMatcher[]
17
+ PreCompact?: RawHookMatcher[]
18
+ }
19
+
20
+ function normalizeHookMatcher(raw: RawHookMatcher): HookMatcher {
21
+ return {
22
+ matcher: raw.matcher ?? raw.pattern ?? "*",
23
+ hooks: raw.hooks,
24
+ }
25
+ }
26
+
27
+ function normalizeHooksConfig(raw: RawClaudeHooksConfig): ClaudeHooksConfig {
28
+ const result: ClaudeHooksConfig = {}
29
+ const eventTypes: (keyof RawClaudeHooksConfig)[] = [
30
+ "PreToolUse",
31
+ "PostToolUse",
32
+ "UserPromptSubmit",
33
+ "Stop",
34
+ "PreCompact",
35
+ ]
36
+
37
+ for (const eventType of eventTypes) {
38
+ if (raw[eventType]) {
39
+ result[eventType] = raw[eventType].map(normalizeHookMatcher)
40
+ }
41
+ }
42
+
43
+ return result
44
+ }
45
+
46
+ export function getClaudeSettingsPaths(customPath?: string): string[] {
47
+ const claudeConfigDir = getClaudeConfigDir()
48
+ const paths = [
49
+ join(claudeConfigDir, "settings.json"),
50
+ join(process.cwd(), ".claude", "settings.json"),
51
+ join(process.cwd(), ".claude", "settings.local.json"),
52
+ ]
53
+
54
+ if (customPath && existsSync(customPath)) {
55
+ paths.unshift(customPath)
56
+ }
57
+
58
+ return paths
59
+ }
60
+
61
+ function mergeHooksConfig(
62
+ base: ClaudeHooksConfig,
63
+ override: ClaudeHooksConfig
64
+ ): ClaudeHooksConfig {
65
+ const result: ClaudeHooksConfig = { ...base }
66
+ const eventTypes: (keyof ClaudeHooksConfig)[] = [
67
+ "PreToolUse",
68
+ "PostToolUse",
69
+ "UserPromptSubmit",
70
+ "Stop",
71
+ "PreCompact",
72
+ ]
73
+ for (const eventType of eventTypes) {
74
+ if (override[eventType]) {
75
+ result[eventType] = [...(base[eventType] || []), ...override[eventType]]
76
+ }
77
+ }
78
+ return result
79
+ }
80
+
81
+ export async function loadClaudeHooksConfig(
82
+ customSettingsPath?: string
83
+ ): Promise<ClaudeHooksConfig | null> {
84
+ const paths = getClaudeSettingsPaths(customSettingsPath)
85
+ let mergedConfig: ClaudeHooksConfig = {}
86
+
87
+ for (const settingsPath of paths) {
88
+ if (existsSync(settingsPath)) {
89
+ try {
90
+ const content = await Bun.file(settingsPath).text()
91
+ const settings = JSON.parse(content) as { hooks?: RawClaudeHooksConfig }
92
+ if (settings.hooks) {
93
+ const normalizedHooks = normalizeHooksConfig(settings.hooks)
94
+ mergedConfig = mergeHooksConfig(mergedConfig, normalizedHooks)
95
+ }
96
+ } catch {
97
+ continue
98
+ }
99
+ }
100
+ }
101
+
102
+ return Object.keys(mergedConfig).length > 0 ? mergedConfig : null
103
+ }