explorbot 0.1.30 → 0.1.32-beta.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 (179) hide show
  1. package/dist/boat/api-tester/example/apibot.config.js +30 -0
  2. package/dist/package.json +11 -26
  3. package/dist/src/action-result.d.ts +133 -0
  4. package/dist/src/action-result.js +22 -7
  5. package/dist/src/action.d.ts +50 -0
  6. package/dist/src/action.js +10 -5
  7. package/dist/src/activity.d.ts +26 -0
  8. package/dist/src/ai/agent.d.ts +3 -0
  9. package/dist/src/ai/captain/file-tools.d.ts +28 -0
  10. package/dist/src/ai/captain/idle-mode.d.ts +11 -0
  11. package/dist/src/ai/captain/mixin.d.ts +10 -0
  12. package/dist/src/ai/captain/test-mode.d.ts +13 -0
  13. package/dist/src/ai/captain/web-mode.d.ts +13 -0
  14. package/dist/src/ai/captain.d.ts +143 -0
  15. package/dist/src/ai/conversation.d.ts +31 -0
  16. package/dist/src/ai/conversation.js +1 -1
  17. package/dist/src/ai/driller.d.ts +161 -0
  18. package/dist/src/ai/experience-compactor.d.ts +53 -0
  19. package/dist/src/ai/fisherman-tools.d.ts +90 -0
  20. package/dist/src/ai/fisherman.d.ts +30 -0
  21. package/dist/src/ai/historian/codeceptjs.d.ts +15 -0
  22. package/dist/src/ai/historian/experience.d.ts +40 -0
  23. package/dist/src/ai/historian/mixin.d.ts +2 -0
  24. package/dist/src/ai/historian/playwright.d.ts +20 -0
  25. package/dist/src/ai/historian/screencast.d.ts +32 -0
  26. package/dist/src/ai/historian/utils.d.ts +4 -0
  27. package/dist/src/ai/historian.d.ts +108 -0
  28. package/dist/src/ai/navigator.d.ts +56 -0
  29. package/dist/src/ai/pilot.d.ts +83 -0
  30. package/dist/src/ai/planner/session-dedup.d.ts +12 -0
  31. package/dist/src/ai/planner/styles.d.ts +6 -0
  32. package/dist/src/ai/planner/subpages.d.ts +35 -0
  33. package/dist/src/ai/planner.d.ts +79 -0
  34. package/dist/src/ai/provider.d.ts +50 -0
  35. package/dist/src/ai/provider.js +13 -5
  36. package/dist/src/ai/quartermaster.d.ts +57 -0
  37. package/dist/src/ai/rerunner.d.ts +49 -0
  38. package/dist/src/ai/researcher/cache.d.ts +6 -0
  39. package/dist/src/ai/researcher/coordinates.d.ts +56 -0
  40. package/dist/src/ai/researcher/deep-analysis.d.ts +74 -0
  41. package/dist/src/ai/researcher/fingerprint-worker.d.ts +1 -0
  42. package/dist/src/ai/researcher/focus.d.ts +8 -0
  43. package/dist/src/ai/researcher/locators.d.ts +36 -0
  44. package/dist/src/ai/researcher/mixin.d.ts +2 -0
  45. package/dist/src/ai/researcher/parser.d.ts +35 -0
  46. package/dist/src/ai/researcher/research-result.d.ts +16 -0
  47. package/dist/src/ai/researcher/sections.d.ts +19 -0
  48. package/dist/src/ai/rules.d.ts +15 -0
  49. package/dist/src/ai/session-analyst.d.ts +11 -0
  50. package/dist/src/ai/task-agent.d.ts +28 -0
  51. package/dist/src/ai/tester.d.ts +103 -0
  52. package/dist/src/ai/tools.d.ts +41 -0
  53. package/dist/src/api/api-client.d.ts +17 -0
  54. package/dist/src/api/request-result.d.ts +44 -0
  55. package/dist/src/api/request-store.d.ts +29 -0
  56. package/dist/src/api/spec-reader.d.ts +5 -0
  57. package/dist/src/api/xhr-capture.d.ts +10 -0
  58. package/dist/src/browser-server.d.ts +10 -0
  59. package/dist/src/command-handler.d.ts +68 -0
  60. package/dist/src/commands/add-rule-command.d.ts +11 -0
  61. package/dist/src/commands/base-command.d.ts +26 -0
  62. package/dist/src/commands/clean-command.d.ts +12 -0
  63. package/dist/src/commands/compact-command.d.ts +20 -0
  64. package/dist/src/commands/context-aria-command.d.ts +6 -0
  65. package/dist/src/commands/context-command.d.ts +11 -0
  66. package/dist/src/commands/context-data-command.d.ts +6 -0
  67. package/dist/src/commands/context-experience-command.d.ts +6 -0
  68. package/dist/src/commands/context-html-command.d.ts +6 -0
  69. package/dist/src/commands/context-knowledge-command.d.ts +6 -0
  70. package/dist/src/commands/debug-command.d.ts +6 -0
  71. package/dist/src/commands/drill-command.d.ts +10 -0
  72. package/dist/src/commands/exit-command.d.ts +7 -0
  73. package/dist/src/commands/experience-command.d.ts +15 -0
  74. package/dist/src/commands/explore-command.d.ts +51 -0
  75. package/dist/src/commands/freesail-command.d.ts +12 -0
  76. package/dist/src/commands/help-command.d.ts +6 -0
  77. package/dist/src/commands/index.d.ts +4 -0
  78. package/dist/src/commands/init-command.d.ts +7 -0
  79. package/dist/src/commands/knows-command.d.ts +10 -0
  80. package/dist/src/commands/learn-command.d.ts +7 -0
  81. package/dist/src/commands/navigate-command.d.ts +7 -0
  82. package/dist/src/commands/path-command.d.ts +10 -0
  83. package/dist/src/commands/plan-clear-command.d.ts +7 -0
  84. package/dist/src/commands/plan-command.d.ts +14 -0
  85. package/dist/src/commands/plan-edit-command.d.ts +7 -0
  86. package/dist/src/commands/plan-load-command.d.ts +7 -0
  87. package/dist/src/commands/plan-reload-command.d.ts +7 -0
  88. package/dist/src/commands/plan-save-command.d.ts +7 -0
  89. package/dist/src/commands/plans-command.d.ts +21 -0
  90. package/dist/src/commands/rerun-command.d.ts +7 -0
  91. package/dist/src/commands/research-command.d.ts +11 -0
  92. package/dist/src/commands/runs-command.d.ts +7 -0
  93. package/dist/src/commands/start-command.d.ts +7 -0
  94. package/dist/src/commands/status-command.d.ts +6 -0
  95. package/dist/src/commands/test-command.d.ts +11 -0
  96. package/dist/src/components/ActivityPane.d.ts +6 -0
  97. package/dist/src/components/AddKnowledge.d.ts +8 -0
  98. package/dist/src/components/AddRule.d.ts +9 -0
  99. package/dist/src/components/App.d.ts +9 -0
  100. package/dist/src/components/Autocomplete.d.ts +3 -0
  101. package/dist/src/components/InputPane.d.ts +13 -0
  102. package/dist/src/components/InputReadline.d.ts +17 -0
  103. package/dist/src/components/LogPane.d.ts +6 -0
  104. package/dist/src/components/PlanEditor.d.ts +9 -0
  105. package/dist/src/components/PlanPane.d.ts +13 -0
  106. package/dist/src/components/SessionTimer.d.ts +6 -0
  107. package/dist/src/components/StateTransitionPane.d.ts +8 -0
  108. package/dist/src/components/StatusPane.d.ts +4 -0
  109. package/dist/src/components/TaskPane.d.ts +9 -0
  110. package/dist/src/components/Welcome.d.ts +3 -0
  111. package/dist/src/components/WelcomeChecklist.d.ts +9 -0
  112. package/dist/src/components/WelcomeCommands.d.ts +6 -0
  113. package/dist/src/components/autocomplete-store.d.ts +10 -0
  114. package/dist/src/components/parse-keypress.d.ts +12 -0
  115. package/dist/src/config.d.ts +251 -0
  116. package/dist/src/execution-controller.d.ts +25 -0
  117. package/dist/src/experience-tracker.d.ts +107 -0
  118. package/dist/src/experience-tracker.js +2 -1
  119. package/dist/src/explorbot.d.ts +107 -0
  120. package/dist/src/explorer.d.ts +140 -0
  121. package/dist/src/explorer.js +13 -9
  122. package/dist/src/index.d.ts +6 -0
  123. package/dist/src/index.js +2 -55
  124. package/dist/src/knowledge-tracker.d.ts +33 -0
  125. package/dist/src/knowledge-tracker.js +9 -2
  126. package/dist/src/observability.d.ts +13 -0
  127. package/dist/src/observability.js +2 -1
  128. package/dist/src/playwright-recorder.d.ts +31 -0
  129. package/dist/src/reporter.d.ts +34 -0
  130. package/dist/src/state-manager.d.ts +185 -0
  131. package/dist/src/state-manager.js +0 -7
  132. package/dist/src/stats.d.ts +24 -0
  133. package/dist/src/suite.d.ts +24 -0
  134. package/dist/src/test-plan.d.ts +166 -0
  135. package/dist/src/utils/aria.d.ts +20 -0
  136. package/dist/src/utils/browser-errors.d.ts +8 -0
  137. package/dist/src/utils/cli-name.d.ts +1 -0
  138. package/dist/src/utils/code-extractor.d.ts +1 -0
  139. package/dist/src/utils/context-formatter.d.ts +25 -0
  140. package/dist/src/utils/error-page.d.ts +12 -0
  141. package/dist/src/utils/expandable.d.ts +4 -0
  142. package/dist/src/utils/hooks-runner.d.ts +15 -0
  143. package/dist/src/utils/html-diff.d.ts +19 -0
  144. package/dist/src/utils/html.d.ts +124 -0
  145. package/dist/src/utils/log-filters.d.ts +6 -0
  146. package/dist/src/utils/logger.d.ts +35 -0
  147. package/dist/src/utils/loop.d.ts +35 -0
  148. package/dist/src/utils/markdown-parser.d.ts +17 -0
  149. package/dist/src/utils/markdown-query.d.ts +40 -0
  150. package/dist/src/utils/markdown-terminal.d.ts +1 -0
  151. package/dist/src/utils/next-steps.d.ts +11 -0
  152. package/dist/src/utils/page-readiness.d.ts +6 -0
  153. package/dist/src/utils/research-parser.d.ts +1 -0
  154. package/dist/src/utils/retry.d.ts +8 -0
  155. package/dist/src/utils/rules-loader.d.ts +12 -0
  156. package/dist/src/utils/secrets.d.ts +4 -0
  157. package/dist/src/utils/secrets.js +28 -0
  158. package/dist/src/utils/step-analyzer.d.ts +11 -0
  159. package/dist/src/utils/strings.d.ts +3 -0
  160. package/dist/src/utils/test-files.d.ts +3 -0
  161. package/dist/src/utils/test-plan-markdown.d.ts +9 -0
  162. package/dist/src/utils/throttle.d.ts +2 -0
  163. package/dist/src/utils/unique-names.d.ts +2 -0
  164. package/dist/src/utils/url-matcher.d.ts +6 -0
  165. package/dist/src/utils/web-element.d.ts +44 -0
  166. package/dist/src/utils/xpath.d.ts +17 -0
  167. package/package.json +11 -26
  168. package/src/action-result.ts +22 -7
  169. package/src/action.ts +12 -5
  170. package/src/ai/conversation.ts +1 -1
  171. package/src/ai/provider.ts +13 -5
  172. package/src/experience-tracker.ts +2 -1
  173. package/src/explorer.ts +14 -9
  174. package/src/index.ts +9 -0
  175. package/src/knowledge-tracker.ts +7 -1
  176. package/src/observability.ts +2 -1
  177. package/src/state-manager.ts +0 -8
  178. package/src/utils/secrets.ts +29 -0
  179. package/src/index.tsx +0 -62
