cc-claw 0.15.2 → 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.
Files changed (2) hide show
  1. package/dist/cli.js +606 -72
  2. 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.15.2" : (() => {
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
- getEnvForSlot(chatId, thinkingOverrides, mode) {
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.getEnvForSlot(parentChatId, void 0, rotationMode);
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.getEnvForSlot(chatId, void 0, rotationMode);
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.getEnvForSlot(chatId);
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.getEnvForSlot(chatId);
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.getEnvForSlot(chatId);
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" },
@@ -15687,13 +15902,13 @@ async function handleEvolveCallback(chatId, data, channel) {
15687
15902
  const { getReflectionStatus: getReflectionStatus2, setReflectionStatus: setReflectionStatus2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
15688
15903
  const current = getReflectionStatus2(getDb(), chatId);
15689
15904
  if (current === "frozen") {
15690
- const { readFileSync: readFileSync21, existsSync: existsSync48 } = await import("fs");
15905
+ const { readFileSync: readFileSync21, existsSync: existsSync49 } = await import("fs");
15691
15906
  const { join: join28 } = await import("path");
15692
15907
  const { CC_CLAW_HOME: CC_CLAW_HOME3 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
15693
15908
  const soulPath = join28(CC_CLAW_HOME3, "identity/SOUL.md");
15694
15909
  const userPath = join28(CC_CLAW_HOME3, "identity/USER.md");
15695
- const soul = existsSync48(soulPath) ? readFileSync21(soulPath, "utf-8") : "";
15696
- const user = existsSync48(userPath) ? readFileSync21(userPath, "utf-8") : "";
15910
+ const soul = existsSync49(soulPath) ? readFileSync21(soulPath, "utf-8") : "";
15911
+ const user = existsSync49(userPath) ? readFileSync21(userPath, "utf-8") : "";
15697
15912
  setReflectionStatus2(getDb(), chatId, "active", soul, user);
15698
15913
  const { logActivity: logActivity2 } = await Promise.resolve().then(() => (init_store3(), store_exports3));
15699
15914
  logActivity2(getDb(), { chatId, source: "telegram", eventType: "reflection_unfrozen", summary: "Reflection enabled" });
@@ -16036,14 +16251,28 @@ Tap to toggle:`,
16036
16251
  }
16037
16252
  const iStats = getIntentStats();
16038
16253
  const iTotal = iStats.chat + iStats.agentic;
16039
- let geminiSlotInfo = "";
16254
+ let slotInfo = "";
16040
16255
  if ((backendId ?? "claude") === "gemini") {
16041
16256
  try {
16042
16257
  const active = getNextGeminiSlot(chatId);
16043
16258
  const totalSlots = getEligibleGeminiSlots().length;
16044
16259
  if (active) {
16045
16260
  const label2 = active.label || `slot-${active.id}`;
16046
- geminiSlotInfo = ` \xB7 \u{1F511} ${label2} (${totalSlots} slots)`;
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
+ }
16047
16276
  }
16048
16277
  } catch {
16049
16278
  }
@@ -16057,7 +16286,7 @@ Tap to toggle:`,
16057
16286
  `\u23F1 Uptime: ${uptimeStr}`,
16058
16287
  ``,
16059
16288
  buildSectionHeader("Engine"),
16060
- `\u{1F9E0} ${adapter?.displayName ?? backendId ?? "not set"} \xB7 ${formatModelShort(model2)}${geminiSlotInfo}`,
16289
+ `\u{1F9E0} ${adapter?.displayName ?? backendId ?? "not set"} \xB7 ${formatModelShort(model2)}${slotInfo}`,
16061
16290
  `\u{1F4AD} Think: ${thinking2} \xB7 Mode: ${mode}`,
16062
16291
  `\u{1F916} Agents: ${getAgentMode(chatId)}`,
16063
16292
  `\u{1F507} Voice: ${voice2 ? "on" : "off"} \xB7 Sig: ${modelSig}`,
@@ -16176,6 +16405,42 @@ Use: /gemini_accounts <name> to pin`, { parseMode: "plain" });
16176
16405
  }
16177
16406
  break;
16178
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
+ }
16179
16444
  case "model": {
16180
16445
  let adapter;
16181
16446
  try {
@@ -17791,6 +18056,28 @@ ${rotationNote}`, { parseMode: "html" });
17791
18056
  await channel.sendKeyboard(chatId, "Gemini Accounts & Rotation:", rows);
17792
18057
  }
17793
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;
17794
18081
  } else if (data.startsWith("shell:")) {
17795
18082
  const parts = data.split(":");
17796
18083
  const action = parts[1];
@@ -18549,6 +18836,12 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
18549
18836
  const slot = getGeminiSlots().find((s) => s.id === slotId);
18550
18837
  if (slot) slotTag = ` \xB7 ${slot.label || `slot-${slot.id}`}`;
18551
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
+ }
18552
18845
  }
18553
18846
  responseText += `
18554
18847
 
@@ -22415,6 +22708,214 @@ var init_gemini2 = __esm({
22415
22708
  }
22416
22709
  });
22417
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
+
22418
22919
  // src/cli/commands/backend.ts
22419
22920
  var backend_exports = {};
22420
22921
  __export(backend_exports, {
@@ -22422,12 +22923,12 @@ __export(backend_exports, {
22422
22923
  backendList: () => backendList,
22423
22924
  backendSet: () => backendSet
22424
22925
  });
22425
- import { existsSync as existsSync28 } from "fs";
22926
+ import { existsSync as existsSync29 } from "fs";
22426
22927
  async function backendList(globalOpts) {
22427
22928
  const { getAvailableAdapters: getAvailableAdapters3 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
22428
22929
  const chatId = resolveChatId(globalOpts);
22429
22930
  let activeBackend = null;
22430
- if (existsSync28(DB_PATH)) {
22931
+ if (existsSync29(DB_PATH)) {
22431
22932
  const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
22432
22933
  const readDb = openDatabaseReadOnly2();
22433
22934
  try {
@@ -22458,7 +22959,7 @@ async function backendList(globalOpts) {
22458
22959
  }
22459
22960
  async function backendGet(globalOpts) {
22460
22961
  const chatId = resolveChatId(globalOpts);
22461
- if (!existsSync28(DB_PATH)) {
22962
+ if (!existsSync29(DB_PATH)) {
22462
22963
  outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
22463
22964
  process.exit(1);
22464
22965
  }
@@ -22502,13 +23003,13 @@ __export(model_exports, {
22502
23003
  modelList: () => modelList,
22503
23004
  modelSet: () => modelSet
22504
23005
  });
22505
- import { existsSync as existsSync29 } from "fs";
23006
+ import { existsSync as existsSync30 } from "fs";
22506
23007
  async function modelList(globalOpts) {
22507
23008
  const chatId = resolveChatId(globalOpts);
22508
23009
  const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
22509
23010
  const { getAdapter: getAdapter4, getAllAdapters: getAllAdapters5 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
22510
23011
  let backendId = "claude";
22511
- if (existsSync29(DB_PATH)) {
23012
+ if (existsSync30(DB_PATH)) {
22512
23013
  const readDb = openDatabaseReadOnly2();
22513
23014
  try {
22514
23015
  const row = readDb.prepare("SELECT backend FROM chat_backend WHERE chat_id = ?").get(chatId);
@@ -22541,7 +23042,7 @@ async function modelList(globalOpts) {
22541
23042
  }
22542
23043
  async function modelGet(globalOpts) {
22543
23044
  const chatId = resolveChatId(globalOpts);
22544
- if (!existsSync29(DB_PATH)) {
23045
+ if (!existsSync30(DB_PATH)) {
22545
23046
  outputError("DB_NOT_FOUND", "Database not found.");
22546
23047
  process.exit(1);
22547
23048
  }
@@ -22585,9 +23086,9 @@ __export(memory_exports2, {
22585
23086
  memoryList: () => memoryList,
22586
23087
  memorySearch: () => memorySearch
22587
23088
  });
22588
- import { existsSync as existsSync30 } from "fs";
23089
+ import { existsSync as existsSync31 } from "fs";
22589
23090
  async function memoryList(globalOpts) {
22590
- if (!existsSync30(DB_PATH)) {
23091
+ if (!existsSync31(DB_PATH)) {
22591
23092
  outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
22592
23093
  process.exit(1);
22593
23094
  }
@@ -22611,7 +23112,7 @@ async function memoryList(globalOpts) {
22611
23112
  });
22612
23113
  }
22613
23114
  async function memorySearch(globalOpts, query) {
22614
- if (!existsSync30(DB_PATH)) {
23115
+ if (!existsSync31(DB_PATH)) {
22615
23116
  outputError("DB_NOT_FOUND", "Database not found.");
22616
23117
  process.exit(1);
22617
23118
  }
@@ -22633,7 +23134,7 @@ async function memorySearch(globalOpts, query) {
22633
23134
  });
22634
23135
  }
22635
23136
  async function memoryHistory(globalOpts, opts) {
22636
- if (!existsSync30(DB_PATH)) {
23137
+ if (!existsSync31(DB_PATH)) {
22637
23138
  outputError("DB_NOT_FOUND", "Database not found.");
22638
23139
  process.exit(1);
22639
23140
  }
@@ -22681,7 +23182,7 @@ __export(cron_exports2, {
22681
23182
  cronList: () => cronList,
22682
23183
  cronRuns: () => cronRuns
22683
23184
  });
22684
- import { existsSync as existsSync31 } from "fs";
23185
+ import { existsSync as existsSync32 } from "fs";
22685
23186
  function parseFallbacks(raw) {
22686
23187
  return raw.slice(0, 3).map((f) => {
22687
23188
  const [backend2, ...rest] = f.split(":");
@@ -22702,7 +23203,7 @@ function parseAndValidateTimeout(raw) {
22702
23203
  return val;
22703
23204
  }
22704
23205
  async function cronList(globalOpts) {
22705
- if (!existsSync31(DB_PATH)) {
23206
+ if (!existsSync32(DB_PATH)) {
22706
23207
  outputError("DB_NOT_FOUND", "Database not found.");
22707
23208
  process.exit(1);
22708
23209
  }
@@ -22740,7 +23241,7 @@ async function cronList(globalOpts) {
22740
23241
  });
22741
23242
  }
22742
23243
  async function cronHealth(globalOpts) {
22743
- if (!existsSync31(DB_PATH)) {
23244
+ if (!existsSync32(DB_PATH)) {
22744
23245
  outputError("DB_NOT_FOUND", "Database not found.");
22745
23246
  process.exit(1);
22746
23247
  }
@@ -22899,7 +23400,7 @@ async function cronEdit(globalOpts, id, opts) {
22899
23400
  }
22900
23401
  }
22901
23402
  async function cronRuns(globalOpts, jobId, opts) {
22902
- if (!existsSync31(DB_PATH)) {
23403
+ if (!existsSync32(DB_PATH)) {
22903
23404
  outputError("DB_NOT_FOUND", "Database not found.");
22904
23405
  process.exit(1);
22905
23406
  }
@@ -22946,9 +23447,9 @@ __export(agents_exports, {
22946
23447
  runnersList: () => runnersList,
22947
23448
  tasksList: () => tasksList
22948
23449
  });
22949
- import { existsSync as existsSync32 } from "fs";
23450
+ import { existsSync as existsSync33 } from "fs";
22950
23451
  async function agentsList(globalOpts) {
22951
- if (!existsSync32(DB_PATH)) {
23452
+ if (!existsSync33(DB_PATH)) {
22952
23453
  outputError("DB_NOT_FOUND", "Database not found.");
22953
23454
  process.exit(1);
22954
23455
  }
@@ -22979,7 +23480,7 @@ async function agentsList(globalOpts) {
22979
23480
  });
22980
23481
  }
22981
23482
  async function tasksList(globalOpts) {
22982
- if (!existsSync32(DB_PATH)) {
23483
+ if (!existsSync33(DB_PATH)) {
22983
23484
  outputError("DB_NOT_FOUND", "Database not found.");
22984
23485
  process.exit(1);
22985
23486
  }
@@ -23107,10 +23608,10 @@ __export(db_exports, {
23107
23608
  dbPath: () => dbPath,
23108
23609
  dbStats: () => dbStats
23109
23610
  });
23110
- import { existsSync as existsSync33, statSync as statSync8, copyFileSync as copyFileSync2, mkdirSync as mkdirSync13 } from "fs";
23611
+ import { existsSync as existsSync34, statSync as statSync8, copyFileSync as copyFileSync2, mkdirSync as mkdirSync13 } from "fs";
23111
23612
  import { dirname as dirname5 } from "path";
23112
23613
  async function dbStats(globalOpts) {
23113
- if (!existsSync33(DB_PATH)) {
23614
+ if (!existsSync34(DB_PATH)) {
23114
23615
  outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
23115
23616
  process.exit(1);
23116
23617
  }
@@ -23118,7 +23619,7 @@ async function dbStats(globalOpts) {
23118
23619
  const readDb = openDatabaseReadOnly2();
23119
23620
  const mainSize = statSync8(DB_PATH).size;
23120
23621
  const walPath = DB_PATH + "-wal";
23121
- const walSize = existsSync33(walPath) ? statSync8(walPath).size : 0;
23622
+ const walSize = existsSync34(walPath) ? statSync8(walPath).size : 0;
23122
23623
  const tableNames = readDb.prepare(
23123
23624
  "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '%_fts%' ORDER BY name"
23124
23625
  ).all();
@@ -23152,7 +23653,7 @@ async function dbPath(globalOpts) {
23152
23653
  output({ path: DB_PATH }, (d) => d.path);
23153
23654
  }
23154
23655
  async function dbBackup(globalOpts, destPath) {
23155
- if (!existsSync33(DB_PATH)) {
23656
+ if (!existsSync34(DB_PATH)) {
23156
23657
  outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
23157
23658
  process.exit(1);
23158
23659
  }
@@ -23161,7 +23662,7 @@ async function dbBackup(globalOpts, destPath) {
23161
23662
  mkdirSync13(dirname5(dest), { recursive: true });
23162
23663
  copyFileSync2(DB_PATH, dest);
23163
23664
  const walPath = DB_PATH + "-wal";
23164
- if (existsSync33(walPath)) copyFileSync2(walPath, dest + "-wal");
23665
+ if (existsSync34(walPath)) copyFileSync2(walPath, dest + "-wal");
23165
23666
  output({ path: dest, sizeBytes: statSync8(dest).size }, (d) => {
23166
23667
  const b = d;
23167
23668
  return `
@@ -23190,9 +23691,9 @@ __export(usage_exports, {
23190
23691
  usageCost: () => usageCost,
23191
23692
  usageTokens: () => usageTokens
23192
23693
  });
23193
- import { existsSync as existsSync34 } from "fs";
23694
+ import { existsSync as existsSync35 } from "fs";
23194
23695
  function ensureDb() {
23195
- if (!existsSync34(DB_PATH)) {
23696
+ if (!existsSync35(DB_PATH)) {
23196
23697
  outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
23197
23698
  process.exit(1);
23198
23699
  }
@@ -23382,9 +23883,9 @@ __export(config_exports2, {
23382
23883
  configList: () => configList,
23383
23884
  configSet: () => configSet
23384
23885
  });
23385
- import { existsSync as existsSync35, readFileSync as readFileSync18 } from "fs";
23886
+ import { existsSync as existsSync36, readFileSync as readFileSync18 } from "fs";
23386
23887
  async function configList(globalOpts) {
23387
- if (!existsSync35(DB_PATH)) {
23888
+ if (!existsSync36(DB_PATH)) {
23388
23889
  outputError("DB_NOT_FOUND", "Database not found.");
23389
23890
  process.exit(1);
23390
23891
  }
@@ -23418,7 +23919,7 @@ async function configGet(globalOpts, key) {
23418
23919
  outputError("INVALID_KEY", `Unknown config key "${key}". Valid keys: ${RUNTIME_KEYS.join(", ")}`);
23419
23920
  process.exit(1);
23420
23921
  }
23421
- if (!existsSync35(DB_PATH)) {
23922
+ if (!existsSync36(DB_PATH)) {
23422
23923
  outputError("DB_NOT_FOUND", "Database not found.");
23423
23924
  process.exit(1);
23424
23925
  }
@@ -23464,7 +23965,7 @@ async function configSet(globalOpts, key, value) {
23464
23965
  }
23465
23966
  }
23466
23967
  async function configEnv(_globalOpts) {
23467
- if (!existsSync35(ENV_PATH)) {
23968
+ if (!existsSync36(ENV_PATH)) {
23468
23969
  outputError("ENV_NOT_FOUND", `No .env file at ${ENV_PATH}. Run cc-claw setup.`);
23469
23970
  process.exit(1);
23470
23971
  }
@@ -23518,9 +24019,9 @@ __export(session_exports, {
23518
24019
  sessionGet: () => sessionGet,
23519
24020
  sessionNew: () => sessionNew
23520
24021
  });
23521
- import { existsSync as existsSync36 } from "fs";
24022
+ import { existsSync as existsSync37 } from "fs";
23522
24023
  async function sessionGet(globalOpts) {
23523
- if (!existsSync36(DB_PATH)) {
24024
+ if (!existsSync37(DB_PATH)) {
23524
24025
  outputError("DB_NOT_FOUND", "Database not found.");
23525
24026
  process.exit(1);
23526
24027
  }
@@ -23581,9 +24082,9 @@ __export(permissions_exports, {
23581
24082
  verboseGet: () => verboseGet,
23582
24083
  verboseSet: () => verboseSet
23583
24084
  });
23584
- import { existsSync as existsSync37 } from "fs";
24085
+ import { existsSync as existsSync38 } from "fs";
23585
24086
  function ensureDb2() {
23586
- if (!existsSync37(DB_PATH)) {
24087
+ if (!existsSync38(DB_PATH)) {
23587
24088
  outputError("DB_NOT_FOUND", "Database not found.");
23588
24089
  process.exit(1);
23589
24090
  }
@@ -23730,9 +24231,9 @@ __export(cwd_exports, {
23730
24231
  cwdGet: () => cwdGet,
23731
24232
  cwdSet: () => cwdSet
23732
24233
  });
23733
- import { existsSync as existsSync38 } from "fs";
24234
+ import { existsSync as existsSync39 } from "fs";
23734
24235
  async function cwdGet(globalOpts) {
23735
- if (!existsSync38(DB_PATH)) {
24236
+ if (!existsSync39(DB_PATH)) {
23736
24237
  outputError("DB_NOT_FOUND", "Database not found.");
23737
24238
  process.exit(1);
23738
24239
  }
@@ -23794,9 +24295,9 @@ __export(voice_exports, {
23794
24295
  voiceGet: () => voiceGet,
23795
24296
  voiceSet: () => voiceSet
23796
24297
  });
23797
- import { existsSync as existsSync39 } from "fs";
24298
+ import { existsSync as existsSync40 } from "fs";
23798
24299
  async function voiceGet(globalOpts) {
23799
- if (!existsSync39(DB_PATH)) {
24300
+ if (!existsSync40(DB_PATH)) {
23800
24301
  outputError("DB_NOT_FOUND", "Database not found.");
23801
24302
  process.exit(1);
23802
24303
  }
@@ -23845,9 +24346,9 @@ __export(heartbeat_exports, {
23845
24346
  heartbeatGet: () => heartbeatGet,
23846
24347
  heartbeatSet: () => heartbeatSet
23847
24348
  });
23848
- import { existsSync as existsSync40 } from "fs";
24349
+ import { existsSync as existsSync41 } from "fs";
23849
24350
  async function heartbeatGet(globalOpts) {
23850
- if (!existsSync40(DB_PATH)) {
24351
+ if (!existsSync41(DB_PATH)) {
23851
24352
  outputError("DB_NOT_FOUND", "Database not found.");
23852
24353
  process.exit(1);
23853
24354
  }
@@ -23956,9 +24457,9 @@ __export(summarizer_exports, {
23956
24457
  summarizerGet: () => summarizerGet,
23957
24458
  summarizerSet: () => summarizerSet
23958
24459
  });
23959
- import { existsSync as existsSync41 } from "fs";
24460
+ import { existsSync as existsSync42 } from "fs";
23960
24461
  async function summarizerGet(globalOpts) {
23961
- if (!existsSync41(DB_PATH)) {
24462
+ if (!existsSync42(DB_PATH)) {
23962
24463
  outputError("DB_NOT_FOUND", "Database not found.");
23963
24464
  process.exit(1);
23964
24465
  }
@@ -24002,9 +24503,9 @@ __export(thinking_exports, {
24002
24503
  thinkingGet: () => thinkingGet,
24003
24504
  thinkingSet: () => thinkingSet
24004
24505
  });
24005
- import { existsSync as existsSync42 } from "fs";
24506
+ import { existsSync as existsSync43 } from "fs";
24006
24507
  async function thinkingGet(globalOpts) {
24007
- if (!existsSync42(DB_PATH)) {
24508
+ if (!existsSync43(DB_PATH)) {
24008
24509
  outputError("DB_NOT_FOUND", "Database not found.");
24009
24510
  process.exit(1);
24010
24511
  }
@@ -24048,9 +24549,9 @@ __export(chats_exports, {
24048
24549
  chatsList: () => chatsList,
24049
24550
  chatsRemoveAlias: () => chatsRemoveAlias
24050
24551
  });
24051
- import { existsSync as existsSync43 } from "fs";
24552
+ import { existsSync as existsSync44 } from "fs";
24052
24553
  async function chatsList(_globalOpts) {
24053
- if (!existsSync43(DB_PATH)) {
24554
+ if (!existsSync44(DB_PATH)) {
24054
24555
  outputError("DB_NOT_FOUND", "Database not found.");
24055
24556
  process.exit(1);
24056
24557
  }
@@ -24178,9 +24679,9 @@ var mcps_exports2 = {};
24178
24679
  __export(mcps_exports2, {
24179
24680
  mcpsList: () => mcpsList
24180
24681
  });
24181
- import { existsSync as existsSync44 } from "fs";
24682
+ import { existsSync as existsSync45 } from "fs";
24182
24683
  async function mcpsList(_globalOpts) {
24183
- if (!existsSync44(DB_PATH)) {
24684
+ if (!existsSync45(DB_PATH)) {
24184
24685
  outputError("DB_NOT_FOUND", "Database not found.");
24185
24686
  process.exit(1);
24186
24687
  }
@@ -24217,11 +24718,11 @@ __export(chat_exports2, {
24217
24718
  chatSend: () => chatSend
24218
24719
  });
24219
24720
  import { request as httpRequest2 } from "http";
24220
- import { readFileSync as readFileSync19, existsSync as existsSync45 } from "fs";
24721
+ import { readFileSync as readFileSync19, existsSync as existsSync46 } from "fs";
24221
24722
  function getToken2() {
24222
24723
  if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
24223
24724
  try {
24224
- if (existsSync45(TOKEN_PATH2)) return readFileSync19(TOKEN_PATH2, "utf-8").trim();
24725
+ if (existsSync46(TOKEN_PATH2)) return readFileSync19(TOKEN_PATH2, "utf-8").trim();
24225
24726
  } catch {
24226
24727
  }
24227
24728
  return null;
@@ -24358,7 +24859,7 @@ var tui_exports = {};
24358
24859
  __export(tui_exports, {
24359
24860
  tuiCommand: () => tuiCommand
24360
24861
  });
24361
- import { createInterface as createInterface6 } from "readline";
24862
+ import { createInterface as createInterface7 } from "readline";
24362
24863
  import pc2 from "picocolors";
24363
24864
  async function tuiCommand(globalOpts, cmdOpts) {
24364
24865
  const { isDaemonRunning: isDaemonRunning2, apiPost: apiPost2 } = await Promise.resolve().then(() => (init_api_client(), api_client_exports));
@@ -24368,7 +24869,7 @@ async function tuiCommand(globalOpts, cmdOpts) {
24368
24869
  }
24369
24870
  const chatId = resolveChatId(globalOpts);
24370
24871
  const { chatSend: chatSend2 } = await Promise.resolve().then(() => (init_chat2(), chat_exports2));
24371
- const rl2 = createInterface6({
24872
+ const rl2 = createInterface7({
24372
24873
  input: process.stdin,
24373
24874
  output: process.stdout,
24374
24875
  prompt: pc2.cyan("you > "),
@@ -24691,9 +25192,9 @@ __export(evolve_exports2, {
24691
25192
  evolveStatus: () => evolveStatus,
24692
25193
  evolveUndo: () => evolveUndo
24693
25194
  });
24694
- import { existsSync as existsSync46 } from "fs";
25195
+ import { existsSync as existsSync47 } from "fs";
24695
25196
  function ensureDb3() {
24696
- if (!existsSync46(DB_PATH)) {
25197
+ if (!existsSync47(DB_PATH)) {
24697
25198
  outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
24698
25199
  process.exit(1);
24699
25200
  }
@@ -25109,9 +25610,9 @@ var init_evolve3 = __esm({
25109
25610
 
25110
25611
  // src/setup.ts
25111
25612
  var setup_exports = {};
25112
- import { existsSync as existsSync47, writeFileSync as writeFileSync11, readFileSync as readFileSync20, copyFileSync as copyFileSync3, mkdirSync as mkdirSync15, statSync as statSync9 } from "fs";
25613
+ import { existsSync as existsSync48, writeFileSync as writeFileSync11, readFileSync as readFileSync20, copyFileSync as copyFileSync3, mkdirSync as mkdirSync15, statSync as statSync9 } from "fs";
25113
25614
  import { execFileSync as execFileSync5 } from "child_process";
25114
- import { createInterface as createInterface7 } from "readline";
25615
+ import { createInterface as createInterface8 } from "readline";
25115
25616
  import { join as join27 } from "path";
25116
25617
  function divider2() {
25117
25618
  console.log(dim("\u2500".repeat(55)));
@@ -25187,10 +25688,10 @@ async function setup() {
25187
25688
  }
25188
25689
  console.log("");
25189
25690
  for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
25190
- if (!existsSync47(dir)) mkdirSync15(dir, { recursive: true });
25691
+ if (!existsSync48(dir)) mkdirSync15(dir, { recursive: true });
25191
25692
  }
25192
25693
  const env = {};
25193
- const envSource = existsSync47(ENV_PATH) ? ENV_PATH : existsSync47(".env") ? ".env" : null;
25694
+ const envSource = existsSync48(ENV_PATH) ? ENV_PATH : existsSync48(".env") ? ".env" : null;
25194
25695
  if (envSource) {
25195
25696
  console.log(yellow(` Found existing config at ${envSource} \u2014 your values will be preserved`));
25196
25697
  console.log(yellow(" unless you enter new ones. Just press Enter to keep existing values.\n"));
@@ -25201,7 +25702,7 @@ async function setup() {
25201
25702
  }
25202
25703
  }
25203
25704
  const cwdDb = join27(process.cwd(), "cc-claw.db");
25204
- if (existsSync47(cwdDb) && !existsSync47(DB_PATH)) {
25705
+ if (existsSync48(cwdDb) && !existsSync48(DB_PATH)) {
25205
25706
  const { size } = statSync9(cwdDb);
25206
25707
  console.log(yellow(` Found existing database at ${cwdDb} (${(size / 1024).toFixed(0)}KB)`));
25207
25708
  const migrate = await confirm("Copy database to ~/.cc-claw/? (preserves memories & history)", true);
@@ -25474,7 +25975,7 @@ var init_setup = __esm({
25474
25975
  "src/setup.ts"() {
25475
25976
  "use strict";
25476
25977
  init_paths();
25477
- rl = createInterface7({ input: process.stdin, output: process.stdout });
25978
+ rl = createInterface8({ input: process.stdin, output: process.stdout });
25478
25979
  ask = (q) => new Promise((resolve) => rl.question(q, resolve));
25479
25980
  bold = (s) => `\x1B[1m${s}\x1B[0m`;
25480
25981
  green = (s) => `\x1B[32m${s}\x1B[0m`;
@@ -25576,6 +26077,39 @@ gemini.command("rotation [mode]").description("Get or set rotation mode (off, al
25576
26077
  const { geminiRotation: geminiRotation2 } = await Promise.resolve().then(() => (init_gemini2(), gemini_exports));
25577
26078
  await geminiRotation2(program.opts(), mode);
25578
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");
25579
26113
  var backend = program.command("backend").description("Manage AI backend");
25580
26114
  backend.command("list").description("Available backends with status").action(async () => {
25581
26115
  const { backendList: backendList2 } = await Promise.resolve().then(() => (init_backend(), backend_exports));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-claw",
3
- "version": "0.15.2",
3
+ "version": "0.16.0",
4
4
  "description": "CC-Claw: Personal AI assistant on Telegram — multi-backend (Claude, Gemini, Codex, Cursor), sub-agent orchestration, MCP management",
5
5
  "type": "module",
6
6
  "main": "dist/cli.js",