Run local usage services in a supervised backend process (#40792)

* Move local usage services into a supervised backend process

* Own usage recovery and worker retirement lifetimes

* Preserve answered usage data during background refresh

* Run independent usage scans concurrently in the backend

* Limit backend startup paths to the delegated usage service

* Show usage failures through backend recovery

* Include usage failure strings in the English catalog

* Keep usage update details beside refresh failures

* Resolve usage freshness failure from the final producer snapshot

* Retain the forced refresh completion requirement

* Keep managed backend failures out of application crash reports

* Preserve usage recovery boundaries across backend reconnects

* Match the backend RPC cancellation signal in the usage seam proof

* Avoid serializing backend requests before port delivery

* Keep receiving request validation in the boundary schemas

* test: align usage transport coverage with renderer project

* fix: preserve unknown usage state and renderer retirement

* fix(usage): revalidate tracking before scan admission

* fix(usage): retry failed backend startup on demand

* test(usage): isolate stale backend ownership checks
This commit is contained in:
Brennan Benson
2026-11-11 16:39:52 -08:00
committed by GitHub
parent 890ad4d8aa
commit 175f10e32b
85 changed files with 4898 additions and 789 deletions
+10 -2
View File
@@ -1,3 +1,7 @@
import type {
BackendConnectionListener,
BackendConnectionPurpose
} from '../../shared/backend-service-contract'
import type { ClaudeUsageBreakdownKind, ClaudeUsageSnapshot } from '../../shared/claude-usage-types'
import type { CodexUsageBreakdownKind, CodexUsageSnapshot } from '../../shared/codex-usage-types'
import type {
@@ -25,10 +29,14 @@ export type UsageQueryArgs<Snapshot extends UsageProviderSnapshot> = Pick<
>
export type UsageProviderApi<Snapshot extends UsageProviderSnapshot, BreakdownKind> = {
getScanState: () => Promise<Snapshot['scanState']>
onConnectionChanged?: (listener: BackendConnectionListener) => () => void
getScanState: (purpose?: BackendConnectionPurpose) => Promise<Snapshot['scanState']>
setEnabled: (args: { enabled: boolean }) => Promise<Snapshot['scanState']>
refresh: (args?: { force?: boolean }) => Promise<Snapshot['scanState']>
getSnapshot: (args: UsageQueryArgs<Snapshot> & { limit?: number }) => Promise<Snapshot>
getSnapshot: (
args: UsageQueryArgs<Snapshot> & { limit?: number },
purpose?: BackendConnectionPurpose
) => Promise<Snapshot>
getSummary: (args: UsageQueryArgs<Snapshot>) => Promise<Snapshot['summary']>
getDaily: (args: UsageQueryArgs<Snapshot>) => Promise<Snapshot['daily']>
getBreakdown: (
+2 -2
View File
@@ -1,8 +1,8 @@
import { ipcRenderer } from 'electron'
import { backendUsageTransport } from '../backend-port-client'
import { createUsageProviderApi } from '../usage-provider-api'
import type { PreloadApi } from '../api-types'
export const claudeUsageApi = createUsageProviderApi(
ipcRenderer,
backendUsageTransport,
'claudeUsage'
) satisfies PreloadApi['claudeUsage']
+2 -2
View File
@@ -1,8 +1,8 @@
import { ipcRenderer } from 'electron'
import { backendUsageTransport } from '../backend-port-client'
import { createUsageProviderApi } from '../usage-provider-api'
import type { PreloadApi } from '../api-types'
export const codexUsageApi = createUsageProviderApi(
ipcRenderer,
backendUsageTransport,
'codexUsage'
) satisfies PreloadApi['codexUsage']
+2 -2
View File
@@ -1,8 +1,8 @@
import { ipcRenderer } from 'electron'
import { backendUsageTransport } from '../backend-port-client'
import { createUsageProviderApi } from '../usage-provider-api'
import type { PreloadApi } from '../api-types'
export const museUsageApi = createUsageProviderApi(
ipcRenderer,
backendUsageTransport,
'museUsage'
) satisfies PreloadApi['museUsage']
+2 -2
View File
@@ -1,8 +1,8 @@
import { ipcRenderer } from 'electron'
import { backendUsageTransport } from '../backend-port-client'
import { createUsageProviderApi } from '../usage-provider-api'
import type { PreloadApi } from '../api-types'
export const openCodeUsageApi = createUsageProviderApi(
ipcRenderer,
backendUsageTransport,
'openCodeUsage'
) satisfies PreloadApi['openCodeUsage']