266 lines · 9.4 KB · TypeScript
RawDownload
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<T extends string = string> {  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<ClientSettings | null>;  setClientSettings: (settings: ClientSettings) => Promise<void>;  getSavedEnvironmentRegistry: () => Promise<readonly PersistedSavedEnvironmentRecord[]>;  setSavedEnvironmentRegistry: (    records: readonly PersistedSavedEnvironmentRecord[],  ) => Promise<void>;  getSavedEnvironmentSecret: (environmentId: EnvironmentId) => Promise<string | null>;  setSavedEnvironmentSecret: (environmentId: EnvironmentId, secret: string) => Promise<boolean>;  removeSavedEnvironmentSecret: (environmentId: EnvironmentId) => Promise<void>;  getServerExposureState: () => Promise<DesktopServerExposureState>;  setServerExposureMode: (mode: DesktopServerExposureMode) => Promise<DesktopServerExposureState>;  pickFolder: () => Promise<string | null>;  confirm: (message: string) => Promise<boolean>;  setTheme: (theme: DesktopTheme) => Promise<void>;  showContextMenu: <T extends string>(    items: readonly ContextMenuItem<T>[],    position?: { x: number; y: number },  ) => Promise<T | null>;  openExternal: (url: string) => Promise<boolean>;  onMenuAction: (listener: (action: string) => void) => () => void;  getUpdateState: () => Promise<DesktopUpdateState>;  checkForUpdate: () => Promise<DesktopUpdateCheckResult>;  downloadUpdate: () => Promise<DesktopUpdateActionResult>;  installUpdate: () => Promise<DesktopUpdateActionResult>;  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<string | null>;    confirm: (message: string) => Promise<boolean>;  };  shell: {    openInEditor: (cwd: string, editor: EditorId) => Promise<void>;    openExternal: (url: string) => Promise<void>;  };  contextMenu: {    show: <T extends string>(      items: readonly ContextMenuItem<T>[],      position?: { x: number; y: number },    ) => Promise<T | null>;  };  persistence: {    getClientSettings: () => Promise<ClientSettings | null>;    setClientSettings: (settings: ClientSettings) => Promise<void>;    getSavedEnvironmentRegistry: () => Promise<readonly PersistedSavedEnvironmentRecord[]>;    setSavedEnvironmentRegistry: (      records: readonly PersistedSavedEnvironmentRecord[],    ) => Promise<void>;    getSavedEnvironmentSecret: (environmentId: EnvironmentId) => Promise<string | null>;    setSavedEnvironmentSecret: (environmentId: EnvironmentId, secret: string) => Promise<boolean>;    removeSavedEnvironmentSecret: (environmentId: EnvironmentId) => Promise<void>;  };  server: {    getConfig: () => Promise<ServerConfig>;    refreshProviders: () => Promise<ServerProviderUpdatedPayload>;    upsertKeybinding: (input: ServerUpsertKeybindingInput) => Promise<ServerUpsertKeybindingResult>;    getSettings: () => Promise<ServerSettings>;    updateSettings: (patch: ServerSettingsPatch) => Promise<ServerSettings>;  };} /** * 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<TerminalSessionSnapshot>;    write: (input: typeof TerminalWriteInput.Encoded) => Promise<void>;    resize: (input: typeof TerminalResizeInput.Encoded) => Promise<void>;    clear: (input: typeof TerminalClearInput.Encoded) => Promise<void>;    restart: (input: typeof TerminalRestartInput.Encoded) => Promise<TerminalSessionSnapshot>;    close: (input: typeof TerminalCloseInput.Encoded) => Promise<void>;    onEvent: (callback: (event: TerminalEvent) => void) => () => void;  };  projects: {    searchEntries: (input: ProjectSearchEntriesInput) => Promise<ProjectSearchEntriesResult>;    writeFile: (input: ProjectWriteFileInput) => Promise<ProjectWriteFileResult>;  };  git: {    listBranches: (input: GitListBranchesInput) => Promise<GitListBranchesResult>;    createWorktree: (input: GitCreateWorktreeInput) => Promise<GitCreateWorktreeResult>;    removeWorktree: (input: GitRemoveWorktreeInput) => Promise<void>;    createBranch: (input: GitCreateBranchInput) => Promise<GitCreateBranchResult>;    checkout: (input: GitCheckoutInput) => Promise<GitCheckoutResult>;    init: (input: GitInitInput) => Promise<void>;    resolvePullRequest: (input: GitPullRequestRefInput) => Promise<GitResolvePullRequestResult>;    preparePullRequestThread: (      input: GitPreparePullRequestThreadInput,    ) => Promise<GitPreparePullRequestThreadResult>;    pull: (input: GitPullInput) => Promise<GitPullResult>;    refreshStatus: (input: GitStatusInput) => Promise<GitStatusResult>;    onStatus: (      input: GitStatusInput,      callback: (status: GitStatusResult) => void,      options?: {        onResubscribe?: () => void;      },    ) => () => void;  };  orchestration: {    getSnapshot: () => Promise<OrchestrationReadModel>;    dispatchCommand: (command: ClientOrchestrationCommand) => Promise<{ sequence: number }>;    getTurnDiff: (input: OrchestrationGetTurnDiffInput) => Promise<OrchestrationGetTurnDiffResult>;    getFullThreadDiff: (      input: OrchestrationGetFullThreadDiffInput,    ) => Promise<OrchestrationGetFullThreadDiffResult>;    replayEvents: (fromSequenceExclusive: number) => Promise<OrchestrationEvent[]>;    onDomainEvent: (      callback: (event: OrchestrationEvent) => void,      options?: {        onResubscribe?: () => void;      },    ) => () => void;  };}