explorbot 0.1.31 → 0.1.32-beta.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/dist/boat/api-tester/example/apibot.config.js +30 -0
- package/dist/package.json +10 -25
- package/dist/src/action-result.d.ts +133 -0
- package/dist/src/action-result.js +22 -7
- package/dist/src/action.d.ts +50 -0
- package/dist/src/action.js +10 -5
- 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.d.ts +143 -0
- package/dist/src/ai/conversation.d.ts +31 -0
- package/dist/src/ai/driller.d.ts +161 -0
- package/dist/src/ai/experience-compactor.d.ts +53 -0
- package/dist/src/ai/fisherman-tools.d.ts +90 -0
- package/dist/src/ai/fisherman.d.ts +30 -0
- package/dist/src/ai/historian/codeceptjs.d.ts +15 -0
- 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 +20 -0
- package/dist/src/ai/historian/screencast.d.ts +32 -0
- package/dist/src/ai/historian/utils.d.ts +4 -0
- package/dist/src/ai/historian.d.ts +108 -0
- package/dist/src/ai/navigator.d.ts +56 -0
- package/dist/src/ai/pilot.d.ts +83 -0
- 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/provider.d.ts +50 -0
- package/dist/src/ai/provider.js +10 -3
- package/dist/src/ai/quartermaster.d.ts +57 -0
- package/dist/src/ai/rerunner.d.ts +49 -0
- package/dist/src/ai/researcher/cache.d.ts +6 -0
- 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/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/research-result.d.ts +16 -0
- package/dist/src/ai/researcher/sections.d.ts +19 -0
- package/dist/src/ai/rules.d.ts +15 -0
- package/dist/src/ai/session-analyst.d.ts +11 -0
- package/dist/src/ai/task-agent.d.ts +28 -0
- package/dist/src/ai/tester.d.ts +103 -0
- package/dist/src/ai/tools.d.ts +41 -0
- 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/context-aria-command.d.ts +6 -0
- package/dist/src/commands/context-command.d.ts +11 -0
- 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/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/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/learn-command.d.ts +7 -0
- 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 +8 -0
- package/dist/src/components/AddRule.d.ts +9 -0
- package/dist/src/components/App.d.ts +9 -0
- 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 +251 -0
- package/dist/src/execution-controller.d.ts +25 -0
- package/dist/src/experience-tracker.d.ts +107 -0
- package/dist/src/experience-tracker.js +2 -1
- package/dist/src/explorbot.d.ts +107 -0
- package/dist/src/explorer.d.ts +140 -0
- package/dist/src/explorer.js +13 -9
- 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 +9 -2
- 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 +185 -0
- package/dist/src/state-manager.js +0 -7
- 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 +20 -0
- package/dist/src/utils/browser-errors.d.ts +8 -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 +25 -0
- 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 +124 -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-parser.d.ts +17 -0
- package/dist/src/utils/markdown-query.d.ts +40 -0
- 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 +6 -0
- 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 +3 -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 +44 -0
- package/dist/src/utils/xpath.d.ts +17 -0
- package/package.json +10 -25
- package/src/action-result.ts +22 -7
- package/src/action.ts +12 -5
- package/src/ai/provider.ts +10 -3
- package/src/experience-tracker.ts +2 -1
- package/src/explorer.ts +14 -9
- package/src/index.ts +9 -0
- package/src/knowledge-tracker.ts +7 -1
- package/src/observability.ts +2 -1
- package/src/state-manager.ts +0 -8
- package/src/utils/secrets.ts +29 -0
- package/src/index.tsx +0 -62
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
export type InputCallback = (prompt: string) => Promise<string | null>;
|
|
3
|
+
export declare class ExecutionController extends EventEmitter {
|
|
4
|
+
static instance: ExecutionController;
|
|
5
|
+
interrupted: boolean;
|
|
6
|
+
inputCallback: InputCallback | null;
|
|
7
|
+
interruptResolvers: Array<() => void>;
|
|
8
|
+
abortController: AbortController | null;
|
|
9
|
+
awaitingInput: boolean;
|
|
10
|
+
constructor();
|
|
11
|
+
static getInstance(): ExecutionController;
|
|
12
|
+
setInputCallback(callback: InputCallback): void;
|
|
13
|
+
startExecution(): void;
|
|
14
|
+
getAbortSignal(): AbortSignal | undefined;
|
|
15
|
+
interrupt(): void;
|
|
16
|
+
isAwaitingInput(): boolean;
|
|
17
|
+
isInterrupted(): boolean;
|
|
18
|
+
waitForInterrupt(): Promise<void>;
|
|
19
|
+
checkInterrupt(): Promise<string | null>;
|
|
20
|
+
handleInterrupt(prompt?: string): Promise<string | null>;
|
|
21
|
+
requestInput(prompt: string): Promise<string | null>;
|
|
22
|
+
readlineInput(prompt: string): Promise<string | null>;
|
|
23
|
+
reset(): void;
|
|
24
|
+
}
|
|
25
|
+
export declare const executionController: ExecutionController;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { ActionResult } from './action-result.js';
|
|
2
|
+
import { KnowledgeTracker } from './knowledge-tracker.js';
|
|
3
|
+
export declare const RECENT_WINDOW_DAYS = 30;
|
|
4
|
+
/**
|
|
5
|
+
* Stores and reads per-page experience files (`./experience/<stateHash>.md`).
|
|
6
|
+
*
|
|
7
|
+
* Two writers, two contracts:
|
|
8
|
+
*
|
|
9
|
+
* writeFlow(state, body, relatedUrls?) — caller hands in a fully-formatted
|
|
10
|
+
* `## FLOW: <imperative title>` block (multi-step,
|
|
11
|
+
* `*` bullets + optional ```js``` + `>` discovery,
|
|
12
|
+
* ends with `---`). Tracker dedups + prepends.
|
|
13
|
+
* writeAction(state, ActionInput) — `## ACTION: <imperative title>`, single-step,
|
|
14
|
+
* optional `Solution:` line + one ```js``` code block.
|
|
15
|
+
* Title normalized via normalizeTitle().
|
|
16
|
+
*
|
|
17
|
+
* - Always h2. Never h3 for FLOW/ACTION.
|
|
18
|
+
* - On read (getSuccessfulExperience), headings are rendered as
|
|
19
|
+
* `## HOW to <title> (multi-step|single-step)` so prompts get natural phrasing.
|
|
20
|
+
*/
|
|
21
|
+
export declare class ExperienceTracker {
|
|
22
|
+
experienceDir: string;
|
|
23
|
+
disabled: boolean;
|
|
24
|
+
knowledgeTracker: KnowledgeTracker;
|
|
25
|
+
constructor(options?: {
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
});
|
|
28
|
+
getExperienceDirectories(): string[];
|
|
29
|
+
ensureDirectory(dir: string): void;
|
|
30
|
+
readExperienceFile(stateHash: string): {
|
|
31
|
+
content: string;
|
|
32
|
+
data: any;
|
|
33
|
+
};
|
|
34
|
+
writeExperienceFile(stateHash: string, content: string, frontmatter?: any): void;
|
|
35
|
+
hasRecentExperience(stateHash: string, prefix?: string): boolean;
|
|
36
|
+
getExperienceFilePath(stateHash: string): string;
|
|
37
|
+
ensureExperienceFile(state: ActionResult): string;
|
|
38
|
+
updateSummary(state: ActionResult, summary: string): void;
|
|
39
|
+
isWritingDisabled(state: ActionResult): boolean;
|
|
40
|
+
writeAction(state: ActionResult, action: ActionInput): void;
|
|
41
|
+
writeFlow(state: ActionResult, body: string, relatedUrls?: string[]): void;
|
|
42
|
+
getAllExperience(): ExperienceFile[];
|
|
43
|
+
getRelevantExperience(state: ActionResult, options?: {
|
|
44
|
+
includeDescendantExperience?: boolean;
|
|
45
|
+
}): ExperienceFile[];
|
|
46
|
+
/**
|
|
47
|
+
* Clean up experience tracker (for testing)
|
|
48
|
+
*/
|
|
49
|
+
cleanup(): void;
|
|
50
|
+
getSuccessfulExperience(state: ActionResult, options?: {
|
|
51
|
+
includeDescendants?: boolean;
|
|
52
|
+
stripCode?: boolean;
|
|
53
|
+
}): string[];
|
|
54
|
+
getExperienceTableOfContents(state: ActionResult, options?: {
|
|
55
|
+
includeDescendantExperience?: boolean;
|
|
56
|
+
}): ExperienceTocEntry[];
|
|
57
|
+
getExperienceSection(fileTag: string, sectionIndex: number, state: ActionResult, options?: {
|
|
58
|
+
includeDescendantExperience?: boolean;
|
|
59
|
+
}): {
|
|
60
|
+
title: string;
|
|
61
|
+
url: string;
|
|
62
|
+
content: string;
|
|
63
|
+
} | null;
|
|
64
|
+
findExperienceFileByHash(fileHash: string): string | null;
|
|
65
|
+
listAllExperienceToc(filter?: string, options?: {
|
|
66
|
+
recency?: 'recent' | 'old';
|
|
67
|
+
}): ExperienceTocEntry[];
|
|
68
|
+
getExperienceSectionByTag(fileTag: string, sectionIndex: number, filter?: string): {
|
|
69
|
+
title: string;
|
|
70
|
+
url: string;
|
|
71
|
+
content: string;
|
|
72
|
+
fileHash: string;
|
|
73
|
+
} | null;
|
|
74
|
+
}
|
|
75
|
+
export declare function renderExperienceToc(toc: ExperienceTocEntry[]): string;
|
|
76
|
+
export interface ExperienceFile {
|
|
77
|
+
filePath: string;
|
|
78
|
+
data: {
|
|
79
|
+
url?: string;
|
|
80
|
+
title?: string;
|
|
81
|
+
[key: string]: any;
|
|
82
|
+
};
|
|
83
|
+
content: string;
|
|
84
|
+
mtime: Date;
|
|
85
|
+
}
|
|
86
|
+
export interface ActionInput {
|
|
87
|
+
title: string;
|
|
88
|
+
code: string;
|
|
89
|
+
explanation?: string;
|
|
90
|
+
}
|
|
91
|
+
export interface SessionStep {
|
|
92
|
+
message: string;
|
|
93
|
+
status: 'passed' | 'failed' | 'neutral';
|
|
94
|
+
tool?: string;
|
|
95
|
+
code?: string;
|
|
96
|
+
discovery?: string;
|
|
97
|
+
}
|
|
98
|
+
export interface ExperienceTocEntry {
|
|
99
|
+
fileTag: string;
|
|
100
|
+
fileHash: string;
|
|
101
|
+
url: string;
|
|
102
|
+
sections: {
|
|
103
|
+
index: number;
|
|
104
|
+
level: 2 | 3;
|
|
105
|
+
title: string;
|
|
106
|
+
}[];
|
|
107
|
+
}
|
|
@@ -6,6 +6,7 @@ import { ConfigParser } from './config.js';
|
|
|
6
6
|
import { KnowledgeTracker } from './knowledge-tracker.js';
|
|
7
7
|
import { createDebug, tag } from './utils/logger.js';
|
|
8
8
|
import { mdq } from './utils/markdown-query.js';
|
|
9
|
+
import { redactSecrets } from './utils/secrets.js';
|
|
9
10
|
import { isNonReusableCode } from "./utils/step-analyzer.js";
|
|
10
11
|
import { extractStatePath } from './utils/url-matcher.js';
|
|
11
12
|
const debugLog = createDebug('explorbot:experience');
|
|
@@ -93,7 +94,7 @@ export class ExperienceTracker {
|
|
|
93
94
|
return;
|
|
94
95
|
}
|
|
95
96
|
const filePath = this.getExperienceFilePath(stateHash);
|
|
96
|
-
const fileContent = matter.stringify(content, frontmatter || {});
|
|
97
|
+
const fileContent = matter.stringify(redactSecrets(content), frontmatter || {});
|
|
97
98
|
writeFileSync(filePath, fileContent, 'utf8');
|
|
98
99
|
}
|
|
99
100
|
hasRecentExperience(stateHash, prefix = '') {
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { Captain } from './ai/captain.js';
|
|
2
|
+
import { Driller } from './ai/driller.js';
|
|
3
|
+
import { ExperienceCompactor } from './ai/experience-compactor.js';
|
|
4
|
+
import { Fisherman } from './ai/fisherman.js';
|
|
5
|
+
import { Historian } from './ai/historian.js';
|
|
6
|
+
import { Navigator } from './ai/navigator.js';
|
|
7
|
+
import { Pilot } from './ai/pilot.js';
|
|
8
|
+
import { Planner } from './ai/planner.js';
|
|
9
|
+
import { AIProvider } from './ai/provider.js';
|
|
10
|
+
import { Quartermaster } from './ai/quartermaster.js';
|
|
11
|
+
import { Rerunner } from './ai/rerunner.js';
|
|
12
|
+
import { Researcher } from './ai/researcher.js';
|
|
13
|
+
import { SessionAnalyst } from './ai/session-analyst.js';
|
|
14
|
+
import { Tester } from './ai/tester.js';
|
|
15
|
+
import type { ExplorbotConfig } from './config.js';
|
|
16
|
+
import { ConfigParser } from './config.js';
|
|
17
|
+
import { ExperienceTracker } from './experience-tracker.js';
|
|
18
|
+
import Explorer from './explorer.js';
|
|
19
|
+
import { KnowledgeTracker } from './knowledge-tracker.js';
|
|
20
|
+
import { WebPageState } from './state-manager.js';
|
|
21
|
+
import type { Suite } from './suite.js';
|
|
22
|
+
import { Plan, type Test } from './test-plan.js';
|
|
23
|
+
export interface ExplorBotOptions {
|
|
24
|
+
from?: string;
|
|
25
|
+
baseUrl?: string;
|
|
26
|
+
verbose?: boolean;
|
|
27
|
+
config?: string;
|
|
28
|
+
path?: string;
|
|
29
|
+
show?: boolean;
|
|
30
|
+
headless?: boolean;
|
|
31
|
+
incognito?: boolean;
|
|
32
|
+
session?: string;
|
|
33
|
+
}
|
|
34
|
+
export type UserResolveFunction = (error?: Error, showWelcome?: boolean) => Promise<string | null>;
|
|
35
|
+
export declare class ExplorBot {
|
|
36
|
+
configParser: ConfigParser;
|
|
37
|
+
explorer: Explorer;
|
|
38
|
+
provider: AIProvider;
|
|
39
|
+
config: ExplorbotConfig;
|
|
40
|
+
options: ExplorBotOptions;
|
|
41
|
+
userResolveFn: UserResolveFunction | null;
|
|
42
|
+
needsInput: boolean;
|
|
43
|
+
currentPlan?: Plan;
|
|
44
|
+
planFeature?: string;
|
|
45
|
+
lastPlanError: Error | null;
|
|
46
|
+
lastSavedPlanPath: string | null;
|
|
47
|
+
agents: Record<string, any>;
|
|
48
|
+
sessionPlans: Plan[];
|
|
49
|
+
lastReportedTestCount: number;
|
|
50
|
+
constructor(options?: ExplorBotOptions);
|
|
51
|
+
get isExploring(): boolean;
|
|
52
|
+
setUserResolve(fn: UserResolveFunction): void;
|
|
53
|
+
start(): Promise<void>;
|
|
54
|
+
startProviderOnly(): Promise<void>;
|
|
55
|
+
stop(): Promise<void>;
|
|
56
|
+
visitInitialState(): Promise<void>;
|
|
57
|
+
visit(url: string): Promise<void>;
|
|
58
|
+
openFreshTab(): Promise<void>;
|
|
59
|
+
getCurrentState(): WebPageState | null;
|
|
60
|
+
getExplorer(): Explorer;
|
|
61
|
+
getKnowledgeTracker(): KnowledgeTracker;
|
|
62
|
+
getExperienceTracker(): ExperienceTracker;
|
|
63
|
+
getConfig(): ExplorbotConfig;
|
|
64
|
+
getOptions(): ExplorBotOptions;
|
|
65
|
+
isReady(): boolean;
|
|
66
|
+
getConfigParser(): ConfigParser;
|
|
67
|
+
getProvider(): AIProvider;
|
|
68
|
+
createAgent<T>(factory: (deps: {
|
|
69
|
+
explorer: Explorer;
|
|
70
|
+
ai: AIProvider;
|
|
71
|
+
config: ExplorbotConfig;
|
|
72
|
+
}) => T): T;
|
|
73
|
+
agentResearcher(): Researcher;
|
|
74
|
+
agentNavigator(): Navigator;
|
|
75
|
+
agentPlanner(): Planner;
|
|
76
|
+
agentPilot(): Pilot;
|
|
77
|
+
agentTester(): Tester;
|
|
78
|
+
agentCaptain(): Captain;
|
|
79
|
+
agentExperienceCompactor(): ExperienceCompactor;
|
|
80
|
+
agentQuartermaster(): Quartermaster | null;
|
|
81
|
+
agentHistorian(): Historian;
|
|
82
|
+
agentRerunner(): Rerunner;
|
|
83
|
+
agentDriller(): Driller;
|
|
84
|
+
agentSessionAnalyst(): SessionAnalyst;
|
|
85
|
+
agentFisherman(): Fisherman | null;
|
|
86
|
+
getCurrentPlan(): Plan | undefined;
|
|
87
|
+
getSuite(): Suite | null;
|
|
88
|
+
getPlanFeature(): string | undefined;
|
|
89
|
+
clearPlan(): void;
|
|
90
|
+
plan(feature?: string, opts?: {
|
|
91
|
+
fresh?: boolean;
|
|
92
|
+
style?: string;
|
|
93
|
+
extend?: Plan;
|
|
94
|
+
completedPlans?: Plan[];
|
|
95
|
+
noSave?: boolean;
|
|
96
|
+
}): Promise<Plan>;
|
|
97
|
+
getPlansDir(): string;
|
|
98
|
+
savePlan(filename?: string): string | null;
|
|
99
|
+
savePlans(plans: Plan[], filename?: string): string | null;
|
|
100
|
+
generatePlanFilename(feature?: string): string;
|
|
101
|
+
resolvePlanPath(filename: string): string;
|
|
102
|
+
loadPlan(filename: string): Plan;
|
|
103
|
+
loadPlans(filename: string): Plan[];
|
|
104
|
+
setCurrentPlan(plan?: Plan): void;
|
|
105
|
+
getSessionTests(): Test[];
|
|
106
|
+
printSessionAnalysis(): Promise<void>;
|
|
107
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import type { BrowserContextOptions } from 'playwright';
|
|
2
|
+
import { ActionResult } from './action-result.js';
|
|
3
|
+
import Action from './action.js';
|
|
4
|
+
import { AIProvider } from './ai/provider.js';
|
|
5
|
+
import { RequestStore } from './api/request-store.js';
|
|
6
|
+
import { XhrCapture } from './api/xhr-capture.js';
|
|
7
|
+
import type { ExplorbotConfig } from './config.js';
|
|
8
|
+
import type { UserResolveFunction } from './explorbot.js';
|
|
9
|
+
import { KnowledgeTracker } from './knowledge-tracker.js';
|
|
10
|
+
import { PlaywrightRecorder } from './playwright-recorder.js';
|
|
11
|
+
import { Reporter } from './reporter.js';
|
|
12
|
+
import { StateManager } from './state-manager.js';
|
|
13
|
+
import { Test } from './test-plan.js';
|
|
14
|
+
import { WebElement } from './utils/web-element.js';
|
|
15
|
+
declare global {
|
|
16
|
+
namespace NodeJS {
|
|
17
|
+
interface Global {
|
|
18
|
+
output_dir: string;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
declare namespace CodeceptJS {
|
|
23
|
+
interface I {
|
|
24
|
+
[key: string]: any;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
interface TabInfo {
|
|
28
|
+
url: string;
|
|
29
|
+
title: string;
|
|
30
|
+
}
|
|
31
|
+
interface BrowserExecutionErrorResult {
|
|
32
|
+
action: 'continue' | 'stop';
|
|
33
|
+
message: string;
|
|
34
|
+
recovered?: boolean;
|
|
35
|
+
}
|
|
36
|
+
declare class Explorer {
|
|
37
|
+
aiProvider: AIProvider;
|
|
38
|
+
playwrightHelper: any;
|
|
39
|
+
isStarted: boolean;
|
|
40
|
+
isSharedBrowser: boolean;
|
|
41
|
+
actor: CodeceptJS.I;
|
|
42
|
+
stateManager: StateManager;
|
|
43
|
+
knowledgeTracker: KnowledgeTracker;
|
|
44
|
+
config: ExplorbotConfig;
|
|
45
|
+
userResolveFn: UserResolveFunction | null;
|
|
46
|
+
options?: {
|
|
47
|
+
show?: boolean;
|
|
48
|
+
headless?: boolean;
|
|
49
|
+
incognito?: boolean;
|
|
50
|
+
session?: string;
|
|
51
|
+
};
|
|
52
|
+
reporter: Reporter;
|
|
53
|
+
otherTabs: TabInfo[];
|
|
54
|
+
_activeTest: Test | null;
|
|
55
|
+
xhrCapture: XhrCapture | null;
|
|
56
|
+
requestStore: RequestStore | null;
|
|
57
|
+
playwrightRecorder: PlaywrightRecorder;
|
|
58
|
+
observedTestPages: Set<any>;
|
|
59
|
+
testPageErrorHandler: ((error: Error) => void) | null;
|
|
60
|
+
testConsoleHandler: ((message: any) => void) | null;
|
|
61
|
+
testDialogHandler: ((dialog: any) => void) | null;
|
|
62
|
+
constructor(config: ExplorbotConfig, aiProvider: AIProvider, options?: {
|
|
63
|
+
show?: boolean;
|
|
64
|
+
headless?: boolean;
|
|
65
|
+
incognito?: boolean;
|
|
66
|
+
session?: string;
|
|
67
|
+
});
|
|
68
|
+
initializeContainer(): void;
|
|
69
|
+
convertToCodeceptConfig(config: ExplorbotConfig): any;
|
|
70
|
+
getConfig(): ExplorbotConfig;
|
|
71
|
+
getConfigPath(): string | null;
|
|
72
|
+
getAIProvider(): AIProvider;
|
|
73
|
+
getStateManager(): StateManager;
|
|
74
|
+
getCurrentUrl(): string;
|
|
75
|
+
getKnowledgeTracker(): KnowledgeTracker;
|
|
76
|
+
getReporter(): Reporter;
|
|
77
|
+
getRequestStore(): RequestStore | null;
|
|
78
|
+
extractCookies(): Promise<Record<string, string>>;
|
|
79
|
+
setupXhrCapture(reuseRequestStore?: boolean): void;
|
|
80
|
+
start(): Promise<any>;
|
|
81
|
+
connectOrLaunchBrowser(): Promise<void>;
|
|
82
|
+
createBrowserContextOptions(): BrowserContextOptions;
|
|
83
|
+
createAction(): Action;
|
|
84
|
+
runWithBrowserRecovery<T>(label: string, operation: () => Promise<T>): Promise<T>;
|
|
85
|
+
capturePageState(opts?: {
|
|
86
|
+
includeScreenshot?: boolean;
|
|
87
|
+
}): Promise<ActionResult>;
|
|
88
|
+
capturePageWithScreenshot(): Promise<ActionResult>;
|
|
89
|
+
executeAction(code: string): Promise<Action>;
|
|
90
|
+
attemptAction(code: string, originalMessage?: string, experience?: boolean): Promise<boolean>;
|
|
91
|
+
getPlaywrightRecorder(): PlaywrightRecorder;
|
|
92
|
+
visit(url: string): Promise<Action>;
|
|
93
|
+
visitOnce(url: string): Promise<Action>;
|
|
94
|
+
annotateElements(): Promise<WebElement[]>;
|
|
95
|
+
visuallyAnnotateElements(opts?: {
|
|
96
|
+
containers?: Array<{
|
|
97
|
+
css: string;
|
|
98
|
+
label: string;
|
|
99
|
+
}>;
|
|
100
|
+
}): Promise<number>;
|
|
101
|
+
getEidxInContainer(containerCss: string | null): Promise<string[]>;
|
|
102
|
+
getEidxByLocator(locator: string, container?: string | null): Promise<string | null>;
|
|
103
|
+
reload(): Promise<void>;
|
|
104
|
+
resolveBrowserUrl(url?: string): string | null;
|
|
105
|
+
isFatalBrowserError(error: unknown): boolean;
|
|
106
|
+
recoverFromBrowserError(): Promise<boolean>;
|
|
107
|
+
restartBrowser(): Promise<boolean>;
|
|
108
|
+
switchToMainFrame(): Promise<void>;
|
|
109
|
+
waitForPageReadiness(): Promise<boolean>;
|
|
110
|
+
isInsideIframe(): Promise<boolean>;
|
|
111
|
+
getCurrentIframeInfo(): string | null;
|
|
112
|
+
hasOtherTabs(): boolean;
|
|
113
|
+
getOtherTabsInfo(): TabInfo[];
|
|
114
|
+
clearOtherTabsInfo(): void;
|
|
115
|
+
setUserResolve(userResolveFn: UserResolveFunction): void;
|
|
116
|
+
listenToStateChanged(): void;
|
|
117
|
+
stop(): Promise<void>;
|
|
118
|
+
get activeTest(): Test | null;
|
|
119
|
+
startTest(test: Test): Promise<boolean>;
|
|
120
|
+
ensurePageAvailable(): Promise<boolean>;
|
|
121
|
+
ensureActiveTestPageAvailable(): Promise<boolean>;
|
|
122
|
+
handleExecutionError(error: unknown): Promise<BrowserExecutionErrorResult>;
|
|
123
|
+
watchActiveTestPage(page?: any): void;
|
|
124
|
+
stopTest(test: Test, meta?: Record<string, string>): Promise<void>;
|
|
125
|
+
unwatchActiveTestPages(): void;
|
|
126
|
+
hasPlaywrightLocator(locatorFn: (page: any) => any, opts?: {
|
|
127
|
+
multiple?: boolean;
|
|
128
|
+
contents?: boolean;
|
|
129
|
+
success?: (locator: any) => Promise<void> | void;
|
|
130
|
+
}): Promise<boolean>;
|
|
131
|
+
playwrightLocatorCount(locatorFn: (page: any) => any): Promise<number>;
|
|
132
|
+
bindFrameNavigated(page: any): void;
|
|
133
|
+
openFreshTab(): Promise<void>;
|
|
134
|
+
closeOtherTabs(): Promise<void>;
|
|
135
|
+
}
|
|
136
|
+
export declare function annotatePageElements(page: any): Promise<{
|
|
137
|
+
ariaSnapshot: string;
|
|
138
|
+
elements: WebElement[];
|
|
139
|
+
}>;
|
|
140
|
+
export default Explorer;
|
package/dist/src/explorer.js
CHANGED
|
@@ -629,17 +629,21 @@ class Explorer {
|
|
|
629
629
|
test.setActiveNoteScreenshot(lastScreenshot);
|
|
630
630
|
};
|
|
631
631
|
this.watchActiveTestPage();
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
codeceptjs.event.dispatcher.on('step.passed', (step) => stepHandler(step, 'passed'));
|
|
635
|
-
codeceptjs.event.dispatcher.on('step.failed', (step, error) => {
|
|
632
|
+
const onStepPassed = (step) => stepHandler(step, 'passed');
|
|
633
|
+
const onStepFailed = (step, error) => {
|
|
636
634
|
stepHandler(step, 'failed', error?.message || String(error), error?.stack);
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
codeceptjs.event.dispatcher.off('step.passed',
|
|
640
|
-
codeceptjs.event.dispatcher.off('step.failed',
|
|
635
|
+
};
|
|
636
|
+
const onTestAfter = () => {
|
|
637
|
+
codeceptjs.event.dispatcher.off('step.passed', onStepPassed);
|
|
638
|
+
codeceptjs.event.dispatcher.off('step.failed', onStepFailed);
|
|
639
|
+
codeceptjs.event.dispatcher.off('test.after', onTestAfter);
|
|
641
640
|
this.unwatchActiveTestPages();
|
|
642
|
-
}
|
|
641
|
+
};
|
|
642
|
+
codeceptjs.event.dispatcher.emit('test.before', codeceptjsTest);
|
|
643
|
+
codeceptjs.event.dispatcher.emit('test.start', codeceptjsTest);
|
|
644
|
+
codeceptjs.event.dispatcher.on('step.passed', onStepPassed);
|
|
645
|
+
codeceptjs.event.dispatcher.on('step.failed', onStepFailed);
|
|
646
|
+
codeceptjs.event.dispatcher.on('test.after', onTestAfter);
|
|
643
647
|
return true;
|
|
644
648
|
}
|
|
645
649
|
async ensurePageAvailable() {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { ExplorBot } from './explorbot.js';
|
|
2
|
+
export type { ExplorBotOptions, UserResolveFunction } from './explorbot.js';
|
|
3
|
+
export { Plan, Test, TestResult, TestStatus } from './test-plan.js';
|
|
4
|
+
export type { Note, StepData, TestResultType, TestStatusType } from './test-plan.js';
|
|
5
|
+
export type { Link, StateTransition, WebPageState } from './state-manager.js';
|
|
6
|
+
export type { AIConfig, ExplorbotConfig, PlaywrightConfig } from './config.js';
|
package/dist/src/index.js
CHANGED
|
@@ -1,55 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { addKnowledgeCommand } from './commands/add-knowledge.js';
|
|
4
|
-
import { cleanCommand } from './commands/clean.js';
|
|
5
|
-
import { exploreCommand } from './commands/explore.js';
|
|
6
|
-
import { initCommand } from './commands/init.js';
|
|
7
|
-
const program = new Command();
|
|
8
|
-
program
|
|
9
|
-
.name('explorbot')
|
|
10
|
-
.description('AI-powered web exploration tool')
|
|
11
|
-
.option('-f, --from <url>', 'Start exploration from a specific URL')
|
|
12
|
-
.option('-v, --verbose', 'Enable verbose logging')
|
|
13
|
-
.option('--debug', 'Enable debug logging (same as --verbose)')
|
|
14
|
-
.option('-c, --config <path>', 'Path to configuration file')
|
|
15
|
-
.option('-p, --path <path>', 'Working directory path')
|
|
16
|
-
.helpOption('-h, --help', 'Show this help message');
|
|
17
|
-
program
|
|
18
|
-
.command('clean')
|
|
19
|
-
.description('Clean up artifacts or experience folders')
|
|
20
|
-
.option('-t, --type <type>', 'Type of cleanup (artifacts|experience|all)', 'artifacts')
|
|
21
|
-
.option('-p, --path <path>', 'Custom path to clean')
|
|
22
|
-
.action(async (options, command) => {
|
|
23
|
-
const globalOptions = command.parent.opts();
|
|
24
|
-
const allOptions = { ...globalOptions, ...options };
|
|
25
|
-
await cleanCommand(allOptions);
|
|
26
|
-
});
|
|
27
|
-
program
|
|
28
|
-
.command('init')
|
|
29
|
-
.description('Initialize a new project with configuration')
|
|
30
|
-
.option('-c, --config-path <path>', 'Path for the config file', './explorbot.config.js')
|
|
31
|
-
.option('-f, --force', 'Overwrite existing config file', false)
|
|
32
|
-
.option('-p, --path <path>', 'Working directory for initialization')
|
|
33
|
-
.action(async (options, command) => {
|
|
34
|
-
const globalOptions = command.parent.opts();
|
|
35
|
-
const allOptions = { ...globalOptions, ...options };
|
|
36
|
-
await initCommand(allOptions);
|
|
37
|
-
});
|
|
38
|
-
program
|
|
39
|
-
.command('add-knowledge')
|
|
40
|
-
.alias('learn')
|
|
41
|
-
.description('Add knowledge for specific URLs')
|
|
42
|
-
.option('-p, --path <path>', 'Knowledge directory path')
|
|
43
|
-
.action(async (options) => {
|
|
44
|
-
await addKnowledgeCommand(options);
|
|
45
|
-
});
|
|
46
|
-
program.parse();
|
|
47
|
-
const options = program.opts();
|
|
48
|
-
const command = program.args[0];
|
|
49
|
-
if (command === 'clean' || command === 'init' || command === 'add-knowledge' || command === 'learn') {
|
|
50
|
-
// These commands are handled by their respective actions
|
|
51
|
-
}
|
|
52
|
-
else {
|
|
53
|
-
// Default to explore command
|
|
54
|
-
exploreCommand(options);
|
|
55
|
-
}
|
|
1
|
+
export { ExplorBot } from "./explorbot.js";
|
|
2
|
+
export { Plan, Test, TestResult, TestStatus } from "./test-plan.js";
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ActionResult } from './action-result.js';
|
|
2
|
+
interface Knowledge {
|
|
3
|
+
filePath: string;
|
|
4
|
+
url: string;
|
|
5
|
+
content: string;
|
|
6
|
+
[key: string]: any;
|
|
7
|
+
}
|
|
8
|
+
export declare class KnowledgeTracker {
|
|
9
|
+
knowledgeDir: string;
|
|
10
|
+
knowledgeFiles: Knowledge[];
|
|
11
|
+
isLoaded: boolean;
|
|
12
|
+
constructor();
|
|
13
|
+
loadKnowledgeFiles(): void;
|
|
14
|
+
getRelevantKnowledge(state: ActionResult): Knowledge[];
|
|
15
|
+
addKnowledge(urlPattern: string, description: string): {
|
|
16
|
+
filename: string;
|
|
17
|
+
filePath: string;
|
|
18
|
+
isNewFile: boolean;
|
|
19
|
+
};
|
|
20
|
+
interpolateVars(content: string): string;
|
|
21
|
+
generateFilename(url: string): string;
|
|
22
|
+
getExistingUrls(): string[];
|
|
23
|
+
getKnowledgeForUrl(urlPattern: string): string[];
|
|
24
|
+
listAllKnowledge(): Array<{
|
|
25
|
+
url: string;
|
|
26
|
+
firstLine: string;
|
|
27
|
+
filePath: string;
|
|
28
|
+
}>;
|
|
29
|
+
getMatchingKnowledge(url: string): Knowledge[];
|
|
30
|
+
normalizeUrl(url: string): string;
|
|
31
|
+
getStateParameters(state: ActionResult, keys: string[]): Record<string, any>;
|
|
32
|
+
}
|
|
33
|
+
export {};
|
|
@@ -5,6 +5,7 @@ import { ActionResult } from './action-result.js';
|
|
|
5
5
|
import { ConfigParser } from './config.js';
|
|
6
6
|
import { getCliName } from "./utils/cli-name.js";
|
|
7
7
|
import { createDebug } from './utils/logger.js';
|
|
8
|
+
import { isSecretName, registerSecret } from './utils/secrets.js';
|
|
8
9
|
const debugLog = createDebug('explorbot:knowledge-tracker');
|
|
9
10
|
export class KnowledgeTracker {
|
|
10
11
|
knowledgeDir;
|
|
@@ -109,9 +110,15 @@ export class KnowledgeTracker {
|
|
|
109
110
|
return match;
|
|
110
111
|
const namespace = expr.slice(0, dotIndex);
|
|
111
112
|
const key = expr.slice(dotIndex + 1);
|
|
112
|
-
if (namespace === 'env')
|
|
113
|
-
|
|
113
|
+
if (namespace === 'env') {
|
|
114
|
+
const value = process.env[key] ?? '';
|
|
115
|
+
if (isSecretName(key))
|
|
116
|
+
registerSecret(value);
|
|
117
|
+
return value;
|
|
118
|
+
}
|
|
114
119
|
if (namespace === 'config') {
|
|
120
|
+
if (isSecretName(key))
|
|
121
|
+
return '';
|
|
115
122
|
const config = ConfigParser.getInstance().getConfig();
|
|
116
123
|
const value = key.split('.').reduce((obj, k) => obj?.[k], config);
|
|
117
124
|
if (value !== undefined && typeof value !== 'object')
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type Span } from '@opentelemetry/api';
|
|
2
|
+
type TelemetryMetadata = Record<string, unknown>;
|
|
3
|
+
export declare const Observability: {
|
|
4
|
+
run<T>(name: string, metadata: TelemetryMetadata, fn: () => Promise<T>): Promise<T>;
|
|
5
|
+
getTelemetry(): {
|
|
6
|
+
isEnabled: boolean;
|
|
7
|
+
functionId: string;
|
|
8
|
+
metadata: Record<string, unknown>;
|
|
9
|
+
};
|
|
10
|
+
isTracing(): boolean;
|
|
11
|
+
getSpan(): Span;
|
|
12
|
+
};
|
|
13
|
+
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { trace } from '@opentelemetry/api';
|
|
2
|
+
import { redactSecrets } from './utils/secrets.js';
|
|
2
3
|
let current = null;
|
|
3
4
|
export const Observability = {
|
|
4
5
|
async run(name, metadata, fn) {
|
|
@@ -70,7 +71,7 @@ function buildRootSpanAttributes(name, metadata) {
|
|
|
70
71
|
attributes['langfuse.trace.tags'] = metadata.tags;
|
|
71
72
|
}
|
|
72
73
|
if (metadata.input !== undefined) {
|
|
73
|
-
attributes['langfuse.trace.input'] = JSON.stringify(metadata.input);
|
|
74
|
+
attributes['langfuse.trace.input'] = redactSecrets(JSON.stringify(metadata.input));
|
|
74
75
|
}
|
|
75
76
|
return attributes;
|
|
76
77
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface TraceCall {
|
|
2
|
+
class: string;
|
|
3
|
+
method: string;
|
|
4
|
+
params: Record<string, any>;
|
|
5
|
+
}
|
|
6
|
+
export interface VerificationStep {
|
|
7
|
+
name: string;
|
|
8
|
+
args: any[];
|
|
9
|
+
}
|
|
10
|
+
export declare class PlaywrightRecorder {
|
|
11
|
+
context: any;
|
|
12
|
+
tracing: any;
|
|
13
|
+
active: boolean;
|
|
14
|
+
nextGroupId: number;
|
|
15
|
+
verifications: VerificationStep[];
|
|
16
|
+
recordVerification(steps: VerificationStep[]): void;
|
|
17
|
+
drainVerifications(): VerificationStep[];
|
|
18
|
+
start(browserContext: any): Promise<void>;
|
|
19
|
+
beginAction(title: string): Promise<string | null>;
|
|
20
|
+
endAction(): Promise<void>;
|
|
21
|
+
exportChunk(): Promise<Map<string, TraceCall[]>>;
|
|
22
|
+
stop(): Promise<void>;
|
|
23
|
+
isActive(): boolean;
|
|
24
|
+
}
|
|
25
|
+
declare function parseTrace(ndjson: string): Map<string, TraceCall[]>;
|
|
26
|
+
export declare function renderCall(call: TraceCall): string;
|
|
27
|
+
export declare function renderAssertion(assertion: {
|
|
28
|
+
name: string;
|
|
29
|
+
args: any[];
|
|
30
|
+
}): string;
|
|
31
|
+
export { parseTrace };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Client } from '@testomatio/reporter';
|
|
2
|
+
import type { Step } from '@testomatio/reporter/types/types.js';
|
|
3
|
+
import type { ReporterConfig } from './config.js';
|
|
4
|
+
import type { StateManager } from './state-manager.js';
|
|
5
|
+
import { Test } from './test-plan.js';
|
|
6
|
+
export type ReporterMeta = Record<string, string | undefined>;
|
|
7
|
+
export interface ReporterStep {
|
|
8
|
+
title: string;
|
|
9
|
+
status: 'passed' | 'failed';
|
|
10
|
+
code: string[];
|
|
11
|
+
discovery?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare class Reporter {
|
|
14
|
+
client: Client;
|
|
15
|
+
isRunStarted: boolean;
|
|
16
|
+
reporterEnabled: boolean;
|
|
17
|
+
stateManager?: StateManager;
|
|
18
|
+
constructor(config?: ReporterConfig, stateManager?: StateManager);
|
|
19
|
+
buildTitle(): string;
|
|
20
|
+
static resolveEnabled(config?: ReporterConfig): boolean;
|
|
21
|
+
configureHtmlPipe(): void;
|
|
22
|
+
configureMarkdownPipe(): void;
|
|
23
|
+
configureRunGroup(runGroup: string | null | undefined): void;
|
|
24
|
+
startRun(): Promise<void>;
|
|
25
|
+
reportTestStart(test: Test): Promise<void>;
|
|
26
|
+
combineStepsAndNotes(test: Test, lastScreenshotFile?: string): Step[];
|
|
27
|
+
buildVerificationStep(test: Test, lastScreenshotFile?: string): Step | undefined;
|
|
28
|
+
reportTest(test: Test, meta?: ReporterMeta): Promise<void>;
|
|
29
|
+
finishRun(): Promise<void>;
|
|
30
|
+
isEnabled(): boolean;
|
|
31
|
+
setRunDescription(text: string): Promise<void>;
|
|
32
|
+
extractLastNoteMessage(test: Test): string;
|
|
33
|
+
reportSteps(test: Test, steps: ReporterStep[]): Promise<void>;
|
|
34
|
+
}
|