@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
@@ -0,0 +1,180 @@
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
+ /**
8
+ * Curated registry of popular MCP servers.
9
+ * Each entry has enough info to generate the config.yaml block.
10
+ */
11
+ export const MCP_REGISTRY = [
12
+ // ── Filesystem ──
13
+ {
14
+ name: 'filesystem',
15
+ package: '@modelcontextprotocol/server-filesystem',
16
+ description: 'Read, write, and manage files on the local filesystem',
17
+ category: 'filesystem',
18
+ args: ['/tmp'],
19
+ riskLevel: 'medium',
20
+ },
21
+ // ── Git & GitHub ──
22
+ {
23
+ name: 'github',
24
+ package: '@modelcontextprotocol/server-github',
25
+ description: 'GitHub API — issues, PRs, repos, code search',
26
+ category: 'git',
27
+ envVars: ['GITHUB_PERSONAL_ACCESS_TOKEN'],
28
+ riskLevel: 'medium',
29
+ },
30
+ {
31
+ name: 'gitlab',
32
+ package: '@modelcontextprotocol/server-gitlab',
33
+ description: 'GitLab API — issues, merge requests, pipelines',
34
+ category: 'git',
35
+ envVars: ['GITLAB_PERSONAL_ACCESS_TOKEN', 'GITLAB_API_URL'],
36
+ riskLevel: 'medium',
37
+ },
38
+ // ── Database ──
39
+ {
40
+ name: 'sqlite',
41
+ package: '@modelcontextprotocol/server-sqlite',
42
+ description: 'Query and modify SQLite databases',
43
+ category: 'database',
44
+ args: ['./database.sqlite'],
45
+ riskLevel: 'medium',
46
+ },
47
+ {
48
+ name: 'postgres',
49
+ package: '@modelcontextprotocol/server-postgres',
50
+ description: 'Query PostgreSQL databases (read-only by default)',
51
+ category: 'database',
52
+ envVars: ['POSTGRES_CONNECTION_STRING'],
53
+ riskLevel: 'medium',
54
+ },
55
+ // ── Search & Web ──
56
+ {
57
+ name: 'brave-search',
58
+ package: '@modelcontextprotocol/server-brave-search',
59
+ description: 'Web search via Brave Search API',
60
+ category: 'search',
61
+ envVars: ['BRAVE_API_KEY'],
62
+ riskLevel: 'low',
63
+ },
64
+ {
65
+ name: 'fetch',
66
+ package: '@modelcontextprotocol/server-fetch',
67
+ description: 'Fetch and parse web pages, convert HTML to markdown',
68
+ category: 'search',
69
+ riskLevel: 'low',
70
+ },
71
+ // ── Productivity ──
72
+ {
73
+ name: 'slack',
74
+ package: '@modelcontextprotocol/server-slack',
75
+ description: 'Read and send Slack messages, list channels',
76
+ category: 'productivity',
77
+ envVars: ['SLACK_BOT_TOKEN'],
78
+ riskLevel: 'high',
79
+ },
80
+ {
81
+ name: 'google-drive',
82
+ package: '@anthropic/mcp-server-google-drive',
83
+ description: 'Search and read Google Drive documents',
84
+ category: 'productivity',
85
+ envVars: ['GOOGLE_DRIVE_CREDENTIALS'],
86
+ riskLevel: 'medium',
87
+ },
88
+ {
89
+ name: 'linear',
90
+ package: '@anthropic/mcp-server-linear',
91
+ description: 'Linear issue tracker — create, update, search issues',
92
+ category: 'productivity',
93
+ envVars: ['LINEAR_API_KEY'],
94
+ riskLevel: 'medium',
95
+ },
96
+ // ── Dev Tools ──
97
+ {
98
+ name: 'docker',
99
+ package: '@modelcontextprotocol/server-docker',
100
+ description: 'Manage Docker containers, images, and volumes',
101
+ category: 'dev-tools',
102
+ riskLevel: 'high',
103
+ },
104
+ {
105
+ name: 'puppeteer',
106
+ package: '@modelcontextprotocol/server-puppeteer',
107
+ description: 'Browser automation — navigate, screenshot, interact with web pages',
108
+ category: 'dev-tools',
109
+ riskLevel: 'medium',
110
+ },
111
+ {
112
+ name: 'memory',
113
+ package: '@modelcontextprotocol/server-memory',
114
+ description: 'Persistent knowledge graph for long-term memory',
115
+ category: 'ai',
116
+ riskLevel: 'low',
117
+ },
118
+ {
119
+ name: 'sequential-thinking',
120
+ package: '@modelcontextprotocol/server-sequential-thinking',
121
+ description: 'Step-by-step reasoning and chain-of-thought tools',
122
+ category: 'ai',
123
+ riskLevel: 'low',
124
+ },
125
+ {
126
+ name: 'context7',
127
+ package: '@anthropic/mcp-server-context7',
128
+ description: 'Fetch up-to-date library documentation for any framework',
129
+ category: 'dev-tools',
130
+ riskLevel: 'low',
131
+ },
132
+ ];
133
+ /** Search the registry by name or keyword */
134
+ export function searchRegistry(query) {
135
+ const q = query.toLowerCase();
136
+ return MCP_REGISTRY.filter(e => e.name.includes(q) ||
137
+ e.description.toLowerCase().includes(q) ||
138
+ e.category.includes(q) ||
139
+ e.package.toLowerCase().includes(q));
140
+ }
141
+ /** Get all entries in a category */
142
+ export function getByCategory(category) {
143
+ return MCP_REGISTRY.filter(e => e.category === category);
144
+ }
145
+ /** Get all unique categories */
146
+ export function getCategories() {
147
+ return [...new Set(MCP_REGISTRY.map(e => e.category))];
148
+ }
149
+ /** Generate the config.yaml block for a registry entry */
150
+ export function generateConfigBlock(entry) {
151
+ const lines = [
152
+ ` - name: ${entry.name}`,
153
+ ` command: npx`,
154
+ ` args: ["-y", "${entry.package}"${entry.args ? ', ' + entry.args.map(a => `"${a}"`).join(', ') : ''}]`,
155
+ ];
156
+ if (entry.envVars && entry.envVars.length > 0) {
157
+ lines.push(' env:');
158
+ for (const v of entry.envVars) {
159
+ lines.push(` ${v}: "YOUR_${v}"`);
160
+ }
161
+ }
162
+ if (entry.riskLevel && entry.riskLevel !== 'medium') {
163
+ lines.push(` riskLevel: ${entry.riskLevel}`);
164
+ }
165
+ return lines.join('\n');
166
+ }
167
+ /** Format registry as a browsable list */
168
+ export function formatRegistry(entries) {
169
+ const list = entries ?? MCP_REGISTRY;
170
+ const categories = [...new Set(list.map(e => e.category))];
171
+ const sections = [];
172
+ for (const cat of categories) {
173
+ const catEntries = list.filter(e => e.category === cat);
174
+ const header = cat.charAt(0).toUpperCase() + cat.slice(1).replace('-', ' ');
175
+ const rows = catEntries.map(e => ` ${e.name.padEnd(20)} ${e.description}${e.envVars ? ' [requires: ' + e.envVars.join(', ') + ']' : ''}`);
176
+ sections.push(`${header}:\n${rows.join('\n')}`);
177
+ }
178
+ return sections.join('\n\n');
179
+ }
180
+ //# sourceMappingURL=registry.js.map
@@ -8,6 +8,7 @@
8
8
  * - types.ts — shared types
