explorbot 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (329) hide show
  1. package/LICENSE +94 -0
  2. package/README.md +267 -0
  3. package/assets/sample-files/sample.docx +0 -0
  4. package/assets/sample-files/sample.mp3 +0 -0
  5. package/assets/sample-files/sample.mp4 +0 -0
  6. package/assets/sample-files/sample.pdf +21 -0
  7. package/assets/sample-files/sample.png +0 -0
  8. package/assets/sample-files/sample.xlsx +0 -0
  9. package/assets/sample-files/sample.zip +0 -0
  10. package/dist/assets/sample-files/sample.docx +0 -0
  11. package/dist/assets/sample-files/sample.mp3 +0 -0
  12. package/dist/assets/sample-files/sample.mp4 +0 -0
  13. package/dist/assets/sample-files/sample.pdf +21 -0
  14. package/dist/assets/sample-files/sample.png +0 -0
  15. package/dist/assets/sample-files/sample.xlsx +0 -0
  16. package/dist/assets/sample-files/sample.zip +0 -0
  17. package/dist/bin/explorbot-cli.js +683 -0
  18. package/dist/bin/explorbot-cli.js.map +1 -0
  19. package/dist/boat/api-tester/bin/apibot-cli.js +5 -0
  20. package/dist/boat/api-tester/bin/apibot-cli.js.map +1 -0
  21. package/dist/boat/api-tester/example/apibot.config.js +31 -0
  22. package/dist/boat/api-tester/example/apibot.config.js.map +1 -0
  23. package/dist/boat/api-tester/src/ai/chief/styles.js +13 -0
  24. package/dist/boat/api-tester/src/ai/chief/styles.js.map +1 -0
  25. package/dist/boat/api-tester/src/ai/chief.js +301 -0
  26. package/dist/boat/api-tester/src/ai/chief.js.map +1 -0
  27. package/dist/boat/api-tester/src/ai/curler-tools.js +263 -0
  28. package/dist/boat/api-tester/src/ai/curler-tools.js.map +1 -0
  29. package/dist/boat/api-tester/src/ai/curler.js +271 -0
  30. package/dist/boat/api-tester/src/ai/curler.js.map +1 -0
  31. package/dist/boat/api-tester/src/api-client.js +26 -0
  32. package/dist/boat/api-tester/src/api-client.js.map +1 -0
  33. package/dist/boat/api-tester/src/apibot.js +166 -0
  34. package/dist/boat/api-tester/src/apibot.js.map +1 -0
  35. package/dist/boat/api-tester/src/cli.js +262 -0
  36. package/dist/boat/api-tester/src/cli.js.map +1 -0
  37. package/dist/boat/api-tester/src/config.js +159 -0
  38. package/dist/boat/api-tester/src/config.js.map +1 -0
  39. package/dist/prompts/audit-rules.md +124 -0
  40. package/dist/rules/chief/general.md +11 -0
  41. package/dist/rules/chief/styles/curious.md +12 -0
  42. package/dist/rules/chief/styles/hacker.md +19 -0
  43. package/dist/rules/chief/styles/normal.md +11 -0
  44. package/dist/rules/chief/styles/psycho.md +17 -0
  45. package/dist/rules/navigator/multiple-locator.md +47 -0
  46. package/dist/rules/navigator/output.md +69 -0
  47. package/dist/rules/navigator/verification-actions.md +122 -0
  48. package/dist/rules/navigator/verification-output.md +53 -0
  49. package/dist/rules/planner/styles/curious.md +39 -0
  50. package/dist/rules/planner/styles/normal.md +21 -0
  51. package/dist/rules/planner/styles/psycho.md +14 -0
  52. package/dist/rules/researcher/list-element.md +11 -0
  53. package/dist/rules/researcher/screenshot-ui-map.md +30 -0
  54. package/dist/rules/researcher/section-ui-map.md +18 -0
  55. package/dist/rules/researcher/ui-map-table.md +18 -0
  56. package/dist/src/action-result.js +574 -0
  57. package/dist/src/action-result.js.map +1 -0
  58. package/dist/src/action.js +388 -0
  59. package/dist/src/action.js.map +1 -0
  60. package/dist/src/activity.js +86 -0
  61. package/dist/src/activity.js.map +1 -0
  62. package/dist/src/ai/agent.js +2 -0
  63. package/dist/src/ai/agent.js.map +1 -0
  64. package/dist/src/ai/bosun.js +443 -0
  65. package/dist/src/ai/bosun.js.map +1 -0
  66. package/dist/src/ai/captain/idle-mode.js +102 -0
  67. package/dist/src/ai/captain/idle-mode.js.map +1 -0
  68. package/dist/src/ai/captain/mixin.js +11 -0
  69. package/dist/src/ai/captain/mixin.js.map +1 -0
  70. package/dist/src/ai/captain/test-mode.js +251 -0
  71. package/dist/src/ai/captain/test-mode.js.map +1 -0
  72. package/dist/src/ai/captain/web-mode.js +124 -0
  73. package/dist/src/ai/captain/web-mode.js.map +1 -0
  74. package/dist/src/ai/captain.js +442 -0
  75. package/dist/src/ai/captain.js.map +1 -0
  76. package/dist/src/ai/conversation.js +176 -0
  77. package/dist/src/ai/conversation.js.map +1 -0
  78. package/dist/src/ai/experience-compactor.js +232 -0
  79. package/dist/src/ai/experience-compactor.js.map +1 -0
  80. package/dist/src/ai/fisherman-tools.js +154 -0
  81. package/dist/src/ai/fisherman-tools.js.map +1 -0
  82. package/dist/src/ai/fisherman.js +184 -0
  83. package/dist/src/ai/fisherman.js.map +1 -0
  84. package/dist/src/ai/historian.js +384 -0
  85. package/dist/src/ai/historian.js.map +1 -0
  86. package/dist/src/ai/navigator.js +493 -0
  87. package/dist/src/ai/navigator.js.map +1 -0
  88. package/dist/src/ai/pilot.js +684 -0
  89. package/dist/src/ai/pilot.js.map +1 -0
  90. package/dist/src/ai/planner/session-dedup.js +28 -0
  91. package/dist/src/ai/planner/session-dedup.js.map +1 -0
  92. package/dist/src/ai/planner/styles.js +15 -0
  93. package/dist/src/ai/planner/styles.js.map +1 -0
  94. package/dist/src/ai/planner/subpages.js +118 -0
  95. package/dist/src/ai/planner/subpages.js.map +1 -0
  96. package/dist/src/ai/planner.js +486 -0
  97. package/dist/src/ai/planner.js.map +1 -0
  98. package/dist/src/ai/provider.js +540 -0
  99. package/dist/src/ai/provider.js.map +1 -0
  100. package/dist/src/ai/quartermaster.js +210 -0
  101. package/dist/src/ai/quartermaster.js.map +1 -0
  102. package/dist/src/ai/researcher/cache.js +95 -0
  103. package/dist/src/ai/researcher/cache.js.map +1 -0
  104. package/dist/src/ai/researcher/coordinates.js +210 -0
  105. package/dist/src/ai/researcher/coordinates.js.map +1 -0
  106. package/dist/src/ai/researcher/deep-analysis.js +364 -0
  107. package/dist/src/ai/researcher/deep-analysis.js.map +1 -0
  108. package/dist/src/ai/researcher/fingerprint-worker.js +46 -0
  109. package/dist/src/ai/researcher/fingerprint-worker.js.map +1 -0
  110. package/dist/src/ai/researcher/focus.js +37 -0
  111. package/dist/src/ai/researcher/focus.js.map +1 -0
  112. package/dist/src/ai/researcher/locators.js +242 -0
  113. package/dist/src/ai/researcher/locators.js.map +1 -0
  114. package/dist/src/ai/researcher/mixin.js +3 -0
  115. package/dist/src/ai/researcher/mixin.js.map +1 -0
  116. package/dist/src/ai/researcher/parser.js +160 -0
  117. package/dist/src/ai/researcher/parser.js.map +1 -0
  118. package/dist/src/ai/researcher/research-result.js +110 -0
  119. package/dist/src/ai/researcher/research-result.js.map +1 -0
  120. package/dist/src/ai/researcher.js +776 -0
  121. package/dist/src/ai/researcher.js.map +1 -0
  122. package/dist/src/ai/rules.js +368 -0
  123. package/dist/src/ai/rules.js.map +1 -0
  124. package/dist/src/ai/task-agent.js +110 -0
  125. package/dist/src/ai/task-agent.js.map +1 -0
  126. package/dist/src/ai/tester.js +840 -0
  127. package/dist/src/ai/tester.js.map +1 -0
  128. package/dist/src/ai/tools.js +980 -0
  129. package/dist/src/ai/tools.js.map +1 -0
  130. package/dist/src/api/api-client.js +91 -0
  131. package/dist/src/api/api-client.js.map +1 -0
  132. package/dist/src/api/request-result.js +177 -0
  133. package/dist/src/api/request-result.js.map +1 -0
  134. package/dist/src/api/request-store.js +109 -0
  135. package/dist/src/api/request-store.js.map +1 -0
  136. package/dist/src/api/spec-reader.js +148 -0
  137. package/dist/src/api/spec-reader.js.map +1 -0
  138. package/dist/src/api/xhr-capture.js +91 -0
  139. package/dist/src/api/xhr-capture.js.map +1 -0
  140. package/dist/src/browser-server.js +67 -0
  141. package/dist/src/browser-server.js.map +1 -0
  142. package/dist/src/command-handler.js +363 -0
  143. package/dist/src/command-handler.js.map +1 -0
  144. package/dist/src/commands/add-rule-command.js +52 -0
  145. package/dist/src/commands/add-rule-command.js.map +1 -0
  146. package/dist/src/commands/base-command.js +14 -0
  147. package/dist/src/commands/base-command.js.map +1 -0
  148. package/dist/src/commands/clean-command.js +67 -0
  149. package/dist/src/commands/clean-command.js.map +1 -0
  150. package/dist/src/commands/context-aria-command.js +18 -0
  151. package/dist/src/commands/context-aria-command.js.map +1 -0
  152. package/dist/src/commands/context-command.js +57 -0
  153. package/dist/src/commands/context-command.js.map +1 -0
  154. package/dist/src/commands/context-data-command.js +25 -0
  155. package/dist/src/commands/context-data-command.js.map +1 -0
  156. package/dist/src/commands/context-experience-command.js +41 -0
  157. package/dist/src/commands/context-experience-command.js.map +1 -0
  158. package/dist/src/commands/context-html-command.js +26 -0
  159. package/dist/src/commands/context-html-command.js.map +1 -0
  160. package/dist/src/commands/context-knowledge-command.js +36 -0
  161. package/dist/src/commands/context-knowledge-command.js.map +1 -0
  162. package/dist/src/commands/debug-command.js +12 -0
  163. package/dist/src/commands/debug-command.js.map +1 -0
  164. package/dist/src/commands/drill-command.js +29 -0
  165. package/dist/src/commands/drill-command.js.map +1 -0
  166. package/dist/src/commands/exit-command.js +26 -0
  167. package/dist/src/commands/exit-command.js.map +1 -0
  168. package/dist/src/commands/explore-command.js +124 -0
  169. package/dist/src/commands/explore-command.js.map +1 -0
  170. package/dist/src/commands/freesail-command.js +84 -0
  171. package/dist/src/commands/freesail-command.js.map +1 -0
  172. package/dist/src/commands/help-command.js +7 -0
  173. package/dist/src/commands/help-command.js.map +1 -0
  174. package/dist/src/commands/index.js +63 -0
  175. package/dist/src/commands/index.js.map +1 -0
  176. package/dist/src/commands/knows-command.js +54 -0
  177. package/dist/src/commands/knows-command.js.map +1 -0
  178. package/dist/src/commands/learn-command.js +35 -0
  179. package/dist/src/commands/learn-command.js.map +1 -0
  180. package/dist/src/commands/navigate-command.js +16 -0
  181. package/dist/src/commands/navigate-command.js.map +1 -0
  182. package/dist/src/commands/path-command.js +70 -0
  183. package/dist/src/commands/path-command.js.map +1 -0
  184. package/dist/src/commands/plan-clear-command.js +13 -0
  185. package/dist/src/commands/plan-clear-command.js.map +1 -0
  186. package/dist/src/commands/plan-command.js +36 -0
  187. package/dist/src/commands/plan-command.js.map +1 -0
  188. package/dist/src/commands/plan-edit-command.js +8 -0
  189. package/dist/src/commands/plan-edit-command.js.map +1 -0
  190. package/dist/src/commands/plan-load-command.js +16 -0
  191. package/dist/src/commands/plan-load-command.js.map +1 -0
  192. package/dist/src/commands/plan-reload-command.js +23 -0
  193. package/dist/src/commands/plan-reload-command.js.map +1 -0
  194. package/dist/src/commands/plan-save-command.js +22 -0
  195. package/dist/src/commands/plan-save-command.js.map +1 -0
  196. package/dist/src/commands/research-command.js +38 -0
  197. package/dist/src/commands/research-command.js.map +1 -0
  198. package/dist/src/commands/start-command.js +12 -0
  199. package/dist/src/commands/start-command.js.map +1 -0
  200. package/dist/src/commands/status-command.js +19 -0
  201. package/dist/src/commands/status-command.js.map +1 -0
  202. package/dist/src/commands/test-command.js +85 -0
  203. package/dist/src/commands/test-command.js.map +1 -0
  204. package/dist/src/components/ActivityPane.js +55 -0
  205. package/dist/src/components/ActivityPane.js.map +1 -0
  206. package/dist/src/components/AddKnowledge.js +122 -0
  207. package/dist/src/components/AddKnowledge.js.map +1 -0
  208. package/dist/src/components/AddRule.js +117 -0
  209. package/dist/src/components/AddRule.js.map +1 -0
  210. package/dist/src/components/App.js +313 -0
  211. package/dist/src/components/App.js.map +1 -0
  212. package/dist/src/components/Autocomplete.js +43 -0
  213. package/dist/src/components/Autocomplete.js.map +1 -0
  214. package/dist/src/components/InputPane.js +207 -0
  215. package/dist/src/components/InputPane.js.map +1 -0
  216. package/dist/src/components/InputReadline.js +598 -0
  217. package/dist/src/components/InputReadline.js.map +1 -0
  218. package/dist/src/components/LogPane.js +123 -0
  219. package/dist/src/components/LogPane.js.map +1 -0
  220. package/dist/src/components/PlanEditor.js +126 -0
  221. package/dist/src/components/PlanEditor.js.map +1 -0
  222. package/dist/src/components/PlanPane.js +51 -0
  223. package/dist/src/components/PlanPane.js.map +1 -0
  224. package/dist/src/components/SessionTimer.js +26 -0
  225. package/dist/src/components/SessionTimer.js.map +1 -0
  226. package/dist/src/components/StateTransitionPane.js +107 -0
  227. package/dist/src/components/StateTransitionPane.js.map +1 -0
  228. package/dist/src/components/StatusPane.js +37 -0
  229. package/dist/src/components/StatusPane.js.map +1 -0
  230. package/dist/src/components/TaskPane.js +96 -0
  231. package/dist/src/components/TaskPane.js.map +1 -0
  232. package/dist/src/components/Welcome.js +52 -0
  233. package/dist/src/components/Welcome.js.map +1 -0
  234. package/dist/src/components/WelcomeChecklist.js +96 -0
  235. package/dist/src/components/WelcomeChecklist.js.map +1 -0
  236. package/dist/src/components/WelcomeCommands.js +61 -0
  237. package/dist/src/components/WelcomeCommands.js.map +1 -0
  238. package/dist/src/components/autocomplete-store.js +22 -0
  239. package/dist/src/components/autocomplete-store.js.map +1 -0
  240. package/dist/src/components/parse-keypress.js +174 -0
  241. package/dist/src/components/parse-keypress.js.map +1 -0
  242. package/dist/src/config.js +249 -0
  243. package/dist/src/config.js.map +1 -0
  244. package/dist/src/execution-controller.js +92 -0
  245. package/dist/src/execution-controller.js.map +1 -0
  246. package/dist/src/experience-tracker.js +294 -0
  247. package/dist/src/experience-tracker.js.map +1 -0
  248. package/dist/src/explorbot.js +348 -0
  249. package/dist/src/explorbot.js.map +1 -0
  250. package/dist/src/explorer.js +611 -0
  251. package/dist/src/explorer.js.map +1 -0
  252. package/dist/src/index.js +56 -0
  253. package/dist/src/index.js.map +1 -0
  254. package/dist/src/knowledge-tracker.js +184 -0
  255. package/dist/src/knowledge-tracker.js.map +1 -0
  256. package/dist/src/observability.js +126 -0
  257. package/dist/src/observability.js.map +1 -0
  258. package/dist/src/reporter.js +185 -0
  259. package/dist/src/reporter.js.map +1 -0
  260. package/dist/src/state-manager.js +427 -0
  261. package/dist/src/state-manager.js.map +1 -0
  262. package/dist/src/stats.js +44 -0
  263. package/dist/src/stats.js.map +1 -0
  264. package/dist/src/test-plan.js +343 -0
  265. package/dist/src/test-plan.js.map +1 -0
  266. package/dist/src/utils/aria.js +588 -0
  267. package/dist/src/utils/aria.js.map +1 -0
  268. package/dist/src/utils/code-extractor.js +21 -0
  269. package/dist/src/utils/code-extractor.js.map +1 -0
  270. package/dist/src/utils/context-formatter.js +205 -0
  271. package/dist/src/utils/context-formatter.js.map +1 -0
  272. package/dist/src/utils/error-page.js +19 -0
  273. package/dist/src/utils/error-page.js.map +1 -0
  274. package/dist/src/utils/expandable.js +35 -0
  275. package/dist/src/utils/expandable.js.map +1 -0
  276. package/dist/src/utils/hooks-runner.js +77 -0
  277. package/dist/src/utils/hooks-runner.js.map +1 -0
  278. package/dist/src/utils/html-diff.js +734 -0
  279. package/dist/src/utils/html-diff.js.map +1 -0
  280. package/dist/src/utils/html.js +1163 -0
  281. package/dist/src/utils/html.js.map +1 -0
  282. package/dist/src/utils/logger.js +465 -0
  283. package/dist/src/utils/logger.js.map +1 -0
  284. package/dist/src/utils/loop.js +126 -0
  285. package/dist/src/utils/loop.js.map +1 -0
  286. package/dist/src/utils/markdown-parser.js +117 -0
  287. package/dist/src/utils/markdown-parser.js.map +1 -0
  288. package/dist/src/utils/markdown-query.js +393 -0
  289. package/dist/src/utils/markdown-query.js.map +1 -0
  290. package/dist/src/utils/markdown-terminal.js +40 -0
  291. package/dist/src/utils/markdown-terminal.js.map +1 -0
  292. package/dist/src/utils/research-parser.js +2 -0
  293. package/dist/src/utils/research-parser.js.map +1 -0
  294. package/dist/src/utils/retry.js +55 -0
  295. package/dist/src/utils/retry.js.map +1 -0
  296. package/dist/src/utils/rules-loader.js +104 -0
  297. package/dist/src/utils/rules-loader.js.map +1 -0
  298. package/dist/src/utils/strings.js +14 -0
  299. package/dist/src/utils/strings.js.map +1 -0
  300. package/dist/src/utils/test-plan-markdown.js +301 -0
  301. package/dist/src/utils/test-plan-markdown.js.map +1 -0
  302. package/dist/src/utils/throttle.js +16 -0
  303. package/dist/src/utils/throttle.js.map +1 -0
  304. package/dist/src/utils/unique-names.js +13 -0
  305. package/dist/src/utils/unique-names.js.map +1 -0
  306. package/dist/src/utils/url-matcher.js +48 -0
  307. package/dist/src/utils/url-matcher.js.map +1 -0
  308. package/dist/src/utils/web-element.js +131 -0
  309. package/dist/src/utils/web-element.js.map +1 -0
  310. package/dist/src/utils/xpath.js +110 -0
  311. package/dist/src/utils/xpath.js.map +1 -0
  312. package/package.json +119 -0
  313. package/prompts/audit-rules.md +124 -0
  314. package/rules/chief/general.md +11 -0
  315. package/rules/chief/styles/curious.md +12 -0
  316. package/rules/chief/styles/hacker.md +19 -0
  317. package/rules/chief/styles/normal.md +11 -0
  318. package/rules/chief/styles/psycho.md +17 -0
  319. package/rules/navigator/multiple-locator.md +47 -0
  320. package/rules/navigator/output.md +69 -0
  321. package/rules/navigator/verification-actions.md +122 -0
  322. package/rules/navigator/verification-output.md +53 -0
  323. package/rules/planner/styles/curious.md +39 -0
  324. package/rules/planner/styles/normal.md +21 -0
  325. package/rules/planner/styles/psycho.md +14 -0
  326. package/rules/researcher/list-element.md +11 -0
  327. package/rules/researcher/screenshot-ui-map.md +30 -0
  328. package/rules/researcher/section-ui-map.md +18 -0
  329. package/rules/researcher/ui-map-table.md +18 -0
