zidane 7.1.3 → 7.1.5

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 (99) hide show
  1. package/dist/{acp-B5UfEhMd.js → acp-DbYGzaVK.js} +2 -2
  2. package/dist/{acp-B5UfEhMd.js.map → acp-DbYGzaVK.js.map} +1 -1
  3. package/dist/acp-cli.js +4 -4
  4. package/dist/acp.d.ts +1 -1
  5. package/dist/acp.js +1 -1
  6. package/dist/{agent-_xxElOgH.js → agent-BlGt76qk.js} +4 -53
  7. package/dist/agent-BlGt76qk.js.map +1 -0
  8. package/dist/agent.d.ts +1 -1
  9. package/dist/agent.js +1 -1
  10. package/dist/{anthropic-DPPs3wjJ.js → anthropic-BQdAnY-w.js} +2 -2
  11. package/dist/{anthropic-DPPs3wjJ.js.map → anthropic-BQdAnY-w.js.map} +1 -1
  12. package/dist/{approvals-u2T19Dc-.js → approvals-BznYVVGD.js} +137 -42
  13. package/dist/{approvals-u2T19Dc-.js.map → approvals-BznYVVGD.js.map} +1 -1
  14. package/dist/{auth-HRKkOErn.js → auth-DvMdkpGD.js} +245 -82
  15. package/dist/{auth-HRKkOErn.js.map → auth-DvMdkpGD.js.map} +1 -1
  16. package/dist/chat/pure.d.ts +4 -4
  17. package/dist/chat/pure.js +3 -3
  18. package/dist/chat.d.ts +6 -6
  19. package/dist/chat.js +6 -6
  20. package/dist/contexts/daytona.d.ts +1 -1
  21. package/dist/contexts/e2b.d.ts +1 -1
  22. package/dist/{context-segments-BrEsRhA0.js → cred-keys-BbbBr4q3.js} +104 -2
  23. package/dist/cred-keys-BbbBr4q3.js.map +1 -0
  24. package/dist/daemon-cli.js +2 -1
  25. package/dist/daemon-cli.js.map +1 -1
  26. package/dist/eval.d.ts +1 -1
  27. package/dist/extensions.d.ts +1 -1
  28. package/dist/extensions.js +1 -1
  29. package/dist/headless.d.ts +1 -1
  30. package/dist/headless.js +1 -1
  31. package/dist/{index-D3TTaaQ5.d.ts → index-D9ntsW7o.d.ts} +20 -198
  32. package/dist/index-D9ntsW7o.d.ts.map +1 -0
  33. package/dist/{index-DZhrTn-v.d.ts → index-Dw8ruU-j.d.ts} +37 -9
  34. package/dist/index-Dw8ruU-j.d.ts.map +1 -0
  35. package/dist/index.d.ts +1 -1
  36. package/dist/index.js +4 -4
  37. package/dist/{ipc-ChQeueur.js → ipc-CNrpBs9P.js} +2 -2
  38. package/dist/{ipc-ChQeueur.js.map → ipc-CNrpBs9P.js.map} +1 -1
  39. package/dist/ipc.d.ts +28 -6
  40. package/dist/ipc.d.ts.map +1 -1
  41. package/dist/ipc.js +4 -4
  42. package/dist/mcp.d.ts +1 -1
  43. package/dist/{oauth-B6F43fti.js → oauth-DxHO17JE.js} +10 -8
  44. package/dist/{oauth-B6F43fti.js.map → oauth-DxHO17JE.js.map} +1 -1
  45. package/dist/output/stream-json.d.ts +1 -1
  46. package/dist/output/terminal.d.ts +1 -1
  47. package/dist/plugins.d.ts +1 -1
  48. package/dist/presets.d.ts +1 -1
  49. package/dist/presets.js +1 -1
  50. package/dist/providers/anthropic.d.ts +1 -1
  51. package/dist/providers/anthropic.js +1 -1
  52. package/dist/providers/arcee.d.ts +1 -1
  53. package/dist/providers/baseten.d.ts +1 -1
  54. package/dist/providers/cerebras.d.ts +1 -1
  55. package/dist/providers/local.d.ts +1 -1
  56. package/dist/providers/openai-compat.d.ts +1 -1
  57. package/dist/providers/openai.d.ts +1 -1
  58. package/dist/providers/openai.js +1 -1
  59. package/dist/providers/openrouter.d.ts +1 -1
  60. package/dist/providers/xai.d.ts +1 -1
  61. package/dist/providers/xai.js +1 -1
  62. package/dist/{providers-DP9kwXYo.js → providers-BVhnFyiY.js} +2 -2
  63. package/dist/{providers-DP9kwXYo.js.map → providers-BVhnFyiY.js.map} +1 -1
  64. package/dist/providers.d.ts +1 -1
  65. package/dist/providers.js +3 -3
  66. package/dist/restate.d.ts +1 -1
  67. package/dist/restate.js +1 -1
  68. package/dist/session/sqlite.d.ts +1 -1
  69. package/dist/session.d.ts +1 -1
  70. package/dist/{server-CTUpOdh3.js → shell-path-3tZ2lyQ2.js} +95 -9
  71. package/dist/shell-path-3tZ2lyQ2.js.map +1 -0
  72. package/dist/skills.d.ts +1 -1
  73. package/dist/{tool-formatters-C5s88MUd.d.ts → tool-formatters-CJoSmRjH.d.ts} +83 -3
  74. package/dist/tool-formatters-CJoSmRjH.d.ts.map +1 -0
  75. package/dist/tools/fetch-url.d.ts +1 -1
  76. package/dist/tools/web-search.d.ts +1 -1
  77. package/dist/tools.d.ts +1 -1
  78. package/dist/tools.js +1 -1
  79. package/dist/{transcript-anchors-DxofXw_y.d.ts → transcript-anchors-nWzUc3WT.d.ts} +201 -3
  80. package/dist/transcript-anchors-nWzUc3WT.d.ts.map +1 -0
  81. package/dist/tui.d.ts +20 -6
  82. package/dist/tui.d.ts.map +1 -1
  83. package/dist/tui.js +388 -58
  84. package/dist/tui.js.map +1 -1
  85. package/dist/{turn-operations-BaQnxzhr.d.ts → turn-operations-GRw5vbtr.d.ts} +34 -4
  86. package/dist/{turn-operations-BaQnxzhr.d.ts.map → turn-operations-GRw5vbtr.d.ts.map} +1 -1
  87. package/dist/{turn-operations-6JDu2ewy.js → turn-operations-JynC5ODZ.js} +31 -3
  88. package/dist/{turn-operations-6JDu2ewy.js.map → turn-operations-JynC5ODZ.js.map} +1 -1
  89. package/dist/types.d.ts +1 -1
  90. package/docs/CHAT.md +10 -0
  91. package/docs/TUI.md +1 -1
  92. package/package.json +1 -1
  93. package/dist/agent-_xxElOgH.js.map +0 -1
  94. package/dist/context-segments-BrEsRhA0.js.map +0 -1
  95. package/dist/index-D3TTaaQ5.d.ts.map +0 -1
  96. package/dist/index-DZhrTn-v.d.ts.map +0 -1
  97. package/dist/server-CTUpOdh3.js.map +0 -1
  98. package/dist/tool-formatters-C5s88MUd.d.ts.map +0 -1
  99. package/dist/transcript-anchors-DxofXw_y.d.ts.map +0 -1
