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
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { normalizeUrl } from "../../../src/state-manager.js";
|
|
3
|
+
import { normalizeInlineText } from "../../../src/utils/strings.js";
|
|
4
|
+
function buildStateGraph(outputDir, pages) {
|
|
5
|
+
const pageIds = new Map();
|
|
6
|
+
const pageNodes = [];
|
|
7
|
+
const adjacency = new Map();
|
|
8
|
+
const classAssignment = new Map([
|
|
9
|
+
['page', []],
|
|
10
|
+
['dialog', []],
|
|
11
|
+
['section', []],
|
|
12
|
+
]);
|
|
13
|
+
for (const [index, page] of pages.entries()) {
|
|
14
|
+
const id = `page${index}`;
|
|
15
|
+
pageIds.set(normalizeUrl(page.url), id);
|
|
16
|
+
adjacency.set(id, new Set());
|
|
17
|
+
classAssignment.get('page')?.push(id);
|
|
18
|
+
pageNodes.push({ id, kind: 'page', label: page.title || page.url, subLabel: page.url, filePath: page.filePath });
|
|
19
|
+
}
|
|
20
|
+
const stateKeys = new Map();
|
|
21
|
+
const transientByPage = new Map();
|
|
22
|
+
const clicks = [];
|
|
23
|
+
const edges = [];
|
|
24
|
+
const drawnBack = new Set();
|
|
25
|
+
let stateIndex = 0;
|
|
26
|
+
for (const [pageIndex, page] of pages.entries()) {
|
|
27
|
+
const sourceId = `page${pageIndex}`;
|
|
28
|
+
for (const transition of page.interactions || []) {
|
|
29
|
+
const targetState = transition.targetState;
|
|
30
|
+
if (!targetState) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
const normalizedTarget = normalizeUrl(targetState.url);
|
|
34
|
+
const isPageTarget = targetState.kind === 'page';
|
|
35
|
+
let pageTargetId;
|
|
36
|
+
if (isPageTarget) {
|
|
37
|
+
pageTargetId = pageIds.get(normalizedTarget);
|
|
38
|
+
}
|
|
39
|
+
let targetId;
|
|
40
|
+
if (pageTargetId && pageTargetId !== sourceId) {
|
|
41
|
+
targetId = pageTargetId;
|
|
42
|
+
}
|
|
43
|
+
if (!targetId) {
|
|
44
|
+
const stateKey = `${sourceId}:${targetState.kind}:${normalizeInlineText(targetState.label)}:${normalizedTarget}`;
|
|
45
|
+
targetId = stateKeys.get(stateKey);
|
|
46
|
+
if (!targetId) {
|
|
47
|
+
targetId = `state${stateIndex++}`;
|
|
48
|
+
stateKeys.set(stateKey, targetId);
|
|
49
|
+
adjacency.set(targetId, new Set());
|
|
50
|
+
classAssignment.get(classForKind(targetState.kind))?.push(targetId);
|
|
51
|
+
const list = transientByPage.get(sourceId) ?? [];
|
|
52
|
+
list.push({ id: targetId, kind: targetState.kind, label: targetState.label, subLabel: targetState.kind, parentPageId: sourceId });
|
|
53
|
+
transientByPage.set(sourceId, list);
|
|
54
|
+
if (transition.screenshot) {
|
|
55
|
+
const screenshotPath = path.resolve(path.dirname(page.filePath), transition.screenshot.relativePath);
|
|
56
|
+
clicks.push({ node: targetId, target: path.relative(outputDir, screenshotPath).replaceAll('\\', '/'), tooltip: 'Open state screenshot' });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (!targetId) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const pairKey = `${sourceId}>${targetId}`;
|
|
64
|
+
if (adjacency.get(targetId)?.has(sourceId)) {
|
|
65
|
+
if (drawnBack.has(pairKey)) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
drawnBack.add(pairKey);
|
|
69
|
+
edges.push({ source: sourceId, target: targetId, action: transition.action, isBack: true });
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (adjacency.get(sourceId)?.has(targetId) || createsCycle(sourceId, targetId, adjacency)) {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
adjacency.get(sourceId)?.add(targetId);
|
|
76
|
+
edges.push({ source: sourceId, target: targetId, action: transition.action, isBack: false });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const pageClicks = [];
|
|
80
|
+
for (const pageNode of pageNodes) {
|
|
81
|
+
const filePath = pageNode.filePath;
|
|
82
|
+
if (!filePath) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const relativeFile = path.relative(outputDir, filePath).replaceAll('\\', '/');
|
|
86
|
+
pageClicks.push({ node: pageNode.id, target: relativeFile, tooltip: `Open ${pageNode.label}` });
|
|
87
|
+
}
|
|
88
|
+
return { pages: pageNodes, transientByPage, edges, clicks: [...pageClicks, ...clicks], classAssignment };
|
|
89
|
+
}
|
|
90
|
+
function renderMermaidBody(outputDir, pages) {
|
|
91
|
+
return renderMermaidFromGraph(buildStateGraph(outputDir, pages));
|
|
92
|
+
}
|
|
93
|
+
function renderMermaidFromGraph(graph) {
|
|
94
|
+
const lines = ['flowchart TD'];
|
|
95
|
+
if (graph.pages.length === 0) {
|
|
96
|
+
lines.push(' empty["No documented states"]');
|
|
97
|
+
return lines.join('\n');
|
|
98
|
+
}
|
|
99
|
+
for (const page of graph.pages) {
|
|
100
|
+
lines.push(` ${renderNodeLine(page)}`);
|
|
101
|
+
const children = graph.transientByPage.get(page.id);
|
|
102
|
+
if (!children || children.length === 0) {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
lines.push(` subgraph sg_${page.id} ["${escapeMermaidLabel(page.label)} — transient states"]`);
|
|
106
|
+
for (const child of children) {
|
|
107
|
+
lines.push(` ${renderNodeLine(child)}`);
|
|
108
|
+
}
|
|
109
|
+
lines.push(' end');
|
|
110
|
+
}
|
|
111
|
+
for (const edge of graph.edges) {
|
|
112
|
+
let arrow = '-->';
|
|
113
|
+
if (edge.isBack) {
|
|
114
|
+
arrow = '-.->';
|
|
115
|
+
}
|
|
116
|
+
lines.push(` ${edge.source} ${arrow}|"${escapeMermaidLabel(edge.action)}"| ${edge.target}`);
|
|
117
|
+
}
|
|
118
|
+
lines.push(' classDef page fill:#dbeafe,stroke:#2563eb,color:#0f172a;');
|
|
119
|
+
lines.push(' classDef dialog fill:#ffedd5,stroke:#ea580c,color:#0f172a;');
|
|
120
|
+
lines.push(' classDef section fill:#f3e8ff,stroke:#9333ea,color:#0f172a;');
|
|
121
|
+
for (const [className, ids] of graph.classAssignment) {
|
|
122
|
+
if (ids.length === 0) {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
lines.push(` class ${ids.join(',')} ${className};`);
|
|
126
|
+
}
|
|
127
|
+
for (const click of graph.clicks) {
|
|
128
|
+
lines.push(` click ${click.node} "${click.target}" "${escapeMermaidLabel(click.tooltip)}"`);
|
|
129
|
+
}
|
|
130
|
+
return lines.join('\n');
|
|
131
|
+
}
|
|
132
|
+
function renderStateMapFromGraph(graph) {
|
|
133
|
+
if (graph.pages.length === 0) {
|
|
134
|
+
return '';
|
|
135
|
+
}
|
|
136
|
+
const clickByNode = new Map(graph.clicks.map((click) => [click.node, click]));
|
|
137
|
+
const rows = ['| State | Type | Open |', '| --- | --- | --- |'];
|
|
138
|
+
for (const pageNode of graph.pages) {
|
|
139
|
+
const pageClick = clickByNode.get(pageNode.id);
|
|
140
|
+
let openCell = '—';
|
|
141
|
+
if (pageClick) {
|
|
142
|
+
openCell = `[open page](${pageClick.target})`;
|
|
143
|
+
}
|
|
144
|
+
rows.push(`| ${escapeTable(pageNode.label)} | page | ${openCell} |`);
|
|
145
|
+
for (const child of graph.transientByPage.get(pageNode.id) ?? []) {
|
|
146
|
+
const childClick = clickByNode.get(child.id);
|
|
147
|
+
let childCell = '—';
|
|
148
|
+
if (childClick) {
|
|
149
|
+
childCell = `[view screenshot](${childClick.target})`;
|
|
150
|
+
}
|
|
151
|
+
rows.push(`| ${escapeTable(child.label)} | ${child.kind} | ${childCell} |`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return rows.join('\n');
|
|
155
|
+
}
|
|
156
|
+
function renderNodeLine(node) {
|
|
157
|
+
const label = `${escapeMermaidLabel(node.label)}<br/>${escapeMermaidLabel(node.subLabel)}`;
|
|
158
|
+
if (node.kind === 'dialog' || node.kind === 'modal') {
|
|
159
|
+
return `${node.id}{{"${label}"}}`;
|
|
160
|
+
}
|
|
161
|
+
if (node.kind === 'section') {
|
|
162
|
+
return `${node.id}("${label}")`;
|
|
163
|
+
}
|
|
164
|
+
return `${node.id}["${label}"]`;
|
|
165
|
+
}
|
|
166
|
+
function createsCycle(sourceId, targetId, adjacency) {
|
|
167
|
+
if (sourceId === targetId) {
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
const pending = [targetId];
|
|
171
|
+
const visited = new Set();
|
|
172
|
+
while (pending.length > 0) {
|
|
173
|
+
const nodeId = pending.pop();
|
|
174
|
+
if (!nodeId || visited.has(nodeId)) {
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
if (nodeId === sourceId) {
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
visited.add(nodeId);
|
|
181
|
+
pending.push(...(adjacency.get(nodeId) || []));
|
|
182
|
+
}
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
function escapeMermaidLabel(value) {
|
|
186
|
+
return normalizeInlineText(value).replaceAll('&', '&').replaceAll('"', '"').replaceAll('|', '|');
|
|
187
|
+
}
|
|
188
|
+
function escapeTable(value) {
|
|
189
|
+
return normalizeInlineText(value).replaceAll('|', '\\|');
|
|
190
|
+
}
|
|
191
|
+
function classForKind(kind) {
|
|
192
|
+
if (kind === 'section') {
|
|
193
|
+
return 'section';
|
|
194
|
+
}
|
|
195
|
+
if (kind === 'page') {
|
|
196
|
+
return 'page';
|
|
197
|
+
}
|
|
198
|
+
return 'dialog';
|
|
199
|
+
}
|
|
200
|
+
export { buildStateGraph, renderMermaidBody, renderMermaidFromGraph, renderStateMapFromGraph };
|
package/dist/package.json
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "explorbot",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "CLI app built with React Ink, CodeceptJS, and Playwright",
|
|
5
5
|
"license": "Elastic-2.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/src/index.js",
|
|
8
|
+
"types": "dist/src/index.d.ts",
|
|
8
9
|
"exports": {
|
|
9
10
|
".": {
|
|
10
|
-
"
|
|
11
|
+
"types": "./dist/src/index.d.ts",
|
|
12
|
+
"bun": "./src/index.ts",
|
|
11
13
|
"import": "./dist/src/index.js"
|
|
12
14
|
}
|
|
13
15
|
},
|
|
@@ -27,13 +29,13 @@
|
|
|
27
29
|
"assets/sample-files/"
|
|
28
30
|
],
|
|
29
31
|
"scripts": {
|
|
30
|
-
"build": "bun run
|
|
32
|
+
"build": "bun run build:bin",
|
|
31
33
|
"build:bin": "bun build bin/explorbot-cli.ts --outdir bin --target node --external commander --format esm",
|
|
32
34
|
"build:npm": "bash scripts/build-npm.sh",
|
|
33
35
|
"prepublishOnly": "npm run build:npm",
|
|
34
|
-
"dev": "bun run
|
|
35
|
-
"start": "node dist/
|
|
36
|
-
"init": "bun run
|
|
36
|
+
"dev": "bun run bin/explorbot-cli.ts start",
|
|
37
|
+
"start": "node dist/bin/explorbot-cli.js",
|
|
38
|
+
"init": "bun run bin/explorbot-cli.ts init",
|
|
37
39
|
"test": "codeceptjs run",
|
|
38
40
|
"test:headless": "codeceptjs run --headless",
|
|
39
41
|
"test:ui": "bun test tests/ui",
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { type HtmlConfig } from './config.js';
|
|
2
|
+
import type { Link, WebPageState } from './state-manager.js';
|
|
3
|
+
import { TTLCache } from './utils/cache.js';
|
|
4
|
+
import { type HtmlDiffPart, type HtmlDiffResult } from './utils/html-diff.js';
|
|
5
|
+
interface ActionResultData extends WebPageState {
|
|
6
|
+
html?: string;
|
|
7
|
+
fullUrl?: string | undefined;
|
|
8
|
+
screenshot?: Buffer;
|
|
9
|
+
screenshotFile?: string;
|
|
10
|
+
logFile?: string;
|
|
11
|
+
htmlFile?: string;
|
|
12
|
+
title?: string;
|
|
13
|
+
timestamp?: Date;
|
|
14
|
+
error?: string | null;
|
|
15
|
+
h1?: string | undefined;
|
|
16
|
+
h2?: string | undefined;
|
|
17
|
+
h3?: string | undefined;
|
|
18
|
+
h4?: string | undefined;
|
|
19
|
+
browserLogs?: any[];
|
|
20
|
+
iframeSnapshots?: Array<{
|
|
21
|
+
src: string;
|
|
22
|
+
html: string;
|
|
23
|
+
id?: string;
|
|
24
|
+
}>;
|
|
25
|
+
ariaSnapshot?: string | null;
|
|
26
|
+
ariaSnapshotFile?: string;
|
|
27
|
+
iframeURL?: string;
|
|
28
|
+
links?: Link[];
|
|
29
|
+
}
|
|
30
|
+
export interface PageDiff {
|
|
31
|
+
urlChanged: boolean;
|
|
32
|
+
previousUrl?: string;
|
|
33
|
+
currentUrl: string;
|
|
34
|
+
ariaChanges?: string | null;
|
|
35
|
+
ariaChangeCount?: number;
|
|
36
|
+
htmlParts?: HtmlDiffPart[];
|
|
37
|
+
iframes?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface ToolResultMetadata {
|
|
40
|
+
url: string;
|
|
41
|
+
locator: string;
|
|
42
|
+
targetedHtml: string;
|
|
43
|
+
pageDiff: PageDiff | null;
|
|
44
|
+
iframeURL?: string;
|
|
45
|
+
}
|
|
46
|
+
export declare class ActionResult implements ActionResultData {
|
|
47
|
+
id?: number;
|
|
48
|
+
title: string;
|
|
49
|
+
httpStatus: number | undefined;
|
|
50
|
+
error: string | null;
|
|
51
|
+
timestamp: Date;
|
|
52
|
+
h1: string | undefined;
|
|
53
|
+
h2: string | undefined;
|
|
54
|
+
h3: string | undefined;
|
|
55
|
+
h4: string | undefined;
|
|
56
|
+
url: string;
|
|
57
|
+
fullUrl: string | undefined;
|
|
58
|
+
browserLogs: any[];
|
|
59
|
+
iframeSnapshots: Array<{
|
|
60
|
+
src: string;
|
|
61
|
+
html: string;
|
|
62
|
+
id?: string;
|
|
63
|
+
}>;
|
|
64
|
+
iframeURL: string | undefined;
|
|
65
|
+
readonly screenshotFile: string | undefined;
|
|
66
|
+
_screenshot: Buffer | undefined;
|
|
67
|
+
readonly htmlFile: string | undefined;
|
|
68
|
+
_html: string | undefined;
|
|
69
|
+
snapshotCache: TTLCache<string>;
|
|
70
|
+
readonly logFile: string | undefined;
|
|
71
|
+
readonly ariaSnapshotFile: string | undefined;
|
|
72
|
+
_ariaSnapshot: string | null | undefined;
|
|
73
|
+
_lastExtractedHtml: string | undefined;
|
|
74
|
+
notes: string[];
|
|
75
|
+
links: Link[];
|
|
76
|
+
verifications?: Record<string, boolean>;
|
|
77
|
+
constructor(data: ActionResultData);
|
|
78
|
+
get hash(): string;
|
|
79
|
+
get html(): string;
|
|
80
|
+
set html(value: string);
|
|
81
|
+
get screenshot(): Buffer | undefined;
|
|
82
|
+
get ariaSnapshot(): string | null;
|
|
83
|
+
set ariaSnapshot(value: string | null);
|
|
84
|
+
extractHeadings(html: string): void;
|
|
85
|
+
addVerification(assertion: string, passed: boolean): void;
|
|
86
|
+
getVerification(message: string | RegExp): boolean | null;
|
|
87
|
+
isSameUrl(state: WebPageState): boolean;
|
|
88
|
+
isMatchedBy(state: WebPageState): boolean;
|
|
89
|
+
isRelevantExperienceRecord(record: WebPageState, options?: {
|
|
90
|
+
includeDescendantExperience?: boolean;
|
|
91
|
+
}): boolean;
|
|
92
|
+
simplifiedHtml(htmlConfig?: HtmlConfig): Promise<string>;
|
|
93
|
+
combinedHtml(htmlConfig?: HtmlConfig & {
|
|
94
|
+
keepPositions?: boolean;
|
|
95
|
+
}): Promise<string>;
|
|
96
|
+
textHtml(htmlConfig?: HtmlConfig): Promise<string>;
|
|
97
|
+
getInteractiveARIA(): string;
|
|
98
|
+
getCompactARIA(): string;
|
|
99
|
+
normalizeHtmlConfig(htmlConfig?: HtmlConfig): HtmlConfig | undefined;
|
|
100
|
+
static fromState(state: WebPageState): ActionResult;
|
|
101
|
+
static loadStateFile(file: string): string | null;
|
|
102
|
+
static loadHtmlFromFile(htmlFile: string): string | null;
|
|
103
|
+
static loadScreenshotFromFile(screenshotFile: string): Buffer | undefined;
|
|
104
|
+
static loadBrowserLogsFromFile(logFile: string): any[];
|
|
105
|
+
static loadAriaSnapshotFromFile(ariaSnapshotFile: string): string | null;
|
|
106
|
+
toAiContext(): string;
|
|
107
|
+
get relativeUrl(): string | null;
|
|
108
|
+
get isInsideIframe(): boolean;
|
|
109
|
+
getStateHash(): string;
|
|
110
|
+
diff(previousState: ActionResult | null): Promise<Diff>;
|
|
111
|
+
toToolResult(previousState: ActionResult | null, locator: string): Promise<ToolResultMetadata>;
|
|
112
|
+
}
|
|
113
|
+
export declare class Diff {
|
|
114
|
+
current: ActionResult;
|
|
115
|
+
previous: ActionResult | null;
|
|
116
|
+
_htmlDiffResult: HtmlDiffResult | null;
|
|
117
|
+
_ariaDiffResult: string | null;
|
|
118
|
+
_ariaChangeCount: number;
|
|
119
|
+
_isSameUrl: boolean;
|
|
120
|
+
constructor(current: ActionResult, previous: ActionResult | null);
|
|
121
|
+
static create(current: ActionResult, previous: ActionResult | null): Promise<Diff>;
|
|
122
|
+
hasChanges(): boolean;
|
|
123
|
+
isSameUrl(): boolean;
|
|
124
|
+
urlHasChanged(): boolean;
|
|
125
|
+
get htmlParts(): HtmlDiffPart[];
|
|
126
|
+
get ariaChanged(): string | null;
|
|
127
|
+
get ariaChangeCount(): number;
|
|
128
|
+
get htmlDiff(): HtmlDiffResult | null;
|
|
129
|
+
calculate(): Promise<void>;
|
|
130
|
+
}
|
|
131
|
+
export {};
|