pi-antigravity-rotator 2.3.1 → 2.3.2
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/CHANGELOG.md +20 -0
- package/README.md +17 -11
- package/package.json +11 -7
- package/src/cli.ts +27 -2
- package/src/compat/translators.ts +58 -8
- package/src/compat.ts +103 -15
- package/src/exposure.ts +17 -0
- package/src/index.ts +12 -0
- package/src/login.ts +4 -3
- package/src/notification-poller.ts +23 -10
- package/src/onboarding.ts +16 -1
- package/src/proxy.ts +398 -392
- package/src/rotator.ts +10 -6
- package/src/static/dashboard.js +7 -2
- package/src/telemetry.ts +7 -5
- package/src/types.ts +2 -9
- package/src/version-check.ts +23 -10
- package/tools/telemetry-receiver/README.md +2 -1
package/src/rotator.ts
CHANGED
|
@@ -44,6 +44,7 @@ import { logger } from "./logger.js";
|
|
|
44
44
|
import { getUpdateInfo } from "./version-check.js";
|
|
45
45
|
import { getNotifications } from "./notification-poller.js";
|
|
46
46
|
import { getConfiguredAdminToken } from "./admin-auth.js";
|
|
47
|
+
import { getProxyExposureWarning } from "./exposure.js";
|
|
47
48
|
import {
|
|
48
49
|
getCachedState,
|
|
49
50
|
setCachedState,
|
|
@@ -876,7 +877,7 @@ export class AccountRotator {
|
|
|
876
877
|
const state = this.modelState.get(modelKey);
|
|
877
878
|
if (state) {
|
|
878
879
|
state.requestsOnActiveAccount++;
|
|
879
|
-
this.
|
|
880
|
+
this.scheduleStateSave();
|
|
880
881
|
}
|
|
881
882
|
}
|
|
882
883
|
|
|
@@ -2165,7 +2166,7 @@ export class AccountRotator {
|
|
|
2165
2166
|
account.dailyRequestCount++;
|
|
2166
2167
|
this.projectRequests[account.config.projectId] =
|
|
2167
2168
|
(this.projectRequests[account.config.projectId] ?? 0) + 1;
|
|
2168
|
-
this.
|
|
2169
|
+
this.scheduleStateSave();
|
|
2169
2170
|
}
|
|
2170
2171
|
|
|
2171
2172
|
getSafetyJitterMs(account: AccountRuntime): number {
|
|
@@ -2655,6 +2656,11 @@ export class AccountRotator {
|
|
|
2655
2656
|
}
|
|
2656
2657
|
}
|
|
2657
2658
|
|
|
2659
|
+
const adminWarning = getConfiguredAdminToken()
|
|
2660
|
+
? null
|
|
2661
|
+
: `Admin routes are exposed on ${this.config.bindHost}:${this.config.proxyPort} because PI_ROTATOR_ADMIN_TOKEN is not configured.`;
|
|
2662
|
+
const proxyWarning = getProxyExposureWarning(this.config);
|
|
2663
|
+
|
|
2658
2664
|
return {
|
|
2659
2665
|
version: updateInfo.currentVersion,
|
|
2660
2666
|
proxyPort: this.config.proxyPort,
|
|
@@ -2676,9 +2682,7 @@ export class AccountRotator {
|
|
|
2676
2682
|
},
|
|
2677
2683
|
security: {
|
|
2678
2684
|
adminTokenConfigured: !!getConfiguredAdminToken(),
|
|
2679
|
-
warning:
|
|
2680
|
-
? null
|
|
2681
|
-
: `Admin routes are exposed on ${this.config.bindHost}:${this.config.proxyPort} because PI_ROTATOR_ADMIN_TOKEN is not configured.`,
|
|
2685
|
+
warning: [adminWarning, proxyWarning].filter(Boolean).join(" ") || null,
|
|
2682
2686
|
bindHost: this.config.bindHost || "0.0.0.0",
|
|
2683
2687
|
},
|
|
2684
2688
|
routingDiagnostics,
|
|
@@ -2905,7 +2909,7 @@ export class AccountRotator {
|
|
|
2905
2909
|
}
|
|
2906
2910
|
|
|
2907
2911
|
setAccountTier(email: string, tier: string): boolean {
|
|
2908
|
-
const validTiers = ["unknown", "free", "pro", "ultra"];
|
|
2912
|
+
const validTiers = ["unknown", "free", "plus", "pro", "ultra"];
|
|
2909
2913
|
if (!validTiers.includes(tier)) return false;
|
|
2910
2914
|
const account = this.accounts.find((a) => a.config.email === email);
|
|
2911
2915
|
if (!account) return false;
|
package/src/static/dashboard.js
CHANGED
|
@@ -370,6 +370,10 @@ function renderAccounts(data) {
|
|
|
370
370
|
"FREE</div>" +
|
|
371
371
|
'<div class="tier-option" onclick="setAccountTier(\'' +
|
|
372
372
|
jsString(a.email) +
|
|
373
|
+
"', 'plus')\">" +
|
|
374
|
+
"PLUS</div>" +
|
|
375
|
+
'<div class="tier-option" onclick="setAccountTier(\'' +
|
|
376
|
+
jsString(a.email) +
|
|
373
377
|
"', 'pro')\">" +
|
|
374
378
|
"PRO</div>" +
|
|
375
379
|
'<div class="tier-option" onclick="setAccountTier(\'' +
|
|
@@ -836,8 +840,9 @@ function renderAttentionPanel(data) {
|
|
|
836
840
|
"Security warning",
|
|
837
841
|
security.warning,
|
|
838
842
|
[
|
|
839
|
-
"
|
|
840
|
-
"
|
|
843
|
+
"Dashboard and admin APIs require the admin token.",
|
|
844
|
+
"Native and /v1 proxy routes do not require a token.",
|
|
845
|
+
"For local-only usage, set bindHost to 127.0.0.1 or bind the Docker port to 127.0.0.1.",
|
|
841
846
|
],
|
|
842
847
|
"warning",
|
|
843
848
|
),
|
package/src/telemetry.ts
CHANGED
|
@@ -9,8 +9,10 @@
|
|
|
9
9
|
// - Flag events: HTTP status, matched patterns, model, pool state,
|
|
10
10
|
// request velocity — everything needed to improve the anti-flag algorithm
|
|
11
11
|
//
|
|
12
|
-
// What we NEVER
|
|
13
|
-
// - Emails, tokens,
|
|
12
|
+
// What we NEVER include in telemetry payloads or event files:
|
|
13
|
+
// - Emails, tokens, project IDs, request bodies, error message text
|
|
14
|
+
// Source IPs are not part of the JSON telemetry payload, but the receiver and
|
|
15
|
+
// network path can observe them for transport and rate limiting.
|
|
14
16
|
//
|
|
15
17
|
// Docs: https://github.com/tuxevil/pi-antigravity-rotator#telemetry
|
|
16
18
|
|
|
@@ -129,8 +131,8 @@ function printTelemetryNotice(): void {
|
|
|
129
131
|
console.log();
|
|
130
132
|
console.log(" ╭──────────────────────────────────────────────────────────╮");
|
|
131
133
|
console.log(" │ Anonymous telemetry is enabled to help improve the │");
|
|
132
|
-
console.log(" │ rotator. No emails, tokens,
|
|
133
|
-
console.log(" │
|
|
134
|
+
console.log(" │ rotator. No emails, tokens, project IDs, request bodies │");
|
|
135
|
+
console.log(" │ or error text are sent — only aggregate usage stats. │");
|
|
134
136
|
console.log(" │ │");
|
|
135
137
|
console.log(" │ Flag events help us improve the anti-flag algorithm │");
|
|
136
138
|
console.log(" │ for everyone. Consider keeping telemetry on! │");
|
|
@@ -182,7 +184,7 @@ export interface TelemetryPayload {
|
|
|
182
184
|
// This is the most important telemetry signal — it drives anti-flag
|
|
183
185
|
// algorithm improvements that benefit all users.
|
|
184
186
|
//
|
|
185
|
-
// NO PII: no email, no error text, no
|
|
187
|
+
// NO PII in the payload: no email, no error text, no projectId, no request body.
|
|
186
188
|
// Only structured, anonymous context about what happened.
|
|
187
189
|
export interface FlagEventData {
|
|
188
190
|
// What triggered it
|
package/src/types.ts
CHANGED
|
@@ -150,14 +150,6 @@ export interface ModelSpecConfig {
|
|
|
150
150
|
isThinking: boolean;
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
// Per-model thinking/output spec used by the compat layer.
|
|
154
|
-
// Operators can override defaults via the `modelSpecs` field in accounts.json.
|
|
155
|
-
export interface ModelSpecConfig {
|
|
156
|
-
maxOutputTokens: number;
|
|
157
|
-
thinkingBudget: number; // -1 = adaptive (model decides), >=0 = fixed
|
|
158
|
-
isThinking: boolean;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
153
|
// Per-model quota info for an account
|
|
162
154
|
export interface ModelQuota {
|
|
163
155
|
modelKey: string;
|
|
@@ -619,9 +611,10 @@ export const CLIENT_SECRET = atob(
|
|
|
619
611
|
);
|
|
620
612
|
export const TOKEN_URL = "https://oauth2.googleapis.com/token";
|
|
621
613
|
|
|
614
|
+
// Production default: use the daily Cloud Code Assist endpoint. The proxy
|
|
615
|
+
// forwarder supports cascading if additional verified endpoints are added here.
|
|
622
616
|
export const ANTIGRAVITY_ENDPOINTS = [
|
|
623
617
|
"https://daily-cloudcode-pa.googleapis.com",
|
|
624
|
-
// "https://cloudcode-pa.googleapis.com",
|
|
625
618
|
] as const;
|
|
626
619
|
|
|
627
620
|
export const QUOTA_API_URL =
|
package/src/version-check.ts
CHANGED
|
@@ -26,6 +26,7 @@ let cachedInfo: UpdateInfo = {
|
|
|
26
26
|
updateAvailable: false,
|
|
27
27
|
checkedAt: 0,
|
|
28
28
|
};
|
|
29
|
+
let initialCheckTimer: ReturnType<typeof setTimeout> | null = null;
|
|
29
30
|
let checkTimer: ReturnType<typeof setInterval> | null = null;
|
|
30
31
|
|
|
31
32
|
/**
|
|
@@ -123,18 +124,26 @@ export function getUpdateInfo(): UpdateInfo {
|
|
|
123
124
|
*/
|
|
124
125
|
export function startVersionChecker(): void {
|
|
125
126
|
// Initial delayed check
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
127
|
+
if (!initialCheckTimer) {
|
|
128
|
+
initialCheckTimer = setTimeout(() => {
|
|
129
|
+
initialCheckTimer = null;
|
|
130
|
+
void checkForUpdate();
|
|
131
|
+
}, 10_000);
|
|
132
|
+
if (initialCheckTimer.unref) {
|
|
133
|
+
initialCheckTimer.unref();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
129
136
|
|
|
130
137
|
// Periodic check
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
checkTimer.unref
|
|
138
|
+
if (!checkTimer) {
|
|
139
|
+
checkTimer = setInterval(() => {
|
|
140
|
+
void checkForUpdate();
|
|
141
|
+
}, CHECK_INTERVAL_MS);
|
|
142
|
+
|
|
143
|
+
// Don't keep process alive just for version checking
|
|
144
|
+
if (checkTimer.unref) {
|
|
145
|
+
checkTimer.unref();
|
|
146
|
+
}
|
|
138
147
|
}
|
|
139
148
|
}
|
|
140
149
|
|
|
@@ -142,6 +151,10 @@ export function startVersionChecker(): void {
|
|
|
142
151
|
* Stop periodic version checking.
|
|
143
152
|
*/
|
|
144
153
|
export function stopVersionChecker(): void {
|
|
154
|
+
if (initialCheckTimer) {
|
|
155
|
+
clearTimeout(initialCheckTimer);
|
|
156
|
+
initialCheckTimer = null;
|
|
157
|
+
}
|
|
145
158
|
if (checkTimer) {
|
|
146
159
|
clearInterval(checkTimer);
|
|
147
160
|
checkTimer = null;
|
|
@@ -113,7 +113,8 @@ curl -H "Authorization: Bearer YOUR_STATS_TOKEN" https://telemetry.yourdomain.co
|
|
|
113
113
|
|
|
114
114
|
## Security
|
|
115
115
|
|
|
116
|
-
- **No PII is stored**: no emails, tokens,
|
|
116
|
+
- **No PII is stored in telemetry event files**: no emails, tokens, project IDs, request bodies, or error text
|
|
117
|
+
- Source IPs are used transiently for in-memory rate limiting and may be visible to your network, host, or reverse-proxy logs. The receiver does not write IPs into telemetry JSONL event files.
|
|
117
118
|
- Email-pattern detection in validation: payloads containing `@` email patterns are rejected
|
|
118
119
|
- Payloads capped at 4KB
|
|
119
120
|
- Rate limited: 12 req/min per IP
|