import { createSimpleContext } from "@opencode-ai/ui/context" import type { AsyncStorage, SyncStorage } from "@solid-primitives/storage" import type { Accessor } from "solid-js" import { ServerConnection } from "./server" type PickerPaths = string | string[] | null type OpenDirectoryPickerOptions = { title?: string; multiple?: boolean } type OpenFilePickerOptions = { title?: string; multiple?: boolean; accept?: string[]; extensions?: string[] } type SaveFilePickerOptions = { title?: string; defaultPath?: string } type UpdateInfo = { updateAvailable: boolean; version?: string } export type LocalServerMode = "windows" | "wsl" export type LocalServerStep = "wsl" | "distro" | "opencode" | "switch" export type LocalServerMismatchAcknowledgement = { path: string version: string } export type LocalServerWslCheck = { available: boolean version: string | null status: string | null error: string | null } export type LocalServerInstalledDistro = { name: string state: string | null version: number | null isDefault: boolean } export type LocalServerOnlineDistro = { name: string label: string } export type LocalServerDistroProbe = { name: string canExecute: boolean hasBash: boolean hasCurl: boolean username: string | null isRoot: boolean | null error: string | null } export type LocalServerDistroCheck = { installed: LocalServerInstalledDistro[] online: LocalServerOnlineDistro[] selected: LocalServerDistroProbe | null error: string | null } export type LocalServerOpencodeCheck = { distro: string | null resolvedPath: string | null version: string | null expectedVersion: string | null matchesDesktop: boolean | null error: string | null } export type LocalServerTranscriptLine = { stream: "stdout" | "stderr" | "system" text: string at: number } export type LocalServerConfig = { mode: LocalServerMode distro: string | null onboarding: { step: LocalServerStep | null complete: boolean pendingRestart: boolean } acknowledgements: { root: string[] mismatch: LocalServerMismatchAcknowledgement[] } } export type LocalServerStatus = | { kind: "idle" } | { kind: "ready" } | { kind: "running"; step: LocalServerStep | null } | { kind: "failed"; step: LocalServerStep | null; message: string } export type LocalServerState = { config: LocalServerConfig runtime: { key: string mode: LocalServerMode distro: string | null } status: LocalServerStatus job: { step: LocalServerStep | null; startedAt: number } | null checks: { wsl: LocalServerWslCheck | null distro: LocalServerDistroCheck | null opencode: LocalServerOpencodeCheck | null } transcript: LocalServerTranscriptLine[] } export type LocalServerEvent = { type: "state" state: LocalServerState } export type LocalServerPlatform = { getState(): Promise setConfig(config: LocalServerConfig): Promise runStep(step: LocalServerStep): Promise cancelJob(): Promise installWsl(): Promise installDistro(name: string): Promise installOpencode(): Promise openTerminal(): Promise subscribe(cb: (event: LocalServerEvent) => void): () => void } export type Platform = { /** Platform discriminator */ platform: "web" | "desktop" /** Desktop OS (Tauri only) */ os?: "macos" | "windows" | "linux" /** App version */ version?: string /** Open a URL in the default browser */ openLink(url: string): void /** Open a local path in a local app (desktop only) */ openPath?(path: string, app?: string): Promise /** Restart the app */ restart(): Promise /** Navigate back in history */ back(): void /** Navigate forward in history */ forward(): void /** Send a system notification (optional deep link) */ notify(title: string, description?: string, href?: string): Promise /** Open directory picker dialog (native on Tauri, server-backed on web) */ openDirectoryPickerDialog?(opts?: OpenDirectoryPickerOptions): Promise /** Open native file picker dialog (Tauri only) */ openFilePickerDialog?(opts?: OpenFilePickerOptions): Promise /** Save file picker dialog (Tauri only) */ saveFilePickerDialog?(opts?: SaveFilePickerOptions): Promise /** Storage mechanism, defaults to localStorage */ storage?: (name?: string) => SyncStorage | AsyncStorage /** Check for updates (Tauri only) */ checkUpdate?(): Promise /** Install updates (Tauri only) */ update?(): Promise /** Fetch override */ fetch?: typeof fetch /** Get the configured default server URL (platform-specific) */ getDefaultServer?(): Promise /** Set the default server URL to use on app startup (platform-specific) */ setDefaultServer?(url: ServerConnection.Key | null): Promise | void /** Manage the desktop Local Server lifecycle (desktop only) */ localServer?: LocalServerPlatform /** Get the configured WSL integration (desktop only) */ getWslEnabled?(): Promise /** Set the configured WSL integration (desktop only) */ setWslEnabled?(config: boolean): Promise | void /** Get the preferred display backend (desktop only) */ getDisplayBackend?(): Promise | DisplayBackend | null /** Set the preferred display backend (desktop only) */ setDisplayBackend?(backend: DisplayBackend): Promise /** Parse markdown to HTML using native parser (desktop only, returns unprocessed code blocks) */ parseMarkdown?(markdown: string): Promise /** Webview zoom level (desktop only) */ webviewZoom?: Accessor /** Check if an editor app exists (desktop only) */ checkAppExists?(appName: string): Promise /** Read image from clipboard (desktop only) */ readClipboardImage?(): Promise } export type DisplayBackend = "auto" | "wayland" export const { use: usePlatform, provider: PlatformProvider } = createSimpleContext({ name: "Platform", init: (props: { value: Platform }) => { return props.value }, })