import type { VcsCreateRefInput, VcsCreateRefResult, VcsCreateWorktreeInput, VcsCreateWorktreeResult, VcsInitInput, VcsListRefsInput, VcsListRefsResult, VcsPullInput, VcsPullResult, VcsRemoveWorktreeInput, VcsSwitchRefInput, VcsSwitchRefResult, GitPreparePullRequestThreadInput, GitPreparePullRequestThreadResult, GitPullRequestRefInput, GitResolvePullRequestResult, VcsStatusInput, VcsStatusResult,} from "./git.ts";import type { ReviewDiffPreviewInput, ReviewDiffPreviewResult } from "./review.ts";import type { FilesystemBrowseInput, FilesystemBrowseResult } from "./filesystem.ts";import type { AssetCreateUrlInput, AssetCreateUrlResult } from "./assets.ts";import type { ProjectListEntriesInput, ProjectListEntriesResult, ProjectReadFileInput, ProjectReadFileResult, ProjectSearchEntriesInput, ProjectSearchEntriesResult, ProjectWriteFileInput, ProjectWriteFileResult,} from "./project.ts";import type { ProviderInstanceId } from "./providerInstance.ts";import type { ServerConfig, ServerProcessDiagnosticsResult, ServerProcessResourceHistoryInput, ServerProcessResourceHistoryResult, ServerProviderUpdateInput, ServerProviderUpdatedPayload, ServerRemoveKeybindingResult, ServerSignalProcessInput, ServerSignalProcessResult, ServerTraceDiagnosticsResult, ServerUpsertKeybindingResult,} from "./server.ts";import type { TerminalAttachInput, TerminalAttachStreamEvent, TerminalClearInput, TerminalCloseInput, TerminalMetadataStreamEvent, TerminalOpenInput, TerminalResizeInput, TerminalRestartInput, TerminalSessionSnapshot, TerminalWriteInput,} from "./terminal.ts";import type { ServerRemoveKeybindingInput, ServerUpsertKeybindingInput } from "./server.ts";import * as Schema from "effect/Schema";import type { DiscoveredLocalServerList, PreviewCloseInput, PreviewEvent, PreviewListInput, PreviewListResult, PreviewNavigateInput, PreviewOpenInput, PreviewRefreshInput, PreviewReportStatusInput, PreviewResizeInput, PreviewSessionSnapshot,} from "./preview.ts";import { PreviewAutomationClickInput, PreviewAutomationEvaluateInput, PreviewAutomationHost, PreviewAutomationHostFocus, PreviewAutomationPressInput, PreviewAutomationResponse, PreviewAutomationScrollInput, PreviewAutomationSnapshot, PreviewAutomationStatus, PreviewAutomationStreamEvent, PreviewAutomationTypeInput, PreviewAutomationWaitForInput,} from "./previewAutomation.ts";import type { ClientOrchestrationCommand, OrchestrationGetFullThreadDiffInput, OrchestrationGetFullThreadDiffResult, OrchestrationGetTurnDiffInput, OrchestrationGetTurnDiffResult, OrchestrationShellSnapshot, OrchestrationShellStreamItem, OrchestrationSubscribeThreadInput, OrchestrationThreadStreamItem,} from "./orchestration.ts";import { EnvironmentId } from "./baseSchemas.ts";import { AuthAccessTokenResult, AuthSessionState, AuthWebSocketTicketResult } from "./auth.ts";import { AdvertisedEndpoint } from "./remoteAccess.ts";import { EditorId } from "./editor.ts";import { ExecutionEnvironmentDescriptor } from "./environment.ts";import type { ClientSettings, ServerSettings, ServerSettingsPatch } from "./settings.ts";import type { SourceControlCloneRepositoryInput, SourceControlCloneRepositoryResult, SourceControlDiscoveryResult, SourceControlPublishRepositoryInput, SourceControlPublishRepositoryResult, SourceControlRepositoryInfo, SourceControlRepositoryLookupInput,} from "./sourceControl.ts"; export interface ContextMenuItem<T extends string = string> { id: T; label: string; destructive?: boolean; disabled?: boolean; /** Renders as a non-interactive section header label. Web fallback only — stripped on desktop native menus. */ header?: boolean; /** Icon keyword resolved by the web fallback. Stripped on desktop native menus. */ icon?: string; children?: readonly ContextMenuItem<T>[];} export interface ContextMenuItemSchemaType { readonly id: string; readonly label: string; readonly destructive?: boolean; readonly disabled?: boolean; readonly header?: boolean; readonly icon?: string; readonly children?: readonly ContextMenuItemSchemaType[];} export const ContextMenuItemSchema: Schema.Codec<ContextMenuItemSchemaType> = Schema.Struct({ id: Schema.String, label: Schema.String, destructive: Schema.optionalKey(Schema.Boolean), disabled: Schema.optionalKey(Schema.Boolean), header: Schema.optionalKey(Schema.Boolean), icon: Schema.optionalKey(Schema.String), children: Schema.optionalKey( Schema.Array( Schema.suspend((): Schema.Codec<ContextMenuItemSchemaType> => ContextMenuItemSchema), ), ),}); 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 type DesktopUpdateChannel = "latest" | "nightly";export type DesktopAppStageLabel = "Alpha" | "Dev" | "Nightly"; export const DesktopUpdateStatusSchema = Schema.Literals([ "disabled", "idle", "checking", "up-to-date", "available", "downloading", "downloaded", "error",]);export const DesktopRuntimeArchSchema = Schema.Literals(["arm64", "x64", "other"]);export const DesktopThemeSchema = Schema.Literals(["light", "dark", "system"]);export const DesktopUpdateChannelSchema = Schema.Literals(["latest", "nightly"]);export const DesktopAppStageLabelSchema = Schema.Literals(["Alpha", "Dev", "Nightly"]); export interface DesktopAppBranding { baseName: string; stageLabel: DesktopAppStageLabel; displayName: string;} export const DesktopAppBrandingSchema = Schema.Struct({ baseName: Schema.String, stageLabel: DesktopAppStageLabelSchema, displayName: Schema.String,}); export interface DesktopRuntimeInfo { hostArch: DesktopRuntimeArch; appArch: DesktopRuntimeArch; runningUnderArm64Translation: boolean;} export const DesktopRuntimeInfoSchema = Schema.Struct({ hostArch: DesktopRuntimeArchSchema, appArch: DesktopRuntimeArchSchema, runningUnderArm64Translation: Schema.Boolean,}); export interface DesktopUpdateState { enabled: boolean; status: DesktopUpdateStatus; channel: DesktopUpdateChannel; currentVersion: string; hostArch: DesktopRuntimeArch; appArch: DesktopRuntimeArch; runningUnderArm64Translation: boolean; availableVersion: string | null; downloadedVersion: string | null; releaseNotes: ReadonlyArray<DesktopUpdateReleaseNote>; downloadPercent: number | null; checkedAt: string | null; message: string | null; errorContext: "check" | "download" | "install" | null; canRetry: boolean;} export interface DesktopUpdateReleaseNote { version: string; items: ReadonlyArray<string>;} export const DesktopUpdateReleaseNoteSchema = Schema.Struct({ version: Schema.String, items: Schema.Array(Schema.String),}); export const DesktopUpdateStateSchema = Schema.Struct({ enabled: Schema.Boolean, status: DesktopUpdateStatusSchema, channel: DesktopUpdateChannelSchema, currentVersion: Schema.String, hostArch: DesktopRuntimeArchSchema, appArch: DesktopRuntimeArchSchema, runningUnderArm64Translation: Schema.Boolean, availableVersion: Schema.NullOr(Schema.String), downloadedVersion: Schema.NullOr(Schema.String), releaseNotes: Schema.Array(DesktopUpdateReleaseNoteSchema), downloadPercent: Schema.NullOr(Schema.Number), checkedAt: Schema.NullOr(Schema.String), message: Schema.NullOr(Schema.String), errorContext: Schema.NullOr(Schema.Literals(["check", "download", "install"])), canRetry: Schema.Boolean,}); export interface DesktopUpdateActionResult { accepted: boolean; completed: boolean; state: DesktopUpdateState;} export const DesktopUpdateActionResultSchema = Schema.Struct({ accepted: Schema.Boolean, completed: Schema.Boolean, state: DesktopUpdateStateSchema,}); export interface DesktopUpdateCheckResult { checked: boolean; state: DesktopUpdateState;} export const DesktopUpdateCheckResultSchema = Schema.Struct({ checked: Schema.Boolean, state: DesktopUpdateStateSchema,}); // Stable id for the Windows-native primary backend. Desktop side wraps// this with a brand inside DesktopBackendManager; web side keeps it as// a plain string so the env-runtime can compare against it without// importing brand machinery from the desktop package.export const PRIMARY_LOCAL_ENVIRONMENT_ID = "primary"; export interface DesktopEnvironmentBootstrap { // Stable backend instance id (e.g. "primary" or "wsl:ubuntu"). The // web env runtime keys local environments off this so projects // routed to a specific backend reopen against the same one. id: string; label: string; // Concrete WSL distro used by the current backend run. This stays separate // from id because a default-tracking instance keeps the stable // "wsl:default" IPC target while each run launches a specific distro. runningDistro?: string | null; httpBaseUrl: string | null; wsBaseUrl: string | null; bootstrapToken?: string;} export const DesktopEnvironmentBootstrapSchema = Schema.Struct({ id: Schema.String, label: Schema.String, runningDistro: Schema.optionalKey(Schema.NullOr(Schema.String)), httpBaseUrl: Schema.NullOr(Schema.String), wsBaseUrl: Schema.NullOr(Schema.String), bootstrapToken: Schema.optionalKey(Schema.String),}); export const DesktopSshEnvironmentTargetSchema = Schema.Struct({ alias: Schema.String, hostname: Schema.String, username: Schema.NullOr(Schema.String), port: Schema.NullOr(Schema.Number),});export type DesktopSshEnvironmentTarget = typeof DesktopSshEnvironmentTargetSchema.Type; export type DesktopSshHostSource = "ssh-config" | "known-hosts";export const DesktopSshHostSourceSchema = Schema.Literals(["ssh-config", "known-hosts"]); export interface DesktopDiscoveredSshHost extends DesktopSshEnvironmentTarget { source: DesktopSshHostSource;} export const DesktopDiscoveredSshHostSchema = Schema.Struct({ alias: Schema.String, hostname: Schema.String, username: Schema.NullOr(Schema.String), port: Schema.NullOr(Schema.Number), source: DesktopSshHostSourceSchema,}); export interface DesktopSshEnvironmentBootstrap { target: DesktopSshEnvironmentTarget; httpBaseUrl: string; wsBaseUrl: string; pairingToken: string | null; remotePort?: number; remoteServerKind?: "external" | "managed";} export const DesktopSshEnvironmentBootstrapSchema = Schema.Struct({ target: DesktopSshEnvironmentTargetSchema, httpBaseUrl: Schema.String, wsBaseUrl: Schema.String, pairingToken: Schema.NullOr(Schema.String), remotePort: Schema.optionalKey(Schema.Number), remoteServerKind: Schema.optionalKey(Schema.Literals(["external", "managed"])),}); export interface DesktopSshPasswordPromptRequest { requestId: string; destination: string; username: string | null; prompt: string; expiresAt: string;} export const DesktopSshPasswordPromptRequestSchema = Schema.Struct({ requestId: Schema.String, destination: Schema.String, username: Schema.NullOr(Schema.String), prompt: Schema.String, expiresAt: Schema.String,}); export const DesktopSshPasswordPromptCancelledType = "ssh-password-prompt-cancelled" as const; export const DesktopSshPasswordPromptCancelledResultSchema = Schema.Struct({ type: Schema.Literal(DesktopSshPasswordPromptCancelledType), message: Schema.String,}); export const DesktopSshEnvironmentEnsureOptionsSchema = Schema.Struct({ issuePairingToken: Schema.optionalKey(Schema.Boolean),}); export const DesktopSshEnvironmentEnsureInputSchema = Schema.Struct({ target: DesktopSshEnvironmentTargetSchema, options: Schema.optionalKey(DesktopSshEnvironmentEnsureOptionsSchema),}); export const DesktopSshEnvironmentEnsureResultSchema = Schema.Union([ DesktopSshEnvironmentBootstrapSchema, DesktopSshPasswordPromptCancelledResultSchema,]); export const DesktopSshHttpBaseUrlInputSchema = Schema.Struct({ httpBaseUrl: Schema.String,}); export const DesktopSshBearerRequestInputSchema = Schema.Struct({ httpBaseUrl: Schema.String, bearerToken: Schema.String,}); export const DesktopSshBearerBootstrapInputSchema = Schema.Struct({ httpBaseUrl: Schema.String, credential: Schema.String,}); export const DesktopSshPasswordPromptResolutionInputSchema = Schema.Struct({ requestId: Schema.String, password: Schema.NullOr(Schema.String),}); export const PersistedSavedEnvironmentRecordSchema = Schema.Struct({ environmentId: EnvironmentId, label: Schema.String, wsBaseUrl: Schema.String, httpBaseUrl: Schema.String, createdAt: Schema.String, lastConnectedAt: Schema.NullOr(Schema.String), desktopSsh: Schema.optionalKey(DesktopSshEnvironmentTargetSchema), relayManaged: Schema.optionalKey( Schema.Struct({ relayUrl: Schema.String, }), ),});export type PersistedSavedEnvironmentRecord = typeof PersistedSavedEnvironmentRecordSchema.Type; export type DesktopServerExposureMode = "local-only" | "network-accessible"; export const DesktopServerExposureModeSchema = Schema.Literals([ "local-only", "network-accessible",]); export interface DesktopServerExposureState { mode: DesktopServerExposureMode; endpointUrl: string | null; advertisedHost: string | null; tailscaleServeEnabled: boolean; tailscaleServePort: number;} export const DesktopServerExposureStateSchema = Schema.Struct({ mode: DesktopServerExposureModeSchema, endpointUrl: Schema.NullOr(Schema.String), advertisedHost: Schema.NullOr(Schema.String), tailscaleServeEnabled: Schema.Boolean, tailscaleServePort: Schema.Number,}); export interface PickFolderOptions { initialPath?: string | null; // When set, the desktop dialog opens against the named backend's // filesystem instead of the primary's. Used by callers that already // know which local environment they're targeting (e.g. opening a // project that lives inside WSL). Omitting it keeps the historical // behavior so non-WSL users never see a different picker. targetEnvironmentId?: string;} export const PickFolderOptionsSchema = Schema.Struct({ initialPath: Schema.optionalKey(Schema.NullOr(Schema.String)), targetEnvironmentId: Schema.optionalKey(Schema.String),}); export interface DesktopWslDistro { name: string; isDefault: boolean; version: 1 | 2;} export const DesktopWslDistroSchema = Schema.Struct({ name: Schema.String, isDefault: Schema.Boolean, version: Schema.Literals([1, 2]),}); export interface DesktopWslState { // True when the user has opted the WSL backend in; the actual backend // process is registered with the desktop pool independently of this // flag and may take a moment to come up after the user enables it. enabled: boolean; // null means "track the current WSL default distro". distro: string | null; available: boolean; // When true (and `enabled` is also true) the desktop runs only the // WSL backend as the primary; the Windows-side Node backend is not // started. Toggling this requires an app restart because the // primary backend's spec is captured once at layer init. wslOnly: boolean; distros: readonly DesktopWslDistro[]; // Reason the dual-mode WSL backend last failed preflight (no node, wrong // version, missing build tools), or null. Surfaced inline in Connections // settings. Always null in wsl-only mode — that path shows a dialog and // falls back to Windows instead. preflightError: string | null;} export const DesktopWslStateSchema = Schema.Struct({ enabled: Schema.Boolean, distro: Schema.NullOr(Schema.String), available: Schema.Boolean, wslOnly: Schema.Boolean, distros: Schema.Array(DesktopWslDistroSchema), preflightError: Schema.NullOr(Schema.String),}); /** * Renderer-facing snapshot of a desktop preview tab. Mirrors the main-process * PreviewTabState shape but uses serialisable primitives only. */Lines 1–500 of 1288. Load more
import type { VcsCreateRefInput, VcsCreateRefResult, VcsCreateWorktreeInput, VcsCreateWorktreeResult, VcsInitInput, VcsListRefsInput, VcsListRefsResult, VcsPullInput, VcsPullResult, VcsRemoveWorktreeInput, VcsSwitchRefInput, VcsSwitchRefResult, GitPreparePullRequestThreadInput, GitPreparePullRequestThreadResult, GitPullRequestRefInput, GitResolvePullRequestResult, VcsStatusInput, VcsStatusResult, } from "./git.ts"; import type { ReviewDiffPreviewInput, ReviewDiffPreviewResult } from "./review.ts"; import type { FilesystemBrowseInput, FilesystemBrowseResult } from "./filesystem.ts"; import type { AssetCreateUrlInput, AssetCreateUrlResult } from "./assets.ts"; import type { ProjectListEntriesInput, ProjectListEntriesResult, ProjectReadFileInput, ProjectReadFileResult, ProjectSearchEntriesInput, ProjectSearchEntriesResult, ProjectWriteFileInput, ProjectWriteFileResult, } from "./project.ts"; import type { ProviderInstanceId } from "./providerInstance.ts"; import type { ServerConfig, ServerProcessDiagnosticsResult, ServerProcessResourceHistoryInput, ServerProcessResourceHistoryResult, ServerProviderUpdateInput, ServerProviderUpdatedPayload, ServerRemoveKeybindingResult, ServerSignalProcessInput, ServerSignalProcessResult, ServerTraceDiagnosticsResult, ServerUpsertKeybindingResult, } from "./server.ts"; import type { TerminalAttachInput, TerminalAttachStreamEvent, TerminalClearInput, TerminalCloseInput, TerminalMetadataStreamEvent, TerminalOpenInput, TerminalResizeInput, TerminalRestartInput, TerminalSessionSnapshot, TerminalWriteInput, } from "./terminal.ts"; import type { ServerRemoveKeybindingInput, ServerUpsertKeybindingInput } from "./server.ts"; import * as Schema from "effect/Schema"; import type { DiscoveredLocalServerList, PreviewCloseInput, PreviewEvent, PreviewListInput, PreviewListResult, PreviewNavigateInput, PreviewOpenInput, PreviewRefreshInput, PreviewReportStatusInput, PreviewResizeInput, PreviewSessionSnapshot, } from "./preview.ts"; import { PreviewAutomationClickInput, PreviewAutomationEvaluateInput, PreviewAutomationHost, PreviewAutomationHostFocus, PreviewAutomationPressInput, PreviewAutomationResponse, PreviewAutomationScrollInput, PreviewAutomationSnapshot, PreviewAutomationStatus, PreviewAutomationStreamEvent, PreviewAutomationTypeInput, PreviewAutomationWaitForInput, } from "./previewAutomation.ts"; import type { ClientOrchestrationCommand, OrchestrationGetFullThreadDiffInput, OrchestrationGetFullThreadDiffResult, OrchestrationGetTurnDiffInput, OrchestrationGetTurnDiffResult, OrchestrationShellSnapshot, OrchestrationShellStreamItem, OrchestrationSubscribeThreadInput, OrchestrationThreadStreamItem, } from "./orchestration.ts"; import { EnvironmentId } from "./baseSchemas.ts"; import { AuthAccessTokenResult, AuthSessionState, AuthWebSocketTicketResult } from "./auth.ts"; import { AdvertisedEndpoint } from "./remoteAccess.ts"; import { EditorId } from "./editor.ts"; import { ExecutionEnvironmentDescriptor } from "./environment.ts"; import type { ClientSettings, ServerSettings, ServerSettingsPatch } from "./settings.ts"; import type { SourceControlCloneRepositoryInput, SourceControlCloneRepositoryResult, SourceControlDiscoveryResult, SourceControlPublishRepositoryInput, SourceControlPublishRepositoryResult, SourceControlRepositoryInfo, SourceControlRepositoryLookupInput, } from "./sourceControl.ts"; export interface ContextMenuItem<T extends string = string> { id: T; label: string; destructive?: boolean; disabled?: boolean; /** Renders as a non-interactive section header label. Web fallback only — stripped on desktop native menus. */ header?: boolean; /** Icon keyword resolved by the web fallback. Stripped on desktop native menus. */ icon?: string; children?: readonly ContextMenuItem<T>[]; } export interface ContextMenuItemSchemaType { readonly id: string; readonly label: string; readonly destructive?: boolean; readonly disabled?: boolean; readonly header?: boolean; readonly icon?: string; readonly children?: readonly ContextMenuItemSchemaType[]; } export const ContextMenuItemSchema: Schema.Codec<ContextMenuItemSchemaType> = Schema.Struct({ id: Schema.String, label: Schema.String, destructive: Schema.optionalKey(Schema.Boolean), disabled: Schema.optionalKey(Schema.Boolean), header: Schema.optionalKey(Schema.Boolean), icon: Schema.optionalKey(Schema.String), children: Schema.optionalKey( Schema.Array( Schema.suspend((): Schema.Codec<ContextMenuItemSchemaType> => ContextMenuItemSchema), ), ), }); 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 type DesktopUpdateChannel = "latest" | "nightly"; export type DesktopAppStageLabel = "Alpha" | "Dev" | "Nightly"; export const DesktopUpdateStatusSchema = Schema.Literals([ "disabled", "idle", "checking", "up-to-date", "available", "downloading", "downloaded", "error", ]); export const DesktopRuntimeArchSchema = Schema.Literals(["arm64", "x64", "other"]); export const DesktopThemeSchema = Schema.Literals(["light", "dark", "system"]); export const DesktopUpdateChannelSchema = Schema.Literals(["latest", "nightly"]); export const DesktopAppStageLabelSchema = Schema.Literals(["Alpha", "Dev", "Nightly"]); export interface DesktopAppBranding { baseName: string; stageLabel: DesktopAppStageLabel; displayName: string; } export const DesktopAppBrandingSchema = Schema.Struct({ baseName: Schema.String, stageLabel: DesktopAppStageLabelSchema, displayName: Schema.String, }); export interface DesktopRuntimeInfo { hostArch: DesktopRuntimeArch; appArch: DesktopRuntimeArch; runningUnderArm64Translation: boolean; } export const DesktopRuntimeInfoSchema = Schema.Struct({ hostArch: DesktopRuntimeArchSchema, appArch: DesktopRuntimeArchSchema, runningUnderArm64Translation: Schema.Boolean, }); export interface DesktopUpdateState { enabled: boolean; status: DesktopUpdateStatus; channel: DesktopUpdateChannel; currentVersion: string; hostArch: DesktopRuntimeArch; appArch: DesktopRuntimeArch; runningUnderArm64Translation: boolean; availableVersion: string | null; downloadedVersion: string | null; releaseNotes: ReadonlyArray<DesktopUpdateReleaseNote>; downloadPercent: number | null; checkedAt: string | null; message: string | null; errorContext: "check" | "download" | "install" | null; canRetry: boolean; } export interface DesktopUpdateReleaseNote { version: string; items: ReadonlyArray<string>; } export const DesktopUpdateReleaseNoteSchema = Schema.Struct({ version: Schema.String, items: Schema.Array(Schema.String), }); export const DesktopUpdateStateSchema = Schema.Struct({ enabled: Schema.Boolean, status: DesktopUpdateStatusSchema, channel: DesktopUpdateChannelSchema, currentVersion: Schema.String, hostArch: DesktopRuntimeArchSchema, appArch: DesktopRuntimeArchSchema, runningUnderArm64Translation: Schema.Boolean, availableVersion: Schema.NullOr(Schema.String), downloadedVersion: Schema.NullOr(Schema.String), releaseNotes: Schema.Array(DesktopUpdateReleaseNoteSchema), downloadPercent: Schema.NullOr(Schema.Number), checkedAt: Schema.NullOr(Schema.String), message: Schema.NullOr(Schema.String), errorContext: Schema.NullOr(Schema.Literals(["check", "download", "install"])), canRetry: Schema.Boolean, }); export interface DesktopUpdateActionResult { accepted: boolean; completed: boolean; state: DesktopUpdateState; } export const DesktopUpdateActionResultSchema = Schema.Struct({ accepted: Schema.Boolean, completed: Schema.Boolean, state: DesktopUpdateStateSchema, }); export interface DesktopUpdateCheckResult { checked: boolean; state: DesktopUpdateState; } export const DesktopUpdateCheckResultSchema = Schema.Struct({ checked: Schema.Boolean, state: DesktopUpdateStateSchema, }); // Stable id for the Windows-native primary backend. Desktop side wraps // this with a brand inside DesktopBackendManager; web side keeps it as // a plain string so the env-runtime can compare against it without // importing brand machinery from the desktop package. export const PRIMARY_LOCAL_ENVIRONMENT_ID = "primary"; export interface DesktopEnvironmentBootstrap { // Stable backend instance id (e.g. "primary" or "wsl:ubuntu"). The // web env runtime keys local environments off this so projects // routed to a specific backend reopen against the same one. id: string; label: string; // Concrete WSL distro used by the current backend run. This stays separate // from id because a default-tracking instance keeps the stable // "wsl:default" IPC target while each run launches a specific distro. runningDistro?: string | null; httpBaseUrl: string | null; wsBaseUrl: string | null; bootstrapToken?: string; } export const DesktopEnvironmentBootstrapSchema = Schema.Struct({ id: Schema.String, label: Schema.String, runningDistro: Schema.optionalKey(Schema.NullOr(Schema.String)), httpBaseUrl: Schema.NullOr(Schema.String), wsBaseUrl: Schema.NullOr(Schema.String), bootstrapToken: Schema.optionalKey(Schema.String), }); export const DesktopSshEnvironmentTargetSchema = Schema.Struct({ alias: Schema.String, hostname: Schema.String, username: Schema.NullOr(Schema.String), port: Schema.NullOr(Schema.Number), }); export type DesktopSshEnvironmentTarget = typeof DesktopSshEnvironmentTargetSchema.Type; export type DesktopSshHostSource = "ssh-config" | "known-hosts"; export const DesktopSshHostSourceSchema = Schema.Literals(["ssh-config", "known-hosts"]); export interface DesktopDiscoveredSshHost extends DesktopSshEnvironmentTarget { source: DesktopSshHostSource; } export const DesktopDiscoveredSshHostSchema = Schema.Struct({ alias: Schema.String, hostname: Schema.String, username: Schema.NullOr(Schema.String), port: Schema.NullOr(Schema.Number), source: DesktopSshHostSourceSchema, }); export interface DesktopSshEnvironmentBootstrap { target: DesktopSshEnvironmentTarget; httpBaseUrl: string; wsBaseUrl: string; pairingToken: string | null; remotePort?: number; remoteServerKind?: "external" | "managed"; } export const DesktopSshEnvironmentBootstrapSchema = Schema.Struct({ target: DesktopSshEnvironmentTargetSchema, httpBaseUrl: Schema.String, wsBaseUrl: Schema.String, pairingToken: Schema.NullOr(Schema.String), remotePort: Schema.optionalKey(Schema.Number), remoteServerKind: Schema.optionalKey(Schema.Literals(["external", "managed"])), }); export interface DesktopSshPasswordPromptRequest { requestId: string; destination: string; username: string | null; prompt: string; expiresAt: string; } export const DesktopSshPasswordPromptRequestSchema = Schema.Struct({ requestId: Schema.String, destination: Schema.String, username: Schema.NullOr(Schema.String), prompt: Schema.String, expiresAt: Schema.String, }); export const DesktopSshPasswordPromptCancelledType = "ssh-password-prompt-cancelled" as const; export const DesktopSshPasswordPromptCancelledResultSchema = Schema.Struct({ type: Schema.Literal(DesktopSshPasswordPromptCancelledType), message: Schema.String, }); export const DesktopSshEnvironmentEnsureOptionsSchema = Schema.Struct({ issuePairingToken: Schema.optionalKey(Schema.Boolean), }); export const DesktopSshEnvironmentEnsureInputSchema = Schema.Struct({ target: DesktopSshEnvironmentTargetSchema, options: Schema.optionalKey(DesktopSshEnvironmentEnsureOptionsSchema), }); export const DesktopSshEnvironmentEnsureResultSchema = Schema.Union([ DesktopSshEnvironmentBootstrapSchema, DesktopSshPasswordPromptCancelledResultSchema, ]); export const DesktopSshHttpBaseUrlInputSchema = Schema.Struct({ httpBaseUrl: Schema.String, }); export const DesktopSshBearerRequestInputSchema = Schema.Struct({ httpBaseUrl: Schema.String, bearerToken: Schema.String, }); export const DesktopSshBearerBootstrapInputSchema = Schema.Struct({ httpBaseUrl: Schema.String, credential: Schema.String, }); export const DesktopSshPasswordPromptResolutionInputSchema = Schema.Struct({ requestId: Schema.String, password: Schema.NullOr(Schema.String), }); export const PersistedSavedEnvironmentRecordSchema = Schema.Struct({ environmentId: EnvironmentId, label: Schema.String, wsBaseUrl: Schema.String, httpBaseUrl: Schema.String, createdAt: Schema.String, lastConnectedAt: Schema.NullOr(Schema.String), desktopSsh: Schema.optionalKey(DesktopSshEnvironmentTargetSchema), relayManaged: Schema.optionalKey( Schema.Struct({ relayUrl: Schema.String, }), ), }); export type PersistedSavedEnvironmentRecord = typeof PersistedSavedEnvironmentRecordSchema.Type; export type DesktopServerExposureMode = "local-only" | "network-accessible"; export const DesktopServerExposureModeSchema = Schema.Literals([ "local-only", "network-accessible", ]); export interface DesktopServerExposureState { mode: DesktopServerExposureMode; endpointUrl: string | null; advertisedHost: string | null; tailscaleServeEnabled: boolean; tailscaleServePort: number; } export const DesktopServerExposureStateSchema = Schema.Struct({ mode: DesktopServerExposureModeSchema, endpointUrl: Schema.NullOr(Schema.String), advertisedHost: Schema.NullOr(Schema.String), tailscaleServeEnabled: Schema.Boolean, tailscaleServePort: Schema.Number, }); export interface PickFolderOptions { initialPath?: string | null; // When set, the desktop dialog opens against the named backend's // filesystem instead of the primary's. Used by callers that already // know which local environment they're targeting (e.g. opening a // project that lives inside WSL). Omitting it keeps the historical // behavior so non-WSL users never see a different picker. targetEnvironmentId?: string; } export const PickFolderOptionsSchema = Schema.Struct({ initialPath: Schema.optionalKey(Schema.NullOr(Schema.String)), targetEnvironmentId: Schema.optionalKey(Schema.String), }); export interface DesktopWslDistro { name: string; isDefault: boolean; version: 1 | 2; } export const DesktopWslDistroSchema = Schema.Struct({ name: Schema.String, isDefault: Schema.Boolean, version: Schema.Literals([1, 2]), }); export interface DesktopWslState { // True when the user has opted the WSL backend in; the actual backend // process is registered with the desktop pool independently of this // flag and may take a moment to come up after the user enables it. enabled: boolean; // null means "track the current WSL default distro". distro: string | null; available: boolean; // When true (and `enabled` is also true) the desktop runs only the // WSL backend as the primary; the Windows-side Node backend is not // started. Toggling this requires an app restart because the // primary backend's spec is captured once at layer init. wslOnly: boolean; distros: readonly DesktopWslDistro[]; // Reason the dual-mode WSL backend last failed preflight (no node, wrong // version, missing build tools), or null. Surfaced inline in Connections // settings. Always null in wsl-only mode — that path shows a dialog and // falls back to Windows instead. preflightError: string | null; } export const DesktopWslStateSchema = Schema.Struct({ enabled: Schema.Boolean, distro: Schema.NullOr(Schema.String), available: Schema.Boolean, wslOnly: Schema.Boolean, distros: Schema.Array(DesktopWslDistroSchema), preflightError: Schema.NullOr(Schema.String), }); /** * Renderer-facing snapshot of a desktop preview tab. Mirrors the main-process * PreviewTabState shape but uses serialisable primitives only. */