explorbot 0.2.1 → 0.2.3
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 +1 -1
- package/bin/explorbot-cli.ts +52 -37
- package/boat/api-tester/src/apibot.ts +4 -2
- package/boat/api-tester/src/cli.ts +2 -2
- package/boat/api-tester/src/config.ts +39 -8
- package/boat/doc-collector/src/ai/documentarian.ts +3 -0
- package/boat/doc-collector/src/ai/tools.ts +17 -5
- package/boat/doc-collector/src/cli.ts +2 -0
- package/boat/doc-collector/src/config.ts +2 -0
- package/boat/doc-collector/src/docbot.ts +39 -11
- package/boat/doc-collector/src/docs-renderer.ts +18 -4
- package/boat/doc-collector/src/interaction-screenshots.ts +160 -0
- package/boat/doc-collector/src/screenshots.ts +22 -14
- package/boat/doc-collector/src/state-diagram.ts +61 -14
- package/boat/prima/bin/prima-cli.ts +5 -0
- package/boat/prima/package.json +16 -0
- package/boat/prima/src/cli.ts +222 -0
- package/boat/prima/src/envelope.ts +141 -0
- package/boat/prima/src/prima.ts +705 -0
- package/boat/prima/src/pw-parser.ts +17 -0
- package/boat/prima/src/pw-registry.ts +75 -0
- package/dist/bin/explorbot-cli.js +44 -31
- package/dist/boat/api-tester/src/apibot.js +3 -2
- package/dist/boat/api-tester/src/cli.js +2 -2
- package/dist/boat/api-tester/src/config.js +36 -8
- package/dist/boat/doc-collector/src/ai/documentarian.js +3 -0
- package/dist/boat/doc-collector/src/ai/tools.js +10 -4
- package/dist/boat/doc-collector/src/cli.js +2 -0
- package/dist/boat/doc-collector/src/config.js +1 -0
- package/dist/boat/doc-collector/src/docbot.js +36 -10
- package/dist/boat/doc-collector/src/docs-renderer.js +17 -3
- package/dist/boat/doc-collector/src/interaction-screenshots.js +156 -0
- package/dist/boat/doc-collector/src/screenshots.js +23 -14
- package/dist/boat/doc-collector/src/state-diagram.js +57 -13
- package/dist/boat/prima/bin/prima-cli.js +4 -0
- package/dist/boat/prima/src/cli.js +200 -0
- package/dist/boat/prima/src/envelope.js +116 -0
- package/dist/boat/prima/src/prima.js +635 -0
- package/dist/boat/prima/src/pw-parser.js +18 -0
- package/dist/boat/prima/src/pw-registry.js +66 -0
- package/dist/models.json +3 -0
- package/dist/package.json +9 -2
- package/dist/src/action.d.ts +5 -2
- package/dist/src/action.js +5 -5
- package/dist/src/ai/captain/mixin.js +3 -4
- package/dist/src/ai/captain/web-mode.js +1 -1
- package/dist/src/ai/navigator.d.ts +4 -0
- package/dist/src/ai/navigator.js +11 -6
- package/dist/src/ai/planner.d.ts +1 -0
- package/dist/src/ai/planner.js +6 -0
- package/dist/src/ai/researcher/locators.js +1 -1
- package/dist/src/ai/researcher.js +1 -1
- package/dist/src/ai/task-agent.js +1 -1
- package/dist/src/ai/tester.d.ts +1 -0
- package/dist/src/ai/tester.js +13 -0
- package/dist/src/application-spec-contract.d.ts +8 -0
- package/dist/src/application-spec-contract.js +8 -0
- package/dist/src/application-spec.d.ts +15 -0
- package/dist/src/application-spec.js +71 -0
- package/dist/src/browser-server.d.ts +12 -6
- package/dist/src/browser-server.js +74 -19
- package/dist/src/commands/clean-command.js +2 -7
- package/dist/src/commands/init-command.d.ts +5 -0
- package/dist/src/commands/init-command.js +119 -1
- package/dist/src/commands/navigate-command.js +1 -1
- package/dist/src/commands/research-command.js +1 -1
- package/dist/src/commands/sites-command.d.ts +6 -0
- package/dist/src/commands/sites-command.js +23 -0
- package/dist/src/components/InitWizard.d.ts +10 -0
- package/dist/src/components/InitWizard.js +133 -0
- package/dist/src/components/InputReadline.d.ts +1 -0
- package/dist/src/components/InputReadline.js +7 -4
- package/dist/src/config.d.ts +24 -5
- package/dist/src/config.js +146 -37
- package/dist/src/explorbot.d.ts +9 -0
- package/dist/src/explorbot.js +24 -5
- package/dist/src/explorer.d.ts +5 -1
- package/dist/src/explorer.js +54 -19
- package/dist/src/global-config.d.ts +22 -0
- package/dist/src/global-config.js +117 -0
- package/dist/src/knowledge-tracker.d.ts +5 -1
- package/dist/src/knowledge-tracker.js +14 -1
- package/dist/src/utils/cli-name.js +6 -2
- package/dist/src/utils/test-files.js +1 -2
- package/dist/src/utils/url-matcher.d.ts +1 -0
- package/dist/src/utils/url-matcher.js +9 -0
- package/models.json +3 -0
- package/package.json +9 -2
- package/src/action.ts +9 -5
- package/src/ai/captain/mixin.ts +3 -3
- package/src/ai/captain/web-mode.ts +1 -1
- package/src/ai/navigator.ts +12 -7
- package/src/ai/planner.ts +7 -0
- package/src/ai/researcher/locators.ts +1 -1
- package/src/ai/researcher.ts +1 -1
- package/src/ai/task-agent.ts +1 -1
- package/src/ai/tester.ts +15 -0
- package/src/application-spec-contract.ts +10 -0
- package/src/application-spec.ts +87 -0
- package/src/browser-server.ts +74 -19
- package/src/commands/clean-command.ts +1 -6
- package/src/commands/init-command.ts +146 -1
- package/src/commands/navigate-command.ts +1 -1
- package/src/commands/research-command.ts +1 -1
- package/src/commands/sites-command.ts +27 -0
- package/src/components/InitWizard.tsx +166 -0
- package/src/components/InputReadline.tsx +8 -4
- package/src/config.ts +162 -39
- package/src/explorbot.ts +30 -5
- package/src/explorer.ts +59 -20
- package/src/global-config.ts +148 -0
- package/src/knowledge-tracker.ts +17 -1
- package/src/utils/cli-name.ts +5 -2
- package/src/utils/test-files.ts +1 -2
- package/src/utils/url-matcher.ts +10 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
export interface InstanceInfo {
|
|
5
|
+
name: string;
|
|
6
|
+
tabs: number;
|
|
7
|
+
startedAgo?: string;
|
|
8
|
+
attached?: string;
|
|
9
|
+
others: Array<{ name: string; tabs: number }>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface HealAttempt {
|
|
13
|
+
code: string;
|
|
14
|
+
outcome: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface EnvelopeData {
|
|
18
|
+
ok: boolean;
|
|
19
|
+
command: string;
|
|
20
|
+
healed?: boolean;
|
|
21
|
+
healNote?: string;
|
|
22
|
+
used?: string[];
|
|
23
|
+
page: { url: string; previousUrl?: string; title: string; state: string; visits: number };
|
|
24
|
+
changes?: string | null;
|
|
25
|
+
answer?: string;
|
|
26
|
+
research?: string;
|
|
27
|
+
verdict?: { passed: boolean; evidence: string; code: string };
|
|
28
|
+
failure?: { error: string; attempts: HealAttempt[]; reasoning?: string; compactAria?: string };
|
|
29
|
+
instance: InstanceInfo;
|
|
30
|
+
artifacts?: { aria: string; html: string; network: string };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function renderEnvelope(data: EnvelopeData): string {
|
|
34
|
+
const sections = [renderResult(data), renderPage(data), renderOutcome(data), ...renderFailure(data), renderInstance(data.instance), renderArtifacts(data)];
|
|
35
|
+
return sections.filter((section) => section).join('\n\n');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function writeArtifacts(dir: string, snapshot: { aria: string | null; html: string | null; requests: unknown[] }): { aria: string; html: string; network: string } {
|
|
39
|
+
mkdirSync(dir, { recursive: true });
|
|
40
|
+
const paths = {
|
|
41
|
+
aria: path.resolve(dir, 'aria.yml'),
|
|
42
|
+
html: path.resolve(dir, 'page.html'),
|
|
43
|
+
network: path.resolve(dir, 'network.jsonl'),
|
|
44
|
+
};
|
|
45
|
+
writeFileSync(paths.aria, snapshot.aria ?? '', 'utf-8');
|
|
46
|
+
writeFileSync(paths.html, snapshot.html ?? '', 'utf-8');
|
|
47
|
+
writeFileSync(paths.network, snapshot.requests.map((request) => `${JSON.stringify(request)}\n`).join(''), 'utf-8');
|
|
48
|
+
return paths;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function renderResult(data: EnvelopeData): string {
|
|
52
|
+
const lines = [`ok: ${data.ok}`, `command: ${data.command}`];
|
|
53
|
+
const healed = renderHealed(data);
|
|
54
|
+
if (healed) lines.push(healed);
|
|
55
|
+
if (data.used?.length) lines.push(`used: ${data.used.join('; ')}`);
|
|
56
|
+
return section('Result', lines.join('\n'));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function renderHealed(data: EnvelopeData): string | null {
|
|
60
|
+
if (data.healed === undefined) return null;
|
|
61
|
+
if (data.healNote) return `healed: ${data.healed} (${data.healNote})`;
|
|
62
|
+
return `healed: ${data.healed}`;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function renderPage(data: EnvelopeData): string {
|
|
66
|
+
const { url, previousUrl, title, state, visits } = data.page;
|
|
67
|
+
const urlLabel = `url: ${url}`;
|
|
68
|
+
const stateLabel = `state: ${state}`;
|
|
69
|
+
const width = Math.max(urlLabel.length, stateLabel.length) + 3;
|
|
70
|
+
let changedMarker = '';
|
|
71
|
+
if (previousUrl && previousUrl !== url) changedMarker = `(changed: ${previousUrl} → ${url})`;
|
|
72
|
+
const lines = [align(urlLabel, changedMarker, width), `title: ${title}`, align(stateLabel, `(visit #${visits})`, width)];
|
|
73
|
+
return section('Page', lines.join('\n'));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function renderOutcome(data: EnvelopeData): string | null {
|
|
77
|
+
if (data.changes) return section('Changes', data.changes);
|
|
78
|
+
if (data.answer) return section('Answer', data.answer);
|
|
79
|
+
if (data.research) return section('Research', data.research);
|
|
80
|
+
if (!data.verdict) return null;
|
|
81
|
+
const lines = [`passed: ${data.verdict.passed}`, `evidence: ${data.verdict.evidence}`, `code: ${data.verdict.code}`];
|
|
82
|
+
return section('Verdict', lines.join('\n'));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function renderFailure(data: EnvelopeData): Array<string | null> {
|
|
86
|
+
if (!data.failure) return [];
|
|
87
|
+
const lines = [`error: ${data.failure.error}`];
|
|
88
|
+
if (data.failure.reasoning) lines.push(`reasoning: ${data.failure.reasoning}`);
|
|
89
|
+
return [section('Failure', lines.join('\n')), renderAttempts(data.failure.attempts), renderCompactAria(data.failure.compactAria)];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function renderAttempts(attempts: HealAttempt[]): string | null {
|
|
93
|
+
if (!attempts?.length) return null;
|
|
94
|
+
const labels = attempts.map((attempt, index) => `${index + 1}. ${attempt.code}`);
|
|
95
|
+
const width = Math.max(...labels.map((label) => label.length)) + 3;
|
|
96
|
+
const lines = labels.map((label, index) => align(label, `→ ${attempts[index].outcome}`, width));
|
|
97
|
+
return section(`Healing attempts (${attempts.length})`, lines.join('\n'));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function renderCompactAria(compactAria?: string): string | null {
|
|
101
|
+
if (!compactAria) return null;
|
|
102
|
+
return section('Current page (compact ARIA)', compactAria);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function renderInstance(instance: InstanceInfo): string {
|
|
106
|
+
const others = instance.others.map((other) => `${other.name} (${tabsLabel(other.tabs)})`);
|
|
107
|
+
const lines = [`instance: ${instance.name} (${tabsLabel(instance.tabs)}) | other instances: ${otherInstances(others)}`, browserLine(instance)];
|
|
108
|
+
return section('Instance', lines.join('\n'));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function otherInstances(others: string[]): string {
|
|
112
|
+
if (!others.length) return 'none';
|
|
113
|
+
return others.join(', ');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function browserLine(instance: InstanceInfo): string {
|
|
117
|
+
if (instance.attached) return `browser: attached (${instance.attached})`;
|
|
118
|
+
if (instance.startedAgo) return `browser: running, started ${instance.startedAgo} ago`;
|
|
119
|
+
if (instance.tabs > 0) return 'browser: running';
|
|
120
|
+
return 'browser: not running';
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function tabsLabel(tabs: number): string {
|
|
124
|
+
if (tabs === 1) return '1 tab';
|
|
125
|
+
return `${tabs} tabs`;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function renderArtifacts(data: EnvelopeData): string | null {
|
|
129
|
+
if (!data.artifacts) return null;
|
|
130
|
+
const lines = [`aria: ${data.artifacts.aria}`, `html: ${data.artifacts.html}`, `network: ${data.artifacts.network}`];
|
|
131
|
+
return section('Artifacts', lines.join('\n'));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function align(label: string, marker: string, width: number): string {
|
|
135
|
+
if (!marker) return label;
|
|
136
|
+
return `${label.padEnd(width)}${marker}`;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function section(title: string, body: string): string {
|
|
140
|
+
return `### ${title}\n${body}`;
|
|
141
|
+
}
|