@@ -1,14 +1,14 @@
1
1
  import { A as mergeCatalogEntry, D as listModelOverlay, O as listModels, k as lookupModel } from "./openai-compat-Dy56weK8.js";
2
- import { gn as isReservedCredKey, hn as alternateCredKey, mn as ALTERNATE_CRED_KEY_SUFFIX } from "./agent-_xxElOgH.js";
2
+ import { c as isReservedCredKey, l as nextAccountCredKey, n as ALTERNATE_CRED_KEY_SUFFIX, o as alternateCredKey, s as isAccountCredKey, t as ACCOUNT_CRED_KEY_INFIX, u as oauthAccountLabel } from "./cred-keys-BbbBr4q3.js";
3
3
  import { t as writeFileAtomic } from "./atomic-write-B7zr1ddF.js";
4
- import { _ as FAST_MODE_OPTIONS, g as ANTHROPIC_EXTRA_MODELS, r as anthropic } from "./anthropic-DPPs3wjJ.js";
5
- import { c as withCredentialsLock, h as registerOAuthProvider, m as refreshOpenAICodexToken, p as refreshAnthropicToken } from "./oauth-B6F43fti.js";
4
+ import { _ as FAST_MODE_OPTIONS, g as ANTHROPIC_EXTRA_MODELS, r as anthropic } from "./anthropic-BQdAnY-w.js";
5
+ import { c as withCredentialsLock, h as registerOAuthProvider, m as refreshOpenAICodexToken, p as refreshAnthropicToken } from "./oauth-DxHO17JE.js";
6
6
  import { arcee } from "./providers/arcee.js";
