@cortexkit/opencode-antigravity-auth 3.0.1 → 3.0.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.
Files changed (138) hide show
  1. package/dist/cli.js.map +2 -2
  2. package/dist/cli.meta.json +3 -3
  3. package/dist/index.d.ts +1 -1
  4. package/dist/index.js +1136 -928
  5. package/dist/index.js.map +4 -4
  6. package/dist/index.meta.json +107 -25
  7. package/dist/server.js +267 -37
  8. package/dist/server.js.map +4 -4
  9. package/dist/server.meta.json +1 -7313
  10. package/dist/src/cli.d.ts +1 -1
  11. package/dist/src/constants.d.ts +1 -1
  12. package/dist/src/ga/rpc/protocol.d.ts +1 -1
  13. package/dist/src/ga/server/index.d.ts +6 -6
  14. package/dist/src/ga/server/index.d.ts.map +1 -1
  15. package/dist/src/ga/server/index.js +29 -1
  16. package/dist/src/ga/server/index.js.map +1 -1
  17. package/dist/src/ga/tui/host-ga.d.ts +2 -2
  18. package/dist/src/hooks/auto-update-checker/checker.d.ts +1 -1
  19. package/dist/src/hooks/auto-update-checker/index.d.ts +4 -4
  20. package/dist/src/plugin/account-access.d.ts +6 -6
  21. package/dist/src/plugin/account-command-oauth.d.ts +2 -2
  22. package/dist/src/plugin/accounts.d.ts +3 -3
  23. package/dist/src/plugin/auth-doctor.d.ts +2 -2
  24. package/dist/src/plugin/auth-drift.d.ts +2 -2
  25. package/dist/src/plugin/auth-loader.d.ts +8 -8
  26. package/dist/src/plugin/auth-loader.d.ts.map +1 -1
  27. package/dist/src/plugin/auth-loader.js +1 -0
  28. package/dist/src/plugin/auth-loader.js.map +1 -1
  29. package/dist/src/plugin/background-quota-refresh.d.ts +3 -3
  30. package/dist/src/plugin/background-vault-quota-refresh.d.ts +43 -0
  31. package/dist/src/plugin/background-vault-quota-refresh.d.ts.map +1 -0
  32. package/dist/src/plugin/background-vault-quota-refresh.js +155 -0
  33. package/dist/src/plugin/background-vault-quota-refresh.js.map +1 -0
  34. package/dist/src/plugin/cache/index.d.ts +1 -1
  35. package/dist/src/plugin/cache/signature-cache.d.ts +2 -2
  36. package/dist/src/plugin/cache.d.ts +6 -6
  37. package/dist/src/plugin/cli.d.ts +6 -6
  38. package/dist/src/plugin/command-apply.d.ts +1 -1
  39. package/dist/src/plugin/command-data.d.ts +6 -4
  40. package/dist/src/plugin/command-data.d.ts.map +1 -1
  41. package/dist/src/plugin/command-data.js +13 -34
  42. package/dist/src/plugin/command-data.js.map +1 -1
  43. package/dist/src/plugin/commands.d.ts +4 -4
  44. package/dist/src/plugin/config/index.d.ts +2 -2
  45. package/dist/src/plugin/config/loader.d.ts +2 -2
  46. package/dist/src/plugin/config/models.d.ts +2 -2
  47. package/dist/src/plugin/config/writer.d.ts +2 -2
  48. package/dist/src/plugin/core/streaming/index.d.ts +2 -2
  49. package/dist/src/plugin/core/streaming/transformer.d.ts +1 -1
  50. package/dist/src/plugin/debug.d.ts +1 -1
  51. package/dist/src/plugin/dependencies.d.ts +3 -3
  52. package/dist/src/plugin/event-handler.d.ts +3 -3
  53. package/dist/src/plugin/fetch-interceptor.d.ts +10 -10
  54. package/dist/src/plugin/fetch-routing.d.ts +3 -3
  55. package/dist/src/plugin/ga-location-services.d.ts +10 -10
  56. package/dist/src/plugin/google-search-tool.d.ts +1 -1
  57. package/dist/src/plugin/index.d.ts +8 -6
  58. package/dist/src/plugin/index.d.ts.map +1 -1
  59. package/dist/src/plugin/index.js +41 -18
  60. package/dist/src/plugin/index.js.map +1 -1
  61. package/dist/src/plugin/killswitch.d.ts +1 -1
  62. package/dist/src/plugin/lifecycle.d.ts +2 -2
  63. package/dist/src/plugin/logger.d.ts +2 -2
  64. package/dist/src/plugin/oauth-login.d.ts +1 -1
  65. package/dist/src/plugin/oauth-methods.d.ts +9 -9
  66. package/dist/src/plugin/operator-settings.d.ts +3 -3
  67. package/dist/src/plugin/persist-account-pool.d.ts +1 -1
  68. package/dist/src/plugin/quota.d.ts +5 -4
  69. package/dist/src/plugin/quota.d.ts.map +1 -1
  70. package/dist/src/plugin/quota.js +1 -0
  71. package/dist/src/plugin/quota.js.map +1 -1
  72. package/dist/src/plugin/recovery/index.d.ts +3 -3
  73. package/dist/src/plugin/recovery/storage.d.ts +1 -1
  74. package/dist/src/plugin/recovery.d.ts +3 -3
  75. package/dist/src/plugin/refresh-queue.d.ts +3 -3
  76. package/dist/src/plugin/request-helpers.d.ts +1 -1
  77. package/dist/src/plugin/request.d.ts +9 -9
  78. package/dist/src/plugin/session-context.d.ts +1 -1
  79. package/dist/src/plugin/shared/request-services.d.ts +9 -9
  80. package/dist/src/plugin/shared/runtime.d.ts +11 -11
  81. package/dist/src/plugin/shared/source-sidebar.d.ts +1 -1
  82. package/dist/src/plugin/shared/vault-menu.d.ts +1 -1
  83. package/dist/src/plugin/shared/vault-request-credentials.d.ts +3 -1
  84. package/dist/src/plugin/shared/vault-request-credentials.d.ts.map +1 -1
  85. package/dist/src/plugin/shared/vault-request-credentials.js +1 -1
  86. package/dist/src/plugin/shared/vault-request-credentials.js.map +1 -1
  87. package/dist/src/plugin/stores/signature-store.d.ts +1 -1
  88. package/dist/src/plugin/token.d.ts +1 -1
  89. package/dist/src/plugin/ui/auth-menu.d.ts +4 -4
  90. package/dist/src/plugin/ui/model-status.d.ts +3 -3
  91. package/dist/src/plugin/ui/quota-status.d.ts +2 -2
  92. package/dist/src/plugin/vault-activation.d.ts +1 -1
  93. package/dist/src/plugin/vault-quota-refresh.d.ts +7 -0
  94. package/dist/src/plugin/vault-quota-refresh.d.ts.map +1 -0
  95. package/dist/src/plugin/vault-quota-refresh.js +12 -0
  96. package/dist/src/plugin/vault-quota-refresh.js.map +1 -0
  97. package/dist/src/plugin/vault-sidebar-projection.d.ts +27 -0
  98. package/dist/src/plugin/vault-sidebar-projection.d.ts.map +1 -0
  99. package/dist/src/plugin/vault-sidebar-projection.js +34 -0
  100. package/dist/src/plugin/vault-sidebar-projection.js.map +1 -0
  101. package/dist/src/rpc/notifications.d.ts +1 -1
  102. package/dist/src/rpc/rpc-server.d.ts +1 -1
  103. package/dist/src/server.d.ts +3 -3
  104. package/dist/src/sidebar-state.d.ts +20 -13
  105. package/dist/src/sidebar-state.d.ts.map +1 -1
  106. package/dist/src/sidebar-state.js +20 -10
  107. package/dist/src/sidebar-state.js.map +1 -1
  108. package/dist/src/tui/command-dialogs.d.ts +1 -1
  109. package/dist/src/tui/host-v1.d.ts +3 -3
  110. package/dist/src/tui.d.ts +3 -3
  111. package/dist/src/tui.js +1 -1
  112. package/dist/tui-build-map.json +6 -6
  113. package/dist/types/src/ga/server/index.d.ts.map +1 -1
  114. package/dist/types/src/plugin/auth-loader.d.ts.map +1 -1
  115. package/dist/types/src/plugin/background-vault-quota-refresh.d.ts +43 -0
  116. package/dist/types/src/plugin/background-vault-quota-refresh.d.ts.map +1 -0
  117. package/dist/types/src/plugin/command-data.d.ts +6 -4
  118. package/dist/types/src/plugin/command-data.d.ts.map +1 -1
  119. package/dist/types/src/plugin/index.d.ts +2 -0
  120. package/dist/types/src/plugin/index.d.ts.map +1 -1
  121. package/dist/types/src/plugin/quota.d.ts +1 -0
  122. package/dist/types/src/plugin/quota.d.ts.map +1 -1
  123. package/dist/types/src/plugin/shared/vault-request-credentials.d.ts +2 -0
  124. package/dist/types/src/plugin/shared/vault-request-credentials.d.ts.map +1 -1
  125. package/dist/types/src/plugin/vault-quota-refresh.d.ts +7 -0
  126. package/dist/types/src/plugin/vault-quota-refresh.d.ts.map +1 -0
  127. package/dist/types/src/plugin/vault-sidebar-projection.d.ts +27 -0
  128. package/dist/types/src/plugin/vault-sidebar-projection.d.ts.map +1 -0
  129. package/dist/types/src/sidebar-state.d.ts +20 -13
  130. package/dist/types/src/sidebar-state.d.ts.map +1 -1
  131. package/package.json +2 -2
  132. package/src/plugin/command-data.ts +19 -47
  133. package/src/sidebar-state.ts +34 -15
  134. package/src/tui-compiled/sidebar-state.js +12 -5
  135. package/src/tui-compiled/tui.js +1 -1
  136. package/src/tui-raw/sidebar-state.js +12 -5
  137. package/src/tui-raw/tui.tsx +1 -1
  138. package/src/tui.tsx +1 -1