@@ -0,0 +1,123 @@
1
+ import dedent from 'dedent';
2
+ import React from 'react';
3
+ import { useCallback, useEffect, useState } from 'react';
4
+ import stripAnsi from 'strip-ansi';
5
+ import { htmlTextSnapshot } from '../utils/html.js';
6
+ import { parseMarkdownToTerminal } from '../utils/markdown-terminal.js';
7
+ import { Box, Text } from 'ink';
8
+ import { isDebugMode, registerLogPane, unregisterLogPane } from '../utils/logger.js';
9
+ const LogPane = React.memo(({ verboseMode }) => {
10
+ const [logs, setLogs] = useState([]);
11
+ const pendingLogsRef = React.useRef([]);
12
+ const flushTimeoutRef = React.useRef(null);
13
+ const flushLogs = useCallback(() => {
14
+ if (pendingLogsRef.current.length === 0)
15
+ return;
16
+ const newLogs = pendingLogsRef.current;
17
+ pendingLogsRef.current = [];
18
+ flushTimeoutRef.current = null;
19
+ setLogs((prevLogs) => {
20
+ const result = [...prevLogs];
21
+ for (const logEntry of newLogs) {
22
+ if (result.length === 0) {
23
+ result.push(logEntry);
24
+ continue;
25
+ }
26
+ const lastLog = result[result.length - 1];
27
+ if (lastLog.type === logEntry.type && lastLog.content === logEntry.content && Math.abs((lastLog.timestamp?.getTime() || 0) - (logEntry.timestamp?.getTime() || 0)) < 1000) {
28
+ continue;
29
+ }
30
+ result.push(logEntry);
31
+ }
32
+ return result;
33
+ });
34
+ }, []);
35
+ const addLog = useCallback((logEntry) => {
36
+ pendingLogsRef.current.push(logEntry);
37
+ if (!flushTimeoutRef.current) {
38
+ flushTimeoutRef.current = setTimeout(flushLogs, 150);
39
+ }
40
+ }, [flushLogs]);
41
+ useEffect(() => {
42
+ registerLogPane(addLog);
43
+ return () => {
44
+ unregisterLogPane(addLog);
45
+ if (flushTimeoutRef.current) {
46
+ clearTimeout(flushTimeoutRef.current);
47
+ }
48
+ };
49
+ }, [addLog]);
50
+ const getLogStyles = (type) => {
51
+ switch (type) {
52
+ case 'success':
53
+ return { color: 'green' };
54
+ case 'error':
55
+ return { color: 'red' };
56
+ case 'warning':
57
+ return { color: 'yellow' };
58
+ case 'debug':
59
+ return { color: 'gray', dimColor: true };
60
+ case 'substep':
61
+ return { color: 'gray', dimColor: true };
62
+ case 'step':
63
+ return { color: 'cyan', dimColor: true };
64
+ case 'multiline':
65
+ return { color: 'gray', dimColor: true };
66
+ case 'html':
67
+ return { color: 'gray' };
68
+ case 'input':
69
+ return { bold: true, color: '#FFA500' };
70
+ default:
71
+ return {};
72
+ }
73
+ };
74
+ const processLogContent = (content) => {
75
+ return content.split('\n').filter((line) => line.length > 0);
76
+ };
77
+ const renderLogEntry = (log, index) => {
78
+ // Skip debug logs when not in verbose mode AND DEBUG env var is not set
79
+ const shouldShowDebug = verboseMode || isDebugMode() || Boolean(process.env.DEBUG?.includes('explorbot:')) || process.env.DEBUG === '*';
80
+ if (log.type === 'debug' && !shouldShowDebug) {
81
+ return null;
82
+ }
83
+ const styles = getLogStyles(log.type);
84
+ if (log.type === 'multiline') {
85
+ const cleaned = stripAnsi(dedent(log.content));
86
+ const parsed = parseMarkdownToTerminal(cleaned);
87
+ const lines = parsed.split('\n');
88
+ const maxLines = 30;
89
+ const truncated = lines.length > maxLines ? `${lines.slice(0, maxLines).join('\n')}\n... (${lines.length - maxLines} more lines)` : cleaned;
90
+ return (React.createElement(Box, { key: index, borderStyle: "classic", borderLeft: false, borderRight: false, marginY: 1, padding: 1, borderColor: "dim", overflow: "hidden" },
91
+ React.createElement(Text, { color: "gray", dimColor: true }, parsed)));
92
+ }
93
+ if (log.type === 'html') {
94
+ // Convert HTML to markdown, then render as multiline
95
+ const markdown = htmlTextSnapshot(log.content);
96
+ const multilineLog = {
97
+ type: 'multiline',
98
+ content: `HTML Content:\n\n${markdown}`,
99
+ timestamp: log.timestamp,
100
+ };
101
+ return renderLogEntry(multilineLog, index);
102
+ }
103
+ const lines = processLogContent(String(log.content));
104
+ if (log.type === 'substep') {
105
+ return (React.createElement(Box, { key: index, marginLeft: 2, flexDirection: "column" }, lines.map((line, lineIndex) => (React.createElement(Text, { key: `${index}-${lineIndex}`, ...styles }, lineIndex === 0 ? `> ${line}` : ` ${line}`)))));
106
+ }
107
+ if (log.type === 'step') {
108
+ return (React.createElement(Box, { key: index, flexDirection: "column", paddingLeft: 2 }, lines.map((line, lineIndex) => (React.createElement(Text, { key: `${index}-${lineIndex}`, ...styles }, line)))));
109
+ }
110
+ let marginTop = 0;
111
+ if (log.type === 'info')
112
+ marginTop = 1;
113
+ const icon = log.type === 'info' ? '◉' : log.type === 'success' ? '✓' : log.type === 'error' ? '✗' : log.type === 'warning' ? '!' : log.type === 'debug' ? '*' : '';
114
+ return (React.createElement(Box, { key: index, columnGap: 1, marginTop: marginTop, flexDirection: "row" },
115
+ icon && React.createElement(Text, { ...styles }, icon),
116
+ React.createElement(Box, { flexDirection: "column" }, lines.map((line, lineIndex) => (React.createElement(Text, { key: `${index}-${lineIndex}`, ...styles }, line))))));
117
+ };
118
+ const maxLogs = 100;
119
+ const visibleLogs = logs.length > maxLogs ? logs.slice(-maxLogs) : logs;
120
+ return React.createElement(Box, { flexDirection: "column" }, visibleLogs.map((log, index) => renderLogEntry(log, index)).filter(Boolean));
121
+ });
122
+ export default LogPane;
123
+ //# sourceMappingURL=LogPane.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LogPane.js","sourceRoot":"","sources":["../../../src/components/LogPane.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,126 @@
1
+ import { Box, Text, useInput } from 'ink';
2
+ import React, { useEffect, useState } from 'react';
3
+ const EDITOR_WINDOW = 12;
4
+ const PlanEditor = ({ tasks, onClose, isActive }) => {
5
+ const [cursorIndex, setCursorIndex] = useState(0);
6
+ const [enabledMap, setEnabledMap] = useState([]);
7
+ useEffect(() => {
8
+ setEnabledMap(tasks.map((t) => t.enabled));
9
+ setCursorIndex(0);
10
+ }, [tasks]);
11
+ useInput((input, key) => {
12
+ if (key.upArrow) {
13
+ setCursorIndex((prev) => Math.max(0, prev - 1));
14
+ return;
15
+ }
16
+ if (key.downArrow) {
17
+ setCursorIndex((prev) => Math.min(tasks.length - 1, prev + 1));
18
+ return;
19
+ }
20
+ if (input === ' ') {
21
+ setEnabledMap((prev) => {
22
+ const next = [...prev];
23
+ next[cursorIndex] = !next[cursorIndex];
24
+ return next;
25
+ });
26
+ return;
27
+ }
28
+ if (input === 'a') {
29
+ setEnabledMap(tasks.map(() => true));
30
+ return;
31
+ }
32
+ if (input === 'n') {
33
+ setEnabledMap(tasks.map(() => false));
34
+ return;
35
+ }
36
+ if (key.delete && tasks[cursorIndex]?.plan) {
37
+ tasks[cursorIndex].plan.removeTest(tasks[cursorIndex]);
38
+ setCursorIndex((prev) => Math.min(prev, tasks.length - 2));
39
+ return;
40
+ }
41
+ if (key.return) {
42
+ for (let i = 0; i < tasks.length; i++) {
43
+ tasks[i].enabled = enabledMap[i];
44
+ }
45
+ tasks[0]?.plan?.notifyChange();
46
+ onClose();
47
+ return;
48
+ }
49
+ if (key.escape) {
50
+ onClose();
51
+ }
52
+ }, { isActive });
53
+ if (!isActive)
54
+ return null;
55
+ const scrollStart = Math.max(0, Math.min(cursorIndex - Math.floor(EDITOR_WINDOW / 2), tasks.length - EDITOR_WINDOW));
56
+ const scrollEnd = Math.min(tasks.length, scrollStart + EDITOR_WINDOW);
57
+ const visibleSlice = tasks.slice(scrollStart, scrollEnd);
58
+ return (React.createElement(Box, { flexDirection: "column", paddingX: 2, paddingY: 1 },
59
+ React.createElement(Box, { marginBottom: 1 },
60
+ React.createElement(Text, { color: "cyan", bold: true }, "Edit Plan"),
61
+ React.createElement(Text, { color: "dim" }, " \u2014 "),
62
+ React.createElement(Text, { color: "dim" }, "("),
63
+ React.createElement(Text, { bold: true }, "\u2191\u2193"),
64
+ React.createElement(Text, { color: "dim" }, ")"),
65
+ React.createElement(Text, { color: "dim" }, " navigate "),
66
+ React.createElement(Text, { color: "dim" }, "("),
67
+ React.createElement(Text, { bold: true }, "Space"),
68
+ React.createElement(Text, { color: "dim" }, ")"),
69
+ React.createElement(Text, { color: "dim" }, " toggle "),
70
+ React.createElement(Text, { color: "dim" }, "("),
71
+ React.createElement(Text, { bold: true }, "a"),
72
+ React.createElement(Text, { color: "dim" }, ")"),
73
+ React.createElement(Text, { color: "dim" }, " all "),
74
+ React.createElement(Text, { color: "dim" }, "("),
75
+ React.createElement(Text, { bold: true }, "n"),
76
+ React.createElement(Text, { color: "dim" }, ")"),
77
+ React.createElement(Text, { color: "dim" }, " none "),
78
+ React.createElement(Text, { color: "dim" }, "("),
79
+ React.createElement(Text, { bold: true }, "Del"),
80
+ React.createElement(Text, { color: "dim" }, ")"),
81
+ React.createElement(Text, { color: "dim" }, " remove "),
82
+ React.createElement(Text, { color: "dim" }, "("),
83
+ React.createElement(Text, { bold: true }, "Enter"),
84
+ React.createElement(Text, { color: "dim" }, ")"),
85
+ React.createElement(Text, { color: "dim" }, " confirm "),
86
+ React.createElement(Text, { color: "dim" }, "("),
87
+ React.createElement(Text, { bold: true }, "Esc"),
88
+ React.createElement(Text, { color: "dim" }, ")"),
89
+ React.createElement(Text, { color: "dim" }, " cancel")),
90
+ scrollStart > 0 && (React.createElement(Text, { color: "dim" },
91
+ ' ',
92
+ "\u25B2 ",
93
+ scrollStart,
94
+ " more")),
95
+ visibleSlice.map((task, i) => {
96
+ const globalIdx = scrollStart + i;
97
+ const isCursor = globalIdx === cursorIndex;
98
+ const isEnabled = enabledMap[globalIdx];
99
+ const checkbox = isEnabled ? '[x]' : '[ ]';
100
+ const cursor = isCursor ? '>' : ' ';
101
+ const color = isEnabled ? 'green' : 'dim';
102
+ return (React.createElement(Box, { key: task.id || globalIdx, flexDirection: "row" },
103
+ React.createElement(Text, { color: isCursor ? 'yellow' : 'dim' },
104
+ cursor,
105
+ " "),
106
+ React.createElement(Text, { color: color },
107
+ checkbox,
108
+ " ",
109
+ globalIdx + 1,
110
+ ". ",
111
+ task.scenario)));
112
+ }),
113
+ scrollEnd < tasks.length && (React.createElement(Text, { color: "dim" },
114
+ ' ',
115
+ "\u25BC ",
116
+ tasks.length - scrollEnd,
117
+ " more")),
118
+ React.createElement(Box, { marginTop: 1 },
119
+ React.createElement(Text, { color: "dim" },
120
+ enabledMap.filter(Boolean).length,
121
+ "/",
122
+ tasks.length,
123
+ " enabled"))));
124
+ };
125
+ export default PlanEditor;
126
+ //# sourceMappingURL=PlanEditor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlanEditor.js","sourceRoot":"","sources":["../../../src/components/PlanEditor.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import { Box, Text } from 'ink';
2
+ import React from 'react';
3
+ const MAX_VISIBLE_PLANS = 2;
4
+ const PlanPane = React.memo(({ completedPlans, activePlan }) => {
5
+ if (!activePlan && completedPlans.length === 0)
6
+ return null;
7
+ const collapsedCount = Math.max(0, completedPlans.length - MAX_VISIBLE_PLANS);
8
+ const collapsedTests = completedPlans.slice(0, collapsedCount).reduce((sum, p) => sum + p.testCount, 0);
9
+ const visiblePlans = completedPlans.slice(collapsedCount);
10
+ return (React.createElement(Box, { flexDirection: "row", width: "100%", paddingX: 1 },
11
+ React.createElement(Box, { flexGrow: 1, flexShrink: 1, flexDirection: "row", overflow: "hidden" },
12
+ collapsedCount > 0 && (React.createElement(React.Fragment, null,
13
+ React.createElement(Text, { backgroundColor: "blue", color: "white", wrap: "truncate-end" },
14
+ "+",
15
+ collapsedCount,
16
+ " plans (",
17
+ collapsedTests,
18
+ " tests)"),
19
+ React.createElement(Text, { backgroundColor: "blue", color: "white" },
20
+ ' ',
21
+ "\u2502",
22
+ ' '))),
23
+ visiblePlans.map((plan, i) => (React.createElement(React.Fragment, { key: i },
24
+ React.createElement(Text, { backgroundColor: "blue", color: "gray", wrap: "truncate-end" },
25
+ plan.title,
26
+ " (",
27
+ formatStats(plan),
28
+ ")"),
29
+ React.createElement(Text, { backgroundColor: "blue", color: "gray" },
30
+ ' ',
31
+ "\u203A",
32
+ ' '))))),
33
+ activePlan && (React.createElement(Box, { flexShrink: 0 },
34
+ React.createElement(Text, { backgroundColor: "blue", color: "white", bold: true },
35
+ activePlan.title,
36
+ " (",
37
+ activePlan.testCount,
38
+ " tests)")))));
39
+ });
40
+ function formatStats(plan) {
41
+ const parts = [];
42
+ if (plan.passed > 0)
43
+ parts.push(`${plan.passed}✓`);
44
+ if (plan.failed > 0)
45
+ parts.push(`${plan.failed}✗`);
46
+ if (parts.length === 0)
47
+ return `${plan.testCount} tests`;
48
+ return parts.join(' ');
49
+ }
50
+ export default PlanPane;
51
+ //# sourceMappingURL=PlanPane.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlanPane.js","sourceRoot":"","sources":["../../../src/components/PlanPane.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAO5B,MAAM,QAAQ,GAA4B,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,cAAc,EAAE,UAAU,EAAE,EAAE,EAAE;IACtF,IAAI,CAAC,UAAU,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAE5D,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,cAAc,CAAC,MAAM,GAAG,iBAAiB,CAAC,CAAC;IAC9E,MAAM,cAAc,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;IACxG,MAAM,YAAY,GAAG,cAAc,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAE1D,OAAO,CACL,oBAAC,GAAG,IAAC,aAAa,EAAC,KAAK,EAAC,KAAK,EAAC,MAAM,EAAC,QAAQ,EAAE,CAAC;QAC/C,oBAAC,GAAG,IAAC,QAAQ,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,aAAa,EAAC,KAAK,EAAC,QAAQ,EAAC,QAAQ;YACnE,cAAc,GAAG,CAAC,IAAI,CACrB;gBACE,oBAAC,IAAI,IAAC,eAAe,EAAC,MAAM,EAAC,KAAK,EAAC,OAAO,EAAC,IAAI,EAAC,cAAc;;oBAC1D,cAAc;;oBAAU,cAAc;8BACnC;gBACP,oBAAC,IAAI,IAAC,eAAe,EAAC,MAAM,EAAC,KAAK,EAAC,OAAO;oBACvC,GAAG;;oBACF,GAAG,CACA,CACN,CACJ;YACA,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAC7B,oBAAC,KAAK,CAAC,QAAQ,IAAC,GAAG,EAAE,CAAC;gBACpB,oBAAC,IAAI,IAAC,eAAe,EAAC,MAAM,EAAC,KAAK,EAAC,MAAM,EAAC,IAAI,EAAC,cAAc;oBAC1D,IAAI,CAAC,KAAK;;oBAAI,WAAW,CAAC,IAAI,CAAC;wBAC3B;gBACP,oBAAC,IAAI,IAAC,eAAe,EAAC,MAAM,EAAC,KAAK,EAAC,MAAM;oBACtC,GAAG;;oBACF,GAAG,CACA,CACQ,CAClB,CAAC,CACE;QAEL,UAAU,IAAI,CACb,oBAAC,GAAG,IAAC,UAAU,EAAE,CAAC;YAChB,oBAAC,IAAI,IAAC,eAAe,EAAC,MAAM,EAAC,KAAK,EAAC,OAAO,EAAC,IAAI;gBAC5C,UAAU,CAAC,KAAK;;gBAAI,UAAU,CAAC,SAAS;0BACpC,CACH,CACP,CACG,CACP,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,SAAS,WAAW,CAAC,IAAiB;IACpC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IACnD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IACnD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,IAAI,CAAC,SAAS,QAAQ,CAAC;IACzD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { Box, Text } from 'ink';
2
+ import React, { useEffect, useState } from 'react';
3
+ const pad = (n) => String(n).padStart(2, '0');
4
+ const SessionTimer = ({ startedAt }) => {
5
+ const [now, setNow] = useState(() => Date.now());
6
+ useEffect(() => {
7
+ const id = setInterval(() => {
8
+ setNow(Date.now());
9
+ }, 1000);
10
+ return () => clearInterval(id);
11
+ }, []);
12
+ const diffSec = Math.floor((now - startedAt) / 1000);
13
+ const seconds = diffSec % 60;
14
+ const minutes = Math.floor(diffSec / 60) % 60;
15
+ const hours = Math.floor(diffSec / 3600);
16
+ return (React.createElement(Box, { borderStyle: "round", paddingX: 1, paddingY: 0 },
17
+ React.createElement(Text, null,
18
+ "Session time: ",
19
+ pad(hours),
20
+ ":",
21
+ pad(minutes),
22
+ ":",
23
+ pad(seconds))));
24
+ };
25
+ export default SessionTimer;
26
+ //# sourceMappingURL=SessionTimer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SessionTimer.js","sourceRoot":"","sources":["../../../src/components/SessionTimer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAMnD,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAEtD,MAAM,YAAY,GAAgC,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE;IAClE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAEjD,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE;YAC1B,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACrB,CAAC,EAAE,IAAI,CAAC,CAAC;QAET,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,OAAO,GAAG,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC;IAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAEzC,OAAO,CACL,oBAAC,GAAG,IAAC,WAAW,EAAC,OAAO,EAAC,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC;QAC/C,oBAAC,IAAI;;YACY,GAAG,CAAC,KAAK,CAAC;;YAAG,GAAG,CAAC,OAAO,CAAC;;YAAG,GAAG,CAAC,OAAO,CAAC,CAClD,CACH,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -0,0 +1,107 @@
1
+ import { Box, Text } from 'ink';
2
+ import React from 'react';
3
+ const StateTransitionPane = ({ transition, currentState }) => {
4
+ if (currentState) {
5
+ return (React.createElement(Box, { flexDirection: "column", flexGrow: 1 },
6
+ React.createElement(Box, { padding: 1, borderStyle: "round", borderColor: "dim", flexDirection: "column" },
7
+ React.createElement(Box, { flexDirection: "row", alignItems: "flex-start", marginBottom: 1 },
8
+ React.createElement(Text, { color: "dim" }, "Current Page "),
9
+ React.createElement(Text, { color: "blue", wrap: "truncate-end" }, currentState.url)),
10
+ React.createElement(Box, { marginY: 0 },
11
+ React.createElement(Text, { color: "dim" },
12
+ "URL:",
13
+ ' ',
14
+ React.createElement(Text, { color: "yellow", wrap: "truncate-end" }, currentState.fullUrl || currentState.url || 'unknown'))),
15
+ React.createElement(Box, { marginY: 0 },
16
+ React.createElement(Text, { color: "dim" },
17
+ "Title: ",
18
+ React.createElement(Text, { color: "yellow" }, currentState.title || 'none'))),
19
+ currentState.h1 && (React.createElement(Box, { marginY: 0 },
20
+ React.createElement(Text, { color: "dim" },
21
+ "H1: ",
22
+ React.createElement(Text, { color: "yellow" }, currentState.h1)))),
23
+ currentState.h2 && (React.createElement(Box, { marginY: 0 },
24
+ React.createElement(Text, { color: "dim" },
25
+ "H2: ",
26
+ React.createElement(Text, { color: "yellow" }, currentState.h2)))))));
27
+ }
28
+ if (!transition) {
29
+ return null;
30
+ }
31
+ const { fromState, toState, trigger, timestamp } = transition;
32
+ const getDifferences = () => {
33
+ const differences = [];
34
+ // URL comparison
35
+ if (fromState?.url !== toState.url) {
36
+ differences.push({
37
+ key: 'url',
38
+ from: fromState?.url || 'none',
39
+ to: toState.url || 'none',
40
+ });
41
+ }
42
+ // Title comparison
43
+ if (fromState?.title !== toState.title) {
44
+ differences.push({
45
+ key: 'title',
46
+ from: fromState?.title || 'none',
47
+ to: toState.title || 'none',
48
+ });
49
+ }
50
+ // H1 comparison
51
+ if (fromState?.h1 !== toState.h1) {
52
+ differences.push({
53
+ key: 'h1',
54
+ from: fromState?.h1 || 'none',
55
+ to: toState.h1 || 'none',
56
+ });
57
+ }
58
+ // H2 comparison
59
+ if (fromState?.h2 !== toState.h2) {
60
+ differences.push({
61
+ key: 'h2',
62
+ from: fromState?.h2 || 'none',
63
+ to: toState.h2 || 'none',
64
+ });
65
+ }
66
+ // H3 comparison
67
+ if (fromState?.h3 !== toState.h3) {
68
+ differences.push({
69
+ key: 'h3',
70
+ from: fromState?.h3 || 'none',
71
+ to: toState.h3 || 'none',
72
+ });
73
+ }
74
+ // H4 comparison
75
+ if (fromState?.h4 !== toState.h4) {
76
+ differences.push({
77
+ key: 'h4',
78
+ from: fromState?.h4 || 'none',
79
+ to: toState.h4 || 'none',
80
+ });
81
+ }
82
+ return differences;
83
+ };
84
+ const differences = getDifferences();
85
+ const timeString = timestamp.toLocaleTimeString();
86
+ if (differences.length === 0) {
87
+ return null;
88
+ }
89
+ return (React.createElement(Box, { flexDirection: "column", flexGrow: 1 },
90
+ React.createElement(Box, { borderStyle: "round", borderColor: "dim", padding: 1, flexDirection: "column" },
91
+ React.createElement(Box, { justifyContent: "space-between", marginBottom: 1 },
92
+ React.createElement(Text, { color: "dim" }, "\uD83D\uDD04 state changed"),
93
+ React.createElement(Text, { color: "dim" },
94
+ "[",
95
+ timeString,
96
+ "] ",
97
+ trigger)),
98
+ differences.map((diff, index) => (React.createElement(Box, { key: index, marginY: 0 },
99
+ React.createElement(Text, { color: "dim" },
100
+ diff.key,
101
+ ": ",
102
+ React.createElement(Text, { color: "red" }, diff.from),
103
+ " \u2192 ",
104
+ React.createElement(Text, { color: "green" }, diff.to))))))));
105
+ };
106
+ export default StateTransitionPane;
107
+ //# sourceMappingURL=StateTransitionPane.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StateTransitionPane.js","sourceRoot":"","sources":["../../../src/components/StateTransitionPane.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { Box, Text } from 'ink';
2
+ import React from 'react';
3
+ import { Stats } from '../stats.js';
4
+ const ROW_WIDTH = 60;
5
+ const LABEL_WIDTH = 45;
6
+ const Row = ({ label, value }) => (React.createElement(Box, { width: ROW_WIDTH },
7
+ React.createElement(Box, { width: LABEL_WIDTH, overflow: "hidden" },
8
+ React.createElement(Text, { color: "dim", wrap: "truncate-end" }, label)),
9
+ React.createElement(Box, { flexGrow: 1 },
10
+ React.createElement(Text, { bold: true }, value))));
11
+ export const StatusPane = ({ onComplete }) => {
12
+ const modelEntries = Object.entries(Stats.models);
13
+ React.useEffect(() => {
14
+ if (!onComplete)
15
+ return;
16
+ const timer = setTimeout(onComplete, 100);
17
+ return () => clearTimeout(timer);
18
+ }, [onComplete]);
19
+ const statsRows = [
20
+ { label: 'Tests', value: Stats.tests },
21
+ { label: 'Plans', value: Stats.plans },
22
+ { label: 'Researches', value: Stats.researches },
23
+ ].filter((row) => row.value > 0);
24
+ const tokenRows = modelEntries.filter(([, tokens]) => tokens.total > 0);
25
+ if (statsRows.length === 0 && tokenRows.length === 0)
26
+ return null;
27
+ return (React.createElement(Box, { flexDirection: "column", borderStyle: "single", borderTop: true, borderBottom: false, borderLeft: false, borderRight: false, paddingX: 1, paddingY: 1, width: ROW_WIDTH + 4 },
28
+ React.createElement(Box, { marginBottom: 1 },
29
+ React.createElement(Text, { bold: true }, "Session Statistics")),
30
+ statsRows.map((row) => (React.createElement(Row, { key: row.label, label: row.label, value: row.value }))),
31
+ tokenRows.length > 0 && (React.createElement(React.Fragment, null,
32
+ React.createElement(Box, { marginTop: 1, marginBottom: 1 },
33
+ React.createElement(Text, { bold: true }, "Usage")),
34
+ React.createElement(Row, { label: "Time", value: Stats.getElapsedTime() }),
35
+ tokenRows.map(([model, tokens]) => (React.createElement(Row, { key: model, label: model, value: `${Stats.humanizeTokens(tokens.total)} tokens` })))))));
36
+ };
37
+ //# sourceMappingURL=StatusPane.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StatusPane.js","sourceRoot":"","sources":["../../../src/components/StatusPane.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ import { Box, Text } from 'ink';
2
+ import React, { useEffect, useState } from 'react';
3
+ export const WINDOW_SIZE = 7;
4
+ const getPriorityIcon = (priority) => {
5
+ switch (priority.toLowerCase()) {
6
+ case 'high':
7
+ return '⭆';
8
+ case 'medium':
9
+ return '⇒';
10
+ case 'low':
11
+ return '⇝';
12
+ default:
13
+ return '⇢';
14
+ }
15
+ };
16
+ const TaskPane = React.memo(({ tasks, scrollOffset = 0 }) => {
17
+ const [blinkOn, setBlinkOn] = useState(false);
18
+ useEffect(() => {
19
+ const hasInProgress = tasks.some((task) => task.status === 'in_progress');
20
+ if (!hasInProgress) {
21
+ setBlinkOn(false);
22
+ return;
23
+ }
24
+ const interval = setInterval(() => {
25
+ setBlinkOn((prev) => !prev);
26
+ }, 1500);
27
+ return () => {
28
+ clearInterval(interval);
29
+ };
30
+ }, [tasks]);
31
+ const visibleTasks = tasks.filter((t) => t.enabled);
32
+ const completedCount = visibleTasks.filter((t) => t.hasFinished).length;
33
+ const inProgressIdx = visibleTasks.findIndex((t) => t.status === 'in_progress');
34
+ let effectiveOffset = scrollOffset;
35
+ if (inProgressIdx >= 0 && (inProgressIdx < scrollOffset || inProgressIdx >= scrollOffset + WINDOW_SIZE)) {
36
+ effectiveOffset = Math.max(0, inProgressIdx - Math.floor(WINDOW_SIZE / 2));
37
+ }
38
+ const clampedOffset = Math.min(effectiveOffset, Math.max(0, visibleTasks.length - WINDOW_SIZE));
39
+ const aboveCount = clampedOffset;
40
+ const belowCount = Math.max(0, visibleTasks.length - clampedOffset - WINDOW_SIZE);
41
+ const windowTasks = visibleTasks.slice(clampedOffset, clampedOffset + WINDOW_SIZE);
42
+ return (React.createElement(Box, { flexDirection: "column", flexGrow: 1 },
43
+ React.createElement(Box, { borderStyle: "round", borderColor: "dim", padding: 1, flexDirection: "column" },
44
+ React.createElement(Box, { justifyContent: "space-between", marginBottom: 1 },
45
+ React.createElement(Text, { color: "dim" }, "\uD83D\uDCCB Tests"),
46
+ React.createElement(Box, null,
47
+ React.createElement(Text, { color: "dim", bold: true }, "Ctrl+E"),
48
+ React.createElement(Text, { color: "dim" }, " edit "),
49
+ React.createElement(Text, { color: "dim" },
50
+ "[",
51
+ completedCount,
52
+ "/",
53
+ visibleTasks.length,
54
+ "]"))),
55
+ aboveCount > 0 && (React.createElement(Text, { color: "dim" },
56
+ ' ',
57
+ "\u25B2 ",
58
+ aboveCount,
59
+ " more")),
60
+ windowTasks.map((task, windowIndex) => {
61
+ const globalIndex = clampedOffset + windowIndex;
62
+ const inProgress = task.status === 'in_progress';
63
+ let taskColor = 'dim';
64
+ let strikethrough = false;
65
+ if (task.isSuccessful) {
66
+ taskColor = 'green';
67
+ strikethrough = true;
68
+ }
69
+ else if (task.isSkipped) {
70
+ taskColor = 'yellow';
71
+ strikethrough = true;
72
+ }
73
+ else if (task.hasFailed) {
74
+ taskColor = 'red';
75
+ }
76
+ else if (inProgress) {
77
+ taskColor = blinkOn ? 'white' : 'dim';
78
+ }
79
+ return (React.createElement(Box, { key: task.id || globalIndex, flexDirection: "row", marginY: 0 },
80
+ React.createElement(Text, null,
81
+ " ",
82
+ getPriorityIcon(task.priority)),
83
+ React.createElement(Text, { color: taskColor, strikethrough: strikethrough, wrap: "truncate-end" },
84
+ ' ',
85
+ globalIndex + 1,
86
+ ". ",
87
+ task.scenario)));
88
+ }),
89
+ belowCount > 0 && (React.createElement(Text, { color: "dim" },
90
+ ' ',
91
+ "\u25BC ",
92
+ belowCount,
93
+ " more")))));
94
+ });
95
+ export default TaskPane;
96
+ //# sourceMappingURL=TaskPane.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskPane.js","sourceRoot":"","sources":["../../../src/components/TaskPane.tsx"],"names":[],"mappings":"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"}