explorbot 0.1.31 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -14
- package/bin/explorbot-cli.ts +4 -3
- package/boat/doc-collector/src/ai/documentarian.ts +22 -27
- package/boat/doc-collector/src/ai/tools.ts +67 -10
- package/boat/doc-collector/src/docbot.ts +28 -7
- package/boat/doc-collector/src/docs-renderer.ts +19 -24
- package/boat/doc-collector/src/screenshots.ts +33 -1
- package/boat/doc-collector/src/state-diagram.ts +281 -0
- package/dist/bin/explorbot-cli.js +3 -3
- package/dist/boat/doc-collector/src/ai/documentarian.js +16 -6
- package/dist/boat/doc-collector/src/ai/tools.js +47 -10
- package/dist/boat/doc-collector/src/docbot.js +25 -6
- package/dist/boat/doc-collector/src/docs-renderer.js +18 -3
- package/dist/boat/doc-collector/src/screenshots.js +29 -0
- package/dist/boat/doc-collector/src/state-diagram.js +200 -0
- package/dist/package.json +8 -6
- package/dist/src/action-result.d.ts +131 -0
- package/dist/src/action-result.js +82 -159
- package/dist/src/action.d.ts +43 -0
- package/dist/src/action.js +18 -106
- package/dist/src/activity.d.ts +26 -0
- package/dist/src/ai/agent.d.ts +3 -0
- package/dist/src/ai/captain/file-tools.d.ts +28 -0
- package/dist/src/ai/captain/idle-mode.d.ts +11 -0
- package/dist/src/ai/captain/mixin.d.ts +10 -0
- package/dist/src/ai/captain/test-mode.d.ts +13 -0
- package/dist/src/ai/captain/web-mode.d.ts +13 -0
- package/dist/src/ai/captain/web-mode.js +0 -7
- package/dist/src/ai/captain.d.ts +141 -0
- package/dist/src/ai/captain.js +4 -19
- package/dist/src/ai/conversation.d.ts +28 -0
- package/dist/src/ai/conversation.js +9 -28
- package/dist/src/ai/driller.d.ts +157 -0
- package/dist/src/ai/driller.js +3 -12
- package/dist/src/ai/experience-compactor.d.ts +53 -0
- package/dist/src/ai/experience-compactor.js +16 -33
- package/dist/src/ai/fisherman-tools.d.ts +90 -0
- package/dist/src/ai/fisherman-tools.js +1 -1
- package/dist/src/ai/fisherman.d.ts +29 -0
- package/dist/src/ai/fisherman.js +0 -3
- package/dist/src/ai/historian/codeceptjs.d.ts +17 -0
- package/dist/src/ai/historian/codeceptjs.js +3 -2
- package/dist/src/ai/historian/experience.d.ts +40 -0
- package/dist/src/ai/historian/mixin.d.ts +2 -0
- package/dist/src/ai/historian/playwright.d.ts +22 -0
- package/dist/src/ai/historian/playwright.js +3 -2
- package/dist/src/ai/historian/screencast.d.ts +32 -0
- package/dist/src/ai/historian/utils.d.ts +3 -0
- package/dist/src/ai/historian/utils.js +0 -1
- package/dist/src/ai/historian.d.ts +109 -0
- package/dist/src/ai/historian.js +1 -5
- package/dist/src/ai/navigator.d.ts +54 -0
- package/dist/src/ai/navigator.js +11 -46
- package/dist/src/ai/pilot.d.ts +81 -0
- package/dist/src/ai/pilot.js +6 -17
- package/dist/src/ai/planner/session-dedup.d.ts +12 -0
- package/dist/src/ai/planner/styles.d.ts +6 -0
- package/dist/src/ai/planner/subpages.d.ts +35 -0
- package/dist/src/ai/planner.d.ts +79 -0
- package/dist/src/ai/planner.js +49 -37
- package/dist/src/ai/provider.d.ts +53 -0
- package/dist/src/ai/provider.js +78 -130
- package/dist/src/ai/quartermaster.d.ts +56 -0
- package/dist/src/ai/quartermaster.js +4 -10
- package/dist/src/ai/rerunner.d.ts +48 -0
- package/dist/src/ai/rerunner.js +14 -22
- package/dist/src/ai/researcher/cache.d.ts +6 -0
- package/dist/src/ai/researcher/cache.js +11 -18
- package/dist/src/ai/researcher/coordinates.d.ts +56 -0
- package/dist/src/ai/researcher/deep-analysis.d.ts +74 -0
- package/dist/src/ai/researcher/deep-analysis.js +3 -6
- package/dist/src/ai/researcher/fingerprint-worker.d.ts +1 -0
- package/dist/src/ai/researcher/focus.d.ts +8 -0
- package/dist/src/ai/researcher/locators.d.ts +36 -0
- package/dist/src/ai/researcher/mixin.d.ts +2 -0
- package/dist/src/ai/researcher/parser.d.ts +35 -0
- package/dist/src/ai/researcher/parser.js +1 -1
- package/dist/src/ai/researcher/research-result.d.ts +15 -0
- package/dist/src/ai/researcher/research-result.js +0 -19
- package/dist/src/ai/researcher/sections.d.ts +19 -0
- package/dist/src/ai/researcher/sections.js +5 -1
- package/dist/src/ai/researcher.js +12 -53
- package/dist/src/ai/rules.d.ts +16 -0
- package/dist/src/ai/rules.js +22 -15
- package/dist/src/ai/session-analyst.d.ts +11 -0
- package/dist/src/ai/session-analyst.js +8 -5
- package/dist/src/ai/task-agent.d.ts +28 -0
- package/dist/src/ai/task-agent.js +2 -27
- package/dist/src/ai/tester.d.ts +101 -0
- package/dist/src/ai/tester.js +10 -61
- package/dist/src/ai/tools.d.ts +52 -0
- package/dist/src/ai/tools.js +119 -101
- package/dist/src/api/api-client.d.ts +17 -0
- package/dist/src/api/request-result.d.ts +44 -0
- package/dist/src/api/request-store.d.ts +29 -0
- package/dist/src/api/spec-reader.d.ts +5 -0
- package/dist/src/api/xhr-capture.d.ts +10 -0
- package/dist/src/browser-server.d.ts +10 -0
- package/dist/src/command-handler.d.ts +68 -0
- package/dist/src/commands/add-rule-command.d.ts +11 -0
- package/dist/src/commands/base-command.d.ts +26 -0
- package/dist/src/commands/clean-command.d.ts +12 -0
- package/dist/src/commands/compact-command.d.ts +20 -0
- package/dist/src/commands/compact-command.js +6 -6
- package/dist/src/commands/context-aria-command.d.ts +6 -0
- package/dist/src/commands/context-command.d.ts +11 -0
- package/dist/src/commands/context-command.js +1 -1
- package/dist/src/commands/context-data-command.d.ts +6 -0
- package/dist/src/commands/context-experience-command.d.ts +6 -0
- package/dist/src/commands/context-html-command.d.ts +6 -0
- package/dist/src/commands/context-knowledge-command.d.ts +6 -0
- package/dist/src/commands/context-knowledge-command.js +1 -1
- package/dist/src/commands/debug-command.d.ts +6 -0
- package/dist/src/commands/drill-command.d.ts +10 -0
- package/dist/src/commands/exit-command.d.ts +7 -0
- package/dist/src/commands/experience-command.d.ts +15 -0
- package/dist/src/commands/experience-command.js +1 -1
- package/dist/src/commands/explore-command.d.ts +51 -0
- package/dist/src/commands/freesail-command.d.ts +12 -0
- package/dist/src/commands/help-command.d.ts +6 -0
- package/dist/src/commands/index.d.ts +4 -0
- package/dist/src/commands/init-command.d.ts +7 -0
- package/dist/src/commands/knows-command.d.ts +10 -0
- package/dist/src/commands/knows-command.js +1 -1
- package/dist/src/commands/learn-command.d.ts +7 -0
- package/dist/src/commands/learn-command.js +3 -1
- package/dist/src/commands/navigate-command.d.ts +7 -0
- package/dist/src/commands/path-command.d.ts +10 -0
- package/dist/src/commands/plan-clear-command.d.ts +7 -0
- package/dist/src/commands/plan-command.d.ts +14 -0
- package/dist/src/commands/plan-edit-command.d.ts +7 -0
- package/dist/src/commands/plan-load-command.d.ts +7 -0
- package/dist/src/commands/plan-reload-command.d.ts +7 -0
- package/dist/src/commands/plan-save-command.d.ts +7 -0
- package/dist/src/commands/plans-command.d.ts +21 -0
- package/dist/src/commands/rerun-command.d.ts +7 -0
- package/dist/src/commands/research-command.d.ts +11 -0
- package/dist/src/commands/runs-command.d.ts +7 -0
- package/dist/src/commands/start-command.d.ts +7 -0
- package/dist/src/commands/status-command.d.ts +6 -0
- package/dist/src/commands/test-command.d.ts +11 -0
- package/dist/src/components/ActivityPane.d.ts +6 -0
- package/dist/src/components/AddKnowledge.d.ts +10 -0
- package/dist/src/components/AddKnowledge.js +3 -7
- package/dist/src/components/AddRule.d.ts +9 -0
- package/dist/src/components/App.d.ts +9 -0
- package/dist/src/components/App.js +2 -2
- package/dist/src/components/Autocomplete.d.ts +3 -0
- package/dist/src/components/InputPane.d.ts +13 -0
- package/dist/src/components/InputReadline.d.ts +17 -0
- package/dist/src/components/LogPane.d.ts +6 -0
- package/dist/src/components/PlanEditor.d.ts +9 -0
- package/dist/src/components/PlanPane.d.ts +13 -0
- package/dist/src/components/SessionTimer.d.ts +6 -0
- package/dist/src/components/StateTransitionPane.d.ts +8 -0
- package/dist/src/components/StatusPane.d.ts +4 -0
- package/dist/src/components/TaskPane.d.ts +9 -0
- package/dist/src/components/Welcome.d.ts +3 -0
- package/dist/src/components/WelcomeChecklist.d.ts +9 -0
- package/dist/src/components/WelcomeCommands.d.ts +6 -0
- package/dist/src/components/autocomplete-store.d.ts +10 -0
- package/dist/src/components/parse-keypress.d.ts +12 -0
- package/dist/src/config.d.ts +253 -0
- package/dist/src/config.js +12 -0
- package/dist/src/execution-controller.d.ts +25 -0
- package/dist/src/experience-tracker.d.ts +112 -0
- package/dist/src/experience-tracker.js +83 -155
- package/dist/src/explorbot.d.ts +106 -0
- package/dist/src/explorbot.js +17 -51
- package/dist/src/explorer.d.ts +129 -0
- package/dist/src/explorer.js +31 -77
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.js +2 -55
- package/dist/src/knowledge-tracker.d.ts +33 -0
- package/dist/src/knowledge-tracker.js +47 -47
- package/dist/src/observability.d.ts +13 -0
- package/dist/src/observability.js +2 -1
- package/dist/src/playwright-recorder.d.ts +31 -0
- package/dist/src/reporter.d.ts +34 -0
- package/dist/src/state-manager.d.ts +160 -0
- package/dist/src/state-manager.js +10 -136
- package/dist/src/stats.d.ts +24 -0
- package/dist/src/suite.d.ts +24 -0
- package/dist/src/test-plan.d.ts +166 -0
- package/dist/src/utils/aria.d.ts +25 -0
- package/dist/src/utils/aria.js +4 -1
- package/dist/src/utils/browser-errors.d.ts +8 -0
- package/dist/src/utils/cache.d.ts +15 -0
- package/dist/src/utils/cache.js +34 -0
- package/dist/src/utils/cli-name.d.ts +1 -0
- package/dist/src/utils/code-extractor.d.ts +1 -0
- package/dist/src/utils/context-formatter.d.ts +31 -0
- package/dist/src/utils/context-formatter.js +15 -27
- package/dist/src/utils/error-page.d.ts +12 -0
- package/dist/src/utils/expandable.d.ts +4 -0
- package/dist/src/utils/hooks-runner.d.ts +15 -0
- package/dist/src/utils/html-diff.d.ts +19 -0
- package/dist/src/utils/html.d.ts +129 -0
- package/dist/src/utils/html.js +71 -0
- package/dist/src/utils/log-filters.d.ts +6 -0
- package/dist/src/utils/logger.d.ts +35 -0
- package/dist/src/utils/loop.d.ts +35 -0
- package/dist/src/utils/markdown-files.d.ts +10 -0
- package/dist/src/utils/markdown-files.js +21 -0
- package/dist/src/utils/markdown-parser.d.ts +17 -0
- package/dist/src/utils/markdown-query.d.ts +46 -0
- package/dist/src/utils/markdown-query.js +14 -1
- package/dist/src/utils/markdown-terminal.d.ts +1 -0
- package/dist/src/utils/next-steps.d.ts +11 -0
- package/dist/src/utils/page-readiness.d.ts +7 -0
- package/dist/src/utils/page-readiness.js +1 -1
- package/dist/src/utils/research-parser.d.ts +1 -0
- package/dist/src/utils/retry.d.ts +8 -0
- package/dist/src/utils/rules-loader.d.ts +12 -0
- package/dist/src/utils/secrets.d.ts +4 -0
- package/dist/src/utils/secrets.js +28 -0
- package/dist/src/utils/step-analyzer.d.ts +11 -0
- package/dist/src/utils/strings.d.ts +5 -0
- package/dist/src/utils/strings.js +10 -0
- package/dist/src/utils/test-files.d.ts +3 -0
- package/dist/src/utils/test-plan-markdown.d.ts +9 -0
- package/dist/src/utils/throttle.d.ts +2 -0
- package/dist/src/utils/unique-names.d.ts +2 -0
- package/dist/src/utils/url-matcher.d.ts +6 -0
- package/dist/src/utils/web-element.d.ts +45 -0
- package/dist/src/utils/web-element.js +3 -0
- package/dist/src/utils/web-sandbox.d.ts +4 -0
- package/dist/src/utils/web-sandbox.js +37 -0
- package/dist/src/utils/xpath.d.ts +17 -0
- package/package.json +8 -6
- package/src/action-result.ts +80 -168
- package/src/action.ts +16 -123
- package/src/ai/captain/web-mode.ts +0 -7
- package/src/ai/captain.ts +5 -17
- package/src/ai/conversation.ts +9 -32
- package/src/ai/driller.ts +3 -16
- package/src/ai/experience-compactor.ts +16 -35
- package/src/ai/fisherman-tools.ts +1 -1
- package/src/ai/fisherman.ts +0 -4
- package/src/ai/historian/codeceptjs.ts +4 -2
- package/src/ai/historian/playwright.ts +4 -2
- package/src/ai/historian/utils.ts +0 -1
- package/src/ai/historian.ts +4 -7
- package/src/ai/navigator.ts +13 -49
- package/src/ai/pilot.ts +6 -16
- package/src/ai/planner.ts +56 -44
- package/src/ai/provider.ts +86 -139
- package/src/ai/quartermaster.ts +34 -41
- package/src/ai/rerunner.ts +17 -21
- package/src/ai/researcher/cache.ts +10 -16
- package/src/ai/researcher/deep-analysis.ts +3 -6
- package/src/ai/researcher/parser.ts +1 -1
- package/src/ai/researcher/research-result.ts +0 -18
- package/src/ai/researcher/sections.ts +5 -1
- package/src/ai/researcher.ts +11 -59
- package/src/ai/rules.ts +24 -13
- package/src/ai/session-analyst.ts +8 -5
- package/src/ai/task-agent.ts +3 -30
- package/src/ai/tester.ts +12 -73
- package/src/ai/tools.ts +119 -106
- package/src/commands/compact-command.ts +7 -8
- package/src/commands/context-command.ts +1 -1
- package/src/commands/context-knowledge-command.ts +1 -1
- package/src/commands/experience-command.ts +1 -1
- package/src/commands/knows-command.ts +1 -1
- package/src/commands/learn-command.ts +3 -1
- package/src/components/AddKnowledge.tsx +5 -7
- package/src/components/App.tsx +2 -2
- package/src/config.ts +12 -0
- package/src/experience-tracker.ts +90 -152
- package/src/explorbot.ts +17 -51
- package/src/explorer.ts +34 -81
- package/src/index.ts +9 -0
- package/src/knowledge-tracker.ts +49 -50
- package/src/observability.ts +2 -1
- package/src/state-manager.ts +15 -164
- package/src/utils/aria.ts +11 -2
- package/src/utils/cache.ts +40 -0
- package/src/utils/context-formatter.ts +12 -15
- package/src/utils/html.ts +79 -0
- package/src/utils/markdown-files.ts +30 -0
- package/src/utils/markdown-query.ts +15 -1
- package/src/utils/page-readiness.ts +1 -1
- package/src/utils/secrets.ts +28 -0
- package/src/utils/strings.ts +12 -0
- package/src/utils/web-element.ts +4 -0
- package/src/utils/web-sandbox.ts +43 -0
- package/src/index.tsx +0 -62
|
@@ -0,0 +1,129 @@
|
|
|
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 { ExperienceTracker } from './experience-tracker.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
|
+
options?: {
|
|
46
|
+
show?: boolean;
|
|
47
|
+
headless?: boolean;
|
|
48
|
+
incognito?: boolean;
|
|
49
|
+
session?: string;
|
|
50
|
+
};
|
|
51
|
+
reporter: Reporter;
|
|
52
|
+
otherTabs: TabInfo[];
|
|
53
|
+
_activeTest: Test | null;
|
|
54
|
+
xhrCapture: XhrCapture | null;
|
|
55
|
+
requestStore: RequestStore | null;
|
|
56
|
+
playwrightRecorder: PlaywrightRecorder;
|
|
57
|
+
observedTestPages: Set<any>;
|
|
58
|
+
testPageErrorHandler: ((error: Error) => void) | null;
|
|
59
|
+
testConsoleHandler: ((message: any) => void) | null;
|
|
60
|
+
testDialogHandler: ((dialog: any) => void) | null;
|
|
61
|
+
constructor(config: ExplorbotConfig, aiProvider: AIProvider, options: {
|
|
62
|
+
show?: boolean;
|
|
63
|
+
headless?: boolean;
|
|
64
|
+
incognito?: boolean;
|
|
65
|
+
session?: string;
|
|
66
|
+
} | undefined, experienceTracker: ExperienceTracker, knowledgeTracker: KnowledgeTracker);
|
|
67
|
+
initializeContainer(): void;
|
|
68
|
+
convertToCodeceptConfig(config: ExplorbotConfig): any;
|
|
69
|
+
getConfig(): ExplorbotConfig;
|
|
70
|
+
getAIProvider(): AIProvider;
|
|
71
|
+
getStateManager(): StateManager;
|
|
72
|
+
getKnowledgeTracker(): KnowledgeTracker;
|
|
73
|
+
getReporter(): Reporter;
|
|
74
|
+
getRequestStore(): RequestStore | null;
|
|
75
|
+
extractCookies(): Promise<Record<string, string>>;
|
|
76
|
+
setupXhrCapture(reuseRequestStore?: boolean): void;
|
|
77
|
+
start(): Promise<any>;
|
|
78
|
+
connectOrLaunchBrowser(): Promise<void>;
|
|
79
|
+
createBrowserContextOptions(): BrowserContextOptions;
|
|
80
|
+
createAction(): Action;
|
|
81
|
+
runWithBrowserRecovery<T>(label: string, operation: () => Promise<T>): Promise<T>;
|
|
82
|
+
capturePageState(opts?: {
|
|
83
|
+
includeScreenshot?: boolean;
|
|
84
|
+
}): Promise<ActionResult>;
|
|
85
|
+
capturePageWithScreenshot(): Promise<ActionResult>;
|
|
86
|
+
executeAction(code: string): Promise<Action>;
|
|
87
|
+
attemptAction(code: string, originalMessage?: string): Promise<boolean>;
|
|
88
|
+
getPlaywrightRecorder(): PlaywrightRecorder;
|
|
89
|
+
visit(url: string): Promise<Action>;
|
|
90
|
+
visitOnce(url: string): Promise<Action>;
|
|
91
|
+
annotateElements(): Promise<WebElement[]>;
|
|
92
|
+
visuallyAnnotateElements(opts?: {
|
|
93
|
+
containers?: Array<{
|
|
94
|
+
css: string;
|
|
95
|
+
label: string;
|
|
96
|
+
}>;
|
|
97
|
+
}): Promise<number>;
|
|
98
|
+
getEidxInContainer(containerCss: string | null): Promise<string[]>;
|
|
99
|
+
getEidxByLocator(locator: string, container?: string | null): Promise<string | null>;
|
|
100
|
+
resolveBrowserUrl(url?: string): string | null;
|
|
101
|
+
isFatalBrowserError(error: unknown): boolean;
|
|
102
|
+
recoverFromBrowserError(): Promise<boolean>;
|
|
103
|
+
restartBrowser(): Promise<boolean>;
|
|
104
|
+
switchToMainFrame(): Promise<void>;
|
|
105
|
+
waitForPageReadiness(): Promise<boolean>;
|
|
106
|
+
isInsideIframe(): Promise<boolean>;
|
|
107
|
+
getCurrentIframeInfo(): string | null;
|
|
108
|
+
hasOtherTabs(): boolean;
|
|
109
|
+
getOtherTabsInfo(): TabInfo[];
|
|
110
|
+
clearOtherTabsInfo(): void;
|
|
111
|
+
listenToStateChanged(): void;
|
|
112
|
+
stop(): Promise<void>;
|
|
113
|
+
get activeTest(): Test | null;
|
|
114
|
+
startTest(test: Test): Promise<boolean>;
|
|
115
|
+
ensurePageAvailable(): Promise<boolean>;
|
|
116
|
+
handleExecutionError(error: unknown): Promise<BrowserExecutionErrorResult>;
|
|
117
|
+
watchActiveTestPage(page?: any): void;
|
|
118
|
+
stopTest(test: Test, meta?: Record<string, string>): Promise<void>;
|
|
119
|
+
unwatchActiveTestPages(): void;
|
|
120
|
+
playwrightLocatorCount(locatorFn: (page: any) => any): Promise<number>;
|
|
121
|
+
bindFrameNavigated(page: any): void;
|
|
122
|
+
openFreshTab(): Promise<void>;
|
|
123
|
+
closeOtherTabs(): Promise<void>;
|
|
124
|
+
}
|
|
125
|
+
export declare function annotatePageElements(page: any): Promise<{
|
|
126
|
+
ariaSnapshot: string;
|
|
127
|
+
elements: WebElement[];
|
|
128
|
+
}>;
|
|
129
|
+
export default Explorer;
|
package/dist/src/explorer.js
CHANGED
|
@@ -12,15 +12,14 @@ import { visuallyAnnotateContainers } from "./ai/researcher/coordinates.js";
|
|
|
12
12
|
import { RequestStore } from "./api/request-store.js";
|
|
13
13
|
import { XhrCapture } from "./api/xhr-capture.js";
|
|
14
14
|
import { ConfigParser } from './config.js';
|
|
15
|
-
import { KnowledgeTracker } from './knowledge-tracker.js';
|
|
16
15
|
import { PlaywrightRecorder } from "./playwright-recorder.js";
|
|
17
16
|
import { Reporter } from "./reporter.js";
|
|
18
17
|
import { StateManager } from './state-manager.js';
|
|
19
18
|
import { TestResult } from "./test-plan.js";
|
|
20
|
-
import { BrowserRecoveryError, isFatalBrowserError, isNavigationTransitionError } from "./utils/browser-errors.js";
|
|
19
|
+
import { BrowserRecoveryError, browserErrorMessage, isFatalBrowserError, isNavigationTransitionError } from "./utils/browser-errors.js";
|
|
21
20
|
import { ELEMENT_EXTRACTION_CONFIG, getElementDataExtractorSource } from "./utils/html.js";
|
|
22
21
|
import { createDebug, log, tag } from './utils/logger.js';
|
|
23
|
-
import { waitForPageReadiness } from "./utils/page-readiness.js";
|
|
22
|
+
import { sleep, waitForPageReadiness } from "./utils/page-readiness.js";
|
|
24
23
|
import { WebElement } from "./utils/web-element.js";
|
|
25
24
|
const debugLog = createDebug('explorbot:explorer');
|
|
26
25
|
const RECOVERABLE_NAVIGATION_ERRORS = /net::ERR_ABORTED|page\.screenshot.*Timeout|waiting for fonts to load/i;
|
|
@@ -33,7 +32,6 @@ class Explorer {
|
|
|
33
32
|
stateManager;
|
|
34
33
|
knowledgeTracker;
|
|
35
34
|
config;
|
|
36
|
-
userResolveFn = null;
|
|
37
35
|
options;
|
|
38
36
|
reporter;
|
|
39
37
|
otherTabs = [];
|
|
@@ -45,21 +43,20 @@ class Explorer {
|
|
|
45
43
|
testPageErrorHandler = null;
|
|
46
44
|
testConsoleHandler = null;
|
|
47
45
|
testDialogHandler = null;
|
|
48
|
-
constructor(config, aiProvider, options) {
|
|
46
|
+
constructor(config, aiProvider, options, experienceTracker, knowledgeTracker) {
|
|
49
47
|
this.config = config;
|
|
50
48
|
this.aiProvider = aiProvider;
|
|
51
49
|
this.options = options;
|
|
52
50
|
this.initializeContainer();
|
|
53
|
-
this.
|
|
54
|
-
this.
|
|
51
|
+
this.knowledgeTracker = knowledgeTracker;
|
|
52
|
+
this.stateManager = new StateManager(experienceTracker, knowledgeTracker);
|
|
55
53
|
this.reporter = new Reporter(config.reporter, this.stateManager);
|
|
56
54
|
}
|
|
57
55
|
initializeContainer() {
|
|
58
56
|
try {
|
|
59
57
|
// Use project root for output directory, not current working directory
|
|
60
58
|
const configParser = ConfigParser.getInstance();
|
|
61
|
-
const
|
|
62
|
-
const projectRoot = configPath ? path.dirname(configPath) : process.cwd();
|
|
59
|
+
const projectRoot = configParser.getProjectRoot();
|
|
63
60
|
global.output_dir = path.join(projectRoot, 'output', 'states');
|
|
64
61
|
global.codecept_dir = projectRoot;
|
|
65
62
|
configParser.validateConfig(this.config);
|
|
@@ -113,31 +110,20 @@ class Explorer {
|
|
|
113
110
|
},
|
|
114
111
|
};
|
|
115
112
|
if (this.config.stepsFile) {
|
|
116
|
-
const
|
|
117
|
-
const projectRoot = configPath ? path.dirname(configPath) : process.cwd();
|
|
113
|
+
const projectRoot = ConfigParser.getInstance().getProjectRoot();
|
|
118
114
|
codeceptConfig.include = { I: path.resolve(projectRoot, this.config.stepsFile) };
|
|
119
115
|
}
|
|
120
116
|
return codeceptConfig;
|
|
121
117
|
}
|
|
122
118
|
getConfig() {
|
|
123
|
-
if (!this.config) {
|
|
124
|
-
throw new Error('Configuration not loaded. Call run() first.');
|
|
125
|
-
}
|
|
126
119
|
return this.config;
|
|
127
120
|
}
|
|
128
|
-
getConfigPath() {
|
|
129
|
-
const configParser = ConfigParser.getInstance();
|
|
130
|
-
return configParser.getConfigPath();
|
|
131
|
-
}
|
|
132
121
|
getAIProvider() {
|
|
133
122
|
return this.aiProvider;
|
|
134
123
|
}
|
|
135
124
|
getStateManager() {
|
|
136
125
|
return this.stateManager;
|
|
137
126
|
}
|
|
138
|
-
getCurrentUrl() {
|
|
139
|
-
return this.stateManager.getCurrentState().url || '?';
|
|
140
|
-
}
|
|
141
127
|
getKnowledgeTracker() {
|
|
142
128
|
return this.knowledgeTracker;
|
|
143
129
|
}
|
|
@@ -175,9 +161,6 @@ class Explorer {
|
|
|
175
161
|
if (this.isStarted) {
|
|
176
162
|
return;
|
|
177
163
|
}
|
|
178
|
-
if (!this.config) {
|
|
179
|
-
await this.initializeContainer();
|
|
180
|
-
}
|
|
181
164
|
await codeceptjs.recorder.start();
|
|
182
165
|
await codeceptjs.container.started(null);
|
|
183
166
|
storeListener();
|
|
@@ -294,8 +277,8 @@ class Explorer {
|
|
|
294
277
|
async executeAction(code) {
|
|
295
278
|
return this.runWithBrowserRecovery('executeAction', () => this.createAction().execute(code));
|
|
296
279
|
}
|
|
297
|
-
async attemptAction(code, originalMessage
|
|
298
|
-
return this.runWithBrowserRecovery('attemptAction', () => this.createAction().attempt(code, originalMessage
|
|
280
|
+
async attemptAction(code, originalMessage) {
|
|
281
|
+
return this.runWithBrowserRecovery('attemptAction', () => this.createAction().attempt(code, originalMessage));
|
|
299
282
|
}
|
|
300
283
|
getPlaywrightRecorder() {
|
|
301
284
|
return this.playwrightRecorder;
|
|
@@ -318,7 +301,7 @@ class Explorer {
|
|
|
318
301
|
await action.execute(`I.amOnPage(${serializedUrl})`);
|
|
319
302
|
}
|
|
320
303
|
catch (err) {
|
|
321
|
-
const msg =
|
|
304
|
+
const msg = browserErrorMessage(err);
|
|
322
305
|
if (!RECOVERABLE_NAVIGATION_ERRORS.test(msg))
|
|
323
306
|
throw err;
|
|
324
307
|
tag('warning').log(`Navigation warning (continuing after load): ${msg.split('\n')[0]}`);
|
|
@@ -363,7 +346,7 @@ class Explorer {
|
|
|
363
346
|
}
|
|
364
347
|
catch (error) {
|
|
365
348
|
if (this.isFatalBrowserError(error)) {
|
|
366
|
-
tag('warning').log(`getEidxInContainer: ${error
|
|
349
|
+
tag('warning').log(`getEidxInContainer: ${browserErrorMessage(error)}`);
|
|
367
350
|
await this.recoverFromBrowserError();
|
|
368
351
|
}
|
|
369
352
|
return [];
|
|
@@ -378,16 +361,12 @@ class Explorer {
|
|
|
378
361
|
}
|
|
379
362
|
catch (error) {
|
|
380
363
|
if (this.isFatalBrowserError(error)) {
|
|
381
|
-
tag('warning').log(`getEidxByLocator: ${error
|
|
364
|
+
tag('warning').log(`getEidxByLocator: ${browserErrorMessage(error)}`);
|
|
382
365
|
await this.recoverFromBrowserError();
|
|
383
366
|
}
|
|
384
367
|
return null;
|
|
385
368
|
}
|
|
386
369
|
}
|
|
387
|
-
async reload() {
|
|
388
|
-
await this.closeOtherTabs();
|
|
389
|
-
await this.playwrightHelper.page.reload();
|
|
390
|
-
}
|
|
391
370
|
resolveBrowserUrl(url) {
|
|
392
371
|
if (!url)
|
|
393
372
|
return null;
|
|
@@ -433,7 +412,7 @@ class Explorer {
|
|
|
433
412
|
return this.waitForPageReadiness();
|
|
434
413
|
}
|
|
435
414
|
catch (err) {
|
|
436
|
-
tag('error').log(`Browser recovery failed: ${err
|
|
415
|
+
tag('error').log(`Browser recovery failed: ${browserErrorMessage(err)}`);
|
|
437
416
|
return false;
|
|
438
417
|
}
|
|
439
418
|
}
|
|
@@ -471,7 +450,7 @@ class Explorer {
|
|
|
471
450
|
return true;
|
|
472
451
|
}
|
|
473
452
|
catch (err) {
|
|
474
|
-
tag('error').log(`Browser restart failed: ${err
|
|
453
|
+
tag('error').log(`Browser restart failed: ${browserErrorMessage(err)}`);
|
|
475
454
|
return false;
|
|
476
455
|
}
|
|
477
456
|
}
|
|
@@ -502,7 +481,7 @@ class Explorer {
|
|
|
502
481
|
}
|
|
503
482
|
catch (error) {
|
|
504
483
|
if (this.isFatalBrowserError(error)) {
|
|
505
|
-
tag('warning').log(`isInsideIframe: ${error
|
|
484
|
+
tag('warning').log(`isInsideIframe: ${browserErrorMessage(error)}`);
|
|
506
485
|
await this.recoverFromBrowserError();
|
|
507
486
|
}
|
|
508
487
|
return false;
|
|
@@ -522,9 +501,6 @@ class Explorer {
|
|
|
522
501
|
clearOtherTabsInfo() {
|
|
523
502
|
this.otherTabs = [];
|
|
524
503
|
}
|
|
525
|
-
setUserResolve(userResolveFn) {
|
|
526
|
-
this.userResolveFn = userResolveFn;
|
|
527
|
-
}
|
|
528
504
|
listenToStateChanged() {
|
|
529
505
|
if (!this.playwrightHelper) {
|
|
530
506
|
debugLog('Playwright helper not available for state monitoring');
|
|
@@ -629,17 +605,21 @@ class Explorer {
|
|
|
629
605
|
test.setActiveNoteScreenshot(lastScreenshot);
|
|
630
606
|
};
|
|
631
607
|
this.watchActiveTestPage();
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
codeceptjs.event.dispatcher.on('step.passed', (step) => stepHandler(step, 'passed'));
|
|
635
|
-
codeceptjs.event.dispatcher.on('step.failed', (step, error) => {
|
|
608
|
+
const onStepPassed = (step) => stepHandler(step, 'passed');
|
|
609
|
+
const onStepFailed = (step, error) => {
|
|
636
610
|
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',
|
|
611
|
+
};
|
|
612
|
+
const onTestAfter = () => {
|
|
613
|
+
codeceptjs.event.dispatcher.off('step.passed', onStepPassed);
|
|
614
|
+
codeceptjs.event.dispatcher.off('step.failed', onStepFailed);
|
|
615
|
+
codeceptjs.event.dispatcher.off('test.after', onTestAfter);
|
|
641
616
|
this.unwatchActiveTestPages();
|
|
642
|
-
}
|
|
617
|
+
};
|
|
618
|
+
codeceptjs.event.dispatcher.emit('test.before', codeceptjsTest);
|
|
619
|
+
codeceptjs.event.dispatcher.emit('test.start', codeceptjsTest);
|
|
620
|
+
codeceptjs.event.dispatcher.on('step.passed', onStepPassed);
|
|
621
|
+
codeceptjs.event.dispatcher.on('step.failed', onStepFailed);
|
|
622
|
+
codeceptjs.event.dispatcher.on('test.after', onTestAfter);
|
|
643
623
|
return true;
|
|
644
624
|
}
|
|
645
625
|
async ensurePageAvailable() {
|
|
@@ -654,11 +634,8 @@ class Explorer {
|
|
|
654
634
|
this.watchActiveTestPage();
|
|
655
635
|
return true;
|
|
656
636
|
}
|
|
657
|
-
async ensureActiveTestPageAvailable() {
|
|
658
|
-
return this.ensurePageAvailable();
|
|
659
|
-
}
|
|
660
637
|
async handleExecutionError(error) {
|
|
661
|
-
const message =
|
|
638
|
+
const message = browserErrorMessage(error);
|
|
662
639
|
tag('error').log(`Browser execution error: ${message}`);
|
|
663
640
|
if (error instanceof Error && error.name === 'AbortError') {
|
|
664
641
|
return {
|
|
@@ -762,29 +739,6 @@ class Explorer {
|
|
|
762
739
|
}
|
|
763
740
|
this.observedTestPages.clear();
|
|
764
741
|
}
|
|
765
|
-
async hasPlaywrightLocator(locatorFn, opts = {}) {
|
|
766
|
-
try {
|
|
767
|
-
const pwLocator = locatorFn(this.playwrightHelper.page);
|
|
768
|
-
const count = await pwLocator.count();
|
|
769
|
-
if (opts.multiple ? count === 0 : count !== 1)
|
|
770
|
-
return false;
|
|
771
|
-
if (opts.contents) {
|
|
772
|
-
const html = await pwLocator.first().innerHTML();
|
|
773
|
-
if (!html?.trim())
|
|
774
|
-
return false;
|
|
775
|
-
}
|
|
776
|
-
if (opts.success)
|
|
777
|
-
await opts.success(pwLocator);
|
|
778
|
-
return true;
|
|
779
|
-
}
|
|
780
|
-
catch (error) {
|
|
781
|
-
if (this.isFatalBrowserError(error)) {
|
|
782
|
-
tag('warning').log(`hasPlaywrightLocator: ${error instanceof Error ? error.message : error}`);
|
|
783
|
-
await this.recoverFromBrowserError();
|
|
784
|
-
}
|
|
785
|
-
return false;
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
742
|
async playwrightLocatorCount(locatorFn) {
|
|
789
743
|
try {
|
|
790
744
|
const pwLocator = locatorFn(this.playwrightHelper.page);
|
|
@@ -792,7 +746,7 @@ class Explorer {
|
|
|
792
746
|
}
|
|
793
747
|
catch (error) {
|
|
794
748
|
if (this.isFatalBrowserError(error)) {
|
|
795
|
-
tag('warning').log(`playwrightLocatorCount: ${error
|
|
749
|
+
tag('warning').log(`playwrightLocatorCount: ${browserErrorMessage(error)}`);
|
|
796
750
|
await this.recoverFromBrowserError();
|
|
797
751
|
}
|
|
798
752
|
throw error;
|
|
@@ -811,7 +765,7 @@ class Explorer {
|
|
|
811
765
|
debugLog('Failed to get page title:', error);
|
|
812
766
|
}
|
|
813
767
|
this.stateManager.updateStateFromBasic(newUrl, newTitle, 'navigation');
|
|
814
|
-
await
|
|
768
|
+
await sleep(500);
|
|
815
769
|
});
|
|
816
770
|
}
|
|
817
771
|
async openFreshTab() {
|
|
@@ -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
|
+
export 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
|
+
renderRelevantKnowledge(state: ActionResult): string;
|
|
16
|
+
addKnowledge(urlPattern: string, description: string): {
|
|
17
|
+
filename: string;
|
|
18
|
+
filePath: string;
|
|
19
|
+
isNewFile: boolean;
|
|
20
|
+
};
|
|
21
|
+
interpolateVars(content: string): string;
|
|
22
|
+
generateFilename(url: string): string;
|
|
23
|
+
getExistingUrls(): string[];
|
|
24
|
+
getKnowledgeForUrl(urlPattern: string): string[];
|
|
25
|
+
listAllKnowledge(): Array<{
|
|
26
|
+
url: string;
|
|
27
|
+
firstLine: string;
|
|
28
|
+
filePath: string;
|
|
29
|
+
}>;
|
|
30
|
+
getMatchingKnowledge(url: string): Knowledge[];
|
|
31
|
+
normalizeUrl(url: string): string;
|
|
32
|
+
getStateParameters(state: ActionResult, keys: string[]): Record<string, any>;
|
|
33
|
+
}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync,
|
|
2
|
-
import {
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import dedent from 'dedent';
|
|
3
4
|
import matter from 'gray-matter';
|
|
4
5
|
import { ActionResult } from './action-result.js';
|
|
5
6
|
import { ConfigParser } from './config.js';
|
|
6
7
|
import { getCliName } from "./utils/cli-name.js";
|
|
7
|
-
import { createDebug } from './utils/logger.js';
|
|
8
|
+
import { createDebug, pluralize, tag } from './utils/logger.js';
|
|
9
|
+
import { loadMarkdownFiles } from './utils/markdown-files.js';
|
|
10
|
+
import { mdq } from './utils/markdown-query.js';
|
|
11
|
+
import { isSecretName, registerSecret } from './utils/secrets.js';
|
|
12
|
+
import { slugify } from './utils/strings.js';
|
|
8
13
|
const debugLog = createDebug('explorbot:knowledge-tracker');
|
|
9
14
|
export class KnowledgeTracker {
|
|
10
15
|
knowledgeDir;
|
|
@@ -13,14 +18,7 @@ export class KnowledgeTracker {
|
|
|
13
18
|
constructor() {
|
|
14
19
|
const configParser = ConfigParser.getInstance();
|
|
15
20
|
const config = configParser.getConfig();
|
|
16
|
-
|
|
17
|
-
if (configPath) {
|
|
18
|
-
const projectRoot = dirname(configPath);
|
|
19
|
-
this.knowledgeDir = join(projectRoot, config.dirs?.knowledge || 'knowledge');
|
|
20
|
-
}
|
|
21
|
-
else {
|
|
22
|
-
this.knowledgeDir = config.dirs?.knowledge || 'knowledge';
|
|
23
|
-
}
|
|
21
|
+
this.knowledgeDir = configParser.resolveProjectDir(config.dirs?.knowledge || 'knowledge');
|
|
24
22
|
if (!existsSync(this.knowledgeDir)) {
|
|
25
23
|
mkdirSync(this.knowledgeDir, { recursive: true });
|
|
26
24
|
}
|
|
@@ -29,27 +27,13 @@ export class KnowledgeTracker {
|
|
|
29
27
|
if (this.isLoaded)
|
|
30
28
|
return;
|
|
31
29
|
this.knowledgeFiles = [];
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
try {
|
|
40
|
-
const fileContent = readFileSync(filePath, 'utf8');
|
|
41
|
-
const parsed = matter(fileContent);
|
|
42
|
-
const urlPattern = parsed.data.url || parsed.data.path || '*';
|
|
43
|
-
this.knowledgeFiles.push({
|
|
44
|
-
filePath,
|
|
45
|
-
url: urlPattern,
|
|
46
|
-
content: this.interpolateVars(parsed.content),
|
|
47
|
-
...parsed.data,
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
catch (error) {
|
|
51
|
-
// Skip invalid files
|
|
52
|
-
}
|
|
30
|
+
for (const entry of loadMarkdownFiles(this.knowledgeDir, { recursive: true })) {
|
|
31
|
+
this.knowledgeFiles.push({
|
|
32
|
+
filePath: entry.filePath,
|
|
33
|
+
url: entry.data.url || entry.data.path || '*',
|
|
34
|
+
content: this.interpolateVars(entry.content),
|
|
35
|
+
...entry.data,
|
|
36
|
+
});
|
|
53
37
|
}
|
|
54
38
|
this.isLoaded = true;
|
|
55
39
|
}
|
|
@@ -59,21 +43,35 @@ export class KnowledgeTracker {
|
|
|
59
43
|
return state.isMatchedBy(knowledge);
|
|
60
44
|
});
|
|
61
45
|
}
|
|
46
|
+
renderRelevantKnowledge(state) {
|
|
47
|
+
const knowledgeFiles = this.getRelevantKnowledge(state);
|
|
48
|
+
if (knowledgeFiles.length === 0)
|
|
49
|
+
return '';
|
|
50
|
+
const knowledgeContent = knowledgeFiles
|
|
51
|
+
.map((k) => k.content)
|
|
52
|
+
.filter((k) => !!k)
|
|
53
|
+
.join('\n\n');
|
|
54
|
+
tag('operation').log(`Found ${knowledgeFiles.length} relevant knowledge ${pluralize(knowledgeFiles.length, 'file')}`);
|
|
55
|
+
return dedent `
|
|
56
|
+
<knowledge>
|
|
57
|
+
Here is relevant knowledge for this page:
|
|
58
|
+
|
|
59
|
+
${knowledgeContent}
|
|
60
|
+
</knowledge>
|
|
61
|
+
`;
|
|
62
|
+
}
|
|
62
63
|
addKnowledge(urlPattern, description) {
|
|
63
64
|
const configParser = ConfigParser.getInstance();
|
|
64
|
-
const config = configParser.getConfig();
|
|
65
65
|
const configPath = configParser.getConfigPath();
|
|
66
66
|
if (!configPath) {
|
|
67
67
|
throw new Error(`No explorbot configuration found. Please run "${getCliName()} init" first.`);
|
|
68
68
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if (!existsSync(knowledgeDir)) {
|
|
72
|
-
mkdirSync(knowledgeDir, { recursive: true });
|
|
69
|
+
if (!existsSync(this.knowledgeDir)) {
|
|
70
|
+
mkdirSync(this.knowledgeDir, { recursive: true });
|
|
73
71
|
}
|
|
74
72
|
const normalizedUrl = this.normalizeUrl(urlPattern);
|
|
75
73
|
const filename = this.generateFilename(normalizedUrl);
|
|
76
|
-
const filePath = join(knowledgeDir, filename);
|
|
74
|
+
const filePath = join(this.knowledgeDir, filename);
|
|
77
75
|
const isNewFile = !existsSync(filePath);
|
|
78
76
|
if (isNewFile) {
|
|
79
77
|
const frontmatter = {
|
|
@@ -100,6 +98,7 @@ export class KnowledgeTracker {
|
|
|
100
98
|
const fileContent = matter.stringify(newContent, frontmatter);
|
|
101
99
|
writeFileSync(filePath, fileContent, 'utf8');
|
|
102
100
|
}
|
|
101
|
+
this.isLoaded = false;
|
|
103
102
|
return { filename, filePath, isNewFile };
|
|
104
103
|
}
|
|
105
104
|
interpolateVars(content) {
|
|
@@ -109,9 +108,15 @@ export class KnowledgeTracker {
|
|
|
109
108
|
return match;
|
|
110
109
|
const namespace = expr.slice(0, dotIndex);
|
|
111
110
|
const key = expr.slice(dotIndex + 1);
|
|
112
|
-
if (namespace === 'env')
|
|
113
|
-
|
|
111
|
+
if (namespace === 'env') {
|
|
112
|
+
const value = process.env[key] ?? '';
|
|
113
|
+
if (isSecretName(key))
|
|
114
|
+
registerSecret(value);
|
|
115
|
+
return value;
|
|
116
|
+
}
|
|
114
117
|
if (namespace === 'config') {
|
|
118
|
+
if (isSecretName(key))
|
|
119
|
+
return '';
|
|
115
120
|
const config = ConfigParser.getInstance().getConfig();
|
|
116
121
|
const value = key.split('.').reduce((obj, k) => obj?.[k], config);
|
|
117
122
|
if (value !== undefined && typeof value !== 'object')
|
|
@@ -122,12 +127,7 @@ export class KnowledgeTracker {
|
|
|
122
127
|
});
|
|
123
128
|
}
|
|
124
129
|
generateFilename(url) {
|
|
125
|
-
let filename = url
|
|
126
|
-
.replace(/https?:\/\//g, '')
|
|
127
|
-
.replace(/[^a-zA-Z0-9_]/g, '_')
|
|
128
|
-
.replace(/_+/g, '_')
|
|
129
|
-
.replace(/^_|_$/g, '')
|
|
130
|
-
.toLowerCase();
|
|
130
|
+
let filename = slugify(url.replace(/https?:\/\//g, ''));
|
|
131
131
|
if (!filename || filename === '*') {
|
|
132
132
|
filename = 'general';
|
|
133
133
|
}
|
|
@@ -149,7 +149,7 @@ export class KnowledgeTracker {
|
|
|
149
149
|
this.loadKnowledgeFiles();
|
|
150
150
|
return this.knowledgeFiles.map((knowledge) => {
|
|
151
151
|
const content = knowledge.content.trim();
|
|
152
|
-
const firstLine = content.split('\n')[0]?.trim() || '';
|
|
152
|
+
const firstLine = mdq(content).meta()[0]?.text.split('\n')[0]?.trim() || '';
|
|
153
153
|
return {
|
|
154
154
|
url: knowledge.url,
|
|
155
155
|
firstLine,
|
|
@@ -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 {};
|