@@ -8,9 +8,9 @@
8
8
  * could leak credentials or pull a heavy manager into the render path.
9
9
  *
10
10
  * The plugin writes a redacted snapshot to the file resolved by
11
- * `getSidebarStateFile()` and the TUI polls it. The contract version is `1`:
12
- * any future field that the TUI cannot understand must be ignored, and any
13
- * broken/missing file must collapse to `DEFAULT_SIDEBAR_STATE`.
11
+ * `getSidebarStateFile()` and the TUI polls it. Writers emit version 2;
12
+ * readers normalize version 1 without inventing precision or reading times.
13
+ * Unknown versions and broken/missing files collapse to `DEFAULT_SIDEBAR_STATE`.
14
14
  *
15
15
  * ## Writer surface
16
16
  *
@@ -39,7 +39,7 @@
39
39
  * 100 entries within 24h.
40
40
  */
41
41
 
42
- import { mkdirSync, readFileSync } from 'node:fs'
42
+ import { chmodSync, mkdirSync, readFileSync } from 'node:fs'
43
43
  import { homedir } from 'node:os'
44
44
  import { dirname, join } from 'node:path'
45
45
  // Subpath imports (not the barrel): this file ships into the TUI's
@@ -52,13 +52,15 @@ import {
52
52
  } from '@cortexkit/antigravity-auth-core/file-lock'