9
9
  */
10
10
  import { toolToAPIFormat } from "../Tool.js";
11
+ import { DeferredTool } from "../DeferredTool.js";
11
12
  import { createAssistantMessage, createUserMessage } from "../types/message.js";
12
13
  import { StreamingToolExecutor } from "../services/StreamingToolExecutor.js";
13
14
  import { getContextWindow } from "../harness/cost.js";
@@ -34,9 +35,16 @@ export async function* query(userMessage, config, existingMessages = []) {
34
35
  const modelInfo = config.provider.getModelInfo?.(config.model ?? '');
35
36
  const toolsSupported = !modelInfo || modelInfo.supportsTools;
36
37
  const apiTools = toolsSupported ? config.tools.map(toolToAPIFormat) : undefined;
37
- const toolPrompts = toolsSupported
38
+ let toolPrompts = toolsSupported
38
39
  ? config.tools.map((t) => t.prompt()).join("\n\n")
39
40
  : "";
41
+ // Hint about deferred tools available via ToolSearch
42
+ if (toolsSupported) {
43
+ const deferredCount = config.tools.filter(t => t instanceof DeferredTool && !t.activated).length;
44
+ if (deferredCount > 0) {
45
+ toolPrompts += `\n\n[${deferredCount} additional tools available — use ToolSearch to discover them]`;
46
+ }
47
+ }
40
48
  const fullSystemPrompt = toolPrompts
41
49
  ? config.systemPrompt + "\n\n# Available Tools\n\n" + toolPrompts
42
50
  : config.systemPrompt;
@@ -73,7 +73,7 @@ export async function executeSingleTool(toolCall, tools, context, permissionMode
73
73
  try {
74
74
  const toolAbort = AbortSignal.timeout(TOOL_TIMEOUT_MS);
75
75
  const contextWithTimeout = { ...context, abortSignal: context.abortSignal ?? toolAbort };
76
- const result = await Promise.race([
76
+ let result = await Promise.race([
77
77
  tool.call(parsed.data, contextWithTimeout),
78
78
  new Promise((_, reject) => {
79
79
  toolAbort.addEventListener("abort", () => reject(new Error(`Tool '${tool.name}' timed out after ${TOOL_TIMEOUT_MS / 1000}s`)));
@@ -85,11 +85,37 @@ export async function executeSingleTool(toolCall, tools, context, permissionMode
85
85
  toolArgs: JSON.stringify(toolCall.arguments).slice(0, 1000),
86
86
  toolOutput: result.output.slice(0, 1000),
87
87
  });
88
- // Strip ANSI and cap output
89
- let output = result.output.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, "");
88
+ // Verification loop: auto-run lint/typecheck after file-modifying tools
89
+ let verificationSuffix = '';
90
+ if (!result.isError && ['Edit', 'Write', 'MultiEdit'].includes(tool.name)) {
91
+ try {
92
+ const { runVerificationForFiles, getVerificationConfig, extractFilePaths } = await import('../harness/verification.js');
93
+ const vConfig = getVerificationConfig();
94
+ if (vConfig?.enabled) {
95
+ const filePaths = extractFilePaths(tool.name, parsed.data);
96
+ if (filePaths.length > 0) {
97
+ const vResult = await runVerificationForFiles(filePaths, vConfig);
98
+ if (vResult.ran) {
99
+ if (!vResult.passed) {
100
+ verificationSuffix = `\n\n[Verification FAILED]\n${vResult.summary}`;
101
+ if (vConfig.mode === 'block') {
102
+ result = { output: result.output, isError: true };
103
+ }
104
+ }
105
+ else {
106
+ verificationSuffix = '\n\n[Verification passed]';
107
+ }
108
+ }
109
+ }
110
+ }
111
+ }
112
+ catch { /* verification should never break tool execution */ }
113
+ }
114
+ // Strip ANSI and cap output, then append verification suffix
115
+ let output = result.output.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, "") + verificationSuffix;
90
116
  if (output.length > MAX_TOOL_RESULT_CHARS) {
91
117
  output = output.slice(0, MAX_TOOL_RESULT_CHARS)
92
- + `\n\n[TRUNCATED: output was ${result.output.length.toLocaleString()} chars, showing first ${MAX_TOOL_RESULT_CHARS.toLocaleString()}]`;
118
+ + `\n\n[TRUNCATED: output was ${output.length.toLocaleString()} chars, showing first ${MAX_TOOL_RESULT_CHARS.toLocaleString()}]`;
93
119
  }
94
120
  return { output, isError: result.isError };
95
121
  }
package/dist/repl.js CHANGED
@@ -48,9 +48,20 @@ export async function startREPL(config) {
48
48
  catch {
49
49
  session = createSession(config.provider.name, config.model ?? '', sessionExtras);
50
50
  }
51
+ // Wake context: inject session summary when resuming
52
+ if (config.resumeSessionId && session.hibernate) {
53
+ const { buildWakeContext } = await import('./harness/session.js');
54
+ const wakeMsg = buildWakeContext(session);
55
+ const { createInfoMessage } = await import('./types/message.js');
56
+ session.messages.push(createInfoMessage(wakeMsg));
57
+ }
51
58
  // Initialize checkpoints for file rewind
52
59
  const { initCheckpoints } = await import('./harness/checkpoints.js');
53
60
  initCheckpoints(session.id);
61
+ // Start background cron executor
62
+ const { CronExecutor } = await import('./services/CronExecutor.js');
63
+ const cronExecutor = new CronExecutor(config.provider, config.tools, config.systemPrompt, config.permissionMode, config.model);
64
+ cronExecutor.start();
54
65
  const cost = new CostTracker();
55
66
  let cachedConfig = readOhConfig();
56
67
  // Centralized state store — all REPL state lives here
@@ -598,6 +609,28 @@ export async function startREPL(config) {
598
609
  renderer.setError(null);
599
610
  // Exit
600
611
  if (input === 'exit' || input === 'quit' || input === '/exit' || input === '/quit' || input === '/q') {
612
+ // Hibernate: save session state for potential wake-up resume
613
+ try {
614
+ const { buildHibernateState } = await import('./harness/session.js');
615
+ session.hibernate = buildHibernateState(messages);
616
+ }
617
+ catch { /* ignore */ }
618
+ // Dream consolidation: prune stale memories before exit
619
+ try {
620
+ const { consolidateMemories } = await import('./harness/memory.js');
621
+ const { readOhConfig } = await import('./harness/config.js');
622
+ const ohCfg = readOhConfig();
623
+ if (ohCfg?.memory?.consolidateOnExit !== false) {
624
+ consolidateMemories();
625
+ }
626
+ }
627
+ catch { /* ignore */ }
628
+ // Emit sessionEnd hook
629
+ try {
630
+ const { emitHookAsync } = await import('./harness/hooks.js');
631
+ await emitHookAsync('sessionEnd', {});
632
+ }
633
+ catch { /* ignore */ }
601
634
  cleanup();
602
635
  process.exit(0);
603
636
  }
@@ -890,6 +923,7 @@ export async function startREPL(config) {
890
923
  if (cleanedUp)
891
924
  return;
892
925
  cleanedUp = true;
926
+ cronExecutor.stop();
893
927
  renderer.stop();
894
928
  session.messages = messages;
895
929
  session.totalCost = cost.totalCost;
@@ -13,6 +13,7 @@ export type AgentTask = {
13
13
  prompt: string;
14
14
  description?: string;
15
15
  blockedBy?: string[];
16
+ allowedTools?: string[];
16
17
  };
17
18
  export type AgentTaskResult = {
18
19
  id: string;
@@ -113,9 +113,18 @@ export class AgentDispatcher {
113
113
  }
114
114
  try {
115
115
  const { query } = await import('../query.js');
116
+ // Filter tools if task specifies allowed tools
117
+ let taskTools = this.tools;
118
+ if (task.allowedTools && task.allowedTools.length > 0) {
119
+ const allowSet = new Set(task.allowedTools.map(n => n.toLowerCase()));
120
+ allowSet.add('askuser');
121
+ const filtered = this.tools.filter(t => allowSet.has(t.name.toLowerCase()));
122
+ if (filtered.length > 0)
123
+ taskTools = filtered;
124
+ }
116
125
  const config = {
117
126
  provider: this.provider,
118
- tools: this.tools,
127
+ tools: taskTools,
119
128
  systemPrompt: this.systemPrompt,
120
129
  permissionMode: this.permissionMode,
121
130
  model: this.model,
@@ -0,0 +1,38 @@
1
+ /**
2
+ * CronExecutor — background scheduler that runs due cron tasks.
3
+ *
4
+ * Checks every 60 seconds for crons that are due, then executes each
5
+ * by running the cron's prompt through a sub-query loop. Results are
6
+ * persisted to ~/.oh/crons/history/ for debugging and audit.
7
+ *
8
+ * Execution is non-blocking and failure-isolated — one failing cron
9
+ * does not affect others or the main REPL session.
10
+ */
11
+ import type { Provider } from '../providers/base.js';
12
+ import type { Tools } from '../Tool.js';
13
+ import type { PermissionMode } from '../types/permissions.js';
14
+ import { type CronResult } from './cron.js';
15
+ export declare class CronExecutor {
16
+ private provider;
17
+ private tools;
18
+ private systemPrompt;
19
+ private permissionMode;
20
+ private model?;
21
+ private intervalId;
22
+ private running;
23
+ private _stopped;
24
+ constructor(provider: Provider, tools: Tools, systemPrompt: string, permissionMode: PermissionMode, model?: string | undefined);
25
+ /** Start the background scheduler */
26
+ start(): void;
27
+ /** Stop the scheduler */
28
+ stop(): void;
29
+ /** Check for due crons and execute them */
30
+ tick(): Promise<CronResult[]>;
31
+ /** Execute a single cron task */
32
+ private executeCron;
33
+ /** Whether the executor is currently running */
34
+ get isRunning(): boolean;
35
+ /** Get IDs of currently executing crons */
36
+ get activeIds(): string[];
37
+ }
38
+ //# sourceMappingURL=CronExecutor.d.ts.map
@@ -0,0 +1,130 @@
1
+ /**
2
+ * CronExecutor — background scheduler that runs due cron tasks.
3
+ *
4
+ * Checks every 60 seconds for crons that are due, then executes each
5
+ * by running the cron's prompt through a sub-query loop. Results are
6
+ * persisted to ~/.oh/crons/history/ for debugging and audit.
7
+ *
8
+ * Execution is non-blocking and failure-isolated — one failing cron
9
+ * does not affect others or the main REPL session.
10
+ */
11
+ import { listCrons, getDueCrons, updateCron, saveCronResult, } from './cron.js';
12
+ const CHECK_INTERVAL_MS = 60_000; // Check every 60 seconds
13
+ const MAX_CRON_TURNS = 10; // Limit sub-query turns for cron tasks
14
+ export class CronExecutor {
15
+ provider;
16
+ tools;
17
+ systemPrompt;
18
+ permissionMode;
19
+ model;
20
+ intervalId = null;
21
+ running = new Set(); // Prevent overlapping executions
22
+ _stopped = false;
23
+ constructor(provider, tools, systemPrompt, permissionMode, model) {
24
+ this.provider = provider;
25
+ this.tools = tools;
26
+ this.systemPrompt = systemPrompt;
27
+ this.permissionMode = permissionMode;
28
+ this.model = model;
29
+ }
30
+ /** Start the background scheduler */
31
+ start() {
32
+ if (this.intervalId)
33
+ return;
34
+ this._stopped = false;
35
+ // Run first tick after a short delay (don't block startup)
36
+ setTimeout(() => {
37
+ if (!this._stopped)
38
+ this.tick().catch(() => { });
39
+ }, 5_000);
40
+ // Then check every 60 seconds
41
+ this.intervalId = setInterval(() => {
42
+ if (!this._stopped)
43
+ this.tick().catch(() => { });
44
+ }, CHECK_INTERVAL_MS);
45
+ }
46
+ /** Stop the scheduler */
47
+ stop() {
48
+ this._stopped = true;
49
+ if (this.intervalId) {
50
+ clearInterval(this.intervalId);
51
+ this.intervalId = null;
52
+ }
53
+ }
54
+ /** Check for due crons and execute them */
55
+ async tick() {
56
+ const allCrons = listCrons();
57
+ const due = getDueCrons(allCrons);
58
+ const results = [];
59
+ for (const cron of due) {
60
+ // Skip if already running (prevent overlapping executions)
61
+ if (this.running.has(cron.id))
62
+ continue;
63
+ try {
64
+ const result = await this.executeCron(cron);
65
+ results.push(result);
66
+ }
67
+ catch (err) {
68
+ // Never let a single cron failure crash the scheduler
69
+ const result = {
70
+ cronId: cron.id,
71
+ timestamp: Date.now(),
72
+ output: '',
73
+ error: err instanceof Error ? err.message : String(err),
74
+ };
75
+ saveCronResult(result);
76
+ results.push(result);
77
+ }
78
+ }
79
+ return results;
80
+ }
81
+ /** Execute a single cron task */
82
+ async executeCron(cron) {
83
+ this.running.add(cron.id);
84
+ const timestamp = Date.now();
85
+ try {
86
+ const { query } = await import('../query.js');
87
+ const config = {
88
+ provider: this.provider,
89
+ tools: this.tools,
90
+ systemPrompt: `[Cron Task: ${cron.name}]\n\n${this.systemPrompt}`,
91
+ permissionMode: this.permissionMode,
92
+ model: this.model,
93
+ maxTurns: MAX_CRON_TURNS,
94
+ };
95
+ let output = '';
96
+ for await (const event of query(cron.prompt, config)) {
97
+ if (event.type === 'text_delta')
98
+ output += event.content;
99
+ if (event.type === 'error') {
100
+ const result = { cronId: cron.id, timestamp, output, error: event.message };
101
+ saveCronResult(result);
102
+ // Still update lastRun on error to prevent rapid retry loops
103
+ cron.lastRun = Date.now();
104
+ cron.runCount++;
105
+ updateCron(cron);
106
+ return result;
107
+ }
108
+ }
109
+ // Success: update cron metadata and save result
110
+ cron.lastRun = Date.now();
111
+ cron.runCount++;
112
+ updateCron(cron);
113
+ const result = { cronId: cron.id, timestamp, output };
114
+ saveCronResult(result);
115
+ return result;
116
+ }
117
+ finally {
118
+ this.running.delete(cron.id);
119
+ }
120
+ }
121
+ /** Whether the executor is currently running */
122
+ get isRunning() {
123
+ return this.intervalId !== null && !this._stopped;
124
+ }
125
+ /** Get IDs of currently executing crons */
126
+ get activeIds() {
127
+ return [...this.running];
128
+ }
129
+ }
130
+ //# sourceMappingURL=CronExecutor.js.map
@@ -94,6 +94,34 @@ export class StreamingToolExecutor {
94
94
  };
95
95
  try {
96
96
  tracked.result = await tool.call(parsed.data, callContext);
97
+ // Verification loop: auto-run lint/typecheck after file-modifying tools
98
+ if (tracked.result && !tracked.result.isError && ['Edit', 'Write', 'MultiEdit'].includes(tool.name)) {
99
+ try {
100
+ const { runVerificationForFiles, getVerificationConfig, extractFilePaths } = await import('../harness/verification.js');
101
+ const vConfig = getVerificationConfig();
102
+ if (vConfig?.enabled) {
103
+ const filePaths = extractFilePaths(tool.name, tracked.toolCall.arguments);
104
+ if (filePaths.length > 0) {
105
+ const vResult = await runVerificationForFiles(filePaths, vConfig);
106
+ if (vResult.ran) {
107
+ if (!vResult.passed) {
108
+ tracked.result = {
109
+ output: tracked.result.output + `\n\n[Verification FAILED]\n${vResult.summary}`,
110
+ isError: vConfig.mode === 'block',
111
+ };
112
+ }
113
+ else {
114
+ tracked.result = {
115
+ output: tracked.result.output + '\n\n[Verification passed]',
116
+ isError: false,
117
+ };
118
+ }
119
+ }
120
+ }
121
+ }
122
+ }
123
+ catch { /* verification should never break tool execution */ }
124
+ }
97
125
  }
98
126
  catch (err) {
99
127
  tracked.result = {
@@ -33,6 +33,10 @@ export declare function deleteCron(id: string): boolean;
33
33
  export declare function updateCron(cron: CronDefinition): void;
34
34
  /** Parse a simplified schedule string into milliseconds interval */
35
35
  export declare function parseScheduleMs(schedule: string): number | null;
36
+ /** Save a cron execution result to history */
37
+ export declare function saveCronResult(result: CronResult): void;
38
+ /** Get execution history for a cron (most recent first) */
39
+ export declare function getCronHistory(cronId: string, limit?: number): CronResult[];
36
40
  /**
37
41
  * Check which crons are due to run based on their schedule and lastRun.
38
42
  */
@@ -72,6 +72,33 @@ export function parseScheduleMs(schedule) {
72
72
  return parseInt(dayMatch[1]) * 24 * 60 * 60 * 1000;
73
73
  return null;
74
74
  }
75
+ // ── Result Persistence ──
76
+ const HISTORY_DIR = join(CRON_DIR, 'history');
77
+ /** Save a cron execution result to history */
78
+ export function saveCronResult(result) {
79
+ mkdirSync(HISTORY_DIR, { recursive: true });
80
+ const filename = `${result.cronId}-${result.timestamp}.json`;
81
+ writeFileSync(join(HISTORY_DIR, filename), JSON.stringify(result, null, 2));
82
+ }
83
+ /** Get execution history for a cron (most recent first) */
84
+ export function getCronHistory(cronId, limit = 10) {
85
+ if (!existsSync(HISTORY_DIR))
86
+ return [];
87
+ return readdirSync(HISTORY_DIR)
88
+ .filter(f => f.startsWith(`${cronId}-`) && f.endsWith('.json'))
89
+ .sort()
90
+ .reverse()
91
+ .slice(0, limit)
92
+ .map(f => {
93
+ try {
94
+ return JSON.parse(readFileSync(join(HISTORY_DIR, f), 'utf-8'));
95
+ }
96
+ catch {
97
+ return null;
98
+ }
99
+ })
100
+ .filter((r) => r !== null);
101
+ }
75
102
  /**
76
103
  * Check which crons are due to run based on their schedule and lastRun.
77
104
  */
@@ -7,6 +7,7 @@ declare const inputSchema: z.ZodObject<{
7
7
  run_in_background: z.ZodOptional<z.ZodBoolean>;
8
8
  model: z.ZodOptional<z.ZodString>;
9
9
  subagent_type: z.ZodOptional<z.ZodString>;
10
+ allowed_tools: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
10
11
  }, "strip", z.ZodTypeAny, {
11
12
  prompt: string;
12
13
  model?: string | undefined;
@@ -14,6 +15,7 @@ declare const inputSchema: z.ZodObject<{
14
15
  run_in_background?: boolean | undefined;
15
16
  isolated?: boolean | undefined;
16
17
  subagent_type?: string | undefined;
18
+ allowed_tools?: string[] | undefined;
17
19
  }, {
18
20
  prompt: string;
19
21
  model?: string | undefined;
@@ -21,6 +23,7 @@ declare const inputSchema: z.ZodObject<{
21
23
  run_in_background?: boolean | undefined;
22
24
  isolated?: boolean | undefined;
23
25
  subagent_type?: string | undefined;
26
+ allowed_tools?: string[] | undefined;
24
27
  }>;
25
28
  export declare const AgentTool: Tool<typeof inputSchema>;
26
29
  export {};