explorbot 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (423) hide show
  1. package/README.md +80 -26
  2. package/bin/explorbot-cli.ts +680 -0
  3. package/boat/api-tester/src/ai/chief/styles.ts +15 -0
  4. package/boat/api-tester/src/ai/chief.ts +335 -0
  5. package/boat/api-tester/src/ai/curler-tools.ts +278 -0
  6. package/boat/api-tester/src/ai/curler.ts +306 -0
  7. package/boat/api-tester/src/api-client.ts +28 -0
  8. package/boat/api-tester/src/apibot.ts +203 -0
  9. package/boat/api-tester/src/cli.ts +301 -0
  10. package/boat/api-tester/src/config.ts +190 -0
  11. package/dist/bin/explorbot-cli.js +23 -101
  12. package/dist/boat/api-tester/bin/apibot-cli.js +0 -1
  13. package/dist/boat/api-tester/src/ai/chief/styles.js +0 -1
  14. package/dist/boat/api-tester/src/ai/chief.js +0 -1
  15. package/dist/boat/api-tester/src/ai/curler-tools.js +0 -1
  16. package/dist/boat/api-tester/src/ai/curler.js +0 -1
  17. package/dist/boat/api-tester/src/api-client.js +0 -1
  18. package/dist/boat/api-tester/src/apibot.js +0 -1
  19. package/dist/boat/api-tester/src/cli.js +0 -1
  20. package/dist/boat/api-tester/src/config.js +0 -1
  21. package/dist/src/action-result.js +0 -1
  22. package/dist/src/action.js +14 -12
  23. package/dist/src/activity.js +0 -1
  24. package/dist/src/ai/agent.js +0 -1
  25. package/dist/src/ai/bosun.js +0 -1
  26. package/dist/src/ai/captain/idle-mode.js +0 -1
  27. package/dist/src/ai/captain/mixin.js +0 -1
  28. package/dist/src/ai/captain/test-mode.js +0 -1
  29. package/dist/src/ai/captain/web-mode.js +0 -1
  30. package/dist/src/ai/captain.js +0 -1
  31. package/dist/src/ai/conversation.js +0 -1
  32. package/dist/src/ai/experience-compactor.js +0 -1
  33. package/dist/src/ai/fisherman-tools.js +0 -1
  34. package/dist/src/ai/fisherman.js +0 -1
  35. package/dist/src/ai/historian.js +0 -1
  36. package/dist/src/ai/navigator.js +0 -1
  37. package/dist/src/ai/pilot.js +0 -1
  38. package/dist/src/ai/planner/session-dedup.js +0 -1
  39. package/dist/src/ai/planner/styles.js +0 -1
  40. package/dist/src/ai/planner/subpages.js +42 -7
  41. package/dist/src/ai/planner.js +15 -4
  42. package/dist/src/ai/provider.js +0 -1
  43. package/dist/src/ai/quartermaster.js +0 -1
  44. package/dist/src/ai/researcher/cache.js +13 -9
  45. package/dist/src/ai/researcher/coordinates.js +4 -3
  46. package/dist/src/ai/researcher/deep-analysis.js +16 -20
  47. package/dist/src/ai/researcher/fingerprint-worker.js +0 -1
  48. package/dist/src/ai/researcher/focus.js +0 -1
  49. package/dist/src/ai/researcher/locators.js +1 -2
  50. package/dist/src/ai/researcher/mixin.js +0 -1
  51. package/dist/src/ai/researcher/parser.js +4 -4
  52. package/dist/src/ai/researcher/research-result.js +2 -1
  53. package/dist/src/ai/researcher.js +6 -6
  54. package/dist/src/ai/rules.js +0 -1
  55. package/dist/src/ai/task-agent.js +0 -1
  56. package/dist/src/ai/tester.js +0 -1
  57. package/dist/src/ai/tools.js +4 -1
  58. package/dist/src/api/api-client.js +0 -1
  59. package/dist/src/api/request-result.js +0 -1
  60. package/dist/src/api/request-store.js +0 -1
  61. package/dist/src/api/spec-reader.js +0 -1
  62. package/dist/src/api/xhr-capture.js +0 -1
  63. package/dist/src/browser-server.js +0 -1
  64. package/dist/src/command-handler.js +0 -1
  65. package/dist/src/commands/add-rule-command.js +0 -1
  66. package/dist/src/commands/base-command.js +0 -1
  67. package/dist/src/commands/clean-command.js +0 -1
  68. package/dist/src/commands/context-aria-command.js +0 -1
  69. package/dist/src/commands/context-command.js +2 -3
  70. package/dist/src/commands/context-data-command.js +0 -1
  71. package/dist/src/commands/context-experience-command.js +0 -1
  72. package/dist/src/commands/context-html-command.js +0 -1
  73. package/dist/src/commands/context-knowledge-command.js +0 -1
  74. package/dist/src/commands/debug-command.js +0 -1
  75. package/dist/src/commands/drill-command.js +0 -1
  76. package/dist/src/commands/exit-command.js +0 -1
  77. package/dist/src/commands/explore-command.js +3 -3
  78. package/dist/src/commands/freesail-command.js +0 -1
  79. package/dist/src/commands/help-command.js +0 -1
  80. package/dist/src/commands/index.js +0 -1
  81. package/dist/src/commands/init-command.js +117 -0
  82. package/dist/src/commands/knows-command.js +0 -1
  83. package/dist/src/commands/learn-command.js +0 -1
  84. package/dist/src/commands/navigate-command.js +0 -1
  85. package/dist/src/commands/path-command.js +0 -1
  86. package/dist/src/commands/plan-clear-command.js +0 -1
  87. package/dist/src/commands/plan-command.js +6 -2
  88. package/dist/src/commands/plan-edit-command.js +0 -1
  89. package/dist/src/commands/plan-load-command.js +0 -1
  90. package/dist/src/commands/plan-reload-command.js +0 -1
  91. package/dist/src/commands/plan-save-command.js +0 -1
  92. package/dist/src/commands/research-command.js +0 -1
  93. package/dist/src/commands/start-command.js +0 -1
  94. package/dist/src/commands/status-command.js +0 -1
  95. package/dist/src/commands/test-command.js +0 -1
  96. package/dist/src/components/ActivityPane.js +0 -1
  97. package/dist/src/components/AddKnowledge.js +0 -1
  98. package/dist/src/components/AddRule.js +0 -1
  99. package/dist/src/components/App.js +0 -1
  100. package/dist/src/components/Autocomplete.js +0 -1
  101. package/dist/src/components/InputPane.js +0 -1
  102. package/dist/src/components/InputReadline.js +0 -1
  103. package/dist/src/components/LogPane.js +0 -1
  104. package/dist/src/components/PlanEditor.js +0 -1
  105. package/dist/src/components/PlanPane.js +0 -1
  106. package/dist/src/components/SessionTimer.js +0 -1
  107. package/dist/src/components/StateTransitionPane.js +0 -1
  108. package/dist/src/components/StatusPane.js +0 -1
  109. package/dist/src/components/TaskPane.js +0 -1
  110. package/dist/src/components/Welcome.js +0 -1
  111. package/dist/src/components/WelcomeChecklist.js +0 -1
  112. package/dist/src/components/WelcomeCommands.js +0 -1
  113. package/dist/src/components/autocomplete-store.js +0 -1
  114. package/dist/src/components/parse-keypress.js +0 -1
  115. package/dist/src/config.js +0 -1
  116. package/dist/src/execution-controller.js +0 -1
  117. package/dist/src/experience-tracker.js +0 -1
  118. package/dist/src/explorbot.js +1 -2
  119. package/dist/src/explorer.js +58 -17
  120. package/dist/src/index.js +0 -1
  121. package/dist/src/knowledge-tracker.js +2 -2
  122. package/dist/src/observability.js +0 -1
  123. package/dist/src/reporter.js +0 -1
  124. package/dist/src/state-manager.js +0 -1
  125. package/dist/src/stats.js +0 -1
  126. package/dist/src/test-plan.js +0 -1
  127. package/dist/src/utils/aria.js +0 -1
  128. package/dist/src/utils/cli-name.js +16 -0
  129. package/dist/src/utils/code-extractor.js +0 -1
  130. package/dist/src/utils/context-formatter.js +0 -1
  131. package/dist/src/utils/error-page.js +0 -1
  132. package/dist/src/utils/expandable.js +0 -1
  133. package/dist/src/utils/hooks-runner.js +0 -1
  134. package/dist/src/utils/html-diff.js +0 -1
  135. package/dist/src/utils/html.js +0 -1
  136. package/dist/src/utils/logger.js +0 -1
  137. package/dist/src/utils/loop.js +0 -1
  138. package/dist/src/utils/markdown-parser.js +0 -1
  139. package/dist/src/utils/markdown-query.js +0 -1
  140. package/dist/src/utils/markdown-terminal.js +0 -1
  141. package/dist/src/utils/research-parser.js +0 -1
  142. package/dist/src/utils/retry.js +0 -1
  143. package/dist/src/utils/rules-loader.js +0 -1
  144. package/dist/src/utils/strings.js +0 -1
  145. package/dist/src/utils/test-plan-markdown.js +0 -1
  146. package/dist/src/utils/throttle.js +0 -1
  147. package/dist/src/utils/unique-names.js +0 -1
  148. package/dist/src/utils/url-matcher.js +0 -1
  149. package/dist/src/utils/web-element.js +6 -5
  150. package/dist/src/utils/xpath.js +0 -1
  151. package/package.json +28 -4
  152. package/src/action-result.ts +694 -0
  153. package/src/action.ts +449 -0
  154. package/src/activity.ts +111 -0
  155. package/src/ai/agent.ts +3 -0
  156. package/src/ai/bosun.ts +557 -0
  157. package/src/ai/captain/idle-mode.ts +116 -0
  158. package/src/ai/captain/mixin.ts +22 -0
  159. package/src/ai/captain/test-mode.ts +262 -0
  160. package/src/ai/captain/web-mode.ts +136 -0
  161. package/src/ai/captain.ts +504 -0
  162. package/src/ai/conversation.ts +205 -0
  163. package/src/ai/experience-compactor.ts +284 -0
  164. package/src/ai/fisherman-tools.ts +181 -0
  165. package/src/ai/fisherman.ts +223 -0
  166. package/src/ai/historian.ts +457 -0
  167. package/src/ai/navigator.ts +572 -0
  168. package/src/ai/pilot.ts +776 -0
  169. package/src/ai/planner/session-dedup.ts +35 -0
  170. package/src/ai/planner/styles.ts +17 -0
  171. package/src/ai/planner/subpages.ts +171 -0
  172. package/src/ai/planner.ts +549 -0
  173. package/src/ai/provider.ts +613 -0
  174. package/src/ai/quartermaster.ts +286 -0
  175. package/src/ai/researcher/cache.ts +109 -0
  176. package/src/ai/researcher/coordinates.ts +239 -0
  177. package/src/ai/researcher/deep-analysis.ts +412 -0
  178. package/src/ai/researcher/fingerprint-worker.ts +59 -0
  179. package/src/ai/researcher/focus.ts +42 -0
  180. package/src/ai/researcher/locators.ts +282 -0
  181. package/src/ai/researcher/mixin.ts +4 -0
  182. package/src/ai/researcher/parser.ts +186 -0
  183. package/src/ai/researcher/research-result.ts +116 -0
  184. package/src/ai/researcher.ts +858 -0
  185. package/src/ai/rules.ts +376 -0
  186. package/src/ai/task-agent.ts +141 -0
  187. package/src/ai/tester.ts +939 -0
  188. package/src/ai/tools.ts +1122 -0
  189. package/src/api/api-client.ts +109 -0
  190. package/src/api/request-result.ts +212 -0
  191. package/src/api/request-store.ts +130 -0
  192. package/src/api/spec-reader.ts +174 -0
  193. package/src/api/xhr-capture.ts +100 -0
  194. package/src/browser-server.ts +74 -0
  195. package/src/command-handler.ts +454 -0
  196. package/src/commands/add-rule-command.ts +63 -0
  197. package/src/commands/base-command.ts +27 -0
  198. package/src/commands/clean-command.ts +73 -0
  199. package/src/commands/context-aria-command.ts +22 -0
  200. package/src/commands/context-command.ts +67 -0
  201. package/src/commands/context-data-command.ts +30 -0
  202. package/src/commands/context-experience-command.ts +48 -0
  203. package/src/commands/context-html-command.ts +33 -0
  204. package/src/commands/context-knowledge-command.ts +43 -0
  205. package/src/commands/debug-command.ts +13 -0
  206. package/src/commands/drill-command.ts +34 -0
  207. package/src/commands/exit-command.ts +32 -0
  208. package/src/commands/explore-command.ts +129 -0
  209. package/src/commands/freesail-command.ts +95 -0
  210. package/src/commands/help-command.ts +8 -0
  211. package/src/commands/index.ts +69 -0
  212. package/src/commands/init-command.ts +131 -0
  213. package/src/commands/knows-command.ts +68 -0
  214. package/src/commands/learn-command.ts +44 -0
  215. package/src/commands/navigate-command.ts +18 -0
  216. package/src/commands/path-command.ts +83 -0
  217. package/src/commands/plan-clear-command.ts +14 -0
  218. package/src/commands/plan-command.ts +46 -0
  219. package/src/commands/plan-edit-command.ts +9 -0
  220. package/src/commands/plan-load-command.ts +18 -0
  221. package/src/commands/plan-reload-command.ts +28 -0
  222. package/src/commands/plan-save-command.ts +25 -0
  223. package/src/commands/research-command.ts +45 -0
  224. package/src/commands/start-command.ts +13 -0
  225. package/src/commands/status-command.tsx +23 -0
  226. package/src/commands/test-command.ts +84 -0
  227. package/src/components/ActivityPane.tsx +80 -0
  228. package/src/components/AddKnowledge.tsx +169 -0
  229. package/src/components/AddRule.tsx +174 -0
  230. package/src/components/App.tsx +377 -0
  231. package/src/components/Autocomplete.tsx +63 -0
  232. package/src/components/InputPane.tsx +259 -0
  233. package/src/components/InputReadline.tsx +704 -0
  234. package/src/components/LogPane.tsx +187 -0
  235. package/src/components/PlanEditor.tsx +150 -0
  236. package/src/components/PlanPane.tsx +71 -0
  237. package/src/components/SessionTimer.tsx +35 -0
  238. package/src/components/StateTransitionPane.tsx +149 -0
  239. package/src/components/StatusPane.tsx +62 -0
  240. package/src/components/TaskPane.tsx +119 -0
  241. package/src/components/Welcome.tsx +83 -0
  242. package/src/components/WelcomeChecklist.tsx +118 -0
  243. package/src/components/WelcomeCommands.tsx +102 -0
  244. package/src/components/autocomplete-store.ts +35 -0
  245. package/src/components/parse-keypress.ts +170 -0
  246. package/src/config.ts +491 -0
  247. package/src/execution-controller.ts +109 -0
  248. package/src/experience-tracker.ts +350 -0
  249. package/src/explorbot.ts +405 -0
  250. package/src/explorer.ts +760 -0
  251. package/src/index.tsx +62 -0
  252. package/src/knowledge-tracker.ts +230 -0
  253. package/src/observability.ts +150 -0
  254. package/src/reporter.ts +224 -0
  255. package/src/state-manager.ts +556 -0
  256. package/src/stats.ts +53 -0
  257. package/src/test-plan.ts +432 -0
  258. package/src/utils/aria.ts +629 -0
  259. package/src/utils/cli-name.ts +13 -0
  260. package/src/utils/code-extractor.ts +22 -0
  261. package/src/utils/context-formatter.ts +239 -0
  262. package/src/utils/error-page.ts +23 -0
  263. package/src/utils/expandable.ts +38 -0
  264. package/src/utils/hooks-runner.ts +79 -0
  265. package/src/utils/html-diff.ts +918 -0
  266. package/src/utils/html.ts +1316 -0
  267. package/src/utils/logger.ts +534 -0
  268. package/src/utils/loop.ts +176 -0
  269. package/src/utils/markdown-parser.ts +127 -0
  270. package/src/utils/markdown-query.ts +466 -0
  271. package/src/utils/markdown-terminal.ts +43 -0
  272. package/src/utils/research-parser.ts +11 -0
  273. package/src/utils/retry.ts +73 -0
  274. package/src/utils/rules-loader.ts +118 -0
  275. package/src/utils/strings.ts +13 -0
  276. package/src/utils/test-plan-markdown.ts +332 -0
  277. package/src/utils/throttle.ts +18 -0
  278. package/src/utils/unique-names.ts +14 -0
  279. package/src/utils/url-matcher.ts +45 -0
  280. package/src/utils/web-element.ts +147 -0
  281. package/src/utils/xpath.ts +129 -0
  282. package/dist/bin/explorbot-cli.js.map +0 -1
  283. package/dist/boat/api-tester/bin/apibot-cli.js.map +0 -1
  284. package/dist/boat/api-tester/example/apibot.config.js +0 -31
  285. package/dist/boat/api-tester/example/apibot.config.js.map +0 -1
  286. package/dist/boat/api-tester/src/ai/chief/styles.js.map +0 -1
  287. package/dist/boat/api-tester/src/ai/chief.js.map +0 -1
  288. package/dist/boat/api-tester/src/ai/curler-tools.js.map +0 -1
  289. package/dist/boat/api-tester/src/ai/curler.js.map +0 -1
  290. package/dist/boat/api-tester/src/api-client.js.map +0 -1
  291. package/dist/boat/api-tester/src/apibot.js.map +0 -1
  292. package/dist/boat/api-tester/src/cli.js.map +0 -1
  293. package/dist/boat/api-tester/src/config.js.map +0 -1
  294. package/dist/prompts/audit-rules.md +0 -124
  295. package/dist/src/action-result.js.map +0 -1
  296. package/dist/src/action.js.map +0 -1
  297. package/dist/src/activity.js.map +0 -1
  298. package/dist/src/ai/agent.js.map +0 -1
  299. package/dist/src/ai/bosun.js.map +0 -1
  300. package/dist/src/ai/captain/idle-mode.js.map +0 -1
  301. package/dist/src/ai/captain/mixin.js.map +0 -1
  302. package/dist/src/ai/captain/test-mode.js.map +0 -1
  303. package/dist/src/ai/captain/web-mode.js.map +0 -1
  304. package/dist/src/ai/captain.js.map +0 -1
  305. package/dist/src/ai/conversation.js.map +0 -1
  306. package/dist/src/ai/experience-compactor.js.map +0 -1
  307. package/dist/src/ai/fisherman-tools.js.map +0 -1
  308. package/dist/src/ai/fisherman.js.map +0 -1
  309. package/dist/src/ai/historian.js.map +0 -1
  310. package/dist/src/ai/navigator.js.map +0 -1
  311. package/dist/src/ai/pilot.js.map +0 -1
  312. package/dist/src/ai/planner/session-dedup.js.map +0 -1
  313. package/dist/src/ai/planner/styles.js.map +0 -1
  314. package/dist/src/ai/planner/subpages.js.map +0 -1
  315. package/dist/src/ai/planner.js.map +0 -1
  316. package/dist/src/ai/provider.js.map +0 -1
  317. package/dist/src/ai/quartermaster.js.map +0 -1
  318. package/dist/src/ai/researcher/cache.js.map +0 -1
  319. package/dist/src/ai/researcher/coordinates.js.map +0 -1
  320. package/dist/src/ai/researcher/deep-analysis.js.map +0 -1
  321. package/dist/src/ai/researcher/fingerprint-worker.js.map +0 -1
  322. package/dist/src/ai/researcher/focus.js.map +0 -1
  323. package/dist/src/ai/researcher/locators.js.map +0 -1
  324. package/dist/src/ai/researcher/mixin.js.map +0 -1
  325. package/dist/src/ai/researcher/parser.js.map +0 -1
  326. package/dist/src/ai/researcher/research-result.js.map +0 -1
  327. package/dist/src/ai/researcher.js.map +0 -1
  328. package/dist/src/ai/rules.js.map +0 -1
  329. package/dist/src/ai/task-agent.js.map +0 -1
  330. package/dist/src/ai/tester.js.map +0 -1
  331. package/dist/src/ai/tools.js.map +0 -1
  332. package/dist/src/api/api-client.js.map +0 -1
  333. package/dist/src/api/request-result.js.map +0 -1
  334. package/dist/src/api/request-store.js.map +0 -1
  335. package/dist/src/api/spec-reader.js.map +0 -1
  336. package/dist/src/api/xhr-capture.js.map +0 -1
  337. package/dist/src/browser-server.js.map +0 -1
  338. package/dist/src/command-handler.js.map +0 -1
  339. package/dist/src/commands/add-rule-command.js.map +0 -1
  340. package/dist/src/commands/base-command.js.map +0 -1
  341. package/dist/src/commands/clean-command.js.map +0 -1
  342. package/dist/src/commands/context-aria-command.js.map +0 -1
  343. package/dist/src/commands/context-command.js.map +0 -1
  344. package/dist/src/commands/context-data-command.js.map +0 -1
  345. package/dist/src/commands/context-experience-command.js.map +0 -1
  346. package/dist/src/commands/context-html-command.js.map +0 -1
  347. package/dist/src/commands/context-knowledge-command.js.map +0 -1
  348. package/dist/src/commands/debug-command.js.map +0 -1
  349. package/dist/src/commands/drill-command.js.map +0 -1
  350. package/dist/src/commands/exit-command.js.map +0 -1
  351. package/dist/src/commands/explore-command.js.map +0 -1
  352. package/dist/src/commands/freesail-command.js.map +0 -1
  353. package/dist/src/commands/help-command.js.map +0 -1
  354. package/dist/src/commands/index.js.map +0 -1
  355. package/dist/src/commands/knows-command.js.map +0 -1
  356. package/dist/src/commands/learn-command.js.map +0 -1
  357. package/dist/src/commands/navigate-command.js.map +0 -1
  358. package/dist/src/commands/path-command.js.map +0 -1
  359. package/dist/src/commands/plan-clear-command.js.map +0 -1
  360. package/dist/src/commands/plan-command.js.map +0 -1
  361. package/dist/src/commands/plan-edit-command.js.map +0 -1
  362. package/dist/src/commands/plan-load-command.js.map +0 -1
  363. package/dist/src/commands/plan-reload-command.js.map +0 -1
  364. package/dist/src/commands/plan-save-command.js.map +0 -1
  365. package/dist/src/commands/research-command.js.map +0 -1
  366. package/dist/src/commands/start-command.js.map +0 -1
  367. package/dist/src/commands/status-command.js.map +0 -1
  368. package/dist/src/commands/test-command.js.map +0 -1
  369. package/dist/src/components/ActivityPane.js.map +0 -1
  370. package/dist/src/components/AddKnowledge.js.map +0 -1
  371. package/dist/src/components/AddRule.js.map +0 -1
  372. package/dist/src/components/App.js.map +0 -1
  373. package/dist/src/components/Autocomplete.js.map +0 -1
  374. package/dist/src/components/InputPane.js.map +0 -1
  375. package/dist/src/components/InputReadline.js.map +0 -1
  376. package/dist/src/components/LogPane.js.map +0 -1
  377. package/dist/src/components/PlanEditor.js.map +0 -1
  378. package/dist/src/components/PlanPane.js.map +0 -1
  379. package/dist/src/components/SessionTimer.js.map +0 -1
  380. package/dist/src/components/StateTransitionPane.js.map +0 -1
  381. package/dist/src/components/StatusPane.js.map +0 -1
  382. package/dist/src/components/TaskPane.js.map +0 -1
  383. package/dist/src/components/Welcome.js.map +0 -1
  384. package/dist/src/components/WelcomeChecklist.js.map +0 -1
  385. package/dist/src/components/WelcomeCommands.js.map +0 -1
  386. package/dist/src/components/autocomplete-store.js.map +0 -1
  387. package/dist/src/components/parse-keypress.js.map +0 -1
  388. package/dist/src/config.js.map +0 -1
  389. package/dist/src/execution-controller.js.map +0 -1
  390. package/dist/src/experience-tracker.js.map +0 -1
  391. package/dist/src/explorbot.js.map +0 -1
  392. package/dist/src/explorer.js.map +0 -1
  393. package/dist/src/index.js.map +0 -1
  394. package/dist/src/knowledge-tracker.js.map +0 -1
  395. package/dist/src/observability.js.map +0 -1
  396. package/dist/src/reporter.js.map +0 -1
  397. package/dist/src/state-manager.js.map +0 -1
  398. package/dist/src/stats.js.map +0 -1
  399. package/dist/src/test-plan.js.map +0 -1
  400. package/dist/src/utils/aria.js.map +0 -1
  401. package/dist/src/utils/code-extractor.js.map +0 -1
  402. package/dist/src/utils/context-formatter.js.map +0 -1
  403. package/dist/src/utils/error-page.js.map +0 -1
  404. package/dist/src/utils/expandable.js.map +0 -1
  405. package/dist/src/utils/hooks-runner.js.map +0 -1
  406. package/dist/src/utils/html-diff.js.map +0 -1
  407. package/dist/src/utils/html.js.map +0 -1
  408. package/dist/src/utils/logger.js.map +0 -1
  409. package/dist/src/utils/loop.js.map +0 -1
  410. package/dist/src/utils/markdown-parser.js.map +0 -1
  411. package/dist/src/utils/markdown-query.js.map +0 -1
  412. package/dist/src/utils/markdown-terminal.js.map +0 -1
  413. package/dist/src/utils/research-parser.js.map +0 -1
  414. package/dist/src/utils/retry.js.map +0 -1
  415. package/dist/src/utils/rules-loader.js.map +0 -1
  416. package/dist/src/utils/strings.js.map +0 -1
  417. package/dist/src/utils/test-plan-markdown.js.map +0 -1
  418. package/dist/src/utils/throttle.js.map +0 -1
  419. package/dist/src/utils/unique-names.js.map +0 -1
  420. package/dist/src/utils/url-matcher.js.map +0 -1
  421. package/dist/src/utils/web-element.js.map +0 -1
  422. package/dist/src/utils/xpath.js.map +0 -1
  423. package/prompts/audit-rules.md +0 -124