7
7
  import { baseten } from "./providers/baseten.js";
8
8
  import { cerebras } from "./providers/cerebras.js";
9
9
  import { t as generatePkce } from "./pkce-t8BcPyEi.js";
10
10
  import { n as createCursorOAuthProvider } from "./cursor-iojRXHF9.js";
11
- import { n as zai, r as mistral } from "./providers-DP9kwXYo.js";
11
+ import { n as zai, r as mistral } from "./providers-BVhnFyiY.js";
12
12
  import { local } from "./providers/local.js";
13
13
  import { openai } from "./providers/openai.js";
14
14
  import { openrouter } from "./providers/openrouter.js";
@@ -1437,16 +1437,16 @@ function normalizeCredentials(parsed) {
1437
1437
  return result;
1438
1438
  }
1439
1439
  /**
1440
- * Canonical file key for a descriptor, rejecting the reserved alternate suffix.
1440
+ * Canonical file key for a descriptor, rejecting the reserved slot separator.
1441
1441
  *
1442
1442
  * Loud on a misconfigured provider instead of quietly mixing its credentials
1443
- * into another provider's alternate slot (extension registration refuses the
1444
- * suffix upfront; this covers descriptors passed in directly). Read paths stay
1445
- * tolerant — only the functions that can WRITE a pair go through here.
1443
+ * into another provider's slot (extension registration refuses the separator
1444
+ * upfront; this covers descriptors passed in directly). Read paths stay
1445
+ * tolerant — only the functions that WRITE slots go through here.
1446
1446
  */
1447
1447
  function assertableCredKey(descriptor) {
1448
1448
  const fileKey = credKeyOf(descriptor);
1449
- if (isReservedCredKey(fileKey)) throw new Error(`Provider "${descriptor.key}" uses credential key "${fileKey}", but the "${ALTERNATE_CRED_KEY_SUFFIX}" suffix is reserved for a provider's second credential slot.`);
1449
+ if (isReservedCredKey(fileKey)) throw new Error(`Provider "${descriptor.key}" uses credential key "${fileKey}", but "#" is reserved for a provider's extra credential slots (\`${ALTERNATE_CRED_KEY_SUFFIX}\`, \`${ACCOUNT_CRED_KEY_INFIX}N\`).`);
1450
1450
  return fileKey;
1451
1451
  }
1452
1452
  /** Read a single provider's credential (translating via the descriptor). */
