Files
orca/src/shared/backend-service-contract.ts
T
Brennan Benson 175f10e32b 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
2026-11-11 16:39:52 -08:00

76 lines
2.2 KiB
TypeScript

import { z } from 'zod'
import type { RuntimeRpcResponse } from './runtime-rpc-envelope'
import type { AutomationRunUsage } from './automations/history/automation-run'
export const BACKEND_PORT_REQUEST = 'backend:connect'
export const BACKEND_PORT_DELIVERY = 'backend:port'
export const BACKEND_CONNECTION_CHANGED = 'backend:connectionChanged'
export const BACKEND_UTILITY_PROCESS_NAME = 'Orca backend'
export type BackendConnectionPurpose = 'demand' | 'recovery'
export type BackendConnectionStatus = { connected: boolean; unavailable?: boolean }
export type BackendConnectionDetail = { initial?: boolean; unavailable?: boolean }
export type BackendConnectionListener = (
connected: boolean,
detail?: BackendConnectionDetail
) => void
export const UsageProviderSchema = z.enum([
'claudeUsage',
'codexUsage',
'openCodeUsage',
'museUsage'
])
export type UsageProviderKey = z.infer<typeof UsageProviderSchema>
export const UsageActionSchema = z.enum([
'getScanState',
'setEnabled',
'refresh',
'getSnapshot',
'getSummary',
'getDaily',
'getBreakdown',
'getRecentSessions'
])
export type UsageAction = z.infer<typeof UsageActionSchema>
export type BackendResponse = RuntimeRpcResponse<unknown>
export const BackendBootstrapSchema = z
.object({
protocol: z.literal(1),
requiredCapabilities: z.array(z.string().max(128)).max(32),
services: z.tuple([z.literal('usage')]),
build: z.string().max(256),
paths: z.object({
userData: z.string().min(1)
}),
appPath: z.string().min(1),
isPackaged: z.boolean()
})
.strip()
export type BackendBootstrap = z.infer<typeof BackendBootstrapSchema>
export const BACKEND_CAPABILITIES = [
'usage',
'usage.catalog',
'usage.claudeProfileDirs',
'usage.telemetry'
] as const
export const BackendRequestSchema = z
.object({
id: z.string().min(1).max(128),
method: z.string().min(1).max(128),
params: z.unknown().optional()
})
.strip()
export type AutomationUsageInput = {
worktreeId: string | null
terminalSessionId: string | null
startedAt: number | null
completedAt: number | null
}
export type AutomationUsageClient = {
getAutomationRunUsage(input: AutomationUsageInput): Promise<AutomationRunUsage>
}