@@ -0,0 +1,680 @@
1
+ #!/usr/bin/env bun
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { Command } from 'commander';
5
+ import { render } from 'ink';
6
+ import React from 'react';
7
+ import { App } from '../src/components/App.js';
8
+ import { StatusPane } from '../src/components/StatusPane.js';
9
+ import { ConfigParser } from '../src/config.js';
10
+ import { ExplorBot, type ExplorBotOptions } from '../src/explorbot.js';
11
+ import { Stats } from '../src/stats.js';
12
+ import { Plan } from '../src/test-plan.js';
13
+ import { getCliName } from '../src/utils/cli-name.ts';
14
+ import { log, setPreserveConsoleLogs } from '../src/utils/logger.js';
15
+ import { jsonToTable } from '../src/utils/markdown-parser.js';
16
+ import { parseMarkdownToTerminal } from '../src/utils/markdown-terminal.js';
17
+
18
+ const program = new Command();
19
+ const cli = getCliName();
20
+
21
+ program.name(cli).description('AI-powered web exploration tool');
22
+
23
+ interface CLIOptions {
24
+ verbose?: boolean;
25
+ debug?: boolean;
26
+ config?: string;
27
+ path?: string;
28
+ show?: boolean;
29
+ headless?: boolean;
30
+ incognito?: boolean;
31
+ session?: string | boolean;
32
+ }
33
+
34
+ function buildExplorBotOptions(from: string | undefined, options: CLIOptions): ExplorBotOptions {
35
+ return {
36
+ from,
37
+ verbose: options.verbose || options.debug,
38
+ config: options.config,
39
+ path: options.path,
40
+ show: options.show,
41
+ headless: options.headless,
42
+ incognito: options.incognito,
43
+ session: options.session === true ? 'output/session.json' : options.session,
44
+ } as ExplorBotOptions;
45
+ }
46
+
47
+ function addCommonOptions(cmd: Command): Command {
48
+ return cmd
49
+ .option('-v, --verbose', 'Enable verbose logging')
50
+ .option('--debug', 'Enable debug logging (same as --verbose)')
51
+ .option('-c, --config <path>', 'Path to configuration file')
52
+ .option('-p, --path <path>', 'Working directory path')
53
+ .option('-s, --show', 'Show browser window')
54
+ .option('--headless', 'Run browser in headless mode')
55
+ .option('--incognito', 'Run without recording experiences')
56
+ .option('--session [file]', 'Save/restore browser session from file');
57
+ }
58
+
59
+ async function startTUI(explorBot: ExplorBot): Promise<void> {
60
+ if (!process.stdin.isTTY) {
61
+ console.error('Warning: Input not available. Running in non-interactive mode.');
62
+ }
63
+
64
+ process.env.INK_RUNNING = 'true';
65
+
66
+ render(React.createElement(App, { explorBot, initialShowInput: false }), {
67
+ exitOnCtrlC: false,
68
+ patchConsole: true,
69
+ });
70
+
71
+ const cleanup = async () => {
72
+ await explorBot.stop();
73
+ process.exit(0);
74
+ };
75
+
76
+ process.on('SIGINT', async () => {
77
+ console.log('\nReceived SIGINT, cleaning up...');
78
+ await cleanup();
79
+ });
80
+
81
+ process.on('SIGTERM', async () => {
82
+ console.log('\nReceived SIGTERM, cleaning up...');
83
+ await cleanup();
84
+ });
85
+ }
86
+
87
+ async function showStatsAndExit(code: number): Promise<never> {
88
+ if (Stats.hasActivity()) {
89
+ await new Promise<void>((resolve) => {
90
+ const { unmount } = render(
91
+ React.createElement(StatusPane, {
92
+ onComplete: () => {
93
+ unmount();
94
+ resolve();
95
+ },
96
+ }),
97
+ {
98
+ exitOnCtrlC: false,
99
+ patchConsole: false,
100
+ }
101
+ );
102
+ });
103
+ }
104
+ process.exit(code);
105
+ }
106
+
107
+ addCommonOptions(program.command('start [path]').alias('sail').description('Start web exploration')).action(async (startPath, options) => {
108
+ setPreserveConsoleLogs(false);
109
+ const explorBot = new ExplorBot(buildExplorBotOptions(startPath, options));
110
+ await explorBot.start();
111
+ await startTUI(explorBot);
112
+ });
113
+
114
+ addCommonOptions(program.command('explore <path>').description('Start web exploration (legacy command)').option('--max-tests <count>', 'Maximum number of tests to run')).action(async (explorePath, options) => {
115
+ try {
116
+ const explorBot = new ExplorBot(buildExplorBotOptions(explorePath, options));
117
+ await explorBot.start();
118
+ await explorBot.visit(explorePath);
119
+ const { ExploreCommand } = await import('../src/commands/explore-command.js');
120
+ const cmd = new ExploreCommand(explorBot);
121
+ if (options.maxTests) cmd.maxTests = Number.parseInt(options.maxTests, 10);
122
+ await cmd.execute('');
123
+ await explorBot.stop();
124
+ await showStatsAndExit(0);
125
+ } catch (error) {
126
+ console.error('Failed:', error instanceof Error ? error.message : 'Unknown error');
127
+ await showStatsAndExit(1);
128
+ }
129
+ });
130
+
131
+ addCommonOptions(program.command('plan <path>').description('Generate test plan for a page and exit'))
132
+ .option('-a, --append', 'Add tests to existing plan file')
133
+ .option('--style <style>', 'Planning style: normal, curious, psycho')
134
+ .option('--focus <feature>', 'Focus area for test planning')
135
+ .action(async (planPath, options) => {
136
+ try {
137
+ const explorBot = new ExplorBot(buildExplorBotOptions(planPath, options));
138
+ await explorBot.start();
139
+
140
+ await explorBot.visit(planPath);
141
+
142
+ if (options.append) {
143
+ const planFilename = explorBot.generatePlanFilename();
144
+ const existingPlanPath = path.join(explorBot.getPlansDir(), planFilename);
145
+ if (fs.existsSync(existingPlanPath)) {
146
+ explorBot.loadPlan(existingPlanPath);
147
+ }
148
+ }
149
+
150
+ await explorBot.plan(options.focus || undefined, {
151
+ fresh: !options.append,
152
+ style: options.style,
153
+ });
154
+
155
+ const plan = explorBot.getCurrentPlan();
156
+ if (!plan?.tests.length) {
157
+ console.error('No test scenarios generated.');
158
+ await explorBot.stop();
159
+ await showStatsAndExit(1);
160
+ }
161
+
162
+ const savedPath = explorBot.savePlan();
163
+ const planFile = savedPath ? path.basename(savedPath) : 'plan.md';
164
+
165
+ const cliFlags = [options.path ? `--path ${options.path}` : '', options.session ? '--session' : ''].filter(Boolean).join(' ');
166
+ const cliSuffix = cliFlags ? ` ${cliFlags}` : '';
167
+
168
+ const lines: string[] = [];
169
+ lines.push('Run tests:');
170
+ lines.push(`\`${cli} test ${planFile} 1${cliSuffix}\` → run first test`);
171
+ lines.push(`\`${cli} test ${planFile} 1-3${cliSuffix}\` → run tests 1 to 3`);
172
+ lines.push(`\`${cli} test ${planFile} *${cliSuffix}\` → run all tests`);
173
+
174
+ log(parseMarkdownToTerminal(lines.join('\n')));
175
+
176
+ await explorBot.stop();
177
+ await showStatsAndExit(0);
178
+ } catch (error) {
179
+ console.error('Failed:', error instanceof Error ? error.message : 'Unknown error');
180
+ await showStatsAndExit(1);
181
+ }
182
+ });
183
+
184
+ addCommonOptions(program.command('plan:load <planfile> [index]').description('Load a plan file and display its tests. Pass index to see test details.')).action(async (planfile: string, index: string | undefined) => {
185
+ try {
186
+ const resolvedPath = path.resolve(planfile);
187
+ if (!fs.existsSync(resolvedPath)) {
188
+ console.error(`Plan file not found: ${resolvedPath}`);
189
+ process.exit(1);
190
+ }
191
+
192
+ const plan = Plan.fromMarkdown(resolvedPath);
193
+ const planFile = path.basename(resolvedPath);
194
+
195
+ if (index) {
196
+ const idx = Number.parseInt(index, 10);
197
+ if (Number.isNaN(idx) || idx < 1 || idx > plan.tests.length) {
198
+ console.error(`Invalid index: ${index}. Must be 1-${plan.tests.length}`);
199
+ process.exit(1);
200
+ }
201
+ const test = plan.tests[idx - 1];
202
+ const lines: string[] = [];
203
+ lines.push(`## #${idx} ${test.scenario}\n`);
204
+ lines.push(`**Priority:** ${test.priority}`);
205
+ const planUrl = plan.url || plan.tests[0]?.startUrl;
206
+ if (planUrl) lines.push(`**Plan URL:** ${planUrl}`);
207
+ if (test.startUrl && test.startUrl !== planUrl) lines.push(`**Test URL:** ${test.startUrl}`);
208
+ if (test.plannedSteps.length) {
209
+ lines.push('\n**Steps:**');
210
+ for (const step of test.plannedSteps) lines.push(`- ${step}`);
211
+ }
212
+ if (test.expected.length) {
213
+ lines.push('\n**Expected:**');
214
+ for (const exp of test.expected) lines.push(`- ${exp}`);
215
+ }
216
+ lines.push('');
217
+ lines.push(`Run: \`${cli} test ${planFile} ${idx}\``);
218
+ console.log(parseMarkdownToTerminal(lines.join('\n')));
219
+ return;
220
+ }
221
+
222
+ const planUrl = plan.url || plan.tests[0]?.startUrl;
223
+ const lines: string[] = [`**${plan.title}** (${plan.tests.length} tests)\n`];
224
+ if (planUrl) {
225
+ lines.push(`URL: ${planUrl}\n`);
226
+ }
227
+
228
+ const rows = plan.tests.map((test, i) => ({
229
+ '#': String(i + 1),
230
+ Priority: test.priority,
231
+ Title: test.scenario.replace(/\|/g, '-'),
232
+ Steps: String(test.plannedSteps.length),
233
+ Expected: String(test.expected.length),
234
+ }));
235
+ lines.push(jsonToTable(rows, ['#', 'Priority', 'Title', 'Steps', 'Expected']));
236
+
237
+ lines.push('View test details:');
238
+ lines.push(`\`${cli} plan:load ${planFile} <index>\`\n`);
239
+ lines.push('Run tests:');
240
+ lines.push(`\`${cli} test ${planFile} 1\` → run first test`);
241
+ lines.push(`\`${cli} test ${planFile} 1-3\` → run tests 1 to 3`);
242
+ lines.push(`\`${cli} test ${planFile} *\` → run all tests`);
243
+
244
+ console.log(parseMarkdownToTerminal(lines.join('\n')));
245
+ } catch (error) {
246
+ console.error('Failed:', error instanceof Error ? error.message : 'Unknown error');
247
+ process.exit(1);
248
+ }
249
+ });
250
+
251
+ addCommonOptions(program.command('test <planfile> [index]').description('Execute tests from a plan file. Index: 1, 1,3, 1-5, *, all').option('--grep <pattern>', 'Run tests matching pattern')).action(async (planfile, index, options) => {
252
+ try {
253
+ const explorBot = new ExplorBot(buildExplorBotOptions(undefined, options));
254
+ await explorBot.start();
255
+
256
+ const plan = explorBot.loadPlan(planfile);
257
+ const pending = plan.getPendingTests();
258
+ log(`Plan loaded: "${plan.title}" (${plan.tests.length} tests, ${pending.length} pending)`);
259
+
260
+ const startUrl = plan.url || pending[0]?.startUrl;
261
+ if (!startUrl) {
262
+ throw new Error('No URL found in plan or tests. Cannot determine where to navigate.');
263
+ }
264
+
265
+ log(`Navigating to ${startUrl}`);
266
+ await explorBot.visit(startUrl);
267
+
268
+ let args = '';
269
+ if (index) args = index;
270
+ else if (options.grep) args = options.grep;
271
+
272
+ const { TestCommand } = await import('../src/commands/test-command.js');
273
+ const cmd = new TestCommand(explorBot);
274
+ await cmd.execute(args);
275
+
276
+ await explorBot.stop();
277
+ await showStatsAndExit(0);
278
+ } catch (error) {
279
+ console.error('Failed:', error instanceof Error ? error.message : 'Unknown error');
280
+ await showStatsAndExit(1);
281
+ }
282
+ });
283
+
284
+ addCommonOptions(
285
+ program
286
+ .command('freesail [startUrl]')
287
+ .description('Continuously explore and navigate to new pages autonomously')
288
+ .option('--deep', 'Depth-first: prioritize newly discovered pages')
289
+ .option('--shallow', 'Breadth-first: pick globally least-visited page')
290
+ .option('--scope <prefix>', 'Restrict navigation to URL prefix')
291
+ .option('--max-tests <count>', 'Maximum number of tests to run')
292
+ ).action(async (startUrl, options) => {
293
+ const explorBot = new ExplorBot(buildExplorBotOptions(startUrl || '/', options));
294
+ await explorBot.start();
295
+ const args = [options.deep && '--deep', options.shallow && '--shallow', options.scope && `--scope ${options.scope}`, options.maxTests && `--max-tests ${options.maxTests}`].filter(Boolean).join(' ');
296
+ const { FreesailCommand } = await import('../src/commands/freesail-command.js');
297
+ const cmd = new FreesailCommand(explorBot);
298
+ await cmd.execute(args);
299
+ });
300
+
301
+ program
302
+ .command('init')
303
+ .description('Initialize a new project with configuration')
304
+ .option('-c, --config-path <path>', 'Path for the config file', './explorbot.config.js')
305
+ .option('-f, --force', 'Overwrite existing config file')
306
+ .option('-p, --path <path>', 'Working directory for initialization')
307
+ .action(async (options) => {
308
+ const { runInitCommand } = await import('../src/commands/init-command.js');
309
+ runInitCommand({
310
+ configPath: options.configPath,
311
+ force: options.force,
312
+ path: options.path,
313
+ });
314
+ });
315
+
316
+ program
317
+ .command('clean [target]')
318
+ .description('Clean files: states, research, plans, experiences, output (default: output + experiences)')
319
+ .option('-p, --path <path>', 'Custom path to clean')
320
+ .action(async (target, options) => {
321
+ const customPath = options.path;
322
+ const originalCwd = process.cwd();
323
+ const basePath = customPath ? path.resolve(originalCwd, customPath) : process.cwd();
324
+
325
+ const targets: Record<string, { description: string; dir: string }> = {
326
+ states: { description: 'page states', dir: path.join(basePath, 'output', 'states') },
327
+ research: { description: 'research cache', dir: path.join(basePath, 'output', 'research') },
328
+ plans: { description: 'test plans', dir: path.join(basePath, 'output', 'plans') },
329
+ experiences: { description: 'experience files', dir: path.join(basePath, 'experience') },
330
+ output: { description: 'all output files', dir: path.join(basePath, 'output') },
331
+ };
332
+
333
+ function cleanDirectoryContents(dirPath: string): number {
334
+ let count = 0;
335
+ for (const item of fs.readdirSync(dirPath)) {
336
+ const itemPath = path.join(dirPath, item);
337
+ if (fs.statSync(itemPath).isDirectory()) {
338
+ count += cleanDirectoryContents(itemPath);
339
+ fs.rmSync(itemPath, { recursive: true });
340
+ } else {
341
+ fs.unlinkSync(itemPath);
342
+ count++;
343
+ }
344
+ }
345
+ return count;
346
+ }
347
+
348
+ function cleanTarget(name: string): void {
349
+ const t = targets[name];
350
+ if (!fs.existsSync(t.dir)) {
351
+ console.log(`${name}: nothing to clean (${t.dir} not found)`);
352
+ return;
353
+ }
354
+ const count = cleanDirectoryContents(t.dir);
355
+ console.log(`Cleaned ${count} ${t.description} files from ${t.dir}`);
356
+ }
357
+
358
+ try {
359
+ if (target && !targets[target]) {
360
+ console.error(`Unknown target: ${target}. Available: ${Object.keys(targets).join(', ')}`);
361
+ process.exit(1);
362
+ }
363
+
364
+ if (!target) {
365
+ cleanTarget('output');
366
+ cleanTarget('experiences');
367
+ } else {
368
+ cleanTarget(target);
369
+ }
370
+
371
+ console.log('Cleanup completed successfully!');
372
+ } catch (error) {
373
+ console.error('Failed to clean:', error);
374
+ process.exit(1);
375
+ }
376
+ });
377
+
378
+ program
379
+ .command('learn [url] [description]')
380
+ .alias('add-knowledge')
381
+ .description('Add knowledge for URLs')
382
+ .option('-p, --path <path>', 'Working directory path')
383
+ .action(async (url, description, options) => {
384
+ try {
385
+ await ConfigParser.getInstance().loadConfig({
386
+ path: options.path || process.cwd(),
387
+ });
388
+
389
+ if (url && description) {
390
+ const { KnowledgeTracker } = await import('../src/knowledge-tracker.js');
391
+ const tracker = new KnowledgeTracker();
392
+ const result = tracker.addKnowledge(url, description);
393
+ const action = result.isNewFile ? 'Created' : 'Updated';
394
+ console.log(`Knowledge ${action} in: ${result.filename}`);
395
+ return;
396
+ }
397
+
398
+ const AddKnowledge = (await import('../src/components/AddKnowledge.js')).default;
399
+ render(React.createElement(AddKnowledge, { initialUrl: url || '' }), {
400
+ exitOnCtrlC: false,
401
+ patchConsole: false,
402
+ });
403
+ } catch (error) {
404
+ console.error('Failed:', error instanceof Error ? error.message : 'Unknown error');
405
+ process.exit(1);
406
+ }
407
+ });
408
+
409
+ program
410
+ .command('knows [url]')
411
+ .description('List all knowledge URLs or show matching knowledge for a URL')
412
+ .option('-p, --path <path>', 'Working directory path')
413
+ .action(async (url, options) => {
414
+ try {
415
+ await ConfigParser.getInstance().loadConfig({
416
+ path: options.path || process.cwd(),
417
+ });
418
+ const { KnowsCommand } = await import('../src/commands/knows-command.js');
419
+ const explorBot = new ExplorBot({ path: options.path });
420
+ const command = new KnowsCommand(explorBot);
421
+ await command.execute(url || '');
422
+ } catch (error) {
423
+ console.error('Failed:', error instanceof Error ? error.message : 'Unknown error');
424
+ process.exit(1);
425
+ }
426
+ });
427
+
428
+ addCommonOptions(program.command('research <url>').description('Research a page and print UI analysis').option('--data', 'Include data extraction in research').option('--deep', 'Enable deep analysis (expand hidden elements)').option('--no-fix', 'Skip locator fix cycle (for debugging)')).action(
429
+ async (url, options) => {
430
+ try {
431
+ const explorBot = new ExplorBot(buildExplorBotOptions(url, options));
432
+ await explorBot.start();
433
+
434
+ const argParts: string[] = [url];
435
+ if (options.data) argParts.push('--data');
436
+ if (options.deep) argParts.push('--deep');
437
+ if (options.fix === false) argParts.push('--no-fix');
438
+
439
+ const { ResearchCommand } = await import('../src/commands/research-command.js');
440
+ await new ResearchCommand(explorBot).execute(argParts.join(' '));
441
+
442
+ await explorBot.stop();
443
+ await showStatsAndExit(0);
444
+ } catch (error) {
445
+ console.error('Failed:', error instanceof Error ? error.message : 'Unknown error');
446
+ await showStatsAndExit(1);
447
+ }
448
+ }
449
+ );
450
+
451
+ addCommonOptions(
452
+ program.command('drill <url>').alias('bosun').description('Drill all components on a page to learn interactions').option('--knowledge <path>', 'Save learned interactions to knowledge file at this URL path').option('--max <count>', 'Maximum number of components to drill', '20')
453
+ ).action(async (url, options) => {
454
+ try {
455
+ const explorBot = new ExplorBot(buildExplorBotOptions(url, options));
456
+ await explorBot.start();
457
+
458
+ await explorBot.visit(url);
459
+
460
+ const plan = await explorBot.agentBosun().drill({
461
+ knowledgePath: options.knowledge,
462
+ maxComponents: Number.parseInt(options.max, 10),
463
+ interactive: false,
464
+ });
465
+
466
+ console.log(`\nDrill completed: ${plan.tests.length} components`);
467
+ console.log(`Successful: ${plan.tests.filter((t) => t.isSuccessful).length}`);
468
+ console.log(`Failed: ${plan.tests.filter((t) => t.hasFailed).length}`);
469
+
470
+ await explorBot.stop();
471
+ await showStatsAndExit(0);
472
+ } catch (error) {
473
+ console.error('Failed:', error instanceof Error ? error.message : 'Unknown error');
474
+ await showStatsAndExit(1);
475
+ }
476
+ });
477
+
478
+ program
479
+ .command('context <url>')
480
+ .description('Print page context (URL, headings, knowledge, experience, interactive elements)')
481
+ .option('-p, --path <path>', 'Working directory path')
482
+ .option('-c, --config <path>', 'Path to configuration file')
483
+ .option('--session [file]', 'Save/restore browser session from file')
484
+ .option('--full', 'Include HTML and all data')
485
+ .option('--compact', 'Compact view with summaries')
486
+ .option('--attached', 'Only auto-attached sections (default)')
487
+ .option('--visual', 'Annotate elements on screenshot and print screenshot path')
488
+ .option('--screenshot', 'Alias for --visual')
489
+ .action(async (url, options) => {
490
+ try {
491
+ const mainOptions: ExplorBotOptions = {
492
+ path: options.path,
493
+ config: options.config,
494
+ headless: true,
495
+ session: options.session === true ? 'output/session.json' : options.session,
496
+ };
497
+
498
+ const explorBot = new ExplorBot(mainOptions);
499
+ await explorBot.start();
500
+
501
+ await explorBot.agentNavigator().visit(url);
502
+
503
+ const { ContextCommand } = await import('../src/commands/context-command.js');
504
+ const argParts: string[] = [];
505
+ if (options.full) argParts.push('--full');
506
+ else if (options.compact) argParts.push('--compact');
507
+ else argParts.push('--attached');
508
+ if (options.visual || options.screenshot) argParts.push('--visual');
509
+ await new ContextCommand(explorBot).execute(argParts.join(' '));
510
+
511
+ await explorBot.stop();
512
+ await showStatsAndExit(0);
513
+ } catch (error) {
514
+ console.error('Failed:', error instanceof Error ? error.message : 'Unknown error');
515
+ await showStatsAndExit(1);
516
+ }
517
+ });
518
+
519
+ addCommonOptions(program.command('shell <url> <command>').description('Execute a CodeceptJS command on a page and exit')).action(async (url, command, options) => {
520
+ try {
521
+ const explorBot = new ExplorBot(buildExplorBotOptions(url, options));
522
+ await explorBot.start();
523
+ await explorBot.agentNavigator().visit(url);
524
+
525
+ const action = explorBot.getExplorer().createAction();
526
+ await action.execute(command);
527
+
528
+ log('Command executed successfully');
529
+ const state = explorBot.getExplorer().getStateManager().getCurrentState();
530
+ if (state) log(`URL: ${state.url}`);
531
+
532
+ await explorBot.stop();
533
+ await showStatsAndExit(0);
534
+ } catch (error) {
535
+ console.error('Failed:', error instanceof Error ? error.message : 'Unknown error');
536
+ await showStatsAndExit(1);
537
+ }
538
+ });
539
+
540
+ const browserCmd = program.command('browser').description('Manage persistent browser server');
541
+
542
+ browserCmd
543
+ .command('start')
544
+ .description('Launch a persistent browser server')
545
+ .option('-s, --show', 'Launch browser in headed mode (visible window)')
546
+ .option('--headless', 'Launch browser in headless mode')
547
+ .option('-c, --config <path>', 'Path to configuration file')
548
+ .option('-p, --path <path>', 'Working directory path')
549
+ .action(async (options) => {
550
+ const { launchServer, removeEndpointFile } = await import('../src/browser-server.js');
551
+ await ConfigParser.getInstance().loadConfig({
552
+ config: options.config,
553
+ path: options.path,
554
+ });
555
+ const config = ConfigParser.getInstance().getConfig();
556
+
557
+ let show = config.playwright.show || false;
558
+ if (options.show !== undefined) show = true;
559
+ if (options.headless !== undefined) show = false;
560
+
561
+ const server = await launchServer({
562
+ browser: config.playwright.browser,
563
+ show,
564
+ });
565
+
566
+ console.log('Browser server is running. Press Ctrl+C to stop.');
567
+
568
+ const cleanup = () => {
569
+ console.log('\nStopping browser server...');
570
+ server.close();
571
+ removeEndpointFile();
572
+ process.exit(0);
573
+ };
574
+
575
+ process.on('SIGINT', cleanup);
576
+ process.on('SIGTERM', cleanup);
577
+ });
578
+
579
+ browserCmd
580
+ .command('stop')
581
+ .description('Stop a running browser server')
582
+ .option('-c, --config <path>', 'Path to configuration file')
583
+ .option('-p, --path <path>', 'Working directory path')
584
+ .action(async (options) => {
585
+ const { getAliveEndpoint, removeEndpointFile } = await import('../src/browser-server.js');
586
+ await ConfigParser.getInstance().loadConfig({
587
+ config: options.config,
588
+ path: options.path,
589
+ });
590
+
591
+ const endpoint = await getAliveEndpoint();
592
+ if (!endpoint) {
593
+ console.log('No running browser server found.');
594
+ process.exit(0);
595
+ }
596
+
597
+ try {
598
+ const { chromium } = await import('playwright-core');
599
+ const browser = await chromium.connect(endpoint, { timeout: 3000 });
600
+ await browser.close();
601
+ } catch {}
602
+
603
+ removeEndpointFile();
604
+ console.log('Browser server stopped.');
605
+ });
606
+
607
+ browserCmd
608
+ .command('status')
609
+ .description('Check if a browser server is running')
610
+ .option('-c, --config <path>', 'Path to configuration file')
611
+ .option('-p, --path <path>', 'Working directory path')
612
+ .action(async (options) => {
613
+ const { getAliveEndpoint } = await import('../src/browser-server.js');
614
+ await ConfigParser.getInstance().loadConfig({
615
+ config: options.config,
616
+ path: options.path,
617
+ });
618
+
619
+ const endpoint = await getAliveEndpoint();
620
+ if (endpoint) {
621
+ console.log(`Browser server is running at: ${endpoint}`);
622
+ } else {
623
+ console.log('No running browser server found.');
624
+ }
625
+ });
626
+
627
+ program
628
+ .command('extract-styles <agent>')
629
+ .description('Extract built-in planning styles to a directory for customization')
630
+ .option('-d, --dir <path>', 'Target directory (default: ./rules/<agent>/styles)')
631
+ .action(async (agent, options) => {
632
+ try {
633
+ const { RulesLoader } = await import('../src/utils/rules-loader.js');
634
+ const targetDir = options.dir || path.resolve(`./rules/${agent}/styles`);
635
+ const extracted = RulesLoader.extractStyles(agent, targetDir);
636
+ if (extracted.length === 0) {
637
+ console.log('All style files already exist in target directory.');
638
+ } else {
639
+ console.log(`\nExtracted ${extracted.length} style files to ${targetDir}`);
640
+ }
641
+ } catch (error) {
642
+ console.error('Failed:', error instanceof Error ? error.message : 'Unknown error');
643
+ process.exit(1);
644
+ }
645
+ });
646
+
647
+ program
648
+ .command('add-rule [agent] [name]')
649
+ .alias('rules:add')
650
+ .description('Create a rule file for an agent')
651
+ .option('--url <pattern>', 'URL pattern for this rule')
652
+ .option('-p, --path <path>', 'Working directory path')
653
+ .action(async (agent, name, options) => {
654
+ if (options.path) process.chdir(path.resolve(options.path));
655
+
656
+ if (agent && name) {
657
+ const { AddRuleCommand } = await import('../src/commands/add-rule-command.js');
658
+ const result = AddRuleCommand.createRuleFile(agent, name, {
659
+ urlPattern: options.url,
660
+ });
661
+ process.exit(result ? 0 : 1);
662
+ }
663
+
664
+ const AddRule = (await import('../src/components/AddRule.js')).default;
665
+ render(
666
+ React.createElement(AddRule, {
667
+ initialAgent: agent || '',
668
+ initialName: name || '',
669
+ }),
670
+ {
671
+ exitOnCtrlC: false,
672
+ patchConsole: false,
673
+ }
674
+ );
675
+ });
676
+
677
+ import { createApiCommands } from '../boat/api-tester/src/cli.ts';
678
+ program.addCommand(createApiCommands('api'));
679
+
680
+ program.parse();
@@ -0,0 +1,15 @@
1
+ import { RulesLoader } from '../../../../../src/utils/rules-loader.ts';
2
+
3
+ export const DEFAULT_STYLES = ['normal', 'curious', 'psycho', 'hacker'];
4
+
5
+ let cache: Record<string, string> | null = null;
6
+
7
+ export function getStyles(): Record<string, string> {
8
+ if (cache) return cache;
9
+ cache = RulesLoader.loadStyles('chief', DEFAULT_STYLES);
10
+ return cache;
11
+ }
12
+
13
+ export function getActiveStyle(iteration: number, override?: string): { name: string; approach: string } {
14
+ return RulesLoader.getActiveStyle(getStyles(), iteration, override);
15
+ }