openhorse 0.1.5

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 (587) hide show
  1. package/README.md +460 -0
  2. package/bin/openhorse +56 -0
  3. package/dist/agents/coder.d.ts +12 -0
  4. package/dist/agents/coder.d.ts.map +1 -0
  5. package/dist/agents/coder.js +48 -0
  6. package/dist/agents/coder.js.map +1 -0
  7. package/dist/agents/leader.d.ts +12 -0
  8. package/dist/agents/leader.d.ts.map +1 -0
  9. package/dist/agents/leader.js +49 -0
  10. package/dist/agents/leader.js.map +1 -0
  11. package/dist/agents/router.d.ts +59 -0
  12. package/dist/agents/router.d.ts.map +1 -0
  13. package/dist/agents/router.js +193 -0
  14. package/dist/agents/router.js.map +1 -0
  15. package/dist/cli-ink.d.ts +7 -0
  16. package/dist/cli-ink.d.ts.map +1 -0
  17. package/dist/cli-ink.js +135 -0
  18. package/dist/cli-ink.js.map +1 -0
  19. package/dist/cli.d.ts +7 -0
  20. package/dist/cli.d.ts.map +1 -0
  21. package/dist/cli.js +638 -0
  22. package/dist/cli.js.map +1 -0
  23. package/dist/commands/index.d.ts +12 -0
  24. package/dist/commands/index.d.ts.map +1 -0
  25. package/dist/commands/index.js +1095 -0
  26. package/dist/commands/index.js.map +1 -0
  27. package/dist/commands/parser.d.ts +26 -0
  28. package/dist/commands/parser.d.ts.map +1 -0
  29. package/dist/commands/parser.js +61 -0
  30. package/dist/commands/parser.js.map +1 -0
  31. package/dist/commands/types.d.ts +61 -0
  32. package/dist/commands/types.d.ts.map +1 -0
  33. package/dist/commands/types.js +32 -0
  34. package/dist/commands/types.js.map +1 -0
  35. package/dist/core/agent.d.ts +66 -0
  36. package/dist/core/agent.d.ts.map +1 -0
  37. package/dist/core/agent.js +55 -0
  38. package/dist/core/agent.js.map +1 -0
  39. package/dist/core/brain.d.ts +41 -0
  40. package/dist/core/brain.d.ts.map +1 -0
  41. package/dist/core/brain.js +92 -0
  42. package/dist/core/brain.js.map +1 -0
  43. package/dist/core/cost-tracker.d.ts +107 -0
  44. package/dist/core/cost-tracker.d.ts.map +1 -0
  45. package/dist/core/cost-tracker.js +199 -0
  46. package/dist/core/cost-tracker.js.map +1 -0
  47. package/dist/core/strategy-tracker.d.ts +61 -0
  48. package/dist/core/strategy-tracker.d.ts.map +1 -0
  49. package/dist/core/strategy-tracker.js +124 -0
  50. package/dist/core/strategy-tracker.js.map +1 -0
  51. package/dist/framework/index.d.ts +20 -0
  52. package/dist/framework/index.d.ts.map +1 -0
  53. package/dist/framework/index.js +29 -0
  54. package/dist/framework/index.js.map +1 -0
  55. package/dist/framework/prompt.d.ts +40 -0
  56. package/dist/framework/prompt.d.ts.map +1 -0
  57. package/dist/framework/prompt.js +112 -0
  58. package/dist/framework/prompt.js.map +1 -0
  59. package/dist/framework/query.d.ts +86 -0
  60. package/dist/framework/query.d.ts.map +1 -0
  61. package/dist/framework/query.js +177 -0
  62. package/dist/framework/query.js.map +1 -0
  63. package/dist/framework/store.d.ts +64 -0
  64. package/dist/framework/store.d.ts.map +1 -0
  65. package/dist/framework/store.js +78 -0
  66. package/dist/framework/store.js.map +1 -0
  67. package/dist/framework/tool-state.d.ts +22 -0
  68. package/dist/framework/tool-state.d.ts.map +1 -0
  69. package/dist/framework/tool-state.js +40 -0
  70. package/dist/framework/tool-state.js.map +1 -0
  71. package/dist/framework/tool.d.ts +88 -0
  72. package/dist/framework/tool.d.ts.map +1 -0
  73. package/dist/framework/tool.js +60 -0
  74. package/dist/framework/tool.js.map +1 -0
  75. package/dist/harness/harness.d.ts +96 -0
  76. package/dist/harness/harness.d.ts.map +1 -0
  77. package/dist/harness/harness.js +224 -0
  78. package/dist/harness/harness.js.map +1 -0
  79. package/dist/harness/safety.d.ts +89 -0
  80. package/dist/harness/safety.d.ts.map +1 -0
  81. package/dist/harness/safety.js +178 -0
  82. package/dist/harness/safety.js.map +1 -0
  83. package/dist/index.d.ts +30 -0
  84. package/dist/index.d.ts.map +1 -0
  85. package/dist/index.js +57 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/init.d.ts +178 -0
  88. package/dist/init.d.ts.map +1 -0
  89. package/dist/init.js +473 -0
  90. package/dist/init.js.map +1 -0
  91. package/dist/ink/bidi.d.ts +16 -0
  92. package/dist/ink/bidi.d.ts.map +1 -0
  93. package/dist/ink/bidi.js +124 -0
  94. package/dist/ink/bidi.js.map +1 -0
  95. package/dist/ink/clearTerminal.d.ts +14 -0
  96. package/dist/ink/clearTerminal.d.ts.map +1 -0
  97. package/dist/ink/clearTerminal.js +63 -0
  98. package/dist/ink/clearTerminal.js.map +1 -0
  99. package/dist/ink/colorize.d.ts +17 -0
  100. package/dist/ink/colorize.d.ts.map +1 -0
  101. package/dist/ink/colorize.js +208 -0
  102. package/dist/ink/colorize.js.map +1 -0
  103. package/dist/ink/components/App.d.ts +73 -0
  104. package/dist/ink/components/App.d.ts.map +1 -0
  105. package/dist/ink/components/App.js +646 -0
  106. package/dist/ink/components/App.js.map +1 -0
  107. package/dist/ink/components/AppContext.d.ts +12 -0
  108. package/dist/ink/components/AppContext.d.ts.map +1 -0
  109. package/dist/ink/components/AppContext.js +14 -0
  110. package/dist/ink/components/AppContext.js.map +1 -0
  111. package/dist/ink/components/Box.d.ts +44 -0
  112. package/dist/ink/components/Box.d.ts.map +1 -0
  113. package/dist/ink/components/Box.js +191 -0
  114. package/dist/ink/components/Box.js.map +1 -0
  115. package/dist/ink/components/ClockContext.d.ts +9 -0
  116. package/dist/ink/components/ClockContext.d.ts.map +1 -0
  117. package/dist/ink/components/ClockContext.js +146 -0
  118. package/dist/ink/components/ClockContext.js.map +1 -0
  119. package/dist/ink/components/CursorDeclarationContext.d.ts +23 -0
  120. package/dist/ink/components/CursorDeclarationContext.d.ts.map +1 -0
  121. package/dist/ink/components/CursorDeclarationContext.js +6 -0
  122. package/dist/ink/components/CursorDeclarationContext.js.map +1 -0
  123. package/dist/ink/components/ErrorOverview.d.ts +6 -0
  124. package/dist/ink/components/ErrorOverview.d.ts.map +1 -0
  125. package/dist/ink/components/ErrorOverview.js +27 -0
  126. package/dist/ink/components/ErrorOverview.js.map +1 -0
  127. package/dist/ink/components/Newline.d.ts +13 -0
  128. package/dist/ink/components/Newline.d.ts.map +1 -0
  129. package/dist/ink/components/Newline.js +36 -0
  130. package/dist/ink/components/Newline.js.map +1 -0
  131. package/dist/ink/components/NoSelect.d.ts +20 -0
  132. package/dist/ink/components/NoSelect.d.ts.map +1 -0
  133. package/dist/ink/components/NoSelect.js +63 -0
  134. package/dist/ink/components/NoSelect.js.map +1 -0
  135. package/dist/ink/components/RawAnsi.d.ts +17 -0
  136. package/dist/ink/components/RawAnsi.d.ts.map +1 -0
  137. package/dist/ink/components/RawAnsi.js +52 -0
  138. package/dist/ink/components/RawAnsi.js.map +1 -0
  139. package/dist/ink/components/Spacer.d.ts +6 -0
  140. package/dist/ink/components/Spacer.d.ts.map +1 -0
  141. package/dist/ink/components/Spacer.js +26 -0
  142. package/dist/ink/components/Spacer.js.map +1 -0
  143. package/dist/ink/components/StdinContext.d.ts +28 -0
  144. package/dist/ink/components/StdinContext.d.ts.map +1 -0
  145. package/dist/ink/components/StdinContext.js +19 -0
  146. package/dist/ink/components/StdinContext.js.map +1 -0
  147. package/dist/ink/components/TerminalFocusContext.d.ts +10 -0
  148. package/dist/ink/components/TerminalFocusContext.d.ts.map +1 -0
  149. package/dist/ink/components/TerminalFocusContext.js +81 -0
  150. package/dist/ink/components/TerminalFocusContext.js.map +1 -0
  151. package/dist/ink/components/TerminalSizeContext.d.ts +6 -0
  152. package/dist/ink/components/TerminalSizeContext.d.ts.map +1 -0
  153. package/dist/ink/components/TerminalSizeContext.js +6 -0
  154. package/dist/ink/components/TerminalSizeContext.js.map +1 -0
  155. package/dist/ink/components/Text.d.ts +56 -0
  156. package/dist/ink/components/Text.d.ts.map +1 -0
  157. package/dist/ink/components/Text.js +201 -0
  158. package/dist/ink/components/Text.js.map +1 -0
  159. package/dist/ink/constants.d.ts +2 -0
  160. package/dist/ink/constants.d.ts.map +1 -0
  161. package/dist/ink/constants.js +6 -0
  162. package/dist/ink/constants.js.map +1 -0
  163. package/dist/ink/devtools.d.ts +3 -0
  164. package/dist/ink/devtools.d.ts.map +1 -0
  165. package/dist/ink/devtools.js +5 -0
  166. package/dist/ink/devtools.js.map +1 -0
  167. package/dist/ink/dom.d.ts +77 -0
  168. package/dist/ink/dom.d.ts.map +1 -0
  169. package/dist/ink/dom.js +322 -0
  170. package/dist/ink/dom.js.map +1 -0
  171. package/dist/ink/events/click-event.d.ts +32 -0
  172. package/dist/ink/events/click-event.d.ts.map +1 -0
  173. package/dist/ink/events/click-event.js +30 -0
  174. package/dist/ink/events/click-event.js.map +1 -0
  175. package/dist/ink/events/dispatcher.d.ts +41 -0
  176. package/dist/ink/events/dispatcher.d.ts.map +1 -0
  177. package/dist/ink/events/dispatcher.js +181 -0
  178. package/dist/ink/events/dispatcher.js.map +1 -0
  179. package/dist/ink/events/emitter.d.ts +6 -0
  180. package/dist/ink/events/emitter.d.ts.map +1 -0
  181. package/dist/ink/events/emitter.js +36 -0
  182. package/dist/ink/events/emitter.js.map +1 -0
  183. package/dist/ink/events/event-handlers.d.ts +47 -0
  184. package/dist/ink/events/event-handlers.d.ts.map +1 -0
  185. package/dist/ink/events/event-handlers.js +34 -0
  186. package/dist/ink/events/event-handlers.js.map +1 -0
  187. package/dist/ink/events/event.d.ts +6 -0
  188. package/dist/ink/events/event.d.ts.map +1 -0
  189. package/dist/ink/events/event.js +16 -0
  190. package/dist/ink/events/event.js.map +1 -0
  191. package/dist/ink/events/focus-event.d.ts +14 -0
  192. package/dist/ink/events/focus-event.d.ts.map +1 -0
  193. package/dist/ink/events/focus-event.js +20 -0
  194. package/dist/ink/events/focus-event.js.map +1 -0
  195. package/dist/ink/events/input-event.d.ts +31 -0
  196. package/dist/ink/events/input-event.d.ts.map +1 -0
  197. package/dist/ink/events/input-event.js +163 -0
  198. package/dist/ink/events/input-event.js.map +1 -0
  199. package/dist/ink/events/keyboard-event.d.ts +20 -0
  200. package/dist/ink/events/keyboard-event.d.ts.map +1 -0
  201. package/dist/ink/events/keyboard-event.js +44 -0
  202. package/dist/ink/events/keyboard-event.js.map +1 -0
  203. package/dist/ink/events/terminal-event.d.ts +55 -0
  204. package/dist/ink/events/terminal-event.d.ts.map +1 -0
  205. package/dist/ink/events/terminal-event.js +79 -0
  206. package/dist/ink/events/terminal-event.js.map +1 -0
  207. package/dist/ink/events/terminal-focus-event.d.ts +14 -0
  208. package/dist/ink/events/terminal-focus-event.d.ts.map +1 -0
  209. package/dist/ink/events/terminal-focus-event.js +19 -0
  210. package/dist/ink/events/terminal-focus-event.js.map +1 -0
  211. package/dist/ink/focus.d.ts +44 -0
  212. package/dist/ink/focus.d.ts.map +1 -0
  213. package/dist/ink/focus.js +164 -0
  214. package/dist/ink/focus.js.map +1 -0
  215. package/dist/ink/frame.d.ts +95 -0
  216. package/dist/ink/frame.d.ts.map +1 -0
  217. package/dist/ink/frame.js +35 -0
  218. package/dist/ink/frame.js.map +1 -0
  219. package/dist/ink/get-max-width.d.ts +18 -0
  220. package/dist/ink/get-max-width.d.ts.map +1 -0
  221. package/dist/ink/get-max-width.js +26 -0
  222. package/dist/ink/get-max-width.js.map +1 -0
  223. package/dist/ink/hit-test.d.ts +34 -0
  224. package/dist/ink/hit-test.d.ts.map +1 -0
  225. package/dist/ink/hit-test.js +119 -0
  226. package/dist/ink/hit-test.js.map +1 -0
  227. package/dist/ink/hooks/use-animation-frame.d.ts +27 -0
  228. package/dist/ink/hooks/use-animation-frame.d.ts.map +1 -0
  229. package/dist/ink/hooks/use-animation-frame.js +52 -0
  230. package/dist/ink/hooks/use-animation-frame.js.map +1 -0
  231. package/dist/ink/hooks/use-app.d.ts +6 -0
  232. package/dist/ink/hooks/use-app.d.ts.map +1 -0
  233. package/dist/ink/hooks/use-app.js +13 -0
  234. package/dist/ink/hooks/use-app.js.map +1 -0
  235. package/dist/ink/hooks/use-declared-cursor.d.ts +27 -0
  236. package/dist/ink/hooks/use-declared-cursor.d.ts.map +1 -0
  237. package/dist/ink/hooks/use-declared-cursor.js +67 -0
  238. package/dist/ink/hooks/use-declared-cursor.js.map +1 -0
  239. package/dist/ink/hooks/use-input.d.ts +38 -0
  240. package/dist/ink/hooks/use-input.d.ts.map +1 -0
  241. package/dist/ink/hooks/use-input.js +86 -0
  242. package/dist/ink/hooks/use-input.js.map +1 -0
  243. package/dist/ink/hooks/use-interval.d.ts +19 -0
  244. package/dist/ink/hooks/use-interval.d.ts.map +1 -0
  245. package/dist/ink/hooks/use-interval.js +59 -0
  246. package/dist/ink/hooks/use-interval.js.map +1 -0
  247. package/dist/ink/hooks/use-search-highlight.d.ts +31 -0
  248. package/dist/ink/hooks/use-search-highlight.d.ts.map +1 -0
  249. package/dist/ink/hooks/use-search-highlight.js +39 -0
  250. package/dist/ink/hooks/use-search-highlight.js.map +1 -0
  251. package/dist/ink/hooks/use-selection.d.ts +40 -0
  252. package/dist/ink/hooks/use-selection.d.ts.map +1 -0
  253. package/dist/ink/hooks/use-selection.js +68 -0
  254. package/dist/ink/hooks/use-selection.js.map +1 -0
  255. package/dist/ink/hooks/use-stdin.d.ts +6 -0
  256. package/dist/ink/hooks/use-stdin.d.ts.map +1 -0
  257. package/dist/ink/hooks/use-stdin.js +13 -0
  258. package/dist/ink/hooks/use-stdin.js.map +1 -0
  259. package/dist/ink/hooks/use-tab-status.d.ts +14 -0
  260. package/dist/ink/hooks/use-tab-status.d.ts.map +1 -0
  261. package/dist/ink/hooks/use-tab-status.js +61 -0
  262. package/dist/ink/hooks/use-tab-status.js.map +1 -0
  263. package/dist/ink/hooks/use-terminal-focus.d.ts +11 -0
  264. package/dist/ink/hooks/use-terminal-focus.d.ts.map +1 -0
  265. package/dist/ink/hooks/use-terminal-focus.js +22 -0
  266. package/dist/ink/hooks/use-terminal-focus.js.map +1 -0
  267. package/dist/ink/hooks/use-terminal-title.d.ts +13 -0
  268. package/dist/ink/hooks/use-terminal-title.d.ts.map +1 -0
  269. package/dist/ink/hooks/use-terminal-title.js +36 -0
  270. package/dist/ink/hooks/use-terminal-title.js.map +1 -0
  271. package/dist/ink/hooks/use-terminal-viewport.d.ts +30 -0
  272. package/dist/ink/hooks/use-terminal-viewport.d.ts.map +1 -0
  273. package/dist/ink/hooks/use-terminal-viewport.js +81 -0
  274. package/dist/ink/hooks/use-terminal-viewport.js.map +1 -0
  275. package/dist/ink/index.d.ts +54 -0
  276. package/dist/ink/index.d.ts.map +1 -0
  277. package/dist/ink/index.js +111 -0
  278. package/dist/ink/index.js.map +1 -0
  279. package/dist/ink/ink.d.ts +371 -0
  280. package/dist/ink/ink.d.ts.map +1 -0
  281. package/dist/ink/ink.js +1686 -0
  282. package/dist/ink/ink.js.map +1 -0
  283. package/dist/ink/instances.d.ts +4 -0
  284. package/dist/ink/instances.d.ts.map +1 -0
  285. package/dist/ink/instances.js +10 -0
  286. package/dist/ink/instances.js.map +1 -0
  287. package/dist/ink/line-width-cache.d.ts +2 -0
  288. package/dist/ink/line-width-cache.d.ts.map +1 -0
  289. package/dist/ink/line-width-cache.js +23 -0
  290. package/dist/ink/line-width-cache.js.map +1 -0
  291. package/dist/ink/log-update.d.ts +18 -0
  292. package/dist/ink/log-update.d.ts.map +1 -0
  293. package/dist/ink/log-update.js +637 -0
  294. package/dist/ink/log-update.js.map +1 -0
  295. package/dist/ink/measure-element.d.ts +17 -0
  296. package/dist/ink/measure-element.d.ts.map +1 -0
  297. package/dist/ink/measure-element.js +11 -0
  298. package/dist/ink/measure-element.js.map +1 -0
  299. package/dist/ink/measure-text.d.ts +7 -0
  300. package/dist/ink/measure-text.d.ts.map +1 -0
  301. package/dist/ink/measure-text.js +38 -0
  302. package/dist/ink/measure-text.js.map +1 -0
  303. package/dist/ink/node-cache.d.ts +21 -0
  304. package/dist/ink/node-cache.d.ts.map +1 -0
  305. package/dist/ink/node-cache.js +36 -0
  306. package/dist/ink/node-cache.js.map +1 -0
  307. package/dist/ink/optimizer.d.ts +16 -0
  308. package/dist/ink/optimizer.d.ts.map +1 -0
  309. package/dist/ink/optimizer.js +85 -0
  310. package/dist/ink/optimizer.js.map +1 -0
  311. package/dist/ink/output.d.ts +120 -0
  312. package/dist/ink/output.d.ts.map +1 -0
  313. package/dist/ink/output.js +559 -0
  314. package/dist/ink/output.js.map +1 -0
  315. package/dist/ink/parse-keypress.d.ts +112 -0
  316. package/dist/ink/parse-keypress.d.ts.map +1 -0
  317. package/dist/ink/parse-keypress.js +719 -0
  318. package/dist/ink/parse-keypress.js.map +1 -0
  319. package/dist/ink/parse-keypress.test.d.ts +2 -0
  320. package/dist/ink/parse-keypress.test.d.ts.map +1 -0
  321. package/dist/ink/parse-keypress.test.js +37 -0
  322. package/dist/ink/parse-keypress.test.js.map +1 -0
  323. package/dist/ink/reconciler.d.ts +12 -0
  324. package/dist/ink/reconciler.d.ts.map +1 -0
  325. package/dist/ink/reconciler.js +456 -0
  326. package/dist/ink/reconciler.js.map +1 -0
  327. package/dist/ink/render-border.d.ts +25 -0
  328. package/dist/ink/render-border.d.ts.map +1 -0
  329. package/dist/ink/render-border.js +141 -0
  330. package/dist/ink/render-border.js.map +1 -0
  331. package/dist/ink/render-node-to-output.d.ts +46 -0
  332. package/dist/ink/render-node-to-output.d.ts.map +1 -0
  333. package/dist/ink/render-node-to-output.js +1257 -0
  334. package/dist/ink/render-node-to-output.js.map +1 -0
  335. package/dist/ink/render-to-screen.d.ts +47 -0
  336. package/dist/ink/render-to-screen.d.ts.map +1 -0
  337. package/dist/ink/render-to-screen.js +213 -0
  338. package/dist/ink/render-to-screen.js.map +1 -0
  339. package/dist/ink/renderer.d.ts +15 -0
  340. package/dist/ink/renderer.d.ts.map +1 -0
  341. package/dist/ink/renderer.js +169 -0
  342. package/dist/ink/renderer.js.map +1 -0
  343. package/dist/ink/root.d.ts +75 -0
  344. package/dist/ink/root.d.ts.map +1 -0
  345. package/dist/ink/root.js +89 -0
  346. package/dist/ink/root.js.map +1 -0
  347. package/dist/ink/screen.d.ts +270 -0
  348. package/dist/ink/screen.d.ts.map +1 -0
  349. package/dist/ink/screen.js +1194 -0
  350. package/dist/ink/screen.js.map +1 -0
  351. package/dist/ink/searchHighlight.d.ts +21 -0
  352. package/dist/ink/searchHighlight.d.ts.map +1 -0
  353. package/dist/ink/searchHighlight.js +82 -0
  354. package/dist/ink/searchHighlight.js.map +1 -0
  355. package/dist/ink/selection.d.ts +230 -0
  356. package/dist/ink/selection.d.ts.map +1 -0
  357. package/dist/ink/selection.js +814 -0
  358. package/dist/ink/selection.js.map +1 -0
  359. package/dist/ink/squash-text-nodes.d.ts +23 -0
  360. package/dist/ink/squash-text-nodes.d.ts.map +1 -0
  361. package/dist/ink/squash-text-nodes.js +60 -0
  362. package/dist/ink/squash-text-nodes.js.map +1 -0
  363. package/dist/ink/stringWidth.d.ts +2 -0
  364. package/dist/ink/stringWidth.d.ts.map +1 -0
  365. package/dist/ink/stringWidth.js +207 -0
  366. package/dist/ink/stringWidth.js.map +1 -0
  367. package/dist/ink/styles.d.ts +307 -0
  368. package/dist/ink/styles.d.ts.map +1 -0
  369. package/dist/ink/styles.js +302 -0
  370. package/dist/ink/styles.js.map +1 -0
  371. package/dist/ink/supports-hyperlinks.d.ts +14 -0
  372. package/dist/ink/supports-hyperlinks.d.ts.map +1 -0
  373. package/dist/ink/supports-hyperlinks.js +48 -0
  374. package/dist/ink/supports-hyperlinks.js.map +1 -0
  375. package/dist/ink/tabstops.d.ts +2 -0
  376. package/dist/ink/tabstops.d.ts.map +1 -0
  377. package/dist/ink/tabstops.js +43 -0
  378. package/dist/ink/tabstops.js.map +1 -0
  379. package/dist/ink/terminal-focus-state.d.ts +7 -0
  380. package/dist/ink/terminal-focus-state.d.ts.map +1 -0
  381. package/dist/ink/terminal-focus-state.js +43 -0
  382. package/dist/ink/terminal-focus-state.js.map +1 -0
  383. package/dist/ink/terminal-querier.d.ts +130 -0
  384. package/dist/ink/terminal-querier.d.ts.map +1 -0
  385. package/dist/ink/terminal-querier.js +184 -0
  386. package/dist/ink/terminal-querier.js.map +1 -0
  387. package/dist/ink/terminal.d.ts +56 -0
  388. package/dist/ink/terminal.d.ts.map +1 -0
  389. package/dist/ink/terminal.js +249 -0
  390. package/dist/ink/terminal.js.map +1 -0
  391. package/dist/ink/termio/csi.d.ts +166 -0
  392. package/dist/ink/termio/csi.d.ts.map +1 -0
  393. package/dist/ink/termio/csi.js +285 -0
  394. package/dist/ink/termio/csi.js.map +1 -0
  395. package/dist/ink/termio/dec.d.ts +38 -0
  396. package/dist/ink/termio/dec.d.ts.map +1 -0
  397. package/dist/ink/termio/dec.js +59 -0
  398. package/dist/ink/termio/dec.js.map +1 -0
  399. package/dist/ink/termio.d.ts +25 -0
  400. package/dist/ink/termio.d.ts.map +1 -0
  401. package/dist/ink/termio.js +32 -0
  402. package/dist/ink/termio.js.map +1 -0
  403. package/dist/ink/useTerminalNotification.d.ts +27 -0
  404. package/dist/ink/useTerminalNotification.d.ts.map +1 -0
  405. package/dist/ink/useTerminalNotification.js +62 -0
  406. package/dist/ink/useTerminalNotification.js.map +1 -0
  407. package/dist/ink/warn.d.ts +2 -0
  408. package/dist/ink/warn.d.ts.map +1 -0
  409. package/dist/ink/warn.js +14 -0
  410. package/dist/ink/warn.js.map +1 -0
  411. package/dist/ink/widest-line.d.ts +2 -0
  412. package/dist/ink/widest-line.d.ts.map +1 -0
  413. package/dist/ink/widest-line.js +18 -0
  414. package/dist/ink/widest-line.js.map +1 -0
  415. package/dist/ink/wrap-text.d.ts +3 -0
  416. package/dist/ink/wrap-text.d.ts.map +1 -0
  417. package/dist/ink/wrap-text.js +61 -0
  418. package/dist/ink/wrap-text.js.map +1 -0
  419. package/dist/ink/wrapAnsi.d.ts +8 -0
  420. package/dist/ink/wrapAnsi.d.ts.map +1 -0
  421. package/dist/ink/wrapAnsi.js +13 -0
  422. package/dist/ink/wrapAnsi.js.map +1 -0
  423. package/dist/memory/embeddings.d.ts +33 -0
  424. package/dist/memory/embeddings.d.ts.map +1 -0
  425. package/dist/memory/embeddings.js +123 -0
  426. package/dist/memory/embeddings.js.map +1 -0
  427. package/dist/memory/index.d.ts +14 -0
  428. package/dist/memory/index.d.ts.map +1 -0
  429. package/dist/memory/index.js +31 -0
  430. package/dist/memory/index.js.map +1 -0
  431. package/dist/memory/prompts.d.ts +12 -0
  432. package/dist/memory/prompts.d.ts.map +1 -0
  433. package/dist/memory/prompts.js +117 -0
  434. package/dist/memory/prompts.js.map +1 -0
  435. package/dist/memory/semantic-search.d.ts +45 -0
  436. package/dist/memory/semantic-search.d.ts.map +1 -0
  437. package/dist/memory/semantic-search.js +112 -0
  438. package/dist/memory/semantic-search.js.map +1 -0
  439. package/dist/memory/storage.d.ts +79 -0
  440. package/dist/memory/storage.d.ts.map +1 -0
  441. package/dist/memory/storage.js +285 -0
  442. package/dist/memory/storage.js.map +1 -0
  443. package/dist/memory/store.d.ts +103 -0
  444. package/dist/memory/store.d.ts.map +1 -0
  445. package/dist/memory/store.js +226 -0
  446. package/dist/memory/store.js.map +1 -0
  447. package/dist/memory/types.d.ts +40 -0
  448. package/dist/memory/types.d.ts.map +1 -0
  449. package/dist/memory/types.js +71 -0
  450. package/dist/memory/types.js.map +1 -0
  451. package/dist/memory/validation.d.ts +28 -0
  452. package/dist/memory/validation.d.ts.map +1 -0
  453. package/dist/memory/validation.js +147 -0
  454. package/dist/memory/validation.js.map +1 -0
  455. package/dist/memory/vector-store.d.ts +49 -0
  456. package/dist/memory/vector-store.d.ts.map +1 -0
  457. package/dist/memory/vector-store.js +259 -0
  458. package/dist/memory/vector-store.js.map +1 -0
  459. package/dist/screens/REPL.d.ts +21 -0
  460. package/dist/screens/REPL.d.ts.map +1 -0
  461. package/dist/screens/REPL.js +139 -0
  462. package/dist/screens/REPL.js.map +1 -0
  463. package/dist/services/agent-runner.d.ts +68 -0
  464. package/dist/services/agent-runner.d.ts.map +1 -0
  465. package/dist/services/agent-runner.js +186 -0
  466. package/dist/services/agent-runner.js.map +1 -0
  467. package/dist/services/atomic-write.d.ts +12 -0
  468. package/dist/services/atomic-write.d.ts.map +1 -0
  469. package/dist/services/atomic-write.js +27 -0
  470. package/dist/services/atomic-write.js.map +1 -0
  471. package/dist/services/config-dir.d.ts +55 -0
  472. package/dist/services/config-dir.d.ts.map +1 -0
  473. package/dist/services/config-dir.js +136 -0
  474. package/dist/services/config-dir.js.map +1 -0
  475. package/dist/services/config.d.ts +54 -0
  476. package/dist/services/config.d.ts.map +1 -0
  477. package/dist/services/config.js +98 -0
  478. package/dist/services/config.js.map +1 -0
  479. package/dist/services/file-glob.d.ts +26 -0
  480. package/dist/services/file-glob.d.ts.map +1 -0
  481. package/dist/services/file-glob.js +134 -0
  482. package/dist/services/file-glob.js.map +1 -0
  483. package/dist/services/global-config.d.ts +109 -0
  484. package/dist/services/global-config.d.ts.map +1 -0
  485. package/dist/services/global-config.js +211 -0
  486. package/dist/services/global-config.js.map +1 -0
  487. package/dist/services/llm.d.ts +139 -0
  488. package/dist/services/llm.d.ts.map +1 -0
  489. package/dist/services/llm.js +376 -0
  490. package/dist/services/llm.js.map +1 -0
  491. package/dist/services/memory.d.ts +39 -0
  492. package/dist/services/memory.d.ts.map +1 -0
  493. package/dist/services/memory.js +88 -0
  494. package/dist/services/memory.js.map +1 -0
  495. package/dist/services/session-storage.d.ts +136 -0
  496. package/dist/services/session-storage.d.ts.map +1 -0
  497. package/dist/services/session-storage.js +304 -0
  498. package/dist/services/session-storage.js.map +1 -0
  499. package/dist/services/task-manager.d.ts +154 -0
  500. package/dist/services/task-manager.d.ts.map +1 -0
  501. package/dist/services/task-manager.js +288 -0
  502. package/dist/services/task-manager.js.map +1 -0
  503. package/dist/services/yaml-config.d.ts +57 -0
  504. package/dist/services/yaml-config.d.ts.map +1 -0
  505. package/dist/services/yaml-config.js +176 -0
  506. package/dist/services/yaml-config.js.map +1 -0
  507. package/dist/skills/discovery.d.ts +22 -0
  508. package/dist/skills/discovery.d.ts.map +1 -0
  509. package/dist/skills/discovery.js +75 -0
  510. package/dist/skills/discovery.js.map +1 -0
  511. package/dist/skills/index.d.ts +10 -0
  512. package/dist/skills/index.d.ts.map +1 -0
  513. package/dist/skills/index.js +26 -0
  514. package/dist/skills/index.js.map +1 -0
  515. package/dist/skills/loader.d.ts +48 -0
  516. package/dist/skills/loader.d.ts.map +1 -0
  517. package/dist/skills/loader.js +231 -0
  518. package/dist/skills/loader.js.map +1 -0
  519. package/dist/skills/registry.d.ts +37 -0
  520. package/dist/skills/registry.d.ts.map +1 -0
  521. package/dist/skills/registry.js +134 -0
  522. package/dist/skills/registry.js.map +1 -0
  523. package/dist/skills/types.d.ts +89 -0
  524. package/dist/skills/types.d.ts.map +1 -0
  525. package/dist/skills/types.js +24 -0
  526. package/dist/skills/types.js.map +1 -0
  527. package/dist/tools/bash_security.d.ts +64 -0
  528. package/dist/tools/bash_security.d.ts.map +1 -0
  529. package/dist/tools/bash_security.js +291 -0
  530. package/dist/tools/bash_security.js.map +1 -0
  531. package/dist/tools/index.d.ts +23 -0
  532. package/dist/tools/index.d.ts.map +1 -0
  533. package/dist/tools/index.js +965 -0
  534. package/dist/tools/index.js.map +1 -0
  535. package/dist/tools/mcp.d.ts +72 -0
  536. package/dist/tools/mcp.d.ts.map +1 -0
  537. package/dist/tools/mcp.js +422 -0
  538. package/dist/tools/mcp.js.map +1 -0
  539. package/dist/tools/plan.d.ts +18 -0
  540. package/dist/tools/plan.d.ts.map +1 -0
  541. package/dist/tools/plan.js +75 -0
  542. package/dist/tools/plan.js.map +1 -0
  543. package/dist/tools/todo.d.ts +18 -0
  544. package/dist/tools/todo.d.ts.map +1 -0
  545. package/dist/tools/todo.js +153 -0
  546. package/dist/tools/todo.js.map +1 -0
  547. package/dist/tools/web.d.ts +13 -0
  548. package/dist/tools/web.d.ts.map +1 -0
  549. package/dist/tools/web.js +377 -0
  550. package/dist/tools/web.js.map +1 -0
  551. package/dist/ui/box.d.ts +56 -0
  552. package/dist/ui/box.d.ts.map +1 -0
  553. package/dist/ui/box.js +241 -0
  554. package/dist/ui/box.js.map +1 -0
  555. package/dist/ui/command-panel.d.ts +55 -0
  556. package/dist/ui/command-panel.d.ts.map +1 -0
  557. package/dist/ui/command-panel.js +212 -0
  558. package/dist/ui/command-panel.js.map +1 -0
  559. package/dist/ui/file-completion.d.ts +62 -0
  560. package/dist/ui/file-completion.d.ts.map +1 -0
  561. package/dist/ui/file-completion.js +209 -0
  562. package/dist/ui/file-completion.js.map +1 -0
  563. package/dist/ui/markdown.d.ts +12 -0
  564. package/dist/ui/markdown.d.ts.map +1 -0
  565. package/dist/ui/markdown.js +215 -0
  566. package/dist/ui/markdown.js.map +1 -0
  567. package/dist/ui/multiline-input.d.ts +47 -0
  568. package/dist/ui/multiline-input.d.ts.map +1 -0
  569. package/dist/ui/multiline-input.js +94 -0
  570. package/dist/ui/multiline-input.js.map +1 -0
  571. package/dist/ui/status-bar.d.ts +33 -0
  572. package/dist/ui/status-bar.d.ts.map +1 -0
  573. package/dist/ui/status-bar.js +96 -0
  574. package/dist/ui/status-bar.js.map +1 -0
  575. package/dist/ui/stream-markdown.d.ts +35 -0
  576. package/dist/ui/stream-markdown.d.ts.map +1 -0
  577. package/dist/ui/stream-markdown.js +138 -0
  578. package/dist/ui/stream-markdown.js.map +1 -0
  579. package/dist/ui/suggestions.d.ts +35 -0
  580. package/dist/ui/suggestions.d.ts.map +1 -0
  581. package/dist/ui/suggestions.js +118 -0
  582. package/dist/ui/suggestions.js.map +1 -0
  583. package/dist/ui/tool-preview.d.ts +34 -0
  584. package/dist/ui/tool-preview.d.ts.map +1 -0
  585. package/dist/ui/tool-preview.js +128 -0
  586. package/dist/ui/tool-preview.js.map +1 -0
  587. package/package.json +93 -0
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ /**
3
+ * openhorse - Plan Mode Tools
4
+ *
5
+ * enter_plan_mode: Enter planning mode for complex tasks
6
+ * exit_plan_mode: Exit planning mode with a plan
7
+ *
8
+ * State is held in the shared tool-state module so the CLI can mirror it
9
+ * into the main Store.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.PLAN_TOOLS = exports.exitPlanModeTool = exports.enterPlanModeTool = void 0;
13
+ exports.isInPlanMode = isInPlanMode;
14
+ exports.getCurrentPlan = getCurrentPlan;
15
+ const tool_1 = require("../framework/tool");
16
+ const tool_state_1 = require("../framework/tool-state");
17
+ exports.enterPlanModeTool = (0, tool_1.buildTool)({
18
+ name: 'enter_plan_mode',
19
+ description: `Enter plan mode for complex tasks requiring exploration and planning.
20
+ In plan mode, you should explore the project structure, understand the problem,
21
+ and create a detailed implementation plan WITHOUT executing any code changes.
22
+ Use this when the task is complex, ambiguous, or requires careful consideration.`,
23
+ parameters: {
24
+ type: 'object',
25
+ properties: {},
26
+ },
27
+ execute: async () => {
28
+ (0, tool_state_1.setToolState)({ planMode: true, currentPlan: null });
29
+ return {
30
+ success: true,
31
+ output: 'Entered plan mode. Explore the project, understand the problem, and create a plan. Use exit_plan_mode when ready with your plan.',
32
+ };
33
+ },
34
+ isReadOnly: () => true,
35
+ isConcurrencySafe: () => true,
36
+ checkPermissions: () => ({ behavior: 'allow', reason: 'Safe mode change' }),
37
+ userFacingName: () => 'Enter plan mode',
38
+ });
39
+ exports.exitPlanModeTool = (0, tool_1.buildTool)({
40
+ name: 'exit_plan_mode',
41
+ description: `Exit plan mode and save the implementation plan.
42
+ This tool finalizes the plan and returns to execution mode.`,
43
+ parameters: {
44
+ type: 'object',
45
+ properties: {
46
+ plan: {
47
+ type: 'string',
48
+ description: 'The detailed implementation plan',
49
+ },
50
+ },
51
+ required: ['plan'],
52
+ },
53
+ execute: async (args) => {
54
+ const plan = args.plan;
55
+ (0, tool_state_1.setToolState)({ planMode: false, currentPlan: plan });
56
+ return {
57
+ success: true,
58
+ output: `Exited plan mode. Plan saved:\n\n${plan}`,
59
+ };
60
+ },
61
+ isReadOnly: () => false,
62
+ isConcurrencySafe: () => true,
63
+ checkPermissions: () => ({ behavior: 'allow', reason: 'Safe mode change' }),
64
+ userFacingName: () => 'Exit plan mode',
65
+ });
66
+ /** Check if currently in plan mode */
67
+ function isInPlanMode() {
68
+ return (0, tool_state_1.getToolState)().planMode;
69
+ }
70
+ /** Get current plan */
71
+ function getCurrentPlan() {
72
+ return (0, tool_state_1.getToolState)().currentPlan ?? '';
73
+ }
74
+ exports.PLAN_TOOLS = [exports.enterPlanModeTool, exports.exitPlanModeTool];
75
+ //# sourceMappingURL=plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/tools/plan.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAyDH,oCAEC;AAGD,wCAEC;AA9DD,4CAAkE;AAClE,wDAAqE;AAExD,QAAA,iBAAiB,GAAkB,IAAA,gBAAS,EAAC;IACxD,IAAI,EAAE,iBAAiB;IACvB,WAAW,EAAE;;;iFAGkE;IAC/E,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,EAAE;KACf;IACD,OAAO,EAAE,KAAK,IAAI,EAAE;QAClB,IAAA,yBAAY,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,OAAO;YACL,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,kIAAkI;SAC3I,CAAC;IACJ,CAAC;IACD,UAAU,EAAE,GAAG,EAAE,CAAC,IAAI;IACtB,iBAAiB,EAAE,GAAG,EAAE,CAAC,IAAI;IAC7B,gBAAgB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC3E,cAAc,EAAE,GAAG,EAAE,CAAC,iBAAiB;CACxC,CAAC,CAAC;AAEU,QAAA,gBAAgB,GAAkB,IAAA,gBAAS,EAAC;IACvD,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE;4DAC6C;IAC1D,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,IAAI,EAAE;gBACJ,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,kCAAkC;aAChD;SACF;QACD,QAAQ,EAAE,CAAC,MAAM,CAAC;KACnB;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACtB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAc,CAAC;QACjC,IAAA,yBAAY,EAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,OAAO;YACL,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,oCAAoC,IAAI,EAAE;SACnD,CAAC;IACJ,CAAC;IACD,UAAU,EAAE,GAAG,EAAE,CAAC,KAAK;IACvB,iBAAiB,EAAE,GAAG,EAAE,CAAC,IAAI;IAC7B,gBAAgB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC3E,cAAc,EAAE,GAAG,EAAE,CAAC,gBAAgB;CACvC,CAAC,CAAC;AAEH,sCAAsC;AACtC,SAAgB,YAAY;IAC1B,OAAO,IAAA,yBAAY,GAAE,CAAC,QAAQ,CAAC;AACjC,CAAC;AAED,uBAAuB;AACvB,SAAgB,cAAc;IAC5B,OAAO,IAAA,yBAAY,GAAE,CAAC,WAAW,IAAI,EAAE,CAAC;AAC1C,CAAC;AAEY,QAAA,UAAU,GAAoB,CAAC,yBAAiB,EAAE,wBAAgB,CAAC,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * openhorse - TodoWrite Tool
3
+ *
4
+ * Manage task progress during coding sessions.
5
+ *
6
+ * State is held in the shared tool-state module so the CLI can mirror it
7
+ * into the main Store and render it in the UI.
8
+ */
9
+ import { type OpenHorseTool } from '../framework/tool';
10
+ import { type TodoItem } from '../framework/tool-state';
11
+ export declare const todoWriteTool: OpenHorseTool;
12
+ /** Get current todos (for UI display) */
13
+ export declare function getCurrentTodos(): TodoItem[];
14
+ /** Format todos for display */
15
+ export declare function formatTodosForDisplay(todos: TodoItem[]): string;
16
+ export type { TodoItem };
17
+ export declare const TODO_TOOLS: OpenHorseTool[];
18
+ //# sourceMappingURL=todo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"todo.d.ts","sourceRoot":"","sources":["../../src/tools/todo.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAa,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAA8B,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AA4CpF,eAAO,MAAM,aAAa,EAAE,aAmF1B,CAAC;AAEH,yCAAyC;AACzC,wBAAgB,eAAe,IAAI,QAAQ,EAAE,CAE5C;AAED,+BAA+B;AAC/B,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,CAc/D;AAED,YAAY,EAAE,QAAQ,EAAE,CAAC;AACzB,eAAO,MAAM,UAAU,EAAE,aAAa,EAAoB,CAAC"}
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ /**
3
+ * openhorse - TodoWrite Tool
4
+ *
5
+ * Manage task progress during coding sessions.
6
+ *
7
+ * State is held in the shared tool-state module so the CLI can mirror it
8
+ * into the main Store and render it in the UI.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.TODO_TOOLS = exports.todoWriteTool = void 0;
12
+ exports.getCurrentTodos = getCurrentTodos;
13
+ exports.formatTodosForDisplay = formatTodosForDisplay;
14
+ const tool_1 = require("../framework/tool");
15
+ const tool_state_1 = require("../framework/tool-state");
16
+ // ============================================================================
17
+ // TodoWrite Tool
18
+ // ============================================================================
19
+ const TODO_PROMPT = `Use this tool to create and manage a structured task list for your current coding session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user.
20
+
21
+ ## When to Use This Tool
22
+
23
+ 1. Complex multi-step tasks - When a task requires 3 or more distinct steps
24
+ 2. Non-trivial tasks - Tasks that require careful planning or multiple operations
25
+ 3. User explicitly requests todo list
26
+ 4. User provides multiple tasks (numbered or comma-separated)
27
+ 5. After receiving new instructions - Immediately capture user requirements
28
+ 6. When you start working on a task - Mark it as in_progress BEFORE beginning
29
+ 7. After completing a task - Mark it completed immediately
30
+
31
+ ## When NOT to Use
32
+
33
+ 1. Single, straightforward task
34
+ 2. Trivial task with no organizational benefit
35
+ 3. Purely conversational or informational
36
+
37
+ ## Task States
38
+
39
+ - pending: Task not yet started
40
+ - in_progress: Currently working on (limit to ONE task at a time)
41
+ - completed: Task finished successfully
42
+
43
+ ## Task Format
44
+
45
+ Each todo must have:
46
+ - content: Imperative form ("Run tests")
47
+ - activeForm: Present continuous form ("Running tests")
48
+ - status: pending | in_progress | completed
49
+
50
+ ## Rules
51
+
52
+ - Exactly ONE task should be in_progress at any time
53
+ - Mark tasks complete IMMEDIATELY after finishing
54
+ - Remove tasks that are no longer relevant
55
+ - Only mark completed when FULLY accomplished`;
56
+ exports.todoWriteTool = (0, tool_1.buildTool)({
57
+ name: 'todo_write',
58
+ description: `Update the todo list for the current session.
59
+
60
+ ${TODO_PROMPT}`,
61
+ parameters: {
62
+ type: 'object',
63
+ properties: {
64
+ todos: {
65
+ type: 'string',
66
+ description: 'JSON array of todos: [{"content":"Task","status":"pending|in_progress|completed","activeForm":"Doing task"}]',
67
+ },
68
+ },
69
+ required: ['todos'],
70
+ },
71
+ execute: async (args) => {
72
+ let todos;
73
+ try {
74
+ todos = JSON.parse(args.todos);
75
+ }
76
+ catch {
77
+ return { success: false, output: '', error: 'todos must be valid JSON array' };
78
+ }
79
+ if (!Array.isArray(todos)) {
80
+ return { success: false, output: '', error: 'todos must be an array' };
81
+ }
82
+ for (const todo of todos) {
83
+ if (!todo.content || typeof todo.content !== 'string') {
84
+ return { success: false, output: '', error: 'Each todo must have a content string' };
85
+ }
86
+ if (!todo.activeForm || typeof todo.activeForm !== 'string') {
87
+ return { success: false, output: '', error: 'Each todo must have an activeForm string' };
88
+ }
89
+ if (!['pending', 'in_progress', 'completed'].includes(todo.status)) {
90
+ return { success: false, output: '', error: `Invalid status: ${todo.status}` };
91
+ }
92
+ }
93
+ const inProgressCount = todos.filter(t => t.status === 'in_progress').length;
94
+ if (inProgressCount > 1) {
95
+ return {
96
+ success: false,
97
+ output: '',
98
+ error: 'Only one task can be in_progress at a time',
99
+ };
100
+ }
101
+ (0, tool_state_1.setToolState)({ todos });
102
+ const lines = [];
103
+ lines.push('Todo list updated:');
104
+ lines.push('');
105
+ for (let i = 0; i < todos.length; i++) {
106
+ const todo = todos[i];
107
+ const icon = todo.status === 'completed' ? '✅' : todo.status === 'in_progress' ? '⏳' : '⬚';
108
+ lines.push(`${i + 1}. [${icon}] ${todo.content}`);
109
+ if (todo.status === 'in_progress') {
110
+ lines.push(` → ${todo.activeForm}`);
111
+ }
112
+ }
113
+ lines.push('');
114
+ lines.push(`Summary: ${todos.length} tasks, ${todos.filter(t => t.status === 'completed').length} completed, ${inProgressCount} in progress`);
115
+ return {
116
+ success: true,
117
+ output: lines.join('\n'),
118
+ };
119
+ },
120
+ isReadOnly: () => false,
121
+ checkPermissions: () => {
122
+ return { behavior: 'allow', reason: 'Todo operations are safe' };
123
+ },
124
+ userFacingName: (args) => {
125
+ try {
126
+ const todos = JSON.parse(args.todos);
127
+ return `Update ${todos.length} todos`;
128
+ }
129
+ catch {
130
+ return 'Update todos';
131
+ }
132
+ },
133
+ });
134
+ /** Get current todos (for UI display) */
135
+ function getCurrentTodos() {
136
+ return (0, tool_state_1.getToolState)().todos;
137
+ }
138
+ /** Format todos for display */
139
+ function formatTodosForDisplay(todos) {
140
+ if (todos.length === 0)
141
+ return 'No active tasks';
142
+ const lines = [];
143
+ lines.push('Tasks:');
144
+ lines.push('');
145
+ for (let i = 0; i < todos.length; i++) {
146
+ const todo = todos[i];
147
+ const icon = todo.status === 'completed' ? '✅' : todo.status === 'in_progress' ? '⏳' : '⬚';
148
+ lines.push(`${i + 1}. [${icon}] ${todo.status === 'in_progress' ? todo.activeForm : todo.content}`);
149
+ }
150
+ return lines.join('\n');
151
+ }
152
+ exports.TODO_TOOLS = [exports.todoWriteTool];
153
+ //# sourceMappingURL=todo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"todo.js","sourceRoot":"","sources":["../../src/tools/todo.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * openhorse - Web Tools
3
+ *
4
+ * WebFetch: Fetch URL content and process with prompt
5
+ * WebSearch: Search the web for information
6
+ */
7
+ import { type OpenHorseTool } from '../framework/tool';
8
+ /** Clear the fetch cache (test helper / debugging) */
9
+ export declare function clearWebFetchCache(): void;
10
+ export declare const webFetchTool: OpenHorseTool;
11
+ export declare const webSearchTool: OpenHorseTool;
12
+ export declare const WEB_TOOLS: OpenHorseTool[];
13
+ //# sourceMappingURL=web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/tools/web.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAa,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAiLlE,sDAAsD;AACtD,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AA0BD,eAAO,MAAM,YAAY,EAAE,aA4EzB,CAAC;AAiFH,eAAO,MAAM,aAAa,EAAE,aAqD1B,CAAC;AAMH,eAAO,MAAM,SAAS,EAAE,aAAa,EAAkC,CAAC"}
@@ -0,0 +1,377 @@
1
+ "use strict";
2
+ /**
3
+ * openhorse - Web Tools
4
+ *
5
+ * WebFetch: Fetch URL content and process with prompt
6
+ * WebSearch: Search the web for information
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.WEB_TOOLS = exports.webSearchTool = exports.webFetchTool = void 0;
10
+ exports.clearWebFetchCache = clearWebFetchCache;
11
+ const tool_1 = require("../framework/tool");
12
+ // ============================================================================
13
+ // WebFetch Tool
14
+ // ============================================================================
15
+ /** Preapproved hosts that don't need permission */
16
+ const PREAPPROVED_HOSTS = [
17
+ 'github.com',
18
+ 'docs.google.com',
19
+ 'stackoverflow.com',
20
+ 'npmjs.com',
21
+ 'nodejs.org',
22
+ 'typescriptlang.org',
23
+ 'reactjs.org',
24
+ 'vuejs.org',
25
+ 'python.org',
26
+ 'golang.org',
27
+ 'rust-lang.org',
28
+ 'mdn.mozilla.org',
29
+ 'developer.mozilla.org',
30
+ 'wikipedia.org',
31
+ 'arxiv.org',
32
+ ];
33
+ const MAX_MARKDOWN_LENGTH = 100000;
34
+ const FETCH_CACHE_TTL_MS = 15 * 60 * 1000;
35
+ const FETCH_CACHE_MAX_ENTRIES = 50;
36
+ const fetchCache = new Map();
37
+ function cacheGet(url) {
38
+ const entry = fetchCache.get(url);
39
+ if (!entry)
40
+ return null;
41
+ if (Date.now() - entry.ts > FETCH_CACHE_TTL_MS) {
42
+ fetchCache.delete(url);
43
+ return null;
44
+ }
45
+ return entry.data;
46
+ }
47
+ function cacheSet(url, data) {
48
+ // Cap size — drop oldest entry when full
49
+ if (fetchCache.size >= FETCH_CACHE_MAX_ENTRIES) {
50
+ const oldest = fetchCache.keys().next().value;
51
+ if (oldest)
52
+ fetchCache.delete(oldest);
53
+ }
54
+ fetchCache.set(url, { ts: Date.now(), data });
55
+ }
56
+ function isPreapprovedHost(hostname, pathname) {
57
+ return PREAPPROVED_HOSTS.some(host => hostname === host || hostname.endsWith('.' + host));
58
+ }
59
+ /** Simple HTML to Markdown converter */
60
+ function htmlToMarkdown(html) {
61
+ let md = html;
62
+ // Remove script, style, nav, header, footer tags
63
+ md = md.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '');
64
+ md = md.replace(/<style[^>]*>[\s\S]*?<\/style>/gi, '');
65
+ md = md.replace(/<nav[^>]*>[\s\S]*?<\/nav>/gi, '');
66
+ md = md.replace(/<header[^>]*>[\s\S]*?<\/header>/gi, '');
67
+ md = md.replace(/<footer[^>]*>[\s\S]*?<\/footer>/gi, '');
68
+ // Convert headings
69
+ md = md.replace(/<h1[^>]*>([\s\S]*?)<\/h1>/gi, '# $1\n\n');
70
+ md = md.replace(/<h2[^>]*>([\s\S]*?)<\/h2>/gi, '## $1\n\n');
71
+ md = md.replace(/<h3[^>]*>([\s\S]*?)<\/h3>/gi, '### $1\n\n');
72
+ md = md.replace(/<h4[^>]*>([\s\S]*?)<\/h4>/gi, '#### $1\n\n');
73
+ md = md.replace(/<h5[^>]*>([\s\S]*?)<\/h5>/gi, '##### $1\n\n');
74
+ md = md.replace(/<h6[^>]*>([\s\S]*?)<\/h6>/gi, '###### $1\n\n');
75
+ // Bold and italic
76
+ md = md.replace(/<strong[^>]*>([\s\S]*?)<\/strong>/gi, '**$1**');
77
+ md = md.replace(/<b[^>]*>([\s\S]*?)<\/b>/gi, '**$1**');
78
+ md = md.replace(/<em[^>]*>([\s\S]*?)<\/em>/gi, '*$1*');
79
+ md = md.replace(/<i[^>]*>([\s\S]*?)<\/i>/gi, '*$1*');
80
+ // Links
81
+ md = md.replace(/<a[^>]*href="([^"]*)"[^>]*>([\s\S]*?)<\/a>/gi, '[$2]($1)');
82
+ // Code blocks
83
+ md = md.replace(/<pre[^>]*><code[^>]*>([\s\S]*?)<\/code><\/pre>/gi, '\n```\n$1\n```\n');
84
+ md = md.replace(/<code[^>]*>([\s\S]*?)<\/code>/gi, '`$1`');
85
+ // Lists
86
+ md = md.replace(/<li[^>]*>([\s\S]*?)<\/li>/gi, '- $1\n');
87
+ md = md.replace(/<ul[^>]*>([\s\S]*?)<\/ul>/gi, '$1');
88
+ md = md.replace(/<ol[^>]*>([\s\S]*?)<\/ol>/gi, '$1');
89
+ // Paragraphs and divs
90
+ md = md.replace(/<p[^>]*>([\s\S]*?)<\/p>/gi, '$1\n\n');
91
+ md = md.replace(/<div[^>]*>([\s\S]*?)<\/div>/gi, '$1\n');
92
+ md = md.replace(/<br\s*\/?>/gi, '\n');
93
+ // Remove remaining tags
94
+ md = md.replace(/<[^>]+>/g, '');
95
+ // Clean up whitespace
96
+ md = md.replace(/\n{3,}/g, '\n\n');
97
+ md = md.trim();
98
+ return md;
99
+ }
100
+ async function fetchUrl(url) {
101
+ const cached = cacheGet(url);
102
+ if (cached)
103
+ return cached;
104
+ try {
105
+ const response = await fetch(url, {
106
+ headers: {
107
+ 'User-Agent': 'OpenHorse/0.1.4',
108
+ 'Accept': 'text/html,application/xhtml+xml,text/markdown,text/plain,*/*',
109
+ },
110
+ });
111
+ const contentType = response.headers.get('content-type') || 'text/plain';
112
+ if (!response.ok) {
113
+ return {
114
+ content: `HTTP Error ${response.status}: ${response.statusText}`,
115
+ code: response.status,
116
+ contentType,
117
+ };
118
+ }
119
+ // Check for redirect to different host
120
+ if (response.redirected) {
121
+ const redirectUrl = response.url;
122
+ const originalHost = new URL(url).hostname;
123
+ const redirectHost = new URL(redirectUrl).hostname;
124
+ if (originalHost !== redirectHost) {
125
+ return {
126
+ content: `REDIRECT DETECTED: URL redirects to a different host.\nOriginal: ${url}\nRedirect: ${redirectUrl}\nPlease fetch the redirect URL instead.`,
127
+ code: 302,
128
+ contentType: 'text/plain',
129
+ };
130
+ }
131
+ }
132
+ const text = await response.text();
133
+ // Convert to markdown if HTML
134
+ let content = text;
135
+ if (contentType.includes('text/html')) {
136
+ content = htmlToMarkdown(text);
137
+ }
138
+ // Truncate if too large
139
+ if (content.length > MAX_MARKDOWN_LENGTH) {
140
+ content = content.slice(0, MAX_MARKDOWN_LENGTH) + '\n\n[... content truncated]';
141
+ }
142
+ const result = {
143
+ content,
144
+ code: response.status,
145
+ contentType,
146
+ };
147
+ if (response.ok)
148
+ cacheSet(url, result);
149
+ return result;
150
+ }
151
+ catch (err) {
152
+ return {
153
+ content: `Fetch error: ${err.message}`,
154
+ code: 0,
155
+ contentType: 'text/plain',
156
+ };
157
+ }
158
+ }
159
+ /** Clear the fetch cache (test helper / debugging) */
160
+ function clearWebFetchCache() {
161
+ fetchCache.clear();
162
+ }
163
+ /** Apply prompt to content using simple extraction */
164
+ function applyPromptToContent(content, prompt) {
165
+ // For simple prompts, return the content directly
166
+ const lowerPrompt = prompt.toLowerCase();
167
+ if (lowerPrompt.includes('title') || lowerPrompt.includes('name')) {
168
+ // Try to extract title
169
+ const titleMatch = content.match(/^#\s+(.+)$/m);
170
+ if (titleMatch) {
171
+ return `Title: ${titleMatch[1]}\n\n${content}`;
172
+ }
173
+ }
174
+ if (lowerPrompt.includes('summary') || lowerPrompt.includes('summarize')) {
175
+ // Return first few paragraphs as summary
176
+ const paragraphs = content.split('\n\n').filter(p => p.length > 50);
177
+ const summary = paragraphs.slice(0, 3).join('\n\n');
178
+ return `Summary:\n${summary}\n\n---\n\nFull content:\n${content}`;
179
+ }
180
+ // Default: return content with prompt context
181
+ return `Prompt: "${prompt}"\n\nContent:\n${content}`;
182
+ }
183
+ exports.webFetchTool = (0, tool_1.buildTool)({
184
+ name: 'web_fetch',
185
+ description: `Fetch content from a URL and process with a prompt.
186
+ IMPORTANT: WebFetch WILL FAIL for authenticated or private URLs.
187
+ Before using this tool, check if the URL points to an authenticated service (e.g. Google Docs, Confluence, Jira, GitHub).`,
188
+ parameters: {
189
+ type: 'object',
190
+ properties: {
191
+ url: {
192
+ type: 'string',
193
+ description: 'The URL to fetch content from (must be a valid URL)',
194
+ },
195
+ prompt: {
196
+ type: 'string',
197
+ description: 'The prompt to run on the fetched content (e.g. "extract the title", "summarize the content")',
198
+ },
199
+ },
200
+ required: ['url', 'prompt'],
201
+ },
202
+ execute: async (args) => {
203
+ const url = args.url;
204
+ const prompt = args.prompt;
205
+ if (!url || typeof url !== 'string') {
206
+ return { success: false, output: '', error: 'web_fetch requires a url parameter' };
207
+ }
208
+ if (!prompt || typeof prompt !== 'string') {
209
+ return { success: false, output: '', error: 'web_fetch requires a prompt parameter' };
210
+ }
211
+ // Validate URL
212
+ try {
213
+ const parsed = new URL(url);
214
+ if (!parsed.protocol.startsWith('http')) {
215
+ return { success: false, output: '', error: 'URL must use http or https protocol' };
216
+ }
217
+ }
218
+ catch {
219
+ return { success: false, output: '', error: `Invalid URL: ${url}` };
220
+ }
221
+ const { content, code, contentType } = await fetchUrl(url);
222
+ if (code !== 200) {
223
+ return { success: false, output: content, error: `HTTP ${code}` };
224
+ }
225
+ const result = applyPromptToContent(content, prompt);
226
+ return {
227
+ success: true,
228
+ output: result,
229
+ };
230
+ },
231
+ isReadOnly: () => true,
232
+ isConcurrencySafe: () => true,
233
+ checkPermissions: (args) => {
234
+ const url = args.url;
235
+ try {
236
+ const parsed = new URL(url);
237
+ if (isPreapprovedHost(parsed.hostname, parsed.pathname)) {
238
+ return { behavior: 'allow', reason: 'Preapproved host' };
239
+ }
240
+ }
241
+ catch {
242
+ // Invalid URL - will fail in execute
243
+ }
244
+ return { behavior: 'ask', reason: 'Fetching external URL' };
245
+ },
246
+ userFacingName: (args) => {
247
+ try {
248
+ const url = new URL(args.url);
249
+ return `Fetch ${url.hostname}`;
250
+ }
251
+ catch {
252
+ return `Fetch ${args.url}`;
253
+ }
254
+ },
255
+ });
256
+ // ============================================================================
257
+ // WebSearch Tool
258
+ // ============================================================================
259
+ /** DuckDuckGo search (free, no API key required) */
260
+ async function duckDuckGoSearch(query, limit) {
261
+ try {
262
+ const searchUrl = `https://duckduckgo.com/html/?q=${encodeURIComponent(query)}`;
263
+ const response = await fetch(searchUrl, {
264
+ headers: {
265
+ 'User-Agent': 'Mozilla/5.0 (compatible; OpenHorse/0.1.4)',
266
+ },
267
+ });
268
+ if (!response.ok) {
269
+ throw new Error(`Search failed: HTTP ${response.status}`);
270
+ }
271
+ const html = await response.text();
272
+ const results = [];
273
+ // Parse search results from HTML
274
+ const resultRegex = /<a[^>]*class="result__a"[^>]*href="([^"]*)"[^>]*>([^<]*)<\/a>/g;
275
+ let match;
276
+ let count = 0;
277
+ while ((match = resultRegex.exec(html)) !== null && count < limit) {
278
+ const url = match[1];
279
+ const title = match[2].trim();
280
+ // DuckDuckGo redirects through their URL - extract actual URL
281
+ let actualUrl = url;
282
+ const uddgMatch = url.match(/uddg=([^&]+)/);
283
+ if (uddgMatch) {
284
+ actualUrl = decodeURIComponent(uddgMatch[1]);
285
+ }
286
+ results.push({
287
+ title,
288
+ url: actualUrl,
289
+ description: '',
290
+ });
291
+ count++;
292
+ }
293
+ return results;
294
+ }
295
+ catch (err) {
296
+ throw new Error(`DuckDuckGo search error: ${err.message}`);
297
+ }
298
+ }
299
+ /** Format search results */
300
+ function formatSearchResults(results, query) {
301
+ if (results.length === 0) {
302
+ return `No results found for query: "${query}"`;
303
+ }
304
+ const lines = [];
305
+ lines.push(`Search results for "${query}":`);
306
+ lines.push('');
307
+ for (let i = 0; i < results.length; i++) {
308
+ const r = results[i];
309
+ lines.push(`${i + 1}. **${r.title}**`);
310
+ lines.push(` URL: ${r.url}`);
311
+ if (r.description) {
312
+ lines.push(` ${r.description}`);
313
+ }
314
+ lines.push('');
315
+ }
316
+ lines.push('Sources:');
317
+ for (const r of results) {
318
+ lines.push(`- [${r.title}](${r.url})`);
319
+ }
320
+ return lines.join('\n');
321
+ }
322
+ exports.webSearchTool = (0, tool_1.buildTool)({
323
+ name: 'web_search',
324
+ description: `Search the web for information using DuckDuckGo.
325
+ Returns search results with titles, URLs, and descriptions.
326
+ You MUST include the Sources section with markdown hyperlinks in your response.`,
327
+ parameters: {
328
+ type: 'object',
329
+ properties: {
330
+ query: {
331
+ type: 'string',
332
+ description: 'The search query (minimum 2 characters)',
333
+ },
334
+ limit: {
335
+ type: 'number',
336
+ description: 'Maximum number of results (optional, default 5)',
337
+ },
338
+ },
339
+ required: ['query'],
340
+ },
341
+ execute: async (args) => {
342
+ const query = args.query;
343
+ const limit = args.limit || 5;
344
+ if (!query || typeof query !== 'string') {
345
+ return { success: false, output: '', error: 'web_search requires a query parameter' };
346
+ }
347
+ if (query.length < 2) {
348
+ return { success: false, output: '', error: 'Query must be at least 2 characters' };
349
+ }
350
+ try {
351
+ const results = await duckDuckGoSearch(query, limit);
352
+ const output = formatSearchResults(results, query);
353
+ return {
354
+ success: true,
355
+ output,
356
+ };
357
+ }
358
+ catch (err) {
359
+ return {
360
+ success: false,
361
+ output: '',
362
+ error: err.message,
363
+ };
364
+ }
365
+ },
366
+ isReadOnly: () => true,
367
+ isConcurrencySafe: () => true,
368
+ checkPermissions: () => {
369
+ return { behavior: 'ask', reason: 'Web search may query external services' };
370
+ },
371
+ userFacingName: (args) => `Search "${args.query?.slice(0, 30)}"`,
372
+ });
373
+ // ============================================================================
374
+ // Export
375
+ // ============================================================================
376
+ exports.WEB_TOOLS = [exports.webFetchTool, exports.webSearchTool];
377
+ //# sourceMappingURL=web.js.map