ltcraft-ai-auto 1.8.0 → 1.11.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/README.md +1 -1
- package/bin/index.js +200 -36
- package/package.json +2 -2
- package//346/225/231/347/250/213.txt +4 -4
package/README.md
CHANGED
package/bin/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import fs from 'fs';
|
|
|
5
5
|
import path from 'path';
|
|
6
6
|
import os from 'os';
|
|
7
7
|
|
|
8
|
-
const API_BASE_URL = 'https://ai.
|
|
8
|
+
const API_BASE_URL = 'https://ai.lt4net.org';
|
|
9
9
|
|
|
10
10
|
const colors = {
|
|
11
11
|
reset: '\x1b[0m',
|
|
@@ -104,9 +104,9 @@ function readTomlValue(content, key) {
|
|
|
104
104
|
return match ? match[1] : null;
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
function mergeTomlConfig(existing, name, baseUrl
|
|
107
|
+
function mergeTomlConfig(existing, name, baseUrl) {
|
|
108
108
|
let content = existing || '';
|
|
109
|
-
const newSection = `[model_providers.ltcraftai]\nname = "${name}"\nbase_url = "${baseUrl}"
|
|
109
|
+
const newSection = `[model_providers.ltcraftai]\nname = "${name}"\nbase_url = "${baseUrl}"`;
|
|
110
110
|
|
|
111
111
|
// 更新或插入顶层 model_provider
|
|
112
112
|
if (/^model_provider\s*=/m.test(content)) {
|
|
@@ -141,7 +141,7 @@ function configureCodex(apiKey) {
|
|
|
141
141
|
ensureDir(codexDir);
|
|
142
142
|
|
|
143
143
|
const existingToml = fs.existsSync(configPath) ? fs.readFileSync(configPath, 'utf-8') : '';
|
|
144
|
-
const merged = mergeTomlConfig(existingToml, 'LTCraftAI', `${API_BASE_URL}/v1
|
|
144
|
+
const merged = mergeTomlConfig(existingToml, 'LTCraftAI', `${API_BASE_URL}/v1`);
|
|
145
145
|
fs.writeFileSync(configPath, merged, 'utf-8');
|
|
146
146
|
console.log(`✓ 已配置: ${configPath}`);
|
|
147
147
|
|
|
@@ -151,7 +151,7 @@ function configureCodex(apiKey) {
|
|
|
151
151
|
console.log('\n🎉 Codex 配置完成!');
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
function configureOpenCode(
|
|
154
|
+
function configureOpenCode(anthropicKey, openaiKey) {
|
|
155
155
|
const homeDir = getHomeDir();
|
|
156
156
|
const configPath = path.join(homeDir, '.config', 'opencode', 'opencode.json');
|
|
157
157
|
backupFile(configPath);
|
|
@@ -163,7 +163,7 @@ function configureOpenCode(apiKey) {
|
|
|
163
163
|
"name": "LTCraft AI(Anthropic)",
|
|
164
164
|
"options": {
|
|
165
165
|
"baseURL": `${API_BASE_URL}/v1`,
|
|
166
|
-
"apiKey":
|
|
166
|
+
"apiKey": anthropicKey
|
|
167
167
|
}
|
|
168
168
|
},
|
|
169
169
|
"openai": {
|
|
@@ -171,7 +171,7 @@ function configureOpenCode(apiKey) {
|
|
|
171
171
|
"name": "LTCraft AI(Openai)",
|
|
172
172
|
"options": {
|
|
173
173
|
"baseURL": `${API_BASE_URL}/v1`,
|
|
174
|
-
"apiKey":
|
|
174
|
+
"apiKey": openaiKey
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
177
|
}
|
|
@@ -183,7 +183,7 @@ function configureOpenCode(apiKey) {
|
|
|
183
183
|
console.log('提示: 运行 opencode 后使用 /model 选择模型');
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
-
function configureOpenClaw(
|
|
186
|
+
function configureOpenClaw(anthropicKey, openaiKey) {
|
|
187
187
|
const homeDir = getHomeDir();
|
|
188
188
|
const configPath = path.join(homeDir, '.openclaw', 'openclaw.json');
|
|
189
189
|
backupFile(configPath);
|
|
@@ -197,13 +197,13 @@ function configureOpenClaw(apiKey) {
|
|
|
197
197
|
"providers": {
|
|
198
198
|
"LTCraft-Anthropic": {
|
|
199
199
|
"baseUrl": API_BASE_URL,
|
|
200
|
-
"apiKey":
|
|
200
|
+
"apiKey": anthropicKey,
|
|
201
201
|
"api": "anthropic-messages",
|
|
202
202
|
"models": modelClaude
|
|
203
203
|
},
|
|
204
204
|
"LTCraft-Openai": {
|
|
205
205
|
"baseUrl": `${API_BASE_URL}/v1`,
|
|
206
|
-
"apiKey":
|
|
206
|
+
"apiKey": openaiKey,
|
|
207
207
|
"api": "openai-completions",
|
|
208
208
|
"models": [
|
|
209
209
|
...modelClaude,
|
|
@@ -231,6 +231,156 @@ function configureOpenClaw(apiKey) {
|
|
|
231
231
|
console.log('\n⚠️ 配置后需要重启 gateway 才能生效: openclaw gateway restart');
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
+
function escapeYamlSingleQuoted(value) {
|
|
235
|
+
return String(value).replace(/'/g, "''");
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function buildHermesOpenaiBlock(indent, openaiKey) {
|
|
239
|
+
const i1 = indent;
|
|
240
|
+
const i2 = i1 + ' ';
|
|
241
|
+
const i3 = i2 + ' ';
|
|
242
|
+
const i4 = i3 + ' ';
|
|
243
|
+
return [
|
|
244
|
+
`${i1}LTCraft-Openai:`,
|
|
245
|
+
`${i2}api_mode: chat_completions`,
|
|
246
|
+
`${i2}base_url: ${API_BASE_URL}/v1`,
|
|
247
|
+
`${i2}api_key: '${escapeYamlSingleQuoted(openaiKey)}'`,
|
|
248
|
+
`${i2}models:`,
|
|
249
|
+
`${i3}gpt-5.5:`,
|
|
250
|
+
`${i4}context_length: 560000`,
|
|
251
|
+
`${i3}gpt-5.4:`,
|
|
252
|
+
`${i4}context_length: 560000`,
|
|
253
|
+
`${i3}gpt-5.4-mini:`,
|
|
254
|
+
`${i4}context_length: 128000`,
|
|
255
|
+
`${i3}gpt-5.3-codex:`,
|
|
256
|
+
`${i4}context_length: 256000`,
|
|
257
|
+
`${i3}gpt-5.2-codex:`,
|
|
258
|
+
`${i4}context_length: 256000`,
|
|
259
|
+
];
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function buildHermesAnthropicBlock(indent, anthropicKey) {
|
|
263
|
+
const i1 = indent;
|
|
264
|
+
const i2 = i1 + ' ';
|
|
265
|
+
const i3 = i2 + ' ';
|
|
266
|
+
const i4 = i3 + ' ';
|
|
267
|
+
return [
|
|
268
|
+
`${i1}LTCraft-Anthropic:`,
|
|
269
|
+
`${i2}api_mode: anthropic_messages`,
|
|
270
|
+
`${i2}base_url: ${API_BASE_URL}/`,
|
|
271
|
+
`${i2}api_key: '${escapeYamlSingleQuoted(anthropicKey)}'`,
|
|
272
|
+
`${i2}models:`,
|
|
273
|
+
`${i3}claude-sonnet-4-5:`,
|
|
274
|
+
`${i4}context_length: 180000`,
|
|
275
|
+
`${i3}claude-sonnet-4-6:`,
|
|
276
|
+
`${i4}context_length: 960000`,
|
|
277
|
+
`${i3}claude-opus-4-6:`,
|
|
278
|
+
`${i4}context_length: 960000`,
|
|
279
|
+
`${i3}claude-opus-4-7:`,
|
|
280
|
+
`${i4}context_length: 960000`,
|
|
281
|
+
];
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// 在 providers 顶层映射下 upsert 一个子节点;保留其他 provider 与顶层字段不变
|
|
285
|
+
function upsertHermesProvider(content, providerName, getBlockLines) {
|
|
286
|
+
const lines = content.split('\n');
|
|
287
|
+
|
|
288
|
+
// 找 providers: 顶级(无缩进)行
|
|
289
|
+
const providersIdx = lines.findIndex(l => /^providers\s*:\s*$/.test(l));
|
|
290
|
+
|
|
291
|
+
if (providersIdx === -1) {
|
|
292
|
+
// 没有 providers 块,追加一个
|
|
293
|
+
const newLines = [`providers:`, ...getBlockLines(' ')];
|
|
294
|
+
let result = content;
|
|
295
|
+
if (result.length > 0 && !result.endsWith('\n')) result += '\n';
|
|
296
|
+
result += newLines.join('\n') + '\n';
|
|
297
|
+
return result;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// 计算 providers 块结束(下一个顶级非空行)
|
|
301
|
+
let providersEnd = lines.length;
|
|
302
|
+
for (let i = providersIdx + 1; i < lines.length; i++) {
|
|
303
|
+
const l = lines[i];
|
|
304
|
+
if (l.length === 0) continue;
|
|
305
|
+
if (/^\s/.test(l)) continue;
|
|
306
|
+
providersEnd = i;
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// 推导 provider 子块的缩进(取 providers 块内第一个有缩进的行)
|
|
311
|
+
let indent = ' ';
|
|
312
|
+
for (let i = providersIdx + 1; i < providersEnd; i++) {
|
|
313
|
+
const m = lines[i].match(/^(\s+)\S/);
|
|
314
|
+
if (m) { indent = m[1]; break; }
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const block = getBlockLines(indent);
|
|
318
|
+
|
|
319
|
+
// 在 providers 块内找指定子 provider
|
|
320
|
+
const headerRe = new RegExp(`^${indent}${providerName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\s*:`);
|
|
321
|
+
let providerStart = -1;
|
|
322
|
+
for (let i = providersIdx + 1; i < providersEnd; i++) {
|
|
323
|
+
if (headerRe.test(lines[i])) { providerStart = i; break; }
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (providerStart === -1) {
|
|
327
|
+
// 追加到 providers 块末尾(在 providersEnd 之前;跳过尾部空行)
|
|
328
|
+
let insertAt = providersEnd;
|
|
329
|
+
while (insertAt > providersIdx + 1 && lines[insertAt - 1].trim() === '') insertAt--;
|
|
330
|
+
lines.splice(insertAt, 0, ...block);
|
|
331
|
+
return lines.join('\n');
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// 计算该子块结束:下一个缩进 <= indent 的非空行
|
|
335
|
+
let providerEnd = providersEnd;
|
|
336
|
+
for (let i = providerStart + 1; i < providersEnd; i++) {
|
|
337
|
+
const l = lines[i];
|
|
338
|
+
if (l.length === 0) continue;
|
|
339
|
+
const m = l.match(/^(\s*)/);
|
|
340
|
+
if (m[1].length <= indent.length && /\S/.test(l)) {
|
|
341
|
+
providerEnd = i;
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
lines.splice(providerStart, providerEnd - providerStart, ...block);
|
|
347
|
+
return lines.join('\n');
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function configureHermes(anthropicKey, openaiKey) {
|
|
351
|
+
const homeDir = getHomeDir();
|
|
352
|
+
const configPath = path.join(homeDir, '.hermes', 'config.yaml');
|
|
353
|
+
backupFile(configPath);
|
|
354
|
+
ensureDir(path.dirname(configPath));
|
|
355
|
+
|
|
356
|
+
let content;
|
|
357
|
+
if (fs.existsSync(configPath)) {
|
|
358
|
+
content = fs.readFileSync(configPath, 'utf-8');
|
|
359
|
+
content = upsertHermesProvider(content, 'LTCraft-Openai', (indent) => buildHermesOpenaiBlock(indent, openaiKey));
|
|
360
|
+
content = upsertHermesProvider(content, 'LTCraft-Anthropic', (indent) => buildHermesAnthropicBlock(indent, anthropicKey));
|
|
361
|
+
if (!content.endsWith('\n')) content += '\n';
|
|
362
|
+
} else {
|
|
363
|
+
// 新建:写入完整模板(含 model 默认)
|
|
364
|
+
const lines = [
|
|
365
|
+
'model:',
|
|
366
|
+
' default: claude-sonnet-4-6',
|
|
367
|
+
' provider: custom:ltcraft-anthropic',
|
|
368
|
+
'providers:',
|
|
369
|
+
...buildHermesOpenaiBlock(' ', openaiKey),
|
|
370
|
+
...buildHermesAnthropicBlock(' ', anthropicKey),
|
|
371
|
+
];
|
|
372
|
+
content = lines.join('\n') + '\n';
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
fs.writeFileSync(configPath, content, 'utf-8');
|
|
376
|
+
console.log(`✓ 已配置: ${configPath}`);
|
|
377
|
+
console.log('\n🎉 Hermes 配置完成!');
|
|
378
|
+
console.log('\n📖 切换模型命令:');
|
|
379
|
+
console.log(' /model 模型ID --provider LTCraft-Anthropic/Openai --global');
|
|
380
|
+
console.log(' 示例: /model claude-sonnet-4-6 --provider LTCraft-Anthropic --global');
|
|
381
|
+
console.log('\n⚠️ 配置后需要重启 gateway 才能生效: hermes gateway restart');
|
|
382
|
+
}
|
|
383
|
+
|
|
234
384
|
// ==================== 配置检测功能 ====================
|
|
235
385
|
|
|
236
386
|
function maskSecret(value) {
|
|
@@ -558,15 +708,13 @@ function checkCodex() {
|
|
|
558
708
|
// 从 TOML 中提取值
|
|
559
709
|
const globalProvider = readTomlValue(globalToml, 'model_provider');
|
|
560
710
|
const globalBaseUrl = readTomlValue(globalToml, 'base_url');
|
|
561
|
-
const globalApiKeyToml = readTomlValue(globalToml, 'api_key');
|
|
562
711
|
const projectProvider = readTomlValue(projectToml, 'model_provider');
|
|
563
712
|
const projectBaseUrl = readTomlValue(projectToml, 'base_url');
|
|
564
|
-
const projectApiKeyToml = readTomlValue(projectToml, 'api_key');
|
|
565
713
|
|
|
566
714
|
const effectiveBaseUrl = envBaseUrl || projectBaseUrl || globalBaseUrl;
|
|
567
|
-
const effectiveApiKey = envApiKey || projectAuth.OPENAI_API_KEY || globalAuth.OPENAI_API_KEY
|
|
715
|
+
const effectiveApiKey = envApiKey || projectAuth.OPENAI_API_KEY || globalAuth.OPENAI_API_KEY;
|
|
568
716
|
const baseUrlSource = envBaseUrl ? '环境变量' : (projectBaseUrl ? '项目配置' : (globalBaseUrl ? '全局配置' : null));
|
|
569
|
-
const apiKeySource = envApiKey ? '环境变量' : (projectAuth.OPENAI_API_KEY ? '项目auth.json' : (globalAuth.OPENAI_API_KEY ? '全局auth.json' :
|
|
717
|
+
const apiKeySource = envApiKey ? '环境变量' : (projectAuth.OPENAI_API_KEY ? '项目auth.json' : (globalAuth.OPENAI_API_KEY ? '全局auth.json' : null));
|
|
570
718
|
|
|
571
719
|
console.log(colorize('\n🔧 关键配置项 (按优先级合并后):', 'blue'));
|
|
572
720
|
printConfigItem('model_provider', effectiveBaseUrl ? (projectProvider || globalProvider) : null, baseUrlSource ? '配置文件' : null);
|
|
@@ -584,7 +732,6 @@ function checkCodex() {
|
|
|
584
732
|
if (fileExists(projectConfigPath)) {
|
|
585
733
|
console.log(` model_provider: ${projectProvider ? colorize(projectProvider, 'green') : colorize('未设置', 'gray')}`);
|
|
586
734
|
console.log(` base_url: ${projectBaseUrl ? colorize(projectBaseUrl, 'green') : colorize('未设置', 'gray')}`);
|
|
587
|
-
console.log(` api_key: ${projectApiKeyToml ? colorize(maskSecret(projectApiKeyToml), 'green') : colorize('未设置', 'gray')}`);
|
|
588
735
|
} else {
|
|
589
736
|
console.log(colorize(' (文件不存在)', 'gray'));
|
|
590
737
|
}
|
|
@@ -602,7 +749,6 @@ function checkCodex() {
|
|
|
602
749
|
if (fileExists(globalConfigPath)) {
|
|
603
750
|
console.log(` model_provider: ${globalProvider ? colorize(globalProvider, 'green') : colorize('未设置', 'gray')}`);
|
|
604
751
|
console.log(` base_url: ${globalBaseUrl ? colorize(globalBaseUrl, 'green') : colorize('未设置', 'gray')}`);
|
|
605
|
-
console.log(` api_key: ${globalApiKeyToml ? colorize(maskSecret(globalApiKeyToml), 'green') : colorize('未设置', 'gray')}`);
|
|
606
752
|
} else {
|
|
607
753
|
console.log(colorize(' (文件不存在)', 'gray'));
|
|
608
754
|
}
|
|
@@ -680,7 +826,7 @@ async function runCheck() {
|
|
|
680
826
|
async function main() {
|
|
681
827
|
console.log('╔════════════════════════════════════════╗');
|
|
682
828
|
console.log('║ LTCraft AI 配置工具 ║');
|
|
683
|
-
console.log('║ API: https://ai.
|
|
829
|
+
console.log('║ API: https://ai.lt4net.org ║');
|
|
684
830
|
console.log('╚════════════════════════════════════════╝\n');
|
|
685
831
|
|
|
686
832
|
const tool = await select({
|
|
@@ -689,37 +835,55 @@ async function main() {
|
|
|
689
835
|
{ name: 'Claude Code', value: 'claude-code' },
|
|
690
836
|
{ name: 'OpenCode', value: 'opencode' },
|
|
691
837
|
{ name: 'OpenClaw', value: 'openclaw' },
|
|
838
|
+
{ name: 'Hermes', value: 'hermes' },
|
|
692
839
|
{ name: 'Codex', value: 'codex' }
|
|
693
840
|
],
|
|
694
841
|
default: 'claude-code'
|
|
695
842
|
});
|
|
696
843
|
|
|
697
|
-
const
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
844
|
+
const askKey = async (message) => {
|
|
845
|
+
const value = await password({
|
|
846
|
+
message,
|
|
847
|
+
mask: '*',
|
|
848
|
+
validate: (input) => {
|
|
849
|
+
if (!input || input.trim().length === 0) {
|
|
850
|
+
return '令牌不能为空';
|
|
851
|
+
}
|
|
852
|
+
return true;
|
|
703
853
|
}
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
const trimmedKey = apiKey.trim();
|
|
854
|
+
});
|
|
855
|
+
return value.trim();
|
|
856
|
+
};
|
|
709
857
|
|
|
710
858
|
switch (tool) {
|
|
711
|
-
case 'claude-code':
|
|
712
|
-
|
|
859
|
+
case 'claude-code': {
|
|
860
|
+
const anthropicKey = await askKey('请输入/粘贴您的 Anthropic API 令牌:');
|
|
861
|
+
configureClaudeCode(anthropicKey);
|
|
713
862
|
break;
|
|
714
|
-
|
|
715
|
-
|
|
863
|
+
}
|
|
864
|
+
case 'codex': {
|
|
865
|
+
const openaiKey = await askKey('请输入/粘贴您的 OpenAI API 令牌:');
|
|
866
|
+
configureCodex(openaiKey);
|
|
716
867
|
break;
|
|
717
|
-
|
|
718
|
-
|
|
868
|
+
}
|
|
869
|
+
case 'opencode': {
|
|
870
|
+
const anthropicKey = await askKey('请输入/粘贴您的 Anthropic API 令牌:');
|
|
871
|
+
const openaiKey = await askKey('请输入/粘贴您的 OpenAI API 令牌:');
|
|
872
|
+
configureOpenCode(anthropicKey, openaiKey);
|
|
719
873
|
break;
|
|
720
|
-
|
|
721
|
-
|
|
874
|
+
}
|
|
875
|
+
case 'openclaw': {
|
|
876
|
+
const anthropicKey = await askKey('请输入/粘贴您的 Anthropic API 令牌:');
|
|
877
|
+
const openaiKey = await askKey('请输入/粘贴您的 OpenAI API 令牌:');
|
|
878
|
+
configureOpenClaw(anthropicKey, openaiKey);
|
|
722
879
|
break;
|
|
880
|
+
}
|
|
881
|
+
case 'hermes': {
|
|
882
|
+
const anthropicKey = await askKey('请输入/粘贴您的 Anthropic API 令牌:');
|
|
883
|
+
const openaiKey = await askKey('请输入/粘贴您的 OpenAI API 令牌:');
|
|
884
|
+
configureHermes(anthropicKey, openaiKey);
|
|
885
|
+
break;
|
|
886
|
+
}
|
|
723
887
|
}
|
|
724
888
|
}
|
|
725
889
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ltcraft-ai-auto",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "一键配置 Claude Code / OpenCode / OpenClaw 的 API 密钥工具",
|
|
3
|
+
"version": "1.11.0",
|
|
4
|
+
"description": "一键配置 Claude Code / OpenCode / OpenClaw / Hermes / Codex 的 API 密钥工具",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"bin": {
|
|
@@ -21,7 +21,7 @@ Claude Code 会按以下优先级读取配置(文件名通常为 settings.json
|
|
|
21
21
|
JSON
|
|
22
22
|
{
|
|
23
23
|
"env": {
|
|
24
|
-
"ANTHROPIC_BASE_URL": "https://ai.
|
|
24
|
+
"ANTHROPIC_BASE_URL": "https://ai.lt4net.org",
|
|
25
25
|
"API_TIMEOUT_MS": 3000000,
|
|
26
26
|
"ANTHROPIC_AUTH_TOKEN": "sk-xxxxxxxxxxxxxxxxxxxxxxxx"
|
|
27
27
|
}
|
|
@@ -49,7 +49,7 @@ C:\Users<用户名>.config\opencode\opencode.json
|
|
|
49
49
|
"provider": {
|
|
50
50
|
"anthropic": {
|
|
51
51
|
"options": {
|
|
52
|
-
"baseURL": "https://ai.
|
|
52
|
+
"baseURL": "https://ai.lt4net.org/v1"
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
}
|
|
@@ -77,7 +77,7 @@ OpenClaw 配置文件教程(仅配置文件)
|
|
|
77
77
|
"models": {
|
|
78
78
|
"providers": {
|
|
79
79
|
"LTCraft-Anthropic": {
|
|
80
|
-
"baseUrl": "https://ai.
|
|
80
|
+
"baseUrl": "https://ai.lt4net.org",
|
|
81
81
|
"apiKey": "${你的apikey}",
|
|
82
82
|
"api": "anthropic-messages",
|
|
83
83
|
"models": [
|
|
@@ -86,7 +86,7 @@ OpenClaw 配置文件教程(仅配置文件)
|
|
|
86
86
|
]
|
|
87
87
|
},
|
|
88
88
|
"LTCraft-Openai": {
|
|
89
|
-
"baseUrl": "https://ai.
|
|
89
|
+
"baseUrl": "https://ai.lt4net.org/v1",
|
|
90
90
|
"apiKey": "${你的apikey}",
|
|
91
91
|
"api": "openai-completions",
|
|
92
92
|
"models": [
|