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
package/dist/src/action.js
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
import { faker } from '@faker-js/faker';
|
|
4
3
|
import { context, trace } from '@opentelemetry/api';
|
|
5
4
|
import { container, recorder } from 'codeceptjs';
|
|
6
5
|
import * as codeceptjs from 'codeceptjs';
|
|
7
|
-
import { hopeThat, retryTo, tryTo, within } from 'codeceptjs/lib/effects';
|
|
8
|
-
import step from 'codeceptjs/steps';
|
|
9
6
|
import { ActionResult } from './action-result.js';
|
|
10
7
|
import { clearActivity, setActivity } from "./activity.js";
|
|
11
8
|
import { ConfigParser, outputPath } from './config.js';
|
|
12
9
|
import { Observability } from "./observability.js";
|
|
13
|
-
import { isFatalBrowserError, isNavigationTransitionError } from "./utils/browser-errors.js";
|
|
14
|
-
import { htmlCombinedSnapshot, minifyHtml } from './utils/html.js';
|
|
10
|
+
import { browserErrorMessage, isFatalBrowserError, isNavigationTransitionError } from "./utils/browser-errors.js";
|
|
11
|
+
import { captureHtmlForSnapshot, htmlCombinedSnapshot, minifyHtml } from './utils/html.js';
|
|
15
12
|
import { createDebug, setStepSpanParent, tag } from './utils/logger.js';
|
|
16
|
-
import { waitForPageReadiness } from "./utils/page-readiness.js";
|
|
13
|
+
import { sleep, waitForPageReadiness } from "./utils/page-readiness.js";
|
|
14
|
+
import { codeceptJSSandbox, hasPlaywrightCommands, playwrightSandbox, sanitizeCodeBlock } from "./utils/web-sandbox.js";
|
|
17
15
|
import { safeFilename } from "./utils/strings.js";
|
|
18
16
|
const debugLog = createDebug('explorbot:action');
|
|
19
17
|
const CAPTURE_NAVIGATION_TRANSITION_ATTEMPTS = 3;
|
|
@@ -24,7 +22,6 @@ class Action {
|
|
|
24
22
|
config;
|
|
25
23
|
// action info
|
|
26
24
|
action = null;
|
|
27
|
-
expectation = null;
|
|
28
25
|
lastError = null;
|
|
29
26
|
playwrightHelper;
|
|
30
27
|
playwrightGroupId = null;
|
|
@@ -38,9 +35,6 @@ class Action {
|
|
|
38
35
|
this.playwrightHelper = container.helpers('Playwright');
|
|
39
36
|
this.recorder = recorder;
|
|
40
37
|
}
|
|
41
|
-
async caputrePageWithScreenshot() {
|
|
42
|
-
return this.capturePageState({ includeScreenshot: true });
|
|
43
|
-
}
|
|
44
38
|
async saveScreenshot() {
|
|
45
39
|
const currentState = this.stateManager.getCurrentState();
|
|
46
40
|
if (currentState?.screenshotFile)
|
|
@@ -58,7 +52,7 @@ class Action {
|
|
|
58
52
|
return undefined;
|
|
59
53
|
}
|
|
60
54
|
}
|
|
61
|
-
async capturePageState({ includeScreenshot = false } = {}) {
|
|
55
|
+
async capturePageState({ includeScreenshot = false, codeBlock } = {}) {
|
|
62
56
|
try {
|
|
63
57
|
const currentState = this.stateManager.getCurrentState();
|
|
64
58
|
const stateHash = currentState?.hash || 'screenshot';
|
|
@@ -145,11 +139,11 @@ class Action {
|
|
|
145
139
|
ariaSnapshotFile,
|
|
146
140
|
iframeURL: frame ? frame.url?.() || 'iframe' : undefined,
|
|
147
141
|
});
|
|
148
|
-
this.stateManager.updateState(result);
|
|
142
|
+
this.stateManager.updateState(result, codeBlock);
|
|
149
143
|
return result;
|
|
150
144
|
}
|
|
151
145
|
catch (err) {
|
|
152
|
-
const msg =
|
|
146
|
+
const msg = browserErrorMessage(err);
|
|
153
147
|
if (isFatalBrowserError(err))
|
|
154
148
|
throw err;
|
|
155
149
|
debugLog('capturePageState failed with non-fatal error:', msg);
|
|
@@ -272,21 +266,18 @@ class Action {
|
|
|
272
266
|
}
|
|
273
267
|
if (isPlaywright) {
|
|
274
268
|
const page = this.playwrightHelper.page;
|
|
275
|
-
|
|
276
|
-
await asyncFn(page);
|
|
269
|
+
await playwrightSandbox(page, sanitizedCode);
|
|
277
270
|
await sleep(this.config.action?.delay || 500);
|
|
278
271
|
}
|
|
279
272
|
else {
|
|
280
|
-
|
|
281
|
-
codeFunction(this.actor, tryTo, retryTo, within, hopeThat, step, faker);
|
|
273
|
+
codeceptJSSandbox(this.actor, sanitizedCode);
|
|
282
274
|
await recorder.add(() => sleep(this.config.action?.delay || 500));
|
|
283
275
|
await recorder.promise();
|
|
284
276
|
}
|
|
285
|
-
const pageState = await this.capturePageState();
|
|
286
277
|
if (executedSteps.length > 0) {
|
|
287
278
|
codeString = executedSteps.join('\n');
|
|
288
279
|
}
|
|
289
|
-
this.
|
|
280
|
+
const pageState = await this.capturePageState({ codeBlock: codeString });
|
|
290
281
|
this.actionResult = pageState;
|
|
291
282
|
this.assertionSteps = assertionSteps;
|
|
292
283
|
}
|
|
@@ -313,79 +304,15 @@ class Action {
|
|
|
313
304
|
}
|
|
314
305
|
return this;
|
|
315
306
|
}
|
|
316
|
-
async
|
|
317
|
-
const codeString = typeof codeOrFunction === 'string' ? codeOrFunction : codeOrFunction.toString();
|
|
318
|
-
this.expectation = codeString.toString();
|
|
319
|
-
const expectationPreview = sanitizeCodeBlock(codeString)
|
|
320
|
-
.split('\n')
|
|
321
|
-
.map((line) => line.trim())
|
|
322
|
-
.filter(Boolean)
|
|
323
|
-
.slice(0, 2)
|
|
324
|
-
.join(' ');
|
|
325
|
-
tag('step').log(`Expecting: ${expectationPreview || 'assertion'}`);
|
|
326
|
-
try {
|
|
327
|
-
debugLog('Executing expectation:', codeString);
|
|
328
|
-
let codeFunction;
|
|
329
|
-
if (typeof codeOrFunction === 'function') {
|
|
330
|
-
codeFunction = codeOrFunction;
|
|
331
|
-
}
|
|
332
|
-
else {
|
|
333
|
-
const sanitizedCode = sanitizeCodeBlock(codeString);
|
|
334
|
-
if (!sanitizedCode) {
|
|
335
|
-
throw new Error('No valid I.* commands found in code block');
|
|
336
|
-
}
|
|
337
|
-
codeFunction = new Function('I', 'tryTo', 'retryTo', 'within', 'hopeThat', 'step', sanitizedCode);
|
|
338
|
-
}
|
|
339
|
-
codeFunction(this.actor, tryTo, retryTo, within, hopeThat, step);
|
|
340
|
-
await recorder.promise();
|
|
341
|
-
debugLog('Expectation executed successfully');
|
|
342
|
-
// Get current state from state manager
|
|
343
|
-
const currentState = this.stateManager.getCurrentState();
|
|
344
|
-
if (currentState) {
|
|
345
|
-
// Create ActionResult from current state for compatibility
|
|
346
|
-
this.actionResult = new ActionResult({
|
|
347
|
-
url: currentState.fullUrl || '',
|
|
348
|
-
title: currentState.title,
|
|
349
|
-
timestamp: currentState.timestamp,
|
|
350
|
-
html: '', // Empty HTML for expectation state
|
|
351
|
-
});
|
|
352
|
-
}
|
|
353
|
-
return this;
|
|
354
|
-
}
|
|
355
|
-
catch (err) {
|
|
356
|
-
tag('error').log('Expectation failed:', errorToString(err));
|
|
357
|
-
this.lastError = err;
|
|
358
|
-
await recorder.reset();
|
|
359
|
-
await recorder.start();
|
|
360
|
-
debugLog('Expectation failed:', errorToString(err));
|
|
361
|
-
}
|
|
362
|
-
finally {
|
|
363
|
-
clearActivity();
|
|
364
|
-
}
|
|
365
|
-
return this;
|
|
366
|
-
}
|
|
367
|
-
async waitForInteraction() {
|
|
368
|
-
// start with basic approach
|
|
369
|
-
await this.actor.wait(0.5);
|
|
370
|
-
return this;
|
|
371
|
-
}
|
|
372
|
-
async attempt(codeBlock, originalMessage, experience = true) {
|
|
307
|
+
async attempt(codeBlock, originalMessage) {
|
|
373
308
|
try {
|
|
374
309
|
debugLog('Resolution attempt...');
|
|
375
310
|
setActivity('🦾 Acting in browser...', 'action');
|
|
376
311
|
if (!this.actionResult) {
|
|
377
312
|
this.actionResult = ActionResult.fromState(this.stateManager.getCurrentState());
|
|
378
313
|
}
|
|
379
|
-
const prevActionResult = this.actionResult;
|
|
380
314
|
this.lastError = null;
|
|
381
315
|
await this.execute(codeBlock);
|
|
382
|
-
if (!this.expectation && originalMessage) {
|
|
383
|
-
this.expectation = originalMessage;
|
|
384
|
-
}
|
|
385
|
-
if (!this.expectation) {
|
|
386
|
-
return true;
|
|
387
|
-
}
|
|
388
|
-
debugLog('Resolved Expectation:', this.expectation);
|
|
389
316
|
return true;
|
|
390
317
|
}
|
|
391
318
|
catch (error) {
|
|
@@ -399,12 +326,6 @@ class Action {
|
|
|
399
326
|
getActor() {
|
|
400
327
|
return this.actor;
|
|
401
328
|
}
|
|
402
|
-
setActor(actor) {
|
|
403
|
-
this.actor = actor;
|
|
404
|
-
}
|
|
405
|
-
getCurrentState() {
|
|
406
|
-
return this.actionResult;
|
|
407
|
-
}
|
|
408
329
|
getActionResult() {
|
|
409
330
|
return this.actionResult;
|
|
410
331
|
}
|
|
@@ -423,6 +344,13 @@ function errorToString(error) {
|
|
|
423
344
|
return error.message || error.toString();
|
|
424
345
|
}
|
|
425
346
|
async function captureHtml(page, frame, actor) {
|
|
347
|
+
for (const scope of [frame, page]) {
|
|
348
|
+
if (!scope?.evaluate)
|
|
349
|
+
continue;
|
|
350
|
+
const html = await scope.evaluate(captureHtmlForSnapshot).catch(() => null);
|
|
351
|
+
if (typeof html === 'string')
|
|
352
|
+
return html;
|
|
353
|
+
}
|
|
426
354
|
if (frame?.content)
|
|
427
355
|
return frame.content();
|
|
428
356
|
if (page?.content)
|
|
@@ -438,22 +366,6 @@ async function captureTitle(page, actor) {
|
|
|
438
366
|
return actor.grabTitle();
|
|
439
367
|
return '';
|
|
440
368
|
}
|
|
441
|
-
function sanitizeCodeBlock(code) {
|
|
442
|
-
return code
|
|
443
|
-
.split('\n')
|
|
444
|
-
.map((line) => line.trim())
|
|
445
|
-
.filter((line) => line.startsWith('I.') || line.startsWith('page.') || line.startsWith('await '))
|
|
446
|
-
.join('\n');
|
|
447
|
-
}
|
|
448
|
-
function hasPlaywrightCommands(code) {
|
|
449
|
-
return code.split('\n').some((line) => {
|
|
450
|
-
const trimmed = line.trim();
|
|
451
|
-
return trimmed.startsWith('page.') || trimmed.startsWith('await page.');
|
|
452
|
-
});
|
|
453
|
-
}
|
|
454
|
-
function sleep(ms) {
|
|
455
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
456
|
-
}
|
|
457
369
|
const ASSERTION_STEP_NAMES = new Set(['see', 'dontSee', 'seeElement', 'dontSeeElement', 'seeInField', 'dontSeeInField', 'seeInCurrentUrl', 'dontSeeInCurrentUrl']);
|
|
458
370
|
const attachStepLogger = (target, assertionsTarget) => {
|
|
459
371
|
const listener = (step, error) => {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface ActivityEntry {
|
|
2
|
+
message: string;
|
|
3
|
+
timestamp: Date;
|
|
4
|
+
type?: 'ai' | 'action' | 'navigation' | 'general';
|
|
5
|
+
}
|
|
6
|
+
type ActivityListener = (activity: ActivityEntry | null) => void;
|
|
7
|
+
declare class Activity {
|
|
8
|
+
static instance: Activity;
|
|
9
|
+
currentActivity: ActivityEntry | null;
|
|
10
|
+
listeners: ActivityListener[];
|
|
11
|
+
clearTimeoutId: NodeJS.Timeout | null;
|
|
12
|
+
constructor();
|
|
13
|
+
static getInstance(): Activity;
|
|
14
|
+
setActivity(message: string, type?: ActivityEntry['type']): void;
|
|
15
|
+
clearActivity(force?: boolean): void;
|
|
16
|
+
getCurrentActivity(): ActivityEntry | null;
|
|
17
|
+
addListener(listener: ActivityListener): void;
|
|
18
|
+
removeListener(listener: ActivityListener): void;
|
|
19
|
+
notifyListeners(): void;
|
|
20
|
+
}
|
|
21
|
+
export declare const setActivity: (message: string, type?: ActivityEntry["type"]) => void;
|
|
22
|
+
export declare const clearActivity: (force?: boolean) => void;
|
|
23
|
+
export declare const getCurrentActivity: () => ActivityEntry;
|
|
24
|
+
export declare const addActivityListener: (listener: ActivityListener) => void;
|
|
25
|
+
export declare const removeActivityListener: (listener: ActivityListener) => void;
|
|
26
|
+
export default Activity;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export declare const CAPTAIN_ARTIFACT_DIRS: readonly ["reports", "plans", "tests", "states"];
|
|
2
|
+
export declare const CAPTAIN_ALLOWED_READ_DIRS: readonly ["output", "knowledge", "experience"];
|
|
3
|
+
export declare const CAPTAIN_ARTIFACT_SCAN_LIMIT = 200;
|
|
4
|
+
export declare const CAPTAIN_ARTIFACT_LIST_LIMIT = 20;
|
|
5
|
+
export declare const CAPTAIN_READ_FILE_DEFAULT_LIMIT = 12000;
|
|
6
|
+
export declare const CAPTAIN_READ_FILE_MAX_LIMIT = 50000;
|
|
7
|
+
export declare const CAPTAIN_READ_FILE_MIN_LIMIT = 1000;
|
|
8
|
+
export declare function listRecentArtifacts(outputDir: string): Array<{
|
|
9
|
+
path: string;
|
|
10
|
+
size: number;
|
|
11
|
+
modifiedAt: string;
|
|
12
|
+
}>;
|
|
13
|
+
export declare function readCaptainFile(projectRoot: string | null, input: ReadCaptainFileInput, allowedDirs?: readonly string[]): ReadCaptainFileResult;
|
|
14
|
+
export interface ReadCaptainFileInput {
|
|
15
|
+
path: string;
|
|
16
|
+
startLine?: number;
|
|
17
|
+
endLine?: number;
|
|
18
|
+
maxChars?: number;
|
|
19
|
+
}
|
|
20
|
+
export type ReadCaptainFileResult = {
|
|
21
|
+
success: true;
|
|
22
|
+
path: string;
|
|
23
|
+
truncated: boolean;
|
|
24
|
+
content: string;
|
|
25
|
+
} | {
|
|
26
|
+
success: false;
|
|
27
|
+
message: string;
|
|
28
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type Constructor, type ModeContext } from './mixin.js';
|
|
2
|
+
export declare function WithIdleMode<T extends Constructor>(Base: T): {
|
|
3
|
+
new (...args: any[]): {
|
|
4
|
+
idleModeTools(ctx: ModeContext): Promise<Record<string, any>>;
|
|
5
|
+
idleModePrompt(): string;
|
|
6
|
+
};
|
|
7
|
+
} & T;
|
|
8
|
+
export interface IdleModeMethods {
|
|
9
|
+
idleModeTools(ctx: ModeContext): Promise<Record<string, any>>;
|
|
10
|
+
idleModePrompt(): string;
|
|
11
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ExplorBot } from '../../explorbot.js';
|
|
2
|
+
import type { Task } from '../../test-plan.js';
|
|
3
|
+
export type Constructor<T = object> = new (...args: any[]) => T;
|
|
4
|
+
export declare const debugLog: (...args: any[]) => void;
|
|
5
|
+
export type CaptainMode = 'idle' | 'web' | 'test' | 'heal';
|
|
6
|
+
export interface ModeContext {
|
|
7
|
+
explorBot: ExplorBot;
|
|
8
|
+
task: Task;
|
|
9
|
+
}
|
|
10
|
+
export declare function resolveProjectRoot(): string | null;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type Constructor, type ModeContext } from './mixin.js';
|
|
2
|
+
export declare function WithTestMode<T extends Constructor>(Base: T): {
|
|
3
|
+
new (...args: any[]): {
|
|
4
|
+
testModeTools(ctx: ModeContext): Record<string, any>;
|
|
5
|
+
testModePrompt(): string;
|
|
6
|
+
testModeRules(): string;
|
|
7
|
+
};
|
|
8
|
+
} & T;
|
|
9
|
+
export interface TestModeMethods {
|
|
10
|
+
testModeTools(ctx: ModeContext): Record<string, any>;
|
|
11
|
+
testModePrompt(): string;
|
|
12
|
+
testModeRules(): string;
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type Constructor, type ModeContext } from './mixin.js';
|
|
2
|
+
export declare function WithWebMode<T extends Constructor>(Base: T): {
|
|
3
|
+
new (...args: any[]): {
|
|
4
|
+
webModeTools(ctx: ModeContext): Record<string, any>;
|
|
5
|
+
webModePrompt(): string;
|
|
6
|
+
webModeRules(): string;
|
|
7
|
+
};
|
|
8
|
+
} & T;
|
|
9
|
+
export interface WebModeMethods {
|
|
10
|
+
webModeTools(ctx: ModeContext): Record<string, any>;
|
|
11
|
+
webModePrompt(): string;
|
|
12
|
+
webModeRules(): string;
|
|
13
|
+
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { tool } from 'ai';
|
|
2
2
|
import dedent from 'dedent';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
import { ActionResult } from "../../action-result.js";
|
|
5
4
|
import { actionRule, locatorRule, sectionContextRule } from "../rules.js";
|
|
6
5
|
import { createAgentTools, createCodeceptJSTools } from "../tools.js";
|
|
7
6
|
import { debugLog } from "./mixin.js";
|
|
@@ -9,17 +8,11 @@ export function WithWebMode(Base) {
|
|
|
9
8
|
return class extends Base {
|
|
10
9
|
webModeTools(ctx) {
|
|
11
10
|
const explorer = ctx.explorBot.getExplorer();
|
|
12
|
-
const stateManager = explorer.getStateManager();
|
|
13
11
|
const codeceptTools = createCodeceptJSTools(explorer, ctx.task);
|
|
14
12
|
const agentTools = createAgentTools({
|
|
15
13
|
explorer,
|
|
16
14
|
researcher: ctx.explorBot.agentResearcher(),
|
|
17
15
|
navigator: ctx.explorBot.agentNavigator(),
|
|
18
|
-
experienceTracker: stateManager.getExperienceTracker(),
|
|
19
|
-
getState: () => {
|
|
20
|
-
const state = stateManager.getCurrentState();
|
|
21
|
-
return state ? ActionResult.fromState(state) : null;
|
|
22
|
-
},
|
|
23
16
|
});
|
|
24
17
|
const { see, context, visualClick, learnExperience } = agentTools;
|
|
25
18
|
return {
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import type { ExperienceTracker } from '../experience-tracker.js';
|
|
2
|
+
import type { ExplorBot } from '../explorbot.js';
|
|
3
|
+
import type { WebPageState } from '../state-manager.js';
|
|
4
|
+
import { Task, Test } from '../test-plan.js';
|
|
5
|
+
import { HooksRunner } from '../utils/hooks-runner.js';
|
|
6
|
+
import type { Agent } from './agent.js';
|
|
7
|
+
import { type CaptainMode, type ModeContext } from './captain/mixin.js';
|
|
8
|
+
import { type Conversation } from './conversation.js';
|
|
9
|
+
import type { Navigator } from './navigator.js';
|
|
10
|
+
import type { Provider } from './provider.js';
|
|
11
|
+
import { TaskAgent } from './task-agent.js';
|
|
12
|
+
declare const CaptainBase: {
|
|
13
|
+
new (...args: any[]): {
|
|
14
|
+
testModeTools(ctx: ModeContext): Record<string, any>;
|
|
15
|
+
testModePrompt(): string;
|
|
16
|
+
testModeRules(): string;
|
|
17
|
+
};
|
|
18
|
+
} & {
|
|
19
|
+
new (...args: any[]): {
|
|
20
|
+
webModeTools(ctx: ModeContext): Record<string, any>;
|
|
21
|
+
webModePrompt(): string;
|
|
22
|
+
webModeRules(): string;
|
|
23
|
+
};
|
|
24
|
+
} & {
|
|
25
|
+
new (...args: any[]): {
|
|
26
|
+
idleModeTools(ctx: ModeContext): Promise<Record<string, any>>;
|
|
27
|
+
idleModePrompt(): string;
|
|
28
|
+
};
|
|
29
|
+
} & (new (...args: any[]) => TaskAgent);
|
|
30
|
+
export declare class Captain extends CaptainBase implements Agent {
|
|
31
|
+
emoji: string;
|
|
32
|
+
explorBot: ExplorBot;
|
|
33
|
+
conversation: Conversation | null;
|
|
34
|
+
experienceTracker: ExperienceTracker;
|
|
35
|
+
hooksRunner: HooksRunner | null;
|
|
36
|
+
commandExecutor: ((cmd: string) => Promise<void>) | null;
|
|
37
|
+
commandDescriptions: {
|
|
38
|
+
name: string;
|
|
39
|
+
description: string;
|
|
40
|
+
options: string;
|
|
41
|
+
}[];
|
|
42
|
+
constructor(explorBot: ExplorBot);
|
|
43
|
+
setCommandExecutor(fn: (cmd: string) => Promise<void>, descriptions: {
|
|
44
|
+
name: string;
|
|
45
|
+
description: string;
|
|
46
|
+
options: string;
|
|
47
|
+
}[]): void;
|
|
48
|
+
getHooksRunner(): HooksRunner;
|
|
49
|
+
getNavigator(): Navigator;
|
|
50
|
+
getExperienceTracker(): ExperienceTracker;
|
|
51
|
+
getKnowledgeTracker(): import("../knowledge-tracker.js").KnowledgeTracker;
|
|
52
|
+
getProvider(): Provider;
|
|
53
|
+
trackToolExecutions(toolExecutions: any[]): void;
|
|
54
|
+
getMode(): CaptainMode;
|
|
55
|
+
systemPrompt(): string;
|
|
56
|
+
resetConversation(): Conversation;
|
|
57
|
+
ensureConversation(): Conversation;
|
|
58
|
+
getPageContext(): Promise<string>;
|
|
59
|
+
planSummary(): string;
|
|
60
|
+
reinjectContextIfNeeded(conversation: Conversation, currentState: WebPageState): Promise<void>;
|
|
61
|
+
coreTools(task: Task, onDone: (summary: string) => void): {
|
|
62
|
+
done: import("@ai-sdk/provider-utils").ExecutableTool<import("ai").Tool<{
|
|
63
|
+
summary: string;
|
|
64
|
+
details?: string;
|
|
65
|
+
}, {
|
|
66
|
+
success: boolean;
|
|
67
|
+
message: string;
|
|
68
|
+
summary?: undefined;
|
|
69
|
+
} | {
|
|
70
|
+
success: boolean;
|
|
71
|
+
summary: any;
|
|
72
|
+
message?: undefined;
|
|
73
|
+
}, import("@ai-sdk/provider-utils").Context>>;
|
|
74
|
+
runCommand: import("@ai-sdk/provider-utils").ExecutableTool<import("ai").Tool<{
|
|
75
|
+
command: any;
|
|
76
|
+
}, {
|
|
77
|
+
success: boolean;
|
|
78
|
+
message: string;
|
|
79
|
+
command?: undefined;
|
|
80
|
+
output?: undefined;
|
|
81
|
+
} | {
|
|
82
|
+
success: boolean;
|
|
83
|
+
command: any;
|
|
84
|
+
message: string;
|
|
85
|
+
output?: undefined;
|
|
86
|
+
} | {
|
|
87
|
+
success: boolean;
|
|
88
|
+
command: any;
|
|
89
|
+
output: string;
|
|
90
|
+
message?: undefined;
|
|
91
|
+
}, import("@ai-sdk/provider-utils").Context>>;
|
|
92
|
+
};
|
|
93
|
+
tools(task: Task, onDone: (summary: string) => void): Promise<{
|
|
94
|
+
done: import("@ai-sdk/provider-utils").ExecutableTool<import("ai").Tool<{
|
|
95
|
+
summary: string;
|
|
96
|
+
details?: string;
|
|
97
|
+
}, {
|
|
98
|
+
success: boolean;
|
|
99
|
+
message: string;
|
|
100
|
+
summary?: undefined;
|
|
101
|
+
} | {
|
|
102
|
+
success: boolean;
|
|
103
|
+
summary: any;
|
|
104
|
+
message?: undefined;
|
|
105
|
+
}, import("@ai-sdk/provider-utils").Context>>;
|
|
106
|
+
runCommand: import("@ai-sdk/provider-utils").ExecutableTool<import("ai").Tool<{
|
|
107
|
+
command: any;
|
|
108
|
+
}, {
|
|
109
|
+
success: boolean;
|
|
110
|
+
message: string;
|
|
111
|
+
command?: undefined;
|
|
112
|
+
output?: undefined;
|
|
113
|
+
} | {
|
|
114
|
+
success: boolean;
|
|
115
|
+
command: any;
|
|
116
|
+
message: string;
|
|
117
|
+
output?: undefined;
|
|
118
|
+
} | {
|
|
119
|
+
success: boolean;
|
|
120
|
+
command: any;
|
|
121
|
+
output: string;
|
|
122
|
+
message?: undefined;
|
|
123
|
+
}, import("@ai-sdk/provider-utils").Context>>;
|
|
124
|
+
}>;
|
|
125
|
+
processSupervisorInterrupt(userMessage: string, activeTest: Test): Promise<SupervisorAction>;
|
|
126
|
+
processExecutionError(error: Error, activeTest: Test): Promise<ExecutionRecoveryAction>;
|
|
127
|
+
canCompleteWithoutDetails(): boolean;
|
|
128
|
+
handle(input: string, options?: {
|
|
129
|
+
reset?: boolean;
|
|
130
|
+
}): Promise<string | null>;
|
|
131
|
+
}
|
|
132
|
+
export default Captain;
|
|
133
|
+
interface SupervisorAction {
|
|
134
|
+
action: 'inject' | 'stop' | 'pass' | 'skip';
|
|
135
|
+
message: string;
|
|
136
|
+
}
|
|
137
|
+
interface ExecutionRecoveryAction {
|
|
138
|
+
action: 'continue' | 'stop';
|
|
139
|
+
message: string;
|
|
140
|
+
recovered?: boolean;
|
|
141
|
+
}
|
package/dist/src/ai/captain.js
CHANGED
|
@@ -2,8 +2,8 @@ import { tool } from 'ai';
|
|
|
2
2
|
import dedent from 'dedent';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { ActionResult } from '../action-result.js';
|
|
5
|
-
import { ExperienceTracker } from '../experience-tracker.js';
|
|
6
5
|
import { Task } from "../test-plan.js";
|
|
6
|
+
import { formatHeadings } from "../utils/context-formatter.js";
|
|
7
7
|
import { HooksRunner } from "../utils/hooks-runner.js";
|
|
8
8
|
import { startLogCapture, stopLogCapture, tag } from '../utils/logger.js';
|
|
9
9
|
import { loop } from '../utils/loop.js';
|
|
@@ -28,7 +28,7 @@ export class Captain extends CaptainBase {
|
|
|
28
28
|
constructor(explorBot) {
|
|
29
29
|
super();
|
|
30
30
|
this.explorBot = explorBot;
|
|
31
|
-
this.experienceTracker =
|
|
31
|
+
this.experienceTracker = explorBot.experienceTracker();
|
|
32
32
|
}
|
|
33
33
|
setCommandExecutor(fn, descriptions) {
|
|
34
34
|
this.commandExecutor = fn;
|
|
@@ -48,7 +48,7 @@ export class Captain extends CaptainBase {
|
|
|
48
48
|
return this.experienceTracker;
|
|
49
49
|
}
|
|
50
50
|
getKnowledgeTracker() {
|
|
51
|
-
return this.explorBot.
|
|
51
|
+
return this.explorBot.knowledgeTracker();
|
|
52
52
|
}
|
|
53
53
|
getProvider() {
|
|
54
54
|
return this.explorBot.getProvider();
|
|
@@ -126,13 +126,6 @@ export class Captain extends CaptainBase {
|
|
|
126
126
|
}
|
|
127
127
|
return this.conversation;
|
|
128
128
|
}
|
|
129
|
-
getConversation() {
|
|
130
|
-
return this.conversation;
|
|
131
|
-
}
|
|
132
|
-
cleanConversation() {
|
|
133
|
-
this.conversation = null;
|
|
134
|
-
tag('info').log('Conversation cleaned');
|
|
135
|
-
}
|
|
136
129
|
async getPageContext() {
|
|
137
130
|
const state = this.explorBot.getExplorer().getStateManager().getCurrentState();
|
|
138
131
|
if (!state) {
|
|
@@ -141,15 +134,7 @@ export class Captain extends CaptainBase {
|
|
|
141
134
|
const actionResult = ActionResult.fromState(state);
|
|
142
135
|
const knowledge = this.getKnowledge(actionResult);
|
|
143
136
|
const experience = this.getExperience(actionResult);
|
|
144
|
-
const headingLines =
|
|
145
|
-
if (state.h1)
|
|
146
|
-
headingLines.push(`H1: ${state.h1}`);
|
|
147
|
-
if (state.h2)
|
|
148
|
-
headingLines.push(`H2: ${state.h2}`);
|
|
149
|
-
if (state.h3)
|
|
150
|
-
headingLines.push(`H3: ${state.h3}`);
|
|
151
|
-
if (state.h4)
|
|
152
|
-
headingLines.push(`H4: ${state.h4}`);
|
|
137
|
+
const headingLines = formatHeadings(state);
|
|
153
138
|
const headingsBlock = headingLines.join('\n');
|
|
154
139
|
let pageSummary = '';
|
|
155
140
|
const cachedResearch = Researcher.getCachedResearch(state);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ModelMessage } from 'ai';
|
|
2
|
+
export interface ToolExecution {
|
|
3
|
+
toolName: string;
|
|
4
|
+
input: any;
|
|
5
|
+
output: any;
|
|
6
|
+
wasSuccessful: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function toToolExecution(toolName: string, input: any, rawOutput: any): ToolExecution;
|
|
9
|
+
export declare function toolExecutionLabel(input: Record<string, any> | undefined): string;
|
|
10
|
+
export declare class Conversation {
|
|
11
|
+
messages: ModelMessage[];
|
|
12
|
+
model: any;
|
|
13
|
+
protectedPrefixCount: number;
|
|
14
|
+
autoTrimRules: Map<string, number>;
|
|
15
|
+
constructor(messages?: ModelMessage[], model?: any);
|
|
16
|
+
protectPrefix(count: number): void;
|
|
17
|
+
addUserText(text: string): void;
|
|
18
|
+
addAssistantText(text: string): void;
|
|
19
|
+
getLastMessage(): string;
|
|
20
|
+
clone(): Conversation;
|
|
21
|
+
cleanupTag(tagName: string, replacement: string, keepLast?: number): void;
|
|
22
|
+
autoTrimTag(tagName: string, maxLength: number): void;
|
|
23
|
+
compactToolResults(keepLastN: number): void;
|
|
24
|
+
markLastMessageCacheable(): void;
|
|
25
|
+
hasTag(tagName: string, lastN?: number): boolean;
|
|
26
|
+
applyAutoTrim(text: string): string;
|
|
27
|
+
getToolExecutions(): ToolExecution[];
|
|
28
|
+
}
|
|
@@ -1,20 +1,22 @@
|
|
|
1
|
+
export function toToolExecution(toolName, input, rawOutput) {
|
|
2
|
+
let output = rawOutput;
|
|
3
|
+
if (rawOutput?.type === 'json' && rawOutput?.value)
|
|
4
|
+
output = rawOutput.value;
|
|
5
|
+
return { toolName, input, output, wasSuccessful: output?.success !== false };
|
|
6
|
+
}
|
|
1
7
|
export function toolExecutionLabel(input) {
|
|
2
8
|
return input?.explanation || input?.assertion || input?.reason || input?.request || '';
|
|
3
9
|
}
|
|
4
10
|
const AUTO_COMPACT_ARIA_CHANGES_CUTOFF = 500;
|
|
5
11
|
const AUTO_COMPACT_TARGETED_HTML_CUTOFF = 500;
|
|
6
12
|
export class Conversation {
|
|
7
|
-
id;
|
|
8
13
|
messages;
|
|
9
14
|
model;
|
|
10
|
-
telemetryFunctionId;
|
|
11
15
|
protectedPrefixCount = 0;
|
|
12
16
|
autoTrimRules;
|
|
13
|
-
constructor(messages = [], model
|
|
14
|
-
this.id = this.generateId();
|
|
17
|
+
constructor(messages = [], model) {
|
|
15
18
|
this.messages = messages;
|
|
16
19
|
this.model = model || '';
|
|
17
|
-
this.telemetryFunctionId = telemetryFunctionId;
|
|
18
20
|
this.autoTrimRules = new Map();
|
|
19
21
|
}
|
|
20
22
|
protectPrefix(count) {
|
|
@@ -26,17 +28,6 @@ export class Conversation {
|
|
|
26
28
|
content: this.applyAutoTrim(text),
|
|
27
29
|
});
|
|
28
30
|
}
|
|
29
|
-
addUserImage(image) {
|
|
30
|
-
if (!image || image.trim() === '') {
|
|
31
|
-
console.warn('Warning: Attempting to add empty image to conversation');
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
const imageData = image.startsWith('data:') ? image : `data:image/png;base64,${image}`;
|
|
35
|
-
this.messages.push({
|
|
36
|
-
role: 'user',
|
|
37
|
-
content: [{ type: 'file', mediaType: 'image/png', data: imageData }],
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
31
|
addAssistantText(text) {
|
|
41
32
|
// Skip empty or whitespace-only messages
|
|
42
33
|
if (!text || text.trim() === '') {
|
|
@@ -61,7 +52,7 @@ export class Conversation {
|
|
|
61
52
|
return '';
|
|
62
53
|
}
|
|
63
54
|
clone() {
|
|
64
|
-
return new Conversation([...this.messages], this.model
|
|
55
|
+
return new Conversation([...this.messages], this.model);
|
|
65
56
|
}
|
|
66
57
|
cleanupTag(tagName, replacement, keepLast = 0) {
|
|
67
58
|
const escapedTag = tagName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
@@ -190,9 +181,6 @@ export class Conversation {
|
|
|
190
181
|
}
|
|
191
182
|
return result;
|
|
192
183
|
}
|
|
193
|
-
generateId() {
|
|
194
|
-
return `conv_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
195
|
-
}
|
|
196
184
|
getToolExecutions() {
|
|
197
185
|
const toolCalls = new Map();
|
|
198
186
|
for (const message of this.messages) {
|
|
@@ -215,14 +203,7 @@ export class Conversation {
|
|
|
215
203
|
for (const part of message.content) {
|
|
216
204
|
if (part.type !== 'tool-result')
|
|
217
205
|
continue;
|
|
218
|
-
|
|
219
|
-
const output = rawOutput?.type === 'json' && rawOutput?.value ? rawOutput.value : rawOutput;
|
|
220
|
-
executions.push({
|
|
221
|
-
toolName: part.toolName,
|
|
222
|
-
input: toolCalls.get(part.toolCallId) || {},
|
|
223
|
-
output,
|
|
224
|
-
wasSuccessful: output?.success !== false,
|
|
225
|
-
});
|
|
206
|
+
executions.push(toToolExecution(part.toolName, toolCalls.get(part.toolCallId) || {}, part.output));
|
|
226
207
|
}
|
|
227
208
|
}
|
|
228
209
|
return executions;
|