@mars-sea/dsh-commandcode-provider 0.12.1 → 0.12.2

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/lib/index.js CHANGED
@@ -103,7 +103,7 @@ const PLAN_ORDER = Object.fromEntries(PLAN_TIER_ORDER.map((tier, index) => [tier
103
103
  * subscription-plan labels, deals, and hourly (peak/off-peak) pricing.
104
104
  *
105
105
  * Everything here is synced from official sources — the command-code CLI
106
- * bundle's model table (`dist/cli.mjs`, re-verified at command-code@1.72.1) and
106
+ * bundle's model table (`dist/cli.mjs`, re-verified at command-code@1.73.0) and
107
107
  * the official plan/pricing/model docs; see the dsh-commandcode-upstream skill
108
108
  * for the extraction procedures. Keeping the snapshot in its own module
109
109
  * confines those frequent sync diffs here: src/adapter.ts holds only the stable
@@ -506,7 +506,7 @@ const KNOWN_IMAGE_MODELS = /* @__PURE__ */ new Set([
506
506
  ]);
507
507
  /**
508
508
  * Models WITHOUT a zero-data-retention upstream, per the official CLI's own
509
- * registry (`command-code@1.72.1` `dist/cli.mjs`): `modelSupportsZdr(id)` is
509
+ * registry (`command-code@1.73.0` `dist/cli.mjs`): `modelSupportsZdr(id)` is
510
510
  * exactly `!nonZdrSet.has(canonicalize(id))`, and `knownModelSupportsZdr`
511
511
  * carries the same membership in the sibling route table — the UNION of both
512
512
  * is this set. Reading only the sibling route table would drop `meituan/
@@ -788,7 +788,7 @@ const DEFAULT_MESSAGES_MAX_TOKENS = 64e3;
788
788
  * `/docs/plans/max` and `/docs/resources/pricing-limits`). Each plan's model
789
789
  * list is a superset of the one below it: Go ⊂ GOAT ⊂ Pro ⊂ Provider/Max.
790
790
  * Models absent from every plan list (Claude Opus/Fable, Fugu Ultra) are
791
- * Provider-tier. Re-verified at command-code@1.72.1 (2026-09-30): 86 catalog
791
+ * Provider-tier. Re-verified at command-code@1.73.0 (2026-10-01): 86 catalog
792
792
  * ids at 53/62/76/84 cumulative, a strict superset chain — every release since
793
793
  * 1.49.0 has been additive with no tier move, and per-entry tags below name the
794
794
  * release that added each row.
@@ -916,7 +916,7 @@ function compareByPlan(a, b) {
916
916
  /**
917
917
  * Subscription plan table, synced from the official CLI bundle's plan maps
918
918
  * (located by the `"individual-go"` key in `dist/cli.mjs`, re-verified unchanged
919
- * through command-code@1.72.1): subscription `planId` prefix → display name and
919
+ * through command-code@1.73.0): subscription `planId` prefix → display name and
920
920
  * the plan's monthly credit total. This is the account's own subscription
921
921
  * (from `/alpha/billing/subscriptions`) — distinct from {@link KNOWN_PLANS},
922
922
  * which maps catalog models to their minimum tier.
@@ -1186,16 +1186,19 @@ function capabilityDescription(modelId, contextWindow, now = Date.now()) {
1186
1186
  * rather than against hard-coded numbers, so this table and the subscription
1187
1187
  * table cannot drift apart silently.
1188
1188
  */
1189
- const ALLOWANCE_TIERS = ["goat", "pro"];
1189
+ const ALLOWANCE_TIERS = [
1190
+ "go",
1191
+ "goat",
1192
+ "pro"
1193
+ ];
1190
1194
  /**
1191
1195
  * Which allowance bracket a plan-tier weight belongs to, or undefined when that
1192
1196
  * plan has no per-model allowance.
1193
1197
  *
1194
1198
  * Weights come from `KNOWN_SUBSCRIPTION_PLANS` (go 0 · goat 1 · pro 2 ·
1195
1199
  * provider 3 · max/ultra 4) and {@link PLAN_ORDER} is the same scale, which is
1196
- * what makes the lookup exact: Go, Provider, Max and Ultra have no published
1197
- * allowance, and answering with a neighbouring tier's figure would be a
1198
- * fabricated number rather than a missing one.
1200
+ * what makes the lookup exact: Provider、Max、Ultra
1201
+ * 没有本地额度;缺项时不能用相邻套餐的数字代替。
1199
1202
  */
1200
1203
  function allowanceTierForWeight(tierWeight) {
1201
1204
  if (tierWeight === void 0) return void 0;
@@ -1223,6 +1226,7 @@ const MODEL_PRICE_ROWS = [
1223
1226
  12.5
1224
1227
  ],
1225
1228
  allowance: {
1229
+ go: 6,
1226
1230
  goat: 20,
1227
1231
  pro: 20
1228
1232
  }
@@ -1236,6 +1240,7 @@ const MODEL_PRICE_ROWS = [
1236
1240
  12.5
1237
1241
  ],
1238
1242
  allowance: {
1243
+ go: 6,
1239
1244
  goat: 20,
1240
1245
  pro: 20
1241
1246
  }
@@ -1249,6 +1254,7 @@ const MODEL_PRICE_ROWS = [
1249
1254
  1.25
1250
1255
  ],
1251
1256
  allowance: {
1257
+ go: 6,
1252
1258
  goat: 20,
1253
1259
  pro: 20
1254
1260
  }
@@ -1262,6 +1268,7 @@ const MODEL_PRICE_ROWS = [
1262
1268
  6.25
1263
1269
  ],
1264
1270
  allowance: {
1271
+ go: 6,
1265
1272
  goat: 20,
1266
1273
  pro: 20
1267
1274
  }
@@ -1275,6 +1282,7 @@ const MODEL_PRICE_ROWS = [
1275
1282
  6.25
1276
1283
  ],
1277
1284
  allowance: {
1285
+ go: 6,
1278
1286
  goat: 20,
1279
1287
  pro: 20
1280
1288
  }
@@ -1288,6 +1296,7 @@ const MODEL_PRICE_ROWS = [
1288
1296
  6.25
1289
1297
  ],
1290
1298
  allowance: {
1299
+ go: 6,
1291
1300
  goat: 20,
1292
1301
  pro: 20
1293
1302
  }
@@ -1301,6 +1310,7 @@ const MODEL_PRICE_ROWS = [
1301
1310
  6.25
1302
1311
  ],
1303
1312
  allowance: {
1313
+ go: 6,
1304
1314
  goat: 20,
1305
1315
  pro: 20
1306
1316
  }
@@ -1314,6 +1324,7 @@ const MODEL_PRICE_ROWS = [
1314
1324
  5
1315
1325
  ],
1316
1326
  allowance: {
1327
+ go: 6,
1317
1328
  goat: 20,
1318
1329
  pro: 20
1319
1330
  }
@@ -1327,6 +1338,7 @@ const MODEL_PRICE_ROWS = [
1327
1338
  3.75
1328
1339
  ],
1329
1340
  allowance: {
1341
+ go: 6,
1330
1342
  goat: 20,
1331
1343
  pro: 20
1332
1344
  }
@@ -1340,6 +1352,7 @@ const MODEL_PRICE_ROWS = [
1340
1352
  2.5
1341
1353
  ],
1342
1354
  allowance: {
1355
+ go: 6,
1343
1356
  goat: 20,
1344
1357
  pro: 20
1345
1358
  }
@@ -1353,6 +1366,7 @@ const MODEL_PRICE_ROWS = [
1353
1366
  2.5
1354
1367
  ],
1355
1368
  allowance: {
1369
+ go: 6,
1356
1370
  goat: 10,
1357
1371
  pro: 20
1358
1372
  }
@@ -1370,6 +1384,7 @@ const MODEL_PRICE_ROWS = [
1370
1384
  .006
1371
1385
  ],
1372
1386
  allowance: {
1387
+ go: 6,
1373
1388
  goat: 60,
1374
1389
  pro: 70
1375
1390
  }
@@ -1382,6 +1397,7 @@ const MODEL_PRICE_ROWS = [
1382
1397
  .07
1383
1398
  ],
1384
1399
  allowance: {
1400
+ go: 8,
1385
1401
  goat: 20,
1386
1402
  pro: 30
1387
1403
  }
@@ -1399,6 +1415,7 @@ const MODEL_PRICE_ROWS = [
1399
1415
  .006
1400
1416
  ],
1401
1417
  allowance: {
1418
+ go: 6,
1402
1419
  goat: 20,
1403
1420
  pro: 30
1404
1421
  }
@@ -1416,6 +1433,7 @@ const MODEL_PRICE_ROWS = [
1416
1433
  .044
1417
1434
  ],
1418
1435
  allowance: {
1436
+ go: 6,
1419
1437
  goat: 20,
1420
1438
  pro: 30
1421
1439
  }
@@ -1433,6 +1451,7 @@ const MODEL_PRICE_ROWS = [
1433
1451
  .006
1434
1452
  ],
1435
1453
  allowance: {
1454
+ go: 10,
1436
1455
  goat: 60,
1437
1456
  pro: 70
1438
1457
  }
@@ -1450,6 +1469,7 @@ const MODEL_PRICE_ROWS = [
1450
1469
  .032
1451
1470
  ],
1452
1471
  allowance: {
1472
+ go: 6,
1453
1473
  goat: 60,
1454
1474
  pro: 70
1455
1475
  }
@@ -1462,6 +1482,7 @@ const MODEL_PRICE_ROWS = [
1462
1482
  .5
1463
1483
  ],
1464
1484
  allowance: {
1485
+ go: 6,
1465
1486
  goat: 20,
1466
1487
  pro: 20
1467
1488
  }
@@ -1474,6 +1495,7 @@ const MODEL_PRICE_ROWS = [
1474
1495
  .03
1475
1496
  ],
1476
1497
  allowance: {
1498
+ go: 6,
1477
1499
  goat: 20,
1478
1500
  pro: 20
1479
1501
  }
@@ -1486,6 +1508,7 @@ const MODEL_PRICE_ROWS = [
1486
1508
  .15
1487
1509
  ],
1488
1510
  allowance: {
1511
+ go: 6,
1489
1512
  goat: 20,
1490
1513
  pro: 20
1491
1514
  }
@@ -1498,6 +1521,7 @@ const MODEL_PRICE_ROWS = [
1498
1521
  .03
1499
1522
  ],
1500
1523
  allowance: {
1524
+ go: 6,
1501
1525
  goat: 20,
1502
1526
  pro: 20
1503
1527
  }
@@ -1510,6 +1534,7 @@ const MODEL_PRICE_ROWS = [
1510
1534
  .15
1511
1535
  ],
1512
1536
  allowance: {
1537
+ go: 6,
1513
1538
  goat: 20,
1514
1539
  pro: 20
1515
1540
  }
@@ -1523,6 +1548,7 @@ const MODEL_PRICE_ROWS = [
1523
1548
  .08334
1524
1549
  ],
1525
1550
  allowance: {
1551
+ go: 6,
1526
1552
  goat: 40,
1527
1553
  pro: 50
1528
1554
  }
@@ -1535,6 +1561,7 @@ const MODEL_PRICE_ROWS = [
1535
1561
  .15
1536
1562
  ],
1537
1563
  allowance: {
1564
+ go: 6,
1538
1565
  goat: 40,
1539
1566
  pro: 50
1540
1567
  }
@@ -1547,6 +1574,7 @@ const MODEL_PRICE_ROWS = [
1547
1574
  .2
1548
1575
  ],
1549
1576
  allowance: {
1577
+ go: 6,
1550
1578
  goat: 20,
1551
1579
  pro: 30
1552
1580
  }
@@ -1559,6 +1587,7 @@ const MODEL_PRICE_ROWS = [
1559
1587
  .26
1560
1588
  ],
1561
1589
  allowance: {
1590
+ go: 6,
1562
1591
  goat: 20,
1563
1592
  pro: 30
1564
1593
  }
@@ -1571,6 +1600,7 @@ const MODEL_PRICE_ROWS = [
1571
1600
  .26
1572
1601
  ],
1573
1602
  allowance: {
1603
+ go: 10,
1574
1604
  goat: 70,
1575
1605
  pro: 80
1576
1606
  }
@@ -1583,6 +1613,7 @@ const MODEL_PRICE_ROWS = [
1583
1613
  .5
1584
1614
  ],
1585
1615
  allowance: {
1616
+ go: 9,
1586
1617
  goat: 20,
1587
1618
  pro: 30
1588
1619
  }
@@ -1595,6 +1626,7 @@ const MODEL_PRICE_ROWS = [
1595
1626
  .26
1596
1627
  ],
1597
1628
  allowance: {
1629
+ go: 10,
1598
1630
  goat: 20,
1599
1631
  pro: 30
1600
1632
  }
@@ -1607,6 +1639,7 @@ const MODEL_PRICE_ROWS = [
1607
1639
  .03
1608
1640
  ],
1609
1641
  allowance: {
1642
+ go: 10,
1610
1643
  goat: 40,
1611
1644
  pro: 50
1612
1645
  }
@@ -1619,6 +1652,7 @@ const MODEL_PRICE_ROWS = [
1619
1652
  .075
1620
1653
  ],
1621
1654
  allowance: {
1655
+ go: 6,
1622
1656
  goat: 20,
1623
1657
  pro: 30
1624
1658
  }
@@ -1632,6 +1666,7 @@ const MODEL_PRICE_ROWS = [
1632
1666
  0
1633
1667
  ],
1634
1668
  allowance: {
1669
+ go: 6,
1635
1670
  goat: 20,
1636
1671
  pro: 20
1637
1672
  }
@@ -1645,6 +1680,7 @@ const MODEL_PRICE_ROWS = [
1645
1680
  0
1646
1681
  ],
1647
1682
  allowance: {
1683
+ go: 6,
1648
1684
  goat: 20,
1649
1685
  pro: 20
1650
1686
  }
@@ -1658,6 +1694,7 @@ const MODEL_PRICE_ROWS = [
1658
1694
  0
1659
1695
  ],
1660
1696
  allowance: {
1697
+ go: 6,
1661
1698
  goat: 20,
1662
1699
  pro: 20
1663
1700
  }
@@ -1671,6 +1708,7 @@ const MODEL_PRICE_ROWS = [
1671
1708
  0
1672
1709
  ],
1673
1710
  allowance: {
1711
+ go: 6,
1674
1712
  goat: 20,
1675
1713
  pro: 20
1676
1714
  }
@@ -1684,6 +1722,7 @@ const MODEL_PRICE_ROWS = [
1684
1722
  .25
1685
1723
  ],
1686
1724
  allowance: {
1725
+ go: 6,
1687
1726
  goat: 20,
1688
1727
  pro: 30
1689
1728
  },
@@ -1711,6 +1750,7 @@ const MODEL_PRICE_ROWS = [
1711
1750
  6.25
1712
1751
  ],
1713
1752
  allowance: {
1753
+ go: 6,
1714
1754
  goat: 70,
1715
1755
  pro: 80
1716
1756
  },
@@ -1738,6 +1778,7 @@ const MODEL_PRICE_ROWS = [
1738
1778
  2.5
1739
1779
  ],
1740
1780
  allowance: {
1781
+ go: 6,
1741
1782
  goat: 20,
1742
1783
  pro: 20
1743
1784
  },
@@ -1765,6 +1806,7 @@ const MODEL_PRICE_ROWS = [
1765
1806
  12.5
1766
1807
  ],
1767
1808
  allowance: {
1809
+ go: 6,
1768
1810
  goat: 20,
1769
1811
  pro: 20
1770
1812
  },
@@ -1783,33 +1825,6 @@ const MODEL_PRICE_ROWS = [
1783
1825
  25
1784
1826
  ] }]
1785
1827
  },
1786
- {
1787
- id: "gpt-6.1-sol",
1788
- rates: [
1789
- 2,
1790
- 10,
1791
- .1,
1792
- 2.5
1793
- ],
1794
- allowance: {
1795
- goat: 20,
1796
- pro: 20
1797
- },
1798
- contextTiers: [{
1799
- "maxContext": 272e3,
1800
- "rates": [
1801
- 2,
1802
- 10,
1803
- .1,
1804
- 2.5
1805
- ]
1806
- }, { "rates": [
1807
- 4,
1808
- 15,
1809
- .2,
1810
- 5
1811
- ] }]
1812
- },
1813
1828
  {
1814
1829
  id: "gpt-6-luna",
1815
1830
  rates: [
@@ -1819,6 +1834,7 @@ const MODEL_PRICE_ROWS = [
1819
1834
  .125
1820
1835
  ],
1821
1836
  allowance: {
1837
+ go: 6,
1822
1838
  goat: 20,
1823
1839
  pro: 30
1824
1840
  },
@@ -1846,6 +1862,7 @@ const MODEL_PRICE_ROWS = [
1846
1862
  2.5
1847
1863
  ],
1848
1864
  allowance: {
1865
+ go: 6,
1849
1866
  goat: 20,
1850
1867
  pro: 20
1851
1868
  },
@@ -1864,6 +1881,34 @@ const MODEL_PRICE_ROWS = [
1864
1881
  5
1865
1882
  ] }]
1866
1883
  },
