@zhijiewang/openharness 0.11.1 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (520) hide show
  1. package/README.md +212 -23
  2. package/dist/DeferredTool.d.ts +34 -0
  3. package/dist/DeferredTool.js +62 -0
  4. package/dist/agents/roles.js +62 -6
  5. package/dist/commands/index.js +31 -2
  6. package/dist/harness/config.d.ts +15 -0
  7. package/dist/harness/config.js +45 -23
  8. package/dist/harness/memory.d.ts +12 -0
  9. package/dist/harness/memory.js +53 -2
  10. package/dist/harness/session.d.ts +19 -0
  11. package/dist/harness/session.js +53 -0
  12. package/dist/harness/verification.d.ts +41 -0
  13. package/dist/harness/verification.js +197 -0
  14. package/dist/mcp/registry.d.ts +31 -0
  15. package/dist/mcp/registry.js +180 -0
  16. package/dist/query/index.js +9 -1
  17. package/dist/query/tools.js +30 -4
  18. package/dist/repl.js +34 -0
  19. package/dist/services/AgentDispatcher.d.ts +1 -0
  20. package/dist/services/AgentDispatcher.js +10 -1
  21. package/dist/services/CronExecutor.d.ts +38 -0
  22. package/dist/services/CronExecutor.js +130 -0
  23. package/dist/services/StreamingToolExecutor.js +28 -0
  24. package/dist/services/cron.d.ts +4 -0
  25. package/dist/services/cron.js +27 -0
  26. package/dist/tools/AgentTool/index.d.ts +3 -0
  27. package/dist/tools/AgentTool/index.js +17 -4
  28. package/dist/tools/MemoryTool/index.d.ts +2 -2
  29. package/dist/tools/ToolSearchTool/index.js +7 -0
  30. package/dist/tools.d.ts +8 -0
  31. package/dist/tools.js +40 -41
  32. package/package.json +5 -2
  33. package/dist/Tool.d.ts.map +0 -1
  34. package/dist/Tool.js.map +0 -1
  35. package/dist/Tool.test.d.ts +0 -2
  36. package/dist/Tool.test.d.ts.map +0 -1
  37. package/dist/Tool.test.js +0 -48
  38. package/dist/Tool.test.js.map +0 -1
  39. package/dist/agents/roles.d.ts.map +0 -1
  40. package/dist/agents/roles.js.map +0 -1
  41. package/dist/agents/roles.test.d.ts +0 -2
  42. package/dist/agents/roles.test.d.ts.map +0 -1
  43. package/dist/agents/roles.test.js +0 -38
  44. package/dist/agents/roles.test.js.map +0 -1
  45. package/dist/commands/commands-new.test.d.ts +0 -5
  46. package/dist/commands/commands-new.test.d.ts.map +0 -1
  47. package/dist/commands/commands-new.test.js +0 -132
  48. package/dist/commands/commands-new.test.js.map +0 -1
  49. package/dist/commands/commands.test.d.ts +0 -2
  50. package/dist/commands/commands.test.d.ts.map +0 -1
  51. package/dist/commands/commands.test.js +0 -98
  52. package/dist/commands/commands.test.js.map +0 -1
  53. package/dist/commands/cybergotchi.d.ts.map +0 -1
  54. package/dist/commands/cybergotchi.js.map +0 -1
  55. package/dist/commands/index.d.ts.map +0 -1
  56. package/dist/commands/index.js.map +0 -1
  57. package/dist/components/App.d.ts.map +0 -1
  58. package/dist/components/App.js.map +0 -1
  59. package/dist/components/CompanionFooter.d.ts.map +0 -1
  60. package/dist/components/CompanionFooter.js.map +0 -1
  61. package/dist/components/CybergotchiBubble.d.ts.map +0 -1
  62. package/dist/components/CybergotchiBubble.js.map +0 -1
  63. package/dist/components/CybergotchiPanel.d.ts.map +0 -1
  64. package/dist/components/CybergotchiPanel.js.map +0 -1
  65. package/dist/components/CybergotchiPanelConnected.d.ts.map +0 -1
  66. package/dist/components/CybergotchiPanelConnected.js.map +0 -1
  67. package/dist/components/CybergotchiSetup.d.ts.map +0 -1
  68. package/dist/components/CybergotchiSetup.js.map +0 -1
  69. package/dist/components/CybergotchiSprite.d.ts.map +0 -1
  70. package/dist/components/CybergotchiSprite.js.map +0 -1
  71. package/dist/components/DiffView.d.ts.map +0 -1
  72. package/dist/components/DiffView.js.map +0 -1
  73. package/dist/components/ErrorBoundary.d.ts.map +0 -1
  74. package/dist/components/ErrorBoundary.js.map +0 -1
  75. package/dist/components/InitWizard.d.ts.map +0 -1
  76. package/dist/components/InitWizard.js.map +0 -1
  77. package/dist/components/Markdown.d.ts.map +0 -1
  78. package/dist/components/Markdown.js.map +0 -1
  79. package/dist/components/Messages.d.ts.map +0 -1
  80. package/dist/components/Messages.js.map +0 -1
  81. package/dist/components/PermissionPrompt.d.ts.map +0 -1
  82. package/dist/components/PermissionPrompt.js.map +0 -1
  83. package/dist/components/REPL.d.ts.map +0 -1
  84. package/dist/components/REPL.js.map +0 -1
  85. package/dist/components/Spinner.d.ts.map +0 -1
  86. package/dist/components/Spinner.js.map +0 -1
  87. package/dist/components/TextInput.d.ts.map +0 -1
  88. package/dist/components/TextInput.js.map +0 -1
  89. package/dist/components/ToolCallDisplay.d.ts.map +0 -1
  90. package/dist/components/ToolCallDisplay.js.map +0 -1
  91. package/dist/cybergotchi/bones.d.ts.map +0 -1
  92. package/dist/cybergotchi/bones.js.map +0 -1
  93. package/dist/cybergotchi/bones.test.d.ts +0 -2
  94. package/dist/cybergotchi/bones.test.d.ts.map +0 -1
  95. package/dist/cybergotchi/bones.test.js +0 -100
  96. package/dist/cybergotchi/bones.test.js.map +0 -1
  97. package/dist/cybergotchi/config.d.ts.map +0 -1
  98. package/dist/cybergotchi/config.js.map +0 -1
  99. package/dist/cybergotchi/events.d.ts.map +0 -1
  100. package/dist/cybergotchi/events.js.map +0 -1
  101. package/dist/cybergotchi/needs.d.ts.map +0 -1
  102. package/dist/cybergotchi/needs.js.map +0 -1
  103. package/dist/cybergotchi/needs.test.d.ts +0 -2
  104. package/dist/cybergotchi/needs.test.d.ts.map +0 -1
  105. package/dist/cybergotchi/needs.test.js +0 -150
  106. package/dist/cybergotchi/needs.test.js.map +0 -1
  107. package/dist/cybergotchi/personality.d.ts.map +0 -1
  108. package/dist/cybergotchi/personality.js.map +0 -1
  109. package/dist/cybergotchi/species.d.ts.map +0 -1
  110. package/dist/cybergotchi/species.js.map +0 -1
  111. package/dist/cybergotchi/speech.d.ts.map +0 -1
  112. package/dist/cybergotchi/speech.js.map +0 -1
  113. package/dist/cybergotchi/types.d.ts.map +0 -1
  114. package/dist/cybergotchi/types.js.map +0 -1
  115. package/dist/cybergotchi/useCybergotchi.d.ts.map +0 -1
  116. package/dist/cybergotchi/useCybergotchi.js.map +0 -1
  117. package/dist/git/git.test.d.ts +0 -2
  118. package/dist/git/git.test.d.ts.map +0 -1
  119. package/dist/git/git.test.js +0 -141
  120. package/dist/git/git.test.js.map +0 -1
  121. package/dist/git/index.d.ts.map +0 -1
  122. package/dist/git/index.js.map +0 -1
  123. package/dist/harness/checkpoints.d.ts.map +0 -1
  124. package/dist/harness/checkpoints.js.map +0 -1
  125. package/dist/harness/config.d.ts.map +0 -1
  126. package/dist/harness/config.js.map +0 -1
  127. package/dist/harness/config.test.d.ts +0 -2
  128. package/dist/harness/config.test.d.ts.map +0 -1
  129. package/dist/harness/config.test.js +0 -107
  130. package/dist/harness/config.test.js.map +0 -1
  131. package/dist/harness/context-warning.d.ts.map +0 -1
  132. package/dist/harness/context-warning.js.map +0 -1
  133. package/dist/harness/context-warning.test.d.ts +0 -2
  134. package/dist/harness/context-warning.test.d.ts.map +0 -1
  135. package/dist/harness/context-warning.test.js +0 -72
  136. package/dist/harness/context-warning.test.js.map +0 -1
  137. package/dist/harness/cost.d.ts.map +0 -1
  138. package/dist/harness/cost.js.map +0 -1
  139. package/dist/harness/cost.test.d.ts +0 -2
  140. package/dist/harness/cost.test.d.ts.map +0 -1
  141. package/dist/harness/cost.test.js +0 -43
  142. package/dist/harness/cost.test.js.map +0 -1
  143. package/dist/harness/credentials.d.ts.map +0 -1
  144. package/dist/harness/credentials.js.map +0 -1
  145. package/dist/harness/credentials.test.d.ts +0 -2
  146. package/dist/harness/credentials.test.d.ts.map +0 -1
  147. package/dist/harness/credentials.test.js +0 -113
  148. package/dist/harness/credentials.test.js.map +0 -1
  149. package/dist/harness/hooks-env.test.d.ts +0 -5
  150. package/dist/harness/hooks-env.test.d.ts.map +0 -1
  151. package/dist/harness/hooks-env.test.js +0 -41
  152. package/dist/harness/hooks-env.test.js.map +0 -1
  153. package/dist/harness/hooks.d.ts.map +0 -1
  154. package/dist/harness/hooks.js.map +0 -1
  155. package/dist/harness/hooks.test.d.ts +0 -2
  156. package/dist/harness/hooks.test.d.ts.map +0 -1
  157. package/dist/harness/hooks.test.js +0 -24
  158. package/dist/harness/hooks.test.js.map +0 -1
  159. package/dist/harness/keybindings.d.ts.map +0 -1
  160. package/dist/harness/keybindings.js.map +0 -1
  161. package/dist/harness/keybindings.test.d.ts +0 -2
  162. package/dist/harness/keybindings.test.d.ts.map +0 -1
  163. package/dist/harness/keybindings.test.js +0 -38
  164. package/dist/harness/keybindings.test.js.map +0 -1
  165. package/dist/harness/memory.d.ts.map +0 -1
  166. package/dist/harness/memory.js.map +0 -1
  167. package/dist/harness/memory.test.d.ts +0 -2
  168. package/dist/harness/memory.test.d.ts.map +0 -1
  169. package/dist/harness/memory.test.js +0 -65
  170. package/dist/harness/memory.test.js.map +0 -1
  171. package/dist/harness/onboarding.d.ts.map +0 -1
  172. package/dist/harness/onboarding.js.map +0 -1
  173. package/dist/harness/onboarding.test.d.ts +0 -5
  174. package/dist/harness/onboarding.test.d.ts.map +0 -1
  175. package/dist/harness/onboarding.test.js +0 -93
  176. package/dist/harness/onboarding.test.js.map +0 -1
  177. package/dist/harness/plugins.d.ts.map +0 -1
  178. package/dist/harness/plugins.js.map +0 -1
  179. package/dist/harness/plugins.test.d.ts +0 -2
  180. package/dist/harness/plugins.test.d.ts.map +0 -1
  181. package/dist/harness/plugins.test.js +0 -97
  182. package/dist/harness/plugins.test.js.map +0 -1
  183. package/dist/harness/rules.d.ts.map +0 -1
  184. package/dist/harness/rules.js.map +0 -1
  185. package/dist/harness/rules.test.d.ts +0 -2
  186. package/dist/harness/rules.test.d.ts.map +0 -1
  187. package/dist/harness/rules.test.js +0 -54
  188. package/dist/harness/rules.test.js.map +0 -1
  189. package/dist/harness/session.d.ts.map +0 -1
  190. package/dist/harness/session.js.map +0 -1
  191. package/dist/harness/session.test.d.ts +0 -2
  192. package/dist/harness/session.test.d.ts.map +0 -1
  193. package/dist/harness/session.test.js +0 -37
  194. package/dist/harness/session.test.js.map +0 -1
  195. package/dist/harness/store.d.ts.map +0 -1
  196. package/dist/harness/store.js.map +0 -1
  197. package/dist/harness/store.test.d.ts +0 -2
  198. package/dist/harness/store.test.d.ts.map +0 -1
  199. package/dist/harness/store.test.js +0 -71
  200. package/dist/harness/store.test.js.map +0 -1
  201. package/dist/harness/submit-handler.d.ts.map +0 -1
  202. package/dist/harness/submit-handler.js.map +0 -1
  203. package/dist/harness/submit-handler.test.d.ts +0 -2
  204. package/dist/harness/submit-handler.test.d.ts.map +0 -1
  205. package/dist/harness/submit-handler.test.js +0 -62
  206. package/dist/harness/submit-handler.test.js.map +0 -1
  207. package/dist/lsp/client.d.ts.map +0 -1
  208. package/dist/lsp/client.js.map +0 -1
  209. package/dist/lsp/client.test.d.ts +0 -2
  210. package/dist/lsp/client.test.d.ts.map +0 -1
  211. package/dist/lsp/client.test.js +0 -44
  212. package/dist/lsp/client.test.js.map +0 -1
  213. package/dist/main.d.ts.map +0 -1
  214. package/dist/main.js.map +0 -1
  215. package/dist/mcp/DeferredMcpTool.d.ts.map +0 -1
  216. package/dist/mcp/DeferredMcpTool.js.map +0 -1
  217. package/dist/mcp/McpTool.d.ts.map +0 -1
  218. package/dist/mcp/McpTool.js.map +0 -1
  219. package/dist/mcp/McpTool.test.d.ts +0 -2
  220. package/dist/mcp/McpTool.test.d.ts.map +0 -1
  221. package/dist/mcp/McpTool.test.js +0 -53
  222. package/dist/mcp/McpTool.test.js.map +0 -1
  223. package/dist/mcp/client.d.ts.map +0 -1
  224. package/dist/mcp/client.js.map +0 -1
  225. package/dist/mcp/loader.d.ts.map +0 -1
  226. package/dist/mcp/loader.js.map +0 -1
  227. package/dist/mcp/loader.test.d.ts +0 -7
  228. package/dist/mcp/loader.test.d.ts.map +0 -1
  229. package/dist/mcp/loader.test.js +0 -25
  230. package/dist/mcp/loader.test.js.map +0 -1
  231. package/dist/mcp/schema.d.ts.map +0 -1
  232. package/dist/mcp/schema.js.map +0 -1
  233. package/dist/mcp/schema.test.d.ts +0 -2
  234. package/dist/mcp/schema.test.d.ts.map +0 -1
  235. package/dist/mcp/schema.test.js +0 -33
  236. package/dist/mcp/schema.test.js.map +0 -1
  237. package/dist/mcp/server.d.ts.map +0 -1
  238. package/dist/mcp/server.js.map +0 -1
  239. package/dist/mcp/server.test.d.ts +0 -2
  240. package/dist/mcp/server.test.d.ts.map +0 -1
  241. package/dist/mcp/server.test.js +0 -54
  242. package/dist/mcp/server.test.js.map +0 -1
  243. package/dist/mcp/types.d.ts.map +0 -1
  244. package/dist/mcp/types.js.map +0 -1
  245. package/dist/providers/anthropic-convert.test.d.ts +0 -5
  246. package/dist/providers/anthropic-convert.test.d.ts.map +0 -1
  247. package/dist/providers/anthropic-convert.test.js +0 -98
  248. package/dist/providers/anthropic-convert.test.js.map +0 -1
  249. package/dist/providers/anthropic.d.ts.map +0 -1
  250. package/dist/providers/anthropic.js.map +0 -1
  251. package/dist/providers/anthropic.test.d.ts +0 -2
  252. package/dist/providers/anthropic.test.d.ts.map +0 -1
  253. package/dist/providers/anthropic.test.js +0 -18
  254. package/dist/providers/anthropic.test.js.map +0 -1
  255. package/dist/providers/base.d.ts.map +0 -1
  256. package/dist/providers/base.js.map +0 -1
  257. package/dist/providers/index.d.ts.map +0 -1
  258. package/dist/providers/index.js.map +0 -1
  259. package/dist/providers/llamacpp.d.ts.map +0 -1
  260. package/dist/providers/llamacpp.js.map +0 -1
  261. package/dist/providers/llamacpp.test.d.ts +0 -2
  262. package/dist/providers/llamacpp.test.d.ts.map +0 -1
  263. package/dist/providers/llamacpp.test.js +0 -33
  264. package/dist/providers/llamacpp.test.js.map +0 -1
  265. package/dist/providers/message-format.test.d.ts +0 -2
  266. package/dist/providers/message-format.test.d.ts.map +0 -1
  267. package/dist/providers/message-format.test.js +0 -31
  268. package/dist/providers/message-format.test.js.map +0 -1
  269. package/dist/providers/ollama.d.ts.map +0 -1
  270. package/dist/providers/ollama.js.map +0 -1
  271. package/dist/providers/ollama.test.d.ts +0 -2
  272. package/dist/providers/ollama.test.d.ts.map +0 -1
  273. package/dist/providers/ollama.test.js +0 -40
  274. package/dist/providers/ollama.test.js.map +0 -1
  275. package/dist/providers/openai.d.ts.map +0 -1
  276. package/dist/providers/openai.js.map +0 -1
  277. package/dist/providers/openai.test.d.ts +0 -2
  278. package/dist/providers/openai.test.d.ts.map +0 -1
  279. package/dist/providers/openai.test.js +0 -23
  280. package/dist/providers/openai.test.js.map +0 -1
  281. package/dist/providers/openrouter.d.ts.map +0 -1
  282. package/dist/providers/openrouter.js.map +0 -1
  283. package/dist/providers/stream-parsing.test.d.ts +0 -6
  284. package/dist/providers/stream-parsing.test.d.ts.map +0 -1
  285. package/dist/providers/stream-parsing.test.js +0 -174
  286. package/dist/providers/stream-parsing.test.js.map +0 -1
  287. package/dist/query/compress.d.ts.map +0 -1
  288. package/dist/query/compress.js.map +0 -1
  289. package/dist/query/errors.d.ts.map +0 -1
  290. package/dist/query/errors.js.map +0 -1
  291. package/dist/query/index.d.ts.map +0 -1
  292. package/dist/query/index.js.map +0 -1
  293. package/dist/query/tools.d.ts.map +0 -1
  294. package/dist/query/tools.js.map +0 -1
  295. package/dist/query/types.d.ts.map +0 -1
  296. package/dist/query/types.js.map +0 -1
  297. package/dist/query.d.ts.map +0 -1
  298. package/dist/query.js.map +0 -1
  299. package/dist/query.test.d.ts +0 -2
  300. package/dist/query.test.d.ts.map +0 -1
  301. package/dist/query.test.js +0 -121
  302. package/dist/query.test.js.map +0 -1
  303. package/dist/remote/server.d.ts.map +0 -1
  304. package/dist/remote/server.js.map +0 -1
  305. package/dist/remote/server.test.d.ts +0 -2
  306. package/dist/remote/server.test.d.ts.map +0 -1
  307. package/dist/remote/server.test.js +0 -120
  308. package/dist/remote/server.test.js.map +0 -1
  309. package/dist/renderer/cells.d.ts.map +0 -1
  310. package/dist/renderer/cells.js.map +0 -1
  311. package/dist/renderer/cells.test.d.ts +0 -2
  312. package/dist/renderer/cells.test.d.ts.map +0 -1
  313. package/dist/renderer/cells.test.js +0 -69
  314. package/dist/renderer/cells.test.js.map +0 -1
  315. package/dist/renderer/colors.d.ts.map +0 -1
  316. package/dist/renderer/colors.js.map +0 -1
  317. package/dist/renderer/diff.d.ts.map +0 -1
  318. package/dist/renderer/diff.js.map +0 -1
  319. package/dist/renderer/diff.test.d.ts +0 -5
  320. package/dist/renderer/diff.test.d.ts.map +0 -1
  321. package/dist/renderer/diff.test.js +0 -140
  322. package/dist/renderer/diff.test.js.map +0 -1
  323. package/dist/renderer/differ.d.ts.map +0 -1
  324. package/dist/renderer/differ.js.map +0 -1
  325. package/dist/renderer/e2e.test.d.ts +0 -6
  326. package/dist/renderer/e2e.test.d.ts.map +0 -1
  327. package/dist/renderer/e2e.test.js +0 -702
  328. package/dist/renderer/e2e.test.js.map +0 -1
  329. package/dist/renderer/image.d.ts.map +0 -1
  330. package/dist/renderer/image.js.map +0 -1
  331. package/dist/renderer/image.test.d.ts +0 -5
  332. package/dist/renderer/image.test.d.ts.map +0 -1
  333. package/dist/renderer/image.test.js +0 -66
  334. package/dist/renderer/image.test.js.map +0 -1
  335. package/dist/renderer/index.d.ts.map +0 -1
  336. package/dist/renderer/index.js.map +0 -1
  337. package/dist/renderer/input.d.ts.map +0 -1
  338. package/dist/renderer/input.js.map +0 -1
  339. package/dist/renderer/input.test.d.ts +0 -5
  340. package/dist/renderer/input.test.d.ts.map +0 -1
  341. package/dist/renderer/input.test.js +0 -129
  342. package/dist/renderer/input.test.js.map +0 -1
  343. package/dist/renderer/layout.d.ts.map +0 -1
  344. package/dist/renderer/layout.js.map +0 -1
  345. package/dist/renderer/markdown.d.ts.map +0 -1
  346. package/dist/renderer/markdown.js.map +0 -1
  347. package/dist/renderer/markdown.test.d.ts +0 -2
  348. package/dist/renderer/markdown.test.d.ts.map +0 -1
  349. package/dist/renderer/markdown.test.js +0 -81
  350. package/dist/renderer/markdown.test.js.map +0 -1
  351. package/dist/renderer/perf.test.d.ts +0 -2
  352. package/dist/renderer/perf.test.d.ts.map +0 -1
  353. package/dist/renderer/perf.test.js +0 -128
  354. package/dist/renderer/perf.test.js.map +0 -1
  355. package/dist/renderer/session-browser.d.ts.map +0 -1
  356. package/dist/renderer/session-browser.js.map +0 -1
  357. package/dist/renderer/session-browser.test.d.ts +0 -6
  358. package/dist/renderer/session-browser.test.d.ts.map +0 -1
  359. package/dist/renderer/session-browser.test.js +0 -95
  360. package/dist/renderer/session-browser.test.js.map +0 -1
  361. package/dist/renderer/ui-ux.test.d.ts +0 -15
  362. package/dist/renderer/ui-ux.test.d.ts.map +0 -1
  363. package/dist/renderer/ui-ux.test.js +0 -470
  364. package/dist/renderer/ui-ux.test.js.map +0 -1
  365. package/dist/repl.d.ts.map +0 -1
  366. package/dist/repl.js.map +0 -1
  367. package/dist/services/AgentDispatcher.d.ts.map +0 -1
  368. package/dist/services/AgentDispatcher.js.map +0 -1
  369. package/dist/services/AgentDispatcher.test.d.ts +0 -2
  370. package/dist/services/AgentDispatcher.test.d.ts.map +0 -1
  371. package/dist/services/AgentDispatcher.test.js +0 -66
  372. package/dist/services/AgentDispatcher.test.js.map +0 -1
  373. package/dist/services/StreamingToolExecutor.d.ts.map +0 -1
  374. package/dist/services/StreamingToolExecutor.js.map +0 -1
  375. package/dist/services/StreamingToolExecutor.test.d.ts +0 -2
  376. package/dist/services/StreamingToolExecutor.test.d.ts.map +0 -1
  377. package/dist/services/StreamingToolExecutor.test.js +0 -103
  378. package/dist/services/StreamingToolExecutor.test.js.map +0 -1
  379. package/dist/services/agent-messaging.d.ts.map +0 -1
  380. package/dist/services/agent-messaging.js.map +0 -1
  381. package/dist/services/agent-messaging.test.d.ts +0 -2
  382. package/dist/services/agent-messaging.test.d.ts.map +0 -1
  383. package/dist/services/agent-messaging.test.js +0 -88
  384. package/dist/services/agent-messaging.test.js.map +0 -1
  385. package/dist/services/cron.d.ts.map +0 -1
  386. package/dist/services/cron.js.map +0 -1
  387. package/dist/services/cron.test.d.ts +0 -2
  388. package/dist/services/cron.test.d.ts.map +0 -1
  389. package/dist/services/cron.test.js +0 -49
  390. package/dist/services/cron.test.js.map +0 -1
  391. package/dist/test-helpers.d.ts +0 -31
  392. package/dist/test-helpers.d.ts.map +0 -1
  393. package/dist/test-helpers.js +0 -106
  394. package/dist/test-helpers.js.map +0 -1
  395. package/dist/tools/AgentTool/index.d.ts.map +0 -1
  396. package/dist/tools/AgentTool/index.js.map +0 -1
  397. package/dist/tools/AskUserTool/index.d.ts.map +0 -1
  398. package/dist/tools/AskUserTool/index.js.map +0 -1
  399. package/dist/tools/BashTool/index.d.ts.map +0 -1
  400. package/dist/tools/BashTool/index.js.map +0 -1
  401. package/dist/tools/CronTool/index.d.ts.map +0 -1
  402. package/dist/tools/CronTool/index.js.map +0 -1
  403. package/dist/tools/DiagnosticsTool/index.d.ts.map +0 -1
  404. package/dist/tools/DiagnosticsTool/index.js.map +0 -1
  405. package/dist/tools/EnterPlanModeTool/index.d.ts.map +0 -1
  406. package/dist/tools/EnterPlanModeTool/index.js.map +0 -1
  407. package/dist/tools/EnterWorktreeTool/index.d.ts.map +0 -1
  408. package/dist/tools/EnterWorktreeTool/index.js.map +0 -1
  409. package/dist/tools/ExitPlanModeTool/index.d.ts.map +0 -1
  410. package/dist/tools/ExitPlanModeTool/index.js.map +0 -1
  411. package/dist/tools/ExitWorktreeTool/index.d.ts.map +0 -1
  412. package/dist/tools/ExitWorktreeTool/index.js.map +0 -1
  413. package/dist/tools/FileEditTool/index.d.ts.map +0 -1
  414. package/dist/tools/FileEditTool/index.js.map +0 -1
  415. package/dist/tools/FileReadTool/index.d.ts.map +0 -1
  416. package/dist/tools/FileReadTool/index.js.map +0 -1
  417. package/dist/tools/FileWriteTool/index.d.ts.map +0 -1
  418. package/dist/tools/FileWriteTool/index.js.map +0 -1
  419. package/dist/tools/GlobTool/index.d.ts.map +0 -1
  420. package/dist/tools/GlobTool/index.js.map +0 -1
  421. package/dist/tools/GrepTool/index.d.ts.map +0 -1
  422. package/dist/tools/GrepTool/index.js.map +0 -1
  423. package/dist/tools/ImageReadTool/index.d.ts.map +0 -1
  424. package/dist/tools/ImageReadTool/index.js.map +0 -1
  425. package/dist/tools/KillProcessTool/index.d.ts.map +0 -1
  426. package/dist/tools/KillProcessTool/index.js.map +0 -1
  427. package/dist/tools/LSTool/index.d.ts.map +0 -1
  428. package/dist/tools/LSTool/index.js.map +0 -1
  429. package/dist/tools/MemoryTool/index.d.ts.map +0 -1
  430. package/dist/tools/MemoryTool/index.js.map +0 -1
  431. package/dist/tools/MultiEditTool/index.d.ts.map +0 -1
  432. package/dist/tools/MultiEditTool/index.js.map +0 -1
  433. package/dist/tools/NotebookEditTool/index.d.ts.map +0 -1
  434. package/dist/tools/NotebookEditTool/index.js.map +0 -1
  435. package/dist/tools/ParallelAgentTool/index.d.ts.map +0 -1
  436. package/dist/tools/ParallelAgentTool/index.js.map +0 -1
  437. package/dist/tools/RemoteTriggerTool/index.d.ts.map +0 -1
  438. package/dist/tools/RemoteTriggerTool/index.js.map +0 -1
  439. package/dist/tools/SendMessageTool/index.d.ts.map +0 -1
  440. package/dist/tools/SendMessageTool/index.js.map +0 -1
  441. package/dist/tools/SkillTool/index.d.ts.map +0 -1
  442. package/dist/tools/SkillTool/index.js.map +0 -1
  443. package/dist/tools/TaskCreateTool/index.d.ts.map +0 -1
  444. package/dist/tools/TaskCreateTool/index.js.map +0 -1
  445. package/dist/tools/TaskGetTool/index.d.ts.map +0 -1
  446. package/dist/tools/TaskGetTool/index.js.map +0 -1
  447. package/dist/tools/TaskListTool/index.d.ts.map +0 -1
  448. package/dist/tools/TaskListTool/index.js.map +0 -1
  449. package/dist/tools/TaskOutputTool/index.d.ts.map +0 -1
  450. package/dist/tools/TaskOutputTool/index.js.map +0 -1
  451. package/dist/tools/TaskStopTool/index.d.ts.map +0 -1
  452. package/dist/tools/TaskStopTool/index.js.map +0 -1
  453. package/dist/tools/TaskUpdateTool/index.d.ts.map +0 -1
  454. package/dist/tools/TaskUpdateTool/index.js.map +0 -1
  455. package/dist/tools/ToolSearchTool/index.d.ts.map +0 -1
  456. package/dist/tools/ToolSearchTool/index.js.map +0 -1
  457. package/dist/tools/WebFetchTool/index.d.ts.map +0 -1
  458. package/dist/tools/WebFetchTool/index.js.map +0 -1
  459. package/dist/tools/WebSearchTool/index.d.ts.map +0 -1
  460. package/dist/tools/WebSearchTool/index.js.map +0 -1
  461. package/dist/tools/file-edit.test.d.ts +0 -2
  462. package/dist/tools/file-edit.test.d.ts.map +0 -1
  463. package/dist/tools/file-edit.test.js +0 -35
  464. package/dist/tools/file-edit.test.js.map +0 -1
  465. package/dist/tools/tools-basic.test.d.ts +0 -6
  466. package/dist/tools/tools-basic.test.d.ts.map +0 -1
  467. package/dist/tools/tools-basic.test.js +0 -379
  468. package/dist/tools/tools-basic.test.js.map +0 -1
  469. package/dist/tools/web-fetch.test.d.ts +0 -2
  470. package/dist/tools/web-fetch.test.d.ts.map +0 -1
  471. package/dist/tools/web-fetch.test.js +0 -27
  472. package/dist/tools/web-fetch.test.js.map +0 -1
  473. package/dist/tools.d.ts.map +0 -1
  474. package/dist/tools.js.map +0 -1
  475. package/dist/types/events.d.ts.map +0 -1
  476. package/dist/types/events.js.map +0 -1
  477. package/dist/types/message.d.ts.map +0 -1
  478. package/dist/types/message.js.map +0 -1
  479. package/dist/types/message.test.d.ts +0 -2
  480. package/dist/types/message.test.d.ts.map +0 -1
  481. package/dist/types/message.test.js +0 -46
  482. package/dist/types/message.test.js.map +0 -1
  483. package/dist/types/permissions.d.ts.map +0 -1
  484. package/dist/types/permissions.js.map +0 -1
  485. package/dist/types/permissions.test.d.ts +0 -2
  486. package/dist/types/permissions.test.d.ts.map +0 -1
  487. package/dist/types/permissions.test.js +0 -127
  488. package/dist/types/permissions.test.js.map +0 -1
  489. package/dist/utils/bash-safety.d.ts.map +0 -1
  490. package/dist/utils/bash-safety.js.map +0 -1
  491. package/dist/utils/bash-safety.test.d.ts +0 -2
  492. package/dist/utils/bash-safety.test.d.ts.map +0 -1
  493. package/dist/utils/bash-safety.test.js +0 -112
  494. package/dist/utils/bash-safety.test.js.map +0 -1
  495. package/dist/utils/diff-algorithm.d.ts.map +0 -1
  496. package/dist/utils/diff-algorithm.js.map +0 -1
  497. package/dist/utils/diff-algorithm.test.d.ts +0 -2
  498. package/dist/utils/diff-algorithm.test.d.ts.map +0 -1
  499. package/dist/utils/diff-algorithm.test.js +0 -49
  500. package/dist/utils/diff-algorithm.test.js.map +0 -1
  501. package/dist/utils/format.d.ts.map +0 -1
  502. package/dist/utils/format.js.map +0 -1
  503. package/dist/utils/fs.d.ts.map +0 -1
  504. package/dist/utils/fs.js.map +0 -1
  505. package/dist/utils/fs.test.d.ts +0 -5
  506. package/dist/utils/fs.test.d.ts.map +0 -1
  507. package/dist/utils/fs.test.js +0 -82
  508. package/dist/utils/fs.test.js.map +0 -1
  509. package/dist/utils/safe-env.d.ts.map +0 -1
  510. package/dist/utils/safe-env.js.map +0 -1
  511. package/dist/utils/theme-data.d.ts.map +0 -1
  512. package/dist/utils/theme-data.js.map +0 -1
  513. package/dist/utils/theme.d.ts.map +0 -1
  514. package/dist/utils/theme.js.map +0 -1
  515. package/dist/utils/tool-summary.d.ts.map +0 -1
  516. package/dist/utils/tool-summary.js.map +0 -1
  517. package/dist/utils/tool-summary.test.d.ts +0 -2
  518. package/dist/utils/tool-summary.test.d.ts.map +0 -1
  519. package/dist/utils/tool-summary.test.js +0 -93
  520. package/dist/utils/tool-summary.test.js.map +0 -1
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import { readFileSync, writeFileSync, mkdirSync, existsSync } from "node:fs";
5
5
  import { join } from "node:path";
