explorbot 0.1.31 → 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 (177) hide show
  1. package/dist/boat/api-tester/example/apibot.config.js +30 -0
  2. package/dist/package.json +10 -25
  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/driller.d.ts +161 -0
  17. package/dist/src/ai/experience-compactor.d.ts +53 -0
  18. package/dist/src/ai/fisherman-tools.d.ts +90 -0
  19. package/dist/src/ai/fisherman.d.ts +30 -0
  20. package/dist/src/ai/historian/codeceptjs.d.ts +15 -0
  21. package/dist/src/ai/historian/experience.d.ts +40 -0
  22. package/dist/src/ai/historian/mixin.d.ts +2 -0
  23. package/dist/src/ai/historian/playwright.d.ts +20 -0
  24. package/dist/src/ai/historian/screencast.d.ts +32 -0
  25. package/dist/src/ai/historian/utils.d.ts +4 -0
  26. package/dist/src/ai/historian.d.ts +108 -0
  27. package/dist/src/ai/navigator.d.ts +56 -0
  28. package/dist/src/ai/pilot.d.ts +83 -0
  29. package/dist/src/ai/planner/session-dedup.d.ts +12 -0
  30. package/dist/src/ai/planner/styles.d.ts +6 -0
  31. package/dist/src/ai/planner/subpages.d.ts +35 -0
  32. package/dist/src/ai/planner.d.ts +79 -0
  33. package/dist/src/ai/provider.d.ts +50 -0
  34. package/dist/src/ai/provider.js +10 -3
  35. package/dist/src/ai/quartermaster.d.ts +57 -0
  36. package/dist/src/ai/rerunner.d.ts +49 -0
  37. package/dist/src/ai/researcher/cache.d.ts +6 -0
  38. package/dist/src/ai/researcher/coordinates.d.ts +56 -0
  39. package/dist/src/ai/researcher/deep-analysis.d.ts +74 -0
  40. package/dist/src/ai/researcher/fingerprint-worker.d.ts +1 -0
  41. package/dist/src/ai/researcher/focus.d.ts +8 -0
  42. package/dist/src/ai/researcher/locators.d.ts +36 -0
  43. package/dist/src/ai/researcher/mixin.d.ts +2 -0
  44. package/dist/src/ai/researcher/parser.d.ts +35 -0
  45. package/dist/src/ai/researcher/research-result.d.ts +16 -0
  46. package/dist/src/ai/researcher/sections.d.ts +19 -0
  47. package/dist/src/ai/rules.d.ts +15 -0
  48. package/dist/src/ai/session-analyst.d.ts +11 -0
  49. package/dist/src/ai/task-agent.d.ts +28 -0
  50. package/dist/src/ai/tester.d.ts +103 -0
  51. package/dist/src/ai/tools.d.ts +41 -0
  52. package/dist/src/api/api-client.d.ts +17 -0
  53. package/dist/src/api/request-result.d.ts +44 -0
  54. package/dist/src/api/request-store.d.ts +29 -0
  55. package/dist/src/api/spec-reader.d.ts +5 -0
  56. package/dist/src/api/xhr-capture.d.ts +10 -0
  57. package/dist/src/browser-server.d.ts +10 -0
  58. package/dist/src/command-handler.d.ts +68 -0
  59. package/dist/src/commands/add-rule-command.d.ts +11 -0
  60. package/dist/src/commands/base-command.d.ts +26 -0
  61. package/dist/src/commands/clean-command.d.ts +12 -0
  62. package/dist/src/commands/compact-command.d.ts +20 -0
  63. package/dist/src/commands/context-aria-command.d.ts +6 -0
  64. package/dist/src/commands/context-command.d.ts +11 -0
  65. package/dist/src/commands/context-data-command.d.ts +6 -0
  66. package/dist/src/commands/context-experience-command.d.ts +6 -0
  67. package/dist/src/commands/context-html-command.d.ts +6 -0
  68. package/dist/src/commands/context-knowledge-command.d.ts +6 -0
  69. package/dist/src/commands/debug-command.d.ts +6 -0
  70. package/dist/src/commands/drill-command.d.ts +10 -0
  71. package/dist/src/commands/exit-command.d.ts +7 -0
  72. package/dist/src/commands/experience-command.d.ts +15 -0
  73. package/dist/src/commands/explore-command.d.ts +51 -0
  74. package/dist/src/commands/freesail-command.d.ts +12 -0
  75. package/dist/src/commands/help-command.d.ts +6 -0
  76. package/dist/src/commands/index.d.ts +4 -0
  77. package/dist/src/commands/init-command.d.ts +7 -0
  78. package/dist/src/commands/knows-command.d.ts +10 -0
  79. package/dist/src/commands/learn-command.d.ts +7 -0
  80. package/dist/src/commands/navigate-command.d.ts +7 -0
  81. package/dist/src/commands/path-command.d.ts +10 -0
  82. package/dist/src/commands/plan-clear-command.d.ts +7 -0
  83. package/dist/src/commands/plan-command.d.ts +14 -0
  84. package/dist/src/commands/plan-edit-command.d.ts +7 -0
  85. package/dist/src/commands/plan-load-command.d.ts +7 -0
  86. package/dist/src/commands/plan-reload-command.d.ts +7 -0
  87. package/dist/src/commands/plan-save-command.d.ts +7 -0
  88. package/dist/src/commands/plans-command.d.ts +21 -0
  89. package/dist/src/commands/rerun-command.d.ts +7 -0
  90. package/dist/src/commands/research-command.d.ts +11 -0
  91. package/dist/src/commands/runs-command.d.ts +7 -0
  92. package/dist/src/commands/start-command.d.ts +7 -0
  93. package/dist/src/commands/status-command.d.ts +6 -0
  94. package/dist/src/commands/test-command.d.ts +11 -0
  95. package/dist/src/components/ActivityPane.d.ts +6 -0
  96. package/dist/src/components/AddKnowledge.d.ts +8 -0
  97. package/dist/src/components/AddRule.d.ts +9 -0
  98. package/dist/src/components/App.d.ts +9 -0
  99. package/dist/src/components/Autocomplete.d.ts +3 -0
  100. package/dist/src/components/InputPane.d.ts +13 -0
  101. package/dist/src/components/InputReadline.d.ts +17 -0
  102. package/dist/src/components/LogPane.d.ts +6 -0
  103. package/dist/src/components/PlanEditor.d.ts +9 -0
  104. package/dist/src/components/PlanPane.d.ts +13 -0
  105. package/dist/src/components/SessionTimer.d.ts +6 -0
  106. package/dist/src/components/StateTransitionPane.d.ts +8 -0
  107. package/dist/src/components/StatusPane.d.ts +4 -0
  108. package/dist/src/components/TaskPane.d.ts +9 -0
  109. package/dist/src/components/Welcome.d.ts +3 -0
  110. package/dist/src/components/WelcomeChecklist.d.ts +9 -0
  111. package/dist/src/components/WelcomeCommands.d.ts +6 -0
  112. package/dist/src/components/autocomplete-store.d.ts +10 -0
  113. package/dist/src/components/parse-keypress.d.ts +12 -0
  114. package/dist/src/config.d.ts +251 -0
  115. package/dist/src/execution-controller.d.ts +25 -0
  116. package/dist/src/experience-tracker.d.ts +107 -0
  117. package/dist/src/experience-tracker.js +2 -1
  118. package/dist/src/explorbot.d.ts +107 -0
  119. package/dist/src/explorer.d.ts +140 -0
  120. package/dist/src/explorer.js +13 -9
  121. package/dist/src/index.d.ts +6 -0
  122. package/dist/src/index.js +2 -55
  123. package/dist/src/knowledge-tracker.d.ts +33 -0
  124. package/dist/src/knowledge-tracker.js +9 -2
  125. package/dist/src/observability.d.ts +13 -0
  126. package/dist/src/observability.js +2 -1
  127. package/dist/src/playwright-recorder.d.ts +31 -0
  128. package/dist/src/reporter.d.ts +34 -0
  129. package/dist/src/state-manager.d.ts +185 -0
  130. package/dist/src/state-manager.js +0 -7
  131. package/dist/src/stats.d.ts +24 -0
  132. package/dist/src/suite.d.ts +24 -0
  133. package/dist/src/test-plan.d.ts +166 -0
  134. package/dist/src/utils/aria.d.ts +20 -0
  135. package/dist/src/utils/browser-errors.d.ts +8 -0
  136. package/dist/src/utils/cli-name.d.ts +1 -0
  137. package/dist/src/utils/code-extractor.d.ts +1 -0
  138. package/dist/src/utils/context-formatter.d.ts +25 -0
  139. package/dist/src/utils/error-page.d.ts +12 -0
  140. package/dist/src/utils/expandable.d.ts +4 -0
  141. package/dist/src/utils/hooks-runner.d.ts +15 -0
  142. package/dist/src/utils/html-diff.d.ts +19 -0
  143. package/dist/src/utils/html.d.ts +124 -0
  144. package/dist/src/utils/log-filters.d.ts +6 -0
  145. package/dist/src/utils/logger.d.ts +35 -0
  146. package/dist/src/utils/loop.d.ts +35 -0
  147. package/dist/src/utils/markdown-parser.d.ts +17 -0
  148. package/dist/src/utils/markdown-query.d.ts +40 -0
  149. package/dist/src/utils/markdown-terminal.d.ts +1 -0
  150. package/dist/src/utils/next-steps.d.ts +11 -0
  151. package/dist/src/utils/page-readiness.d.ts +6 -0
  152. package/dist/src/utils/research-parser.d.ts +1 -0
  153. package/dist/src/utils/retry.d.ts +8 -0
  154. package/dist/src/utils/rules-loader.d.ts +12 -0
  155. package/dist/src/utils/secrets.d.ts +4 -0
  156. package/dist/src/utils/secrets.js +28 -0
  157. package/dist/src/utils/step-analyzer.d.ts +11 -0
  158. package/dist/src/utils/strings.d.ts +3 -0
  159. package/dist/src/utils/test-files.d.ts +3 -0
  160. package/dist/src/utils/test-plan-markdown.d.ts +9 -0
  161. package/dist/src/utils/throttle.d.ts +2 -0
  162. package/dist/src/utils/unique-names.d.ts +2 -0
  163. package/dist/src/utils/url-matcher.d.ts +6 -0
  164. package/dist/src/utils/web-element.d.ts +44 -0
  165. package/dist/src/utils/xpath.d.ts +17 -0
  166. package/package.json +10 -25
  167. package/src/action-result.ts +22 -7
  168. package/src/action.ts +12 -5
  169. package/src/ai/provider.ts +10 -3
  170. package/src/experience-tracker.ts +2 -1
  171. package/src/explorer.ts +14 -9
  172. package/src/index.ts +9 -0
  173. package/src/knowledge-tracker.ts +7 -1
  174. package/src/observability.ts +2 -1
  175. package/src/state-manager.ts +0 -8
  176. package/src/utils/secrets.ts +29 -0
  177. package/src/index.tsx +0 -62
