Files
orca/src/shared/hosted-sandbox/cloud-workspace-api.ts
T
Neil ce321f0bb5 feat(open-external): Copy link split button on every sign-in, account, billing and GitHub browser hop
Every button that opens a URL in the external browser gets a chevron with
"Copy link" that copies the exact URL (minted the same way for lazy links),
for incognito windows or another browser profile.
2026-11-12 17:36:32 -08:00

154 lines
6.8 KiB
TypeScript

// Window ↔ main contract for Orca Cloud workspace lifecycle surfaces: status panel, Restart,
// archive/unarchive, wake progress, OOM notices. Keyed by the renderer's workspace (worktree) id;
// main maps it to the Orca Cloud runtime record and its sandbox.
import type {
HostedArchivePullRequest,
HostedArchiveResponse,
HostedSandboxConfigResponse,
HostedWorkspaceStatus
} from './hosted-sandbox-wire'
import type {
HostedGithubRepoAccessResponse,
HostedGithubRepositoriesResponse,
HostedGithubUser
} from './hosted-github-wire'
export type CloudWorkspaceErrorCode =
| 'not_cloud'
| 'unauthorized'
| 'entitlement_denied'
| 'conflict'
| 'unavailable'
| 'not_found'
| 'failed'
export type CloudWorkspaceResult<T> =
| { ok: true; value: T }
| {
ok: false
code: CloudWorkspaceErrorCode
message: string
reason?: string | null
/** Copy written for people (renderer-authored); shown as is. `message` may be raw. */
userMessage?: string
}
/** Why a wake started; every source goes through the control plane's single-flight wake. */
export type CloudWakeSource = 'open' | 'message' | 'ssh' | 'preview' | 'restart' | 'unarchive'
export type CloudWakeProgressEvent = {
workspaceId: string
phase: 'waking' | 'connecting' | 'ready' | 'failed'
source: CloudWakeSource
/** Epoch ms the wake began (the overlay's elapsed timer). */
startedAt: number
at: number
message?: string
}
export type CloudOomEvent = {
workspaceId: string
/** Kernel OOM-kill counter after this notice (monotonic per VM boot). */
oomKills: number
victim: string | null
at: number
}
/** The status panel's read plus what the desktop needs from the sandbox view alongside it. */
export type CloudWorkspaceStatus = HostedWorkspaceStatus & {
/** GIT-SETUP: commits and pushes are refused in the VM until a boot installs the identities. */
gitSetupFailed?: true
}
export type CloudArchiveInfo = NonNullable<HostedArchiveResponse['archive']>
/** A cloud workspace by its sidebar id; a paired one also names its server's environment. */
export type CloudWorkspaceTarget = { workspaceId: string; environmentId?: string }
export type OrcaCloudWorkspaceApi = {
/**
* Live status: state, CPU/mem/disk, uptime, cost so far, archive. Cheap; the panel polls it while open.
* `environmentId` names a PAIRED workspace's server (no runtime record on this desktop): main
* answers for it only when that server is bound to a cloud sandbox.
*/
getStatus: (args: CloudWorkspaceTarget) => Promise<CloudWorkspaceResult<CloudWorkspaceStatus>>
/** "Restart" (Unresponsive / OOM): rehydrate the same disk and re-pair; agents auto-resume. */
restart: (args: { workspaceId: string }) => Promise<CloudWorkspaceResult<null>>
/** Sleep, then archive with a snapshot TTL; metadata captured in the VM or from the client cache. */
archive: (args: {
workspaceId: string
pullRequests?: HostedArchivePullRequest[]
}) => Promise<CloudWorkspaceResult<null>>
unarchive: (args: { workspaceId: string }) => Promise<CloudWorkspaceResult<null>>
getArchive: (args: CloudWorkspaceTarget) => Promise<CloudWorkspaceResult<CloudArchiveInfo | null>>
/** Workspace ids of every Orca Cloud workspace this desktop knows (the sidebar dot / hover card). */
listCloudWorkspaceIds: () => Promise<string[]>
/** Product constants and measured timings; null when the control plane can't be reached. */
getConfig: () => Promise<HostedSandboxConfigResponse | null>
/**
* Opens GitHub in the browser to give Orca Cloud access to the account's repositories. With a
* repository, GitHub's page preselects it, and a setup session gets the browser back afterwards.
*/
connectGitHub: (args?: {
repoUrl?: string
setupSessionId?: string
}) => Promise<CloudWorkspaceResult<null>>
/** "Copy link" for connectGitHub: the same single-use GitHub install page, minted but not opened. */
gitHubInstallLink: (args?: {
repoUrl?: string
setupSessionId?: string
}) => Promise<CloudWorkspaceResult<string>>
/** Whether the signed-in person connected their own GitHub (cloud commit attribution). */
getGitHubUser: () => Promise<CloudWorkspaceResult<HostedGithubUser>>
/** Opens GitHub's OAuth page in the browser so the person connects their own GitHub identity. */
connectGitHubUser: () => Promise<CloudWorkspaceResult<null>>
/** "Copy link" for connectGitHubUser: the same GitHub OAuth page, minted but not opened. */
gitHubUserConnectLink: () => Promise<CloudWorkspaceResult<string>>
/** Forgets the person's GitHub identity; cloud commits use Orca Cloud's name again. */
disconnectGitHubUser: () => Promise<CloudWorkspaceResult<HostedGithubUser>>
/** Can Orca Cloud clone this https GitHub repository for the signed-in account (cloud-start N2)? */
getRepoAccess: (args: {
repoUrl: string
setupSessionId?: string
}) => Promise<CloudWorkspaceResult<HostedGithubRepoAccessResponse>>
/** One page of the repositories the account's GitHub installations reach (cloud-start N12). */
listGitHubRepositories: (args: {
cursor?: string | null
}) => Promise<CloudWorkspaceResult<HostedGithubRepositoriesResponse>>
/**
* Starts a sandbox that clones a GitHub repository with no copy on this computer (cloud-start
* D4). Resolves once it is ready; the window then opens it like any cloud workspace.
*/
createFromGitHub: (args: {
repoUrl: string
/** The name typed in the composer; becomes the workspace's title (NAME-DROPPED). */
title?: string
}) => Promise<CloudWorkspaceResult<{ sandboxId: string }>>
onWakeProgress: (callback: (event: CloudWakeProgressEvent) => void) => () => void
onOom: (callback: (event: CloudOomEvent) => void) => () => void
}
export const ORCA_CLOUD_WORKSPACE_CHANNELS = {
getStatus: 'orcaCloudWorkspace:getStatus',
restart: 'orcaCloudWorkspace:restart',
archive: 'orcaCloudWorkspace:archive',
unarchive: 'orcaCloudWorkspace:unarchive',
getArchive: 'orcaCloudWorkspace:getArchive',
listCloudWorkspaceIds: 'orcaCloudWorkspace:listIds',
getConfig: 'orcaCloudWorkspace:getConfig',
connectGitHub: 'orcaCloudWorkspace:connectGitHub',
gitHubInstallLink: 'orcaCloudWorkspace:gitHubInstallLink',
getGitHubUser: 'orcaCloudWorkspace:getGitHubUser',
connectGitHubUser: 'orcaCloudWorkspace:connectGitHubUser',
gitHubUserConnectLink: 'orcaCloudWorkspace:gitHubUserConnectLink',
disconnectGitHubUser: 'orcaCloudWorkspace:disconnectGitHubUser',
getRepoAccess: 'orcaCloudWorkspace:getRepoAccess',
listGitHubRepositories: 'orcaCloudWorkspace:listGitHubRepositories',
createFromGitHub: 'orcaCloudWorkspace:createFromGitHub',
wakeProgress: 'orcaCloudWorkspace:wakeProgress',
oom: 'orcaCloudWorkspace:oom'
} as const
/** Thrown by the desktop wake path for an archived Orca Cloud workspace: only Unarchive wakes it. */
export const CLOUD_WORKSPACE_ARCHIVED_ERROR = 'orca_cloud_workspace_archived'