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/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, planSubscriptionSchema, customModelRateSchema, clearDataSchema, hardRebuildSchema;
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 ? preciseAmount2(retailAmount) : null,
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, planSubscriptions, planBillingPeriods) {
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" ? preciseAmount2(convertedAmount) : null,
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 ? preciseAmount2(amount.amount) : null,
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 preciseAmount2(value) {
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
  }