explorbot 0.0.1 → 0.0.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 (423) hide show
  1. package/README.md +80 -26
  2. package/bin/explorbot-cli.ts +679 -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 +19 -98
  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 +0 -1
  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 +0 -1
  41. package/dist/src/ai/planner.js +0 -1
  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 +0 -1
  45. package/dist/src/ai/researcher/coordinates.js +0 -1
  46. package/dist/src/ai/researcher/deep-analysis.js +0 -1
  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 +0 -1
  50. package/dist/src/ai/researcher/mixin.js +0 -1
  51. package/dist/src/ai/researcher/parser.js +0 -1
  52. package/dist/src/ai/researcher/research-result.js +0 -1
  53. package/dist/src/ai/researcher.js +0 -1
  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 +0 -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 +0 -1
  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 +2 -2
  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 +115 -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 +0 -1
  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 +0 -1
  119. package/dist/src/explorer.js +0 -1
  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 +0 -1
  150. package/dist/src/utils/xpath.js +0 -1
  151. package/package.json +27 -3
  152. package/src/action-result.ts +694 -0
  153. package/src/action.ts +445 -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 +141 -0
  172. package/src/ai/planner.ts +536 -0
  173. package/src/ai/provider.ts +613 -0
  174. package/src/ai/quartermaster.ts +286 -0
  175. package/src/ai/researcher/cache.ts +103 -0
  176. package/src/ai/researcher/coordinates.ts +238 -0
  177. package/src/ai/researcher/deep-analysis.ts +415 -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 +115 -0
  184. package/src/ai/researcher.ts +857 -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 +1117 -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 +128 -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 +41 -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 +490 -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 +713 -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 +145 -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,556 @@
