explorbot 0.1.12 → 0.1.13

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 (59) hide show
  1. package/bin/explorbot-cli.ts +21 -21
  2. package/dist/bin/explorbot-cli.js +3 -3
  3. package/dist/package.json +3 -2
  4. package/dist/rules/researcher/container-rules.md +2 -0
  5. package/dist/src/action-result.js +2 -1
  6. package/dist/src/action.js +0 -6
  7. package/dist/src/ai/captain.js +0 -2
  8. package/dist/src/ai/driller.js +1108 -0
  9. package/dist/src/ai/pilot.js +31 -22
  10. package/dist/src/ai/rules.js +3 -5
  11. package/dist/src/ai/session-analyst.js +117 -0
  12. package/dist/src/ai/tester.js +13 -2
  13. package/dist/src/commands/base-command.js +6 -6
  14. package/dist/src/commands/drill-command.js +3 -2
  15. package/dist/src/commands/exit-command.js +1 -0
  16. package/dist/src/commands/explore-command.js +1 -0
  17. package/dist/src/components/AddRule.js +1 -1
  18. package/dist/src/explorbot.js +48 -8
  19. package/dist/src/explorer.js +9 -8
  20. package/dist/src/reporter.js +64 -3
  21. package/dist/src/state-manager.js +4 -3
  22. package/dist/src/stats.js +5 -0
  23. package/dist/src/utils/aria.js +354 -529
  24. package/dist/src/utils/hooks-runner.js +2 -8
  25. package/dist/src/utils/html.js +371 -0
  26. package/dist/src/utils/unique-names.js +12 -1
  27. package/dist/src/utils/url-matcher.js +6 -1
  28. package/dist/src/utils/web-element.js +27 -24
  29. package/dist/src/utils/xpath.js +1 -1
  30. package/package.json +3 -2
  31. package/rules/researcher/container-rules.md +2 -0
  32. package/src/action-result.ts +2 -1
  33. package/src/action.ts +0 -8
  34. package/src/ai/captain.ts +0 -2
  35. package/src/ai/driller.ts +1194 -0
  36. package/src/ai/pilot.ts +31 -21
  37. package/src/ai/rules.ts +3 -5
  38. package/src/ai/session-analyst.ts +133 -0
  39. package/src/ai/tester.ts +15 -2
  40. package/src/commands/base-command.ts +6 -6
  41. package/src/commands/drill-command.ts +3 -2
  42. package/src/commands/exit-command.ts +1 -0
  43. package/src/commands/explore-command.ts +1 -0
  44. package/src/components/AddRule.tsx +1 -1
  45. package/src/config.ts +4 -0
  46. package/src/explorbot.ts +55 -10
  47. package/src/explorer.ts +9 -8
  48. package/src/reporter.ts +64 -3
  49. package/src/state-manager.ts +4 -3
  50. package/src/stats.ts +7 -0
  51. package/src/utils/aria.ts +367 -537
  52. package/src/utils/hooks-runner.ts +2 -6
  53. package/src/utils/html.ts +381 -0
  54. package/src/utils/unique-names.ts +13 -0
  55. package/src/utils/url-matcher.ts +5 -1
  56. package/src/utils/web-element.ts +31 -28
  57. package/src/utils/xpath.ts +1 -1
  58. package/dist/src/ai/bosun.js +0 -456
  59. package/src/ai/bosun.ts +0 -571
package/src/reporter.ts CHANGED
@@ -33,8 +33,21 @@ export class Reporter {
33
33
  this.configureHtmlPipe();
34
34
  }
35
35
 
36
- const pipe = process.env.TESTOMATIO && config?.html ? 'both' : process.env.TESTOMATIO ? 'testomatio' : 'html';
37
- debugLog('Reporter initialized', { enabled: this.reporterEnabled, pipe });
36
+ if (this.reporterEnabled && config?.markdown) {
37
+ this.configureMarkdownPipe();
38
+ }
39
+
40
+ if (this.reporterEnabled) {
41
+ this.configureRunGroup(config?.runGroup);
42
+ }
43
+
44
+ debugLog('Reporter initialized', {
45
+ enabled: this.reporterEnabled,
46
+ testomatio: Boolean(process.env.TESTOMATIO),
47
+ html: Boolean(process.env.TESTOMATIO_HTML_REPORT_SAVE),
48
+ markdown: Boolean(process.env.TESTOMATIO_MARKDOWN_REPORT_SAVE),
49
+ runGroup: process.env.TESTOMATIO_RUNGROUP_TITLE || null,
50
+ });
38
51
  }
39
52
 
