explorbot 0.1.32-beta.1 → 0.2.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.
- package/README.md +35 -19
- package/bin/explorbot-cli.ts +33 -10
- package/boat/api-tester/src/config.ts +45 -3
- package/boat/doc-collector/src/ai/documentarian.ts +26 -28
- package/boat/doc-collector/src/ai/tools.ts +74 -16
- package/boat/doc-collector/src/cli.ts +1 -6
- package/boat/doc-collector/src/docbot.ts +30 -9
- package/boat/doc-collector/src/docs-renderer.ts +19 -24
- package/boat/doc-collector/src/screenshots.ts +34 -2
- package/boat/doc-collector/src/state-diagram.ts +281 -0
- package/dist/bin/explorbot-cli.js +29 -9
- package/dist/boat/api-tester/src/config.js +43 -4
- package/dist/boat/doc-collector/src/ai/documentarian.js +19 -7
- package/dist/boat/doc-collector/src/ai/tools.js +53 -16
- package/dist/boat/doc-collector/src/cli.js +1 -5
- package/dist/boat/doc-collector/src/docbot.js +27 -8
- package/dist/boat/doc-collector/src/docs-renderer.js +18 -3
- package/dist/boat/doc-collector/src/screenshots.js +30 -1
- package/dist/boat/doc-collector/src/state-diagram.js +200 -0
- package/dist/models.json +30 -0
- package/dist/package.json +23 -3
- package/dist/src/action-result.d.ts +8 -10
- package/dist/src/action-result.js +72 -164
- package/dist/src/action.d.ts +13 -12
- package/dist/src/action.js +37 -113
- package/dist/src/ai/agent.d.ts +17 -0
- package/dist/src/ai/captain/idle-mode.js +1 -1
- package/dist/src/ai/captain/test-mode.js +1 -1
- package/dist/src/ai/captain/web-mode.js +18 -29
- package/dist/src/ai/captain.d.ts +1 -3
- package/dist/src/ai/captain.js +17 -45
- package/dist/src/ai/conversation.d.ts +2 -5
- package/dist/src/ai/conversation.js +9 -28
- package/dist/src/ai/driller.d.ts +2 -17
- package/dist/src/ai/driller.js +26 -50
- package/dist/src/ai/experience-compactor.d.ts +2 -2
- package/dist/src/ai/experience-compactor.js +16 -33
- package/dist/src/ai/fisherman-tools.js +1 -1
- package/dist/src/ai/fisherman.d.ts +0 -1
- package/dist/src/ai/fisherman.js +0 -3
- package/dist/src/ai/historian/codeceptjs.d.ts +2 -0
- package/dist/src/ai/historian/codeceptjs.js +4 -3
- package/dist/src/ai/historian/playwright.d.ts +4 -1
- package/dist/src/ai/historian/playwright.js +4 -3
- package/dist/src/ai/historian/screencast.d.ts +2 -1
- package/dist/src/ai/historian/screencast.js +2 -2
- package/dist/src/ai/historian/utils.d.ts +0 -1
- package/dist/src/ai/historian/utils.js +0 -1
- package/dist/src/ai/historian.d.ts +10 -8
- package/dist/src/ai/historian.js +1 -5
- package/dist/src/ai/navigator.d.ts +8 -6
- package/dist/src/ai/navigator.js +34 -65
- package/dist/src/ai/pilot.d.ts +13 -8
- package/dist/src/ai/pilot.js +53 -59
- package/dist/src/ai/planner.d.ts +5 -4
- package/dist/src/ai/planner.js +66 -52
- package/dist/src/ai/provider.d.ts +4 -1
- package/dist/src/ai/provider.js +77 -137
- package/dist/src/ai/quartermaster.d.ts +22 -22
- package/dist/src/ai/quartermaster.js +8 -14
- package/dist/src/ai/rerunner.d.ts +3 -13
- package/dist/src/ai/rerunner.js +23 -44
- package/dist/src/ai/researcher/cache.js +11 -18
- package/dist/src/ai/researcher/coordinates.js +4 -3
- package/dist/src/ai/researcher/deep-analysis.d.ts +2 -0
- package/dist/src/ai/researcher/deep-analysis.js +8 -11
- package/dist/src/ai/researcher/locators.d.ts +9 -2
- package/dist/src/ai/researcher/locators.js +65 -8
- package/dist/src/ai/researcher/parser.js +1 -1
- package/dist/src/ai/researcher/research-result.d.ts +0 -1
- package/dist/src/ai/researcher/research-result.js +0 -19
- package/dist/src/ai/researcher/sections.d.ts +2 -0
- package/dist/src/ai/researcher/sections.js +7 -3
- package/dist/src/ai/researcher.js +40 -106
- package/dist/src/ai/rules.d.ts +1 -0
- package/dist/src/ai/rules.js +22 -15
- package/dist/src/ai/session-analyst.js +8 -5
- package/dist/src/ai/task-agent.d.ts +19 -6
- package/dist/src/ai/task-agent.js +37 -33
- package/dist/src/ai/tester.d.ts +6 -14
- package/dist/src/ai/tester.js +46 -111
- package/dist/src/ai/tools.d.ts +26 -14
- package/dist/src/ai/tools.js +138 -132
- package/dist/src/command-handler.js +1 -1
- package/dist/src/commands/compact-command.d.ts +1 -1
- package/dist/src/commands/compact-command.js +6 -6
- package/dist/src/commands/context-aria-command.js +1 -1
- package/dist/src/commands/context-command.js +8 -6
- package/dist/src/commands/context-data-command.js +2 -2
- package/dist/src/commands/context-experience-command.js +2 -2
- package/dist/src/commands/context-html-command.js +2 -2
- package/dist/src/commands/context-knowledge-command.js +2 -2
- package/dist/src/commands/drill-command.js +1 -1
- package/dist/src/commands/experience-command.js +1 -1
- package/dist/src/commands/explore-command.js +4 -3
- package/dist/src/commands/freesail-command.js +2 -2
- package/dist/src/commands/knows-command.js +1 -1
- package/dist/src/commands/learn-command.js +5 -3
- package/dist/src/commands/path-command.js +1 -1
- package/dist/src/commands/research-command.js +1 -1
- package/dist/src/commands/test-command.js +1 -1
- package/dist/src/components/AddKnowledge.d.ts +2 -0
- package/dist/src/components/AddKnowledge.js +3 -7
- package/dist/src/components/App.js +3 -3
- package/dist/src/config.d.ts +19 -0
- package/dist/src/config.js +156 -10
- package/dist/src/experience-tracker.d.ts +11 -6
- package/dist/src/experience-tracker.js +82 -155
- package/dist/src/explorbot.d.ts +21 -13
- package/dist/src/explorbot.js +84 -80
- package/dist/src/explorer.d.ts +66 -102
- package/dist/src/explorer.js +332 -623
- package/dist/src/knowledge-tracker.d.ts +2 -2
- package/dist/src/knowledge-tracker.js +38 -45
- package/dist/src/state-manager.d.ts +10 -30
- package/dist/src/state-manager.js +11 -129
- package/dist/src/utils/aria.d.ts +6 -1
- package/dist/src/utils/aria.js +4 -1
- package/dist/src/utils/cache.d.ts +15 -0
- package/dist/src/utils/cache.js +34 -0
- package/dist/src/utils/context-formatter.d.ts +6 -0
- package/dist/src/utils/context-formatter.js +15 -27
- package/dist/src/utils/hooks-runner.js +2 -4
- package/dist/src/utils/html.d.ts +5 -0
- package/dist/src/utils/html.js +71 -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-query.d.ts +6 -0
- package/dist/src/utils/markdown-query.js +14 -1
- package/dist/src/utils/page-readiness.d.ts +1 -0
- package/dist/src/utils/page-readiness.js +1 -1
- package/dist/src/utils/secrets.js +2 -2
- package/dist/src/utils/strings.d.ts +2 -0
- package/dist/src/utils/strings.js +10 -0
- package/dist/src/utils/test-files.js +1 -1
- package/dist/src/utils/web-annotate.d.ts +5 -0
- package/dist/src/utils/web-annotate.js +58 -0
- package/dist/src/utils/web-eidx.d.ts +2 -0
- package/dist/src/utils/web-eidx.js +20 -0
- package/dist/src/utils/web-element.d.ts +3 -1
- package/dist/src/utils/web-element.js +32 -0
- package/dist/src/utils/web-sandbox.d.ts +4 -0
- package/dist/src/utils/web-sandbox.js +37 -0
- package/models.json +30 -0
- package/package.json +23 -3
- package/src/action-result.ts +70 -173
- package/src/action.ts +38 -132
- package/src/ai/agent.ts +20 -0
- package/src/ai/captain/idle-mode.ts +1 -1
- package/src/ai/captain/test-mode.ts +1 -1
- package/src/ai/captain/web-mode.ts +18 -30
- package/src/ai/captain.ts +17 -42
- package/src/ai/conversation.ts +9 -32
- package/src/ai/driller.ts +53 -83
- 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 +5 -3
- package/src/ai/historian/playwright.ts +7 -4
- package/src/ai/historian/screencast.ts +4 -3
- package/src/ai/historian/utils.ts +0 -1
- package/src/ai/historian.ts +6 -8
- package/src/ai/navigator.ts +39 -70
- package/src/ai/pilot.ts +59 -61
- package/src/ai/planner.ts +76 -62
- package/src/ai/provider.ts +85 -146
- package/src/ai/quartermaster.ts +39 -45
- package/src/ai/rerunner.ts +27 -50
- package/src/ai/researcher/cache.ts +10 -16
- package/src/ai/researcher/coordinates.ts +4 -3
- package/src/ai/researcher/deep-analysis.ts +10 -11
- package/src/ai/researcher/locators.ts +66 -9
- package/src/ai/researcher/parser.ts +1 -1
- package/src/ai/researcher/research-result.ts +0 -18
- package/src/ai/researcher/sections.ts +9 -3
- package/src/ai/researcher.ts +42 -119
- package/src/ai/rules.ts +24 -13
- package/src/ai/session-analyst.ts +8 -5
- package/src/ai/task-agent.ts +45 -38
- package/src/ai/tester.ts +51 -129
- package/src/ai/tools.ts +145 -153
- package/src/command-handler.ts +1 -1
- package/src/commands/compact-command.ts +7 -8
- package/src/commands/context-aria-command.ts +1 -1
- package/src/commands/context-command.ts +8 -6
- package/src/commands/context-data-command.ts +2 -2
- package/src/commands/context-experience-command.ts +2 -2
- package/src/commands/context-html-command.ts +2 -2
- package/src/commands/context-knowledge-command.ts +2 -2
- package/src/commands/drill-command.ts +1 -1
- package/src/commands/experience-command.ts +1 -1
- package/src/commands/explore-command.ts +4 -3
- package/src/commands/freesail-command.ts +2 -2
- package/src/commands/knows-command.ts +1 -1
- package/src/commands/learn-command.ts +5 -3
- package/src/commands/path-command.ts +1 -1
- package/src/commands/research-command.ts +1 -1
- package/src/commands/test-command.ts +1 -1
- package/src/components/AddKnowledge.tsx +5 -7
- package/src/components/App.tsx +3 -3
- package/src/config.ts +185 -11
- package/src/experience-tracker.ts +89 -152
- package/src/explorbot.ts +88 -83
- package/src/explorer.ts +402 -693
- package/src/knowledge-tracker.ts +42 -49
- package/src/state-manager.ts +20 -155
- 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/hooks-runner.ts +2 -4
- 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 +2 -3
- package/src/utils/strings.ts +12 -0
- package/src/utils/test-files.ts +1 -1
- package/src/utils/web-annotate.ts +64 -0
- package/src/utils/web-eidx.ts +21 -0
- package/src/utils/web-element.ts +34 -0
- package/src/utils/web-sandbox.ts +43 -0
- package/dist/boat/api-tester/example/apibot.config.js +0 -30
package/src/command-handler.ts
CHANGED
|
@@ -178,7 +178,7 @@ export class CommandHandler implements InputManager {
|
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
private async executeBrowserCommand(input: string): Promise<void> {
|
|
181
|
-
const action = this.explorBot.getExplorer().
|
|
181
|
+
const action = this.explorBot.getExplorer().action();
|
|
182
182
|
await action.execute(input);
|
|
183
183
|
}
|
|
184
184
|
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { basename } from 'node:path';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import
|
|
3
|
+
import { COMPACT_MAX_LENGTH } from '../ai/experience-compactor.js';
|
|
4
|
+
import type { ExperienceFile } from '../experience-tracker.js';
|
|
4
5
|
import type { ExperienceTracker } from '../experience-tracker.js';
|
|
5
6
|
import { tag } from '../utils/logger.js';
|
|
6
7
|
import { BaseCommand, type Suggestion } from './base-command.js';
|
|
7
8
|
|
|
8
|
-
const COMPACT_THRESHOLD = 5000;
|
|
9
|
-
|
|
10
9
|
export class CompactCommand extends BaseCommand {
|
|
11
10
|
name = 'compact';
|
|
12
11
|
description = 'Compact stored experience files; optionally filtered by filename or URL substring';
|
|
@@ -22,7 +21,7 @@ export class CompactCommand extends BaseCommand {
|
|
|
22
21
|
const dryRun = !!opts.dryRun;
|
|
23
22
|
const merge = opts.merge !== false;
|
|
24
23
|
|
|
25
|
-
const tracker = this.explorBot.
|
|
24
|
+
const tracker = this.explorBot.experienceTracker();
|
|
26
25
|
const files = this.resolveTarget(tracker, target);
|
|
27
26
|
|
|
28
27
|
if (files === null) {
|
|
@@ -62,7 +61,7 @@ export class CompactCommand extends BaseCommand {
|
|
|
62
61
|
private buildDryRunSuggestions(compactor: ReturnType<typeof this.explorBot.agentExperienceCompactor>, files: ExperienceFile[], target?: string): Suggestion[] {
|
|
63
62
|
const wouldTouch = files.filter((f) => {
|
|
64
63
|
const stripped = compactor.stripNonUsefulEntries(f.content);
|
|
65
|
-
return stripped !== f.content || stripped.length >=
|
|
64
|
+
return stripped !== f.content || stripped.length >= COMPACT_MAX_LENGTH || compactor.isRecent(f);
|
|
66
65
|
});
|
|
67
66
|
if (wouldTouch.length === 0) return [];
|
|
68
67
|
const argsPart = target ? ` ${target}` : '';
|
|
@@ -73,7 +72,7 @@ export class CompactCommand extends BaseCommand {
|
|
|
73
72
|
private async runFullSweep(compactor: ReturnType<typeof this.explorBot.agentExperienceCompactor>, merge: boolean): Promise<{ merged: number; compacted: number }> {
|
|
74
73
|
if (!merge) {
|
|
75
74
|
tag('info').log('Compacting all experience files (merge skipped)…');
|
|
76
|
-
const compacted = await compactor.compactFiles(this.explorBot.
|
|
75
|
+
const compacted = await compactor.compactFiles(this.explorBot.experienceTracker().getAllExperience());
|
|
77
76
|
return { merged: 0, compacted };
|
|
78
77
|
}
|
|
79
78
|
|
|
@@ -119,7 +118,7 @@ export class CompactCommand extends BaseCommand {
|
|
|
119
118
|
const charsRemoved = chars - strippedChars;
|
|
120
119
|
const willStrip = stripped !== file.content;
|
|
121
120
|
const willReview = compactor.isRecent(file);
|
|
122
|
-
const willAi = strippedChars >=
|
|
121
|
+
const willAi = strippedChars >= COMPACT_MAX_LENGTH;
|
|
123
122
|
|
|
124
123
|
if (willStrip) wouldStrip++;
|
|
125
124
|
if (willReview) wouldAiReview++;
|
|
@@ -148,7 +147,7 @@ export class CompactCommand extends BaseCommand {
|
|
|
148
147
|
lines.push(` ${chalk.dim('Files matched:')} ${chalk.bold(String(files.length))}`);
|
|
149
148
|
lines.push(` ${chalk.dim('Would strip:')} ${chalk.bold(String(wouldStrip))} ${chalk.dim('(remove legacy / FAILED / Visual click, rename to FLOW/ACTION)')}`);
|
|
150
149
|
lines.push(` ${chalk.dim('Would ai-review:')} ${chalk.bold(String(wouldAiReview))} ${chalk.dim('(recent files ≤30d — quality/reusability check)')}`);
|
|
151
|
-
lines.push(` ${chalk.dim('Would ai-compact:')} ${chalk.bold(String(wouldAiCompact))} ${chalk.dim(`(over ${
|
|
150
|
+
lines.push(` ${chalk.dim('Would ai-compact:')} ${chalk.bold(String(wouldAiCompact))} ${chalk.dim(`(over ${COMPACT_MAX_LENGTH} chars after strip)`)}`);
|
|
152
151
|
lines.push(` ${chalk.dim('Total chars:')} ${chalk.bold(String(totalChars))}`);
|
|
153
152
|
|
|
154
153
|
tag('info').log(lines.join('\n'));
|
|
@@ -6,7 +6,7 @@ export class ContextAriaCommand extends BaseCommand {
|
|
|
6
6
|
description = 'Print full ARIA snapshot for current page';
|
|
7
7
|
|
|
8
8
|
async execute(_args: string): Promise<void> {
|
|
9
|
-
const state = this.explorBot.
|
|
9
|
+
const state = this.explorBot.stateManager().getCurrentState();
|
|
10
10
|
|
|
11
11
|
if (!state) {
|
|
12
12
|
throw new Error('No active page to snapshot');
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { ActionResult } from '../action-result.js';
|
|
2
2
|
import { Researcher } from '../ai/researcher.js';
|
|
3
|
+
import { visuallyAnnotateContainers } from '../ai/researcher/coordinates.js';
|
|
3
4
|
import { outputPath } from '../config.js';
|
|
4
5
|
import { type ContextData, type ContextMode, formatContextSummary } from '../utils/context-formatter.js';
|
|
5
6
|
import { tag } from '../utils/logger.js';
|
|
6
7
|
import { extractValidContainers } from '../utils/research-parser.js';
|
|
8
|
+
import { annotatePageElements } from '../utils/web-annotate.js';
|
|
7
9
|
import { BaseCommand, type Suggestion } from './base-command.js';
|
|
8
10
|
|
|
9
11
|
export class ContextCommand extends BaseCommand {
|
|
@@ -25,7 +27,7 @@ export class ContextCommand extends BaseCommand {
|
|
|
25
27
|
|
|
26
28
|
async execute(args: string): Promise<void> {
|
|
27
29
|
const explorer = this.explorBot.getExplorer();
|
|
28
|
-
const state =
|
|
30
|
+
const state = this.explorBot.stateManager().getCurrentState();
|
|
29
31
|
|
|
30
32
|
if (!state) {
|
|
31
33
|
throw new Error('No active page to show context for');
|
|
@@ -34,17 +36,17 @@ export class ContextCommand extends BaseCommand {
|
|
|
34
36
|
const { opts } = this.parseArgs(args);
|
|
35
37
|
const isVisual = !!(opts.visual || opts.screenshot);
|
|
36
38
|
|
|
37
|
-
await explorer.
|
|
39
|
+
await explorer.withPage(annotatePageElements);
|
|
38
40
|
|
|
39
41
|
if (isVisual) {
|
|
40
42
|
const cachedResearch = Researcher.getCachedResearch(state);
|
|
41
43
|
const containers = cachedResearch ? extractValidContainers(cachedResearch) : [];
|
|
42
|
-
await explorer.
|
|
44
|
+
await explorer.withPage((page) => visuallyAnnotateContainers(page, containers));
|
|
43
45
|
}
|
|
44
46
|
|
|
45
|
-
const actionResult = await explorer.
|
|
46
|
-
const experienceTracker =
|
|
47
|
-
const knowledgeTracker = this.explorBot.
|
|
47
|
+
const actionResult = await explorer.capture({ screenshot: isVisual });
|
|
48
|
+
const experienceTracker = this.explorBot.experienceTracker();
|
|
49
|
+
const knowledgeTracker = this.explorBot.knowledgeTracker();
|
|
48
50
|
|
|
49
51
|
let mode: ContextMode = 'compact';
|
|
50
52
|
if (opts.full) {
|
|
@@ -8,7 +8,7 @@ export class ContextDataCommand extends BaseCommand {
|
|
|
8
8
|
|
|
9
9
|
async execute(_args: string): Promise<void> {
|
|
10
10
|
const explorer = this.explorBot.getExplorer();
|
|
11
|
-
const state =
|
|
11
|
+
const state = this.explorBot.stateManager().getCurrentState();
|
|
12
12
|
|
|
13
13
|
if (!state) {
|
|
14
14
|
throw new Error('No active page to extract data from');
|
|
@@ -18,7 +18,7 @@ export class ContextDataCommand extends BaseCommand {
|
|
|
18
18
|
|
|
19
19
|
if (!actionResult.html || actionResult.html.trim().length < 100) {
|
|
20
20
|
tag('info').log('Capturing fresh page content...');
|
|
21
|
-
const freshResult = await explorer.
|
|
21
|
+
const freshResult = await explorer.capture();
|
|
22
22
|
const table = await this.explorBot.agentResearcher().extractData(freshResult);
|
|
23
23
|
tag('multiline').log(table);
|
|
24
24
|
return;
|
|
@@ -10,14 +10,14 @@ export class ContextExperienceCommand extends BaseCommand {
|
|
|
10
10
|
|
|
11
11
|
async execute(_args: string): Promise<void> {
|
|
12
12
|
const explorer = this.explorBot.getExplorer();
|
|
13
|
-
const state =
|
|
13
|
+
const state = this.explorBot.stateManager().getCurrentState();
|
|
14
14
|
|
|
15
15
|
if (!state) {
|
|
16
16
|
throw new Error('No active page');
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
const actionResult = ActionResult.fromState(state);
|
|
20
|
-
const experienceTracker =
|
|
20
|
+
const experienceTracker = this.explorBot.experienceTracker();
|
|
21
21
|
const experience = experienceTracker.getRelevantExperience(actionResult);
|
|
22
22
|
|
|
23
23
|
if (experience.length === 0) {
|
|
@@ -8,7 +8,7 @@ export class ContextHtmlCommand extends BaseCommand {
|
|
|
8
8
|
|
|
9
9
|
async execute(_args: string): Promise<void> {
|
|
10
10
|
const explorer = this.explorBot.getExplorer();
|
|
11
|
-
const manager =
|
|
11
|
+
const manager = this.explorBot.stateManager();
|
|
12
12
|
const state = manager.getCurrentState();
|
|
13
13
|
|
|
14
14
|
if (!state) {
|
|
@@ -19,7 +19,7 @@ export class ContextHtmlCommand extends BaseCommand {
|
|
|
19
19
|
|
|
20
20
|
if (!actionResult.html || actionResult.html.trim().length < 100) {
|
|
21
21
|
tag('info').log('Capturing fresh page content...');
|
|
22
|
-
actionResult = await explorer.
|
|
22
|
+
actionResult = await explorer.capture();
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
const html = await actionResult.combinedHtml();
|
|
@@ -10,14 +10,14 @@ export class ContextKnowledgeCommand extends BaseCommand {
|
|
|
10
10
|
|
|
11
11
|
async execute(_args: string): Promise<void> {
|
|
12
12
|
const explorer = this.explorBot.getExplorer();
|
|
13
|
-
const state =
|
|
13
|
+
const state = this.explorBot.stateManager().getCurrentState();
|
|
14
14
|
|
|
15
15
|
if (!state) {
|
|
16
16
|
throw new Error('No active page');
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
const actionResult = ActionResult.fromState(state);
|
|
20
|
-
const knowledgeTracker = this.explorBot.
|
|
20
|
+
const knowledgeTracker = this.explorBot.knowledgeTracker();
|
|
21
21
|
const knowledge = knowledgeTracker.getRelevantKnowledge(actionResult);
|
|
22
22
|
|
|
23
23
|
if (knowledge.length === 0) {
|
|
@@ -13,7 +13,7 @@ export class DrillCommand extends BaseCommand {
|
|
|
13
13
|
const knowledgePath = this.parseKnowledgeArg(args);
|
|
14
14
|
const maxComponents = this.parseMaxArg(args);
|
|
15
15
|
|
|
16
|
-
const state = this.explorBot.
|
|
16
|
+
const state = this.explorBot.stateManager().getCurrentState();
|
|
17
17
|
if (!state) {
|
|
18
18
|
throw new Error('No active page to drill');
|
|
19
19
|
}
|
|
@@ -20,7 +20,7 @@ export class ExperienceCommand extends BaseCommand {
|
|
|
20
20
|
}
|
|
21
21
|
const recency = opts.recent ? 'recent' : opts.old ? 'old' : undefined;
|
|
22
22
|
|
|
23
|
-
const tracker = this.explorBot.
|
|
23
|
+
const tracker = this.explorBot.experienceTracker();
|
|
24
24
|
const [first, second] = remaining;
|
|
25
25
|
|
|
26
26
|
const combinedRef = first?.match(/^([A-Z]+)[.\-]?(\d+)$/i);
|
|
@@ -4,6 +4,7 @@ import { outputPath } from '../config.js';
|
|
|
4
4
|
import { normalizeUrl } from '../state-manager.js';
|
|
5
5
|
import { Stats } from '../stats.js';
|
|
6
6
|
import { type Plan, type Test, TestResult } from '../test-plan.js';
|
|
7
|
+
import { browserErrorMessage } from '../utils/browser-errors.ts';
|
|
7
8
|
import { getCliName } from '../utils/cli-name.ts';
|
|
8
9
|
import { ErrorPageError, getStateErrorPageError } from '../utils/error-page.ts';
|
|
9
10
|
import { tag } from '../utils/logger.js';
|
|
@@ -38,7 +39,7 @@ export class ExploreCommand extends BaseCommand {
|
|
|
38
39
|
private priorityFilter?: Set<string>;
|
|
39
40
|
|
|
40
41
|
private getCurrentPageUrl(): string | undefined {
|
|
41
|
-
const state = this.explorBot.
|
|
42
|
+
const state = this.explorBot.stateManager().getCurrentState();
|
|
42
43
|
return state?.fullUrl || state?.url;
|
|
43
44
|
}
|
|
44
45
|
|
|
@@ -56,7 +57,7 @@ export class ExploreCommand extends BaseCommand {
|
|
|
56
57
|
Stats.mode ??= 'explore';
|
|
57
58
|
Stats.focus ??= feature;
|
|
58
59
|
const mainUrl = this.getCurrentPageUrl();
|
|
59
|
-
const error = getStateErrorPageError(this.explorBot.
|
|
60
|
+
const error = getStateErrorPageError(this.explorBot.stateManager().getCurrentState());
|
|
60
61
|
if (error) {
|
|
61
62
|
tag('warning').log(error.message);
|
|
62
63
|
return;
|
|
@@ -74,7 +75,7 @@ export class ExploreCommand extends BaseCommand {
|
|
|
74
75
|
this.printResults();
|
|
75
76
|
return;
|
|
76
77
|
}
|
|
77
|
-
if (mainUrl) await this.explorBot.visit(mainUrl);
|
|
78
|
+
if (mainUrl) await this.explorBot.visit(mainUrl).catch((err) => tag('warning').log(`Could not return to ${mainUrl}: ${browserErrorMessage(err)}`));
|
|
78
79
|
const savedPath = this.explorBot.savePlans(this.completedPlans);
|
|
79
80
|
this.printResults();
|
|
80
81
|
await this.explorBot.printSessionAnalysis();
|
|
@@ -35,7 +35,7 @@ export class FreesailCommand extends BaseCommand {
|
|
|
35
35
|
async (ctx) => {
|
|
36
36
|
if (maxTests != null && testsRun >= maxTests) ctx.stop();
|
|
37
37
|
|
|
38
|
-
const stateManager = this.explorBot.
|
|
38
|
+
const stateManager = this.explorBot.stateManager();
|
|
39
39
|
const state = stateManager.getCurrentState();
|
|
40
40
|
|
|
41
41
|
if (state && !Researcher.getCachedResearch(state)) {
|
|
@@ -70,7 +70,7 @@ export class FreesailCommand extends BaseCommand {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
tag('info').log(`Navigating to: ${suggestion.target} - ${suggestion.reason}`);
|
|
73
|
-
await this.explorBot.
|
|
73
|
+
await this.explorBot.openTab();
|
|
74
74
|
await this.explorBot.visit(suggestion.target);
|
|
75
75
|
this.explorBot.clearPlan();
|
|
76
76
|
},
|
|
@@ -23,7 +23,7 @@ export class KnowsCommand extends BaseCommand {
|
|
|
23
23
|
|
|
24
24
|
async execute(args: string, limit = 0): Promise<void> {
|
|
25
25
|
const url = args.trim();
|
|
26
|
-
const tracker = this.explorBot.
|
|
26
|
+
const tracker = this.explorBot.knowledgeTracker();
|
|
27
27
|
|
|
28
28
|
if (!url) {
|
|
29
29
|
const allKnowledge = tracker.listAllKnowledge();
|
|
@@ -13,12 +13,14 @@ export class LearnCommand extends BaseCommand {
|
|
|
13
13
|
|
|
14
14
|
if (!note) {
|
|
15
15
|
const AddKnowledge = (await import('../components/AddKnowledge.js')).default;
|
|
16
|
-
const
|
|
16
|
+
const explorer = this.explorBot.getExplorer();
|
|
17
|
+
const state = this.explorBot.stateManager().getCurrentState();
|
|
17
18
|
const initialUrl = state?.url || '';
|
|
18
19
|
|
|
19
20
|
const { unmount } = render(
|
|
20
21
|
React.createElement(AddKnowledge, {
|
|
21
22
|
initialUrl,
|
|
23
|
+
knowledgeTracker: this.explorBot.knowledgeTracker(),
|
|
22
24
|
onComplete: () => unmount(),
|
|
23
25
|
onCancel: () => unmount(),
|
|
24
26
|
}),
|
|
@@ -31,14 +33,14 @@ export class LearnCommand extends BaseCommand {
|
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
const explorer = this.explorBot.getExplorer();
|
|
34
|
-
const state =
|
|
36
|
+
const state = this.explorBot.stateManager().getCurrentState();
|
|
35
37
|
|
|
36
38
|
if (!state) {
|
|
37
39
|
throw new Error('No active page to attach knowledge');
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
const targetUrl = state.url || state.fullUrl || '/';
|
|
41
|
-
|
|
43
|
+
this.explorBot.knowledgeTracker().addKnowledge(targetUrl, note);
|
|
42
44
|
tag('success').log('Knowledge saved for current page');
|
|
43
45
|
}
|
|
44
46
|
}
|
|
@@ -16,7 +16,7 @@ export class PathCommand extends BaseCommand {
|
|
|
16
16
|
async execute(args: string): Promise<void> {
|
|
17
17
|
const { opts } = this.parseArgs(args);
|
|
18
18
|
const showLinks = !!opts.links;
|
|
19
|
-
const stateManager = this.explorBot.
|
|
19
|
+
const stateManager = this.explorBot.stateManager();
|
|
20
20
|
const history = stateManager.getStateHistory();
|
|
21
21
|
|
|
22
22
|
if (history.length === 0) {
|
|
@@ -27,7 +27,7 @@ export class ResearchCommand extends BaseCommand {
|
|
|
27
27
|
await this.explorBot.agentNavigator().visit(target);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
const state = this.explorBot.
|
|
30
|
+
const state = this.explorBot.stateManager().getCurrentState();
|
|
31
31
|
if (!state) {
|
|
32
32
|
throw new Error('No active page to research');
|
|
33
33
|
}
|
|
@@ -48,7 +48,7 @@ export class TestCommand extends BaseCommand {
|
|
|
48
48
|
if (matching.length > 0) {
|
|
49
49
|
toExecute.push(...matching);
|
|
50
50
|
} else {
|
|
51
|
-
const state = this.explorBot.
|
|
51
|
+
const state = this.explorBot.stateManager().getCurrentState();
|
|
52
52
|
if (!state) {
|
|
53
53
|
throw new Error('No page loaded. Please navigate to a page first.');
|
|
54
54
|
}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { Box, Text, useInput } from 'ink';
|
|
2
2
|
import React, { useEffect, useState } from 'react';
|
|
3
|
-
import { KnowledgeTracker } from '../knowledge-tracker.js';
|
|
3
|
+
import type { KnowledgeTracker } from '../knowledge-tracker.js';
|
|
4
4
|
import InputReadline from './InputReadline.js';
|
|
5
5
|
|
|
6
6
|
interface AddKnowledgeProps {
|
|
7
7
|
initialUrl?: string;
|
|
8
|
+
knowledgeTracker: KnowledgeTracker;
|
|
8
9
|
onComplete?: () => void;
|
|
9
10
|
onCancel?: () => void;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
const AddKnowledge: React.FC<AddKnowledgeProps> = ({ initialUrl = '', onComplete, onCancel }) => {
|
|
13
|
+
const AddKnowledge: React.FC<AddKnowledgeProps> = ({ initialUrl = '', knowledgeTracker, onComplete, onCancel }) => {
|
|
13
14
|
const [urlPattern, setUrlPattern] = useState(initialUrl);
|
|
14
15
|
const [description, setDescription] = useState('');
|
|
15
16
|
const [activeField, setActiveField] = useState<'url' | 'description'>(initialUrl ? 'description' : 'url');
|
|
@@ -20,18 +21,16 @@ const AddKnowledge: React.FC<AddKnowledgeProps> = ({ initialUrl = '', onComplete
|
|
|
20
21
|
|
|
21
22
|
useEffect(() => {
|
|
22
23
|
try {
|
|
23
|
-
const knowledgeTracker = new KnowledgeTracker();
|
|
24
24
|
const urls = knowledgeTracker.getExistingUrls();
|
|
25
25
|
setSuggestedUrls(urls);
|
|
26
26
|
} catch (error) {
|
|
27
27
|
console.error('Failed to load suggestions:', error);
|
|
28
28
|
}
|
|
29
|
-
}, []);
|
|
29
|
+
}, [knowledgeTracker]);
|
|
30
30
|
|
|
31
31
|
useEffect(() => {
|
|
32
32
|
if (urlPattern.trim()) {
|
|
33
33
|
try {
|
|
34
|
-
const knowledgeTracker = new KnowledgeTracker();
|
|
35
34
|
const knowledge = knowledgeTracker.getKnowledgeForUrl(urlPattern);
|
|
36
35
|
setExistingKnowledge(knowledge);
|
|
37
36
|
} catch (error) {
|
|
@@ -41,7 +40,7 @@ const AddKnowledge: React.FC<AddKnowledgeProps> = ({ initialUrl = '', onComplete
|
|
|
41
40
|
} else {
|
|
42
41
|
setExistingKnowledge([]);
|
|
43
42
|
}
|
|
44
|
-
}, [urlPattern]);
|
|
43
|
+
}, [urlPattern, knowledgeTracker]);
|
|
45
44
|
|
|
46
45
|
const handleSave = () => {
|
|
47
46
|
if (!urlPattern.trim() || !description.trim()) {
|
|
@@ -49,7 +48,6 @@ const AddKnowledge: React.FC<AddKnowledgeProps> = ({ initialUrl = '', onComplete
|
|
|
49
48
|
}
|
|
50
49
|
|
|
51
50
|
try {
|
|
52
|
-
const knowledgeTracker = new KnowledgeTracker();
|
|
53
51
|
const result = knowledgeTracker.addKnowledge(urlPattern.trim(), description.trim());
|
|
54
52
|
const action = result.isNewFile ? 'Created' : 'Updated';
|
|
55
53
|
console.log(`\nKnowledge ${action} in: ${result.filename}`);
|
package/src/components/App.tsx
CHANGED
|
@@ -68,7 +68,7 @@ export function App({ explorBot, initialShowInput = false, exitOnEmptyInput = fa
|
|
|
68
68
|
});
|
|
69
69
|
});
|
|
70
70
|
|
|
71
|
-
const manager = explorBot.
|
|
71
|
+
const manager = explorBot.stateManager();
|
|
72
72
|
|
|
73
73
|
unsubscribe = manager.onStateChange((transition: StateTransition) => {
|
|
74
74
|
if (mounted) {
|
|
@@ -142,7 +142,7 @@ export function App({ explorBot, initialShowInput = false, exitOnEmptyInput = fa
|
|
|
142
142
|
if (!mounted) return;
|
|
143
143
|
setChecklistData({
|
|
144
144
|
config: explorBot.getConfig(),
|
|
145
|
-
knowledgeTracker: explorBot.
|
|
145
|
+
knowledgeTracker: explorBot.knowledgeTracker(),
|
|
146
146
|
});
|
|
147
147
|
setShowWelcome(true);
|
|
148
148
|
setShowInput(true);
|
|
@@ -334,7 +334,7 @@ export function App({ explorBot, initialShowInput = false, exitOnEmptyInput = fa
|
|
|
334
334
|
{showSessionTimer && <SessionTimer startedAt={sessionStartedAtRef.current} />}
|
|
335
335
|
</Box>
|
|
336
336
|
|
|
337
|
-
{showWelcome && <WelcomeCommands hasKnowledge={explorBot.
|
|
337
|
+
{showWelcome && <WelcomeCommands hasKnowledge={explorBot.knowledgeTracker().listAllKnowledge().length > 0} />}
|
|
338
338
|
{showInput && <Box height={1} />}
|
|
339
339
|
{interruptPrompt && showInput && (
|
|
340
340
|
<Box paddingX={1}>
|