@@ -0,0 +1,25 @@
1
+ import { EventEmitter } from 'node:events';
2
+ export type InputCallback = (prompt: string) => Promise<string | null>;
3
+ export declare class ExecutionController extends EventEmitter {
4
+ static instance: ExecutionController;
5
+ interrupted: boolean;
6
+ inputCallback: InputCallback | null;
7
+ interruptResolvers: Array<() => void>;
8
+ abortController: AbortController | null;
9
+ awaitingInput: boolean;
10
+ constructor();
11
+ static getInstance(): ExecutionController;
12
+ setInputCallback(callback: InputCallback): void;
13
+ startExecution(): void;
14
+ getAbortSignal(): AbortSignal | undefined;
15
+ interrupt(): void;
16
+ isAwaitingInput(): boolean;
17
+ isInterrupted(): boolean;
18
+ waitForInterrupt(): Promise<void>;
19
+ checkInterrupt(): Promise<string | null>;
20
+ handleInterrupt(prompt?: string): Promise<string | null>;
21
+ requestInput(prompt: string): Promise<string | null>;
22
+ readlineInput(prompt: string): Promise<string | null>;
23
+ reset(): void;
24
+ }
25
+ export declare const executionController: ExecutionController;
@@ -0,0 +1,107 @@
1
+ import type { ActionResult } from './action-result.js';
2
+ import { KnowledgeTracker } from './knowledge-tracker.js';
3
+ export declare const RECENT_WINDOW_DAYS = 30;
4
+ /**
5
+ * Stores and reads per-page experience files (`./experience/<stateHash>.md`).
6
+ *
7
+ * Two writers, two contracts:
8
+ *
9
+ * writeFlow(state, body, relatedUrls?) — caller hands in a fully-formatted
10
+ * `## FLOW: <imperative title>` block (multi-step,
11
+ * `*` bullets + optional ```js``` + `>` discovery,
12
+ * ends with `---`). Tracker dedups + prepends.
13
+ * writeAction(state, ActionInput) — `## ACTION: <imperative title>`, single-step,
14
+ * optional `Solution:` line + one ```js``` code block.
15
+ * Title normalized via normalizeTitle().
16
+ *
17
+ * - Always h2. Never h3 for FLOW/ACTION.
18
+ * - On read (getSuccessfulExperience), headings are rendered as
19
+ * `## HOW to <title> (multi-step|single-step)` so prompts get natural phrasing.
20
+ */
21
+ export declare class ExperienceTracker {
22
+ experienceDir: string;
23
+ disabled: boolean;
24
+ knowledgeTracker: KnowledgeTracker;
25
+ constructor(options?: {
26
+ disabled?: boolean;
27
+ });
28
+ getExperienceDirectories(): string[];
29
+ ensureDirectory(dir: string): void;
30
+ readExperienceFile(stateHash: string): {
31
+ content: string;
32
+ data: any;
33
+ };
34
+ writeExperienceFile(stateHash: string, content: string, frontmatter?: any): void;
35
+ hasRecentExperience(stateHash: string, prefix?: string): boolean;
36
+ getExperienceFilePath(stateHash: string): string;
37
+ ensureExperienceFile(state: ActionResult): string;
38
+ updateSummary(state: ActionResult, summary: string): void;
39
+ isWritingDisabled(state: ActionResult): boolean;
40
+ writeAction(state: ActionResult, action: ActionInput): void;
41
+ writeFlow(state: ActionResult, body: string, relatedUrls?: string[]): void;
42
+ getAllExperience(): ExperienceFile[];
43
+ getRelevantExperience(state: ActionResult, options?: {
44
+ includeDescendantExperience?: boolean;
45
+ }): ExperienceFile[];
46
+ /**
47
+ * Clean up experience tracker (for testing)
48
+ */
49
+ cleanup(): void;
50
+ getSuccessfulExperience(state: ActionResult, options?: {
51
+ includeDescendants?: boolean;
52
+ stripCode?: boolean;
53
+ }): string[];
54
+ getExperienceTableOfContents(state: ActionResult, options?: {
55
+ includeDescendantExperience?: boolean;
56
+ }): ExperienceTocEntry[];
57
+ getExperienceSection(fileTag: string, sectionIndex: number, state: ActionResult, options?: {
58
+ includeDescendantExperience?: boolean;
59
+ }): {
60
+ title: string;
61
+ url: string;
62
+ content: string;
63
+ } | null;
64
+ findExperienceFileByHash(fileHash: string): string | null;
65
+ listAllExperienceToc(filter?: string, options?: {
66
+ recency?: 'recent' | 'old';
67
+ }): ExperienceTocEntry[];
68
+ getExperienceSectionByTag(fileTag: string, sectionIndex: number, filter?: string): {
69
+ title: string;
70
+ url: string;
71
+ content: string;
72
+ fileHash: string;
73
+ } | null;
74
+ }
75
+ export declare function renderExperienceToc(toc: ExperienceTocEntry[]): string;
76
+ export interface ExperienceFile {
77
+ filePath: string;
78
+ data: {
79
+ url?: string;
80
+ title?: string;
81
+ [key: string]: any;
82
+ };
83
+ content: string;
84
+ mtime: Date;
85
+ }
86
+ export interface ActionInput {
87
+ title: string;
88
+ code: string;
89
+ explanation?: string;
90
+ }
91
+ export interface SessionStep {
92
+ message: string;
93
+ status: 'passed' | 'failed' | 'neutral';
94
+ tool?: string;
95
+ code?: string;
96
+ discovery?: string;
97
+ }
98
+ export interface ExperienceTocEntry {
99
+ fileTag: string;
100
+ fileHash: string;
101
+ url: string;
102
+ sections: {
103
+ index: number;
104
+ level: 2 | 3;
105
+ title: string;
106
+ }[];
107
+ }
@@ -6,6 +6,7 @@ import { ConfigParser } from './config.js';
6
6
  import { KnowledgeTracker } from './knowledge-tracker.js';
