deepspace 0.26.2 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/lib/repo-api.ts","../src/cli/lib/cli-format.ts","../src/cli/lib/fetch-retry.ts","../src/cli/lib/api.ts","../src/cli/lib/workspace-id.ts","../src/cli/lib/command.ts","../src/cli/lib/spinner.ts","../src/cli/lib/output.ts","../src/cli/lib/cli-errors.ts","../src/cli/lib/source-api.ts"],"sourcesContent":["/**\n * Typed client for the deploy-worker's /api/repo JSON surface — the DeepSpace\n * layer on top of the git remote: refs for scripting, workspaces, the activity\n * feed, and the release history. Object transfer itself never goes through\n * here; that's real git against the smart-HTTP endpoint (lib/vc-remote.ts).\n *\n * Idempotency: `createWorkspace` carries a client-minted key, so a retried\n * create replays the recorded outcome instead of double-writing. sync, land\n * and drop are idempotent by CONSTRUCTION instead — each is a state\n * transition whose replay is a no-op (same tip, already-landed, already-\n * dropped all return the current view) — so they send no key.\n */\n\nimport { randomUUID } from 'node:crypto'\nimport { apiFetch, ApiError } from './api'\nimport { displayText } from './cli-format'\nimport { isWorkspaceId } from './workspace-id'\nimport { githubSourceRefusal } from './source-api'\n\n/** The ref the server owns for a workspace: the prefix plus the workspace id\n * (`vc/do/workspaces.ts` composes exactly this). */\nfunction isWorkspaceRef(ref: string): boolean {\n const prefix = 'refs/deepspace/ws/'\n return ref.startsWith(prefix) && isWorkspaceId(ref.slice(prefix.length))\n}\n\nexport interface RemoteRef {\n name: string\n oid: string\n updatedAt: string\n updatedBy: string\n}\n\nexport interface RemoteRefsResult {\n refs: RemoteRef[]\n head: string | null\n}\n\nexport interface RemoteRelease {\n id: string\n seq: number\n commitOid: string | null\n cfVersionId: string | null\n rollbackAvailable: boolean\n config: unknown\n actor: string\n url: string | null\n kind: 'deploy' | 'rollback'\n createdAt: string\n source: { provider: 'deepspace' } | { provider: 'github'; repository: string } | null\n sourceRevision: number | null\n /** Whether the shipped working tree carried uncommitted changes; absent or\n * null when unknown (older server, or no repository to ask). */\n sourceDirty?: boolean | null\n}\n\n/**\n * How a release names the code it shipped, on the HUMAN surfaces —\n * `releases`, `status`'s Live line, and `activity`. A GitHub-source release\n * records no commit at all (deploy ships the working tree without touching\n * Git), so those three each rendered `commitOid === null` as \"no source\n * recorded\" / \"unknown source\" / \"?\" — directly contradicting the `source` the\n * same release carries in `--json` and the `Source` line printed above it.\n * One formatter so the three cannot disagree about one release again.\n */\nexport function releaseSourceLabel(release: {\n commitOid: string | null\n source: RemoteRelease['source']\n sourceDirty?: boolean | null\n}): string {\n // The dirty flag is the ledger's only trace of what a release actually\n // shipped beyond its label — without it a dirty deploy and a clean one read\n // identically, and a rollback picks between them blind. A commit-bearing\n // dirty release is the `--no-push` case: the recorded commit is NOT what\n // shipped, and saying so is the whole point.\n const dirty = release.sourceDirty === true ? ' (dirty worktree)' : ''\n if (release.commitOid) return `commit ${release.commitOid.slice(0, 10)}${dirty}`\n if (release.source?.provider === 'github') {\n return `GitHub · ${release.source.repository}${dirty ? ', dirty worktree' : ''}`\n }\n if (release.source?.provider === 'deepspace') {\n return `DeepSpace source, no commit recorded${dirty}`\n }\n return `no source recorded${dirty}`\n}\n\nexport interface RemoteWorkspace {\n id: string\n task: string\n baseOid: string\n ref: string\n status: 'active' | 'landed' | 'dropped'\n createdBy: string\n createdAt: string\n updatedAt: string\n landedOid: string | null\n}\n\nexport interface RemoteCommitCount {\n count: number\n capped: boolean\n}\n\n/** Commit-graph facts the repo DO owns. Path-level coordination (which other\n * workspaces touch the same files) is computed client-side from local diffs —\n * see `workspace.ts`. */\nexport interface RemoteWorkspaceView {\n workspace: RemoteWorkspace\n tipOid: string | null\n aheadOfBase: RemoteCommitCount | null\n behindTrunk: RemoteCommitCount | null\n}\n\nexport interface RemoteActivityEvent {\n seq: number\n kind: string\n subjectId: string | null\n summary: unknown\n actor: string\n createdAt: string\n}\n\nexport function mintIdempotencyKey(): string {\n return randomUUID()\n}\n\n/**\n * Resolve a live subdomain name to its app id via the deploy worker's\n * access-gated resolver (`GET /api/repo/resolve-name/:name`). Unlike the\n * owner-only `/api/apps` list, this also finds apps the caller merely\n * COLLABORATES on. Returns null when the name is unknown, malformed, or the\n * caller has no access — the server deliberately doesn't distinguish the\n * first from the last (no existence oracle).\n */\nexport async function resolveAppIdByName(\n deployUrl: string,\n token: string,\n name: string,\n): Promise<string | null> {\n try {\n const { appId } = await apiFetch<{ appId: string }>(\n deployUrl,\n token,\n `/api/repo/resolve-name/${encodeURIComponent(name)}`,\n )\n return appId ?? null\n } catch (err) {\n if (err instanceof ApiError && (err.status === 404 || err.status === 400)) return null\n throw err\n }\n}\n\nexport function repoApi(deployUrl: string, token: string, appId: string) {\n const base = `/api/repo/${encodeURIComponent(appId)}`\n const call = async <T>(path: string, init?: RequestInit): Promise<T> => {\n // The bare-404 \"wrong/old service\" case (→ unrecognized_service) is handled\n // uniformly in apiFetch now, for every caller incl. rollback's direct endpoint.\n return await apiFetch<T>(deployUrl, token, `${base}${path}`, init)\n }\n const post = <T>(path: string, body: unknown) =>\n call<T>(path, { method: 'POST', body: JSON.stringify(body) })\n\n // A well-formed repo-API 2xx body carries the endpoint's documented fields with\n // the right shape. A wrong/broken service can answer 200 with `{}` (or an empty\n // body, which apiFetch reads as `{}`), a null-valued field, or the wrong type;\n // left unchecked those destructure to `undefined`/`null` downstream and surface\n // as a false `ok:true` or an uncoded `reading '…' of null|undefined` crash. Code\n // such a body as invalid_response — the same slug apiFetch uses for a\n // null/array/non-JSON 2xx. This enforces every SCHEMA-FREE degeneracy check —\n // present, correct JSON type, non-null, arrays carry no null entries, objects\n // are non-empty — and stops exactly where a check would need the per-endpoint\n // field schema (a populated-but-wrong-fielded entity like `{view:{wrong:1}}` or\n // `[{}]` is left to the caller's TS types + happy-path tests, NOT re-validated\n // here). Kinds: `array` (a list, never null, no null entries), `object` (a\n // non-empty, non-null, non-array object — a real entity is never `{}`, and no\n // top-level field is a legitimately-empty map; do NOT tag such a field `object`\n // if one is ever added), `present` (key exists; value may be null — e.g. a\n // nullable ref like getRefs' `head`).\n const KIND = {\n array: (v: unknown) => Array.isArray(v) && v.every((e) => e !== null),\n object: (v: unknown) =>\n v !== null && typeof v === 'object' && !Array.isArray(v) && Object.keys(v).length > 0,\n present: (v: unknown) => v !== undefined,\n }\n type Kind = keyof typeof KIND\n const shapeError = (path: string) =>\n new ApiError(\n `The deploy service at ${deployUrl} returned an unexpected response shape — check DEEPSPACE_DEPLOY_URL (is this the service the app lives on?).`,\n 200,\n 'invalid_response',\n `${base}${path}`,\n )\n // Each `spec` key must name a documented top-level field of the response (a\n // typo'd key rejects every valid 2xx as invalid_response — fail-loud, caught by\n // the per-endpoint happy-path tests). Keys stay strings (not `keyof T`) so T\n // still infers from each method's return annotation rather than from the spec.\n /**\n * The ONE seam where a server workspace becomes CLI data.\n *\n * `task` is peer-authored prose: one agent writes it, every other seat's\n * `workspace list`/`attach`/`status` prints it. Escaping it here rather than\n * at each print site is what makes the rule hold — the print sites are\n * spread across six files and the next one added would be raw again.\n *\n * `ref` goes straight into git argv and into emitted `action.argv`, so it is\n * validated rather than escaped: a server that answers with anything but the\n * ref shape it owns is a broken service, not a rendering problem.\n */\n const normalizeWorkspace = (view: unknown, path: string): void => {\n if (view === null || typeof view !== 'object') return\n const workspace = (view as { workspace?: unknown }).workspace\n if (workspace === null || typeof workspace !== 'object') return\n const fields = workspace as Record<string, unknown>\n if (typeof fields.ref !== 'string' || !isWorkspaceRef(fields.ref)) throw shapeError(path)\n if (typeof fields.task === 'string') fields.task = displayText(fields.task)\n }\n const assertShape = <T>(r: T, spec: Record<string, Kind>, path: string): T => {\n if (r === null || typeof r !== 'object') throw shapeError(path)\n const obj = r as Record<string, unknown>\n for (const [key, kind] of Object.entries(spec)) {\n if (!KIND[kind](obj[key])) throw shapeError(path)\n }\n // Every workspace endpoint answers `{view}` or `{views}`; both funnel here.\n normalizeWorkspace(obj.view, path)\n if (Array.isArray(obj.views)) for (const view of obj.views) normalizeWorkspace(view, path)\n return r\n }\n const getShape = async <T>(path: string, spec: Record<string, Kind>): Promise<T> =>\n assertShape(await call<T>(path), spec, path)\n const postShape = async <T>(\n path: string,\n body: unknown,\n spec: Record<string, Kind>,\n ): Promise<T> => assertShape(await post<T>(path, body), spec, path)\n\n return {\n /** null ⇒ the app has never been registered (fresh repo, no history). */\n async getRefs(): Promise<RemoteRefsResult | null> {\n try {\n return await getShape<RemoteRefsResult>('/refs', { refs: 'array', head: 'present' })\n } catch (err) {\n if (err instanceof ApiError && err.code === 'app_not_found') return null\n // The cloud-repo read every source verb starts with, so this is where\n // `pull`/`clone`/`workspace` all meet a GitHub-source app — translate\n // once, into the same refusal `push` raises from its own /source read.\n if (err instanceof ApiError && err.code === 'source_managed_by_github') {\n const repository = err.details?.repository\n if (typeof repository === 'string') throw githubSourceRefusal(appId, repository)\n }\n throw err\n }\n },\n\n createWorkspace(args: {\n workspaceId: string\n task: string\n baseOid: string\n idempotencyKey: string\n }): Promise<{ view: RemoteWorkspaceView }> {\n return postShape('/workspaces', args, { view: 'object' })\n },\n\n /** `truncated` ⇒ the server had more rows than `limit` and stopped. Without\n * it a capped page is indistinguishable from the whole set, so a caller\n * reading \"3 workspaces\" cannot tell that a fourth exists. */\n listWorkspaces(opts?: {\n all?: boolean\n limit?: number\n }): Promise<{ views: RemoteWorkspaceView[]; truncated?: boolean }> {\n const params = new URLSearchParams()\n if (opts?.all) params.set('all', '1')\n if (opts?.limit) params.set('limit', String(opts.limit))\n const qs = params.toString()\n return getShape(`/workspaces${qs ? `?${qs}` : ''}`, { views: 'array' })\n },\n\n getWorkspace(id: string): Promise<{ view: RemoteWorkspaceView }> {\n return getShape(`/workspaces/${encodeURIComponent(id)}`, { view: 'object' })\n },\n\n syncWorkspace(id: string, args: { headOid: string }): Promise<{ view: RemoteWorkspaceView }> {\n return postShape(`/workspaces/${encodeURIComponent(id)}/sync`, args, { view: 'object' })\n },\n\n landWorkspace(\n id: string,\n args: { landedOid: string; intoRef?: string },\n ): Promise<{ view: RemoteWorkspaceView }> {\n return postShape(`/workspaces/${encodeURIComponent(id)}/land`, args, { view: 'object' })\n },\n\n dropWorkspace(id: string): Promise<{ view: RemoteWorkspaceView }> {\n return postShape(`/workspaces/${encodeURIComponent(id)}/drop`, {}, { view: 'object' })\n },\n\n listActivity(opts?: {\n since?: number\n limit?: number\n tail?: boolean\n }): Promise<{ events: RemoteActivityEvent[]; cursor: number; hasMore: boolean }> {\n const params = new URLSearchParams()\n if (opts?.since) params.set('since', String(opts.since))\n if (opts?.limit) params.set('limit', String(opts.limit))\n if (opts?.tail) params.set('tail', '1')\n const qs = params.toString()\n return getShape(`/activity${qs ? `?${qs}` : ''}`, {\n events: 'array',\n cursor: 'present',\n hasMore: 'present',\n })\n },\n\n listReleases(limit?: number): Promise<{ releases: RemoteRelease[] }> {\n return getShape(`/releases${limit ? `?limit=${limit}` : ''}`, { releases: 'array' })\n },\n\n latestRelease(): Promise<{ release: RemoteRelease | null }> {\n // `release` is nullable (no releases yet) — presence-only, not `object`.\n return getShape('/releases/latest', { release: 'present' })\n },\n\n getRelease(id: string): Promise<{ release: RemoteRelease }> {\n return getShape(`/releases/${encodeURIComponent(id)}`, { release: 'object' })\n },\n }\n}\n\nexport type RepoApi = ReturnType<typeof repoApi>\n","// eslint-disable-next-line no-control-regex\nconst ANSI_RE = /\u001b\\[[0-9;]*m/g\n\n/** Drop SGR escapes so a machine-read string carries no styling. */\nexport function stripAnsi(s: string): string {\n return s.replace(ANSI_RE, '')\n}\n\n/**\n * Styling belongs to terminals. citty freezes its own no-color decision at\n * module load and only honors `NO_COLOR=1` — it never consults stdout — so\n * everything it renders must pass through here before it is printed.\n */\nexport function forTerminal(s: string): string {\n return process.stdout.isTTY ? s : stripAnsi(s)\n}\n\n/** POSIX single-quote a string for safe interpolation into a human-facing\n * \"run this\" command. Never use the result as a machine contract — that's\n * what structured {cwd, argv} is for. */\nexport function shQuote(s: string): string {\n return `'${s.replace(/'/g, \"'\\\\''\")}'`\n}\n\n/** Render argv as a copy-pasteable human command. */\nexport function humanCommand(argv: readonly string[]): string {\n return argv.map((arg) => (/^[A-Za-z0-9_./=:@-]+$/.test(arg) ? arg : shQuote(arg))).join(' ')\n}\n\n/**\n * Render peer-written text (a workspace task, a branch name, a commit subject)\n * safely into ONE terminal line. Raw, an `ESC[2K\\r` erases the row and\n * reprints attacker-chosen text; U+202E and friends reorder a line VISUALLY\n * with no byte changed (\"trojan source\"). Escaped, not stripped — the text\n * stays readable.\n */\nexport function displayText(value: string): string {\n return (\n value\n // eslint-disable-next-line no-control-regex\n .replace(/[\\u0000-\\u001f\\u007f-\\u009f]/g, (ch) => {\n if (ch === '\\t') return ' '\n const code = ch.codePointAt(0)!\n return `\\\\x${code.toString(16).padStart(2, '0')}`\n })\n // Every format character (Unicode category Cf) EXCEPT the two joiners,\n // plus the LINE and PARAGRAPH separators. An explicit list kept missing\n // Cf members — U+061C, U+2060, the whole astral U+E0000 tag block — so\n // \\p{Cf} is used as the closed set the standard maintains. U+2028/U+2029\n // are Zl/Zp rather than Cf and break a line in a terminal, and\n // `displayLines` splits on `\\n` alone, so without them a single field\n // could still forge a second row.\n .replace(/[\\p{Cf}\\p{Zl}\\p{Zp}]/gu, (ch) => {\n // ZWJ and ZWNJ are ORTHOGRAPHY, not attack surface: they carry no\n // reordering or hiding power, and escaping them mangles every emoji\n // sequence (👨‍💻), Persian (می‌شود) and Indic (क्‍ष) string that uses\n // them. The characters this defends against are the bidi overrides\n // and isolates, which reorder a line with no byte changed.\n if (ch === '\\u200c' || ch === '\\u200d') return ch\n const code = ch.codePointAt(0)!\n return `\\\\u{${code.toString(16)}}`\n })\n )\n}\n\n/**\n * The same rule for a COMPOSED message. `displayText` escapes newlines, which\n * is right for a field that must stay one line and wrong for a refusal whose\n * newlines are ours. Both are idempotent, which is what lets this sit at the\n * one exit every human line and every `--json` `error` passes through.\n */\nexport function displayLines(value: string): string {\n return value\n .split('\\n')\n .map((line) => displayText(line))\n .join('\\n')\n}\n","/** Generic bounded retry loop. The final attempt's response/error always wins. */\nexport async function retryTransient<T>(\n run: () => Promise<T>,\n {\n delaysMs,\n shouldRetryError = () => true,\n shouldRetryResult = () => false,\n }: {\n delaysMs: number[]\n shouldRetryError?: (error: unknown) => boolean\n shouldRetryResult?: (result: T) => boolean\n },\n): Promise<T> {\n for (let attempt = 0; ; attempt++) {\n try {\n const result = await run()\n if (!shouldRetryResult(result) || attempt >= delaysMs.length) return result\n } catch (error) {\n if (!shouldRetryError(error) || attempt >= delaysMs.length) throw error\n }\n await new Promise((resolve) => setTimeout(resolve, delaysMs[attempt]))\n }\n}\n\n/** Retry rebuilt request bodies on network failures and eligible responses. */\nexport async function fetchWithTransientRetry(\n url: string,\n makeInit: () => RequestInit,\n {\n attempts = 4,\n retryServerErrors = true,\n timeoutMs = 60_000,\n }: { attempts?: number; retryServerErrors?: boolean; timeoutMs?: number } = {},\n): Promise<Response> {\n return retryTransient(\n async () => {\n // Every attempt is bounded: a hung service must surface as a fast,\n // retryable failure, never inherit undici's multi-minute default.\n return await fetch(url, { ...makeInit(), signal: AbortSignal.timeout(timeoutMs) })\n },\n {\n delaysMs: Array.from({ length: Math.max(0, attempts - 1) }, (_, attempt) =>\n Math.min(8_000, 500 * 2 ** attempt),\n ),\n shouldRetryResult: (response) =>\n retryServerErrors &&\n (response.status >= 500 || response.status === 408 || response.status === 429),\n },\n )\n}\n","/**\n * Authenticated JSON fetch against a platform worker.\n *\n * Shared by the CLI commands that call the platform as the logged-in user\n * (`domain`, `feedback`, `collaborators`, `transfer`, …). Sends a Bearer\n * token, parses the JSON body, and on a non-2xx response throws an ApiError\n * carrying the worker's `{ error, code }` — message for display, code for\n * branching — so callers never string-sniff error text.\n */\n\nimport { displayLines } from './cli-format'\nimport { retryTransient } from './fetch-retry'\n\nexport class ApiError extends Error {\n constructor(\n message: string,\n readonly status: number,\n readonly code?: string,\n /** Internal REST path — kept off the message (DEBUG-only rendering). */\n readonly apiPath?: string,\n /**\n * Structured fields the server sent alongside `error`/`code` — e.g. a\n * `merge_conflicted` path list, a storage refusal's `usedBytes`/\n * `limitBytes`. The failure envelope spreads these into `--json`, so a\n * caller reads the values the API already computed instead of parsing\n * them back out of the sentence.\n */\n readonly details?: Record<string, unknown>,\n ) {\n // Server prose reaches the terminal and the `--json` envelope through\n // `formatCliError`, which bypasses the Refusal/InputError exits entirely,\n // so this is the seam that escapes it — server sentences name branches,\n // paths and secret names that a peer chose.\n super(displayLines(message))\n }\n}\n\n/**\n * Registered by auth.ts at load: force-mint a fresh JWT from the stored\n * session, bypassing the cached token file. Lets apiFetch heal a 401 whose\n * cause is a token that is locally \"valid\" but rejected server-side (signing-\n * key rotation, revocation) with one silent refresh + retry instead of a hard\n * error an agent has to reason about. Null ⇒ the session itself is dead and\n * the original 401 stands. A callback (not an import) so this low-level\n * module stays dependency-free of auth.ts.\n */\nlet refreshAuthToken: (() => Promise<string | null>) | null = null\nexport function registerAuthRefresh(fn: () => Promise<string | null>): void {\n refreshAuthToken = fn\n}\n\nexport async function apiFetch<T>(\n baseUrl: string,\n token: string,\n path: string,\n init?: RequestInit,\n isRetry = false,\n): Promise<T> {\n let res: Response\n let text: string\n try {\n res = await fetch(`${baseUrl}${path}`, {\n ...init,\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n ...(init?.headers ?? {}),\n },\n })\n } catch (err) {\n // A network-level failure (connection refused, DNS, TLS, offline) throws a\n // TypeError('fetch failed'), not an HTTP status — give it a stable code so a\n // --json caller can classify the transport outage instead of scraping prose.\n throw new ApiError(\n `Could not reach the deploy service at ${baseUrl}: ${err instanceof Error ? err.message : String(err)}. Check your connection (and DEEPSPACE_DEPLOY_URL), then retry.`,\n 0,\n 'network_error',\n path,\n )\n }\n // One transparent recovery per request. Keep the exchange outside the\n // deploy-service fetch catch: an auth-service outage is not evidence that\n // this bearer or the stored session is invalid, and must retain its code.\n if (res.status === 401 && !isRetry && refreshAuthToken) {\n const fresh = await refreshAuthToken()\n if (fresh && fresh !== token) return apiFetch<T>(baseUrl, fresh, path, init, true)\n }\n try {\n text = await res.text()\n } catch (err) {\n throw new ApiError(\n `Could not read the deploy service response at ${baseUrl}: ${err instanceof Error ? err.message : String(err)}. Check your connection (and DEEPSPACE_DEPLOY_URL), then retry.`,\n 0,\n 'network_error',\n path,\n )\n }\n if (!res.ok) {\n let msg = text\n let code: string | undefined\n // Everything the refusal carried BESIDES its sentence and slug — e.g. the\n // GitHub-source 422's `repository`, a storage refusal's byte counts. The\n // server already computed them; dropping them here is what forced callers\n // to read numbers and names back out of the prose.\n let details: Record<string, unknown> | undefined\n try {\n const body = JSON.parse(text) as Record<string, unknown>\n if (body !== null && typeof body === 'object' && !Array.isArray(body)) {\n msg = typeof body.error === 'string' ? body.error : text\n code = typeof body.code === 'string' ? body.code : undefined\n const rest = Object.fromEntries(\n Object.entries(body).filter(([key]) => key !== 'error' && key !== 'code'),\n )\n if (Object.keys(rest).length > 0) details = rest\n }\n } catch {\n // not JSON\n }\n // A bare router 404 (\"Not found\", no server code) means DEEPSPACE_DEPLOY_URL\n // points at a service that doesn't host this route (wrong/old URL, or a\n // worker predating it). Give it an actionable message + code UNIFORMLY for\n // every caller (incl. rollback's direct endpoint), so a --json agent gets\n // one stable slug for this case. Matched on `msg`, not the raw body: the\n // worker's notFound handler answers JSON `{\"error\":\"Not found\"}`, so the\n // plain-text form alone misses the ACTUAL router 404 and leaves it coded\n // `http_error` — the generic slug every other 4xx already carries, so\n // nothing keyed on `unrecognized_service` can tell the cases apart.\n if (!code && res.status === 404 && msg.trim() === 'Not found') {\n code = 'unrecognized_service'\n msg = `The deploy service at ${baseUrl} doesn't recognize this request — check DEEPSPACE_DEPLOY_URL (is this the service the app lives on?); if it is, the server may be older than this CLI.`\n }\n // Any other server error that supplied no `code` of its own (a non-conforming\n // 5xx, an HTML error page) still needs a stable slug to classify.\n code = code ?? (res.status >= 500 ? 'server_error' : 'http_error')\n // Message = the server's sentence only. The internal REST path and raw\n // status read like a stack trace to users (same treatment as secretsApi);\n // they stay on the error's fields for DEBUG rendering and branching.\n throw new ApiError(msg || `Request failed (${res.status})`, res.status, code, path, details)\n }\n if (!text) return {} as T\n let parsed: unknown\n try {\n parsed = JSON.parse(text)\n } catch {\n // A 2xx with a non-JSON body isn't the repo API — code it so a --json caller\n // doesn't get a bare SyntaxError.\n throw new ApiError(\n `The deploy service at ${baseUrl} returned a malformed (non-JSON) response — check DEEPSPACE_DEPLOY_URL (is this the service the app lives on?).`,\n res.status,\n 'invalid_response',\n path,\n )\n }\n // Every repo-API response is a JSON object; a null/array/primitive 2xx body is a\n // wrong/broken service — reject it with a code instead of letting a caller\n // destructure null and crash uncoded.\n if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new ApiError(\n `The deploy service at ${baseUrl} returned an unexpected response shape — check DEEPSPACE_DEPLOY_URL (is this the service the app lives on?).`,\n res.status,\n 'invalid_response',\n path,\n )\n }\n return parsed as T\n}\n\n/** Retry a platform request whose caller has established that replay is safe.\n * Ordinary mutations keep using apiFetch directly; only read-only requests\n * and operations with an explicit idempotency contract belong here. */\nexport async function apiFetchWithTransientRetry<T>(\n baseUrl: string,\n token: string,\n path: string,\n init?: RequestInit,\n): Promise<T> {\n return retryTransient(\n async () =>\n await apiFetch<T>(baseUrl, token, path, {\n ...init,\n signal: AbortSignal.timeout(15_000),\n }),\n {\n delaysMs: [250, 750, 1500],\n // A 401 refresh owns its own bounded auth-service retry loop. Only retry\n // failures produced by this deploy-service request, never multiply an\n // exhausted /api/auth/token exchange by replaying the rejected bearer.\n shouldRetryError: (error) => isTransientFailure(error) && error.apiPath === path,\n },\n )\n}\n\n/** Safe-by-construction GET variant for ordinary platform reads. */\nexport function apiFetchReadWithRetry<T>(baseUrl: string, token: string, path: string): Promise<T> {\n return apiFetchWithTransientRetry<T>(baseUrl, token, path)\n}\n\nfunction isTransientFailure(error: unknown): error is ApiError {\n return (\n error instanceof ApiError &&\n (error.status === 0 || error.status === 408 || error.status === 429 || error.status >= 500)\n )\n}\n","/**\n * Workspace naming — the deterministic mapping between a server workspace id\n * (`ws_<26-char Crockford ULID>`) and its local git branch (`ws/<ulid,\n * lowercased>`). Deterministic both ways so `workspace sync`/`land`/`status`\n * can infer which workspace a worktree belongs to from nothing but the\n * checked-out branch, on any machine.\n */\n\nconst ULID_RE = /^[0-9A-HJKMNP-TV-Z]{26}$/i\nconst WORKSPACE_ID_RE = /^ws_[0-9A-HJKMNP-TV-Z]{26}$/\n\nexport function isWorkspaceId(id: string): boolean {\n return WORKSPACE_ID_RE.test(id)\n}\n\nexport function workspaceBranchName(workspaceId: string): string {\n return `ws/${workspaceId.replace(/^ws_/, '').toLowerCase()}`\n}\n\n/** `ws/<ulid>` → `ws_<ULID>`, or null when the branch isn't workspace-shaped. */\nexport function workspaceIdFromBranch(branch: string | null): string | null {\n if (!branch || !branch.startsWith('ws/')) return null\n const ulid = branch.slice(3)\n if (!ULID_RE.test(ulid)) return null\n return `ws_${ulid.toUpperCase()}`\n}\n\nexport function isSelectedWorkspaceCheckout(branch: string | null, workspaceId: string): boolean {\n return workspaceIdFromBranch(branch) === workspaceId\n}\n\n/** Find a workspace's checkout among the repository's linked worktrees. */\nexport function resolveWorkspaceWorktree(\n worktrees: readonly { path: string; branch: string | null }[],\n workspaceId: string,\n): string | null {\n const branch = workspaceBranchName(workspaceId)\n return worktrees.find((worktree) => worktree.branch === branch)?.path ?? null\n}\n","/**\n * The shared command-output boundary. Command bodies return content or throw\n * a {@link Refusal}; this runtime owns JSON envelopes, human slugs and optional\n * actions, plus the 0/1/2 exit convention.\n */\n\nimport { defineCommand, parseArgs, type ArgsDef, type CommandDef } from 'citty'\nimport * as p from '@clack/prompts'\nimport { stopActiveSpinner } from './spinner'\nimport { executableAction, printAction, withSlug, type CliAction } from './output'\nimport {\n Refusal,\n errorCode,\n failureEnvelope,\n failureExitCode,\n formatCliError,\n withoutReservedKeys,\n} from './cli-errors'\n\nexport { cliAction } from './output'\n// The refusal class lives with the error renderer (lib/cli-errors) so a plain\n// citty command's escaped Refusal renders identically; re-exported here because\n// every command imports it from the runtime.\nexport { Refusal }\n\n/** What a command body returns: the machine payload plus its follow-ups. */\nexport interface CommandResult {\n /** Merged into the `--json` envelope. Omit for commands with no payload. */\n data?: Record<string, unknown>\n /** One executable follow-up: the `Next:` line and envelope's `action`. */\n action?: CliAction\n}\n\n/**\n * Record the exit code and hand control back, letting Node exit naturally once\n * the event loop drains. Never process.exit(): on Windows, exiting after a\n * successful built-in fetch() trips libuv's\n * `!(handle->flags & UV_HANDLE_CLOSING)` assertion (src/win/async.c) and\n * aborts the process (0xC0000409) AFTER the result was printed. Natural exit\n * still guarantees stdout lands whole: `console.log` on a PIPE is asynchronous\n * past the OS buffer (64 KiB on Linux/macOS), but a queued stdout write is an\n * active libuv handle, so Node drains it before the loop empties — no\n * flush-then-exit dance needed for large `--json` payloads.\n */\nfunction finishCommand(code: number): void {\n // A live spinner's repaint interval would keep the naturally-exiting\n // process alive forever; stop it (idempotent) before handing the loop back.\n stopActiveSpinner()\n process.exitCode = code\n}\n\nexport interface DeepspaceCommandDef<A extends ArgsDef> {\n meta: { name: string; description: string }\n args?: A\n /** Override when a command streams child output before its final envelope. */\n jsonDescription?: string\n /** Print human output yourself; return the machine payload. Throw a\n * {@link Refusal} for an actionable failure. */\n run: (ctx: { args: Record<string, unknown> & { json: boolean } }) => Promise<CommandResult | void>\n}\n\n/** Both spellings citty's parser can produce for one declared name. */\nfunction nameVariants(name: string): string[] {\n return [\n name,\n name.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase()),\n name.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`),\n ]\n}\n\n/**\n * Option names the command never declared.\n *\n * citty 0.2.2 hardcodes its parser to `strict: false` and exposes no way to\n * change it, so an unknown flag is not rejected — it is silently dropped into\n * the parsed object. `--limitt 1` therefore swallowed both the flag and its\n * value and returned every release, exit 0; `--jsonn` printed human prose to\n * stdout while the caller waited for JSON. Unknown SUBCOMMANDS and bad flag\n * VALUES are both already rejected — only flag names went unchecked.\n *\n * Reading the leftovers back out is what makes one central check possible: no\n * per-command tables, no second parser. Pure + exported for tests.\n */\nexport function unknownOptionNames(parsed: Record<string, unknown>, args: ArgsDef): string[] {\n const known = new Set<string>(['_'])\n for (const [name, def] of Object.entries(args)) {\n for (const variant of nameVariants(name)) known.add(variant)\n const alias = (def as { alias?: string | string[] }).alias\n for (const a of Array.isArray(alias) ? alias : alias ? [alias] : []) {\n for (const variant of nameVariants(a)) known.add(variant)\n }\n }\n return Object.keys(parsed).filter((key) => !known.has(key))\n}\n\n/** Parse only option names, without letting required positionals or enum\n * validation hide an unknown option before the executable-wide preflight can\n * report it. */\nexport function unknownOptionNamesFromRaw(rawArgs: string[], args: ArgsDef): string[] {\n const relaxedArgs = Object.fromEntries(\n Object.entries(args).map(([name, definition]) => [\n name,\n definition.type === 'enum'\n ? { ...definition, type: 'string' as const, required: false, options: undefined }\n : { ...definition, required: false },\n ]),\n ) as ArgsDef\n return unknownOptionNames(parseArgs(rawArgs, relaxedArgs), args)\n}\n\nexport function unknownOptionMessage(\n commandName: string,\n unknown: string[],\n args: ArgsDef,\n): string {\n const valid = Object.entries(args)\n .filter(([, definition]) => definition.type !== 'positional')\n .map(([name]) => name)\n .sort()\n .join(', ')\n return (\n `Unknown ${unknown.length === 1 ? 'option' : 'options'}: ` +\n `${unknown.map((name) => `--${name}`).join(', ')}. ` +\n `\\`${commandName}\\` accepts: ${valid || '(none)'}.`\n )\n}\n\n/**\n * Wrap a command body in the contract. Injects `--json`, renders both output\n * paths, and owns the exit codes — a body never calls process.exit itself.\n */\nexport function defineDeepspaceCommand<A extends ArgsDef>(def: DeepspaceCommandDef<A>): CommandDef {\n // The injected `json` arg widens citty's inferred ArgsDef generic, which no\n // longer matches the bare `CommandDef` the registry holds. The runtime reads\n // args dynamically, so the erasure is safe and keeps every command in the\n // tree one uniform type.\n const declaredArgs: ArgsDef = {\n ...(def.args ?? ({} as A)),\n json: {\n type: 'boolean',\n description: def.jsonDescription ?? 'Emit a single-line JSON result for scripts/agents',\n default: false,\n },\n }\n return defineCommand({\n meta: def.meta,\n args: declaredArgs,\n async run({ args }) {\n const json = Boolean((args as { json?: boolean }).json)\n let succeeded = false\n try {\n // Before any side effect: a typo'd flag must not run the command with\n // the caller's intent silently dropped.\n const unknown = unknownOptionNames(args as Record<string, unknown>, declaredArgs)\n if (unknown.length > 0) {\n throw new Refusal(\n unknownOptionMessage(def.meta.name, unknown, declaredArgs),\n 'unknown_option',\n )\n }\n // Hoisting `args` to a named ArgsDef (so the unknown-option check can\n // read the same declaration citty parsed against) widens what citty\n // infers here, so the erasure needs the explicit unknown hop.\n const out =\n (await def.run({\n args: args as unknown as Record<string, unknown> & { json: boolean },\n })) ?? {}\n // Success-path actions honor the same contract refusal actions do:\n // executable exactly as given, in the stated cwd — which means the\n // interpreter must be pinned (a linked worktree has no `deepspace`\n // on PATH and no node_modules of its own).\n if (out.action) out.action = executableAction(out.action)\n if (json) {\n console.log(\n JSON.stringify({\n ok: true,\n ...withoutReservedKeys(out.data ?? {}),\n ...(out.action ? { action: out.action } : {}),\n }),\n )\n } else if (out.action) {\n printAction(out.action)\n }\n succeeded = true\n } catch (err) {\n stopActiveSpinner()\n const refusal = err instanceof Refusal ? err : null\n const code = errorCode(err)\n if (json) {\n console.log(JSON.stringify(failureEnvelope(err)))\n } else {\n const message = formatCliError(err)\n const line = code ? withSlug(message, code) : message\n if (refusal?.actionRequired) p.log.warn(line)\n else p.log.error(line)\n if (refusal?.action) printAction(refusal.action)\n }\n finishCommand(failureExitCode(err))\n }\n // `succeeded` gates the fall-through from the catch above: a failure\n // has already recorded its 1/2 exit code and must not be overwritten\n // with 0.\n if (succeeded) finishCommand(0)\n },\n }) as CommandDef\n}\n","import * as p from '@clack/prompts'\nimport { displayLines } from './cli-format'\n\nexport interface Spinner {\n start: (msg?: string) => void\n stop: (msg?: string) => void\n message: (msg?: string) => void\n}\n\n// The spinner currently painting the terminal, if any. On Windows a live\n// @clack/prompts spinner registers a `process.on('exit')` handler that writes\n// a final frame to the TTY; calling process.exit() while it is still running\n// makes that write land as libuv tears the TTY handle down —\n// `Assertion failed: !(handle->flags & UV_HANDLE_CLOSING)` — turning a clean\n// exit(1) into an abort. Tracking the active spinner lets error helpers stop it\n// (which clears the interval and neuters that exit handler) before they exit.\nlet activeSpinner: Spinner | null = null\n\n// One chokepoint for machine-readable runs (the routeChildStdoutToStderr\n// pattern): a command that emits a JSON envelope calls this once and every\n// spinner it creates from then on is a plain static line per phase instead\n// of animated TTY repaints. The lines still go through console.log, so a\n// command that also redirects stdout (deploy's createDeployOutput) both\n// records them for its crash envelope and keeps them off the envelope stream.\nlet plainProgress = false\nexport function setPlainProgress(enabled: boolean): void {\n plainProgress = enabled\n}\n\n// In a real terminal, @clack/prompts repaints the spinner by writing `\\r`\n// to overwrite the previous frame. In non-TTY contexts (agents, CI logs,\n// pipes, `tee`-ed output) `\\r` does nothing and every frame becomes a new\n// line — a single long phase floods the log with thousands of repeats.\n// When stdout is not a TTY we fall back to one static line per phase.\nexport function createSpinner(): Spinner {\n const impl: Spinner =\n !plainProgress && process.stdout.isTTY\n ? p.spinner()\n : {\n start: (msg?: string) => {\n if (msg) console.log(msg)\n },\n stop: (msg?: string) => {\n if (msg) console.log(msg)\n },\n message: (msg?: string) => {\n if (msg) console.log(msg)\n },\n }\n // The other output exit. Progress lines were escaped at their call sites and\n // OUTCOME lines were not — `Checking <branch> before push…` sanitised, then\n // `Pushed <branch> → abc1234.` raw — so the split ran through push, pull,\n // status, land and deploy. Every message this wrapper carries is a\n // composed human line, and `displayLines` is idempotent, so the sites that\n // already escape their fields are unaffected.\n const wrapper: Spinner = {\n start: (msg?: string) => {\n activeSpinner = wrapper\n impl.start(msg === undefined ? msg : displayLines(msg))\n },\n stop: (msg?: string) => {\n impl.stop(msg === undefined ? msg : displayLines(msg))\n if (activeSpinner === wrapper) activeSpinner = null\n },\n message: (msg?: string) => impl.message(msg === undefined ? msg : displayLines(msg)),\n }\n return wrapper\n}\n\n/**\n * Stop whatever spinner is currently painting, if any. Call on every exit\n * path: a live spinner's repaint interval would keep a naturally-exiting\n * process alive, and its exit-time frame tears down mid-write on Windows\n * (see activeSpinner above). Idempotent and safe when nothing is active.\n */\nexport function stopActiveSpinner(): void {\n activeSpinner?.stop()\n}\n","/**\n * The output contract (docs: agent-experience standard).\n *\n * Agents read text: the human output is the interface and must be complete.\n * These helpers standardize its two optional machine anchors —\n *\n * 1. a refusal's final line carries its slug: `…message. [non_fast_forward]`\n * 2. when a command owns one safe follow-up, its final line names it:\n * `Next: deepspace pull`\n *\n * `--json` mirrors them (`code`, `action: { cwd, argv }`) but is never the primary\n * surface. Exit codes stay load-bearing: 0 done, 1 failed, 2 succeeded with\n * a local step remaining.\n */\n\nimport * as p from '@clack/prompts'\nimport { readFileSync, realpathSync } from 'node:fs'\nimport { dirname, isAbsolute, resolve } from 'node:path'\nimport { displayText, shQuote } from './cli-format'\n\n/** One executable recovery step. Commands decide which action is appropriate;\n * the runtime only transports and renders it. */\nexport interface CliAction {\n cwd: string\n argv: string[]\n}\n\n/**\n * An action naming `deepspace` is only runnable where a `deepspace` binary is\n * on PATH — which a linked worktree (a checkout with no `node_modules` of its\n * own), a bare clone directory, or any agent that invokes us through\n * `npx deepspace` is not. Prefer the SDK installed at the action's cwd: a\n * command such as `workspace land` may remove the checkout containing the\n * running CLI before its follow-up executes. Otherwise pin the CLI entry we\n * are running from. Both paths resolve symlinks and verify package ownership.\n * Anywhere the entry is unidentifiable (embedded, tests), the plain name is\n * left alone.\n */\nexport function resolveActionArgv(argv: string[], cwd?: string): string[] {\n if (argv[0] !== 'deepspace') return argv\n const entry = (cwd ? installedCliEntry(cwd) : null) ?? cliEntryPath()\n return entry ? [process.execPath, entry, ...argv.slice(1)] : argv\n}\n\n/** Find the nearest ordinary node_modules install visible from a target cwd. */\nfunction installedCliEntry(cwd: string): string | null {\n let dir = resolve(cwd)\n while (true) {\n const entry = verifiedCliEntry(resolve(dir, 'node_modules', 'deepspace', 'dist', 'cli.js'))\n if (entry) return entry\n const parent = dirname(dir)\n if (parent === dir) return null\n dir = parent\n }\n}\n\n/**\n * The real path of the CLI entry we are executing, or null when it cannot be\n * identified (embedded use, tests, a Windows `.cmd` shim as argv[1] — all\n * fall back to the bare name, which is the pre-pinning behavior, not an\n * error). `npx deepspace` and `node_modules/.bin` on POSIX hand us a symlink\n * to the package's `dist/cli.js` — resolve it, or a pinned action would name\n * a link that only exists in one checkout.\n */\nfunction cliEntryPath(): string | null {\n const entry = process.argv[1]\n if (!entry || !isAbsolute(entry)) return null\n return verifiedCliEntry(entry)\n}\n\nfunction verifiedCliEntry(entry: string): string | null {\n let real: string\n try {\n real = realpathSync(entry)\n } catch {\n return null\n }\n if (!/(^|[\\\\/])cli\\.[cm]?js$/.test(real)) return null\n // `cli.js` is a common entry basename — pin only when it is OUR package's,\n // or an embedding host would be handed deepspace's arguments.\n try {\n const pkg = JSON.parse(readFileSync(resolve(dirname(real), '..', 'package.json'), 'utf-8')) as {\n name?: string\n }\n return pkg.name === 'deepspace' ? real : null\n } catch {\n return null\n }\n}\n\n/** The single door every emitted action goes through: pinned, then validated.\n * Idempotent — a pinned argv starts with the interpreter, not `deepspace`,\n * so re-applying it is a no-op. */\nexport function executableAction(action: CliAction): CliAction {\n const pinned = { ...action, argv: resolveActionArgv(action.argv, action.cwd) }\n assertExecutableAction(pinned)\n return pinned\n}\n\n/** Construct an action without turning argv back into a shell program. */\nexport function cliAction(...argv: string[]): CliAction {\n return executableAction({ cwd: process.cwd(), argv })\n}\n\n/** Reject action-shaped hints that an agent cannot execute verbatim. */\nexport function assertExecutableAction(action: CliAction): void {\n if (!isAbsolute(action.cwd)) throw new TypeError('CLI action cwd must be absolute')\n if (action.argv.length === 0 || action.argv[0].trim() === '') {\n throw new TypeError('CLI action argv must name an executable')\n }\n if (action.argv.some((arg) => /^<[^<>]+>$/.test(arg))) {\n throw new TypeError('CLI action argv must not contain placeholder tokens')\n }\n}\n\n/** Suffix a refusal message with its machine slug, last line only. Idempotent\n * (a message already carrying `[slug]` at the end is left alone) so wrapper\n * layers can apply it without double-tagging. */\nexport function withSlug(msg: string, code: string): string {\n const tag = `[${code}]`\n return msg.trimEnd().endsWith(tag) ? msg : `${msg.trimEnd()} ${tag}`\n}\n\n/** Shell-quote for the human line, and escape what quoting does not fix: a\n * branch name carrying U+202E reorders the printed `Next:` command while the\n * argv it renders is unchanged, so the line and the action disagree.\n * Sanitize FIRST, then quote for the target shell. */\nfunction displayArg(arg: string): string {\n const safe = displayText(arg)\n if (/^[A-Za-z0-9_./:@%+=,-]+$/.test(safe)) return safe\n // cmd.exe and PowerShell treat single quotes as literal characters, so the\n // POSIX quoting would render Windows paths un-pasteable; double quotes work\n // in both shells.\n if (process.platform === 'win32') return `\"${safe.replaceAll('\"', '\"\"')}\"`\n return shQuote(safe)\n}\n\n/** Render the same structured action exposed to agents as a copy-pasteable\n * human command. The shell string is presentation only, never machine data. */\nexport function printAction(action: CliAction): void {\n assertExecutableAction(action)\n // Rule 2: this line renders the SAME value `argv` carries. A pinned\n // self-invocation therefore prints as the interpreter + entry it will\n // actually run — `npx deepspace …` would read nicer but is a different\n // command (a registry lookup that can resolve another version).\n const command = action.argv.map(displayArg).join(' ')\n const prefix = action.cwd === process.cwd() ? '' : `cd ${displayArg(action.cwd)} && `\n p.log.message(`Next: ${prefix}${command}`)\n}\n","/**\n * Friendly rendering for errors that escape a command's run().\n *\n * citty's runMain catches escaped errors and console.errors the full Error\n * object — stack trace and all. For expected operational failures (an API\n * 403, a network hiccup) that reads like a crash. wrapCommandErrors()\n * recursively wraps every command's run() so escaped errors render as a\n * single clean message (with known API error slugs translated), while\n * citty's own help/version/usage handling stays untouched. Set DEBUG=1 to\n * get the full stack back.\n */\n\nimport type { CommandDef } from 'citty'\nimport { stopActiveSpinner } from './spinner'\nimport { executableAction, printAction, withSlug, type CliAction } from './output'\nimport { displayLines } from './cli-format'\nimport { ApiError } from './api'\n\n/**\n * A client-side or precondition failure that carries a machine `code`, so a\n * thrown error (a blank `--app`, \"not logged in\", an empty repo) reads in\n * `--json` exactly like a server ApiError — `{ ok:false, code, error }` — rather\n * than a bare message. Reuses no HTTP semantics (unlike ApiError). Most instances\n * are pure client-side validation that never touch the network; a few are\n * preconditions checked before the real work (e.g. an expired session, detected\n * after a refresh attempt) — the shared contract is only \"carries a stable code\".\n */\nexport class InputError extends Error {\n constructor(\n message: string,\n readonly code: string,\n ) {\n // Same exit rule as `Refusal` (lib/command.ts): a refusal's text and its\n // `--json` `error` are the same string, so it is escaped once, here.\n super(displayLines(message))\n }\n}\n\n/** `uv_cwd` — the process's working directory no longer exists. Node reports\n * it as a bare ENOENT whose syscall/message names uv_cwd rather than a path. */\nexport function isMissingCwdError(err: unknown): boolean {\n if (!(err instanceof Error)) return false\n const errno = err as NodeJS.ErrnoException & { syscall?: string }\n if (errno.code !== 'ENOENT') return false\n // `syscall` alone. Matching the MESSAGE for 'uv_cwd' also matched an\n // ordinary missing FILE whose path happens to contain that string, and\n // reported it as a vanished working directory — the genuine error always\n // carries the syscall, so the substring bought nothing.\n return errno.syscall === 'uv_cwd'\n}\n\n/**\n * A refusal the caller can act on: carries the machine slug that appears both\n * in `--json` as `code` and at the end of the human line, plus at most one\n * executable action that resolves it.\n *\n * `actionRequired` marks the third exit state — the operation did what it\n * could and a LOCAL step remains (merge the tip, commit the tree). It exits 2,\n * which is the difference between \"this failed\" and \"your turn\", and is the\n * single most useful signal an agent gets from this CLI.\n *\n * Lives here (not in the command runtime) so that {@link errorCode} and\n * {@link renderCliError} — the path a plain citty command's escaped error\n * takes — read it exactly like the runtime does. Before, a Refusal thrown by a\n * shared helper (`ensureToken`, the app-target resolver) lost its code and its\n * action the moment it crossed into a command that renders through here.\n */\nexport class Refusal extends Error {\n readonly code: string\n readonly action: CliAction | undefined\n readonly actionRequired: boolean\n readonly extra: Record<string, unknown>\n\n constructor(\n message: string,\n code: string,\n opts: { action?: CliAction; actionRequired?: boolean; extra?: Record<string, unknown> } = {},\n ) {\n // The exit every refusal passes through, human and `--json` alike —\n // `Refusal.message` IS the envelope's `error`. Escaping it here rather than\n // at each call site is the whole point: three rounds of sink-by-sink fixes\n // closed a branch-list echo while leaving the `--into` argument raw in the\n // same sentence, and left `push`, `pull` and `status` untouched.\n super(displayLines(message))\n this.name = 'Refusal'\n this.code = code\n // Actions built as object literals get the same executable-argv treatment\n // `cliAction` applies, so no refusal can hand out a bare `deepspace` that\n // its own `cwd` cannot run.\n this.action = opts.action ? executableAction(opts.action) : undefined\n this.actionRequired = opts.actionRequired ?? false\n this.extra = opts.extra ?? {}\n }\n}\n\n/**\n * Strip the envelope's reserved keys from a payload before it is spread into\n * the envelope. `data`/`extra` can carry raw server JSON (`integrations\n * invoke` forwards the response body verbatim), and a payload containing\n * `ok`, `action`, or `actionRequired` must not be able to flip a failure to\n * success or hand an agent an unvalidated recovery action.\n */\nexport function withoutReservedKeys(payload: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(payload).filter(\n ([key]) =>\n !['ok', 'code', 'error', 'action', 'actionRequired', 'next', 'nextAction', 'resume'].includes(\n key,\n ),\n ),\n )\n}\n\n/**\n * The one `--json` failure envelope: `{ ok:false, code?, actionRequired?, error,\n * action?, …details }`. Details are a Refusal's `extra`, else the structured\n * fields a server refusal carried (an {@link ApiError}'s `details`) — without\n * them the envelope kept only the sentence, and an agent had to read numbers\n * like remaining storage back out of prose the API had already quantified.\n */\nexport function failureEnvelope(err: unknown): Record<string, unknown> {\n const refusal = err instanceof Refusal ? err : null\n const code = errorCode(err)\n const details = refusal?.extra ?? (err instanceof ApiError ? err.details : undefined) ?? {}\n return {\n ok: false,\n ...(code ? { code } : {}),\n ...(refusal?.actionRequired ? { actionRequired: true } : {}),\n error: formatCliError(err),\n ...(refusal?.action ? { action: refusal.action } : {}),\n ...withoutReservedKeys(details),\n }\n}\n\n/** 2 = \"it worked, but a local step remains\"; 1 = it failed. */\nexport function failureExitCode(err: unknown): 1 | 2 {\n return err instanceof Refusal && err.actionRequired ? 2 : 1\n}\n\n/**\n * Thrown by an output owner (deploy's `die()`/`bail()`) AFTER it has fully\n * rendered a failure, purely to end control flow; it carries only the exit\n * code. {@link renderCliError} recognizes it and records the code without a\n * second rendering. A thrown sentinel rather than process.exit() because on\n * Windows exiting after a completed built-in fetch() aborts the process —\n * see lib/command.ts.\n */\nexport class CliExit extends Error {\n constructor(readonly exitCode: number) {\n super(`exit ${exitCode}`)\n this.name = 'CliExit'\n }\n}\n\n/**\n * The machine `code` slug an error carries, if any — an {@link ApiError} (server\n * failure) or an {@link InputError} (client-side validation). Lets a command's\n * `--json` catch surface `code` uniformly without knowing the concrete type.\n * Deliberately narrow: it does NOT read arbitrary `.code` properties (a Node\n * `ENOENT` fs error must not leak into the machine contract as a `code`).\n */\nexport function errorCode(err: unknown): string | undefined {\n if (err instanceof ApiError || err instanceof InputError || err instanceof Refusal) return err.code\n // The ONE Node errno that is not an internal detail: the process's own\n // working directory is gone, which is what a deleted worktree looks like\n // from inside it (`uv_cwd`). It throws at the first `process.cwd()` a\n // command reaches — usually its opening line — so without this the whole\n // CLI answers an uncoded `ENOENT: … uv_cwd` from every verb, and the\n // `worktree_missing` diagnosis one layer down is unreachable exactly when\n // it is needed.\n if (isMissingCwdError(err)) return 'worktree_missing'\n // GitError (raw git operation/transport failure) — duck-typed by `name` to\n // avoid a cli-errors↔git import cycle. Give it a generic `git_error` (or its\n // own slug, if set) so a --json caller can branch on \"a git op failed\"\n // instead of scraping the fatal-… prose.\n if (err instanceof Error && err.name === 'GitError') return (err as { code?: string }).code ?? 'git_error'\n // WranglerConfigError (unreadable / malformed / self-contradictory\n // wrangler.toml) — duck-typed for the same reason: it lives in the one\n // wrangler.toml reader, which `deepspace/build` imports and which therefore\n // must not pull this module's CLI stack into an app's build graph.\n if (err instanceof Error && err.name === 'WranglerConfigError')\n return (err as { code?: string }).code ?? 'invalid_config'\n return undefined\n}\n\n/**\n * API error slugs that genuinely confuse people → what to tell them. Slugs\n * whose meaning is obvious from the name (invalid_email, ...) stay unmapped\n * and render as-is; don't grow this into a mirror of the server's errors.\n */\nconst API_ERROR_HINTS: Record<string, string> = {\n // Starts where the server sentence (\"Only the app owner can do this.\")\n // stops, so the two read as one message instead of a stutter.\n // Neutral about the reader's standing: this hint also reaches a REMOVED\n // collaborator, to whom \"collaborators can deploy\" reads as \"you should\n // have been able to\" (v0.26.0 collab AX).\n not_app_owner:\n 'Ownership verbs (collaborators, transfer, undeploy) run only as the owner; current ' +\n 'collaborators can deploy and manage secrets, and an account that was removed has no ' +\n 'access at all (`deepspace app list` shows your standing). Ask the owner to run it, have ' +\n 'them transfer the app (`deepspace app transfer offer`), or fork your checkout as your ' +\n 'own app (`deepspace app init --new-id`).',\n app_not_found:\n 'App not found on the service this command asked. Check the app id — the DEEPSPACE_APP_ID ' +\n 'value in wrangler.toml, usually `app_…` (a legacy app\\'s id is its name); list your apps ' +\n 'with `deepspace app list`. If you are overriding DEEPSPACE_DEPLOY_URL (staging), note that ' +\n 'account/collaborator commands go to the PLATFORM API — an app registered only on a staging ' +\n 'deploy service is unknown there. (`domain` commands take the deployed app *name* instead.)',\n not_app_owner_or_collaborator: 'You must be the app owner or a collaborator to do this.',\n test_account_cannot_be_collaborator:\n 'Test accounts cannot be added as collaborators. Use a real DeepSpace account.',\n user_not_found:\n 'No DeepSpace user with that email. They need to log in to DeepSpace at least once ' +\n '(`deepspace auth login`, or sign in to any app) before they can be referenced by email.',\n insufficient_credits:\n 'Out of credits. Inviting a new collaborator by email sends them a transactional ' +\n 'email billed to your account — top up your credits and try again.',\n // \"Try again\" alone sends callers into a loop when the address itself is the\n // problem — the send is what failed, and an undeliverable address fails the\n // same way every time.\n invite_email_failed:\n 'The invite itself was not created and the charge was voided — nothing to undo. Retrying ' +\n 'helps only if the send was transient; check the address is real and deliverable first. ' +\n 'An email is needed ONLY for someone with no DeepSpace account yet: an existing user is ' +\n 'added instantly, so having them sign in once and re-running this skips email entirely. ' +\n 'If a retry now reports `already_invited` with no email sent, cancel the stuck invite ' +\n '(`deepspace app collaborators cancel <email>`) and invite again.',\n}\n\n/** Exported for tests. One clean message for an escaped error. */\nexport function formatCliError(err: unknown): string {\n // `ENOENT: no such file or directory, uv_cwd` names neither the directory\n // nor the fix. This is the message every command produces when the shell is\n // sitting in a worktree that was landed, dropped, or merged away.\n if (isMissingCwdError(err)) {\n // The path is NOT knowable from the error (process.cwd() is what failed),\n // but the shell exports PWD, so name it when it is there. And do not\n // assert a cause: every verb answers this, including ones with nothing to\n // do with version control, and \"it was most likely a workspace worktree\"\n // is a guess dressed as a finding.\n const pwd = process.env.PWD\n return (\n `The directory this command was run from no longer exists${pwd ? ` (${pwd})` : ''} — ` +\n 'it was deleted or moved while the shell was still in it. Move somewhere that exists ' +\n '(`cd` to the main checkout). If it was a workspace worktree that a land, merge, or drop ' +\n 'removed, `deepspace workspace attach <ws_…>` re-materializes it there.'\n )\n }\n const message = err instanceof Error ? err.message : String(err)\n // The platform returns { error: <sentence>, code: <slug> }, and apiFetch\n // preserves that code on a typed error. Never infer machine state from prose.\n const slug = errorCode(err)\n const hint = slug ? API_ERROR_HINTS[slug] : undefined\n // The server sentence and the hint can say the same thing — don't stutter.\n return hint && !message.includes(hint) ? `${message}\\n${hint}` : message\n}\n\n/**\n * Records the exit code via process.exitCode and RETURNS — never\n * process.exit(), which on Windows aborts the process when called after a\n * completed built-in fetch() (see lib/command.ts). Every caller is the last\n * act of its command, so returning lets Node exit naturally.\n */\nexport function renderCliError(err: unknown): void {\n // A command may throw with its progress spinner still live; stop it FIRST,\n // on every path including CliExit — its repaint interval would keep the\n // naturally-exiting process alive, and its exit-time frame can abort on\n // Windows (see spinner.ts). Idempotent, so an already-stopped spinner is\n // free.\n stopActiveSpinner()\n // A CliExit was already rendered by its thrower (deploy's die()/bail());\n // just record its code — a second rendering would double the output.\n if (err instanceof CliExit) {\n process.exitCode = err.exitCode\n return\n }\n const message = formatCliError(err)\n const slug = errorCode(err)\n // `--json` callers get the envelope every other refusal path emits. Without\n // this, an error that ESCAPES a command's own try/catch printed prose to\n // stderr and left stdout EMPTY — a machine consumer saw a non-zero exit with\n // nothing to parse. Commands that catch their own errors are unaffected;\n // this is the fallback for the ~15 that don't.\n if (process.argv.includes('--json')) {\n console.log(JSON.stringify(failureEnvelope(err)))\n process.exitCode = failureExitCode(err)\n return\n }\n // Human path: the last line carries the machine slug, per the output\n // contract (lib/output.ts), and a Refusal's one executable follow-up.\n console.error(slug ? withSlug(message, slug) : message)\n if (err instanceof Refusal && err.action) printAction(err.action)\n if (process.env.DEBUG) {\n // ApiError keeps the internal REST path off the message; show it here.\n const { apiPath, status } = err as { apiPath?: string; status?: number }\n if (apiPath) console.error(`\\nAPI ${apiPath}${status ? ` (${status})` : ''}`)\n if (err instanceof Error && err.stack) console.error('\\n' + err.stack)\n }\n process.exitCode = failureExitCode(err)\n}\n\ntype RunFn = NonNullable<CommandDef['run']>\n\n/**\n * Recursively wrap a concrete command tree's run() handlers. Only plain\n * object subcommands are wrapped — every command in this CLI is one; lazy\n * (function/promise) subcommand definitions would pass through unwrapped.\n */\nexport function wrapCommandErrors<T extends CommandDef>(cmd: T): T {\n const run = cmd.run\n if (run) {\n cmd.run = (async (ctx: Parameters<RunFn>[0]) => {\n try {\n await run(ctx)\n } catch (err) {\n renderCliError(err)\n }\n }) as RunFn\n }\n if (cmd.subCommands && typeof cmd.subCommands === 'object') {\n for (const sub of Object.values(cmd.subCommands)) {\n if (sub && typeof sub === 'object') wrapCommandErrors(sub as CommandDef)\n }\n }\n return cmd\n}\n","import { apiFetchReadWithRetry, ApiError } from './api'\nimport { Refusal } from './command'\n\nexport type AppSource = { provider: 'deepspace' } | { provider: 'github'; repository: string }\n\n/**\n * THE GitHub-source refusal, for every source verb. `push` reaches it from its\n * own `/source` read, `pull`/`clone`/`workspace` from the repo API's 422 — one\n * sentence and one set of machine fields either way, so an agent's parser never\n * has to special-case which verb it ran (it used to get `appId`/`repository`\n * from `push` and prose-only from the other two).\n *\n * Deliberately no executable `action`: which command comes next depends on\n * whether the caller wanted to clone, fetch or push, and the CLI knows only\n * `owner/repo` — never the clone URL's protocol — so any `git clone` it printed\n * would be a guess.\n */\nexport function githubSourceRefusal(appId: string, repository: string): Refusal {\n return new Refusal(\n `This app uses GitHub source (${repository}). Use normal Git/GitHub for source operations ` +\n '(clone, fetch, push); `deepspace deploy` ships the local working tree without changing Git.',\n 'source_managed_by_github',\n { extra: { appId, repository } },\n )\n}\n\n/**\n * The INFERRED twin of {@link githubSourceRefusal}, for apps that are not\n * claimed as anything: their releases record GitHub, so an empty DeepSpace\n * cloud repo is not \"push first\" — it is \"the source lives on GitHub\". The\n * v0.26.0 AX pass caught `pull`, `clone`, and `workspace new`\n * all prescribing `deepspace push` here, which is the PERMANENT DeepSpace\n * claim: three verbs steering GitHub users through a one-way door. Same code\n * as the claimed refusal, so parsers need no new case; the sentence carries\n * the one fact that changes the decision — pushing claims, permanently.\n */\nexport function githubInferredRefusal(appId: string, repository: string): Refusal {\n return new Refusal(\n `This app ships from GitHub (${repository}) — inferred from its releases; ` +\n 'its DeepSpace cloud repo is intentionally empty. Use normal Git/GitHub for source ' +\n 'operations. (`deepspace push` would permanently claim DeepSpace source for this app — ' +\n 'only run it to adopt DeepSpace source on purpose.)',\n 'source_managed_by_github',\n { extra: { appId, repository, inferred: true } },\n )\n}\n\n/**\n * The repository an UNCLAIMED app's GitHub inference points at, or null when\n * nothing does. Evidence is the RELEASE LEDGER only — the latest release's\n * recorded source. Deliberately not the checkout's remotes: with no releases\n * at all there is no evidence the app \"ships from GitHub\", and a real\n * DeepSpace app whose owner merely keeps a GitHub mirror must not be refused\n * its first `pull`/`workspace new` on the strength of a remote name. One\n * bounded read, only ever consulted on refusal paths — never the happy path.\n */\nexport async function inferredGitHubRepository(\n deployUrl: string,\n token: string,\n appId: string,\n): Promise<string | null> {\n try {\n // Dynamic: repo-api imports this module's refusal, so a static import\n // back at it would cycle.\n const { repoApi } = await import('./repo-api')\n const { release } = await repoApi(deployUrl, token, appId).latestRelease()\n if (release?.source?.provider === 'github') return release.source.repository\n } catch {\n // No release ledger to consult: no evidence.\n }\n return null\n}\n\nexport interface AppSourceState {\n appId: string\n source: AppSource | null\n revision: number\n registered: boolean\n /**\n * The app's live subdomain host, or null when it has never been deployed.\n * `deploy` compares it against the wrangler `name` to settle a rename BEFORE\n * it builds. Absent from a platform older than this field.\n */\n registeredHost?: string | null\n /**\n * Present only when the caller is NOT the app's owner: whether the live\n * version carries the APP_OWNER_JWT an on-behalf deploy has to inherit.\n * Absent when the platform could not determine it (or predates the field) —\n * treat absence as unknown and let the commit-time guard answer.\n */\n onBehalf?: { ownerJwtLive: boolean }\n}\n\nexport async function getAppSource(\n deployUrl: string,\n token: string,\n appId: string,\n): Promise<AppSourceState> {\n try {\n const state = await apiFetchReadWithRetry<Omit<AppSourceState, 'registered'>>(\n deployUrl,\n token,\n `/api/apps/${encodeURIComponent(appId)}/source`,\n )\n return { ...state, registered: true }\n } catch (error) {\n if (error instanceof ApiError && error.code === 'app_not_found') {\n return { appId, source: null, revision: 0, registered: false }\n }\n throw error\n }\n}\n"],"mappings":"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","names":["resolve","p","p","repoApi"]}
@@ -1274,7 +1274,7 @@ function renderInlineMarkdown(value) {
1274
1274
  import { useEffect as useEffect6, useRef as useRef5, useState as useState5 } from "react";
1275
1275
 
1276
1276
  // package.json
1277
- var version = "0.26.2";
1277
+ var version = "0.27.0";
1278
1278
 
1279
1279
  // src/documentation/runtime/navigation.tsx
1280
1280
  import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
@@ -1954,4 +1954,4 @@ export {
1954
1954
  DefaultDocumentation,
1955
1955
  DocumentationContent
1956
1956
  };
1957
- //# sourceMappingURL=chunk-S2OGAK6U.js.map
1957
+ //# sourceMappingURL=chunk-SF6GNPYL.js.map