cc-claw 0.15.1 → 0.16.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.js +609 -74
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -33,7 +33,7 @@ var VERSION;
|
|
|
33
33
|
var init_version = __esm({
|
|
34
34
|
"src/version.ts"() {
|
|
35
35
|
"use strict";
|
|
36
|
-
VERSION = true ? "0.
|
|
36
|
+
VERSION = true ? "0.16.0" : (() => {
|
|
37
37
|
try {
|
|
38
38
|
return JSON.parse(readFileSync(join(process.cwd(), "package.json"), "utf-8")).version ?? "unknown";
|
|
39
39
|
} catch {
|
|
@@ -1729,6 +1729,30 @@ function initSchema(db3) {
|
|
|
1729
1729
|
mode TEXT NOT NULL DEFAULT 'auto'
|
|
1730
1730
|
);
|
|
1731
1731
|
`);
|
|
1732
|
+
db3.exec(`
|
|
1733
|
+
CREATE TABLE IF NOT EXISTS backend_credentials (
|
|
1734
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
1735
|
+
backend TEXT NOT NULL,
|
|
1736
|
+
slot_type TEXT NOT NULL DEFAULT 'api_key',
|
|
1737
|
+
label TEXT,
|
|
1738
|
+
api_key TEXT,
|
|
1739
|
+
config_home TEXT,
|
|
1740
|
+
priority INTEGER NOT NULL DEFAULT 0,
|
|
1741
|
+
enabled INTEGER NOT NULL DEFAULT 1,
|
|
1742
|
+
cooldown_until TEXT,
|
|
1743
|
+
last_used TEXT,
|
|
1744
|
+
consecutive_errors INTEGER NOT NULL DEFAULT 0,
|
|
1745
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1746
|
+
);
|
|
1747
|
+
`);
|
|
1748
|
+
db3.exec(`
|
|
1749
|
+
CREATE TABLE IF NOT EXISTS chat_backend_slot (
|
|
1750
|
+
chat_id TEXT NOT NULL,
|
|
1751
|
+
backend TEXT NOT NULL,
|
|
1752
|
+
slot_id INTEGER,
|
|
1753
|
+
PRIMARY KEY (chat_id, backend)
|
|
1754
|
+
);
|
|
1755
|
+
`);
|
|
1732
1756
|
try {
|
|
1733
1757
|
const deleted = db3.prepare(
|
|
1734
1758
|
"DELETE FROM usage_log WHERE created_at < datetime('now', '-90 days')"
|
|
@@ -3311,10 +3335,108 @@ var init_gemini_slots = __esm({
|
|
|
3311
3335
|
}
|
|
3312
3336
|
});
|
|
3313
3337
|
|
|
3338
|
+
// src/memory/backend-slots.ts
|
|
3339
|
+
function getBackendSlots(backend2) {
|
|
3340
|
+
return getDb().prepare(`
|
|
3341
|
+
SELECT ${SLOT_COLUMNS}
|
|
3342
|
+
FROM backend_credentials WHERE backend = ? ORDER BY priority ASC, id ASC
|
|
3343
|
+
`).all(backend2);
|
|
3344
|
+
}
|
|
3345
|
+
function getEligibleBackendSlots(backend2) {
|
|
3346
|
+
return getDb().prepare(`
|
|
3347
|
+
SELECT ${SLOT_COLUMNS}
|
|
3348
|
+
FROM backend_credentials
|
|
3349
|
+
WHERE backend = ? AND enabled = 1
|
|
3350
|
+
AND (cooldown_until IS NULL OR cooldown_until <= datetime('now'))
|
|
3351
|
+
ORDER BY priority ASC, last_used ASC NULLS FIRST
|
|
3352
|
+
`).all(backend2);
|
|
3353
|
+
}
|
|
3354
|
+
function getChatBackendSlotId(chatId, backend2) {
|
|
3355
|
+
const row = getDb().prepare(
|
|
3356
|
+
"SELECT slot_id FROM chat_backend_slot WHERE chat_id = ? AND backend = ?"
|
|
3357
|
+
).get(chatId, backend2);
|
|
3358
|
+
return row?.slot_id ?? null;
|
|
3359
|
+
}
|
|
3360
|
+
function getNextBackendSlot(chatId, backend2) {
|
|
3361
|
+
const pinned = getDb().prepare(`
|
|
3362
|
+
SELECT ${SLOT_COLUMNS}
|
|
3363
|
+
FROM backend_credentials bc
|
|
3364
|
+
JOIN chat_backend_slot cbs ON cbs.slot_id = bc.id
|
|
3365
|
+
WHERE cbs.chat_id = ? AND cbs.backend = ? AND bc.enabled = 1
|
|
3366
|
+
AND (bc.cooldown_until IS NULL OR bc.cooldown_until <= datetime('now'))
|
|
3367
|
+
`).get(chatId, backend2);
|
|
3368
|
+
if (pinned) return pinned;
|
|
3369
|
+
const eligible = getEligibleBackendSlots(backend2);
|
|
3370
|
+
return eligible.length > 0 ? eligible[0] : null;
|
|
3371
|
+
}
|
|
3372
|
+
function markBackendSlotSuccess(slotId) {
|
|
3373
|
+
getDb().prepare(`
|
|
3374
|
+
UPDATE backend_credentials
|
|
3375
|
+
SET last_used = datetime('now'), consecutive_errors = 0,
|
|
3376
|
+
cooldown_until = CASE WHEN cooldown_until < datetime('now') THEN NULL ELSE cooldown_until END
|
|
3377
|
+
WHERE id = ?
|
|
3378
|
+
`).run(slotId);
|
|
3379
|
+
}
|
|
3380
|
+
function markBackendSlotExhausted(slotId, cooldownHours = 6) {
|
|
3381
|
+
getDb().prepare(`
|
|
3382
|
+
UPDATE backend_credentials
|
|
3383
|
+
SET cooldown_until = datetime('now', '+' || ? || ' hours'),
|
|
3384
|
+
consecutive_errors = consecutive_errors + 1,
|
|
3385
|
+
enabled = CASE WHEN consecutive_errors + 1 >= 10 THEN 0 ELSE enabled END
|
|
3386
|
+
WHERE id = ?
|
|
3387
|
+
`).run(cooldownHours, slotId);
|
|
3388
|
+
}
|
|
3389
|
+
function pinChatBackendSlot(chatId, backend2, slotId) {
|
|
3390
|
+
getDb().prepare(`
|
|
3391
|
+
INSERT INTO chat_backend_slot (chat_id, backend, slot_id) VALUES (?, ?, ?)
|
|
3392
|
+
ON CONFLICT(chat_id, backend) DO UPDATE SET slot_id = excluded.slot_id
|
|
3393
|
+
`).run(chatId, backend2, slotId);
|
|
3394
|
+
}
|
|
3395
|
+
function clearChatBackendSlot(chatId, backend2) {
|
|
3396
|
+
getDb().prepare("DELETE FROM chat_backend_slot WHERE chat_id = ? AND backend = ?").run(chatId, backend2);
|
|
3397
|
+
}
|
|
3398
|
+
function addBackendSlot(opts) {
|
|
3399
|
+
const result = getDb().prepare(`
|
|
3400
|
+
INSERT INTO backend_credentials (backend, slot_type, label, api_key, config_home, priority)
|
|
3401
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
3402
|
+
`).run(opts.backend, opts.slotType, opts.label ?? null, opts.apiKey ?? null, opts.configHome ?? null, opts.priority ?? 0);
|
|
3403
|
+
return Number(result.lastInsertRowid);
|
|
3404
|
+
}
|
|
3405
|
+
function removeBackendSlot(id) {
|
|
3406
|
+
getDb().prepare("DELETE FROM chat_backend_slot WHERE slot_id = ?").run(id);
|
|
3407
|
+
return getDb().prepare("DELETE FROM backend_credentials WHERE id = ?").run(id).changes > 0;
|
|
3408
|
+
}
|
|
3409
|
+
function setBackendSlotEnabled(id, enabled) {
|
|
3410
|
+
getDb().prepare("UPDATE backend_credentials SET enabled = ? WHERE id = ?").run(enabled ? 1 : 0, id);
|
|
3411
|
+
}
|
|
3412
|
+
function reorderBackendSlot(id, priority) {
|
|
3413
|
+
getDb().prepare("UPDATE backend_credentials SET priority = ? WHERE id = ?").run(priority, id);
|
|
3414
|
+
}
|
|
3415
|
+
function reenableBackendSlot(slotId) {
|
|
3416
|
+
getDb().prepare(`
|
|
3417
|
+
UPDATE backend_credentials
|
|
3418
|
+
SET enabled = 1, consecutive_errors = 0, cooldown_until = NULL
|
|
3419
|
+
WHERE id = ?
|
|
3420
|
+
`).run(slotId);
|
|
3421
|
+
}
|
|
3422
|
+
var SLOT_COLUMNS;
|
|
3423
|
+
var init_backend_slots = __esm({
|
|
3424
|
+
"src/memory/backend-slots.ts"() {
|
|
3425
|
+
"use strict";
|
|
3426
|
+
init_store5();
|
|
3427
|
+
SLOT_COLUMNS = `
|
|
3428
|
+
id, backend, slot_type AS slotType, label, api_key AS apiKey, config_home AS configHome,
|
|
3429
|
+
priority, enabled, cooldown_until AS cooldownUntil, last_used AS lastUsed,
|
|
3430
|
+
consecutive_errors AS consecutiveErrors, created_at AS createdAt
|
|
3431
|
+
`;
|
|
3432
|
+
}
|
|
3433
|
+
});
|
|
3434
|
+
|
|
3314
3435
|
// src/memory/store.ts
|
|
3315
3436
|
var store_exports5 = {};
|
|
3316
3437
|
__export(store_exports5, {
|
|
3317
3438
|
ALL_TOOLS: () => ALL_TOOLS,
|
|
3439
|
+
addBackendSlot: () => addBackendSlot,
|
|
3318
3440
|
addGeminiSlot: () => addGeminiSlot,
|
|
3319
3441
|
addHeartbeatWatch: () => addHeartbeatWatch,
|
|
3320
3442
|
addUsage: () => addUsage,
|
|
@@ -3325,6 +3447,7 @@ __export(store_exports5, {
|
|
|
3325
3447
|
clearAgentMode: () => clearAgentMode,
|
|
3326
3448
|
clearAllSessions: () => clearAllSessions,
|
|
3327
3449
|
clearBackendLimit: () => clearBackendLimit,
|
|
3450
|
+
clearChatBackendSlot: () => clearChatBackendSlot,
|
|
3328
3451
|
clearChatGeminiSlot: () => clearChatGeminiSlot,
|
|
3329
3452
|
clearCwd: () => clearCwd,
|
|
3330
3453
|
clearMessageLog: () => clearMessageLog,
|
|
@@ -3352,13 +3475,16 @@ __export(store_exports5, {
|
|
|
3352
3475
|
getAllTimeUsage: () => getAllTimeUsage,
|
|
3353
3476
|
getBackend: () => getBackend,
|
|
3354
3477
|
getBackendLimit: () => getBackendLimit,
|
|
3478
|
+
getBackendSlots: () => getBackendSlots,
|
|
3355
3479
|
getBackendUsageInWindow: () => getBackendUsageInWindow,
|
|
3356
3480
|
getBookmark: () => getBookmark,
|
|
3481
|
+
getChatBackendSlotId: () => getChatBackendSlotId,
|
|
3357
3482
|
getChatGeminiSlotId: () => getChatGeminiSlotId,
|
|
3358
3483
|
getChatIdByAlias: () => getChatIdByAlias,
|
|
3359
3484
|
getChatUsageByModel: () => getChatUsageByModel,
|
|
3360
3485
|
getCwd: () => getCwd,
|
|
3361
3486
|
getDb: () => getDb,
|
|
3487
|
+
getEligibleBackendSlots: () => getEligibleBackendSlots,
|
|
3362
3488
|
getEligibleGeminiSlots: () => getEligibleGeminiSlots,
|
|
3363
3489
|
getEnabledTools: () => getEnabledTools,
|
|
3364
3490
|
getGeminiRotationMode: () => getGeminiRotationMode,
|
|
@@ -3371,6 +3497,7 @@ __export(store_exports5, {
|
|
|
3371
3497
|
getMode: () => getMode,
|
|
3372
3498
|
getModel: () => getModel,
|
|
3373
3499
|
getModelSignature: () => getModelSignature,
|
|
3500
|
+
getNextBackendSlot: () => getNextBackendSlot,
|
|
3374
3501
|
getNextGeminiSlot: () => getNextGeminiSlot,
|
|
3375
3502
|
getPendingEscalation: () => getPendingEscalation,
|
|
3376
3503
|
getRecentBookmarks: () => getRecentBookmarks,
|
|
@@ -3394,18 +3521,24 @@ __export(store_exports5, {
|
|
|
3394
3521
|
insertJobRun: () => insertJobRun,
|
|
3395
3522
|
listMemories: () => listMemories,
|
|
3396
3523
|
listSessionSummaries: () => listSessionSummaries,
|
|
3524
|
+
markBackendSlotExhausted: () => markBackendSlotExhausted,
|
|
3525
|
+
markBackendSlotSuccess: () => markBackendSlotSuccess,
|
|
3397
3526
|
markMessageLogSummarized: () => markMessageLogSummarized,
|
|
3398
3527
|
markSlotExhausted: () => markSlotExhausted,
|
|
3399
3528
|
markSlotSuccess: () => markSlotSuccess,
|
|
3400
3529
|
openDatabaseReadOnly: () => openDatabaseReadOnly,
|
|
3530
|
+
pinChatBackendSlot: () => pinChatBackendSlot,
|
|
3401
3531
|
pinChatGeminiSlot: () => pinChatGeminiSlot,
|
|
3402
3532
|
pruneJobRuns: () => pruneJobRuns,
|
|
3403
3533
|
pruneMessageLog: () => pruneMessageLog,
|
|
3534
|
+
reenableBackendSlot: () => reenableBackendSlot,
|
|
3404
3535
|
reenableSlot: () => reenableSlot,
|
|
3536
|
+
removeBackendSlot: () => removeBackendSlot,
|
|
3405
3537
|
removeChatAlias: () => removeChatAlias,
|
|
3406
3538
|
removeGeminiSlot: () => removeGeminiSlot,
|
|
3407
3539
|
removeHeartbeatWatch: () => removeHeartbeatWatch,
|
|
3408
3540
|
removePendingEscalation: () => removePendingEscalation,
|
|
3541
|
+
reorderBackendSlot: () => reorderBackendSlot,
|
|
3409
3542
|
reorderGeminiSlot: () => reorderGeminiSlot,
|
|
3410
3543
|
resetJobFailures: () => resetJobFailures,
|
|
3411
3544
|
resetTools: () => resetTools,
|
|
@@ -3420,6 +3553,7 @@ __export(store_exports5, {
|
|
|
3420
3553
|
setAgentMode: () => setAgentMode,
|
|
3421
3554
|
setBackend: () => setBackend,
|
|
3422
3555
|
setBackendLimit: () => setBackendLimit,
|
|
3556
|
+
setBackendSlotEnabled: () => setBackendSlotEnabled,
|
|
3423
3557
|
setBootTime: () => setBootTime,
|
|
3424
3558
|
setChatAlias: () => setChatAlias,
|
|
3425
3559
|
setCwd: () => setCwd,
|
|
@@ -3480,6 +3614,7 @@ var init_store5 = __esm({
|
|
|
3480
3614
|
init_aliases();
|
|
3481
3615
|
init_message_log();
|
|
3482
3616
|
init_gemini_slots();
|
|
3617
|
+
init_backend_slots();
|
|
3483
3618
|
}
|
|
3484
3619
|
});
|
|
3485
3620
|
|
|
@@ -3672,6 +3807,16 @@ var init_claude = __esm({
|
|
|
3672
3807
|
env.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC = "1";
|
|
3673
3808
|
return env;
|
|
3674
3809
|
}
|
|
3810
|
+
getEnvForSlot(slot) {
|
|
3811
|
+
const env = this.getEnv();
|
|
3812
|
+
if (slot.slotType === "api_key" && slot.apiKey) {
|
|
3813
|
+
env.ANTHROPIC_API_KEY = slot.apiKey;
|
|
3814
|
+
} else if (slot.slotType === "oauth" && slot.configHome) {
|
|
3815
|
+
env.HOME = slot.configHome;
|
|
3816
|
+
delete env.ANTHROPIC_API_KEY;
|
|
3817
|
+
}
|
|
3818
|
+
return env;
|
|
3819
|
+
}
|
|
3675
3820
|
applyThinkingConfig(level, model2) {
|
|
3676
3821
|
if (level === "auto") return {};
|
|
3677
3822
|
if (level === "off") return { envOverrides: { MAX_THINKING_TOKENS: "0" } };
|
|
@@ -3961,7 +4106,7 @@ var init_gemini = __esm({
|
|
|
3961
4106
|
* OAuth slots set GEMINI_CLI_HOME for isolated config and unset GEMINI_API_KEY so
|
|
3962
4107
|
* the CLI uses OAuth instead. Returns the slot used (or null for default behavior).
|
|
3963
4108
|
*/
|
|
3964
|
-
|
|
4109
|
+
resolveSlotEnv(chatId, thinkingOverrides, mode) {
|
|
3965
4110
|
const slot = getNextGeminiSlot(chatId, mode);
|
|
3966
4111
|
const env = this.getEnv(thinkingOverrides);
|
|
3967
4112
|
if (!slot) return { env, slot: null };
|
|
@@ -4072,6 +4217,15 @@ var init_codex = __esm({
|
|
|
4072
4217
|
getEnv(thinkingOverrides) {
|
|
4073
4218
|
return buildBaseEnv(thinkingOverrides);
|
|
4074
4219
|
}
|
|
4220
|
+
getEnvForSlot(slot) {
|
|
4221
|
+
const env = this.getEnv();
|
|
4222
|
+
if (slot.slotType === "api_key" && slot.apiKey) {
|
|
4223
|
+
env.OPENAI_API_KEY = slot.apiKey;
|
|
4224
|
+
} else if (slot.slotType === "oauth" && slot.configHome) {
|
|
4225
|
+
env.CODEX_HOME = slot.configHome;
|
|
4226
|
+
}
|
|
4227
|
+
return env;
|
|
4228
|
+
}
|
|
4075
4229
|
applyThinkingConfig(level, _model) {
|
|
4076
4230
|
if (level === "auto") return {};
|
|
4077
4231
|
const mapped = level === "off" ? "low" : level === "extra_high" ? "xhigh" : level;
|
|
@@ -10572,6 +10726,53 @@ Partial output: ${accumulatedText.slice(-500)}`;
|
|
|
10572
10726
|
});
|
|
10573
10727
|
});
|
|
10574
10728
|
}
|
|
10729
|
+
async function spawnWithSlotRotation(chatId, adapter, baseConfig, configWithSession, model2, cancelState, thinkingLevel, timeoutMs, maxTurns, opts, onSlotRotation) {
|
|
10730
|
+
const slots = getEligibleBackendSlots(adapter.id);
|
|
10731
|
+
if (slots.length === 0) {
|
|
10732
|
+
return spawnQuery(adapter, configWithSession, model2, cancelState, thinkingLevel, timeoutMs, maxTurns, opts);
|
|
10733
|
+
}
|
|
10734
|
+
const maxAttempts = slots.length;
|
|
10735
|
+
let lastError;
|
|
10736
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
10737
|
+
const slot = getNextBackendSlot(chatId, adapter.id);
|
|
10738
|
+
if (!slot) break;
|
|
10739
|
+
const slotLabel = slot.label || `slot-${slot.id}`;
|
|
10740
|
+
log(`[agent:${adapter.id}-rotation] Trying ${slotLabel} (${slot.slotType}, attempt ${i + 1}/${maxAttempts})`);
|
|
10741
|
+
if (i === 0) pinChatBackendSlot(chatId, adapter.id, slot.id);
|
|
10742
|
+
const slotEnv = adapter.getEnvForSlot?.(slot) ?? adapter.getEnv();
|
|
10743
|
+
const effectiveConfig = i === 0 ? configWithSession : baseConfig;
|
|
10744
|
+
try {
|
|
10745
|
+
const result = await spawnQuery(adapter, effectiveConfig, model2, cancelState, thinkingLevel, timeoutMs, maxTurns, { ...opts, envOverride: slotEnv });
|
|
10746
|
+
markBackendSlotSuccess(slot.id);
|
|
10747
|
+
return result;
|
|
10748
|
+
} catch (err) {
|
|
10749
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
10750
|
+
if (/rate.?limit|too many requests|429|503|timeout/i.test(errMsg)) {
|
|
10751
|
+
throw err;
|
|
10752
|
+
}
|
|
10753
|
+
const isExhausted = /quota|exhausted|exceeded|insufficient|credit|billing|unauthorized|forbidden|401|403/i.test(errMsg);
|
|
10754
|
+
if (isExhausted) {
|
|
10755
|
+
warn(`[agent:${adapter.id}-rotation] Slot ${slotLabel} exhausted: ${errMsg.slice(0, 200)}`);
|
|
10756
|
+
markBackendSlotExhausted(slot.id, 6);
|
|
10757
|
+
lastError = err instanceof Error ? err : new Error(errMsg);
|
|
10758
|
+
try {
|
|
10759
|
+
await summarizeWithFallbackChain(chatId, void 0, adapter.id);
|
|
10760
|
+
clearSession(chatId);
|
|
10761
|
+
} catch {
|
|
10762
|
+
}
|
|
10763
|
+
const nextSlot = getEligibleBackendSlots(adapter.id)[0];
|
|
10764
|
+
if (nextSlot && onSlotRotation) {
|
|
10765
|
+
const nextLabel = nextSlot.label || `slot-${nextSlot.id}`;
|
|
10766
|
+
onSlotRotation(slotLabel, nextLabel);
|
|
10767
|
+
pinChatBackendSlot(chatId, adapter.id, nextSlot.id);
|
|
10768
|
+
}
|
|
10769
|
+
continue;
|
|
10770
|
+
}
|
|
10771
|
+
throw err;
|
|
10772
|
+
}
|
|
10773
|
+
}
|
|
10774
|
+
throw lastError ?? new Error(`All ${adapter.id} credential slots exhausted`);
|
|
10775
|
+
}
|
|
10575
10776
|
async function spawnGeminiWithRotation(chatId, adapter, baseConfig, configWithSession, model2, cancelState, thinkingLevel, timeoutMs, maxTurns, rotationMode, opts, onSlotRotation, parentChatId, onModelDowngrade) {
|
|
10576
10777
|
const geminiAdapter = adapter;
|
|
10577
10778
|
const slots = getEligibleGeminiSlots(rotationMode);
|
|
@@ -10579,14 +10780,14 @@ async function spawnGeminiWithRotation(chatId, adapter, baseConfig, configWithSe
|
|
|
10579
10780
|
return spawnQuery(adapter, configWithSession, model2, cancelState, thinkingLevel, timeoutMs, maxTurns, opts);
|
|
10580
10781
|
}
|
|
10581
10782
|
if (parentChatId) {
|
|
10582
|
-
const { env } = geminiAdapter.
|
|
10783
|
+
const { env } = geminiAdapter.resolveSlotEnv(parentChatId, void 0, rotationMode);
|
|
10583
10784
|
return await spawnQuery(adapter, configWithSession, model2, cancelState, thinkingLevel, timeoutMs, maxTurns, { ...opts, envOverride: env });
|
|
10584
10785
|
}
|
|
10585
10786
|
const maxAttempts = slots.length;
|
|
10586
10787
|
let lastError;
|
|
10587
10788
|
let unknownRetried = false;
|
|
10588
10789
|
for (let i = 0; i < maxAttempts; i++) {
|
|
10589
|
-
const { env, slot } = geminiAdapter.
|
|
10790
|
+
const { env, slot } = geminiAdapter.resolveSlotEnv(chatId, void 0, rotationMode);
|
|
10590
10791
|
if (!slot) break;
|
|
10591
10792
|
const slotLabel = slot.label || `slot-${slot.id}`;
|
|
10592
10793
|
log(`[agent:gemini-rotation] Trying ${slotLabel} (${slot.slotType}, attempt ${i + 1}/${maxAttempts})`);
|
|
@@ -10739,16 +10940,20 @@ async function askAgentImpl(chatId, userMessage, opts) {
|
|
|
10739
10940
|
let result = { resultText: "", sessionId: void 0, input: 0, output: 0, cacheRead: 0, sawToolEvents: false, sawResultEvent: false };
|
|
10740
10941
|
const rotationMode = adapter.id === "gemini" ? getGeminiRotationMode() : "off";
|
|
10741
10942
|
const useGeminiRotation = rotationMode !== "off" && getEligibleGeminiSlots(rotationMode).length > 0;
|
|
10943
|
+
const useBackendRotation = adapter.id !== "gemini" && getEligibleBackendSlots(adapter.id).length > 0;
|
|
10742
10944
|
try {
|
|
10743
10945
|
if (useGeminiRotation) {
|
|
10744
10946
|
const rotationCb = onSlotRotation ? (from, to) => onSlotRotation(chatId, from, to) : void 0;
|
|
10745
10947
|
const downgradeCb = onModelDowngrade ? (from, to, reason) => onModelDowngrade(chatId, from, to, reason) : void 0;
|
|
10746
10948
|
result = await spawnGeminiWithRotation(chatId, adapter, baseConfig, configWithSession, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, rotationMode, spawnOpts, rotationCb, settingsSourceChatId, downgradeCb);
|
|
10949
|
+
} else if (useBackendRotation) {
|
|
10950
|
+
const rotationCb = onSlotRotation ? (from, to) => onSlotRotation(chatId, from, to) : void 0;
|
|
10951
|
+
result = await spawnWithSlotRotation(chatId, adapter, baseConfig, configWithSession, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, spawnOpts, rotationCb);
|
|
10747
10952
|
} else {
|
|
10748
10953
|
const slotSpawnOpts = (() => {
|
|
10749
10954
|
if (adapter.id !== "gemini") return spawnOpts;
|
|
10750
10955
|
const geminiAdapter = adapter;
|
|
10751
|
-
const { env, slot } = geminiAdapter.
|
|
10956
|
+
const { env, slot } = geminiAdapter.resolveSlotEnv(chatId);
|
|
10752
10957
|
if (slot) {
|
|
10753
10958
|
log(`[agent] rotation=off, using pinned slot: ${slot.label || `slot-${slot.id}`} (${slot.slotType})`);
|
|
10754
10959
|
return { ...spawnOpts, envOverride: env };
|
|
@@ -10795,11 +11000,14 @@ async function askAgentImpl(chatId, userMessage, opts) {
|
|
|
10795
11000
|
const rotationCb = onSlotRotation ? (from, to) => onSlotRotation(chatId, from, to) : void 0;
|
|
10796
11001
|
const downgradeCb = onModelDowngrade ? (from, to, reason) => onModelDowngrade(chatId, from, to, reason) : void 0;
|
|
10797
11002
|
result = await spawnGeminiWithRotation(chatId, adapter, baseConfig, baseConfig, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, rotationMode, spawnOpts, rotationCb, settingsSourceChatId, downgradeCb);
|
|
11003
|
+
} else if (useBackendRotation) {
|
|
11004
|
+
const rotationCb = onSlotRotation ? (from, to) => onSlotRotation(chatId, from, to) : void 0;
|
|
11005
|
+
result = await spawnWithSlotRotation(chatId, adapter, baseConfig, baseConfig, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, spawnOpts, rotationCb);
|
|
10798
11006
|
} else {
|
|
10799
11007
|
const retryOpts = (() => {
|
|
10800
11008
|
if (adapter.id !== "gemini") return spawnOpts;
|
|
10801
11009
|
const geminiAdapter = adapter;
|
|
10802
|
-
const { env, slot } = geminiAdapter.
|
|
11010
|
+
const { env, slot } = geminiAdapter.resolveSlotEnv(chatId);
|
|
10803
11011
|
if (slot) return { ...spawnOpts, envOverride: env };
|
|
10804
11012
|
return spawnOpts;
|
|
10805
11013
|
})();
|
|
@@ -10815,11 +11023,14 @@ async function askAgentImpl(chatId, userMessage, opts) {
|
|
|
10815
11023
|
const rotationCb = onSlotRotation ? (from, to) => onSlotRotation(chatId, from, to) : void 0;
|
|
10816
11024
|
const downgradeCb = onModelDowngrade ? (from, to, reason) => onModelDowngrade(chatId, from, to, reason) : void 0;
|
|
10817
11025
|
result = await spawnGeminiWithRotation(chatId, adapter, baseConfig, baseConfig, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, rotationMode, spawnOpts, rotationCb, settingsSourceChatId, downgradeCb);
|
|
11026
|
+
} else if (useBackendRotation) {
|
|
11027
|
+
const rotationCb = onSlotRotation ? (from, to) => onSlotRotation(chatId, from, to) : void 0;
|
|
11028
|
+
result = await spawnWithSlotRotation(chatId, adapter, baseConfig, baseConfig, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, spawnOpts, rotationCb);
|
|
10818
11029
|
} else {
|
|
10819
11030
|
const retryOpts = (() => {
|
|
10820
11031
|
if (adapter.id !== "gemini") return spawnOpts;
|
|
10821
11032
|
const geminiAdapter = adapter;
|
|
10822
|
-
const { env, slot } = geminiAdapter.
|
|
11033
|
+
const { env, slot } = geminiAdapter.resolveSlotEnv(chatId);
|
|
10823
11034
|
if (slot) return { ...spawnOpts, envOverride: env };
|
|
10824
11035
|
return spawnOpts;
|
|
10825
11036
|
})();
|
|
@@ -10944,6 +11155,7 @@ var init_agent = __esm({
|
|
|
10944
11155
|
init_summarize();
|
|
10945
11156
|
init_quota();
|
|
10946
11157
|
init_store5();
|
|
11158
|
+
init_store5();
|
|
10947
11159
|
init_server();
|
|
10948
11160
|
init_mcp_config();
|
|
10949
11161
|
init_store5();
|
|
@@ -12812,7 +13024,10 @@ var init_helpers = __esm({
|
|
|
12812
13024
|
{ cmd: "/thinking", desc: "Adjust thinking level" },
|
|
12813
13025
|
{ cmd: "/permissions", desc: "Set permission mode" },
|
|
12814
13026
|
{ cmd: "/response_style", desc: "Set response verbosity" },
|
|
12815
|
-
{ cmd: "/model_signature", desc: "Toggle model signature" }
|
|
13027
|
+
{ cmd: "/model_signature", desc: "Toggle model signature" },
|
|
13028
|
+
{ cmd: "/gemini_accounts", desc: "Gemini credential slots" },
|
|
13029
|
+
{ cmd: "/claude_accounts", desc: "Claude credential slots" },
|
|
13030
|
+
{ cmd: "/codex_accounts", desc: "Codex credential slots" }
|
|
12816
13031
|
],
|
|
12817
13032
|
Memory: [
|
|
12818
13033
|
{ cmd: "/memory", desc: "Browse stored memories" },
|
|
@@ -15345,7 +15560,9 @@ async function doBackendSwitch(chatId, backendId, channel) {
|
|
|
15345
15560
|
clearSession(chatId);
|
|
15346
15561
|
clearModel(chatId);
|
|
15347
15562
|
clearThinkingLevel(chatId);
|
|
15348
|
-
|
|
15563
|
+
if (backendId !== "gemini") {
|
|
15564
|
+
clearChatGeminiSlot(chatId);
|
|
15565
|
+
}
|
|
15349
15566
|
setBackend(chatId, backendId);
|
|
15350
15567
|
logActivity(getDb(), { chatId, source: "telegram", eventType: "config_changed", summary: `Backend switched to ${targetAdapter.displayName}`, detail: { field: "backend", value: backendId } });
|
|
15351
15568
|
if (typeof channel.sendKeyboard === "function") {
|
|
@@ -15685,13 +15902,13 @@ async function handleEvolveCallback(chatId, data, channel) {
|
|
|
15685
15902
|
const { getReflectionStatus: getReflectionStatus2, setReflectionStatus: setReflectionStatus2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
15686
15903
|
const current = getReflectionStatus2(getDb(), chatId);
|
|
15687
15904
|
if (current === "frozen") {
|
|
15688
|
-
const { readFileSync: readFileSync21, existsSync:
|
|
15905
|
+
const { readFileSync: readFileSync21, existsSync: existsSync49 } = await import("fs");
|
|
15689
15906
|
const { join: join28 } = await import("path");
|
|
15690
15907
|
const { CC_CLAW_HOME: CC_CLAW_HOME3 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
15691
15908
|
const soulPath = join28(CC_CLAW_HOME3, "identity/SOUL.md");
|
|
15692
15909
|
const userPath = join28(CC_CLAW_HOME3, "identity/USER.md");
|
|
15693
|
-
const soul =
|
|
15694
|
-
const user =
|
|
15910
|
+
const soul = existsSync49(soulPath) ? readFileSync21(soulPath, "utf-8") : "";
|
|
15911
|
+
const user = existsSync49(userPath) ? readFileSync21(userPath, "utf-8") : "";
|
|
15695
15912
|
setReflectionStatus2(getDb(), chatId, "active", soul, user);
|
|
15696
15913
|
const { logActivity: logActivity2 } = await Promise.resolve().then(() => (init_store3(), store_exports3));
|
|
15697
15914
|
logActivity2(getDb(), { chatId, source: "telegram", eventType: "reflection_unfrozen", summary: "Reflection enabled" });
|
|
@@ -15895,7 +16112,6 @@ Tap to toggle:`,
|
|
|
15895
16112
|
const exchangeCount = getMessagePairCount(chatId);
|
|
15896
16113
|
const summarized = await summarizeSession(chatId);
|
|
15897
16114
|
clearSession(chatId);
|
|
15898
|
-
clearChatGeminiSlot(chatId);
|
|
15899
16115
|
setSessionStartedAt(chatId);
|
|
15900
16116
|
logActivity(getDb(), { chatId, source: "telegram", eventType: "config_changed", summary: "New session started", detail: { field: "session", action: "reset", summarized } });
|
|
15901
16117
|
if (typeof channel.sendKeyboard === "function" && oldSessionId) {
|
|
@@ -16035,14 +16251,28 @@ Tap to toggle:`,
|
|
|
16035
16251
|
}
|
|
16036
16252
|
const iStats = getIntentStats();
|
|
16037
16253
|
const iTotal = iStats.chat + iStats.agentic;
|
|
16038
|
-
let
|
|
16254
|
+
let slotInfo = "";
|
|
16039
16255
|
if ((backendId ?? "claude") === "gemini") {
|
|
16040
16256
|
try {
|
|
16041
16257
|
const active = getNextGeminiSlot(chatId);
|
|
16042
16258
|
const totalSlots = getEligibleGeminiSlots().length;
|
|
16043
16259
|
if (active) {
|
|
16044
16260
|
const label2 = active.label || `slot-${active.id}`;
|
|
16045
|
-
|
|
16261
|
+
slotInfo = ` \xB7 \u{1F511} ${label2} (${totalSlots} slots)`;
|
|
16262
|
+
}
|
|
16263
|
+
} catch {
|
|
16264
|
+
}
|
|
16265
|
+
} else if (backendId === "claude" || backendId === "codex") {
|
|
16266
|
+
try {
|
|
16267
|
+
const slots = getBackendSlots(backendId);
|
|
16268
|
+
const enabledSlots = slots.filter((s) => s.enabled);
|
|
16269
|
+
if (enabledSlots.length > 0) {
|
|
16270
|
+
const pinnedId = getChatBackendSlotId(chatId, backendId);
|
|
16271
|
+
const active = pinnedId ? slots.find((s) => s.id === pinnedId) : enabledSlots[0];
|
|
16272
|
+
if (active) {
|
|
16273
|
+
const label2 = active.label || `slot-${active.id}`;
|
|
16274
|
+
slotInfo = ` \xB7 \u{1F511} ${label2} (${enabledSlots.length} slots)`;
|
|
16275
|
+
}
|
|
16046
16276
|
}
|
|
16047
16277
|
} catch {
|
|
16048
16278
|
}
|
|
@@ -16056,7 +16286,7 @@ Tap to toggle:`,
|
|
|
16056
16286
|
`\u23F1 Uptime: ${uptimeStr}`,
|
|
16057
16287
|
``,
|
|
16058
16288
|
buildSectionHeader("Engine"),
|
|
16059
|
-
`\u{1F9E0} ${adapter?.displayName ?? backendId ?? "not set"} \xB7 ${formatModelShort(model2)}${
|
|
16289
|
+
`\u{1F9E0} ${adapter?.displayName ?? backendId ?? "not set"} \xB7 ${formatModelShort(model2)}${slotInfo}`,
|
|
16060
16290
|
`\u{1F4AD} Think: ${thinking2} \xB7 Mode: ${mode}`,
|
|
16061
16291
|
`\u{1F916} Agents: ${getAgentMode(chatId)}`,
|
|
16062
16292
|
`\u{1F507} Voice: ${voice2 ? "on" : "off"} \xB7 Sig: ${modelSig}`,
|
|
@@ -16175,6 +16405,42 @@ Use: /gemini_accounts <name> to pin`, { parseMode: "plain" });
|
|
|
16175
16405
|
}
|
|
16176
16406
|
break;
|
|
16177
16407
|
}
|
|
16408
|
+
case "claude_accounts":
|
|
16409
|
+
case "codex_accounts": {
|
|
16410
|
+
const slotBackend = command === "claude_accounts" ? "claude" : "codex";
|
|
16411
|
+
const slotDisplayName = command === "claude_accounts" ? "Claude" : "Codex";
|
|
16412
|
+
const slots = getBackendSlots(slotBackend);
|
|
16413
|
+
if (slots.length === 0) {
|
|
16414
|
+
await channel.sendText(chatId, `No ${slotDisplayName} credentials configured.
|
|
16415
|
+
Add with: <code>cc-claw ${slotBackend} add-key</code>`, { parseMode: "html" });
|
|
16416
|
+
break;
|
|
16417
|
+
}
|
|
16418
|
+
if (typeof channel.sendKeyboard === "function") {
|
|
16419
|
+
const pinnedSlotId = getChatBackendSlotId(chatId, slotBackend);
|
|
16420
|
+
const slotButtons = slots.filter((s) => s.enabled).map((s) => {
|
|
16421
|
+
const label2 = s.label || `slot-${s.id}`;
|
|
16422
|
+
const icon = s.slotType === "oauth" ? "\u{1F468}\u{1F3FD}\u200D\u{1F4BB}" : "\u{1F511}";
|
|
16423
|
+
const marker = pinnedSlotId === s.id ? " \u2713" : "";
|
|
16424
|
+
return { label: `${icon} ${label2}${marker}`, data: `bslot:${slotBackend}:${s.id}` };
|
|
16425
|
+
});
|
|
16426
|
+
const rows = [];
|
|
16427
|
+
for (let i = 0; i < slotButtons.length; i += 2) {
|
|
16428
|
+
rows.push(slotButtons.slice(i, i + 2));
|
|
16429
|
+
}
|
|
16430
|
+
rows.push([{ label: "\u{1F504} Auto (rotation)", data: `bslot:${slotBackend}:auto` }]);
|
|
16431
|
+
await channel.sendKeyboard(chatId, `${slotDisplayName} Accounts:`, rows);
|
|
16432
|
+
} else {
|
|
16433
|
+
const list = slots.filter((s) => s.enabled).map((s) => {
|
|
16434
|
+
const icon = s.slotType === "oauth" ? "\u{1F468}\u{1F3FD}\u200D\u{1F4BB}" : "\u{1F511}";
|
|
16435
|
+
return `${icon} ${s.label || `slot-${s.id}`} (#${s.id})`;
|
|
16436
|
+
}).join("\n");
|
|
16437
|
+
await channel.sendText(chatId, `${slotDisplayName} Slots:
|
|
16438
|
+
${list}
|
|
16439
|
+
|
|
16440
|
+
Use: /${command} <name> to pin`, { parseMode: "plain" });
|
|
16441
|
+
}
|
|
16442
|
+
break;
|
|
16443
|
+
}
|
|
16178
16444
|
case "model": {
|
|
16179
16445
|
let adapter;
|
|
16180
16446
|
try {
|
|
@@ -17790,6 +18056,28 @@ ${rotationNote}`, { parseMode: "html" });
|
|
|
17790
18056
|
await channel.sendKeyboard(chatId, "Gemini Accounts & Rotation:", rows);
|
|
17791
18057
|
}
|
|
17792
18058
|
return;
|
|
18059
|
+
} else if (data.startsWith("bslot:")) {
|
|
18060
|
+
const parts = data.split(":");
|
|
18061
|
+
const backend2 = parts[1];
|
|
18062
|
+
const val = parts[2];
|
|
18063
|
+
const displayName = backend2 === "claude" ? "Claude" : "Codex";
|
|
18064
|
+
if (val === "auto") {
|
|
18065
|
+
clearChatBackendSlot(chatId, backend2);
|
|
18066
|
+
clearSession(chatId);
|
|
18067
|
+
await channel.sendText(chatId, `${displayName} slot set to <b>\u{1F504} auto rotation</b>.`, { parseMode: "html" });
|
|
18068
|
+
} else {
|
|
18069
|
+
const slotId = parseInt(val, 10);
|
|
18070
|
+
const slots = getBackendSlots(backend2);
|
|
18071
|
+
const slot = slots.find((s) => s.id === slotId);
|
|
18072
|
+
if (slot) {
|
|
18073
|
+
pinChatBackendSlot(chatId, backend2, slotId);
|
|
18074
|
+
clearSession(chatId);
|
|
18075
|
+
const label2 = slot.label || `slot-${slot.id}`;
|
|
18076
|
+
const icon = slot.slotType === "oauth" ? "\u{1F468}\u{1F3FD}\u200D\u{1F4BB}" : "\u{1F511}";
|
|
18077
|
+
await channel.sendText(chatId, `${icon} ${displayName} account set to <b>${label2}</b>`, { parseMode: "html" });
|
|
18078
|
+
}
|
|
18079
|
+
}
|
|
18080
|
+
return;
|
|
17793
18081
|
} else if (data.startsWith("shell:")) {
|
|
17794
18082
|
const parts = data.split(":");
|
|
17795
18083
|
const action = parts[1];
|
|
@@ -18548,6 +18836,12 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
18548
18836
|
const slot = getGeminiSlots().find((s) => s.id === slotId);
|
|
18549
18837
|
if (slot) slotTag = ` \xB7 ${slot.label || `slot-${slot.id}`}`;
|
|
18550
18838
|
}
|
|
18839
|
+
} else if (adapter.id === "claude" || adapter.id === "codex") {
|
|
18840
|
+
const slotId = getChatBackendSlotId(chatId, adapter.id);
|
|
18841
|
+
if (slotId) {
|
|
18842
|
+
const slot = getBackendSlots(adapter.id).find((s) => s.id === slotId);
|
|
18843
|
+
if (slot) slotTag = ` \xB7 ${slot.label || `slot-${slot.id}`}`;
|
|
18844
|
+
}
|
|
18551
18845
|
}
|
|
18552
18846
|
responseText += `
|
|
18553
18847
|
|
|
@@ -22414,6 +22708,214 @@ var init_gemini2 = __esm({
|
|
|
22414
22708
|
}
|
|
22415
22709
|
});
|
|
22416
22710
|
|
|
22711
|
+
// src/cli/commands/backend-cmd-factory.ts
|
|
22712
|
+
var backend_cmd_factory_exports = {};
|
|
22713
|
+
__export(backend_cmd_factory_exports, {
|
|
22714
|
+
makeAddKey: () => makeAddKey,
|
|
22715
|
+
makeDisable: () => makeDisable,
|
|
22716
|
+
makeEnable: () => makeEnable,
|
|
22717
|
+
makeList: () => makeList,
|
|
22718
|
+
makeRefresh: () => makeRefresh,
|
|
22719
|
+
makeRemove: () => makeRemove,
|
|
22720
|
+
makeReorder: () => makeReorder,
|
|
22721
|
+
registerBackendSlotCommands: () => registerBackendSlotCommands
|
|
22722
|
+
});
|
|
22723
|
+
import { existsSync as existsSync28 } from "fs";
|
|
22724
|
+
import { createInterface as createInterface6 } from "readline";
|
|
22725
|
+
function requireDb2() {
|
|
22726
|
+
if (!existsSync28(DB_PATH)) {
|
|
22727
|
+
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
22728
|
+
process.exit(1);
|
|
22729
|
+
}
|
|
22730
|
+
}
|
|
22731
|
+
async function requireWriteDb2() {
|
|
22732
|
+
requireDb2();
|
|
22733
|
+
if (!dbInitialized2) {
|
|
22734
|
+
const { initDatabase: initDatabase2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
22735
|
+
initDatabase2();
|
|
22736
|
+
dbInitialized2 = true;
|
|
22737
|
+
}
|
|
22738
|
+
}
|
|
22739
|
+
async function resolveSlotId2(backend2, idOrLabel) {
|
|
22740
|
+
const numeric = parseInt(idOrLabel, 10);
|
|
22741
|
+
if (!isNaN(numeric)) return numeric;
|
|
22742
|
+
const { getBackendSlots: getBackendSlots2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
22743
|
+
const match = getBackendSlots2(backend2).find(
|
|
22744
|
+
(s) => s.label?.toLowerCase() === idOrLabel.toLowerCase()
|
|
22745
|
+
);
|
|
22746
|
+
return match?.id ?? null;
|
|
22747
|
+
}
|
|
22748
|
+
function makeList(backend2, displayName) {
|
|
22749
|
+
return async function list(_globalOpts) {
|
|
22750
|
+
requireDb2();
|
|
22751
|
+
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
22752
|
+
const readDb = openDatabaseReadOnly2();
|
|
22753
|
+
const slots = readDb.prepare(`
|
|
22754
|
+
SELECT id, slot_type, label, config_home, priority, enabled, cooldown_until, last_used, consecutive_errors, created_at
|
|
22755
|
+
FROM backend_credentials WHERE backend = ? ORDER BY priority ASC, id ASC
|
|
22756
|
+
`).all(backend2);
|
|
22757
|
+
readDb.close();
|
|
22758
|
+
if (slots.length === 0) {
|
|
22759
|
+
output({ slots: [] }, () => `No ${displayName} credential slots configured.
|
|
22760
|
+
Add one with: cc-claw ${backend2} add-key`);
|
|
22761
|
+
return;
|
|
22762
|
+
}
|
|
22763
|
+
output(slots, (data) => {
|
|
22764
|
+
const list2 = data;
|
|
22765
|
+
const lines = ["", divider(`${displayName} Credential Slots`), ""];
|
|
22766
|
+
for (const s of list2) {
|
|
22767
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
22768
|
+
const inCooldown = s.cooldown_until && s.cooldown_until > now;
|
|
22769
|
+
const icon = !s.enabled ? error2("\u25CB disabled") : inCooldown ? warning("\u25D1 cooldown") : success("\u25CF active");
|
|
22770
|
+
const label2 = s.label || `slot-${s.id}`;
|
|
22771
|
+
const type = s.slot_type === "oauth" ? "\u{1F468}\u{1F3FD}\u200D\u{1F4BB}" : "\u{1F511}";
|
|
22772
|
+
lines.push(` ${icon} ${label2} ${muted(`(${type}, #${s.id}, priority ${s.priority})`)}`);
|
|
22773
|
+
if (inCooldown) lines.push(` Cooldown until: ${warning(s.cooldown_until)}`);
|
|
22774
|
+
if (s.consecutive_errors > 0) lines.push(` Consecutive errors: ${warning(String(s.consecutive_errors))}`);
|
|
22775
|
+
if (s.last_used) lines.push(` Last used: ${muted(s.last_used)}`);
|
|
22776
|
+
}
|
|
22777
|
+
lines.push("");
|
|
22778
|
+
return lines.join("\n");
|
|
22779
|
+
});
|
|
22780
|
+
};
|
|
22781
|
+
}
|
|
22782
|
+
function makeAddKey(backend2, displayName) {
|
|
22783
|
+
return async function addKey(_globalOpts, opts) {
|
|
22784
|
+
await requireWriteDb2();
|
|
22785
|
+
const rl2 = createInterface6({ input: process.stdin, output: process.stdout });
|
|
22786
|
+
const ask2 = (q) => new Promise((r) => rl2.question(q, r));
|
|
22787
|
+
const key = await ask2(`Paste your ${displayName} API key: `);
|
|
22788
|
+
rl2.close();
|
|
22789
|
+
if (!key.trim()) {
|
|
22790
|
+
outputError("EMPTY_KEY", "No key provided.");
|
|
22791
|
+
process.exit(1);
|
|
22792
|
+
}
|
|
22793
|
+
const { addBackendSlot: addBackendSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
22794
|
+
const id = addBackendSlot2({
|
|
22795
|
+
backend: backend2,
|
|
22796
|
+
slotType: "api_key",
|
|
22797
|
+
label: opts.label,
|
|
22798
|
+
apiKey: key.trim(),
|
|
22799
|
+
priority: opts.priority ? parseInt(opts.priority, 10) : 0
|
|
22800
|
+
});
|
|
22801
|
+
output(
|
|
22802
|
+
{ id, type: "api_key", backend: backend2, label: opts.label ?? null },
|
|
22803
|
+
() => success(`Added ${displayName} API key slot #${id}${opts.label ? ` (${opts.label})` : ""}`)
|
|
22804
|
+
);
|
|
22805
|
+
};
|
|
22806
|
+
}
|
|
22807
|
+
function makeRemove(backend2, displayName) {
|
|
22808
|
+
return async function remove(_globalOpts, idOrLabel) {
|
|
22809
|
+
await requireWriteDb2();
|
|
22810
|
+
const slotId = await resolveSlotId2(backend2, idOrLabel);
|
|
22811
|
+
if (!slotId) {
|
|
22812
|
+
outputError("NOT_FOUND", `Slot "${idOrLabel}" not found.`);
|
|
22813
|
+
return;
|
|
22814
|
+
}
|
|
22815
|
+
const { removeBackendSlot: removeBackendSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
22816
|
+
const removed = removeBackendSlot2(slotId);
|
|
22817
|
+
if (removed) {
|
|
22818
|
+
output({ removed: true, id: slotId }, () => success(`Removed slot "${idOrLabel}" (#${slotId})`));
|
|
22819
|
+
} else {
|
|
22820
|
+
outputError("NOT_FOUND", `Slot "${idOrLabel}" not found.`);
|
|
22821
|
+
}
|
|
22822
|
+
};
|
|
22823
|
+
}
|
|
22824
|
+
function makeEnable(backend2, _displayName) {
|
|
22825
|
+
return async function enable(_globalOpts, idOrLabel) {
|
|
22826
|
+
await requireWriteDb2();
|
|
22827
|
+
const slotId = await resolveSlotId2(backend2, idOrLabel);
|
|
22828
|
+
if (!slotId) {
|
|
22829
|
+
outputError("NOT_FOUND", `Slot "${idOrLabel}" not found.`);
|
|
22830
|
+
return;
|
|
22831
|
+
}
|
|
22832
|
+
const { setBackendSlotEnabled: setBackendSlotEnabled2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
22833
|
+
setBackendSlotEnabled2(slotId, true);
|
|
22834
|
+
output({ id: slotId, enabled: true }, () => success(`Enabled slot "${idOrLabel}" (#${slotId})`));
|
|
22835
|
+
};
|
|
22836
|
+
}
|
|
22837
|
+
function makeDisable(backend2, _displayName) {
|
|
22838
|
+
return async function disable(_globalOpts, idOrLabel) {
|
|
22839
|
+
await requireWriteDb2();
|
|
22840
|
+
const slotId = await resolveSlotId2(backend2, idOrLabel);
|
|
22841
|
+
if (!slotId) {
|
|
22842
|
+
outputError("NOT_FOUND", `Slot "${idOrLabel}" not found.`);
|
|
22843
|
+
return;
|
|
22844
|
+
}
|
|
22845
|
+
const { setBackendSlotEnabled: setBackendSlotEnabled2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
22846
|
+
setBackendSlotEnabled2(slotId, false);
|
|
22847
|
+
output({ id: slotId, enabled: false }, () => warning(`Disabled slot "${idOrLabel}" (#${slotId})`));
|
|
22848
|
+
};
|
|
22849
|
+
}
|
|
22850
|
+
function makeReorder(backend2, _displayName) {
|
|
22851
|
+
return async function reorder(_globalOpts, idOrLabel, priority) {
|
|
22852
|
+
await requireWriteDb2();
|
|
22853
|
+
const slotId = await resolveSlotId2(backend2, idOrLabel);
|
|
22854
|
+
if (!slotId) {
|
|
22855
|
+
outputError("NOT_FOUND", `Slot "${idOrLabel}" not found.`);
|
|
22856
|
+
return;
|
|
22857
|
+
}
|
|
22858
|
+
const { reorderBackendSlot: reorderBackendSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
22859
|
+
reorderBackendSlot2(slotId, parseInt(priority, 10));
|
|
22860
|
+
output(
|
|
22861
|
+
{ id: slotId, priority: parseInt(priority, 10) },
|
|
22862
|
+
() => success(`Slot "${idOrLabel}" (#${slotId}) priority set to ${priority}`)
|
|
22863
|
+
);
|
|
22864
|
+
};
|
|
22865
|
+
}
|
|
22866
|
+
function makeRefresh(backend2, displayName) {
|
|
22867
|
+
return async function refresh(_globalOpts) {
|
|
22868
|
+
await requireWriteDb2();
|
|
22869
|
+
const { getBackendSlots: getBackendSlots2, reenableBackendSlot: reenableBackendSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
22870
|
+
const slots = getBackendSlots2(backend2);
|
|
22871
|
+
let count = 0;
|
|
22872
|
+
for (const s of slots) {
|
|
22873
|
+
if (!s.enabled || s.cooldownUntil || s.consecutiveErrors > 0) {
|
|
22874
|
+
reenableBackendSlot2(s.id);
|
|
22875
|
+
count++;
|
|
22876
|
+
}
|
|
22877
|
+
}
|
|
22878
|
+
output(
|
|
22879
|
+
{ refreshed: count },
|
|
22880
|
+
() => count > 0 ? success(`Refreshed ${count} ${displayName} slot(s) \u2014 cooldowns cleared, errors reset`) : `All ${displayName} slots are already healthy.`
|
|
22881
|
+
);
|
|
22882
|
+
};
|
|
22883
|
+
}
|
|
22884
|
+
function registerBackendSlotCommands(parentCommand, backend2, displayName, globalOpts) {
|
|
22885
|
+
const cmd = parentCommand.command(backend2).description(`Manage ${displayName} credential slots`);
|
|
22886
|
+
cmd.command("list").description(`Show all configured ${displayName} credential slots`).action(async () => {
|
|
22887
|
+
await makeList(backend2, displayName)(globalOpts());
|
|
22888
|
+
});
|
|
22889
|
+
cmd.command("add-key").description("Add an API key slot (prompts for key in terminal)").option("--label <name>", "Friendly label for this slot").option("--priority <n>", "Priority (lower = preferred)", "0").action(async (opts) => {
|
|
22890
|
+
await makeAddKey(backend2, displayName)(globalOpts(), opts);
|
|
22891
|
+
});
|
|
22892
|
+
cmd.command("remove <id-or-label>").description("Remove a credential slot (by ID or label)").action(async (id) => {
|
|
22893
|
+
await makeRemove(backend2, displayName)(globalOpts(), id);
|
|
22894
|
+
});
|
|
22895
|
+
cmd.command("enable <id-or-label>").description("Re-enable a disabled slot").action(async (id) => {
|
|
22896
|
+
await makeEnable(backend2, displayName)(globalOpts(), id);
|
|
22897
|
+
});
|
|
22898
|
+
cmd.command("disable <id-or-label>").description("Disable a slot").action(async (id) => {
|
|
22899
|
+
await makeDisable(backend2, displayName)(globalOpts(), id);
|
|
22900
|
+
});
|
|
22901
|
+
cmd.command("reorder <id-or-label> <priority>").description("Set slot priority (lower = preferred)").action(async (id, priority) => {
|
|
22902
|
+
await makeReorder(backend2, displayName)(globalOpts(), id, priority);
|
|
22903
|
+
});
|
|
22904
|
+
cmd.command("refresh").description("Re-enable all slots, clear cooldowns and errors").action(async () => {
|
|
22905
|
+
await makeRefresh(backend2, displayName)(globalOpts());
|
|
22906
|
+
});
|
|
22907
|
+
return cmd;
|
|
22908
|
+
}
|
|
22909
|
+
var dbInitialized2;
|
|
22910
|
+
var init_backend_cmd_factory = __esm({
|
|
22911
|
+
"src/cli/commands/backend-cmd-factory.ts"() {
|
|
22912
|
+
"use strict";
|
|
22913
|
+
init_format2();
|
|
22914
|
+
init_paths();
|
|
22915
|
+
dbInitialized2 = false;
|
|
22916
|
+
}
|
|
22917
|
+
});
|
|
22918
|
+
|
|
22417
22919
|
// src/cli/commands/backend.ts
|
|
22418
22920
|
var backend_exports = {};
|
|
22419
22921
|
__export(backend_exports, {
|
|
@@ -22421,12 +22923,12 @@ __export(backend_exports, {
|
|
|
22421
22923
|
backendList: () => backendList,
|
|
22422
22924
|
backendSet: () => backendSet
|
|
22423
22925
|
});
|
|
22424
|
-
import { existsSync as
|
|
22926
|
+
import { existsSync as existsSync29 } from "fs";
|
|
22425
22927
|
async function backendList(globalOpts) {
|
|
22426
22928
|
const { getAvailableAdapters: getAvailableAdapters3 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
22427
22929
|
const chatId = resolveChatId(globalOpts);
|
|
22428
22930
|
let activeBackend = null;
|
|
22429
|
-
if (
|
|
22931
|
+
if (existsSync29(DB_PATH)) {
|
|
22430
22932
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
22431
22933
|
const readDb = openDatabaseReadOnly2();
|
|
22432
22934
|
try {
|
|
@@ -22457,7 +22959,7 @@ async function backendList(globalOpts) {
|
|
|
22457
22959
|
}
|
|
22458
22960
|
async function backendGet(globalOpts) {
|
|
22459
22961
|
const chatId = resolveChatId(globalOpts);
|
|
22460
|
-
if (!
|
|
22962
|
+
if (!existsSync29(DB_PATH)) {
|
|
22461
22963
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
22462
22964
|
process.exit(1);
|
|
22463
22965
|
}
|
|
@@ -22501,13 +23003,13 @@ __export(model_exports, {
|
|
|
22501
23003
|
modelList: () => modelList,
|
|
22502
23004
|
modelSet: () => modelSet
|
|
22503
23005
|
});
|
|
22504
|
-
import { existsSync as
|
|
23006
|
+
import { existsSync as existsSync30 } from "fs";
|
|
22505
23007
|
async function modelList(globalOpts) {
|
|
22506
23008
|
const chatId = resolveChatId(globalOpts);
|
|
22507
23009
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
22508
23010
|
const { getAdapter: getAdapter4, getAllAdapters: getAllAdapters5 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
22509
23011
|
let backendId = "claude";
|
|
22510
|
-
if (
|
|
23012
|
+
if (existsSync30(DB_PATH)) {
|
|
22511
23013
|
const readDb = openDatabaseReadOnly2();
|
|
22512
23014
|
try {
|
|
22513
23015
|
const row = readDb.prepare("SELECT backend FROM chat_backend WHERE chat_id = ?").get(chatId);
|
|
@@ -22540,7 +23042,7 @@ async function modelList(globalOpts) {
|
|
|
22540
23042
|
}
|
|
22541
23043
|
async function modelGet(globalOpts) {
|
|
22542
23044
|
const chatId = resolveChatId(globalOpts);
|
|
22543
|
-
if (!
|
|
23045
|
+
if (!existsSync30(DB_PATH)) {
|
|
22544
23046
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
22545
23047
|
process.exit(1);
|
|
22546
23048
|
}
|
|
@@ -22584,9 +23086,9 @@ __export(memory_exports2, {
|
|
|
22584
23086
|
memoryList: () => memoryList,
|
|
22585
23087
|
memorySearch: () => memorySearch
|
|
22586
23088
|
});
|
|
22587
|
-
import { existsSync as
|
|
23089
|
+
import { existsSync as existsSync31 } from "fs";
|
|
22588
23090
|
async function memoryList(globalOpts) {
|
|
22589
|
-
if (!
|
|
23091
|
+
if (!existsSync31(DB_PATH)) {
|
|
22590
23092
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
22591
23093
|
process.exit(1);
|
|
22592
23094
|
}
|
|
@@ -22610,7 +23112,7 @@ async function memoryList(globalOpts) {
|
|
|
22610
23112
|
});
|
|
22611
23113
|
}
|
|
22612
23114
|
async function memorySearch(globalOpts, query) {
|
|
22613
|
-
if (!
|
|
23115
|
+
if (!existsSync31(DB_PATH)) {
|
|
22614
23116
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
22615
23117
|
process.exit(1);
|
|
22616
23118
|
}
|
|
@@ -22632,7 +23134,7 @@ async function memorySearch(globalOpts, query) {
|
|
|
22632
23134
|
});
|
|
22633
23135
|
}
|
|
22634
23136
|
async function memoryHistory(globalOpts, opts) {
|
|
22635
|
-
if (!
|
|
23137
|
+
if (!existsSync31(DB_PATH)) {
|
|
22636
23138
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
22637
23139
|
process.exit(1);
|
|
22638
23140
|
}
|
|
@@ -22680,7 +23182,7 @@ __export(cron_exports2, {
|
|
|
22680
23182
|
cronList: () => cronList,
|
|
22681
23183
|
cronRuns: () => cronRuns
|
|
22682
23184
|
});
|
|
22683
|
-
import { existsSync as
|
|
23185
|
+
import { existsSync as existsSync32 } from "fs";
|
|
22684
23186
|
function parseFallbacks(raw) {
|
|
22685
23187
|
return raw.slice(0, 3).map((f) => {
|
|
22686
23188
|
const [backend2, ...rest] = f.split(":");
|
|
@@ -22701,7 +23203,7 @@ function parseAndValidateTimeout(raw) {
|
|
|
22701
23203
|
return val;
|
|
22702
23204
|
}
|
|
22703
23205
|
async function cronList(globalOpts) {
|
|
22704
|
-
if (!
|
|
23206
|
+
if (!existsSync32(DB_PATH)) {
|
|
22705
23207
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
22706
23208
|
process.exit(1);
|
|
22707
23209
|
}
|
|
@@ -22739,7 +23241,7 @@ async function cronList(globalOpts) {
|
|
|
22739
23241
|
});
|
|
22740
23242
|
}
|
|
22741
23243
|
async function cronHealth(globalOpts) {
|
|
22742
|
-
if (!
|
|
23244
|
+
if (!existsSync32(DB_PATH)) {
|
|
22743
23245
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
22744
23246
|
process.exit(1);
|
|
22745
23247
|
}
|
|
@@ -22898,7 +23400,7 @@ async function cronEdit(globalOpts, id, opts) {
|
|
|
22898
23400
|
}
|
|
22899
23401
|
}
|
|
22900
23402
|
async function cronRuns(globalOpts, jobId, opts) {
|
|
22901
|
-
if (!
|
|
23403
|
+
if (!existsSync32(DB_PATH)) {
|
|
22902
23404
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
22903
23405
|
process.exit(1);
|
|
22904
23406
|
}
|
|
@@ -22945,9 +23447,9 @@ __export(agents_exports, {
|
|
|
22945
23447
|
runnersList: () => runnersList,
|
|
22946
23448
|
tasksList: () => tasksList
|
|
22947
23449
|
});
|
|
22948
|
-
import { existsSync as
|
|
23450
|
+
import { existsSync as existsSync33 } from "fs";
|
|
22949
23451
|
async function agentsList(globalOpts) {
|
|
22950
|
-
if (!
|
|
23452
|
+
if (!existsSync33(DB_PATH)) {
|
|
22951
23453
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
22952
23454
|
process.exit(1);
|
|
22953
23455
|
}
|
|
@@ -22978,7 +23480,7 @@ async function agentsList(globalOpts) {
|
|
|
22978
23480
|
});
|
|
22979
23481
|
}
|
|
22980
23482
|
async function tasksList(globalOpts) {
|
|
22981
|
-
if (!
|
|
23483
|
+
if (!existsSync33(DB_PATH)) {
|
|
22982
23484
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
22983
23485
|
process.exit(1);
|
|
22984
23486
|
}
|
|
@@ -23106,10 +23608,10 @@ __export(db_exports, {
|
|
|
23106
23608
|
dbPath: () => dbPath,
|
|
23107
23609
|
dbStats: () => dbStats
|
|
23108
23610
|
});
|
|
23109
|
-
import { existsSync as
|
|
23611
|
+
import { existsSync as existsSync34, statSync as statSync8, copyFileSync as copyFileSync2, mkdirSync as mkdirSync13 } from "fs";
|
|
23110
23612
|
import { dirname as dirname5 } from "path";
|
|
23111
23613
|
async function dbStats(globalOpts) {
|
|
23112
|
-
if (!
|
|
23614
|
+
if (!existsSync34(DB_PATH)) {
|
|
23113
23615
|
outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
|
|
23114
23616
|
process.exit(1);
|
|
23115
23617
|
}
|
|
@@ -23117,7 +23619,7 @@ async function dbStats(globalOpts) {
|
|
|
23117
23619
|
const readDb = openDatabaseReadOnly2();
|
|
23118
23620
|
const mainSize = statSync8(DB_PATH).size;
|
|
23119
23621
|
const walPath = DB_PATH + "-wal";
|
|
23120
|
-
const walSize =
|
|
23622
|
+
const walSize = existsSync34(walPath) ? statSync8(walPath).size : 0;
|
|
23121
23623
|
const tableNames = readDb.prepare(
|
|
23122
23624
|
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '%_fts%' ORDER BY name"
|
|
23123
23625
|
).all();
|
|
@@ -23151,7 +23653,7 @@ async function dbPath(globalOpts) {
|
|
|
23151
23653
|
output({ path: DB_PATH }, (d) => d.path);
|
|
23152
23654
|
}
|
|
23153
23655
|
async function dbBackup(globalOpts, destPath) {
|
|
23154
|
-
if (!
|
|
23656
|
+
if (!existsSync34(DB_PATH)) {
|
|
23155
23657
|
outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
|
|
23156
23658
|
process.exit(1);
|
|
23157
23659
|
}
|
|
@@ -23160,7 +23662,7 @@ async function dbBackup(globalOpts, destPath) {
|
|
|
23160
23662
|
mkdirSync13(dirname5(dest), { recursive: true });
|
|
23161
23663
|
copyFileSync2(DB_PATH, dest);
|
|
23162
23664
|
const walPath = DB_PATH + "-wal";
|
|
23163
|
-
if (
|
|
23665
|
+
if (existsSync34(walPath)) copyFileSync2(walPath, dest + "-wal");
|
|
23164
23666
|
output({ path: dest, sizeBytes: statSync8(dest).size }, (d) => {
|
|
23165
23667
|
const b = d;
|
|
23166
23668
|
return `
|
|
@@ -23189,9 +23691,9 @@ __export(usage_exports, {
|
|
|
23189
23691
|
usageCost: () => usageCost,
|
|
23190
23692
|
usageTokens: () => usageTokens
|
|
23191
23693
|
});
|
|
23192
|
-
import { existsSync as
|
|
23694
|
+
import { existsSync as existsSync35 } from "fs";
|
|
23193
23695
|
function ensureDb() {
|
|
23194
|
-
if (!
|
|
23696
|
+
if (!existsSync35(DB_PATH)) {
|
|
23195
23697
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
23196
23698
|
process.exit(1);
|
|
23197
23699
|
}
|
|
@@ -23381,9 +23883,9 @@ __export(config_exports2, {
|
|
|
23381
23883
|
configList: () => configList,
|
|
23382
23884
|
configSet: () => configSet
|
|
23383
23885
|
});
|
|
23384
|
-
import { existsSync as
|
|
23886
|
+
import { existsSync as existsSync36, readFileSync as readFileSync18 } from "fs";
|
|
23385
23887
|
async function configList(globalOpts) {
|
|
23386
|
-
if (!
|
|
23888
|
+
if (!existsSync36(DB_PATH)) {
|
|
23387
23889
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23388
23890
|
process.exit(1);
|
|
23389
23891
|
}
|
|
@@ -23417,7 +23919,7 @@ async function configGet(globalOpts, key) {
|
|
|
23417
23919
|
outputError("INVALID_KEY", `Unknown config key "${key}". Valid keys: ${RUNTIME_KEYS.join(", ")}`);
|
|
23418
23920
|
process.exit(1);
|
|
23419
23921
|
}
|
|
23420
|
-
if (!
|
|
23922
|
+
if (!existsSync36(DB_PATH)) {
|
|
23421
23923
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23422
23924
|
process.exit(1);
|
|
23423
23925
|
}
|
|
@@ -23463,7 +23965,7 @@ async function configSet(globalOpts, key, value) {
|
|
|
23463
23965
|
}
|
|
23464
23966
|
}
|
|
23465
23967
|
async function configEnv(_globalOpts) {
|
|
23466
|
-
if (!
|
|
23968
|
+
if (!existsSync36(ENV_PATH)) {
|
|
23467
23969
|
outputError("ENV_NOT_FOUND", `No .env file at ${ENV_PATH}. Run cc-claw setup.`);
|
|
23468
23970
|
process.exit(1);
|
|
23469
23971
|
}
|
|
@@ -23517,9 +24019,9 @@ __export(session_exports, {
|
|
|
23517
24019
|
sessionGet: () => sessionGet,
|
|
23518
24020
|
sessionNew: () => sessionNew
|
|
23519
24021
|
});
|
|
23520
|
-
import { existsSync as
|
|
24022
|
+
import { existsSync as existsSync37 } from "fs";
|
|
23521
24023
|
async function sessionGet(globalOpts) {
|
|
23522
|
-
if (!
|
|
24024
|
+
if (!existsSync37(DB_PATH)) {
|
|
23523
24025
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23524
24026
|
process.exit(1);
|
|
23525
24027
|
}
|
|
@@ -23580,9 +24082,9 @@ __export(permissions_exports, {
|
|
|
23580
24082
|
verboseGet: () => verboseGet,
|
|
23581
24083
|
verboseSet: () => verboseSet
|
|
23582
24084
|
});
|
|
23583
|
-
import { existsSync as
|
|
24085
|
+
import { existsSync as existsSync38 } from "fs";
|
|
23584
24086
|
function ensureDb2() {
|
|
23585
|
-
if (!
|
|
24087
|
+
if (!existsSync38(DB_PATH)) {
|
|
23586
24088
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23587
24089
|
process.exit(1);
|
|
23588
24090
|
}
|
|
@@ -23729,9 +24231,9 @@ __export(cwd_exports, {
|
|
|
23729
24231
|
cwdGet: () => cwdGet,
|
|
23730
24232
|
cwdSet: () => cwdSet
|
|
23731
24233
|
});
|
|
23732
|
-
import { existsSync as
|
|
24234
|
+
import { existsSync as existsSync39 } from "fs";
|
|
23733
24235
|
async function cwdGet(globalOpts) {
|
|
23734
|
-
if (!
|
|
24236
|
+
if (!existsSync39(DB_PATH)) {
|
|
23735
24237
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23736
24238
|
process.exit(1);
|
|
23737
24239
|
}
|
|
@@ -23793,9 +24295,9 @@ __export(voice_exports, {
|
|
|
23793
24295
|
voiceGet: () => voiceGet,
|
|
23794
24296
|
voiceSet: () => voiceSet
|
|
23795
24297
|
});
|
|
23796
|
-
import { existsSync as
|
|
24298
|
+
import { existsSync as existsSync40 } from "fs";
|
|
23797
24299
|
async function voiceGet(globalOpts) {
|
|
23798
|
-
if (!
|
|
24300
|
+
if (!existsSync40(DB_PATH)) {
|
|
23799
24301
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23800
24302
|
process.exit(1);
|
|
23801
24303
|
}
|
|
@@ -23844,9 +24346,9 @@ __export(heartbeat_exports, {
|
|
|
23844
24346
|
heartbeatGet: () => heartbeatGet,
|
|
23845
24347
|
heartbeatSet: () => heartbeatSet
|
|
23846
24348
|
});
|
|
23847
|
-
import { existsSync as
|
|
24349
|
+
import { existsSync as existsSync41 } from "fs";
|
|
23848
24350
|
async function heartbeatGet(globalOpts) {
|
|
23849
|
-
if (!
|
|
24351
|
+
if (!existsSync41(DB_PATH)) {
|
|
23850
24352
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23851
24353
|
process.exit(1);
|
|
23852
24354
|
}
|
|
@@ -23955,9 +24457,9 @@ __export(summarizer_exports, {
|
|
|
23955
24457
|
summarizerGet: () => summarizerGet,
|
|
23956
24458
|
summarizerSet: () => summarizerSet
|
|
23957
24459
|
});
|
|
23958
|
-
import { existsSync as
|
|
24460
|
+
import { existsSync as existsSync42 } from "fs";
|
|
23959
24461
|
async function summarizerGet(globalOpts) {
|
|
23960
|
-
if (!
|
|
24462
|
+
if (!existsSync42(DB_PATH)) {
|
|
23961
24463
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23962
24464
|
process.exit(1);
|
|
23963
24465
|
}
|
|
@@ -24001,9 +24503,9 @@ __export(thinking_exports, {
|
|
|
24001
24503
|
thinkingGet: () => thinkingGet,
|
|
24002
24504
|
thinkingSet: () => thinkingSet
|
|
24003
24505
|
});
|
|
24004
|
-
import { existsSync as
|
|
24506
|
+
import { existsSync as existsSync43 } from "fs";
|
|
24005
24507
|
async function thinkingGet(globalOpts) {
|
|
24006
|
-
if (!
|
|
24508
|
+
if (!existsSync43(DB_PATH)) {
|
|
24007
24509
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24008
24510
|
process.exit(1);
|
|
24009
24511
|
}
|
|
@@ -24047,9 +24549,9 @@ __export(chats_exports, {
|
|
|
24047
24549
|
chatsList: () => chatsList,
|
|
24048
24550
|
chatsRemoveAlias: () => chatsRemoveAlias
|
|
24049
24551
|
});
|
|
24050
|
-
import { existsSync as
|
|
24552
|
+
import { existsSync as existsSync44 } from "fs";
|
|
24051
24553
|
async function chatsList(_globalOpts) {
|
|
24052
|
-
if (!
|
|
24554
|
+
if (!existsSync44(DB_PATH)) {
|
|
24053
24555
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24054
24556
|
process.exit(1);
|
|
24055
24557
|
}
|
|
@@ -24177,9 +24679,9 @@ var mcps_exports2 = {};
|
|
|
24177
24679
|
__export(mcps_exports2, {
|
|
24178
24680
|
mcpsList: () => mcpsList
|
|
24179
24681
|
});
|
|
24180
|
-
import { existsSync as
|
|
24682
|
+
import { existsSync as existsSync45 } from "fs";
|
|
24181
24683
|
async function mcpsList(_globalOpts) {
|
|
24182
|
-
if (!
|
|
24684
|
+
if (!existsSync45(DB_PATH)) {
|
|
24183
24685
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24184
24686
|
process.exit(1);
|
|
24185
24687
|
}
|
|
@@ -24216,11 +24718,11 @@ __export(chat_exports2, {
|
|
|
24216
24718
|
chatSend: () => chatSend
|
|
24217
24719
|
});
|
|
24218
24720
|
import { request as httpRequest2 } from "http";
|
|
24219
|
-
import { readFileSync as readFileSync19, existsSync as
|
|
24721
|
+
import { readFileSync as readFileSync19, existsSync as existsSync46 } from "fs";
|
|
24220
24722
|
function getToken2() {
|
|
24221
24723
|
if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
|
|
24222
24724
|
try {
|
|
24223
|
-
if (
|
|
24725
|
+
if (existsSync46(TOKEN_PATH2)) return readFileSync19(TOKEN_PATH2, "utf-8").trim();
|
|
24224
24726
|
} catch {
|
|
24225
24727
|
}
|
|
24226
24728
|
return null;
|
|
@@ -24357,7 +24859,7 @@ var tui_exports = {};
|
|
|
24357
24859
|
__export(tui_exports, {
|
|
24358
24860
|
tuiCommand: () => tuiCommand
|
|
24359
24861
|
});
|
|
24360
|
-
import { createInterface as
|
|
24862
|
+
import { createInterface as createInterface7 } from "readline";
|
|
24361
24863
|
import pc2 from "picocolors";
|
|
24362
24864
|
async function tuiCommand(globalOpts, cmdOpts) {
|
|
24363
24865
|
const { isDaemonRunning: isDaemonRunning2, apiPost: apiPost2 } = await Promise.resolve().then(() => (init_api_client(), api_client_exports));
|
|
@@ -24367,7 +24869,7 @@ async function tuiCommand(globalOpts, cmdOpts) {
|
|
|
24367
24869
|
}
|
|
24368
24870
|
const chatId = resolveChatId(globalOpts);
|
|
24369
24871
|
const { chatSend: chatSend2 } = await Promise.resolve().then(() => (init_chat2(), chat_exports2));
|
|
24370
|
-
const rl2 =
|
|
24872
|
+
const rl2 = createInterface7({
|
|
24371
24873
|
input: process.stdin,
|
|
24372
24874
|
output: process.stdout,
|
|
24373
24875
|
prompt: pc2.cyan("you > "),
|
|
@@ -24690,9 +25192,9 @@ __export(evolve_exports2, {
|
|
|
24690
25192
|
evolveStatus: () => evolveStatus,
|
|
24691
25193
|
evolveUndo: () => evolveUndo
|
|
24692
25194
|
});
|
|
24693
|
-
import { existsSync as
|
|
25195
|
+
import { existsSync as existsSync47 } from "fs";
|
|
24694
25196
|
function ensureDb3() {
|
|
24695
|
-
if (!
|
|
25197
|
+
if (!existsSync47(DB_PATH)) {
|
|
24696
25198
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
24697
25199
|
process.exit(1);
|
|
24698
25200
|
}
|
|
@@ -25108,9 +25610,9 @@ var init_evolve3 = __esm({
|
|
|
25108
25610
|
|
|
25109
25611
|
// src/setup.ts
|
|
25110
25612
|
var setup_exports = {};
|
|
25111
|
-
import { existsSync as
|
|
25613
|
+
import { existsSync as existsSync48, writeFileSync as writeFileSync11, readFileSync as readFileSync20, copyFileSync as copyFileSync3, mkdirSync as mkdirSync15, statSync as statSync9 } from "fs";
|
|
25112
25614
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
25113
|
-
import { createInterface as
|
|
25615
|
+
import { createInterface as createInterface8 } from "readline";
|
|
25114
25616
|
import { join as join27 } from "path";
|
|
25115
25617
|
function divider2() {
|
|
25116
25618
|
console.log(dim("\u2500".repeat(55)));
|
|
@@ -25186,10 +25688,10 @@ async function setup() {
|
|
|
25186
25688
|
}
|
|
25187
25689
|
console.log("");
|
|
25188
25690
|
for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
|
|
25189
|
-
if (!
|
|
25691
|
+
if (!existsSync48(dir)) mkdirSync15(dir, { recursive: true });
|
|
25190
25692
|
}
|
|
25191
25693
|
const env = {};
|
|
25192
|
-
const envSource =
|
|
25694
|
+
const envSource = existsSync48(ENV_PATH) ? ENV_PATH : existsSync48(".env") ? ".env" : null;
|
|
25193
25695
|
if (envSource) {
|
|
25194
25696
|
console.log(yellow(` Found existing config at ${envSource} \u2014 your values will be preserved`));
|
|
25195
25697
|
console.log(yellow(" unless you enter new ones. Just press Enter to keep existing values.\n"));
|
|
@@ -25200,7 +25702,7 @@ async function setup() {
|
|
|
25200
25702
|
}
|
|
25201
25703
|
}
|
|
25202
25704
|
const cwdDb = join27(process.cwd(), "cc-claw.db");
|
|
25203
|
-
if (
|
|
25705
|
+
if (existsSync48(cwdDb) && !existsSync48(DB_PATH)) {
|
|
25204
25706
|
const { size } = statSync9(cwdDb);
|
|
25205
25707
|
console.log(yellow(` Found existing database at ${cwdDb} (${(size / 1024).toFixed(0)}KB)`));
|
|
25206
25708
|
const migrate = await confirm("Copy database to ~/.cc-claw/? (preserves memories & history)", true);
|
|
@@ -25473,7 +25975,7 @@ var init_setup = __esm({
|
|
|
25473
25975
|
"src/setup.ts"() {
|
|
25474
25976
|
"use strict";
|
|
25475
25977
|
init_paths();
|
|
25476
|
-
rl =
|
|
25978
|
+
rl = createInterface8({ input: process.stdin, output: process.stdout });
|
|
25477
25979
|
ask = (q) => new Promise((resolve) => rl.question(q, resolve));
|
|
25478
25980
|
bold = (s) => `\x1B[1m${s}\x1B[0m`;
|
|
25479
25981
|
green = (s) => `\x1B[32m${s}\x1B[0m`;
|
|
@@ -25575,6 +26077,39 @@ gemini.command("rotation [mode]").description("Get or set rotation mode (off, al
|
|
|
25575
26077
|
const { geminiRotation: geminiRotation2 } = await Promise.resolve().then(() => (init_gemini2(), gemini_exports));
|
|
25576
26078
|
await geminiRotation2(program.opts(), mode);
|
|
25577
26079
|
});
|
|
26080
|
+
function registerUnifiedSlotCommands(parentCmd, backendId, displayName) {
|
|
26081
|
+
const cmd = parentCmd.command(backendId).description(`Manage ${displayName} credential slots`);
|
|
26082
|
+
cmd.command("list").description(`Show all configured ${displayName} credential slots`).action(async () => {
|
|
26083
|
+
const { makeList: makeList2 } = await Promise.resolve().then(() => (init_backend_cmd_factory(), backend_cmd_factory_exports));
|
|
26084
|
+
await makeList2(backendId, displayName)(program.opts());
|
|
26085
|
+
});
|
|
26086
|
+
cmd.command("add-key").description("Add an API key slot (prompts for key in terminal)").option("--label <name>", "Friendly label for this slot").option("--priority <n>", "Priority (lower = preferred)", "0").action(async (opts) => {
|
|
26087
|
+
const { makeAddKey: makeAddKey2 } = await Promise.resolve().then(() => (init_backend_cmd_factory(), backend_cmd_factory_exports));
|
|
26088
|
+
await makeAddKey2(backendId, displayName)(program.opts(), opts);
|
|
26089
|
+
});
|
|
26090
|
+
cmd.command("remove <id-or-label>").description("Remove a credential slot (by ID or label)").action(async (id) => {
|
|
26091
|
+
const { makeRemove: makeRemove2 } = await Promise.resolve().then(() => (init_backend_cmd_factory(), backend_cmd_factory_exports));
|
|
26092
|
+
await makeRemove2(backendId, displayName)(program.opts(), id);
|
|
26093
|
+
});
|
|
26094
|
+
cmd.command("enable <id-or-label>").description("Re-enable a disabled slot").action(async (id) => {
|
|
26095
|
+
const { makeEnable: makeEnable2 } = await Promise.resolve().then(() => (init_backend_cmd_factory(), backend_cmd_factory_exports));
|
|
26096
|
+
await makeEnable2(backendId, displayName)(program.opts(), id);
|
|
26097
|
+
});
|
|
26098
|
+
cmd.command("disable <id-or-label>").description("Disable a slot").action(async (id) => {
|
|
26099
|
+
const { makeDisable: makeDisable2 } = await Promise.resolve().then(() => (init_backend_cmd_factory(), backend_cmd_factory_exports));
|
|
26100
|
+
await makeDisable2(backendId, displayName)(program.opts(), id);
|
|
26101
|
+
});
|
|
26102
|
+
cmd.command("reorder <id-or-label> <priority>").description("Set slot priority (lower = preferred)").action(async (id, priority) => {
|
|
26103
|
+
const { makeReorder: makeReorder2 } = await Promise.resolve().then(() => (init_backend_cmd_factory(), backend_cmd_factory_exports));
|
|
26104
|
+
await makeReorder2(backendId, displayName)(program.opts(), id, priority);
|
|
26105
|
+
});
|
|
26106
|
+
cmd.command("refresh").description("Re-enable all slots, clear cooldowns and errors").action(async () => {
|
|
26107
|
+
const { makeRefresh: makeRefresh2 } = await Promise.resolve().then(() => (init_backend_cmd_factory(), backend_cmd_factory_exports));
|
|
26108
|
+
await makeRefresh2(backendId, displayName)(program.opts());
|
|
26109
|
+
});
|
|
26110
|
+
}
|
|
26111
|
+
registerUnifiedSlotCommands(program, "claude", "Claude");
|
|
26112
|
+
registerUnifiedSlotCommands(program, "codex", "Codex");
|
|
25578
26113
|
var backend = program.command("backend").description("Manage AI backend");
|
|
25579
26114
|
backend.command("list").description("Available backends with status").action(async () => {
|
|
25580
26115
|
const { backendList: backendList2 } = await Promise.resolve().then(() => (init_backend(), backend_exports));
|
package/package.json
CHANGED