package/dist/src/index.js CHANGED
@@ -1,55 +1,2 @@
1
- #!/usr/bin/env node
2
- import { Command } from 'commander';
3
- import { addKnowledgeCommand } from './commands/add-knowledge.js';
4
- import { cleanCommand } from './commands/clean.js';
5
- import { exploreCommand } from './commands/explore.js';
6
- import { initCommand } from './commands/init.js';
7
- const program = new Command();
8
- program
9
- .name('explorbot')
10
- .description('AI-powered web exploration tool')
11
- .option('-f, --from <url>', 'Start exploration from a specific URL')
12
- .option('-v, --verbose', 'Enable verbose logging')
13
- .option('--debug', 'Enable debug logging (same as --verbose)')
14
- .option('-c, --config <path>', 'Path to configuration file')
15
- .option('-p, --path <path>', 'Working directory path')
16
- .helpOption('-h, --help', 'Show this help message');
17
- program
18
- .command('clean')
19
- .description('Clean up artifacts or experience folders')
20
- .option('-t, --type <type>', 'Type of cleanup (artifacts|experience|all)', 'artifacts')
21
- .option('-p, --path <path>', 'Custom path to clean')
22
- .action(async (options, command) => {
23
- const globalOptions = command.parent.opts();
24
- const allOptions = { ...globalOptions, ...options };
25
- await cleanCommand(allOptions);
26
- });
27
- program
28
- .command('init')
29
- .description('Initialize a new project with configuration')
30
- .option('-c, --config-path <path>', 'Path for the config file', './explorbot.config.js')
31
- .option('-f, --force', 'Overwrite existing config file', false)
32
- .option('-p, --path <path>', 'Working directory for initialization')
33
- .action(async (options, command) => {
34
- const globalOptions = command.parent.opts();
35
- const allOptions = { ...globalOptions, ...options };
36
- await initCommand(allOptions);
37
- });
38
- program
39
- .command('add-knowledge')
40
- .alias('learn')
41
- .description('Add knowledge for specific URLs')
42
- .option('-p, --path <path>', 'Knowledge directory path')
43
- .action(async (options) => {
44
- await addKnowledgeCommand(options);
45
- });
46
- program.parse();
47
- const options = program.opts();
48
- const command = program.args[0];
49
- if (command === 'clean' || command === 'init' || command === 'add-knowledge' || command === 'learn') {
50
- // These commands are handled by their respective actions
51
- }
52
- else {
53
- // Default to explore command
54
- exploreCommand(options);
55
- }
1
+ export { ExplorBot } from "./explorbot.js";
2
+ export { Plan, Test, TestResult, TestStatus } from "./test-plan.js";
@@ -0,0 +1,33 @@
1
+ import { ActionResult } from './action-result.js';
2
+ interface Knowledge {
3
+ filePath: string;
4
+ url: string;
5
+ content: string;
6
+ [key: string]: any;
7
+ }
8
+ export declare class KnowledgeTracker {
9
+ knowledgeDir: string;
10
+ knowledgeFiles: Knowledge[];
11
+ isLoaded: boolean;
12
+ constructor();
13
+ loadKnowledgeFiles(): void;
14
+ getRelevantKnowledge(state: ActionResult): Knowledge[];
15
+ addKnowledge(urlPattern: string, description: string): {
16
+ filename: string;
17
+ filePath: string;
18
+ isNewFile: boolean;
19
+ };
20
+ interpolateVars(content: string): string;
21
+ generateFilename(url: string): string;
22
+ getExistingUrls(): string[];
23
+ getKnowledgeForUrl(urlPattern: string): string[];
24
+ listAllKnowledge(): Array<{
25
+ url: string;
26
+ firstLine: string;
27
+ filePath: string;
28
+ }>;
29
+ getMatchingKnowledge(url: string): Knowledge[];
30
+ normalizeUrl(url: string): string;
31
+ getStateParameters(state: ActionResult, keys: string[]): Record<string, any>;
32
+ }
33
+ export {};
@@ -5,6 +5,7 @@ import { ActionResult } from './action-result.js';
5
5
  import { ConfigParser } from './config.js';
