Skip to content

Commit 29e6531

Browse files
authored
Merge pull request #27 from DeepFundAI/ls-dev
Ls dev
2 parents c3f249b + 0323d8d commit 29e6531

File tree

11 files changed

+549
-667
lines changed

11 files changed

+549
-667
lines changed

docs/shotscreen/home.png

16.9 KB
Loading

electron/main/services/eko-service.ts

Lines changed: 77 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { BrowserAgent, FileAgent } from "@jarvis-agent/electron";
33
import type { EkoResult } from "@jarvis-agent/core/types";
44
import { BrowserWindow, WebContentsView, app } from "electron";
55
import path from "node:path";
6+
import fs from "node:fs";
67
import { randomUUID } from "node:crypto";
78
import { ConfigManager } from "../utils/config-manager";
89
import type { HumanRequestMessage, HumanResponseMessage, HumanInteractionContext } from "../../../src/models/human-interaction";
@@ -12,7 +13,7 @@ export class EkoService {
1213
private mainWindow: BrowserWindow;
1314
private detailView: WebContentsView;
1415
private mcpClient!: SimpleSseMcpClient;
15-
private agents!: any[];
16+
private browserAgent: BrowserAgent | null = null;
1617

1718
// Store pending human interaction requests
1819
private pendingHumanRequests = new Map<string, {
@@ -104,13 +105,14 @@ export class EkoService {
104105
agentContext: AgentContext,
105106
prompt: string,
106107
options: string[],
107-
multiple: boolean
108+
multiple?: boolean,
109+
_extInfo?: any
108110
): Promise<string[]> => {
109111
const result = await this.requestHumanInteraction(agentContext, {
110112
interactType: 'select',
111113
prompt,
112114
selectOptions: options,
113-
selectMultiple: multiple
115+
selectMultiple: multiple ?? false
114116
});
115117
return Array.isArray(result) ? result : [];
116118
},
@@ -142,31 +144,63 @@ export class EkoService {
142144
};
143145
}
144146

145-
private initializeEko() {
146-
const configManager = ConfigManager.getInstance();
147-
const llms: LLMs = configManager.getLLMsConfig();
148-
const agentConfig = configManager.getAgentConfig();
149-
150-
const appPath = app.isPackaged
147+
/**
148+
* Get base work path for file storage
149+
*/
150+
private getBaseWorkPath(): string {
151+
return app.isPackaged
151152
? path.join(app.getPath('userData'), 'static')
152153
: path.join(process.cwd(), 'public', 'static');
154+
}
153155

154-
this.mcpClient = new SimpleSseMcpClient("http://localhost:5173/api/mcp/sse");
155-
this.agents = [];
156+
/**
157+
* Get task-specific work path with unique taskId
158+
*/
159+
private getTaskWorkPath(taskId: string): string {
160+
return path.join(this.getBaseWorkPath(), taskId);
161+
}
156162

157-
if (agentConfig.browserAgent.enabled) {
158-
this.agents.push(
159-
new BrowserAgent(this.detailView, this.mcpClient, agentConfig.browserAgent.customPrompt)
160-
);
163+
/**
164+
* Create Eko instance for a specific task with unique work directory
165+
*/
166+
private createEkoForTask(taskId: string): Eko {
167+
const configManager = ConfigManager.getInstance();
168+
const llms: LLMs = configManager.getLLMsConfig();
169+
const agentConfig = configManager.getAgentConfig();
170+
const agents: any[] = [];
171+
172+
// Reuse BrowserAgent (no file storage involved)
173+
if (this.browserAgent) {
174+
agents.push(this.browserAgent);
161175
}
162176

177+
// Create FileAgent with task-specific work directory
163178
if (agentConfig.fileAgent.enabled) {
164-
this.agents.push(
165-
new FileAgent(this.detailView, appPath, this.mcpClient, agentConfig.fileAgent.customPrompt)
179+
const taskWorkPath = this.getTaskWorkPath(taskId);
180+
fs.mkdirSync(taskWorkPath, { recursive: true });
181+
agents.push(
182+
new FileAgent(this.detailView, taskWorkPath, this.mcpClient, agentConfig.fileAgent.customPrompt)
166183
);
167184
}
168185

169-
this.eko = new Eko({ llms, agents: this.agents, callback: this.createCallback() });
186+
return new Eko({ llms, agents, callback: this.createCallback() });
187+
}
188+
189+
private initializeEko() {
190+
const configManager = ConfigManager.getInstance();
191+
const llms: LLMs = configManager.getLLMsConfig();
192+
const agentConfig = configManager.getAgentConfig();
193+
194+
this.mcpClient = new SimpleSseMcpClient("http://localhost:5173/api/mcp/sse");
195+
196+
// Only create BrowserAgent once (no file storage involved)
197+
if (agentConfig.browserAgent.enabled) {
198+
this.browserAgent = new BrowserAgent(this.detailView, this.mcpClient, agentConfig.browserAgent.customPrompt);
199+
}
200+
201+
// Create default Eko instance with only BrowserAgent for restore/modify scenarios
202+
const defaultAgents = this.browserAgent ? [this.browserAgent] : [];
203+
this.eko = new Eko({ llms, agents: defaultAgents, callback: this.createCallback() });
170204
}
171205

172206
/**
@@ -187,8 +221,18 @@ export class EkoService {
187221

188222
const configManager = ConfigManager.getInstance();
189223
const llms: LLMs = configManager.getLLMsConfig();
224+
const agentConfig = configManager.getAgentConfig();
190225

191-
this.eko = new Eko({ llms, agents: this.agents, callback: this.createCallback() });
226+
// Recreate BrowserAgent with new config
227+
if (agentConfig.browserAgent.enabled) {
228+
this.browserAgent = new BrowserAgent(this.detailView, this.mcpClient, agentConfig.browserAgent.customPrompt);
229+
} else {
230+
this.browserAgent = null;
231+
}
232+
233+
// Create default Eko instance
234+
const defaultAgents = this.browserAgent ? [this.browserAgent] : [];
235+
this.eko = new Eko({ llms, agents: defaultAgents, callback: this.createCallback() });
192236

193237
if (this.mainWindow && !this.mainWindow.isDestroyed()) {
194238
this.mainWindow.webContents.send('eko-config-reloaded', {
@@ -199,14 +243,15 @@ export class EkoService {
199243
}
200244

201245
async run(message: string): Promise<EkoResult | null> {
202-
if (!this.eko) {
203-
console.error('[EkoService] Eko service not initialized');
204-
this.sendErrorToFrontend('Eko service not initialized');
205-
return null;
206-
}
207-
208246
try {
209-
return await this.eko.run(message);
247+
// Generate unique taskId for this execution
248+
const taskId = randomUUID();
249+
250+
// Create Eko instance with task-specific work directory
251+
this.eko = this.createEkoForTask(taskId);
252+
253+
// Execute with the specified taskId
254+
return await this.eko.run(message, taskId);
210255
} catch (error: any) {
211256
console.error('[EkoService] Run error:', error);
212257
this.sendErrorToFrontend(error?.message || 'Unknown error occurred', error);
@@ -325,20 +370,20 @@ export class EkoService {
325370
chainPlanRequest?: any,
326371
chainPlanResult?: string
327372
): Promise<string | null> {
328-
if (!this.eko) {
329-
console.error('[EkoService] Eko service not initialized');
330-
return null;
331-
}
332-
333373
try {
374+
const taskId = workflow.taskId;
375+
376+
// Create Eko instance with task-specific work directory for restored task
377+
this.eko = this.createEkoForTask(taskId);
378+
334379
const context = await this.eko.initContext(workflow, contextParams);
335380

336381
if (chainPlanRequest && chainPlanResult) {
337382
context.chain.planRequest = chainPlanRequest;
338383
context.chain.planResult = chainPlanResult;
339384
}
340385

341-
return workflow.taskId;
386+
return taskId;
342387
} catch (error: any) {
343388
console.error('[EkoService] Failed to restore task:', error);
344389
return null;

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ai-browser",
3-
"version": "0.0.12",
3+
"version": "0.0.13",
44
"description": "DeepFundAI Browser - AI-Powered Intelligent Browser",
55
"author": "Shuai Liu <lsustc@mail.ustc.edu.cn>",
66
"license": "MIT",
@@ -30,7 +30,7 @@
3030
"@ant-design/cssinjs": "^1.23.0",
3131
"@ant-design/icons": "5.x",
3232
"@jarvis-agent/core": "^0.1.5",
33-
"@jarvis-agent/electron": "^0.1.10",
33+
"@jarvis-agent/electron": "^0.1.11",
3434
"@jest/globals": "^30.1.2",
3535
"@react-spring/web": "^10.0.1",
3636
"antd": "^5.26.5",
@@ -48,9 +48,9 @@
4848
"immer": "^10.2.0",
4949
"json-schema": "^0.4.0",
5050
"microsoft-cognitiveservices-speech-sdk": "^1.45.0",
51-
"next": "15.4.1",
52-
"react": "19.1.0",
53-
"react-dom": "19.1.0",
51+
"next": "15.4.8",
52+
"react": "19.1.2",
53+
"react-dom": "19.1.2",
5454
"react-i18next": "^16.2.3",
5555
"react-icons": "^5.5.0",
5656
"react-markdown": "^10.1.0",

0 commit comments

Comments
 (0)