@jclaw/core 0.4.0 → 0.4.2
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 +47 -233
- package/dist/runtime/llm-client.d.ts +10 -96
- package/dist/runtime/llm-client.d.ts.map +1 -1
- package/dist/runtime/llm-client.js +15 -95
- package/package.json +4 -11
- package/dist/auto-skill/generator.js.map +0 -1
- package/dist/auto-skill/index.js.map +0 -1
- package/dist/auto-skill/installer.js.map +0 -1
- package/dist/auto-skill/types.js.map +0 -1
- package/dist/cli/commands/config.js.map +0 -1
- package/dist/cli/commands/exec.js.map +0 -1
- package/dist/cli/index.js.map +0 -1
- package/dist/cli/run.js.map +0 -1
- package/dist/context/index.js.map +0 -1
- package/dist/context/memsearch-client.js.map +0 -1
- package/dist/context/mock-client.js.map +0 -1
- package/dist/context/openviking-client.d.ts +0 -87
- package/dist/context/openviking-client.d.ts.map +0 -1
- package/dist/context/openviking-client.js +0 -166
- package/dist/context/openviking-client.js.map +0 -1
- package/dist/context/openviking-mcp-client.d.ts +0 -29
- package/dist/context/openviking-mcp-client.d.ts.map +0 -1
- package/dist/context/openviking-mcp-client.js +0 -81
- package/dist/context/openviking-mcp-client.js.map +0 -1
- package/dist/context/simple-memory-client.enhanced.d.ts +0 -39
- package/dist/context/simple-memory-client.enhanced.d.ts.map +0 -1
- package/dist/context/simple-memory-client.enhanced.js +0 -207
- package/dist/context/simple-memory-client.enhanced.js.map +0 -1
- package/dist/context/simple-memory-client.js.map +0 -1
- package/dist/evolution/continuous.d.ts +0 -127
- package/dist/evolution/continuous.d.ts.map +0 -1
- package/dist/evolution/continuous.js +0 -238
- package/dist/evolution/continuous.js.map +0 -1
- package/dist/evolution/engine.js.map +0 -1
- package/dist/evolution/evolver-adapter.js.map +0 -1
- package/dist/evolution/index.js.map +0 -1
- package/dist/evolution/memory.d.ts +0 -106
- package/dist/evolution/memory.d.ts.map +0 -1
- package/dist/evolution/memory.js +0 -232
- package/dist/evolution/memory.js.map +0 -1
- package/dist/evolution/mutation.js.map +0 -1
- package/dist/evolution/sandbox.js.map +0 -1
- package/dist/evolution/types.js.map +0 -1
- package/dist/executor/index.js.map +0 -1
- package/dist/executor/interface.js.map +0 -1
- package/dist/executor/local.js.map +0 -1
- package/dist/extension-system/capability-router.js.map +0 -1
- package/dist/extension-system/index.js.map +0 -1
- package/dist/extension-system/loader.js.map +0 -1
- package/dist/extension-system/registry.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/network/client.js.map +0 -1
- package/dist/network/index.js.map +0 -1
- package/dist/network/protocol.js.map +0 -1
- package/dist/runtime/agent.js.map +0 -1
- package/dist/runtime/agent_fixed.d.ts +0 -39
- package/dist/runtime/agent_fixed.d.ts.map +0 -1
- package/dist/runtime/agent_fixed.js +0 -193
- package/dist/runtime/agent_fixed.js.map +0 -1
- package/dist/runtime/index.js.map +0 -1
- package/dist/runtime/llm-client.js.map +0 -1
- package/dist/runtime/task-executor.js.map +0 -1
- package/dist/skill-sh/adapter.js.map +0 -1
- package/dist/skill-sh/converter.js.map +0 -1
- package/dist/skill-sh/discovery.js.map +0 -1
- package/dist/skill-sh/index.js.map +0 -1
- package/dist/skill-sh/quality.js.map +0 -1
- package/dist/skill-sh/registry.js.map +0 -1
- package/dist/skill-sh/types.js.map +0 -1
- package/dist/types.js.map +0 -1
package/dist/cli/jclaw.js
CHANGED
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* JClaw CLI - Support flexible LLM configuration via environment variables
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
2
|
import { JClawAgent } from '../runtime/agent.js';
|
|
8
3
|
import { createSimpleMemoryClient } from '../context/simple-memory-client.js';
|
|
9
|
-
import { readFile, writeFile
|
|
4
|
+
import { readFile, writeFile } from 'fs/promises';
|
|
10
5
|
import { existsSync } from 'fs';
|
|
11
6
|
|
|
12
|
-
// 命令行参数
|
|
13
7
|
const args = process.argv.slice(2);
|
|
14
8
|
const command = args[0];
|
|
15
9
|
|
|
16
|
-
// 帮助信息
|
|
17
10
|
function showHelp() {
|
|
18
11
|
console.log(`
|
|
19
12
|
🧬 JClaw - Universal Self-Evolving Agent Framework
|
|
@@ -27,153 +20,74 @@ function showHelp() {
|
|
|
27
20
|
init 初始化项目
|
|
28
21
|
help 显示帮助
|
|
29
22
|
|
|
30
|
-
示例:
|
|
31
|
-
jclaw execute "分析我的简历,推荐公司和职位"
|
|
32
|
-
jclaw chat
|
|
33
|
-
|
|
34
23
|
环境变量:
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
LLM_MODEL_NAME
|
|
38
|
-
|
|
39
|
-
或使用 provider 特定变量:
|
|
40
|
-
OPENAI_API_KEY, INFINI_API_KEY, AZURE_OPENAI_KEY, ANTHROPIC_API_KEY
|
|
41
|
-
LLM_PROVIDER provider 名称(openai, infini-openai, azure-openai, anthropic)
|
|
24
|
+
LLM_API_KEY API 密钥
|
|
25
|
+
LLM_BASE_URL API 地址
|
|
26
|
+
LLM_MODEL_NAME 模型名称
|
|
42
27
|
`);
|
|
43
28
|
}
|
|
44
29
|
|
|
45
|
-
// 从配置文件加载 LLM 设置
|
|
46
30
|
async function loadLLMConfig() {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const apiKey = process.env[provider.apiKeyEnv];
|
|
58
|
-
|
|
59
|
-
if (!apiKey) {
|
|
60
|
-
console.error(`❌ 错误:请设置 ${provider.apiKeyEnv} 环境变量`);
|
|
61
|
-
process.exit(1);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return {
|
|
65
|
-
apiBase: provider.baseURL,
|
|
66
|
-
apiKey: apiKey,
|
|
67
|
-
model: llm.model || provider.models[0]
|
|
68
|
-
};
|
|
31
|
+
if (existsSync('./jclaw.config.js')) {
|
|
32
|
+
try {
|
|
33
|
+
const config = await import('./jclaw.config.js');
|
|
34
|
+
const { llm, providers } = config.default || config;
|
|
35
|
+
if (llm && llm.provider && providers && providers[llm.provider]) {
|
|
36
|
+
const provider = providers[llm.provider];
|
|
37
|
+
const apiKey = process.env[provider.apiKeyEnv];
|
|
38
|
+
if (!apiKey) {
|
|
39
|
+
console.error(`❌ 请设置 ${provider.apiKeyEnv}`);
|
|
40
|
+
process.exit(1);
|
|
69
41
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
model: llm.model || 'gpt-4'
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
} catch (e) {
|
|
79
|
-
// 配置文件加载失败,继续
|
|
42
|
+
return {
|
|
43
|
+
apiBase: provider.baseURL,
|
|
44
|
+
apiKey: apiKey,
|
|
45
|
+
model: llm.model || provider.models[0]
|
|
46
|
+
};
|
|
80
47
|
}
|
|
81
|
-
|
|
48
|
+
if (llm && llm.apiKey) {
|
|
49
|
+
return {
|
|
50
|
+
apiBase: llm.apiBase || 'https://api.openai.com/v1',
|
|
51
|
+
apiKey: llm.apiKey,
|
|
52
|
+
model: llm.model || 'gpt-4'
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
} catch (e) {}
|
|
82
56
|
}
|
|
83
|
-
|
|
84
57
|
return null;
|
|
85
58
|
}
|
|
86
59
|
|
|
87
|
-
// 获取 LLM 配置(支持多种环境变量组合)
|
|
88
60
|
async function getLLMConfig() {
|
|
89
|
-
// 1. 优先使用配置文件
|
|
90
61
|
const configFile = await loadLLMConfig();
|
|
91
62
|
if (configFile) return configFile;
|
|
92
63
|
|
|
93
|
-
// 2. 使用通用环境变量(最灵活)
|
|
94
64
|
if (process.env.LLM_API_KEY) {
|
|
95
65
|
return {
|
|
96
66
|
apiBase: process.env.LLM_BASE_URL || 'https://api.openai.com/v1',
|
|
97
67
|
apiKey: process.env.LLM_API_KEY,
|
|
98
|
-
model: process.env.LLM_MODEL_NAME || 'gpt-4'
|
|
68
|
+
model: process.env.LLM_MODEL_NAME || 'gpt-4',
|
|
69
|
+
temperature: process.env.LLM_TEMPERATURE ? parseFloat(process.env.LLM_TEMPERATURE) : 1.0
|
|
99
70
|
};
|
|
100
71
|
}
|
|
101
72
|
|
|
102
|
-
// 3. 使用 LLM_PROVIDER 指定 provider
|
|
103
|
-
if (process.env.LLM_PROVIDER) {
|
|
104
|
-
const providerConfigs = {
|
|
105
|
-
'openai': {
|
|
106
|
-
baseURL: 'https://api.openai.com/v1',
|
|
107
|
-
apiKeyEnv: 'OPENAI_API_KEY',
|
|
108
|
-
defaultModel: 'gpt-4'
|
|
109
|
-
},
|
|
110
|
-
'infini-openai': {
|
|
111
|
-
baseURL: 'https://cloud.infini-ai.com/maas/coding/v1',
|
|
112
|
-
apiKeyEnv: 'INFINI_API_KEY',
|
|
113
|
-
defaultModel: 'kimi-k2.5'
|
|
114
|
-
},
|
|
115
|
-
'azure-openai': {
|
|
116
|
-
baseURL: 'https://YOUR_RESOURCE.openai.azure.com',
|
|
117
|
-
apiKeyEnv: 'AZURE_OPENAI_KEY',
|
|
118
|
-
defaultModel: 'gpt-4'
|
|
119
|
-
},
|
|
120
|
-
'anthropic': {
|
|
121
|
-
baseURL: 'https://api.anthropic.com',
|
|
122
|
-
apiKeyEnv: 'ANTHROPIC_API_KEY',
|
|
123
|
-
defaultModel: 'claude-3-opus'
|
|
124
|
-
}
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
const provider = providerConfigs[process.env.LLM_PROVIDER];
|
|
128
|
-
if (provider) {
|
|
129
|
-
const apiKey = process.env[provider.apiKeyEnv];
|
|
130
|
-
if (!apiKey) {
|
|
131
|
-
console.error(`❌ 错误:请设置 ${provider.apiKeyEnv} 环境变量`);
|
|
132
|
-
process.exit(1);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return {
|
|
136
|
-
apiBase: provider.baseURL,
|
|
137
|
-
apiKey: apiKey,
|
|
138
|
-
model: process.env.LLM_MODEL_NAME || provider.defaultModel
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// 4. 使用默认 OpenAI 环境变量
|
|
144
73
|
if (process.env.OPENAI_API_KEY) {
|
|
145
74
|
return {
|
|
146
75
|
apiBase: process.env.LLM_BASE_URL || 'https://api.openai.com/v1',
|
|
147
76
|
apiKey: process.env.OPENAI_API_KEY,
|
|
148
|
-
model: process.env.LLM_MODEL_NAME || 'gpt-4'
|
|
77
|
+
model: process.env.LLM_MODEL_NAME || 'gpt-4',
|
|
78
|
+
temperature: process.env.LLM_TEMPERATURE ? parseFloat(process.env.LLM_TEMPERATURE) : 1.0
|
|
149
79
|
};
|
|
150
80
|
}
|
|
151
81
|
|
|
152
|
-
|
|
153
|
-
console.error('❌ 错误:请设置 LLM 配置');
|
|
154
|
-
console.error('');
|
|
155
|
-
console.error('方式 1: 使用通用环境变量(推荐)');
|
|
156
|
-
console.error(' export LLM_API_KEY=sk-...');
|
|
157
|
-
console.error(' export LLM_BASE_URL=https://api.openai.com/v1');
|
|
158
|
-
console.error(' export LLM_MODEL_NAME=gpt-4');
|
|
159
|
-
console.error('');
|
|
160
|
-
console.error('方式 2: 使用 provider 特定变量');
|
|
161
|
-
console.error(' export LLM_PROVIDER=infini-openai');
|
|
162
|
-
console.error(' export INFINI_API_KEY=sk-cp-...');
|
|
163
|
-
console.error(' export LLM_MODEL_NAME=kimi-k2.5');
|
|
164
|
-
console.error('');
|
|
165
|
-
console.error('方式 3: 使用配置文件');
|
|
166
|
-
console.error(' 创建 jclaw.config.js');
|
|
82
|
+
console.error('❌ 请设置 LLM_API_KEY 或 OPENAI_API_KEY');
|
|
167
83
|
process.exit(1);
|
|
168
84
|
}
|
|
169
85
|
|
|
170
|
-
// 执行命令
|
|
171
86
|
async function execute(prompt) {
|
|
172
87
|
const llmConfig = await getLLMConfig();
|
|
173
|
-
|
|
174
88
|
console.log('🧬 启动 JClaw...\n');
|
|
175
|
-
console.log(`📡
|
|
176
|
-
console.log(`🔌 API
|
|
89
|
+
console.log(`📡 模型:${llmConfig.model}`);
|
|
90
|
+
console.log(`🔌 API: ${llmConfig.apiBase}\n`);
|
|
177
91
|
|
|
178
92
|
const agent = new JClawAgent({
|
|
179
93
|
enableAutoSkill: true,
|
|
@@ -189,30 +103,20 @@ async function execute(prompt) {
|
|
|
189
103
|
console.log('✅ JClaw 已启动\n');
|
|
190
104
|
console.log('📝 任务:', prompt, '\n');
|
|
191
105
|
|
|
192
|
-
const result = await agent.execute({
|
|
193
|
-
id: 'cli-task',
|
|
194
|
-
prompt
|
|
195
|
-
});
|
|
106
|
+
const result = await agent.execute({ id: 'cli-task', prompt });
|
|
196
107
|
|
|
197
108
|
console.log('\n✅ 结果:\n');
|
|
198
109
|
console.log(result.output || result.error);
|
|
199
|
-
|
|
200
110
|
await agent.stop();
|
|
201
111
|
console.log('\n🎉 完成!\n');
|
|
202
112
|
}
|
|
203
113
|
|
|
204
|
-
// 交互模式
|
|
205
114
|
async function chat() {
|
|
206
115
|
const llmConfig = await getLLMConfig();
|
|
207
|
-
|
|
208
116
|
console.log('🧬 JClaw 交互模式 (输入 "exit" 退出)\n');
|
|
209
|
-
console.log(`📡
|
|
210
|
-
|
|
211
|
-
const agent = new JClawAgent({
|
|
212
|
-
enableAutoSkill: true,
|
|
213
|
-
llm: llmConfig
|
|
214
|
-
});
|
|
117
|
+
console.log(`📡 模型:${llmConfig.model}\n`);
|
|
215
118
|
|
|
119
|
+
const agent = new JClawAgent({ enableAutoSkill: true, llm: llmConfig });
|
|
216
120
|
await agent.start();
|
|
217
121
|
|
|
218
122
|
const readline = await import('readline');
|
|
@@ -229,154 +133,62 @@ async function chat() {
|
|
|
229
133
|
console.log('\n👋 再见!\n');
|
|
230
134
|
return;
|
|
231
135
|
}
|
|
232
|
-
|
|
233
136
|
console.log('\n🤖 JClaw:\n');
|
|
234
|
-
const result = await agent.execute({
|
|
235
|
-
id: 'chat',
|
|
236
|
-
prompt: input
|
|
237
|
-
});
|
|
137
|
+
const result = await agent.execute({ id: 'chat', prompt: input });
|
|
238
138
|
console.log(result.output || result.error);
|
|
239
139
|
console.log('');
|
|
240
140
|
ask();
|
|
241
141
|
});
|
|
242
142
|
};
|
|
243
|
-
|
|
244
143
|
ask();
|
|
245
144
|
}
|
|
246
145
|
|
|
247
|
-
// 初始化项目
|
|
248
146
|
async function init() {
|
|
249
147
|
console.log('🧬 初始化 JClaw 项目...\n');
|
|
250
|
-
|
|
251
|
-
const configTemplate = `// JClaw 配置文件 - 支持多种 LLM provider
|
|
252
|
-
export default {
|
|
148
|
+
const configTemplate = `export default {
|
|
253
149
|
enableAutoSkill: true,
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
llm: {
|
|
257
|
-
provider: 'openai', // 或 'infini-openai', 'azure-openai', 'anthropic'
|
|
258
|
-
model: 'gpt-4' // 具体模型
|
|
259
|
-
},
|
|
260
|
-
|
|
150
|
+
llm: { provider: 'openai', model: 'gpt-4' },
|
|
261
151
|
providers: {
|
|
262
152
|
'openai': {
|
|
263
153
|
baseURL: 'https://api.openai.com/v1',
|
|
264
154
|
apiKeyEnv: 'OPENAI_API_KEY',
|
|
265
|
-
models: ['gpt-4', 'gpt-4o'
|
|
266
|
-
},
|
|
267
|
-
'infini-openai': {
|
|
268
|
-
baseURL: 'https://cloud.infini-ai.com/maas/coding/v1',
|
|
269
|
-
apiKeyEnv: 'INFINI_API_KEY',
|
|
270
|
-
models: ['kimi-k2.5', 'other-model']
|
|
155
|
+
models: ['gpt-4', 'gpt-4o']
|
|
271
156
|
}
|
|
272
|
-
},
|
|
273
|
-
|
|
274
|
-
contextManager: {
|
|
275
|
-
enableSynonyms: true,
|
|
276
|
-
enableFuzzyMatch: true,
|
|
277
|
-
memoryPath: './.jclaw/memory'
|
|
278
157
|
}
|
|
279
158
|
};
|
|
280
159
|
`;
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
'jclaw.config.js'
|
|
284
|
-
'README.md': `# JClaw Project
|
|
285
|
-
|
|
286
|
-
## 使用环境变量
|
|
287
|
-
|
|
288
|
-
### 方式 1: 通用环境变量(推荐)
|
|
289
|
-
export LLM_API_KEY=sk-...
|
|
290
|
-
export LLM_BASE_URL=https://api.openai.com/v1
|
|
291
|
-
export LLM_MODEL_NAME=gpt-4
|
|
292
|
-
jclaw "你的任务"
|
|
293
|
-
|
|
294
|
-
### 方式 2: Provider 特定变量
|
|
295
|
-
export LLM_PROVIDER=infini-openai
|
|
296
|
-
export INFINI_API_KEY=sk-cp-...
|
|
297
|
-
export LLM_MODEL_NAME=kimi-k2.5
|
|
298
|
-
jclaw "你的任务"
|
|
299
|
-
|
|
300
|
-
## 或使用配置文件
|
|
301
|
-
jclaw "你的任务"
|
|
302
|
-
`
|
|
303
|
-
};
|
|
304
|
-
|
|
305
|
-
for (const [name, content] of Object.entries(files)) {
|
|
306
|
-
if (!existsSync(name)) {
|
|
307
|
-
await writeFile(name, content);
|
|
308
|
-
console.log('✅ 创建:', name);
|
|
309
|
-
}
|
|
160
|
+
if (!existsSync('jclaw.config.js')) {
|
|
161
|
+
await writeFile('jclaw.config.js', configTemplate);
|
|
162
|
+
console.log('✅ 创建:jclaw.config.js');
|
|
310
163
|
}
|
|
311
|
-
|
|
312
164
|
console.log('\n🎉 初始化完成!\n');
|
|
313
165
|
}
|
|
314
166
|
|
|
315
|
-
// 主逻辑
|
|
316
|
-
switch (command) {
|
|
317
|
-
case 'execute':
|
|
318
|
-
case 'exec':
|
|
319
|
-
case 'e':
|
|
320
|
-
const prompt = args.slice(1).join(' ');
|
|
321
|
-
if (!prompt) {
|
|
322
|
-
console.error('❌ 错误:请提供任务描述');
|
|
323
|
-
console.error('示例:jclaw execute "分析我的简历"');
|
|
324
|
-
process.exit(1);
|
|
325
|
-
}
|
|
326
|
-
execute(prompt);
|
|
327
|
-
break;
|
|
328
|
-
|
|
329
|
-
case 'chat':
|
|
330
|
-
case 'c':
|
|
331
|
-
chat();
|
|
332
|
-
break;
|
|
333
|
-
|
|
334
|
-
case 'init':
|
|
335
|
-
case 'i':
|
|
336
|
-
init();
|
|
337
|
-
break;
|
|
338
|
-
|
|
339
|
-
case 'help':
|
|
340
|
-
case 'h':
|
|
341
|
-
case '--help':
|
|
342
|
-
case '-h':
|
|
343
|
-
showHelp();
|
|
344
|
-
break;
|
|
345
|
-
|
|
346
|
-
default:
|
|
347
|
-
if (command)
|
|
348
|
-
|
|
349
|
-
// 主逻辑
|
|
350
167
|
switch (command) {
|
|
351
168
|
case 'execute':
|
|
352
169
|
case 'exec':
|
|
353
170
|
case 'e':
|
|
354
171
|
const prompt = args.slice(1).join(' ');
|
|
355
172
|
if (!prompt) {
|
|
356
|
-
console.error('❌
|
|
357
|
-
console.error('示例:jclaw execute "分析我的简历"');
|
|
173
|
+
console.error('❌ 请提供任务描述');
|
|
358
174
|
process.exit(1);
|
|
359
175
|
}
|
|
360
176
|
execute(prompt);
|
|
361
177
|
break;
|
|
362
|
-
|
|
363
178
|
case 'chat':
|
|
364
179
|
case 'c':
|
|
365
180
|
chat();
|
|
366
181
|
break;
|
|
367
|
-
|
|
368
182
|
case 'init':
|
|
369
183
|
case 'i':
|
|
370
184
|
init();
|
|
371
185
|
break;
|
|
372
|
-
|
|
373
186
|
case 'help':
|
|
374
187
|
case 'h':
|
|
375
188
|
case '--help':
|
|
376
189
|
case '-h':
|
|
377
190
|
showHelp();
|
|
378
191
|
break;
|
|
379
|
-
|
|
380
192
|
default:
|
|
381
193
|
if (command) {
|
|
382
194
|
execute(args.join(' '));
|
|
@@ -384,3 +196,5 @@ switch (command) {
|
|
|
384
196
|
showHelp();
|
|
385
197
|
}
|
|
386
198
|
}
|
|
199
|
+
|
|
200
|
+
// Add temperature env var support
|
|
@@ -1,108 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* LLM Client
|
|
3
|
-
*
|
|
4
|
-
* Provides a generic interface for LLM API calls.
|
|
5
|
-
* Supports OpenAI-compatible APIs and can be extended for other providers.
|
|
6
|
-
*
|
|
7
|
-
* @module @jclaw/core/runtime/llm-client
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Configuration for LLM client
|
|
2
|
+
* LLM Client - Support flexible configuration
|
|
11
3
|
*/
|
|
12
4
|
export interface LLMClientConfig {
|
|
13
|
-
|
|
14
|
-
apiBase: string;
|
|
15
|
-
/** API key for authentication */
|
|
5
|
+
apiBase?: string;
|
|
16
6
|
apiKey: string;
|
|
17
|
-
|
|
18
|
-
model: string;
|
|
19
|
-
/** Request timeout in milliseconds (default: 60000) */
|
|
20
|
-
timeout?: number;
|
|
21
|
-
/** Maximum tokens in response (default: 4096) */
|
|
22
|
-
maxTokens?: number;
|
|
23
|
-
/** Temperature for sampling (default: 0.7) */
|
|
7
|
+
model?: string;
|
|
24
8
|
temperature?: number;
|
|
9
|
+
maxTokens?: number;
|
|
25
10
|
}
|
|
26
|
-
/**
|
|
27
|
-
* Message structure for chat completions
|
|
28
|
-
*/
|
|
29
|
-
export interface ChatMessage {
|
|
30
|
-
/** Role of the message sender */
|
|
31
|
-
role: 'system' | 'user' | 'assistant';
|
|
32
|
-
/** Content of the message */
|
|
33
|
-
content: string;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Response from LLM completion
|
|
37
|
-
*/
|
|
38
|
-
export interface LLMResponse {
|
|
39
|
-
/** Generated text content */
|
|
40
|
-
content: string;
|
|
41
|
-
/** Model used for generation */
|
|
42
|
-
model: string;
|
|
43
|
-
/** Token usage statistics */
|
|
44
|
-
usage?: {
|
|
45
|
-
promptTokens: number;
|
|
46
|
-
completionTokens: number;
|
|
47
|
-
totalTokens: number;
|
|
48
|
-
};
|
|
49
|
-
/** Duration of the request in milliseconds */
|
|
50
|
-
duration: number;
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* LLM Client for making API calls to language models.
|
|
54
|
-
*
|
|
55
|
-
* Supports OpenAI-compatible APIs and provides a unified interface
|
|
56
|
-
* for chat completions.
|
|
57
|
-
*
|
|
58
|
-
* @example
|
|
59
|
-
* ```typescript
|
|
60
|
-
* const client = new LLMClient({
|
|
61
|
-
* apiBase: 'https://api.openai.com/v1',
|
|
62
|
-
* apiKey: 'sk-...',
|
|
63
|
-
* model: 'gpt-4'
|
|
64
|
-
* });
|
|
65
|
-
*
|
|
66
|
-
* const response = await client.chat([
|
|
67
|
-
* { role: 'user', content: 'Hello!' }
|
|
68
|
-
* ]);
|
|
69
|
-
* ```
|
|
70
|
-
*/
|
|
71
11
|
export declare class LLMClient {
|
|
72
12
|
private readonly config;
|
|
73
|
-
/**
|
|
74
|
-
* Create a new LLM client instance.
|
|
75
|
-
*
|
|
76
|
-
* @param config - Configuration options including API credentials
|
|
77
|
-
*/
|
|
78
13
|
constructor(config: LLMClientConfig);
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
* @throws Error if the API request fails
|
|
86
|
-
*/
|
|
87
|
-
chat(messages: ChatMessage[], options?: Partial<Pick<LLMClientConfig, 'maxTokens' | 'temperature'>>): Promise<LLMResponse>;
|
|
88
|
-
/**
|
|
89
|
-
* Send a simple text prompt and get a response.
|
|
90
|
-
*
|
|
91
|
-
* @param prompt - The prompt text
|
|
92
|
-
* @param systemPrompt - Optional system prompt
|
|
93
|
-
* @returns Promise resolving to response content
|
|
94
|
-
*/
|
|
95
|
-
complete(prompt: string, systemPrompt?: string): Promise<string>;
|
|
96
|
-
/**
|
|
97
|
-
* Get the configured model name.
|
|
98
|
-
*/
|
|
99
|
-
get model(): string;
|
|
14
|
+
chat(messages: Array<{
|
|
15
|
+
role: string;
|
|
16
|
+
content: string;
|
|
17
|
+
}>): Promise<{
|
|
18
|
+
content: string;
|
|
19
|
+
}>;
|
|
100
20
|
}
|
|
101
|
-
/**
|
|
102
|
-
* Create a new LLM client instance.
|
|
103
|
-
*
|
|
104
|
-
* @param config - Configuration options
|
|
105
|
-
* @returns New LLMClient instance
|
|
106
|
-
*/
|
|
107
21
|
export declare function createLLMClient(config: LLMClientConfig): LLMClient;
|
|
108
22
|
//# sourceMappingURL=llm-client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm-client.d.ts","sourceRoot":"","sources":["../../src/runtime/llm-client.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"llm-client.d.ts","sourceRoot":"","sources":["../../src/runtime/llm-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAErB;gBAEU,MAAM,EAAE,eAAe;IAU7B,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CA2B7F;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,SAAS,CAElE"}
|
|
@@ -1,124 +1,44 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* LLM Client
|
|
3
|
-
*
|
|
4
|
-
* Provides a generic interface for LLM API calls.
|
|
5
|
-
* Supports OpenAI-compatible APIs and can be extended for other providers.
|
|
6
|
-
*
|
|
7
|
-
* @module @jclaw/core/runtime/llm-client
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* LLM Client for making API calls to language models.
|
|
11
|
-
*
|
|
12
|
-
* Supports OpenAI-compatible APIs and provides a unified interface
|
|
13
|
-
* for chat completions.
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* ```typescript
|
|
17
|
-
* const client = new LLMClient({
|
|
18
|
-
* apiBase: 'https://api.openai.com/v1',
|
|
19
|
-
* apiKey: 'sk-...',
|
|
20
|
-
* model: 'gpt-4'
|
|
21
|
-
* });
|
|
22
|
-
*
|
|
23
|
-
* const response = await client.chat([
|
|
24
|
-
* { role: 'user', content: 'Hello!' }
|
|
25
|
-
* ]);
|
|
26
|
-
* ```
|
|
2
|
+
* LLM Client - Support flexible configuration
|
|
27
3
|
*/
|
|
28
4
|
export class LLMClient {
|
|
29
5
|
config;
|
|
30
|
-
/**
|
|
31
|
-
* Create a new LLM client instance.
|
|
32
|
-
*
|
|
33
|
-
* @param config - Configuration options including API credentials
|
|
34
|
-
*/
|
|
35
6
|
constructor(config) {
|
|
36
7
|
this.config = {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
8
|
+
apiBase: config.apiBase || 'https://api.openai.com/v1',
|
|
9
|
+
apiKey: config.apiKey,
|
|
10
|
+
model: config.model || 'gpt-4',
|
|
11
|
+
temperature: config.temperature ?? 0.7,
|
|
12
|
+
maxTokens: config.maxTokens || 4096,
|
|
41
13
|
};
|
|
42
14
|
}
|
|
43
|
-
|
|
44
|
-
* Send a chat completion request to the LLM.
|
|
45
|
-
*
|
|
46
|
-
* @param messages - Array of chat messages
|
|
47
|
-
* @param options - Optional overrides for this specific request
|
|
48
|
-
* @returns Promise resolving to LLM response
|
|
49
|
-
* @throws Error if the API request fails
|
|
50
|
-
*/
|
|
51
|
-
async chat(messages, options) {
|
|
52
|
-
const startTime = Date.now();
|
|
15
|
+
async chat(messages) {
|
|
53
16
|
try {
|
|
54
17
|
const response = await fetch(`${this.config.apiBase}/chat/completions`, {
|
|
55
18
|
method: 'POST',
|
|
56
19
|
headers: {
|
|
57
20
|
'Content-Type': 'application/json',
|
|
58
|
-
Authorization: `Bearer ${this.config.apiKey}`,
|
|
21
|
+
'Authorization': `Bearer ${this.config.apiKey}`,
|
|
59
22
|
},
|
|
60
23
|
body: JSON.stringify({
|
|
61
24
|
model: this.config.model,
|
|
62
25
|
messages,
|
|
63
|
-
|
|
64
|
-
|
|
26
|
+
temperature: this.config.temperature,
|
|
27
|
+
max_tokens: this.config.maxTokens,
|
|
65
28
|
}),
|
|
66
|
-
signal: AbortSignal.timeout(this.config.timeout),
|
|
67
29
|
});
|
|
68
30
|
if (!response.ok) {
|
|
69
|
-
const
|
|
70
|
-
throw new Error(`LLM API error: ${response.status} - ${
|
|
31
|
+
const error = await response.text();
|
|
32
|
+
throw new Error(`LLM API error: ${response.status} - ${error}`);
|
|
71
33
|
}
|
|
72
|
-
const data =
|
|
73
|
-
|
|
74
|
-
const duration = Date.now() - startTime;
|
|
75
|
-
return {
|
|
76
|
-
content,
|
|
77
|
-
model: data.model,
|
|
78
|
-
usage: data.usage
|
|
79
|
-
? {
|
|
80
|
-
promptTokens: data.usage.prompt_tokens,
|
|
81
|
-
completionTokens: data.usage.completion_tokens,
|
|
82
|
-
totalTokens: data.usage.total_tokens,
|
|
83
|
-
}
|
|
84
|
-
: undefined,
|
|
85
|
-
duration,
|
|
86
|
-
};
|
|
34
|
+
const data = await response.json();
|
|
35
|
+
return { content: data.choices[0]?.message?.content || '' };
|
|
87
36
|
}
|
|
88
37
|
catch (error) {
|
|
89
|
-
|
|
90
|
-
throw new Error(`LLM request failed: ${message}`);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Send a simple text prompt and get a response.
|
|
95
|
-
*
|
|
96
|
-
* @param prompt - The prompt text
|
|
97
|
-
* @param systemPrompt - Optional system prompt
|
|
98
|
-
* @returns Promise resolving to response content
|
|
99
|
-
*/
|
|
100
|
-
async complete(prompt, systemPrompt) {
|
|
101
|
-
const messages = [];
|
|
102
|
-
if (systemPrompt) {
|
|
103
|
-
messages.push({ role: 'system', content: systemPrompt });
|
|
38
|
+
throw new Error(`LLM request failed: ${error}`);
|
|
104
39
|
}
|
|
105
|
-
messages.push({ role: 'user', content: prompt });
|
|
106
|
-
const response = await this.chat(messages);
|
|
107
|
-
return response.content;
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Get the configured model name.
|
|
111
|
-
*/
|
|
112
|
-
get model() {
|
|
113
|
-
return this.config.model;
|
|
114
40
|
}
|
|
115
41
|
}
|
|
116
|
-
/**
|
|
117
|
-
* Create a new LLM client instance.
|
|
118
|
-
*
|
|
119
|
-
* @param config - Configuration options
|
|
120
|
-
* @returns New LLMClient instance
|
|
121
|
-
*/
|
|
122
42
|
export function createLLMClient(config) {
|
|
123
43
|
return new LLMClient(config);
|
|
124
44
|
}
|