explorbot 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -5
- package/bin/explorbot-cli.ts +29 -7
- package/boat/api-tester/src/config.ts +45 -3
- package/boat/doc-collector/src/ai/documentarian.ts +5 -2
- package/boat/doc-collector/src/ai/tools.ts +12 -11
- package/boat/doc-collector/src/cli.ts +1 -6
- package/boat/doc-collector/src/docbot.ts +3 -3
- package/boat/doc-collector/src/screenshots.ts +2 -2
- package/dist/bin/explorbot-cli.js +26 -6
- package/dist/boat/api-tester/src/config.js +43 -4
- package/dist/boat/doc-collector/src/ai/documentarian.js +4 -2
- package/dist/boat/doc-collector/src/ai/tools.js +11 -11
- package/dist/boat/doc-collector/src/cli.js +1 -5
- package/dist/boat/doc-collector/src/docbot.js +3 -3
- package/dist/boat/doc-collector/src/screenshots.js +2 -2
- package/dist/models.json +30 -0
- package/dist/package.json +5 -2
- package/dist/src/action.d.ts +11 -3
- package/dist/src/action.js +22 -5
- package/dist/src/ai/agent.d.ts +17 -0
- package/dist/src/ai/captain/idle-mode.js +1 -1
- package/dist/src/ai/captain/test-mode.js +1 -1
- package/dist/src/ai/captain/web-mode.js +18 -22
- package/dist/src/ai/captain.js +13 -26
- package/dist/src/ai/driller.d.ts +2 -13
- package/dist/src/ai/driller.js +23 -38
- package/dist/src/ai/historian/codeceptjs.js +1 -1
- package/dist/src/ai/historian/playwright.d.ts +3 -2
- package/dist/src/ai/historian/playwright.js +1 -1
- package/dist/src/ai/historian/screencast.d.ts +2 -1
- package/dist/src/ai/historian/screencast.js +2 -2
- package/dist/src/ai/historian.d.ts +5 -4
- package/dist/src/ai/navigator.d.ts +6 -2
- package/dist/src/ai/navigator.js +26 -22
- package/dist/src/ai/pilot.d.ts +13 -6
- package/dist/src/ai/pilot.js +49 -44
- package/dist/src/ai/planner.d.ts +3 -2
- package/dist/src/ai/planner.js +19 -17
- package/dist/src/ai/provider.js +0 -1
- package/dist/src/ai/quartermaster.d.ts +3 -2
- package/dist/src/ai/quartermaster.js +4 -4
- package/dist/src/ai/rerunner.d.ts +2 -11
- package/dist/src/ai/rerunner.js +9 -22
- package/dist/src/ai/researcher/coordinates.js +4 -3
- package/dist/src/ai/researcher/deep-analysis.d.ts +2 -0
- package/dist/src/ai/researcher/deep-analysis.js +6 -6
- package/dist/src/ai/researcher/locators.d.ts +9 -2
- package/dist/src/ai/researcher/locators.js +65 -8
- package/dist/src/ai/researcher/sections.d.ts +2 -0
- package/dist/src/ai/researcher/sections.js +2 -2
- package/dist/src/ai/researcher.js +29 -54
- package/dist/src/ai/task-agent.d.ts +18 -5
- package/dist/src/ai/task-agent.js +35 -6
- package/dist/src/ai/tester.d.ts +6 -12
- package/dist/src/ai/tester.js +37 -51
- package/dist/src/ai/tools.d.ts +11 -10
- package/dist/src/ai/tools.js +24 -36
- package/dist/src/command-handler.js +1 -1
- package/dist/src/commands/context-aria-command.js +1 -1
- package/dist/src/commands/context-command.js +7 -5
- package/dist/src/commands/context-data-command.js +2 -2
- package/dist/src/commands/context-experience-command.js +2 -2
- package/dist/src/commands/context-html-command.js +2 -2
- package/dist/src/commands/context-knowledge-command.js +1 -1
- package/dist/src/commands/drill-command.js +1 -1
- package/dist/src/commands/explore-command.js +4 -3
- package/dist/src/commands/freesail-command.js +2 -2
- package/dist/src/commands/learn-command.js +4 -4
- package/dist/src/commands/path-command.js +1 -1
- package/dist/src/commands/research-command.js +1 -1
- package/dist/src/commands/test-command.js +1 -1
- package/dist/src/components/App.js +1 -1
- package/dist/src/config.d.ts +17 -0
- package/dist/src/config.js +144 -10
- package/dist/src/experience-tracker.js +1 -1
- package/dist/src/explorbot.d.ts +17 -8
- package/dist/src/explorbot.js +74 -36
- package/dist/src/explorer.d.ts +66 -91
- package/dist/src/explorer.js +326 -567
- package/dist/src/state-manager.d.ts +6 -1
- package/dist/src/state-manager.js +1 -0
- package/dist/src/utils/hooks-runner.js +2 -4
- package/dist/src/utils/test-files.js +1 -1
- package/dist/src/utils/web-annotate.d.ts +5 -0
- package/dist/src/utils/web-annotate.js +58 -0
- package/dist/src/utils/web-eidx.d.ts +2 -0
- package/dist/src/utils/web-eidx.js +20 -0
- package/dist/src/utils/web-element.d.ts +1 -0
- package/dist/src/utils/web-element.js +29 -0
- package/models.json +30 -0
- package/package.json +5 -2
- package/src/action.ts +25 -5
- package/src/ai/agent.ts +20 -0
- package/src/ai/captain/idle-mode.ts +1 -1
- package/src/ai/captain/test-mode.ts +1 -1
- package/src/ai/captain/web-mode.ts +18 -23
- package/src/ai/captain.ts +12 -25
- package/src/ai/driller.ts +50 -67
- package/src/ai/historian/codeceptjs.ts +1 -1
- package/src/ai/historian/playwright.ts +4 -3
- package/src/ai/historian/screencast.ts +4 -3
- package/src/ai/historian.ts +3 -2
- package/src/ai/navigator.ts +30 -25
- package/src/ai/pilot.ts +55 -47
- package/src/ai/planner.ts +22 -20
- package/src/ai/provider.ts +0 -1
- package/src/ai/quartermaster.ts +5 -4
- package/src/ai/rerunner.ts +10 -29
- package/src/ai/researcher/coordinates.ts +4 -3
- package/src/ai/researcher/deep-analysis.ts +8 -6
- package/src/ai/researcher/locators.ts +66 -9
- package/src/ai/researcher/sections.ts +4 -2
- package/src/ai/researcher.ts +32 -61
- package/src/ai/task-agent.ts +45 -11
- package/src/ai/tester.ts +40 -57
- package/src/ai/tools.ts +32 -53
- package/src/command-handler.ts +1 -1
- package/src/commands/context-aria-command.ts +1 -1
- package/src/commands/context-command.ts +7 -5
- package/src/commands/context-data-command.ts +2 -2
- package/src/commands/context-experience-command.ts +2 -2
- package/src/commands/context-html-command.ts +2 -2
- package/src/commands/context-knowledge-command.ts +1 -1
- package/src/commands/drill-command.ts +1 -1
- package/src/commands/explore-command.ts +4 -3
- package/src/commands/freesail-command.ts +2 -2
- package/src/commands/learn-command.ts +4 -4
- package/src/commands/path-command.ts +1 -1
- package/src/commands/research-command.ts +1 -1
- package/src/commands/test-command.ts +1 -1
- package/src/components/App.tsx +1 -1
- package/src/config.ts +173 -11
- package/src/experience-tracker.ts +1 -1
- package/src/explorbot.ts +78 -39
- package/src/explorer.ts +389 -628
- package/src/state-manager.ts +7 -1
- package/src/utils/hooks-runner.ts +2 -4
- package/src/utils/test-files.ts +1 -1
- package/src/utils/web-annotate.ts +64 -0
- package/src/utils/web-eidx.ts +21 -0
- package/src/utils/web-element.ts +30 -0
package/src/explorbot.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync, mkdirSync } from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
import type { AgentDeps } from './ai/agent.ts';
|
|
3
4
|
import { Captain } from './ai/captain.ts';
|
|
4
5
|
import { Driller } from './ai/driller.ts';
|
|
5
6
|
import { ExperienceCompactor } from './ai/experience-compactor.ts';
|
|
@@ -23,7 +24,9 @@ import { ConfigParser } from './config.ts';
|
|
|
23
24
|
import { ExperienceTracker } from './experience-tracker.ts';
|
|
24
25
|
import Explorer from './explorer.ts';
|
|
25
26
|
import { KnowledgeTracker } from './knowledge-tracker.ts';
|
|
26
|
-
import {
|
|
27
|
+
import { PlaywrightRecorder } from './playwright-recorder.ts';
|
|
28
|
+
import { Reporter } from './reporter.ts';
|
|
29
|
+
import { StateManager, WebPageState } from './state-manager.ts';
|
|
27
30
|
import { Stats } from './stats.ts';
|
|
28
31
|
import type { Suite } from './suite.ts';
|
|
29
32
|
import { Plan, type Test } from './test-plan.ts';
|
|
@@ -42,7 +45,7 @@ export interface ExplorBotOptions {
|
|
|
42
45
|
show?: boolean;
|
|
43
46
|
headless?: boolean;
|
|
44
47
|
incognito?: boolean;
|
|
45
|
-
session?: string;
|
|
48
|
+
session?: string | boolean;
|
|
46
49
|
}
|
|
47
50
|
|
|
48
51
|
export type UserResolveFunction = (error?: Error, showWelcome?: boolean) => Promise<string | null>;
|
|
@@ -63,6 +66,10 @@ export class ExplorBot {
|
|
|
63
66
|
private lastReportedTestCount = 0;
|
|
64
67
|
private _experienceTracker?: ExperienceTracker;
|
|
65
68
|
private _knowledgeTracker?: KnowledgeTracker;
|
|
69
|
+
private _stateManager?: StateManager;
|
|
70
|
+
private _reporter?: Reporter;
|
|
71
|
+
private _requestStore?: RequestStore;
|
|
72
|
+
private _playwrightRecorder?: PlaywrightRecorder;
|
|
66
73
|
|
|
67
74
|
constructor(options: ExplorBotOptions = {}) {
|
|
68
75
|
this.options = options;
|
|
@@ -74,7 +81,7 @@ export class ExplorBot {
|
|
|
74
81
|
}
|
|
75
82
|
|
|
76
83
|
get isExploring(): boolean {
|
|
77
|
-
return this.explorer
|
|
84
|
+
return !!this.explorer;
|
|
78
85
|
}
|
|
79
86
|
|
|
80
87
|
setUserResolve(fn: UserResolveFunction): void {
|
|
@@ -82,13 +89,20 @@ export class ExplorBot {
|
|
|
82
89
|
}
|
|
83
90
|
|
|
84
91
|
async start(): Promise<void> {
|
|
85
|
-
if (this.explorer
|
|
92
|
+
if (this.explorer) {
|
|
86
93
|
return;
|
|
87
94
|
}
|
|
88
95
|
|
|
89
96
|
try {
|
|
90
97
|
await this.startProviderOnly();
|
|
91
|
-
|
|
98
|
+
const explorerOptions = { ...this.options, session: typeof this.options.session === 'string' ? this.options.session : undefined };
|
|
99
|
+
this.explorer = new Explorer(this.config, explorerOptions, {
|
|
100
|
+
stateManager: this.stateManager(),
|
|
101
|
+
knowledgeTracker: this.knowledgeTracker(),
|
|
102
|
+
reporter: this.reporter(),
|
|
103
|
+
requestStore: this.requestStore(),
|
|
104
|
+
playwrightRecorder: this.playwrightRecorder(),
|
|
105
|
+
});
|
|
92
106
|
await this.explorer.start();
|
|
93
107
|
if (!this.options.incognito) {
|
|
94
108
|
await this.agentExperienceCompactor().autocompact();
|
|
@@ -103,6 +117,7 @@ export class ExplorBot {
|
|
|
103
117
|
async startProviderOnly(): Promise<void> {
|
|
104
118
|
if (this.provider) return;
|
|
105
119
|
this.config = await this.configParser.loadConfig(this.options);
|
|
120
|
+
if (this.options.session === true) this.options.session = path.join(this.configParser.getOutputDir(), 'session.json');
|
|
106
121
|
this.provider = new AIProvider(this.config.ai);
|
|
107
122
|
await this.provider.validateConnection();
|
|
108
123
|
}
|
|
@@ -121,12 +136,12 @@ export class ExplorBot {
|
|
|
121
136
|
return this.agentNavigator().visit(url);
|
|
122
137
|
}
|
|
123
138
|
|
|
124
|
-
async
|
|
125
|
-
await this.explorer.
|
|
139
|
+
async openTab(): Promise<void> {
|
|
140
|
+
await this.explorer.openTab();
|
|
126
141
|
}
|
|
127
142
|
|
|
128
143
|
getCurrentState(): WebPageState | null {
|
|
129
|
-
return this.
|
|
144
|
+
return this._stateManager?.getCurrentState() ?? null;
|
|
130
145
|
}
|
|
131
146
|
|
|
132
147
|
getExplorer(): Explorer {
|
|
@@ -141,6 +156,22 @@ export class ExplorBot {
|
|
|
141
156
|
return (this._experienceTracker ||= new ExperienceTracker(this.knowledgeTracker()));
|
|
142
157
|
}
|
|
143
158
|
|
|
159
|
+
stateManager(): StateManager {
|
|
160
|
+
return (this._stateManager ||= new StateManager(this.experienceTracker(), this.knowledgeTracker()));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
reporter(): Reporter {
|
|
164
|
+
return (this._reporter ||= new Reporter(this.config.reporter, this.stateManager()));
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
requestStore(): RequestStore {
|
|
168
|
+
return (this._requestStore ||= new RequestStore(this.configParser.getOutputDir()));
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
playwrightRecorder(): PlaywrightRecorder {
|
|
172
|
+
return (this._playwrightRecorder ||= new PlaywrightRecorder());
|
|
173
|
+
}
|
|
174
|
+
|
|
144
175
|
getConfig(): ExplorbotConfig {
|
|
145
176
|
return this.config;
|
|
146
177
|
}
|
|
@@ -153,11 +184,15 @@ export class ExplorBot {
|
|
|
153
184
|
return this.provider;
|
|
154
185
|
}
|
|
155
186
|
|
|
156
|
-
createAgent<T>(factory: (deps:
|
|
187
|
+
createAgent<T>(factory: (deps: AgentDeps) => T): T {
|
|
157
188
|
const agent = factory({
|
|
158
189
|
explorer: this.explorer,
|
|
159
190
|
ai: this.provider,
|
|
160
191
|
config: this.config,
|
|
192
|
+
stateManager: this.stateManager(),
|
|
193
|
+
knowledgeTracker: this.knowledgeTracker(),
|
|
194
|
+
requestStore: this.requestStore(),
|
|
195
|
+
playwrightRecorder: this.playwrightRecorder(),
|
|
161
196
|
});
|
|
162
197
|
|
|
163
198
|
const agentName = (agent as any).constructor.name.toLowerCase();
|
|
@@ -167,18 +202,16 @@ export class ExplorBot {
|
|
|
167
202
|
}
|
|
168
203
|
|
|
169
204
|
agentResearcher(): Researcher {
|
|
170
|
-
return (this.agents.researcher ||= this.createAgent((
|
|
205
|
+
return (this.agents.researcher ||= this.createAgent((deps) => new Researcher(deps)));
|
|
171
206
|
}
|
|
172
207
|
|
|
173
208
|
agentNavigator(): Navigator {
|
|
174
|
-
return (this.agents.navigator ||= this.createAgent((
|
|
175
|
-
return new Navigator(explorer, ai);
|
|
176
|
-
}));
|
|
209
|
+
return (this.agents.navigator ||= this.createAgent((deps) => new Navigator(deps)));
|
|
177
210
|
}
|
|
178
211
|
|
|
179
212
|
agentPlanner(): Planner {
|
|
180
213
|
if (!this.agents.planner) {
|
|
181
|
-
this.agents.planner = this.createAgent((
|
|
214
|
+
this.agents.planner = this.createAgent((deps) => new Planner(deps, this.agentResearcher()));
|
|
182
215
|
const fisherman = this.agentFisherman();
|
|
183
216
|
if (fisherman) this.agents.planner.setFisherman(fisherman);
|
|
184
217
|
}
|
|
@@ -186,26 +219,26 @@ export class ExplorBot {
|
|
|
186
219
|
}
|
|
187
220
|
|
|
188
221
|
agentPilot(): Pilot {
|
|
189
|
-
return (this.agents.pilot ||= this.createAgent((
|
|
222
|
+
return (this.agents.pilot ||= this.createAgent((deps) => {
|
|
190
223
|
const researcher = this.agentResearcher();
|
|
191
224
|
const navigator = this.agentNavigator();
|
|
192
|
-
const tools = createAgentTools({
|
|
193
|
-
return new Pilot(
|
|
225
|
+
const tools = createAgentTools({ ...deps, researcher, navigator, supervisor: true });
|
|
226
|
+
return new Pilot(deps, tools, researcher);
|
|
194
227
|
}));
|
|
195
228
|
}
|
|
196
229
|
|
|
197
230
|
agentTester(): Tester {
|
|
198
231
|
if (!this.agents.tester) {
|
|
199
|
-
this.agents.tester = this.createAgent((
|
|
232
|
+
this.agents.tester = this.createAgent((deps) => {
|
|
200
233
|
const researcher = this.agentResearcher();
|
|
201
234
|
const navigator = this.agentNavigator();
|
|
202
|
-
const tools = createAgentTools({
|
|
203
|
-
return new Tester(
|
|
235
|
+
const tools = createAgentTools({ ...deps, researcher, navigator });
|
|
236
|
+
return new Tester(deps, researcher, navigator, tools);
|
|
204
237
|
});
|
|
205
238
|
|
|
206
239
|
const qm = this.agentQuartermaster();
|
|
207
240
|
if (qm) this.agents.tester.setQuartermaster(qm);
|
|
208
|
-
this.agents.tester.setHistorian(this.agentHistorian());
|
|
241
|
+
if (this.isHistorianEnabled()) this.agents.tester.setHistorian(this.agentHistorian());
|
|
209
242
|
this.agents.tester.setPilot(this.agentPilot());
|
|
210
243
|
this.agents.tester.setCaptain(this.agentCaptain());
|
|
211
244
|
|
|
@@ -234,39 +267,37 @@ export class ExplorBot {
|
|
|
234
267
|
this.agents.quartermaster = new Quartermaster(this.provider, {
|
|
235
268
|
model: config?.model,
|
|
236
269
|
});
|
|
237
|
-
this.agents.quartermaster.start(this.explorer
|
|
270
|
+
this.agents.quartermaster.start(this.explorer, this.stateManager());
|
|
238
271
|
}
|
|
239
272
|
return this.agents.quartermaster;
|
|
240
273
|
}
|
|
241
274
|
|
|
242
275
|
agentHistorian(): Historian {
|
|
243
|
-
return (this.agents.historian ||= this.createAgent(({ ai, explorer, config }) => {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
recorder: explorer.getPlaywrightRecorder(),
|
|
248
|
-
helper: explorer.playwrightHelper,
|
|
276
|
+
return (this.agents.historian ||= this.createAgent(({ ai, explorer, config, stateManager, playwrightRecorder }) => {
|
|
277
|
+
return new Historian(ai, this.experienceTracker(), this.reporter(), stateManager, config, {
|
|
278
|
+
recorder: playwrightRecorder,
|
|
279
|
+
explorer,
|
|
249
280
|
});
|
|
250
281
|
}));
|
|
251
282
|
}
|
|
252
283
|
|
|
253
284
|
agentRerunner(): Rerunner {
|
|
254
285
|
if (!this.agents.rerunner) {
|
|
255
|
-
this.agents.rerunner = this.createAgent((
|
|
286
|
+
this.agents.rerunner = this.createAgent((deps) => {
|
|
256
287
|
const researcher = this.agentResearcher();
|
|
257
288
|
const navigator = this.agentNavigator();
|
|
258
|
-
const tools = createAgentTools({
|
|
259
|
-
return new Rerunner(
|
|
289
|
+
const tools = createAgentTools({ ...deps, researcher, navigator, withExperience: false });
|
|
290
|
+
return new Rerunner(deps, tools);
|
|
260
291
|
});
|
|
261
|
-
this.agents.rerunner.setHistorian(this.agentHistorian());
|
|
292
|
+
if (this.isHistorianEnabled()) this.agents.rerunner.setHistorian(this.agentHistorian());
|
|
262
293
|
}
|
|
263
294
|
return this.agents.rerunner;
|
|
264
295
|
}
|
|
265
296
|
|
|
266
297
|
agentDriller(): Driller {
|
|
267
|
-
return (this.agents.driller ||= this.createAgent((
|
|
298
|
+
return (this.agents.driller ||= this.createAgent((deps) => {
|
|
268
299
|
const navigator = this.agentNavigator();
|
|
269
|
-
return new Driller(
|
|
300
|
+
return new Driller(deps, navigator);
|
|
270
301
|
}));
|
|
271
302
|
}
|
|
272
303
|
|
|
@@ -283,7 +314,7 @@ export class ExplorBot {
|
|
|
283
314
|
if (!this.agents.fisherman) {
|
|
284
315
|
const apiConfig = this.config.api;
|
|
285
316
|
const outputDir = this.configParser.getOutputDir();
|
|
286
|
-
const requestStore = this.
|
|
317
|
+
const requestStore = this.requestStore();
|
|
287
318
|
const baseEndpoint = apiConfig?.baseEndpoint || this.config.playwright.url;
|
|
288
319
|
const configHeaders = apiConfig?.headers || {};
|
|
289
320
|
const apiClient = new ApiClient(baseEndpoint);
|
|
@@ -298,7 +329,11 @@ export class ExplorBot {
|
|
|
298
329
|
}
|
|
299
330
|
};
|
|
300
331
|
|
|
301
|
-
const cookieProvider = () =>
|
|
332
|
+
const cookieProvider = async (): Promise<Record<string, string>> => {
|
|
333
|
+
const cookies = await this.explorer.withPage((page) => page.context().cookies()).catch(() => []);
|
|
334
|
+
if (!cookies.length) return {};
|
|
335
|
+
return { Cookie: cookies.map((c: any) => `${c.name}=${c.value}`).join('; ') };
|
|
336
|
+
};
|
|
302
337
|
|
|
303
338
|
this.agents.fisherman = this.createAgent(({ ai }) => {
|
|
304
339
|
return new Fisherman(ai, apiClient, requestStore, specLoader, baseEndpoint, cookieProvider, configHeaders, hasApiConfig);
|
|
@@ -332,7 +367,7 @@ export class ExplorBot {
|
|
|
332
367
|
}
|
|
333
368
|
|
|
334
369
|
if (!opts.extend && this.currentPlan?.url) {
|
|
335
|
-
const currentUrl = this.
|
|
370
|
+
const currentUrl = this._stateManager?.getCurrentState()?.url;
|
|
336
371
|
if (currentUrl && currentUrl !== this.currentPlan.url) {
|
|
337
372
|
tag('info').log('Different page detected, clearing previous plan');
|
|
338
373
|
this.clearPlan();
|
|
@@ -385,7 +420,7 @@ export class ExplorBot {
|
|
|
385
420
|
}
|
|
386
421
|
|
|
387
422
|
generatePlanFilename(feature?: string): string {
|
|
388
|
-
const state = this.
|
|
423
|
+
const state = this._stateManager?.getCurrentState();
|
|
389
424
|
const urlPath = state?.url || '/';
|
|
390
425
|
const urlPart = sanitizeFilename(urlPath) || 'root';
|
|
391
426
|
const suffix = '.md';
|
|
@@ -465,7 +500,7 @@ export class ExplorBot {
|
|
|
465
500
|
const filePath = this.agentSessionAnalyst().writeReport(markdown);
|
|
466
501
|
tag('info').log(`Session report saved: ${relativeToCwd(filePath)}`);
|
|
467
502
|
|
|
468
|
-
const reporter = this.
|
|
503
|
+
const reporter = this._reporter;
|
|
469
504
|
if (reporter?.isEnabled()) {
|
|
470
505
|
let description = markdown;
|
|
471
506
|
const modelsTable = Stats.modelsTable(this.provider.getConfiguredModels());
|
|
@@ -479,4 +514,8 @@ export class ExplorBot {
|
|
|
479
514
|
tag('warning').log(`Session analysis failed: ${message}`);
|
|
480
515
|
}
|
|
481
516
|
}
|
|
517
|
+
|
|
518
|
+
private isHistorianEnabled(): boolean {
|
|
519
|
+
return this.config.ai?.agents?.historian?.enabled !== false;
|
|
520
|
+
}
|
|
482
521
|
}
|