clawzempic 1.0.6 → 1.0.8
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/bin/clawzempic.js +87 -54
- package/package.json +1 -1
package/bin/clawzempic.js
CHANGED
|
@@ -12,6 +12,11 @@
|
|
|
12
12
|
* npx clawzempic test Verify your connection works
|
|
13
13
|
* npx clawzempic status Check usage and savings
|
|
14
14
|
* npx clawzempic doctor Diagnose common issues
|
|
15
|
+
*
|
|
16
|
+
* Flags:
|
|
17
|
+
* --key <key> Provide API key (skip interactive prompt)
|
|
18
|
+
* --yes, -y Auto-confirm all prompts (non-interactive)
|
|
19
|
+
* --no-test Skip connection test after init
|
|
15
20
|
*/
|
|
16
21
|
|
|
17
22
|
import { createInterface } from 'node:readline/promises';
|
|
@@ -22,7 +27,7 @@ import { join, basename } from 'node:path';
|
|
|
22
27
|
// ── Constants ─────────────────────────────────────────────────────────────────
|
|
23
28
|
|
|
24
29
|
const API_BASE = 'https://api.clawzempic.ai';
|
|
25
|
-
const VERSION = '1.0.
|
|
30
|
+
const VERSION = '1.0.8';
|
|
26
31
|
const OPENCLAW_DIR_NAME = '.openclaw';
|
|
27
32
|
|
|
28
33
|
// ── ANSI Colors (no dependencies) ─────────────────────────────────────────────
|
|
@@ -192,6 +197,8 @@ async function ask(question, opts = {}) {
|
|
|
192
197
|
}
|
|
193
198
|
|
|
194
199
|
async function confirm(question, defaultYes = true) {
|
|
200
|
+
// --yes flag auto-confirms everything
|
|
201
|
+
if (globalArgs?.yes) return true;
|
|
195
202
|
const hint = defaultYes ? 'Y/n' : 'y/N';
|
|
196
203
|
const answer = await ask(`${question} ${c.dim}(${hint})${c.reset}`, { required: false });
|
|
197
204
|
if (!answer) return defaultYes;
|
|
@@ -281,7 +288,7 @@ const FRAMEWORKS = [
|
|
|
281
288
|
return false;
|
|
282
289
|
},
|
|
283
290
|
envFile: '.env',
|
|
284
|
-
envVars: {
|
|
291
|
+
envVars: { LLM_API_KEY: null, LLM_BASE_URL: API_BASE },
|
|
285
292
|
},
|
|
286
293
|
{
|
|
287
294
|
id: 'nanobot',
|
|
@@ -297,11 +304,11 @@ const FRAMEWORKS = [
|
|
|
297
304
|
return false;
|
|
298
305
|
},
|
|
299
306
|
envFile: '.env',
|
|
300
|
-
envVars: {
|
|
307
|
+
envVars: { LLM_API_KEY: null, LLM_BASE_URL: API_BASE },
|
|
301
308
|
},
|
|
302
309
|
{
|
|
303
310
|
id: 'python',
|
|
304
|
-
name: 'Python (Anthropic SDK)',
|
|
311
|
+
name: 'Python (Anthropic/OpenRouter SDK)',
|
|
305
312
|
detect: (dir) => {
|
|
306
313
|
for (const f of ['requirements.txt', 'pyproject.toml', 'Pipfile']) {
|
|
307
314
|
if (existsSync(join(dir, f))) {
|
|
@@ -314,7 +321,7 @@ const FRAMEWORKS = [
|
|
|
314
321
|
return false;
|
|
315
322
|
},
|
|
316
323
|
envFile: '.env',
|
|
317
|
-
envVars: {
|
|
324
|
+
envVars: { LLM_API_KEY: null, LLM_BASE_URL: API_BASE },
|
|
318
325
|
},
|
|
319
326
|
{
|
|
320
327
|
id: 'langchain',
|
|
@@ -331,11 +338,11 @@ const FRAMEWORKS = [
|
|
|
331
338
|
return false;
|
|
332
339
|
},
|
|
333
340
|
envFile: '.env',
|
|
334
|
-
envVars: {
|
|
341
|
+
envVars: { LLM_API_KEY: null, LLM_BASE_URL: API_BASE },
|
|
335
342
|
},
|
|
336
343
|
{
|
|
337
344
|
id: 'node',
|
|
338
|
-
name: 'Node.js (Anthropic SDK)',
|
|
345
|
+
name: 'Node.js (Anthropic/OpenRouter SDK)',
|
|
339
346
|
detect: (dir) => {
|
|
340
347
|
if (existsSync(join(dir, 'package.json'))) {
|
|
341
348
|
try {
|
|
@@ -346,7 +353,7 @@ const FRAMEWORKS = [
|
|
|
346
353
|
return false;
|
|
347
354
|
},
|
|
348
355
|
envFile: '.env',
|
|
349
|
-
envVars: {
|
|
356
|
+
envVars: { LLM_API_KEY: null, LLM_BASE_URL: API_BASE },
|
|
350
357
|
},
|
|
351
358
|
];
|
|
352
359
|
|
|
@@ -436,10 +443,12 @@ function findOpenClawDir(dir) {
|
|
|
436
443
|
}
|
|
437
444
|
|
|
438
445
|
/**
|
|
439
|
-
* Check if this is OpenClaw v2026.2+ (has auth-profiles.json).
|
|
446
|
+
* Check if this is OpenClaw v2026.2+ (has auth-profiles.json or openclaw.json).
|
|
447
|
+
* Fresh installs may not have auth-profiles.json yet, but openclaw.json is always present.
|
|
440
448
|
*/
|
|
441
449
|
function isModernOpenClaw(openclawDir) {
|
|
442
|
-
return existsSync(join(openclawDir, 'auth-profiles.json'))
|
|
450
|
+
return existsSync(join(openclawDir, 'auth-profiles.json')) ||
|
|
451
|
+
existsSync(join(openclawDir, 'openclaw.json'));
|
|
443
452
|
}
|
|
444
453
|
|
|
445
454
|
/**
|
|
@@ -558,8 +567,8 @@ function findKeyInAuthProfiles(openclawDir) {
|
|
|
558
567
|
* Find API key from all possible locations.
|
|
559
568
|
*/
|
|
560
569
|
function findApiKey(dir) {
|
|
561
|
-
// 1. Environment variables
|
|
562
|
-
const envKey = process.env.CLAWZEMPIC_API_KEY || process.env.ANTHROPIC_API_KEY;
|
|
570
|
+
// 1. Environment variables (check new names first, fall back to old)
|
|
571
|
+
const envKey = process.env.CLAWZEMPIC_API_KEY || process.env.LLM_API_KEY || process.env.ANTHROPIC_API_KEY;
|
|
563
572
|
if (envKey && (envKey.startsWith('sk-clwz-') || envKey.startsWith('sr_'))) {
|
|
564
573
|
return { key: envKey, source: 'environment variable' };
|
|
565
574
|
}
|
|
@@ -578,7 +587,7 @@ function findApiKey(dir) {
|
|
|
578
587
|
if (existsSync(envPath)) {
|
|
579
588
|
try {
|
|
580
589
|
const content = readFileSync(envPath, 'utf8');
|
|
581
|
-
const match = content.match(/^(?:CLAWZEMPIC_API_KEY|ANTHROPIC_API_KEY)\s*=\s*(.+)$/m);
|
|
590
|
+
const match = content.match(/^(?:CLAWZEMPIC_API_KEY|LLM_API_KEY|ANTHROPIC_API_KEY)\s*=\s*(.+)$/m);
|
|
582
591
|
if (match) {
|
|
583
592
|
const val = match[1].trim();
|
|
584
593
|
if (val.startsWith('sk-clwz-') || val.startsWith('sr_')) {
|
|
@@ -778,7 +787,7 @@ async function cmdInit(args) {
|
|
|
778
787
|
// Build env vars: proxy key + base URL. Keep provider key separate.
|
|
779
788
|
const envVars = {
|
|
780
789
|
CLAWZEMPIC_API_KEY: clawzempicKey,
|
|
781
|
-
|
|
790
|
+
LLM_BASE_URL: API_BASE,
|
|
782
791
|
};
|
|
783
792
|
|
|
784
793
|
// Show what we'll do
|
|
@@ -800,7 +809,7 @@ async function cmdInit(args) {
|
|
|
800
809
|
return cleanup();
|
|
801
810
|
}
|
|
802
811
|
|
|
803
|
-
// Clean up v1.0.3 bug
|
|
812
|
+
// Clean up legacy: remove Clawzempic keys from ANTHROPIC_API_KEY (v1.0.3 bug + old naming)
|
|
804
813
|
if (existsSync(envPath)) {
|
|
805
814
|
const existing = readFileSync(envPath, 'utf8');
|
|
806
815
|
const badMatch = existing.match(/^ANTHROPIC_API_KEY\s*=\s*(.+)$/m);
|
|
@@ -809,9 +818,16 @@ async function cmdInit(args) {
|
|
|
809
818
|
if (badVal.startsWith('sr_') || badVal.startsWith('sk-clwz-')) {
|
|
810
819
|
const cleaned = existing.replace(/^ANTHROPIC_API_KEY\s*=\s*(?:sr_|sk-clwz-).+\n?/m, '');
|
|
811
820
|
writeFileSync(envPath, cleaned, 'utf8');
|
|
812
|
-
bullet(warn, `Removed stale ANTHROPIC_API_KEY (had a Clawzempic key
|
|
821
|
+
bullet(warn, `Removed stale ANTHROPIC_API_KEY (had a Clawzempic key — use CLAWZEMPIC_API_KEY instead)`);
|
|
813
822
|
}
|
|
814
823
|
}
|
|
824
|
+
// Also clean up old ANTHROPIC_BASE_URL pointing to clawzempic
|
|
825
|
+
const oldBaseMatch = existing.match(/^ANTHROPIC_BASE_URL\s*=\s*(.+)$/m);
|
|
826
|
+
if (oldBaseMatch && oldBaseMatch[1].includes('clawzempic.ai')) {
|
|
827
|
+
const cleaned2 = existing.replace(/^ANTHROPIC_BASE_URL\s*=\s*.+clawzempic\.ai.+\n?/m, '');
|
|
828
|
+
writeFileSync(envPath, cleaned2, 'utf8');
|
|
829
|
+
bullet(warn, `Migrated ANTHROPIC_BASE_URL → LLM_BASE_URL`);
|
|
830
|
+
}
|
|
815
831
|
}
|
|
816
832
|
|
|
817
833
|
// Apply
|
|
@@ -828,10 +844,15 @@ async function cmdInit(args) {
|
|
|
828
844
|
// ── Test Connection ──────────────────────────────────────────────────────
|
|
829
845
|
|
|
830
846
|
blank();
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
847
|
+
let testPassed = true;
|
|
848
|
+
if (args.noTest) {
|
|
849
|
+
bullet(info, 'Skipping connection test (--no-test)');
|
|
850
|
+
} else {
|
|
851
|
+
const runTest = await confirm('Test the connection?');
|
|
852
|
+
testPassed = !runTest; // skip = assume ok
|
|
853
|
+
if (runTest) {
|
|
854
|
+
testPassed = await runConnectionTest(clawzempicKey);
|
|
855
|
+
}
|
|
835
856
|
}
|
|
836
857
|
|
|
837
858
|
// ── Done ─────────────────────────────────────────────────────────────────
|
|
@@ -1093,7 +1114,7 @@ async function cmdDoctor() {
|
|
|
1093
1114
|
|
|
1094
1115
|
// 2. Check for Clawzempic config
|
|
1095
1116
|
const content = readFileSync(envPath, 'utf8');
|
|
1096
|
-
const keyMatch = content.match(/^(?:CLAWZEMPIC_API_KEY|ANTHROPIC_API_KEY)\s*=\s*(.+)$/m);
|
|
1117
|
+
const keyMatch = content.match(/^(?:CLAWZEMPIC_API_KEY|LLM_API_KEY|ANTHROPIC_API_KEY)\s*=\s*(.+)$/m);
|
|
1097
1118
|
if (keyMatch && (keyMatch[1].startsWith('sk-clwz-') || keyMatch[1].startsWith('sr_'))) {
|
|
1098
1119
|
bullet(ok, `Clawzempic API key found`);
|
|
1099
1120
|
} else if (keyMatch) {
|
|
@@ -1104,14 +1125,14 @@ async function cmdDoctor() {
|
|
|
1104
1125
|
return cleanup(1);
|
|
1105
1126
|
}
|
|
1106
1127
|
|
|
1107
|
-
// 3. Check base URL
|
|
1108
|
-
const baseUrlMatch = content.match(/^ANTHROPIC_BASE_URL\s*=\s*(.+)$/m);
|
|
1128
|
+
// 3. Check base URL (check LLM_BASE_URL first, fall back to ANTHROPIC_BASE_URL)
|
|
1129
|
+
const baseUrlMatch = content.match(/^(?:LLM_BASE_URL|ANTHROPIC_BASE_URL)\s*=\s*(.+)$/m);
|
|
1109
1130
|
if (baseUrlMatch && baseUrlMatch[1].includes('clawzempic.ai')) {
|
|
1110
1131
|
bullet(ok, `Base URL pointing to Clawzempic`);
|
|
1111
1132
|
} else if (baseUrlMatch) {
|
|
1112
1133
|
bullet(warn, `Base URL set to ${baseUrlMatch[1]} — not pointing to Clawzempic`);
|
|
1113
1134
|
} else {
|
|
1114
|
-
bullet(fail, `
|
|
1135
|
+
bullet(fail, `LLM_BASE_URL not set — requests go directly to your provider, bypassing Clawzempic`);
|
|
1115
1136
|
}
|
|
1116
1137
|
|
|
1117
1138
|
// 4. Check framework
|
|
@@ -1189,13 +1210,15 @@ function cmdHelp() {
|
|
|
1189
1210
|
// ── Arg Parsing ───────────────────────────────────────────────────────────────
|
|
1190
1211
|
|
|
1191
1212
|
function parseArgs(argv) {
|
|
1192
|
-
const args = { command: null, key: null, help: false, version: false };
|
|
1213
|
+
const args = { command: null, key: null, help: false, version: false, yes: false, noTest: false };
|
|
1193
1214
|
const positional = [];
|
|
1194
1215
|
|
|
1195
1216
|
for (let i = 2; i < argv.length; i++) {
|
|
1196
1217
|
const arg = argv[i];
|
|
1197
1218
|
if (arg === '--help' || arg === '-h') args.help = true;
|
|
1198
1219
|
else if (arg === '--version' || arg === '-v') args.version = true;
|
|
1220
|
+
else if (arg === '--yes' || arg === '-y') args.yes = true;
|
|
1221
|
+
else if (arg === '--no-test') args.noTest = true;
|
|
1199
1222
|
else if (arg === '--key' && argv[i + 1]) { args.key = argv[++i]; }
|
|
1200
1223
|
else if (!arg.startsWith('-')) positional.push(arg);
|
|
1201
1224
|
}
|
|
@@ -1222,38 +1245,48 @@ process.on('SIGINT', () => {
|
|
|
1222
1245
|
|
|
1223
1246
|
// ── Main ──────────────────────────────────────────────────────────────────────
|
|
1224
1247
|
|
|
1225
|
-
|
|
1248
|
+
let globalArgs = null;
|
|
1226
1249
|
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
}
|
|
1250
|
+
async function main() {
|
|
1251
|
+
const args = parseArgs(process.argv);
|
|
1252
|
+
globalArgs = args;
|
|
1231
1253
|
|
|
1232
|
-
if (args.
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
}
|
|
1254
|
+
if (args.version) {
|
|
1255
|
+
console.log(`clawzempic ${VERSION}`);
|
|
1256
|
+
process.exit(0);
|
|
1257
|
+
}
|
|
1236
1258
|
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
switch (command) {
|
|
1240
|
-
case 'init':
|
|
1241
|
-
await cmdInit(args);
|
|
1242
|
-
break;
|
|
1243
|
-
case 'test':
|
|
1244
|
-
await cmdTest(args);
|
|
1245
|
-
break;
|
|
1246
|
-
case 'status':
|
|
1247
|
-
await cmdStatus(args);
|
|
1248
|
-
break;
|
|
1249
|
-
case 'doctor':
|
|
1250
|
-
await cmdDoctor();
|
|
1251
|
-
break;
|
|
1252
|
-
case 'help':
|
|
1259
|
+
if (args.help && !args.command) {
|
|
1253
1260
|
cmdHelp();
|
|
1254
1261
|
process.exit(0);
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
const command = args.command || 'init';
|
|
1265
|
+
|
|
1266
|
+
switch (command) {
|
|
1267
|
+
case 'init':
|
|
1268
|
+
await cmdInit(args);
|
|
1269
|
+
break;
|
|
1270
|
+
case 'test':
|
|
1271
|
+
await cmdTest(args);
|
|
1272
|
+
break;
|
|
1273
|
+
case 'status':
|
|
1274
|
+
await cmdStatus(args);
|
|
1275
|
+
break;
|
|
1276
|
+
case 'doctor':
|
|
1277
|
+
await cmdDoctor();
|
|
1278
|
+
break;
|
|
1279
|
+
case 'help':
|
|
1280
|
+
cmdHelp();
|
|
1281
|
+
process.exit(0);
|
|
1282
|
+
break;
|
|
1283
|
+
default:
|
|
1284
|
+
console.error(`Unknown command: ${command}. Run 'npx clawzempic --help' for usage.`);
|
|
1285
|
+
process.exit(1);
|
|
1286
|
+
}
|
|
1259
1287
|
}
|
|
1288
|
+
|
|
1289
|
+
main().catch(err => {
|
|
1290
|
+
console.error(`\n ${c.red}Fatal:${c.reset} ${err.message}\n`);
|
|
1291
|
+
process.exit(1);
|
|
1292
|
+
});
|
package/package.json
CHANGED