@@ -1456,6 +1456,9 @@ function readProviderCredential(dataDir, descriptor) {
1456
1456
  /**
1457
1457
  * Both stored credentials for a provider: `active` is the one every reader
1458
1458
  * resolves, `alternate` is the stored-but-not-preferred one (if any).
1459
+ *
1460
+ * Predates multi-account and only sees the `#alt` slot; use
1461
+ * {@link readProviderCredentials} to list every stored account.
1459
1462
  */
1460
1463
  function readProviderCredentialPair(dataDir, descriptor) {
1461
1464
  const all = readCredentials(dataDir);
@@ -1466,6 +1469,40 @@ function readProviderCredentialPair(dataDir, descriptor) {
1466
1469
  };
1467
1470
  }
1468
1471
  /**
1472
+ * Every file key holding one of `fileKey`'s credentials, in display order:
1473
+ * canonical, `#alt`, then `#account:N` ascending. Only keys present in `all`.
1474
+ */
1475
+ function slotKeysOf(all, fileKey) {
1476
+ const altKey = alternateCredKey(fileKey);
1477
+ const accounts = Object.keys(all).filter((key) => isAccountCredKey(fileKey, key)).sort((a, b) => Number(a.slice(a.lastIndexOf(":") + 1)) - Number(b.slice(b.lastIndexOf(":") + 1)));
1478
+ return [
1479
+ ...fileKey in all ? [fileKey] : [],
1480
+ ...altKey in all ? [altKey] : [],
1481
+ ...accounts
1482
+ ];
1483
+ }
1484
+ function isSlotOf(fileKey, key) {
1485
+ return key === fileKey || key === alternateCredKey(fileKey) || isAccountCredKey(fileKey, key);
1486
+ }
1487
+ /**
1488
+ * Every stored credential of a provider, active first.
1489
+ *
1490
+ * Tolerant of any kind in any slot: `#alt` is meant for the API key and
1491
+ * `#account:N` for OAuth accounts, but a file written by an older build (which
1492
+ * parked the OAuth alternate in `#alt`) must still list everything it holds.
1493
+ */
1494
+ function readProviderCredentials(dataDir, descriptor) {
1495
+ return storedCredentialsOf(readCredentials(dataDir), credKeyOf(descriptor));
1496
+ }
1497
+ /** Pure form of {@link readProviderCredentials} over an already-read file. */
1498
+ function storedCredentialsOf(all, fileKey) {
1499
+ return slotKeysOf(all, fileKey).map((key) => ({
1500
+ key,
1501
+ credential: all[key],
1502
+ active: key === fileKey
1503
+ }));
1504
+ }
1505
+ /**
1469
1506
  * Write credentials atomically (write-then-rename) with mode 0o600.
1470
1507
  *
1471
1508
  * Atomic on the same filesystem — readers either see the previous file or the
@@ -1482,76 +1519,196 @@ function writeCredentialsUnlocked(dataDir, creds) {
1482
1519
  });
1483
1520
  }
1484
1521
  /**
1485
- * Store a credential as the provider's preferred one.
1486
- *
1487
- * A credential of the OTHER kind already in the canonical slot is demoted to
1488
- * {@link alternateCredKey}, not destroyed: authenticating with OAuth used to
1489
- * silently delete a working API key (and vice versa), leaving the user to
1490
- * re-enter it. Replacing a credential of the SAME kind is a plain overwrite —
1491
- * that's a re-auth, not a second source.
1492
- *
1493
- * The pair holds AT MOST ONE credential of each kind. A same-kind alternate is
1494
- * therefore stale — no code path here can produce one, but a file written by an
1495
- * older build can carry it, and it would surface as two identical source rows
1496
- * that "switch" between each other. Dropping it on the next write self-heals.
1522
+ * Run `fn` against the on-disk file under the mutation lock and persist what it
1523
+ * returns. Migrates the legacy file first (migration takes the same lock).
1497
1524
  */
1498
- function setProviderCredential(dataDir, descriptor, cred) {
1525
+ function mutateCredentials(dataDir, fn) {
1499
1526
  readCredentials(dataDir);
1500
1527
  return withCredentialsLock(credentialsPath(dataDir), () => {
1501
1528
  const all = readStoredCredentials(credentialsPath(dataDir));
1529
+ const { result, write } = fn(all);
1530
+ if (write) writeCredentialsUnlocked(dataDir, all);
1531
+ return result;
1532
+ });
1533
+ }
1534
+ /**
1535
+ * Move an OAuth grant out of `#alt` into an account slot.
1536
+ *
1537
+ * Before multi-account, `#alt` held whichever kind was not active — so a file
1538
+ * from that era can have an OAuth grant there. `#alt` is now the API key's
1539
+ * slot, and every writer below relies on that; relocating first means the
1540
+ * grant is preserved instead of overwritten when an API key gets demoted.
1541
+ */
1542
+ function relocateLegacyOAuthAlternate(all, fileKey) {
1543
+ const altKey = alternateCredKey(fileKey);
1544
+ const alt = all[altKey];
1545
+ if (alt?.kind !== "oauth") return;
1546
+ delete all[altKey];
1547
+ all[nextAccountCredKey(fileKey, Object.keys(all))] = alt;
1548
+ }
1549
+ /**
1550
+ * Park a credential that just lost the canonical slot.
1551
+ *
1552
+ * API keys go to `#alt` (there is at most one, so the slot is free once
1553
+ * `relocateLegacyOAuthAlternate` has run). OAuth grants reuse the slot the
1554
+ * promoted credential vacated when that was an account slot — a swap, no new
1555
+ * numbering — and otherwise take the next free `#account:N`.
1556
+ */
1557
+ function parkDemoted(all, fileKey, cred, vacated) {
1558
+ if (cred.kind === "apikey") {
1559
+ all[alternateCredKey(fileKey)] = cred;
1560
+ return;
1561
+ }
1562
+ if (vacated && isAccountCredKey(fileKey, vacated)) {
1563
+ all[vacated] = cred;
1564
+ return;
1565
+ }
1566
+ all[nextAccountCredKey(fileKey, Object.keys(all))] = cred;
1567
+ }
1568
+ /**
1569
+ * Store a credential as the provider's preferred one.
1570
+ *
1571
+ * The previous active credential is demoted, not destroyed: authenticating
1572
+ * with OAuth used to silently delete a working API key (and vice versa), and a
1573
+ * second OAuth login used to overwrite the first account. An API key moves to
1574
+ * {@link alternateCredKey}; an OAuth grant moves to the next free account slot.
1575
+ * Replacing an API key with an API key is a plain overwrite — there is only
1576
+ * ever one — and so is an OAuth login that names its predecessor via
1577
+ * `replaceKey`.
1578
+ */
1579
+ function setProviderCredential(dataDir, descriptor, cred, opts = {}) {
1580
+ mutateCredentials(dataDir, (all) => {
1502
1581
  const fileKey = assertableCredKey(descriptor);
1503
- const altKey = alternateCredKey(fileKey);
1582
+ relocateLegacyOAuthAlternate(all, fileKey);
1583
+ if (opts.replaceKey !== void 0) {
1584
+ if (!isSlotOf(fileKey, opts.replaceKey)) throw new Error(`"${opts.replaceKey}" is not a credential slot of provider "${descriptor.key}"`);
1585
+ if (opts.replaceKey in all) {
1586
+ all[opts.replaceKey] = cred;
1587
+ return {
1588
+ result: void 0,
1589
+ write: true
1590
+ };
1591
+ }
1592
+ }
1504
1593
  const previous = all[fileKey];
1505
- if (previous && previous.kind !== cred.kind) all[altKey] = previous;
1506
- else if (all[altKey]?.kind === cred.kind) delete all[altKey];
1594
+ if (previous && !(previous.kind === "apikey" && cred.kind === "apikey")) parkDemoted(all, fileKey, previous);
1595
+ else if (cred.kind === "apikey") delete all[alternateCredKey(fileKey)];
1507
1596
  all[fileKey] = cred;
1508
- writeCredentialsUnlocked(dataDir, all);
1597
+ return {
1598
+ result: void 0,
1599
+ write: true
1600
+ };
1509
1601
  });
1510
1602
  }
1511
1603
  /**
1512
- * Make the provider's stored `source` credential the preferred one.
1604
+ * Make one of the provider's stored credentials the preferred one.
1513
1605
  *
1514
- * Only promotes when a credential of that kind is sitting in the alternate
1515
- * slot; calling it for the already-active source is harmless. Returns which of
1516
- * those happened so a caller cannot report a swap that provably did not occur
1517
- * — the write is silent either way, and a success-shaped `void` was a trap for
1518
- * any caller that trusted it instead of refetching.
1606
+ * Swaps the target into the canonical slot and parks the previous active one
1607
+ * (see {@link parkDemoted}). Returns which of the three outcomes happened so a
1608
+ * caller cannot report a swap that provably did not occur — the write is
1609
+ * silent either way, and a success-shaped `void` was a trap for any caller that
1610
+ * trusted it instead of refetching.
1519
1611
  */
1520
- function setPreferredCredential(dataDir, descriptor, source) {
1521
- readCredentials(dataDir);
1522
- return withCredentialsLock(credentialsPath(dataDir), () => {
1523
- const all = readStoredCredentials(credentialsPath(dataDir));
1612
+ function setPreferredCredential(dataDir, descriptor, target) {
1613
+ return mutateCredentials(dataDir, (all) => {
1524
1614
  const fileKey = assertableCredKey(descriptor);
1525
- const altKey = alternateCredKey(fileKey);
1526
- const alternate = all[altKey];
1527
- if (!alternate || alternate.kind !== source) return all[fileKey]?.kind === source ? "already-active" : "not-stored";
1615
+ relocateLegacyOAuthAlternate(all, fileKey);
1528
1616
  const active = all[fileKey];
1529
- all[fileKey] = alternate;
1530
- if (active) all[altKey] = active;
1531
- else delete all[altKey];
1532
- writeCredentialsUnlocked(dataDir, all);
1533
- return "promoted";
1617
+ let key;
1618
+ if (typeof target === "string") {
1619
+ if (active?.kind === target) return {
1620
+ result: "already-active",
1621
+ write: false
1622
+ };
1623
+ key = slotKeysOf(all, fileKey).find((k) => k !== fileKey && all[k]?.kind === target);
1624
+ } else {
1625
+ if (target.key === fileKey && active) return {
1626
+ result: "already-active",
1627
+ write: false
1628
+ };
1629
+ key = isSlotOf(fileKey, target.key) && target.key in all ? target.key : void 0;
1630
+ }
1631
+ if (key === void 0) return {
1632
+ result: "not-stored",
1633
+ write: false
1634
+ };
1635
+ const promoted = all[key];
1636
+ delete all[key];
1637
+ all[fileKey] = promoted;
1638
+ if (active) parkDemoted(all, fileKey, active, key);
1639
+ return {
1640
+ result: "promoted",
1641
+ write: true
1642
+ };
1643
+ });
1644
+ }
1645
+ /**
1646
+ * Drop ONE stored credential. Removing the active one promotes a survivor —
1647
+ * another credential of the same kind when there is one (a second OAuth
1648
+ * account), else whatever is left — so the provider does not go dark while it
1649
+ * still holds a working credential. Returns false when `key` was not stored.
1650
+ */
1651
+ function removeStoredCredential(dataDir, descriptor, key) {
1652
+ return mutateCredentials(dataDir, (all) => {
1653
+ const fileKey = credKeyOf(descriptor);
1654
+ if (!isSlotOf(fileKey, key) || !(key in all)) return {
1655
+ result: false,
1656
+ write: false
1657
+ };
1658
+ const removed = all[key];
1659
+ delete all[key];
1660
+ if (key === fileKey) {
1661
+ const rest = slotKeysOf(all, fileKey);
1662
+ const successor = rest.find((k) => all[k]?.kind === removed.kind) ?? rest[0];
1663
+ if (successor !== void 0) {
1664
+ all[fileKey] = all[successor];
1665
+ delete all[successor];
1666
+ }
1667
+ }
1668
+ return {
1669
+ result: true,
1670
+ write: true
1671
+ };
1534
1672
  });
1535
1673
  }
1536
1674
  /**
1537
- * Sign a provider out — drops BOTH stored credentials.
1675
+ * Name a stored OAuth account. An empty label drops the field, which reads
1676
+ * back as {@link DEFAULT_OAUTH_ACCOUNT_LABEL}. Returns false when `key` holds
1677
+ * no OAuth credential.
1678
+ */
1679
+ function setCredentialLabel(dataDir, descriptor, key, label) {
1680
+ return mutateCredentials(dataDir, (all) => {
1681
+ const entry = isSlotOf(credKeyOf(descriptor), key) ? all[key] : void 0;
1682
+ if (entry?.kind !== "oauth") return {
1683
+ result: false,
1684
+ write: false
1685
+ };
1686
+ const trimmed = label.trim();
1687
+ if (trimmed) entry.label = trimmed;
1688
+ else delete entry.label;
1689
+ return {
1690
+ result: true,
1691
+ write: true
1692
+ };
1693
+ });
1694
+ }
1695
+ /**
1696
+ * Sign a provider out — drops EVERY stored credential.
1538
1697
  *
1539
1698
  * "Signed out" has to mean the provider resolves nothing afterwards, which is
1540
- * what this has always guaranteed and what callers named it for; promoting the
1541
- * alternate instead would silently leave the provider authenticated through the
1542
- * other source. Callers that want the fall-back behavior can read the pair
1543
- * first ({@link readProviderCredentialPair}) and re-store the survivor.
1699
+ * what this has always guaranteed and what callers named it for; promoting a
1700
+ * survivor instead would silently leave the provider authenticated through
1701
+ * another source. Callers that want that behavior use
1702
+ * {@link removeStoredCredential} on the one slot they mean.
1544
1703
  */
1545
1704
  function removeProviderCredential(dataDir, descriptor) {
1546
- readCredentials(dataDir);
1547
- return withCredentialsLock(credentialsPath(dataDir), () => {
1548
- const all = readStoredCredentials(credentialsPath(dataDir));
1549
- const fileKey = credKeyOf(descriptor);
1550
- const altKey = alternateCredKey(fileKey);
1551
- if (!(fileKey in all) && !(altKey in all)) return;
1552
- delete all[fileKey];
1553
- delete all[altKey];
1554
- writeCredentialsUnlocked(dataDir, all);
1705
+ mutateCredentials(dataDir, (all) => {
1706
+ const keys = slotKeysOf(all, credKeyOf(descriptor));
1707
+ for (const key of keys) delete all[key];
1708
+ return {
1709
+ result: void 0,
1710
+ write: keys.length > 0
1711
+ };
1555
1712
  });
1556
1713
  }
1557
1714
  /**
@@ -1689,13 +1846,14 @@ function isOAuthLegacy(value) {
1689
1846
  *
1690
1847
  * - `kind: 'apikey'` from `credentials.json` (injected into env at TUI launch)
1691
1848
  * - explicit env var (descriptor's `envKey`)
1692
- * - `kind: 'oauth'` from `credentials.json` (or legacy `cwd/.credentials.json`)
1849
+ * - `kind: 'oauth'` from `credentials.json` (or legacy `cwd/.credentials.json`),
1850
+ * one per stored account
1693
1851
  *
1694
- * A provider may store one of EACH kind. The preferred one lives in the
1695
- * canonical file key and is flagged {@link AuthMethod.active}; the other sits
1696
- * in `alternateCredKey` and is reported too, so the UI can offer to promote it.
1697
- * Order within `methods` is presentational — it is no longer a resolution
1698
- * order, because the active flag answers that directly.
1852
+ * The preferred credential lives in the canonical file key and is flagged
1853
+ * {@link AuthMethod.active}; the others sit in sibling slots and are reported
1854
+ * too, keyed by {@link AuthMethod.key}, so the UI can offer to promote or
1855
+ * remove them. Order within `methods` is presentational — active first — not a
1856
+ * resolution order, because the active flag answers that directly.
1699
1857
  *
1700
1858
  * Pure read — never refreshes or rewrites the credentials file.
1701
1859
  */
@@ -1703,23 +1861,30 @@ function detectAuth(dataDir, registry, env = process.env) {
1703
1861
  const creds = readCredentials(dataDir);
1704
1862
  return Object.values(registry).map((descriptor) => {
1705
1863
  const methods = [];
1706
- const fileKey = credKeyOf(descriptor);
1707
- const fileEntry = creds[fileKey];
1708
- const altEntry = creds[alternateCredKey(fileKey)];
1709
- const describeStored = (entry, active) => {
1710
- if (entry?.kind === "apikey" && entry.value) return {
1864
+ const stored = storedCredentialsOf(creds, credKeyOf(descriptor));
1865
+ const fileEntry = stored.find((s) => s.active)?.credential;
1866
+ const describeStored = (key, entry, active) => {
1867
+ if (entry.kind === "apikey" && entry.value) return {
1711
1868
  source: "apikey",
1712
1869
  detail: "credentials.json",
1713
- active
1714
- };
1715
- if (entry?.kind === "oauth" && entry.access) return {
1716
- source: "oauth",
1717
- detail: typeof entry.expires === "number" ? `oauth · expires ${new Date(entry.expires).toLocaleString()}` : "oauth · credentials.json",
1718
- active
1870
+ active,
1871
+ key
1719
1872
  };
1873
+ if (entry.kind === "oauth" && entry.access) {
1874
+ const label = oauthAccountLabel(entry);
1875
+ return {
1876
+ source: "oauth",
1877
+ detail: `${label} · ${typeof entry.expires === "number" ? `expires ${new Date(entry.expires).toLocaleString()}` : "credentials.json"}`,
1878
+ active,
1879
+ key,
1880
+ label
1881
+ };
1882
+ }
1720
1883
  };
1721
- const activeMethod = describeStored(fileEntry, true);
1722
- if (activeMethod) methods.push(activeMethod);
1884
+ for (const slot of stored) {
1885
+ const method = describeStored(slot.key, slot.credential, slot.active);
1886
+ if (method) methods.push(method);
1887
+ }
1723
1888
  if (fileEntry?.kind === "apikey" && !fileEntry.value && descriptor.customFields && descriptor.customFields.length > 0) {
1724
1889
  const stored = fileEntry.customFields ?? {};
1725
1890
  if (descriptor.customFields.filter((f) => f.required).every((f) => typeof stored[f.key] === "string" && stored[f.key].length > 0)) methods.push({
@@ -1736,15 +1901,13 @@ function detectAuth(dataDir, registry, env = process.env) {
1736
1901
  active: false
1737
1902
  });
1738
1903
  }
1739
- const alternateMethod = describeStored(altEntry, false);
1740
- if (alternateMethod) methods.push(alternateMethod);
1741
1904
  if (descriptor.envKey && env[descriptor.envKey]) methods.push({
1742
1905
  source: "env",
1743
1906
  detail: descriptor.envKey,
1744
1907
  active: false
1745
1908
  });
1746
1909
  const unique = [];
1747
- for (const method of methods) if (!unique.some((seen) => seen.source === method.source)) unique.push(method);
1910
+ for (const method of methods) if (!unique.some((seen) => method.source === "oauth" ? seen.key !== void 0 && seen.key === method.key : seen.source === method.source)) unique.push(method);
1748
1911
  return {
1749
1912
  key: descriptor.key,
1750
1913
  label: descriptor.label,
@@ -1755,6 +1918,6 @@ function detectAuth(dataDir, registry, env = process.env) {
1755
1918
  });
1756
1919
  }
1757
1920
  //#endregion
1758
- export { openrouterDescriptor as C, renderDefaultCallbackPage as E, openaiDescriptor as S, restoreModelOptions as T, getModelInfo as _, readProviderCredential as a, modelSupportsReasoning as b, setPreferredCredential as c, BUILTIN_PROVIDERS as d, anthropicDescriptor as f, getContextWindow as g, enabledModelOptions as h, readCredentials as i, setProviderCredential as l, credKeyOf as m, applyApiKeyEnv as n, readProviderCredentialPair as o, cerebrasDescriptor as p, credentialsPath as r, removeProviderCredential as s, detectAuth as t, writeCredentials as u, localDescriptor as v, piIdOf as w, modelsForDescriptor as x, modelOptionsFor as y };
1921
+ export { renderDefaultCallbackPage as A, modelOptionsFor as C, openrouterDescriptor as D, openaiDescriptor as E, piIdOf as O, localDescriptor as S, modelsForDescriptor as T, cerebrasDescriptor as _, readProviderCredential as a, getContextWindow as b, removeProviderCredential as c, setPreferredCredential as d, setProviderCredential as f, anthropicDescriptor as g, BUILTIN_PROVIDERS as h, readCredentials as i, restoreModelOptions as k, removeStoredCredential as l, writeCredentials as m, applyApiKeyEnv as n, readProviderCredentialPair as o, storedCredentialsOf as p, credentialsPath as r, readProviderCredentials as s, detectAuth as t, setCredentialLabel as u, credKeyOf as v, modelSupportsReasoning as w, getModelInfo as x, enabledModelOptions as y };
1759
1922
 
1760
- //# sourceMappingURL=auth-HRKkOErn.js.map
1923
+ //# sourceMappingURL=auth-DvMdkpGD.js.map