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,119 @@
1
+ import { Box, Text } from 'ink';
2
+ import React, { useEffect, useState } from 'react';
3
+ import { Test } from '../test-plan.ts';
4
+
5
+ export const WINDOW_SIZE = 7;
6
+
7
+ interface TaskPaneProps {
8
+ tasks: Test[];
9
+ scrollOffset?: number;
10
+ }
11
+
12
+ const getPriorityIcon = (priority: string): string => {
13
+ switch (priority.toLowerCase()) {
14
+ case 'high':
15
+ return '⭆';
16
+ case 'medium':
17
+ return '⇒';
18
+ case 'low':
19
+ return '⇝';
20
+ default:
21
+ return '⇢';
22
+ }
23
+ };
24
+
25
+ const TaskPane: React.FC<TaskPaneProps> = React.memo(({ tasks, scrollOffset = 0 }) => {
26
+ const [blinkOn, setBlinkOn] = useState(false);
27
+
28
+ useEffect(() => {
29
+ const hasInProgress = tasks.some((task) => task.status === 'in_progress');
30
+ if (!hasInProgress) {
31
+ setBlinkOn(false);
32
+ return;
33
+ }
34
+
35
+ const interval = setInterval(() => {
36
+ setBlinkOn((prev) => !prev);
37
+ }, 1500);
38
+
39
+ return () => {
40
+ clearInterval(interval);
41
+ };
42
+ }, [tasks]);
43
+
44
+ const visibleTasks = tasks.filter((t) => t.enabled);
45
+ const completedCount = visibleTasks.filter((t) => t.hasFinished).length;
46
+
47
+ const inProgressIdx = visibleTasks.findIndex((t) => t.status === 'in_progress');
48
+ let effectiveOffset = scrollOffset;
49
+ if (inProgressIdx >= 0 && (inProgressIdx < scrollOffset || inProgressIdx >= scrollOffset + WINDOW_SIZE)) {
50
+ effectiveOffset = Math.max(0, inProgressIdx - Math.floor(WINDOW_SIZE / 2));
51
+ }
52
+
53
+ const clampedOffset = Math.min(effectiveOffset, Math.max(0, visibleTasks.length - WINDOW_SIZE));
54
+ const aboveCount = clampedOffset;
55
+ const belowCount = Math.max(0, visibleTasks.length - clampedOffset - WINDOW_SIZE);
56
+ const windowTasks = visibleTasks.slice(clampedOffset, clampedOffset + WINDOW_SIZE);
57
+
58
+ return (
59
+ <Box flexDirection="column" flexGrow={1}>
60
+ <Box borderStyle="round" borderColor="dim" padding={1} flexDirection="column">
61
+ <Box justifyContent="space-between" marginBottom={1}>
62
+ <Text color="dim">📋 Tests</Text>
63
+ <Box>
64
+ <Text color="dim" bold>
65
+ Ctrl+E
66
+ </Text>
67
+ <Text color="dim"> edit </Text>
68
+ <Text color="dim">
69
+ [{completedCount}/{visibleTasks.length}]
70
+ </Text>
71
+ </Box>
72
+ </Box>
73
+
74
+ {aboveCount > 0 && (
75
+ <Text color="dim">
76
+ {' '}▲ {aboveCount} more
77
+ </Text>
78
+ )}
79
+
80
+ {windowTasks.map((task: Test, windowIndex) => {
81
+ const globalIndex = clampedOffset + windowIndex;
82
+ const inProgress = task.status === 'in_progress';
83
+ let taskColor = 'dim';
84
+ let strikethrough = false;
85
+
86
+ if (task.isSuccessful) {
87
+ taskColor = 'green';
88
+ strikethrough = true;
89
+ } else if (task.isSkipped) {
90
+ taskColor = 'yellow';
91
+ strikethrough = true;
92
+ } else if (task.hasFailed) {
93
+ taskColor = 'red';
94
+ } else if (inProgress) {
95
+ taskColor = blinkOn ? 'white' : 'dim';
96
+ }
97
+
98
+ return (
99
+ <Box key={task.id || globalIndex} flexDirection="row" marginY={0}>
100
+ <Text> {getPriorityIcon(task.priority)}</Text>
101
+ <Text color={taskColor} strikethrough={strikethrough} wrap="truncate-end">
102
+ {' '}
103
+ {globalIndex + 1}. {task.scenario}
104
+ </Text>
105
+ </Box>
106
+ );
107
+ })}
108
+
109
+ {belowCount > 0 && (
110
+ <Text color="dim">
111
+ {' '}▼ {belowCount} more
112
+ </Text>
113
+ )}
114
+ </Box>
115
+ </Box>
116
+ );
117
+ });
118
+
119
+ export default TaskPane;
@@ -0,0 +1,83 @@
1
+ import { Box, Text } from 'ink';
2
+ import React from 'react';
3
+ import { useEffect, useState } from 'react';
4
+ import { ConfigParser } from '../config.js';
5
+
6
+ interface ConfigInfo {
7
+ aiProvider: string;
8
+ playwrightUrl: string;
9
+ loaded: boolean;
10
+ error?: string;
11
+ }
12
+
13
+ const Welcome: React.FC = () => {
14
+ const [configInfo, setConfigInfo] = useState<ConfigInfo>({
15
+ aiProvider: '',
16
+ playwrightUrl: '',
17
+ loaded: false,
18
+ });
19
+
20
+ useEffect(() => {
21
+ const loadConfig = async () => {
22
+ try {
23
+ const configParser = ConfigParser.getInstance();
24
+ const loadedConfig = await configParser.loadConfig();
25
+
26
+ let aiProviderName = 'Not configured';
27
+ if (loadedConfig.ai?.model) {
28
+ const model = loadedConfig.ai.model;
29
+ aiProviderName = model?.modelId || model?.provider || 'configured';
30
+ }
31
+
32
+ setConfigInfo({
33
+ aiProvider: aiProviderName,
34
+ playwrightUrl: loadedConfig.playwright?.url || 'Not configured',
35
+ loaded: true,
36
+ });
37
+ } catch (error) {
38
+ setConfigInfo({
39
+ aiProvider: '',
40
+ playwrightUrl: '',
41
+ loaded: true,
42
+ error: error instanceof Error ? error.message : 'Unknown error',
43
+ });
44
+ }
45
+ };
46
+
47
+ loadConfig();
48
+ }, []);
49
+
50
+ return (
51
+ <Box flexDirection="column" padding={1}>
52
+ <Box marginBottom={1} alignItems="center">
53
+ <Text color="yellow" bold>
54
+ 🧐 Let's do some exploratory testing!
55
+ </Text>
56
+ </Box>
57
+ {configInfo.loaded && !configInfo.error && (
58
+ <Box flexDirection="row" marginTop={1}>
59
+ <Box marginRight={2}>
60
+ <Text color="gray" bold>
61
+ [Config]
62
+ </Text>
63
+ </Box>
64
+
65
+ <Box marginRight={2}>
66
+ <Text color="gray">AI: </Text>
67
+ <Text color="cyan" bold>
68
+ {configInfo.aiProvider}
69
+ </Text>
70
+ </Box>
71
+ <Box>
72
+ <Text color="gray">URL: </Text>
73
+ <Text color="cyan" bold>
74
+ {configInfo.playwrightUrl}
75
+ </Text>
76
+ </Box>
77
+ </Box>
78
+ )}
79
+ </Box>
80
+ );
81
+ };
82
+
83
+ export default Welcome;
@@ -0,0 +1,118 @@
1
+ import { Box, Text } from 'ink';
2
+ import React from 'react';
3
+ import type { ExplorbotConfig } from '../config.js';
4
+ import type { KnowledgeTracker } from '../knowledge-tracker.js';
5
+ import { Reporter } from '../reporter.js';
6
+
7
+ interface ChecklistItem {
8
+ label: string;
9
+ description: string;
10
+ enabled: boolean;
11
+ value?: string;
12
+ suggestion?: string;
13
+ }
14
+
15
+ interface WelcomeChecklistProps {
16
+ config: ExplorbotConfig;
17
+ knowledgeTracker: KnowledgeTracker;
18
+ }
19
+
20
+ const ChecklistRow: React.FC<{ item: ChecklistItem }> = ({ item }) => (
21
+ <Box>
22
+ <Text color={item.enabled ? 'green' : 'gray'}>{item.enabled ? ' ✓ ' : ' ○ '}</Text>
23
+ <Text color={item.enabled ? 'white' : 'gray'}>{item.label}</Text>
24
+ {item.value && <Text color="cyan"> ({item.value})</Text>}
25
+ <Text color="gray"> - {item.description}</Text>
26
+ {!item.enabled && item.suggestion && <Text color="yellow"> → {item.suggestion}</Text>}
27
+ </Box>
28
+ );
29
+
30
+ function getModelLabel(model: any): string | undefined {
31
+ if (!model) return undefined;
32
+ const modelId = model?.modelId;
33
+ const provider = model?.provider;
34
+ if (!modelId) return undefined;
35
+ if (provider) return `${provider}:${modelId}`;
36
+ return modelId;
37
+ }
38
+
39
+ const WelcomeChecklist: React.FC<WelcomeChecklistProps> = ({ config, knowledgeTracker }) => {
40
+ const knowledge = knowledgeTracker.listAllKnowledge();
41
+ const knowledgeCount = knowledge.length;
42
+
43
+ const langfusePublicKey = config.ai?.langfuse?.publicKey || process.env.LANGFUSE_PUBLIC_KEY;
44
+ const langfuseSecretKey = config.ai?.langfuse?.secretKey || process.env.LANGFUSE_SECRET_KEY;
45
+ const langfuseEnabled = config.ai?.langfuse?.enabled ?? Boolean(langfusePublicKey && langfuseSecretKey);
46
+
47
+ const items: ChecklistItem[] = [
48
+ {
49
+ label: 'Model',
50
+ description: 'default model for all agents',
51
+ enabled: Boolean(config.ai?.model),
52
+ value: getModelLabel(config.ai?.model),
53
+ suggestion: 'set ai.model in config',
54
+ },
55
+ {
56
+ label: 'Vision model',
57
+ description: 'analyze screenshots for visual assertions',
58
+ enabled: Boolean(config.ai?.visionModel || config.ai?.vision),
59
+ value: getModelLabel(config.ai?.visionModel),
60
+ suggestion: 'set ai.visionModel in config',
61
+ },
62
+ {
63
+ label: 'Agentic model',
64
+ description: 'smarter model for Captain & Pilot decisions',
65
+ enabled: Boolean(config.ai?.agenticModel),
66
+ value: getModelLabel(config.ai?.agenticModel),
67
+ suggestion: 'set ai.agenticModel in config',
68
+ },
69
+ {
70
+ label: 'Knowledge',
71
+ description: 'teach AI web app usage, pass credentials',
72
+ enabled: knowledgeCount > 0,
73
+ value: knowledgeCount > 0 ? `${knowledgeCount} file${knowledgeCount > 1 ? 's' : ''}` : undefined,
74
+ suggestion: 'use /learn',
75
+ },
76
+ {
77
+ label: 'Reporter',
78
+ description: 'get a complete test run report',
79
+ enabled: Reporter.resolveEnabled(config.reporter),
80
+ value: process.env.TESTOMATIO ? 'cloud report to Testomat.io' : undefined,
81
+ suggestion: 'set reporter.enabled in config',
82
+ },
83
+ {
84
+ label: 'Quartermaster',
85
+ description: 'additional a11y checks',
86
+ enabled: config.ai?.agents?.quartermaster?.enabled === true || (config as any).agents?.quartermaster?.enabled === true,
87
+ suggestion: 'enable ai.agents.quartermaster',
88
+ },
89
+ {
90
+ label: 'Fisherman',
91
+ description: 'prepare test data via API',
92
+ enabled: config.ai?.agents?.fisherman?.enabled === true || !!(config as any).api,
93
+ value: (config as any).api ? 'achieve mode' : 'replicate mode',
94
+ suggestion: 'enable ai.agents.fisherman or configure api section',
95
+ },
96
+ {
97
+ label: 'Langfuse',
98
+ description: 'collect execution reports and analyze failures',
99
+ enabled: langfuseEnabled,
100
+ suggestion: 'enable ai.langfuse',
101
+ },
102
+ ];
103
+
104
+ return (
105
+ <Box borderStyle="round" borderColor="gray" flexDirection="column" paddingX={1}>
106
+ <Box marginBottom={1}>
107
+ <Text color="cyan" bold>
108
+ Configuration
109
+ </Text>
110
+ </Box>
111
+ {items.map((item, index) => (
112
+ <ChecklistRow key={index} item={item} />
113
+ ))}
114
+ </Box>
115
+ );
116
+ };
117
+
118
+ export default WelcomeChecklist;
@@ -0,0 +1,102 @@
1
+ import { Box, Text } from 'ink';
2
+ import React from 'react';
3
+
4
+ interface CommandInfo {
5
+ command: string;
6
+ description: string;
7
+ examples?: string[];
8
+ }
9
+
10
+ interface WelcomeCommandsProps {
11
+ hasKnowledge: boolean;
12
+ }
13
+
14
+ const Command: React.FC<{ text: string }> = ({ text }) => (
15
+ <Text bold color="#9B59B6">
16
+ {text}
17
+ </Text>
18
+ );
19
+
20
+ const WelcomeCommands: React.FC<WelcomeCommandsProps> = ({ hasKnowledge }) => {
21
+ const commands: CommandInfo[] = [
22
+ {
23
+ command: '/explore',
24
+ description: 'AI creates test plan and runs all tests automatically',
25
+ examples: ['/explore', '/explore checkout flow'],
26
+ },
27
+ {
28
+ command: '/plan',
29
+ description: 'generate test scenarios for current page without running them',
30
+ examples: ['/plan', '/plan user registration'],
31
+ },
32
+ {
33
+ command: '/test',
34
+ description: 'run tests from current plan (requires /plan first)',
35
+ examples: ['/test', '/test 2', '/test *'],
36
+ },
37
+ {
38
+ command: '/navigate',
39
+ description: 'AI navigates to a specific page or state',
40
+ examples: ['/navigate /users/settings'],
41
+ },
42
+ {
43
+ command: '/research',
44
+ description: 'analyze current page and list available actions',
45
+ },
46
+ ];
47
+
48
+ const knowledgeCommand: CommandInfo = {
49
+ command: '/learn',
50
+ description: 'add knowledge about your app (credentials, workflows)',
51
+ examples: ['/learn login uses admin@test.com'],
52
+ };
53
+
54
+ return (
55
+ <Box flexDirection="column" paddingX={1} marginTop={1}>
56
+ <Box marginBottom={1}>
57
+ <Text>What should we do next?</Text>
58
+ </Box>
59
+
60
+ {!hasKnowledge && (
61
+ <Box flexDirection="column" marginBottom={1}>
62
+ <Box>
63
+ <Text color="yellow">→ </Text>
64
+ <Text>Start by adding knowledge about your app:</Text>
65
+ </Box>
66
+ <Box paddingLeft={2}>
67
+ <Command text={knowledgeCommand.command} />
68
+ <Text color="gray"> - {knowledgeCommand.description}</Text>
69
+ </Box>
70
+ {knowledgeCommand.examples && (
71
+ <Box paddingLeft={4}>
72
+ <Text color="gray" dimColor>
73
+ {knowledgeCommand.examples.join(' ')}
74
+ </Text>
75
+ </Box>
76
+ )}
77
+ </Box>
78
+ )}
79
+
80
+ <Box flexDirection="column">
81
+ {commands.map((cmd, index) => (
82
+ <Box key={index} flexDirection="column">
83
+ <Box>
84
+ <Text> </Text>
85
+ <Command text={cmd.command} />
86
+ <Text color="gray"> - {cmd.description}</Text>
87
+ </Box>
88
+ {cmd.examples && (
89
+ <Box paddingLeft={4}>
90
+ <Text color="gray" dimColor>
91
+ {cmd.examples.join(' ')}
92
+ </Text>
93
+ </Box>
94
+ )}
95
+ </Box>
96
+ ))}
97
+ </Box>
98
+ </Box>
99
+ );
100
+ };
101
+
102
+ export default WelcomeCommands;
@@ -0,0 +1,35 @@
1
+ import { useSyncExternalStore } from 'react';
2
+ import type { CommandAutocompleteSuggestion } from '../command-handler.js';
3
+
4
+ interface AutocompleteState {
5
+ suggestions: CommandAutocompleteSuggestion[];
6
+ argumentHint?: string;
7
+ selectedIndex: number;
8
+ visible: boolean;
9
+ }
10
+
11
+ const listeners = new Set<() => void>();
12
+
13
+ let state: AutocompleteState = {
14
+ suggestions: [],
15
+ selectedIndex: 0,
16
+ visible: false,
17
+ };
18
+
19
+ const subscribe = (listener: () => void) => {
20
+ listeners.add(listener);
21
+ return () => {
22
+ listeners.delete(listener);
23
+ };
24
+ };
25
+
26
+ const getSnapshot = () => state;
27
+
28
+ export const setAutocompleteState = (next: AutocompleteState) => {
29
+ state = next;
30
+ for (const listener of listeners) {
31
+ listener();
32
+ }
33
+ };
34
+
35
+ export const useAutocompleteState = () => useSyncExternalStore(subscribe, getSnapshot);
@@ -0,0 +1,170 @@
1
+ import { Buffer } from 'node:buffer';
2
+
3
+ const metaCharRe = /^[a-zA-Z0-9]$/;
4
+ const fnKeyRe = /^(O|N|\[|\[\[)(?:(\d+)(?:;(\d+))?([~^$])|(?:1;)?(\d+)?([a-zA-Z]))/;
5
+
6
+ const keyName: Record<string, string> = {
7
+ OP: 'f1',
8
+ OQ: 'f2',
9
+ OR: 'f3',
10
+ OS: 'f4',
11
+ '[11~': 'f1',
12
+ '[12~': 'f2',
13
+ '[13~': 'f3',
14
+ '[14~': 'f4',
15
+ '[[A': 'f1',
16
+ '[[B': 'f2',
17
+ '[[C': 'f3',
18
+ '[[D': 'f4',
19
+ '[[E': 'f5',
20
+ '[15~': 'f5',
21
+ '[17~': 'f6',
22
+ '[18~': 'f7',
23
+ '[19~': 'f8',
24
+ '[20~': 'f9',
25
+ '[21~': 'f10',
26
+ '[23~': 'f11',
27
+ '[24~': 'f12',
28
+ '[A': 'up',
29
+ '[B': 'down',
30
+ '[C': 'right',
31
+ '[D': 'left',
32
+ '[E': 'clear',
33
+ '[F': 'end',
34
+ '[H': 'home',
35
+ OA: 'up',
36
+ OB: 'down',
37
+ OC: 'right',
38
+ OD: 'left',
39
+ OE: 'clear',
40
+ OF: 'end',
41
+ OH: 'home',
42
+ '[1~': 'home',
43
+ '[2~': 'insert',
44
+ '[3~': 'delete',
45
+ '[4~': 'end',
46
+ '[5~': 'pageup',
47
+ '[6~': 'pagedown',
48
+ '[[5~': 'pageup',
49
+ '[[6~': 'pagedown',
50
+ '[7~': 'home',
51
+ '[8~': 'end',
52
+ '[a': 'up',
53
+ '[b': 'down',
54
+ '[c': 'right',
55
+ '[d': 'left',
56
+ '[e': 'clear',
57
+ '[2$': 'insert',
58
+ '[3$': 'delete',
59
+ '[5$': 'pageup',
60
+ '[6$': 'pagedown',
61
+ '[7$': 'home',
62
+ '[8$': 'end',
63
+ Oa: 'up',
64
+ Ob: 'down',
65
+ Oc: 'right',
66
+ Od: 'left',
67
+ Oe: 'clear',
68
+ '[2^': 'insert',
69
+ '[3^': 'delete',
70
+ '[5^': 'pageup',
71
+ '[6^': 'pagedown',
72
+ '[7^': 'home',
73
+ '[8^': 'end',
74
+ '[Z': 'tab',
75
+ };
76
+
77
+ export const nonAlphanumericKeys = [...Object.values(keyName), 'backspace'];
78
+
79
+ const isShiftKey = (code: string) => ['[a', '[b', '[c', '[d', '[e', '[2$', '[3$', '[5$', '[6$', '[7$', '[8$', '[Z'].includes(code);
80
+
81
+ const isCtrlKey = (code: string) => ['Oa', 'Ob', 'Oc', 'Od', 'Oe', '[2^', '[3^', '[5^', '[6^', '[7^', '[8^'].includes(code);
82
+
83
+ export default function parseKeypress(value: string | Buffer = '') {
84
+ let parts: RegExpExecArray | null;
85
+ let sequence = value;
86
+
87
+ if (Buffer.isBuffer(sequence)) {
88
+ if (sequence[0] > 127 && sequence[1] === undefined) {
89
+ sequence[0] -= 128;
90
+ sequence = `\x1b${String(sequence)}`;
91
+ } else {
92
+ sequence = String(sequence);
93
+ }
94
+ } else if (sequence !== undefined && typeof sequence !== 'string') {
95
+ sequence = String(sequence);
96
+ } else if (!sequence) {
97
+ sequence = '';
98
+ }
99
+
100
+ const key = {
101
+ name: '',
102
+ ctrl: false,
103
+ meta: false,
104
+ shift: false,
105
+ option: false,
106
+ sequence,
107
+ raw: sequence as string | undefined,
108
+ code: undefined as string | undefined,
109
+ };
110
+
111
+ if (sequence === '\r') {
112
+ key.raw = undefined;
113
+ key.name = 'return';
114
+ } else if (sequence === '\n') {
115
+ key.name = 'enter';
116
+ } else if (sequence === '\t') {
117
+ key.name = 'tab';
118
+ } else if (sequence === '\b' || sequence === '\x1b\b') {
119
+ key.name = 'backspace';
120
+ key.meta = sequence.charAt(0) === '\x1b';
121
+ } else if (sequence === '\x7f' || sequence === '\x1b\x7f') {
122
+ key.name = 'backspace';
123
+ key.meta = sequence.charAt(0) === '\x1b';
124
+ } else if (sequence === '\x1b' || sequence === '\x1b\x1b') {
125
+ key.name = 'escape';
126
+ key.meta = sequence.length === 2;
127
+ } else if (sequence === ' ' || sequence === '\x1b ') {
128
+ key.name = 'space';
129
+ key.meta = sequence.length === 2;
130
+ } else if (sequence.length === 1 && sequence <= '\x1a') {
131
+ key.name = String.fromCharCode(sequence.charCodeAt(0) + 'a'.charCodeAt(0) - 1);
132
+ key.ctrl = true;
133
+ } else if (sequence.length === 1 && sequence >= '0' && sequence <= '9') {
134
+ key.name = 'number';
135
+ } else if (sequence.length === 1 && sequence >= 'a' && sequence <= 'z') {
136
+ key.name = sequence;
137
+ } else if (sequence.length === 1 && sequence >= 'A' && sequence <= 'Z') {
138
+ key.name = sequence.toLowerCase();
139
+ key.shift = true;
140
+ } else if (sequence.startsWith('\x1b') && sequence.length === 2 && metaCharRe.test(sequence[1] || '')) {
141
+ key.meta = true;
142
+ key.shift = /^[A-Z]$/.test(sequence[1] || '');
143
+ } else {
144
+ let escapePrefixLength = 0;
145
+ while (sequence[escapePrefixLength] === '\x1b') {
146
+ escapePrefixLength += 1;
147
+ }
148
+ const sequenceBody = sequence.slice(escapePrefixLength);
149
+ parts = fnKeyRe.exec(sequenceBody);
150
+ if (!parts) {
151
+ return key;
152
+ }
153
+
154
+ if (escapePrefixLength > 1) {
155
+ key.option = true;
156
+ }
157
+
158
+ const code = [parts[1], parts[2], parts[4], parts[6]].filter(Boolean).join('');
159
+ const modifier = Number(parts[3] || parts[5] || 1) - 1;
160
+ key.ctrl = Boolean(modifier & 4);
161
+ key.meta = Boolean(modifier & 10);
162
+ key.shift = Boolean(modifier & 1);
163
+ key.code = code;
164
+ key.name = keyName[code] || '';
165
+ key.shift = isShiftKey(code) || key.shift;
166
+ key.ctrl = isCtrlKey(code) || key.ctrl;
167
+ }
168
+
169
+ return key;
170
+ }