mirror of
https://github.com/stablyai/orca.git
synced 2026-09-26 00:02:34 +00:00
`src/preload/api-types.ts` was 3,752 raw lines (3,533 counted, 11.8x the 300-line budget) behind an `eslint-disable max-lines`. Almost all of it was a single `PreloadApi` object type whose ~83 namespace properties were declared inline, so any IPC surface change meant editing one 2,600-line type. Give each namespace a named type in its own module under `src/preload/api/` (`pty-api.ts`, `filesystem-api.ts`, `github-pull-request-api.ts`, ...) and recompose `PreloadApi` from those names. `api-types.ts` keeps the `declare global` Window augmentation and re-exports every moved name, so all 52 import sites are untouched. Two shapes needed care to stay type-identical rather than merely compatible: - Three keys (`gh`, `git`, `ui`) are composed from two modules each. A plain intersection is NOT identical to the original flat object literal, so those use a `Merged<T>` mapped type; a negative control confirmed that dropping it fails the parity assertion. - Keys whose module groups several namespaces use indexed access (`fs: FilesystemApi['fs']`) to preserve exact identity and source order. `config/tsconfig.web.json` and `tsconfig.tc.web.json` enumerate files by path, so they need `src/preload/api/**/*` alongside the existing `api-types.ts` seed or the web projects fail TS6307. Verified by exact type identity, not assignability: 41 assertions of the form `Equals<Now.X, Before.X>` against a frozen pre-split snapshot, covering every exported name, plus a per-key pass over all 83 `PreloadApi` keys. All three projects typecheck clean with those assertions active. Verification note: these tsconfigs are `composite: true`, and `tsc --noEmit` will reuse a stale `.tsbuildinfo` and report clean for a state that genuinely fails. Every result above was produced after deleting the buildinfo, including a negative control confirming the gate still fails on deliberate drift. Drops the `max-lines` bypass and its baseline entry (ratchet 346 -> 345).
192 lines
6.4 KiB
TypeScript
192 lines
6.4 KiB
TypeScript
import type {
|
|
PluginPanelActionOutcome,
|
|
PluginPanelEntry
|
|
} from '../../shared/plugins/plugin-panel-bridge'
|
|
import type { PluginConsentRequest } from '../../shared/plugins/plugin-consent-request'
|
|
import type { PluginLanguagePackRegistration } from '../../shared/plugins/plugin-language-pack-artifact'
|
|
import type { PluginChangeEvent } from '../../shared/plugins/plugin-change-event'
|
|
import type { PluginManifest } from '../../shared/plugins/plugin-manifest'
|
|
import type { PluginMarketplaceGitSource } from '../../shared/plugins/plugin-marketplace'
|
|
|
|
/** Panel contribution as surfaced by the main-process plugin service. */
|
|
export type PluginHostPanel = {
|
|
id: string
|
|
title: string
|
|
/** Lucide icon name declared in the plugin manifest. */
|
|
icon?: string
|
|
tabKey: `plugin:${string}`
|
|
}
|
|
|
|
/** `pending` = awaiting (re-)consent; `idle` = enabled, worker not running
|
|
* (lazy); `restarting` = waiting for supervised backoff; `errored` = crashed past the restart budget or failed to start;
|
|
* `invalid` = unreadable manifest. */
|
|
export type PluginHostStatus =
|
|
| 'running'
|
|
| 'restarting'
|
|
| 'idle'
|
|
| 'pending'
|
|
| 'disabled'
|
|
| 'errored'
|
|
| 'invalid'
|
|
|
|
/** Wire shape of plugins:list — must stay assignable from the main-process
|
|
* projection in src/main/plugins/plugin-list-projection.ts. */
|
|
export type PluginHostListEntry = {
|
|
pluginKey: string
|
|
consentFingerprint: string | null
|
|
name: string
|
|
version: string
|
|
publisher: string
|
|
description?: string
|
|
status: PluginHostStatus
|
|
needsReconsent: boolean
|
|
error?: string
|
|
isDev: boolean
|
|
official: boolean
|
|
bundled: boolean
|
|
capabilities: { kind: string; description: string }[]
|
|
panels: PluginHostPanel[]
|
|
commands: {
|
|
id: string
|
|
title: string
|
|
context: 'global' | 'worktree'
|
|
handler: { type: 'built-in'; action: string } | { type: 'worker' }
|
|
keybindings: { key: string; when: 'global' | 'worktree' }[]
|
|
}[]
|
|
hasWorker: boolean
|
|
vmRecipes?: {
|
|
id: string
|
|
name: string
|
|
description?: string
|
|
commands: {
|
|
phase: 'create' | 'suspend' | 'resume' | 'destroy'
|
|
command: string
|
|
}[]
|
|
}[]
|
|
restarts: number
|
|
blockedByKillList?: { reason: string; advisoryUrl?: string }
|
|
source?: {
|
|
kind: 'local-path' | 'git' | 'marketplace' | 'bundled'
|
|
reference: string
|
|
resolvedCommit: string | null
|
|
contentHash: string
|
|
marketplace?: { reference: string; resolvedCommit: string }
|
|
}
|
|
}
|
|
|
|
export type PluginHostLogLine = {
|
|
ts: number
|
|
level: 'info' | 'warn' | 'error'
|
|
line: string
|
|
}
|
|
|
|
export type PluginHostInstallSource =
|
|
| { kind: 'local-path'; path: string }
|
|
| { kind: 'git'; url: string; ref: string }
|
|
|
|
export type PluginHostInstallResult =
|
|
| {
|
|
ok: true
|
|
pluginKey: string
|
|
version: string
|
|
contentHash: string
|
|
consentFingerprint: string
|
|
resolvedCommit: string | null
|
|
}
|
|
| { ok: false; error: string }
|
|
|
|
export type PluginMarketplaceHostSourceState = {
|
|
id: string
|
|
source: PluginMarketplaceGitSource
|
|
addedAt: number
|
|
marketplace: {
|
|
name: string
|
|
owner: string
|
|
resolvedCommit: string
|
|
fetchedAt: number
|
|
} | null
|
|
stale: boolean
|
|
official: boolean
|
|
error?: string
|
|
}
|
|
|
|
export type PluginMarketplaceHostListing = {
|
|
marketplaceSourceId: string
|
|
marketplaceName: string
|
|
marketplaceOwner: string
|
|
marketplaceCommit: string
|
|
pluginKey: string
|
|
source: PluginMarketplaceGitSource
|
|
description?: string
|
|
categories: string[]
|
|
official: boolean
|
|
bundled: boolean
|
|
blockedByKillList?: { reason: string; advisoryUrl?: string }
|
|
}
|
|
|
|
export type PluginMarketplaceHostInstallPreview = {
|
|
marketplaceSourceId: string
|
|
marketplaceName: string
|
|
marketplaceOwner: string
|
|
marketplaceCommit: string
|
|
pluginKey: string
|
|
source: PluginMarketplaceGitSource
|
|
resolvedCommit: string
|
|
contentHash: string
|
|
consentFingerprint: string
|
|
manifest: PluginManifest
|
|
official: boolean
|
|
bundled: boolean
|
|
blockedByKillList?: { reason: string; advisoryUrl?: string }
|
|
}
|
|
|
|
export type PluginsApi = {
|
|
list: () => Promise<PluginHostListEntry[]>
|
|
listLanguagePacks: () => Promise<PluginLanguagePackRegistration[]>
|
|
/** Records the consent-dialog answer; approval is keyed to the plugin's
|
|
* current capability and trusted-worker fingerprint. */
|
|
consent: (args: PluginConsentRequest) => Promise<PluginHostListEntry[]>
|
|
setEnabled: (args: { pluginKey: string; enabled: boolean }) => Promise<PluginHostListEntry[]>
|
|
/** Returns the panel's CSP-wrapped HTML, or null when the plugin or
|
|
* panel is missing/disabled. Rendered only inside a sandboxed iframe. */
|
|
readPanelEntry: (args: { pluginKey: string; panelId: string }) => Promise<PluginPanelEntry | null>
|
|
invokeCommand: (args: {
|
|
pluginKey: string
|
|
commandId: string
|
|
args?: unknown
|
|
}) => Promise<unknown>
|
|
/** Relays a sandboxed panel's bridge request to main, which enforces the
|
|
* plugin's consented capabilities before executing. */
|
|
panelAction: (args: {
|
|
sessionToken: string
|
|
action: string
|
|
params?: unknown
|
|
}) => Promise<PluginPanelActionOutcome>
|
|
install: (source: PluginHostInstallSource) => Promise<PluginHostInstallResult>
|
|
listMarketplaces: () => Promise<PluginMarketplaceHostSourceState[]>
|
|
addMarketplace: (source: PluginMarketplaceGitSource) => Promise<PluginMarketplaceHostSourceState>
|
|
removeMarketplace: (args: { sourceId: string }) => Promise<PluginMarketplaceHostSourceState[]>
|
|
refreshMarketplaces: (args?: { sourceId?: string }) => Promise<PluginMarketplaceHostSourceState[]>
|
|
listMarketplacePlugins: () => Promise<PluginMarketplaceHostListing[]>
|
|
previewMarketplacePlugin: (args: {
|
|
marketplaceSourceId: string
|
|
pluginKey: string
|
|
}) => Promise<PluginMarketplaceHostInstallPreview>
|
|
installMarketplacePlugin: (
|
|
preview: Pick<
|
|
PluginMarketplaceHostInstallPreview,
|
|
'marketplaceSourceId' | 'marketplaceCommit' | 'pluginKey' | 'resolvedCommit'
|
|
>
|
|
) => Promise<PluginHostInstallResult>
|
|
previewMarketplaceUpdate: (args: {
|
|
pluginKey: string
|
|
}) => Promise<PluginMarketplaceHostInstallPreview>
|
|
rollbackMarketplacePlugin: (args: { pluginKey: string }) => Promise<PluginHostInstallResult>
|
|
remove: (args: { pluginKey: string }) => Promise<PluginHostListEntry[]>
|
|
getLogs: (args: { pluginKey: string }) => Promise<PluginHostLogLine[]>
|
|
/** Re-discovers after settings edits (feature flag, dev paths). */
|
|
refresh: () => Promise<PluginHostListEntry[]>
|
|
/** Fires whenever installed plugins, worker states, panels, or content packs change. */
|
|
onChanged: (callback: (event: PluginChangeEvent) => void) => () => void
|
|
}
|