@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.
- package/LICENSE +21 -0
- package/NOTICE +29 -0
- package/README.md +999 -0
- package/config/models/pi-multi-account.v1.json +32 -0
- package/config/subscription-plans.v1.json +122 -0
- package/package.json +76 -0
- package/packages/pi-anthropic-oauth/LICENSE +21 -0
- package/packages/pi-anthropic-oauth/package.json +54 -0
- package/packages/pi-anthropic-oauth/src/auth.ts +396 -0
- package/packages/pi-anthropic-oauth/src/context.ts +116 -0
- package/packages/pi-anthropic-oauth/src/convert.ts +303 -0
- package/packages/pi-anthropic-oauth/src/index.ts +37 -0
- package/packages/pi-anthropic-oauth/src/prompt.ts +137 -0
- package/packages/pi-anthropic-oauth/src/stream.ts +476 -0
- package/packages/pi-antigravity/LICENSE +21 -0
- package/packages/pi-antigravity/package.json +77 -0
- package/packages/pi-antigravity/src/auth/index.ts +14 -0
- package/packages/pi-antigravity/src/auth/oauth.ts +442 -0
- package/packages/pi-antigravity/src/client/client.ts +561 -0
- package/packages/pi-antigravity/src/client/index.ts +1 -0
- package/packages/pi-antigravity/src/context.ts +110 -0
- package/packages/pi-antigravity/src/diagnostics/diagnostics.ts +96 -0
- package/packages/pi-antigravity/src/diagnostics/index.ts +1 -0
- package/packages/pi-antigravity/src/image/image.ts +336 -0
- package/packages/pi-antigravity/src/image/index.ts +1 -0
- package/packages/pi-antigravity/src/index.ts +280 -0
- package/packages/pi-antigravity/src/models/discovery.ts +154 -0
- package/packages/pi-antigravity/src/models/grouping.ts +424 -0
- package/packages/pi-antigravity/src/models/index.ts +3 -0
- package/packages/pi-antigravity/src/models/models.ts +500 -0
- package/packages/pi-antigravity/src/stream/index.ts +1 -0
- package/packages/pi-antigravity/src/stream/stream.ts +1478 -0
- package/packages/pi-antigravity/src/types/enums.ts +42 -0
- package/packages/pi-antigravity/src/types/index.ts +2 -0
- package/packages/pi-antigravity/src/types/types.ts +292 -0
- package/packages/pi-antigravity/src/usage/index.ts +1 -0
- package/packages/pi-antigravity/src/usage/usage.ts +416 -0
- package/packages/pi-antigravity/src/utils/http.ts +91 -0
- package/packages/pi-antigravity/src/utils/index.ts +3 -0
- package/packages/pi-antigravity/src/utils/security.ts +73 -0
- package/packages/pi-antigravity/src/utils/util.ts +132 -0
- package/scripts/multi-account.mjs +44 -0
- package/src/account-labels.ts +223 -0
- package/src/account-plan-assignment.ts +340 -0
- package/src/account-rate-history.ts +372 -0
- package/src/anthropic-adaptive-stream.ts +531 -0
- package/src/anthropic-alias-stream.ts +140 -0
- package/src/anthropic-context-compat.ts +80 -0
- package/src/api-pricing.ts +579 -0
- package/src/bounded-file-lines.ts +97 -0
- package/src/catalog-rebinding.ts +177 -0
- package/src/catalog-registration-probe.ts +111 -0
- package/src/codex-adapter.ts +345 -0
- package/src/codex-model-defaults.ts +785 -0
- package/src/command-completions.ts +404 -0
- package/src/commands.ts +2000 -0
- package/src/compaction.ts +14 -0
- package/src/config.ts +1317 -0
- package/src/continuation.ts +569 -0
- package/src/cooldowns.ts +110 -0
- package/src/cost-digest-store.ts +332 -0
- package/src/cost-digest.ts +1044 -0
- package/src/cost-history.ts +251 -0
- package/src/cost-period-closer.ts +160 -0
- package/src/cost-report-json.ts +318 -0
- package/src/cost-report-reader.ts +368 -0
- package/src/cost-report-render.ts +207 -0
- package/src/cost-report.ts +1104 -0
- package/src/coverage-attestation.ts +397 -0
- package/src/credential-lifecycle.ts +169 -0
- package/src/credential-refresh.ts +248 -0
- package/src/declaration-notice-marker.ts +238 -0
- package/src/diagnostic-store.ts +276 -0
- package/src/diagnostics.ts +309 -0
- package/src/discovery.ts +471 -0
- package/src/duration.ts +13 -0
- package/src/error-classification.ts +256 -0
- package/src/fuzzy.ts +15 -0
- package/src/group-policy.ts +81 -0
- package/src/history-store.ts +897 -0
- package/src/index.ts +5572 -0
- package/src/lifecycle.ts +378 -0
- package/src/logical-dispatch.ts +279 -0
- package/src/logical-model-selector.ts +254 -0
- package/src/logical-model-switcher.ts +430 -0
- package/src/logical-provider-attribution.ts +544 -0
- package/src/logical-provider.ts +1237 -0
- package/src/logical-route-indicator.ts +215 -0
- package/src/machine-lease.ts +445 -0
- package/src/model-support.ts +66 -0
- package/src/models-declaration.ts +1091 -0
- package/src/openai-adapter.ts +117 -0
- package/src/openrouter-budget.ts +304 -0
- package/src/openrouter-fallback.ts +146 -0
- package/src/period-boundaries.ts +376 -0
- package/src/pi-anthropic-oauth.d.ts +6 -0
- package/src/preflight.ts +253 -0
- package/src/pricing-cache.ts +235 -0
- package/src/project-identity.ts +100 -0
- package/src/provider-registration.ts +942 -0
- package/src/rate-formula.ts +163 -0
- package/src/recovery-engine.ts +853 -0
- package/src/recovery-output.ts +837 -0
- package/src/recovery-plan.ts +239 -0
- package/src/report-range.ts +203 -0
- package/src/route-resolver.ts +789 -0
- package/src/routing-config-transaction.ts +232 -0
- package/src/routing.ts +1163 -0
- package/src/runtime-state.ts +630 -0
- package/src/session-account-groups.ts +284 -0
- package/src/session-restore.ts +287 -0
- package/src/shared-usage.ts +1392 -0
- package/src/standalone-cli.ts +720 -0
- package/src/status-view.ts +578 -0
- package/src/subscription-plan-catalog.ts +346 -0
- package/src/tier-model-resolver.ts +46 -0
- package/src/upstream-anthropic.ts +315 -0
- package/src/upstream-antigravity.ts +327 -0
- package/src/usage-fetch.ts +1634 -0
- package/src/usage.ts +1026 -0
- package/src/vendor.ts +87 -0
- package/src/warmer.ts +231 -0
- package/src/watchdog.ts +219 -0
- 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
|
+
}
|