7
7
  import { createDebug, tag } from './utils/logger.js';
8
8
  import { mdq } from './utils/markdown-query.js';
9
+ import { redactSecrets } from './utils/secrets.js';
9
10
  import { isNonReusableCode } from "./utils/step-analyzer.js";
10
11
  import { extractStatePath } from './utils/url-matcher.js';
11
12
  const debugLog = createDebug('explorbot:experience');
@@ -93,7 +94,7 @@ export class ExperienceTracker {
93
94
  return;
94
95
  }
95
96
  const filePath = this.getExperienceFilePath(stateHash);
96
- const fileContent = matter.stringify(content, frontmatter || {});
97
+ const fileContent = matter.stringify(redactSecrets(content), frontmatter || {});
97
98
  writeFileSync(filePath, fileContent, 'utf8');
98
99
  }
99
100
  hasRecentExperience(stateHash, prefix = '') {
@@ -0,0 +1,107 @@
1
+ import { Captain } from './ai/captain.js';
2
+ import { Driller } from './ai/driller.js';
3
+ import { ExperienceCompactor } from './ai/experience-compactor.js';
4
+ import { Fisherman } from './ai/fisherman.js';
5
+ import { Historian } from './ai/historian.js';
6
+ import { Navigator } from './ai/navigator.js';
7
+ import { Pilot } from './ai/pilot.js';
8
+ import { Planner } from './ai/planner.js';
9
+ import { AIProvider } from './ai/provider.js';
10
+ import { Quartermaster } from './ai/quartermaster.js';
11
+ import { Rerunner } from './ai/rerunner.js';
12
+ import { Researcher } from './ai/researcher.js';
13
+ import { SessionAnalyst } from './ai/session-analyst.js';
14
+ import { Tester } from './ai/tester.js';
15
+ import type { ExplorbotConfig } from './config.js';
16
+ import { ConfigParser } from './config.js';
17
+ import { ExperienceTracker } from './experience-tracker.js';
18
+ import Explorer from './explorer.js';
19
+ import { KnowledgeTracker } from './knowledge-tracker.js';
20
+ import { WebPageState } from './state-manager.js';
21
+ import type { Suite } from './suite.js';
22
+ import { Plan, type Test } from './test-plan.js';
23
+ export interface ExplorBotOptions {
24
+ from?: string;
25
+ baseUrl?: string;
26
+ verbose?: boolean;
27
+ config?: string;
28
+ path?: string;
29
+ show?: boolean;
30
+ headless?: boolean;
31
+ incognito?: boolean;
32
+ session?: string;
33
+ }
34
+ export type UserResolveFunction = (error?: Error, showWelcome?: boolean) => Promise<string | null>;
35
+ export declare class ExplorBot {
36
+ configParser: ConfigParser;
37
+ explorer: Explorer;
38
+ provider: AIProvider;
39
+ config: ExplorbotConfig;
40
+ options: ExplorBotOptions;
41
+ userResolveFn: UserResolveFunction | null;
42
+ needsInput: boolean;
43
+ currentPlan?: Plan;
44
+ planFeature?: string;
45
+ lastPlanError: Error | null;
46
+ lastSavedPlanPath: string | null;
47
+ agents: Record<string, any>;
48
+ sessionPlans: Plan[];
49
+ lastReportedTestCount: number;
50
+ constructor(options?: ExplorBotOptions);
51
+ get isExploring(): boolean;
52
+ setUserResolve(fn: UserResolveFunction): void;
53
+ start(): Promise<void>;
54
+ startProviderOnly(): Promise<void>;
55
+ stop(): Promise<void>;
56
+ visitInitialState(): Promise<void>;
57
+ visit(url: string): Promise<void>;
58
+ openFreshTab(): Promise<void>;
59
+ getCurrentState(): WebPageState | null;
60
+ getExplorer(): Explorer;
61
+ getKnowledgeTracker(): KnowledgeTracker;
62
+ getExperienceTracker(): ExperienceTracker;
63
+ getConfig(): ExplorbotConfig;
64
+ getOptions(): ExplorBotOptions;
65
+ isReady(): boolean;
66
+ getConfigParser(): ConfigParser;
67
+ getProvider(): AIProvider;
68
+ createAgent<T>(factory: (deps: {
69
+ explorer: Explorer;
70
+ ai: AIProvider;
71
+ config: ExplorbotConfig;
72
+ }) => T): T;
73
+ agentResearcher(): Researcher;
74
+ agentNavigator(): Navigator;
75
+ agentPlanner(): Planner;
76
+ agentPilot(): Pilot;
77
+ agentTester(): Tester;
78
+ agentCaptain(): Captain;
79
+ agentExperienceCompactor(): ExperienceCompactor;
80
+ agentQuartermaster(): Quartermaster | null;
81
+ agentHistorian(): Historian;
82
+ agentRerunner(): Rerunner;
83
+ agentDriller(): Driller;
84
+ agentSessionAnalyst(): SessionAnalyst;
85
+ agentFisherman(): Fisherman | null;
86
+ getCurrentPlan(): Plan | undefined;
87
+ getSuite(): Suite | null;
88
+ getPlanFeature(): string | undefined;
89
+ clearPlan(): void;
90
+ plan(feature?: string, opts?: {
91
+ fresh?: boolean;
92
+ style?: string;
93
+ extend?: Plan;
94
+ completedPlans?: Plan[];
95
+ noSave?: boolean;
96
+ }): Promise<Plan>;
97
+ getPlansDir(): string;
98
+ savePlan(filename?: string): string | null;
99
+ savePlans(plans: Plan[], filename?: string): string | null;
100
+ generatePlanFilename(feature?: string): string;
101
+ resolvePlanPath(filename: string): string;
102
+ loadPlan(filename: string): Plan;
103
+ loadPlans(filename: string): Plan[];
104
+ setCurrentPlan(plan?: Plan): void;
105
+ getSessionTests(): Test[];
106
+ printSessionAnalysis(): Promise<void>;
107
+ }
@@ -0,0 +1,140 @@
1
+ import type { BrowserContextOptions } from 'playwright';
2
+ import { ActionResult } from './action-result.js';
3
+ import Action from './action.js';
4
+ import { AIProvider } from './ai/provider.js';
5
+ import { RequestStore } from './api/request-store.js';
6
+ import { XhrCapture } from './api/xhr-capture.js';
7
+ import type { ExplorbotConfig } from './config.js';
8
+ import type { UserResolveFunction } from './explorbot.js';
9
+ import { KnowledgeTracker } from './knowledge-tracker.js';
10
+ import { PlaywrightRecorder } from './playwright-recorder.js';
11
+ import { Reporter } from './reporter.js';
12
+ import { StateManager } from './state-manager.js';
13
+ import { Test } from './test-plan.js';
14
+ import { WebElement } from './utils/web-element.js';
15
+ declare global {
16
+ namespace NodeJS {
17
+ interface Global {
18
+ output_dir: string;
19
+ }
20
+ }
21
+ }
22
+ declare namespace CodeceptJS {
23
+ interface I {
24
+ [key: string]: any;
25
+ }
26
+ }
27
+ interface TabInfo {
28
+ url: string;
29
+ title: string;
30
+ }
31
+ interface BrowserExecutionErrorResult {
32
+ action: 'continue' | 'stop';
33
+ message: string;
34
+ recovered?: boolean;
35
+ }
36
+ declare class Explorer {
37
+ aiProvider: AIProvider;
38
+ playwrightHelper: any;
39
+ isStarted: boolean;
40
+ isSharedBrowser: boolean;
41
+ actor: CodeceptJS.I;
42
+ stateManager: StateManager;
43
+ knowledgeTracker: KnowledgeTracker;
44
+ config: ExplorbotConfig;
45
+ userResolveFn: UserResolveFunction | null;
46
+ options?: {
47
+ show?: boolean;
48
+ headless?: boolean;
49
+ incognito?: boolean;
50
+ session?: string;
51
+ };
52
+ reporter: Reporter;
53
+ otherTabs: TabInfo[];
54
+ _activeTest: Test | null;
55
+ xhrCapture: XhrCapture | null;
56
+ requestStore: RequestStore | null;
57
+ playwrightRecorder: PlaywrightRecorder;
58
+ observedTestPages: Set<any>;
59
+ testPageErrorHandler: ((error: Error) => void) | null;
60
+ testConsoleHandler: ((message: any) => void) | null;
61
+ testDialogHandler: ((dialog: any) => void) | null;
62
+ constructor(config: ExplorbotConfig, aiProvider: AIProvider, options?: {
63
+ show?: boolean;
64
+ headless?: boolean;
65
+ incognito?: boolean;
66
+ session?: string;
67
+ });
68
+ initializeContainer(): void;
69
+ convertToCodeceptConfig(config: ExplorbotConfig): any;
70
+ getConfig(): ExplorbotConfig;
71
+ getConfigPath(): string | null;
72
+ getAIProvider(): AIProvider;
73
+ getStateManager(): StateManager;
74
+ getCurrentUrl(): string;
75
+ getKnowledgeTracker(): KnowledgeTracker;
76
+ getReporter(): Reporter;
77
+ getRequestStore(): RequestStore | null;
78
+ extractCookies(): Promise<Record<string, string>>;
79
+ setupXhrCapture(reuseRequestStore?: boolean): void;
80
+ start(): Promise<any>;
81
+ connectOrLaunchBrowser(): Promise<void>;
82
+ createBrowserContextOptions(): BrowserContextOptions;
83
+ createAction(): Action;
84
+ runWithBrowserRecovery<T>(label: string, operation: () => Promise<T>): Promise<T>;
85
+ capturePageState(opts?: {
86
+ includeScreenshot?: boolean;
87
+ }): Promise<ActionResult>;
88
+ capturePageWithScreenshot(): Promise<ActionResult>;
89
+ executeAction(code: string): Promise<Action>;
90
+ attemptAction(code: string, originalMessage?: string, experience?: boolean): Promise<boolean>;
91
+ getPlaywrightRecorder(): PlaywrightRecorder;
92
+ visit(url: string): Promise<Action>;
93
+ visitOnce(url: string): Promise<Action>;
94
+ annotateElements(): Promise<WebElement[]>;
95
+ visuallyAnnotateElements(opts?: {
96
+ containers?: Array<{
97
+ css: string;
98
+ label: string;
99
+ }>;
100
+ }): Promise<number>;
101
+ getEidxInContainer(containerCss: string | null): Promise<string[]>;
102
+ getEidxByLocator(locator: string, container?: string | null): Promise<string | null>;
103
+ reload(): Promise<void>;
104
+ resolveBrowserUrl(url?: string): string | null;
105
+ isFatalBrowserError(error: unknown): boolean;
106
+ recoverFromBrowserError(): Promise<boolean>;
107
+ restartBrowser(): Promise<boolean>;
108
+ switchToMainFrame(): Promise<void>;
109
+ waitForPageReadiness(): Promise<boolean>;
110
+ isInsideIframe(): Promise<boolean>;
111
+ getCurrentIframeInfo(): string | null;
112
+ hasOtherTabs(): boolean;
113
+ getOtherTabsInfo(): TabInfo[];
114
+ clearOtherTabsInfo(): void;
115
+ setUserResolve(userResolveFn: UserResolveFunction): void;
116
+ listenToStateChanged(): void;
117
+ stop(): Promise<void>;
118
+ get activeTest(): Test | null;
119
+ startTest(test: Test): Promise<boolean>;
120
+ ensurePageAvailable(): Promise<boolean>;
121
+ ensureActiveTestPageAvailable(): Promise<boolean>;
122
+ handleExecutionError(error: unknown): Promise<BrowserExecutionErrorResult>;
123
+ watchActiveTestPage(page?: any): void;
124
+ stopTest(test: Test, meta?: Record<string, string>): Promise<void>;
125
+ unwatchActiveTestPages(): void;
126
+ hasPlaywrightLocator(locatorFn: (page: any) => any, opts?: {
127
+ multiple?: boolean;
128
+ contents?: boolean;
129
+ success?: (locator: any) => Promise<void> | void;
130
+ }): Promise<boolean>;
131
+ playwrightLocatorCount(locatorFn: (page: any) => any): Promise<number>;
132
+ bindFrameNavigated(page: any): void;
133
+ openFreshTab(): Promise<void>;
134
+ closeOtherTabs(): Promise<void>;
135
+ }
136
+ export declare function annotatePageElements(page: any): Promise<{
137
+ ariaSnapshot: string;
138
+ elements: WebElement[];
139
+ }>;
140
+ export default Explorer;
@@ -629,17 +629,21 @@ class Explorer {
629
629
  test.setActiveNoteScreenshot(lastScreenshot);
630
630
  };
631
631
  this.watchActiveTestPage();
632
- codeceptjs.event.dispatcher.emit('test.before', codeceptjsTest);
633
- codeceptjs.event.dispatcher.emit('test.start', codeceptjsTest);
634
- codeceptjs.event.dispatcher.on('step.passed', (step) => stepHandler(step, 'passed'));
635
- codeceptjs.event.dispatcher.on('step.failed', (step, error) => {
632
+ const onStepPassed = (step) => stepHandler(step, 'passed');
633
+ const onStepFailed = (step, error) => {
636
634
  stepHandler(step, 'failed', error?.message || String(error), error?.stack);
637
- });
638
- codeceptjs.event.dispatcher.on('test.after', () => {
639
- codeceptjs.event.dispatcher.off('step.passed', stepHandler);
640
- codeceptjs.event.dispatcher.off('step.failed', stepHandler);
635
+ };
636
+ const onTestAfter = () => {
637
+ codeceptjs.event.dispatcher.off('step.passed', onStepPassed);
638
+ codeceptjs.event.dispatcher.off('step.failed', onStepFailed);
639
+ codeceptjs.event.dispatcher.off('test.after', onTestAfter);
641
640
  this.unwatchActiveTestPages();
642
- });
641
+ };
642
+ codeceptjs.event.dispatcher.emit('test.before', codeceptjsTest);
643
+ codeceptjs.event.dispatcher.emit('test.start', codeceptjsTest);
644
+ codeceptjs.event.dispatcher.on('step.passed', onStepPassed);
645
+ codeceptjs.event.dispatcher.on('step.failed', onStepFailed);
646
+ codeceptjs.event.dispatcher.on('test.after', onTestAfter);
643
647
  return true;
644
648
  }
645
649
  async ensurePageAvailable() {
@@ -0,0 +1,6 @@
1
+ export { ExplorBot } from './explorbot.js';
2
+ export type { ExplorBotOptions, UserResolveFunction } from './explorbot.js';
3
+ export { Plan, Test, TestResult, TestStatus } from './test-plan.js';
4
+ export type { Note, StepData, TestResultType, TestStatusType } from './test-plan.js';
5
+ export type { Link, StateTransition, WebPageState } from './state-manager.js';
6
+ export type { AIConfig, ExplorbotConfig, PlaywrightConfig } from './config.js';
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
+ }