shariq-pi-extensions 0.2.25 → 0.2.26
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/extensions/antigravity-provider/README.md +1 -1
- package/extensions/antigravity-provider/antigravity/dashboard.ts +26 -5
- package/extensions/antigravity-provider/antigravity/index.ts +1 -3
- package/extensions/factory-provider/API_KEYS.md +1 -1
- package/extensions/factory-provider/README.md +1 -1
- package/extensions/factory-provider/factory/dashboard.ts +24 -10
- package/extensions/factory-provider/index.ts +1 -3
- package/package.json +1 -1
|
@@ -10,7 +10,7 @@ Local persistent Pi provider for Google Antigravity-compatible models.
|
|
|
10
10
|
|
|
11
11
|
The provider includes an IPv4 OAuth token-exchange fallback for Node environments where the default request fails. Its curated catalog follows current Antigravity model identifiers and runtime behavior.
|
|
12
12
|
|
|
13
|
-
Successful logins are added to `<agent-dir>/antigravity/accounts.json`, written with owner-only permissions. A missing account file triggers one-time migration of an existing Pi OAuth credential; after that, the valid account file is authoritative, so removing an account cannot be undone by a stale credential in `auth.json`. Requests select the least recently used eligible account, skip disabled/cooling/exhausted accounts, refresh expiring OAuth tokens, and rotate to another account when an auth, rate, quota, or capacity failure occurs before response streaming begins. Cached per-model remaining quota and reset times guide selection; `/antigravity` refreshes the authoritative catalog, uses `d` to reversibly enable or disable an account, and uses `x`
|
|
13
|
+
Successful logins are added to `<agent-dir>/antigravity/accounts.json`, written with owner-only permissions. A missing account file triggers one-time migration of an existing Pi OAuth credential; after that, the valid account file is authoritative, so removing an account cannot be undone by a stale credential in `auth.json`. Requests select the least recently used eligible account, skip disabled/cooling/exhausted accounts, refresh expiring OAuth tokens, and rotate to another account when an auth, rate, quota, or capacity failure occurs before response streaming begins. Cached per-model remaining quota and reset times guide selection; `/antigravity` refreshes the authoritative catalog, uses `d` to reversibly enable or disable an account, and uses `x` twice to confirm and remove one permanently; Escape cancels an armed removal.
|
|
14
14
|
|
|
15
15
|
Current public model IDs:
|
|
16
16
|
- `antigravity/gemini-3.7-flash`
|
|
@@ -71,6 +71,7 @@ function compactGroup(label: string, entries: AntigravityQuotaEntry[]) {
|
|
|
71
71
|
export class AntigravityDashboard implements Component {
|
|
72
72
|
private selected = 0;
|
|
73
73
|
private refreshing = false;
|
|
74
|
+
private pendingRemoval: { id: string; label: string } | undefined;
|
|
74
75
|
private closed = false;
|
|
75
76
|
private readonly tui: TUI;
|
|
76
77
|
private readonly theme: Theme;
|
|
@@ -132,21 +133,36 @@ export class AntigravityDashboard implements Component {
|
|
|
132
133
|
handleInput(data: string) {
|
|
133
134
|
const accounts = this.snapshot.accounts;
|
|
134
135
|
if (this.keys.matches(data, "tui.select.cancel")) {
|
|
136
|
+
if (this.pendingRemoval) {
|
|
137
|
+
this.pendingRemoval = undefined;
|
|
138
|
+
this.tui.requestRender();
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
135
141
|
this.closed = true;
|
|
136
142
|
this.done();
|
|
137
143
|
return;
|
|
138
144
|
}
|
|
139
145
|
if (this.keys.matches(data, "tui.select.up") || data === "k") {
|
|
146
|
+
this.pendingRemoval = undefined;
|
|
140
147
|
if (accounts.length) this.selected = (this.selected - 1 + accounts.length) % accounts.length;
|
|
141
148
|
} else if (this.keys.matches(data, "tui.select.down") || data === "j") {
|
|
149
|
+
this.pendingRemoval = undefined;
|
|
142
150
|
if (accounts.length) this.selected = (this.selected + 1) % accounts.length;
|
|
143
151
|
} else if (data === "r") {
|
|
152
|
+
this.pendingRemoval = undefined;
|
|
144
153
|
this.startRefresh(true);
|
|
145
154
|
} else if ((data === "d" || data === "x") && accounts[this.selected] && !this.refreshing) {
|
|
146
155
|
const account = accounts[this.selected]!;
|
|
156
|
+
const label = account.email || `account-${account.id.slice(0, 6)}`;
|
|
157
|
+
if (data === "x" && this.pendingRemoval?.id !== account.id) {
|
|
158
|
+
this.pendingRemoval = { id: account.id, label };
|
|
159
|
+
this.tui.requestRender();
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
this.pendingRemoval = undefined;
|
|
147
163
|
this.refreshing = true;
|
|
148
164
|
const action = data === "x"
|
|
149
|
-
? this.removeAccount(account.id,
|
|
165
|
+
? this.removeAccount(account.id, label)
|
|
150
166
|
: this.toggleAccount(account.id, account.disabled === true);
|
|
151
167
|
void action
|
|
152
168
|
.then((snapshot) => this.replaceSnapshot(snapshot))
|
|
@@ -172,9 +188,11 @@ export class AntigravityDashboard implements Component {
|
|
|
172
188
|
const active = accounts.filter((account) => account.active).length;
|
|
173
189
|
const right = this.refreshing
|
|
174
190
|
? this.theme.fg("warning", "refreshing…")
|
|
175
|
-
: this.
|
|
176
|
-
? this.theme.fg("warning", oneLine(this.
|
|
177
|
-
: this.
|
|
191
|
+
: this.pendingRemoval
|
|
192
|
+
? this.theme.fg("warning", `press x again to remove ${oneLine(this.pendingRemoval.label)}`)
|
|
193
|
+
: this.snapshot.warning
|
|
194
|
+
? this.theme.fg("warning", oneLine(this.snapshot.warning))
|
|
195
|
+
: this.theme.fg("muted", `${active}/${accounts.length} active · ${this.snapshot.modelCount} models`);
|
|
178
196
|
const title = ` ${this.theme.fg("accent", this.theme.bold("◆ ANTIGRAVITY"))} ${this.theme.fg("dim", `· ${this.snapshot.authentication}`)}`;
|
|
179
197
|
const lines = width >= 64
|
|
180
198
|
? [joinSides(title, `${right} `, width)]
|
|
@@ -194,7 +212,10 @@ export class AntigravityDashboard implements Component {
|
|
|
194
212
|
for (let row = 0; row < bodyHeight; row++) lines.push(this.theme.fg("border", "│") + padLine(list[row] ?? "", inner) + this.theme.fg("border", "│"));
|
|
195
213
|
}
|
|
196
214
|
lines.push(frameBottom(this.theme, width));
|
|
197
|
-
|
|
215
|
+
const controls = this.pendingRemoval
|
|
216
|
+
? `${this.theme.fg("warning", " x")} ${this.theme.fg("warning", "confirm permanent removal")} ${this.theme.fg("accent", "esc")} ${this.theme.fg("dim", "cancel")}`
|
|
217
|
+
: `${this.theme.fg("accent", " ↑↓ / j k")} ${this.theme.fg("dim", "select")} ${this.theme.fg("accent", "r")} ${this.theme.fg("dim", "refresh")} ${this.theme.fg("accent", "d")} ${this.theme.fg("dim", "enable/disable")} ${this.theme.fg("accent", "x")} ${this.theme.fg("dim", "remove")} ${this.theme.fg("accent", "esc")} ${this.theme.fg("dim", "close")}`;
|
|
218
|
+
lines.push(truncateToWidth(controls, width, ""));
|
|
198
219
|
return lines.map((line) => truncateToWidth(line, width, ""));
|
|
199
220
|
}
|
|
200
221
|
|
|
@@ -135,9 +135,7 @@ export default function antigravityProviderExtension(pi: ExtensionAPI) {
|
|
|
135
135
|
if (enabled) await refreshAntigravityQuotas({ force: true, signal: ctx.signal });
|
|
136
136
|
return dashboardSnapshot(ctx);
|
|
137
137
|
},
|
|
138
|
-
async (id
|
|
139
|
-
const confirmed = await ctx.ui.confirm("Remove Antigravity account?", `Permanently remove ${label} from this Pi installation?`);
|
|
140
|
-
if (!confirmed) return dashboardSnapshot(ctx);
|
|
138
|
+
async (id) => {
|
|
141
139
|
removeAntigravityAccount(id);
|
|
142
140
|
await reconcileStoredCredential(ctx);
|
|
143
141
|
return dashboardSnapshot(ctx);
|
|
@@ -14,4 +14,4 @@ Alternatively choose Pi's top-level **Use an API key** authentication method to
|
|
|
14
14
|
|
|
15
15
|
Use `/logout` to remove the active Factory authentication selection. The configured key file is intentionally not deleted by logout.
|
|
16
16
|
|
|
17
|
-
Open `/factory` to inspect every account, its Standard/Core usage, and rotation status. File-backed keys remain visible when disabled: select one and press `d` to enable/disable it, or press `x`
|
|
17
|
+
Open `/factory` to inspect every account, its Standard/Core usage, and rotation status. File-backed keys remain visible when disabled: select one and press `d` to enable/disable it, or press `x` twice to confirm permanent removal from `api-keys.json`; Escape cancels an armed removal. Environment-provided keys are read-only. For a smoke test, use the current `factory/kimi-k3` model.
|
|
@@ -59,7 +59,7 @@ There are no `-oauth` or `-api-key` model duplicates. The user-curated catalog e
|
|
|
59
59
|
/factory
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
`/factory` opens a full-width account dashboard combining provider status, authentication, Droid/model metadata, rotation cooldowns, and separate Standard and Droid Core usage for every credential. Percentages are explicitly labeled as **used**. Navigate with the arrow keys or `j`/`k`, press `r` to force-refresh every account, use `d` to reversibly enable or disable a rotating file-backed key,
|
|
62
|
+
`/factory` opens a full-width account dashboard combining provider status, authentication, Droid/model metadata, rotation cooldowns, and separate Standard and Droid Core usage for every credential. Percentages are explicitly labeled as **used**. Navigate with the arrow keys or `j`/`k`, press `r` to force-refresh every account, use `d` to reversibly enable or disable a rotating file-backed key, press `x` twice to confirm and remove one permanently, and press Escape to cancel an armed removal or close the dashboard. Environment variables and single credentials managed by Pi auth remain read-only in this dashboard.
|
|
63
63
|
|
|
64
64
|
Usage is never estimated from Pi token counts: Factory's API already applies model multipliers and cache-hit discounts. Cached records refresh at most every 15 minutes during normal sessions and after Factory runs; the manual command is the explicit force-refresh path.
|
|
65
65
|
|
|
@@ -119,6 +119,7 @@ function stateColor(state: string) {
|
|
|
119
119
|
export class FactoryDashboard implements Component {
|
|
120
120
|
private selected = 0;
|
|
121
121
|
private refreshing = false;
|
|
122
|
+
private pendingRemoval: { id: string; label: string } | undefined;
|
|
122
123
|
private closed = false;
|
|
123
124
|
private readonly tui: TUI;
|
|
124
125
|
private readonly theme: Theme;
|
|
@@ -190,20 +191,34 @@ export class FactoryDashboard implements Component {
|
|
|
190
191
|
handleInput(data: string) {
|
|
191
192
|
const accounts = this.snapshot.accounts;
|
|
192
193
|
if (this.keys.matches(data, "tui.select.cancel")) {
|
|
194
|
+
if (this.pendingRemoval) {
|
|
195
|
+
this.pendingRemoval = undefined;
|
|
196
|
+
this.tui.requestRender();
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
193
199
|
this.closed = true;
|
|
194
200
|
this.done();
|
|
195
201
|
return;
|
|
196
202
|
}
|
|
197
203
|
if (this.keys.matches(data, "tui.select.up") || data === "k") {
|
|
204
|
+
this.pendingRemoval = undefined;
|
|
198
205
|
if (accounts.length) {
|
|
199
206
|
this.selected = (this.selected - 1 + accounts.length) % accounts.length;
|
|
200
207
|
}
|
|
201
208
|
} else if (this.keys.matches(data, "tui.select.down") || data === "j") {
|
|
209
|
+
this.pendingRemoval = undefined;
|
|
202
210
|
if (accounts.length) this.selected = (this.selected + 1) % accounts.length;
|
|
203
211
|
} else if (data === "r") {
|
|
212
|
+
this.pendingRemoval = undefined;
|
|
204
213
|
this.startRefresh(true);
|
|
205
214
|
} else if ((data === "d" || data === "x") && accounts[this.selected]?.editable && !this.refreshing) {
|
|
206
215
|
const account = accounts[this.selected]!;
|
|
216
|
+
if (data === "x" && this.pendingRemoval?.id !== account.id) {
|
|
217
|
+
this.pendingRemoval = { id: account.id, label: account.label };
|
|
218
|
+
this.tui.requestRender();
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
this.pendingRemoval = undefined;
|
|
207
222
|
this.refreshing = true;
|
|
208
223
|
const action = data === "x"
|
|
209
224
|
? this.removeAccount(account.id, account.label)
|
|
@@ -232,9 +247,11 @@ export class FactoryDashboard implements Component {
|
|
|
232
247
|
const ready = `${this.snapshot.active}/${this.snapshot.configured} active`;
|
|
233
248
|
const headerRight = this.refreshing
|
|
234
249
|
? this.theme.fg("warning", "refreshing…")
|
|
235
|
-
: this.
|
|
236
|
-
? this.theme.fg("warning", oneLine(this.
|
|
237
|
-
: this.
|
|
250
|
+
: this.pendingRemoval
|
|
251
|
+
? this.theme.fg("warning", `press x again to remove ${oneLine(this.pendingRemoval.label)}`)
|
|
252
|
+
: this.snapshot.warning
|
|
253
|
+
? this.theme.fg("warning", oneLine(this.snapshot.warning))
|
|
254
|
+
: this.theme.fg("muted", `${ready} · ${this.snapshot.modelCount} models · Droid ${this.snapshot.version}`);
|
|
238
255
|
const title = ` ${this.theme.fg("accent", this.theme.bold("◆ FACTORY"))} ${this.theme.fg("dim", `· ${this.snapshot.authentication}`)}`;
|
|
239
256
|
const lines = width >= 60
|
|
240
257
|
? [joinSides(title, `${headerRight} `, width)]
|
|
@@ -268,13 +285,10 @@ export class FactoryDashboard implements Component {
|
|
|
268
285
|
}
|
|
269
286
|
}
|
|
270
287
|
lines.push(frameBottom(this.theme, width));
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
"",
|
|
276
|
-
),
|
|
277
|
-
);
|
|
288
|
+
const controls = this.pendingRemoval
|
|
289
|
+
? `${this.theme.fg("warning", " x")} ${this.theme.fg("warning", "confirm permanent removal")} ${this.theme.fg("accent", "esc")} ${this.theme.fg("dim", "cancel")}`
|
|
290
|
+
: `${this.theme.fg("accent", " ↑↓ / j k")} ${this.theme.fg("dim", "select")} ${this.theme.fg("accent", "r")} ${this.theme.fg("dim", "refresh all")} ${this.theme.fg("accent", "d")} ${this.theme.fg("dim", "enable/disable")} ${this.theme.fg("accent", "x")} ${this.theme.fg("dim", "remove")} ${this.theme.fg("accent", "esc")} ${this.theme.fg("dim", "close")}`;
|
|
291
|
+
lines.push(truncateToWidth(controls, width, ""));
|
|
278
292
|
return lines.map((line) => truncateToWidth(line, width, ""));
|
|
279
293
|
}
|
|
280
294
|
|
|
@@ -223,9 +223,7 @@ export default async function factoryExtension(pi: ExtensionAPI) {
|
|
|
223
223
|
if (enabled) await refreshLimits(ctx, true);
|
|
224
224
|
return dashboardSnapshot(ctx);
|
|
225
225
|
},
|
|
226
|
-
async (id
|
|
227
|
-
const confirmed = await ctx.ui.confirm("Remove Factory account?", `Permanently remove ${label} from the rotating-key file?`);
|
|
228
|
-
if (!confirmed) return dashboardSnapshot(ctx);
|
|
226
|
+
async (id) => {
|
|
229
227
|
if (!removeFactoryApiKey(id)) throw new Error("This Factory credential is not editable from the rotating-key file.");
|
|
230
228
|
return dashboardSnapshot(ctx);
|
|
231
229
|
},
|