40
53
  private buildTitle(): string {
@@ -56,7 +69,31 @@ export class Reporter {
56
69
  private configureHtmlPipe(): void {
57
70
  process.env.TESTOMATIO_HTML_REPORT_SAVE = '1';
58
71
  process.env.TESTOMATIO_HTML_REPORT_FOLDER = outputPath('reports');
59
- debugLog('HTML report pipe configured', { folder: process.env.TESTOMATIO_HTML_REPORT_FOLDER });
72
+ process.env.TESTOMATIO_HTML_FILENAME = `${Stats.sessionLabel()}.html`;
73
+ debugLog('HTML report pipe configured', {
74
+ folder: process.env.TESTOMATIO_HTML_REPORT_FOLDER,
75
+ filename: process.env.TESTOMATIO_HTML_FILENAME,
76
+ });
77
+ }
78
+
79
+ private configureMarkdownPipe(): void {
80
+ process.env.TESTOMATIO_MARKDOWN_REPORT_SAVE = '1';
81
+ process.env.TESTOMATIO_MARKDOWN_REPORT_FOLDER = outputPath('reports');
82
+ process.env.TESTOMATIO_MARKDOWN_FILENAME = `${Stats.sessionLabel()}-tests.md`;
83
+ debugLog('Markdown report pipe configured', {
84
+ folder: process.env.TESTOMATIO_MARKDOWN_REPORT_FOLDER,
85
+ filename: process.env.TESTOMATIO_MARKDOWN_FILENAME,
86
+ });
87
+ }
88
+
89
+ private configureRunGroup(runGroup: string | null | undefined): void {
90
+ if (process.env.TESTOMATIO_RUNGROUP_TITLE) return;
91
+ if (runGroup === null) return;
92
+ if (runGroup) {
93
+ process.env.TESTOMATIO_RUNGROUP_TITLE = runGroup;
94
+ return;
95
+ }
96
+ process.env.TESTOMATIO_RUNGROUP_TITLE = `Explorbot ${new Date().toISOString().slice(0, 10)}`;
60
97
  }
61
98
 
62
99
  async startRun(): Promise<void> {
@@ -229,6 +266,30 @@ export class Reporter {
229
266
  return this.isRunStarted;
230
267
  }
231
268
 
269
+ async setRunDescription(text: string): Promise<void> {
270
+ if (!this.isRunStarted) return;
271
+ if (!process.env.TESTOMATIO) return;
272
+ const runId = this.client.runId;
273
+ if (!runId) return;
274
+
275
+ const baseUrl = process.env.TESTOMATIO_URL || 'https://app.testomat.io';
276
+ const url = `${baseUrl}/api/reporter/${runId}`;
277
+ try {
278
+ const response = await fetch(url, {
279
+ method: 'PUT',
280
+ headers: { 'Content-Type': 'application/json' },
281
+ body: JSON.stringify({ api_key: process.env.TESTOMATIO, description: text }),
282
+ });
283
+ if (!response.ok) {
284
+ debugLog('Run description update failed:', response.status, response.statusText);
285
+ return;
286
+ }
287
+ debugLog('Run description updated');
288
+ } catch (error) {
289
+ debugLog('Failed to update run description:', error);
290
+ }
291
+ }
292
+
232
293
  private extractLastNoteMessage(test: Test): string {
233
294
  const notes = Object.values(test.notes);
234
295
  if (notes.length === 0) return '';
@@ -142,8 +142,8 @@ export class StateManager {
142
142
 
143
143
  /**
144
144
  * Extract state path from full URL
145
- * Removes domain, port, protocol, and query params
146
- * Keeps path and hash: /path/to/page#section
145
+ * Removes domain, port, protocol
146
+ * Keeps path, query, and hash: /path/to/page?tab=users#section
147
147
  */
148
148
  /**
149
149
  * Update current state from ActionResult and record transition if state changed
@@ -549,7 +549,8 @@ export class StateManager {
549
549
  export function normalizeUrl(url: string): string {
550
550
  try {
551
551
  const parsed = new URL(url, 'http://localhost');
552
- return parsed.pathname.replace(/^\/+|\/+$/g, '');
552
+ const path = parsed.pathname.replace(/^\/+|\/+$/g, '');
553
+ return `${path}${parsed.search}${parsed.hash}`;
553
554
  } catch {
554
555
  return url.replace(/^\/+|\/+$/g, '');
555
556
  }
package/src/stats.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { uniqExplorationName } from './utils/unique-names.ts';
2
+
1
3
  interface TokenUsage {
2
4
  input: number;
3
5
  output: number;
@@ -8,6 +10,7 @@ export type ExplorbotMode = 'explore' | 'test' | 'freesail' | 'tui';
8
10
 
9
11
  export class Stats {
10
12
  static startTime = Date.now();
13
+ static sessionName = uniqExplorationName();
11
14
  static researches = 0;
12
15
  static tests = 0;
13
16
  static plans = 0;
@@ -54,4 +57,8 @@ export class Stats {
54
57
  const totalTokens = Object.values(Stats.models).reduce((sum, m) => sum + m.total, 0);
55
58
  return totalTokens > 0;
56
59
  }
60
+
61
+ static sessionLabel(): string {
62
+ return `${Stats.mode || 'session'}-${Stats.sessionName}`;
63
+ }
57
64
  }