@cortexkit/opencode-antigravity-auth 2.0.0 → 2.1.0
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/README.md +3 -8
- package/dist/cli.js +330 -83
- package/dist/cli.js.map +4 -4
- package/dist/index.js +17039 -15773
- package/dist/index.js.map +4 -4
- package/dist/src/plugin/account-command-oauth.d.ts +34 -0
- package/dist/src/plugin/account-command-oauth.d.ts.map +1 -0
- package/dist/src/plugin/account-command-oauth.js +156 -0
- package/dist/src/plugin/account-command-oauth.js.map +1 -0
- package/dist/src/plugin/auth-loader.d.ts +16 -1
- package/dist/src/plugin/auth-loader.d.ts.map +1 -1
- package/dist/src/plugin/auth-loader.js +113 -32
- package/dist/src/plugin/auth-loader.js.map +1 -1
- package/dist/src/plugin/background-quota-refresh.d.ts +146 -0
- package/dist/src/plugin/background-quota-refresh.d.ts.map +1 -0
- package/dist/src/plugin/background-quota-refresh.js +347 -0
- package/dist/src/plugin/background-quota-refresh.js.map +1 -0
- package/dist/src/plugin/command-data.d.ts +61 -8
- package/dist/src/plugin/command-data.d.ts.map +1 -1
- package/dist/src/plugin/command-data.js +231 -39
- package/dist/src/plugin/command-data.js.map +1 -1
- package/dist/src/plugin/commands.d.ts +12 -9
- package/dist/src/plugin/commands.d.ts.map +1 -1
- package/dist/src/plugin/commands.js +140 -33
- package/dist/src/plugin/commands.js.map +1 -1
- package/dist/src/plugin/config/schema.d.ts +2 -0
- package/dist/src/plugin/config/schema.d.ts.map +1 -1
- package/dist/src/plugin/config/schema.js +24 -0
- package/dist/src/plugin/config/schema.js.map +1 -1
- package/dist/src/plugin/debug.d.ts +7 -0
- package/dist/src/plugin/debug.d.ts.map +1 -1
- package/dist/src/plugin/debug.js +25 -0
- package/dist/src/plugin/debug.js.map +1 -1
- package/dist/src/plugin/fetch-interceptor.d.ts.map +1 -1
- package/dist/src/plugin/fetch-interceptor.js +13 -1
- package/dist/src/plugin/fetch-interceptor.js.map +1 -1
- package/dist/src/plugin/index.d.ts +7 -0
- package/dist/src/plugin/index.d.ts.map +1 -1
- package/dist/src/plugin/index.js +127 -24
- package/dist/src/plugin/index.js.map +1 -1
- package/dist/src/plugin/killswitch.d.ts.map +1 -1
- package/dist/src/plugin/killswitch.js +12 -9
- package/dist/src/plugin/killswitch.js.map +1 -1
- package/dist/src/plugin/oauth-methods.d.ts.map +1 -1
- package/dist/src/plugin/oauth-methods.js +2 -10
- package/dist/src/plugin/oauth-methods.js.map +1 -1
- package/dist/src/plugin/quota.d.ts +42 -1
- package/dist/src/plugin/quota.d.ts.map +1 -1
- package/dist/src/plugin/quota.js +185 -41
- package/dist/src/plugin/quota.js.map +1 -1
- package/dist/src/plugin/request.d.ts.map +1 -1
- package/dist/src/plugin/request.js +6 -2
- package/dist/src/plugin/request.js.map +1 -1
- package/dist/src/plugin/ui/auth-menu.d.ts.map +1 -1
- package/dist/src/plugin/ui/auth-menu.js +2 -4
- package/dist/src/plugin/ui/auth-menu.js.map +1 -1
- package/dist/src/plugin/ui/quota-status.d.ts.map +1 -1
- package/dist/src/plugin/ui/quota-status.js +3 -5
- package/dist/src/plugin/ui/quota-status.js.map +1 -1
- package/dist/src/sidebar-state.d.ts +126 -9
- package/dist/src/sidebar-state.d.ts.map +1 -1
- package/dist/src/sidebar-state.js +185 -25
- package/dist/src/sidebar-state.js.map +1 -1
- package/dist/src/tui/command-dialogs.js +101 -3
- package/dist/src/tui/command-dialogs.js.map +1 -1
- package/dist/src/tui.d.ts.map +1 -1
- package/dist/src/tui.js +55 -20
- package/dist/src/tui.js.map +1 -1
- package/package.json +6 -6
- package/src/plugin/command-data.ts +331 -51
- package/src/sidebar-state.ts +306 -32
- package/src/tui/command-dialogs.tsx +136 -3
- package/src/tui-compiled/plugin/command-data.ts +331 -51
- package/src/tui-compiled/sidebar-state.ts +306 -32
- package/src/tui-compiled/tui/command-dialogs.tsx +189 -69
- package/src/tui-compiled/tui.tsx +73 -30
- package/src/tui.tsx +82 -28
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { createTextNode as _$createTextNode } from "opentui:runtime-module:%40opentui%2Fsolid";
|
|
2
|
-
import { insertNode as _$insertNode } from "opentui:runtime-module:%40opentui%2Fsolid";
|
|
3
1
|
import { memo as _$memo } from "opentui:runtime-module:%40opentui%2Fsolid";
|
|
4
2
|
import { insert as _$insert } from "opentui:runtime-module:%40opentui%2Fsolid";
|
|
5
3
|
import { setProp as _$setProp } from "opentui:runtime-module:%40opentui%2Fsolid";
|
|
4
|
+
import { createTextNode as _$createTextNode } from "opentui:runtime-module:%40opentui%2Fsolid";
|
|
5
|
+
import { insertNode as _$insertNode } from "opentui:runtime-module:%40opentui%2Fsolid";
|
|
6
6
|
import { createElement as _$createElement } from "opentui:runtime-module:%40opentui%2Fsolid";
|
|
7
7
|
import { createComponent as _$createComponent } from "opentui:runtime-module:%40opentui%2Fsolid";
|
|
8
8
|
/** @jsxImportSource @opentui/solid */
|
|
@@ -228,27 +228,153 @@ function renderAccountDialog(api, initialPayload, apply) {
|
|
|
228
228
|
renderMain();
|
|
229
229
|
return null;
|
|
230
230
|
};
|
|
231
|
+
const updateAccounts = knobs => {
|
|
232
|
+
const accounts = knobs.accounts;
|
|
233
|
+
if (!Array.isArray(accounts)) return;
|
|
234
|
+
payload.knobs = {
|
|
235
|
+
...payload.knobs,
|
|
236
|
+
accounts: accounts
|
|
237
|
+
};
|
|
238
|
+
};
|
|
239
|
+
const openOAuthLabelPrompt = (code, oauthUrl) => {
|
|
240
|
+
const DialogPrompt = api.ui.DialogPrompt;
|
|
241
|
+
api.ui.dialog.setSize('xlarge');
|
|
242
|
+
api.ui.dialog.replace(() => _$createComponent(DialogPrompt, {
|
|
243
|
+
title: "OAuth sign-in \u2014 label",
|
|
244
|
+
description: () => (() => {
|
|
245
|
+
var _el$ = _$createElement("text");
|
|
246
|
+
_$insertNode(_el$, _$createTextNode(`A short name for this account (optional).`));
|
|
247
|
+
return _el$;
|
|
248
|
+
})(),
|
|
249
|
+
placeholder: "e.g. work",
|
|
250
|
+
value: "",
|
|
251
|
+
onConfirm: value => {
|
|
252
|
+
const label = value.trim();
|
|
253
|
+
const args = label ? `add-oauth-finish ${code} --label ${label}` : `add-oauth-finish ${code}`;
|
|
254
|
+
void apply('antigravity-account', args, {
|
|
255
|
+
timeoutMs: 120_000
|
|
256
|
+
}).then(result => {
|
|
257
|
+
api.ui.toast({
|
|
258
|
+
message: result.text
|
|
259
|
+
});
|
|
260
|
+
updateAccounts(result.knobs);
|
|
261
|
+
renderMain();
|
|
262
|
+
}).catch(() => {
|
|
263
|
+
api.ui.toast({
|
|
264
|
+
message: 'OAuth account add failed'
|
|
265
|
+
});
|
|
266
|
+
renderMain();
|
|
267
|
+
});
|
|
268
|
+
},
|
|
269
|
+
onCancel: () => openOAuthCodePrompt(oauthUrl)
|
|
270
|
+
}));
|
|
271
|
+
};
|
|
272
|
+
const openOAuthCodePrompt = oauthUrl => {
|
|
273
|
+
const DialogPrompt = api.ui.DialogPrompt;
|
|
274
|
+
api.ui.dialog.setSize('xlarge');
|
|
275
|
+
api.ui.dialog.replace(() => _$createComponent(DialogPrompt, {
|
|
276
|
+
title: "OAuth sign-in \u2014 enter code",
|
|
277
|
+
description: () => (() => {
|
|
278
|
+
var _el$3 = _$createElement("text");
|
|
279
|
+
_$insertNode(_el$3, _$createTextNode(`After signing in, paste the full callback URL or authorization code.`));
|
|
280
|
+
return _el$3;
|
|
281
|
+
})(),
|
|
282
|
+
placeholder: "Paste callback URL or code here",
|
|
283
|
+
value: "",
|
|
284
|
+
onConfirm: value => {
|
|
285
|
+
const code = value.trim();
|
|
286
|
+
if (!code) {
|
|
287
|
+
// Empty submit must keep the user inside the flow, not
|
|
288
|
+
// silently drop them back to the account list. Surface the
|
|
289
|
+
// validation message and reopen the same prompt so the
|
|
290
|
+
// user can paste again.
|
|
291
|
+
api.ui.toast({
|
|
292
|
+
message: 'Please paste the callback URL or authorization code.'
|
|
293
|
+
});
|
|
294
|
+
openOAuthCodePrompt(oauthUrl);
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
openOAuthLabelPrompt(code, oauthUrl);
|
|
298
|
+
},
|
|
299
|
+
onCancel: () => openOAuthUrlScreen(oauthUrl)
|
|
300
|
+
}));
|
|
301
|
+
};
|
|
302
|
+
const openOAuthUrlScreen = oauthUrl => {
|
|
303
|
+
const DialogSelect = api.ui.DialogSelect;
|
|
304
|
+
api.ui.dialog.setSize('xlarge');
|
|
305
|
+
api.ui.dialog.replace(() => _$createComponent(DialogSelect, {
|
|
306
|
+
title: "OAuth sign-in",
|
|
307
|
+
options: [{
|
|
308
|
+
title: 'Copy URL to clipboard',
|
|
309
|
+
value: 'copy',
|
|
310
|
+
description: oauthUrl
|
|
311
|
+
}, {
|
|
312
|
+
title: 'Enter sign-in code',
|
|
313
|
+
value: 'code',
|
|
314
|
+
description: 'Open the URL in your browser, sign in, then paste the callback URL or code.'
|
|
315
|
+
}, {
|
|
316
|
+
title: 'Cancel',
|
|
317
|
+
value: 'cancel'
|
|
318
|
+
}],
|
|
319
|
+
onSelect: option => {
|
|
320
|
+
if (option.value === 'cancel') {
|
|
321
|
+
renderMain();
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
if (option.value === 'copy') {
|
|
325
|
+
const copied = api.renderer.copyToClipboardOSC52(oauthUrl);
|
|
326
|
+
api.ui.toast({
|
|
327
|
+
message: copied ? 'URL copied to clipboard' : 'Copy unavailable — select the URL text above to copy'
|
|
328
|
+
});
|
|
329
|
+
openOAuthUrlScreen(oauthUrl);
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
openOAuthCodePrompt(oauthUrl);
|
|
333
|
+
}
|
|
334
|
+
}));
|
|
335
|
+
};
|
|
336
|
+
const openAddOAuthStart = () => {
|
|
337
|
+
void apply('antigravity-account', 'add-oauth-start', {
|
|
338
|
+
timeoutMs: 120_000
|
|
339
|
+
}).then(result => {
|
|
340
|
+
updateAccounts(result.knobs);
|
|
341
|
+
const oauthUrl = result.knobs.oauthUrl;
|
|
342
|
+
if (typeof oauthUrl === 'string' && oauthUrl.length > 0) {
|
|
343
|
+
openOAuthUrlScreen(oauthUrl);
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
api.ui.toast({
|
|
347
|
+
message: result.text
|
|
348
|
+
});
|
|
349
|
+
renderMain();
|
|
350
|
+
}).catch(() => {
|
|
351
|
+
api.ui.toast({
|
|
352
|
+
message: 'OAuth account add failed'
|
|
353
|
+
});
|
|
354
|
+
renderMain();
|
|
355
|
+
});
|
|
356
|
+
};
|
|
231
357
|
const renderManageRow = row => {
|
|
232
358
|
const DialogSelect = api.ui.DialogSelect;
|
|
233
359
|
api.ui.dialog.setSize('xlarge');
|
|
234
360
|
api.ui.dialog.replace(() => (() => {
|
|
235
|
-
var _el$ = _$createElement("box"),
|
|
236
|
-
_el$
|
|
237
|
-
_el$
|
|
238
|
-
_el$
|
|
239
|
-
_$insertNode(_el
|
|
240
|
-
_$insertNode(_el
|
|
241
|
-
_$insertNode(_el
|
|
242
|
-
_$setProp(_el
|
|
243
|
-
_$setProp(_el
|
|
244
|
-
_$setProp(_el
|
|
245
|
-
_$insert(_el$
|
|
246
|
-
_$insert(_el$
|
|
361
|
+
var _el$5 = _$createElement("box"),
|
|
362
|
+
_el$6 = _$createElement("text"),
|
|
363
|
+
_el$7 = _$createElement("text"),
|
|
364
|
+
_el$8 = _$createElement("box");
|
|
365
|
+
_$insertNode(_el$5, _el$6);
|
|
366
|
+
_$insertNode(_el$5, _el$7);
|
|
367
|
+
_$insertNode(_el$5, _el$8);
|
|
368
|
+
_$setProp(_el$5, "flexDirection", 'column');
|
|
369
|
+
_$setProp(_el$5, "padding", 1);
|
|
370
|
+
_$setProp(_el$5, "width", '100%');
|
|
371
|
+
_$insert(_el$6, () => row.label);
|
|
372
|
+
_$insert(_el$7, (() => {
|
|
247
373
|
var _c$ = _$memo(() => row.quota.length === 0);
|
|
248
374
|
return () => _c$() ? 'no cached quota' : row.quota.map(q => q.remainingPercent == null ? `${q.label} –%` : `${q.label} ${q.remainingPercent}%`).join(', ');
|
|
249
375
|
})());
|
|
250
|
-
_$setProp(_el$
|
|
251
|
-
_$insert(_el$
|
|
376
|
+
_$setProp(_el$8, "marginTop", 1);
|
|
377
|
+
_$insert(_el$8, _$createComponent(DialogSelect, {
|
|
252
378
|
get title() {
|
|
253
379
|
return `Manage ${row.label}`;
|
|
254
380
|
},
|
|
@@ -297,7 +423,7 @@ function renderAccountDialog(api, initialPayload, apply) {
|
|
|
297
423
|
});
|
|
298
424
|
}
|
|
299
425
|
}));
|
|
300
|
-
return _el
|
|
426
|
+
return _el$5;
|
|
301
427
|
})());
|
|
302
428
|
};
|
|
303
429
|
const promptRemove = index => {
|
|
@@ -335,19 +461,19 @@ function renderAccountDialog(api, initialPayload, apply) {
|
|
|
335
461
|
const rows = rowsFromKnobs();
|
|
336
462
|
const bodyLines = rows.length ? rows.map(formatQuotaRowLine) : ['No accounts configured. Add one via the menu below.'];
|
|
337
463
|
api.ui.dialog.replace(() => (() => {
|
|
338
|
-
var _el$
|
|
339
|
-
_el$
|
|
340
|
-
_$insertNode(_el$
|
|
341
|
-
_$setProp(_el$
|
|
342
|
-
_$setProp(_el$
|
|
343
|
-
_$setProp(_el$
|
|
344
|
-
_$insert(_el$
|
|
345
|
-
var _el$
|
|
346
|
-
_$insert(_el$
|
|
347
|
-
return _el$
|
|
348
|
-
})()), _el$
|
|
349
|
-
_$setProp(_el$
|
|
350
|
-
_$insert(_el$
|
|
464
|
+
var _el$9 = _$createElement("box"),
|
|
465
|
+
_el$0 = _$createElement("box");
|
|
466
|
+
_$insertNode(_el$9, _el$0);
|
|
467
|
+
_$setProp(_el$9, "flexDirection", 'column');
|
|
468
|
+
_$setProp(_el$9, "padding", 1);
|
|
469
|
+
_$setProp(_el$9, "width", '100%');
|
|
470
|
+
_$insert(_el$9, () => bodyLines.map(line => (() => {
|
|
471
|
+
var _el$1 = _$createElement("text");
|
|
472
|
+
_$insert(_el$1, line);
|
|
473
|
+
return _el$1;
|
|
474
|
+
})()), _el$0);
|
|
475
|
+
_$setProp(_el$0, "marginTop", 1);
|
|
476
|
+
_$insert(_el$0, _$createComponent(DialogSelect, {
|
|
351
477
|
title: "Antigravity accounts",
|
|
352
478
|
get options() {
|
|
353
479
|
return [{
|
|
@@ -370,13 +496,7 @@ function renderAccountDialog(api, initialPayload, apply) {
|
|
|
370
496
|
return;
|
|
371
497
|
}
|
|
372
498
|
if (raw === 'add') {
|
|
373
|
-
|
|
374
|
-
timeoutMs: 120_000
|
|
375
|
-
}).catch(() => {
|
|
376
|
-
api.ui.toast({
|
|
377
|
-
message: 'Account add failed'
|
|
378
|
-
});
|
|
379
|
-
});
|
|
499
|
+
openAddOAuthStart();
|
|
380
500
|
return;
|
|
381
501
|
}
|
|
382
502
|
if (raw.startsWith('__manage__ ')) {
|
|
@@ -390,7 +510,7 @@ function renderAccountDialog(api, initialPayload, apply) {
|
|
|
390
510
|
});
|
|
391
511
|
}
|
|
392
512
|
}));
|
|
393
|
-
return _el$
|
|
513
|
+
return _el$9;
|
|
394
514
|
})());
|
|
395
515
|
};
|
|
396
516
|
renderMain();
|
|
@@ -452,19 +572,19 @@ function renderRoutingDialog(api, initialPayload, apply) {
|
|
|
452
572
|
} = readRouting();
|
|
453
573
|
const bodyLines = [`cli_first: ${cliFirst ? 'on' : 'off'}`, `quota_style_fallback: ${quotaFallback ? 'on' : 'off'}`];
|
|
454
574
|
api.ui.dialog.replace(() => (() => {
|
|
455
|
-
var _el$
|
|
456
|
-
_el$
|
|
457
|
-
_$insertNode(_el$
|
|
458
|
-
_$setProp(_el$
|
|
459
|
-
_$setProp(_el$
|
|
460
|
-
_$setProp(_el$
|
|
461
|
-
_$insert(_el$
|
|
462
|
-
var _el$
|
|
463
|
-
_$insert(_el$
|
|
464
|
-
return _el$
|
|
465
|
-
})()), _el$
|
|
466
|
-
_$setProp(_el$
|
|
467
|
-
_$insert(_el$
|
|
575
|
+
var _el$10 = _$createElement("box"),
|
|
576
|
+
_el$11 = _$createElement("box");
|
|
577
|
+
_$insertNode(_el$10, _el$11);
|
|
578
|
+
_$setProp(_el$10, "flexDirection", 'column');
|
|
579
|
+
_$setProp(_el$10, "padding", 1);
|
|
580
|
+
_$setProp(_el$10, "width", '100%');
|
|
581
|
+
_$insert(_el$10, () => bodyLines.map(line => (() => {
|
|
582
|
+
var _el$12 = _$createElement("text");
|
|
583
|
+
_$insert(_el$12, line);
|
|
584
|
+
return _el$12;
|
|
585
|
+
})()), _el$11);
|
|
586
|
+
_$setProp(_el$11, "marginTop", 1);
|
|
587
|
+
_$insert(_el$11, _$createComponent(DialogSelect, {
|
|
468
588
|
title: "Antigravity routing",
|
|
469
589
|
options: [{
|
|
470
590
|
title: `${cliFirst ? '●' : '○'} cli_first: ${cliFirst}`,
|
|
@@ -498,7 +618,7 @@ function renderRoutingDialog(api, initialPayload, apply) {
|
|
|
498
618
|
});
|
|
499
619
|
}
|
|
500
620
|
}));
|
|
501
|
-
return _el$
|
|
621
|
+
return _el$10;
|
|
502
622
|
})());
|
|
503
623
|
};
|
|
504
624
|
renderMain();
|
|
@@ -559,9 +679,9 @@ function renderKillswitchDialog(api, initialPayload, apply) {
|
|
|
559
679
|
api.ui.dialog.replace(() => _$createComponent(DialogPrompt, {
|
|
560
680
|
title: "Antigravity killswitch \u2014 set threshold",
|
|
561
681
|
description: () => (() => {
|
|
562
|
-
var _el$
|
|
563
|
-
_$insertNode(_el$
|
|
564
|
-
return _el$
|
|
682
|
+
var _el$13 = _$createElement("text");
|
|
683
|
+
_$insertNode(_el$13, _$createTextNode(`Enter a new minimum_remaining_percent (0-100). Empty input cancels.`));
|
|
684
|
+
return _el$13;
|
|
565
685
|
})(),
|
|
566
686
|
placeholder: `${currentMinimum}`,
|
|
567
687
|
value: `${currentMinimum}`,
|
|
@@ -602,19 +722,19 @@ function renderKillswitchDialog(api, initialPayload, apply) {
|
|
|
602
722
|
const accountKeys = Object.keys(accounts);
|
|
603
723
|
const bodyLines = [`Killswitch: ${enabled ? 'enabled' : 'disabled'}`, `Minimum remaining percent: ${minimum}%`, ...(accountKeys.length > 0 ? ['Per-account overrides:', ...accountKeys.map(key => ` ${key}: ${accounts[key] ?? 0}%`)] : [])];
|
|
604
724
|
api.ui.dialog.replace(() => (() => {
|
|
605
|
-
var _el$
|
|
606
|
-
_el$
|
|
607
|
-
_$insertNode(_el$
|
|
608
|
-
_$setProp(_el$
|
|
609
|
-
_$setProp(_el$
|
|
610
|
-
_$setProp(_el$
|
|
611
|
-
_$insert(_el$
|
|
612
|
-
var _el$
|
|
613
|
-
_$insert(_el$
|
|
614
|
-
return _el$
|
|
615
|
-
})()), _el$
|
|
616
|
-
_$setProp(_el$
|
|
617
|
-
_$insert(_el$
|
|
725
|
+
var _el$15 = _$createElement("box"),
|
|
726
|
+
_el$16 = _$createElement("box");
|
|
727
|
+
_$insertNode(_el$15, _el$16);
|
|
728
|
+
_$setProp(_el$15, "flexDirection", 'column');
|
|
729
|
+
_$setProp(_el$15, "padding", 1);
|
|
730
|
+
_$setProp(_el$15, "width", '100%');
|
|
731
|
+
_$insert(_el$15, () => bodyLines.map(line => (() => {
|
|
732
|
+
var _el$17 = _$createElement("text");
|
|
733
|
+
_$insert(_el$17, line);
|
|
734
|
+
return _el$17;
|
|
735
|
+
})()), _el$16);
|
|
736
|
+
_$setProp(_el$16, "marginTop", 1);
|
|
737
|
+
_$insert(_el$16, _$createComponent(DialogSelect, {
|
|
618
738
|
title: "Antigravity killswitch",
|
|
619
739
|
options: [{
|
|
620
740
|
title: `${enabled ? '●' : '○'} Killswitch: ${enabled ? 'enabled' : 'disabled'}`,
|
|
@@ -652,7 +772,7 @@ function renderKillswitchDialog(api, initialPayload, apply) {
|
|
|
652
772
|
});
|
|
653
773
|
}
|
|
654
774
|
}));
|
|
655
|
-
return _el$
|
|
775
|
+
return _el$15;
|
|
656
776
|
})());
|
|
657
777
|
};
|
|
658
778
|
renderMain();
|
package/src/tui-compiled/tui.tsx
CHANGED
|
@@ -17,9 +17,9 @@ import { createElement as _$createElement } from "opentui:runtime-module:%40open
|
|
|
17
17
|
* `AccountBlock` per visible account, a Routing section that surfaces the
|
|
18
18
|
* most recent session route, and a Health section that only appears when
|
|
19
19
|
* something is wrong. The Antigravity data model is richer than the
|
|
20
|
-
* Claude/Codex one (per-account
|
|
21
|
-
*
|
|
22
|
-
*
|
|
20
|
+
* Claude/Codex one (per-account Gemini + Non-Gemini quota pools, a health
|
|
21
|
+
* score, and per-session routing decisions), so the fleet components are
|
|
22
|
+
* adapted rather than copied verbatim:
|
|
23
23
|
*
|
|
24
24
|
* - `QuotaRow` reads `remainingPercent + resetAt` from the Antigravity
|
|
25
25
|
* `SidebarQuotaEntry` shape and colors via `quotaTone` (remaining
|
|
@@ -99,12 +99,14 @@ let rpcInFlight = false;
|
|
|
99
99
|
const GLOBAL_NOTIFICATION_CURSOR = '__global__';
|
|
100
100
|
const MAX_NOTIFICATION_CURSORS = 256;
|
|
101
101
|
const QUOTA_LABELS = {
|
|
102
|
-
|
|
103
|
-
'gemini
|
|
104
|
-
|
|
105
|
-
|
|
102
|
+
gemini: 'Gm',
|
|
103
|
+
'non-gemini': 'NG'
|
|
104
|
+
};
|
|
105
|
+
const QUOTA_ORDER = ['gemini', 'non-gemini'];
|
|
106
|
+
const WINDOW_GUTTER = {
|
|
107
|
+
weekly: '7d',
|
|
108
|
+
'5h': '5h'
|
|
106
109
|
};
|
|
107
|
-
const QUOTA_ORDER = ['claude', 'gemini-pro', 'gemini-flash', 'gpt-oss'];
|
|
108
110
|
|
|
109
111
|
// --- Theme tokens ----------------------------------------------------------
|
|
110
112
|
//
|
|
@@ -440,7 +442,7 @@ function QuotaRow(props) {
|
|
|
440
442
|
_$setProp(_el$14, "width", '100%');
|
|
441
443
|
_$setProp(_el$14, "flexDirection", 'row');
|
|
442
444
|
_$setProp(_el$14, "justifyContent", 'space-between');
|
|
443
|
-
_$insert(_el$15, () => props.label.padEnd(
|
|
445
|
+
_$insert(_el$15, () => props.label.padEnd(5));
|
|
444
446
|
_$insertNode(_el$16, _$createTextNode(`—`));
|
|
445
447
|
_$effect(_p$ => {
|
|
446
448
|
var _v$6 = props.theme().textMuted,
|
|
@@ -469,7 +471,7 @@ function QuotaRow(props) {
|
|
|
469
471
|
_$insertNode(_el$1, _el$11);
|
|
470
472
|
_$insertNode(_el$1, _el$12);
|
|
471
473
|
_$setProp(_el$1, "flexDirection", 'row');
|
|
472
|
-
_$setProp(_el$10, "width",
|
|
474
|
+
_$setProp(_el$10, "width", 5);
|
|
473
475
|
_$setProp(_el$10, "flexShrink", 0);
|
|
474
476
|
_$insert(_el$10, () => props.label);
|
|
475
477
|
_$setProp(_el$11, "flexShrink", 0);
|
|
@@ -572,23 +574,49 @@ function AccountBlock(props) {
|
|
|
572
574
|
_$insert(_el$24, statusWord);
|
|
573
575
|
_$insert(_el$19, _$createComponent(For, {
|
|
574
576
|
each: QUOTA_ORDER,
|
|
575
|
-
children: key =>
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
577
|
+
children: key => {
|
|
578
|
+
const poolEntry = props.account.quota[key];
|
|
579
|
+
const windows = poolEntry?.windows;
|
|
580
|
+
// Legacy: no windows array — render a single row with the pool label.
|
|
581
|
+
const hasWindows = windows && windows.length > 0;
|
|
582
|
+
if (!hasWindows) {
|
|
583
|
+
return _$createComponent(QuotaRow, {
|
|
584
|
+
get theme() {
|
|
585
|
+
return props.theme;
|
|
586
|
+
},
|
|
587
|
+
get appearance() {
|
|
588
|
+
return props.appearance;
|
|
589
|
+
},
|
|
590
|
+
get label() {
|
|
591
|
+
return QUOTA_LABELS[key];
|
|
592
|
+
},
|
|
593
|
+
entry: poolEntry,
|
|
594
|
+
get now() {
|
|
595
|
+
return props.now;
|
|
596
|
+
}
|
|
597
|
+
});
|
|
590
598
|
}
|
|
591
|
-
|
|
599
|
+
return _$memo(() => windows.map(w => _$createComponent(QuotaRow, {
|
|
600
|
+
get theme() {
|
|
601
|
+
return props.theme;
|
|
602
|
+
},
|
|
603
|
+
get appearance() {
|
|
604
|
+
return props.appearance;
|
|
605
|
+
},
|
|
606
|
+
get label() {
|
|
607
|
+
return `${QUOTA_LABELS[key]} ${WINDOW_GUTTER[w.window] ?? w.window}`;
|
|
608
|
+
},
|
|
609
|
+
get entry() {
|
|
610
|
+
return {
|
|
611
|
+
remainingPercent: w.remainingPercent,
|
|
612
|
+
resetAt: w.resetAt
|
|
613
|
+
};
|
|
614
|
+
},
|
|
615
|
+
get now() {
|
|
616
|
+
return props.now;
|
|
617
|
+
}
|
|
618
|
+
})));
|
|
619
|
+
}
|
|
592
620
|
}), _el$25);
|
|
593
621
|
_$insertNode(_el$25, _el$26);
|
|
594
622
|
_$setProp(_el$25, "width", '100%');
|
|
@@ -837,8 +865,23 @@ export function SidebarPanel(props) {
|
|
|
837
865
|
return (() => {
|
|
838
866
|
const account = () => visibleAccounts().find(entry => entry.current) ?? visibleAccounts()[0];
|
|
839
867
|
const used = () => {
|
|
840
|
-
const
|
|
841
|
-
|
|
868
|
+
const q = account()?.quota;
|
|
869
|
+
// Derive tone from the WORST (most-constrained) pool so a
|
|
870
|
+
// critical non-gemini pool doesn't hide behind a healthy
|
|
871
|
+
// gemini tone. Worst = highest used-percent across available pools.
|
|
872
|
+
const geminiUsed = q?.gemini != null ? 100 - clamp(q.gemini.remainingPercent, 0, 100) : null;
|
|
873
|
+
const nonGeminiUsed = q?.['non-gemini'] != null ? 100 - clamp(q['non-gemini'].remainingPercent, 0, 100) : null;
|
|
874
|
+
if (geminiUsed === null && nonGeminiUsed === null) return null;
|
|
875
|
+
return Math.max(geminiUsed ?? 0, nonGeminiUsed ?? 0);
|
|
876
|
+
};
|
|
877
|
+
const poolText = key => {
|
|
878
|
+
const entry = account()?.quota[key];
|
|
879
|
+
if (!entry) return `${QUOTA_LABELS[key]}: —`;
|
|
880
|
+
const pct = Math.round(100 - clamp(entry.remainingPercent, 0, 100));
|
|
881
|
+
// Show binding window when available, else just pool label.
|
|
882
|
+
const bindingWindow = entry.windows?.reduce((best, w) => best === null || w.remainingPercent < best.remainingPercent ? w : best, null);
|
|
883
|
+
const gutter = bindingWindow ? ` ${WINDOW_GUTTER[bindingWindow.window] ?? bindingWindow.window}` : '';
|
|
884
|
+
return `${QUOTA_LABELS[key]}${gutter}: ${pct}%`;
|
|
842
885
|
};
|
|
843
886
|
const unavailable = () => {
|
|
844
887
|
const selected = account();
|
|
@@ -863,8 +906,8 @@ export function SidebarPanel(props) {
|
|
|
863
906
|
_$setProp(_el$43, "flexDirection", 'row');
|
|
864
907
|
_$insertNode(_el$44, _el$45);
|
|
865
908
|
_$insert(_el$45, (() => {
|
|
866
|
-
var _c$ = _$memo(() =>
|
|
867
|
-
return () => _c$() ? '—' :
|
|
909
|
+
var _c$ = _$memo(() => !!(account()?.quota.gemini == null && account()?.quota['non-gemini'] == null));
|
|
910
|
+
return () => _c$() ? '—' : `${poolText('gemini')} · ${poolText('non-gemini')}`;
|
|
868
911
|
})());
|
|
869
912
|
_$insert(_el$46, () => unavailable() ? ' ⊘' : ' ●');
|
|
870
913
|
_$effect(_p$ => {
|
package/src/tui.tsx
CHANGED
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
* `AccountBlock` per visible account, a Routing section that surfaces the
|
|
10
10
|
* most recent session route, and a Health section that only appears when
|
|
11
11
|
* something is wrong. The Antigravity data model is richer than the
|
|
12
|
-
* Claude/Codex one (per-account
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* Claude/Codex one (per-account Gemini + Non-Gemini quota pools, a health
|
|
13
|
+
* score, and per-session routing decisions), so the fleet components are
|
|
14
|
+
* adapted rather than copied verbatim:
|
|
15
15
|
*
|
|
16
16
|
* - `QuotaRow` reads `remainingPercent + resetAt` from the Antigravity
|
|
17
17
|
* `SidebarQuotaEntry` shape and colors via `quotaTone` (remaining
|
|
@@ -128,18 +128,16 @@ const GLOBAL_NOTIFICATION_CURSOR = '__global__'
|
|
|
128
128
|
const MAX_NOTIFICATION_CURSORS = 256
|
|
129
129
|
|
|
130
130
|
const QUOTA_LABELS: Record<SidebarQuotaKey, string> = {
|
|
131
|
-
|
|
132
|
-
'gemini
|
|
133
|
-
'gemini-flash': 'GF',
|
|
134
|
-
'gpt-oss': 'GPT',
|
|
131
|
+
gemini: 'Gm',
|
|
132
|
+
'non-gemini': 'NG',
|
|
135
133
|
}
|
|
136
134
|
|
|
137
|
-
const QUOTA_ORDER: readonly SidebarQuotaKey[] = [
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
'
|
|
141
|
-
'
|
|
142
|
-
|
|
135
|
+
const QUOTA_ORDER: readonly SidebarQuotaKey[] = ['gemini', 'non-gemini']
|
|
136
|
+
|
|
137
|
+
const WINDOW_GUTTER: Record<string, string> = {
|
|
138
|
+
weekly: '7d',
|
|
139
|
+
'5h': '5h',
|
|
140
|
+
}
|
|
143
141
|
|
|
144
142
|
// --- Theme tokens ----------------------------------------------------------
|
|
145
143
|
//
|
|
@@ -517,14 +515,14 @@ function QuotaRow(props: {
|
|
|
517
515
|
when={used() != null}
|
|
518
516
|
fallback={
|
|
519
517
|
<box width='100%' flexDirection='row' justifyContent='space-between'>
|
|
520
|
-
<text fg={props.theme().textMuted}>{props.label.padEnd(
|
|
518
|
+
<text fg={props.theme().textMuted}>{props.label.padEnd(5)}</text>
|
|
521
519
|
<text fg={props.theme().textMuted}>{'\u2014'}</text>
|
|
522
520
|
</box>
|
|
523
521
|
}
|
|
524
522
|
>
|
|
525
523
|
<box width='100%' flexDirection='row' justifyContent='space-between'>
|
|
526
524
|
<box flexDirection='row'>
|
|
527
|
-
<text width={
|
|
525
|
+
<text width={5} flexShrink={0} fg={props.theme().textMuted}>
|
|
528
526
|
{props.label}
|
|
529
527
|
</text>
|
|
530
528
|
<box
|
|
@@ -610,15 +608,39 @@ function AccountBlock(props: {
|
|
|
610
608
|
</text>
|
|
611
609
|
</box>
|
|
612
610
|
<For each={QUOTA_ORDER}>
|
|
613
|
-
{(key) =>
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
611
|
+
{(key) => {
|
|
612
|
+
const poolEntry = props.account.quota[key]
|
|
613
|
+
const windows = poolEntry?.windows
|
|
614
|
+
// Legacy: no windows array — render a single row with the pool label.
|
|
615
|
+
const hasWindows = windows && windows.length > 0
|
|
616
|
+
if (!hasWindows) {
|
|
617
|
+
return (
|
|
618
|
+
<QuotaRow
|
|
619
|
+
theme={props.theme}
|
|
620
|
+
appearance={props.appearance}
|
|
621
|
+
label={QUOTA_LABELS[key]}
|
|
622
|
+
entry={poolEntry}
|
|
623
|
+
now={props.now}
|
|
624
|
+
/>
|
|
625
|
+
)
|
|
626
|
+
}
|
|
627
|
+
return (
|
|
628
|
+
<>
|
|
629
|
+
{windows.map((w) => (
|
|
630
|
+
<QuotaRow
|
|
631
|
+
theme={props.theme}
|
|
632
|
+
appearance={props.appearance}
|
|
633
|
+
label={`${QUOTA_LABELS[key]} ${WINDOW_GUTTER[w.window] ?? w.window}`}
|
|
634
|
+
entry={{
|
|
635
|
+
remainingPercent: w.remainingPercent,
|
|
636
|
+
resetAt: w.resetAt,
|
|
637
|
+
}}
|
|
638
|
+
now={props.now}
|
|
639
|
+
/>
|
|
640
|
+
))}
|
|
641
|
+
</>
|
|
642
|
+
)
|
|
643
|
+
}}
|
|
622
644
|
</For>
|
|
623
645
|
<box width='100%' flexDirection='row'>
|
|
624
646
|
<text fg={props.theme().textMuted}>{` ${healthText()}`}</text>
|
|
@@ -835,8 +857,39 @@ export function SidebarPanel(props: SidebarPanelProps): JSX.Element {
|
|
|
835
857
|
visibleAccounts().find((entry) => entry.current) ??
|
|
836
858
|
visibleAccounts()[0]
|
|
837
859
|
const used = () => {
|
|
838
|
-
const
|
|
839
|
-
|
|
860
|
+
const q = account()?.quota
|
|
861
|
+
// Derive tone from the WORST (most-constrained) pool so a
|
|
862
|
+
// critical non-gemini pool doesn't hide behind a healthy
|
|
863
|
+
// gemini tone. Worst = highest used-percent across available pools.
|
|
864
|
+
const geminiUsed =
|
|
865
|
+
q?.gemini != null
|
|
866
|
+
? 100 - clamp(q.gemini.remainingPercent, 0, 100)
|
|
867
|
+
: null
|
|
868
|
+
const nonGeminiUsed =
|
|
869
|
+
q?.['non-gemini'] != null
|
|
870
|
+
? 100 - clamp(q['non-gemini'].remainingPercent, 0, 100)
|
|
871
|
+
: null
|
|
872
|
+
if (geminiUsed === null && nonGeminiUsed === null) return null
|
|
873
|
+
return Math.max(geminiUsed ?? 0, nonGeminiUsed ?? 0)
|
|
874
|
+
}
|
|
875
|
+
const poolText = (key: 'gemini' | 'non-gemini') => {
|
|
876
|
+
const entry = account()?.quota[key]
|
|
877
|
+
if (!entry) return `${QUOTA_LABELS[key]}: —`
|
|
878
|
+
const pct = Math.round(100 - clamp(entry.remainingPercent, 0, 100))
|
|
879
|
+
// Show binding window when available, else just pool label.
|
|
880
|
+
const bindingWindow = entry.windows?.reduce<
|
|
881
|
+
(typeof entry.windows)[0] | null
|
|
882
|
+
>(
|
|
883
|
+
(best, w) =>
|
|
884
|
+
best === null || w.remainingPercent < best.remainingPercent
|
|
885
|
+
? w
|
|
886
|
+
: best,
|
|
887
|
+
null,
|
|
888
|
+
)
|
|
889
|
+
const gutter = bindingWindow
|
|
890
|
+
? ` ${WINDOW_GUTTER[bindingWindow.window] ?? bindingWindow.window}`
|
|
891
|
+
: ''
|
|
892
|
+
return `${QUOTA_LABELS[key]}${gutter}: ${pct}%`
|
|
840
893
|
}
|
|
841
894
|
const unavailable = () => {
|
|
842
895
|
const selected = account()
|
|
@@ -861,9 +914,10 @@ export function SidebarPanel(props: SidebarPanelProps): JSX.Element {
|
|
|
861
914
|
)}
|
|
862
915
|
>
|
|
863
916
|
<b>
|
|
864
|
-
{
|
|
917
|
+
{account()?.quota.gemini == null &&
|
|
918
|
+
account()?.quota['non-gemini'] == null
|
|
865
919
|
? '—'
|
|
866
|
-
:
|
|
920
|
+
: `${poolText('gemini')} · ${poolText('non-gemini')}`}
|
|
867
921
|
</b>
|
|
868
922
|
</text>
|
|
869
923
|
<text
|