6
+ import { homedir } from "node:os";
6
7
  import { parse, stringify } from "yaml";
7
8
  function yamlScalar(value) {
8
9
  return `'${value.replace(/'/g, "''")}'`;
@@ -17,41 +18,62 @@ export function invalidateConfigCache() {
17
18
  _configCache = undefined;
18
19
  _configCacheRoot = undefined;
19
20
  }
21
+ /** Path to global config: ~/.oh/config.yaml */
22
+ function globalConfigPath() {
23
+ return join(homedir(), '.oh', 'config.yaml');
24
+ }
25
+ /** Read global config as fallback defaults */
26
+ function readGlobalConfig() {
27
+ const p = globalConfigPath();
28
+ if (!existsSync(p))
29
+ return null;
30
+ try {
31
+ return parse(readFileSync(p, 'utf-8'));
32
+ }
33
+ catch {
34
+ return null;
35
+ }
36
+ }
20
37
  export function readOhConfig(root) {
21
38
  const effectiveRoot = root ?? ".";
22
39
  if (_configCache !== undefined && _configCacheRoot === effectiveRoot)
23
40
  return _configCache;
24
41
  const p = configPath(root);
25
- if (!existsSync(p)) {
42
+ // Layer 1: Global defaults from ~/.oh/config.yaml
43
+ const globalCfg = readGlobalConfig();
44
+ // Layer 2: Project config from .oh/config.yaml
45
+ let projectCfg = null;
46
+ if (existsSync(p)) {
47
+ try {
48
+ projectCfg = parse(readFileSync(p, "utf-8"));
49
+ }
50
+ catch { /* ignore malformed project config */ }
51
+ }
52
+ // If neither exists, no config
53
+ if (!globalCfg && !projectCfg) {
26
54
  _configCache = null;
27
55
  _configCacheRoot = effectiveRoot;
28
56
  return null;
29
57
  }
30
- try {
31
- const base = parse(readFileSync(p, "utf-8"));
32
- // Merge local overrides from config.local.yaml (gitignored personal settings)
33
- const localPath = join(root ?? ".", ".oh", "config.local.yaml");
34
- if (existsSync(localPath)) {
35
- try {
36
- const local = parse(readFileSync(localPath, "utf-8"));
37
- if (local) {
38
- const merged = { ...base, ...local };
39
- _configCache = merged;
40
- _configCacheRoot = effectiveRoot;
41
- return merged;
42
- }
58
+ // Merge: global → project (project overrides global)
59
+ const base = { ...globalCfg, ...projectCfg };
60
+ // Layer 3: Local overrides from .oh/config.local.yaml (gitignored personal settings)
61
+ const localPath = join(root ?? ".", ".oh", "config.local.yaml");
62
+ if (existsSync(localPath)) {
63
+ try {
64
+ const local = parse(readFileSync(localPath, "utf-8"));
65
+ if (local) {
66
+ const merged = { ...base, ...local };
67
+ _configCache = merged;
68
+ _configCacheRoot = effectiveRoot;
69
+ return merged;
43
70
  }
44
- catch { /* ignore malformed local config */ }
45
71
  }
46
- _configCache = base;
47
- _configCacheRoot = effectiveRoot;
48
- return base;
49
- }
50
- catch {
51
- _configCache = null;
52
- _configCacheRoot = effectiveRoot;
53
- return null;
72
+ catch { /* ignore malformed local config */ }
54
73
  }
74
+ _configCache = base;
75
+ _configCacheRoot = effectiveRoot;
76
+ return base;
55
77
  }
56
78
  export function writeOhConfig(cfg, root) {
57
79
  invalidateConfigCache();
@@ -41,6 +41,18 @@ export declare function decayAndPrune(memories: MemoryEntry[]): {
41
41
  };
42
42
  /** Load memories with decay applied, sorted by relevance */
43
43
  export declare function loadActiveMemories(): MemoryEntry[];
44
+ /** Delete memory files that have been pruned (relevance < 0.1) */
45
+ export declare function deletePrunedMemories(pruned: MemoryEntry[]): number;
46
+ export type ConsolidationResult = {
47
+ total: number;
48
+ pruned: number;
49
+ decayed: number;
50
+ };
51
+ /**
52
+ * Run full memory consolidation: apply decay, delete pruned files,
53
+ * persist updated relevance scores. Designed to run on session end.
54
+ */
55
+ export declare function consolidateMemories(): ConsolidationResult;
44
56
  /**
45
57
  * Detect if recent assistant messages contain learnable patterns.
46
58
  * Returns structured memories to save, or empty array.
@@ -7,8 +7,8 @@
7
7
  * The system detects learnable patterns from assistant responses and saves them
8
8
  * without user intervention.
9
9
  */
10
- import { readFileSync, writeFileSync, mkdirSync, readdirSync, existsSync } from 'node:fs';
11
- import { join } from 'node:path';
10
+ import { readFileSync, writeFileSync, mkdirSync, readdirSync, existsSync, unlinkSync } from 'node:fs';
11
+ import { join, resolve, sep } from 'node:path';
12
12
  import { homedir } from 'node:os';
13
13
  import { createUserMessage } from '../types/message.js';
14
14
  const PROJECT_MEMORY_DIR = join('.oh', 'memory');
@@ -159,6 +159,57 @@ export function loadActiveMemories() {
159
159
  // Sort by relevance (highest first), then by access count
160
160
  return active.sort((a, b) => (b.relevance ?? 0.5) - (a.relevance ?? 0.5) || (b.accessCount ?? 0) - (a.accessCount ?? 0));
161
161
  }
162
+ // ── Dream Consolidation ──
163
+ // Background memory pruning and relevance persistence on session end.
164
+ /** Delete memory files that have been pruned (relevance < 0.1) */
165
+ export function deletePrunedMemories(pruned) {
166
+ // Guard: only delete files within known memory directories
167
+ const allowedDirs = [PROJECT_MEMORY_DIR, GLOBAL_MEMORY_DIR].map(d => resolve(d));
168
+ let count = 0;
169
+ for (const m of pruned) {
170
+ const resolved = resolve(m.filePath);
171
+ if (!allowedDirs.some(d => resolved.startsWith(d + sep)))
172
+ continue;
173
+ try {
174
+ unlinkSync(m.filePath);
175
+ count++;
176
+ }
177
+ catch { /* ignore */ }
178
+ }
179
+ return count;
180
+ }
181
+ /** Write back decayed relevance score to file frontmatter */
182
+ function persistDecayedRelevance(entry) {
183
+ try {
184
+ let raw = readFileSync(entry.filePath, 'utf-8');
185
+ if (raw.match(/^relevance:/m)) {
186
+ raw = raw.replace(/^relevance:\s*[0-9.]+$/m, `relevance: ${(entry.relevance ?? 0.5).toFixed(2)}`);
187
+ writeFileSync(entry.filePath, raw);
188
+ }
189
+ }
190
+ catch { /* ignore */ }
191
+ }
192
+ /**
193
+ * Run full memory consolidation: apply decay, delete pruned files,
194
+ * persist updated relevance scores. Designed to run on session end.
195
+ */
196
+ export function consolidateMemories() {
197
+ const all = loadMemories();
198
+ if (all.length === 0)
199
+ return { total: 0, pruned: 0, decayed: 0 };
200
+ const { active, pruned } = decayAndPrune(all);
201
+ // Delete pruned memory files
202
+ const prunedCount = deletePrunedMemories(pruned);
203
+ // Persist updated relevance scores for decayed memories
204
+ let decayedCount = 0;
205
+ for (const m of active) {
206
+ if ((m.relevance ?? 0.5) < 0.5) {
207
+ persistDecayedRelevance(m);
208
+ decayedCount++;
209
+ }
210
+ }
211
+ return { total: all.length, pruned: prunedCount, decayed: decayedCount };
212
+ }
162
213
  /**
163
214
  * Detect if recent assistant messages contain learnable patterns.
164
215
  * Returns structured memories to save, or empty array.
@@ -13,6 +13,14 @@ export type Session = {
13
13
  gitBranch?: string;
14
14
  workingDir?: string;
15
15
  tools?: string[];
16
+ /** Hibernate state — saved on exit for wake reconstruction */
17
+ hibernate?: {
18
+ summary?: string;
19
+ lastUserMessage?: string;
20
+ pendingTask?: string;
21
+ totalInputTokens?: number;
22
+ totalOutputTokens?: number;
23
+ };
16
24
  };
17
25
  export declare function createSession(provider: string, model: string, extras?: {
18
26
  gitBranch?: string;
@@ -30,6 +38,17 @@ export declare function listSessions(dir?: string): Array<{
30
38
  }>;
31
39
  /** Returns the ID of the most recently updated session, or null if none exist. */
32
40
  export declare function getLastSessionId(dir?: string): string | null;
41
+ /**
42
+ * Build hibernate state from the current session.
43
+ * Captures the last user message, recent assistant activity,
44
+ * and a brief summary for context reconstruction on wake.
45
+ */
46
+ export declare function buildHibernateState(messages: Message[]): Session['hibernate'];
47
+ /**
48
+ * Generate a wake-up context message for a resumed session.
49
+ * Tells the LLM what happened in the previous session.
50
+ */
51
+ export declare function buildWakeContext(session: Session): string;
33
52
  /**
34
53
  * Evict oldest sessions when count exceeds MAX_SESSIONS.
35
54
  * Called automatically by saveSession.
@@ -72,6 +72,59 @@ export function getLastSessionId(dir) {
72
72
  const sessions = listSessions(dir);
73
73
  return sessions.length > 0 ? sessions[0].id : null;
74
74
  }
75
+ /**
76
+ * Build hibernate state from the current session.
77
+ * Captures the last user message, recent assistant activity,
78
+ * and a brief summary for context reconstruction on wake.
79
+ */
80
+ export function buildHibernateState(messages) {
81
+ if (messages.length === 0)
82
+ return undefined;
83
+ // Find last user message
84
+ const lastUser = [...messages].reverse().find(m => m.role === 'user');
85
+ const lastAssistant = [...messages].reverse().find(m => m.role === 'assistant');
86
+ // Build a brief summary from the last few exchanges
87
+ const recentMsgs = messages.slice(-6);
88
+ const summaryParts = [];
89
+ for (const m of recentMsgs) {
90
+ if (m.role === 'user') {
91
+ summaryParts.push(`User: ${m.content.slice(0, 100)}`);
92
+ }
93
+ else if (m.role === 'assistant' && m.content) {
94
+ summaryParts.push(`Assistant: ${m.content.slice(0, 100)}`);
95
+ }
96
+ }
97
+ return {
98
+ lastUserMessage: lastUser?.content.slice(0, 200),
99
+ pendingTask: lastAssistant?.content.slice(0, 200),
100
+ summary: summaryParts.join('\n'),
101
+ };
102
+ }
103
+ /**
104
+ * Generate a wake-up context message for a resumed session.
105
+ * Tells the LLM what happened in the previous session.
106
+ */
107
+ export function buildWakeContext(session) {
108
+ const parts = ['[Session Resumed]'];
109
+ if (session.workingDir) {
110
+ parts.push(`Previous working directory: ${session.workingDir}`);
111
+ if (session.workingDir !== process.cwd()) {
112
+ parts.push(`WARNING: Working directory changed! Was: ${session.workingDir}, Now: ${process.cwd()}`);
113
+ }
114
+ }
115
+ if (session.gitBranch) {
116
+ parts.push(`Previous git branch: ${session.gitBranch}`);
117
+ }
118
+ if (session.hibernate?.summary) {
119
+ parts.push(`\nPrevious session context:\n${session.hibernate.summary}`);
120
+ }
121
+ if (session.hibernate?.lastUserMessage) {
122
+ parts.push(`\nLast user request: ${session.hibernate.lastUserMessage}`);
123
+ }
124
+ parts.push(`\nSession has ${session.messages.length} messages and cost $${session.totalCost.toFixed(4)} so far.`);
125
+ parts.push('Continue where you left off. If the user\'s last request was incomplete, acknowledge that and ask how to proceed.');
126
+ return parts.join('\n');
127
+ }
75
128
  /** Maximum number of sessions to keep on disk. */
76
129
  const MAX_SESSIONS = 100;
77
130
  /**
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Verification loops — auto-run lint/typecheck after file edits.
3
+ *
4
+ * After file-modifying tools (Edit, Write, MultiEdit) execute,
5
+ * runs language-appropriate verification commands and returns
6
+ * concise results to feed back into the agent loop.
7
+ *
8
+ * This is the single highest-impact harness engineering pattern —
9
+ * research shows 2-3x quality improvement from automated feedback.
10
+ */
11
+ export type VerificationRule = {
12
+ extensions: string[];
13
+ lint?: string;
14
+ timeout?: number;
15
+ };
16
+ export type VerificationConfig = {
17
+ enabled: boolean;
18
+ mode: 'warn' | 'block';
19
+ rules: VerificationRule[];
20
+ };
21
+ export type VerificationResult = {
22
+ ran: boolean;
23
+ passed: boolean;
24
+ summary: string;
25
+ };
26
+ /** Detect verification rules from project files */
27
+ export declare function autoDetectRules(projectRoot?: string): VerificationRule[];
28
+ /** Get verification config from .oh/config.yaml or auto-detect */
29
+ export declare function getVerificationConfig(): VerificationConfig | null;
30
+ /** Clear cached config (for testing or after config changes) */
31
+ export declare function invalidateVerificationCache(): void;
32
+ /** Extract file paths from tool input that were modified */
33
+ export declare function extractFilePaths(toolName: string, toolInput: Record<string, unknown>): string[];
34
+ /**
35
+ * Run verification for multiple files. Aggregates results.
36
+ * Returns a single result summarizing all files checked.
37
+ */
38
+ export declare function runVerificationForFiles(filePaths: string[], config: VerificationConfig): Promise<VerificationResult>;
39
+ /** Run verification for a single file. Returns result with concise summary. */
40
+ export declare function runVerification(filePath: string, config: VerificationConfig): Promise<VerificationResult>;
41
+ //# sourceMappingURL=verification.d.ts.map
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Verification loops — auto-run lint/typecheck after file edits.
3
+ *
4
+ * After file-modifying tools (Edit, Write, MultiEdit) execute,
5
+ * runs language-appropriate verification commands and returns
6
+ * concise results to feed back into the agent loop.
7
+ *
8
+ * This is the single highest-impact harness engineering pattern —
9
+ * research shows 2-3x quality improvement from automated feedback.
10
+ */
11
+ import { execSync } from 'node:child_process';
12
+ import { existsSync } from 'node:fs';
13
+ import { extname, join } from 'node:path';
14
+ import { readOhConfig } from './config.js';
15
+ const MAX_SUMMARY_CHARS = 500;
16
+ const DEFAULT_TIMEOUT_MS = 10_000;
17
+ // ── Auto-detection ──
18
+ /** Detect verification rules from project files */
19
+ export function autoDetectRules(projectRoot) {
20
+ const root = projectRoot ?? process.cwd();
21
+ const rules = [];
22
+ // TypeScript
23
+ if (existsSync(join(root, 'tsconfig.json'))) {
24
+ rules.push({
25
+ extensions: ['.ts', '.tsx'],
26
+ lint: 'npx tsc --noEmit 2>&1 | head -20',
27
+ timeout: 15_000,
28
+ });
29
+ }
30
+ // ESLint (JS/TS)
31
+ const eslintConfigs = ['.eslintrc', '.eslintrc.js', '.eslintrc.json', '.eslintrc.yml', 'eslint.config.js', 'eslint.config.mjs'];
32
+ if (eslintConfigs.some(f => existsSync(join(root, f)))) {
33
+ rules.push({
34
+ extensions: ['.js', '.jsx', '.ts', '.tsx'],
35
+ lint: 'npx eslint {file} --no-color 2>&1 | head -15',
36
+ timeout: 10_000,
37
+ });
38
+ }
39
+ // Python — ruff (fast) or pylint
40
+ if (existsSync(join(root, 'pyproject.toml')) || existsSync(join(root, 'setup.py'))) {
41
+ rules.push({
42
+ extensions: ['.py'],
43
+ lint: 'ruff check {file} 2>&1 | head -10',
44
+ timeout: 10_000,
45
+ });
46
+ }
47
+ // Go
48
+ if (existsSync(join(root, 'go.mod'))) {
49
+ rules.push({
50
+ extensions: ['.go'],
51
+ lint: 'go vet ./... 2>&1 | head -10',
52
+ timeout: 15_000,
53
+ });
54
+ }
55
+ // Rust
56
+ if (existsSync(join(root, 'Cargo.toml'))) {
57
+ rules.push({
58
+ extensions: ['.rs'],
59
+ lint: 'cargo check 2>&1 | tail -10',
60
+ timeout: 30_000,
61
+ });
62
+ }
63
+ return rules;
64
+ }
65
+ // ── Config ──
66
+ let _cachedConfig;
67
+ /** Get verification config from .oh/config.yaml or auto-detect */
68
+ export function getVerificationConfig() {
69
+ if (_cachedConfig !== undefined)
70
+ return _cachedConfig;
71
+ const ohConfig = readOhConfig();
72
+ if (ohConfig?.verification) {
73
+ const v = ohConfig.verification;
74
+ // Explicitly disabled
75
+ if (v.enabled === false) {
76
+ _cachedConfig = null;
77
+ return null;
78
+ }
79
+ _cachedConfig = {
80
+ enabled: true,
81
+ mode: v.mode ?? 'warn',
82
+ rules: v.rules ?? autoDetectRules(),
83
+ };
84
+ return _cachedConfig;
85
+ }
86
+ // Auto-detect if no config
87
+ const autoRules = autoDetectRules();
88
+ if (autoRules.length === 0) {
89
+ _cachedConfig = null;
90
+ return null;
91
+ }
92
+ _cachedConfig = { enabled: true, mode: 'warn', rules: autoRules };
93
+ return _cachedConfig;
94
+ }
95
+ /** Clear cached config (for testing or after config changes) */
96
+ export function invalidateVerificationCache() {
97
+ _cachedConfig = undefined;
98
+ }
99
+ // ── File path extraction ──
100
+ /** Extract file paths from tool input that were modified */
101
+ export function extractFilePaths(toolName, toolInput) {
102
+ switch (toolName) {
103
+ case 'Write':
104
+ case 'Edit':
105
+ return toolInput.file_path ? [String(toolInput.file_path)] : [];
106
+ case 'MultiEdit':
107
+ // MultiEdit has an array of edits, each with file_path
108
+ if (Array.isArray(toolInput.edits)) {
109
+ const paths = new Set();
110
+ for (const edit of toolInput.edits) {
111
+ if (edit && typeof edit === 'object' && 'file_path' in edit) {
112
+ paths.add(String(edit.file_path));
113
+ }
114
+ }
115
+ return [...paths];
116
+ }
117
+ return toolInput.file_path ? [String(toolInput.file_path)] : [];
118
+ default:
119
+ return [];
120
+ }
121
+ }
122
+ // ── Verification execution ──
123
+ /** Find the matching rule for a file extension */
124
+ function findRule(filePath, rules) {
125
+ const ext = extname(filePath).toLowerCase();
126
+ return rules.find(r => r.extensions.includes(ext)) ?? null;
127
+ }
128
+ /**
129
+ * Shell-escape a file path to prevent command injection.
130
+ * Wraps in single quotes and escapes any embedded single quotes.
131
+ */
132
+ function shellEscape(s) {
133
+ // On Windows, use double quotes; on POSIX, use single quotes
134
+ if (process.platform === 'win32') {
135
+ // Double-quote and escape internal double quotes and special chars
136
+ return `"${s.replace(/"/g, '\\"')}"`;
137
+ }
138
+ // POSIX: single-quote and escape embedded single quotes
139
+ return `'${s.replace(/'/g, "'\\''")}'`;
140
+ }
141
+ /**
142
+ * Run verification for multiple files. Aggregates results.
143
+ * Returns a single result summarizing all files checked.
144
+ */
145
+ export async function runVerificationForFiles(filePaths, config) {
146
+ if (filePaths.length === 0)
147
+ return { ran: false, passed: true, summary: '' };
148
+ if (filePaths.length === 1)
149
+ return runVerification(filePaths[0], config);
150
+ const results = [];
151
+ for (const fp of filePaths) {
152
+ results.push(await runVerification(fp, config));
153
+ }
154
+ const ran = results.some(r => r.ran);
155
+ const passed = results.every(r => r.passed);
156
+ const failures = results.filter(r => r.ran && !r.passed);
157
+ if (!ran)
158
+ return { ran: false, passed: true, summary: '' };
159
+ if (passed)
160
+ return { ran: true, passed: true, summary: '' };
161
+ // Aggregate failure summaries (cap total to MAX_SUMMARY_CHARS)
162
+ const summaryParts = failures.map(r => r.summary).filter(Boolean);
163
+ const summary = summaryParts.join('\n---\n').slice(0, MAX_SUMMARY_CHARS);
164
+ return { ran: true, passed: false, summary };
165
+ }
166
+ /** Run verification for a single file. Returns result with concise summary. */
167
+ export async function runVerification(filePath, config) {
168
+ const rule = findRule(filePath, config.rules);
169
+ if (!rule || !rule.lint) {
170
+ return { ran: false, passed: true, summary: '' };
171
+ }
172
+ const command = rule.lint.replace(/\{file\}/g, shellEscape(filePath));
173
+ const timeout = rule.timeout ?? DEFAULT_TIMEOUT_MS;
174
+ try {
175
+ execSync(command, {
176
+ timeout,
177
+ cwd: process.cwd(),
178
+ encoding: 'utf-8',
179
+ stdio: ['pipe', 'pipe', 'pipe'],
180
+ windowsHide: true,
181
+ });
182
+ // Exit code 0 = passed
183
+ return { ran: true, passed: true, summary: '' };
184
+ }
185
+ catch (err) {
186
+ // Timeout detection — check killed flag, signal, or error code
187
+ const isTimeout = err.killed || err.signal === 'SIGTERM' || err.code === 'ETIMEDOUT'
188
+ || (err.status === null && err.signal);
189
+ if (isTimeout) {
190
+ return { ran: true, passed: false, summary: `Verification timed out after ${timeout / 1000}s` };
191
+ }
192
+ const output = String(err.stdout ?? err.stderr ?? err.message ?? 'Unknown error');
193
+ const summary = output.slice(0, MAX_SUMMARY_CHARS).trim();
194
+ return { ran: true, passed: false, summary };
195
+ }
196
+ }
197
+ //# sourceMappingURL=verification.js.map
@@ -0,0 +1,31 @@
1
+ /**
2
+ * MCP Server Registry — curated list of compatible MCP servers.
3
+ *
4
+ * Provides a browsable catalog of MCP servers that users can add
5
+ * to their .oh/config.yaml with a single command.
6
+ */
7
+ export type McpRegistryEntry = {
8
+ name: string;
9
+ package: string;
10
+ description: string;
11
+ category: 'filesystem' | 'git' | 'database' | 'api' | 'search' | 'productivity' | 'dev-tools' | 'ai';
12
+ args?: string[];
13
+ envVars?: string[];
14
+ riskLevel?: 'low' | 'medium' | 'high';
15
+ };
16
+ /**
17
+ * Curated registry of popular MCP servers.
18
+ * Each entry has enough info to generate the config.yaml block.
19
+ */
20
+ export declare const MCP_REGISTRY: McpRegistryEntry[];
21
+ /** Search the registry by name or keyword */
22
+ export declare function searchRegistry(query: string): McpRegistryEntry[];
23
+ /** Get all entries in a category */
24
+ export declare function getByCategory(category: McpRegistryEntry['category']): McpRegistryEntry[];
25
+ /** Get all unique categories */
26
+ export declare function getCategories(): string[];
27
+ /** Generate the config.yaml block for a registry entry */
28
+ export declare function generateConfigBlock(entry: McpRegistryEntry): string;
29
+ /** Format registry as a browsable list */
30
+ export declare function formatRegistry(entries?: McpRegistryEntry[]): string;
31
+ //# sourceMappingURL=registry.d.ts.map