@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,163 @@
1
+ import type { WindowSample } from "./window-history.js";
2
+ import { utilizationFromRemainingFraction } from "./window-history.js";
3
+
4
+ export type RateStatus = "available" | "unavailable";
5
+
6
+ export interface RateResult {
7
+ readonly status: RateStatus;
8
+ readonly rate?: number;
9
+ readonly reason?: string;
10
+ }
11
+
12
+ const MIN_SAMPLES_REQUIRED = 3;
13
+ const MAX_GAP_MINUTES = 30;
14
+ const MAX_GAP_MS = MAX_GAP_MINUTES * 60 * 1000;
15
+ const MS_PER_HOUR = 3600 * 1000;
16
+
17
+ /**
18
+ * Compute burn rate for one window from retained samples.
19
+ *
20
+ * Rate formula: 100 × (latest utilization - earliest utilization) / elapsed hours
21
+ * Reported as PERCENTAGE POINTS consumed per hour.
22
+ *
23
+ * REQ-RATE-FORMULA: requires at least three consecutive samples with every adjacent
24
+ * gap at most 30 minutes, all sharing one unchanged reset epoch. Any of the following
25
+ * starts a NEW series and reports unavailable:
26
+ * - fewer than three samples
27
+ * - any adjacent gap over 30 minutes
28
+ * - a decreased utilization value (backward move)
29
+ * - a backward-moving or corrected reset epoch
30
+ *
31
+ * REQ-WINDOW-UNIT: converts stored remainingFraction to utilization using the SAME
32
+ * deterministic conversion as window-history.ts (1 - remainingFraction).
33
+ *
34
+ * REQ-RESET-DETECTION: no rate may span an epoch boundary; a changed epoch immediately
35
+ * yields unavailable.
36
+ */
37
+ export function computeWindowRate(
38
+ samples: readonly WindowSample[],
39
+ windowId: string,
40
+ ): RateResult {
41
+ // Filter to the requested window and usable samples only
42
+ // REQ-RESET-DETECTION: samples must have resetEpoch for rate computation
43
+ const windowSamples = samples.filter(
44
+ s => s.windowId === windowId && s.usable === true && s.resetEpoch !== undefined && s.remainingFraction !== undefined
45
+ );
46
+
47
+ if (windowSamples.length < MIN_SAMPLES_REQUIRED) {
48
+ return {
49
+ status: "unavailable",
50
+ reason: `fewer than ${MIN_SAMPLES_REQUIRED} usable samples`,
51
+ };
52
+ }
53
+
54
+ // Sort by recordedAtMs ascending
55
+ const sorted = [...windowSamples].sort((a, b) => a.recordedAtMs - b.recordedAtMs);
56
+
57
+ // Find the longest contiguous series that satisfies all rate conditions:
58
+ // - all samples in the same reset epoch
59
+ // - every adjacent gap ≤ 30 minutes
60
+ // - monotonically non-decreasing utilization
61
+
62
+ // Start searching from the MOST RECENT samples backward (we want the most current rate)
63
+ for (let endIdx = sorted.length - 1; endIdx >= MIN_SAMPLES_REQUIRED - 1; endIdx -= 1) {
64
+ // Try to build a series ending at endIdx
65
+ const seriesEnd = sorted[endIdx];
66
+ if (!seriesEnd) continue; // TypeScript guard
67
+
68
+ const seriesEndEpoch = seriesEnd.resetEpoch;
69
+ if (seriesEndEpoch === undefined) {
70
+ // Cannot build a series without a reset epoch
71
+ continue;
72
+ }
73
+
74
+ const series: WindowSample[] = [seriesEnd];
75
+
76
+ // Walk backward from endIdx to find the longest valid prefix
77
+ for (let i = endIdx - 1; i >= 0; i -= 1) {
78
+ const candidate = sorted[i]; // EARLIER in time
79
+ if (!candidate) break; // TypeScript guard
80
+
81
+ const nextSample = series[0]; // The most recent sample we've added
82
+ if (!nextSample) break; // TypeScript guard
83
+
84
+ // Check reset epoch unchanged
85
+ if (candidate.resetEpoch !== seriesEndEpoch) {
86
+ break;
87
+ }
88
+
89
+ // Check gap constraint: gap between candidate and the NEXT sample (which is series[0] on first iteration)
90
+ // We're building backward, so we prepend to series
91
+ // series[0] will be the sample immediately AFTER candidate in chronological order
92
+ const gap = nextSample.recordedAtMs - candidate.recordedAtMs;
93
+ if (gap > MAX_GAP_MS) {
94
+ break;
95
+ }
96
+
97
+ // Check monotonic non-decreasing utilization
98
+ const candidateUtil = utilizationFromRemainingFraction(candidate.remainingFraction!);
99
+ const nextUtil = utilizationFromRemainingFraction(nextSample.remainingFraction!);
100
+
101
+ if (candidateUtil === undefined || nextUtil === undefined) {
102
+ break;
103
+ }
104
+
105
+ // Utilization must be non-decreasing as we move forward in time
106
+ // candidate is EARLIER than nextSample
107
+ // Therefore candidateUtil must be ≤ nextUtil
108
+ if (candidateUtil > nextUtil) {
109
+ // Utilization decreased moving forward in time - reset boundary
110
+ break;
111
+ }
112
+
113
+ // Prepend to series (we're building backward)
114
+ series.unshift(candidate);
115
+ }
116
+
117
+ // Series is now in chronological order (oldest first) because we prepended
118
+
119
+ if (series.length >= MIN_SAMPLES_REQUIRED) {
120
+ // We have a valid series - compute rate
121
+ const earliest = series[0];
122
+ const latest = series[series.length - 1];
123
+
124
+ if (!earliest || !latest) {
125
+ // Should not happen, but TypeScript guard
126
+ continue;
127
+ }
128
+
129
+ const earliestUtil = utilizationFromRemainingFraction(earliest.remainingFraction!);
130
+ const latestUtil = utilizationFromRemainingFraction(latest.remainingFraction!);
131
+
132
+ if (earliestUtil === undefined || latestUtil === undefined) {
133
+ // Should not happen given prior checks, but be defensive
134
+ continue;
135
+ }
136
+
137
+ const elapsedMs = latest.recordedAtMs - earliest.recordedAtMs;
138
+
139
+ if (elapsedMs <= 0) {
140
+ // All samples at the same timestamp - cannot compute rate
141
+ return {
142
+ status: "unavailable",
143
+ reason: "zero elapsed time",
144
+ };
145
+ }
146
+
147
+ const elapsedHours = elapsedMs / MS_PER_HOUR;
148
+ const utilizationDelta = latestUtil - earliestUtil;
149
+ const rate = 100 * utilizationDelta / elapsedHours;
150
+
151
+ return {
152
+ status: "available",
153
+ rate,
154
+ };
155
+ }
156
+ }
157
+
158
+ // No valid series found
159
+ return {
160
+ status: "unavailable",
161
+ reason: "no valid series found (epoch boundary, gap >30min, or utilization decreased)",
162
+ };
163
+ }