@centerforagenticai/pi-multi-account 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +29 -0
  3. package/README.md +999 -0
  4. package/config/models/pi-multi-account.v1.json +32 -0
  5. package/config/subscription-plans.v1.json +122 -0
  6. package/package.json +76 -0
  7. package/packages/pi-anthropic-oauth/LICENSE +21 -0
  8. package/packages/pi-anthropic-oauth/package.json +54 -0
  9. package/packages/pi-anthropic-oauth/src/auth.ts +396 -0
  10. package/packages/pi-anthropic-oauth/src/context.ts +116 -0
  11. package/packages/pi-anthropic-oauth/src/convert.ts +303 -0
  12. package/packages/pi-anthropic-oauth/src/index.ts +37 -0
  13. package/packages/pi-anthropic-oauth/src/prompt.ts +137 -0
  14. package/packages/pi-anthropic-oauth/src/stream.ts +476 -0
  15. package/packages/pi-antigravity/LICENSE +21 -0
  16. package/packages/pi-antigravity/package.json +77 -0
  17. package/packages/pi-antigravity/src/auth/index.ts +14 -0
  18. package/packages/pi-antigravity/src/auth/oauth.ts +442 -0
  19. package/packages/pi-antigravity/src/client/client.ts +561 -0
  20. package/packages/pi-antigravity/src/client/index.ts +1 -0
  21. package/packages/pi-antigravity/src/context.ts +110 -0
  22. package/packages/pi-antigravity/src/diagnostics/diagnostics.ts +96 -0
  23. package/packages/pi-antigravity/src/diagnostics/index.ts +1 -0
  24. package/packages/pi-antigravity/src/image/image.ts +336 -0
  25. package/packages/pi-antigravity/src/image/index.ts +1 -0
  26. package/packages/pi-antigravity/src/index.ts +280 -0
  27. package/packages/pi-antigravity/src/models/discovery.ts +154 -0
  28. package/packages/pi-antigravity/src/models/grouping.ts +424 -0
  29. package/packages/pi-antigravity/src/models/index.ts +3 -0
  30. package/packages/pi-antigravity/src/models/models.ts +500 -0
  31. package/packages/pi-antigravity/src/stream/index.ts +1 -0
  32. package/packages/pi-antigravity/src/stream/stream.ts +1478 -0
  33. package/packages/pi-antigravity/src/types/enums.ts +42 -0
  34. package/packages/pi-antigravity/src/types/index.ts +2 -0
  35. package/packages/pi-antigravity/src/types/types.ts +292 -0
  36. package/packages/pi-antigravity/src/usage/index.ts +1 -0
  37. package/packages/pi-antigravity/src/usage/usage.ts +416 -0
  38. package/packages/pi-antigravity/src/utils/http.ts +91 -0
  39. package/packages/pi-antigravity/src/utils/index.ts +3 -0
  40. package/packages/pi-antigravity/src/utils/security.ts +73 -0
  41. package/packages/pi-antigravity/src/utils/util.ts +132 -0
  42. package/scripts/multi-account.mjs +44 -0
  43. package/src/account-labels.ts +223 -0
  44. package/src/account-plan-assignment.ts +340 -0
  45. package/src/account-rate-history.ts +372 -0
  46. package/src/anthropic-adaptive-stream.ts +531 -0
  47. package/src/anthropic-alias-stream.ts +140 -0
  48. package/src/anthropic-context-compat.ts +80 -0
  49. package/src/api-pricing.ts +579 -0
  50. package/src/bounded-file-lines.ts +97 -0
  51. package/src/catalog-rebinding.ts +177 -0
  52. package/src/catalog-registration-probe.ts +111 -0
  53. package/src/codex-adapter.ts +345 -0
  54. package/src/codex-model-defaults.ts +785 -0
  55. package/src/command-completions.ts +404 -0
  56. package/src/commands.ts +2000 -0
  57. package/src/compaction.ts +14 -0
  58. package/src/config.ts +1317 -0
  59. package/src/continuation.ts +569 -0
  60. package/src/cooldowns.ts +110 -0
  61. package/src/cost-digest-store.ts +332 -0
  62. package/src/cost-digest.ts +1044 -0
  63. package/src/cost-history.ts +251 -0
  64. package/src/cost-period-closer.ts +160 -0
  65. package/src/cost-report-json.ts +318 -0
  66. package/src/cost-report-reader.ts +368 -0
  67. package/src/cost-report-render.ts +207 -0
  68. package/src/cost-report.ts +1104 -0
  69. package/src/coverage-attestation.ts +397 -0
  70. package/src/credential-lifecycle.ts +169 -0
  71. package/src/credential-refresh.ts +248 -0
  72. package/src/declaration-notice-marker.ts +238 -0
  73. package/src/diagnostic-store.ts +276 -0
  74. package/src/diagnostics.ts +309 -0
  75. package/src/discovery.ts +471 -0
  76. package/src/duration.ts +13 -0
  77. package/src/error-classification.ts +256 -0
  78. package/src/fuzzy.ts +15 -0
  79. package/src/group-policy.ts +81 -0
  80. package/src/history-store.ts +897 -0
  81. package/src/index.ts +5572 -0
  82. package/src/lifecycle.ts +378 -0
  83. package/src/logical-dispatch.ts +279 -0
  84. package/src/logical-model-selector.ts +254 -0
  85. package/src/logical-model-switcher.ts +430 -0
  86. package/src/logical-provider-attribution.ts +544 -0
  87. package/src/logical-provider.ts +1237 -0
  88. package/src/logical-route-indicator.ts +215 -0
  89. package/src/machine-lease.ts +445 -0
  90. package/src/model-support.ts +66 -0
  91. package/src/models-declaration.ts +1091 -0
  92. package/src/openai-adapter.ts +117 -0
  93. package/src/openrouter-budget.ts +304 -0
  94. package/src/openrouter-fallback.ts +146 -0
  95. package/src/period-boundaries.ts +376 -0
  96. package/src/pi-anthropic-oauth.d.ts +6 -0
  97. package/src/preflight.ts +253 -0
  98. package/src/pricing-cache.ts +235 -0
  99. package/src/project-identity.ts +100 -0
  100. package/src/provider-registration.ts +942 -0
  101. package/src/rate-formula.ts +163 -0
  102. package/src/recovery-engine.ts +853 -0
  103. package/src/recovery-output.ts +837 -0
  104. package/src/recovery-plan.ts +239 -0
  105. package/src/report-range.ts +203 -0
  106. package/src/route-resolver.ts +789 -0
  107. package/src/routing-config-transaction.ts +232 -0
  108. package/src/routing.ts +1163 -0
  109. package/src/runtime-state.ts +630 -0
  110. package/src/session-account-groups.ts +284 -0
  111. package/src/session-restore.ts +287 -0
  112. package/src/shared-usage.ts +1392 -0
  113. package/src/standalone-cli.ts +720 -0
  114. package/src/status-view.ts +578 -0
  115. package/src/subscription-plan-catalog.ts +346 -0
  116. package/src/tier-model-resolver.ts +46 -0
  117. package/src/upstream-anthropic.ts +315 -0
  118. package/src/upstream-antigravity.ts +327 -0
  119. package/src/usage-fetch.ts +1634 -0
  120. package/src/usage.ts +1026 -0
  121. package/src/vendor.ts +87 -0
  122. package/src/warmer.ts +231 -0
  123. package/src/watchdog.ts +219 -0
  124. package/src/window-history.ts +270 -0
