@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/CHANGELOG.md +29 -0
- package/README.md +5 -1
- package/README.zh-CN.md +6 -1
- package/lib/client.js +245 -69
- package/lib/client.js.map +1 -1
- package/lib/index.d.ts +67 -16
- package/lib/index.js +367 -175
- package/lib/index.js.map +1 -1
- package/package.json +40 -40
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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 = [
|
|
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:
|
|
1197
|
-
*
|
|
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
|
|
2949
|
-
|
|
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
|
|
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.
|
|
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.
|
|
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
|
-
*
|
|
3804
|
-
* from
|
|
3805
|
-
*
|
|
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.
|
|
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")
|
|
4138
|
-
|
|
4139
|
-
|
|
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": "
|
|
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
|
-
|
|
5485
|
-
|
|
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)
|
|
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
|
|
5794
|
-
*
|
|
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
|
|
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
|
-
|
|
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
|
|
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*
|
|
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)
|
|
6475
|
-
|
|
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)
|
|
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
|
-
|
|
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)
|
|
6899
|
-
|
|
6900
|
-
|
|
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)
|
|
7020
|
-
|
|
7021
|
-
|
|
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(
|
|
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
|
-
/**
|
|
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: "
|
|
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.
|
|
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
|
-
/**
|
|
8345
|
-
|
|
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.
|
|
8669
|
-
*
|
|
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
|
-
|
|
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:
|
|
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 =
|
|
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;
|