@jclaw/core 0.6.1 → 0.7.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/dist/cli/jclaw.js.backup +212 -0
- package/dist/runtime/agent.d.ts.map +1 -1
- package/dist/runtime/agent.js +2 -1
- package/dist/runtime/task-executor.d.ts +5 -73
- package/dist/runtime/task-executor.d.ts.map +1 -1
- package/dist/runtime/task-executor.js +77 -138
- package/dist/runtime/task-executor.js.backup +295 -0
- package/package.json +24 -7
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { JClawAgent } from '../runtime/agent.js';
|
|
3
|
+
import { createSimpleMemoryClient } from '../context/simple-memory-client.js';
|
|
4
|
+
import { readFile, writeFile } from 'fs/promises';
|
|
5
|
+
import { existsSync } from 'fs';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
import { dirname, join } from 'path';
|
|
8
|
+
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = dirname(__filename);
|
|
11
|
+
|
|
12
|
+
// Read version from package.json
|
|
13
|
+
const packageJsonPath = join(__dirname, '../../package.json');
|
|
14
|
+
const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf-8'));
|
|
15
|
+
const VERSION = packageJson.version;
|
|
16
|
+
|
|
17
|
+
const args = process.argv.slice(2);
|
|
18
|
+
const command = args[0];
|
|
19
|
+
|
|
20
|
+
function showHelp() {
|
|
21
|
+
console.log(`
|
|
22
|
+
🧬 JClaw - Universal Self-Evolving Agent Framework
|
|
23
|
+
|
|
24
|
+
用法:
|
|
25
|
+
jclaw <command> [options]
|
|
26
|
+
|
|
27
|
+
命令:
|
|
28
|
+
execute <prompt> 执行任务
|
|
29
|
+
chat 交互模式
|
|
30
|
+
init 初始化项目
|
|
31
|
+
help 显示帮助
|
|
32
|
+
|
|
33
|
+
环境变量:
|
|
34
|
+
LLM_API_KEY API 密钥
|
|
35
|
+
LLM_BASE_URL API 地址
|
|
36
|
+
LLM_MODEL_NAME 模型名称
|
|
37
|
+
`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function loadLLMConfig() {
|
|
41
|
+
if (existsSync('./jclaw.config.js')) {
|
|
42
|
+
try {
|
|
43
|
+
const config = await import('./jclaw.config.js');
|
|
44
|
+
const { llm, providers } = config.default || config;
|
|
45
|
+
if (llm && llm.provider && providers && providers[llm.provider]) {
|
|
46
|
+
const provider = providers[llm.provider];
|
|
47
|
+
const apiKey = process.env[provider.apiKeyEnv];
|
|
48
|
+
if (!apiKey) {
|
|
49
|
+
console.error(`❌ 请设置 ${provider.apiKeyEnv}`);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
apiBase: provider.baseURL,
|
|
54
|
+
apiKey: apiKey,
|
|
55
|
+
model: llm.model || provider.models[0]
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
if (llm && llm.apiKey) {
|
|
59
|
+
return {
|
|
60
|
+
apiBase: llm.apiBase || 'https://api.openai.com/v1',
|
|
61
|
+
apiKey: llm.apiKey,
|
|
62
|
+
model: llm.model || 'gpt-4'
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
} catch (e) {}
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function getLLMConfig() {
|
|
71
|
+
const configFile = await loadLLMConfig();
|
|
72
|
+
if (configFile) return configFile;
|
|
73
|
+
|
|
74
|
+
if (process.env.LLM_API_KEY) {
|
|
75
|
+
return {
|
|
76
|
+
apiBase: process.env.LLM_BASE_URL || 'https://api.openai.com/v1',
|
|
77
|
+
apiKey: process.env.LLM_API_KEY,
|
|
78
|
+
model: process.env.LLM_MODEL_NAME || 'gpt-4',
|
|
79
|
+
temperature: process.env.LLM_TEMPERATURE ? parseFloat(process.env.LLM_TEMPERATURE) : 1.0
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (process.env.OPENAI_API_KEY) {
|
|
84
|
+
return {
|
|
85
|
+
apiBase: process.env.LLM_BASE_URL || 'https://api.openai.com/v1',
|
|
86
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
87
|
+
model: process.env.LLM_MODEL_NAME || 'gpt-4',
|
|
88
|
+
temperature: process.env.LLM_TEMPERATURE ? parseFloat(process.env.LLM_TEMPERATURE) : 1.0
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
console.error('❌ 请设置 LLM_API_KEY 或 OPENAI_API_KEY');
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function execute(prompt) {
|
|
97
|
+
const llmConfig = await getLLMConfig();
|
|
98
|
+
console.log('🧬 启动 JClaw...\n');
|
|
99
|
+
console.log(`📡 模型:${llmConfig.model}`);
|
|
100
|
+
console.log(`🔌 API: ${llmConfig.apiBase}\n`);
|
|
101
|
+
|
|
102
|
+
const agent = new JClawAgent({
|
|
103
|
+
name: 'jclaw-cli',
|
|
104
|
+
version: VERSION,
|
|
105
|
+
enableAutoSkill: true,
|
|
106
|
+
skillShConfig: { enableCache: true },
|
|
107
|
+
llm: llmConfig,
|
|
108
|
+
contextManager: createSimpleMemoryClient({
|
|
109
|
+
enableSynonyms: true,
|
|
110
|
+
enableFuzzyMatch: true
|
|
111
|
+
})
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
await agent.start();
|
|
115
|
+
console.log('✅ JClaw 已启动\n');
|
|
116
|
+
console.log('📝 任务:', prompt, '\n');
|
|
117
|
+
|
|
118
|
+
const result = await agent.execute({ id: 'cli-task', prompt });
|
|
119
|
+
|
|
120
|
+
console.log('\n✅ 结果:\n');
|
|
121
|
+
console.log(result.output || result.error);
|
|
122
|
+
await agent.stop();
|
|
123
|
+
console.log('\n🎉 完成!\n');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async function chat() {
|
|
127
|
+
const llmConfig = await getLLMConfig();
|
|
128
|
+
console.log('🧬 JClaw 交互模式 (输入 "exit" 退出)\n');
|
|
129
|
+
console.log(`📡 模型:${llmConfig.model}\n`);
|
|
130
|
+
|
|
131
|
+
const agent = new JClawAgent({ name: 'jclaw-chat', version: VERSION, enableAutoSkill: true, llm: llmConfig });
|
|
132
|
+
await agent.start();
|
|
133
|
+
|
|
134
|
+
const readline = await import('readline');
|
|
135
|
+
const rl = readline.createInterface({
|
|
136
|
+
input: process.stdin,
|
|
137
|
+
output: process.stdout
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
const ask = () => {
|
|
141
|
+
rl.question('你:', async (input) => {
|
|
142
|
+
if (input.toLowerCase() === 'exit') {
|
|
143
|
+
await agent.stop();
|
|
144
|
+
rl.close();
|
|
145
|
+
console.log('\n👋 再见!\n');
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
console.log('\n🤖 JClaw:\n');
|
|
149
|
+
const result = await agent.execute({ id: 'chat', prompt: input });
|
|
150
|
+
console.log(result.output || result.error);
|
|
151
|
+
console.log('');
|
|
152
|
+
ask();
|
|
153
|
+
});
|
|
154
|
+
};
|
|
155
|
+
ask();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async function init() {
|
|
159
|
+
console.log('🧬 初始化 JClaw 项目...\n');
|
|
160
|
+
const configTemplate = `export default {
|
|
161
|
+
enableAutoSkill: true,
|
|
162
|
+
llm: { provider: 'openai', model: 'gpt-4' },
|
|
163
|
+
providers: {
|
|
164
|
+
'openai': {
|
|
165
|
+
baseURL: 'https://api.openai.com/v1',
|
|
166
|
+
apiKeyEnv: 'OPENAI_API_KEY',
|
|
167
|
+
models: ['gpt-4', 'gpt-4o']
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
`;
|
|
172
|
+
if (!existsSync('jclaw.config.js')) {
|
|
173
|
+
await writeFile('jclaw.config.js', configTemplate);
|
|
174
|
+
console.log('✅ 创建:jclaw.config.js');
|
|
175
|
+
}
|
|
176
|
+
console.log('\n🎉 初始化完成!\n');
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
switch (command) {
|
|
180
|
+
case 'execute':
|
|
181
|
+
case 'exec':
|
|
182
|
+
case 'e':
|
|
183
|
+
const prompt = args.slice(1).join(' ');
|
|
184
|
+
if (!prompt) {
|
|
185
|
+
console.error('❌ 请提供任务描述');
|
|
186
|
+
process.exit(1);
|
|
187
|
+
}
|
|
188
|
+
execute(prompt);
|
|
189
|
+
break;
|
|
190
|
+
case 'chat':
|
|
191
|
+
case 'c':
|
|
192
|
+
chat();
|
|
193
|
+
break;
|
|
194
|
+
case 'init':
|
|
195
|
+
case 'i':
|
|
196
|
+
init();
|
|
197
|
+
break;
|
|
198
|
+
case 'help':
|
|
199
|
+
case 'h':
|
|
200
|
+
case '--help':
|
|
201
|
+
case '-h':
|
|
202
|
+
showHelp();
|
|
203
|
+
break;
|
|
204
|
+
default:
|
|
205
|
+
if (command) {
|
|
206
|
+
execute(args.join(' '));
|
|
207
|
+
} else {
|
|
208
|
+
showHelp();
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Add temperature env var support
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/runtime/agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElF,OAAO,EAAa,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAOpE,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAGpF,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC9C,GAAG,CAAC,EAAE,eAAe,CAAC;IACtB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAC3C,aAAa,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC9C,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC;AAED,qBAAa,UAAW,YAAW,YAAY;IAC7C,QAAQ,CAAC,aAAa,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACtD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAM;IAC7B,OAAO,CAAC,SAAS,CAAC,CAAY;IAC9B,OAAO,CAAC,YAAY,CAAC,CAAe;IACpC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,kBAAkB,CAAC,CAAqB;IAChD,OAAO,CAAC,kBAAkB,CAAC,CAAqB;IAChD,OAAO,CAAC,cAAc,CAAC,CAAuB;IAC9C,OAAO,CAAC,eAAe,CAAC,CAAkB;IAC1C,OAAO,CAAC,iBAAiB,CAAC,CAAoB;gBAElC,MAAM,GAAE,WAAgB;IAapC,IAAI,OAAO,IAAI,cAAc,CAG5B;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/runtime/agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElF,OAAO,EAAa,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAOpE,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAGpF,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC9C,GAAG,CAAC,EAAE,eAAe,CAAC;IACtB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAC3C,aAAa,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC9C,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC;AAED,qBAAa,UAAW,YAAW,YAAY;IAC7C,QAAQ,CAAC,aAAa,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACtD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAM;IAC7B,OAAO,CAAC,SAAS,CAAC,CAAY;IAC9B,OAAO,CAAC,YAAY,CAAC,CAAe;IACpC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,kBAAkB,CAAC,CAAqB;IAChD,OAAO,CAAC,kBAAkB,CAAC,CAAqB;IAChD,OAAO,CAAC,cAAc,CAAC,CAAuB;IAC9C,OAAO,CAAC,eAAe,CAAC,CAAkB;IAC1C,OAAO,CAAC,iBAAiB,CAAC,CAAoB;gBAElC,MAAM,GAAE,WAAgB;IAapC,IAAI,OAAO,IAAI,cAAc,CAG5B;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAuCtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAOrB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC;YAQhC,oBAAoB;IA6ClC,SAAS,IAAI,OAAO;IACpB,IAAI,IAAI,IAAI,MAAM,CAA6B;IAC/C,IAAI,OAAO,IAAI,MAAM,CAAgC;CACtD;AAED,wBAAgB,WAAW,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,UAAU,CAE5D"}
|
package/dist/runtime/agent.js
CHANGED
|
@@ -46,7 +46,8 @@ export class JClawAgent {
|
|
|
46
46
|
}
|
|
47
47
|
this.taskExecutor = new TaskExecutor({
|
|
48
48
|
llmClient: this.llmClient,
|
|
49
|
-
|
|
49
|
+
contextManager: this.config.contextManager,
|
|
50
|
+
extensionRegistry: this.extensionRegistry,
|
|
50
51
|
verbose: this.config.verbose,
|
|
51
52
|
});
|
|
52
53
|
if (this.config.enableAutoSkill) {
|
|
@@ -1,92 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Task Executor
|
|
3
|
-
*
|
|
4
|
-
* Manages task execution workflow including context retrieval,
|
|
5
|
-
* LLM interaction, and command execution.
|
|
6
|
-
*
|
|
7
|
-
* @module @jclaw/core/runtime/task-executor
|
|
2
|
+
* Task Executor - Enhanced with Capability Support
|
|
8
3
|
*/
|
|
9
4
|
import type { Task, TaskResult, ContextManager, Executor } from '../types.js';
|
|
10
5
|
import { LLMClient } from './llm-client.js';
|
|
11
|
-
|
|
12
|
-
* Configuration for task executor
|
|
13
|
-
*/
|
|
6
|
+
import { ExtensionRegistry } from '../extension-system/registry.js';
|
|
14
7
|
export interface TaskExecutorConfig {
|
|
15
|
-
/** LLM client for generating responses */
|
|
16
8
|
llmClient: LLMClient;
|
|
17
|
-
/** Context manager for knowledge retrieval */
|
|
18
9
|
contextManager?: ContextManager;
|
|
19
|
-
/** Command executor for running shell commands */
|
|
20
10
|
executor?: Executor;
|
|
21
|
-
|
|
11
|
+
extensionRegistry?: ExtensionRegistry;
|
|
22
12
|
systemPrompt?: string;
|
|
23
|
-
/** Maximum retries for failed tasks (default: 3) */
|
|
24
13
|
maxRetries?: number;
|
|
25
|
-
/** Enable verbose logging */
|
|
26
14
|
verbose?: boolean;
|
|
27
15
|
}
|
|
28
|
-
/**
|
|
29
|
-
* Task Executor
|
|
30
|
-
*
|
|
31
|
-
* Orchestrates task execution by:
|
|
32
|
-
* - Retrieving relevant context
|
|
33
|
-
* - Generating plans with LLM
|
|
34
|
-
* - Executing commands when needed
|
|
35
|
-
* - Handling errors and retries
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* ```typescript
|
|
39
|
-
* const executor = new TaskExecutor({
|
|
40
|
-
* llmClient: createLLMClient(config),
|
|
41
|
-
* contextManager: openVikingClient,
|
|
42
|
-
* executor: localExecutor
|
|
43
|
-
* });
|
|
44
|
-
*
|
|
45
|
-
* const result = await executor.execute({
|
|
46
|
-
* id: 'task-1',
|
|
47
|
-
* prompt: 'List all files in the current directory'
|
|
48
|
-
* });
|
|
49
|
-
* ```
|
|
50
|
-
*/
|
|
51
16
|
export declare class TaskExecutor {
|
|
52
17
|
private readonly config;
|
|
53
|
-
/**
|
|
54
|
-
* Create a new task executor instance.
|
|
55
|
-
*
|
|
56
|
-
* @param config - Configuration options
|
|
57
|
-
*/
|
|
58
18
|
constructor(config: TaskExecutorConfig);
|
|
59
|
-
/**
|
|
60
|
-
* Execute a task and return the result.
|
|
61
|
-
*
|
|
62
|
-
* @param task - The task to execute
|
|
63
|
-
* @returns Promise resolving to task result
|
|
64
|
-
*/
|
|
65
19
|
execute(task: Task): Promise<TaskResult>;
|
|
66
|
-
/**
|
|
67
|
-
* Internal method to execute a single task attempt.
|
|
68
|
-
*/
|
|
69
20
|
private executeTask;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
*
|
|
73
|
-
* Looks for commands in code blocks marked as shell/bash.
|
|
74
|
-
*/
|
|
75
|
-
private extractCommands;
|
|
76
|
-
/**
|
|
77
|
-
* Log message if verbose mode is enabled.
|
|
78
|
-
*/
|
|
79
|
-
private log;
|
|
80
|
-
/**
|
|
81
|
-
* Sleep for specified milliseconds.
|
|
82
|
-
*/
|
|
83
|
-
private sleep;
|
|
21
|
+
private buildSystemPrompt;
|
|
22
|
+
private extractCapabilityCall;
|
|
84
23
|
}
|
|
85
|
-
/**
|
|
86
|
-
* Create a new task executor instance.
|
|
87
|
-
*
|
|
88
|
-
* @param config - Configuration options
|
|
89
|
-
* @returns New TaskExecutor instance
|
|
90
|
-
*/
|
|
91
|
-
export declare function createTaskExecutor(config: TaskExecutorConfig): TaskExecutor;
|
|
92
24
|
//# sourceMappingURL=task-executor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-executor.d.ts","sourceRoot":"","sources":["../../src/runtime/task-executor.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"task-executor.d.ts","sourceRoot":"","sources":["../../src/runtime/task-executor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,SAAS,EAAoB,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAKpE,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,SAAS,CAAC;IACrB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAIrB;gBAEU,MAAM,EAAE,kBAAkB;IAIhC,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC;YAsBhC,WAAW;IAkDzB,OAAO,CAAC,iBAAiB;IAyBzB,OAAO,CAAC,qBAAqB;CAuC/B"}
|
|
@@ -1,202 +1,141 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Task Executor
|
|
3
|
-
*
|
|
4
|
-
* Manages task execution workflow including context retrieval,
|
|
5
|
-
* LLM interaction, and command execution.
|
|
6
|
-
*
|
|
7
|
-
* @module @jclaw/core/runtime/task-executor
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* System prompt for the agent
|
|
11
|
-
*/
|
|
12
|
-
const DEFAULT_SYSTEM_PROMPT = `You are JClaw, a self-evolving AI agent.
|
|
13
|
-
You help users complete tasks by:
|
|
14
|
-
1. Understanding their request
|
|
15
|
-
2. Planning the necessary steps
|
|
16
|
-
3. Executing commands when needed
|
|
17
|
-
4. Reporting results clearly
|
|
18
|
-
|
|
19
|
-
Always think step by step and explain your reasoning.`;
|
|
20
|
-
/**
|
|
21
|
-
* Task Executor
|
|
22
|
-
*
|
|
23
|
-
* Orchestrates task execution by:
|
|
24
|
-
* - Retrieving relevant context
|
|
25
|
-
* - Generating plans with LLM
|
|
26
|
-
* - Executing commands when needed
|
|
27
|
-
* - Handling errors and retries
|
|
28
|
-
*
|
|
29
|
-
* @example
|
|
30
|
-
* ```typescript
|
|
31
|
-
* const executor = new TaskExecutor({
|
|
32
|
-
* llmClient: createLLMClient(config),
|
|
33
|
-
* contextManager: openVikingClient,
|
|
34
|
-
* executor: localExecutor
|
|
35
|
-
* });
|
|
36
|
-
*
|
|
37
|
-
* const result = await executor.execute({
|
|
38
|
-
* id: 'task-1',
|
|
39
|
-
* prompt: 'List all files in the current directory'
|
|
40
|
-
* });
|
|
41
|
-
* ```
|
|
42
3
|
*/
|
|
43
4
|
export class TaskExecutor {
|
|
44
|
-
config;
|
|
45
|
-
/**
|
|
46
|
-
* Create a new task executor instance.
|
|
47
|
-
*
|
|
48
|
-
* @param config - Configuration options
|
|
49
|
-
*/
|
|
50
5
|
constructor(config) {
|
|
51
6
|
this.config = {
|
|
52
|
-
systemPrompt:
|
|
7
|
+
systemPrompt: `You are JClaw, a self-evolving AI agent.`,
|
|
53
8
|
maxRetries: 3,
|
|
54
9
|
verbose: false,
|
|
55
10
|
...config,
|
|
56
11
|
};
|
|
57
12
|
}
|
|
58
|
-
|
|
59
|
-
* Execute a task and return the result.
|
|
60
|
-
*
|
|
61
|
-
* @param task - The task to execute
|
|
62
|
-
* @returns Promise resolving to task result
|
|
63
|
-
*/
|
|
13
|
+
|
|
64
14
|
async execute(task) {
|
|
65
15
|
const startTime = Date.now();
|
|
66
16
|
let attempts = 0;
|
|
67
17
|
let lastError;
|
|
18
|
+
|
|
68
19
|
while (attempts < this.config.maxRetries) {
|
|
69
20
|
attempts++;
|
|
70
21
|
try {
|
|
71
22
|
const output = await this.executeTask(task);
|
|
72
|
-
const duration = Date.now() - startTime;
|
|
73
23
|
return {
|
|
74
24
|
taskId: task.id,
|
|
75
25
|
success: true,
|
|
76
26
|
output,
|
|
77
|
-
duration,
|
|
27
|
+
duration: Date.now() - startTime,
|
|
78
28
|
};
|
|
79
|
-
}
|
|
80
|
-
catch (error) {
|
|
29
|
+
} catch (error) {
|
|
81
30
|
lastError = error instanceof Error ? error.message : 'Unknown error';
|
|
82
|
-
this.log(`Attempt ${attempts} failed: ${lastError}`);
|
|
83
|
-
// Wait before retry (exponential backoff)
|
|
84
31
|
if (attempts < this.config.maxRetries) {
|
|
85
32
|
await this.sleep(1000 * Math.pow(2, attempts - 1));
|
|
86
33
|
}
|
|
87
34
|
}
|
|
88
35
|
}
|
|
89
|
-
|
|
36
|
+
|
|
90
37
|
return {
|
|
91
38
|
taskId: task.id,
|
|
92
39
|
success: false,
|
|
93
|
-
error:
|
|
94
|
-
duration,
|
|
40
|
+
error: lastError,
|
|
41
|
+
duration: Date.now() - startTime,
|
|
95
42
|
};
|
|
96
43
|
}
|
|
97
|
-
|
|
98
|
-
* Internal method to execute a single task attempt.
|
|
99
|
-
*/
|
|
44
|
+
|
|
100
45
|
async executeTask(task) {
|
|
101
|
-
// Build messages array
|
|
102
46
|
const messages = [
|
|
103
|
-
{ role: 'system', content: this.
|
|
47
|
+
{ role: 'system', content: this.buildSystemPrompt() },
|
|
104
48
|
];
|
|
105
|
-
|
|
49
|
+
|
|
106
50
|
if (this.config.contextManager) {
|
|
107
51
|
try {
|
|
108
52
|
const context = await this.config.contextManager.query(task.prompt, { topK: 5 });
|
|
109
|
-
if (context) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
53
|
+
if (context) messages.push({ role: 'system', content: 'Context: ' + context });
|
|
54
|
+
} catch {}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
messages.push({ role: 'user', content: task.prompt });
|
|
58
|
+
|
|
59
|
+
let iterationCount = 0;
|
|
60
|
+
const maxIterations = 5;
|
|
61
|
+
|
|
62
|
+
while (iterationCount < maxIterations) {
|
|
63
|
+
iterationCount++;
|
|
64
|
+
const response = await this.config.llmClient.chat(messages);
|
|
65
|
+
|
|
66
|
+
// Check for capability calls
|
|
67
|
+
const capabilityCall = this.extractCapabilityCall(response.content);
|
|
68
|
+
if (capabilityCall && this.config.extensionRegistry) {
|
|
69
|
+
const registeredCap = this.config.extensionRegistry.getCapability(capabilityCall.name);
|
|
70
|
+
if (registeredCap?.capability?.handler) {
|
|
71
|
+
try {
|
|
72
|
+
const result = await registeredCap.capability.handler(capabilityCall.input);
|
|
73
|
+
messages.push({ role: 'assistant', content: response.content });
|
|
74
|
+
messages.push({ role: 'system', content: 'Result: ' + JSON.stringify(result) });
|
|
75
|
+
continue;
|
|
76
|
+
} catch (error) {
|
|
77
|
+
messages.push({ role: 'assistant', content: response.content });
|
|
78
|
+
messages.push({ role: 'system', content: 'Error: ' + error.message });
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
114
81
|
}
|
|
115
82
|
}
|
|
116
|
-
|
|
117
|
-
|
|
83
|
+
|
|
84
|
+
// Check for commands
|
|
85
|
+
const commands = this.extractCommands(response.content);
|
|
86
|
+
if (commands.length > 0 && this.config.executor) {
|
|
87
|
+
return response.content;
|
|
118
88
|
}
|
|
89
|
+
|
|
90
|
+
return response.content;
|
|
119
91
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
// Check if we need to execute commands
|
|
132
|
-
const commands = this.extractCommands(response.content);
|
|
133
|
-
if (commands.length > 0 && this.config.executor) {
|
|
134
|
-
for (const cmd of commands) {
|
|
135
|
-
this.log(`Executing command: ${cmd}`);
|
|
136
|
-
const result = await this.config.executor.execute(cmd, {
|
|
137
|
-
mode: task.executionMode,
|
|
138
|
-
});
|
|
139
|
-
if (result.exitCode !== 0) {
|
|
140
|
-
// Feed error back to LLM
|
|
141
|
-
messages.push({ role: 'assistant', content: response.content });
|
|
142
|
-
messages.push({
|
|
143
|
-
role: 'user',
|
|
144
|
-
content: `Command failed with exit code ${result.exitCode}:\n${result.stderr}`,
|
|
145
|
-
});
|
|
146
|
-
const retryResponse = await this.config.llmClient.chat(messages);
|
|
147
|
-
return retryResponse.content;
|
|
148
|
-
}
|
|
149
|
-
// Feed output back to LLM
|
|
150
|
-
messages.push({ role: 'assistant', content: response.content });
|
|
151
|
-
messages.push({
|
|
152
|
-
role: 'user',
|
|
153
|
-
content: `Command output:\n${result.stdout}`,
|
|
154
|
-
});
|
|
92
|
+
|
|
93
|
+
return (await this.config.llmClient.chat(messages)).content;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
buildSystemPrompt() {
|
|
97
|
+
let prompt = this.config.systemPrompt;
|
|
98
|
+
if (this.config.extensionRegistry) {
|
|
99
|
+
const capabilities = this.config.extensionRegistry.getCapabilityNames();
|
|
100
|
+
if (capabilities.length > 0) {
|
|
101
|
+
prompt += '\n\nAvailable Capabilities:\n' + capabilities.map(c => '- ' + c).join('\n');
|
|
102
|
+
prompt += '\n\nTo use: ```capability\n{\n "name": "capability_name",\n "input": {...}\n}\n```';
|
|
155
103
|
}
|
|
156
|
-
const finalResponse = await this.config.llmClient.chat(messages);
|
|
157
|
-
return finalResponse.content;
|
|
158
104
|
}
|
|
159
|
-
return
|
|
105
|
+
return prompt;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
extractCapabilityCall(content) {
|
|
109
|
+
const match = /```capability\s*\n([\s\S]*?)\n\s*```/.exec(content);
|
|
110
|
+
if (match && match[1]) {
|
|
111
|
+
try {
|
|
112
|
+
const parsed = JSON.parse(match[1].trim());
|
|
113
|
+
if (parsed.name) return { name: parsed.name, input: parsed.input || {} };
|
|
114
|
+
} catch {}
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
160
117
|
}
|
|
161
|
-
|
|
162
|
-
* Extract shell commands from LLM response.
|
|
163
|
-
*
|
|
164
|
-
* Looks for commands in code blocks marked as shell/bash.
|
|
165
|
-
*/
|
|
118
|
+
|
|
166
119
|
extractCommands(content) {
|
|
167
120
|
const commands = [];
|
|
168
|
-
|
|
169
|
-
const shellBlockRegex = /```(?:shell|bash|sh)\n([\s\S]*?)```/g;
|
|
121
|
+
const regex = /```(?:shell|bash|sh)\n([\s\S]*?)```/g;
|
|
170
122
|
let match;
|
|
171
|
-
while ((match =
|
|
123
|
+
while ((match = regex.exec(content)) !== null) {
|
|
172
124
|
const cmd = match[1]?.trim();
|
|
173
|
-
if (cmd && !cmd.startsWith('#'))
|
|
174
|
-
commands.push(cmd);
|
|
175
|
-
}
|
|
125
|
+
if (cmd && !cmd.startsWith('#')) commands.push(cmd);
|
|
176
126
|
}
|
|
177
127
|
return commands;
|
|
178
128
|
}
|
|
179
|
-
|
|
180
|
-
* Log message if verbose mode is enabled.
|
|
181
|
-
*/
|
|
129
|
+
|
|
182
130
|
log(message) {
|
|
183
|
-
if (this.config.verbose)
|
|
184
|
-
console.log(`[TaskExecutor] ${message}`);
|
|
185
|
-
}
|
|
131
|
+
if (this.config.verbose) console.log('[TaskExecutor] ' + message);
|
|
186
132
|
}
|
|
187
|
-
|
|
188
|
-
* Sleep for specified milliseconds.
|
|
189
|
-
*/
|
|
133
|
+
|
|
190
134
|
sleep(ms) {
|
|
191
135
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
192
136
|
}
|
|
193
137
|
}
|
|
194
|
-
|
|
195
|
-
* Create a new task executor instance.
|
|
196
|
-
*
|
|
197
|
-
* @param config - Configuration options
|
|
198
|
-
* @returns New TaskExecutor instance
|
|
199
|
-
*/
|
|
138
|
+
|
|
200
139
|
export function createTaskExecutor(config) {
|
|
201
140
|
return new TaskExecutor(config);
|
|
202
141
|
}
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task Executor
|
|
3
|
+
*
|
|
4
|
+
* Manages task execution workflow including context retrieval,
|
|
5
|
+
* LLM interaction, and command execution.
|
|
6
|
+
*
|
|
7
|
+
* @module @jclaw/core/runtime/task-executor
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* System prompt for the agent
|
|
11
|
+
*/
|
|
12
|
+
const DEFAULT_SYSTEM_PROMPT = `You are JClaw, a self-evolving AI agent.
|
|
13
|
+
You help users complete tasks by:
|
|
14
|
+
1. Understanding their request
|
|
15
|
+
2. Planning the necessary steps
|
|
16
|
+
3. Executing commands when needed
|
|
17
|
+
4. Reporting results clearly
|
|
18
|
+
|
|
19
|
+
Always think step by step and explain your reasoning.`;
|
|
20
|
+
/**
|
|
21
|
+
* Task Executor
|
|
22
|
+
*
|
|
23
|
+
* Orchestrates task execution by:
|
|
24
|
+
* - Retrieving relevant context
|
|
25
|
+
* - Generating plans with LLM
|
|
26
|
+
* - Executing commands when needed
|
|
27
|
+
* - Handling errors and retries
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* const executor = new TaskExecutor({
|
|
32
|
+
* llmClient: createLLMClient(config),
|
|
33
|
+
* contextManager: openVikingClient,
|
|
34
|
+
* executor: localExecutor
|
|
35
|
+
* });
|
|
36
|
+
*
|
|
37
|
+
* const result = await executor.execute({
|
|
38
|
+
* id: 'task-1',
|
|
39
|
+
* prompt: 'List all files in the current directory'
|
|
40
|
+
* });
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export class TaskExecutor {
|
|
44
|
+
config;
|
|
45
|
+
/**
|
|
46
|
+
* Create a new task executor instance.
|
|
47
|
+
*
|
|
48
|
+
* @param config - Configuration options
|
|
49
|
+
*/
|
|
50
|
+
constructor(config) {
|
|
51
|
+
this.config = {
|
|
52
|
+
systemPrompt: DEFAULT_SYSTEM_PROMPT,
|
|
53
|
+
maxRetries: 3,
|
|
54
|
+
verbose: false,
|
|
55
|
+
...config,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Execute a task and return the result.
|
|
60
|
+
*
|
|
61
|
+
* @param task - The task to execute
|
|
62
|
+
* @returns Promise resolving to task result
|
|
63
|
+
*/
|
|
64
|
+
async execute(task) {
|
|
65
|
+
const startTime = Date.now();
|
|
66
|
+
let attempts = 0;
|
|
67
|
+
let lastError;
|
|
68
|
+
while (attempts < this.config.maxRetries) {
|
|
69
|
+
attempts++;
|
|
70
|
+
try {
|
|
71
|
+
const output = await this.executeTask(task);
|
|
72
|
+
const duration = Date.now() - startTime;
|
|
73
|
+
return {
|
|
74
|
+
taskId: task.id,
|
|
75
|
+
success: true,
|
|
76
|
+
output,
|
|
77
|
+
duration,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
lastError = error instanceof Error ? error.message : 'Unknown error';
|
|
82
|
+
this.log(`Attempt ${attempts} failed: ${lastError}`);
|
|
83
|
+
// Wait before retry (exponential backoff)
|
|
84
|
+
if (attempts < this.config.maxRetries) {
|
|
85
|
+
await this.sleep(1000 * Math.pow(2, attempts - 1));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const duration = Date.now() - startTime;
|
|
90
|
+
return {
|
|
91
|
+
taskId: task.id,
|
|
92
|
+
success: false,
|
|
93
|
+
error: `Task failed after ${attempts} attempts. Last error: ${lastError}`,
|
|
94
|
+
duration,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Internal method to execute a single task attempt.
|
|
99
|
+
*/
|
|
100
|
+
async executeTask(task) {
|
|
101
|
+
// Build messages array
|
|
102
|
+
const messages = [
|
|
103
|
+
{ role: 'system', content: this.config.systemPrompt },
|
|
104
|
+
];
|
|
105
|
+
// Add context if available
|
|
106
|
+
if (this.config.contextManager) {
|
|
107
|
+
try {
|
|
108
|
+
const context = await this.config.contextManager.query(task.prompt, { topK: 5 });
|
|
109
|
+
if (context) {
|
|
110
|
+
messages.push({
|
|
111
|
+
role: 'system',
|
|
112
|
+
content: `Relevant context:\n${context}`,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
this.log('Warning: Failed to retrieve context');
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// Add user prompt
|
|
121
|
+
messages.push({ role: 'user', content: task.prompt });
|
|
122
|
+
// Add task context if provided
|
|
123
|
+
if (task.context) {
|
|
124
|
+
messages.push({
|
|
125
|
+
role: 'user',
|
|
126
|
+
content: `Additional context: ${JSON.stringify(task.context, null, 2)}`,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
// Get LLM response
|
|
130
|
+
const response = await this.config.llmClient.chat(messages);
|
|
131
|
+
// Check if we need to execute commands
|
|
132
|
+
const commands = this.extractCommands(response.content);
|
|
133
|
+
if (commands.length > 0 && this.config.executor) {
|
|
134
|
+
for (const cmd of commands) {
|
|
135
|
+
this.log(`Executing command: ${cmd}`);
|
|
136
|
+
const result = await this.config.executor.execute(cmd, {
|
|
137
|
+
mode: task.executionMode,
|
|
138
|
+
});
|
|
139
|
+
if (result.exitCode !== 0) {
|
|
140
|
+
// Feed error back to LLM
|
|
141
|
+
messages.push({ role: 'assistant', content: response.content });
|
|
142
|
+
messages.push({
|
|
143
|
+
role: 'user',
|
|
144
|
+
content: `Command failed with exit code ${result.exitCode}:\n${result.stderr}`,
|
|
145
|
+
});
|
|
146
|
+
const retryResponse = await this.config.llmClient.chat(messages);
|
|
147
|
+
return retryResponse.content;
|
|
148
|
+
}
|
|
149
|
+
// Feed output back to LLM
|
|
150
|
+
messages.push({ role: 'assistant', content: response.content });
|
|
151
|
+
messages.push({
|
|
152
|
+
role: 'user',
|
|
153
|
+
content: `Command output:\n${result.stdout}`,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
const finalResponse = await this.config.llmClient.chat(messages);
|
|
157
|
+
return finalResponse.content;
|
|
158
|
+
}
|
|
159
|
+
return response.content;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Extract shell commands from LLM response.
|
|
163
|
+
*
|
|
164
|
+
* Looks for commands in code blocks marked as shell/bash.
|
|
165
|
+
*/
|
|
166
|
+
extractCommands(content) {
|
|
167
|
+
const commands = [];
|
|
168
|
+
// Match ```shell or ```bash code blocks
|
|
169
|
+
const shellBlockRegex = /```(?:shell|bash|sh)\n([\s\S]*?)```/g;
|
|
170
|
+
let match;
|
|
171
|
+
while ((match = shellBlockRegex.exec(content)) !== null) {
|
|
172
|
+
const cmd = match[1]?.trim();
|
|
173
|
+
if (cmd && !cmd.startsWith('#')) {
|
|
174
|
+
commands.push(cmd);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return commands;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Log message if verbose mode is enabled.
|
|
181
|
+
*/
|
|
182
|
+
log(message) {
|
|
183
|
+
if (this.config.verbose) {
|
|
184
|
+
console.log(`[TaskExecutor] ${message}`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Sleep for specified milliseconds.
|
|
189
|
+
*/
|
|
190
|
+
sleep(ms) {
|
|
191
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Build system prompt with available capabilities.
|
|
195
|
+
*/
|
|
196
|
+
buildSystemPrompt() {
|
|
197
|
+
let prompt = this.config.systemPrompt;
|
|
198
|
+
// Add available capabilities if registry exists
|
|
199
|
+
if (this.config.extensionRegistry) {
|
|
200
|
+
const capabilities = this.config.extensionRegistry.getCapabilityNames();
|
|
201
|
+
if (capabilities.length > 0) {
|
|
202
|
+
prompt += '\n\n## Available Capabilities\n\nYou have access to the following capabilities:\n';
|
|
203
|
+
capabilities.forEach(cap => {
|
|
204
|
+
prompt += `- \`${cap}\` - Use this capability when appropriate\n`;
|
|
205
|
+
});
|
|
206
|
+
prompt += '\n### How to Use a Capability\n\n';
|
|
207
|
+
prompt += 'To use a capability, respond with a code block in this format:\n';
|
|
208
|
+
prompt += '```capability\n{\n "name": "capability_name",\n "input": { ... }\n}\n```\n\n';
|
|
209
|
+
prompt += 'The capability will be executed and the result will be provided to you.\n';
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return prompt;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Extract capability call from LLM response.
|
|
216
|
+
*/
|
|
217
|
+
extractCapabilityCall(content) {
|
|
218
|
+
// Match ```capability { ... } ``` blocks
|
|
219
|
+
const capabilityRegex = /```capability\s*\n([\s\S]*?)\n\s*```/;
|
|
220
|
+
const match = capabilityRegex.exec(content);
|
|
221
|
+
if (match && match[1]) {
|
|
222
|
+
try {
|
|
223
|
+
const parsed = JSON.parse(match[1].trim());
|
|
224
|
+
if (parsed.name && typeof parsed.name === 'string') {
|
|
225
|
+
return {
|
|
226
|
+
name: parsed.name,
|
|
227
|
+
input: parsed.input || {}
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
catch (e) {
|
|
232
|
+
this.log(`Failed to parse capability call: ${e}`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Extract shell commands from LLM response.
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Create a new task executor instance.
|
|
243
|
+
*
|
|
244
|
+
* @param config - Configuration options
|
|
245
|
+
* @returns New TaskExecutor instance
|
|
246
|
+
*/
|
|
247
|
+
export function createTaskExecutor(config) {
|
|
248
|
+
return new TaskExecutor(config);
|
|
249
|
+
}
|
|
250
|
+
buildSystemPrompt();
|
|
251
|
+
string;
|
|
252
|
+
{
|
|
253
|
+
let prompt = this.config.systemPrompt;
|
|
254
|
+
// Add available capabilities if registry exists
|
|
255
|
+
if (this.config.extensionRegistry) {
|
|
256
|
+
const capabilities = this.config.extensionRegistry.getCapabilityNames();
|
|
257
|
+
if (capabilities.length > 0) {
|
|
258
|
+
prompt += '\n\n## Available Capabilities\n\nYou have access to the following capabilities:\n';
|
|
259
|
+
capabilities.forEach(cap => {
|
|
260
|
+
prompt += `- \`${cap}\` - Use this capability when appropriate\n`;
|
|
261
|
+
});
|
|
262
|
+
prompt += '\n### How to Use a Capability\n\n';
|
|
263
|
+
prompt += 'To use a capability, respond with a code block in this format:\n';
|
|
264
|
+
prompt += '```capability\n{\n "name": "capability_name",\n "input": { ... }\n}\n```\n\n';
|
|
265
|
+
prompt += 'The capability will be executed and the result will be provided to you.\n';
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return prompt;
|
|
269
|
+
}
|
|
270
|
+
extractCapabilityCall(content, string);
|
|
271
|
+
{
|
|
272
|
+
name: string;
|
|
273
|
+
input: unknown;
|
|
274
|
+
}
|
|
275
|
+
| null;
|
|
276
|
+
{
|
|
277
|
+
// Match ```capability { ... } ``` blocks
|
|
278
|
+
const capabilityRegex = /```capability\s*\n([\s\S]*?)\n\s*```/;
|
|
279
|
+
const match = capabilityRegex.exec(content);
|
|
280
|
+
if (match && match[1]) {
|
|
281
|
+
try {
|
|
282
|
+
const parsed = JSON.parse(match[1].trim());
|
|
283
|
+
if (parsed.name && typeof parsed.name === 'string') {
|
|
284
|
+
return {
|
|
285
|
+
name: parsed.name,
|
|
286
|
+
input: parsed.input || {}
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
catch (e) {
|
|
291
|
+
this.log(`Failed to parse capability call: ${e}`);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return null;
|
|
295
|
+
}
|
package/package.json
CHANGED
|
@@ -1,18 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jclaw/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Universal self-evolving Agent with improved AutoSkill retry logic",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
|
-
"bin": {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"
|
|
12
|
-
|
|
8
|
+
"bin": {
|
|
9
|
+
"jclaw": "./dist/cli/jclaw.js"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"ai",
|
|
26
|
+
"agent",
|
|
27
|
+
"cli",
|
|
28
|
+
"self-evolving"
|
|
29
|
+
],
|
|
13
30
|
"author": "JClaw Team",
|
|
14
31
|
"license": "MIT",
|
|
15
32
|
"dependencies": {
|
|
16
33
|
"glob": "^10.3.10"
|
|
17
34
|
}
|
|
18
|
-
}
|
|
35
|
+
}
|