1884
+ {
1885
+ id: "gpt-6.1-sol",
1886
+ rates: [
1887
+ 2,
1888
+ 10,
1889
+ .1,
1890
+ 2.5
1891
+ ],
1892
+ allowance: {
1893
+ go: 6,
1894
+ goat: 20,
1895
+ pro: 20
1896
+ },
1897
+ contextTiers: [{
1898
+ "maxContext": 272e3,
1899
+ "rates": [
1900
+ 2,
1901
+ 10,
1902
+ .1,
1903
+ 2.5
1904
+ ]
1905
+ }, { "rates": [
1906
+ 4,
1907
+ 15,
1908
+ .2,
1909
+ 5
1910
+ ] }]
1911
+ },
1867
1912
  {
1868
1913
  id: "grok-4.5",
1869
1914
  rates: [
@@ -1872,6 +1917,7 @@ const MODEL_PRICE_ROWS = [
1872
1917
  .5
1873
1918
  ],
1874
1919
  allowance: {
1920
+ go: 6,
1875
1921
  goat: 20,
1876
1922
  pro: 30
1877
1923
  }
@@ -1884,6 +1930,7 @@ const MODEL_PRICE_ROWS = [
1884
1930
  .5
1885
1931
  ],
1886
1932
  allowance: {
1933
+ go: 6,
1887
1934
  goat: 20,
1888
1935
  pro: 30
1889
1936
  },
@@ -1908,6 +1955,7 @@ const MODEL_PRICE_ROWS = [
1908
1955
  .5
1909
1956
  ],
1910
1957
  allowance: {
1958
+ go: 6,
1911
1959
  goat: 20,
1912
1960
  pro: 30
1913
1961
  },
@@ -1932,6 +1980,7 @@ const MODEL_PRICE_ROWS = [
1932
1980
  .17
1933
1981
  ],
1934
1982
  allowance: {
1983
+ go: 6,
1935
1984
  goat: 20,
1936
1985
  pro: 30
1937
1986
  }
@@ -1944,6 +1993,7 @@ const MODEL_PRICE_ROWS = [
1944
1993
  .1
1945
1994
  ],
1946
1995
  allowance: {
1996
+ go: 6,
1947
1997
  goat: 20,
1948
1998
  pro: 30
1949
1999
  }
@@ -1956,6 +2006,7 @@ const MODEL_PRICE_ROWS = [
1956
2006
  .1
1957
2007
  ],
1958
2008
  allowance: {
2009
+ go: 6,
1959
2010
  goat: 20,
1960
2011
  pro: 30
1961
2012
  }
@@ -1968,6 +2019,7 @@ const MODEL_PRICE_ROWS = [
1968
2019
  .16
1969
2020
  ],
1970
2021
  allowance: {
2022
+ go: 6,
1971
2023
  goat: 20,
1972
2024
  pro: 30
1973
2025
  }
@@ -1980,6 +2032,7 @@ const MODEL_PRICE_ROWS = [
1980
2032
  .19
1981
2033
  ],
1982
2034
  allowance: {
2035
+ go: 9,
1983
2036
  goat: 60,
1984
2037
  pro: 70
1985
2038
  }
@@ -1992,6 +2045,7 @@ const MODEL_PRICE_ROWS = [
1992
2045
  .38
1993
2046
  ],
1994
2047
  allowance: {
2048
+ go: 6,
1995
2049
  goat: 20,
1996
2050
  pro: 30
1997
2051
  }
@@ -2004,6 +2058,7 @@ const MODEL_PRICE_ROWS = [
2004
2058
  .3
2005
2059
  ],
2006
2060
  allowance: {
2061
+ go: 8,
2007
2062
  goat: 20,
2008
2063
  pro: 30
2009
2064
  }
@@ -2016,6 +2071,7 @@ const MODEL_PRICE_ROWS = [
2016
2071
  .006
2017
2072
  ],
2018
2073
  allowance: {
2074
+ go: 10,
2019
2075
  goat: 50,
2020
2076
  pro: 60
2021
2077
  }
@@ -2033,6 +2089,7 @@ const MODEL_PRICE_ROWS = [
2033
2089
  .16
2034
2090
  ],
2035
2091
  allowance: {
2092
+ go: 6,
2036
2093
  goat: 30,
2037
2094
  pro: 40
2038
2095
  }
@@ -2050,6 +2107,7 @@ const MODEL_PRICE_ROWS = [
2050
2107
  .4
2051
2108
  ],
2052
2109
  allowance: {
2110
+ go: 6,
2053
2111
  goat: 20,
2054
2112
  pro: 30
2055
2113
  }
@@ -2062,6 +2120,7 @@ const MODEL_PRICE_ROWS = [
2062
2120
  .0028
2063
2121
  ],
2064
2122
  allowance: {
2123
+ go: 6,
2065
2124
  goat: 20,
2066
2125
  pro: 30
2067
2126
  }
@@ -2074,6 +2133,7 @@ const MODEL_PRICE_ROWS = [
2074
2133
  .0036
2075
2134
  ],
2076
2135
  allowance: {
2136
+ go: 6,
2077
2137
  goat: 20,
2078
2138
  pro: 30
2079
2139
  }
@@ -2086,6 +2146,7 @@ const MODEL_PRICE_ROWS = [
2086
2146
  .036
2087
2147
  ],
2088
2148
  allowance: {
2149
+ go: 6,
2089
2150
  goat: 10,
2090
2151
  pro: 20
2091
2152
  }
@@ -2098,6 +2159,7 @@ const MODEL_PRICE_ROWS = [
2098
2159
  .03
2099
2160
  ],
2100
2161
  allowance: {
2162
+ go: 6,
2101
2163
  goat: 20,
2102
2164
  pro: 30
2103
2165
  }
@@ -2110,6 +2172,7 @@ const MODEL_PRICE_ROWS = [
2110
2172
  .06
2111
2173
  ],
2112
2174
  allowance: {
2175
+ go: 6,
2113
2176
  goat: 20,
2114
2177
  pro: 30
2115
2178
  }
@@ -2127,6 +2190,7 @@ const MODEL_PRICE_ROWS = [
2127
2190
  .12
2128
2191
  ],
2129
2192
  allowance: {
2193
+ go: 8,
2130
2194
  goat: 47,
2131
2195
  pro: 57
2132
2196
  }
@@ -2139,6 +2203,7 @@ const MODEL_PRICE_ROWS = [
2139
2203
  .15
2140
2204
  ],
2141
2205
  allowance: {
2206
+ go: 6,
2142
2207
  goat: 20,
2143
2208
  pro: 20
2144
2209
  }
@@ -2151,6 +2216,7 @@ const MODEL_PRICE_ROWS = [
2151
2216
  .15
2152
2217
  ],
2153
2218
  allowance: {
2219
+ go: 6,
2154
2220
  goat: 20,
2155
2221
  pro: 30
2156
2222
  }
@@ -2163,6 +2229,7 @@ const MODEL_PRICE_ROWS = [
2163
2229
  .002
2164
2230
  ],
2165
2231
  allowance: {
2232
+ go: 6,
2166
2233
  goat: 20,
2167
2234
  pro: 30
2168
2235
  }
@@ -2175,6 +2242,7 @@ const MODEL_PRICE_ROWS = [
2175
2242
  .15
2176
2243
  ],
2177
2244
  allowance: {
2245
+ go: 6,
2178
2246
  goat: 20,
2179
2247
  pro: 30
2180
2248
  }
@@ -2187,6 +2255,7 @@ const MODEL_PRICE_ROWS = [
2187
2255
  .002
2188
2256
  ],
2189
2257
  allowance: {
2258
+ go: 6,
2190
2259
  goat: 20,
2191
2260
  pro: 30
2192
2261
  }
@@ -2199,6 +2268,7 @@ const MODEL_PRICE_ROWS = [
2199
2268
  .12
2200
2269
  ],
2201
2270
  allowance: {
2271
+ go: 6,
2202
2272
  goat: 20,
2203
2273
  pro: 30
2204
2274
  }
@@ -2212,6 +2282,7 @@ const MODEL_PRICE_ROWS = [
2212
2282
  1.63
2213
2283
  ],
2214
2284
  allowance: {
2285
+ go: 6,
2215
2286
  goat: 20,
2216
2287
  pro: 30
2217
2288
  }
@@ -2224,6 +2295,7 @@ const MODEL_PRICE_ROWS = [
2224
2295
  .1
2225
2296
  ],
2226
2297
  allowance: {
2298
+ go: 10,
2227
2299
  goat: 33,
2228
2300
  pro: 43
2229
2301
  },
@@ -2249,6 +2321,7 @@ const MODEL_PRICE_ROWS = [
2249
2321
  .038
2250
2322
  ],
2251
2323
  allowance: {
2324
+ go: 6,
2252
2325
  goat: 20,
2253
2326
  pro: 30
2254
2327
  },
@@ -2288,6 +2361,7 @@ const MODEL_PRICE_ROWS = [
2288
2361
  3.13
2289
2362
  ],
2290
2363
  allowance: {
2364
+ go: 10,
2291
2365
  goat: 33,
2292
2366
  pro: 43
2293
2367
  }
@@ -2301,6 +2375,7 @@ const MODEL_PRICE_ROWS = [
2301
2375
  .5
2302
2376
  ],
2303
2377
  allowance: {
2378
+ go: 10,
2304
2379
  goat: 33,
2305
2380
  pro: 43
2306
2381
  },
@@ -2327,6 +2402,7 @@ const MODEL_PRICE_ROWS = [
2327
2402
  .04
2328
2403
  ],
2329
2404
  allowance: {
2405
+ go: 10,
2330
2406
  goat: 70,
2331
2407
  pro: 80
2332
2408
  }
@@ -2339,6 +2415,7 @@ const MODEL_PRICE_ROWS = [
2339
2415
  .016
2340
2416
  ],
2341
2417
  allowance: {
2418
+ go: 6,
2342
2419
  goat: 20,
2343
2420
  pro: 30
2344
2421
  }
@@ -2352,6 +2429,7 @@ const MODEL_PRICE_ROWS = [
2352
2429
  2.5
2353
2430
  ],
2354
2431
  allowance: {
2432
+ go: 7,
2355
2433
  goat: 20,
2356
2434
  pro: 30
2357
2435
  }
@@ -2364,6 +2442,7 @@ const MODEL_PRICE_ROWS = [
2364
2442
  .25
2365
2443
  ],
2366
2444
  allowance: {
2445
+ go: 7,
2367
2446
  goat: 20,
2368
2447
  pro: 30
2369
2448
  }
@@ -2376,6 +2455,7 @@ const MODEL_PRICE_ROWS = [
2376
2455
  .016
2377
2456
  ],
2378
2457
  allowance: {
2458
+ go: 6,
2379
2459
  goat: 20,
2380
2460
  pro: 30
2381
2461
  }
@@ -2388,6 +2468,7 @@ const MODEL_PRICE_ROWS = [
2388
2468
  .02
2389
2469
  ],
2390
2470
  allowance: {
2471
+ go: 6,
2391
2472
  goat: 20,
2392
2473
  pro: 30
2393
2474
  }
@@ -2400,6 +2481,7 @@ const MODEL_PRICE_ROWS = [
2400
2481
  .04
2401
2482
  ],
2402
2483
  allowance: {
2484
+ go: 6,
2403
2485
  goat: 20,
2404
2486
  pro: 30
2405
2487
  }
@@ -2412,6 +2494,7 @@ const MODEL_PRICE_ROWS = [
2412
2494
  .05
2413
2495
  ],
2414
2496
  allowance: {
2497
+ go: 6,
2415
2498
  goat: 20,
2416
2499
  pro: 30
2417
2500
  }
@@ -2424,6 +2507,7 @@ const MODEL_PRICE_ROWS = [
2424
2507
  .035
2425
2508
  ],
2426
2509
  allowance: {
2510
+ go: 10,
2427
2511
  goat: 70,
2428
2512
  pro: 80
2429
2513
  }
@@ -2436,6 +2520,7 @@ const MODEL_PRICE_ROWS = [
2436
2520
  .042
2437
2521
  ],
2438
2522
  allowance: {
2523
+ go: 6,
2439
2524
  goat: 20,
2440
2525
  pro: 30
2441
2526
  }
@@ -2448,6 +2533,7 @@ const MODEL_PRICE_ROWS = [
2448
2533
  0
2449
2534
  ],
2450
2535
  allowance: {
2536
+ go: 6,
2451
2537
  goat: 20,
2452
2538
  pro: 30
2453
2539
  }
@@ -2760,6 +2846,16 @@ function installCostProjection(ctx) {
2760
2846
  * JSON, SSE, and pre-stream error bodies undecoded.
2761
2847
  */
2762
2848
  const IDENTITY_ENCODING_HEADER = { "accept-encoding": "identity" };
2849
+ //#endregion
2850
+ //#region src/timeout-limits.ts
2851
+ const MAX_TIMEOUT_SECONDS = 3600;
2852
+ //#endregion
2853
+ //#region src/model-visibility.ts
2854
+ /** 网页、终端与模型目录共用的选择规则;显式开关优先于白名单。 */
2855
+ function modelIsVisible(id, allowlist, overrides) {
2856
+ const flag = overrides !== null && typeof overrides === "object" && !Array.isArray(overrides) ? overrides[id] : void 0;
2857
+ return typeof flag === "boolean" ? flag : allowlist.length === 0 || allowlist.includes(id);
2858
+ }
2763
2859
  const THROTTLED_CODE = "THROTTLED";
2764
2860
  const boundedCodes = /* @__PURE__ */ new Set([
2765
2861
  "EMPTY_RESPONSE",
@@ -2945,28 +3041,10 @@ var CommandCodeAccountPool = class {
2945
3041
  if (routed !== void 0) return this.pick(routed);
2946
3042
  const chosen = selectActiveAccount(available, preferred);
2947
3043
  if (chosen !== void 0) {
2948
- const explicit = this.explicitAccount(available, options?.model ?? "", preferred);
2949
- if (explicit !== void 0 && explicit.key !== chosen.key && this.canProbeExplicit(explicit)) {
2950
- const revived = await this.probeExplicit(explicit);
2951
- if (revived !== void 0) return this.pick(revived);
2952
- }
2953
- return this.pick(chosen);
3044
+ const revived = await this.reviveExplicit(available, options?.model ?? "", preferred, chosen);
3045
+ return this.pick(revived ?? chosen);
2954
3046
  }
2955
- await Promise.all(available.map(async (account) => {
2956
- if (account.state?.kind === "disabled") return;
2957
- let probe;
2958
- try {
2959
- probe = await this.deps.probeWindow(account.key);
2960
- } catch {
2961
- return;
2962
- }
2963
- if (probe === void 0) return;
2964
- if (!probe.exceeded) {
2965
- this.states.delete(account.key);
2966
- return;
2967
- }
2968
- this.stampWindowMark(account, probe);
2969
- }));
3047
+ await this.probeAllMarked(available);
2970
3048
  const latestAccounts = await this.resolvedAccounts();
2971
3049
  const revived = selectActiveAccount(tried === void 0 || tried.length === 0 ? latestAccounts : latestAccounts.filter((account) => !tried.includes(account.key)), preferred);
2972
3050
  if (revived !== void 0) return this.pick(revived);
@@ -2974,6 +3052,34 @@ var CommandCodeAccountPool = class {
2974
3052
  throw allAccountsUnusable(latestAccounts.length > 0 ? latestAccounts : accounts);
2975
3053
  }
2976
3054
  /**
3055
+ * Which account is serving right now, for display (the settings page's
3056
+ * account card, the sidebar usage stats) — without consuming a request's
3057
+ * `tried` budget and without throwing when nothing can serve.
3058
+ *
3059
+ * Reads and self-heals exactly like {@link resolveKey} would: an `unknown`
3060
+ * mark on the pinned account is re-probed (throttled the same way, sharing
3061
+ * the same per-key timestamp), and a pool where nothing currently resolves
3062
+ * gets one batch probe pass too. Without this, the badge read a possibly
3063
+ * stale mark forever — nothing but an actual generate request ever cleared
3064
+ * an `unknown` mark, so a page left open with no chat activity kept
3065
+ * showing "switched to the fallback account" long after a real request
3066
+ * would have quietly recovered (issue #51's follow-up report: the account
3067
+ * card and the sidebar stats both stuck on the wrong account).
3068
+ *
3069
+ * No `model` parameter: the badge describes the pool as a whole, not one
3070
+ * request, so model-routing rules are deliberately not consulted here —
3071
+ * matching what the direct `selectActiveAccount` call this replaces did.
3072
+ */
3073
+ async activeAccount() {
3074
+ const accounts = await this.resolvedAccounts();
3075
+ if (accounts.length === 0) return void 0;
3076
+ const preferred = this.deps.preferredId?.();
3077
+ const chosen = selectActiveAccount(accounts, preferred);
3078
+ if (chosen !== void 0) return await this.reviveExplicit(accounts, "", preferred, chosen) ?? chosen;
3079
+ await this.probeAllMarked(accounts);
3080
+ return selectActiveAccount(await this.resolvedAccounts(), preferred);
3081
+ }
3082
+ /**
2977
3083
  * Record a rejection against one key. A `throttled` rejection (the plain 429
2978
3084
  * that named no window) marks the key with the `throttle` cause, leaving
2979
3085
  * rotation exactly like a window mark but keeping the pool's own diagnosis at
@@ -3123,6 +3229,46 @@ var CommandCodeAccountPool = class {
3123
3229
  until: 0
3124
3230
  });
3125
3231
  }
3232
+ /**
3233
+ * The explicit-account fallback re-check: when `chosen` (what rotation
3234
+ * would currently serve) is not the account the user actually asked for,
3235
+ * re-probe that explicit account's mark before accepting the fallback —
3236
+ * so a rate-limit mark never demotes the user's own selection for good
3237
+ * (issue #51). Returns the revived account, or `undefined` when there is
3238
+ * nothing to revive (explicit account already serving, not due for a
3239
+ * probe, or the probe found it still exceeded). Shared by {@link resolveKey}
3240
+ * (the request path) and {@link activeAccount} (the display path), so both
3241
+ * agree on what "currently usable" means instead of drifting apart.
3242
+ */
3243
+ async reviveExplicit(accounts, model, preferred, chosen) {
3244
+ const explicit = this.explicitAccount(accounts, model, preferred);
3245
+ if (explicit === void 0 || explicit.key === chosen.key || !this.canProbeExplicit(explicit)) return;
3246
+ return this.probeExplicit(explicit);
3247
+ }
3248
+ /**
3249
+ * Probe every marked account's real usage window when nothing currently
3250
+ * resolves. Disabled (401) keys are not probed — an invalid key stays
3251
+ * invalid. A throwing probe counts as "unknown" (like a failed one): it
3252
+ * must not turn the all-exhausted path into a raw rejection instead of
3253
+ * RATE_LIMIT. Shared by {@link resolveKey} and {@link activeAccount}.
3254
+ */
3255
+ async probeAllMarked(accounts) {
3256
+ await Promise.all(accounts.map(async (account) => {
3257
+ if (account.state?.kind === "disabled") return;
3258
+ let probe;
3259
+ try {
3260
+ probe = await this.deps.probeWindow(account.key);
3261
+ } catch {
3262
+ return;
3263
+ }
3264
+ if (probe === void 0) return;
3265
+ if (!probe.exceeded) {
3266
+ this.states.delete(account.key);
3267
+ return;
3268
+ }
3269
+ this.stampWindowMark(account, probe);
3270
+ }));
3271
+ }
3126
3272
  /** Hand out the chosen account's key. */
3127
3273
  pick(account) {
3128
3274
  return {
@@ -3680,7 +3826,7 @@ function openRequestTiming(model, sink) {
3680
3826
  * `/provider/v1/messages`),
3681
3827
  * message conversion, SSE/JSONL parsing, the catalog + its on-disk cache, and
3682
3828
  * the pre-stream account rotation loop. The wire protocol is
3683
- * reverse-engineered (command-code@1.28.4, re-verified through 1.72.1);
3829
+ * reverse-engineered (command-code@1.28.4, re-verified through 1.73.0);
3684
3830
  * docs/agent-reference/adapter-protocol.md holds the full protocol record.
3685
3831
  *
3686
3832
  * The adapter is deliberately free of cordis/schemastery: it receives a
@@ -3782,7 +3928,7 @@ function outputCeilingRefusal(apiBase, modelId, error) {
3782
3928
  function bilingual(code, en, zh, options) {
3783
3929
  return new LlmError(`${en};${zh}`, code, options);
3784
3930
  }
3785
- const COMMAND_CODE_CLI_VERSION = "1.72.1";
3931
+ const COMMAND_CODE_CLI_VERSION = "1.73.0";
3786
3932
  const DEFAULT_API_BASE = "https://api.commandcode.ai";
3787
3933
  /**
3788
3934
  * The output budget this bundle asks for, and the ceiling it will never exceed.
@@ -3800,9 +3946,16 @@ const DEFAULT_API_BASE = "https://api.commandcode.ai";
3800
3946
  * (a 64 000 request answered headers in 1.28 s against 1.57 s for 131 072) but
3801
3947
  * it did cap what a model could ever say in one turn.
3802
3948
  *
3803
- * This is only an UPPER bound. `requestContextBudget` lowers it per request
3804
- * from the prompt actually being sent, so raising the ceiling cannot push a
3805
- * large session over its window.
3949
+ * No client-side clamp is applied on top of this: an earlier version pre-shrank
3950
+ * `max_tokens` from an estimate of the prompt already sent (`requestContextBudget()`,
3951
+ * issue #67), but that estimate over-corrected on ordinary long conversations —
3952
+ * exactly the "output gets cut short as the conversation grows" symptom issue #74
3953
+ * reported — while a live A/B probe (2026-09-30, `stealth/space-bunny-alpha`,
3954
+ * ~19.6% over its 1,000,000-token window with no client-side shrink) showed the
3955
+ * endpoint answers a genuine overflow with an unambiguous `400 … exceeds the
3956
+ * model's context window`, which `isContextOverflowDetail()` below already
3957
+ * classifies as `CONTEXT_WINDOW_EXCEEDED` independently of this constant. See
3958
+ * [决策记录](../docs/决策记录.md).
3806
3959
  */
3807
3960
  const DEFAULT_GENERATE_MAX_TOKENS = 131072;
3808
3961
  /**
@@ -3815,8 +3968,6 @@ const DEFAULT_GENERATE_MAX_TOKENS = 131072;
3815
3968
  * `Math.min(contextLength, this)` before the ceiling above is ever consulted.
3816
3969
  */
3817
3970
  const DEFAULT_MAX_OUTPUT_TOKENS = 131072;
3818
- /** Preserve a small usable answer budget when the heuristic overshoots. */
3819
- const MIN_CONTEXT_OUTPUT_TOKENS = 1024;
3820
3971
  const MODELS_TIMEOUT_MS = 1e4;
3821
3972
  /** 目录短期复用;刷新失败只短暂退避,避免反复阻塞模型选择器。 */
3822
3973
  const MODEL_CATALOG_TTL_MS = 3e5;
@@ -4073,8 +4224,6 @@ const CLI_CONTEXT_OVERFLOW_PATTERN = /prompt is too long|context.*(length|window
4073
4224
  function isContextOverflowDetail(detail) {
4074
4225
  return isContextWindowExceededError(detail) || CLI_CONTEXT_OVERFLOW_PATTERN.test(detail);
4075
4226
  }
4076
- /** A gateway refusal observed for an over-reserved request, but not unique to that cause. */
4077
- const AMBIGUOUS_SIZE_REJECTION = /\bmodel could not complete the request\b/i;
4078
4227
  /**
4079
4228
  * A request-side `max_tokens` refusal, told apart from a context overflow that
4080
4229
  * mentions the same field. Kept narrow on purpose: the overflow pattern also
@@ -4107,10 +4256,7 @@ function parseOutputCeiling(detail) {
4107
4256
  /**
4108
4257
  * The advice floor for a Provider-API timeout: doubling a 60 s budget is still
4109
4258
  * short for a slow upstream first token, so the suggestion never goes below 5
4110
- * minutes. Capped by `RETRY_MAX_DELAY_MS` rather than the schema's timer
4111
- * ceiling on purpose — a single header wait that outlasts the whole retry
4112
- * backoff is not a budget, and clamping to the engine constant would also pull
4113
- * a runtime dependency into the bundle.
4259
+ * minutes. 提示上限与页面可编辑范围相同,重试退避上限不约束单次请求。
4114
4260
  */
4115
4261
  const MIN_SUGGESTED_TIMEOUT_MS = 3e5;
4116
4262
  /**
@@ -4134,10 +4280,13 @@ const MIN_SUGGESTED_TIMEOUT_MS = 3e5;
4134
4280
  * @param timeoutMs - the header budget that just expired.
4135
4281
  */
4136
4282
  function headersTimeoutAdvice(protocol, timeoutMs) {
4137
- if (protocol === "openai") return {
4138
- cause: "upstream-first-token",
4139
- suggestionMs: Math.min(RETRY_MAX_DELAY_MS, Math.max(timeoutMs * 2, MIN_SUGGESTED_TIMEOUT_MS))
4140
- };
4283
+ if (protocol === "openai") {
4284
+ const suggestionMs = Math.min(MAX_TIMEOUT_SECONDS * 1e3, Math.max(timeoutMs * 2, MIN_SUGGESTED_TIMEOUT_MS));
4285
+ return {
4286
+ cause: "upstream-first-token",
4287
+ ...suggestionMs > timeoutMs ? { suggestionMs } : {}
4288
+ };
4289
+ }
4141
4290
  return { cause: "gateway" };
4142
4291
  }
4143
4292
  /**
@@ -4423,21 +4572,21 @@ function parseCatalogResponse(value, apiBase) {
4423
4572
  if (models.length === 0) throw new LlmError("Command Code returned an empty model catalog", "PROVIDER_PROTOCOL_ERROR");
4424
4573
  return models;
4425
4574
  }
4426
- async function readModelsCache(cachePath, apiBase) {
4575
+ async function readModelsCache(cachePath, apiBase, restorePublished = true) {
4427
4576
  const parsed = JSON.parse(await readFile(cachePath, "utf-8"));
4428
4577
  if (!isRecord(parsed) || parsed.version !== MODEL_CACHE_VERSION || parsed.apiBase !== apiBase || !Array.isArray(parsed.models)) throw new Error(`Invalid model cache at ${cachePath}`);
4429
- publishedOutputLimits.set(apiBase, /* @__PURE__ */ new Map());
4578
+ if (restorePublished) publishedOutputLimits.set(apiBase, /* @__PURE__ */ new Map());
4430
4579
  return parsed.models.map((entry) => {
4431
4580
  const model = isRecord(entry) ? entry : {};
4432
4581
  const endpoints = Array.isArray(model.supportedEndpoints) ? model.supportedEndpoints.filter((item) => typeof item === "string") : [];
4433
4582
  const id = stringValue(model.id);
4434
4583
  const published = numberValue(model.publishedMaxTokens);
4435
- if (id !== void 0 && published !== void 0 && published > 0) outputLimitsFor(publishedOutputLimits, apiBase).set(id, published);
4584
+ if (restorePublished && id !== void 0 && published !== void 0 && published > 0) outputLimitsFor(publishedOutputLimits, apiBase).set(id, published);
4436
4585
  const contextWindow = numberValue(model.contextWindow);
4437
4586
  return {
4438
4587
  ...model,
4439
4588
  supportedEndpoints: endpoints,
4440
- maxTokens: id === void 0 || contextWindow === void 0 ? numberValue(model.maxTokens) ?? 131072 : Math.min(contextWindow, modelOutputTokenLimit(apiBase, id))
4589
+ maxTokens: id === void 0 || contextWindow === void 0 ? numberValue(model.maxTokens) ?? 131072 : Math.min(contextWindow, modelOutputTokenLimit(apiBase, id), published !== void 0 && published > 0 ? published : Infinity)
4441
4590
  };
4442
4591
  });
4443
4592
  }
@@ -5264,6 +5413,7 @@ async function buildCliBody(options, connection, facts) {
5264
5413
  memory: null,
5265
5414
  taste: null,
5266
5415
  skills: null,
5416
+ permissionMode: "standard",
5267
5417
  params: {
5268
5418
  model: options.model,
5269
5419
  messages: await messagesToCC(options.messages, facts.readImage),
@@ -5363,41 +5513,6 @@ async function buildMessagesBody(options, facts) {
5363
5513
  return body;
5364
5514
  }
5365
5515
  /**
5366
- * Estimate the text the selected transport actually sends. JSON framing and
5367
- * punctuation each get a token; ordinary ASCII words get one, with an extra
5368
- * allowance for long identifiers. UTF-8 bytes / 4 tracks the measured CJK
5369
- * case better than the engine's UTF-16 characters / 4. This is a heuristic,
5370
- * never proof that a prompt cannot fit: a valid long English prompt can still
5371
- * be larger under this estimate than under the provider's tokenizer.
5372
- */
5373
- function estimateWireInputTokens(protocol, body, messages, model) {
5374
- const params = protocol === "cli" ? recordOrEmpty(body.params) : body;
5375
- const wire = JSON.stringify(params, (_key, value) => typeof value === "string" && /^data:[^,]*;base64,/.test(value) ? "[image]" : value);
5376
- let tokens = 0;
5377
- for (const match of wire.matchAll(/[A-Za-z0-9_]+|[^\x00-\x7f]+|[^\s]/gu)) {
5378
- const part = match[0];
5379
- if (/^[A-Za-z0-9_]+$/.test(part)) tokens += 1 + Math.ceil(Math.max(0, part.length - 12) / 4);
5380
- else if (part.charCodeAt(0) > 127) tokens += Math.ceil(Buffer.byteLength(part) / 4);
5381
- else tokens += 1;
5382
- }
5383
- for (const message of messages) for (const block of message.content) if (block.type === "image") tokens += priceRequestImage(block, model, true).visualTokens;
5384
- return tokens;
5385
- }
5386
- function requestContextBudget(protocol, body, messages, model, contextWindow, requestedMaxTokens) {
5387
- if (contextWindow === void 0) return {
5388
- maxTokens: requestedMaxTokens,
5389
- sizePressure: false
5390
- };
5391
- const estimatedInput = estimateWireInputTokens(protocol, body, messages, model);
5392
- const headroom = Math.min(16384, Math.max(2048, Math.ceil(contextWindow * .02)));
5393
- const available = Math.floor(contextWindow - estimatedInput - headroom);
5394
- const floor = Math.min(requestedMaxTokens, MIN_CONTEXT_OUTPUT_TOKENS, Math.max(1, Math.floor(contextWindow / 8)));
5395
- return {
5396
- maxTokens: Math.min(requestedMaxTokens, Math.max(floor, available)),
5397
- sizePressure: estimatedInput >= contextWindow / 4 && estimatedInput + requestedMaxTokens + headroom >= contextWindow
5398
- };
5399
- }
5400
- /**
5401
5516
  * One connect attempt's inputs: everything `connectGenerate` needs beyond
5402
5517
  * the per-attempt key and protocol. Passed explicitly (not closed over) so
5403
5518
  * the rotation loop's mutation of `protocol`/`body` stays visible at the
@@ -5408,6 +5523,42 @@ function protocolEndpoint(protocol, apiBase) {
5408
5523
  if (protocol === "cli") return `${apiBase}/alpha/generate`;
5409
5524
  return protocol === "messages" ? `${apiBase}/provider/v1/messages` : `${apiBase}/provider/v1/chat/completions`;
5410
5525
  }
5526
+ /** 错误正文只供诊断与分类使用,不能让坏网关占满内存或无限拖住重试。 */
5527
+ async function readGenerateErrorBody(response, abort, timeoutMs) {
5528
+ if (response.body === null) return "";
5529
+ const reader = response.body.getReader();
5530
+ const decoder = new TextDecoder();
5531
+ let text = "";
5532
+ let bytes = 0;
5533
+ const limit = 65536;
5534
+ let removeAbort = () => void 0;
5535
+ const stopped = new Promise((resolve) => {
5536
+ if (abort.signal.aborted) resolve(void 0);
5537
+ else abort.signal.addEventListener("abort", onAbort, { once: true });
5538
+ function onAbort() {
5539
+ resolve(void 0);
5540
+ }
5541
+ removeAbort = () => abort.signal.removeEventListener("abort", onAbort);
5542
+ });
5543
+ const timer = setTimeout(() => abort.abort(), Math.min(timeoutMs, 3e4));
5544
+ try {
5545
+ while (bytes < limit) {
5546
+ const read = await Promise.race([reader.read(), stopped]);
5547
+ if (read === void 0 || read.done) break;
5548
+ const remaining = limit - bytes;
5549
+ text += decoder.decode(read.value.subarray(0, remaining), { stream: true });
5550
+ bytes += read.value.byteLength;
5551
+ }
5552
+ return text + decoder.decode();
5553
+ } catch {
5554
+ return text + decoder.decode();
5555
+ } finally {
5556
+ clearTimeout(timer);
5557
+ removeAbort();
5558
+ reader.cancel().catch(() => void 0);
5559
+ reader.releaseLock();
5560
+ }
5561
+ }
5411
5562
  /**
5412
5563
  * One pre-stream connect attempt: POST the body and wait for response
5413
5564
  * headers only (`requestTimeoutMs` must never bound the body stream). Returns
@@ -5450,7 +5601,7 @@ async function connectGenerate(deps, key, protocol, serializedBody) {
5450
5601
  "x-command-code-version": COMMAND_CODE_CLI_VERSION,
5451
5602
  "x-cli-environment": "production",
5452
5603
  "x-project-slug": projectSlugFromPath(connection.workingDir),
5453
- "x-taste-learning": "true",
5604
+ "x-taste-learning": "false",
5454
5605
  "x-co-flag": "false"
5455
5606
  } : {
5456
5607
  ...sharedHeaders,
@@ -5481,8 +5632,13 @@ async function connectGenerate(deps, key, protocol, serializedBody) {
5481
5632
  }
5482
5633
  deps.onResponse(response);
5483
5634
  if (!response.ok) {
5484
- const errText = await response.text().catch(() => "");
5485
- cleanup();
5635
+ let errText;
5636
+ try {
5637
+ errText = await readGenerateErrorBody(response, connectAbort, connection.requestTimeoutMs);
5638
+ if (options.signal?.aborted) throw options.signal.reason ?? new DOMException("已取消请求", "AbortError");
5639
+ } finally {
5640
+ cleanup();
5641
+ }
5486
5642
  const retryAfterMs = parseRetryAfterMs(response.headers.get("retry-after"));
5487
5643
  return retryAfterMs === void 0 ? {
5488
5644
  status: response.status,
@@ -5511,6 +5667,7 @@ function createBlockAssembler() {
5511
5667
  cliCacheWriteTokens: void 0,
5512
5668
  openAiToolCalls: [],
5513
5669
  messagesBlocks: /* @__PURE__ */ new Map(),
5670
+ messagesUsage: void 0,
5514
5671
  replayBlocks: []
5515
5672
  };
5516
5673
  }
@@ -5720,6 +5877,17 @@ var CommandCodeAdapter = class CommandCodeAdapter extends LlmAdapter {
5720
5877
  }
5721
5878
  return this.catalogState;
5722
5879
  }
5880
+ /** 直接生成也使用本地可信目录,不额外联网;并发冷请求共用一次文件读取。 */
5881
+ async catalogForGenerate(connection) {
5882
+ const state = this.currentCatalogState(connection);
5883
+ if (this.catalog.length > 0 || state.expiresAt > 0) return this.catalog;
5884
+ state.disk ??= readModelsCache(connection.modelsCachePath, connection.apiBase, false).catch(() => []);
5885
+ const cached = await state.disk;
5886
+ if (this.catalogState !== state) return cached;
5887
+ if (this.catalog.length > 0 || state.expiresAt > 0) return this.catalog;
5888
+ if (state.inflight === void 0) this.catalog = cached;
5889
+ return cached;
5890
+ }
5723
5891
  /** 共享一次刷新;调用者取消只结束自己的等待,不取消其他调用者的请求。 */
5724
5892
  async loadCatalog(signal) {
5725
5893
  signal?.throwIfAborted();
@@ -5778,21 +5946,16 @@ var CommandCodeAdapter = class CommandCodeAdapter extends LlmAdapter {
5778
5946
  if (opts?.unfiltered === true) return catalog.map(toInfo).sort(compareByPlan);
5779
5947
  const accesses = this.deps.options().filterModelsByPlan === false ? void 0 : await this.loadPoolBillingAccess();
5780
5948
  const visible = this.deps.options().visibleModels;
5781
- const allow = Array.isArray(visible) && visible.length > 0 ? new Set(visible.filter((id) => typeof id === "string" && id !== "")) : void 0;
5949
+ const allow = Array.isArray(visible) ? visible.filter((id) => typeof id === "string" && id !== "") : [];
5782
5950
  const overrides = this.deps.options().modelVisibility;
5783
- return catalog.filter((model) => modelVisibleForAnyAccount(model.id, accesses)).filter((model) => {
5784
- const override = overrides?.[model.id];
5785
- if (typeof override === "boolean") return override;
5786
- return allow === void 0 || allow.has(model.id);
5787
- }).map(toInfo).sort(compareByPlan);
5951
+ return catalog.filter((model) => modelVisibleForAnyAccount(model.id, accesses)).filter((model) => modelIsVisible(model.id, allow, overrides)).map(toInfo).sort(compareByPlan);
5788
5952
  }
5789
5953
  /**
5790
5954
  * The per-model allowance bracket this account POOL falls into, or undefined
5791
5955
  * when there is nothing honest to show.
5792
5956
  *
5793
- * The pricing page publishes a per-model monthly allowance for GOAT and Pro
5794
- * only — its own words are "the boost is a per-model allowance, so it lives on
5795
- * the plans that have them" — so a pool whose highest plan is Go, Provider,
5957
+ * The pricing page publishes per-model monthly allowances for Go, GOAT and
5958
+ * Pro. A pool whose highest plan is Provider,
5796
5959
  * Max or Ultra gets undefined rather than a neighbouring tier's figure. Taking
5797
5960
  * the HIGHEST tier matches the question the picker already answers for a pool
5798
5961
  * (see `modelVisibleForAnyAccount`): what the user can reach, not what the one
@@ -6234,14 +6397,12 @@ var CommandCodeAdapter = class CommandCodeAdapter extends LlmAdapter {
6234
6397
  } finally {
6235
6398
  finishCredentials();
6236
6399
  }
6237
- const modelEntry = this.catalog.find((m) => m.id === options.model);
6400
+ const catalog = await this.catalogForGenerate(connection);
6401
+ options.signal?.throwIfAborted();
6402
+ const modelEntry = catalog.find((m) => m.id === options.model);
6238
6403
  const modelMax = Math.min(modelEntry?.maxTokens ?? Infinity, modelOutputTokenLimit(connection.apiBase, options.model));
6239
6404
  const requestedMaxTokens = Math.min(options.maxTokens ?? modelMax, modelMax, DEFAULT_GENERATE_MAX_TOKENS);
6240
- let maxTokens = requestedMaxTokens;
6241
- let contextBudget = {
6242
- maxTokens,
6243
- sizePressure: false
6244
- };
6405
+ const maxTokens = requestedMaxTokens;
6245
6406
  const effort = options.reasoningEffort;
6246
6407
  const supported = KNOWN_EFFORTS[options.model];
6247
6408
  const reasoningEffort = effort && effort !== "off" && supported?.includes(effort) ? effort : void 0;
@@ -6259,8 +6420,6 @@ var CommandCodeAdapter = class CommandCodeAdapter extends LlmAdapter {
6259
6420
  readImage
6260
6421
  };
6261
6422
  const built = target === "cli" ? await buildCliBody(requestOptions, connection, facts) : target === "messages" ? await buildMessagesBody(requestOptions, facts) : await buildOpenAIBody(requestOptions, facts);
6262
- contextBudget = requestContextBudget(target, built, requestOptions.messages, options.model, modelEntry?.contextWindow, requestedMaxTokens);
6263
- maxTokens = contextBudget.maxTokens;
6264
6423
  if (target === "cli") recordOrEmpty(built.params).max_tokens = maxTokens;
6265
6424
  else built.max_tokens = maxTokens;
6266
6425
  return built;
@@ -6370,7 +6529,7 @@ var CommandCodeAdapter = class CommandCodeAdapter extends LlmAdapter {
6370
6529
  ...wait > 0 && wait <= 9e5 ? { providerRetryAfterMs: wait } : {}
6371
6530
  });
6372
6531
  }
6373
- throw generateHttpError(attempt.status, attempt.errText, attempt.retryAfterMs, providerError, contextBudget.sizePressure);
6532
+ throw generateHttpError(attempt.status, attempt.errText, attempt.retryAfterMs, providerError);
6374
6533
  }
6375
6534
  } catch (error) {
6376
6535
  trace.record("connect-error", {
@@ -6419,12 +6578,21 @@ var CommandCodeAdapter = class CommandCodeAdapter extends LlmAdapter {
6419
6578
  let usage;
6420
6579
  let usageEmitted = false;
6421
6580
  let endRecorded = false;
6581
+ let protocolStopped = false;
6422
6582
  function* handle(event) {
6423
6583
  captureResponseIdentifiers(responseMetadata, event);
6584
+ if (protocol === "messages" && isRecord(event) && event.type === "message_stop") protocolStopped = true;
6424
6585
  for (const chunk of handleEvent(asm, protocol, event)) if (chunk.type === "finish") finish = chunk;
6425
6586
  else if (chunk.type === "usage") usage = chunk.usage;
6426
6587
  else yield chunk;
6427
6588
  }
6589
+ function* handleLine(line) {
6590
+ if (protocol === "openai" && line.trim().replace(/^data:\s*/, "") === "[DONE]") {
6591
+ protocolStopped = true;
6592
+ return;
6593
+ }
6594
+ yield* handle(parseStreamEventLine(line));
6595
+ }
6428
6596
  try {
6429
6597
  for (;;) {
6430
6598
  let read;
@@ -6455,7 +6623,7 @@ var CommandCodeAdapter = class CommandCodeAdapter extends LlmAdapter {
6455
6623
  buffered: buffer.length
6456
6624
  });
6457
6625
  if (idleFired) throw bilingual("TIMEOUT", `Command Code API stream from ${connection.apiBase} was idle for ${connection.streamIdleTimeoutMs}ms (no events) and was treated as a dead connection`, `Command Code API 流式响应已 ${connection.streamIdleTimeoutMs} 毫秒无任何事件,被判定为死连接——长思考模型可在设置中调大流空闲超时`);
6458
- if (buffer.trim()) yield* handle(parseStreamEventLine(buffer));
6626
+ if (buffer.trim()) yield* handleLine(buffer);
6459
6627
  break;
6460
6628
  }
6461
6629
  const text = decoder.decode(value, { stream: true });
@@ -6471,8 +6639,11 @@ var CommandCodeAdapter = class CommandCodeAdapter extends LlmAdapter {
6471
6639
  });
6472
6640
  const lines = buffer.split("\n");
6473
6641
  buffer = lines.pop() ?? "";
6474
- for (const line of lines) yield* handle(parseStreamEventLine(line));
6475
- if (finish !== void 0) break;
6642
+ for (const line of lines) {
6643
+ yield* handleLine(line);
6644
+ if (protocolStopped) break;
6645
+ }
6646
+ if (protocolStopped || protocol === "cli" && finish !== void 0) break;
6476
6647
  }
6477
6648
  if (usage !== void 0) {
6478
6649
  usageEmitted = true;
@@ -6590,7 +6761,7 @@ function parseProviderError(errText) {
6590
6761
  return { message: errText };
6591
6762
  }
6592
6763
  }
6593
- function generateHttpError(status, errText, retryAfterMs, parsed = parseProviderError(errText), sizePressure = false) {
6764
+ function generateHttpError(status, errText, retryAfterMs, parsed = parseProviderError(errText)) {
6594
6765
  const providerCode = parsed.nested === void 0 ? void 0 : parsed.code;
6595
6766
  const providerDetail = parsed.nested === void 0 ? "" : [
6596
6767
  parsed.code,
@@ -6604,11 +6775,12 @@ function generateHttpError(status, errText, retryAfterMs, parsed = parseProvider
6604
6775
  return bilingual("PROVIDER_HTTP_ERROR", `Command Code API error ${status}: this request's max_tokens is not valid for this model` + (stated ? ` (${stated})` : "") + " — the session is not oversized, so compacting it will not help; lower \"Max output tokens\" or pick a model with a larger output ceiling", `Command Code API 返回 ${status}:本次请求的 max_tokens 对该模型不合法` + (stated ? `(${stated})` : "") + "——会话内容并未超长,压缩上下文无效;请调低「最大输出 token」或改用输出上限更大的模型", { status });
6605
6776
  }
6606
6777
  if (status < 500 && isContextOverflowDetail(overflowDetail)) return bilingual(CONTEXT_WINDOW_EXCEEDED_CODE, `Command Code API error ${status}: the request exceeds the model's context window — this session is being compacted and the request retried`, `Command Code API 返回 ${status}:请求内容超出模型上下文窗口——正在压缩上下文后重试;如仍失败,请新建会话或减少上下文`, { status });
6607
- if (status === 400 && sizePressure && AMBIGUOUS_SIZE_REJECTION.test(providerDetail) && /\bprovider_error\b/i.test(providerDetail)) return bilingual(CONTEXT_WINDOW_EXCEEDED_CODE, "Command Code API error 400: the provider could not complete a request near the model context limit — compacting the session and retrying", "Command Code API 返回 400:请求接近模型上下文上限,服务商无法完成——正在压缩上下文后重试", { status });
6608
6778
  if (status === 422 && isZdrNoProviders(providerCode, providerDetail, errText)) return bilingual("PROVIDER_HTTP_ERROR", `Command Code API error 422 (${detail}): zero data retention is enforced but no ZDR-capable upstream is available for this model — turn the ZDR setting off (or use another model)`, "Command Code API 返回 422:已开启零数据保留(ZDR),但该模型当前没有可用的 ZDR 上游——请关闭 ZDR 开关,或改用其他模型", { status: 422 });
6609
6779
  if (status === 401) return bilingual("INVALID_CREDENTIAL", `Command Code API error 401 (${detail}): the API key is missing or invalid — check the key stored for COMMANDCODE_API_KEY (Models page) or the auth file`, "Command Code API 返回 401:API 密钥缺失或无效——请在设置页检查 COMMANDCODE_API_KEY 存储的密钥,或检查 auth 文件", { status: 401 });
6610
6780
  if (status === 413) return bilingual("PROVIDER_HTTP_ERROR", "Command Code API error 413: the request body exceeds the provider's size limit (the cap is undocumented, measured at about 50 MB) — the session history is too large to send, usually because of accumulated image attachments. Start a new session, or drop the image-heavy part of this one, and retry", "Command Code API 返回 413:请求体超过服务端的体积上限(官方未公开,实测约 50 MB)——会话历史过大,通常是历史图片累积所致。请新建会话,或移除本会话中图片较多的部分后重试", { status: 413 });
6611
- return new LlmError(`Command Code API error ${status}${detail === `HTTP ${status}` ? "" : ` (${detail})`}: ${errText.slice(0, 500)}`, httpErrorCode(status), {
6781
+ const diagnosticCode = parsed.code ?? /^\s*(MODEL_NOT_IN_PLAN|INSUFFICIENT_CREDITS|USAGE_EXCEEDED|PREMIUM_CREDITS_EXHAUSTED)\b/i.exec(parsed.message ?? "")?.[1];
6782
+ const diagnostic = diagnosticCode !== void 0 && /^[A-Za-z0-9_.:-]{1,80}$/.test(diagnosticCode) ? `(${diagnosticCode})` : "";
6783
+ return new LlmError(`Command Code 请求失败(HTTP ${status})${diagnostic}:` + (status === 429 ? "请求受到用量或速率限制,请稍后重试并检查账户额度。" : status === 408 ? "服务端处理超时,请稍后重试。" : status >= 500 ? "上游服务暂时无法完成请求,请稍后重试。" : "服务端拒绝了本次请求,请检查模型、套餐和请求设置。"), httpErrorCode(status), {
6612
6784
  status,
6613
6785
  ...retryAfterMs !== void 0 && retryAfterMs > 0 && retryAfterMs <= 9e5 ? { providerRetryAfterMs: retryAfterMs } : {}
6614
6786
  });
@@ -6856,13 +7028,13 @@ function handleOpenAIEvent(asm, event) {
6856
7028
  * cache_read_input_tokens, output_tokens, output_tokens_details:
6857
7029
  * { thinking_tokens } }`, plus gateway additions the meter ignores.
6858
7030
  */
6859
- function mapMessagesUsage(raw) {
7031
+ function mapMessagesUsage(raw, previous) {
6860
7032
  if (!isRecord(raw)) return void 0;
6861
- const inputTokens = numberValue(raw.input_tokens) ?? 0;
6862
- const outputTokens = numberValue(raw.output_tokens) ?? 0;
6863
- const cacheRead = numberValue(raw.cache_read_input_tokens) ?? 0;
6864
- const cacheWrite = numberValue(raw.cache_creation_input_tokens) ?? 0;
6865
- const reasoningTokens = numberValue((isRecord(raw.output_tokens_details) ? raw.output_tokens_details : void 0)?.thinking_tokens);
7033
+ const inputTokens = numberValue(raw.input_tokens) ?? previous?.inputTokens ?? 0;
7034
+ const outputTokens = numberValue(raw.output_tokens) ?? previous?.outputTokens ?? 0;
7035
+ const cacheRead = numberValue(raw.cache_read_input_tokens) ?? previous?.cacheReadTokens ?? 0;
7036
+ const cacheWrite = numberValue(raw.cache_creation_input_tokens) ?? previous?.cacheWriteTokens ?? 0;
7037
+ const reasoningTokens = numberValue((isRecord(raw.output_tokens_details) ? raw.output_tokens_details : void 0)?.thinking_tokens) ?? previous?.reasoningTokens;
6866
7038
  const usage = {
6867
7039
  inputTokens: Math.max(0, inputTokens),
6868
7040
  outputTokens,
@@ -6895,10 +7067,13 @@ function handleMessagesEvent(asm, event) {
6895
7067
  switch (event.type) {
6896
7068
  case "message_start": {
6897
7069
  const usage = mapMessagesUsage((isRecord(event.message) ? event.message : void 0)?.usage);
6898
- if (usage) chunks.push({
6899
- type: "usage",
6900
- usage
6901
- });
7070
+ if (usage) {
7071
+ asm.messagesUsage = usage;
7072
+ chunks.push({
7073
+ type: "usage",
7074
+ usage
7075
+ });
7076
+ }
6902
7077
  break;
6903
7078
  }
6904
7079
  case "content_block_start": {
@@ -7015,18 +7190,22 @@ function handleMessagesEvent(asm, event) {
7015
7190
  case "message_delta": {
7016
7191
  const reason = stringValue((isRecord(event.delta) ? event.delta : void 0)?.stop_reason);
7017
7192
  if (reason !== void 0) asm.finishReason = reason;
7018
- const usage = mapMessagesUsage(event.usage);
7019
- if (usage) chunks.push({
7020
- type: "usage",
7021
- usage
7022
- });
7193
+ const usage = mapMessagesUsage(event.usage, asm.messagesUsage);
7194
+ if (usage) {
7195
+ asm.messagesUsage = usage;
7196
+ chunks.push({
7197
+ type: "usage",
7198
+ usage
7199
+ });
7200
+ }
7201
+ break;
7202
+ }
7203
+ case "message_stop":
7023
7204
  chunks.push({
7024
7205
  type: "finish",
7025
- reason: mapFinishReason(reason)
7206
+ reason: mapFinishReason(asm.finishReason)
7026
7207
  });
7027
7208
  break;
7028
- }
7029
- case "message_stop":
7030
7209
  case "ping": break;
7031
7210
  case "error": throw streamErrorToLlmError(event.error ?? event, stringValue(event.message));
7032
7211
  }
@@ -7909,7 +8088,7 @@ function applyUsageRemote(ctx, deps) {
7909
8088
  *
7910
8089
  * @module dsh-commandcode-provider/login
7911
8090
  */
7912
- /** Give up on the browser after this long without a callback (mirrors the CLI). */
8091
+ /** 登录总期限包含浏览器回调、密钥验证与存储,不能在收到回调后撤掉保护。 */
7913
8092
  const LOGIN_TIMEOUT_MS = 12e4;
7914
8093
  /** First local port the flow tries (mirrors the CLI). */
7915
8094
  const LOGIN_START_PORT = 5959;
@@ -7947,7 +8126,7 @@ function studioBaseForApiBase(apiBase) {
7947
8126
  * tests). Mirrors the CLI's verdicts: 401 → invalid_key, other non-OK →
7948
8127
  * server_error, transport failure → network_error.
7949
8128
  */
7950
- async function validateCommandApiKey(fetchImpl, apiBase, apiKey) {
8129
+ async function validateCommandApiKey(fetchImpl, apiBase, apiKey, signal) {
7951
8130
  try {
7952
8131
  const response = await fetchImpl(`${apiBase}/alpha/whoami`, {
7953
8132
  method: "GET",
@@ -7955,8 +8134,10 @@ async function validateCommandApiKey(fetchImpl, apiBase, apiKey) {
7955
8134
  "Content-Type": "application/json",
7956
8135
  ...IDENTITY_ENCODING_HEADER,
7957
8136
  Authorization: `Bearer ${apiKey}`
7958
- }
8137
+ },
8138
+ ...signal === void 0 ? {} : { signal }
7959
8139
  });
8140
+ response.body?.cancel().catch(() => void 0);
7960
8141
  if (response.status === 401) return {
7961
8142
  valid: false,
7962
8143
  error: "invalid_key"
@@ -8002,6 +8183,7 @@ var CommandCodeLoginFlow = class {
8002
8183
  statusValue = { state: "idle" };
8003
8184
  server;
8004
8185
  timer;
8186
+ attemptAbort;
8005
8187
  /** Settle hooks of the live attempt's callback promise. */
8006
8188
  settle;
8007
8189
  /**
@@ -8071,6 +8253,7 @@ var CommandCodeLoginFlow = class {
8071
8253
  async startAttempt(targetRef) {
8072
8254
  this.teardown();
8073
8255
  const attempt = ++this.attemptSeq;
8256
+ this.attemptAbort = new AbortController();
8074
8257
  const port = await this.findPort();
8075
8258
  const expectedState = this.deps.randomToken?.(32) ?? randomBytes(32).toString("base64url");
8076
8259
  const settled = new Promise((resolve, reject) => {
@@ -8100,11 +8283,12 @@ var CommandCodeLoginFlow = class {
8100
8283
  })
8101
8284
  });
8102
8285
  this.timer = setTimeout(() => {
8286
+ if (!this.ownsAttempt(attempt)) return;
8103
8287
  this.teardown();
8104
8288
  this.setStatus({
8105
8289
  state: "failed",
8106
8290
  reason: "timeout",
8107
- message: "No browser callback arrived within the login window."
8291
+ message: "登录未在规定时间内完成,请重试。"
8108
8292
  });
8109
8293
  }, this.deps.timeoutMs ?? 12e4);
8110
8294
  this.timer.unref?.();
@@ -8272,7 +8456,8 @@ var CommandCodeLoginFlow = class {
8272
8456
  settleAttempt(json, code, body, failure, credentials) {
8273
8457
  json(code, body);
8274
8458
  const settle = this.settle;
8275
- this.teardown();
8459
+ if (failure !== void 0) this.teardown();
8460
+ else this.closeCallback();
8276
8461
  if (settle === void 0) return;
8277
8462
  if (failure !== void 0) settle.reject(failure);
8278
8463
  else if (credentials !== void 0) settle.resolve(credentials);
@@ -8289,10 +8474,11 @@ var CommandCodeLoginFlow = class {
8289
8474
  */
8290
8475
  async complete(attempt, credentials, targetRef) {
8291
8476
  if (!this.ownsAttempt(attempt)) return;
8292
- const validation = await validateCommandApiKey(this.deps.fetchImpl ?? fetch, this.readApiBase(), credentials.apiKey);
8477
+ const validation = await validateCommandApiKey(this.deps.fetchImpl ?? fetch, this.readApiBase(), credentials.apiKey, this.attemptAbort?.signal);
8293
8478
  if (!this.ownsAttempt(attempt)) return;
8294
8479
  if (!validation.valid) {
8295
8480
  const reason = validation.error === "invalid_key" ? "invalid-key" : validation.error === "network_error" ? "network" : "error";
8481
+ this.teardown();
8296
8482
  this.setStatus({
8297
8483
  state: "failed",
8298
8484
  reason,
@@ -8306,6 +8492,7 @@ var CommandCodeLoginFlow = class {
8306
8492
  await this.deps.storeKey(credentials, targetRef);
8307
8493
  } catch (error) {
8308
8494
  if (!this.ownsAttempt(attempt)) return;
8495
+ this.teardown();
8309
8496
  this.setStatus({
8310
8497
  state: "failed",
8311
8498
  reason: "unavailable",
@@ -8314,7 +8501,7 @@ var CommandCodeLoginFlow = class {
8314
8501
  return;
8315
8502
  }
8316
8503
  if (!this.ownsAttempt(attempt)) return;
8317
- this.clearTimer();
8504
+ this.teardown();
8318
8505
  this.setStatus({
8319
8506
  state: "success",
8320
8507
  userName: credentials.userName,
@@ -8329,6 +8516,7 @@ var CommandCodeLoginFlow = class {
8329
8516
  failFrom(attempt, failure) {
8330
8517
  if (!(failure instanceof LoginSettleError)) return;
8331
8518
  if (!this.ownsAttempt(attempt)) return;
8519
+ this.teardown();
8332
8520
  this.setStatus({
8333
8521
  state: "failed",
8334
8522
  reason: failure.reason,
@@ -8341,13 +8529,19 @@ var CommandCodeLoginFlow = class {
8341
8529
  this.timer = void 0;
8342
8530
  }
8343
8531
  }
8344
- /** Close the server and watchdog without touching the published status. */
8345
- teardown() {
8346
- this.clearTimer();
8532
+ /** 消费一次回调后关闭监听;保留总期限以约束后续验证。 */
8533
+ closeCallback() {
8347
8534
  closeServer(this.server);
8348
8535
  this.server = void 0;
8349
8536
  this.settle = void 0;
8350
8537
  }
8538
+ /** 结束整个尝试,同时中止验证请求,迟到结果由所有权检查拦截。 */
8539
+ teardown() {
8540
+ this.clearTimer();
8541
+ this.attemptAbort?.abort();
8542
+ this.attemptAbort = void 0;
8543
+ this.closeCallback();
8544
+ }
8351
8545
  };
8352
8546
  /** Close one loopback server without letting "not running"/"already closed" escape. */
8353
8547
  function closeServer(server) {
@@ -8665,9 +8859,8 @@ function buildCommandCodeTuiSection(deps) {
8665
8859
  * ONE draft: every one of them then parses that same draft on save, all N
8666
8860
  * write ops address the same path, and only the LAST field's op survives —
8667
8861
  * which silently rewrote the allowlist from the last catalog model instead
8668
- * of the one that was toggled. An override equal to what the array already
8669
- * says is written as a CLEAR, so toggling a model back to its inherited
8670
- * state leaves no residue.
8862
+ * of the one that was toggled. 保存显式布尔值,不能因为与白名单相同就
8863
+ * 清除用户层:清除后可能重新露出基础配置中的相反开关。
8671
8864
  */
8672
8865
  const modelField = (id, hint, group) => ({
8673
8866
  path: ["modelVisibility", id],
@@ -8681,11 +8874,9 @@ function buildCommandCodeTuiSection(deps) {
8681
8874
  return String(listed.length === 0 || listed.includes(id));
8682
8875
  },
8683
8876
  parse: (text) => {
8684
- const on = text.trim() === "true";
8685
- const listed = storedIds(deps.visibleModels());
8686
- return on === (listed.length === 0 || listed.includes(id)) ? { kind: "clear" } : {
8877
+ return {
8687
8878
  kind: "set",
8688
- value: on
8879
+ value: text.trim() === "true"
8689
8880
  };
8690
8881
  }
8691
8882
  });
@@ -9132,6 +9323,7 @@ const Config = z.object(markVolatileFields({
9132
9323
  apiKey: z.string().role("secret")
9133
9324
  })),
9134
9325
  activeAccount: z.string(),
9326
+ credentialCleanupRefs: z.array(z.string().role("credential-ref")),
9135
9327
  modelAccountRules: z.array(z.object({
9136
9328
  models: z.array(z.string()),
9137
9329
  account: z.string()
@@ -9291,7 +9483,7 @@ function apply(ctx, config) {
9291
9483
  const usageReports = async () => {
9292
9484
  const described = await pool.describeAccounts();
9293
9485
  const byId = new Map(described.map((account) => [account.slot.id, account]));
9294
- const active = selectActiveAccount(await pool.resolvedAccounts(), preferredId());
9486
+ const active = await pool.activeAccount();
9295
9487
  return { accounts: await Promise.all(slots().map(async (slot) => {
9296
9488
  const account = byId.get(slot.id);
9297
9489
  let report;