@jclaw/core 0.6.1 → 0.8.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/context/index.d.ts +1 -0
- package/dist/context/index.d.ts.map +1 -1
- package/dist/context/index.js +5 -4
- package/dist/context/memsearch-ts-client.d.ts +37 -0
- package/dist/context/memsearch-ts-client.d.ts.map +1 -0
- package/dist/context/memsearch-ts-client.js +121 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/planning/index.d.ts +8 -0
- package/dist/planning/index.d.ts.map +1 -0
- package/dist/planning/index.js +6 -0
- package/dist/planning/planner.d.ts +23 -0
- package/dist/planning/planner.d.ts.map +1 -0
- package/dist/planning/planner.js +184 -0
- package/dist/planning/types.d.ts +34 -0
- package/dist/planning/types.d.ts.map +1 -0
- package/dist/planning/types.js +6 -0
- package/dist/runtime/agent.d.ts +3 -4
- package/dist/runtime/agent.d.ts.map +1 -1
- package/dist/runtime/agent.js +76 -45
- package/dist/runtime/task-executor.d.ts +5 -69
- package/dist/runtime/task-executor.d.ts.map +1 -1
- package/dist/runtime/task-executor.js +67 -151
- package/dist/runtime/task-executor.js.backup +295 -0
- package/package.json +26 -8
|
@@ -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
|
package/dist/context/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Context Module
|
|
3
3
|
*/
|
|
4
|
+
export { MemSearchTsClient, type MemSearchTsConfig, createMemSearchTsClient } from './memsearch-ts-client.js';
|
|
4
5
|
export { SimpleMemoryClient, type SimpleMemoryConfig, createSimpleMemoryClient } from './simple-memory-client.js';
|
|
5
6
|
export { MockClient } from './mock-client.js';
|
|
6
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/context/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/context/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAG9G,OAAO,EAAE,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAQlH,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/context/index.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Context Module
|
|
3
3
|
*/
|
|
4
|
-
//
|
|
4
|
+
// MemSearch-TS (推荐 - 纯 TypeScript,零 Python 依赖,语义搜索)
|
|
5
|
+
export { MemSearchTsClient, createMemSearchTsClient } from './memsearch-ts-client.js';
|
|
6
|
+
// SimpleMemory (备选 - 纯 JavaScript,无需向量数据库)
|
|
5
7
|
export { SimpleMemoryClient, createSimpleMemoryClient } from './simple-memory-client.js';
|
|
6
|
-
// MemSearch (需要 Python
|
|
8
|
+
// MemSearch (已弃用 - 需要 Python)
|
|
7
9
|
// export { MemSearchClient, type MemSearchConfig, createMemSearchClient } from './memsearch-client.js';
|
|
8
|
-
// OpenViking (已弃用 - 需要 Docker
|
|
10
|
+
// OpenViking (已弃用 - 需要 Docker)
|
|
9
11
|
// export { OpenVikingClient, type OpenVikingConfig } from './openviking-client.js';
|
|
10
|
-
// export { OpenVikingMCPClient, type OpenVikingMCPConfig, createOpenVikingMCPClient } from './openviking-mcp-client.js';
|
|
11
12
|
export { MockClient } from './mock-client.js';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MemSearch-TS Client
|
|
3
|
+
*
|
|
4
|
+
* TypeScript-native semantic memory client using memsearch-core.
|
|
5
|
+
* Zero Python dependency, built on Milvus vector database.
|
|
6
|
+
*
|
|
7
|
+
* @module @jclaw/core/context/memsearch-ts-client
|
|
8
|
+
*/
|
|
9
|
+
import type { ContextManager } from '../types.js';
|
|
10
|
+
export interface MemSearchTsConfig {
|
|
11
|
+
memoryPath?: string;
|
|
12
|
+
embeddingProvider?: 'openai' | 'ollama';
|
|
13
|
+
embeddingModel?: string;
|
|
14
|
+
milvusUri?: string;
|
|
15
|
+
collectionName?: string;
|
|
16
|
+
verbose?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare class MemSearchTsClient implements ContextManager {
|
|
19
|
+
private initialized;
|
|
20
|
+
private readonly config;
|
|
21
|
+
private mem;
|
|
22
|
+
constructor(config?: MemSearchTsConfig);
|
|
23
|
+
connect(): Promise<void>;
|
|
24
|
+
disconnect(): Promise<void>;
|
|
25
|
+
query(question: string, options?: {
|
|
26
|
+
topK?: number;
|
|
27
|
+
}): Promise<string>;
|
|
28
|
+
saveMemory(content: string, title?: string): Promise<void>;
|
|
29
|
+
addResource(resourcePath: string): Promise<string>;
|
|
30
|
+
isConnected(): boolean;
|
|
31
|
+
getStats(): {
|
|
32
|
+
memoryPath: string;
|
|
33
|
+
connected: boolean;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export declare function createMemSearchTsClient(config?: MemSearchTsConfig): MemSearchTsClient;
|
|
37
|
+
//# sourceMappingURL=memsearch-ts-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memsearch-ts-client.d.ts","sourceRoot":"","sources":["../../src/context/memsearch-ts-client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,WAAW,iBAAiB;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IACxC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAcD,qBAAa,iBAAkB,YAAW,cAAc;IACtD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8B;IACrD,OAAO,CAAC,GAAG,CAAkC;gBAEjC,MAAM,GAAE,iBAAsB;IAWpC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAgCxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAsBrE,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqB1D,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAkBxD,WAAW,IAAI,OAAO;IAItB,QAAQ,IAAI;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE;CAMvD;AAED,wBAAgB,uBAAuB,CAAC,MAAM,CAAC,EAAE,iBAAiB,GAAG,iBAAiB,CAErF"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MemSearch-TS Client
|
|
3
|
+
*
|
|
4
|
+
* TypeScript-native semantic memory client using memsearch-core.
|
|
5
|
+
* Zero Python dependency, built on Milvus vector database.
|
|
6
|
+
*
|
|
7
|
+
* @module @jclaw/core/context/memsearch-ts-client
|
|
8
|
+
*/
|
|
9
|
+
import { writeFile, mkdir } from 'fs/promises';
|
|
10
|
+
import { existsSync } from 'fs';
|
|
11
|
+
import { join } from 'path';
|
|
12
|
+
export class MemSearchTsClient {
|
|
13
|
+
initialized = false;
|
|
14
|
+
config;
|
|
15
|
+
mem = null;
|
|
16
|
+
constructor(config = {}) {
|
|
17
|
+
this.config = {
|
|
18
|
+
memoryPath: config.memoryPath || './.jclaw/memory',
|
|
19
|
+
embeddingProvider: config.embeddingProvider || 'openai',
|
|
20
|
+
embeddingModel: config.embeddingModel || 'text-embedding-3-small',
|
|
21
|
+
milvusUri: config.milvusUri || join(process.env.HOME || '.', '.jclaw', 'milvus.db'),
|
|
22
|
+
collectionName: config.collectionName || 'jclaw_memories',
|
|
23
|
+
verbose: config.verbose || false,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
async connect() {
|
|
27
|
+
try {
|
|
28
|
+
if (!existsSync(this.config.memoryPath)) {
|
|
29
|
+
await mkdir(this.config.memoryPath, { recursive: true });
|
|
30
|
+
}
|
|
31
|
+
const { MemSearch } = await import('memsearch-core');
|
|
32
|
+
this.mem = new MemSearch({
|
|
33
|
+
paths: [this.config.memoryPath],
|
|
34
|
+
embedding: {
|
|
35
|
+
provider: this.config.embeddingProvider,
|
|
36
|
+
model: this.config.embeddingModel,
|
|
37
|
+
},
|
|
38
|
+
milvus: {
|
|
39
|
+
uri: this.config.milvusUri,
|
|
40
|
+
collection: this.config.collectionName,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
await this.mem.index();
|
|
44
|
+
this.initialized = true;
|
|
45
|
+
if (this.config.verbose) {
|
|
46
|
+
console.log('[MemSearch-TS] Connected, memory path: ' + this.config.memoryPath);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
51
|
+
throw new Error('Failed to initialize MemSearch-TS: ' + message);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
async disconnect() {
|
|
55
|
+
if (this.mem) {
|
|
56
|
+
this.mem.close();
|
|
57
|
+
this.mem = null;
|
|
58
|
+
}
|
|
59
|
+
this.initialized = false;
|
|
60
|
+
}
|
|
61
|
+
async query(question, options) {
|
|
62
|
+
if (!this.initialized || !this.mem) {
|
|
63
|
+
throw new Error('MemSearch-TS client not initialized');
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
await this.mem.index();
|
|
67
|
+
const results = await this.mem.search(question, { topK: options?.topK ?? 5 });
|
|
68
|
+
if (this.config.verbose) {
|
|
69
|
+
console.log('[MemSearch-TS] Found ' + results.length + ' results');
|
|
70
|
+
}
|
|
71
|
+
return results.map((r, i) => '[' + (i + 1) + '] (score: ' + r.score.toFixed(2) + ')\n' + r.content).join('\n\n---\n\n');
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
if (this.config.verbose) {
|
|
75
|
+
console.error('[MemSearch-TS] Search failed:', error);
|
|
76
|
+
}
|
|
77
|
+
return '';
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async saveMemory(content, title) {
|
|
81
|
+
const date = new Date().toISOString().split('T')[0];
|
|
82
|
+
const timestamp = new Date().toISOString();
|
|
83
|
+
const fileName = date + '.md';
|
|
84
|
+
const filePath = join(this.config.memoryPath, fileName);
|
|
85
|
+
const entry = title
|
|
86
|
+
? '\n## ' + title + '\n\n> Saved at: ' + timestamp + '\n\n' + content + '\n\n---\n'
|
|
87
|
+
: '\n> Saved at: ' + timestamp + '\n\n' + content + '\n\n---\n';
|
|
88
|
+
await writeFile(filePath, entry, { flag: 'a' });
|
|
89
|
+
if (this.config.verbose) {
|
|
90
|
+
console.log('[MemSearch-TS] Saved memory: ' + (title || 'untitled'));
|
|
91
|
+
}
|
|
92
|
+
if (this.mem) {
|
|
93
|
+
await this.mem.index();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async addResource(resourcePath) {
|
|
97
|
+
if (!this.initialized) {
|
|
98
|
+
throw new Error('MemSearch-TS client not initialized');
|
|
99
|
+
}
|
|
100
|
+
const { copyFile } = await import('fs/promises');
|
|
101
|
+
const { basename } = await import('path');
|
|
102
|
+
const destPath = join(this.config.memoryPath, basename(resourcePath));
|
|
103
|
+
await copyFile(resourcePath, destPath);
|
|
104
|
+
if (this.mem) {
|
|
105
|
+
await this.mem.index();
|
|
106
|
+
}
|
|
107
|
+
return destPath;
|
|
108
|
+
}
|
|
109
|
+
isConnected() {
|
|
110
|
+
return this.initialized;
|
|
111
|
+
}
|
|
112
|
+
getStats() {
|
|
113
|
+
return {
|
|
114
|
+
memoryPath: this.config.memoryPath,
|
|
115
|
+
connected: this.initialized,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export function createMemSearchTsClient(config) {
|
|
120
|
+
return new MemSearchTsClient(config);
|
|
121
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,4 +12,5 @@ export { MutationGenerator, createMutationGenerator, type MutationGeneratorConfi
|
|
|
12
12
|
export { AutoSkillGenerator, createAutoSkillGenerator, AutoSkillInstaller, createAutoSkillInstaller, type AutoSkillConfig, type CapabilityGap, type DiscoveryResult, type GeneratedExtension, type GenerationResult, type GenerationStep, type InstallationResult, type SkillUsageStats, type AutoSkillMetadata, type SkillVersion, } from './auto-skill/index.js';
|
|
13
13
|
export { A2AProtocol, GEPProtocol, type A2AMessage, type A2AMessageType, type GEPPacket, type NodeInfo, type GeneSharePayload, type GeneRequestPayload, type TaskDelegatePayload, EvoMapClient, createEvoMapClient, type EvoMapConfig, type GeneResponse, } from './network/index.js';
|
|
14
14
|
export { fileOperationsExtension } from './extensions/built-in/file-operations.js';
|
|
15
|
+
export { Planner, createPlanner, type Step, type StepStatus, type Plan, type PlannerConfig, type PlanAdjustment, } from './planning/index.js';
|
|
15
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,YAAY,EACV,IAAI,EACJ,UAAU,EACV,cAAc,EACd,aAAa,EACb,QAAQ,EACR,cAAc,EACd,UAAU,EACV,SAAS,EACT,YAAY,GACb,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAGzE,OAAO,EACL,kBAAkB,EAClB,KAAK,kBAAkB,EACvB,wBAAwB,EACxB,UAAU,GACX,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAG3E,OAAO,EACL,SAAS,EACT,eAAe,EACf,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,YAAY,EACZ,kBAAkB,EAClB,KAAK,kBAAkB,EACvB,UAAU,EACV,WAAW,EACX,KAAK,WAAW,GACjB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,KAAK,uBAAuB,EAC5B,gBAAgB,EAChB,aAAa,EACb,KAAK,aAAa,EAClB,eAAe,EACf,qBAAqB,EACrB,KAAK,iBAAiB,EACtB,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,IAAI,EACT,KAAK,eAAe,EACpB,cAAc,EACd,oBAAoB,EACpB,KAAK,oBAAoB,EACzB,KAAK,aAAa,GACnB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,kBAAkB,EAClB,wBAAwB,EACxB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,YAAY,GAClB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,WAAW,EACX,WAAW,EACX,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,YAAY,EACZ,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,YAAY,GAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,YAAY,EACV,IAAI,EACJ,UAAU,EACV,cAAc,EACd,aAAa,EACb,QAAQ,EACR,cAAc,EACd,UAAU,EACV,SAAS,EACT,YAAY,GACb,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAGzE,OAAO,EACL,kBAAkB,EAClB,KAAK,kBAAkB,EACvB,wBAAwB,EACxB,UAAU,GACX,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAG3E,OAAO,EACL,SAAS,EACT,eAAe,EACf,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,YAAY,EACZ,kBAAkB,EAClB,KAAK,kBAAkB,EACvB,UAAU,EACV,WAAW,EACX,KAAK,WAAW,GACjB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,KAAK,uBAAuB,EAC5B,gBAAgB,EAChB,aAAa,EACb,KAAK,aAAa,EAClB,eAAe,EACf,qBAAqB,EACrB,KAAK,iBAAiB,EACtB,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,IAAI,EACT,KAAK,eAAe,EACpB,cAAc,EACd,oBAAoB,EACpB,KAAK,oBAAoB,EACzB,KAAK,aAAa,GACnB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,kBAAkB,EAClB,wBAAwB,EACxB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,YAAY,GAClB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,WAAW,EACX,WAAW,EACX,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,YAAY,EACZ,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,YAAY,GAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AAGnF,OAAO,EACL,OAAO,EACP,aAAa,EACb,KAAK,IAAI,EACT,KAAK,UAAU,EACf,KAAK,IAAI,EACT,KAAK,aAAa,EAClB,KAAK,cAAc,GACpB,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -18,3 +18,5 @@ export { AutoSkillGenerator, createAutoSkillGenerator, AutoSkillInstaller, creat
|
|
|
18
18
|
// Network
|
|
19
19
|
export { A2AProtocol, GEPProtocol, EvoMapClient, createEvoMapClient, } from './network/index.js';
|
|
20
20
|
export { fileOperationsExtension } from './extensions/built-in/file-operations.js';
|
|
21
|
+
// Planning Module (任务规划)
|
|
22
|
+
export { Planner, createPlanner, } from './planning/index.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/planning/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACxF,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task Planner
|
|
3
|
+
*
|
|
4
|
+
* Breaks down tasks into executable steps using LLM.
|
|
5
|
+
*
|
|
6
|
+
* @module @jclaw/core/planning/planner
|
|
7
|
+
*/
|
|
8
|
+
import type { LLMClient } from '../runtime/llm-client.js';
|
|
9
|
+
import type { Plan, Step, PlannerConfig, PlanAdjustment } from './types.js';
|
|
10
|
+
export declare class Planner {
|
|
11
|
+
private readonly llmClient;
|
|
12
|
+
private readonly config;
|
|
13
|
+
constructor(llmClient: LLMClient, config?: PlannerConfig);
|
|
14
|
+
plan(taskPrompt: string, relevantExperiences?: string): Promise<Plan>;
|
|
15
|
+
adjust(plan: Plan, failedStep: Step, error: string): Promise<PlanAdjustment>;
|
|
16
|
+
getNextStep(plan: Plan): Step | null;
|
|
17
|
+
advanceStep(plan: Plan, output?: unknown): Plan;
|
|
18
|
+
markStepFailed(plan: Plan, error: string): Plan;
|
|
19
|
+
isComplete(plan: Plan): boolean;
|
|
20
|
+
private parseSteps;
|
|
21
|
+
}
|
|
22
|
+
export declare function createPlanner(llmClient: LLMClient, config?: PlannerConfig): Planner;
|
|
23
|
+
//# sourceMappingURL=planner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planner.d.ts","sourceRoot":"","sources":["../../src/planning/planner.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AA+B5E,qBAAa,OAAO;IAClB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;gBAErC,SAAS,EAAE,SAAS,EAAE,MAAM,GAAE,aAAkB;IAQtD,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,mBAAmB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmDrE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IA8BlF,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI;IAOpC,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI;IAkB/C,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAgB/C,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO;IAI/B,OAAO,CAAC,UAAU;CA6BnB;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAEnF"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task Planner
|
|
3
|
+
*
|
|
4
|
+
* Breaks down tasks into executable steps using LLM.
|
|
5
|
+
*
|
|
6
|
+
* @module @jclaw/core/planning/planner
|
|
7
|
+
*/
|
|
8
|
+
const PLANNING_PROMPT = `You are a task planner. Break down the given task into clear, sequential steps.
|
|
9
|
+
|
|
10
|
+
Available capabilities:
|
|
11
|
+
- file_read: Read file contents
|
|
12
|
+
- file_write: Write to file
|
|
13
|
+
- file_create: Create new file
|
|
14
|
+
- file_delete: Delete file
|
|
15
|
+
- dir_create: Create directory
|
|
16
|
+
- dir_list: List directory contents
|
|
17
|
+
- file_glob: Search files by pattern
|
|
18
|
+
- file_find: Find file by name
|
|
19
|
+
|
|
20
|
+
Task: {TASK}
|
|
21
|
+
|
|
22
|
+
{CONTEXT}
|
|
23
|
+
|
|
24
|
+
Output ONLY a JSON array of steps, each with:
|
|
25
|
+
- description: What to do (string)
|
|
26
|
+
- capability: Which capability to use (string, optional)
|
|
27
|
+
|
|
28
|
+
Example:
|
|
29
|
+
[
|
|
30
|
+
{"description": "Read the configuration file", "capability": "file_read"},
|
|
31
|
+
{"description": "Analyze the content and prepare modifications"},
|
|
32
|
+
{"description": "Write the updated configuration", "capability": "file_write"}
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
Steps:`;
|
|
36
|
+
export class Planner {
|
|
37
|
+
llmClient;
|
|
38
|
+
config;
|
|
39
|
+
constructor(llmClient, config = {}) {
|
|
40
|
+
this.llmClient = llmClient;
|
|
41
|
+
this.config = {
|
|
42
|
+
maxSteps: config.maxSteps ?? 5,
|
|
43
|
+
verbose: config.verbose ?? false,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
async plan(taskPrompt, relevantExperiences) {
|
|
47
|
+
const taskId = 'plan-' + Date.now() + '-' + Math.random().toString(36).substr(2, 9);
|
|
48
|
+
// Build prompt
|
|
49
|
+
let prompt = PLANNING_PROMPT.replace('{TASK}', taskPrompt);
|
|
50
|
+
prompt = prompt.replace('{CONTEXT}', relevantExperiences
|
|
51
|
+
? 'Relevant past experiences:\n' + relevantExperiences
|
|
52
|
+
: 'No relevant past experiences found.');
|
|
53
|
+
try {
|
|
54
|
+
// Get plan from LLM
|
|
55
|
+
const response = await this.llmClient.chat([
|
|
56
|
+
{ role: 'user', content: prompt }
|
|
57
|
+
]);
|
|
58
|
+
// Parse steps
|
|
59
|
+
const steps = this.parseSteps(response.content);
|
|
60
|
+
if (this.config.verbose) {
|
|
61
|
+
console.log('[Planner] Created plan with ' + steps.length + ' steps');
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
taskId,
|
|
65
|
+
taskPrompt,
|
|
66
|
+
steps,
|
|
67
|
+
currentStepIndex: 0,
|
|
68
|
+
createdAt: Date.now(),
|
|
69
|
+
relevantExperiences,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
// Fallback: single-step plan
|
|
74
|
+
if (this.config.verbose) {
|
|
75
|
+
console.log('[Planner] Using fallback single-step plan');
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
taskId,
|
|
79
|
+
taskPrompt,
|
|
80
|
+
steps: [{
|
|
81
|
+
id: 'step-1',
|
|
82
|
+
description: taskPrompt,
|
|
83
|
+
status: 'pending',
|
|
84
|
+
}],
|
|
85
|
+
currentStepIndex: 0,
|
|
86
|
+
createdAt: Date.now(),
|
|
87
|
+
relevantExperiences,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async adjust(plan, failedStep, error) {
|
|
92
|
+
// Simple adjustment logic
|
|
93
|
+
const stepIndex = plan.steps.findIndex(s => s.id === failedStep.id);
|
|
94
|
+
if (stepIndex === -1) {
|
|
95
|
+
return { type: 'abort', reason: 'Step not found in plan' };
|
|
96
|
+
}
|
|
97
|
+
// Check if we should retry
|
|
98
|
+
const retryCount = failedStep.retryCount || 0;
|
|
99
|
+
if (retryCount < 2) {
|
|
100
|
+
return {
|
|
101
|
+
type: 'retry',
|
|
102
|
+
reason: 'Retrying failed step',
|
|
103
|
+
newSteps: plan.steps.map(s => s.id === failedStep.id
|
|
104
|
+
? { ...s, retryCount: retryCount + 1 }
|
|
105
|
+
: s),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
// Check if we can skip
|
|
109
|
+
if (plan.steps.length > stepIndex + 1) {
|
|
110
|
+
return { type: 'skip', reason: 'Skipping failed step, continuing with next' };
|
|
111
|
+
}
|
|
112
|
+
return { type: 'abort', reason: error };
|
|
113
|
+
}
|
|
114
|
+
getNextStep(plan) {
|
|
115
|
+
if (plan.currentStepIndex >= plan.steps.length) {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
return plan.steps[plan.currentStepIndex];
|
|
119
|
+
}
|
|
120
|
+
advanceStep(plan, output) {
|
|
121
|
+
const updatedSteps = [...plan.steps];
|
|
122
|
+
if (output !== undefined && plan.currentStepIndex < updatedSteps.length) {
|
|
123
|
+
updatedSteps[plan.currentStepIndex] = {
|
|
124
|
+
...updatedSteps[plan.currentStepIndex],
|
|
125
|
+
status: 'completed',
|
|
126
|
+
output,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
...plan,
|
|
131
|
+
steps: updatedSteps,
|
|
132
|
+
currentStepIndex: plan.currentStepIndex + 1,
|
|
133
|
+
completedAt: plan.currentStepIndex + 1 >= plan.steps.length ? Date.now() : undefined,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
markStepFailed(plan, error) {
|
|
137
|
+
const updatedSteps = [...plan.steps];
|
|
138
|
+
if (plan.currentStepIndex < updatedSteps.length) {
|
|
139
|
+
updatedSteps[plan.currentStepIndex] = {
|
|
140
|
+
...updatedSteps[plan.currentStepIndex],
|
|
141
|
+
status: 'failed',
|
|
142
|
+
error,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
...plan,
|
|
147
|
+
steps: updatedSteps,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
isComplete(plan) {
|
|
151
|
+
return plan.currentStepIndex >= plan.steps.length;
|
|
152
|
+
}
|
|
153
|
+
parseSteps(content) {
|
|
154
|
+
try {
|
|
155
|
+
// Try to extract JSON array from response
|
|
156
|
+
const jsonMatch = content.match(/\[[\s\S]*\]/);
|
|
157
|
+
if (!jsonMatch) {
|
|
158
|
+
throw new Error('No JSON array found');
|
|
159
|
+
}
|
|
160
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
161
|
+
if (!Array.isArray(parsed)) {
|
|
162
|
+
throw new Error('Parsed content is not an array');
|
|
163
|
+
}
|
|
164
|
+
return parsed.slice(0, this.config.maxSteps).map((step, i) => ({
|
|
165
|
+
id: 'step-' + (i + 1),
|
|
166
|
+
description: step.description || step,
|
|
167
|
+
status: 'pending',
|
|
168
|
+
capability: step.capability,
|
|
169
|
+
input: step.input,
|
|
170
|
+
}));
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
// Fallback: treat entire response as single step
|
|
174
|
+
return [{
|
|
175
|
+
id: 'step-1',
|
|
176
|
+
description: content.slice(0, 200),
|
|
177
|
+
status: 'pending',
|
|
178
|
+
}];
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
export function createPlanner(llmClient, config) {
|
|
183
|
+
return new Planner(llmClient, config);
|
|
184
|
+
}
|