53
53
  import { xdgState } from 'xdg-basedir'
54
54
 
55
- export const SIDEBAR_STATE_VERSION = 1 as const
55
+ export const SIDEBAR_STATE_VERSION = 2 as const
56
56
 
57
57
  export type SidebarQuotaKey = 'gemini' | 'non-gemini'
58
58
 
59
59
  export interface SidebarQuotaWindowEntry {
60
60
  window: 'weekly' | '5h'
61
61
  remainingPercent: number
62
+ /** Unrounded fraction in [0, 1]; absent in normalized version 1 data. */
63
+ remainingFraction?: number
62
64
  checkedAt?: number
63
65
  resetAt?: number
64
66
  }
@@ -66,6 +68,8 @@ export interface SidebarQuotaWindowEntry {
66
68
  export interface SidebarQuotaEntry {
67
69
  /** Most-constrained window's remaining % (derived, for back-compat). */
68
70
  remainingPercent: number
71
+ /** Unrounded fraction in [0, 1]; absent in normalized version 1 data. */
72
+ remainingFraction?: number
69
73
  checkedAt?: number
70
74
  resetAt?: number
71
75
  /** Per-window breakdown. Omitted in pre-windows snapshots. */
@@ -75,6 +79,8 @@ export interface SidebarQuotaEntry {
75
79
  export interface SidebarAccountState {
76
80
  id: string
77
81
  label: string
82
+ /** Owner-only machine identity; never rendered by the TUI. */
83
+ email?: string
78
84
  enabled: boolean
79
85
  health: number
80
86
  current: boolean
@@ -95,7 +101,7 @@ export interface SidebarRoutingEntry {
95
101
  updatedAt: number
96
102
  }
97
103
 
98
- export interface SidebarStateV1 {
104
+ export interface SidebarStateV2 {
99
105
  version: typeof SIDEBAR_STATE_VERSION
100
106
  checkedAt: number
101
107
  accounts: SidebarAccountState[]
@@ -105,8 +111,11 @@ export interface SidebarStateV1 {
105
111
  lastError?: string
106
112
  }
107
113
 
114
+ /** Source compatibility for callers; normalized states now always use version 2. */
115
+ export type SidebarStateV1 = SidebarStateV2
116
+
108
117
  /**
109
- * The subset of `SidebarStateV1` that a non-routing writer may set. The
118
+ * The subset of `SidebarStateV2` that a non-routing writer may set. The
110
119
  * fetch interceptor writes `activeRouting` directly via its own entry point
111
120
  * because routing is session-scoped, not machine-scoped.
112
121
  */
@@ -253,7 +262,7 @@ function normalizeSidebarState(input: unknown): SidebarStateV1 {
253
262
  }
254
263
  const record = input as Record<string, unknown>
255
264
  const version = record.version
256
- if (version !== SIDEBAR_STATE_VERSION) {
265
+ if (version !== 1 && version !== SIDEBAR_STATE_VERSION) {
257
266
  return {
258
267
  ...DEFAULT_SIDEBAR_STATE,
259
268
  lastError: `unsupported-version:${stringifySafe(version)}`,
@@ -318,6 +327,7 @@ function normalizeAccount(input: unknown): SidebarAccountState | null {
318
327
  return {
319
328
  id,
320
329
  label,
330
+ ...(typeof record.email === 'string' ? { email: record.email } : {}),
321
331
  enabled,
322
332
  health,
323
333
  current,
@@ -347,6 +357,7 @@ function normalizeQuota(input: unknown): SidebarQuotaEntry | null {
347
357
  if (!isObject(input)) return null
348
358
  const record = input as Record<string, unknown>
349
359
  const remaining = toFiniteNumber(record.remainingPercent)
360
+ const fraction = toFiniteNumber(record.remainingFraction)
350
361
  if (remaining === null) return null
351
362
  const resetAt = toFiniteNumber(record.resetAt) ?? undefined
352
363
  const checkedAt = toFiniteNumber(record.checkedAt) ?? undefined
@@ -364,10 +375,12 @@ function normalizeQuota(input: unknown): SidebarQuotaEntry | null {
364
375
  )
365
376
  const ra = toFiniteNumber((w as Record<string, unknown>).resetAt)
366
377
  const ca = toFiniteNumber(w.checkedAt)
378
+ const rf = toFiniteNumber(w.remainingFraction)
367
379
  if ((win !== 'weekly' && win !== '5h') || rp === null) return null
368
380
  return {
369
381
  window: win as 'weekly' | '5h',
370
382
  remainingPercent: clampNumber(rp, 0, 100),
383
+ ...(rf !== null ? { remainingFraction: clampNumber(rf, 0, 1) } : {}),
371
384
  resetAt: ra ?? undefined,
372
385
  ...(ca !== null && ca >= 0 ? { checkedAt: ca } : {}),
373
386
  }
@@ -378,6 +391,9 @@ function normalizeQuota(input: unknown): SidebarQuotaEntry | null {
378
391
 
379
392
  return {
380
393
  remainingPercent: clampNumber(remaining, 0, 100),
394
+ ...(fraction !== null
395
+ ? { remainingFraction: clampNumber(fraction, 0, 1) }
396
+ : {}),
381
397
  resetAt,
382
398
  ...(checkedAt !== undefined ? { checkedAt } : {}),
383
399
  windows,
@@ -451,6 +467,7 @@ export function ensureSidebarStateDir(
451
467
  path: string = getSidebarStateFile(),
452
468
  ): void {
453
469
  mkdirSync(dirname(path), { recursive: true, mode: SIDEBAR_STATE_DIR_MODE })
470
+ chmodSync(dirname(path), SIDEBAR_STATE_DIR_MODE)
454
471
  }
455
472
 
456
473
  /**
@@ -482,15 +499,15 @@ export function pruneActiveRouting(
482
499
  * shape on callers (and so the TUI's compiled tree does not see the core
483
500
  * ManagedAccount shape beyond what's actually used).
484
501
  *
485
- * Deliberately excludes `email`: the sidebar/redaction boundary is a PII
486
- * firewall. Adding `email` here would re-introduce the leak this boundary
487
- * exists to prevent. Legacy profile labels are accepted but never serialized.
502
+ * Email is retained only for owner-only machine consumers. The renderer uses
503
+ * ordinal labels, never email. Legacy profile labels are never serialized.
488
504
  */
489
505
  export interface SidebarAccountRedactionInput {
490
506
  /** Position in the harness-visible account array. */
491
507
  index: number
492
508
  /** Legacy profile label; deliberately ignored by the redactor. */
493
509
  label?: string
510
+ email?: string
494
511
  enabled?: boolean
495
512
  current?: boolean
496
513
  coolingDownUntil?: number
@@ -710,6 +727,7 @@ export function projectQuotaPoolForSidebar(
710
727
  0,
711
728
  100,
712
729
  ),
730
+ remainingFraction: clampNumber(w.remainingFraction, 0, 1),
713
731
  resetAt:
714
732
  typeof w.resetTime === 'string' && w.resetTime.length > 0
715
733
  ? (() => {
@@ -722,6 +740,7 @@ export function projectQuotaPoolForSidebar(
722
740
 
723
741
  return {
724
742
  remainingPercent,
743
+ remainingFraction: clampNumber(fraction, 0, 1),
725
744
  resetAt,
726
745
  windows,
727
746
  ...(readingAt !== undefined ? { checkedAt: readingAt } : {}),
@@ -743,10 +762,9 @@ export function isAccountCurrent(
743
762
  }
744
763
 
745
764
  /**
746
- * Convert a live account snapshot into the redacted shape the TUI renders.
747
- * The redacted `SidebarAccountState` carries no email, refresh token, access
748
- * token, project ID, fingerprint, OAuth profile name, or other personal or
749
- * credential-shaped fields. Display labels are generated ordinal account names.
765
+ * Convert a live account into an owner-only machine snapshot. Known email
766
+ * survives for machine consumers, but display labels remain ordinal. Tokens,
767
+ * project IDs, fingerprints and OAuth profile names never cross this boundary.
750
768
  */
751
769
  export function redactAccountForSidebar(
752
770
  source: SidebarAccountRedactionInput,
@@ -796,6 +814,7 @@ export function redactAccountForSidebar(
796
814
  return {
797
815
  id,
798
816
  label,
817
+ ...(typeof source.email === 'string' ? { email: source.email } : {}),
799
818
  enabled,
800
819
  health,
801
820
  current,
@@ -1,4 +1,4 @@
1
- import { mkdirSync, readFileSync } from "node:fs";
1
+ import { chmodSync, mkdirSync, readFileSync } from "node:fs";
2
2
  import { homedir } from "node:os";
3
3
  import { dirname, join } from "node:path";
4
4
  import { writeJsonAtomic } from "@cortexkit/antigravity-auth-core/atomic-write";
@@ -6,7 +6,7 @@ import {
6
6
  acquireFencedFileLock
7
7
  } from "@cortexkit/antigravity-auth-core/file-lock";
8
8
  import { xdgState } from "xdg-basedir";
9
- export const SIDEBAR_STATE_VERSION = 1, DEFAULT_SIDEBAR_STATE = {
9
+ export const SIDEBAR_STATE_VERSION = 2, DEFAULT_SIDEBAR_STATE = {
10
10
  version: SIDEBAR_STATE_VERSION,
11
11
  checkedAt: 0,
12
12
  accounts: [],
@@ -56,7 +56,7 @@ function normalizeSidebarState(input) {
56
56
  if (!isObject(input))
57
57
  return { ...DEFAULT_SIDEBAR_STATE, lastError: "shape" };
58
58
  const record = input, version = record.version;
59
- if (version !== SIDEBAR_STATE_VERSION)
59
+ if (version !== 1 && version !== SIDEBAR_STATE_VERSION)
60
60
  return {
61
61
  ...DEFAULT_SIDEBAR_STATE,
62
62
  lastError: `unsupported-version:${stringifySafe(version)}`
@@ -96,6 +96,7 @@ function normalizeAccount(input) {
96
96
  return {
97
97
  id,
98
98
  label,
99
+ ...typeof record.email === "string" ? { email: record.email } : {},
99
100
  enabled,
100
101
  health,
101
102
  current,
@@ -116,19 +117,20 @@ function normalizeTier(input) {
116
117
  function normalizeQuota(input) {
117
118
  if (!isObject(input))
118
119
  return null;
119
- const record = input, remaining = toFiniteNumber(record.remainingPercent);
120
+ const record = input, remaining = toFiniteNumber(record.remainingPercent), fraction = toFiniteNumber(record.remainingFraction);
120
121
  if (remaining === null)
121
122
  return null;
122
123
  const resetAt = toFiniteNumber(record.resetAt) ?? void 0, checkedAt = toFiniteNumber(record.checkedAt) ?? void 0, windowsRaw = record.windows;
123
124
  let windows;
124
125
  if (Array.isArray(windowsRaw)) {
125
126
  const parsed = windowsRaw.filter(isObject).map((w) => {
126
- const win = w.window, rp = toFiniteNumber(w.remainingPercent), ra = toFiniteNumber(w.resetAt), ca = toFiniteNumber(w.checkedAt);
127
+ const win = w.window, rp = toFiniteNumber(w.remainingPercent), ra = toFiniteNumber(w.resetAt), ca = toFiniteNumber(w.checkedAt), rf = toFiniteNumber(w.remainingFraction);
127
128
  if (win !== "weekly" && win !== "5h" || rp === null)
128
129
  return null;
129
130
  return {
130
131
  window: win,
131
132
  remainingPercent: clampNumber(rp, 0, 100),
133
+ ...rf !== null ? { remainingFraction: clampNumber(rf, 0, 1) } : {},
132
134
  resetAt: ra ?? void 0,
133
135
  ...ca !== null && ca >= 0 ? { checkedAt: ca } : {}
134
136
  };
@@ -138,6 +140,7 @@ function normalizeQuota(input) {
138
140
  }
139
141
  return {
140
142
  remainingPercent: clampNumber(remaining, 0, 100),
143
+ ...fraction !== null ? { remainingFraction: clampNumber(fraction, 0, 1) } : {},
141
144
  resetAt,
142
145
  ...checkedAt !== void 0 ? { checkedAt } : {},
143
146
  windows
@@ -189,6 +192,7 @@ function stringifySafe(value) {
189
192
  }
190
193
  export function ensureSidebarStateDir(path = getSidebarStateFile()) {
191
194
  mkdirSync(dirname(path), { recursive: !0, mode: SIDEBAR_STATE_DIR_MODE });
195
+ chmodSync(dirname(path), SIDEBAR_STATE_DIR_MODE);
192
196
  }
193
197
  export function pruneActiveRouting(map, now) {
194
198
  const cutoff = now - ACTIVE_ROUTING_MAX_AGE_MS, filtered = [];
@@ -249,6 +253,7 @@ export function projectQuotaPoolForSidebar(source, checkedAt) {
249
253
  window: w.window,
250
254
  ...readingAt !== void 0 ? { checkedAt: readingAt } : {},
251
255
  remainingPercent: clampNumber(Math.round(w.remainingFraction * 100), 0, 100),
256
+ remainingFraction: clampNumber(w.remainingFraction, 0, 1),
252
257
  resetAt: typeof w.resetTime === "string" && w.resetTime.length > 0 ? (() => {
253
258
  const parsed = Date.parse(w.resetTime);
254
259
  return Number.isFinite(parsed) ? parsed : void 0;
@@ -256,6 +261,7 @@ export function projectQuotaPoolForSidebar(source, checkedAt) {
256
261
  })) : void 0;
257
262
  return {
258
263
  remainingPercent,
264
+ remainingFraction: clampNumber(fraction, 0, 1),
259
265
  resetAt,
260
266
  windows,
261
267
  ...readingAt !== void 0 ? { checkedAt: readingAt } : {}
@@ -278,6 +284,7 @@ export function redactAccountForSidebar(source) {
278
284
  return {
279
285
  id,
280
286
  label,
287
+ ...typeof source.email === "string" ? { email: source.email } : {},
281
288
  enabled,
282
289
  health,
283
290
  current,
@@ -213,7 +213,7 @@ function quotaBarSegments(remainingPct, appearance) {
213
213
  }].filter(segment => segment.text.length > 0);
214
214
  }
215
215
  const EMPTY_STATE = {
216
- version: 1,
216
+ version: 2,
217
217
  checkedAt: 0,
218
218
  accounts: [],
219
219
  activeRouting: {},
@@ -1,4 +1,4 @@
1
- import { mkdirSync, readFileSync } from "node:fs";
1
+ import { chmodSync, mkdirSync, readFileSync } from "node:fs";
2
2
  import { homedir } from "node:os";
3
3
  import { dirname, join } from "node:path";
4
4
  import { writeJsonAtomic } from "@cortexkit/antigravity-auth-core/atomic-write";
@@ -6,7 +6,7 @@ import {
6
6
  acquireFencedFileLock
7
7
  } from "@cortexkit/antigravity-auth-core/file-lock";
8
8
  import { xdgState } from "xdg-basedir";
9
- export const SIDEBAR_STATE_VERSION = 1, DEFAULT_SIDEBAR_STATE = {
9
+ export const SIDEBAR_STATE_VERSION = 2, DEFAULT_SIDEBAR_STATE = {
10
10
  version: SIDEBAR_STATE_VERSION,
11
11
  checkedAt: 0,
12
12
  accounts: [],
@@ -56,7 +56,7 @@ function normalizeSidebarState(input) {
56
56
  if (!isObject(input))
57
57
  return { ...DEFAULT_SIDEBAR_STATE, lastError: "shape" };
58
58
  const record = input, version = record.version;
59
- if (version !== SIDEBAR_STATE_VERSION)
59
+ if (version !== 1 && version !== SIDEBAR_STATE_VERSION)
60
60
  return {
61
61
  ...DEFAULT_SIDEBAR_STATE,
62
62
  lastError: `unsupported-version:${stringifySafe(version)}`
@@ -96,6 +96,7 @@ function normalizeAccount(input) {
96
96
  return {
97
97
  id,
98
98
  label,
99
+ ...typeof record.email === "string" ? { email: record.email } : {},
99
100
  enabled,
100
101
  health,
101
102
  current,
@@ -116,19 +117,20 @@ function normalizeTier(input) {
116
117
  function normalizeQuota(input) {
117
118
  if (!isObject(input))
118
119
  return null;
119
- const record = input, remaining = toFiniteNumber(record.remainingPercent);
120
+ const record = input, remaining = toFiniteNumber(record.remainingPercent), fraction = toFiniteNumber(record.remainingFraction);
120
121
  if (remaining === null)
121
122
  return null;
122
123
  const resetAt = toFiniteNumber(record.resetAt) ?? void 0, checkedAt = toFiniteNumber(record.checkedAt) ?? void 0, windowsRaw = record.windows;
123
124
  let windows;
124
125
  if (Array.isArray(windowsRaw)) {
125
126
  const parsed = windowsRaw.filter(isObject).map((w) => {
126
- const win = w.window, rp = toFiniteNumber(w.remainingPercent), ra = toFiniteNumber(w.resetAt), ca = toFiniteNumber(w.checkedAt);
127
+ const win = w.window, rp = toFiniteNumber(w.remainingPercent), ra = toFiniteNumber(w.resetAt), ca = toFiniteNumber(w.checkedAt), rf = toFiniteNumber(w.remainingFraction);
127
128
  if (win !== "weekly" && win !== "5h" || rp === null)
128
129
  return null;
129
130
  return {
130
131
  window: win,
131
132
  remainingPercent: clampNumber(rp, 0, 100),
133
+ ...rf !== null ? { remainingFraction: clampNumber(rf, 0, 1) } : {},
132
134
  resetAt: ra ?? void 0,
133
135
  ...ca !== null && ca >= 0 ? { checkedAt: ca } : {}
134
136
  };
@@ -138,6 +140,7 @@ function normalizeQuota(input) {
138
140
  }
139
141
  return {
140
142
  remainingPercent: clampNumber(remaining, 0, 100),
143
+ ...fraction !== null ? { remainingFraction: clampNumber(fraction, 0, 1) } : {},
141
144
  resetAt,
142
145
  ...checkedAt !== void 0 ? { checkedAt } : {},
143
146
  windows
@@ -189,6 +192,7 @@ function stringifySafe(value) {
189
192
  }
190
193
  export function ensureSidebarStateDir(path = getSidebarStateFile()) {
191
194
  mkdirSync(dirname(path), { recursive: !0, mode: SIDEBAR_STATE_DIR_MODE });
195
+ chmodSync(dirname(path), SIDEBAR_STATE_DIR_MODE);
192
196
  }
193
197
  export function pruneActiveRouting(map, now) {
194
198
  const cutoff = now - ACTIVE_ROUTING_MAX_AGE_MS, filtered = [];
@@ -249,6 +253,7 @@ export function projectQuotaPoolForSidebar(source, checkedAt) {
249
253
  window: w.window,
250
254
  ...readingAt !== void 0 ? { checkedAt: readingAt } : {},
251
255
  remainingPercent: clampNumber(Math.round(w.remainingFraction * 100), 0, 100),
256
+ remainingFraction: clampNumber(w.remainingFraction, 0, 1),
252
257
  resetAt: typeof w.resetTime === "string" && w.resetTime.length > 0 ? (() => {
253
258
  const parsed = Date.parse(w.resetTime);
254
259
  return Number.isFinite(parsed) ? parsed : void 0;
@@ -256,6 +261,7 @@ export function projectQuotaPoolForSidebar(source, checkedAt) {
256
261
  })) : void 0;
257
262
  return {
258
263
  remainingPercent,
264
+ remainingFraction: clampNumber(fraction, 0, 1),
259
265
  resetAt,
260
266
  windows,
261
267
  ...readingAt !== void 0 ? { checkedAt: readingAt } : {}
@@ -278,6 +284,7 @@ export function redactAccountForSidebar(source) {
278
284
  return {
279
285
  id,
280
286
  label,
287
+ ...typeof source.email === "string" ? { email: source.email } : {},
281
288
  enabled,
282
289
  health,
283
290
  current,
@@ -285,7 +285,7 @@ interface InternalState {
285
285
  }
286
286
 
287
287
  const EMPTY_STATE: SidebarStateV1 = {
288
- version: 1,
288
+ version: 2,
289
289
  checkedAt: 0,
290
290
  accounts: [],
291
291
  activeRouting: {},
package/src/tui.tsx CHANGED
@@ -285,7 +285,7 @@ interface InternalState {
285
285
  }
286
286
 
287
287
  const EMPTY_STATE: SidebarStateV1 = {
288
- version: 1,
288
+ version: 2,
289
289
  checkedAt: 0,
290
290
  accounts: [],
291
291
  activeRouting: {},