agent-usage-all-in-one 0.7.2 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -13
- package/README.zh-CN.md +2 -7
- package/dist/cli.js +152 -693
- package/dist/cli.js.map +1 -1
- package/dist/web/_app/immutable/assets/2.B3WVopjI.css +1 -0
- package/dist/web/_app/immutable/chunks/{CkDl_J6h.js → BbLPJCwg.js} +2 -2
- package/dist/web/_app/immutable/chunks/Bwn50i54.js +1 -0
- package/dist/web/_app/immutable/chunks/CiAz1kOc.js +1 -0
- package/dist/web/_app/immutable/entry/app.Z7FhDi1v.js +2 -0
- package/dist/web/_app/immutable/entry/start.DEVa4z2m.js +1 -0
- package/dist/web/_app/immutable/nodes/0.BLRcVrxx.js +1 -0
- package/dist/web/_app/immutable/nodes/1.oDSuYnui.js +1 -0
- package/dist/web/_app/immutable/nodes/2.8Hl62Zo_.js +26 -0
- package/dist/web/_app/version.json +1 -1
- package/dist/web/index.html +9 -9
- package/package.json +1 -1
- package/dist/web/_app/immutable/assets/2.RN1Pn-E8.css +0 -1
- package/dist/web/_app/immutable/chunks/BxFVQ2kE.js +0 -1
- package/dist/web/_app/immutable/chunks/YtE49JQT.js +0 -1
- package/dist/web/_app/immutable/entry/app.DoE5iRPD.js +0 -2
- package/dist/web/_app/immutable/entry/start.-kFQj1Re.js +0 -1
- package/dist/web/_app/immutable/nodes/0.Bc_BSNVt.js +0 -1
- package/dist/web/_app/immutable/nodes/1.CO2k9heq.js +0 -1
- package/dist/web/_app/immutable/nodes/2.C49HhYIP.js +0 -28
package/dist/cli.js
CHANGED
|
@@ -1450,382 +1450,6 @@ var init_retail_pricing = __esm({
|
|
|
1450
1450
|
}
|
|
1451
1451
|
});
|
|
1452
1452
|
|
|
1453
|
-
// src/core/plan-pricing.ts
|
|
1454
|
-
function buildBillingPeriod(subscription, summary, comparisonCurrency, rates) {
|
|
1455
|
-
if (!summary) return null;
|
|
1456
|
-
const start = new Date(summary.start).getTime();
|
|
1457
|
-
const end = new Date(summary.end).getTime();
|
|
1458
|
-
const observedThrough = new Date(summary.observedThrough).getTime();
|
|
1459
|
-
const totalDays = (end - start) / MILLISECONDS_PER_DAY;
|
|
1460
|
-
const elapsedDays = Math.max(0, Math.min(observedThrough, end) - start) / MILLISECONDS_PER_DAY;
|
|
1461
|
-
const periodCost = planMoneyAmount(
|
|
1462
|
-
preciseAmount(subscription.amount),
|
|
1463
|
-
subscription.currency,
|
|
1464
|
-
comparisonCurrency,
|
|
1465
|
-
// The period's own rate evidence first, so a short rolling window cannot
|
|
1466
|
-
// leave a cycle amount unconverted.
|
|
1467
|
-
[...summary.retailEquivalent.exchangeRates, ...rates],
|
|
1468
|
-
summary.observedThrough
|
|
1469
|
-
);
|
|
1470
|
-
const retailAmount = summary.retailEquivalent.status === "available" ? summary.retailEquivalent.amount : null;
|
|
1471
|
-
const breakEvenRatio = periodCost.amount !== null && periodCost.amount > 0 && retailAmount !== null ? preciseAmount(retailAmount / periodCost.amount) : null;
|
|
1472
|
-
return {
|
|
1473
|
-
start: summary.start,
|
|
1474
|
-
end: summary.end,
|
|
1475
|
-
elapsedDays: preciseAmount(elapsedDays),
|
|
1476
|
-
totalDays: preciseAmount(totalDays),
|
|
1477
|
-
progress: totalDays > 0 ? preciseAmount(Math.min(1, elapsedDays / totalDays)) : 0,
|
|
1478
|
-
periodCost,
|
|
1479
|
-
recordedTokens: summary.observationCount > 0 ? summary.recordedTokens : null,
|
|
1480
|
-
retailEquivalent: summary.retailEquivalent,
|
|
1481
|
-
breakEvenRatio,
|
|
1482
|
-
ratioBound: ratioBoundFor(breakEvenRatio, summary.retailEquivalent.pricingCoverage)
|
|
1483
|
-
};
|
|
1484
|
-
}
|
|
1485
|
-
function planCatalogEntry(catalog, id) {
|
|
1486
|
-
return catalog.entries.find((entry) => entry.id === id) ?? null;
|
|
1487
|
-
}
|
|
1488
|
-
function planCatalogEntriesForDomain(catalog, providerId, billingDomainId) {
|
|
1489
|
-
return catalog.entries.filter(
|
|
1490
|
-
(entry) => entry.providerId === providerId && entry.billingDomainId === billingDomainId
|
|
1491
|
-
);
|
|
1492
|
-
}
|
|
1493
|
-
function addMonths(date, months) {
|
|
1494
|
-
const day = date.getUTCDate();
|
|
1495
|
-
const shifted = new Date(
|
|
1496
|
-
Date.UTC(
|
|
1497
|
-
date.getUTCFullYear(),
|
|
1498
|
-
date.getUTCMonth() + months,
|
|
1499
|
-
1,
|
|
1500
|
-
date.getUTCHours(),
|
|
1501
|
-
date.getUTCMinutes(),
|
|
1502
|
-
date.getUTCSeconds(),
|
|
1503
|
-
date.getUTCMilliseconds()
|
|
1504
|
-
)
|
|
1505
|
-
);
|
|
1506
|
-
const lastDayOfMonth = new Date(
|
|
1507
|
-
Date.UTC(shifted.getUTCFullYear(), shifted.getUTCMonth() + 1, 0)
|
|
1508
|
-
).getUTCDate();
|
|
1509
|
-
shifted.setUTCDate(Math.min(day, lastDayOfMonth));
|
|
1510
|
-
return shifted;
|
|
1511
|
-
}
|
|
1512
|
-
function billingPeriodContaining(anchorDate, billingPeriod, at) {
|
|
1513
|
-
const anchor = new Date(anchorDate.length === 10 ? `${anchorDate}T00:00:00.000Z` : anchorDate);
|
|
1514
|
-
if (Number.isNaN(anchor.getTime())) return null;
|
|
1515
|
-
const step = billingPeriod === "monthly" ? 1 : 12;
|
|
1516
|
-
const monthsApart = (at.getUTCFullYear() - anchor.getUTCFullYear()) * 12 + (at.getUTCMonth() - anchor.getUTCMonth());
|
|
1517
|
-
let index = Math.floor(monthsApart / step);
|
|
1518
|
-
let start = addMonths(anchor, index * step);
|
|
1519
|
-
while (start.getTime() > at.getTime()) {
|
|
1520
|
-
index -= 1;
|
|
1521
|
-
start = addMonths(anchor, index * step);
|
|
1522
|
-
}
|
|
1523
|
-
let end = addMonths(anchor, (index + 1) * step);
|
|
1524
|
-
while (end.getTime() <= at.getTime()) {
|
|
1525
|
-
index += 1;
|
|
1526
|
-
start = end;
|
|
1527
|
-
end = addMonths(anchor, (index + 1) * step);
|
|
1528
|
-
}
|
|
1529
|
-
return { start, end };
|
|
1530
|
-
}
|
|
1531
|
-
function windowDays(start, end) {
|
|
1532
|
-
const span = new Date(end).getTime() - new Date(start).getTime();
|
|
1533
|
-
return span > 0 ? span / MILLISECONDS_PER_DAY : 0;
|
|
1534
|
-
}
|
|
1535
|
-
function proratePlanPrice(amount, billingPeriod, days) {
|
|
1536
|
-
return amount * days / PLAN_PERIOD_DAYS[billingPeriod];
|
|
1537
|
-
}
|
|
1538
|
-
function convertPlanAmount(amount, currency, comparisonCurrency, rates, end) {
|
|
1539
|
-
if (currency.toUpperCase() === comparisonCurrency.toUpperCase()) {
|
|
1540
|
-
return { amount, reason: null, rate: null };
|
|
1541
|
-
}
|
|
1542
|
-
const rate = rates.find(
|
|
1543
|
-
(candidate) => candidate.baseCurrency.toUpperCase() === currency.toUpperCase() && candidate.quoteCurrency.toUpperCase() === comparisonCurrency.toUpperCase()
|
|
1544
|
-
);
|
|
1545
|
-
if (!rate) return { amount: null, reason: "missing-rate", rate: null };
|
|
1546
|
-
if (new Date(end).getTime() - new Date(rate.observedAt).getTime() > STALE_RATE_MILLISECONDS) {
|
|
1547
|
-
return { amount: null, reason: "stale-rate", rate };
|
|
1548
|
-
}
|
|
1549
|
-
return { amount: amount * rate.rate, reason: null, rate };
|
|
1550
|
-
}
|
|
1551
|
-
function preciseAmount(value) {
|
|
1552
|
-
return Number(value.toPrecision(12));
|
|
1553
|
-
}
|
|
1554
|
-
function planMoneyAmount(nativeAmount, nativeCurrency, comparisonCurrency, rates, end) {
|
|
1555
|
-
const converted = convertPlanAmount(nativeAmount, nativeCurrency, comparisonCurrency, rates, end);
|
|
1556
|
-
return {
|
|
1557
|
-
status: converted.amount === null ? "unavailable" : "available",
|
|
1558
|
-
amount: converted.amount === null ? null : preciseAmount(converted.amount),
|
|
1559
|
-
nativeAmount,
|
|
1560
|
-
nativeCurrency,
|
|
1561
|
-
comparisonCurrency,
|
|
1562
|
-
conversionUnavailableReason: converted.reason,
|
|
1563
|
-
exchangeRates: converted.rate ? [converted.rate] : []
|
|
1564
|
-
};
|
|
1565
|
-
}
|
|
1566
|
-
function ratioBoundFor(ratio, pricingCoverage) {
|
|
1567
|
-
if (ratio === null) return "unavailable";
|
|
1568
|
-
return pricingCoverage !== null && pricingCoverage < 0.999 ? "lower" : "exact";
|
|
1569
|
-
}
|
|
1570
|
-
function unitPricePerMillion(amount, tokens) {
|
|
1571
|
-
if (amount === null || tokens <= 0) return null;
|
|
1572
|
-
return preciseAmount(amount / (tokens / 1e6));
|
|
1573
|
-
}
|
|
1574
|
-
function buildWorkbenchPlanValue(options) {
|
|
1575
|
-
const { comparisonCurrency, start, end, rates } = options;
|
|
1576
|
-
const days = windowDays(start, end);
|
|
1577
|
-
const subscriptionByDomain = new Map(
|
|
1578
|
-
options.subscriptions.map((subscription) => [
|
|
1579
|
-
`${subscription.providerId}:${subscription.billingDomainId}`,
|
|
1580
|
-
subscription
|
|
1581
|
-
])
|
|
1582
|
-
);
|
|
1583
|
-
const entries = [];
|
|
1584
|
-
const metered = [];
|
|
1585
|
-
const unconfigured = [];
|
|
1586
|
-
for (const domain of options.domains) {
|
|
1587
|
-
const subscription = subscriptionByDomain.get(`${domain.providerId}:${domain.billingDomainId}`);
|
|
1588
|
-
if (!subscription) {
|
|
1589
|
-
if (domain.actualCost.records > 0) {
|
|
1590
|
-
metered.push({
|
|
1591
|
-
providerId: domain.providerId,
|
|
1592
|
-
providerDisplayName: domain.providerDisplayName,
|
|
1593
|
-
billingDomainId: domain.billingDomainId,
|
|
1594
|
-
billingDomainDisplayName: domain.billingDomainDisplayName,
|
|
1595
|
-
recordedTokens: domain.observationCount > 0 ? domain.recordedTokens : null,
|
|
1596
|
-
actualCost: domain.actualCost,
|
|
1597
|
-
retailEquivalent: domain.retailEquivalent
|
|
1598
|
-
});
|
|
1599
|
-
continue;
|
|
1600
|
-
}
|
|
1601
|
-
if (domain.observationCount > 0) {
|
|
1602
|
-
unconfigured.push({
|
|
1603
|
-
providerId: domain.providerId,
|
|
1604
|
-
providerDisplayName: domain.providerDisplayName,
|
|
1605
|
-
billingDomainId: domain.billingDomainId,
|
|
1606
|
-
billingDomainDisplayName: domain.billingDomainDisplayName,
|
|
1607
|
-
recordedTokens: domain.recordedTokens
|
|
1608
|
-
});
|
|
1609
|
-
}
|
|
1610
|
-
continue;
|
|
1611
|
-
}
|
|
1612
|
-
const windowPlanCost = planMoneyAmount(
|
|
1613
|
-
preciseAmount(proratePlanPrice(subscription.amount, subscription.billingPeriod, days)),
|
|
1614
|
-
subscription.currency,
|
|
1615
|
-
comparisonCurrency,
|
|
1616
|
-
rates,
|
|
1617
|
-
end
|
|
1618
|
-
);
|
|
1619
|
-
const retail = domain.retailEquivalent;
|
|
1620
|
-
const retailAmount = retail.status === "available" ? retail.amount : null;
|
|
1621
|
-
const valueRatio = windowPlanCost.amount !== null && windowPlanCost.amount > 0 && retailAmount !== null ? preciseAmount(retailAmount / windowPlanCost.amount) : null;
|
|
1622
|
-
const ratioBound = ratioBoundFor(valueRatio, retail.pricingCoverage);
|
|
1623
|
-
const billingPeriod = buildBillingPeriod(
|
|
1624
|
-
subscription,
|
|
1625
|
-
options.billingPeriods?.get(`${domain.providerId}:${domain.billingDomainId}`),
|
|
1626
|
-
comparisonCurrency,
|
|
1627
|
-
rates
|
|
1628
|
-
);
|
|
1629
|
-
entries.push({
|
|
1630
|
-
providerId: domain.providerId,
|
|
1631
|
-
providerDisplayName: domain.providerDisplayName,
|
|
1632
|
-
billingDomainId: domain.billingDomainId,
|
|
1633
|
-
billingDomainDisplayName: domain.billingDomainDisplayName,
|
|
1634
|
-
includedInHeadline: domain.includedInHeadline,
|
|
1635
|
-
plan: {
|
|
1636
|
-
planId: subscription.planId,
|
|
1637
|
-
displayName: subscription.displayName,
|
|
1638
|
-
amount: subscription.amount,
|
|
1639
|
-
currency: subscription.currency,
|
|
1640
|
-
billingPeriod: subscription.billingPeriod,
|
|
1641
|
-
anchorDate: subscription.anchorDate,
|
|
1642
|
-
priceSource: subscription.priceSource,
|
|
1643
|
-
updatedAt: subscription.updatedAt
|
|
1644
|
-
},
|
|
1645
|
-
windowDays: preciseAmount(days),
|
|
1646
|
-
windowPlanCost,
|
|
1647
|
-
billingPeriod,
|
|
1648
|
-
recordedTokens: domain.observationCount > 0 ? domain.recordedTokens : null,
|
|
1649
|
-
retailEquivalent: retail,
|
|
1650
|
-
valueRatio,
|
|
1651
|
-
ratioBound,
|
|
1652
|
-
status: valueRatio === null ? "unavailable" : ratioBound === "lower" ? "partial" : "available",
|
|
1653
|
-
effectiveUnitPrice: unitPricePerMillion(windowPlanCost.amount, domain.recordedTokens),
|
|
1654
|
-
retailUnitPrice: unitPricePerMillion(retailAmount, retail.pricedTokens),
|
|
1655
|
-
pricingCoverage: retail.pricingCoverage,
|
|
1656
|
-
authorities: domain.authorities,
|
|
1657
|
-
lastObservedAt: domain.lastObservedAt
|
|
1658
|
-
});
|
|
1659
|
-
}
|
|
1660
|
-
const rank = (entry) => entry.valueRatio ?? -1;
|
|
1661
|
-
entries.sort(
|
|
1662
|
-
(left, right) => rank(right) - rank(left) || `${left.providerId}:${left.billingDomainId}`.localeCompare(
|
|
1663
|
-
`${right.providerId}:${right.billingDomainId}`
|
|
1664
|
-
)
|
|
1665
|
-
);
|
|
1666
|
-
metered.sort(
|
|
1667
|
-
(left, right) => `${left.providerId}:${left.billingDomainId}`.localeCompare(
|
|
1668
|
-
`${right.providerId}:${right.billingDomainId}`
|
|
1669
|
-
)
|
|
1670
|
-
);
|
|
1671
|
-
unconfigured.sort(
|
|
1672
|
-
(left, right) => right.recordedTokens - left.recordedTokens || `${left.providerId}:${left.billingDomainId}`.localeCompare(
|
|
1673
|
-
`${right.providerId}:${right.billingDomainId}`
|
|
1674
|
-
)
|
|
1675
|
-
);
|
|
1676
|
-
return {
|
|
1677
|
-
windowDays: preciseAmount(days),
|
|
1678
|
-
comparisonCurrency,
|
|
1679
|
-
catalogVersion: SUBSCRIPTION_PLAN_CATALOG.version,
|
|
1680
|
-
entries,
|
|
1681
|
-
meteredDomains: metered,
|
|
1682
|
-
unconfiguredDomains: unconfigured
|
|
1683
|
-
};
|
|
1684
|
-
}
|
|
1685
|
-
var PLAN_PERIOD_DAYS, MILLISECONDS_PER_DAY, STALE_RATE_MILLISECONDS, SUBSCRIPTION_PLAN_CATALOG;
|
|
1686
|
-
var init_plan_pricing = __esm({
|
|
1687
|
-
"src/core/plan-pricing.ts"() {
|
|
1688
|
-
"use strict";
|
|
1689
|
-
PLAN_PERIOD_DAYS = {
|
|
1690
|
-
monthly: 365.25 / 12,
|
|
1691
|
-
annual: 365.25
|
|
1692
|
-
};
|
|
1693
|
-
MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1e3;
|
|
1694
|
-
STALE_RATE_MILLISECONDS = 7 * MILLISECONDS_PER_DAY;
|
|
1695
|
-
SUBSCRIPTION_PLAN_CATALOG = {
|
|
1696
|
-
version: "2026-08-30",
|
|
1697
|
-
entries: [
|
|
1698
|
-
{
|
|
1699
|
-
id: "claude-pro-monthly",
|
|
1700
|
-
providerId: "claude-code",
|
|
1701
|
-
billingDomainId: "subscription",
|
|
1702
|
-
displayName: "Claude Pro",
|
|
1703
|
-
amount: 20,
|
|
1704
|
-
currency: "USD",
|
|
1705
|
-
billingPeriod: "monthly",
|
|
1706
|
-
source: {
|
|
1707
|
-
title: "Claude plans and pricing",
|
|
1708
|
-
url: "https://claude.com/pricing",
|
|
1709
|
-
retrievedAt: "2026-08-30"
|
|
1710
|
-
}
|
|
1711
|
-
},
|
|
1712
|
-
{
|
|
1713
|
-
id: "claude-pro-annual",
|
|
1714
|
-
providerId: "claude-code",
|
|
1715
|
-
billingDomainId: "subscription",
|
|
1716
|
-
displayName: "Claude Pro (annual billing)",
|
|
1717
|
-
amount: 17 * 12,
|
|
1718
|
-
currency: "USD",
|
|
1719
|
-
billingPeriod: "annual",
|
|
1720
|
-
source: {
|
|
1721
|
-
title: "Claude plans and pricing",
|
|
1722
|
-
url: "https://claude.com/pricing",
|
|
1723
|
-
retrievedAt: "2026-08-30"
|
|
1724
|
-
}
|
|
1725
|
-
},
|
|
1726
|
-
{
|
|
1727
|
-
id: "claude-max-5x",
|
|
1728
|
-
providerId: "claude-code",
|
|
1729
|
-
billingDomainId: "subscription",
|
|
1730
|
-
displayName: "Claude Max 5x",
|
|
1731
|
-
amount: 100,
|
|
1732
|
-
currency: "USD",
|
|
1733
|
-
billingPeriod: "monthly",
|
|
1734
|
-
source: {
|
|
1735
|
-
title: "What is the Max plan?",
|
|
1736
|
-
url: "https://support.claude.com/en/articles/11049741-what-is-the-max-plan",
|
|
1737
|
-
retrievedAt: "2026-08-30"
|
|
1738
|
-
}
|
|
1739
|
-
},
|
|
1740
|
-
{
|
|
1741
|
-
id: "claude-max-20x",
|
|
1742
|
-
providerId: "claude-code",
|
|
1743
|
-
billingDomainId: "subscription",
|
|
1744
|
-
displayName: "Claude Max 20x",
|
|
1745
|
-
amount: 200,
|
|
1746
|
-
currency: "USD",
|
|
1747
|
-
billingPeriod: "monthly",
|
|
1748
|
-
source: {
|
|
1749
|
-
title: "What is the Max plan?",
|
|
1750
|
-
url: "https://support.claude.com/en/articles/11049741-what-is-the-max-plan",
|
|
1751
|
-
retrievedAt: "2026-08-30"
|
|
1752
|
-
}
|
|
1753
|
-
},
|
|
1754
|
-
{
|
|
1755
|
-
id: "chatgpt-plus",
|
|
1756
|
-
providerId: "codex",
|
|
1757
|
-
billingDomainId: "subscription",
|
|
1758
|
-
displayName: "ChatGPT Plus",
|
|
1759
|
-
amount: 20,
|
|
1760
|
-
currency: "USD",
|
|
1761
|
-
billingPeriod: "monthly",
|
|
1762
|
-
source: {
|
|
1763
|
-
title: "ChatGPT pricing",
|
|
1764
|
-
url: "https://chatgpt.com/pricing/",
|
|
1765
|
-
retrievedAt: "2026-08-30"
|
|
1766
|
-
}
|
|
1767
|
-
},
|
|
1768
|
-
{
|
|
1769
|
-
id: "chatgpt-pro-100",
|
|
1770
|
-
providerId: "codex",
|
|
1771
|
-
billingDomainId: "subscription",
|
|
1772
|
-
displayName: "ChatGPT Pro (5x)",
|
|
1773
|
-
amount: 100,
|
|
1774
|
-
currency: "USD",
|
|
1775
|
-
billingPeriod: "monthly",
|
|
1776
|
-
source: {
|
|
1777
|
-
title: "About ChatGPT Pro tiers",
|
|
1778
|
-
url: "https://help.openai.com/en/articles/9793128-about-chatgpt-pro-tiers",
|
|
1779
|
-
retrievedAt: "2026-08-30"
|
|
1780
|
-
}
|
|
1781
|
-
},
|
|
1782
|
-
{
|
|
1783
|
-
id: "chatgpt-pro-200",
|
|
1784
|
-
providerId: "codex",
|
|
1785
|
-
billingDomainId: "subscription",
|
|
1786
|
-
displayName: "ChatGPT Pro (20x)",
|
|
1787
|
-
amount: 200,
|
|
1788
|
-
currency: "USD",
|
|
1789
|
-
billingPeriod: "monthly",
|
|
1790
|
-
source: {
|
|
1791
|
-
title: "About ChatGPT Pro tiers",
|
|
1792
|
-
url: "https://help.openai.com/en/articles/9793128-about-chatgpt-pro-tiers",
|
|
1793
|
-
retrievedAt: "2026-08-30"
|
|
1794
|
-
}
|
|
1795
|
-
},
|
|
1796
|
-
{
|
|
1797
|
-
id: "chatgpt-business-seat",
|
|
1798
|
-
providerId: "codex",
|
|
1799
|
-
billingDomainId: "subscription",
|
|
1800
|
-
displayName: "ChatGPT Business (one seat)",
|
|
1801
|
-
amount: 25,
|
|
1802
|
-
currency: "USD",
|
|
1803
|
-
billingPeriod: "monthly",
|
|
1804
|
-
source: {
|
|
1805
|
-
title: "ChatGPT Business pricing",
|
|
1806
|
-
url: "https://openai.com/business/chatgpt-pricing/",
|
|
1807
|
-
retrievedAt: "2026-08-30"
|
|
1808
|
-
}
|
|
1809
|
-
},
|
|
1810
|
-
{
|
|
1811
|
-
id: "opencode-go-monthly",
|
|
1812
|
-
providerId: "opencode-go",
|
|
1813
|
-
billingDomainId: "go-subscription",
|
|
1814
|
-
displayName: "OpenCode Go",
|
|
1815
|
-
amount: 10,
|
|
1816
|
-
currency: "USD",
|
|
1817
|
-
billingPeriod: "monthly",
|
|
1818
|
-
source: {
|
|
1819
|
-
title: "OpenCode Go",
|
|
1820
|
-
url: "https://opencode.ai/go",
|
|
1821
|
-
retrievedAt: "2026-08-30"
|
|
1822
|
-
}
|
|
1823
|
-
}
|
|
1824
|
-
]
|
|
1825
|
-
};
|
|
1826
|
-
}
|
|
1827
|
-
});
|
|
1828
|
-
|
|
1829
1453
|
// src/core/usage-application.ts
|
|
1830
1454
|
import { randomUUID } from "crypto";
|
|
1831
1455
|
function safeConnectorFailure(error) {
|
|
@@ -1946,7 +1570,6 @@ var init_usage_application = __esm({
|
|
|
1946
1570
|
init_redaction();
|
|
1947
1571
|
init_usage_export();
|
|
1948
1572
|
init_retail_pricing();
|
|
1949
|
-
init_plan_pricing();
|
|
1950
1573
|
UsageApplication = class {
|
|
1951
1574
|
#repository;
|
|
1952
1575
|
#connectors;
|
|
@@ -1961,7 +1584,6 @@ var init_usage_application = __esm({
|
|
|
1961
1584
|
#startAtLoginManager;
|
|
1962
1585
|
#basePriceCatalog;
|
|
1963
1586
|
#priceCatalog;
|
|
1964
|
-
#planCatalog;
|
|
1965
1587
|
#refreshPromise = null;
|
|
1966
1588
|
#refreshMode = null;
|
|
1967
1589
|
#backgroundPromise = null;
|
|
@@ -1984,7 +1606,6 @@ var init_usage_application = __esm({
|
|
|
1984
1606
|
this.#startAtLoginManager = options.startAtLoginManager;
|
|
1985
1607
|
this.#basePriceCatalog = options.priceCatalog === void 0 ? OFFICIAL_PRICING_CATALOG : options.priceCatalog;
|
|
1986
1608
|
this.#priceCatalog = this.#resolvePriceCatalog();
|
|
1987
|
-
this.#planCatalog = options.planCatalog ?? SUBSCRIPTION_PLAN_CATALOG;
|
|
1988
1609
|
this.#processingStatus = createProcessingStatus(this.#clock().toISOString(), false);
|
|
1989
1610
|
}
|
|
1990
1611
|
#resolvePriceCatalog() {
|
|
@@ -2290,54 +1911,6 @@ var init_usage_application = __esm({
|
|
|
2290
1911
|
connectors: this.#repository.getConnectorRuntimeStates()
|
|
2291
1912
|
};
|
|
2292
1913
|
}
|
|
2293
|
-
async getPlanSettings() {
|
|
2294
|
-
return {
|
|
2295
|
-
catalogVersion: this.#planCatalog.version,
|
|
2296
|
-
domains: this.#planEligibleDomains(),
|
|
2297
|
-
subscriptions: this.#repository.getPlanSubscriptions()
|
|
2298
|
-
};
|
|
2299
|
-
}
|
|
2300
|
-
async updatePlanSubscription(input) {
|
|
2301
|
-
const domain = this.#planEligibleDomains().find(
|
|
2302
|
-
(candidate) => candidate.providerId === input.providerId && candidate.billingDomainId === input.billingDomainId
|
|
2303
|
-
);
|
|
2304
|
-
if (!domain) throw new Error("Unknown subscription billing domain");
|
|
2305
|
-
if (input.plan === null) {
|
|
2306
|
-
this.#repository.deletePlanSubscription(input.providerId, input.billingDomainId);
|
|
2307
|
-
return this.getPlanSettings();
|
|
2308
|
-
}
|
|
2309
|
-
const preset = input.plan.planId ? planCatalogEntry(this.#planCatalog, input.plan.planId) : null;
|
|
2310
|
-
if (input.plan.planId && !preset) throw new Error("Unknown plan preset");
|
|
2311
|
-
if (preset && (preset.providerId !== input.providerId || preset.billingDomainId !== input.billingDomainId)) {
|
|
2312
|
-
throw new Error("Plan preset belongs to another billing domain");
|
|
2313
|
-
}
|
|
2314
|
-
const amount = input.plan.amount ?? preset?.amount;
|
|
2315
|
-
if (amount === void 0) throw new Error("A plan price is required");
|
|
2316
|
-
if (!Number.isFinite(amount) || amount <= 0) {
|
|
2317
|
-
throw new Error("A plan price must be a positive amount");
|
|
2318
|
-
}
|
|
2319
|
-
const currency = (input.plan.currency ?? preset?.currency ?? "USD").toUpperCase();
|
|
2320
|
-
if (!/^[A-Z]{3}$/.test(currency)) throw new Error("A plan currency must be a 3-letter code");
|
|
2321
|
-
const billingPeriod = input.plan.billingPeriod ?? preset?.billingPeriod ?? "monthly";
|
|
2322
|
-
const anchorDate = input.plan.anchorDate ?? null;
|
|
2323
|
-
if (anchorDate !== null && Number.isNaN((/* @__PURE__ */ new Date(`${anchorDate}T00:00:00.000Z`)).getTime())) {
|
|
2324
|
-
throw new Error("A renewal date must be a calendar date");
|
|
2325
|
-
}
|
|
2326
|
-
const overridesPreset = preset !== null && (amount !== preset.amount || currency !== preset.currency.toUpperCase() || billingPeriod !== preset.billingPeriod);
|
|
2327
|
-
this.#repository.savePlanSubscription({
|
|
2328
|
-
providerId: input.providerId,
|
|
2329
|
-
billingDomainId: input.billingDomainId,
|
|
2330
|
-
planId: preset?.id ?? null,
|
|
2331
|
-
displayName: preset?.displayName ?? "",
|
|
2332
|
-
amount,
|
|
2333
|
-
currency,
|
|
2334
|
-
billingPeriod,
|
|
2335
|
-
anchorDate,
|
|
2336
|
-
priceSource: preset && !overridesPreset ? "catalog-preset" : "user-entered",
|
|
2337
|
-
updatedAt: this.#clock().toISOString()
|
|
2338
|
-
});
|
|
2339
|
-
return this.getPlanSettings();
|
|
2340
|
-
}
|
|
2341
1914
|
async getCustomModelRates() {
|
|
2342
1915
|
return this.#repository.getCustomModelRates?.() ?? [];
|
|
2343
1916
|
}
|
|
@@ -2389,35 +1962,6 @@ var init_usage_application = __esm({
|
|
|
2389
1962
|
}
|
|
2390
1963
|
return deleted;
|
|
2391
1964
|
}
|
|
2392
|
-
/**
|
|
2393
|
-
* A billing domain can carry a plan price when its connector does not report
|
|
2394
|
-
* an actual metered charge. Metered domains keep their own billed amounts and
|
|
2395
|
-
* never receive a declared subscription price.
|
|
2396
|
-
*/
|
|
2397
|
-
#planEligibleDomains() {
|
|
2398
|
-
const domains = /* @__PURE__ */ new Map();
|
|
2399
|
-
for (const definition of this.#connectorDefinitions) {
|
|
2400
|
-
if (definition.expectedCoverage?.includes("actual-cost")) continue;
|
|
2401
|
-
const key = `${definition.target.provider.id}:${definition.target.billingDomain.id}`;
|
|
2402
|
-
if (domains.has(key)) continue;
|
|
2403
|
-
domains.set(key, {
|
|
2404
|
-
providerId: definition.target.provider.id,
|
|
2405
|
-
providerDisplayName: definition.target.provider.displayName,
|
|
2406
|
-
billingDomainId: definition.target.billingDomain.id,
|
|
2407
|
-
billingDomainDisplayName: definition.target.billingDomain.displayName,
|
|
2408
|
-
presets: planCatalogEntriesForDomain(
|
|
2409
|
-
this.#planCatalog,
|
|
2410
|
-
definition.target.provider.id,
|
|
2411
|
-
definition.target.billingDomain.id
|
|
2412
|
-
)
|
|
2413
|
-
});
|
|
2414
|
-
}
|
|
2415
|
-
return [...domains.values()].sort(
|
|
2416
|
-
(left, right) => `${left.providerId}:${left.billingDomainId}`.localeCompare(
|
|
2417
|
-
`${right.providerId}:${right.billingDomainId}`
|
|
2418
|
-
)
|
|
2419
|
-
);
|
|
2420
|
-
}
|
|
2421
1965
|
async #sendNotificationTransitions() {
|
|
2422
1966
|
if (!this.#notifier) return;
|
|
2423
1967
|
const overview = this.#repository.getOverview(this.#clock());
|
|
@@ -2566,6 +2110,12 @@ var init_usage_application = __esm({
|
|
|
2566
2110
|
async getOverview(query = {}) {
|
|
2567
2111
|
return this.#repository.getOverview(this.#clock(), query);
|
|
2568
2112
|
}
|
|
2113
|
+
async getUsageWall(query = {}) {
|
|
2114
|
+
if (!this.#repository.getUsageWall) {
|
|
2115
|
+
throw new Error("Usage wall is unavailable");
|
|
2116
|
+
}
|
|
2117
|
+
return this.#repository.getUsageWall(this.#clock(), query);
|
|
2118
|
+
}
|
|
2569
2119
|
async getAgentProviderIndex() {
|
|
2570
2120
|
const now = this.#clock();
|
|
2571
2121
|
return this.#repository.getAgentProviderIndex?.(now) ?? pickAgentProviderIndex(this.#repository.getOverview(now));
|
|
@@ -7452,6 +7002,16 @@ async function startLocalServer(options) {
|
|
|
7452
7002
|
sendJson(response, 200, await options.application.getOverview(query));
|
|
7453
7003
|
return;
|
|
7454
7004
|
}
|
|
7005
|
+
if (request.method === "GET" && requestUrl.pathname === "/api/usage-wall") {
|
|
7006
|
+
sendJson(
|
|
7007
|
+
response,
|
|
7008
|
+
200,
|
|
7009
|
+
await options.application.getUsageWall({
|
|
7010
|
+
timeZone: requestUrl.searchParams.get("timeZone") ?? void 0
|
|
7011
|
+
})
|
|
7012
|
+
);
|
|
7013
|
+
return;
|
|
7014
|
+
}
|
|
7455
7015
|
if (request.method === "POST" && requestUrl.pathname === "/api/refresh") {
|
|
7456
7016
|
if (authentication === "browser" && request.headers.origin !== origin) {
|
|
7457
7017
|
sendJson(response, 403, { error: "invalid-origin" });
|
|
@@ -7516,19 +7076,6 @@ async function startLocalServer(options) {
|
|
|
7516
7076
|
sendJson(response, 200, await options.application.clearData(input));
|
|
7517
7077
|
return;
|
|
7518
7078
|
}
|
|
7519
|
-
if (request.method === "GET" && requestUrl.pathname === "/api/plans") {
|
|
7520
|
-
sendJson(response, 200, await options.application.getPlanSettings());
|
|
7521
|
-
return;
|
|
7522
|
-
}
|
|
7523
|
-
if (request.method === "PATCH" && requestUrl.pathname === "/api/plans") {
|
|
7524
|
-
if (!validMutationOrigin(authentication, request, origin)) {
|
|
7525
|
-
sendJson(response, 403, { error: "invalid-origin" });
|
|
7526
|
-
return;
|
|
7527
|
-
}
|
|
7528
|
-
const input = planSubscriptionSchema.parse(await readJsonBody(request));
|
|
7529
|
-
sendJson(response, 200, await options.application.updatePlanSubscription(input));
|
|
7530
|
-
return;
|
|
7531
|
-
}
|
|
7532
7079
|
if (request.method === "GET" && requestUrl.pathname === "/api/custom-rates") {
|
|
7533
7080
|
const rates = await options.application.getCustomModelRates();
|
|
7534
7081
|
sendJson(response, 200, { rates });
|
|
@@ -7790,7 +7337,7 @@ function sendHtml(response, status, body) {
|
|
|
7790
7337
|
response.writeHead(status, { "content-type": "text/html; charset=utf-8" });
|
|
7791
7338
|
response.end(body);
|
|
7792
7339
|
}
|
|
7793
|
-
var SESSION_COOKIE, connectorActionSchema, usageQuerySchema, monitoringSettingsSchema,
|
|
7340
|
+
var SESSION_COOKIE, connectorActionSchema, usageQuerySchema, monitoringSettingsSchema, customModelRateSchema, clearDataSchema, hardRebuildSchema;
|
|
7794
7341
|
var init_local_server = __esm({
|
|
7795
7342
|
"src/server/local-server.ts"() {
|
|
7796
7343
|
"use strict";
|
|
@@ -7813,17 +7360,6 @@ var init_local_server = __esm({
|
|
|
7813
7360
|
notificationsEnabled: z9.boolean().optional(),
|
|
7814
7361
|
startAtLogin: z9.boolean().optional()
|
|
7815
7362
|
}).refine((value) => Object.keys(value).length > 0, "At least one setting is required");
|
|
7816
|
-
planSubscriptionSchema = z9.object({
|
|
7817
|
-
providerId: z9.string().min(1),
|
|
7818
|
-
billingDomainId: z9.string().min(1),
|
|
7819
|
-
plan: z9.object({
|
|
7820
|
-
planId: z9.string().min(1).nullable(),
|
|
7821
|
-
amount: z9.number().positive().finite().optional(),
|
|
7822
|
-
currency: z9.string().length(3).optional(),
|
|
7823
|
-
billingPeriod: z9.enum(["monthly", "annual"]).optional(),
|
|
7824
|
-
anchorDate: z9.string().regex(/^\d{4}-\d{2}-\d{2}$/).nullable().optional()
|
|
7825
|
-
}).nullable()
|
|
7826
|
-
});
|
|
7827
7363
|
customModelRateSchema = z9.object({
|
|
7828
7364
|
id: z9.string().optional(),
|
|
7829
7365
|
providerId: z9.string().min(1),
|
|
@@ -8283,7 +7819,7 @@ function buildGlobalSummary(providers, riskSummary, now, query) {
|
|
|
8283
7819
|
tokenEvidence,
|
|
8284
7820
|
apiRetailEquivalent: {
|
|
8285
7821
|
status: sawRetailEquivalent ? "available" : "unavailable",
|
|
8286
|
-
amount: sawRetailEquivalent ?
|
|
7822
|
+
amount: sawRetailEquivalent ? preciseAmount(retailAmount) : null,
|
|
8287
7823
|
currency: "USD",
|
|
8288
7824
|
pricingCoverage: tokenEvidence.recordedTokens === 0 ? null : retailPricedTokens / tokenEvidence.recordedTokens
|
|
8289
7825
|
},
|
|
@@ -8293,7 +7829,7 @@ function buildGlobalSummary(providers, riskSummary, now, query) {
|
|
|
8293
7829
|
contributions
|
|
8294
7830
|
};
|
|
8295
7831
|
}
|
|
8296
|
-
function buildTokenMoneyWorkbench(providers, now, query
|
|
7832
|
+
function buildTokenMoneyWorkbench(providers, now, query) {
|
|
8297
7833
|
const normalized = normalizeUsageQuery(now, query);
|
|
8298
7834
|
const allHistories = allDomainHistories(providers);
|
|
8299
7835
|
const headlineHistories = allHistories.filter(({ includedInHeadline }) => includedInHeadline);
|
|
@@ -8484,43 +8020,9 @@ function buildTokenMoneyWorkbench(providers, now, query, planSubscriptions, plan
|
|
|
8484
8020
|
observationCount > 0 ? recordedTokens : null,
|
|
8485
8021
|
retailEquivalent,
|
|
8486
8022
|
reportedEstimate
|
|
8487
|
-
)
|
|
8488
|
-
planValue: buildWorkbenchPlanValue({
|
|
8489
|
-
domains: planValueDomains(allHistories, comparisonCurrency),
|
|
8490
|
-
subscriptions: planSubscriptions,
|
|
8491
|
-
comparisonCurrency,
|
|
8492
|
-
start: normalized.start.toISOString(),
|
|
8493
|
-
end: normalized.end.toISOString(),
|
|
8494
|
-
rates: uniqueExchangeRates(allHistories.flatMap(({ history }) => history.exchangeRates)),
|
|
8495
|
-
billingPeriods: planBillingPeriods
|
|
8496
|
-
})
|
|
8023
|
+
)
|
|
8497
8024
|
};
|
|
8498
8025
|
}
|
|
8499
|
-
function planValueDomains(histories, comparisonCurrency) {
|
|
8500
|
-
return histories.map(({ provider, domain, history, includedInHeadline }) => {
|
|
8501
|
-
const domainTokens = history.tokenEvidence.recordedTokens;
|
|
8502
|
-
const metric = (purpose) => buildWorkbenchMetric(
|
|
8503
|
-
history.costs,
|
|
8504
|
-
purpose,
|
|
8505
|
-
comparisonCurrency,
|
|
8506
|
-
domainTokens,
|
|
8507
|
-
history.exchangeRates
|
|
8508
|
-
);
|
|
8509
|
-
return {
|
|
8510
|
-
providerId: provider.id,
|
|
8511
|
-
providerDisplayName: provider.displayName,
|
|
8512
|
-
billingDomainId: domain.id,
|
|
8513
|
-
billingDomainDisplayName: domain.displayName,
|
|
8514
|
-
includedInHeadline,
|
|
8515
|
-
recordedTokens: domainTokens,
|
|
8516
|
-
observationCount: history.tokenEvidence.observationCount,
|
|
8517
|
-
retailEquivalent: metric("retail-equivalent"),
|
|
8518
|
-
actualCost: metric("actual"),
|
|
8519
|
-
authorities: history.authorities ?? [],
|
|
8520
|
-
lastObservedAt: history.lastObservedAt ?? null
|
|
8521
|
-
};
|
|
8522
|
-
});
|
|
8523
|
-
}
|
|
8524
8026
|
function allDomainHistories(providers) {
|
|
8525
8027
|
return providers.flatMap(
|
|
8526
8028
|
(provider) => provider.billingDomains.map((domain) => ({
|
|
@@ -8576,11 +8078,11 @@ function buildWorkbenchMetric(costs, purpose, comparisonCurrency, recordedTokens
|
|
|
8576
8078
|
return {
|
|
8577
8079
|
purpose,
|
|
8578
8080
|
status,
|
|
8579
|
-
amount: status === "available" ?
|
|
8081
|
+
amount: status === "available" ? preciseAmount(convertedAmount) : null,
|
|
8580
8082
|
comparisonCurrency,
|
|
8581
8083
|
nativeAmounts: [...native.entries()].map(([currency, amount]) => ({
|
|
8582
8084
|
currency,
|
|
8583
|
-
amount: amount.complete ?
|
|
8085
|
+
amount: amount.complete ? preciseAmount(amount.amount) : null,
|
|
8584
8086
|
records: amount.records,
|
|
8585
8087
|
knownRecords: amount.knownRecords
|
|
8586
8088
|
})).sort((left, right) => left.currency.localeCompare(right.currency)),
|
|
@@ -8990,6 +8492,49 @@ function mapUnclassifiedObservation(row) {
|
|
|
8990
8492
|
}
|
|
8991
8493
|
};
|
|
8992
8494
|
}
|
|
8495
|
+
function addLocalDays(date, days) {
|
|
8496
|
+
const next = /* @__PURE__ */ new Date(`${date}T00:00:00.000Z`);
|
|
8497
|
+
next.setUTCDate(next.getUTCDate() + days);
|
|
8498
|
+
return next.toISOString().slice(0, 10);
|
|
8499
|
+
}
|
|
8500
|
+
function zonedStartOfDay(date, timeZone) {
|
|
8501
|
+
const [year, month, day] = date.split("-").map(Number);
|
|
8502
|
+
const desiredUtc = Date.UTC(year, month - 1, day);
|
|
8503
|
+
let result = desiredUtc;
|
|
8504
|
+
for (let iteration = 0; iteration < 2; iteration += 1) {
|
|
8505
|
+
const parts = new Intl.DateTimeFormat("en-GB", {
|
|
8506
|
+
timeZone,
|
|
8507
|
+
year: "numeric",
|
|
8508
|
+
month: "2-digit",
|
|
8509
|
+
day: "2-digit",
|
|
8510
|
+
hour: "2-digit",
|
|
8511
|
+
minute: "2-digit",
|
|
8512
|
+
second: "2-digit",
|
|
8513
|
+
hourCycle: "h23"
|
|
8514
|
+
}).formatToParts(result);
|
|
8515
|
+
const part = (type) => Number(parts.find((candidate) => candidate.type === type)?.value);
|
|
8516
|
+
const representedUtc = Date.UTC(
|
|
8517
|
+
part("year"),
|
|
8518
|
+
part("month") - 1,
|
|
8519
|
+
part("day"),
|
|
8520
|
+
part("hour"),
|
|
8521
|
+
part("minute"),
|
|
8522
|
+
part("second")
|
|
8523
|
+
);
|
|
8524
|
+
result += desiredUtc - representedUtc;
|
|
8525
|
+
}
|
|
8526
|
+
return new Date(result).toISOString();
|
|
8527
|
+
}
|
|
8528
|
+
function usageWallLevel(recordedTokens, positiveTotals) {
|
|
8529
|
+
if (recordedTokens <= 0 || positiveTotals.length === 0) return 0;
|
|
8530
|
+
const index = positiveTotals.findIndex((value) => value >= recordedTokens);
|
|
8531
|
+
const rank = index === -1 ? positiveTotals.length - 1 : index;
|
|
8532
|
+
const ratio = (rank + 1) / positiveTotals.length;
|
|
8533
|
+
if (ratio <= 0.25) return 1;
|
|
8534
|
+
if (ratio <= 0.5) return 2;
|
|
8535
|
+
if (ratio <= 0.75) return 3;
|
|
8536
|
+
return 4;
|
|
8537
|
+
}
|
|
8993
8538
|
function localDay(observedAt, timeZone) {
|
|
8994
8539
|
const parts = new Intl.DateTimeFormat("en-US", {
|
|
8995
8540
|
timeZone,
|
|
@@ -9226,7 +8771,7 @@ function round(value) {
|
|
|
9226
8771
|
function pricingInputsChanged(existing, observation) {
|
|
9227
8772
|
return existing.billing_domain_id !== observation.billingDomainId || existing.model !== (observation.model?.trim() || "__unclassified__") || existing.observed_at !== observation.observedAt || Number(existing.total_tokens) !== observation.recordedTokens || Number(existing.input_tokens) !== observation.inputTokens || Number(existing.output_tokens) !== observation.outputTokens || Number(existing.reasoning_tokens) !== observation.reasoningTokens || Number(existing.cache_read_tokens) !== observation.cacheReadTokens || Number(existing.cache_write_tokens) !== observation.cacheWriteTokens || (existing.cache_write_5m_tokens === null ? null : Number(existing.cache_write_5m_tokens)) !== (observation.cacheWriteTokenBreakdown?.fiveMinute ?? null) || (existing.cache_write_1h_tokens === null ? null : Number(existing.cache_write_1h_tokens)) !== (observation.cacheWriteTokenBreakdown?.oneHour ?? null) || Number(existing.unclassified_tokens) !== observation.unclassifiedTokens || existing.reasoning_semantics !== observation.tokenSemantics.reasoning || existing.cache_read_semantics !== observation.tokenSemantics.cacheRead || existing.cache_write_semantics !== observation.tokenSemantics.cacheWrite || existing.model_attribution !== observation.modelAttribution || existing.time_precision !== observation.timePrecision || existing.aggregation_temporality !== observation.aggregationTemporality;
|
|
9228
8773
|
}
|
|
9229
|
-
function
|
|
8774
|
+
function preciseAmount(value) {
|
|
9230
8775
|
return Number(value.toFixed(12));
|
|
9231
8776
|
}
|
|
9232
8777
|
function tokenAuthority(authorities) {
|
|
@@ -9263,7 +8808,6 @@ var init_sqlite_usage_repository = __esm({
|
|
|
9263
8808
|
"use strict";
|
|
9264
8809
|
init_token_normalization();
|
|
9265
8810
|
init_quota_normalization();
|
|
9266
|
-
init_plan_pricing();
|
|
9267
8811
|
FRESHNESS_WINDOW_MS = 15 * 60 * 1e3;
|
|
9268
8812
|
QUERY_INDEXES_SQL = `
|
|
9269
8813
|
CREATE INDEX IF NOT EXISTS usage_observed_at_idx
|
|
@@ -9848,23 +9392,101 @@ var init_sqlite_usage_repository = __esm({
|
|
|
9848
9392
|
(provider) => this.#getProviderOverview(provider, now, query)
|
|
9849
9393
|
);
|
|
9850
9394
|
const riskSummary = buildRiskSummary(overviews);
|
|
9851
|
-
const planSubscriptions = this.getPlanSubscriptions();
|
|
9852
9395
|
const overview = {
|
|
9853
9396
|
generatedAt: now.toISOString(),
|
|
9854
9397
|
globalSummary: buildGlobalSummary(overviews, riskSummary, now, query),
|
|
9855
|
-
workbench: buildTokenMoneyWorkbench(
|
|
9856
|
-
overviews,
|
|
9857
|
-
now,
|
|
9858
|
-
query,
|
|
9859
|
-
planSubscriptions,
|
|
9860
|
-
this.#planBillingPeriodSummaries(planSubscriptions, now, query)
|
|
9861
|
-
),
|
|
9398
|
+
workbench: buildTokenMoneyWorkbench(overviews, now, query),
|
|
9862
9399
|
providers: overviews,
|
|
9863
9400
|
riskSummary
|
|
9864
9401
|
};
|
|
9865
9402
|
if (!query.auditEvidence) dropAuditEvidence(overviews);
|
|
9866
9403
|
return overview;
|
|
9867
9404
|
}
|
|
9405
|
+
getUsageWall(now, query = {}) {
|
|
9406
|
+
const timeZone = validTimeZone(query.timeZone) ? query.timeZone : "UTC";
|
|
9407
|
+
const today = localDay(now.toISOString(), timeZone);
|
|
9408
|
+
const start = addLocalDays(today, -365);
|
|
9409
|
+
const startInstant = zonedStartOfDay(start, timeZone);
|
|
9410
|
+
const endExclusiveInstant = zonedStartOfDay(addLocalDays(today, 1), timeZone);
|
|
9411
|
+
const providers = this.#database.prepare("SELECT id, display_name FROM providers ORDER BY id").all();
|
|
9412
|
+
const visibleProviders = this.#hideDemoProvider ? providers.filter((provider) => provider.id !== "demo") : providers;
|
|
9413
|
+
const headlineDomains = /* @__PURE__ */ new Map();
|
|
9414
|
+
for (const provider of visibleProviders) {
|
|
9415
|
+
const domains = this.#database.prepare(
|
|
9416
|
+
`SELECT id, display_name, last_success_at
|
|
9417
|
+
FROM billing_domains WHERE provider_id = ? ORDER BY id`
|
|
9418
|
+
).all(provider.id);
|
|
9419
|
+
const summaryBillingDomainId = selectSummaryBillingDomainId(provider.id, domains);
|
|
9420
|
+
if (!summaryBillingDomainId) continue;
|
|
9421
|
+
headlineDomains.set(`${provider.id}:${summaryBillingDomainId}`, {
|
|
9422
|
+
displayName: provider.display_name,
|
|
9423
|
+
domainId: summaryBillingDomainId
|
|
9424
|
+
});
|
|
9425
|
+
}
|
|
9426
|
+
const totals = /* @__PURE__ */ new Map();
|
|
9427
|
+
const addContribution = (date, providerId, displayName, recordedTokens2) => {
|
|
9428
|
+
if (date < start || date > today || recordedTokens2 <= 0) return;
|
|
9429
|
+
const current = totals.get(date) ?? { recordedTokens: 0, providers: /* @__PURE__ */ new Map() };
|
|
9430
|
+
current.recordedTokens += recordedTokens2;
|
|
9431
|
+
current.providers.set(providerId, { providerId, displayName });
|
|
9432
|
+
totals.set(date, current);
|
|
9433
|
+
};
|
|
9434
|
+
const observationRows = this.#database.prepare(
|
|
9435
|
+
`SELECT provider_id, billing_domain_id, observed_at, total_tokens
|
|
9436
|
+
FROM usage_observations
|
|
9437
|
+
WHERE observed_at >= ? AND observed_at < ? AND ${additiveUsagePredicate()}
|
|
9438
|
+
ORDER BY observed_at, id`
|
|
9439
|
+
).all(startInstant, endExclusiveInstant);
|
|
9440
|
+
for (const row of observationRows) {
|
|
9441
|
+
const headline = headlineDomains.get(`${row.provider_id}:${row.billing_domain_id}`);
|
|
9442
|
+
if (!headline) continue;
|
|
9443
|
+
addContribution(
|
|
9444
|
+
localDay(row.observed_at, timeZone),
|
|
9445
|
+
row.provider_id,
|
|
9446
|
+
headline.displayName,
|
|
9447
|
+
Number(row.total_tokens)
|
|
9448
|
+
);
|
|
9449
|
+
}
|
|
9450
|
+
const aggregateRows = this.#database.prepare(
|
|
9451
|
+
`SELECT provider_id, billing_domain_id, day_utc, total_tokens
|
|
9452
|
+
FROM daily_usage_aggregates
|
|
9453
|
+
WHERE day_utc >= ? AND day_utc <= ?
|
|
9454
|
+
ORDER BY day_utc, provider_id, billing_domain_id`
|
|
9455
|
+
).all(start, today);
|
|
9456
|
+
for (const row of aggregateRows) {
|
|
9457
|
+
const headline = headlineDomains.get(`${row.provider_id}:${row.billing_domain_id}`);
|
|
9458
|
+
if (!headline) continue;
|
|
9459
|
+
addContribution(
|
|
9460
|
+
localDay(`${row.day_utc}T12:00:00.000Z`, timeZone),
|
|
9461
|
+
row.provider_id,
|
|
9462
|
+
headline.displayName,
|
|
9463
|
+
Number(row.total_tokens)
|
|
9464
|
+
);
|
|
9465
|
+
}
|
|
9466
|
+
const positiveTotals = [...totals.values()].map((day) => day.recordedTokens).filter((value) => value > 0).sort((left, right) => left - right);
|
|
9467
|
+
const days = [];
|
|
9468
|
+
let recordedTokens = 0;
|
|
9469
|
+
for (let cursor = start; cursor <= today; cursor = addLocalDays(cursor, 1)) {
|
|
9470
|
+
const contribution = totals.get(cursor);
|
|
9471
|
+
const dayTokens = contribution?.recordedTokens ?? 0;
|
|
9472
|
+
recordedTokens += dayTokens;
|
|
9473
|
+
days.push({
|
|
9474
|
+
date: cursor,
|
|
9475
|
+
recordedTokens: dayTokens,
|
|
9476
|
+
level: usageWallLevel(dayTokens, positiveTotals),
|
|
9477
|
+
providers: contribution ? [...contribution.providers.values()].sort(
|
|
9478
|
+
(left, right) => left.providerId.localeCompare(right.providerId)
|
|
9479
|
+
) : []
|
|
9480
|
+
});
|
|
9481
|
+
}
|
|
9482
|
+
return {
|
|
9483
|
+
timeZone,
|
|
9484
|
+
start,
|
|
9485
|
+
end: today,
|
|
9486
|
+
recordedTokens,
|
|
9487
|
+
days
|
|
9488
|
+
};
|
|
9489
|
+
}
|
|
9868
9490
|
getAgentProviderIndex(now) {
|
|
9869
9491
|
const providers = this.#database.prepare("SELECT id, display_name FROM providers ORDER BY id").all();
|
|
9870
9492
|
return {
|
|
@@ -9960,57 +9582,6 @@ var init_sqlite_usage_repository = __esm({
|
|
|
9960
9582
|
settings.startAtLogin ? 1 : 0
|
|
9961
9583
|
);
|
|
9962
9584
|
}
|
|
9963
|
-
getPlanSubscriptions() {
|
|
9964
|
-
const rows = this.#database.prepare(
|
|
9965
|
-
`SELECT provider_id, billing_domain_id, plan_id, display_name, amount, currency,
|
|
9966
|
-
billing_period, anchor_date, price_source, updated_at
|
|
9967
|
-
FROM plan_subscriptions
|
|
9968
|
-
ORDER BY provider_id, billing_domain_id`
|
|
9969
|
-
).all();
|
|
9970
|
-
return rows.map((row) => ({
|
|
9971
|
-
providerId: row.provider_id,
|
|
9972
|
-
billingDomainId: row.billing_domain_id,
|
|
9973
|
-
planId: row.plan_id,
|
|
9974
|
-
displayName: row.display_name,
|
|
9975
|
-
amount: row.amount,
|
|
9976
|
-
currency: row.currency,
|
|
9977
|
-
billingPeriod: row.billing_period,
|
|
9978
|
-
anchorDate: row.anchor_date,
|
|
9979
|
-
priceSource: row.price_source,
|
|
9980
|
-
updatedAt: row.updated_at
|
|
9981
|
-
}));
|
|
9982
|
-
}
|
|
9983
|
-
savePlanSubscription(subscription) {
|
|
9984
|
-
this.#database.prepare(
|
|
9985
|
-
`INSERT INTO plan_subscriptions (
|
|
9986
|
-
provider_id, billing_domain_id, plan_id, display_name, amount, currency,
|
|
9987
|
-
billing_period, anchor_date, price_source, updated_at
|
|
9988
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
9989
|
-
ON CONFLICT(provider_id, billing_domain_id) DO UPDATE SET
|
|
9990
|
-
plan_id = excluded.plan_id,
|
|
9991
|
-
display_name = excluded.display_name,
|
|
9992
|
-
amount = excluded.amount,
|
|
9993
|
-
currency = excluded.currency,
|
|
9994
|
-
billing_period = excluded.billing_period,
|
|
9995
|
-
anchor_date = excluded.anchor_date,
|
|
9996
|
-
price_source = excluded.price_source,
|
|
9997
|
-
updated_at = excluded.updated_at`
|
|
9998
|
-
).run(
|
|
9999
|
-
subscription.providerId,
|
|
10000
|
-
subscription.billingDomainId,
|
|
10001
|
-
subscription.planId,
|
|
10002
|
-
subscription.displayName,
|
|
10003
|
-
subscription.amount,
|
|
10004
|
-
subscription.currency,
|
|
10005
|
-
subscription.billingPeriod,
|
|
10006
|
-
subscription.anchorDate,
|
|
10007
|
-
subscription.priceSource,
|
|
10008
|
-
subscription.updatedAt
|
|
10009
|
-
);
|
|
10010
|
-
}
|
|
10011
|
-
deletePlanSubscription(providerId, billingDomainId) {
|
|
10012
|
-
this.#database.prepare("DELETE FROM plan_subscriptions WHERE provider_id = ? AND billing_domain_id = ?").run(providerId, billingDomainId);
|
|
10013
|
-
}
|
|
10014
9585
|
getCustomModelRates() {
|
|
10015
9586
|
const rows = this.#database.prepare(
|
|
10016
9587
|
`SELECT id, provider_id, billing_domain_id, model,
|
|
@@ -10588,101 +10159,6 @@ var init_sqlite_usage_repository = __esm({
|
|
|
10588
10159
|
coverageByDomain
|
|
10589
10160
|
};
|
|
10590
10161
|
}
|
|
10591
|
-
/**
|
|
10592
|
-
* Cycle-to-date evidence for every subscription that declares a renewal date.
|
|
10593
|
-
* Each Provider is measured over its own billing period, which is why this
|
|
10594
|
-
* cannot reuse the one rolling window the rest of the workbench shares.
|
|
10595
|
-
*/
|
|
10596
|
-
#planBillingPeriodSummaries(subscriptions, now, query) {
|
|
10597
|
-
const normalized = normalizeUsageQuery(now, query);
|
|
10598
|
-
const summaries = /* @__PURE__ */ new Map();
|
|
10599
|
-
for (const subscription of subscriptions) {
|
|
10600
|
-
if (!subscription.anchorDate) continue;
|
|
10601
|
-
const period = billingPeriodContaining(
|
|
10602
|
-
subscription.anchorDate,
|
|
10603
|
-
subscription.billingPeriod,
|
|
10604
|
-
now
|
|
10605
|
-
);
|
|
10606
|
-
if (!period) continue;
|
|
10607
|
-
const observedThrough = new Date(Math.min(now.getTime(), period.end.getTime()));
|
|
10608
|
-
summaries.set(`${subscription.providerId}:${subscription.billingDomainId}`, {
|
|
10609
|
-
start: period.start.toISOString(),
|
|
10610
|
-
end: period.end.toISOString(),
|
|
10611
|
-
observedThrough: observedThrough.toISOString(),
|
|
10612
|
-
...this.#rangeUsageSummary(
|
|
10613
|
-
subscription.providerId,
|
|
10614
|
-
subscription.billingDomainId,
|
|
10615
|
-
period.start,
|
|
10616
|
-
observedThrough,
|
|
10617
|
-
normalized.comparisonCurrency
|
|
10618
|
-
)
|
|
10619
|
-
});
|
|
10620
|
-
}
|
|
10621
|
-
return summaries;
|
|
10622
|
-
}
|
|
10623
|
-
#rangeUsageSummary(providerId, billingDomainId, start, end, comparisonCurrency) {
|
|
10624
|
-
const startIso = start.toISOString();
|
|
10625
|
-
const endIso = end.toISOString();
|
|
10626
|
-
const usage = this.#database.prepare(
|
|
10627
|
-
`SELECT id, model, observed_at, authority, total_tokens, input_tokens, output_tokens,
|
|
10628
|
-
reasoning_tokens, cache_read_tokens, cache_write_tokens, cache_write_5m_tokens,
|
|
10629
|
-
cache_write_1h_tokens, source_reported_total_tokens,
|
|
10630
|
-
unclassified_tokens, total_derivation, model_attribution, time_precision,
|
|
10631
|
-
usage_scope, aggregation_temporality, reasoning_semantics,
|
|
10632
|
-
cache_read_semantics, cache_write_semantics
|
|
10633
|
-
FROM usage_observations
|
|
10634
|
-
WHERE provider_id = ? AND billing_domain_id = ?
|
|
10635
|
-
AND observed_at >= ? AND observed_at < ?
|
|
10636
|
-
AND ${additiveUsagePredicate()}
|
|
10637
|
-
ORDER BY observed_at, id`
|
|
10638
|
-
).all(providerId, billingDomainId, startIso, endIso);
|
|
10639
|
-
const costs = this.#database.prepare(
|
|
10640
|
-
`SELECT id, source_id, billing_domain_id, observed_at, kind, amount, currency, authority,
|
|
10641
|
-
price_snapshot_id, price_snapshot_version, price_snapshot_source,
|
|
10642
|
-
price_snapshot_canonical_model, price_snapshot_effective_at,
|
|
10643
|
-
price_snapshot_effective_until, price_snapshot_currency,
|
|
10644
|
-
price_snapshot_rates_json, price_snapshot_source_url,
|
|
10645
|
-
price_snapshot_context_tier, model, usage_observation_id, priced_tokens,
|
|
10646
|
-
line_items_json, calculated_at
|
|
10647
|
-
FROM cost_records
|
|
10648
|
-
WHERE provider_id = ? AND billing_domain_id = ?
|
|
10649
|
-
AND observed_at >= ? AND observed_at < ?
|
|
10650
|
-
ORDER BY observed_at, id`
|
|
10651
|
-
).all(providerId, billingDomainId, startIso, endIso);
|
|
10652
|
-
const rateRows = this.#database.prepare(
|
|
10653
|
-
`SELECT id, base_currency, quote_currency, rate, observed_at, source
|
|
10654
|
-
FROM exchange_rate_snapshots WHERE observed_at < ? ORDER BY observed_at DESC, id`
|
|
10655
|
-
).all(endIso);
|
|
10656
|
-
const rateByCurrency = /* @__PURE__ */ new Map();
|
|
10657
|
-
for (const row of rateRows) {
|
|
10658
|
-
if (row.quote_currency === comparisonCurrency && !rateByCurrency.has(row.base_currency)) {
|
|
10659
|
-
rateByCurrency.set(row.base_currency, row);
|
|
10660
|
-
}
|
|
10661
|
-
}
|
|
10662
|
-
const evidence = emptyTokenEvidence();
|
|
10663
|
-
for (const row of usage) addTokenEvidence(evidence, row);
|
|
10664
|
-
const finished = finishTokenEvidence(evidence);
|
|
10665
|
-
const usedRates = /* @__PURE__ */ new Map();
|
|
10666
|
-
const historyCosts = summarizeHistoryCosts(
|
|
10667
|
-
costs,
|
|
10668
|
-
finished.recordedTokens,
|
|
10669
|
-
rateByCurrency,
|
|
10670
|
-
comparisonCurrency,
|
|
10671
|
-
end,
|
|
10672
|
-
usedRates
|
|
10673
|
-
);
|
|
10674
|
-
return {
|
|
10675
|
-
recordedTokens: finished.recordedTokens,
|
|
10676
|
-
observationCount: finished.observationCount,
|
|
10677
|
-
retailEquivalent: buildWorkbenchMetric(
|
|
10678
|
-
historyCosts,
|
|
10679
|
-
"retail-equivalent",
|
|
10680
|
-
comparisonCurrency,
|
|
10681
|
-
finished.recordedTokens,
|
|
10682
|
-
[...usedRates.values()]
|
|
10683
|
-
)
|
|
10684
|
-
};
|
|
10685
|
-
}
|
|
10686
10162
|
#getBillingHistory(providerId, billingDomainId, now, query) {
|
|
10687
10163
|
const normalized = normalizeUsageQuery(now, query);
|
|
10688
10164
|
const start = normalized.start.toISOString();
|
|
@@ -11091,19 +10567,6 @@ var init_sqlite_usage_repository = __esm({
|
|
|
11091
10567
|
key TEXT PRIMARY KEY,
|
|
11092
10568
|
value TEXT NOT NULL
|
|
11093
10569
|
);
|
|
11094
|
-
CREATE TABLE IF NOT EXISTS plan_subscriptions (
|
|
11095
|
-
provider_id TEXT NOT NULL,
|
|
11096
|
-
billing_domain_id TEXT NOT NULL,
|
|
11097
|
-
plan_id TEXT,
|
|
11098
|
-
display_name TEXT NOT NULL,
|
|
11099
|
-
amount REAL NOT NULL,
|
|
11100
|
-
currency TEXT NOT NULL,
|
|
11101
|
-
billing_period TEXT NOT NULL,
|
|
11102
|
-
anchor_date TEXT,
|
|
11103
|
-
price_source TEXT NOT NULL,
|
|
11104
|
-
updated_at TEXT NOT NULL,
|
|
11105
|
-
PRIMARY KEY (provider_id, billing_domain_id)
|
|
11106
|
-
);
|
|
11107
10570
|
CREATE TABLE IF NOT EXISTS custom_model_rates (
|
|
11108
10571
|
id TEXT PRIMARY KEY,
|
|
11109
10572
|
provider_id TEXT NOT NULL,
|
|
@@ -11284,10 +10747,6 @@ var init_sqlite_usage_repository = __esm({
|
|
|
11284
10747
|
this.#database.exec(`ALTER TABLE quota_buckets ADD COLUMN ${name} ${type}`);
|
|
11285
10748
|
}
|
|
11286
10749
|
}
|
|
11287
|
-
const planColumns = this.#database.prepare("PRAGMA table_info(plan_subscriptions)").all();
|
|
11288
|
-
if (planColumns.length > 0 && !planColumns.some((column) => column.name === "anchor_date")) {
|
|
11289
|
-
this.#database.exec("ALTER TABLE plan_subscriptions ADD COLUMN anchor_date TEXT");
|
|
11290
|
-
}
|
|
11291
10750
|
}
|
|
11292
10751
|
};
|
|
11293
10752
|
}
|