6
6
  import { getCliName } from "./utils/cli-name.js";
7
7
  import { createDebug } from './utils/logger.js';
8
+ import { isSecretName, registerSecret } from './utils/secrets.js';
8
9
  const debugLog = createDebug('explorbot:knowledge-tracker');
9
10
  export class KnowledgeTracker {
10
11
  knowledgeDir;
@@ -109,9 +110,15 @@ export class KnowledgeTracker {
109
110
  return match;
110
111
  const namespace = expr.slice(0, dotIndex);
111
112
  const key = expr.slice(dotIndex + 1);
112
- if (namespace === 'env')
113
- return process.env[key] ?? '';
113
+ if (namespace === 'env') {
114
+ const value = process.env[key] ?? '';
115
+ if (isSecretName(key))
116
+ registerSecret(value);
117
+ return value;
118
+ }
114
119
  if (namespace === 'config') {
120
+ if (isSecretName(key))
121
+ return '';
115
122
  const config = ConfigParser.getInstance().getConfig();
116
123
  const value = key.split('.').reduce((obj, k) => obj?.[k], config);
117
124
  if (value !== undefined && typeof value !== 'object')
@@ -0,0 +1,13 @@
1
+ import { type Span } from '@opentelemetry/api';
2
+ type TelemetryMetadata = Record<string, unknown>;
3
+ export declare const Observability: {
4
+ run<T>(name: string, metadata: TelemetryMetadata, fn: () => Promise<T>): Promise<T>;
5
+ getTelemetry(): {
6
+ isEnabled: boolean;
7
+ functionId: string;
8
+ metadata: Record<string, unknown>;
9
+ };
10
+ isTracing(): boolean;
11
+ getSpan(): Span;
12
+ };
13
+ export {};
@@ -1,4 +1,5 @@
1
1
  import { trace } from '@opentelemetry/api';
2
+ import { redactSecrets } from './utils/secrets.js';
2
3
  let current = null;
3
4
  export const Observability = {
4
5
  async run(name, metadata, fn) {
@@ -70,7 +71,7 @@ function buildRootSpanAttributes(name, metadata) {
70
71
  attributes['langfuse.trace.tags'] = metadata.tags;
71
72
  }
72
73
  if (metadata.input !== undefined) {
73
- attributes['langfuse.trace.input'] = JSON.stringify(metadata.input);
74
+ attributes['langfuse.trace.input'] = redactSecrets(JSON.stringify(metadata.input));
74
75
  }
75
76
  return attributes;
76
77
  }
@@ -0,0 +1,31 @@
1
+ export interface TraceCall {
2
+ class: string;
3
+ method: string;
4
+ params: Record<string, any>;
5
+ }
6
+ export interface VerificationStep {
7
+ name: string;
8
+ args: any[];
9
+ }
10
+ export declare class PlaywrightRecorder {
11
+ context: any;
12
+ tracing: any;
13
+ active: boolean;
14
+ nextGroupId: number;
15
+ verifications: VerificationStep[];
16
+ recordVerification(steps: VerificationStep[]): void;
17
+ drainVerifications(): VerificationStep[];
18
+ start(browserContext: any): Promise<void>;
19
+ beginAction(title: string): Promise<string | null>;
20
+ endAction(): Promise<void>;
21
+ exportChunk(): Promise<Map<string, TraceCall[]>>;
22
+ stop(): Promise<void>;
23
+ isActive(): boolean;
24
+ }
25
+ declare function parseTrace(ndjson: string): Map<string, TraceCall[]>;
26
+ export declare function renderCall(call: TraceCall): string;
27
+ export declare function renderAssertion(assertion: {
28
+ name: string;
29
+ args: any[];
30
+ }): string;
31
+ export { parseTrace };
@@ -0,0 +1,34 @@
1
+ import { Client } from '@testomatio/reporter';
2
+ import type { Step } from '@testomatio/reporter/types/types.js';
3
+ import type { ReporterConfig } from './config.js';
4
+ import type { StateManager } from './state-manager.js';
5
+ import { Test } from './test-plan.js';
6
+ export type ReporterMeta = Record<string, string | undefined>;
7
+ export interface ReporterStep {
8
+ title: string;
9
+ status: 'passed' | 'failed';
10
+ code: string[];
11
+ discovery?: string;
12
+ }
13
+ export declare class Reporter {
14
+ client: Client;
15
+ isRunStarted: boolean;
16
+ reporterEnabled: boolean;
17
+ stateManager?: StateManager;
18
+ constructor(config?: ReporterConfig, stateManager?: StateManager);
19
+ buildTitle(): string;
20
+ static resolveEnabled(config?: ReporterConfig): boolean;
21
+ configureHtmlPipe(): void;
22
+ configureMarkdownPipe(): void;
23
+ configureRunGroup(runGroup: string | null | undefined): void;
24
+ startRun(): Promise<void>;
25
+ reportTestStart(test: Test): Promise<void>;
26
+ combineStepsAndNotes(test: Test, lastScreenshotFile?: string): Step[];
27
+ buildVerificationStep(test: Test, lastScreenshotFile?: string): Step | undefined;
28
+ reportTest(test: Test, meta?: ReporterMeta): Promise<void>;
29
+ finishRun(): Promise<void>;
30
+ isEnabled(): boolean;
31
+ setRunDescription(text: string): Promise<void>;
32
+ extractLastNoteMessage(test: Test): string;
33
+ reportSteps(test: Test, steps: ReporterStep[]): Promise<void>;
34
+ }
@@ -0,0 +1,185 @@
1
+ import { ActionResult } from './action-result.js';
2
+ import { ExperienceTracker } from './experience-tracker.js';
3
+ export interface Link {
4
+ title: string;
5
+ url: string;
6
+ visible?: boolean;
7
+ }
8
+ export interface WebPageState {
9
+ /** Unique incremental state identifier */
10
+ id?: number;
11
+ /** URL path without domain, including hash: /path/to/page#section */
12
+ url: string;
13
+ /** Page title */
14
+ title?: string;
15
+ /** HTTP status of the main document navigation */
16
+ httpStatus?: number;
17
+ /** Full URL for reference */
18
+ fullUrl?: string;
19
+ /** Timestamp when state was captured */
20
+ timestamp?: Date;
21
+ /** Hash of the state for unique identification */
22
+ hash?: string;
23
+ /** HTML file path */
24
+ htmlFile?: string;
25
+ /** Screenshot file path */
26
+ screenshotFile?: string;
27
+ /** Log file path */
28
+ logFile?: string;
29
+ /** HTML content */
30
+ html?: string;
31
+ notes?: string[];
32
+ /** Page headings */
33
+ h1?: string;
34
+ h2?: string;
35
+ h3?: string;
36
+ h4?: string;
37
+ ariaSnapshot?: string | null;
38
+ ariaSnapshotFile?: string;
39
+ links?: Link[];
40
+ verifications?: Record<string, boolean>;
41
+ }
42
+ export interface StateTransition {
43
+ /** Previous state (null if this is the first state) */
44
+ fromState: WebPageState | null;
45
+ /** Current state */
46
+ toState: WebPageState;
47
+ /** Code block that caused the transition */
48
+ codeBlock: string;
49
+ /** Timestamp of the transition */
50
+ timestamp: Date;
51
+ /** Any error that occurred during transition */
52
+ error?: string;
53
+ /** What triggered the state change */
54
+ trigger: 'manual' | 'navigation' | 'automatic';
55
+ }
56
+ export type StateChangeListener = (event: StateTransition) => void;
57
+ export interface Knowledge extends WebPageState {
58
+ /** File path */
59
+ filePath: string;
60
+ /** Markdown content */
61
+ content: string;
62
+ }
63
+ export declare class StateManager {
64
+ currentState: WebPageState | null;
65
+ stateHistory: StateTransition[];
66
+ allVisitedUrls: Set<string>;
67
+ knowledgeCache: Knowledge[];
68
+ lastKnowledgeScan: Date | null;
69
+ stateChangeListeners: StateChangeListener[];
70
+ experienceTracker: ExperienceTracker;
71
+ knowledgeDir: string;
72
+ nextStateId: number;
73
+ constructor();
74
+ getExperienceTracker(): ExperienceTracker;
75
+ /**
76
+ * Subscribe to state change events
77
+ */
78
+ onStateChange(listener: StateChangeListener): () => void;
79
+ /**
80
+ * Emit state change event to all listeners
81
+ */
82
+ emitStateChange(event: StateTransition): void;
83
+ /**
84
+ * Extract state path from full URL
85
+ * Removes domain, port, protocol
86
+ * Keeps path, query, and hash: /path/to/page?tab=users#section
87
+ */
88
+ /**
89
+ * Update current state from ActionResult and record transition if state changed
90
+ */
91
+ updateState(actionResult: ActionResult, codeBlock?: string, trigger?: 'manual' | 'navigation' | 'automatic'): WebPageState;
92
+ /**
93
+ * Update state from basic data (for navigation events)
94
+ */
95
+ updateStateFromBasic(url: string, title?: string, trigger?: 'manual' | 'navigation' | 'automatic'): WebPageState;
96
+ hasDialogAppeared(previousState: WebPageState | null, newState: WebPageState): boolean;
97
+ /**
98
+ * Generate a basic hash for state comparison
99
+ */
100
+ generateBasicHash(url: string, title?: string): string;
101
+ /**
102
+ * Get current state
103
+ */
104
+ getCurrentState(): WebPageState | null;
105
+ /**
106
+ * Check if state has changed since a given state
107
+ */
108
+ hasStateChanged(previousState: WebPageState | null): boolean;
109
+ /**
110
+ * Compare two states by their hash
111
+ */
112
+ statesEqual(state1: WebPageState | null, state2: WebPageState | null): boolean;
113
+ /**
114
+ * Get state history
115
+ */
116
+ getStateHistory(): StateTransition[];
117
+ isInDeadLoop(): boolean;
118
+ /**
119
+ * Get the last N transitions
120
+ */
121
+ getRecentTransitions(count?: number): StateTransition[];
122
+ /**
123
+ * Scan knowledge directory for .md files and cache them
124
+ */
125
+ scanKnowledgeFiles(): void;
126
+ /**
127
+ * Get relevant knowledge files for current state
128
+ */
129
+ getRelevantKnowledge(): Knowledge[];
130
+ /**
131
+ * Get relevant experience files for current state
132
+ */
133
+ getRelevantExperience(): string[];
134
+ /**
135
+ * Get all context for current state (knowledge + experience)
136
+ */
137
+ getCurrentContext(): {
138
+ state: WebPageState;
139
+ knowledge: Knowledge[];
140
+ experience: string[];
141
+ recentTransitions: StateTransition[];
142
+ };
143
+ /**
144
+ * Check if we've been in this state before
145
+ */
146
+ hasVisitedState(path: string): boolean;
147
+ getAllVisitedUrls(): Set<string>;
148
+ /**
149
+ * Get how many times we've visited a specific path
150
+ */
151
+ getVisitCount(path: string): number;
152
+ /**
153
+ * Find the most recent transition to a specific path
154
+ */
155
+ getLastVisitToPath(path: string): StateTransition | null;
156
+ /**
157
+ * Get previous state from history for comparison.
158
+ * If the last transition changed URL, returns the fromState (for URL change detection).
159
+ * Otherwise returns the most recent toState with content (for diffing).
160
+ */
161
+ getPreviousState(): WebPageState | null;
162
+ /**
163
+ * Load HTML content from file
164
+ */
165
+ loadHtmlFromFile(htmlFile: string): string | null;
166
+ /**
167
+ * Clear state history (useful for testing or reset)
168
+ * Note: This preserves the current state, only clears navigation history
169
+ */
170
+ clearHistory(): void;
171
+ /**
172
+ * Get the number of active state change listeners
173
+ */
174
+ getListenerCount(): number;
175
+ /**
176
+ * Clear all state change listeners
177
+ */
178
+ clearListeners(): void;
179
+ /**
180
+ * Complete cleanup of the StateManager instance
181
+ * Clears all state, history, listeners, and caches
182
+ */
183
+ cleanup(): void;
184
+ }
185
+ export declare function normalizeUrl(url: string): string;
@@ -5,7 +5,6 @@ import { ActionResult } from './action-result.js';
5
5
  import { ConfigParser, outputPath } from './config.js';
6
6
  import { ExperienceTracker } from './experience-tracker.js';
7
7
  import { detectFocusArea } from './utils/aria.js';
8
- import { htmlTextSnapshot } from './utils/html.js';
9
8
  import { createDebug } from './utils/logger.js';
10
9
  import { extractStatePath } from './utils/url-matcher.js';
11
10
  const debugLog = createDebug('explorbot:state');
@@ -53,12 +52,6 @@ export class StateManager {
53
52
  * Emit state change event to all listeners
54
53
  */
55
54
  emitStateChange(event) {
56
- // Log HTML content when state changes
57
- if (event.toState.html && event.toState.html !== event.fromState?.html) {
58
- let htmlContent = event?.toState?.html ?? '';
59
- htmlContent = htmlTextSnapshot(htmlContent);
60
- // tag('html').log(`Page HTML for ${event.toState.url}:\n${htmlContent}`);
61
- }
62
55
  this.stateChangeListeners.forEach((listener) => {
63
56
  try {
64
57
  listener(event);
@@ -0,0 +1,24 @@
1
+ interface TokenUsage {
2
+ input: number;
3
+ output: number;
4
+ total: number;
5
+ cached?: number;
6
+ }
7
+ export type ExplorbotMode = 'explore' | 'test' | 'freesail' | 'tui';
8
+ export declare class Stats {
9
+ static startTime: number;
10
+ static sessionName: string;
11
+ static researches: number;
12
+ static tests: number;
13
+ static plans: number;
14
+ static mode?: ExplorbotMode;
15
+ static focus?: string;
16
+ static models: Record<string, TokenUsage>;
17
+ static recordTokens(_agent: string, model: string, usage: TokenUsage): void;
18
+ static getElapsedTime(): string;
19
+ static humanizeTokens(num: number): string;
20
+ static modelsTable(roleModels: Record<string, string>): string;
21
+ static hasActivity(): boolean;
22
+ static sessionLabel(): string;
23
+ }
24
+ export {};
@@ -0,0 +1,24 @@
1
+ export declare class Suite {
2
+ readonly url: string;
3
+ _automatedTests: AutomatedTest[] | null;
4
+ _plannedScenarios: string[] | null;
5
+ constructor(url: string);
6
+ getAutomatedTests(): AutomatedTest[];
7
+ getPlannedScenarios(): string[];
8
+ getActiveScenarioTitles(): Set<string>;
9
+ get automatedTestCount(): number;
10
+ getAutomatedTestNames(): string[];
11
+ getAutomatedTestFiles(): string[];
12
+ loadAutomatedTests(): AutomatedTest[];
13
+ parseTestFile(filePath: string): {
14
+ url: string;
15
+ tests: AutomatedTest[];
16
+ } | null;
17
+ loadPlannedScenarios(): string[];
18
+ }
19
+ interface AutomatedTest {
20
+ title: string;
21
+ pending: boolean;
22
+ file: string;
23
+ }
24
+ export {};
@@ -0,0 +1,166 @@
1
+ import { WebPageState } from './state-manager.js';
2
+ export declare const TestResult: {
3
+ readonly PASSED: "passed";
4
+ readonly FAILED: "failed";
5
+ readonly SKIPPED: "skipped";
6
+ };
7
+ export type TestResultType = (typeof TestResult)[keyof typeof TestResult] | null;
8
+ export declare const TestStatus: {
9
+ readonly PENDING: "pending";
10
+ readonly IN_PROGRESS: "in_progress";
11
+ readonly DONE: "done";
12
+ };
13
+ export type TestStatusType = (typeof TestStatus)[keyof typeof TestStatus];
14
+ export interface Note {
15
+ message: string;
16
+ status?: TestResultType;
17
+ startTime: number;
18
+ endTime: number;
19
+ screenshot?: string;
20
+ log?: string;
21
+ }
22
+ export declare class ActiveNote {
23
+ task: Task;
24
+ startTime: number;
25
+ message: string;
26
+ status?: TestResultType;
27
+ screenshot?: string;
28
+ log?: string;
29
+ constructor(task: Task, message: string, status?: TestResultType);
30
+ commit(finalStatus?: TestResultType): void;
31
+ getMessage(): string;
32
+ getStartTime(): number;
33
+ }
34
+ export interface StepData {
35
+ text: string;
36
+ duration?: number;
37
+ status?: string;
38
+ error?: string;
39
+ log?: string;
40
+ artifacts?: string[];
41
+ noteStartTime?: number;
42
+ }
43
+ export declare class Task {
44
+ id: string;
45
+ description: string;
46
+ notes: Record<string, Note>;
47
+ steps: Record<string, StepData>;
48
+ states: WebPageState[];
49
+ startUrl: string;
50
+ verification?: Verification;
51
+ timestampCounter: number;
52
+ activeNote?: ActiveNote;
53
+ constructor(description: string, startUrl?: string);
54
+ startNote(message: string, status?: TestResultType): ActiveNote;
55
+ finishNote(activeNote: ActiveNote, endTime: number, finalStatus?: TestResultType): void;
56
+ getPrintableNotes(): string[];
57
+ notesToString(): string;
58
+ addNote(message: string, status?: TestResultType, screenshot?: string, log?: string): void;
59
+ addUrlNote(state: UrlNoteState, prevState?: {
60
+ title?: string;
61
+ h1?: string;
62
+ h2?: string;
63
+ }): void;
64
+ addState(state: WebPageState): void;
65
+ addStep(text: string, duration?: number, status?: string, error?: string, log?: string, artifacts?: string[]): void;
66
+ setActiveNoteScreenshot(screenshotFile?: string): void;
67
+ setVerification(message: string, status: TestResultType, state?: UrlNoteState): void;
68
+ addVerificationDetail(detail: string): void;
69
+ getLog(): Array<{
70
+ type: 'step' | 'note' | 'artifact';
71
+ content: string;
72
+ timestamp: number;
73
+ }>;
74
+ getLogString(): string;
75
+ getRunResult(): 'success' | 'partial' | 'failed';
76
+ }
77
+ export declare class Test extends Task {
78
+ scenario: string;
79
+ sessionName?: string;
80
+ status: TestStatusType;
81
+ result: TestResultType;
82
+ priority: 'critical' | 'important' | 'high' | 'normal' | 'low';
83
+ expected: string[];
84
+ plannedSteps: string[];
85
+ plan?: Plan;
86
+ summary: string;
87
+ artifacts: Record<string, string>;
88
+ generatedCode?: string;
89
+ style?: string;
90
+ planIteration: number;
91
+ enabled: boolean;
92
+ startTime?: number;
93
+ endTime?: number;
94
+ resetCount: number;
95
+ constructor(scenario: string, priority: 'critical' | 'important' | 'high' | 'normal' | 'low', expectedOutcome: string | string[], startUrl: string, plannedSteps?: string[]);
96
+ getVisitedUrls({ localOnly }?: {
97
+ localOnly?: boolean;
98
+ }): string[];
99
+ addArtifact(artifact?: string): void;
100
+ get hasFinished(): boolean;
101
+ get isSuccessful(): boolean;
102
+ get hasFailed(): boolean;
103
+ get isSkipped(): boolean;
104
+ getCheckedNotes(): Note[];
105
+ getCheckedExpectations(): string[];
106
+ hasAchievedAny(): boolean;
107
+ getRunResult(): 'success' | 'partial' | 'failed';
108
+ hasAchievedAll(): boolean;
109
+ isComplete(): boolean;
110
+ start(): void;
111
+ finish(result?: TestResultType): void;
112
+ getDurationMs(): number | null;
113
+ getRemainingExpectations(): string[];
114
+ getLog(): Array<{
115
+ type: 'step' | 'note' | 'artifact';
116
+ content: string;
117
+ timestamp: number;
118
+ }>;
119
+ }
120
+ type PlanChangeListener = (tests: Test[]) => void;
121
+ export declare class Plan {
122
+ title: string;
123
+ tests: Test[];
124
+ url?: string;
125
+ iteration: number;
126
+ parentPlan?: Plan;
127
+ changeListeners: PlanChangeListener[];
128
+ constructor(title: string);
129
+ nextIteration(): void;
130
+ addTest(test: Test): void;
131
+ removeTest(test: Test): void;
132
+ onTestsChange(listener: PlanChangeListener): () => void;
133
+ notifyChange(): void;
134
+ getAllTests(): Test[];
135
+ listTests(): Test[];
136
+ getPendingTests(): Test[];
137
+ get isComplete(): boolean;
138
+ get allSuccessful(): boolean;
139
+ get allFailed(): boolean;
140
+ updateStatus(): void;
141
+ static fromMarkdown(filePath: string): Plan;
142
+ saveToMarkdown(filePath: string): void;
143
+ static saveMultipleToMarkdown(plans: Plan[], filePath: string): void;
144
+ getVisitedPages(): WebPageState[];
145
+ merge(otherPlan: Plan): Plan;
146
+ toAiContext(options?: {
147
+ skipSteps?: boolean;
148
+ }): string;
149
+ }
150
+ interface Verification {
151
+ message: string;
152
+ status: TestResultType;
153
+ screenshot?: string;
154
+ url?: string;
155
+ pageLabel?: string;
156
+ details: string[];
157
+ }
158
+ interface UrlNoteState {
159
+ url?: string;
160
+ fullUrl?: string;
161
+ title?: string;
162
+ h1?: string;
163
+ h2?: string;
164
+ screenshotFile?: string;
165
+ }
166
+ export {};
@@ -0,0 +1,20 @@
1
+ export interface FocusAreaResult {
2
+ detected: boolean;
3
+ type: 'dialog' | 'modal' | null;
4
+ name: string | null;
5
+ }
6
+ export declare const compactAriaSnapshot: (snapshot: string | null, keepNamed?: boolean) => string;
7
+ export declare const diffAriaSnapshots: (previous: string | null, current: string | null) => string | null;
8
+ export declare const detectFocusArea: (snapshot: string | null) => FocusAreaResult;
9
+ export declare const collectInteractiveNodes: (snapshot: string | null) => Array<Record<string, unknown>>;
10
+ export interface FocusedElementInfo {
11
+ role: string;
12
+ name: string;
13
+ value?: string;
14
+ attributes?: string[];
15
+ }
16
+ export declare function extractFocusedElement(ariaSnapshot: string | null): FocusedElementInfo | null;
17
+ export declare function parseAriaLocator(ariaStr: string): {
18
+ role: string;
19
+ text: string;
20
+ } | null;
@@ -0,0 +1,8 @@
1
+ export declare class BrowserRecoveryError extends Error {
2
+ originalError: unknown;
3
+ recovered: boolean;
4
+ constructor(label: string, originalError: unknown, recovered: boolean);
5
+ }
6
+ export declare function isFatalBrowserError(error: unknown): boolean;
7
+ export declare function isNavigationTransitionError(error: unknown): boolean;
8
+ export declare function browserErrorMessage(error: unknown): string;
@@ -0,0 +1 @@
1
+ export declare function getCliName(): string;
@@ -0,0 +1 @@
1
+ export declare function extractCodeBlocks(aiResponse: string): string[];