1
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import matter from 'gray-matter';
4
+ import { ActionResult } from './action-result.js';
5
+ import { ConfigParser, outputPath } from './config.js';
6
+ import { ExperienceTracker } from './experience-tracker.js';
7
+ import { detectFocusArea } from './utils/aria.js';
8
+ import { htmlTextSnapshot } from './utils/html.js';
9
+ import { createDebug, tag } from './utils/logger.js';
10
+ import { extractStatePath } from './utils/url-matcher.js';
11
+
12
+ const debugLog = createDebug('explorbot:state');
13
+
14
+ export interface Link {
15
+ title: string;
16
+ url: string;
17
+ visible?: boolean;
18
+ }
19
+
20
+ export interface WebPageState {
21
+ /** Unique incremental state identifier */
22
+ id?: number;
23
+ /** URL path without domain, including hash: /path/to/page#section */
24
+ url: string;
25
+ /** Page title */
26
+ title?: string;
27
+ /** Full URL for reference */
28
+ fullUrl?: string;
29
+ /** Timestamp when state was captured */
30
+ timestamp?: Date;
31
+ /** Hash of the state for unique identification */
32
+ hash?: string;
33
+ /** HTML file path */
34
+ htmlFile?: string;
35
+ /** Screenshot file path */
36
+ screenshotFile?: string;
37
+ /** Log file path */
38
+ logFile?: string;
39
+ /** HTML content */
40
+ html?: string;
41
+
42
+ notes?: string[];
43
+ /** Page headings */
44
+ h1?: string;
45
+ h2?: string;
46
+ h3?: string;
47
+ h4?: string;
48
+ ariaSnapshot?: string | null;
49
+ ariaSnapshotFile?: string;
50
+ links?: Link[];
51
+ verifications?: Record<string, boolean>;
52
+ }
53
+
54
+ export interface StateTransition {
55
+ /** Previous state (null if this is the first state) */
56
+ fromState: WebPageState | null;
57
+ /** Current state */
58
+ toState: WebPageState;
59
+ /** Code block that caused the transition */
60
+ codeBlock: string;
61
+ /** Timestamp of the transition */
62
+ timestamp: Date;
63
+ /** Any error that occurred during transition */
64
+ error?: string;
65
+ /** What triggered the state change */
66
+ trigger: 'manual' | 'navigation' | 'automatic';
67
+ }
68
+
69
+ export type StateChangeListener = (event: StateTransition) => void;
70
+
71
+ export interface Knowledge extends WebPageState {
72
+ /** File path */
73
+ filePath: string;
74
+ /** Markdown content */
75
+ content: string;
76
+ }
77
+
78
+ export class StateManager {
79
+ private currentState: WebPageState | null = null;
80
+ private stateHistory: StateTransition[] = [];
81
+ private allVisitedUrls: Set<string> = new Set();
82
+ private knowledgeCache: Knowledge[] = [];
83
+ private lastKnowledgeScan: Date | null = null;
84
+ private stateChangeListeners: StateChangeListener[] = [];
85
+ private experienceTracker!: ExperienceTracker;
86
+ private knowledgeDir: string;
87
+ private nextStateId = 1;
88
+
89
+ constructor() {
90
+ this.experienceTracker = new ExperienceTracker();
91
+ const configParser = ConfigParser.getInstance();
92
+ const config = configParser.getConfig();
93
+ const configPath = configParser.getConfigPath();
94
+
95
+ // Resolve knowledge directory relative to the config file location (project root)
96
+ if (configPath) {
97
+ const projectRoot = dirname(configPath);
98
+ this.knowledgeDir = join(projectRoot, config.dirs?.knowledge || 'knowledge');
99
+ } else {
100
+ this.knowledgeDir = config.dirs?.knowledge || 'knowledge';
101
+ }
102
+ }
103
+
104
+ getExperienceTracker(): ExperienceTracker {
105
+ return this.experienceTracker;
106
+ }
107
+
108
+ /**
109
+ * Subscribe to state change events
110
+ */
111
+ onStateChange(listener: StateChangeListener): () => void {
112
+ this.stateChangeListeners.push(listener);
113
+
114
+ // Return unsubscribe function
115
+ return () => {
116
+ const index = this.stateChangeListeners.indexOf(listener);
117
+ if (index > -1) {
118
+ this.stateChangeListeners.splice(index, 1);
119
+ }
120
+ };
121
+ }
122
+
123
+ /**
124
+ * Emit state change event to all listeners
125
+ */
126
+ private emitStateChange(event: StateTransition): void {
127
+ // Log HTML content when state changes
128
+ if (event.toState.html && event.toState.html !== event.fromState?.html) {
129
+ let htmlContent = event?.toState?.html ?? '';
130
+ htmlContent = htmlTextSnapshot(htmlContent);
131
+ // tag('html').log(`Page HTML for ${event.toState.url}:\n${htmlContent}`);
132
+ }
133
+
134
+ this.stateChangeListeners.forEach((listener) => {
135
+ try {
136
+ listener(event);
137
+ } catch (error) {
138
+ debugLog('Error in state change listener:', error);
139
+ }
140
+ });
141
+ }
142
+
143
+ /**
144
+ * Extract state path from full URL
145
+ * Removes domain, port, protocol, and query params
146
+ * Keeps path and hash: /path/to/page#section
147
+ */
148
+ /**
149
+ * Update current state from ActionResult and record transition if state changed
150
+ */
151
+ updateState(actionResult: ActionResult, codeBlock?: string, trigger: 'manual' | 'navigation' | 'automatic' = 'manual'): WebPageState {
152
+ const previousState = this.currentState;
153
+ const previousHash = previousState?.hash;
154
+
155
+ const newState = actionResult;
156
+ this.currentState = newState;
157
+ this.currentState.id = this.nextStateId++;
158
+ if (newState.url) this.allVisitedUrls.add(normalizeUrl(newState.url));
159
+
160
+ const hashChanged = actionResult.hash !== previousHash;
161
+ const dialogOpened = !hashChanged && this.hasDialogAppeared(previousState, newState);
162
+
163
+ if (hashChanged || dialogOpened) {
164
+ const transition: StateTransition = {
165
+ fromState: previousState,
166
+ toState: newState,
167
+ codeBlock: codeBlock || '',
168
+ timestamp: new Date(),
169
+ trigger,
170
+ };
171
+ this.stateHistory.push(transition);
172
+ this.emitStateChange(transition);
173
+
174
+ if (dialogOpened) {
175
+ debugLog('State change detected: modal dialog appeared');
176
+ }
177
+ }
178
+
179
+ debugLog(`State updated: ${this.currentState.url} (${this.currentState.hash})`);
180
+
181
+ return newState;
182
+ }
183
+
184
+ /**
185
+ * Update state from basic data (for navigation events)
186
+ */
187
+ updateStateFromBasic(url: string, title?: string, trigger: 'manual' | 'navigation' | 'automatic' = 'navigation'): WebPageState {
188
+ const path = extractStatePath(url) || '/';
189
+
190
+ // no extra navigation happened
191
+ if (normalizeUrl(this.currentState?.url || '') === normalizeUrl(path)) {
192
+ return this.currentState!;
193
+ }
194
+
195
+ const newState: WebPageState = {
196
+ id: this.nextStateId++,
197
+ url: path,
198
+ title: title || 'Unknown Page',
199
+ fullUrl: url,
200
+ timestamp: new Date(),
201
+ hash: this.generateBasicHash(path, title),
202
+ };
203
+
204
+ // Create transition record
205
+ const transition: StateTransition = {
206
+ fromState: this.currentState,
207
+ toState: newState,
208
+ codeBlock: '',
209
+ timestamp: new Date(),
210
+ trigger,
211
+ };
212
+
213
+ this.stateHistory.push(transition);
214
+ this.currentState = newState;
215
+ this.allVisitedUrls.add(normalizeUrl(newState.url));
216
+
217
+ this.emitStateChange(transition);
218
+
219
+ debugLog(`State updated from navigation: ${this.currentState.url} (${this.currentState.hash})`);
220
+
221
+ return newState;
222
+ }
223
+
224
+ private hasDialogAppeared(previousState: WebPageState | null, newState: WebPageState): boolean {
225
+ const prevFocus = detectFocusArea(previousState?.ariaSnapshot ?? null);
226
+ const newFocus = detectFocusArea(newState.ariaSnapshot ?? null);
227
+ return !prevFocus.detected && newFocus.detected;
228
+ }
229
+
230
+ /**
231
+ * Generate a basic hash for state comparison
232
+ */
233
+ private generateBasicHash(url: string, title?: string): string {
234
+ const parts = [url];
235
+ if (title) {
236
+ parts.push(`title_${title}`);
237
+ }
238
+
239
+ return parts
240
+ .join('_')
241
+ .replace(/[^a-zA-Z0-9_]/g, '_')
242
+ .replace(/_+/g, '_')
243
+ .replace(/^_|_$/g, '')
244
+ .toLowerCase()
245
+ .substring(0, 200);
246
+ }
247
+
248
+ /**
249
+ * Get current state
250
+ */
251
+ getCurrentState(): WebPageState | null {
252
+ return this.currentState;
253
+ }
254
+
255
+ /**
256
+ * Check if state has changed since a given state
257
+ */
258
+ hasStateChanged(previousState: WebPageState | null): boolean {
259
+ if (!previousState && !this.currentState) return false;
260
+ if (!previousState || !this.currentState) return true;
261
+ return previousState.hash !== this.currentState.hash;
262
+ }
263
+
264
+ /**
265
+ * Compare two states by their hash
266
+ */
267
+ statesEqual(state1: WebPageState | null, state2: WebPageState | null): boolean {
268
+ if (!state1 && !state2) return true;
269
+ if (!state1 || !state2) return false;
270
+ return state1.hash === state2.hash;
271
+ }
272
+
273
+ /**
274
+ * Get state history
275
+ */
276
+ getStateHistory(): StateTransition[] {
277
+ return [...this.stateHistory];
278
+ }
279
+
280
+ isInDeadLoop(): boolean {
281
+ const minWindow = 6;
282
+ const increment = 2;
283
+ const stateHashes = this.stateHistory.map((transition) => {
284
+ const state = transition.toState;
285
+ return state.hash || this.generateBasicHash(state.url || '/', state.title);
286
+ });
287
+
288
+ debugLog(`Current state hash: ${this.currentState?.hash}`);
289
+ debugLog(`State hashes: ${stateHashes.join(', ')}`);
290
+
291
+ if (stateHashes.length < minWindow) {
292
+ return false;
293
+ }
294
+
295
+ const currentHash = this.currentState?.hash || stateHashes[stateHashes.length - 1];
296
+ if (!currentHash) {
297
+ return false;
298
+ }
299
+
300
+ let windowSize = minWindow;
301
+ let uniqueLimit = 1;
302
+
303
+ while (windowSize <= stateHashes.length) {
304
+ const window = stateHashes.slice(-windowSize);
305
+ if (!window.includes(currentHash)) {
306
+ return false;
307
+ }
308
+
309
+ const unique = new Map<string, number>();
310
+ for (const hash of window) {
311
+ unique.set(hash, (unique.get(hash) || 0) + 1);
312
+ if (unique.size > uniqueLimit) {
313
+ break;
314
+ }
315
+ }
316
+
317
+ if (unique.size <= uniqueLimit) {
318
+ debugLog(`DEAD LOOP DETECTED: ${window.join(', ')}`);
319
+ return true;
320
+ }
321
+
322
+ windowSize += increment;
323
+ uniqueLimit += 1;
324
+ }
325
+
326
+ return false;
327
+ }
328
+
329
+ /**
330
+ * Get the last N transitions
331
+ */
332
+ getRecentTransitions(count = 5): StateTransition[] {
333
+ return this.stateHistory.slice(-count);
334
+ }
335
+
336
+ /**
337
+ * Scan knowledge directory for .md files and cache them
338
+ */
339
+ private scanKnowledgeFiles(): void {
340
+ const now = new Date();
341
+
342
+ // Only rescan every 30 seconds to avoid excessive file I/O
343
+ if (this.lastKnowledgeScan && now.getTime() - this.lastKnowledgeScan.getTime() < 30000) {
344
+ return;
345
+ }
346
+
347
+ this.knowledgeCache = [];
348
+
349
+ if (!existsSync(this.knowledgeDir)) {
350
+ debugLog(`Knowledge directory not found: ${this.knowledgeDir}`);
351
+ return;
352
+ }
353
+
354
+ try {
355
+ const files = readdirSync(this.knowledgeDir, { recursive: true })
356
+ .filter((file) => typeof file === 'string' && file.endsWith('.md'))
357
+ .map((file) => join(this.knowledgeDir, file as string));
358
+
359
+ for (const filePath of files) {
360
+ try {
361
+ const fileContent = readFileSync(filePath, 'utf8');
362
+ const parsed = matter(fileContent);
363
+
364
+ const urlPattern = parsed.data.url || parsed.data.path || '*';
365
+
366
+ this.knowledgeCache.push({
367
+ filePath,
368
+ url: urlPattern,
369
+ ...parsed.data,
370
+ content: parsed.content,
371
+ });
372
+
373
+ debugLog(`Loaded knowledge file: ${filePath} (pattern: ${urlPattern})`);
374
+ } catch (error) {
375
+ debugLog(`Failed to load knowledge file ${filePath}:`, error);
376
+ }
377
+ }
378
+
379
+ this.lastKnowledgeScan = now;
380
+ debugLog(`Scanned ${this.knowledgeCache.length} knowledge files`);
381
+ } catch (error) {
382
+ debugLog('Failed to scan knowledge directory:', error);
383
+ }
384
+ }
385
+ /**
386
+ * Get relevant knowledge files for current state
387
+ */
388
+ getRelevantKnowledge(): Knowledge[] {
389
+ if (!this.currentState) return [];
390
+
391
+ this.scanKnowledgeFiles();
392
+
393
+ const actionResult = ActionResult.fromState(this.currentState);
394
+ return this.knowledgeCache.filter((knowledge) => actionResult.isMatchedBy(knowledge));
395
+ }
396
+
397
+ /**
398
+ * Get relevant experience files for current state
399
+ */
400
+ getRelevantExperience(): string[] {
401
+ if (!this.currentState) {
402
+ return [];
403
+ }
404
+ const actionResult = ActionResult.fromState(this.currentState);
405
+ return this.experienceTracker.getRelevantExperience(actionResult).map((experience) => experience.content);
406
+ }
407
+
408
+ /**
409
+ * Get all context for current state (knowledge + experience)
410
+ */
411
+ getCurrentContext(): {
412
+ state: WebPageState;
413
+ knowledge: Knowledge[];
414
+ experience: string[];
415
+ recentTransitions: StateTransition[];
416
+ } {
417
+ if (!this.currentState) {
418
+ throw new Error('No current state available');
419
+ }
420
+
421
+ return {
422
+ state: this.currentState,
423
+ knowledge: this.getRelevantKnowledge(),
424
+ experience: this.getRelevantExperience(),
425
+ recentTransitions: this.getRecentTransitions(),
426
+ };
427
+ }
428
+
429
+ /**
430
+ * Check if we've been in this state before
431
+ */
432
+ hasVisitedState(path: string): boolean {
433
+ return this.allVisitedUrls.has(normalizeUrl(path));
434
+ }
435
+
436
+ getAllVisitedUrls(): Set<string> {
437
+ return this.allVisitedUrls;
438
+ }
439
+
440
+ /**
441
+ * Get how many times we've visited a specific path
442
+ */
443
+ getVisitCount(path: string): number {
444
+ return this.stateHistory.filter((transition) => normalizeUrl(transition.toState.url) === normalizeUrl(path)).length;
445
+ }
446
+
447
+ /**
448
+ * Find the most recent transition to a specific path
449
+ */
450
+ getLastVisitToPath(path: string): StateTransition | null {
451
+ for (let i = this.stateHistory.length - 1; i >= 0; i--) {
452
+ if (normalizeUrl(this.stateHistory[i].toState.url) === normalizeUrl(path)) {
453
+ return this.stateHistory[i];
454
+ }
455
+ }
456
+ return null;
457
+ }
458
+
459
+ /**
460
+ * Get previous state from history for comparison.
461
+ * If the last transition changed URL, returns the fromState (for URL change detection).
462
+ * Otherwise returns the most recent toState with content (for diffing).
463
+ */
464
+ getPreviousState(): WebPageState | null {
465
+ if (this.stateHistory.length === 0) return null;
466
+
467
+ const lastTransition = this.stateHistory[this.stateHistory.length - 1];
468
+
469
+ if (lastTransition.fromState?.url !== lastTransition.toState?.url) {
470
+ return lastTransition.fromState;
471
+ }
472
+
473
+ for (let i = this.stateHistory.length - 1; i >= 0; i--) {
474
+ const toState = this.stateHistory[i].toState;
475
+
476
+ if (!toState) continue;
477
+ if (toState.id === this.currentState?.id) continue;
478
+
479
+ if (toState.html || toState.ariaSnapshot) {
480
+ return toState;
481
+ }
482
+ }
483
+
484
+ return null;
485
+ }
486
+
487
+ /**
488
+ * Load HTML content from file
489
+ */
490
+ loadHtmlFromFile(htmlFile: string): string | null {
491
+ try {
492
+ const filePath = outputPath('states', htmlFile);
493
+ if (existsSync(filePath)) {
494
+ return readFileSync(filePath, 'utf8');
495
+ }
496
+ return null;
497
+ } catch (error) {
498
+ debugLog('Failed to load HTML from file:', error);
499
+ return null;
500
+ }
501
+ }
502
+
503
+ /**
504
+ * Clear state history (useful for testing or reset)
505
+ * Note: This preserves the current state, only clears navigation history
506
+ */
507
+ clearHistory(): void {
508
+ this.stateHistory = [];
509
+ debugLog('State history cleared');
510
+ }
511
+
512
+ /**
513
+ * Get the number of active state change listeners
514
+ */
515
+ getListenerCount(): number {
516
+ return this.stateChangeListeners.length;
517
+ }
518
+
519
+ /**
520
+ * Clear all state change listeners
521
+ */
522
+ clearListeners(): void {
523
+ this.stateChangeListeners = [];
524
+ debugLog('All state change listeners cleared');
525
+ }
526
+
527
+ /**
528
+ * Complete cleanup of the StateManager instance
529
+ * Clears all state, history, listeners, and caches
530
+ */
531
+ cleanup(): void {
532
+ this.currentState = null;
533
+ this.stateHistory = [];
534
+ this.allVisitedUrls.clear();
535
+ this.stateChangeListeners = [];
536
+ this.knowledgeCache = [];
537
+ this.lastKnowledgeScan = null;
538
+ this.nextStateId = 1;
539
+
540
+ // Clean up experience tracker if it has cleanup method
541
+ if (this.experienceTracker && typeof this.experienceTracker.cleanup === 'function') {
542
+ this.experienceTracker.cleanup();
543
+ }
544
+
545
+ debugLog('StateManager cleanup completed');
546
+ }
547
+ }
548
+
549
+ export function normalizeUrl(url: string): string {
550
+ try {
551
+ const parsed = new URL(url, 'http://localhost');
552
+ return parsed.pathname.replace(/^\/+|\/+$/g, '');
553
+ } catch {
554
+ return url.replace(/^\/+|\/+$/g, '');
555
+ }
556
+ }
package/src/stats.ts ADDED
@@ -0,0 +1,53 @@
1
+ interface TokenUsage {
2
+ input: number;
3
+ output: number;
4
+ total: number;
5
+ }
6
+
7
+ export class Stats {
8
+ static startTime = Date.now();
9
+ static researches = 0;
10
+ static tests = 0;
11
+ static plans = 0;
12
+ static models: Record<string, TokenUsage> = {};
13
+
14
+ static recordTokens(_agent: string, model: string, usage: TokenUsage): void {
15
+ if (!Stats.models[model]) {
16
+ Stats.models[model] = { input: 0, output: 0, total: 0 };
17
+ }
18
+ Stats.models[model].input += usage.input;
19
+ Stats.models[model].output += usage.output;
20
+ Stats.models[model].total += usage.total;
21
+ }
22
+
23
+ static getElapsedTime(): string {
24
+ const elapsed = Date.now() - Stats.startTime;
25
+ const seconds = Math.floor(elapsed / 1000) % 60;
26
+ const minutes = Math.floor(elapsed / 60000) % 60;
27
+ const hours = Math.floor(elapsed / 3600000);
28
+
29
+ if (hours > 0) {
30
+ return `${hours}h ${minutes}m ${seconds}s`;
31
+ }
32
+ if (minutes > 0) {
33
+ return `${minutes}m ${seconds}s`;
34
+ }
35
+ return `${seconds}s`;
36
+ }
37
+
38
+ static humanizeTokens(num: number): string {
39
+ if (num >= 1_000_000) {
40
+ return `${(num / 1_000_000).toFixed(1)}M`;
41
+ }
42
+ if (num >= 1_000) {
43
+ return `${(num / 1_000).toFixed(0)}K`;
44
+ }
45
+ return String(num);
46
+ }
47
+
48
+ static hasActivity(): boolean {
49
+ if (Stats.tests > 0 || Stats.plans > 0 || Stats.researches > 0) return true;
50
+ const totalTokens = Object.values(Stats.models).reduce((sum, m) => sum + m.total, 0);
51
+ return totalTokens > 0;
52
+ }
53
+ }