explorbot 0.1.31 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -14
- package/bin/explorbot-cli.ts +4 -3
- package/boat/doc-collector/src/ai/documentarian.ts +22 -27
- package/boat/doc-collector/src/ai/tools.ts +67 -10
- package/boat/doc-collector/src/docbot.ts +28 -7
- package/boat/doc-collector/src/docs-renderer.ts +19 -24
- package/boat/doc-collector/src/screenshots.ts +33 -1
- package/boat/doc-collector/src/state-diagram.ts +281 -0
- package/dist/bin/explorbot-cli.js +3 -3
- package/dist/boat/doc-collector/src/ai/documentarian.js +16 -6
- package/dist/boat/doc-collector/src/ai/tools.js +47 -10
- package/dist/boat/doc-collector/src/docbot.js +25 -6
- package/dist/boat/doc-collector/src/docs-renderer.js +18 -3
- package/dist/boat/doc-collector/src/screenshots.js +29 -0
- package/dist/boat/doc-collector/src/state-diagram.js +200 -0
- package/dist/package.json +8 -6
- package/dist/src/action-result.d.ts +131 -0
- package/dist/src/action-result.js +82 -159
- package/dist/src/action.d.ts +43 -0
- package/dist/src/action.js +18 -106
- package/dist/src/activity.d.ts +26 -0
- package/dist/src/ai/agent.d.ts +3 -0
- package/dist/src/ai/captain/file-tools.d.ts +28 -0
- package/dist/src/ai/captain/idle-mode.d.ts +11 -0
- package/dist/src/ai/captain/mixin.d.ts +10 -0
- package/dist/src/ai/captain/test-mode.d.ts +13 -0
- package/dist/src/ai/captain/web-mode.d.ts +13 -0
- package/dist/src/ai/captain/web-mode.js +0 -7
- package/dist/src/ai/captain.d.ts +141 -0
- package/dist/src/ai/captain.js +4 -19
- package/dist/src/ai/conversation.d.ts +28 -0
- package/dist/src/ai/conversation.js +9 -28
- package/dist/src/ai/driller.d.ts +157 -0
- package/dist/src/ai/driller.js +3 -12
- package/dist/src/ai/experience-compactor.d.ts +53 -0
- package/dist/src/ai/experience-compactor.js +16 -33
- package/dist/src/ai/fisherman-tools.d.ts +90 -0
- package/dist/src/ai/fisherman-tools.js +1 -1
- package/dist/src/ai/fisherman.d.ts +29 -0
- package/dist/src/ai/fisherman.js +0 -3
- package/dist/src/ai/historian/codeceptjs.d.ts +17 -0
- package/dist/src/ai/historian/codeceptjs.js +3 -2
- package/dist/src/ai/historian/experience.d.ts +40 -0
- package/dist/src/ai/historian/mixin.d.ts +2 -0
- package/dist/src/ai/historian/playwright.d.ts +22 -0
- package/dist/src/ai/historian/playwright.js +3 -2
- package/dist/src/ai/historian/screencast.d.ts +32 -0
- package/dist/src/ai/historian/utils.d.ts +3 -0
- package/dist/src/ai/historian/utils.js +0 -1
- package/dist/src/ai/historian.d.ts +109 -0
- package/dist/src/ai/historian.js +1 -5
- package/dist/src/ai/navigator.d.ts +54 -0
- package/dist/src/ai/navigator.js +11 -46
- package/dist/src/ai/pilot.d.ts +81 -0
- package/dist/src/ai/pilot.js +6 -17
- package/dist/src/ai/planner/session-dedup.d.ts +12 -0
- package/dist/src/ai/planner/styles.d.ts +6 -0
- package/dist/src/ai/planner/subpages.d.ts +35 -0
- package/dist/src/ai/planner.d.ts +79 -0
- package/dist/src/ai/planner.js +49 -37
- package/dist/src/ai/provider.d.ts +53 -0
- package/dist/src/ai/provider.js +78 -130
- package/dist/src/ai/quartermaster.d.ts +56 -0
- package/dist/src/ai/quartermaster.js +4 -10
- package/dist/src/ai/rerunner.d.ts +48 -0
- package/dist/src/ai/rerunner.js +14 -22
- package/dist/src/ai/researcher/cache.d.ts +6 -0
- package/dist/src/ai/researcher/cache.js +11 -18
- package/dist/src/ai/researcher/coordinates.d.ts +56 -0
- package/dist/src/ai/researcher/deep-analysis.d.ts +74 -0
- package/dist/src/ai/researcher/deep-analysis.js +3 -6
- package/dist/src/ai/researcher/fingerprint-worker.d.ts +1 -0
- package/dist/src/ai/researcher/focus.d.ts +8 -0
- package/dist/src/ai/researcher/locators.d.ts +36 -0
- package/dist/src/ai/researcher/mixin.d.ts +2 -0
- package/dist/src/ai/researcher/parser.d.ts +35 -0
- package/dist/src/ai/researcher/parser.js +1 -1
- package/dist/src/ai/researcher/research-result.d.ts +15 -0
- package/dist/src/ai/researcher/research-result.js +0 -19
- package/dist/src/ai/researcher/sections.d.ts +19 -0
- package/dist/src/ai/researcher/sections.js +5 -1
- package/dist/src/ai/researcher.js +12 -53
- package/dist/src/ai/rules.d.ts +16 -0
- package/dist/src/ai/rules.js +22 -15
- package/dist/src/ai/session-analyst.d.ts +11 -0
- package/dist/src/ai/session-analyst.js +8 -5
- package/dist/src/ai/task-agent.d.ts +28 -0
- package/dist/src/ai/task-agent.js +2 -27
- package/dist/src/ai/tester.d.ts +101 -0
- package/dist/src/ai/tester.js +10 -61
- package/dist/src/ai/tools.d.ts +52 -0
- package/dist/src/ai/tools.js +119 -101
- package/dist/src/api/api-client.d.ts +17 -0
- package/dist/src/api/request-result.d.ts +44 -0
- package/dist/src/api/request-store.d.ts +29 -0
- package/dist/src/api/spec-reader.d.ts +5 -0
- package/dist/src/api/xhr-capture.d.ts +10 -0
- package/dist/src/browser-server.d.ts +10 -0
- package/dist/src/command-handler.d.ts +68 -0
- package/dist/src/commands/add-rule-command.d.ts +11 -0
- package/dist/src/commands/base-command.d.ts +26 -0
- package/dist/src/commands/clean-command.d.ts +12 -0
- package/dist/src/commands/compact-command.d.ts +20 -0
- package/dist/src/commands/compact-command.js +6 -6
- package/dist/src/commands/context-aria-command.d.ts +6 -0
- package/dist/src/commands/context-command.d.ts +11 -0
- package/dist/src/commands/context-command.js +1 -1
- package/dist/src/commands/context-data-command.d.ts +6 -0
- package/dist/src/commands/context-experience-command.d.ts +6 -0
- package/dist/src/commands/context-html-command.d.ts +6 -0
- package/dist/src/commands/context-knowledge-command.d.ts +6 -0
- package/dist/src/commands/context-knowledge-command.js +1 -1
- package/dist/src/commands/debug-command.d.ts +6 -0
- package/dist/src/commands/drill-command.d.ts +10 -0
- package/dist/src/commands/exit-command.d.ts +7 -0
- package/dist/src/commands/experience-command.d.ts +15 -0
- package/dist/src/commands/experience-command.js +1 -1
- package/dist/src/commands/explore-command.d.ts +51 -0
- package/dist/src/commands/freesail-command.d.ts +12 -0
- package/dist/src/commands/help-command.d.ts +6 -0
- package/dist/src/commands/index.d.ts +4 -0
- package/dist/src/commands/init-command.d.ts +7 -0
- package/dist/src/commands/knows-command.d.ts +10 -0
- package/dist/src/commands/knows-command.js +1 -1
- package/dist/src/commands/learn-command.d.ts +7 -0
- package/dist/src/commands/learn-command.js +3 -1
- package/dist/src/commands/navigate-command.d.ts +7 -0
- package/dist/src/commands/path-command.d.ts +10 -0
- package/dist/src/commands/plan-clear-command.d.ts +7 -0
- package/dist/src/commands/plan-command.d.ts +14 -0
- package/dist/src/commands/plan-edit-command.d.ts +7 -0
- package/dist/src/commands/plan-load-command.d.ts +7 -0
- package/dist/src/commands/plan-reload-command.d.ts +7 -0
- package/dist/src/commands/plan-save-command.d.ts +7 -0
- package/dist/src/commands/plans-command.d.ts +21 -0
- package/dist/src/commands/rerun-command.d.ts +7 -0
- package/dist/src/commands/research-command.d.ts +11 -0
- package/dist/src/commands/runs-command.d.ts +7 -0
- package/dist/src/commands/start-command.d.ts +7 -0
- package/dist/src/commands/status-command.d.ts +6 -0
- package/dist/src/commands/test-command.d.ts +11 -0
- package/dist/src/components/ActivityPane.d.ts +6 -0
- package/dist/src/components/AddKnowledge.d.ts +10 -0
- package/dist/src/components/AddKnowledge.js +3 -7
- package/dist/src/components/AddRule.d.ts +9 -0
- package/dist/src/components/App.d.ts +9 -0
- package/dist/src/components/App.js +2 -2
- package/dist/src/components/Autocomplete.d.ts +3 -0
- package/dist/src/components/InputPane.d.ts +13 -0
- package/dist/src/components/InputReadline.d.ts +17 -0
- package/dist/src/components/LogPane.d.ts +6 -0
- package/dist/src/components/PlanEditor.d.ts +9 -0
- package/dist/src/components/PlanPane.d.ts +13 -0
- package/dist/src/components/SessionTimer.d.ts +6 -0
- package/dist/src/components/StateTransitionPane.d.ts +8 -0
- package/dist/src/components/StatusPane.d.ts +4 -0
- package/dist/src/components/TaskPane.d.ts +9 -0
- package/dist/src/components/Welcome.d.ts +3 -0
- package/dist/src/components/WelcomeChecklist.d.ts +9 -0
- package/dist/src/components/WelcomeCommands.d.ts +6 -0
- package/dist/src/components/autocomplete-store.d.ts +10 -0
- package/dist/src/components/parse-keypress.d.ts +12 -0
- package/dist/src/config.d.ts +253 -0
- package/dist/src/config.js +12 -0
- package/dist/src/execution-controller.d.ts +25 -0
- package/dist/src/experience-tracker.d.ts +112 -0
- package/dist/src/experience-tracker.js +83 -155
- package/dist/src/explorbot.d.ts +106 -0
- package/dist/src/explorbot.js +17 -51
- package/dist/src/explorer.d.ts +129 -0
- package/dist/src/explorer.js +31 -77
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.js +2 -55
- package/dist/src/knowledge-tracker.d.ts +33 -0
- package/dist/src/knowledge-tracker.js +47 -47
- package/dist/src/observability.d.ts +13 -0
- package/dist/src/observability.js +2 -1
- package/dist/src/playwright-recorder.d.ts +31 -0
- package/dist/src/reporter.d.ts +34 -0
- package/dist/src/state-manager.d.ts +160 -0
- package/dist/src/state-manager.js +10 -136
- package/dist/src/stats.d.ts +24 -0
- package/dist/src/suite.d.ts +24 -0
- package/dist/src/test-plan.d.ts +166 -0
- package/dist/src/utils/aria.d.ts +25 -0
- package/dist/src/utils/aria.js +4 -1
- package/dist/src/utils/browser-errors.d.ts +8 -0
- package/dist/src/utils/cache.d.ts +15 -0
- package/dist/src/utils/cache.js +34 -0
- package/dist/src/utils/cli-name.d.ts +1 -0
- package/dist/src/utils/code-extractor.d.ts +1 -0
- package/dist/src/utils/context-formatter.d.ts +31 -0
- package/dist/src/utils/context-formatter.js +15 -27
- package/dist/src/utils/error-page.d.ts +12 -0
- package/dist/src/utils/expandable.d.ts +4 -0
- package/dist/src/utils/hooks-runner.d.ts +15 -0
- package/dist/src/utils/html-diff.d.ts +19 -0
- package/dist/src/utils/html.d.ts +129 -0
- package/dist/src/utils/html.js +71 -0
- package/dist/src/utils/log-filters.d.ts +6 -0
- package/dist/src/utils/logger.d.ts +35 -0
- package/dist/src/utils/loop.d.ts +35 -0
- package/dist/src/utils/markdown-files.d.ts +10 -0
- package/dist/src/utils/markdown-files.js +21 -0
- package/dist/src/utils/markdown-parser.d.ts +17 -0
- package/dist/src/utils/markdown-query.d.ts +46 -0
- package/dist/src/utils/markdown-query.js +14 -1
- package/dist/src/utils/markdown-terminal.d.ts +1 -0
- package/dist/src/utils/next-steps.d.ts +11 -0
- package/dist/src/utils/page-readiness.d.ts +7 -0
- package/dist/src/utils/page-readiness.js +1 -1
- package/dist/src/utils/research-parser.d.ts +1 -0
- package/dist/src/utils/retry.d.ts +8 -0
- package/dist/src/utils/rules-loader.d.ts +12 -0
- package/dist/src/utils/secrets.d.ts +4 -0
- package/dist/src/utils/secrets.js +28 -0
- package/dist/src/utils/step-analyzer.d.ts +11 -0
- package/dist/src/utils/strings.d.ts +5 -0
- package/dist/src/utils/strings.js +10 -0
- package/dist/src/utils/test-files.d.ts +3 -0
- package/dist/src/utils/test-plan-markdown.d.ts +9 -0
- package/dist/src/utils/throttle.d.ts +2 -0
- package/dist/src/utils/unique-names.d.ts +2 -0
- package/dist/src/utils/url-matcher.d.ts +6 -0
- package/dist/src/utils/web-element.d.ts +45 -0
- package/dist/src/utils/web-element.js +3 -0
- package/dist/src/utils/web-sandbox.d.ts +4 -0
- package/dist/src/utils/web-sandbox.js +37 -0
- package/dist/src/utils/xpath.d.ts +17 -0
- package/package.json +8 -6
- package/src/action-result.ts +80 -168
- package/src/action.ts +16 -123
- package/src/ai/captain/web-mode.ts +0 -7
- package/src/ai/captain.ts +5 -17
- package/src/ai/conversation.ts +9 -32
- package/src/ai/driller.ts +3 -16
- package/src/ai/experience-compactor.ts +16 -35
- package/src/ai/fisherman-tools.ts +1 -1
- package/src/ai/fisherman.ts +0 -4
- package/src/ai/historian/codeceptjs.ts +4 -2
- package/src/ai/historian/playwright.ts +4 -2
- package/src/ai/historian/utils.ts +0 -1
- package/src/ai/historian.ts +4 -7
- package/src/ai/navigator.ts +13 -49
- package/src/ai/pilot.ts +6 -16
- package/src/ai/planner.ts +56 -44
- package/src/ai/provider.ts +86 -139
- package/src/ai/quartermaster.ts +34 -41
- package/src/ai/rerunner.ts +17 -21
- package/src/ai/researcher/cache.ts +10 -16
- package/src/ai/researcher/deep-analysis.ts +3 -6
- package/src/ai/researcher/parser.ts +1 -1
- package/src/ai/researcher/research-result.ts +0 -18
- package/src/ai/researcher/sections.ts +5 -1
- package/src/ai/researcher.ts +11 -59
- package/src/ai/rules.ts +24 -13
- package/src/ai/session-analyst.ts +8 -5
- package/src/ai/task-agent.ts +3 -30
- package/src/ai/tester.ts +12 -73
- package/src/ai/tools.ts +119 -106
- package/src/commands/compact-command.ts +7 -8
- package/src/commands/context-command.ts +1 -1
- package/src/commands/context-knowledge-command.ts +1 -1
- package/src/commands/experience-command.ts +1 -1
- package/src/commands/knows-command.ts +1 -1
- package/src/commands/learn-command.ts +3 -1
- package/src/components/AddKnowledge.tsx +5 -7
- package/src/components/App.tsx +2 -2
- package/src/config.ts +12 -0
- package/src/experience-tracker.ts +90 -152
- package/src/explorbot.ts +17 -51
- package/src/explorer.ts +34 -81
- package/src/index.ts +9 -0
- package/src/knowledge-tracker.ts +49 -50
- package/src/observability.ts +2 -1
- package/src/state-manager.ts +15 -164
- package/src/utils/aria.ts +11 -2
- package/src/utils/cache.ts +40 -0
- package/src/utils/context-formatter.ts +12 -15
- package/src/utils/html.ts +79 -0
- package/src/utils/markdown-files.ts +30 -0
- package/src/utils/markdown-query.ts +15 -1
- package/src/utils/page-readiness.ts +1 -1
- package/src/utils/secrets.ts +28 -0
- package/src/utils/strings.ts +12 -0
- package/src/utils/web-element.ts +4 -0
- package/src/utils/web-sandbox.ts +43 -0
- package/src/index.tsx +0 -62
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
-
import { join } from 'node:path';
|
|
3
2
|
import { ConfigParser, outputPath } from "./config.js";
|
|
4
|
-
import { compactAriaSnapshot, diffAriaSnapshots } from "./utils/aria.js";
|
|
3
|
+
import { LARGE_ARIA_CHANGE_THRESHOLD, compactAriaSnapshot, diffAriaSnapshots } from "./utils/aria.js";
|
|
4
|
+
import { TTLCache } from "./utils/cache.js";
|
|
5
5
|
import { htmlDiff } from "./utils/html-diff.js";
|
|
6
6
|
import { extractHeadings, extractLinks, extractTargetedHtml, htmlCombinedSnapshot, htmlMinimalUISnapshot, htmlTextSnapshot, minifyHtml } from "./utils/html.js";
|
|
7
7
|
import { createDebug } from "./utils/logger.js";
|
|
8
|
+
import { slugify } from "./utils/strings.js";
|
|
8
9
|
import { extractStatePath, matchesUrl } from "./utils/url-matcher.js";
|
|
9
10
|
const debugLog = createDebug('explorbot:state');
|
|
10
11
|
export class ActionResult {
|
|
@@ -26,12 +27,12 @@ export class ActionResult {
|
|
|
26
27
|
_screenshot = undefined;
|
|
27
28
|
htmlFile = undefined;
|
|
28
29
|
_html = undefined;
|
|
30
|
+
snapshotCache = new TTLCache();
|
|
29
31
|
logFile = undefined;
|
|
30
|
-
_browserLogs = undefined;
|
|
31
32
|
ariaSnapshotFile = undefined;
|
|
32
33
|
_ariaSnapshot = undefined;
|
|
33
34
|
_lastExtractedHtml = undefined;
|
|
34
|
-
notes;
|
|
35
|
+
notes = [];
|
|
35
36
|
links = [];
|
|
36
37
|
verifications;
|
|
37
38
|
constructor(data) {
|
|
@@ -60,20 +61,17 @@ export class ActionResult {
|
|
|
60
61
|
if (data.ariaSnapshotFile !== undefined) {
|
|
61
62
|
this.ariaSnapshotFile = data.ariaSnapshotFile;
|
|
62
63
|
}
|
|
63
|
-
// Store HTML
|
|
64
|
+
// Store HTML in a private property if provided
|
|
64
65
|
if (data.html !== undefined) {
|
|
65
66
|
this._html = data.html;
|
|
66
67
|
}
|
|
67
|
-
if (data.browserLogs !== undefined) {
|
|
68
|
-
this._browserLogs = data.browserLogs;
|
|
69
|
-
}
|
|
70
68
|
if (data.screenshot !== undefined) {
|
|
71
69
|
this._screenshot = data.screenshot;
|
|
72
70
|
}
|
|
73
71
|
if (data.ariaSnapshot !== undefined) {
|
|
74
72
|
this._ariaSnapshot = data.ariaSnapshot;
|
|
75
73
|
}
|
|
76
|
-
if (!this.fullUrl && this.url
|
|
74
|
+
if (!this.fullUrl && this.url) {
|
|
77
75
|
this.fullUrl = this.url;
|
|
78
76
|
}
|
|
79
77
|
this.extractHeadings(this.html);
|
|
@@ -83,7 +81,7 @@ export class ActionResult {
|
|
|
83
81
|
else if (this._html) {
|
|
84
82
|
this.links = extractLinks(this._html);
|
|
85
83
|
}
|
|
86
|
-
if (this.url
|
|
84
|
+
if (this.url) {
|
|
87
85
|
this.url = extractStatePath(this.url);
|
|
88
86
|
}
|
|
89
87
|
}
|
|
@@ -100,6 +98,7 @@ export class ActionResult {
|
|
|
100
98
|
}
|
|
101
99
|
set html(value) {
|
|
102
100
|
this._html = value;
|
|
101
|
+
this.snapshotCache.clear();
|
|
103
102
|
}
|
|
104
103
|
get screenshot() {
|
|
105
104
|
if (this._screenshot) {
|
|
@@ -110,15 +109,6 @@ export class ActionResult {
|
|
|
110
109
|
}
|
|
111
110
|
return undefined;
|
|
112
111
|
}
|
|
113
|
-
get browserLogsContent() {
|
|
114
|
-
if (this._browserLogs !== undefined) {
|
|
115
|
-
return this._browserLogs;
|
|
116
|
-
}
|
|
117
|
-
if (this.logFile) {
|
|
118
|
-
return ActionResult.loadBrowserLogsFromFile(this.logFile);
|
|
119
|
-
}
|
|
120
|
-
return [];
|
|
121
|
-
}
|
|
122
112
|
get ariaSnapshot() {
|
|
123
113
|
if (this._ariaSnapshot !== undefined) {
|
|
124
114
|
return this._ariaSnapshot;
|
|
@@ -166,13 +156,13 @@ export class ActionResult {
|
|
|
166
156
|
return null;
|
|
167
157
|
}
|
|
168
158
|
isSameUrl(state) {
|
|
169
|
-
if (!this.url
|
|
159
|
+
if (!this.url) {
|
|
170
160
|
return false;
|
|
171
161
|
}
|
|
172
162
|
return extractStatePath(state.url) === extractStatePath(this.url);
|
|
173
163
|
}
|
|
174
164
|
isMatchedBy(state) {
|
|
175
|
-
if (!this.url
|
|
165
|
+
if (!this.url) {
|
|
176
166
|
return false;
|
|
177
167
|
}
|
|
178
168
|
const isRelevant = matchesUrl(extractStatePath(state.url), extractStatePath(this.url));
|
|
@@ -206,19 +196,24 @@ export class ActionResult {
|
|
|
206
196
|
}
|
|
207
197
|
async simplifiedHtml(htmlConfig) {
|
|
208
198
|
const normalizedConfig = this.normalizeHtmlConfig(htmlConfig);
|
|
209
|
-
|
|
199
|
+
const cacheKey = `simplified:${JSON.stringify(normalizedConfig?.minimal ?? null)}`;
|
|
200
|
+
return this.snapshotCache.fetch(cacheKey, () => minifyHtml(htmlMinimalUISnapshot(this.html ?? '', normalizedConfig?.minimal)));
|
|
210
201
|
}
|
|
211
202
|
async combinedHtml(htmlConfig) {
|
|
212
203
|
const normalizedConfig = this.normalizeHtmlConfig(htmlConfig);
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
204
|
+
const cacheKey = `combined:${!!htmlConfig?.keepPositions}:${JSON.stringify(normalizedConfig?.combined ?? null)}`;
|
|
205
|
+
return this.snapshotCache.fetch(cacheKey, async () => {
|
|
206
|
+
const combinedHtml = await minifyHtml(htmlCombinedSnapshot(this.html ?? '', normalizedConfig?.combined, { keepPositions: htmlConfig?.keepPositions }));
|
|
207
|
+
debugLog(`----${this.url}----`);
|
|
208
|
+
debugLog(`Combined HTML: \n${combinedHtml}`);
|
|
209
|
+
debugLog('----');
|
|
210
|
+
return combinedHtml;
|
|
211
|
+
});
|
|
218
212
|
}
|
|
219
213
|
async textHtml(htmlConfig) {
|
|
220
214
|
const normalizedConfig = this.normalizeHtmlConfig(htmlConfig);
|
|
221
|
-
|
|
215
|
+
const cacheKey = `text:${JSON.stringify(normalizedConfig?.text ?? null)}`;
|
|
216
|
+
return this.snapshotCache.fetch(cacheKey, () => minifyHtml(htmlTextSnapshot(this.html ?? '', normalizedConfig?.text)));
|
|
222
217
|
}
|
|
223
218
|
getInteractiveARIA() {
|
|
224
219
|
return compactAriaSnapshot(this.ariaSnapshot, false);
|
|
@@ -270,26 +265,27 @@ export class ActionResult {
|
|
|
270
265
|
}
|
|
271
266
|
return new ActionResult(actionResultData);
|
|
272
267
|
}
|
|
273
|
-
static
|
|
268
|
+
static loadStateFile(file) {
|
|
274
269
|
try {
|
|
275
|
-
const filePath = outputPath('states',
|
|
276
|
-
if (fs.existsSync(filePath))
|
|
277
|
-
return
|
|
278
|
-
|
|
279
|
-
return null;
|
|
270
|
+
const filePath = outputPath('states', file);
|
|
271
|
+
if (!fs.existsSync(filePath))
|
|
272
|
+
return null;
|
|
273
|
+
return fs.readFileSync(filePath, 'utf8');
|
|
280
274
|
}
|
|
281
275
|
catch (error) {
|
|
282
|
-
console.error('Failed to load
|
|
276
|
+
console.error('Failed to load state file:', error);
|
|
283
277
|
return null;
|
|
284
278
|
}
|
|
285
279
|
}
|
|
280
|
+
static loadHtmlFromFile(htmlFile) {
|
|
281
|
+
return ActionResult.loadStateFile(htmlFile);
|
|
282
|
+
}
|
|
286
283
|
static loadScreenshotFromFile(screenshotFile) {
|
|
287
284
|
try {
|
|
288
285
|
const filePath = outputPath('states', screenshotFile);
|
|
289
|
-
if (fs.existsSync(filePath))
|
|
290
|
-
return
|
|
291
|
-
|
|
292
|
-
return undefined;
|
|
286
|
+
if (!fs.existsSync(filePath))
|
|
287
|
+
return undefined;
|
|
288
|
+
return fs.readFileSync(filePath);
|
|
293
289
|
}
|
|
294
290
|
catch (error) {
|
|
295
291
|
console.error('Failed to load screenshot from file:', error);
|
|
@@ -297,55 +293,38 @@ export class ActionResult {
|
|
|
297
293
|
}
|
|
298
294
|
}
|
|
299
295
|
static loadBrowserLogsFromFile(logFile) {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
if (fs.existsSync(filePath)) {
|
|
303
|
-
const logContent = fs.readFileSync(filePath, 'utf8');
|
|
304
|
-
return logContent
|
|
305
|
-
.split('\n')
|
|
306
|
-
.filter((line) => line.trim())
|
|
307
|
-
.map((line) => {
|
|
308
|
-
const match = line.match(/\[([^\]]+)\] (\w+): (.+)/);
|
|
309
|
-
if (match) {
|
|
310
|
-
return {
|
|
311
|
-
timestamp: match[1],
|
|
312
|
-
type: match[2].toLowerCase(),
|
|
313
|
-
text: match[3],
|
|
314
|
-
level: match[2].toLowerCase(),
|
|
315
|
-
message: match[3],
|
|
316
|
-
};
|
|
317
|
-
}
|
|
318
|
-
return { text: line, type: 'log', level: 'log', message: line };
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
|
-
return [];
|
|
322
|
-
}
|
|
323
|
-
catch (error) {
|
|
324
|
-
console.error('Failed to load browser logs from file:', error);
|
|
296
|
+
const logContent = ActionResult.loadStateFile(logFile);
|
|
297
|
+
if (!logContent)
|
|
325
298
|
return [];
|
|
326
|
-
|
|
299
|
+
return logContent
|
|
300
|
+
.split('\n')
|
|
301
|
+
.filter((line) => line.trim())
|
|
302
|
+
.map((line) => {
|
|
303
|
+
const match = line.match(/\[([^\]]+)\] (\w+): (.+)/);
|
|
304
|
+
if (match) {
|
|
305
|
+
return {
|
|
306
|
+
timestamp: match[1],
|
|
307
|
+
type: match[2].toLowerCase(),
|
|
308
|
+
text: match[3],
|
|
309
|
+
level: match[2].toLowerCase(),
|
|
310
|
+
message: match[3],
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
return { text: line, type: 'log', level: 'log', message: line };
|
|
314
|
+
});
|
|
327
315
|
}
|
|
328
316
|
static loadAriaSnapshotFromFile(ariaSnapshotFile) {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
if (!fs.existsSync(filePath)) {
|
|
332
|
-
return null;
|
|
333
|
-
}
|
|
334
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
335
|
-
const trimmed = content.trim();
|
|
336
|
-
if (!trimmed) {
|
|
337
|
-
return null;
|
|
338
|
-
}
|
|
339
|
-
return trimmed.endsWith('\n') ? trimmed : `${trimmed}\n`;
|
|
340
|
-
}
|
|
341
|
-
catch (error) {
|
|
342
|
-
console.error('Failed to load aria snapshot from file:', error);
|
|
317
|
+
const content = ActionResult.loadStateFile(ariaSnapshotFile);
|
|
318
|
+
if (!content)
|
|
343
319
|
return null;
|
|
344
|
-
|
|
320
|
+
const trimmed = content.trim();
|
|
321
|
+
if (!trimmed)
|
|
322
|
+
return null;
|
|
323
|
+
return trimmed.endsWith('\n') ? trimmed : `${trimmed}\n`;
|
|
345
324
|
}
|
|
346
325
|
toAiContext() {
|
|
347
326
|
const parts = [];
|
|
348
|
-
if (this.url
|
|
327
|
+
if (this.url) {
|
|
349
328
|
parts.push(`<url>${this.url}</url>`);
|
|
350
329
|
}
|
|
351
330
|
if (this.title) {
|
|
@@ -380,7 +359,7 @@ export class ActionResult {
|
|
|
380
359
|
return parts.join('\n');
|
|
381
360
|
}
|
|
382
361
|
get relativeUrl() {
|
|
383
|
-
if (!this.url
|
|
362
|
+
if (!this.url)
|
|
384
363
|
return null;
|
|
385
364
|
try {
|
|
386
365
|
const urlObj = new URL(this.url);
|
|
@@ -401,20 +380,11 @@ export class ActionResult {
|
|
|
401
380
|
const parts = [];
|
|
402
381
|
parts.push(this.relativeUrl || this.url || '/');
|
|
403
382
|
this.extractHeadings(this.html);
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
let stateString = parts
|
|
412
|
-
.map((part) => part.substring(0, 100))
|
|
413
|
-
.join('_')
|
|
414
|
-
.replace(/[^a-zA-Z0-9_]/g, '_')
|
|
415
|
-
.replace(/_+/g, '_')
|
|
416
|
-
.replace(/^_|_$/g, '')
|
|
417
|
-
.toLowerCase();
|
|
383
|
+
if (this.h1)
|
|
384
|
+
parts.push(`h1_${this.h1}`);
|
|
385
|
+
if (this.h2)
|
|
386
|
+
parts.push(`h2_${this.h2}`);
|
|
387
|
+
let stateString = slugify(parts.map((part) => part.substring(0, 100)).join('_'));
|
|
418
388
|
if (stateString.length > 200) {
|
|
419
389
|
stateString = stateString.substring(0, 200);
|
|
420
390
|
if (stateString.endsWith('_')) {
|
|
@@ -423,55 +393,8 @@ export class ActionResult {
|
|
|
423
393
|
}
|
|
424
394
|
return stateString;
|
|
425
395
|
}
|
|
426
|
-
saveBrowserLogs() {
|
|
427
|
-
const logs = this.browserLogsContent;
|
|
428
|
-
if (!logs || logs.length === 0)
|
|
429
|
-
return;
|
|
430
|
-
try {
|
|
431
|
-
const outputDir = 'output';
|
|
432
|
-
const stateHash = this.getStateHash();
|
|
433
|
-
const filename = `${stateHash}.log`;
|
|
434
|
-
const filePath = join(outputDir, filename);
|
|
435
|
-
// Ensure output directory exists
|
|
436
|
-
if (!fs.existsSync(outputDir)) {
|
|
437
|
-
fs.mkdirSync(outputDir, { recursive: true });
|
|
438
|
-
}
|
|
439
|
-
// Format logs for saving
|
|
440
|
-
const formattedLogs = logs.map((log) => {
|
|
441
|
-
const timestamp = new Date().toISOString();
|
|
442
|
-
const level = (log.type || log.level || 'LOG').toUpperCase();
|
|
443
|
-
const message = log.text || log.message || String(log);
|
|
444
|
-
return `[${timestamp}] ${level}: ${message}`;
|
|
445
|
-
});
|
|
446
|
-
// Save log content to file
|
|
447
|
-
const logContent = `${formattedLogs.join('\n')}\n`;
|
|
448
|
-
fs.writeFileSync(filePath, logContent, 'utf8');
|
|
449
|
-
}
|
|
450
|
-
catch (error) {
|
|
451
|
-
// Silently fail to avoid breaking the main flow
|
|
452
|
-
console.error('Failed to save browser logs:', error);
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
saveHtmlOutput() {
|
|
456
|
-
try {
|
|
457
|
-
const outputDir = 'output';
|
|
458
|
-
const stateHash = this.getStateHash();
|
|
459
|
-
const filename = `${stateHash}.html`;
|
|
460
|
-
const filePath = join(outputDir, filename);
|
|
461
|
-
// Ensure output directory exists
|
|
462
|
-
if (!fs.existsSync(outputDir)) {
|
|
463
|
-
fs.mkdirSync(outputDir, { recursive: true });
|
|
464
|
-
}
|
|
465
|
-
// Save HTML content to file
|
|
466
|
-
fs.writeFileSync(filePath, this.html, 'utf8');
|
|
467
|
-
}
|
|
468
|
-
catch (error) {
|
|
469
|
-
// Silently fail to avoid breaking the main flow
|
|
470
|
-
console.error('Failed to save HTML output:', error);
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
396
|
async diff(previousState) {
|
|
474
|
-
return
|
|
397
|
+
return Diff.create(this, previousState);
|
|
475
398
|
}
|
|
476
399
|
async toToolResult(previousState, locator) {
|
|
477
400
|
const result = {
|
|
@@ -497,7 +420,6 @@ export class ActionResult {
|
|
|
497
420
|
return result;
|
|
498
421
|
}
|
|
499
422
|
const diff = await this.diff(previousState);
|
|
500
|
-
await diff.calculate();
|
|
501
423
|
const pageDiff = {
|
|
502
424
|
urlChanged,
|
|
503
425
|
previousUrl: previousState.url,
|
|
@@ -505,6 +427,7 @@ export class ActionResult {
|
|
|
505
427
|
};
|
|
506
428
|
if (diff.ariaChanged) {
|
|
507
429
|
pageDiff.ariaChanges = diff.ariaChanged;
|
|
430
|
+
pageDiff.ariaChangeCount = diff.ariaChangeCount;
|
|
508
431
|
}
|
|
509
432
|
if (diff.htmlParts.length > 0) {
|
|
510
433
|
const htmlConfig = this.normalizeHtmlConfig();
|
|
@@ -521,10 +444,7 @@ export class ActionResult {
|
|
|
521
444
|
}
|
|
522
445
|
}
|
|
523
446
|
if (pageDiff.ariaChanges && this.iframeSnapshots.length > 0) {
|
|
524
|
-
|
|
525
|
-
const removedMatch = pageDiff.ariaChanges.match(/removed: (\d+) interactive/);
|
|
526
|
-
const removedCount = removedMatch ? Number.parseInt(removedMatch[1]) : 0;
|
|
527
|
-
if (addedCount + removedCount >= 50) {
|
|
447
|
+
if (diff.ariaChangeCount >= LARGE_ARIA_CHANGE_THRESHOLD) {
|
|
528
448
|
pageDiff.iframes = this.iframeSnapshots.map((snap) => `iframe src="${snap.src}":\n${snap.html}`).join('\n\n');
|
|
529
449
|
}
|
|
530
450
|
}
|
|
@@ -559,18 +479,22 @@ export class Diff {
|
|
|
559
479
|
previous;
|
|
560
480
|
_htmlDiffResult = null;
|
|
561
481
|
_ariaDiffResult = null;
|
|
482
|
+
_ariaChangeCount = 0;
|
|
562
483
|
_isSameUrl;
|
|
563
|
-
_urlChanged;
|
|
564
484
|
constructor(current, previous) {
|
|
565
485
|
this.current = current;
|
|
566
486
|
this.previous = previous;
|
|
567
487
|
this._isSameUrl = previous ? current.isSameUrl({ url: previous.url }) : false;
|
|
568
|
-
|
|
488
|
+
}
|
|
489
|
+
static async create(current, previous) {
|
|
490
|
+
const diff = new Diff(current, previous);
|
|
491
|
+
await diff.calculate();
|
|
492
|
+
return diff;
|
|
569
493
|
}
|
|
570
494
|
hasChanges() {
|
|
571
495
|
if (!this.previous)
|
|
572
496
|
return false;
|
|
573
|
-
if (this.
|
|
497
|
+
if (!this._isSameUrl)
|
|
574
498
|
return true;
|
|
575
499
|
const hasHtmlChanges = this._htmlDiffResult && (this._htmlDiffResult.parts.length > 0 || this._htmlDiffResult.added.length > 0 || this._htmlDiffResult.removed.length > 0);
|
|
576
500
|
const hasAriaChanges = this._ariaDiffResult !== null;
|
|
@@ -580,7 +504,7 @@ export class Diff {
|
|
|
580
504
|
return this._isSameUrl;
|
|
581
505
|
}
|
|
582
506
|
urlHasChanged() {
|
|
583
|
-
return this.
|
|
507
|
+
return !this._isSameUrl;
|
|
584
508
|
}
|
|
585
509
|
get htmlParts() {
|
|
586
510
|
if (!this._htmlDiffResult)
|
|
@@ -590,21 +514,20 @@ export class Diff {
|
|
|
590
514
|
get ariaChanged() {
|
|
591
515
|
return this._ariaDiffResult;
|
|
592
516
|
}
|
|
593
|
-
get
|
|
594
|
-
return this.
|
|
517
|
+
get ariaChangeCount() {
|
|
518
|
+
return this._ariaChangeCount;
|
|
595
519
|
}
|
|
596
520
|
get htmlDiff() {
|
|
597
521
|
return this._htmlDiffResult;
|
|
598
522
|
}
|
|
599
|
-
get ariaDiff() {
|
|
600
|
-
return this._ariaDiffResult;
|
|
601
|
-
}
|
|
602
523
|
async calculate() {
|
|
603
524
|
if (!this.previous)
|
|
604
525
|
return;
|
|
605
526
|
if (this._isSameUrl) {
|
|
606
527
|
this._htmlDiffResult = await htmlDiff(this.previous.html, this.current.html, ConfigParser.getInstance().getConfig().html);
|
|
607
528
|
}
|
|
608
|
-
|
|
529
|
+
const ariaDiff = diffAriaSnapshots(this.previous.ariaSnapshot, this.current.ariaSnapshot);
|
|
530
|
+
this._ariaDiffResult = ariaDiff.text;
|
|
531
|
+
this._ariaChangeCount = ariaDiff.count;
|
|
609
532
|
}
|
|
610
533
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ActionResult } from './action-result.js';
|
|
2
|
+
import type { ExplorbotConfig } from './config.js';
|
|
3
|
+
import type { PlaywrightRecorder } from './playwright-recorder.js';
|
|
4
|
+
import type { StateManager } from './state-manager.js';
|
|
5
|
+
declare class Action {
|
|
6
|
+
actor: CodeceptJS.I;
|
|
7
|
+
stateManager: StateManager;
|
|
8
|
+
actionResult: ActionResult | null;
|
|
9
|
+
config: ExplorbotConfig;
|
|
10
|
+
action: string | null;
|
|
11
|
+
lastError: Error | null;
|
|
12
|
+
playwrightHelper: any;
|
|
13
|
+
playwrightGroupId: string | null;
|
|
14
|
+
assertionSteps: Array<{
|
|
15
|
+
name: string;
|
|
16
|
+
args: any[];
|
|
17
|
+
}>;
|
|
18
|
+
recorder?: PlaywrightRecorder;
|
|
19
|
+
mainDocumentStatus: number | undefined;
|
|
20
|
+
constructor(actor: CodeceptJS.I, stateManager: StateManager, recorder?: PlaywrightRecorder);
|
|
21
|
+
saveScreenshot(): Promise<string | undefined>;
|
|
22
|
+
capturePageState({ includeScreenshot, codeBlock }?: {
|
|
23
|
+
includeScreenshot?: boolean;
|
|
24
|
+
codeBlock?: string;
|
|
25
|
+
}): Promise<ActionResult>;
|
|
26
|
+
captureMainDocumentStatus(): Promise<number | undefined>;
|
|
27
|
+
captureMainDocumentResponse(): () => void;
|
|
28
|
+
/**
|
|
29
|
+
* Capture HTML snapshots of all iframes on the page
|
|
30
|
+
*/
|
|
31
|
+
captureIframeSnapshots(mainHtml: string): Promise<Array<{
|
|
32
|
+
src: string;
|
|
33
|
+
html: string;
|
|
34
|
+
id?: string;
|
|
35
|
+
}>>;
|
|
36
|
+
captureBrowserLogs(): Promise<any[]>;
|
|
37
|
+
execute(code: string): Promise<Action>;
|
|
38
|
+
attempt(codeBlock: string, originalMessage?: string): Promise<boolean>;
|
|
39
|
+
getActor(): CodeceptJS.I;
|
|
40
|
+
getActionResult(): ActionResult | null;
|
|
41
|
+
waitForPageReadiness(page: any): Promise<void>;
|
|
42
|
+
}
|
|
43
|
+
export default Action;
|