@eko-ai/eko 1.0.1 → 1.0.3
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 +56 -44
- package/dist/core/eko.d.ts +1 -0
- package/dist/core/tool-registry.d.ts +1 -1
- package/dist/extension/content/index.d.ts +12 -4
- package/dist/extension/index.d.ts +0 -2
- package/dist/extension/script/build_dom_tree.d.ts +38 -0
- package/dist/extension/script/build_dom_tree.js +7 -3
- package/dist/extension/tools/browser.d.ts +8 -8
- package/dist/extension/tools/browser_use.d.ts +1 -0
- package/dist/extension/tools/html_script.d.ts +1 -12
- package/dist/extension/tools/index.d.ts +1 -2
- package/dist/extension.cjs.js +171 -346
- package/dist/extension.esm.js +172 -346
- package/dist/extension_content_script.js +105 -76
- package/dist/index.cjs.js +59 -49
- package/dist/index.esm.js +59 -49
- package/dist/models/action.d.ts +3 -2
- package/dist/nodejs/core.d.ts +2 -0
- package/dist/nodejs/index.d.ts +1 -0
- package/dist/nodejs/tools/command_execute.d.ts +12 -0
- package/dist/nodejs/tools/file_read.d.ts +11 -0
- package/dist/nodejs/tools/file_write.d.ts +15 -0
- package/dist/nodejs/tools/index.d.ts +3 -1
- package/dist/nodejs.cjs.js +227 -3
- package/dist/nodejs.esm.js +226 -3
- package/dist/schemas/workflow.schema.d.ts +3 -0
- package/dist/services/llm/claude-provider.d.ts +1 -0
- package/dist/services/llm/openai-provider.d.ts +1 -0
- package/dist/types/action.types.d.ts +2 -0
- package/dist/web/core.d.ts +2 -0
- package/dist/web/index.d.ts +1 -0
- package/dist/web/script/build_dom_tree.d.ts +10 -0
- package/dist/web/tools/browser.d.ts +20 -0
- package/dist/web/tools/browser_use.d.ts +19 -0
- package/dist/web/tools/element_click.d.ts +12 -0
- package/dist/web/tools/export_file.d.ts +18 -0
- package/dist/web/tools/extract_content.d.ts +17 -0
- package/dist/web/tools/find_element_position.d.ts +12 -0
- package/dist/web/tools/html_script.d.ts +10 -0
- package/dist/web/tools/index.d.ts +7 -1
- package/dist/web/tools/screenshot.d.ts +18 -0
- package/dist/web.cjs.js +9377 -3
- package/dist/web.esm.js +9376 -3
- package/package.json +2 -1
package/dist/index.esm.js
CHANGED
|
@@ -165,9 +165,10 @@ function createReturnTool(outputSchema) {
|
|
|
165
165
|
}
|
|
166
166
|
class ActionImpl {
|
|
167
167
|
constructor(type, // Only support prompt type
|
|
168
|
-
name, tools, llmProvider, llmConfig, config) {
|
|
168
|
+
name, description, tools, llmProvider, llmConfig, config) {
|
|
169
169
|
this.type = type;
|
|
170
170
|
this.name = name;
|
|
171
|
+
this.description = description;
|
|
171
172
|
this.tools = tools;
|
|
172
173
|
this.llmProvider = llmProvider;
|
|
173
174
|
this.llmConfig = llmConfig;
|
|
@@ -191,7 +192,6 @@ class ActionImpl {
|
|
|
191
192
|
const handler = {
|
|
192
193
|
onContent: (content) => {
|
|
193
194
|
if (content.trim()) {
|
|
194
|
-
console.log('LLM:', content);
|
|
195
195
|
assistantTextMessage += content;
|
|
196
196
|
}
|
|
197
197
|
},
|
|
@@ -309,12 +309,10 @@ class ActionImpl {
|
|
|
309
309
|
(_a = context.tools) === null || _a === void 0 ? void 0 : _a.forEach((tool) => toolMap.set(tool.name, tool));
|
|
310
310
|
toolMap.set(returnTool.name, returnTool);
|
|
311
311
|
// Prepare initial messages
|
|
312
|
-
const messages =
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
]
|
|
317
|
-
: [{ role: 'user', content: this.formatSystemPrompt(context) }];
|
|
312
|
+
const messages = [
|
|
313
|
+
{ role: 'system', content: this.formatSystemPrompt() },
|
|
314
|
+
{ role: 'user', content: this.formatUserPrompt(context, input) },
|
|
315
|
+
];
|
|
318
316
|
console.log('Starting LLM conversation...');
|
|
319
317
|
console.log('Initial messages:', messages);
|
|
320
318
|
console.log('Output schema:', outputSchema);
|
|
@@ -339,6 +337,7 @@ class ActionImpl {
|
|
|
339
337
|
if (!hasToolUse && response) {
|
|
340
338
|
// LLM sent a message without using tools - request explicit return
|
|
341
339
|
console.log('No tool use detected, requesting explicit return');
|
|
340
|
+
console.log('Response:', response);
|
|
342
341
|
const returnOnlyParams = {
|
|
343
342
|
...params,
|
|
344
343
|
tools: [
|
|
@@ -391,32 +390,30 @@ class ActionImpl {
|
|
|
391
390
|
}
|
|
392
391
|
return output;
|
|
393
392
|
}
|
|
394
|
-
formatSystemPrompt(
|
|
393
|
+
formatSystemPrompt() {
|
|
394
|
+
return `You are a task executor. You need to complete the task specified by the user, using the tools provided. When you need to store results or outputs, use the write_context tool. When you are ready to return the final output, use the return_output tool.
|
|
395
|
+
|
|
396
|
+
Remember to:
|
|
397
|
+
1. Use tools when needed to accomplish the task
|
|
398
|
+
2. Store important results using write_context, including intermediate and final results
|
|
399
|
+
3. Think step by step about what needs to be done`;
|
|
400
|
+
}
|
|
401
|
+
formatUserPrompt(context, input) {
|
|
395
402
|
// Create a description of the current context
|
|
396
403
|
const contextDescription = Array.from(context.variables.entries())
|
|
397
404
|
.map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
|
|
398
405
|
.join('\n');
|
|
399
|
-
return `You are executing the action "${this.name}". You have access to the following context:
|
|
400
|
-
|
|
401
|
-
${contextDescription || 'No context variables set'}
|
|
406
|
+
return `You are executing the action "${this.name}". The specific instructions are: "${this.description}". You have access to the following context:
|
|
402
407
|
|
|
403
|
-
|
|
404
|
-
use the write_context tool to save them to the workflow context.
|
|
408
|
+
${contextDescription || 'No context variables set'}
|
|
405
409
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
3. Think step by step about what needs to be done`;
|
|
410
|
-
}
|
|
411
|
-
formatUserPrompt(input) {
|
|
412
|
-
if (typeof input === 'string') {
|
|
413
|
-
return input;
|
|
414
|
-
}
|
|
415
|
-
return JSON.stringify(input, null, 2);
|
|
410
|
+
You have been provided with the following input:
|
|
411
|
+
${(typeof input === 'string' ? input : JSON.stringify(input, null, 2)) || 'No additional input provided'}
|
|
412
|
+
`;
|
|
416
413
|
}
|
|
417
414
|
// Static factory method
|
|
418
|
-
static createPromptAction(name, tools, llmProvider, llmConfig) {
|
|
419
|
-
return new ActionImpl('prompt', name, tools, llmProvider, llmConfig);
|
|
415
|
+
static createPromptAction(name, description, tools, llmProvider, llmConfig) {
|
|
416
|
+
return new ActionImpl('prompt', name, description, tools, llmProvider, llmConfig);
|
|
420
417
|
}
|
|
421
418
|
}
|
|
422
419
|
|
|
@@ -440,7 +437,8 @@ Generate a complete workflow that:
|
|
|
440
437
|
1. Only uses the tools listed above
|
|
441
438
|
2. Properly sequences tool usage based on dependencies
|
|
442
439
|
3. Ensures each action has appropriate input/output schemas
|
|
443
|
-
4. Creates a clear, logical flow to accomplish the user's goal
|
|
440
|
+
4. Creates a clear, logical flow to accomplish the user's goal
|
|
441
|
+
5. Includes detailed descriptions for each action, ensuring that the actions, when combined, is a complete solution to the user's problem`;
|
|
444
442
|
},
|
|
445
443
|
formatUserPrompt: (requirement) => `Create a workflow for the following requirement: ${requirement}`,
|
|
446
444
|
};
|
|
@@ -560,7 +558,7 @@ class WorkflowGenerator {
|
|
|
560
558
|
if (Array.isArray(data.nodes)) {
|
|
561
559
|
data.nodes.forEach((nodeData) => {
|
|
562
560
|
const tools = nodeData.action.tools.map((toolName) => this.toolRegistry.getTool(toolName));
|
|
563
|
-
const action = ActionImpl.createPromptAction(nodeData.action.name, tools, this.llmProvider, { maxTokens: 1000 });
|
|
561
|
+
const action = ActionImpl.createPromptAction(nodeData.action.name, nodeData.action.description, tools, this.llmProvider, { maxTokens: 1000 });
|
|
564
562
|
const node = {
|
|
565
563
|
id: nodeData.id,
|
|
566
564
|
name: nodeData.name || nodeData.id,
|
|
@@ -3282,16 +3280,21 @@ Anthropic.ModelInfosPage = ModelInfosPage;
|
|
|
3282
3280
|
Anthropic.Beta = Beta$1;
|
|
3283
3281
|
|
|
3284
3282
|
class ClaudeProvider {
|
|
3285
|
-
constructor(
|
|
3283
|
+
constructor(param, defaultModel, options) {
|
|
3286
3284
|
this.defaultModel = 'claude-3-5-sonnet-20241022';
|
|
3287
3285
|
if (defaultModel) {
|
|
3288
3286
|
this.defaultModel = defaultModel;
|
|
3289
3287
|
}
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3288
|
+
if (typeof param == 'string') {
|
|
3289
|
+
this.client = new Anthropic({
|
|
3290
|
+
apiKey: param,
|
|
3291
|
+
dangerouslyAllowBrowser: true,
|
|
3292
|
+
...options,
|
|
3293
|
+
});
|
|
3294
|
+
}
|
|
3295
|
+
else {
|
|
3296
|
+
this.client = new Anthropic(param);
|
|
3297
|
+
}
|
|
3295
3298
|
}
|
|
3296
3299
|
processResponse(response) {
|
|
3297
3300
|
const toolCalls = response.content
|
|
@@ -3385,7 +3388,7 @@ class ClaudeProvider {
|
|
|
3385
3388
|
const toolCall = {
|
|
3386
3389
|
id: currentToolUse.id,
|
|
3387
3390
|
name: currentToolUse.name,
|
|
3388
|
-
input: JSON.parse(currentToolUse.accumulatedJson),
|
|
3391
|
+
input: JSON.parse(currentToolUse.accumulatedJson || '{}'),
|
|
3389
3392
|
};
|
|
3390
3393
|
(_d = handler.onToolUse) === null || _d === void 0 ? void 0 : _d.call(handler, toolCall);
|
|
3391
3394
|
currentToolUse = null;
|
|
@@ -8684,16 +8687,21 @@ OpenAI.BatchesPage = BatchesPage;
|
|
|
8684
8687
|
OpenAI.Uploads = Uploads;
|
|
8685
8688
|
|
|
8686
8689
|
class OpenaiProvider {
|
|
8687
|
-
constructor(
|
|
8690
|
+
constructor(param, defaultModel, options) {
|
|
8688
8691
|
this.defaultModel = 'gpt-4o';
|
|
8689
8692
|
if (defaultModel) {
|
|
8690
8693
|
this.defaultModel = defaultModel;
|
|
8691
8694
|
}
|
|
8692
|
-
|
|
8693
|
-
|
|
8694
|
-
|
|
8695
|
-
|
|
8696
|
-
|
|
8695
|
+
if (typeof param == 'string') {
|
|
8696
|
+
this.client = new OpenAI({
|
|
8697
|
+
apiKey: param,
|
|
8698
|
+
dangerouslyAllowBrowser: true,
|
|
8699
|
+
...options,
|
|
8700
|
+
});
|
|
8701
|
+
}
|
|
8702
|
+
else {
|
|
8703
|
+
this.client = new OpenAI(param);
|
|
8704
|
+
}
|
|
8697
8705
|
}
|
|
8698
8706
|
buildParams(messages, params, stream) {
|
|
8699
8707
|
let tools = undefined;
|
|
@@ -8971,7 +8979,7 @@ const workflowSchema = {
|
|
|
8971
8979
|
},
|
|
8972
8980
|
action: {
|
|
8973
8981
|
type: "object",
|
|
8974
|
-
required: ["type", "name"],
|
|
8982
|
+
required: ["type", "name", "description"],
|
|
8975
8983
|
properties: {
|
|
8976
8984
|
type: {
|
|
8977
8985
|
type: "string",
|
|
@@ -8979,6 +8987,7 @@ const workflowSchema = {
|
|
|
8979
8987
|
enum: ["prompt"],
|
|
8980
8988
|
},
|
|
8981
8989
|
name: { type: "string" },
|
|
8990
|
+
description: { type: "string" },
|
|
8982
8991
|
params: { type: "object" },
|
|
8983
8992
|
tools: {
|
|
8984
8993
|
type: "array",
|
|
@@ -9002,16 +9011,10 @@ class ToolRegistry {
|
|
|
9002
9011
|
this.tools = new Map();
|
|
9003
9012
|
}
|
|
9004
9013
|
registerTool(tool) {
|
|
9005
|
-
if (this.tools.has(tool.name)) {
|
|
9006
|
-
throw new Error(`Tool with name ${tool.name} already registered`);
|
|
9007
|
-
}
|
|
9008
9014
|
this.tools.set(tool.name, tool);
|
|
9009
9015
|
}
|
|
9010
9016
|
unregisterTool(toolName) {
|
|
9011
|
-
|
|
9012
|
-
throw new Error(`Tool with name ${toolName} not found`);
|
|
9013
|
-
}
|
|
9014
|
-
this.tools.delete(toolName);
|
|
9017
|
+
return this.tools.delete(toolName);
|
|
9015
9018
|
}
|
|
9016
9019
|
getTool(toolName) {
|
|
9017
9020
|
const tool = this.tools.get(toolName);
|
|
@@ -9077,6 +9080,7 @@ class Eko {
|
|
|
9077
9080
|
else {
|
|
9078
9081
|
this.llmProvider = config;
|
|
9079
9082
|
}
|
|
9083
|
+
Eko.tools.forEach((tool) => this.toolRegistry.registerTool(tool));
|
|
9080
9084
|
}
|
|
9081
9085
|
async generateWorkflow(prompt, param) {
|
|
9082
9086
|
let toolRegistry = this.toolRegistry;
|
|
@@ -9103,6 +9107,9 @@ class Eko {
|
|
|
9103
9107
|
if (this.toolRegistry.hasTools([toolName])) {
|
|
9104
9108
|
tool = this.toolRegistry.getTool(toolName);
|
|
9105
9109
|
}
|
|
9110
|
+
else if (Eko.tools.has(toolName)) {
|
|
9111
|
+
tool = Eko.tools.get(toolName);
|
|
9112
|
+
}
|
|
9106
9113
|
else {
|
|
9107
9114
|
throw new Error(`Tool with name ${toolName} not found`);
|
|
9108
9115
|
}
|
|
@@ -9131,6 +9138,7 @@ class Eko {
|
|
|
9131
9138
|
this.toolRegistry.unregisterTool(toolName);
|
|
9132
9139
|
}
|
|
9133
9140
|
}
|
|
9141
|
+
Eko.tools = new Map();
|
|
9134
9142
|
|
|
9135
9143
|
class WorkflowParser {
|
|
9136
9144
|
/**
|
|
@@ -9289,6 +9297,7 @@ class WorkflowParser {
|
|
|
9289
9297
|
action: {
|
|
9290
9298
|
type: nodeJson.action.type,
|
|
9291
9299
|
name: nodeJson.action.name,
|
|
9300
|
+
description: nodeJson.action.description,
|
|
9292
9301
|
tools: nodeJson.action.tools || [],
|
|
9293
9302
|
execute: async (input, context) => {
|
|
9294
9303
|
// Default implementation - should be overridden by specific action types
|
|
@@ -9319,6 +9328,7 @@ class WorkflowParser {
|
|
|
9319
9328
|
action: {
|
|
9320
9329
|
type: node.action.type,
|
|
9321
9330
|
name: node.action.name,
|
|
9331
|
+
description: node.action.description,
|
|
9322
9332
|
tools: node.action.tools,
|
|
9323
9333
|
},
|
|
9324
9334
|
})),
|
package/dist/models/action.d.ts
CHANGED
|
@@ -3,18 +3,19 @@ import { LLMProvider, LLMParameters } from '../types/llm.types';
|
|
|
3
3
|
export declare class ActionImpl implements Action {
|
|
4
4
|
type: 'prompt';
|
|
5
5
|
name: string;
|
|
6
|
+
description: string;
|
|
6
7
|
tools: Tool<any, any>[];
|
|
7
8
|
private llmProvider;
|
|
8
9
|
private llmConfig?;
|
|
9
10
|
private readonly maxRounds;
|
|
10
11
|
private writeContextTool;
|
|
11
12
|
constructor(type: 'prompt', // Only support prompt type
|
|
12
|
-
name: string, tools: Tool<any, any>[], llmProvider: LLMProvider, llmConfig?: LLMParameters | undefined, config?: {
|
|
13
|
+
name: string, description: string, tools: Tool<any, any>[], llmProvider: LLMProvider, llmConfig?: LLMParameters | undefined, config?: {
|
|
13
14
|
maxRounds?: number;
|
|
14
15
|
});
|
|
15
16
|
private executeSingleRound;
|
|
16
17
|
execute(input: unknown, context: ExecutionContext, outputSchema?: unknown): Promise<unknown>;
|
|
17
18
|
private formatSystemPrompt;
|
|
18
19
|
private formatUserPrompt;
|
|
19
|
-
static createPromptAction(name: string, tools: Tool<any, any>[], llmProvider: LLMProvider, llmConfig?: LLMParameters): Action;
|
|
20
|
+
static createPromptAction(name: string, description: string, tools: Tool<any, any>[], llmProvider: LLMProvider, llmConfig?: LLMParameters): Action;
|
|
20
21
|
}
|
package/dist/nodejs/index.d.ts
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Tool, InputSchema, ExecutionContext } from '../../types/action.types';
|
|
2
|
+
export interface CommandExecuteParams {
|
|
3
|
+
command: string;
|
|
4
|
+
cwd?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class CommandExecute implements Tool<CommandExecuteParams, any> {
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
input_schema: InputSchema;
|
|
10
|
+
private getUserConfirmation;
|
|
11
|
+
execute(context: ExecutionContext, params: CommandExecuteParams): Promise<any>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Tool, InputSchema, ExecutionContext } from '../../types/action.types';
|
|
2
|
+
export interface FileReadParams {
|
|
3
|
+
path: string;
|
|
4
|
+
encoding?: BufferEncoding;
|
|
5
|
+
}
|
|
6
|
+
export declare class FileRead implements Tool<FileReadParams, any> {
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
input_schema: InputSchema;
|
|
10
|
+
execute(context: ExecutionContext, params: FileReadParams): Promise<any>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Tool, InputSchema, ExecutionContext } from '../../types/action.types';
|
|
2
|
+
export interface FileWriteParams {
|
|
3
|
+
path: string;
|
|
4
|
+
content: string;
|
|
5
|
+
append?: boolean;
|
|
6
|
+
encoding?: BufferEncoding;
|
|
7
|
+
}
|
|
8
|
+
export declare class FileWrite implements Tool<FileWriteParams, any> {
|
|
9
|
+
name: string;
|
|
10
|
+
description: string;
|
|
11
|
+
input_schema: InputSchema;
|
|
12
|
+
private checkFileExists;
|
|
13
|
+
private getUserConfirmation;
|
|
14
|
+
execute(context: ExecutionContext, params: FileWriteParams): Promise<any>;
|
|
15
|
+
}
|
package/dist/nodejs.cjs.js
CHANGED
|
@@ -1,7 +1,231 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
|
|
3
|
+
var readline = require('readline');
|
|
4
|
+
var child_process = require('child_process');
|
|
5
|
+
var util = require('util');
|
|
6
|
+
var promises = require('fs/promises');
|
|
7
|
+
var path = require('path');
|
|
8
|
+
var fs = require('fs');
|
|
9
|
+
|
|
10
|
+
const execAsync = util.promisify(child_process.exec);
|
|
11
|
+
class CommandExecute {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.name = 'command_execute';
|
|
14
|
+
this.description = 'Execute a shell command with user confirmation';
|
|
15
|
+
this.input_schema = {
|
|
16
|
+
type: 'object',
|
|
17
|
+
properties: {
|
|
18
|
+
command: {
|
|
19
|
+
type: 'string',
|
|
20
|
+
description: 'The command to execute. Ensure that the command is non-interactive and does not require user input.'
|
|
21
|
+
},
|
|
22
|
+
cwd: {
|
|
23
|
+
type: 'string',
|
|
24
|
+
description: 'Working directory for command execution'
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
required: ['command']
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
async getUserConfirmation(command) {
|
|
31
|
+
const rl = readline.createInterface({
|
|
32
|
+
input: process.stdin,
|
|
33
|
+
output: process.stdout
|
|
34
|
+
});
|
|
35
|
+
return new Promise(resolve => {
|
|
36
|
+
rl.question(`Are you sure you want to execute command: "${command}"? (y/N) `, answer => {
|
|
37
|
+
rl.close();
|
|
38
|
+
resolve(answer.toLowerCase() === 'y');
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
async execute(context, params) {
|
|
43
|
+
const confirmed = await this.getUserConfirmation(params.command);
|
|
44
|
+
if (!confirmed) {
|
|
45
|
+
return {
|
|
46
|
+
executed: false,
|
|
47
|
+
reason: 'User cancelled execution'
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
const { stdout, stderr } = await execAsync(params.command, {
|
|
52
|
+
cwd: params.cwd
|
|
53
|
+
});
|
|
54
|
+
return {
|
|
55
|
+
executed: true,
|
|
56
|
+
stdout,
|
|
57
|
+
stderr
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
const err = error;
|
|
62
|
+
return {
|
|
63
|
+
executed: false,
|
|
64
|
+
error: err.message,
|
|
65
|
+
code: err.code,
|
|
66
|
+
stderr: err.stderr
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
class FileRead {
|
|
73
|
+
constructor() {
|
|
74
|
+
this.name = 'file_read';
|
|
75
|
+
this.description = 'Read content from a file';
|
|
76
|
+
this.input_schema = {
|
|
77
|
+
type: 'object',
|
|
78
|
+
properties: {
|
|
79
|
+
path: {
|
|
80
|
+
type: 'string',
|
|
81
|
+
description: 'Path to the file to read'
|
|
82
|
+
},
|
|
83
|
+
encoding: {
|
|
84
|
+
type: 'string',
|
|
85
|
+
description: 'File encoding (default: utf8)',
|
|
86
|
+
enum: ['utf8', 'ascii', 'utf16le', 'base64', 'binary']
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
required: ['path']
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
async execute(context, params) {
|
|
93
|
+
try {
|
|
94
|
+
const fullPath = path.resolve(params.path);
|
|
95
|
+
const content = await promises.readFile(fullPath, {
|
|
96
|
+
encoding: params.encoding || 'utf8'
|
|
97
|
+
});
|
|
98
|
+
return {
|
|
99
|
+
success: true,
|
|
100
|
+
path: fullPath,
|
|
101
|
+
content
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
const err = error;
|
|
106
|
+
return {
|
|
107
|
+
success: false,
|
|
108
|
+
error: err.message,
|
|
109
|
+
code: err.code
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
class FileWrite {
|
|
116
|
+
constructor() {
|
|
117
|
+
this.name = 'file_write';
|
|
118
|
+
this.description = 'Write content to a file with user confirmation';
|
|
119
|
+
this.input_schema = {
|
|
120
|
+
type: 'object',
|
|
121
|
+
properties: {
|
|
122
|
+
path: {
|
|
123
|
+
type: 'string',
|
|
124
|
+
description: 'Path to write the file'
|
|
125
|
+
},
|
|
126
|
+
content: {
|
|
127
|
+
type: 'string',
|
|
128
|
+
description: 'Content to write to the file'
|
|
129
|
+
},
|
|
130
|
+
append: {
|
|
131
|
+
type: 'boolean',
|
|
132
|
+
description: 'Whether to append to existing file (default: false)'
|
|
133
|
+
},
|
|
134
|
+
encoding: {
|
|
135
|
+
type: 'string',
|
|
136
|
+
description: 'File encoding (default: utf8)',
|
|
137
|
+
enum: ['utf8', 'ascii', 'utf16le', 'base64', 'binary']
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
required: ['path', 'content']
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
async checkFileExists(path) {
|
|
144
|
+
try {
|
|
145
|
+
await promises.access(path, fs.constants.F_OK);
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
catch (_a) {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
async getUserConfirmation(path, exists, append) {
|
|
153
|
+
const rl = readline.createInterface({
|
|
154
|
+
input: process.stdin,
|
|
155
|
+
output: process.stdout
|
|
156
|
+
});
|
|
157
|
+
const action = exists
|
|
158
|
+
? (append ? 'append to' : 'overwrite')
|
|
159
|
+
: 'create';
|
|
160
|
+
return new Promise(resolve => {
|
|
161
|
+
rl.question(`Are you sure you want to ${action} file at "${path}"? (y/N) `, answer => {
|
|
162
|
+
rl.close();
|
|
163
|
+
resolve(answer.toLowerCase() === 'y');
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
async execute(context, params) {
|
|
168
|
+
try {
|
|
169
|
+
const fullPath = path.resolve(params.path);
|
|
170
|
+
const exists = await this.checkFileExists(fullPath);
|
|
171
|
+
const append = params.append || false;
|
|
172
|
+
const confirmed = await this.getUserConfirmation(fullPath, exists, append);
|
|
173
|
+
if (!confirmed) {
|
|
174
|
+
return {
|
|
175
|
+
success: false,
|
|
176
|
+
reason: 'User cancelled operation'
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
if (append) {
|
|
180
|
+
await promises.appendFile(fullPath, params.content, {
|
|
181
|
+
encoding: params.encoding || 'utf8'
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
await promises.writeFile(fullPath, params.content, {
|
|
186
|
+
encoding: params.encoding || 'utf8'
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
success: true,
|
|
191
|
+
path: fullPath,
|
|
192
|
+
action: append ? 'append' : 'write'
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
const err = error;
|
|
197
|
+
return {
|
|
198
|
+
success: false,
|
|
199
|
+
error: err.message,
|
|
200
|
+
code: err.code
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
var tools = /*#__PURE__*/Object.freeze({
|
|
207
|
+
__proto__: null,
|
|
208
|
+
CommandExecute: CommandExecute,
|
|
209
|
+
FileRead: FileRead,
|
|
210
|
+
FileWrite: FileWrite
|
|
5
211
|
});
|
|
6
212
|
|
|
7
|
-
|
|
213
|
+
function getAllTools() {
|
|
214
|
+
let toolsMap = new Map();
|
|
215
|
+
for (const key in tools) {
|
|
216
|
+
let tool = tools[key];
|
|
217
|
+
if (typeof tool === 'function' && tool.prototype && 'execute' in tool.prototype) {
|
|
218
|
+
try {
|
|
219
|
+
let instance = new tool();
|
|
220
|
+
toolsMap.set(instance.name || key, instance);
|
|
221
|
+
}
|
|
222
|
+
catch (e) {
|
|
223
|
+
console.error(`Failed to instantiate ${key}:`, e);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return toolsMap;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
exports.getAllTools = getAllTools;
|
|
231
|
+
exports.tools = tools;
|