@@ -0,0 +1,207 @@
1
+ import type {
2
+ AccountValueSummary,
3
+ CostReport,
4
+ CostReportApiEquivalent,
5
+ CostReportPeriod,
6
+ CostReportTokens,
7
+ RecordedRate,
8
+ SubsidizationPoint,
9
+ ValueComparison,
10
+ } from "./cost-report.js";
11
+
12
+ function iso(timestampMs: number): string {
13
+ return new Date(timestampMs).toISOString();
14
+ }
15
+
16
+ function usd(value: number): string {
17
+ if (value !== 0 && value < 0.000001) return `$${value.toExponential(4)}`;
18
+ return `$${value.toFixed(6)}`;
19
+ }
20
+
21
+ function tokenBreakdown(tokens: CostReportTokens): string {
22
+ return (
23
+ `${tokens.input} input, ${tokens.output} output, ` +
24
+ `${tokens.cacheRead} cache-read, ${tokens.cacheWrite} cache-write, ` +
25
+ `${tokens.cacheWrite1h} one-hour cache-write`
26
+ );
27
+ }
28
+
29
+ function apiEquivalent(value: CostReportApiEquivalent): string {
30
+ if (value.status === "unpriced") {
31
+ return `API-equivalent estimate: unpriced (${value.reasons.join(", ")})`;
32
+ }
33
+ const stamps = value.rateAsOfMs.map(iso).join(", ");
34
+ return `API-equivalent estimate: ${usd(value.estimatedUsd)} (rate snapshot: ${stamps || "none"})`;
35
+ }
36
+
37
+ function periodHeading(period: CostReportPeriod): string {
38
+ const scope = period.completed ? "completed" : "current partial";
39
+ return `${scope} ${iso(period.periodStartMs)} .. ${iso(period.periodEndMs)} through ${iso(period.throughMs)} — coverage: ${period.coverage}`;
40
+ }
41
+
42
+ function renderPeriod(period: CostReportPeriod): readonly string[] {
43
+ const lines = [
44
+ periodHeading(period),
45
+ ` tokens: ${tokenBreakdown(period.tokens)}; Pi model-price estimate (retained provider cost: ${usd(period.retainedCostUsd)}); ${apiEquivalent(period.apiEquivalent)}`,
46
+ ];
47
+ if (period.coverage === "gap") {
48
+ lines.push(" gap: no immutable digest row exists for this period.");
49
+ return lines;
50
+ }
51
+ for (const project of period.projects) {
52
+ lines.push(` project ${project.label} [${project.projectKey}]`);
53
+ for (const account of project.accounts) {
54
+ lines.push(` account ${account.canonicalAccountId}`);
55
+ for (const model of account.models) {
56
+ lines.push(
57
+ ` model ${model.requestedModel}: ${tokenBreakdown(model.tokens)}; Pi model-price estimate (retained provider cost ${usd(model.retainedCostUsd)}); ${apiEquivalent(model.apiEquivalent)}`,
58
+ );
59
+ }
60
+ }
61
+ }
62
+ return lines;
63
+ }
64
+
65
+ /**
66
+ * The leading, operator-first block: the requested scope, then the saved Pi
67
+ * model-price estimate and the independently calculated API-equivalent
68
+ * estimate as two clearly labeled, terse value lines -- always both, even
69
+ * when their amounts happen to match -- followed by one disclaimer paragraph
70
+ * that neither figure is an actual provider bill, payment, refund, tax
71
+ * record, or bank charge. This runs before any project/account/model detail
72
+ * so the requested-scope summary is the first thing an operator reads.
73
+ */
74
+ function renderRequestedScopeSummary(report: CostReport): readonly string[] {
75
+ const current = report.current;
76
+ const matchNote =
77
+ current.apiEquivalent.status === "priced" &&
78
+ current.apiEquivalent.estimatedUsd === current.retainedCostUsd
79
+ ? " These two figures happen to match for this window;"
80
+ : "";
81
+ return [
82
+ `Requested scope: ${periodHeading(current)}`,
83
+ ` Pi model-price estimate (saved): ${usd(current.retainedCostUsd)}`,
84
+ ` ${apiEquivalent(current.apiEquivalent)}`,
85
+ ` Both figures above are independent calculations, not the same measurement.${matchNote} Neither is an actual provider bill, payment, refund, tax record, or bank charge.`,
86
+ ];
87
+ }
88
+
89
+ function renderRecordedRate(rate: RecordedRate): string {
90
+ if (rate.status === "unknown") return "unknown (no recorded account rate as of this window)";
91
+ return rate.monthlyUsd === 0
92
+ ? `${usd(rate.monthlyUsd)} (explicit zero rate)`
93
+ : usd(rate.monthlyUsd);
94
+ }
95
+
96
+ function renderComparison(comparison: ValueComparison): string {
97
+ if (comparison.status === "suppressed") {
98
+ return `not compared (${comparison.reason})`;
99
+ }
100
+ if (comparison.status === "conditional-lower-bound") {
101
+ return `at least ${comparison.ratio.toFixed(4)}x — conditional lower bound (${comparison.premise})`;
102
+ }
103
+ return `${comparison.ratio.toFixed(4)}x — definitive comparison of report figures only`;
104
+ }
105
+
106
+ function renderAccountValue(entry: AccountValueSummary): string {
107
+ const allocation = entry.allocationHasUnknownCoverage
108
+ ? `${usd(entry.allocatedAccountCostUsd)} (partial: part of this window has no recorded account rate)`
109
+ : usd(entry.allocatedAccountCostUsd);
110
+ return (
111
+ ` ${entry.canonicalAccountId}: recorded monthly account rate ${renderRecordedRate(entry.recordedRate)}; ` +
112
+ `allocated account cost ${allocation}; comparison: ${renderComparison(entry.comparison)}`
113
+ );
114
+ }
115
+
116
+ function apiEquivalentEstimate(value: number): string {
117
+ return `API-equivalent estimate ${usd(value)}`;
118
+ }
119
+
120
+ /**
121
+ * A legacy subsidization point never shows a bare ratio unless `coverage` is
122
+ * `"complete"`. `"partial"` or `"unknown"` coverage means the underlying
123
+ * retained data or its data-completeness classification cannot support a
124
+ * definitive comparison for this window, so the ratio (and any consecutive
125
+ * delta, itself a difference of ratios) is withheld -- "not compared", the
126
+ * same vocabulary {@link renderComparison} uses for the modern account-value
127
+ * comparison. The two figures that would have produced the ratio,
128
+ * `apiEquivalentEstimateUsd` and `apportionedSubscriptionUsd`, are always
129
+ * still shown: only the ratio itself is suppressed, nothing is hidden.
130
+ *
131
+ * `deltaFromPrevious` (cost-report.ts's `withConsecutiveDeltas`) is a
132
+ * difference of two ratios, so it is only ever as reliable as its weaker
133
+ * side: it is shown only when both this point AND the immediately
134
+ * preceding point in the same series have `coverage: "complete"`. A
135
+ * complete point that follows a partial or unknown predecessor still shows
136
+ * its own valid ratio, but the delta is withheld with an explicit reason
137
+ * instead of silently bridging past the untrusted predecessor.
138
+ */
139
+ function subsidyPoint(point: SubsidizationPoint, previous?: SubsidizationPoint): string {
140
+ const period = `${iso(point.periodStartMs)} .. ${iso(point.periodEndMs)}`;
141
+ if (point.status === "gap") return `${period}: gap`;
142
+ if (point.status === "unpriced") {
143
+ return `${period}: unpriced; coverage ${point.coverage}`;
144
+ }
145
+ const known = `${apiEquivalentEstimate(point.apiEquivalentEstimateUsd)} / apportioned subscription ${usd(point.apportionedSubscriptionUsd)}`;
146
+ if (point.coverage !== "complete") {
147
+ return `${period}: not compared (legacy-subsidization-${point.coverage}-coverage) — ${known}; coverage ${point.coverage}`;
148
+ }
149
+ const deltaBasisComplete =
150
+ previous !== undefined && previous.status === "priced" && previous.coverage === "complete";
151
+ const delta =
152
+ point.deltaFromPrevious === undefined
153
+ ? ""
154
+ : deltaBasisComplete
155
+ ? `; consecutive delta ${point.deltaFromPrevious >= 0 ? "+" : ""}${point.deltaFromPrevious.toFixed(4)}x`
156
+ : "; consecutive delta withheld (legacy-subsidization-delta-predecessor-incomplete)";
157
+ return `${period}: ${point.ratio.toFixed(4)}x (${known}); coverage ${point.coverage}${delta}`;
158
+ }
159
+
160
+ export function renderCostReport(report: CostReport): string {
161
+ const lines: string[] = [
162
+ `Cost intelligence — ${report.periodType} — generated ${iso(report.generatedAtMs)}`,
163
+ ...renderRequestedScopeSummary(report),
164
+ ...renderPeriod(report.current),
165
+ ];
166
+ if (report.completed.length === 0) {
167
+ lines.push("Completed periods: none available.");
168
+ } else {
169
+ lines.push("Completed periods:");
170
+ for (const period of report.completed) {
171
+ lines.push(...renderPeriod(period).map((line) => ` ${line}`));
172
+ }
173
+ }
174
+ if (report.accountValue !== undefined && report.accountValue.length > 0) {
175
+ lines.push(
176
+ "Recorded account rate and allocated account cost by account (comparison figures only; never an invoice, payment, refund, tax record, or bank charge):",
177
+ );
178
+ for (const entry of report.accountValue) {
179
+ lines.push(renderAccountValue(entry));
180
+ }
181
+ }
182
+ if (report.subsidization.length > 0) {
183
+ lines.push(
184
+ "Subscription subsidization by account (legacy comparison using the superseded flat monthly figure; see recorded account rate above for the current method — not an actual subsidy, bill, or savings figure):",
185
+ );
186
+ for (const series of report.subsidization) {
187
+ lines.push(
188
+ ` ${series.canonicalAccountId}: monthly subscription ${usd(series.monthlySubscriptionUsd)}; completed ratio periods ${series.observedPeriods}`,
189
+ );
190
+ if (series.current !== undefined) {
191
+ lines.push(` current: ${subsidyPoint(series.current)}`);
192
+ }
193
+ for (const [index, point] of series.completed.entries()) {
194
+ lines.push(` ${subsidyPoint(point, series.completed[index - 1])}`);
195
+ }
196
+ }
197
+ }
198
+ if (report.legacyUnattributed.length > 0) {
199
+ lines.push("Legacy unattributed retained cost (no project key):");
200
+ for (const entry of report.legacyUnattributed) {
201
+ lines.push(
202
+ ` ${entry.canonicalAccountId}/${entry.requestedModel}: ${entry.observationCount} observations; ${tokenBreakdown(entry.tokens)}; Pi model-price estimate (retained provider cost ${usd(entry.retainedCostUsd)})`,
203
+ );
204
+ }
205
+ }
206
+ return lines.join("\n");
207
+ }