import type { GitCheckoutInput, GitCheckoutResult, GitCreateBranchInput, GitPreparePullRequestThreadInput, GitPreparePullRequestThreadResult, GitPullRequestRefInput, GitCreateWorktreeInput, GitCreateWorktreeResult, GitInitInput, GitListBranchesInput, GitListBranchesResult, GitPullInput, GitPullResult, GitRemoveWorktreeInput, GitResolvePullRequestResult, GitStatusInput, GitStatusResult, GitCreateBranchResult, } from "./git"; import type { ProjectSearchEntriesInput, ProjectSearchEntriesResult, ProjectWriteFileInput, ProjectWriteFileResult, } from "./project"; import type { ServerConfig, ServerProviderUpdatedPayload, ServerUpsertKeybindingResult, } from "./server"; import type { TerminalClearInput, TerminalCloseInput, TerminalEvent, TerminalOpenInput, TerminalResizeInput, TerminalRestartInput, TerminalSessionSnapshot, TerminalWriteInput, } from "./terminal"; import type { ServerUpsertKeybindingInput } from "./server"; import type { ClientOrchestrationCommand, OrchestrationGetFullThreadDiffInput, OrchestrationGetFullThreadDiffResult, OrchestrationGetTurnDiffInput, OrchestrationGetTurnDiffResult, OrchestrationEvent, OrchestrationReadModel, } from "./orchestration"; import type { EnvironmentId } from "./baseSchemas"; import { EditorId } from "./editor"; import { ClientSettings, ServerSettings, ServerSettingsPatch } from "./settings"; export interface ContextMenuItem { id: T; label: string; destructive?: boolean; disabled?: boolean; } export type DesktopUpdateStatus = | "disabled" | "idle" | "checking" | "up-to-date" | "available" | "downloading" | "downloaded" | "error"; export type DesktopRuntimeArch = "arm64" | "x64" | "other"; export type DesktopTheme = "light" | "dark" | "system"; export interface DesktopRuntimeInfo { hostArch: DesktopRuntimeArch; appArch: DesktopRuntimeArch; runningUnderArm64Translation: boolean; } export interface DesktopUpdateState { enabled: boolean; status: DesktopUpdateStatus; currentVersion: string; hostArch: DesktopRuntimeArch; appArch: DesktopRuntimeArch; runningUnderArm64Translation: boolean; availableVersion: string | null; downloadedVersion: string | null; downloadPercent: number | null; checkedAt: string | null; message: string | null; errorContext: "check" | "download" | "install" | null; canRetry: boolean; } export interface DesktopUpdateActionResult { accepted: boolean; completed: boolean; state: DesktopUpdateState; } export interface DesktopUpdateCheckResult { checked: boolean; state: DesktopUpdateState; } export interface DesktopEnvironmentBootstrap { label: string; httpBaseUrl: string | null; wsBaseUrl: string | null; bootstrapToken?: string; } export interface PersistedSavedEnvironmentRecord { environmentId: EnvironmentId; label: string; wsBaseUrl: string; httpBaseUrl: string; createdAt: string; lastConnectedAt: string | null; } export type DesktopServerExposureMode = "local-only" | "network-accessible"; export interface DesktopServerExposureState { mode: DesktopServerExposureMode; endpointUrl: string | null; advertisedHost: string | null; } export interface DesktopBridge { getLocalEnvironmentBootstrap: () => DesktopEnvironmentBootstrap | null; getClientSettings: () => Promise; setClientSettings: (settings: ClientSettings) => Promise; getSavedEnvironmentRegistry: () => Promise; setSavedEnvironmentRegistry: ( records: readonly PersistedSavedEnvironmentRecord[], ) => Promise; getSavedEnvironmentSecret: (environmentId: EnvironmentId) => Promise; setSavedEnvironmentSecret: (environmentId: EnvironmentId, secret: string) => Promise; removeSavedEnvironmentSecret: (environmentId: EnvironmentId) => Promise; getServerExposureState: () => Promise; setServerExposureMode: (mode: DesktopServerExposureMode) => Promise; pickFolder: () => Promise; confirm: (message: string) => Promise; setTheme: (theme: DesktopTheme) => Promise; showContextMenu: ( items: readonly ContextMenuItem[], position?: { x: number; y: number }, ) => Promise; openExternal: (url: string) => Promise; onMenuAction: (listener: (action: string) => void) => () => void; getUpdateState: () => Promise; checkForUpdate: () => Promise; downloadUpdate: () => Promise; installUpdate: () => Promise; onUpdateState: (listener: (state: DesktopUpdateState) => void) => () => void; } /** * APIs bound to the local app shell, not to any particular backend environment. * * These capabilities describe the desktop/browser host that the user is * currently running: dialogs, editor/external-link opening, context menus, and * app-level settings/config access. They must not be used as a proxy for * "whatever environment the user is targeting", because in a multi-environment * world the local shell and a selected backend environment are distinct * concepts. */ export interface LocalApi { dialogs: { pickFolder: () => Promise; confirm: (message: string) => Promise; }; shell: { openInEditor: (cwd: string, editor: EditorId) => Promise; openExternal: (url: string) => Promise; }; contextMenu: { show: ( items: readonly ContextMenuItem[], position?: { x: number; y: number }, ) => Promise; }; persistence: { getClientSettings: () => Promise; setClientSettings: (settings: ClientSettings) => Promise; getSavedEnvironmentRegistry: () => Promise; setSavedEnvironmentRegistry: ( records: readonly PersistedSavedEnvironmentRecord[], ) => Promise; getSavedEnvironmentSecret: (environmentId: EnvironmentId) => Promise; setSavedEnvironmentSecret: (environmentId: EnvironmentId, secret: string) => Promise; removeSavedEnvironmentSecret: (environmentId: EnvironmentId) => Promise; }; server: { getConfig: () => Promise; refreshProviders: () => Promise; upsertKeybinding: (input: ServerUpsertKeybindingInput) => Promise; getSettings: () => Promise; updateSettings: (patch: ServerSettingsPatch) => Promise; }; } /** * APIs bound to a specific backend environment connection. * * These operations must always be routed with explicit environment context. * They represent remote stateful capabilities such as orchestration, terminal, * project, and git operations. In multi-environment mode, each environment gets * its own instance of this surface, and callers should resolve it by * `environmentId` rather than reaching through the local desktop bridge. */ export interface EnvironmentApi { terminal: { open: (input: typeof TerminalOpenInput.Encoded) => Promise; write: (input: typeof TerminalWriteInput.Encoded) => Promise; resize: (input: typeof TerminalResizeInput.Encoded) => Promise; clear: (input: typeof TerminalClearInput.Encoded) => Promise; restart: (input: typeof TerminalRestartInput.Encoded) => Promise; close: (input: typeof TerminalCloseInput.Encoded) => Promise; onEvent: (callback: (event: TerminalEvent) => void) => () => void; }; projects: { searchEntries: (input: ProjectSearchEntriesInput) => Promise; writeFile: (input: ProjectWriteFileInput) => Promise; }; git: { listBranches: (input: GitListBranchesInput) => Promise; createWorktree: (input: GitCreateWorktreeInput) => Promise; removeWorktree: (input: GitRemoveWorktreeInput) => Promise; createBranch: (input: GitCreateBranchInput) => Promise; checkout: (input: GitCheckoutInput) => Promise; init: (input: GitInitInput) => Promise; resolvePullRequest: (input: GitPullRequestRefInput) => Promise; preparePullRequestThread: ( input: GitPreparePullRequestThreadInput, ) => Promise; pull: (input: GitPullInput) => Promise; refreshStatus: (input: GitStatusInput) => Promise; onStatus: ( input: GitStatusInput, callback: (status: GitStatusResult) => void, options?: { onResubscribe?: () => void; }, ) => () => void; }; orchestration: { getSnapshot: () => Promise; dispatchCommand: (command: ClientOrchestrationCommand) => Promise<{ sequence: number }>; getTurnDiff: (input: OrchestrationGetTurnDiffInput) => Promise; getFullThreadDiff: ( input: OrchestrationGetFullThreadDiffInput, ) => Promise; replayEvents: (fromSequenceExclusive: number) => Promise; onDomainEvent: ( callback: (event: OrchestrationEvent) => void, options?: { onResubscribe?: () => void; }, ) => () => void; }; }