@pipod/cli 0.0.0-stage → 0.1.4
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.
- package/LICENSE +661 -0
- package/README.md +73 -2
- package/dist/chords-SOJBLC6R.js +9 -0
- package/dist/chords-SOJBLC6R.js.map +1 -0
- package/dist/chunk-GNKF75X7.js +204 -0
- package/dist/chunk-GNKF75X7.js.map +1 -0
- package/dist/cli.js +20179 -0
- package/dist/cli.js.map +1 -0
- package/docs/ci-validation.md +17 -0
- package/docs/classic-runtime-coupling.md +106 -0
- package/docs/config-simplification.md +162 -0
- package/docs/extension-aux-bridge.md +96 -0
- package/docs/image-attachments.md +58 -0
- package/docs/personal-workstation.md +132 -0
- package/docs/sandbox-cost-controls.md +77 -0
- package/docs/workspace-seeding.md +106 -0
- package/image/Dockerfile +65 -0
- package/package.json +47 -4
- package/templates/user-config.jsonc +25 -0
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/errors.ts","../src/account/api.ts","../src/log.ts","../src/redact.ts","../src/account/oidc.ts","../src/account/store.ts","../src/userconfig.ts","../src/hostconfig.ts","../src/image.ts","../src/client/piversion.ts","../src/image-recipe.ts","../src/account/workstation.ts","../src/account/billing.ts","../src/account/client.ts","../src/account/doctor.ts","../src/config.ts","../src/dotenv.ts","../src/secret-refs.ts","../src/account/launch-overlays.ts","../src/jsonc.ts","../src/account/workspace-seed.ts","../src/account/launch-preflight.ts","../src/prompt.ts","../src/account/bundle-source.ts","../src/providers/meta.ts","../src/providers/registry.ts","../src/account/launch-resources.ts","../src/account/launch-seed.ts","../src/send.ts","../src/tarball.ts","../src/account/ref.ts","../src/account/capacity-errors.ts","../src/account/launch-provision.ts","../src/account/launch-args.ts","../src/piargv.ts","../src/account/session.ts","../src/client/podinfo.ts","../src/shim/agentd.ts","../src/shim/pi-pod-ext.ts","../src/client/protocol.ts","../src/client/compat.ts","../src/client/headless.ts","../src/client/pod-title.ts","../src/client/runtime/attested-extensions.ts","../src/client/runtime/local-extensions.ts","../src/client/runtime/state.ts","../src/client/runtime/pod-command-overrides.ts","../src/client/runtime/local-images.ts","../src/client/runtime/pod-derived-config.ts","../src/client/runtime/pod-manifest.ts","../src/account/pod-config-sync.ts","../src/client/runtime/remote-runtime.ts","../src/client/runtime/bridge.ts","../src/client/runtime/pod-file-completion.ts","../src/client/runtime/auth-bridge.ts","../src/wire-codec.ts","../src/client/runtime/extension-ui.ts","../src/client/runtime/pod-extension-bridge.ts","../src/client/runtime/extension-model-registry.ts","../src/client/runtime/remote-ui.ts","../src/remote-ui-protocol.ts","../src/client/runtime/stream-heal.ts","../src/account/credential-login.ts","../src/account/gateway-rpc.ts","../src/client/stream-events.ts","../src/client/rpc.ts","../src/account/gateway-rpc-codec.ts","../src/account/pi-readiness.ts","../src/account/asleep-wake.ts","../src/account/pod-status.ts","../src/account/pods.ts","../src/account/bundle-bootstrap.ts","../src/account/template-ref.ts","../src/account/launch-handoff.ts","../src/account/jobs.ts","../src/jobfiles.ts","../src/account/billing-cli.ts","../src/account/login.ts","../src/account/receive.ts","../src/commands/credentials.ts","../src/commands/secrets.ts","../src/secrets.ts","../src/commands/templates.ts","../src/commands/layers.ts","../src/commands/pull.ts","../src/commands/push.ts","../src/commands/settings.ts","../src/scaffold.ts","../src/update.ts"],"sourcesContent":["#!/usr/bin/env node\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { AccountClient } from \"./account/api.js\";\nimport { requireAccountClient } from \"./account/client.js\";\nimport { runAccountDoctor } from \"./account/doctor.js\";\nimport { runAccountJobs } from \"./account/jobs.js\";\nimport { runAccountLaunch } from \"./account/launch.js\";\nimport { runBillingCommand } from \"./account/billing-cli.js\";\nimport { runLogin, runLogout, runOpenAccount, runOpenOrgAdmin, runWhoami } from \"./account/login.js\";\nimport {\n runAccountAttach,\n runAccountFork,\n runAccountGc,\n runAccountList,\n runAccountPodAction,\n runAccountRename,\n runAccountSend,\n runAccountStop,\n type AccountPodFlags,\n} from \"./account/pods.js\";\nimport { runAccountReceive } from \"./account/receive.js\";\nimport { bundledPiVersion } from \"./client/piversion.js\";\nimport { runCredentials } from \"./commands/credentials.js\";\nimport { runSecrets } from \"./commands/secrets.js\";\nimport { runTemplates } from \"./commands/templates.js\";\nimport { runDiff } from \"./commands/layers.js\";\nimport { runPull } from \"./commands/pull.js\";\nimport { runPush } from \"./commands/push.js\";\nimport { runSettings } from \"./commands/settings.js\";\nimport { findConfigPath } from \"./config.js\";\nimport { CancelledError, EXIT, PiPodError, isPiPodError } from \"./errors.js\";\nimport { launcherVersion } from \"./image.js\";\nimport {\n color,\n error,\n hint as printHint,\n info,\n isVerbose,\n out,\n plain,\n setVerbose,\n warn,\n} from \"./log.js\";\nimport { printInitResult, scaffold } from \"./scaffold.js\";\nimport { runUpdate } from \"./update.js\";\nimport { displayPath, ensureUserConfig } from \"./userconfig.js\";\n\nexport const VERSION = launcherVersion();\n\nconst SUBCOMMANDS = [\n \"init\",\n \"login\",\n \"logout\",\n \"whoami\",\n \"account\",\n \"org-admin\",\n \"gc\",\n \"doctor\",\n \"attach\",\n \"list\",\n \"stop\",\n \"rename\",\n \"fork\",\n \"send\",\n \"receive\",\n \"archive\",\n \"restore\",\n \"jobs\",\n \"credentials\",\n \"secrets\",\n \"templates\",\n \"push\",\n \"pull\",\n \"diff\",\n \"settings\",\n \"billing\",\n \"update\",\n] as const;\n\ntype Subcommand = (typeof SUBCOMMANDS)[number];\n\nexport const SIGNED_OUT_COMMANDS = new Set<Subcommand>([\"login\", \"whoami\", \"init\", \"doctor\", \"update\"]);\n\nconst ALIASES: Record<string, Subcommand> = {\n a: \"attach\",\n ls: \"list\",\n};\n\nconst HELP = `pipod ${VERSION} — run pi sessions in server-managed pods\n\nUsage:\n pipod [options] launch a pod for this project and start pi\n pipod [options] -- <pi args…> launch and pass arguments to pi: prompt words,\n --model <id>, --thinking <level>, --tui-mode <mode>,\n -e/--extension <path>, --skill <path>,\n --prompt-template <path> (each repeatable)\n pipod <command> [options] run a command\n pipod help [command] show help (same as --help)\n\nSign in first with \\`pipod login\\`. A pod-scoped PI_POD_SERVER_TOKEN also counts as\nsigned in. While signed out, only login, whoami, init, doctor, update, help, and\nversion are available.\n\nPod commands:\n list [pod] List pods; \\`list <pod>\\` shows one machine's group (ls)\n attach [pod] Reconnect to a pod session (a)\n stop [pod…] Stop pods now (files kept; attach restarts them)\n fork <pod> Launch a new pod forked from a pod's session\n rename <pod> <name> Rename a pod\n send [pod] <path> Copy host files into a pod\n receive [pod] <path> Copy pod files into the current directory\n archive [pod…] Hide pods from the list (files kept; restore brings them back)\n restore [pod…] Bring archived pods back\n gc Report retention state; --delete removes reclaimable pods\n\nAccount commands:\n login Sign in to a pi pod server via Zitadel\n logout Revoke this session and delete the stored credentials\n whoami Show the signed-in account\n account Open the Zitadel self-service console\n org-admin Open the Zitadel Console for this organization\n billing Open Stripe Checkout or the billing portal (authenticated)\n credentials Connect account model-provider sign-ins\n\nConfiguration commands:\n init Scaffold .pi-pod/ config, env, env.example, and init.sh\n templates Manage account templates\n push Upload a local config layer to its server bundle\n pull Write a server bundle into its local config layer\n diff Show local vs server drift for a config layer\n secrets Manage server and project secret scopes\n settings Show or edit one server settings config directly\n jobs Manage server-scheduled jobs\n\nMaintenance commands:\n doctor Check auth, server, org, and launch-resolution layers\n update Upgrade pi pod itself\n\nLaunch options:\n --template <name|id> Launch from an account template\n --on <pod|self> Co-locate the new pod on an existing pod's machine\n --reuse Restart this project's newest stopped pod instead of creating one\n --no-seed Start the pod with an empty workspace (skip workspace seeding)\n --dry-run Resolve and print the launch plan; create nothing\n\nGeneral options:\n -y, --yes Skip supported confirmations\n -v, --verbose Debug logging (secrets redacted)\n --version Print CLI, Node, and bundled Pi versions\n -h, --help Show help\n\nSettings resolve on the server: built-in → org → org-template → user → user-template\n→ org policy. Each bundle has a local directory as its source of truth (see\n\\`pipod push --help\\`); local project settings apply after \\`pipod push\\`, and the\nfirst launch in a project offers to bootstrap a template.\n\nPer-launch Pi resources (--extension, --skill, --prompt-template) name files or\ndirectories inside the pod as absolute paths and add to the pod's configured Pi\nresources for that launch; anything else Pi-related belongs in the pi.args config.\n\nWorkspace seeding: launching from a directory with no .pi-pod/config.json seeds the\nnew pod from that directory (its git repository root when inside one). A clean,\npushed checkout whose remote tip matches HEAD is cloned at that exact commit;\nanything else — dirty trees, unpushed commits, private remotes without usable\ncredentials, plain directories — is streamed in as a tar archive (git-ignored\npaths, node_modules and .pi-pod/env excluded). Private-remote credentials are\nforwarded only after a prompt (\\`--yes\\` approves it) and are never stored.\n\\`--dry-run\\` prints the decision without prompting or creating a pod. Forks,\nreused pods, \\`--on\\` co-location and \\`--no-seed\\` never seed.\n\nRun \\`pipod <command> --help\\` for command-specific usage.\n`;\n\nconst SUBCOMMAND_HELP: Record<Subcommand, string> = {\n login: `Usage: pipod login [--server <url>] [--issuer <url>] [--org <alias>] [--token <jwt>]\n\nSign this machine in to a pi pod server via Zitadel (authorization code + PKCE,\nin your browser). The session is stored in ~/.pi-pod/auth.json.\n\nOptions:\n --server <url> Server to sign in to (default: the previous session's server,\n $PI_POD_ACCOUNT_URL, or the production server)\n --issuer <url> OIDC issuer (default: $PI_POD_ISSUER, else the one the\n server publishes); needed only for a server too old to\n publish its own\n --org <alias> Only sign in to the organization with this primary domain;\n omit it to sign in to your own organization\n --token <jwt> Use an existing access token instead of the browser flow (dev/CI)\n`,\n account: `Usage: pipod account\n\nOpen the Zitadel self-service console in your browser to manage profile,\npassword, MFA, and active sessions.\n`,\n \"org-admin\": `Usage: pipod org-admin\n\nOpen the Zitadel Console in your browser. Organization owners manage members\nand role grants there.\n`,\n billing: `Usage: pipod billing checkout [--plan standard|pro] [--trial]\n pipod billing portal\n pipod billing change --plan standard|pro [--yes]\n pipod billing change preview --plan standard|pro\n pipod billing change confirm --quote <quoteId> [--yes]\n\nAuthenticated Stripe Checkout and billing portal. Checkout sends trial:false\n(paid) unless --trial. Closed public trial refuses --trial with 402. Change\npreviews a Standard<->Pro plan change and confirms it only after an explicit\nyes; stale quotes are never auto-confirmed. Return\npages do not grant a plan. Public npm is not a supported install path; use a\nGitHub release tarball or git clone + npm run build.\n`,\n logout: `Usage: pipod logout\n\nRevoke the current account session and delete ~/.pi-pod/auth.json. Pod\noperations are unavailable until the next \\`pipod login\\`.\n`,\n whoami: `Usage: pipod whoami\n\nShow the signed-in server, user, permissions, active organization, and console\nlinks. Exits 1 when signed out.\n`,\n init: `Usage: pipod init [--force]\n\nScaffold project configuration under .pi-pod/ in the current directory:\nconfig.json, env.example, env (mode 600), and init.sh.\n\nOptions:\n --force Overwrite scaffold files that already exist\n`,\n doctor: `Usage: pipod doctor [--template <name|id>]\n\nCheck each layer a launch depends on: account auth, server reachability and\nversion, organization membership and roles, secret references, and the\nserver-resolved settings bundle chain for this directory. Works while signed\nout to diagnose auth problems. Exits non-zero when a layer fails.\n\nOptions:\n --template <name|id> Plan the checked launch with this template\n`,\n list: `Usage: pipod list [pod] [--all] [--archived] [--template <name|id>] [--quiet]\n\nAlias: ls\n\nList pods on the signed-in server with stable short refs (p-…). The project is\nthe directory's git repository (or the directory, or its .pi-pod/ config): a\nlisting shows that project's pods when it has any — its pinned template's when\nit pins one — and every pod otherwise. Co-located pods are grouped under the pod\nwhose machine they share, with an ON column naming it.\nWith a pod argument, show just that machine's group: the pod and everything\nco-located on it.\n\nStatus says where a pod's files are: a stopped pod keeps them on disk and restarts on\nattach; an archived workspace is restored on next use, which takes longer the bigger it is.\nPods you archive stay hidden unless --archived is passed.\n\nOptions:\n -a, --all Every pod; ignore the current project and its template pin\n --archived Include logically archived pods\n --template <name|id> Only pods launched from that template (whole account)\n -q, --quiet Print pod ids only, one per line\n`,\n attach: `Usage: pipod attach [pod] [--yes] [-- <prompt…> [--tui-mode <mode>]]\n\nAlias: a\n\nReconnect to a pod session through the server gateway. Name the pod by id,\nshort ref (p-…), or name; omit it when this project has exactly one pod.\nQuitting detaches: the pod keeps running until the server's idle policy reaps\nit or \\`pipod stop\\` stops it. Raw pod shells are not available.\nAttaching to an archived pod offers to restore it first.\n\nAfter --:\n <prompt…> Words are sent to the session as a startup prompt\n --tui-mode <mode> Local TUI layout for this attach: regular or fullscreen\n\nOptions:\n -y, --yes Restore an archived pod without asking\n`,\n stop: `Usage: pipod stop [pod…]\n\nStop pods now by id, short ref (p-…), or name; omit the argument when this\nproject has exactly one pod. Stopped pods keep their files and \\`pipod attach\\`\nrestarts them. Stopping a pod that hosts co-located pods stops those too.\n`,\n fork: `Usage: pipod fork <pod> [--session <path>] [launch options] [-- <pi args…>]\n\nLaunch a new pod whose session starts as a fork of <pod>'s current session.\n<pod> is an id, short ref (p-…), or name. The workspace is not copied —\ncommit and push first if the new pod needs those changes. --on is not\nsupported: a fork launches a new sandbox, not a co-located pod.\n\nOptions:\n --session <path> Fork a specific session file instead of the newest\n --template <name|id> Launch the new pod from an account template\n --dry-run Resolve and print the launch plan; create nothing\n -y, --yes Skip supported confirmations\n`,\n rename: `Usage: pipod rename <pod> <name>\n\nRename a server-managed pod. <pod> is an id, short ref (p-…), or the current\nname.\n`,\n send: `Usage: pipod send [pod] <path> [--yes]\n\nCopy a host file or directory into a pod through the server. Omit the pod when\nthis project has exactly one. Sending to an archived pod offers to restore it\nfirst.\n\nOptions:\n -y, --yes Restore an archived pod without asking\n`,\n receive: `Usage: pipod receive [pod] <path> [--yes]\n\nCopy a file or directory from a pod into the current local directory. <path>\nmay be a workdir-relative path or an absolute path inside that workdir, such\nas foo or /workspace/foo. The destination must not already exist. Omit the\npod when this project has exactly one. Receiving from an archived pod offers\nto restore it first.\n\nOptions:\n -y, --yes Restore an archived pod without asking\n`,\n archive: `Usage: pipod archive [pod…] [--all] [--template <name|id>] [--idle <duration>] [--dry-run] [--yes]\n\nArchive pods by id, short ref (p-…), or name. Archiving hides pods from\n\\`pipod list\\` (\\`pipod list --archived\\` shows them); it never deletes work, and\n\\`pipod restore\\` brings them back. Archiving a pod that hosts co-located pods\narchives those too.\n\nOptions:\n -a, --all Archive every pod (cannot be combined with pod refs)\n --template <name|id> Only pods launched from that template (whole account)\n --idle <duration> Only pods whose last activity is older than this (4h, 2d, 30m)\n --dry-run Print the matching pods; archive nothing\n -y, --yes Skip the bulk confirmation\n`,\n restore: `Usage: pipod restore [pod…] [--all] [--yes]\n\nBring archived pods back by id, short ref (p-…), or name. Restoring a host\nrestores the co-located pods archived with it. \\`pipod attach\\` then starts the\npod; a workspace in cold storage takes longer the bigger it is.\n\nOptions:\n -a, --all Restore every archived pod (cannot be combined with pod refs)\n -y, --yes Skip the --all confirmation\n`,\n gc: `Usage: pipod gc [--delete] [--yes]\n\nList the archived and failed pods that can be deleted for good; --delete deletes\nthem. (The server stops idle pods and moves stopped workspaces to cold storage on\nits own schedule; that never deletes anything.)\n\nOptions:\n --delete Permanently delete the reclaimable pods\n -y, --yes Delete without a confirmation prompt\n`,\n jobs: `Usage: pipod jobs [action] [args] [--quiet] [--yes] [--project] [--org]\n\nManage scheduled jobs the pi pod server runs for you: at each trigger it\nlaunches a pod from the job's template and sends the job's prompt. Local job\nfiles in .pi-pod/jobs/ (project) or ~/.pi-pod/jobs/ (user) are the reviewable\nsource; \\`jobs push\\` promotes them to the server. <job> is an id, short ref\n(j-…), or name.\n\nActions:\n list List server jobs (default)\n show <job> Show a job's schedule, template, model, and prompt\n runs <job> List a job's recent runs\n run <job> Run an active job once, now; its schedule is unchanged\n activate <job> Activate a job\n pause <job> Pause a job's schedule\n resume <job> Resume a paused job\n rm <job> Remove a job; its schedule stops firing\n push [job…] Create or update server jobs from local job files\n pull <job> Write a server job to a local job file\n diff [job…] Show local vs server drift; exits 1 when drifted\n\nOptions:\n --org push: create org-scoped jobs or promote matching user jobs\n (promotion is one-way)\n --project pull: write into this project's .pi-pod/jobs/ instead of\n ~/.pi-pod/jobs/\n -q, --quiet list: print job ids only, one per line\n -y, --yes Skip confirmations; pull: overwrite an existing local file\n`,\n credentials: `Usage: pipod credentials [action]\n\nManage account-scoped model-provider sign-ins. Connected credentials apply to\nevery pod you launch; OAuth refresh tokens stay in server custody and never\nreach pods or this machine.\n\nActions:\n list Saved credentials and connectable providers (default)\n connect Connect every provider your local pi is signed in to:\n API keys are imported, everything else is a fresh\n account login; ready credentials are left alone\n connect <provider> Sign in to a provider (OAuth by default)\n reconnect <provider> Redo the sign-in for a saved credential\n test <provider> Verify a saved credential against the provider\n remove <provider> [--yes] Delete a saved credential (alias: rm)\n\nconnect options:\n --api-key Enter an API key instead of the OAuth flow\n --api-key --from-pi Import the API key your local pi resolves for that\n provider (auth.json or env) instead of typing it.\n OAuth grants are never imported.\n`,\n secrets: `Usage: pipod secrets [action]\n\nManage the secret layers pods see. Requires account or pod-token auth. Server\nscopes are org, user, and template/<name>; project is this project's dotenv\nfile, the highest-precedence layer for launches from the project.\n\nActions:\n list Every secret a pod launched here would see,\n which layer wins, and who set it (default)\n set <scope> <NAME> Store a secret, its value read from a hidden\n prompt or stdin (never the command line)\n rm <scope> <NAME> Remove a secret (aliases: remove, unset)\n sync <scope> Upload a dotenv file to a server scope\n\nsync options (scope must be org, user, or template/<name>):\n --file <path> Dotenv file to upload (default: ~/.pi-pod/secrets/<scope>.env)\n --prune Also delete server secrets that are not in the file\n --dry-run Show what would change without writing\n\nValues may be op:// references; they resolve just-in-time (at upload for\nserver scopes, at launch for the project file) and the references themselves\nare never stored on the server.\n`,\n templates: `Usage: pipod templates [action]\n\nManage pod templates on the pi pod server. A template stores config, init and\nbake scripts, Pi settings files, and named secrets. Templates are personal by\ndefault: only their owner sees and launches them. --org at creation or\n\\`templates share\\` makes one org-wide.\n\nActions:\n list List templates with scope and key counts (default)\n show <name|id> Show config, scripts, Pi settings, and secret names\n create <name> Create a template\n edit <name|id> Update a template's name, description, config, or scripts\n share <name|id> Make a personal template org-wide (cannot be undone)\n rm <name|id> Delete a template (alias: delete)\n\ncreate/edit options:\n --name <name> New name (edit only)\n --description <text> Set the description\n --config <file> Store this config file (same shape as .pi-pod/config.json)\n --from-here create only: store this project's authored config,\n scripts, and sanitized Pi files (contradicts --config)\n --init-script <file> Store this init script\n --bake-script <file> Store this bake script\n --org create only: make the template org-wide from the start\n --with-secrets With --from-here: also upload project env values as\n template secrets\n -y, --yes Skip confirmations (rm)\n`,\n push: `Usage: pipod push [template [<name>] | user | org] [--dir <path>]\n [--with-secrets] [--yes]\n\nReplace a server config bundle with its local source, whole. The layer names\nboth sides; edit the local files with any editor, then push. A diff preview\nprecedes the confirmation.\n\nLayers and their local source:\n template [<name>] This project: .pi-pod/config.json, its init and bake\n scripts, Pi files under .pi/, and the project env file\n (secrets, with --with-secrets or a prompt). Without\n <name> the project's pinned template is used.\n user ~/.pi-pod/config.json and ~/.pi/agent/ (settings.json,\n models.json, mcporter.json, subagents.json, agents/)\n org ~/.pi-pod/org/: config.json, init.sh, bake.sh, pi/…, and\n an optional env file whose values become org secrets\n\nInside a project the layer defaults to template; elsewhere it is required.\nProvider credentials, hooks, mcpServers, and model credential values never\nleave this machine.\n\nOptions:\n --dir <path> org only: read the org source from <path> instead\n --with-secrets Also upload the layer's env values as secrets\n -y, --yes Apply the replacement without the confirmation prompt\n`,\n pull: `Usage: pipod pull [template [<name>] | user | org] [--dir <path>] [--yes]\n\nWrite a server config bundle into its local source files (see\n\\`pipod push --help\\` for the layer → directory table). A diff preview\nprecedes the confirmation; nothing is written when the two already match.\n\nWhat pull keeps from the local files:\n config.json client-only keys: $schema, template, secretResolver,\n pi.chords, pi.sessionNaming\n settings.json hooks and mcpServers (and packages when hostConfig.packages\n is off)\n models.json credential values the push had dropped\n agents/ files the bundle no longer contains are removed\n\nSecrets stay on the server; their names are listed. The user layer has no\nlocal script files, so user bundle scripts are shown but not written.\n\nOptions:\n --dir <path> org only: write the org source to <path> instead\n -y, --yes Apply the local changes without the confirmation prompt\n`,\n diff: `Usage: pipod diff [template [<name>] | user | org] [--dir <path>]\n\nCompare a config layer's local source with its server bundle (see\n\\`pipod push --help\\` for the layer → directory table). Secrets compare by\nname only. Exits 1 when they differ, 0 when they match.\n\nOptions:\n --dir <path> org only: read the org source from <path> instead\n`,\n settings: `Usage: pipod settings <user|org> [show | edit | set <key> <value> | unset <key>]\n\nShow or edit a persistent settings bundle on the server: your own user bundle,\nor the org-wide defaults (org scope needs the org:manage permission). Edits\nchange only the config; scripts and Pi files stay as they are — replace the\nwhole bundle from local files with \\`pipod push user\\` or \\`pipod push org\\`.\nEdits use compare-and-swap on the bundle version, so concurrent changes fail\ncleanly instead of overwriting each other.\n\nActions:\n show Print the settings bundle as JSON (default)\n edit Edit the config in $VISUAL/$EDITOR, then save\n set <key> <value> Set one dotted key to a JSON value, or to the text as\n a string: pipod settings user set pi.model provider/model\n unset <key> Remove one dotted key, so the layers below decide it\n`,\n update: `Usage: pipod update [--dry-run]\n\nUpgrade pi pod itself: a registry install updates to the latest published\nversion; a git checkout pulls its upstream and rebuilds.\n\nOptions:\n --dry-run Report what an update would do without changing anything\n`,\n};\n\nexport interface GlobalFlags {\n /** `--on <pod|self>`: co-locate the launch on an existing pod's machine. */\n on?: string;\n reuse?: boolean;\n /** `--no-seed`: leave a fresh pod's workspace empty. */\n seed?: boolean;\n dryRun: boolean;\n verbose: boolean;\n help: boolean;\n version: boolean;\n all: boolean;\n yes: boolean;\n destroy: boolean;\n quiet: boolean;\n archived: boolean;\n template?: string;\n /** `archive --idle <duration>`: only pods whose last activity is older than this. */\n idle?: string;\n project?: boolean;\n force: boolean;\n server?: string;\n org?: string;\n jobsOrg?: boolean;\n token?: string;\n session?: string;\n issuer?: string;\n}\n\nexport interface ParsedArgs {\n subcommand: Subcommand | null;\n subcommandArgs: string[];\n flags: GlobalFlags;\n piArgs: string[];\n seenFlags: Set<string>;\n}\n\nconst SELF_PARSING_SUBCOMMANDS = new Set<Subcommand>([\"credentials\", \"secrets\", \"templates\", \"push\", \"pull\", \"diff\", \"settings\", \"billing\"]);\nconst UNIVERSAL_FLAGS = new Set([\"--verbose\", \"--version\", \"--help\"]);\nconst FLAG_SCOPE: Record<string, ReadonlySet<string>> = {\n \"--template\": new Set([\"launch\", \"list\", \"doctor\", \"fork\", \"archive\"]),\n \"--project\": new Set([\"jobs\"]),\n \"--on\": new Set([\"launch\"]),\n \"--reuse\": new Set([\"launch\"]),\n \"--no-seed\": new Set([\"launch\"]),\n \"--dry-run\": new Set([\"launch\", \"update\", \"fork\", \"archive\"]),\n \"--idle\": new Set([\"archive\"]),\n \"--session\": new Set([\"fork\"]),\n \"--all\": new Set([\"list\", \"archive\", \"restore\"]),\n \"--yes\": new Set([\"launch\", \"fork\", \"archive\", \"restore\", \"gc\", \"jobs\", \"credentials\", \"templates\", \"attach\", \"send\", \"receive\", \"push\", \"pull\"]),\n \"--delete\": new Set([\"gc\"]),\n \"--quiet\": new Set([\"list\", \"jobs\"]),\n \"--archived\": new Set([\"list\"]),\n \"--force\": new Set([\"init\"]),\n \"--server\": new Set([\"login\"]),\n \"--org\": new Set([\"login\", \"jobs\"]),\n \"--token\": new Set([\"login\"]),\n \"--issuer\": new Set([\"login\"]),\n};\n\nfunction resolveSubcommand(positional: string | undefined): Subcommand | null {\n if (positional === undefined) return null;\n const resolved = ALIASES[positional] ?? positional;\n return (SUBCOMMANDS as readonly string[]).includes(resolved) ? resolved as Subcommand : null;\n}\n\nexport function checkFlagScope(subcommand: string | null, seenFlags: ReadonlySet<string>): string[] {\n const command = subcommand ?? \"launch\";\n const ignored: string[] = [];\n for (const flag of seenFlags) {\n if (UNIVERSAL_FLAGS.has(flag)) continue;\n const scope = FLAG_SCOPE[flag];\n if (!scope || scope.has(command)) continue;\n if (flag === \"--dry-run\") {\n throw new PiPodError(`--dry-run is not supported by \\`pipod ${subcommand}\\``, {\n hint: \"nothing was done — remove the flag to run the command for real\",\n exitCode: EXIT.USAGE,\n });\n }\n if (flag === \"--on\" && command === \"fork\") {\n throw new PiPodError(\"forking into a co-located pod is not supported yet\", {\n hint: \"fork without --on, or launch a plain co-located pod\",\n exitCode: EXIT.USAGE,\n });\n }\n ignored.push(flag);\n }\n return ignored;\n}\n\nexport function parseArgs(argv: string[]): ParsedArgs {\n const flags: GlobalFlags = {\n dryRun: false,\n verbose: false,\n help: false,\n version: false,\n all: false,\n yes: false,\n destroy: false,\n quiet: false,\n archived: false,\n force: false,\n };\n const positionals: string[] = [];\n const piArgs: string[] = [];\n const seenFlags = new Set<string>();\n\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i]!;\n if (arg === \"--\") {\n piArgs.push(...argv.slice(i + 1));\n break;\n }\n if (!arg.startsWith(\"-\")) {\n positionals.push(arg);\n const command = positionals.length === 1 ? resolveSubcommand(arg) : null;\n if (command && SELF_PARSING_SUBCOMMANDS.has(command)) {\n const tail = argv.slice(i + 1);\n positionals.push(...tail.filter((entry) => entry !== \"--help\" && entry !== \"-h\"));\n if (tail.some((entry) => entry === \"--help\" || entry === \"-h\")) flags.help = true;\n break;\n }\n continue;\n }\n\n const equals = arg.indexOf(\"=\");\n const name = equals >= 0 ? arg.slice(0, equals) : arg;\n const inlineValue = equals >= 0 ? arg.slice(equals + 1) : undefined;\n const takeValue = (): string => {\n if (inlineValue !== undefined) return inlineValue;\n const value = argv[++i];\n if (value === undefined) throw new PiPodError(`${name} requires a value`, { exitCode: EXIT.USAGE });\n return value;\n };\n const canonical = canonicalFlagName(name);\n seenFlags.add(canonical);\n\n switch (name) {\n case \"--on\": flags.on = takeValue(); break;\n case \"--reuse\": flags.reuse = true; break;\n case \"--no-seed\": flags.seed = false; break;\n case \"--dry-run\": flags.dryRun = true; break;\n case \"--verbose\":\n case \"-v\": flags.verbose = true; break;\n case \"--version\": flags.version = true; break;\n case \"--help\":\n case \"-h\": flags.help = true; break;\n case \"--all\":\n case \"-a\": flags.all = true; break;\n case \"--yes\":\n case \"-y\": flags.yes = true; break;\n case \"--delete\": flags.destroy = true; break;\n case \"--quiet\":\n case \"-q\": flags.quiet = true; break;\n case \"--archived\": flags.archived = true; break;\n case \"--template\": flags.template = takeValue(); break;\n case \"--idle\": flags.idle = takeValue(); break;\n case \"--project\": flags.project = true; break;\n case \"--force\": flags.force = true; break;\n case \"--server\": flags.server = takeValue(); break;\n case \"--org\":\n if (resolveSubcommand(positionals[0]) === \"jobs\") flags.jobsOrg = true;\n else flags.org = takeValue();\n break;\n case \"--token\": flags.token = takeValue(); break;\n case \"--session\": flags.session = takeValue(); break;\n case \"--issuer\": flags.issuer = takeValue(); break;\n default:\n throw new PiPodError(`unknown pi pod option \"${name}\"`, {\n hint: \"pass Pi options after `--`, for example: pipod -- --model claude-opus\",\n exitCode: EXIT.USAGE,\n });\n }\n }\n\n let commandPositionals = positionals;\n if (positionals[0] === \"help\") {\n flags.help = true;\n seenFlags.add(\"--help\");\n commandPositionals = positionals.slice(1);\n }\n const subcommand = resolveSubcommand(commandPositionals[0]);\n if (!subcommand && commandPositionals.length > 0) {\n throw new PiPodError(`unknown pi pod command \"${commandPositionals[0]}\"`, {\n hint: \"pass all Pi arguments after `--`, for example: pipod -- \\\"review this change\\\"\",\n exitCode: EXIT.USAGE,\n });\n }\n if (subcommand === \"jobs\" && flags.org !== undefined) {\n // `--org` before `jobs` parses login-style and takes a value; for jobs it is a\n // boolean that belongs after the action. Fail rather than silently scoping wrong.\n throw new PiPodError(`--org ${flags.org} does not apply here`, {\n hint: \"for jobs it is a flag after the action: `pipod jobs push --org` (login takes `--org <alias>`)\",\n exitCode: EXIT.USAGE,\n });\n }\n return {\n subcommand,\n subcommandArgs: subcommand ? commandPositionals.slice(1) : [],\n flags,\n piArgs,\n seenFlags,\n };\n}\n\nfunction canonicalFlagName(name: string): string {\n switch (name) {\n case \"-v\": return \"--verbose\";\n case \"-h\": return \"--help\";\n case \"-a\": return \"--all\";\n case \"-y\": return \"--yes\";\n case \"-q\": return \"--quiet\";\n default: return name;\n }\n}\n\nexport async function main(argv: string[]): Promise<number> {\n const { subcommand, subcommandArgs, flags, piArgs, seenFlags } = parseArgs(argv);\n setVerbose(flags.verbose);\n if (flags.help) {\n process.stdout.write(subcommand ? SUBCOMMAND_HELP[subcommand] : HELP);\n return EXIT.OK;\n }\n for (const flag of checkFlagScope(subcommand, seenFlags)) {\n warn(`${flag} has no effect with \\`pipod ${subcommand}\\` — ignoring it`);\n }\n announceUserConfig();\n if (flags.version) return printVersion();\n\n switch (subcommand) {\n case \"init\":\n return runInit(flags);\n case \"login\":\n return runLogin({ server: flags.server, org: flags.org, token: flags.token, issuer: flags.issuer });\n case \"whoami\":\n return runWhoami({});\n case \"logout\":\n return runLogout({});\n case \"doctor\":\n return runAccountDoctor({\n template: flags.template,\n });\n case \"update\":\n await runUpdate({ dryRun: flags.dryRun });\n return EXIT.OK;\n }\n\n const account = requireAccountClient();\n switch (subcommand) {\n case \"account\":\n return runOpenAccount({});\n case \"org-admin\":\n return runOpenOrgAdmin({});\n case \"billing\":\n return runBillingCommand(account, subcommandArgs);\n case \"gc\":\n return runAccountGc(account, { ...podFlagsOf(flags), destroy: flags.destroy });\n case \"attach\":\n return runAccountAttach(account, subcommandArgs, piArgs, { yes: flags.yes });\n case \"list\":\n return runAccountList(account, podFlagsOf(flags), subcommandArgs[0]);\n case \"stop\":\n return runAccountStop(account, subcommandArgs, podFlagsOf(flags));\n case \"rename\":\n return runAccountRename(account, subcommandArgs);\n case \"fork\":\n return runAccountFork(account, subcommandArgs, {\n yes: flags.yes,\n dryRun: flags.dryRun,\n template: flags.template,\n session: flags.session,\n on: flags.on,\n }, piArgs);\n case \"send\":\n return runAccountSend(account, subcommandArgs, { yes: flags.yes });\n case \"receive\":\n return runAccountReceive(account, subcommandArgs, { yes: flags.yes });\n case \"archive\":\n return runAccountPodAction(account, subcommandArgs, podFlagsOf(flags), \"archive\");\n case \"restore\":\n return runAccountPodAction(account, subcommandArgs, podFlagsOf(flags), \"restore\");\n case \"jobs\":\n return runAccountJobs(account, subcommandArgs, {\n quiet: flags.quiet,\n yes: flags.yes,\n project: flags.project,\n org: flags.jobsOrg,\n });\n case \"credentials\":\n return runCredentials(subcommandArgs, { client: account, yes: flags.yes });\n case \"secrets\":\n return runSecrets(subcommandArgs, { client: account, yes: flags.yes });\n case \"templates\":\n return runTemplates(subcommandArgs, { client: account, yes: flags.yes });\n case \"push\":\n return runPush(subcommandArgs, { client: account, yes: flags.yes });\n case \"pull\":\n return runPull(subcommandArgs, { client: account, yes: flags.yes });\n case \"diff\":\n return runDiff(subcommandArgs, { client: account });\n case \"settings\":\n return runSettings(subcommandArgs, { client: account });\n default:\n return runAccountLaunch({\n client: account,\n flags: {\n yes: flags.yes,\n on: flags.on,\n reuse: flags.reuse,\n seed: flags.seed,\n dryRun: flags.dryRun,\n template: flags.template,\n },\n piArgs,\n });\n }\n}\n\nfunction podFlagsOf(flags: GlobalFlags): AccountPodFlags {\n return {\n all: flags.all,\n quiet: flags.quiet,\n archived: flags.archived,\n yes: flags.yes,\n template: flags.template,\n idle: flags.idle,\n dryRun: flags.dryRun,\n };\n}\n\nfunction announceUserConfig(): void {\n const result = ensureUserConfig();\n for (const file of result.created) info(`created ${color.bold(displayPath(file))}, this machine's pi pod preferences`);\n}\n\nfunction runInit(flags: GlobalFlags): number {\n const cwd = process.cwd();\n const existing = findConfigPath(cwd);\n if (existing !== null && path.dirname(path.dirname(existing)) !== fs.realpathSync(cwd)) {\n info(`note: ${color.bold(displayPath(existing))} defines an enclosing project; this scaffold shadows it here`);\n }\n const result = scaffold({ projectRoot: cwd, force: flags.force });\n printInitResult(result, cwd);\n return EXIT.OK;\n}\n\nfunction printVersion(): number {\n out(`pipod ${VERSION}`);\n out(`node ${process.versions.node}`);\n out(`pi ${bundledPiVersion()}`);\n return EXIT.OK;\n}\n\nexport function reportError(errorValue: unknown): number {\n if (errorValue instanceof CancelledError) {\n error(errorValue.message);\n return errorValue.exitCode;\n }\n if (isPiPodError(errorValue)) {\n error(errorValue.message);\n if (errorValue.hint) printHint(errorValue.hint);\n if (isVerbose() && errorValue.cause) plain(String(errorValue.cause));\n return errorValue.exitCode;\n }\n error(errorValue instanceof Error ? errorValue.message : String(errorValue));\n if (errorValue instanceof Error && errorValue.stack) plain(color.dim(errorValue.stack));\n return EXIT.FAILURE;\n}\n\nconst invokedDirectly =\n process.argv[1] !== undefined &&\n [\"cli.js\", \"cli.ts\", \"pipod\", \"pi-pod\", \"pp\"].includes(path.basename(process.argv[1]));\n\nif (invokedDirectly) {\n // `pipod list | head` closes the pipe early; the reader has what it wanted.\n for (const stream of [process.stdout, process.stderr]) {\n stream.on(\"error\", (failure: NodeJS.ErrnoException) => {\n if (failure.code === \"EPIPE\") process.exit(process.exitCode ?? 0);\n throw failure;\n });\n }\n main(process.argv.slice(2))\n .then((code) => { process.exitCode = code; })\n .catch((failure) => { process.exitCode = reportError(failure); });\n}\n","/** Exit codes used by the launcher. Remote pi exit codes pass through unchanged (§8). */\nexport const EXIT = {\n OK: 0,\n /** Launcher-level failure (preflight, provisioning, teardown). */\n FAILURE: 1,\n /** Bad CLI usage. */\n USAGE: 2,\n /** Interrupted (Ctrl-C) — §9. */\n INTERRUPTED: 130,\n} as const;\n\n/**\n * An error that is the user's to fix. Printed without a stack trace, with a remediation\n * hint when there is one. Everything else is a bug and prints a full stack.\n */\nexport class PiPodError extends Error {\n readonly hint?: string;\n readonly exitCode: number;\n /** HTTP status when this came from a server response, so callers can tell 404 from 502. */\n readonly status?: number;\n /** A stable machine-readable server/protocol error code, when one is available. */\n readonly code?: string;\n /** A blip — an unreachable server or a 5xx — rather than a refusal that will repeat. */\n readonly transient: boolean;\n /**\n * Safe server `detail` payload passthrough (capacity `reason`/`retryable` hints,\n * credential metadata). Presenters must render only validated codes/numbers from it —\n * never raw provider text, URLs, or secrets.\n */\n readonly detail?: unknown;\n\n constructor(\n message: string,\n opts: {\n hint?: string;\n exitCode?: number;\n cause?: unknown;\n status?: number;\n code?: string;\n transient?: boolean;\n detail?: unknown;\n } = {},\n ) {\n super(message, opts.cause !== undefined ? { cause: opts.cause } : undefined);\n this.name = \"PiPodError\";\n this.hint = opts.hint;\n this.exitCode = opts.exitCode ?? EXIT.FAILURE;\n this.status = opts.status;\n this.code = opts.code;\n this.transient = opts.transient ?? (opts.status !== undefined && opts.status >= 500);\n this.detail = opts.detail;\n }\n}\n\n/** Raised when the user cancels (Ctrl-C, or declining a confirmation). */\nexport class CancelledError extends PiPodError {\n constructor(message = \"Cancelled\") {\n super(message, { exitCode: EXIT.INTERRUPTED });\n this.name = \"CancelledError\";\n }\n}\n\nexport function isPiPodError(e: unknown): e is PiPodError {\n return e instanceof PiPodError;\n}\n\nexport function errorMessage(e: unknown): string {\n if (e instanceof Error) return e.message;\n return String(e);\n}\n\n/**\n * Gateway close reasons (code 4420) that mean the user's whole personal workstation is not\n * up, rather than that this pod went to sleep on an otherwise running machine. The code is\n * the same for both, so only the reason tells them apart — and the difference is the\n * difference between seconds and the 243-to-708 seconds production measured for a workstation.\n *\n * It lives here rather than in `account/workstation.ts` because the error copy below needs it\n * and that module already depends on this one.\n */\nexport const WORKSTATION_ASLEEP_REASONS: ReadonlySet<string> = new Set([\n \"host_starting\",\n \"host_stopped\",\n \"host_archived\",\n]);\n\nexport function isWorkstationAsleepReason(reason: string): boolean {\n return WORKSTATION_ASLEEP_REASONS.has(reason);\n}\n\n/**\n * Close reasons where a later keystroke can still start the sandbox. Logical\n * archive (`archived`) restores in place on wake, then attaches.\n *\n * The workstation reasons are wakeable too — a keystroke asks the server to start the machine\n * — but they are not fast, and the copy below says so instead of promising seconds.\n */\nexport const WAKEABLE_ASLEEP_REASONS = new Set([\n \"idle_stop\",\n \"provider_stopped\",\n \"provider_archived\",\n \"archive\",\n \"archived\",\n ...WORKSTATION_ASLEEP_REASONS,\n]);\n\nexport function isWakeableAsleepReason(reason: string): boolean {\n return WAKEABLE_ASLEEP_REASONS.has(reason);\n\n}\n\nexport function isRestoreRequiredError(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error);\n const status = error instanceof PiPodError ? error.status : undefined;\n return status === 409 && /restore the pod/i.test(message);\n\n}\n\n/**\n * The gateway closed the session because the pod is stopped or archived (close 4420).\n * Distinct from a broken transport: the TUI stays up and a later user action can wake it.\n */\nexport class PodAsleepError extends PiPodError {\n readonly reason: string;\n\n constructor(reason: string) {\n super(\n isWorkstationAsleepReason(reason)\n ? `your workstation is not running (${reason})`\n : `pod is asleep (${reason})`,\n {\n hint: isWorkstationAsleepReason(reason)\n ? \"press Enter to start it — that takes several minutes, and your files are retained; /quit to exit\"\n : isWakeableAsleepReason(reason)\n ? reason === \"archived\" || reason === \"archive\" || reason === \"provider_archived\"\n ? \"press Enter to restore & reattach, or /quit to exit\"\n : \"press Enter or type to wake it, or /quit to exit\"\n : \"/quit to exit\",\n },\n );\n this.name = \"PodAsleepError\";\n this.reason = reason;\n }\n\n}\n\nexport function isPodAsleepError(e: unknown): e is PodAsleepError {\n return e instanceof PodAsleepError;\n\n}\n","/**\n * src/account/api.ts — the REST half of account mode (account-mode-spec §5, §7).\n *\n * A thin, typed client over the server's `/v1` surface. One deliberate behavior: a 401 is\n * retried exactly once by refreshing directly at Zitadel, rewriting `auth.json` with the new\n * pair, so a laptop that slept through a token expiry never surfaces it (§3.2). A failed\n * refresh names the fix (`pipod login`) instead of leaking an HTTP status.\n */\nimport * as fs from \"node:fs\";\nimport { Readable } from \"node:stream\";\nimport { PiPodError } from \"../errors.js\";\nimport { debug } from \"../log.js\";\nimport type { ConfigProvenanceEntry } from \"../userconfig.js\";\nimport { discover, refreshTokens, DEFAULT_CLIENT_ID } from \"./oidc.js\";\nimport { readAccountAuth, withAccountAuthLock, writeAccountAuth, type AccountAuth } from \"./store.js\";\nimport {\n isWorkstationHostId,\n parseWorkstationDemand,\n parseWorkstationStatus,\n WorkstationNotReadyError,\n type WorkstationStatus,\n} from \"./workstation.js\";\nimport {\n parseAccountBilling,\n parseBillingAccountPlan,\n parsePlanChangeQuote,\n type AccountBilling,\n type BillingAccountPlan,\n type BillingPlanKey,\n type PlanChangeQuoteView,\n} from \"./billing.js\";\n\nexport const REST_TIMEOUT_MS = 30_000;\n/** Extra time on top of a long-poll `wait` so a just-in-time answer is not raced. */\nexport const LONG_POLL_SLACK_MS = 10_000;\n/** A workspace clone runs a network fetch inside the sandbox; a large repository takes minutes. */\nexport const WORKSPACE_CLONE_TIMEOUT_MS = 15 * 60_000;\n/** Streaming a multi-hundred-MiB archive and extracting it in the sandbox is slow on purpose. */\nexport const WORKSPACE_ARCHIVE_TIMEOUT_MS = 30 * 60_000;\n/** The MIME type the archive route expects: a gzip-compressed POSIX tar stream. */\nexport const WORKSPACE_ARCHIVE_CONTENT_TYPE = \"application/x-tar+gzip\";\n\nexport interface ApiRequestOptions {\n method?: string;\n body?: unknown;\n query?: Record<string, string | number | boolean | undefined>;\n /** Expected \"not found is fine\" paths return null instead of throwing. */\n allow404?: boolean;\n /** Override the default fetch timeout (30s, or wait + slack for long-polls). */\n timeoutMs?: number;\n /** Caller-owned cancellation (Ctrl-C mid-upload); combined with the timeout. */\n signal?: AbortSignal;\n}\n\n/** A request whose body is a file on disk, streamed rather than read into memory. */\nexport interface ApiUploadOptions {\n method: \"PUT\" | \"POST\";\n filePath: string;\n contentType: string;\n /** Sent as Content-Length so the server can refuse an oversized body before reading it. */\n contentLength: number;\n timeoutMs?: number;\n signal?: AbortSignal;\n /** Called with cumulative bytes handed to the socket; drives the client-side progress line. */\n onProgress?: (sentBytes: number) => void;\n}\n\n/** Body of `POST /pods/:id/workspace/clone`; the credential travels once and is never stored. */\nexport interface WorkspaceCloneBody {\n url: string;\n branch: string;\n commit: string;\n credential?: { username: string; password: string };\n}\n\n/** What the workspace seed routes answer; every field is optional because the contract is additive. */\nexport interface WorkspaceSeedResult {\n id?: string;\n kind?: \"clone\" | \"archive\";\n status?: WorkspaceSeedReport[\"status\"];\n /** Present when the server measured the transfer; clients only display it. */\n bytes?: number;\n uncompressedBytes?: number;\n entries?: number;\n commit?: string;\n durationMs?: number;\n /** True when this call opened a seed gate and Pi is starting now. */\n piStarting?: boolean;\n}\n\n/**\n * The server's frozen record of a pod's workspace seed. `pending` is the seed gate: the launch\n * asked the server to hold Pi until the client fills the workdir. Safe metadata only.\n */\nexport interface WorkspaceSeedReport {\n status: \"pending\" | \"seeding\" | \"seeded\" | \"failed\" | \"skipped\";\n kind?: \"clone\" | \"archive\";\n requestedAt: string;\n startedAt?: string;\n finishedAt?: string;\n durationMs?: number;\n bytes?: number;\n entries?: number;\n host?: string;\n branch?: string;\n commit?: string;\n credentialed?: boolean;\n reason?: string;\n}\n\n/** The three secret scopes the server stores; `machine` and `project` are local files. */\nexport type ServerSecretScope = \"org\" | \"user\" | \"template\";\n\nexport interface ApiSecret {\n name: string;\n scopeType: ServerSecretScope;\n scopeId: string;\n updatedAt: string;\n createdBy?: string;\n}\n\nexport interface ApiTemplate {\n id: string;\n name: string;\n description: string | null;\n status: \"active\";\n /** Older servers predate scoping and treat every template as org-wide. */\n scope?: \"user\" | \"org\";\n initScript: string | null;\n /** Older servers omit this; treat as unset rather than empty. */\n bakeScript?: string | null;\n config: Record<string, unknown>;\n /** Sanitized flat Pi files owned by this template. Legacy servers may return two scopes. */\n piSettings?: PiSettingsFilesBody | PiSettingsBundleBody;\n /** Optional on servers that expose a monotonic template revision. */\n version?: number;\n createdFromPod?: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface TemplateBody {\n name: string;\n description?: string;\n initScript?: string;\n bakeScript?: string;\n scope?: \"user\" | \"org\";\n config: Record<string, unknown>;\n /** Explicit template custody. The CLI always writes the flat file map; the two-scope read shape stays accepted on responses only. */\n piSettings?: PiSettingsFilesBody;\n}\n\nexport interface PiSettingsFilesBody {\n settings?: Record<string, unknown>;\n models?: Record<string, unknown>;\n mcporter?: Record<string, unknown>;\n subagents?: Record<string, unknown>;\n /** UTF-8 file contents keyed by path relative to this scope's `.pi/agents/`. */\n agents?: Record<string, string>;\n}\n\n/** The single sanitized two-scope Pi bundle used by project uploads and template custody. */\nexport interface PiSettingsBundleBody {\n user?: PiSettingsFilesBody;\n project?: Pick<PiSettingsFilesBody, \"settings\" | \"mcporter\" | \"subagents\" | \"agents\">;\n}\n\n/** Persistent user/org bundle returned by the settings API. */\nexport interface ApiSettingsBundle {\n config: Record<string, unknown>;\n version: number;\n initScript: string;\n bakeScript: string;\n piFiles: PiSettingsFilesBody;\n}\n\n/** CAS body: omitted scripts/files stay unchanged; empty values clear them. */\nexport interface PutSettingsBundleBody {\n config: Record<string, unknown>;\n version: number;\n initScript?: string;\n bakeScript?: string;\n piFiles?: PiSettingsFilesBody;\n}\n\n/**\n * Bounded capacity-wait view (capacity contract §1). Present only while a launch or wake\n * is queued for room; null when the pod never queued. Older servers omit the field —\n * treat a missing value exactly like null and run today's immediate-error flow.\n */\nexport interface CapacityWaitDetail {\n kind: \"admission\";\n reason: string;\n resource?: string;\n unit?: string;\n retryable?: boolean;\n retryAfterMs?: number;\n required?: number;\n available?: number;\n budget?: number;\n committed?: number;\n requested?: { cpu?: number; memoryGB?: number; diskGB?: number };\n maximum?: { cpu: number; memoryGB: number; diskGB: number };\n}\n\nexport type CapacityWaitStateName = \"waiting\" | \"cancelled\" | \"expired\" | \"admitted\";\n\nexport interface CapacityWaitState {\n state: CapacityWaitStateName;\n reason: string | null;\n detail: CapacityWaitDetail | null;\n attempts: number;\n /** Milliseconds until the final deadline; 0 once passed. */\n deadlineInMs: number;\n cancelRequested: boolean;\n /**\n * Future create/wake discriminator (capacity lead, in progress). Tolerated and\n * currently unused: cancel paths must NEVER delete or stop on a wake-kind wait —\n * only the cooperative cancel (DELETE capacity-wait) or pod deletion by explicit\n * user command ends it. Server owns the semantics.\n */\n kind?: string | null;\n /** Validated numeric display fields (additive). */\n required?: number;\n available?: number;\n unit?: string;\n /** ISO timestamp of the final deadline (additive: countdowns render off it). */\n deadlineAt?: string;\n /** Seconds waited once terminal (expired/cancelled/admitted); null while waiting. */\n waitedSeconds?: number | null;\n}\n\nexport interface ApiPod {\n id: string;\n templateId: string | null;\n userId: string;\n /** The pod that launched this one; null for pods a person launched. Absent on old servers. */\n parentPodId?: string | null;\n /** Machine owner for co-located pods; null for machine-backed pods. Absent on old servers. */\n hostPodId?: string | null;\n hostPodName?: string | null;\n /** Display-oriented \"where does this pod live\": provider name, or `on <host>`. */\n location?: string;\n /** 0 for a pod a person launched, parent depth + 1 for a child. */\n lineageDepth?: number;\n /** The pod whose session this one was forked from. Absent on old servers. */\n forkedFromPodId?: string | null;\n name: string;\n /** Legacy project identity on pods created by older clients. */\n project: string | null;\n provider: string;\n state: string;\n /**\n * Raw provider layer (`started`|`stopped`|`archived`|…), so clients can tell a stopped\n * sandbox (local disk retained, restarts in seconds) from a provider-archived one\n * (restores on next use, minutes, size-dependent). Optional: older servers omit it.\n */\n sandboxState?: string | null;\n /**\n * Bounded capacity wait for this launch/wake, or null when it never queued.\n * Optional: servers predating the capacity contract omit it.\n */\n capacityWait?: CapacityWaitState | null;\n /** True when the sandbox can accept a session immediately; false stays provider-agnostic. */\n ready: boolean;\n /** Live gateway channel: connected, reconnecting (lease stale), or detached. Absent on old servers. */\n /** Live gateway channel: connected, reconnecting (lease stale), detached, or asleep. Absent on old servers. */\n connection?: \"connected\" | \"reconnecting\" | \"detached\" | \"asleep\";\n initializing: boolean;\n preparationPhase?: \"preparing-image\" | \"provisioning-sandbox\" | \"waiting-for-capacity\" | \"running-init\" | \"ready\" | \"failed\" | null;\n stateReason: string | null;\n /** Typed launch-failure code (capacity_wait_expired / capacity_wait_orphaned); absent on older servers. */\n stateReasonCode?: string | null;\n lastActivityAt: string | null;\n createdAt: string;\n resolvedConfig: {\n clamps: Array<{ path: string; from: unknown; to: unknown; reason: string }>;\n secretKeys: string[];\n secretScopes: Record<string, string> | null;\n /** Layers that set the same name and lost, lowest precedence first. */\n secretShadows?: Record<string, string[]> | null;\n /** Redacted config origins frozen with the pod; older servers omit this. */\n configProvenance?: ConfigProvenanceEntry[] | null;\n initSteps: Array<{ scope: string; status: string }> | null;\n piAuthProviders: string[] | null;\n piSettings?: {\n files: string[];\n bytes: number;\n packageCount: number;\n droppedKeys: string[];\n status: \"pending\" | \"installing\" | \"ready\" | \"degraded\";\n installedPackageCount?: number;\n failedPackageCount?: number;\n /** Launch-resolved npm identities — the code channel's attested set (newer servers). */\n resolvedPackages?: Array<{ name: string; version: string; source: string }>;\n } | null;\n egress: { description: string; mode: string };\n /** Server-side provisioning phase durations in ms; null on older servers. */\n timings?: Record<string, number> | null;\n /** This launch reused a stopped pod's warm disk (§6.5). */\n reused?: boolean;\n /** Set when a reuse attempt refused the pod and returned it to stopped. */\n reuseRefused?: string | null;\n warnings: string[];\n /** Frozen sandbox workdir; absent on older servers. */\n workdir?: string;\n /** Client-driven workspace seed status; absent on servers without the seed routes. */\n workspaceSeed?: WorkspaceSeedReport | null;\n idleTimeoutMinutes?: number;\n archiveAfterMinutes?: number;\n archiveAfterDays?: number;\n archiveTransition?:\n | { kind: \"same-as-stop\"; expiryDays: null }\n | { kind: \"after-stop\"; maxDelayDays: number };\n providerExpiryDocumented?: boolean;\n image?: string;\n imagePreparation?: {\n ref: string;\n managed: boolean;\n provenance: string;\n assetDigest: string;\n status: \"unknown\" | \"ready\" | \"preparing\";\n } | null;\n };\n}\n\nexport interface LaunchReport {\n clamps: Array<{ path: string; from: unknown; to: unknown; reason: string }>;\n /** Redacted config origins; values never travel in provenance rows. */\n configProvenance?: ConfigProvenanceEntry[] | null;\n secretKeys: string[];\n secretScopes?: Record<string, string> | null;\n /** Layers that set the same name and lost, lowest precedence first. */\n secretShadows?: Record<string, string[]> | null;\n warnings: string[];\n}\n\n/** Answer of POST /pods/resolve: the same merge launch uses, without a pod row. */\nexport interface ResolveReport {\n provider: string;\n /** The org template this launch would start from, if any. */\n template?: { id: string; name: string } | null;\n config: Record<string, unknown>;\n clamps: Array<{ path: string; from: unknown; to: unknown; reason: string }>;\n warnings: string[];\n credential: {\n envVar: string;\n available: boolean;\n source: \"org-secret\" | \"platform\" | null;\n };\n secretKeys: string[];\n secretScopes: Record<string, string> | null;\n /** Layers that set the same name and lost, lowest precedence first. */\n secretShadows?: Record<string, string[]> | null;\n initSteps: Array<{ scope: string }>;\n /** Present when the composed bake script would travel; older servers omit it. */\n bake?: { digest: string } | null;\n piAuthProviders: string[];\n piSettings?: ApiPod[\"resolvedConfig\"][\"piSettings\"];\n workdir: string;\n image: string;\n imageStatus?: \"ready\" | \"missing-buildable\" | \"missing-custom\" | \"unavailable\";\n imageManaged?: boolean;\n imageProvenance?: string;\n imageResources?: { cpu?: number; memoryGB?: number; diskGB?: number } | null;\n egress: { mode: string };\n /** Canonical redacted config origins; older servers may expose only `provenance`. */\n configProvenance?: ConfigProvenanceEntry[] | null;\n /** Compatibility alias for servers predating `configProvenance`. */\n provenance?: ConfigProvenanceEntry[] | null;\n /** Persistent layers (plus a bootstrap-only project preview) in precedence order. */\n layerOrder?: Array<\"org\" | \"template\" | \"user\" | \"project\">;\n /** Echo confirms the server applied this request-scoped selection. */\n piOverrides?: PiLaunchOverrides | null;\n /** Dry-run provenance for a fork; older servers omit it. */\n forkFrom?: { podId: string; sessionPath?: string | null } | null;\n}\n\nexport type AccountThinkingLevel = \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\";\n\n/**\n * Structured Pi startup choices accepted per account-mode pod launch.\n *\n * Beyond the model selection, a launch may add Pi resources — extensions, skills, prompt\n * templates — to the pod's configured set for that launch only. Each array holds pod-local\n * absolute paths (files or directories) naming resources on the pod, not this machine;\n * the server appends the corresponding `--extension`/`--skill`/`--prompt-template` pairs\n * to the pod's configured `pi.args` without replacing them. An empty array appends nothing.\n */\nexport interface PiLaunchOverrides {\n model?: string;\n thinking?: AccountThinkingLevel;\n extensions?: string[];\n skills?: string[];\n promptTemplates?: string[];\n}\n\nexport type ApiJobTrigger =\n | { type: \"cron\"; cron: string }\n | { type: \"at\"; times: string[] };\n\nexport interface ApiJob {\n id: string;\n name: string;\n /** Older servers omit scope and behave as user-scoped for the caller. */\n scope?: \"user\" | \"org\";\n description: string | null;\n status: \"draft\" | \"active\" | \"paused\" | \"completed\";\n trigger: ApiJobTrigger;\n templateId: string | null;\n model: string;\n prompt: string;\n createdFromPod: string | null;\n nextRunAt: string | null;\n lastRunAt: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface ApiJobRun {\n id: string;\n podId: string | null;\n scheduledAt: string;\n status: \"running\" | \"completed\" | \"failed\";\n error: string | null;\n startedAt: string;\n finishedAt: string | null;\n}\n\nexport type CredentialStatus =\n | {\n providerId: string;\n type: \"oauth\" | \"api_key\";\n state: \"ready\";\n expiresAt?: string;\n lastRefreshAt?: string;\n revision: number;\n }\n | {\n providerId: string;\n type: \"oauth\" | \"api_key\";\n state: \"reconnect_required\";\n reason: \"revoked\" | \"invalid_grant\" | \"missing_refresh_token\" | \"migration_required\";\n revision: number;\n }\n | {\n providerId: string;\n type: \"oauth\" | \"api_key\";\n state: \"temporarily_unavailable\";\n retryAfter?: string;\n revision: number;\n };\n\nexport interface ConnectableProvider {\n id: string;\n name: string;\n oauth: { loginLabel: string } | null;\n apiKey: boolean;\n brokerSupported: boolean;\n}\n\nexport interface CredentialErrorDetail {\n code: string;\n message?: string;\n provider?: string;\n requiredBy?: string;\n retryable?: boolean;\n minimumVersion?: string;\n}\n\nfunction sessionTokensChanged(left: AccountAuth, right: AccountAuth): boolean {\n return (\n left.accessToken !== right.accessToken ||\n left.refreshToken !== right.refreshToken ||\n left.idToken !== right.idToken ||\n left.issuer !== right.issuer ||\n left.clientId !== right.clientId\n );\n}\n\n/** Same server, identity provider, organization and user: a token rotation, not another sign-in. */\nfunction sameAccount(left: AccountAuth, right: AccountAuth): boolean {\n return (\n left.serverUrl === right.serverUrl &&\n left.issuer === right.issuer &&\n left.clientId === right.clientId &&\n left.orgId === right.orgId &&\n left.user.id === right.user.id\n );\n}\n\n/**\n * GET /v1/version. Every field after `version` is absent on older servers, and `schema` /\n * `launchAdmission` are null when the server cannot read them.\n */\nexport interface ApiServerVersion {\n version: string;\n /** Source commit the server image was built from. */\n revision?: string | null;\n /** How the server's database compares with the migrations its release ships. */\n schema?: { state: \"current\" | \"behind\" | \"ahead\"; pending: number; unknown: number } | null;\n /** Whether the server admits new launches. */\n launchAdmission?: \"open\" | \"held\" | null;\n}\n\nexport class AccountClient {\n private refreshPromise: Promise<void> | null = null;\n\n constructor(\n private auth: AccountAuth,\n private readonly opts: { home?: string | undefined } = {},\n ) {}\n\n get serverUrl(): string {\n return this.auth.serverUrl;\n }\n\n get orgId(): string {\n return this.auth.orgId;\n }\n\n get user(): AccountAuth[\"user\"] {\n return this.auth.user;\n }\n\n get userId(): string {\n return this.auth.user.id;\n }\n\n /** True when this client speaks as a pod (nested pods), not as a signed-in person. */\n get isPodToken(): boolean {\n return this.auth.podToken === true;\n }\n\n async request<T = unknown>(apiPath: string, opts: ApiRequestOptions = {}): Promise<T> {\n const attempt = () => this.rawRequest(apiPath, opts, this.auth.accessToken);\n let res: Response;\n try {\n res = await attempt();\n } catch (e) {\n throw new PiPodError(`cannot reach the pi pod server at ${this.auth.serverUrl}`, {\n hint: `check that the server is running and reachable\\n(${e instanceof Error ? e.message : String(e)})`,\n transient: true,\n });\n }\n if (res.status === 401 && this.auth.refreshToken) {\n await this.refresh();\n res = await attempt();\n }\n if (res.status === 401) {\n if (this.auth.podToken) {\n throw new PiPodError(\"this pod's server token was revoked\", {\n hint: \"the pod was deleted, or its token rotated — the session it belongs to is over\",\n });\n }\n throw new PiPodError(\"your pi pod server session has expired\", {\n hint: \"run `pipod login`\",\n status: 401,\n });\n }\n if (opts.allow404 && res.status === 404) return null as T;\n if (!res.ok) {\n throw await responseError(res, opts.method ?? \"GET\", apiPath);\n }\n if (res.status === 204) return undefined as T;\n return (await res.json()) as T;\n }\n\n private async rawRequest(apiPath: string, opts: ApiRequestOptions, token: string): Promise<Response> {\n const url = new URL(`/v1${apiPath}`, this.auth.serverUrl);\n for (const [key, value] of Object.entries(opts.query ?? {})) {\n if (value !== undefined) url.searchParams.set(key, String(value));\n }\n debug(`account api: ${opts.method ?? \"GET\"} ${url.pathname}`);\n const waitMs = typeof opts.query?.[\"wait\"] === \"number\" ? Number(opts.query[\"wait\"]) : undefined;\n const timeoutMs =\n opts.timeoutMs ??\n (waitMs !== undefined && waitMs > 0 ? waitMs + LONG_POLL_SLACK_MS : REST_TIMEOUT_MS);\n return fetch(url, {\n method: opts.method ?? \"GET\",\n headers: {\n authorization: `Bearer ${token}`,\n ...(opts.body !== undefined ? { \"content-type\": \"application/json\" } : {}),\n },\n ...(opts.body !== undefined ? { body: JSON.stringify(opts.body) } : {}),\n signal: combineSignals(AbortSignal.timeout(timeoutMs), opts.signal),\n });\n }\n\n /**\n * Stream a file as the request body. Mirrors `request()` — same 401-refresh-once contract,\n * same error mapping — but the body is re-opened from disk for the retry, since a consumed\n * stream cannot be replayed. The caller keeps the file until this resolves.\n */\n async upload<T = unknown>(apiPath: string, opts: ApiUploadOptions): Promise<T> {\n const attempt = () => this.rawUpload(apiPath, opts, this.auth.accessToken);\n let res: Response;\n try {\n res = await attempt();\n } catch (e) {\n if (opts.signal?.aborted) throw e;\n throw new PiPodError(`cannot reach the pi pod server at ${this.auth.serverUrl}`, {\n hint: `check that the server is running and reachable\\n(${e instanceof Error ? e.message : String(e)})`,\n transient: true,\n });\n }\n if (res.status === 401 && this.auth.refreshToken) {\n await this.refresh();\n res = await attempt();\n }\n if (res.status === 401) {\n if (this.auth.podToken) {\n throw new PiPodError(\"this pod's server token was revoked\", {\n hint: \"the pod was deleted, or its token rotated — the session it belongs to is over\",\n });\n }\n throw new PiPodError(\"your pi pod server session has expired\", {\n hint: \"run `pipod login`\",\n status: 401,\n });\n }\n if (!res.ok) throw await responseError(res, opts.method, apiPath);\n if (res.status === 204) return undefined as T;\n return (await res.json()) as T;\n }\n\n private rawUpload(apiPath: string, opts: ApiUploadOptions, token: string): Promise<Response> {\n const url = new URL(`/v1${apiPath}`, this.auth.serverUrl);\n debug(`account api: ${opts.method} ${url.pathname} (${opts.contentLength} bytes streamed)`);\n let sent = 0;\n const file = fs.createReadStream(opts.filePath);\n if (opts.onProgress) {\n const report = opts.onProgress;\n file.on(\"data\", (chunk: string | Buffer) => {\n sent += chunk.length;\n report(sent);\n });\n }\n return fetch(url, {\n method: opts.method,\n headers: {\n authorization: `Bearer ${token}`,\n \"content-type\": opts.contentType,\n \"content-length\": String(opts.contentLength),\n },\n body: Readable.toWeb(file) as ReadableStream,\n // Node's fetch refuses a streaming body without an explicit duplex mode.\n duplex: \"half\",\n signal: combineSignals(AbortSignal.timeout(opts.timeoutMs ?? REST_TIMEOUT_MS), opts.signal),\n } as RequestInit);\n }\n\n\n private refresh(): Promise<void> {\n if (!this.refreshPromise) {\n this.refreshPromise = this.performRefresh().finally(() => {\n this.refreshPromise = null;\n });\n }\n return this.refreshPromise;\n }\n\n /**\n * Adopts a rotation another process wrote, but never a different account: a request\n * retried after `pipod login` elsewhere would carry its body to that account's server.\n * A session signed out elsewhere is refreshed for this request only, never written back.\n */\n private async performRefresh(): Promise<void> {\n await withAccountAuthLock(this.opts.home, async () => {\n const diskAuth = readAccountAuth(this.opts.home);\n if (diskAuth && !sameAccount(this.auth, diskAuth)) {\n throw new PiPodError(\"the pi pod session changed while this command was running\", {\n hint: \"another `pipod login` switched account or server; run the command again\",\n });\n }\n if (diskAuth && sessionTokensChanged(this.auth, diskAuth)) {\n this.auth = diskAuth;\n return;\n }\n\n const refreshAuth = diskAuth ?? this.auth;\n if (!refreshAuth.issuer || !refreshAuth.clientId || !refreshAuth.refreshToken) {\n throw new PiPodError(\"your pi pod server session has expired\", { hint: \"run `pipod login`\" });\n }\n this.auth = refreshAuth;\n try {\n const meta = await discover(refreshAuth.issuer);\n const pair = await refreshTokens(meta, {\n clientId: refreshAuth.clientId ?? DEFAULT_CLIENT_ID,\n refreshToken: refreshAuth.refreshToken,\n });\n this.auth = {\n ...refreshAuth,\n accessToken: pair.accessToken,\n refreshToken: pair.refreshToken ?? refreshAuth.refreshToken,\n ...(pair.idToken ? { idToken: pair.idToken } : {}),\n };\n if (diskAuth) writeAccountAuth(this.auth, this.opts.home);\n } catch (error) {\n // A process not using this lock (or a stale owner finishing) may still have won rotation.\n const changedAuth = readAccountAuth(this.opts.home);\n if (changedAuth && sameAccount(refreshAuth, changedAuth) && sessionTokensChanged(refreshAuth, changedAuth)) {\n this.auth = changedAuth;\n return;\n }\n throw error;\n }\n });\n }\n\n // --- typed surface --------------------------------------------------------\n\n me(): Promise<{\n user: { id: string; email?: string; displayName?: string };\n currentOrgId: string | null;\n /** Absent when the token carries no roles — callers must tolerate undefined. */\n permissions?: string[];\n organization?: { id: string; alias: string | null; name: string | null } | null;\n accountConsoleUrl?: string;\n adminConsoleUrl?: string;\n /**\n * SaaS-only workstation plan/usage block. Absent under the self-hosted static backend,\n * which has no plans, no metered hours and no spend caps — so it is deliberately untyped\n * here and validated field by field by `parseAccountBilling`.\n */\n workstation?: unknown;\n }> {\n return this.request(\"/me\");\n }\n\n /** Null from a server that predates the route. */\n serverVersion(): Promise<ApiServerVersion | null> {\n return this.request(\"/version\", { allow404: true });\n }\n\n\n /** Store an org-scoped secret (BYO provider keys live here). Needs secrets:org:write. */\n putOrgSecret(name: string, value: string): Promise<void> {\n return this.putSecret(\"org\", this.auth.orgId, name, value);\n }\n\n /** Names and metadata only — the secret API never reads values back. */\n listSecrets(scope: ServerSecretScope, scopeId: string): Promise<{ secrets: ApiSecret[] }> {\n return this.request(`/secrets/${scope}/${encodeURIComponent(scopeId)}`);\n }\n\n putSecret(scope: ServerSecretScope, scopeId: string, name: string, value: string): Promise<void> {\n return this.request(`/secrets/${scope}/${encodeURIComponent(scopeId)}/${encodeURIComponent(name)}`, {\n method: \"PUT\",\n body: { value },\n });\n }\n\n deleteSecret(scope: ServerSecretScope, scopeId: string, name: string): Promise<void> {\n return this.request(`/secrets/${scope}/${encodeURIComponent(scopeId)}/${encodeURIComponent(name)}`, {\n method: \"DELETE\",\n });\n }\n\n listTemplates(): Promise<{ templates: ApiTemplate[] }> {\n return this.request(\"/templates\");\n }\n\n getTemplate(id: string): Promise<ApiTemplate> {\n return this.request(`/templates/${id}`);\n }\n\n createTemplate(body: TemplateBody): Promise<ApiTemplate> {\n return this.request(\"/templates\", { method: \"POST\", body });\n }\n\n /** `expectedVersion` makes the write compare-and-swap on servers that expose template versions. */\n updateTemplate(id: string, body: Partial<TemplateBody> & { expectedVersion?: number }): Promise<ApiTemplate> {\n return this.request(`/templates/${id}`, { method: \"PATCH\", body });\n }\n\n activateTemplate(id: string): Promise<{ id: string; status: string }> {\n return this.request(`/templates/${id}/activate`, { method: \"POST\" });\n }\n\n deleteTemplate(id: string): Promise<void> {\n return this.request(`/templates/${id}`, { method: \"DELETE\" });\n }\n\n getUserSettings(): Promise<ApiSettingsBundle> {\n return this.request(`/users/${encodeURIComponent(this.userId)}/settings`);\n }\n\n putUserSettings(body: PutSettingsBundleBody): Promise<{ version: number }> {\n return this.request(`/users/${encodeURIComponent(this.userId)}/settings`, { method: \"PUT\", body });\n }\n\n getOrgSettings(): Promise<ApiSettingsBundle> {\n return this.request(`/orgs/${encodeURIComponent(this.orgId)}/settings`);\n }\n\n putOrgSettings(body: PutSettingsBundleBody): Promise<{ version: number }> {\n return this.request(`/orgs/${encodeURIComponent(this.orgId)}/settings`, { method: \"PUT\", body });\n }\n\n\n launch(body: {\n templateId?: string;\n /** The project launching it ({@link currentProjectName}); names the pod and scopes lists. */\n project?: { name: string };\n piOverrides?: PiLaunchOverrides;\n forkFrom?: { podId: string; sessionPath?: string };\n /** Co-located placement: run the new pod on an existing pod's machine. */\n placement?: { host: string };\n /**\n * Seed gate: this launch will clone or archive into the workdir right after provisioning,\n * so the server holds Pi until the seed completes, is skipped, or times out.\n */\n workspaceSeed?: boolean;\n }): Promise<{ pod: ApiPod; report: LaunchReport }> {\n return this.request(\"/pods\", { method: \"POST\", body });\n }\n\n /** §6.5: relaunch onto a stopped pod's warm disk. 4xx means \"not eligible — launch fresh\". */\n reusePod(\n podId: string,\n body: {\n templateId?: string;\n project?: { name: string };\n piOverrides?: PiLaunchOverrides;\n },\n ): Promise<{ pod: ApiPod; report: LaunchReport }> {\n return this.request(`/pods/${podId}/reuse`, { method: \"POST\", body });\n }\n\n /**\n * Same merge/clamps/credential check as launch, no pod row. Returns null on older\n * servers that lack the endpoint so callers can fall back to a local approximation.\n */\n resolve(body: {\n /** Bootstrap preview only; never accompanies templateId or a launch request. */\n projectConfig?: Record<string, unknown>;\n templateId?: string;\n piOverrides?: PiLaunchOverrides;\n forkFrom?: { podId: string; sessionPath?: string };\n /** False skips the sandbox image lookup when only merged config is needed. */\n checkImage?: boolean;\n }): Promise<ResolveReport | null> {\n const { checkImage, ...payload } = body;\n const query = {\n ...(checkImage !== undefined ? { check_image: checkImage } : {}),\n };\n return this.request(\"/pods/resolve\", {\n method: \"POST\",\n body: payload,\n ...(Object.keys(query).length > 0 ? { query } : {}),\n allow404: true,\n });\n }\n\n listPods(\n query: {\n project?: string;\n state?: string;\n mine?: boolean;\n limit?: number;\n templateId?: string;\n /** Pods less recently active than this timestamp: the cursor for the next page. */\n before?: string;\n /** Include provider_state 'gone' rows (failed launches that never acquired compute). */\n includeGone?: boolean;\n } = {},\n ): Promise<{ pods: ApiPod[] }> {\n return this.request(\"/pods\", { query });\n }\n\n /** `waitMs` long-polls: a supporting server answers on the next pod change; older servers ignore it. */\n getPod(id: string, opts: { waitMs?: number; timeoutMs?: number } = {}): Promise<ApiPod> {\n const waitMs = opts.waitMs != null && opts.waitMs > 0 ? Math.floor(opts.waitMs) : undefined;\n return this.request(`/pods/${id}`, {\n ...(waitMs !== undefined ? { query: { wait: waitMs } } : {}),\n ...(opts.timeoutMs !== undefined ? { timeoutMs: opts.timeoutMs } : {}),\n });\n }\n\n podCommand(\n id: string,\n command: \"stop\" | \"archive\" | \"restore\",\n ): Promise<{ id: string; state: string; message?: string; cascaded?: string[] }> {\n return this.request(`/pods/${id}/${command}`, { method: \"POST\" });\n }\n\n /**\n * Cooperatively cancel a bounded capacity wait (capacity contract §1). The waiter\n * observes it on its next heartbeat and fails the pod as cancelled; the pod row\n * itself survives. Returns null (404) when the pod never queued. Older servers\n * answer 404 for the unknown route, which reads the same way: nothing to cancel.\n */\n cancelCapacityWait(\n id: string,\n ): Promise<{ cancelled: boolean; capacityWait: CapacityWaitState | null } | null> {\n return this.request(`/pods/${id}/capacity-wait`, { method: \"DELETE\", allow404: true });\n }\n\n /** `cascade` takes the pod's whole subtree down; without it, live children answer 409. */\n deletePod(id: string, opts: { cascade?: boolean } = {}): Promise<{ id: string; state: \"gone\"; deleted: boolean; cascaded?: string[] }> {\n return this.request(`/pods/${id}`, {\n method: \"DELETE\",\n ...(opts.cascade ? { query: { cascade: true } } : {}),\n });\n }\n\n renamePod(id: string, name: string): Promise<{ id: string; name: string }> {\n return this.request(`/pods/${id}`, { method: \"PATCH\", body: { name } });\n }\n\n /**\n * Seed an empty pod workdir by cloning an exact commit on the server side. The optional\n * credential is used for that one clone and discarded; it never appears in pod metadata.\n */\n seedWorkspaceClone(\n podId: string,\n body: WorkspaceCloneBody,\n opts: { signal?: AbortSignal; timeoutMs?: number } = {},\n ): Promise<WorkspaceSeedResult> {\n return this.request(`/pods/${podId}/workspace/clone`, {\n method: \"POST\",\n body,\n timeoutMs: opts.timeoutMs ?? WORKSPACE_CLONE_TIMEOUT_MS,\n ...(opts.signal ? { signal: opts.signal } : {}),\n });\n }\n\n /** Release a seed gate the launch armed: the client will not seed after all, so Pi may start. */\n seedWorkspaceSkip(podId: string, reason: string): Promise<WorkspaceSeedResult> {\n return this.request(`/pods/${podId}/workspace/skip`, { method: \"POST\", body: { reason: reason.slice(0, 512) } });\n }\n\n /** Seed an empty pod workdir from a gzip tar archive streamed straight from disk. */\n seedWorkspaceArchive(\n podId: string,\n archive: { filePath: string; bytes: number },\n opts: { signal?: AbortSignal; timeoutMs?: number; onProgress?: (sentBytes: number) => void } = {},\n ): Promise<WorkspaceSeedResult> {\n return this.upload(`/pods/${podId}/workspace/archive`, {\n method: \"PUT\",\n filePath: archive.filePath,\n contentType: WORKSPACE_ARCHIVE_CONTENT_TYPE,\n contentLength: archive.bytes,\n timeoutMs: opts.timeoutMs ?? WORKSPACE_ARCHIVE_TIMEOUT_MS,\n ...(opts.signal ? { signal: opts.signal } : {}),\n ...(opts.onProgress ? { onProgress: opts.onProgress } : {}),\n });\n }\n\n\n wsTicket(id: string): Promise<{ ticket: string; expiresAt: string }> {\n return this.request(`/pods/${id}/ws-ticket`, { method: \"POST\" });\n }\n\n /**\n * Durable status of the caller's own workstation (SaaS edition). The path is built from a\n * validated host id, never from a `statusHref` a response chose. Null covers everything that\n * means \"no status to show\": an unknown id, a server without the route (the self-hosted\n * static backend has no workstations at all), or a refusal.\n */\n async getWorkstation(hostId: string): Promise<WorkstationStatus | null> {\n if (!isWorkstationHostId(hostId)) return null;\n const raw = await this.request(`/workstations/${encodeURIComponent(hostId)}`, { allow404: true });\n return parseWorkstationStatus(raw);\n }\n\n /**\n * Plan, active hours and spend cap for the signed-in account, or null when the server does\n * not report them. Absence is the self-hosted edition: it has no plans, no metered hours and\n * no caps, so the whole surface stays hidden rather than rendering zeroes.\n */\n async accountBilling(): Promise<AccountBilling | null> {\n try {\n const me = await this.me();\n return parseAccountBilling((me as { workstation?: unknown }).workstation);\n } catch (error) {\n debug(`account billing unavailable: ${error instanceof Error ? error.message : String(error)}`);\n return null;\n }\n }\n\n /** `POST /v1/billing/checkout-session`. `trial:false` is paid subscribe. */\n createCheckoutSession(body: { plan: \"standard\" | \"pro\"; trial: boolean }): Promise<{ url: string; trial: boolean }> {\n return this.request(\"/billing/checkout-session\", { method: \"POST\", body });\n }\n\n /** `POST /v1/billing/portal-session`. */\n createPortalSession(): Promise<{ url: string }> {\n return this.request(\"/billing/portal-session\", { method: \"POST\", body: {} });\n }\n\n /**\n * `GET /v1/billing/account` narrowed to the plan-change surface. Null when the\n * server has no `/v1/billing` at all (the self-hosted static backend) — the\n * caller omits the change command rather than rendering a guess.\n */\n async billingAccountPlan(): Promise<BillingAccountPlan | null> {\n const raw = await this.request<unknown>(\"/billing/account\", { allow404: true });\n if (raw === null) return null;\n const parsed = parseBillingAccountPlan(raw);\n if (!parsed) {\n throw new PiPodError(\"the server returned an unusable billing account\", {\n hint: \"run `pipod update`, then try again\",\n });\n }\n return parsed;\n }\n\n /**\n * `POST /v1/billing/plan-change/preview`. The body carries the target plan\n * only; every amount comes back from Stripe via the server.\n */\n async previewPlanChange(plan: BillingPlanKey): Promise<PlanChangeQuoteView> {\n const raw = await this.request<unknown>(\"/billing/plan-change/preview\", {\n method: \"POST\",\n body: { plan },\n });\n const quote = parsePlanChangeQuote(raw);\n if (!quote) {\n throw new PiPodError(\"the server returned an unusable plan-change quote\", {\n hint: \"run `pipod update`, then try again\",\n });\n }\n return quote;\n }\n\n /**\n * `POST /v1/billing/plan-change/confirm`. The body carries the quote id only —\n * never a caller-selected plan. The response is `{ applied, ...quote, account }`:\n * success is `applied === true` AND the returned `account.planKey`\n * (or `pendingPlanKey` for a period-end downgrade) matching `quote.targetPlan`.\n * A missing `applied` never grants: it is `plan_change_not_applied`.\n * No hosted payment URL field (`hostedPaymentUrl|paymentUrl|checkoutUrl|url`)\n * exists on this view and none is read here.\n */\n async confirmPlanChange(quoteId: string): Promise<{ quote: PlanChangeQuoteView; account: BillingAccountPlan | null; applied: boolean }> {\n const raw = await this.request<unknown>(\"/billing/plan-change/confirm\", {\n method: \"POST\",\n body: { quoteId },\n });\n const root =\n raw !== null && typeof raw === \"object\" && !Array.isArray(raw)\n ? (raw as Record<string, unknown>)\n : null;\n const quote = root ? parsePlanChangeQuote(root) : null;\n if (!root || !quote) {\n throw new PiPodError(\"the server returned an unusable plan-change confirmation\", {\n hint: \"refresh with `pipod billing change preview` and compare before retrying\",\n });\n }\n return { quote, account: parseBillingAccountPlan(root[\"account\"]), applied: root[\"applied\"] === true };\n }\n\n sessionEvents(\n sessionId: string,\n query: { afterSeq?: number; limit?: number } = {},\n ): Promise<{\n truncatedBelowSeq: number | null;\n events: Array<{ seq: number; kind: string; payload: unknown; createdAt: string }>;\n }> {\n return this.request(`/sessions/${sessionId}/events`, {\n query: { after_seq: query.afterSeq ?? 0, limit: query.limit ?? 500 },\n });\n }\n\n listJobs(query: { before?: string; beforeId?: string; limit?: number } = {}): Promise<{ jobs: ApiJob[] }> {\n return this.request(\"/jobs\", {\n query: { limit: query.limit ?? 200, before: query.before, beforeId: query.beforeId },\n });\n }\n\n getJob(id: string): Promise<ApiJob> {\n return this.request(`/jobs/${id}`);\n }\n\n createJob(body: {\n name: string;\n description?: string;\n trigger: ApiJobTrigger;\n templateId?: string | null;\n model: string;\n prompt: string;\n scope?: \"user\" | \"org\";\n }): Promise<ApiJob> {\n return this.request(\"/jobs\", { method: \"POST\", body });\n }\n\n patchJob(\n id: string,\n body: Partial<{\n name: string;\n description: string;\n trigger: ApiJobTrigger;\n templateId: string | null;\n model: string;\n prompt: string;\n scope: \"org\";\n }>,\n ): Promise<ApiJob> {\n return this.request(`/jobs/${id}`, { method: \"PATCH\", body });\n }\n\n jobCommand(id: string, command: \"activate\" | \"pause\" | \"resume\" | \"run\"): Promise<{ id: string; status: string }> {\n return this.request(`/jobs/${id}/${command}`, { method: \"POST\" });\n }\n\n deleteJob(id: string): Promise<void> {\n return this.request(`/jobs/${id}`, { method: \"DELETE\" });\n }\n\n jobRuns(id: string): Promise<{ runs: ApiJobRun[] }> {\n return this.request(`/jobs/${id}/runs`);\n }\n\n modelCredentials(): Promise<{ credentials: CredentialStatus[]; providers: ConnectableProvider[] }> {\n return this.request(\"/model-credentials\");\n }\n\n createCredentialLoginTicket(\n providerId: string,\n body: { authType: \"oauth\" | \"api_key\"; podId?: string },\n ): Promise<{ ticket: string; expiresAt: string }> {\n return this.request(`/model-credentials/${encodeURIComponent(providerId)}/login-ticket`, {\n method: \"POST\",\n body,\n });\n }\n\n credentialLoginWsUrl(providerId: string, ticket: string): string {\n const url = new URL(`/v1/model-credentials/${encodeURIComponent(providerId)}/login`, this.auth.serverUrl);\n url.protocol = url.protocol === \"https:\" ? \"wss:\" : \"ws:\";\n url.searchParams.set(\"ticket\", ticket);\n return url.toString();\n }\n\n testModelCredential(providerId: string): Promise<{ status: CredentialStatus }> {\n return this.request(`/model-credentials/${encodeURIComponent(providerId)}/test`, { method: \"POST\" });\n }\n\n deleteModelCredential(providerId: string): Promise<void> {\n return this.request(`/model-credentials/${encodeURIComponent(providerId)}`, { method: \"DELETE\" });\n }\n\n\n /** The session WebSocket endpoint for a pod, ready for a ticket query (§6). */\n sessionWsUrl(podId: string, params: { ticket: string; fromSeq?: number; fromSession?: string }): string {\n const url = new URL(`/v1/pods/${podId}/session`, this.auth.serverUrl);\n url.protocol = url.protocol === \"https:\" ? \"wss:\" : \"ws:\";\n url.searchParams.set(\"ticket\", params.ticket);\n if (params.fromSeq !== undefined) url.searchParams.set(\"from_seq\", String(params.fromSeq));\n if (params.fromSession) url.searchParams.set(\"from_session\", params.fromSession);\n return url.toString();\n }\n}\n\nexport function credentialProtocolError(\n code: string,\n message: string | undefined,\n provider: string | undefined,\n opts: { status?: number } = {},\n): PiPodError {\n const namedProvider = provider ?? \"provider\";\n switch (code) {\n case \"credential_reconnect_required\":\n return new PiPodError(message ?? `The saved ${namedProvider} credential must be reconnected.`, {\n status: opts.status,\n code,\n hint: `run \\`pipod credentials connect ${namedProvider}\\``,\n });\n case \"credential_temporarily_unavailable\":\n return new PiPodError(message ?? `The ${namedProvider} credential is temporarily unavailable.`, {\n status: opts.status,\n code,\n transient: true,\n });\n case \"credential_provider_unsupported\":\n return new PiPodError(message ?? `${namedProvider} cannot be connected through the account credential broker.`, {\n status: opts.status,\n code,\n hint: \"if this provider accepts an API key, store it as a scoped secret with `pipod secrets set user <NAME>`\",\n });\n case \"client_upgrade_required\":\n return new PiPodError(message ?? \"this operation requires a newer pi pod client; upgrade pi pod before continuing\", {\n status: opts.status,\n code,\n hint: \"run `pipod update`\",\n });\n default:\n return new PiPodError(message ?? `credential operation failed (${code})`, {\n status: opts.status,\n code,\n });\n }\n}\n\nasync function responseError(res: Response, method: string, apiPath: string): Promise<PiPodError> {\n let body: { message?: unknown; error?: unknown; detail?: unknown } = {};\n try {\n body = (await res.json()) as typeof body;\n } catch {\n // Error bodies are deliberately not copied into diagnostics: credential endpoints may\n // grow token-bearing fields, while status and the bounded message are sufficient here.\n }\n const detail = isCredentialErrorDetail(body.detail) ? body.detail : undefined;\n if (detail && [\n \"credential_reconnect_required\",\n \"credential_temporarily_unavailable\",\n \"credential_provider_unsupported\",\n \"client_upgrade_required\",\n ].includes(detail.code)) {\n const typedMessage = detail.message ?? (\n detail.code === \"client_upgrade_required\" && detail.minimumVersion\n ? `pi pod ${detail.minimumVersion} or newer is required; upgrade pi pod before continuing`\n : undefined\n );\n return credentialProtocolError(detail.code, typedMessage, detail.provider, { status: res.status });\n }\n const message =\n detail?.message ??\n (typeof body.message === \"string\" ? body.message : undefined) ??\n (typeof body.error === \"string\" ? body.error : undefined) ??\n `HTTP ${res.status}`;\n // Routes without a structured `detail` still name their refusal with a stable snake_case\n // `error` code (`workspace_not_empty`); surface it so callers can branch without regexes.\n const code = detail?.code ?? (typeof body.error === \"string\" && /^[a-z][a-z0-9_]*$/.test(body.error) ? body.error : undefined);\n // A personal-workstation refusal is its own shape (`kind: admission` + `transitions` +\n // `count`), and it carries a host id, a status link and a durable operation that the\n // capacity allowlist below would reject wholesale — dropping exactly the fields the client\n // needs to wait for the machine. Recognize it first, rebuilt from validated parts.\n const demand = parseWorkstationDemand(body.detail);\n if (demand !== null && res.status === 503) {\n // Carry the workstation's own copy rather than \"the server refused POST /v1/pods\": on the\n // paths that wait, the sentence is replaced by progress anyway, and on the paths that do\n // not, this is the only thing the user will see.\n debug(`account api: ${method} ${apiPath} refused — workstation ${demand.reason}`);\n return new WorkstationNotReadyError({ ...demand, ...(message ? { message: message.slice(0, 240) } : {}) });\n }\n // Preserve a safe server `detail` for capacity classification (reason/retryable hints).\n // Presenters render only validated codes/numbers from it — never raw provider text.\n const safeDetail = isSafeCapacityDetail(body.detail) ? body.detail : undefined;\n // A missing permission is the user's to resolve, not the request's: say which, and who.\n const permission = res.status === 403 ? /^requires ([a-z:_]+)$/.exec(message)?.[1] : undefined;\n if (permission) {\n debug(`account api: ${method} ${apiPath} refused — ${message}`);\n return new PiPodError(`you do not have the ${permission} permission this needs`, {\n status: res.status,\n hint: \"an owner of your organization can grant it (`pipod org-admin` opens the console)\",\n });\n }\n return new PiPodError(`the pi pod server refused ${method} ${apiPath}: ${message}`, {\n status: res.status,\n ...(code ? { code } : {}),\n ...(safeDetail !== undefined ? { detail: safeDetail } : {}),\n });\n}\n\n/**\n * Future typed capacity detail the cost-control workstreams may add\n * (`reason`, `retryable`, bounded numeric hints). Allowlisted keys with primitive values\n * only, so arbitrary provider text, URLs, and secrets never ride into error presentation.\n */\nfunction isSafeCapacityDetail(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) return false;\n const record = value as Record<string, unknown>;\n const allowed = new Set([\n \"reason\", \"code\", \"retryable\", \"retryAfterMs\", \"retryAfter\", \"required\", \"available\",\n \"requiredMemoryGB\", \"availableMemoryGB\", \"requiredDiskGB\", \"availableDiskGB\", \"message\",\n // Billing refusal `detail` (HTTP 402, `kind: \"billing\"`): the reason plus the numbers and\n // dates the copy is allowed to quote back, so it never has to invent one. Every key here\n // is one the server's `workstationStartRefusal()` actually sends.\n \"kind\", \"planKey\", \"activeHoursUsed\", \"includedActiveHours\", \"spendCapUsdCents\",\n \"projectedSpendUsdCents\", \"currentPeriodEnd\",\n // Plan-change `plan_change_in_flight` resume pointer (409 while applying):\n // `{ quoteId, state }` — the id the client must resume, never a new preview.\n // No payment URL keys are allowlisted here by design (the API defines none).\n \"quoteId\", \"state\", \"targetPlan\",\n ]);\n for (const [key, entry] of Object.entries(record)) {\n if (!allowed.has(key)) return false;\n const type = typeof entry;\n if (entry !== null && type !== \"string\" && type !== \"number\" && type !== \"boolean\") return false;\n if (type === \"string\" && (entry as string).length > 240) return false;\n }\n return Object.keys(record).length > 0;\n}\n\n/** One signal that fires when either does; a missing caller signal leaves the timeout alone. */\nfunction combineSignals(timeout: AbortSignal, caller?: AbortSignal): AbortSignal {\n if (!caller) return timeout;\n return AbortSignal.any([timeout, caller]);\n}\n\nfunction isCredentialErrorDetail(value: unknown): value is CredentialErrorDetail {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) return false;\n const detail = value as Record<string, unknown>;\n return (\n typeof detail[\"code\"] === \"string\" &&\n (detail[\"message\"] === undefined || typeof detail[\"message\"] === \"string\") &&\n (detail[\"provider\"] === undefined || typeof detail[\"provider\"] === \"string\") &&\n (detail[\"requiredBy\"] === undefined || typeof detail[\"requiredBy\"] === \"string\") &&\n (detail[\"retryable\"] === undefined || typeof detail[\"retryable\"] === \"boolean\") &&\n (detail[\"minimumVersion\"] === undefined || typeof detail[\"minimumVersion\"] === \"string\")\n );\n}\n","/**\n * src/log.ts — the launcher's logger. Everything user-visible goes through here so that\n * redaction (§7.3) is structural rather than something each call site has to remember.\n */\nimport { stripVTControlCharacters } from \"node:util\";\nimport { redact } from \"./redact.js\";\n\nlet verbose = false;\nlet colorEnabled = process.stderr.isTTY === true && !process.env.NO_COLOR;\n\nexport function setVerbose(v: boolean): void {\n verbose = v;\n}\n\nexport function isVerbose(): boolean {\n return verbose;\n}\n\nexport function setColor(enabled: boolean): void {\n colorEnabled = enabled;\n}\n\nconst CODES = {\n reset: \"\\u001b[0m\",\n dim: \"\\u001b[2m\",\n bold: \"\\u001b[1m\",\n red: \"\\u001b[31m\",\n yellow: \"\\u001b[33m\",\n cyan: \"\\u001b[36m\",\n green: \"\\u001b[32m\",\n} as const;\n\nfunction paint(code: keyof typeof CODES, s: string): string {\n return colorEnabled ? `${CODES[code]}${s}${CODES.reset}` : s;\n}\n\nexport const color = {\n dim: (s: string) => paint(\"dim\", s),\n bold: (s: string) => paint(\"bold\", s),\n red: (s: string) => paint(\"red\", s),\n yellow: (s: string) => paint(\"yellow\", s),\n cyan: (s: string) => paint(\"cyan\", s),\n green: (s: string) => paint(\"green\", s),\n};\n\n/**\n * Diagnostics go to stderr so that stdout stays clean for the PTY stream and for\n * machine-readable output (`--dry-run`, `--version`).\n */\nfunction write(line: string): void {\n process.stderr.write(redact(line) + \"\\n\");\n}\n\nexport function info(msg: string): void {\n write(`${paint(\"cyan\", \"pi pod\")} ${msg}`);\n}\n\nexport function step(phase: string, msg: string): void {\n write(`${paint(\"cyan\", \"pi pod\")} ${paint(\"dim\", `[${phase}]`)} ${msg}`);\n}\n\nexport function warn(msg: string): void {\n write(`${paint(\"yellow\", \"warning\")} ${msg}`);\n}\n\nexport function error(msg: string): void {\n write(`${paint(\"red\", \"error\")} ${msg}`);\n}\n\n/** Multi-line hints are one hint: the prefix appears once, continuation lines align under it. */\nexport function hint(msg: string): void {\n const lines = msg.split(\"\\n\");\n write(`${paint(\"dim\", \" hint:\")} ${lines[0] ?? \"\"}`);\n for (const line of lines.slice(1)) write(paint(\"dim\", ` ${line}`));\n}\n\nexport function debug(msg: string): void {\n if (verbose) write(`${paint(\"dim\", \"debug\")} ${paint(\"dim\", msg)}`);\n}\n\nexport function plain(msg: string): void {\n write(msg);\n}\n\n/**\n * Direct stdout writer for command results and machine-readable output; still redacted.\n * Color is useful at a terminal but must never leak into a pipe or redirected file.\n */\nexport function out(msg: string): void {\n const line = redact(msg);\n process.stdout.write((process.stdout.isTTY === true ? line : stripVTControlCharacters(line)) + \"\\n\");\n}\n\n/**\n * Wall-clock phase timings for one launch/attach, so the summary line can say where the\n * time went. Overlapping (parallelized) phases each record their own duration; the summary\n * total is wall time, not the sum.\n */\nexport interface PhaseTiming {\n phase: string;\n ms: number;\n}\n\nconst phaseTimings: PhaseTiming[] = [];\n\nexport function resetPhaseTimings(): void {\n phaseTimings.length = 0;\n}\n\nexport function recordPhase(phase: string, ms: number): void {\n phaseTimings.push({ phase, ms });\n}\n\nexport async function timePhase<T>(phase: string, work: () => Promise<T>): Promise<T> {\n const startedAt = Date.now();\n try {\n return await work();\n } finally {\n recordPhase(phase, Date.now() - startedAt);\n }\n}\n\nfunction fmtSeconds(ms: number): string {\n return `${(ms / 1000).toFixed(1)}s`;\n}\n\n/** One line naming total wall time and every phase that cost at least 100ms. */\nexport function phaseSummary(label: string, totalMs: number): string {\n const parts = phaseTimings.filter((t) => t.ms >= 100).map((t) => `${t.phase} ${fmtSeconds(t.ms)}`);\n const breakdown = parts.length > 0 ? ` (${parts.join(\" · \")})` : \"\";\n return `${label} in ${fmtSeconds(totalMs)}${breakdown}`;\n}\n\n/**\n * Print a periodic \"still …\" line while a long provider operation runs, so a multi-minute\n * wait is distinguishable from a hang. The line names the elapsed time and, when known,\n * roughly how long the wait usually takes.\n */\nexport const LIVENESS_INTERVAL_MS = 15_000;\n\nexport async function withLiveness<T>(\n label: string,\n work: () => Promise<T>,\n opts: { intervalMs?: number; expectation?: string } = {},\n): Promise<T> {\n const intervalMs = opts.intervalMs ?? LIVENESS_INTERVAL_MS;\n const startedAt = Date.now();\n const timer = setInterval(() => {\n const elapsed = Math.round((Date.now() - startedAt) / 1000);\n const usually = opts.expectation ? `, ${opts.expectation}` : \"\";\n write(`${paint(\"cyan\", \"pi pod\")} ${paint(\"dim\", `still ${label} (${elapsed}s elapsed${usually})`)}`);\n }, intervalMs);\n timer.unref?.();\n try {\n return await work();\n } finally {\n clearInterval(timer);\n }\n}\n\n/**\n * Stream a child stream to the terminal with a prefix (`[init]`, §4.3). Handles partial\n * lines so a chunk boundary never splits a prefix.\n */\nexport function prefixedStreamer(prefix: string): (chunk: Uint8Array) => void {\n let pending = \"\";\n const flushLine = (line: string) => write(`${paint(\"dim\", prefix)} ${line}`);\n return (chunk: Uint8Array) => {\n pending += Buffer.from(chunk).toString(\"utf8\");\n const lines = pending.split(/\\r?\\n/);\n pending = lines.pop() ?? \"\";\n for (const line of lines) flushLine(line);\n // Guard against a runaway line with no newline ever arriving.\n if (pending.length > 8192) {\n flushLine(pending);\n pending = \"\";\n }\n };\n}\n","/**\n * src/redact.ts — secret-aware log redaction (§7.3).\n *\n * Every value originating from the env file is registered here; the logger runs all output\n * through `redact()`. The conformance suite (§14) asserts that no registered value ever\n * appears in captured logs.\n */\n\n/** Values short enough to appear coincidentally are not worth redacting (and would mangle output). */\nconst MIN_REDACTABLE_LENGTH = 4;\n\nconst secrets = new Set<string>();\n\nexport function registerSecret(value: string | undefined | null): void {\n if (!value) return;\n const v = String(value);\n if (v.length < MIN_REDACTABLE_LENGTH) return;\n secrets.add(v);\n}\n\nexport function registerSecrets(values: Record<string, string>): void {\n for (const v of Object.values(values)) registerSecret(v);\n}\n\n/** Test/reset hook. */\nexport function clearSecrets(): void {\n secrets.clear();\n}\n\nexport function registeredSecretCount(): number {\n return secrets.size;\n}\n\n/**\n * Replace every registered secret with `[redacted]`. Longest-first so that a secret which\n * contains another secret as a substring is not partially revealed.\n */\nexport function redact(input: string): string {\n if (secrets.size === 0) return input;\n let out = input;\n for (const secret of [...secrets].sort((a, b) => b.length - a.length)) {\n if (out.includes(secret)) out = out.split(secret).join(\"[redacted]\");\n }\n return out;\n}\n\nexport function redactBytes(input: Uint8Array): Uint8Array {\n if (secrets.size === 0) return input;\n const text = Buffer.from(input).toString(\"utf8\");\n const cleaned = redact(text);\n return cleaned === text ? input : Buffer.from(cleaned, \"utf8\");\n}\n\n/** Redact an arbitrary structure for debug dumps. Keys are preserved, values scrubbed. */\nexport function redactDeep<T>(value: T): T {\n if (typeof value === \"string\") return redact(value) as unknown as T;\n if (Array.isArray(value)) return value.map((v) => redactDeep(v)) as unknown as T;\n if (value && typeof value === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) out[k] = redactDeep(v);\n return out as unknown as T;\n }\n return value;\n}\n","/**\n * Direct Zitadel OIDC for the CLI public client (the `pipod-cli` app).\n * Discovery is the runtime contract; authorization/token/end-session paths are never hardcoded.\n */\nimport { createHash, randomBytes, timingSafeEqual } from \"node:crypto\";\nimport { createRemoteJWKSet, jwtVerify } from \"jose\";\nimport { PiPodError } from \"../errors.js\";\n\nexport const DEFAULT_ISSUER = \"https://auth.pipod.dev\";\n/** Zitadel generates client ids; ship the production `pipod-cli` id here after reconcile prints it. Override with PI_POD_OIDC_CLIENT_ID. */\nexport const DEFAULT_CLIENT_ID = \"388199922844827655\";\n/** Zitadel reserved scopes: assert the resource-owner organization and project role claims. */\nexport const RESOURCE_OWNER_SCOPE = \"urn:zitadel:iam:user:resourceowner\";\nexport const PROJECT_ROLES_SCOPE = \"urn:zitadel:iam:org:projects:roles\";\n/** Required for Zitadel to issue a refresh token (pipod-cli enables the refresh-token grant). */\nexport const OFFLINE_ACCESS_SCOPE = \"offline_access\";\nexport const OIDC_NETWORK_TIMEOUT_MS = 10_000;\nexport const ID_TOKEN_CLOCK_TOLERANCE_SECONDS = 30;\nexport const ORGANIZATION_ALIAS_MAX_LENGTH = 128;\n\nexport interface OidcMetadata {\n issuer: string;\n authorization_endpoint: string;\n token_endpoint: string;\n end_session_endpoint?: string;\n revocation_endpoint?: string;\n jwks_uri: string;\n}\n\nexport interface TokenSet {\n accessToken: string;\n refreshToken?: string;\n idToken?: string;\n}\n\nconst metadataCache = new Map<string, OidcMetadata>();\nconst idTokenJwksCache = new Map<string, ReturnType<typeof createRemoteJWKSet>>();\n\nexport function normalizeIssuer(raw: string): string {\n return raw.replace(/\\/+$/, \"\");\n}\n\nfunction isLoopback(hostname: string): boolean {\n return hostname === \"localhost\" || hostname === \"127.0.0.1\" || hostname === \"::1\" || hostname === \"[::1]\";\n}\n\nfunction parseSecureOidcUrl(raw: string, name: string): URL {\n let url: URL;\n try {\n url = new URL(raw);\n } catch {\n throw new PiPodError(`identity provider ${name} is not a valid URL`);\n }\n if (url.username || url.password || url.hash) {\n throw new PiPodError(`identity provider ${name} must not contain credentials or a fragment`);\n }\n if (url.protocol !== \"https:\" && !(url.protocol === \"http:\" && isLoopback(url.hostname))) {\n throw new PiPodError(`identity provider ${name} must use HTTPS except for loopback development`);\n }\n return url;\n}\n\nexport function discoveryUrl(issuer: string): string {\n return `${normalizeIssuer(issuer)}/.well-known/openid-configuration`;\n}\n\nexport async function discover(issuer: string): Promise<OidcMetadata> {\n const key = normalizeIssuer(issuer);\n const issuerUrl = parseSecureOidcUrl(key, \"issuer\");\n if (issuerUrl.search) {\n throw new PiPodError(\"identity provider issuer must not contain a query string\");\n }\n const cached = metadataCache.get(key);\n if (cached) return cached;\n\n const res = await fetch(discoveryUrl(key), {\n redirect: \"error\",\n signal: AbortSignal.timeout(OIDC_NETWORK_TIMEOUT_MS),\n }).catch((e) => {\n throw new PiPodError(`cannot reach the identity provider at ${key}`, {\n hint: String(e instanceof Error ? e.message : e),\n });\n });\n if (!res.ok) {\n throw new PiPodError(`identity provider discovery failed (HTTP ${res.status})`, {\n hint: `check PI_POD_ISSUER / --issuer (${key})`,\n });\n }\n\n let body: Partial<OidcMetadata>;\n try {\n body = (await res.json()) as Partial<OidcMetadata>;\n } catch {\n throw new PiPodError(\"identity provider discovery returned invalid JSON\");\n }\n if (body.issuer !== key) {\n throw new PiPodError(\"identity provider discovery returned a different issuer\", {\n hint: `expected ${key}, received ${String(body.issuer ?? \"(missing)\")}`,\n });\n }\n if (!body.authorization_endpoint || !body.token_endpoint || !body.jwks_uri) {\n throw new PiPodError(\"identity provider discovery document is missing required endpoints\");\n }\n\n for (const [name, value] of Object.entries({\n authorization_endpoint: body.authorization_endpoint,\n token_endpoint: body.token_endpoint,\n jwks_uri: body.jwks_uri,\n end_session_endpoint: body.end_session_endpoint,\n revocation_endpoint: body.revocation_endpoint,\n })) {\n if (!value) continue;\n const endpoint = parseSecureOidcUrl(value, name);\n if (endpoint.origin !== issuerUrl.origin) {\n throw new PiPodError(`identity provider discovery returned a cross-origin ${name}`);\n }\n }\n\n const meta: OidcMetadata = {\n issuer: body.issuer,\n authorization_endpoint: body.authorization_endpoint,\n token_endpoint: body.token_endpoint,\n jwks_uri: body.jwks_uri,\n ...(body.end_session_endpoint ? { end_session_endpoint: body.end_session_endpoint } : {}),\n ...(body.revocation_endpoint ? { revocation_endpoint: body.revocation_endpoint } : {}),\n };\n metadataCache.set(key, meta);\n return meta;\n}\n\nexport function clearOidcCache(): void {\n metadataCache.clear();\n idTokenJwksCache.clear();\n}\n\nexport function createPkce(): { verifier: string; challenge: string } {\n const verifier = randomBytes(48).toString(\"base64url\");\n return { verifier, challenge: createHash(\"sha256\").update(verifier).digest(\"base64url\") };\n}\n\nexport function createState(): string {\n return randomBytes(24).toString(\"base64url\");\n}\n\nexport function createNonce(): string {\n return randomBytes(24).toString(\"base64url\");\n}\n\n/**\n * Organization selection scope. Without an alias, Zitadel resolves the user's own\n * organization (the resource owner). With one, login is restricted to the organization\n * whose primary domain matches.\n */\nexport function organizationScope(alias?: string): string {\n if (alias === undefined) return \"\";\n if (\n alias.length === 0 ||\n alias.length > ORGANIZATION_ALIAS_MAX_LENGTH ||\n !/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(alias)\n ) {\n throw new PiPodError(\"organization alias contains invalid characters\");\n }\n return `urn:zitadel:iam:org:domain:primary:${alias}`;\n}\n\nexport function authorizeUrl(\n meta: OidcMetadata,\n args: {\n clientId: string;\n redirectUri: string;\n challenge: string;\n state: string;\n nonce: string;\n orgAlias?: string;\n },\n): string {\n const url = new URL(meta.authorization_endpoint);\n url.searchParams.set(\"response_type\", \"code\");\n url.searchParams.set(\"client_id\", args.clientId);\n url.searchParams.set(\"redirect_uri\", args.redirectUri);\n const scopes = [\"openid\", \"profile\", \"email\", OFFLINE_ACCESS_SCOPE, RESOURCE_OWNER_SCOPE, PROJECT_ROLES_SCOPE];\n const orgScope = organizationScope(args.orgAlias);\n if (orgScope) scopes.push(orgScope);\n url.searchParams.set(\"scope\", scopes.join(\" \"));\n url.searchParams.set(\"code_challenge\", args.challenge);\n url.searchParams.set(\"code_challenge_method\", \"S256\");\n url.searchParams.set(\"state\", args.state);\n url.searchParams.set(\"nonce\", args.nonce);\n return url.toString();\n}\n\nasync function readTokenResponse(res: Response): Promise<TokenSet> {\n if (!res.ok) {\n throw new PiPodError(\"the identity provider refused the token request\", {\n hint: `HTTP ${res.status} — run \\`pipod login\\` again`,\n });\n }\n let body: { access_token?: string; refresh_token?: string; id_token?: string };\n try {\n body = (await res.json()) as typeof body;\n } catch {\n throw new PiPodError(\"the identity provider returned an invalid token response\");\n }\n if (!body.access_token) throw new PiPodError(\"the identity provider returned no access token\");\n return {\n accessToken: body.access_token,\n ...(body.refresh_token ? { refreshToken: body.refresh_token } : {}),\n ...(body.id_token ? { idToken: body.id_token } : {}),\n };\n}\n\nexport async function exchangeCode(\n meta: OidcMetadata,\n args: { clientId: string; code: string; verifier: string; redirectUri: string; nonce: string },\n): Promise<TokenSet> {\n const res = await fetch(meta.token_endpoint, {\n method: \"POST\",\n redirect: \"error\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: \"authorization_code\",\n client_id: args.clientId,\n code: args.code,\n code_verifier: args.verifier,\n redirect_uri: args.redirectUri,\n }),\n signal: AbortSignal.timeout(OIDC_NETWORK_TIMEOUT_MS),\n }).catch((e) => {\n throw new PiPodError(\"cannot reach the identity provider token endpoint\", {\n hint: String(e instanceof Error ? e.message : e),\n });\n });\n const tokens = await readTokenResponse(res);\n if (!tokens.idToken) throw new PiPodError(\"the identity provider returned no ID token\");\n await verifyIdToken(meta, tokens.idToken, args.clientId, tokens.accessToken, args.nonce);\n return tokens;\n}\n\nasync function verifyIdToken(\n meta: OidcMetadata,\n token: string,\n clientId: string,\n accessToken: string,\n expectedNonce?: string,\n): Promise<void> {\n let jwks = idTokenJwksCache.get(meta.jwks_uri);\n if (!jwks) {\n jwks = createRemoteJWKSet(new URL(meta.jwks_uri), { timeoutDuration: OIDC_NETWORK_TIMEOUT_MS });\n idTokenJwksCache.set(meta.jwks_uri, jwks);\n }\n try {\n const { payload } = await jwtVerify(token, jwks, {\n issuer: meta.issuer,\n audience: clientId,\n algorithms: [\"RS256\"],\n requiredClaims: [\"sub\", \"iat\", \"exp\"],\n clockTolerance: ID_TOKEN_CLOCK_TOLERANCE_SECONDS,\n });\n if (typeof payload.sub !== \"string\" || payload.sub.length === 0) throw new Error(\"missing subject\");\n if (\n typeof payload.iat !== \"number\" ||\n payload.iat > Math.floor(Date.now() / 1000) + ID_TOKEN_CLOCK_TOLERANCE_SECONDS\n ) {\n throw new Error(\"invalid issued-at time\");\n }\n if (\n expectedNonce !== undefined &&\n (typeof payload.nonce !== \"string\" || !timingSafeEqualString(payload.nonce, expectedNonce))\n ) {\n throw new Error(\"nonce mismatch\");\n }\n if (payload.at_hash !== undefined) {\n if (typeof payload.at_hash !== \"string\") throw new Error(\"invalid access-token hash\");\n const expectedAtHash = createHash(\"sha256\").update(accessToken).digest().subarray(0, 16).toString(\"base64url\");\n if (!timingSafeEqualString(payload.at_hash, expectedAtHash)) throw new Error(\"access-token hash mismatch\");\n }\n } catch {\n throw new PiPodError(\"the identity provider returned an invalid ID token\", {\n hint: \"run `pipod login` again\",\n });\n }\n}\n\nexport async function refreshTokens(\n meta: OidcMetadata,\n args: { clientId: string; refreshToken: string },\n): Promise<TokenSet> {\n const res = await fetch(meta.token_endpoint, {\n method: \"POST\",\n redirect: \"error\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: \"refresh_token\",\n client_id: args.clientId,\n refresh_token: args.refreshToken,\n }),\n signal: AbortSignal.timeout(OIDC_NETWORK_TIMEOUT_MS),\n }).catch(() => null);\n if (!res) throw new PiPodError(\"your pi pod server session has expired\", { hint: \"run `pipod login`\" });\n try {\n const tokens = await readTokenResponse(res);\n if (tokens.idToken) {\n await verifyIdToken(meta, tokens.idToken, args.clientId, tokens.accessToken);\n }\n return tokens;\n } catch {\n throw new PiPodError(\"your pi pod server session has expired\", { hint: \"run `pipod login`\" });\n }\n}\n\nexport async function revokeToken(\n meta: OidcMetadata,\n args: { clientId: string; token: string; tokenTypeHint?: string },\n): Promise<void> {\n if (!meta.revocation_endpoint) return;\n await fetch(meta.revocation_endpoint, {\n method: \"POST\",\n redirect: \"error\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n client_id: args.clientId,\n token: args.token,\n ...(args.tokenTypeHint ? { token_type_hint: args.tokenTypeHint } : {}),\n }),\n signal: AbortSignal.timeout(OIDC_NETWORK_TIMEOUT_MS),\n }).catch(() => {});\n}\n\nexport function endSessionUrl(\n meta: OidcMetadata,\n args: { idToken?: string; postLogoutRedirectUri?: string; clientId: string },\n): string | null {\n if (!meta.end_session_endpoint) return null;\n const url = new URL(meta.end_session_endpoint);\n if (args.idToken) url.searchParams.set(\"id_token_hint\", args.idToken);\n url.searchParams.set(\"client_id\", args.clientId);\n if (args.postLogoutRedirectUri) url.searchParams.set(\"post_logout_redirect_uri\", args.postLogoutRedirectUri);\n return url.toString();\n}\n\nexport function accountConsoleUrl(issuer: string): string {\n return `${normalizeIssuer(issuer)}/ui/console/users/me`;\n}\n\nexport function adminConsoleUrl(issuer: string): string {\n return `${normalizeIssuer(issuer)}/ui/console`;\n}\n\nexport function timingSafeEqualString(left: string, right: string): boolean {\n if (left.length !== right.length) return false;\n return timingSafeEqual(Buffer.from(left), Buffer.from(right));\n}\n\nexport function decodeJwtPayload(token: string): Record<string, unknown> | null {\n const parts = token.split(\".\");\n if (parts.length < 2) return null;\n try {\n return JSON.parse(Buffer.from(parts[1]!, \"base64url\").toString(\"utf8\")) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\nexport function organizationFromAccessToken(token: string): {\n id: string;\n alias: string;\n name: string | null;\n permissions: string[];\n} | null {\n const payload = decodeJwtPayload(token);\n if (!payload) return null;\n const id = payload[\"urn:zitadel:iam:user:resourceowner:id\"];\n if (typeof id !== \"string\" || !id) return null;\n const domain = payload[\"urn:zitadel:iam:user:resourceowner:primary_domain\"];\n const name = payload[\"urn:zitadel:iam:user:resourceowner:name\"];\n // Only role grants attributed to the token's own organization count as permissions.\n const permissions = new Set<string>();\n for (const [claim, container] of Object.entries(payload)) {\n const isRolesClaim =\n claim === \"urn:zitadel:iam:org:project:roles\" ||\n /^urn:zitadel:iam:org:project:[^:]+:roles$/.test(claim);\n if (!isRolesClaim || !container || typeof container !== \"object\" || Array.isArray(container)) continue;\n for (const [role, grants] of Object.entries(container as Record<string, unknown>)) {\n if (!role || !grants || typeof grants !== \"object\" || Array.isArray(grants)) continue;\n if (Object.prototype.hasOwnProperty.call(grants, id)) permissions.add(role);\n }\n }\n return {\n id,\n alias: typeof domain === \"string\" && domain ? domain : id,\n name: typeof name === \"string\" && name ? name : null,\n permissions: [...permissions],\n };\n}\n","/**\n * src/account/store.ts — the machine's pi pod server session, `~/.pi-pod/auth.json`\n * (account-mode-spec §3.2).\n *\n * Presence of this file IS account mode (§2): every command that would otherwise talk to a\n * provider reads it first and, when it holds a session, talks to the server instead. It\n * lives next to `~/.pi-pod/env`, which already holds secrets of equivalent severity, and is\n * written 600 the same way.\n */\nimport { randomBytes } from \"node:crypto\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { PiPodError } from \"../errors.js\";\nimport { userConfigDir } from \"../userconfig.js\";\n\nexport const AUTH_FILE = \"auth.json\";\nexport const AUTH_LOCK_STALE_MS = 2 * 60 * 1000;\nexport const AUTH_LOCK_WAIT_MS = 30 * 1000;\nconst AUTH_LOCK_RETRY_MS = 25;\n\nexport interface AccountUser {\n id: string;\n email: string;\n displayName?: string | null;\n}\n\nexport interface AccountAuth {\n serverUrl: string;\n accessToken: string;\n /** Absent for `login --token` sessions (dev/CI): they expire hard, by design. */\n refreshToken?: string;\n /** Present after a direct Zitadel login; used for RP-initiated logout. */\n idToken?: string;\n /** Zitadel instance issuer used for discovery, refresh, and logout. */\n issuer?: string;\n clientId?: string;\n user: AccountUser;\n /** Active organization id copied from the verified token; not a request selector. */\n orgId: string;\n orgAlias?: string;\n /** A pod's own scoped token rather than a person's session: reaches only its children. */\n podToken?: boolean;\n}\n\nexport function accountAuthPath(home?: string | undefined): string | null {\n const dir = userConfigDir(home);\n return dir ? path.join(dir, AUTH_FILE) : null;\n}\n\nexport function readAccountAuth(home?: string | undefined): AccountAuth | null {\n const file = accountAuthPath(home);\n if (!file || !fs.existsSync(file)) return null;\n let parsed: unknown;\n try {\n parsed = JSON.parse(fs.readFileSync(file, \"utf8\"));\n } catch {\n throw new PiPodError(`could not parse ${file}`, {\n hint: \"run `pipod login` again to replace the invalid session\",\n });\n }\n const auth = parsed as AccountAuth;\n if (\n !auth ||\n typeof auth.serverUrl !== \"string\" ||\n typeof auth.accessToken !== \"string\" ||\n !auth.user ||\n typeof auth.orgId !== \"string\"\n ) {\n throw new PiPodError(`${file} is not a pi pod session`, {\n hint: \"run `pipod login` again to replace the invalid session\",\n });\n }\n if (!auth.podToken && auth.refreshToken && (typeof auth.issuer !== \"string\" || typeof auth.clientId !== \"string\")) {\n throw new PiPodError(`${file} contains a session from an unsupported identity provider`, {\n hint: \"run `pipod login` again to create a Zitadel OIDC session\",\n });\n }\n return auth;\n}\n\n/**\n * Account mode from inside a pod (nested pods): the server injected this pod's scoped token,\n * so `pipod` works here without a sign-in — bounded to the pods this one launched. The org\n * and user are the server's to know; the token names them on every request.\n */\nexport function readPodTokenAuth(env: NodeJS.ProcessEnv = process.env): AccountAuth | null {\n const serverUrl = env[\"PI_POD_SERVER_URL\"]?.trim();\n const accessToken = env[\"PI_POD_SERVER_TOKEN\"]?.trim();\n if (!serverUrl || !accessToken) return null;\n return {\n serverUrl,\n accessToken,\n user: { id: env[\"PI_POD_SERVER_POD_ID\"] ?? \"\", email: \"this pod\" },\n orgId: \"\",\n podToken: true,\n };\n}\n\n/** Replace auth.json atomically so readers see either the old or complete new owner-only file. */\nexport function writeAccountAuth(auth: AccountAuth, home?: string | undefined): string {\n const file = accountAuthPath(home);\n if (!file) throw new PiPodError(\"cannot resolve a home directory to store the login in\");\n fs.mkdirSync(path.dirname(file), { recursive: true });\n const temp = `${file}.${process.pid}.${randomBytes(8).toString(\"hex\")}.tmp`;\n let handle: number | null = null;\n try {\n handle = fs.openSync(temp, \"wx\", 0o600);\n fs.writeFileSync(handle, `${JSON.stringify(auth, null, 2)}\\n`, \"utf8\");\n fs.fsyncSync(handle);\n fs.closeSync(handle);\n handle = null;\n fs.renameSync(temp, file);\n } finally {\n if (handle !== null) fs.closeSync(handle);\n fs.rmSync(temp, { force: true });\n }\n return file;\n}\n\n/** Serialize refresh-token rotation across independent CLI processes. */\nexport async function withAccountAuthLock<T>(\n home: string | undefined,\n action: () => Promise<T>,\n): Promise<T> {\n const file = accountAuthPath(home);\n if (!file) throw new PiPodError(\"cannot resolve a home directory to refresh the login in\");\n fs.mkdirSync(path.dirname(file), { recursive: true });\n const lock = `${file}.lock`;\n const owner = `${process.pid}:${randomBytes(16).toString(\"hex\")}`;\n const deadline = Date.now() + AUTH_LOCK_WAIT_MS;\n\n while (true) {\n try {\n const handle = fs.openSync(lock, \"wx\", 0o600);\n try {\n fs.writeFileSync(handle, owner, \"utf8\");\n fs.fsyncSync(handle);\n } finally {\n fs.closeSync(handle);\n }\n break;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n try {\n const stat = fs.statSync(lock);\n if (Date.now() - stat.mtimeMs > AUTH_LOCK_STALE_MS) {\n fs.rmSync(lock, { force: true });\n continue;\n }\n } catch (statError) {\n if ((statError as NodeJS.ErrnoException).code === \"ENOENT\") continue;\n throw statError;\n }\n if (Date.now() >= deadline) {\n throw new PiPodError(\"timed out waiting for another pi pod process to refresh the login\", {\n hint: \"retry the command; if it persists, run `pipod login` again\",\n });\n }\n await new Promise((resolve) => setTimeout(resolve, AUTH_LOCK_RETRY_MS));\n }\n }\n\n try {\n return await action();\n } finally {\n try {\n if (fs.readFileSync(lock, \"utf8\") === owner) fs.rmSync(lock, { force: true });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n }\n}\n\nexport function clearAccountAuth(home?: string | undefined): boolean {\n const file = accountAuthPath(home);\n if (!file || !fs.existsSync(file)) return false;\n fs.rmSync(file);\n return true;\n}\n","/**\n * `~/.pi-pod/` client state. config.json holds client preferences only; pod settings live in\n * organization, template, and project layers. This module also retains generic deep-merge and\n * provenance helpers shared with config validation and historical callers.\n */\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { hostHome } from \"./hostconfig.js\";\nimport { packageRoot } from \"./image.js\";\n\n/** Same name as the repo directory, one level up in the hierarchy — deliberately. */\nexport const USER_CONFIG_DIR = \".pi-pod\";\nexport const USER_CONFIG_FILE = \"config.json\";\n\n/** Server-scope sync files (`org.env`, `user.env`, `template-<name>.env`), mode 600. */\nexport const USER_SECRETS_DIR = \"secrets\";\n\n/** The packaged template `~/.pi-pod/` starts life as. */\nexport const USER_CONFIG_TEMPLATE_PATH = [\"templates\", \"user-config.jsonc\"] as const;\n\n/** The retired machine secrets layer — read only to warn a migrator, never as a source. */\nconst LEGACY_USER_ENV_FILE = \"env\";\n\nexport function userConfigDir(home?: string | undefined): string | null {\n const resolved = hostHome(home);\n return resolved ? path.join(resolved, USER_CONFIG_DIR) : null;\n}\n\nexport function userConfigPath(home?: string | undefined): string | null {\n const dir = userConfigDir(home);\n return dir ? path.join(dir, USER_CONFIG_FILE) : null;\n}\n\nexport function userSecretsDir(home?: string | undefined): string | null {\n const dir = userConfigDir(home);\n return dir ? path.join(dir, USER_SECRETS_DIR) : null;\n}\n\n/**\n * A warning when `~/.pi-pod/env` still holds keys. The machine secrets layer is gone: its\n * job is done by the synced `user` scope (or a project env file). The file is never read as\n * a secret source and never deleted — only the person who put keys in it knows which scope\n * each one belongs in. Empty and comments-only files are ignored.\n */\nexport function legacyUserEnvWarning(home?: string | undefined): string | null {\n const dir = userConfigDir(home);\n if (!dir) return null;\n const file = path.join(dir, LEGACY_USER_ENV_FILE);\n let text: string;\n try {\n text = fs.readFileSync(file, \"utf8\");\n } catch {\n return null;\n }\n const names = text\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line !== \"\" && !line.startsWith(\"#\"))\n .map((line) => (line.startsWith(\"export \") ? line.slice(7).trim() : line))\n .filter((line) => {\n const eq = line.indexOf(\"=\");\n return eq > 0 && line.slice(eq + 1).trim() !== \"\";\n })\n .map((line) => line.slice(0, line.indexOf(\"=\")).trim());\n if (names.length === 0) return null;\n return (\n `${displayPath(file, home)} is no longer read (${names.join(\", \")}) — move each value into ` +\n `~/.pi-pod/secrets/user.env and run \\`pipod secrets sync user\\`, or into a project .pi-pod/env, ` +\n `then delete the file`\n );\n}\n\n/**\n * A packaged template's contents, or null when the file is missing.\n *\n * Static assets rather than strings built from {@link DEFAULT_CONFIG}, so the file a user reads\n * keeps its comments. Drift between template and defaults is caught by a unit test that parses\n * the config template and compares it against the built-in defaults.\n */\nexport function readTemplate(relative: readonly string[]): string | null {\n try {\n return fs.readFileSync(path.join(packageRoot(), ...relative), \"utf8\");\n } catch {\n return null;\n }\n}\n\nexport function readUserConfigTemplate(): string | null {\n return readTemplate(USER_CONFIG_TEMPLATE_PATH);\n}\n\nexport interface EnsureUserConfigResult {\n /** Absolute path of the config, or null when there is no home directory to put it in. */\n path: string | null;\n /** Files this call actually wrote — the caller announces a real side effect, once. */\n created: string[];\n}\n\n/**\n * Create `~/.pi-pod/` if it is not there: the config, and the secrets sync directory.\n *\n * Idempotent and never destructive: existing files are left exactly as the user left them, with\n * no `--force` to say otherwise — clobbering real keys is not a thing an install hook should be\n * able to do. This runs at install time *and* at the top of every command, because the install\n * hook is the one part of this that a `--ignore-scripts` install, a `npm link` from a checkout,\n * or a copied binary can skip.\n *\n * Never throws. A read-only home directory is a reason to run without a user layer, not a\n * reason a session cannot start.\n */\nexport function ensureUserConfig(opts: { home?: string | undefined } = {}): EnsureUserConfigResult {\n const dir = userConfigDir(opts.home);\n const target = userConfigPath(opts.home);\n if (!dir || !target) return { path: null, created: [] };\n\n const created: string[] = [];\n if (!fs.existsSync(target)) {\n const template = readTemplate(USER_CONFIG_TEMPLATE_PATH);\n if (template !== null) {\n try {\n fs.mkdirSync(dir, { recursive: true });\n // wx: two pi pod invocations racing here must not have one clobber the other's file.\n fs.writeFileSync(target, template, { flag: \"wx\", mode: 0o644 });\n fs.chmodSync(target, 0o644);\n created.push(target);\n } catch {\n // Already there, or a home directory we cannot write. Neither stops a session.\n }\n }\n }\n\n // Mode 700 like the files it will hold: `secrets sync` should never find its default\n // directory missing, and never find it world-readable either.\n try {\n fs.mkdirSync(path.join(dir, USER_SECRETS_DIR), { recursive: true, mode: 0o700 });\n } catch {\n // Same tolerance as above.\n }\n\n return { path: target, created };\n}\n\n/** `/Users/x/.pi-pod/config.json` → `~/.pi-pod/config.json`, for messages. */\nexport function displayPath(target: string, home?: string | undefined): string {\n const resolved = hostHome(home);\n if (!resolved) return target;\n const rel = path.relative(resolved, target);\n return rel === \"\" || rel.startsWith(\"..\") || path.isAbsolute(rel) ? target : path.join(\"~\", rel);\n}\n\n/**\n * Merge one config layer over another, per key, all the way down.\n *\n * Objects recurse; everything else is replaced by the override, including `null` (which is a\n * real value here — `repo.branch: null` means \"the branch the host is on\") and arrays. Arrays\n * replacing rather than concatenating is the one rule worth stating out loud: an `egress.allow`\n * that meant \"these hosts, plus whatever is in the reader's home directory\" would make a\n * committed allowlist unreviewable.\n */\nexport function mergeConfigLayers(base: unknown, override: unknown): unknown {\n if (override === undefined) return base;\n if (!isPlainObject(base) || !isPlainObject(override)) return override;\n\n const out: Record<string, unknown> = { ...base };\n for (const [key, value] of Object.entries(override)) {\n out[key] = Object.hasOwn(base, key) ? mergeConfigLayers(base[key], value) : value;\n }\n return out;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\n/** One explicitly-configured leaf value and which layer's setting of it won. */\nexport interface ConfigProvenanceEntry {\n /** Dotted config path, e.g. `pi.model` or `egress.allow`. Arrays are one leaf. */\n path: string;\n /** The last layer that set this path — the value the merged config carries. */\n winner: string;\n /** Earlier layers whose different explicit values were overridden, oldest first. */\n over: string[];\n}\n\n/**\n * Per-leaf provenance across ordered config layers (earliest first, later wins), matching\n * {@link mergeConfigLayers} semantics: objects recurse, arrays and scalars are leaves.\n * Layers that agree are not reported as overriding each other because nothing was lost.\n */\nexport function configProvenance(\n layers: Array<{ name: string; raw: unknown }>,\n): ConfigProvenanceEntry[] {\n const entries = new Map<string, { winner: string; value: string; over: string[] }>();\n const visit = (name: string, value: unknown, path: string): void => {\n if (isPlainObject(value)) {\n for (const [key, child] of Object.entries(value)) {\n if (child === undefined) continue;\n visit(name, child, path === \"\" ? key : `${path}.${key}`);\n }\n return;\n }\n const serialized = JSON.stringify(value) ?? \"undefined\";\n const existing = entries.get(path);\n if (!existing) {\n entries.set(path, { winner: name, value: serialized, over: [] });\n return;\n }\n if (existing.winner !== name && existing.value !== serialized) existing.over.push(existing.winner);\n existing.winner = name;\n existing.value = serialized;\n };\n for (const layer of layers) {\n if (layer.raw == null || !isPlainObject(layer.raw)) continue;\n visit(layer.name, layer.raw, \"\");\n }\n return [...entries.entries()].map(([path, e]) => ({ path, winner: e.winner, over: e.over }));\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { PiPodError } from \"./errors.js\";\n\nexport const HOST_PI_AGENT_SUBPATH = path.join(\".pi\", \"agent\");\nexport const HOST_COUPLED_SETTINGS_KEYS = [\"hooks\", \"mcpServers\"] as const;\n\nexport interface HostConfigSelection {\n settings: boolean;\n packages: boolean;\n}\n\nexport const DEFAULT_HOST_CONFIG: HostConfigSelection = {\n settings: true,\n packages: true,\n};\n\nconst ENV_REFERENCE = /^\\$(?:[A-Z_][A-Z0-9_]*|\\{[A-Z_][A-Z0-9_]*\\})$/;\nconst CREDENTIAL_FIELD =\n /(?:^|[-_])(?:api[-_]?key|api[-_]?token|access[-_]?token|auth(?:orization)?|auth[-_]?token|bearer|client[-_]?secret|credentials?|password|secret|token)$/i;\n\nexport function sanitizeModelsForTransport(\n input: Record<string, unknown>,\n): { models: Record<string, unknown>; dropped: string[] } {\n const dropped: string[] = [];\n const visit = (value: unknown, pathParts: string[], inHeaders = false): unknown => {\n if (Array.isArray(value)) return value.map((item, index) => visit(item, [...pathParts, String(index)], inHeaders));\n if (value === null || typeof value !== \"object\") return value;\n const result: Record<string, unknown> = {};\n for (const [key, child] of Object.entries(value as Record<string, unknown>)) {\n const credentialField = CREDENTIAL_FIELD.test(key) || (inHeaders && /(?:key|token|secret)$/i.test(key));\n if (credentialField && (typeof child !== \"string\" || !ENV_REFERENCE.test(child))) {\n dropped.push([...pathParts, key].join(\".\"));\n continue;\n }\n result[key] = visit(child, [...pathParts, key], inHeaders || key === \"headers\");\n }\n return result;\n };\n return { models: visit(input, []) as Record<string, unknown>, dropped };\n}\n\nexport function hostHome(explicit?: string | undefined): string | null {\n return explicit ?? process.env[\"HOME\"] ?? process.env[\"USERPROFILE\"] ?? null;\n}\n\nexport function hostPiAuthPath(home: string): string {\n return path.join(home, HOST_PI_AGENT_SUBPATH, \"auth.json\");\n}\n\nexport function readPiAuthOAuthProviders(home: string): string[] {\n try {\n const parsed = JSON.parse(fs.readFileSync(hostPiAuthPath(home), \"utf8\")) as unknown;\n if (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) return [];\n return Object.entries(parsed as Record<string, unknown>)\n .filter(([, entry]) =>\n entry !== null && typeof entry === \"object\" && !Array.isArray(entry) &&\n (entry as Record<string, unknown>)[\"type\"] === \"oauth\")\n .map(([provider]) => provider)\n .sort();\n } catch {\n return [];\n }\n}\n\nexport const PI_AUTH_PROBE_DEFAULT_MODELS: Record<string, string> = {\n anthropic: \"claude-sonnet-4-5\",\n \"openai-codex\": \"gpt-5\",\n xai: \"grok-4.5\",\n \"google-gemini-cli\": \"gemini-2.5-pro\",\n \"kimi-coding\": \"kimi-for-coding\",\n meta: \"muse-spark-1.2\",\n};\n\nexport function piAuthProbeModel(\n provider: string,\n hostModel: { provider: string; model: string } | null,\n): string | null {\n if (hostModel && hostModel.provider === provider && hostModel.model) return hostModel.model;\n return PI_AUTH_PROBE_DEFAULT_MODELS[provider] ?? null;\n}\n\nexport function piAuthPrintBearerCommand(provider: string, model: string): string {\n return `pi auth print-bearer-token --provider ${provider} --model ${model}`;\n}\n\nexport function mergePiAuthContents(local: string, remote: string): string {\n let localParsed: unknown;\n let remoteParsed: unknown;\n try {\n localParsed = JSON.parse(local);\n remoteParsed = JSON.parse(remote);\n } catch {\n return remote;\n }\n const isObject = (value: unknown): value is Record<string, unknown> =>\n value !== null && typeof value === \"object\" && !Array.isArray(value);\n if (!isObject(localParsed) || !isObject(remoteParsed)) return remote;\n return JSON.stringify({ ...localParsed, ...remoteParsed }, null, 2) + \"\\n\";\n}\n\nexport interface FilteredSettings {\n settings: Record<string, unknown>;\n dropped: string[];\n}\n\nexport function filterSettings(\n raw: string,\n sourcePath: string,\n opts: { packages: boolean },\n): FilteredSettings {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (error) {\n throw new PiPodError(`${sourcePath} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`, {\n hint: 'fix it, or set \"pi\": { \"hostConfig\": { \"settings\": false } }',\n });\n }\n if (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new PiPodError(`${sourcePath} is not a JSON object`);\n }\n const settings = { ...(parsed as Record<string, unknown>) };\n const dropped: string[] = [];\n for (const key of HOST_COUPLED_SETTINGS_KEYS) {\n if (!Object.hasOwn(settings, key)) continue;\n delete settings[key];\n dropped.push(key);\n }\n if (!opts.packages && Object.hasOwn(settings, \"packages\")) {\n delete settings[\"packages\"];\n dropped.push(\"packages\");\n }\n return { settings, dropped };\n}\n\nexport function npmSpecOf(source: string): string | null {\n return source.startsWith(\"npm:\") ? source.slice(\"npm:\".length) : null;\n}\n\nexport function npmPackageName(spec: string): string {\n const at = spec.lastIndexOf(\"@\");\n return at > 0 ? spec.slice(0, at) : spec;\n}\n\nexport function packageSpecNamesClientExtension(spec: string, name: string): boolean {\n if (spec === name) return true;\n const npmSpec = npmSpecOf(spec);\n return npmSpec !== null && npmPackageName(npmSpec) === name;\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { bundledPiVersion } from \"./client/piversion.js\";\nimport { derivedImageRef, managedImageAssetDigest, type ImageResources } from \"./image-recipe.js\";\n\nexport {\n IMAGE_NAME,\n bakeDigest,\n composeBakeScript,\n derivedImageRef,\n isEffectivelyEmptyScript,\n isManagedImageRef,\n managedImageAssetDigest,\n normalizeImagePackages,\n packagesDigest,\n type ImageResources,\n} from \"./image-recipe.js\";\n\nexport function launcherVersion(): string {\n try {\n const pkg = JSON.parse(fs.readFileSync(path.join(packageRoot(), \"package.json\"), \"utf8\")) as { version?: string };\n return pkg.version ?? \"0.0.0\";\n } catch {\n return \"0.0.0\";\n }\n}\n\nexport function defaultImageRef(\n version: string,\n resources?: ImageResources,\n packages?: string[],\n assetRoot: string = packageRoot(),\n bakeScript?: string,\n): string {\n return derivedImageRef({\n launcherVersion: version,\n piVersion: bundledPiVersion(),\n assetDigest: managedImageAssetDigest(assetRoot),\n resources,\n packages,\n bakeScript,\n });\n}\n\nexport function packageRoot(): string {\n const here = path.dirname(fileURLToPath(import.meta.url));\n let dir = here;\n for (let i = 0; i < 5; i++) {\n if (fs.existsSync(path.join(dir, \"package.json\"))) return dir;\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return path.resolve(here, \"..\");\n}\n","/**\n * src/client/piversion.ts — the pi version this launcher bundles (§10).\n *\n * pi pod pins pi exactly for newly built images. The shim reports the pod's pi in its hello;\n * account sessions enforce that exact version before exposing Pi's unversioned RPC surface.\n */\nimport { execFile } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { debug } from \"../log.js\";\n\nexport interface InstalledPiPackage {\n root: string;\n version: string;\n /** Package-declared `pi` executable, relative to `root`. */\n bin: string;\n}\n\nlet cached: InstalledPiPackage | null = null;\n\n/** The installed package this launcher actually imports — version and delivery share this authority. */\nexport function installedPiPackage(): InstalledPiPackage {\n if (cached) return cached;\n // The package is ESM-only and its exports map hides package.json, so resolve the entry\n // module and walk up to the package root.\n const entry = fileURLToPath(import.meta.resolve(\"@earendil-works/pi-coding-agent\"));\n const root = path.join(path.dirname(entry), \"..\");\n const pkg = JSON.parse(fs.readFileSync(path.join(root, \"package.json\"), \"utf8\")) as {\n version: string;\n bin?: string | Record<string, string>;\n };\n const bin = typeof pkg.bin === \"string\" ? pkg.bin : pkg.bin?.[\"pi\"];\n if (!bin || path.isAbsolute(bin) || path.normalize(bin).startsWith(`..${path.sep}`)) {\n throw new Error(\"the installed pi package has no safe package-declared `pi` executable\");\n }\n cached = { root, version: pkg.version, bin: bin.split(path.sep).join(path.posix.sep) };\n return cached;\n}\n\nexport function bundledPiVersion(): string {\n return installedPiPackage().version;\n}\n\nexport function describeVersionSkew(podPi: string, hostPi: string): string {\n return `the pod runs pi ${podPi} but this pi pod bundles pi ${hostPi}`;\n}\n\nexport type PiVersionComparison = -1 | 0 | 1;\n\n/** Compare two semantic pi versions, ignoring build metadata as SemVer requires. */\nexport function comparePiVersions(podPi: string, hostPi: string): PiVersionComparison | null {\n const pod = parseSemanticVersion(podPi);\n const host = parseSemanticVersion(hostPi);\n if (!pod || !host) return null;\n\n for (let i = 0; i < pod.core.length; i += 1) {\n const order = compareNumericIdentifier(pod.core[i]!, host.core[i]!);\n if (order !== 0) return order;\n }\n\n if (pod.prerelease === null && host.prerelease === null) return 0;\n if (pod.prerelease === null) return 1;\n if (host.prerelease === null) return -1;\n\n const length = Math.max(pod.prerelease.length, host.prerelease.length);\n for (let i = 0; i < length; i += 1) {\n const podPart = pod.prerelease[i];\n const hostPart = host.prerelease[i];\n if (podPart === undefined) return -1;\n if (hostPart === undefined) return 1;\n if (podPart === hostPart) continue;\n\n const podNumeric = /^\\d+$/.test(podPart);\n const hostNumeric = /^\\d+$/.test(hostPart);\n if (podNumeric && hostNumeric) return compareNumericIdentifier(podPart, hostPart);\n if (podNumeric) return -1;\n if (hostNumeric) return 1;\n return podPart < hostPart ? -1 : 1;\n }\n return 0;\n}\n\ninterface ParsedSemanticVersion {\n core: readonly [string, string, string];\n prerelease: readonly string[] | null;\n}\n\nfunction parseSemanticVersion(version: string): ParsedSemanticVersion | null {\n const match =\n /^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-([0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*))?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$/.exec(\n version,\n );\n if (!match) return null;\n\n const prerelease = match[4]?.split(\".\") ?? null;\n if (prerelease?.some((part) => /^\\d+$/.test(part) && part.length > 1 && part.startsWith(\"0\"))) {\n return null;\n }\n\n return { core: [match[1]!, match[2]!, match[3]!], prerelease };\n}\n\nfunction compareNumericIdentifier(left: string, right: string): PiVersionComparison {\n if (left.length !== right.length) return left.length < right.length ? -1 : 1;\n if (left === right) return 0;\n return left < right ? -1 : 1;\n}\n\n/**\n * Does a pod running this pi have `pi auth print-api-key` / `print-bearer-token`? The\n * commands landed in 0.83.0, and the pod-side Claude Code `apiKeyHelper` (§7.6) is built on\n * them.\n */\nexport function supportsCredentialPrint(version: string): boolean {\n const match = /^(\\d+)\\.(\\d+)\\.(\\d+)/.exec(version);\n if (!match) return false;\n const major = Number(match[1]);\n const minor = Number(match[2]);\n return major >= 1 || minor >= 83;\n}\n/** The npm package pods get their pi from; also the package this launcher bundles. */\nconst PI_PACKAGE = \"@earendil-works/pi-coding-agent\";\n\nlet latestCached: Promise<string | null> | null = null;\n\n/**\n * The newest pi published to npm, or `null` when the registry cannot be asked.\n *\n * Pods inherit pi from the launcher's bundle (§10), so \"are pods running the latest pi\" is\n * really \"is this launcher current\" — and this is the other half of that comparison. Used by\n * `image build`, which refuses to bake a stale pi, and by preflight, which warns that the\n * pods it is about to start are behind.\n *\n * `npm view` rather than a hand-rolled registry fetch because it honors the user's own\n * registry, proxy and auth configuration — the same route `pipod update` takes. Never\n * rejects and is cached for the process: an unreachable registry is a debug line, not a\n * failed launch, and no run needs to ask twice.\n */\nexport function latestPiVersion(opts: { timeoutMs?: number } = {}): Promise<string | null> {\n latestCached ??= queryLatestPi(opts.timeoutMs ?? 10_000);\n return latestCached;\n}\n\n/** Tests run several registries in one process. */\nexport function resetLatestPiVersion(): void {\n latestCached = null;\n}\n\nfunction queryLatestPi(timeoutMs: number): Promise<string | null> {\n return new Promise((resolve) => {\n execFile(\n \"npm\",\n [\"view\", `${PI_PACKAGE}@latest`, \"version\"],\n { timeout: timeoutMs, encoding: \"utf8\" },\n (err, stdout) => {\n if (err) {\n debug(`could not ask npm for the latest pi version: ${err.message}`);\n resolve(null);\n return;\n }\n const version = stdout.trim().split(\"\\n\").at(-1)?.trim() ?? \"\";\n resolve(version === \"\" ? null : version);\n },\n );\n });\n}\n\n/**\n * Is `candidate` a newer release than `current`? Numeric compare over the dot-separated\n * core; a pre-release suffix is ignored, which is fine for the one question this answers —\n * whether the pods this launcher builds are behind the latest pi.\n */\nexport function isNewerVersion(candidate: string, current: string): boolean {\n const core = (v: string) => v.split(\"-\")[0]!.split(\".\").map((p) => Number.parseInt(p, 10) || 0);\n const a = core(candidate);\n const b = core(current);\n for (let i = 0; i < Math.max(a.length, b.length); i++) {\n const x = a[i] ?? 0;\n const y = b[i] ?? 0;\n if (x !== y) return x > y;\n }\n return false;\n}\n","import { createHash } from \"node:crypto\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nexport const IMAGE_RECIPE_SCHEMA = 1;\nexport const IMAGE_NAME = \"pi-pod-base\";\nexport type ImageResources = { cpu?: number; memoryGB?: number; diskGB?: number };\n\nexport function normalizeImagePackages(packages: string[]): string[] {\n return [...new Set(packages.map((entry) => entry.trim()).filter(Boolean))].sort();\n}\n\nexport function packagesDigest(packages: string[]): string {\n const normalized = normalizeImagePackages(packages);\n if (normalized.length === 0) return \"\";\n return createHash(\"sha256\").update(normalized.join(\"\\n\")).digest(\"hex\").slice(0, 12);\n}\n\nexport function isEffectivelyEmptyScript(script: string): boolean {\n return !script\n .split(\"\\n\")\n .map((line) => line.trim())\n .some((line) => line.length > 0 && !line.startsWith(\"#\"));\n}\n\nexport function composeBakeScript(steps: Array<{ scope: string; script: string }>): string {\n const meaningful = steps.filter((step) => !isEffectivelyEmptyScript(step.script));\n if (meaningful.length === 0) return \"\";\n return meaningful\n .map(\n (step) =>\n `echo \"[bake] ${step.scope} bake script\"\\n(\\n${step.script}\\n)\\ncode=$?\\n` +\n `if [ \"$code\" -ne 0 ]; then echo \"[bake] ${step.scope} bake script failed with exit $code\" >&2; exit \"$code\"; fi`,\n )\n .join(\"\\n\");\n}\n\nexport function bakeDigest(bakeScript: string): string {\n return bakeScript ? createHash(\"sha256\").update(bakeScript).digest(\"hex\").slice(0, 12) : \"\";\n}\n\nexport function managedImageAssetDigest(assetRoot: string): string {\n const dockerfile = path.join(assetRoot, \"image\", \"Dockerfile\");\n if (!fs.existsSync(dockerfile)) throw new Error(`managed image Dockerfile not found: ${dockerfile}`);\n const stat = fs.lstatSync(dockerfile);\n return createHash(\"sha256\")\n .update(`image/Dockerfile\\0${stat.mode & 0o777}\\0`)\n .update(fs.readFileSync(dockerfile))\n .update(\"\\0\")\n .digest(\"hex\")\n .slice(0, 12);\n}\n\nexport function isManagedImageRef(ref: string): boolean {\n return ref === IMAGE_NAME || ref.startsWith(`${IMAGE_NAME}:`);\n}\n\nfunction resourceSuffix(resources?: ImageResources): string {\n if (!resources) return \"\";\n return [\n resources.cpu === undefined ? \"\" : `${resources.cpu}c`,\n resources.memoryGB === undefined ? \"\" : `${resources.memoryGB}m`,\n resources.diskGB === undefined ? \"\" : `${resources.diskGB}d`,\n ].join(\"\");\n}\n\nexport function derivedImageRef(input: {\n launcherVersion: string;\n piVersion: string;\n assetDigest: string;\n resources?: ImageResources;\n packages?: string[];\n bakeScript?: string;\n}): string {\n const sizing = resourceSuffix(input.resources);\n const packageId = packagesDigest(input.packages ?? []);\n const bakeId = bakeDigest(input.bakeScript ?? \"\");\n return [\n `${IMAGE_NAME}:r${IMAGE_RECIPE_SCHEMA}-pi${input.piVersion}`,\n sizing || null,\n `img${input.assetDigest}`,\n packageId ? `pkg${packageId}` : null,\n bakeId ? `bake${bakeId}` : null,\n ].filter((part): part is string => part !== null).join(\"-\");\n}\n","/**\n * src/account/workstation.ts — the personal workstation (SaaS edition) as the client sees it.\n *\n * On the SaaS backend every user gets a whole machine of their own — a \"workstation\" — and it\n * sleeps when idle. Any call that needs it while it is asleep or coming up is refused with a\n * typed, retryable HTTP 503 (or WebSocket close 4420) naming the workstation, its durable\n * operation, and how long to wait before asking again. That refusal is NOT fleet pressure, is\n * not the user's concurrency limit, and never means anything was lost: a stopped workstation\n * keeps every workspace on its own disk.\n *\n * The honest number matters here. Production measured, 2026-09-10 (ten operations across two\n * hosts in one evening — measurements, not an SLA):\n *\n * cold create → ready 407 s (host with eight pods), 708 s (empty host)\n * resume → ready 243 s, 690 s, 483 s, 312 s, 357 s\n * pod launch → ready 46 s, once the workstation is already warm\n *\n * So the copy in this file says \"several minutes\" and shows elapsed time, and never promises a\n * duration the server did not send. The old fleet copy (\"waiting for fleet capacity\", \"ask an\n * owner to register capacity\") stays valid for a real shared fleet on the self-hosted backend\n * and must never be reached from here.\n *\n * Everything is validated the way the server validates it on the way out\n * (`server/src/server/safe-errors.ts`): the reason against the allowlist, the host id\n * against the workstation route's own rule, the status href RECOMPUTED from the id rather than\n * trusted, the retry hint bounded, the operation reduced to the seven fields the status route\n * exposes. A malformed field means \"no detail\", never a forged one.\n */\n\nimport { CancelledError, isWorkstationAsleepReason, PiPodError, WORKSTATION_ASLEEP_REASONS } from \"../errors.js\";\nimport { color, debug, step } from \"../log.js\";\n\n/** Path shape of the owned-workstation status route, and of `hostId` inside a demand. */\nconst WORKSTATION_HOST_ID_RULE = /^boat-[A-Za-z0-9._-]{1,180}$/;\n/** `sandbox_hosts.boat_state`. */\nconst WORKSTATION_STATES: ReadonlySet<string> = new Set([\n \"provisioning\", \"starting\", \"running\", \"stopping\", \"stopped\", \"error\", \"unknown\", \"deleting\", \"deleted\",\n]);\n/** `boat_operations.kind` / `.state`, and the bounded phase slug the controller writes. */\nconst OPERATION_KINDS: ReadonlySet<string> = new Set([\n \"create\", \"resume\", \"stop\", \"delete\", \"publish\", \"activate\", \"ttl\",\n]);\nconst OPERATION_STATES: ReadonlySet<string> = new Set([\n \"pending\", \"running\", \"uncertain\", \"succeeded\", \"failed\", \"cancelled\",\n]);\nconst OPERATION_ID_RULE = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;\nconst PHASE_RULE = /^[A-Za-z0-9._:-]{1,64}$/;\nconst ERROR_CODE_RULE = /^[A-Za-z0-9._-]{1,64}$/;\n\n/**\n * The six reasons a host-demand refusal can carry (server `BOAT_HOST_DEMAND_REASONS`). A\n * seventh value from a newer server is tolerated: `retryable` on the wire decides, not this\n * list, and unrecognized reasons fall back to the server's own sentence.\n */\nexport const WORKSTATION_DEMAND_REASONS = [\n \"host_starting\",\n \"host_stopped\",\n \"host_deleted\",\n \"host_retired\",\n \"host_requires_reconciliation\",\n \"boat_starts_disabled\",\n] as const;\nexport type WorkstationDemandReason = (typeof WORKSTATION_DEMAND_REASONS)[number];\nconst WORKSTATION_DEMAND_REASON_SET: ReadonlySet<string> = new Set(WORKSTATION_DEMAND_REASONS);\n\n/**\n * Close reasons the gateway sends with code 4420 for a workstation that is not up\n * (`wsCloseForError`). 4420 is also the ordinary \"this pod is asleep\" code, so the reason —\n * not the code — is what tells the two apart. `host_archived` is the gateway's spelling of a\n * host that is no longer dialable.\n */\nexport const WORKSTATION_CLOSE_REASONS = WORKSTATION_ASLEEP_REASONS;\nexport const isWorkstationCloseReason = isWorkstationAsleepReason;\n\nexport interface WorkstationOperation {\n id: string;\n kind: string;\n state: string;\n phase: string;\n deadlineAt: string;\n retryAt: string | null;\n errorCode: string | null;\n}\n\n/**\n * A validated host-demand refusal: what the server said about the caller's own machine.\n *\n * The three constant fields are kept rather than collapsed away, so the value round-trips:\n * `PiPodError.detail` holds this object, and re-parsing it must recognize the same shape it\n * recognized on the wire.\n */\nexport interface WorkstationDemand {\n kind: \"admission\";\n resource: \"transitions\";\n unit: \"count\";\n reason: string;\n retryable: boolean;\n hostId?: string;\n /** Always recomputed from `hostId`; never the string the server sent. */\n statusHref?: string;\n state?: string;\n retryAfterMs?: number;\n operation?: WorkstationOperation | null;\n /**\n * The server's own sentence for this reason, when the response carried one. Not a wire\n * field of the demand: the transport copies it off the response body so an unrecognized\n * future reason can still be explained in the server's words rather than a generic\n * placeholder. Oversized or non-string values are dropped, never rejected — unlike the\n * validated fields above, nothing depends on it.\n */\n message?: string;\n}\n\n/** What `GET /v1/workstations/:hostId` answers. */\nexport interface WorkstationStatus {\n hostId: string;\n state?: string;\n operation: WorkstationOperation | null;\n}\n\n/**\n * One read of each own data property into a null-prototype object, so an accessor cannot\n * answer the validation and the copy differently, and an inherited property cannot answer at\n * all. Same defence the server applies on the way out.\n */\nfunction ownDataProperties(value: object): Record<string, unknown> {\n const snapshot: Record<string, unknown> = Object.create(null) as Record<string, unknown>;\n for (const key of Object.getOwnPropertyNames(value)) {\n const descriptor = Object.getOwnPropertyDescriptor(value, key);\n if (!descriptor || !(\"value\" in descriptor)) continue;\n snapshot[key] = descriptor.value;\n }\n return snapshot;\n}\n\nconst ISO_INSTANT_RULE = /^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,6})?(Z|[+-]\\d{2}:?\\d{2})?$/;\n\n/** A canonical instant re-rendered from the parse, so no server string survives verbatim. */\nfunction isoInstant(value: unknown): string | null {\n if (typeof value !== \"string\" || value.length > 40 || !ISO_INSTANT_RULE.test(value)) return null;\n const parsed = Date.parse(value);\n if (!Number.isFinite(parsed)) return null;\n return new Date(parsed).toISOString();\n}\n\n/** The seven fields the workstation status route exposes; all required, anything else dropped. */\nexport function parseWorkstationOperation(value: unknown): WorkstationOperation | null {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) return null;\n const record = ownDataProperties(value);\n if (typeof record[\"id\"] !== \"string\" || !OPERATION_ID_RULE.test(record[\"id\"])) return null;\n if (typeof record[\"kind\"] !== \"string\" || !OPERATION_KINDS.has(record[\"kind\"])) return null;\n if (typeof record[\"state\"] !== \"string\" || !OPERATION_STATES.has(record[\"state\"])) return null;\n if (typeof record[\"phase\"] !== \"string\" || !PHASE_RULE.test(record[\"phase\"])) return null;\n const deadlineAt = isoInstant(record[\"deadlineAt\"]);\n if (deadlineAt === null) return null;\n let retryAt: string | null = null;\n if (record[\"retryAt\"] !== undefined && record[\"retryAt\"] !== null) {\n retryAt = isoInstant(record[\"retryAt\"]);\n if (retryAt === null) return null;\n }\n let errorCode: string | null = null;\n if (record[\"errorCode\"] !== undefined && record[\"errorCode\"] !== null) {\n if (typeof record[\"errorCode\"] !== \"string\" || !ERROR_CODE_RULE.test(record[\"errorCode\"])) return null;\n errorCode = record[\"errorCode\"];\n }\n return { id: record[\"id\"], kind: record[\"kind\"], state: record[\"state\"], phase: record[\"phase\"], deadlineAt, retryAt, errorCode };\n}\n\n/**\n * Recognize a host-demand `detail` (server `boatHostDemandDetail`). The three constant fields\n * `kind`/`resource`/`unit` plus a string `reason` and a boolean `retryable` are what identify\n * the shape; every other field is a hint that degrades gracefully. A forged or malformed host\n * pair is dropped — never dialled, never trusted — and the demand still waits, just without a\n * status poll (the contract's \"unhosted\" wait: re-issue the original request on the same\n * schedule). The same holds for a malformed `state`, `retryAfterMs` or `operation`: every use\n * downstream already clamps or allowlists, so dropping the hint is safe and killing the whole\n * wait over one bad hint would strand a real workstation start on a typo.\n */\nexport function parseWorkstationDemand(value: unknown): WorkstationDemand | null {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) return null;\n const record = ownDataProperties(value);\n if (record[\"kind\"] !== \"admission\") return null;\n if (record[\"resource\"] !== \"transitions\" || record[\"unit\"] !== \"count\") return null;\n if (typeof record[\"reason\"] !== \"string\" || record[\"reason\"].length > 64) return null;\n if (typeof record[\"retryable\"] !== \"boolean\") return null;\n const demand: WorkstationDemand = {\n kind: \"admission\",\n resource: \"transitions\",\n unit: \"count\",\n reason: record[\"reason\"],\n retryable: record[\"retryable\"],\n };\n if (typeof record[\"hostId\"] === \"string\" && WORKSTATION_HOST_ID_RULE.test(record[\"hostId\"])) {\n // Recompute the link and compare rather than copying it: a path we dial is never a\n // string the response chose. On a mismatch both are dropped and the wait runs unhosted.\n if (record[\"statusHref\"] === undefined || record[\"statusHref\"] === workstationStatusHref(record[\"hostId\"])) {\n demand.hostId = record[\"hostId\"];\n demand.statusHref = workstationStatusHref(record[\"hostId\"]);\n }\n }\n if (typeof record[\"state\"] === \"string\" && WORKSTATION_STATES.has(record[\"state\"])) {\n demand.state = record[\"state\"];\n }\n if (typeof record[\"retryAfterMs\"] === \"number\" && Number.isFinite(record[\"retryAfterMs\"])) {\n const rounded = Math.round(record[\"retryAfterMs\"]);\n if (rounded >= 0 && rounded <= 300_000) demand.retryAfterMs = rounded;\n }\n if (record[\"operation\"] !== undefined) {\n if (record[\"operation\"] === null) {\n demand.operation = null;\n } else {\n const operation = parseWorkstationOperation(record[\"operation\"]);\n if (operation !== null) demand.operation = operation;\n }\n }\n if (typeof record[\"message\"] === \"string\" && record[\"message\"].length > 0 && record[\"message\"].length <= 240) {\n demand.message = record[\"message\"];\n }\n return demand;\n}\n\nexport function workstationStatusHref(hostId: string): string {\n return `/v1/workstations/${encodeURIComponent(hostId)}`;\n}\n\nexport function isWorkstationHostId(value: unknown): value is string {\n return typeof value === \"string\" && WORKSTATION_HOST_ID_RULE.test(value);\n}\n\n/** `GET /v1/workstations/:hostId`, validated the same way as the demand it corroborates. */\nexport function parseWorkstationStatus(value: unknown): WorkstationStatus | null {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) return null;\n const record = ownDataProperties(value);\n if (!isWorkstationHostId(record[\"hostId\"])) return null;\n const status: WorkstationStatus = { hostId: record[\"hostId\"], operation: null };\n if (record[\"state\"] !== undefined && record[\"state\"] !== null) {\n if (typeof record[\"state\"] !== \"string\" || !WORKSTATION_STATES.has(record[\"state\"])) return null;\n status.state = record[\"state\"];\n }\n if (record[\"operation\"] !== undefined && record[\"operation\"] !== null) {\n const operation = parseWorkstationOperation(record[\"operation\"]);\n if (operation === null) return null;\n status.operation = operation;\n }\n return status;\n}\n\n/** The demand carried by a server refusal, or null when this is not one. */\nexport function workstationDemandOf(error: unknown): WorkstationDemand | null {\n if (!(error instanceof PiPodError)) return null;\n if (error.status !== 503) return null;\n return parseWorkstationDemand(error.detail);\n}\n\n/**\n * Per-reason copy. Static, keyed by the validated reason — never interpolated from the\n * response — so a server sentence can never become client copy by accident.\n *\n * Every line has to hold two truths at once: this takes minutes, and nothing was lost.\n */\nconst WORKSTATION_COPY: Record<string, { headline: string; hint: string }> = {\n // Only the gateway spells it this way (`wsCloseForError`), for a host that cannot be\n // dialled. It means the same thing to the user as `host_stopped`: the machine is down and\n // being brought back.\n host_archived: {\n headline: \"Your workstation is asleep and is being started. This may take several minutes\",\n hint: \"sleeping keeps every workspace on the workstation's own disk \\u2014 nothing is lost and nothing needs recreating\",\n },\n host_starting: {\n headline: \"Your workstation is starting. This may take several minutes\",\n hint: \"your files are on its disk and are retained; the same command attaches once it is up\",\n },\n host_stopped: {\n headline: \"Your workstation is asleep and is being started. This may take several minutes\",\n hint: \"sleeping keeps every workspace on the workstation's own disk — nothing is lost and nothing needs recreating\",\n },\n host_requires_reconciliation: {\n headline: \"Your workstation is being checked after an interrupted change. This may take several minutes\",\n hint: \"the server settles the machine's state before using it again; your files are retained\",\n },\n boat_starts_disabled: {\n headline: \"Workstation starts are paused right now, so yours cannot be started\",\n hint: \"your files are retained on its disk — retry shortly, or ask an operator when starts resume\",\n },\n host_deleted: {\n headline: \"Your workstation has been deleted\",\n hint: \"a new workstation is created for you on the next launch; pods that lived on the old one cannot be resumed\",\n },\n host_retired: {\n headline: \"Your workstation has been retired\",\n hint: \"a new workstation is created for you on the next launch; pods that lived on the retired one cannot be resumed\",\n },\n};\n\n/**\n * `Object.hasOwn`, not a plain lookup: a reason of \"constructor\" would otherwise read the\n * object prototype and return a function where copy belongs.\n */\nfunction workstationCopy(reason: string): { headline: string; hint: string } | null {\n return Object.hasOwn(WORKSTATION_COPY, reason) ? WORKSTATION_COPY[reason]! : null;\n}\n\n/** Headline for a demand: the reason's static copy, else the server's own sentence. */\nexport function workstationHeadline(demand: WorkstationDemand): string {\n const copy = workstationCopy(demand.reason);\n if (copy) return copy.headline;\n return demand.message ?? \"Your workstation is not ready yet. This may take several minutes\";\n}\n\nexport function workstationHint(demand: WorkstationDemand): string {\n const copy = workstationCopy(demand.reason);\n if (copy) return copy.hint;\n return demand.retryable\n ? \"your files are retained on the workstation's disk; retry the same command\"\n : \"your files may no longer be reachable on that workstation; a new one is created on the next launch\";\n}\n\n/** `4m07s`. Elapsed time is the only duration this client ever states on its own. */\nexport function formatElapsed(ms: number): string {\n const total = Math.max(0, Math.round(ms / 1000));\n const minutes = Math.floor(total / 60);\n const seconds = total % 60;\n return minutes > 0 ? `${minutes}m${String(seconds).padStart(2, \"0\")}s` : `${seconds}s`;\n}\n\n/**\n * The progress line for a wait in flight: elapsed time plus whatever the server actually\n * reported. No countdown, no estimate — the measured spread is 243 s to 708 s and a countdown\n * against a made-up number is a lie that gets discovered every time.\n */\nexport function workstationProgressLine(demand: WorkstationDemand, elapsedMs: number): string {\n const parts: string[] = [];\n if (demand.state) parts.push(demand.state);\n const operation = demand.operation;\n if (operation) {\n parts.push(operation.errorCode ? `${operation.kind}: ${operation.phase} (${operation.errorCode})` : `${operation.kind}: ${operation.phase}`);\n }\n const detail = parts.length > 0 ? ` ${color.dim(`(${parts.join(\" · \")})`)}` : \"\";\n return `still starting your workstation — ${formatElapsed(elapsedMs)} elapsed${detail}`;\n}\n\n/** How long the client waits when the server sent no hint, and the bounds it clamps into. */\nexport const WORKSTATION_POLL_DEFAULT_MS = 10_000;\nexport const WORKSTATION_POLL_MIN_MS = 5_000;\nexport const WORKSTATION_POLL_MAX_MS = 60_000;\n/** Consecutive unreachable-server errors on an idempotent attempt, not a workstation exit. */\nexport const WORKSTATION_WAIT_BUDGET_MS = 20 * 60_000;\n/** Never wait past this, whatever deadline a response claims. */\nexport const WORKSTATION_WAIT_MAX_MS = 30 * 60_000;\nexport const WORKSTATION_WAIT_MIN_MS = 60_000;\n/** A 700-second wait has to look alive, so progress re-renders at least this often. */\nexport const WORKSTATION_PROGRESS_INTERVAL_MS = 15_000;\n\nexport function workstationPollMs(demand: WorkstationDemand): number {\n const hint = demand.retryAfterMs ?? WORKSTATION_POLL_DEFAULT_MS;\n return Math.min(WORKSTATION_POLL_MAX_MS, Math.max(WORKSTATION_POLL_MIN_MS, hint));\n}\n\n/**\n * Diagnostic only. The operation deadline bounds mutation issuance on the server; it is not\n * a client exit. `withWorkstationWait` does not stop because this elapsed.\n */\nexport function workstationDeadlineMs(demand: WorkstationDemand, now: number): number {\n const deadlineAt = demand.operation?.deadlineAt;\n if (deadlineAt !== undefined) {\n const parsed = Date.parse(deadlineAt);\n if (Number.isFinite(parsed)) {\n return Math.min(WORKSTATION_WAIT_MAX_MS, Math.max(WORKSTATION_WAIT_MIN_MS, parsed - now));\n }\n }\n return WORKSTATION_WAIT_BUDGET_MS;\n}\n\n/** Terminal refusal (`retryable: false`), as an error with copy the user can act on. */\nexport function workstationTerminalError(demand: WorkstationDemand, cause?: unknown): PiPodError {\n return new PiPodError(workstationHeadline(demand), {\n hint: workstationHint(demand),\n code: demand.reason,\n ...(cause !== undefined ? { cause } : {}),\n });\n}\n\n/**\n * A workstation refusal that did not arrive as an HTTP response — today, the gateway's close\n * 4420 with a host reason. `status` is 503 so it reads exactly like the REST refusal it\n * mirrors, and `detail` carries the demand, so one recognizer serves both transports.\n */\nexport class WorkstationNotReadyError extends PiPodError {\n readonly demand: WorkstationDemand;\n\n constructor(demand: WorkstationDemand, cause?: unknown) {\n super(workstationHeadline(demand), {\n hint: workstationHint(demand),\n status: 503,\n code: demand.reason,\n detail: demand,\n ...(cause !== undefined ? { cause } : {}),\n });\n this.name = \"WorkstationNotReadyError\";\n this.demand = demand;\n }\n}\n\n/**\n * The demand behind a gateway close. The close frame carries a reason and nothing else — no\n * host id, no operation — so the wait runs without a status poll and simply re-attaches on\n * its schedule.\n */\nexport function workstationCloseError(reason: string): WorkstationNotReadyError {\n return new WorkstationNotReadyError({\n kind: \"admission\",\n resource: \"transitions\",\n unit: \"count\",\n reason,\n retryable: true,\n });\n}\n\n/**\n * A gateway session `error` frame (or a close reason) that means the personal workstation\n * is not up. Must not treat billing 402 reasons as a wake.\n */\nexport function workstationErrorFromSessionMessage(\n message: Record<string, unknown>,\n): WorkstationNotReadyError | null {\n const fromDetail = parseWorkstationDemand(message[\"detail\"]);\n if (fromDetail) return new WorkstationNotReadyError(fromDetail);\n const code = typeof message[\"code\"] === \"string\" ? message[\"code\"] : \"\";\n if (!code || !isWorkstationCloseReason(code)) return null;\n return workstationCloseError(code);\n}\n\n/** Only `getWorkstation` is needed here, so tests inject three lines instead of a client. */\nexport interface WorkstationStatusSource {\n getWorkstation(hostId: string): Promise<WorkstationStatus | null>;\n}\n\n/** Start-family operations a demand can re-arm. A stop or delete is not a start cycle. */\nconst START_KINDS = new Set([\"create\", \"resume\", \"activate\"]);\n\n/**\n * Invocation-local count of start cycles that ended stopped without the awaited request\n * succeeding. Shared across every wait in one launch so a second resolve/launch entry cannot\n * reset it.\n */\nexport interface WorkstationCycleTracker {\n unsuccessfulIds: string[];\n}\n\nexport function createWorkstationCycleTracker(): WorkstationCycleTracker {\n return { unsuccessfulIds: [] };\n}\n\nexport const WORKSTATION_START_GUARD_MESSAGE =\n \"Two workstation start attempts ended without becoming usable; operator investigation is required. Your existing workstation has not been replaced.\";\n\nfunction startOperationId(demand: WorkstationDemand): string | null {\n const operation = demand.operation;\n if (!operation || !START_KINDS.has(operation.kind)) return null;\n return operation.id;\n}\n\nfunction noteUnsuccessfulCycle(tracker: WorkstationCycleTracker, operationId: string): number {\n if (!tracker.unsuccessfulIds.includes(operationId)) tracker.unsuccessfulIds.push(operationId);\n return tracker.unsuccessfulIds.length;\n}\n\nexport interface WorkstationWaitOptions {\n /** True once the user has interrupted; checked before every sleep and every attempt. */\n cancelled?: (() => boolean) | undefined;\n now?: (() => number) | undefined;\n sleep?: ((ms: number) => Promise<void>) | undefined;\n /** Where progress goes; defaults to the `[workstation]` step line. */\n progress?: ((line: string) => void) | undefined;\n progressIntervalMs?: number | undefined;\n /**\n * The refusal that already happened, for a caller holding one. Without it the routine has\n * to make the failing call again just to learn what the caller already knows.\n */\n from?: WorkstationDemand | undefined;\n /**\n * Shared across waits in one launch. Absent means this wait has its own tracker, which is\n * enough for a single attach but not for resolve-then-launch.\n */\n cycles?: WorkstationCycleTracker | undefined;\n /**\n * False for a mutating launch POST: a timeout is not proof the request did not commit, so\n * the waiter must not issue it again. Typed workstation 503s are still retried.\n */\n replayTransport?: boolean | undefined;\n /**\n * How long consecutive unreachable-server errors may be retried on an idempotent attempt.\n * This is not a workstation deadline and does not ask the user to re-run.\n */\n transportGraceMs?: number | undefined;\n}\n\nconst defaultSleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Run `attempt`, and if the server refuses because the caller's workstation is not up, wait\n * for it and run the SAME request again.\n *\n * A typed workstation 503 is raised before a pod row exists, so asking again does not create\n * a second pod. A mutating launch whose reply was lost is different: the waiter does not\n * reissue that POST (`replayTransport: false`); the caller decides from an identified pod,\n * never from an empty list.\n *\n * The operation deadline is not an exit. While the server still reports the start, this wait\n * continues. It stops on cancel, a terminal refusal, two observed start cycles that ended\n * stopped without success, or — for an idempotent attempt only — a server that stays\n * unreachable past the transport grace. It never tells the user to come back and re-run.\n *\n * Readiness is the server's to declare. A status poll that says `running` starts the next\n * attempt immediately, but only a successful attempt ends the wait.\n */\nexport async function withWorkstationWait<T>(\n source: WorkstationStatusSource,\n attempt: () => Promise<T>,\n opts: WorkstationWaitOptions = {},\n): Promise<T> {\n const now = opts.now ?? Date.now;\n const sleep = opts.sleep ?? defaultSleep;\n const progress = opts.progress ?? ((line: string) => step(\"workstation\", line));\n const progressIntervalMs = opts.progressIntervalMs ?? WORKSTATION_PROGRESS_INTERVAL_MS;\n const cancelled = opts.cancelled;\n const tracker = opts.cycles ?? createWorkstationCycleTracker();\n const replayTransport = opts.replayTransport !== false;\n const transportGraceMs = opts.transportGraceMs ?? WORKSTATION_WAIT_BUDGET_MS;\n\n const checkCancelled = (demand: WorkstationDemand | null): void => {\n if (!cancelled?.()) return;\n throw new CancelledError(\n demand\n ? \"interrupted — your workstation keeps starting on the server and your files are retained; a later launch attaches to the same workstation\"\n : \"interrupted\",\n );\n };\n\n let demand: WorkstationDemand | null = opts.from ?? null;\n // A caller that already holds the refusal can be cancelled before any retry. The discovering\n // attempt itself still runs: an interrupt that arrives with the refusal has to be told that\n // the workstation keeps starting, and that attempt is what learned the demand.\n if (demand) checkCancelled(demand);\n if (demand === null) {\n try {\n return await attempt();\n } catch (error) {\n demand = workstationDemandOf(error);\n if (!demand) throw error;\n if (!demand.retryable) throw workstationTerminalError(demand, error);\n checkCancelled(demand);\n }\n } else if (!demand.retryable) {\n throw workstationTerminalError(demand);\n }\n\n const startedAt = now();\n progress(`${workstationHeadline(demand)} — ${workstationHint(demand)}`);\n let lastProgressAt = startedAt;\n let observedStartId = startOperationId(demand);\n let transportSince: number | null = null;\n\n for (;;) {\n checkCancelled(demand);\n const waitMs = workstationPollMs(demand);\n await sleep(waitMs);\n checkCancelled(demand);\n\n if (demand.hostId) {\n const status = await pollStatus(source, demand.hostId);\n checkCancelled(demand);\n if (status && status.hostId === demand.hostId) {\n const operation = status.operation;\n if (operation && START_KINDS.has(operation.kind)) {\n // A different id is not proof the previous cycle failed.\n observedStartId = operation.id;\n demand = {\n ...demand,\n ...(status.state !== undefined ? { state: status.state } : {}),\n operation,\n };\n } else if (operation === null && status.state === \"stopped\" && observedStartId) {\n const counted = noteUnsuccessfulCycle(tracker, observedStartId);\n observedStartId = null;\n demand = { ...demand, state: \"stopped\", operation: null };\n if (counted >= 2) {\n throw new PiPodError(WORKSTATION_START_GUARD_MESSAGE, {\n code: \"workstation_start_guard\",\n transient: false,\n });\n }\n } else {\n demand = {\n ...demand,\n ...(status.state !== undefined ? { state: status.state } : {}),\n operation,\n };\n }\n }\n }\n\n if (now() - lastProgressAt >= progressIntervalMs) {\n lastProgressAt = now();\n progress(workstationProgressLine(demand, now() - startedAt));\n }\n\n checkCancelled(demand);\n try {\n return await attempt();\n } catch (error) {\n checkCancelled(demand);\n const next = workstationDemandOf(error);\n if (next) {\n if (!next.retryable) throw workstationTerminalError(next, error);\n transportSince = null;\n const nextStart = startOperationId(next);\n if (nextStart) observedStartId = nextStart;\n demand = next;\n } else if (replayTransport && error instanceof PiPodError && error.transient && error.status === undefined) {\n transportSince ??= now();\n if (now() - transportSince >= transportGraceMs) throw error;\n progress(`the server did not answer in time — retrying on the wait schedule (${formatElapsed(now() - startedAt)} elapsed)`);\n lastProgressAt = now();\n } else {\n throw error;\n }\n }\n }\n}\n\n/** A status poll is progress reporting, not a gate: a failed poll never ends the wait. */\nasync function pollStatus(source: WorkstationStatusSource, hostId: string): Promise<WorkstationStatus | null> {\n try {\n return await source.getWorkstation(hostId);\n } catch (error) {\n debug(`workstation status poll failed: ${error instanceof Error ? error.message : String(error)}`);\n return null;\n }\n}\n","/**\n * src/account/billing.ts — the SaaS workstation/usage surface, and the edition boundary that hides it.\n *\n * pi pod ships in two editions from one codebase. The self-hosted edition runs the sandbox\n * runtime next to the server on hardware the operator already pays for: it has no plan, no\n * metered active hours and no spend cap, so the server omits the `workstation` block entirely.\n * The SaaS edition (`SANDBOX_HOST_BACKEND=boat`) meters a personal workstation per user and\n * sends a flat `workstation` block on `GET /v1/me`.\n *\n * The client's whole half of that boundary is this rule: **when the block is absent, the\n * surface disappears silently.** Not a zero, not \"unknown\", not an empty heading — nothing.\n * A self-hosted operator must never see a spend cap they do not have, and must never be\n * asked to explain one to their users.\n *\n * The wire shape is the server's `workstationSummary()` (src/server/billing/routes.ts): flat\n * keys, no nesting. Every field here is independently optional and independently validated.\n * A partial block renders its parts; a malformed field is treated as absent rather than as a\n * value; and no number is ever computed, projected or priced by the client. \"12.4 of 60 active\n * hours\" is allowed because the server sent both numbers. \"48 hours left, about $12 more\" is not.\n */\n\n/** Bounded so a hostile or buggy value cannot become an unbounded terminal line. */\nconst MAX_LABEL_LENGTH = 64;\n\n/** The account's billing state inside the `workstation` block (`BillingStatus` server-side). */\nexport type BillingStatus = \"none\" | \"trialing\" | \"active\" | \"past_due\" | \"canceled\";\n\n/** How close the account is to its cap; informational only, never recomputed here. */\nexport type SpendCapState = \"ok\" | \"warning\" | \"reached\";\n\n/** Why a machine start is refused (`StartBlockedReason` server-side). */\nexport type StartBlockedReason =\n | \"subscription_required\" | \"trial_expired\" | \"trial_hours_exhausted\"\n | \"payment_past_due\" | \"spend_cap_reached\" | \"billing_meter_history_unknown\";\n\nconst BILLING_STATUSES: ReadonlySet<string> = new Set([\"none\", \"trialing\", \"active\", \"past_due\", \"canceled\"]);\nconst SPEND_CAP_STATES: ReadonlySet<string> = new Set([\"ok\", \"warning\", \"reached\"]);\nconst START_BLOCKED_REASONS: ReadonlySet<string> = new Set([\n \"subscription_required\", \"trial_expired\", \"trial_hours_exhausted\",\n \"payment_past_due\", \"spend_cap_reached\", \"billing_meter_history_unknown\",\n]);\nconst METERING_HOLDS: ReadonlySet<string> = new Set([\n \"payment_past_due\", \"spend_cap_reached\", \"billing_meter_history_unknown\",\n]);\n\n/**\n * The flat `workstation` block, field for field. Unknown keys are dropped and unknown enum\n * values are ignored while the numbers beside them are kept — a server that grows a state the\n * client does not know still renders the hours and the cap it does.\n */\nexport interface AccountBilling {\n planKey?: string;\n planName?: string;\n status?: BillingStatus;\n /** Wall-clock diagnostic (may include unvouched time). Prefer billable seconds for allowance. */\n activeHoursUsed?: number;\n includedActiveHours?: number;\n overageHours?: number;\n overageUsdCentsPerHour?: number;\n spendCapUsdCents?: number;\n projectedSpendUsdCents?: number;\n uncappedSpendUsdCents?: number;\n spendCapState?: SpendCapState;\n startsBlocked?: boolean;\n startBlockedReason?: StartBlockedReason;\n parallelSandboxes?: number;\n workspaceStorageGb?: number;\n currentPeriodEnd?: string;\n trialEndsAt?: string;\n /** Vendor-vouched seconds. Unit change to hours for display only. */\n billableActiveSeconds?: number;\n /** Unvouched/UNKNOWN seconds. Shown separately, never added into confirmed hours. */\n unknownActiveSeconds?: number;\n /** Server-owned hold. Null money remains unknown; the client never prices it. */\n meteringHold?: \"payment_past_due\" | \"spend_cap_reached\" | \"billing_meter_history_unknown\";\n committedOverageUsdCents?: number;\n}\n\nfunction record(value: unknown): Record<string, unknown> | null {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) return null;\n const snapshot: Record<string, unknown> = Object.create(null) as Record<string, unknown>;\n for (const key of Object.getOwnPropertyNames(value)) {\n const descriptor = Object.getOwnPropertyDescriptor(value, key);\n if (!descriptor || !(\"value\" in descriptor)) continue;\n snapshot[key] = descriptor.value;\n }\n return snapshot;\n}\n\n/** A number worth showing: finite and non-negative. Overage above an allowance is expected. */\nfunction amount(value: unknown): number | undefined {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < 0) return undefined;\n return value;\n}\n\nfunction label(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n if (trimmed.length === 0 || trimmed.length > MAX_LABEL_LENGTH) return undefined;\n // Rendered as data on a terminal line: control characters are not data, and a plan name\n // is never a reason to move the cursor.\n if (/[\\u0000-\\u001f\\u007f]/.test(trimmed)) return undefined;\n return trimmed;\n}\n\nfunction instant(value: unknown): string | undefined {\n if (typeof value !== \"string\" || value.length > 40) return undefined;\n const parsed = Date.parse(value);\n if (!Number.isFinite(parsed)) return undefined;\n return new Date(parsed).toISOString();\n}\n\nfunction member(value: unknown, allowed: ReadonlySet<string>): string | undefined {\n return typeof value === \"string\" && allowed.has(value) ? value : undefined;\n}\n\nfunction defined<T extends object>(value: T): T | undefined {\n return Object.keys(value).length > 0 ? value : undefined;\n}\n\n/**\n * Parse the optional flat `workstation` block (already unwrapped from `/v1/me`). Returns null\n * when the server sent nothing, sent something unusable, or sent an object with no field this\n * client can render — all three of which mean exactly the same thing to the user: there is no\n * plan surface here.\n */\nexport function parseAccountBilling(value: unknown): AccountBilling | null {\n const root = record(value);\n if (!root) return null;\n\n const billing: AccountBilling = {};\n\n const planKey = label(root[\"planKey\"]);\n const planName = label(root[\"planName\"]);\n if (planKey !== undefined) billing.planKey = planKey;\n if (planName !== undefined) billing.planName = planName;\n\n const status = member(root[\"status\"], BILLING_STATUSES) as BillingStatus | undefined;\n if (status !== undefined) billing.status = status;\n\n const numbers: Array<[keyof AccountBilling, string]> = [\n [\"activeHoursUsed\", \"activeHoursUsed\"],\n [\"includedActiveHours\", \"includedActiveHours\"],\n [\"overageHours\", \"overageHours\"],\n [\"overageUsdCentsPerHour\", \"overageUsdCentsPerHour\"],\n [\"spendCapUsdCents\", \"spendCapUsdCents\"],\n [\"projectedSpendUsdCents\", \"projectedSpendUsdCents\"],\n [\"uncappedSpendUsdCents\", \"uncappedSpendUsdCents\"],\n [\"parallelSandboxes\", \"parallelSandboxes\"],\n [\"workspaceStorageGb\", \"workspaceStorageGb\"],\n [\"billableActiveSeconds\", \"billableActiveSeconds\"],\n [\"unknownActiveSeconds\", \"unknownActiveSeconds\"],\n [\"committedOverageUsdCents\", \"committedOverageUsdCents\"],\n ];\n const target = billing as Record<string, unknown>;\n for (const [field, key] of numbers) {\n const kept = amount(root[key]);\n if (kept !== undefined) target[field] = kept;\n }\n\n const spendCapState = member(root[\"spendCapState\"], SPEND_CAP_STATES) as SpendCapState | undefined;\n if (spendCapState !== undefined) billing.spendCapState = spendCapState;\n\n const startBlockedReason = member(root[\"startBlockedReason\"], START_BLOCKED_REASONS) as StartBlockedReason | undefined;\n if (startBlockedReason !== undefined) billing.startBlockedReason = startBlockedReason;\n\n const startsBlocked = root[\"startsBlocked\"];\n if (typeof startsBlocked === \"boolean\") billing.startsBlocked = startsBlocked;\n\n const currentPeriodEnd = instant(root[\"currentPeriodEnd\"]);\n if (currentPeriodEnd !== undefined) billing.currentPeriodEnd = currentPeriodEnd;\n\n const trialEndsAt = instant(root[\"trialEndsAt\"]);\n if (trialEndsAt !== undefined) billing.trialEndsAt = trialEndsAt;\n const meteringHold = member(root[\"meteringHold\"], METERING_HOLDS) as AccountBilling[\"meteringHold\"];\n if (meteringHold !== undefined) billing.meteringHold = meteringHold;\n\n return defined(billing) ?? null;\n}\n\n/** `12.4` — one decimal place, and no trailing `.0` on a whole number. */\nfunction hours(value: number): string {\n return Number.isInteger(value) ? String(value) : value.toFixed(1);\n}\n\n/** `$40`, `$32.50` — the server quotes cents; the terminal shows dollars. */\nfunction usd(cents: number): string {\n const dollars = cents / 100;\n return Number.isInteger(dollars) ? `$${dollars}` : `$${dollars.toFixed(2)}`;\n}\n\nexport function formatUsdCents(cents: number): string {\n return usd(cents);\n}\n\nfunction day(iso: string): string {\n return iso.slice(0, 10);\n}\n\n/**\n * The one-line workstation summary for `pipod list`, or null when there is nothing to say.\n * Every segment is omitted independently, so a server that reports only active hours renders\n * only active hours. The trial note appears only while the account is actually trialing.\n */\nexport function billingSummaryLine(billing: AccountBilling | null): string | null {\n if (!billing) return null;\n const segments: string[] = [];\n\n if (billing.planName !== undefined) segments.push(billing.planName);\n else if (billing.planKey !== undefined) segments.push(billing.planKey);\n\n const included = billing.includedActiveHours;\n const billableHours =\n billing.billableActiveSeconds !== undefined ? billing.billableActiveSeconds / 3600 : undefined;\n const unknownHours =\n billing.unknownActiveSeconds !== undefined ? billing.unknownActiveSeconds / 3600 : undefined;\n // Confirmed (billable) hours against the allowance when the server sent seconds.\n // Fall back to the wall diagnostic only on a 17-key envelope that has no coverage fields.\n const confirmed = billableHours !== undefined ? billableHours : billing.activeHoursUsed;\n const confirmedLabel = billableHours !== undefined ? \"confirmed hours\" : \"active hours\";\n if (confirmed !== undefined && included !== undefined) {\n segments.push(`${hours(confirmed)} of ${hours(included)} ${confirmedLabel}`);\n } else if (confirmed !== undefined) {\n segments.push(\n billableHours !== undefined\n ? `${hours(confirmed)} confirmed hours used`\n : `${hours(confirmed)} active hours used`,\n );\n } else if (included !== undefined) {\n segments.push(`${hours(included)} active hours included`);\n }\n if (unknownHours !== undefined && unknownHours > 0) {\n segments.push(`unconfirmed ${hours(unknownHours)} h`);\n }\n\n if (billing.spendCapUsdCents !== undefined) segments.push(`spend cap ${usd(billing.spendCapUsdCents)}`);\n\n if (billing.currentPeriodEnd !== undefined) segments.push(`period ends ${day(billing.currentPeriodEnd)}`);\n\n // A trial note is true only while the account is trialing: a leftover `trialEndsAt` on a\n // past_due account is history, not a deadline the user still has.\n if (billing.status === \"trialing\" && billing.trialEndsAt !== undefined) {\n segments.push(`trial ends ${day(billing.trialEndsAt)}`);\n }\n\n return segments.length > 0 ? segments.join(\" · \") : null;\n}\n\n// --- plan-change quotes (M5; M4 server `plan-change.ts` `PlanChangeQuoteView`) ---------\n\n/** The two paid plans a quote can move between. */\nexport type BillingPlanKey = \"standard\" | \"pro\";\n\n/** `immediate` upgrades bill proration now; `period_end` downgrades wait for renewal. */\nexport type PlanChangeTiming = \"immediate\" | \"period_end\";\n\nconst BILLING_PLAN_KEYS: ReadonlySet<string> = new Set([\"standard\", \"pro\"]);\nconst PLAN_CHANGE_TIMINGS: ReadonlySet<string> = new Set([\"immediate\", \"period_end\"]);\nconst QUOTE_ITEM_KINDS: ReadonlySet<string> = new Set([\"base\", \"overage\"]);\n\n/** One priced line of a quote: the recurring base price and the metered overage price. */\nexport interface PlanChangeQuoteItem {\n priceId: string;\n kind: \"base\" | \"overage\";\n}\n\n/**\n * The server's `PlanChangeQuoteView`, field for field — nothing invented. On an\n * immediate upgrade `recurringAmountCents` is the target licensed base (e.g.\n * 5000) and `nextPeriodAmountCents` equals it (never 0, never a free month);\n * on a period-end downgrade `amountDueNowCents` is 0 and `nextPeriodAmountCents`\n * is the `proration_behavior=none` preview. No hosted payment URL field exists\n * on this view (`hostedPaymentUrl|paymentUrl|checkoutUrl|url` must not be read).\n */\nexport interface PlanChangeQuoteView {\n quoteId: string;\n currentPlan: BillingPlanKey;\n targetPlan: BillingPlanKey;\n timing: PlanChangeTiming;\n amountDueNowCents: number;\n recurringAmountCents: number;\n nextPeriodAmountCents: number;\n currency: string;\n currentPeriodEnd: string | null;\n effectiveAt: string | null;\n expiresAt: string;\n pendingUpdateExpiresAt: string | null;\n pendingInvoiceId: string | null;\n state: string;\n items: PlanChangeQuoteItem[];\n}\n\n/**\n * The authoritative resume pointer from `GET /v1/billing/account`: the open\n * quote or null. `quoted|applying` are the open states; when `canChangePlan`\n * is false because the open quote is `applying`, the client resumes the same\n * `quoteId` instead of minting a fresh preview. The server sends the full\n * quote view here; only `quoteId`/`state` (plus an optional `targetPlan`)\n * are read — everything else is ignored and never blocks a resume.\n */\nexport interface OpenPlanChange {\n quoteId: string;\n state: string;\n targetPlan?: BillingPlanKey | null;\n}\n\n/**\n * The narrow slice of `GET /v1/billing/account` the change command reads: the\n * capability flags, the authoritative `openPlanChange` resume pointer, plus the\n * pending/cancel truth it reports back. Every field the server's `accountView`\n * sends under these names; everything else is ignored.\n *\n * `canResumePlanChange` is true when `openPlanChange.state === \"applying\"` —\n * restart confirms that quoteId even when `canChangePlan` is false.\n */\nexport interface BillingAccountPlan {\n canChangePlan: boolean;\n canResumePlanChange: boolean;\n openPlanChange: OpenPlanChange | null;\n planKey?: string;\n status?: BillingStatus;\n pendingPlanKey?: string | null;\n pendingScheduleUnreadable: boolean;\n cancelAtPeriodEnd: boolean;\n /** Recurring prices per plan key, a display fallback when a quote omits renewal. */\n planPrices: Array<{ key: string; name?: string; priceUsdCents?: number }>;\n}\n\nfunction cents(value: unknown): number | undefined {\n if (typeof value !== \"number\" || !Number.isInteger(value) || value < 0 || value > 100_000_00) return undefined;\n return value;\n}\n\nfunction uuidLike(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n if (trimmed.length === 0 || trimmed.length > 64) return undefined;\n if (/[\\u0000-\\u001f\\u007f\\s]/.test(trimmed)) return undefined;\n return trimmed;\n}\n\nfunction currencyCode(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim().toLowerCase();\n if (!/^[a-z]{3}$/.test(trimmed)) return undefined;\n return trimmed;\n}\n\nfunction nullableInstant(value: unknown): string | null | undefined {\n if (value === null) return null;\n const parsed = instant(value);\n return parsed === undefined ? undefined : parsed;\n}\n\nfunction nullableId(value: unknown): string | null | undefined {\n if (value === null) return null;\n const parsed = uuidLike(value);\n if (parsed !== undefined) return parsed;\n // Non-UUID invoice-style ids (e.g. `in_...`): bounded opaque token, never rendered as a URL.\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n if (trimmed.length === 0 || trimmed.length > 128) return undefined;\n if (/[\\u0000-\\u001f\\u007f\\s]/.test(trimmed)) return undefined;\n return trimmed;\n}\n\nfunction quoteState(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n if (trimmed.length === 0 || trimmed.length > 32) return undefined;\n if (!/^[a-z][a-z0-9_]*$/.test(trimmed)) return undefined;\n return trimmed;\n}\n\n/**\n * Minimal resume pointer: the open quote's id plus its `quoted|applying` state.\n * The server sends the full quote view here, so extra keys are ignored and an\n * optional `targetPlan` (or legacy `plan`) is carried when it names a known plan.\n */\nfunction openPlanChange(value: unknown): OpenPlanChange | null {\n if (value === null || value === undefined) return null;\n const root = record(value);\n if (!root) return null;\n const quoteId = uuidLike(root[\"quoteId\"]);\n const state = quoteState(root[\"state\"]);\n if (quoteId === undefined || state === undefined) return null;\n const rawTarget = root[\"targetPlan\"] ?? root[\"plan\"];\n const targetPlan =\n typeof rawTarget === \"string\" && BILLING_PLAN_KEYS.has(rawTarget)\n ? (rawTarget as BillingPlanKey)\n : null;\n return targetPlan ? { quoteId, state, targetPlan } : { quoteId, state };\n}\n\nfunction quoteItem(value: unknown): PlanChangeQuoteItem | null {\n const root = record(value);\n if (!root) return null;\n const priceId = root[\"priceId\"];\n const kind = root[\"kind\"];\n if (typeof priceId !== \"string\" || priceId.length === 0 || priceId.length > 128) return null;\n if (typeof kind !== \"string\" || !QUOTE_ITEM_KINDS.has(kind)) return null;\n return { priceId, kind: kind as \"base\" | \"overage\" };\n}\n\n/**\n * Validate a `PlanChangeQuoteView` body field by field. Returns null when any\n * field the command prints or sends back is missing or malformed — the caller\n * reports that instead of rendering a half quote.\n */\nexport function parsePlanChangeQuote(value: unknown): PlanChangeQuoteView | null {\n const root = record(value);\n if (!root) return null;\n const quoteId = uuidLike(root[\"quoteId\"]);\n const currentPlan = member(root[\"currentPlan\"], BILLING_PLAN_KEYS) as BillingPlanKey | undefined;\n const targetPlan = member(root[\"targetPlan\"], BILLING_PLAN_KEYS) as BillingPlanKey | undefined;\n const timing = member(root[\"timing\"], PLAN_CHANGE_TIMINGS) as PlanChangeTiming | undefined;\n const amountDueNowCents = cents(root[\"amountDueNowCents\"]);\n const recurringAmountCents = cents(root[\"recurringAmountCents\"]);\n const nextPeriodAmountCents = cents(root[\"nextPeriodAmountCents\"]);\n const currency = currencyCode(root[\"currency\"]);\n const currentPeriodEnd = nullableInstant(root[\"currentPeriodEnd\"]);\n const effectiveAt = nullableInstant(root[\"effectiveAt\"]);\n const expiresAt = instant(root[\"expiresAt\"]);\n const pendingUpdateExpiresAt = nullableInstant(root[\"pendingUpdateExpiresAt\"] ?? null);\n const pendingInvoiceId = nullableId(root[\"pendingInvoiceId\"] ?? null);\n const state = quoteState(root[\"state\"]);\n const rawItems = root[\"items\"];\n if (\n quoteId === undefined || currentPlan === undefined || targetPlan === undefined ||\n timing === undefined || amountDueNowCents === undefined || recurringAmountCents === undefined ||\n nextPeriodAmountCents === undefined ||\n currency === undefined || currentPeriodEnd === undefined || effectiveAt === undefined ||\n expiresAt === undefined || pendingUpdateExpiresAt === undefined || pendingInvoiceId === undefined ||\n state === undefined || !Array.isArray(rawItems)\n ) {\n return null;\n }\n const items: PlanChangeQuoteItem[] = [];\n for (const entry of rawItems) {\n const item = quoteItem(entry);\n if (!item) return null;\n items.push(item);\n }\n return {\n quoteId, currentPlan, targetPlan, timing, amountDueNowCents, recurringAmountCents,\n nextPeriodAmountCents, currency, currentPeriodEnd, effectiveAt, expiresAt,\n pendingUpdateExpiresAt, pendingInvoiceId, state, items,\n };\n}\n\n/**\n * Validate the `GET /v1/billing/account` body down to the fields the change\n * command needs. Unknown keys are ignored; a non-object body is null.\n */\nexport function parseBillingAccountPlan(value: unknown): BillingAccountPlan | null {\n const root = record(value);\n if (!root) return null;\n const planKey = label(root[\"planKey\"]);\n const status = member(root[\"status\"], BILLING_STATUSES) as BillingStatus | undefined;\n const pending = root[\"pendingPlanKey\"];\n let pendingPlanKey: string | null | undefined;\n if (pending === null) pendingPlanKey = null;\n else if (typeof pending === \"string\") pendingPlanKey = label(pending) ?? null;\n const planPrices: BillingAccountPlan[\"planPrices\"] = [];\n const rawPlans = root[\"availablePlans\"];\n if (Array.isArray(rawPlans)) {\n for (const entry of rawPlans) {\n const plan = record(entry);\n if (!plan || typeof plan[\"key\"] !== \"string\") continue;\n const key = plan[\"key\"].trim();\n if (key.length === 0 || key.length > MAX_LABEL_LENGTH) continue;\n const name = label(plan[\"name\"]);\n const price = plan[\"priceUsdCents\"];\n planPrices.push({\n key,\n ...(name !== undefined ? { name } : {}),\n ...(typeof price === \"number\" && Number.isInteger(price) && price >= 0 ? { priceUsdCents: price } : {}),\n });\n }\n }\n const open = openPlanChange(root[\"openPlanChange\"] ?? null);\n // A malformed openPlanChange is treated as absent (older servers omit it),\n // never as a reason to block or to mint a quote. `open` is null here in both\n // the absent and the malformed case by construction.\n return {\n canChangePlan: root[\"canChangePlan\"] === true,\n canResumePlanChange: root[\"canResumePlanChange\"] === true,\n openPlanChange: open,\n ...(planKey !== undefined ? { planKey } : {}),\n ...(status !== undefined ? { status } : {}),\n ...(pendingPlanKey !== undefined ? { pendingPlanKey } : {}),\n pendingScheduleUnreadable: root[\"pendingScheduleUnreadable\"] === true,\n cancelAtPeriodEnd: root[\"cancelAtPeriodEnd\"] === true,\n planPrices,\n };\n}\n","import { PiPodError } from \"../errors.js\";\nimport { AccountClient } from \"./api.js\";\nimport { readAccountAuth, readPodTokenAuth } from \"./store.js\";\n\nexport function signInRequiredError(cause?: unknown): PiPodError {\n return new PiPodError(\"sign in required for pod operations\", {\n hint: \"sign in with `pipod login`\",\n ...(cause !== undefined ? { cause } : {}),\n });\n}\n\nexport function accountClientOrNull(opts: {\n home?: string | undefined;\n env?: NodeJS.ProcessEnv;\n} = {}): AccountClient | null {\n let auth;\n try {\n auth = readAccountAuth(opts.home) ?? readPodTokenAuth(opts.env ?? process.env);\n } catch (error) {\n throw signInRequiredError(error);\n }\n return auth ? new AccountClient(auth, { home: opts.home }) : null;\n}\n\nexport function requireAccountClient(opts: {\n home?: string | undefined;\n env?: NodeJS.ProcessEnv;\n} = {}): AccountClient {\n const client = accountClientOrNull(opts);\n if (!client) throw signInRequiredError();\n return client;\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { CONFIG_DIR, findConfigPath } from \"../config.js\";\nimport { parseDotenv } from \"../dotenv.js\";\nimport { EXIT, PiPodError } from \"../errors.js\";\nimport { hint, info, warn } from \"../log.js\";\nimport { checkSecretResolver, hasSecretRefs, mergeSecretResolver } from \"../secret-refs.js\";\nimport { userSecretsDir } from \"../userconfig.js\";\nimport type { ApiServerVersion } from \"./api.js\";\nimport { accountClientOrNull } from \"./client.js\";\nimport { formatSettingsChain, planAccountLaunch, readSecretResolverLayers } from \"./launch.js\";\nimport { warnNoModelProvider } from \"./launch-handoff.js\";\nimport { projectTemplateStaleness, userLayerStaleness } from \"./bundle-bootstrap.js\";\nimport { describeWorkspaceSeed } from \"./workspace-seed.js\";\n\nexport interface AccountDoctorFlags {\n home?: string | undefined;\n template?: string | undefined;\n}\n\nexport async function runAccountDoctor(flags: AccountDoctorFlags, cwd = process.cwd()): Promise<number> {\n let client;\n try {\n client = accountClientOrNull({ home: flags.home });\n } catch (error) {\n warn(`auth: ${error instanceof Error ? error.message : String(error)}`);\n hint(\"sign in with `pipod login`\");\n return EXIT.FAILURE;\n }\n if (!client) {\n warn(\"auth: not signed in\");\n hint(\"sign in with `pipod login`\");\n return EXIT.FAILURE;\n }\n\n let failed = false;\n if (await checkSecretRefs(flags, cwd)) failed = true;\n\n try {\n const release = await client.serverVersion();\n info(`server: reachable at ${client.serverUrl} (${describeServerRelease(release)})`);\n if (reportServerUpgradeState(release)) failed = true;\n if (client.isPodToken) {\n info(\"auth: valid pod-scoped server token\");\n info(\"org: inherited from the parent pod token\");\n } else {\n const me = await client.me();\n const orgName = me.organization?.name ?? me.organization?.alias ?? client.orgId;\n info(`auth: valid for ${me.user.email ?? (client.user.email || me.user.id)}`);\n if (!me.currentOrgId) {\n warn(\"org: none in this access token — membership is pending in Zitadel\");\n failed = true;\n } else if ((me.permissions ?? []).length === 0) {\n warn(`org: ${orgName} (no API roles yet — grant a role bundle in Zitadel)`);\n } else {\n info(`org: ${orgName}`);\n }\n }\n } catch (error) {\n warn(`server/auth: ${error instanceof Error ? error.message : String(error)}`);\n return EXIT.FAILURE;\n }\n\n try {\n const plan = await planAccountLaunch(\n client,\n {\n yes: true,\n dryRun: true,\n template: flags.template,\n home: flags.home,\n },\n cwd,\n );\n const resolved = plan.resolve;\n if (plan.projectRoot && plan.templateId) {\n const stale = await projectTemplateStaleness({ client, cwd, home: flags.home });\n if (stale) warn(stale);\n }\n const userStale = await userLayerStaleness({ client, home: flags.home });\n if (userStale) warn(userStale);\n info(`layers: ${formatSettingsChain(plan)}`);\n if (plan.bootstrapPreview) {\n info(\"project config: bootstrap preview only; launches use it after it is pushed to a template\");\n }\n info(`resolve: provider ${resolved.provider}; image ${resolved.image}; egress ${resolved.egress.mode}`);\n if (resolved.credential.available) {\n info(`credential: ${resolved.credential.envVar} available (${resolved.credential.source})`);\n } else {\n warn(`credential: ${resolved.credential.envVar} is missing on the server`);\n failed = true;\n }\n for (const clamp of resolved.clamps) {\n warn(`org policy: ${clamp.path} → ${JSON.stringify(clamp.to)} (${clamp.reason})`);\n }\n warnNoModelProvider(resolved);\n reportWorkspaceSeed(plan.workspaceSeed);\n const seen = new Set<string>();\n for (const warning of [...plan.warnings, ...resolved.warnings]) {\n if (seen.has(warning)) continue;\n seen.add(warning);\n warn(warning);\n }\n } catch (error) {\n failed = true;\n if (error instanceof PiPodError) {\n warn(`resolve: ${error.message}`);\n if (error.hint) hint(error.hint);\n } else {\n warn(`resolve: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n if (!failed) info(\"account checks passed\");\n return failed ? EXIT.FAILURE : EXIT.OK;\n}\n\nfunction describeServerRelease(release: ApiServerVersion | null): string {\n if (!release) return \"version not reported\";\n return release.revision\n ? `version ${release.version}, revision ${release.revision.slice(0, 12)}`\n : `version ${release.version}`;\n}\n\n/**\n * Warn about the server-side upgrade state that refuses or endangers work. True when launches\n * will fail: a database missing this release's migrations, or held launch admission.\n */\nfunction reportServerUpgradeState(release: ApiServerVersion | null): boolean {\n let failed = false;\n const schema = release?.schema;\n if (schema?.state === \"behind\") {\n warn(`server: its database is missing ${schema.pending} migration(s) this server release needs`);\n hint(\n \"a self-hosted server applies them when it starts with UPGRADE_ON_START=true, as the Compose bundle does; \" +\n \"otherwise run `node dist/migrate.js` in the server image\",\n );\n failed = true;\n } else if (schema?.state === \"ahead\") {\n warn(`server: its database has ${schema.unknown} migration(s) from a newer server release`);\n hint(\"self-hosted: run the newer release again, or restore the backup taken before the upgrade\");\n }\n if (release?.launchAdmission === \"held\") {\n warn(\"server: launch admission is held, so new launches are refused\");\n hint(\"self-hosted: `node dist/fleet.js launch-gate status` in the server container says why\");\n failed = true;\n }\n return failed;\n}\n\n/**\n * Name the seed root and the clone-or-archive decision a launch from here would make. Doctor\n * plans as a dry run, so this probes git locally and anonymously but never reads or forwards\n * credentials — a private remote is reported as \"would clone if credentials work\".\n */\nfunction reportWorkspaceSeed(seed: AccountLaunchPlanSeed): void {\n if (!seed) return;\n switch (seed.kind) {\n case \"none\":\n info(`workspace seed: none (${seed.reason})`);\n return;\n case \"copy\":\n info(`workspace seed: project ${seed.root} is copied into a fresh pod (${seed.reason})`);\n return;\n case \"clone\":\n case \"archive\":\n info(`workspace seed root: ${seed.root}${seed.subdir ? ` (launching from ${seed.subdir}/)` : \"\"}`);\n info(`workspace seed: ${describeWorkspaceSeed(seed)}`);\n if (seed.kind === \"clone\" && seed.access === \"credential\") {\n hint(`the remote is private: a launch reads git credentials for ${seed.host} and asks before forwarding them; declining sends an archive`);\n }\n }\n}\n\ntype AccountLaunchPlanSeed = Awaited<ReturnType<typeof planAccountLaunch>>[\"workspaceSeed\"];\n\n/** When an applicable env file holds `op://` refs, confirm `op` (and tokenCommand) work. */\nasync function checkSecretRefs(flags: AccountDoctorFlags, cwd: string): Promise<boolean> {\n const files: string[] = [];\n const dir = userSecretsDir(flags.home);\n if (dir && fs.existsSync(dir)) {\n for (const entry of fs.readdirSync(dir)) {\n if (entry.endsWith(\".env\")) files.push(path.join(dir, entry));\n }\n }\n const configPath = findConfigPath(cwd, { home: flags.home });\n if (configPath) {\n const projectRoot =\n path.basename(path.dirname(configPath)) === CONFIG_DIR\n ? path.dirname(path.dirname(configPath))\n : cwd;\n files.push(path.join(projectRoot, CONFIG_DIR, \"env\"));\n }\n const values: Record<string, string> = {};\n for (const file of files) {\n if (!fs.existsSync(file)) continue;\n Object.assign(values, parseDotenv(fs.readFileSync(file, \"utf8\")).values);\n }\n if (!hasSecretRefs(values)) return false;\n\n const layers = readSecretResolverLayers({ cwd, home: flags.home });\n try {\n await checkSecretResolver(mergeSecretResolver(layers.machine, layers.project), { home: flags.home });\n info(\"secret refs: 1Password CLI available\");\n return false;\n } catch (error) {\n warn(`secret refs: ${error instanceof Error ? error.message : String(error)}`);\n if (error instanceof PiPodError && error.hint) hint(error.hint);\n return true;\n }\n}\n","/**\n * src/config.ts — `.pi-pod/config.json` loading, validation and defaulting (§4.1).\n *\n * Parsed as JSONC so the annotated example in the spec is valid as written. Validation is\n * hand-rolled rather than schema-library-driven so that every message can name the offending\n * path and say what to do about it. Unknown keys warn (forward compatibility: a config\n * written for a newer launcher should still run); wrong types are hard errors.\n *\n * Account launches send the project file to the server; machine config is client preferences\n * only. The lower-level validation and legacy loader remain useful to tests and compatibility\n * callers, while launch planning owns the server-visible layer boundary.\n */\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { ChordConfig } from \"./client/runtime/chords.js\";\nimport { POD_SUBCOMMANDS } from \"./client/runtime/pod-commands.js\";\nimport { DEFAULT_HOST_CONFIG, type HostConfigSelection } from \"./hostconfig.js\";\nimport { defaultImageRef, launcherVersion } from \"./image.js\";\nimport { userConfigPath } from \"./userconfig.js\";\n\nexport const CONFIG_DIR = \".pi-pod\";\nexport const CONFIG_RELATIVE_PATH = path.join(CONFIG_DIR, \"config.json\");\n\nexport type InitOnFailure = \"abort\" | \"prompt\" | \"continue\";\n/**\n * Conventional project file paths. These used to be configurable (`envFile`, `initScript`,\n * `bakeScript`); they are fixed now so the server bundle never stores client filesystem\n * layout. See docs/config-simplification.md.\n */\nexport const PROJECT_ENV_FILE = path.join(CONFIG_DIR, \"env\");\nexport const PROJECT_INIT_SCRIPT = path.join(CONFIG_DIR, \"init.sh\");\nexport const PROJECT_BAKE_SCRIPT = path.join(CONFIG_DIR, \"bake.sh\");\n\n/**\n * Top-level config keys retired by the config simplification, each with its migration.\n * Presence is a hard error (not an unknown-key warning): a custom script path that is\n * silently ignored would read the wrong file, and a no-op key that is silently kept\n * would never get cleaned up.\n */\nexport const REMOVED_CONFIG_KEYS: Record<string, string> = {\n envFile: `envFile was removed — the project env file is always ${PROJECT_ENV_FILE}; move your file there and delete this key`,\n initScript: `initScript was removed — the project init script is always ${PROJECT_INIT_SCRIPT}; move your script there and delete this key`,\n bakeScript: `bakeScript was removed — the project bake script is always ${PROJECT_BAKE_SCRIPT}; move your script there and delete this key`,\n reuse: \"reuse was removed — pass --reuse to reuse a stopped project pod (fresh pods are the default); delete this key\",\n};\n\n/**\n * Retired `pi.hostConfig` name lists. Neither ever reached the server (zero server reads)\n * nor selected anything locally — the whole local agents directory always syncs — so\n * they were pure no-ops. `settings`/`packages` stay live.\n */\nexport const REMOVED_HOSTCONFIG_KEYS: Record<string, string> = {\n skills: \"pi.hostConfig.skills was removed — it never selected anything; delete this key (the whole local agents directory still syncs)\",\n extensions: \"pi.hostConfig.extensions was removed — it never selected anything; delete this key\",\n};\n\n/**\n * Retired sandbox-provider selection keys. Single-provider build: `sandbox` is the only\n * backend, so both are warn-and-ignore locally and stripped from every outgoing bundle.\n * Old project/template/org files keep running with a migration warning instead of failing.\n */\nexport const RETIRED_PROVIDER_CONFIG_KEYS: Record<string, string> = {\n provider: \"provider was removed — sandbox is the only backend; delete this key\",\n deniedProviders: \"deniedProviders was removed — sandbox is the only backend; delete this key\",\n};\n\n/** Names from RETIRED_PROVIDER_CONFIG_KEYS present on a raw config object. */\nexport function retiredProviderConfigKeysFound(raw: Record<string, unknown>): string[] {\n return Object.keys(RETIRED_PROVIDER_CONFIG_KEYS).filter((key) => Object.hasOwn(raw, key));\n}\n\n/**\n * Keys that stay valid locally but must never travel in a server bundle: the server\n * rejects them on write (400). `template` is the local pin (a template id travels\n * instead); `reuse` is retired locally but old bundles may still carry it; the rest\n * are retired path pointers and hostConfig name lists — listed here as defense for\n * old files and old bundles.\n */\nconst OUTGOING_STRIPPED_TOP_KEYS = [\n \"template\",\n \"reuse\",\n \"envFile\",\n \"initScript\",\n \"bakeScript\",\n \"provider\",\n \"deniedProviders\",\n];\n\n/** Names from REMOVED_CONFIG_KEYS present on a raw config object. */\nexport function removedConfigKeysFound(raw: Record<string, unknown>): string[] {\n return Object.keys(REMOVED_CONFIG_KEYS).filter((key) => Object.hasOwn(raw, key));\n}\n\n/** Names from REMOVED_HOSTCONFIG_KEYS present on a raw pi.hostConfig object. */\nexport function removedHostConfigKeysFound(raw: Record<string, unknown>): string[] {\n return Object.keys(REMOVED_HOSTCONFIG_KEYS).filter((key) => Object.hasOwn(raw, key));\n}\n\n/** Retired-key findings on one local file: dotted path plus its migration hint. */\nexport interface RetiredKeyFinding {\n path: string;\n hint: string;\n}\n\n/** Top-level and nested (`pi.hostConfig`) retired keys present on a raw local object. */\nexport function retiredLocalKeysFound(raw: Record<string, unknown>): RetiredKeyFinding[] {\n const found: RetiredKeyFinding[] = [];\n for (const key of removedConfigKeysFound(raw)) {\n found.push({ path: key, hint: REMOVED_CONFIG_KEYS[key]! });\n }\n const pi = raw[\"pi\"];\n if (pi !== null && typeof pi === \"object\" && !Array.isArray(pi)) {\n const hostConfig = (pi as Record<string, unknown>)[\"hostConfig\"];\n if (hostConfig !== null && typeof hostConfig === \"object\" && !Array.isArray(hostConfig)) {\n for (const key of removedHostConfigKeysFound(hostConfig as Record<string, unknown>)) {\n found.push({ path: `pi.hostConfig.${key}`, hint: REMOVED_HOSTCONFIG_KEYS[key]! });\n }\n }\n }\n return found;\n}\n\n/**\n * Client-only keys that live in local files but never in a bundle. `template` is covered\n * by the outgoing list; these are the rest.\n */\nconst CLIENT_ONLY_TOP_KEYS = [\"$schema\", \"secretResolver\"] as const;\nconst CLIENT_ONLY_PI_KEYS = [\"chords\", \"sessionNaming\"] as const;\n\n/** Every dotted name a bundle payload must not contain: rejected keys plus client-only ones. */\nexport function nonBundleKeysFound(config: Record<string, unknown>): string[] {\n const found = outgoingStrippedKeysFound(config);\n for (const key of CLIENT_ONLY_TOP_KEYS) {\n if (Object.hasOwn(config, key) && !found.includes(key)) found.push(key);\n }\n const pi = config[\"pi\"];\n if (pi !== null && typeof pi === \"object\" && !Array.isArray(pi)) {\n for (const key of CLIENT_ONLY_PI_KEYS) {\n const dotted = `pi.${key}`;\n if (Object.hasOwn(pi as Record<string, unknown>, key) && !found.includes(dotted)) {\n found.push(dotted);\n }\n }\n }\n return found;\n}\n\n/**\n * The single deep boundary for every outgoing server-bundle config: rejected keys and\n * client-only metadata are dropped, and a `pi` left holding only metadata is removed.\n */\nexport function stripNonBundleKeys<T extends Record<string, unknown>>(config: T): T {\n if (nonBundleKeysFound(config).length === 0) return config;\n const next = stripOutgoingConfigKeys({ ...config });\n for (const key of CLIENT_ONLY_TOP_KEYS) delete next[key];\n const pi = next[\"pi\"];\n if (pi !== null && typeof pi === \"object\" && !Array.isArray(pi)) {\n const podPi = { ...(pi as Record<string, unknown>) };\n for (const key of CLIENT_ONLY_PI_KEYS) delete podPi[key];\n if (Object.keys(podPi).length > 0) (next as Record<string, unknown>)[\"pi\"] = podPi;\n else delete next[\"pi\"];\n }\n return next;\n}\n\n/**\n * Drop retired keys from server-resident config before validating it. Old templates and\n * bundles may still carry them; they were path pointers or no-ops, never pod settings.\n * Local files are validated strictly instead, so a stale local key fails closed.\n */\nexport function stripRemovedConfigKeys<T extends Record<string, unknown>>(config: T): T {\n const hostConfig = (config[\"pi\"] as Record<string, unknown> | undefined)?.[\"hostConfig\"];\n const nested = hostConfig !== null && typeof hostConfig === \"object\" && !Array.isArray(hostConfig)\n ? removedHostConfigKeysFound(hostConfig as Record<string, unknown>)\n : [];\n if (\n removedConfigKeysFound(config).length === 0 &&\n retiredProviderConfigKeysFound(config).length === 0 &&\n nested.length === 0\n )\n return config;\n const next: Record<string, unknown> = { ...config };\n for (const key of Object.keys(REMOVED_CONFIG_KEYS)) delete next[key];\n for (const key of Object.keys(RETIRED_PROVIDER_CONFIG_KEYS)) delete next[key];\n if (nested.length > 0) {\n const pi = { ...((next[\"pi\"] as Record<string, unknown>) ?? {}) };\n const hc = { ...((pi[\"hostConfig\"] as Record<string, unknown>) ?? {}) };\n for (const key of Object.keys(REMOVED_HOSTCONFIG_KEYS)) delete hc[key];\n pi[\"hostConfig\"] = hc;\n next[\"pi\"] = pi;\n }\n return next as T;\n}\n\n/** Dotted names an outgoing bundle config would lose to the server write contract. */\nexport function outgoingStrippedKeysFound(config: Record<string, unknown>): string[] {\n const found = OUTGOING_STRIPPED_TOP_KEYS.filter((key) => Object.hasOwn(config, key));\n const pi = config[\"pi\"];\n if (pi !== null && typeof pi === \"object\" && !Array.isArray(pi)) {\n const hostConfig = (pi as Record<string, unknown>)[\"hostConfig\"];\n if (hostConfig !== null && typeof hostConfig === \"object\" && !Array.isArray(hostConfig)) {\n for (const key of removedHostConfigKeysFound(hostConfig as Record<string, unknown>)) {\n found.push(`pi.hostConfig.${key}`);\n }\n }\n }\n return found;\n}\n\n/**\n * Strip everything the server bundle-write contract rejects (400) from an outgoing\n * config payload. Local-only pins (`template`), the retired `reuse` key, retired\n * path pointers, and retired hostConfig name lists never reach the server.\n */\nexport function stripOutgoingConfigKeys<T extends Record<string, unknown>>(config: T): T {\n if (outgoingStrippedKeysFound(config).length === 0) return config;\n const next = stripRemovedConfigKeys({ ...config });\n for (const key of OUTGOING_STRIPPED_TOP_KEYS) delete next[key];\n return next;\n}\n\nexport type EgressMode = \"allowlist\" | \"open\";\nexport const PI_THINKING_LEVELS = [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const;\nexport type PiThinkingLevel = (typeof PI_THINKING_LEVELS)[number];\n\nexport interface EgressConfig {\n mode: EgressMode;\n /**\n * Also allow the hosts implied by *this checkout*: the git remote, and any base URL named\n * in the env file (§11.1).\n *\n * Narrow on purpose. It used to switch on a table of env-var-name → endpoint compiled into\n * the launcher, which is now `egress.allow` — a list you can read. What remains under this\n * flag is only what a committed file cannot state: the remote changes when you change\n * remotes, and a base URL comes out of a gitignored env file.\n */\n builtins: boolean;\n /** The allowlist. Hostnames or `*.`-prefixed wildcards; never addresses. */\n allow: string[];\n}\n\n/** Who names a session: the model, from the first prompt, or nobody (§5.4). */\nexport type SessionNaming = \"auto\" | \"off\";\n\nexport interface PiConfig {\n /** Default model for a fresh Pi process; a per-launch selection wins. */\n model: string | null;\n /** Default reasoning effort for a fresh Pi process; a per-launch selection wins. */\n thinking: PiThinkingLevel | null;\n command: string;\n args: string[];\n /** Historical name for sanitization gates applied to stored/project Pi bundles. */\n hostConfig: HostConfigSelection;\n /** `Ctrl-\\`-prefixed keystroke aliases for the /pod commands (§7). */\n chords: ChordConfig;\n /**\n * Whether a fresh session names itself from its first prompt (§5.4).\n *\n * The name is pi's own `session_info` name — the thing `/name` sets, the terminal tab shows\n * and `pipod list` mirrors — so \"off\" costs the automatic naming, not the feature.\n */\n sessionNaming: SessionNaming;\n}\n\nexport interface ResourcesConfig {\n cpu: number;\n memoryGB: number;\n diskGB: number;\n}\n\nexport interface PiPodConfig {\n image: string;\n resources: ResourcesConfig;\n egress: EgressConfig;\n /** Project identity for pod naming, list scoping, and reuse; null derives it from the project directory name. */\n name: string | null;\n /**\n * Account-mode default template (name or id). Client-only: it selects which template\n * layer a launch applies, and never travels in a launch overlay. null = built-in default.\n */\n template: string | null;\n workdir: string;\n initTimeoutSeconds: number;\n initOnFailure: InitOnFailure;\n pi: PiConfig;\n idleTimeoutMinutes: number;\n /** Canonical inactivity archive interval, counted from the moment a pod stops. */\n archiveAfterMinutes: number;\n labels: Record<string, string>;\n}\n\n/** The managed image identity used when no layer pins one explicitly. */\nexport function defaultImage(): string {\n return defaultImageRef(launcherVersion());\n}\n\n/** The pi-tui KeyId the chord prefix defaults to (§7). */\nexport const DEFAULT_CHORD_PREFIX = \"ctrl+\\\\\";\n\n/** One ending per /pod subcommand (§4). */\nexport const DEFAULT_CHORD_BINDINGS: Record<string, string> = {\n d: \"detach\",\n a: \"archive\",\n s: \"status\",\n l: \"list\",\n w: \"switch\",\n};\n\nexport const DEFAULT_CONFIG: Omit<PiPodConfig, \"image\"> = {\n resources: { cpu: 2, memoryGB: 4, diskGB: 5 },\n egress: { mode: \"open\", builtins: true, allow: [] },\n name: null,\n template: null,\n workdir: \"/workspace\",\n initTimeoutSeconds: 600,\n initOnFailure: \"abort\",\n pi: {\n model: null,\n thinking: null,\n command: \"pi\",\n args: [],\n hostConfig: DEFAULT_HOST_CONFIG,\n chords: { enabled: true, prefix: DEFAULT_CHORD_PREFIX, bindings: DEFAULT_CHORD_BINDINGS },\n sessionNaming: \"auto\",\n },\n idleTimeoutMinutes: 15,\n archiveAfterMinutes: 60,\n labels: {},\n};\n\n// ---------------------------------------------------------------------------\n// Validation primitives\n// ---------------------------------------------------------------------------\n\nclass Validator {\n readonly errors: string[] = [];\n readonly warnings: string[] = [];\n /**\n * The config path each finding is about, positionally parallel to `errors` / `warnings`.\n *\n * Kept alongside rendered strings so launch planning can attribute merged-config findings.\n * Empty where the finding is not about a single key.\n */\n readonly errorPaths: string[] = [];\n readonly warningPaths: string[] = [];\n\n fail(pathStr: string, message: string): void {\n this.errors.push(`${pathStr}: ${message}`);\n this.errorPaths.push(pathStr);\n }\n\n /** A finding whose message already names the setting it is about. */\n failMessage(pathStr: string, message: string): void {\n this.errors.push(message);\n this.errorPaths.push(pathStr);\n }\n\n warn(pathStr: string, message: string): void {\n this.warnings.push(message);\n this.warningPaths.push(pathStr);\n }\n\n warnUnknownKeys(pathStr: string, obj: Record<string, unknown>, known: string[]): void {\n for (const key of Object.keys(obj)) {\n if (key === \"$schema\") continue;\n if (known.includes(key)) continue;\n const full = pathStr === \"\" ? key : `${pathStr}.${key}`;\n this.warn(full, `${full}: unknown key (ignored)`);\n }\n }\n\n object(pathStr: string, value: unknown, fallback: Record<string, unknown> = {}) {\n if (value === undefined) return fallback;\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n this.fail(pathStr, `expected an object, got ${describe(value)}`);\n return fallback;\n }\n return value as Record<string, unknown>;\n }\n\n string(pathStr: string, value: unknown, fallback: string): string {\n if (value === undefined) return fallback;\n if (typeof value !== \"string\") {\n this.fail(pathStr, `expected a string, got ${describe(value)}`);\n return fallback;\n }\n return value;\n }\n\n requiredString(pathStr: string, value: unknown): string {\n if (value === undefined || value === null) {\n this.fail(pathStr, \"is required\");\n return \"\";\n }\n if (typeof value !== \"string\" || value.trim() === \"\") {\n this.fail(pathStr, `expected a non-empty string, got ${describe(value)}`);\n return \"\";\n }\n return value;\n }\n\n nullableString(pathStr: string, value: unknown, fallback: string | null): string | null {\n if (value === undefined) return fallback;\n if (value === null) return null;\n if (typeof value !== \"string\") {\n this.fail(pathStr, `expected a string or null, got ${describe(value)}`);\n return fallback;\n }\n return value;\n }\n\n bool(pathStr: string, value: unknown, fallback: boolean): boolean {\n if (value === undefined) return fallback;\n if (typeof value !== \"boolean\") {\n this.fail(pathStr, `expected true or false, got ${describe(value)}`);\n return fallback;\n }\n return value;\n }\n\n int(pathStr: string, value: unknown, fallback: number, opts: { min?: number } = {}): number {\n if (value === undefined) return fallback;\n if (typeof value !== \"number\" || !Number.isInteger(value)) {\n this.fail(pathStr, `expected an integer, got ${describe(value)}`);\n return fallback;\n }\n if (opts.min !== undefined && value < opts.min) {\n this.fail(pathStr, `must be >= ${opts.min}, got ${value}`);\n return fallback;\n }\n return value;\n }\n\n stringArray(pathStr: string, value: unknown, fallback: string[]): string[] {\n if (value === undefined) return fallback;\n if (!Array.isArray(value)) {\n this.fail(pathStr, `expected an array of strings, got ${describe(value)}`);\n return fallback;\n }\n const out: string[] = [];\n value.forEach((item, idx) => {\n if (typeof item !== \"string\") {\n this.fail(`${pathStr}[${idx}]`, `expected a string, got ${describe(item)}`);\n return;\n }\n out.push(item);\n });\n return out;\n }\n\n stringMap(\n pathStr: string,\n value: unknown,\n fallback: Record<string, string>,\n ): Record<string, string> {\n if (value === undefined) return fallback;\n const obj = this.object(pathStr, value);\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(obj)) {\n if (typeof v !== \"string\") {\n this.fail(`${pathStr}.${k}`, `expected a string, got ${describe(v)}`);\n continue;\n }\n out[k] = v;\n }\n return out;\n }\n\n enumValue<T extends string>(pathStr: string, value: unknown, allowed: T[], fallback: T): T {\n if (value === undefined) return fallback;\n if (typeof value !== \"string\" || !allowed.includes(value as T)) {\n this.fail(pathStr, `expected one of ${allowed.map((a) => `\"${a}\"`).join(\", \")}, got ${describe(value)}`);\n return fallback;\n }\n return value as T;\n }\n\n nullableEnumValue<T extends string>(\n pathStr: string,\n value: unknown,\n allowed: readonly T[],\n fallback: T | null,\n ): T | null {\n if (value === undefined) return fallback;\n if (value === null) return null;\n if (typeof value !== \"string\" || !allowed.includes(value as T)) {\n this.fail(pathStr, `expected null or one of ${allowed.map((a) => `\"${a}\"`).join(\", \")}, got ${describe(value)}`);\n return fallback;\n }\n return value as T;\n }\n}\n\nfunction describe(value: unknown): string {\n if (value === null) return \"null\";\n if (Array.isArray(value)) return \"an array\";\n return typeof value;\n}\n\n// ---------------------------------------------------------------------------\n// Chords (§7)\n// ---------------------------------------------------------------------------\n\nconst CHORD_MODIFIERS: Record<string, string> = {\n c: \"ctrl\",\n ctrl: \"ctrl\",\n control: \"ctrl\",\n s: \"shift\",\n shift: \"shift\",\n a: \"alt\",\n m: \"alt\",\n alt: \"alt\",\n meta: \"alt\",\n super: \"super\",\n cmd: \"super\",\n};\n\n/** Canonical modifier order, so two spellings of one key compare equal. */\nconst CHORD_MODIFIER_ORDER = [\"ctrl\", \"shift\", \"alt\", \"super\"];\n\nconst CHORD_SYMBOLS = new Set(\"`-=[]\\\\;',./!@#$%^&*()_+|~{}:<>?\".split(\"\"));\n\nconst CHORD_NAMED_KEYS = new Set([\n \"escape\", \"esc\", \"enter\", \"return\", \"tab\", \"space\", \"backspace\", \"delete\", \"insert\",\n \"clear\", \"home\", \"end\", \"pageup\", \"pagedown\", \"up\", \"down\", \"left\", \"right\",\n \"f1\", \"f2\", \"f3\", \"f4\", \"f5\", \"f6\", \"f7\", \"f8\", \"f9\", \"f10\", \"f11\", \"f12\",\n]);\n\n/**\n * A configured key in either spelling — the historical `C-\\` or pi-tui's own `ctrl+\\` — as the\n * KeyId `matchesKey` takes. Null when it names no key at all, which is a config error rather\n * than something to guess at: a keystroke is only testable by pressing it, and the moment you\n * would press it is at the end of a session, inside a provisioned pod.\n */\nfunction normalizeChordKey(raw: string): string | null {\n const text = raw.trim();\n if (text === \"\") return null;\n\n let base = text;\n const modifiers: string[] = [];\n const legacy = /^((?:[a-zA-Z]-)+)(.+)$/.exec(text);\n if (text.includes(\"+\")) {\n const parts = text.split(\"+\");\n base = parts[parts.length - 1]!;\n for (const part of parts.slice(0, -1)) modifiers.push(part.trim().toLowerCase());\n } else if (legacy) {\n for (const part of legacy[1]!.split(\"-\")) {\n if (part !== \"\") modifiers.push(part.toLowerCase());\n }\n base = legacy[2]!;\n }\n\n const resolved = new Set<string>();\n for (const modifier of modifiers) {\n const name = CHORD_MODIFIERS[modifier];\n if (name === undefined) return null;\n resolved.add(name);\n }\n\n base = base.toLowerCase();\n const known =\n (base.length === 1 && ((base >= \"a\" && base <= \"z\") || (base >= \"0\" && base <= \"9\") || CHORD_SYMBOLS.has(base))) ||\n CHORD_NAMED_KEYS.has(base);\n if (!known) return null;\n\n return [...CHORD_MODIFIER_ORDER.filter((m) => resolved.has(m)), base].join(\"+\");\n}\n\nfunction parseChords(v: Validator, raw: Record<string, unknown>, d: ChordConfig): ChordConfig {\n const prefixRaw = v.string(\"pi.chords.prefix\", raw[\"prefix\"], d.prefix);\n let prefix = normalizeChordKey(prefixRaw);\n if (prefix === null || !prefix.includes(\"+\")) {\n v.fail(\"pi.chords.prefix\", `expected a modified key such as \"C-\\\\\" or \"ctrl+\\\\\", got \"${prefixRaw}\"`);\n prefix = d.prefix;\n } else if (prefix === \"ctrl+m\") {\n // 0x0D is both Ctrl-M and Return: a chord here would hold every Enter press.\n v.fail(\"pi.chords.prefix\", \"C-m is what the terminal sends for Return — a chord on it would intercept every Enter press\");\n prefix = d.prefix;\n }\n\n const subcommands = POD_SUBCOMMANDS.map((c) => c.name);\n const bindingsRaw = v.object(\"pi.chords.bindings\", raw[\"bindings\"]);\n const bindings: Record<string, string> = { ...d.bindings };\n const named = new Set<string>();\n for (const [key, value] of Object.entries(bindingsRaw)) {\n const at = `pi.chords.bindings.${key}`;\n const ending = normalizeChordKey(key);\n if (ending === null) {\n v.fail(at, `\"${key}\" names no key — use a single key such as \"d\", or a modified one such as \"C-d\"`);\n continue;\n }\n if (typeof value === \"string\" && value === \"shell\") {\n v.warn(at, \"`shell` is no longer a pod command — this binding is ignored\");\n continue;\n }\n if (typeof value !== \"string\" || !subcommands.includes(value)) {\n v.fail(at, `expected one of ${subcommands.map((n) => `\"${n}\"`).join(\", \")}, got ${describe(value)}`);\n continue;\n }\n // A binding that can never fire is only discoverable at the worst possible moment.\n if (named.has(ending)) {\n v.fail(at, `binds ${ending} a second time — only one of the two could ever fire`);\n continue;\n }\n if (ending === prefix) {\n v.fail(at, `is the chord prefix itself — the prefix is consumed before an ending is read`);\n continue;\n }\n named.add(ending);\n bindings[ending] = value;\n }\n\n return { enabled: v.bool(\"pi.chords.enabled\", raw[\"enabled\"], d.enabled), prefix, bindings };\n}\n\n// ---------------------------------------------------------------------------\n// Parsing\n// ---------------------------------------------------------------------------\n\nconst TOP_LEVEL_KEYS = [\n \"image\",\n \"resources\",\n \"egress\",\n \"name\",\n \"template\",\n \"secretResolver\",\n \"workdir\",\n \"initTimeoutSeconds\",\n \"initOnFailure\",\n \"pi\",\n \"idleTimeoutMinutes\",\n \"archiveAfterMinutes\",\n \"labels\",\n];\n\nexport interface ParsedConfigResult {\n config: PiPodConfig;\n warnings: string[];\n errors: string[];\n /** Config path per finding, positionally parallel to `errors` / `warnings`. */\n errorPaths: string[];\n warningPaths: string[];\n /** False when `image` was defaulted rather than named. */\n imagePinned: boolean;\n}\n\n/** Validate + default an already-parsed config object. Exposed for unit tests. */\nexport function validateConfig(raw: unknown): ParsedConfigResult {\n const v = new Validator();\n const root = v.object(\"\", raw);\n // Retired keys fail closed with a migration (never the generic unknown-key warning).\n // Retired provider-selection keys warn-and-ignore instead: single-provider build runs\n // old files with a migration warning rather than failing the launch.\n v.warnUnknownKeys(\"\", root, [\n ...TOP_LEVEL_KEYS,\n ...Object.keys(REMOVED_CONFIG_KEYS),\n ...Object.keys(RETIRED_PROVIDER_CONFIG_KEYS),\n ]);\n for (const key of removedConfigKeysFound(root)) {\n v.fail(key, REMOVED_CONFIG_KEYS[key]!);\n }\n for (const key of retiredProviderConfigKeysFound(root)) {\n v.warn(key, `${key}: ${RETIRED_PROVIDER_CONFIG_KEYS[key]!}`);\n }\n\n const d = DEFAULT_CONFIG;\n\n const resourcesRaw = v.object(\"resources\", root[\"resources\"]);\n v.warnUnknownKeys(\"resources\", resourcesRaw, [\"cpu\", \"memoryGB\", \"diskGB\"]);\n // The client never clamps resources itself: the server-resolved chain is authoritative and\n // reports any clamp explicitly. In particular an 8-GiB request is gated server-side — it\n // either receives 8 GiB on a qualified host or a clear refusal, never a silent 4-GiB clamp.\n\n const egressRaw = v.object(\"egress\", root[\"egress\"]);\n v.warnUnknownKeys(\"egress\", egressRaw, [\"mode\", \"builtins\", \"allow\"]);\n\n const piRaw = v.object(\"pi\", root[\"pi\"]);\n v.warnUnknownKeys(\"pi\", piRaw, [\n \"model\",\n \"thinking\",\n \"command\",\n \"args\",\n \"hostConfig\",\n \"chords\",\n \"sessionNaming\",\n ]);\n\n const hostConfigRaw = v.object(\"pi.hostConfig\", piRaw[\"hostConfig\"]);\n v.warnUnknownKeys(\"pi.hostConfig\", hostConfigRaw, [\n \"settings\",\n \"packages\",\n ...Object.keys(REMOVED_HOSTCONFIG_KEYS),\n ]);\n for (const key of Object.keys(REMOVED_HOSTCONFIG_KEYS).filter((k) => Object.hasOwn(hostConfigRaw, k))) {\n v.fail(`pi.hostConfig.${key}`, REMOVED_HOSTCONFIG_KEYS[key]!);\n }\n\n const chordsRaw = v.object(\"pi.chords\", piRaw[\"chords\"]);\n v.warnUnknownKeys(\"pi.chords\", chordsRaw, [\"enabled\", \"prefix\", \"bindings\"]);\n\n const config: PiPodConfig = {\n image: v.string(\"image\", root[\"image\"], defaultImage()),\n resources: {\n cpu: v.int(\"resources.cpu\", resourcesRaw[\"cpu\"], d.resources.cpu, { min: 1 }),\n memoryGB: v.int(\"resources.memoryGB\", resourcesRaw[\"memoryGB\"], d.resources.memoryGB, {\n min: 1,\n }),\n diskGB: v.int(\"resources.diskGB\", resourcesRaw[\"diskGB\"], d.resources.diskGB, { min: 1 }),\n },\n egress: {\n mode: v.enumValue<EgressMode>(\n \"egress.mode\",\n egressRaw[\"mode\"],\n [\"allowlist\", \"open\"],\n d.egress.mode,\n ),\n builtins: v.bool(\"egress.builtins\", egressRaw[\"builtins\"], d.egress.builtins),\n allow: v.stringArray(\"egress.allow\", egressRaw[\"allow\"], d.egress.allow),\n },\n name: v.nullableString(\"name\", root[\"name\"], d.name),\n template: v.nullableString(\"template\", root[\"template\"], d.template),\n workdir: v.string(\"workdir\", root[\"workdir\"], d.workdir),\n initTimeoutSeconds: v.int(\"initTimeoutSeconds\", root[\"initTimeoutSeconds\"], d.initTimeoutSeconds, {\n min: 1,\n }),\n initOnFailure: v.enumValue<InitOnFailure>(\n \"initOnFailure\",\n root[\"initOnFailure\"],\n [\"abort\", \"prompt\", \"continue\"],\n d.initOnFailure,\n ),\n pi: {\n model: v.nullableString(\"pi.model\", piRaw[\"model\"], d.pi.model),\n thinking: v.nullableEnumValue<PiThinkingLevel>(\n \"pi.thinking\",\n piRaw[\"thinking\"],\n PI_THINKING_LEVELS,\n d.pi.thinking,\n ),\n command: v.string(\"pi.command\", piRaw[\"command\"], d.pi.command),\n args: v.stringArray(\"pi.args\", piRaw[\"args\"], d.pi.args),\n hostConfig: {\n settings: v.bool(\"pi.hostConfig.settings\", hostConfigRaw[\"settings\"], d.pi.hostConfig.settings),\n packages: v.bool(\"pi.hostConfig.packages\", hostConfigRaw[\"packages\"], d.pi.hostConfig.packages),\n },\n chords: parseChords(v, chordsRaw, d.pi.chords),\n sessionNaming: v.enumValue<SessionNaming>(\n \"pi.sessionNaming\",\n piRaw[\"sessionNaming\"],\n [\"auto\", \"off\"],\n d.pi.sessionNaming,\n ),\n },\n // 0 is meaningful here (auto-stop off), so the floor is 0 rather than 1.\n idleTimeoutMinutes: v.int(\"idleTimeoutMinutes\", root[\"idleTimeoutMinutes\"], d.idleTimeoutMinutes, {\n min: 0,\n }),\n archiveAfterMinutes: v.int(\"archiveAfterMinutes\", root[\"archiveAfterMinutes\"], d.archiveAfterMinutes, {\n min: 0,\n }),\n labels: v.stringMap(\"labels\", root[\"labels\"], d.labels),\n };\n\n // Cross-field rules -------------------------------------------------------\n\n if (\n config.pi.model !== null &&\n (config.pi.model.length === 0 ||\n config.pi.model.length > 512 ||\n config.pi.model.trim() !== config.pi.model ||\n config.pi.model.startsWith(\"-\"))\n ) {\n v.fail(\n \"pi.model\",\n \"must be 1–512 characters, with no surrounding whitespace, and must not start with '-'\",\n );\n }\n\n if (config.name !== null && !/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(config.name)) {\n v.fail(\"name\", \"must be 1-64 characters of letters, digits, dots, dashes or underscores\");\n }\n\n if (\n config.template !== null &&\n (config.template.length === 0 ||\n config.template.length > 100 ||\n config.template.trim() !== config.template)\n ) {\n v.fail(\n \"template\",\n \"must be 1–100 characters, with no surrounding whitespace, or null to launch without a template\",\n );\n }\n\n\n if (!path.posix.isAbsolute(config.workdir)) {\n v.fail(\"workdir\", `must be an absolute path inside the sandbox, got \"${config.workdir}\"`);\n }\n\n // Archival is measured from the moment a pod *stops* (§9), and idle auto-stop is what\n // stops it. Turning auto-stop off therefore removes the trigger for archival as well: the\n // pod never goes quiet, never gets archived, and bills at the running rate until\n // someone runs `pipod gc`.\n if (config.idleTimeoutMinutes === 0) {\n v.warn(\n \"idleTimeoutMinutes\",\n \"idleTimeoutMinutes: 0 requests disabled idle auto-stop. \" +\n \"A detached pod runs (and bills) until `pipod gc`; the server \" +\n \"reports the effective maximum during preflight\",\n );\n }\n\n // \"open\" leaves network policy to the sandbox; a stray allow list next to it is\n // dead config that reads as protection.\n if (config.egress.mode === \"open\" && config.egress.allow.length > 0) {\n v.warn(\n \"egress.allow\",\n 'egress.allow: ignored because egress.mode is \"open\" (all egress is permitted)',\n );\n }\n\n return {\n config,\n warnings: v.warnings,\n errors: v.errors,\n errorPaths: v.errorPaths,\n warningPaths: v.warningPaths,\n imagePinned: root[\"image\"] !== undefined,\n };\n}\n\n/** A path with symlinks resolved, or the path itself when it cannot be resolved. */\nfunction realpathOr(p: string): string {\n try {\n return fs.realpathSync(p);\n } catch {\n return p;\n }\n}\n\n/**\n * The same file or directory by two names.\n *\n * Compared through `realpath` because git reports the toplevel with symlinks resolved and a cwd\n * generally is not — on macOS `/var` is a symlink to `/private/var`, which is where both the\n * temp dirs the tests run in and many real checkouts live.\n */\nfunction samePath(a: string, b: string): boolean {\n return a === b || realpathOr(a) === realpathOr(b);\n}\n\nexport interface FindConfigOptions {\n /** Host home directory. Defaults to $HOME; a parameter so tests need no real one. */\n home?: string | undefined;\n}\n\n/**\n * The nearest *project* `.pi-pod/config.json` at or above `startDir`, or null when there is\n * none. Purely a filesystem walk — no version-control tool is consulted.\n *\n * `~/.pi-pod/config.json` never answers: it is client preferences, not a project contract.\n * The walk also stops *at* `$HOME` — a `.pi-pod/` above the home directory belongs to nobody's\n * project.\n */\nexport function findConfigPath(startDir: string, opts: FindConfigOptions = {}): string | null {\n const userPath = userConfigPath(opts.home);\n const homeDir = userPath !== null ? path.dirname(path.dirname(userPath)) : null;\n\n let dir = path.resolve(startDir);\n for (;;) {\n const candidate = path.join(dir, CONFIG_RELATIVE_PATH);\n if (fs.existsSync(candidate) && !(userPath !== null && samePath(candidate, userPath))) {\n return candidate;\n }\n if (homeDir !== null && samePath(dir, homeDir)) return null;\n const parent = path.dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n","/**\n * src/dotenv.ts — env file parser (§4.2).\n *\n * Standard dotenv format, parsed on the host. Comments, blank lines and `export KEY=value`\n * prefixes are supported. There is deliberately no variable expansion and no command\n * substitution: values are literal strings, because these are secrets headed for a third\n * party's control plane and surprising transformations are the last thing anyone wants.\n */\n\nexport interface DotenvEntry {\n key: string;\n value: string;\n /** 1-based line number, for diagnostics. */\n line: number;\n}\n\nexport interface DotenvParseResult {\n values: Record<string, string>;\n entries: DotenvEntry[];\n /** Lines that were neither blank, comment, nor KEY=value. */\n malformed: Array<{ line: number; text: string }>;\n}\n\nconst KEY_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\nexport function parseDotenv(text: string): DotenvParseResult {\n const values: Record<string, string> = {};\n const entries: DotenvEntry[] = [];\n const malformed: Array<{ line: number; text: string }> = [];\n\n const lines = text.split(/\\r?\\n/);\n for (let i = 0; i < lines.length; i++) {\n const raw = lines[i]!;\n const lineNo = i + 1;\n const trimmed = raw.trim();\n\n if (trimmed === \"\" || trimmed.startsWith(\"#\")) continue;\n\n const withoutExport = trimmed.startsWith(\"export \")\n ? trimmed.slice(\"export \".length).trim()\n : trimmed;\n\n const eq = withoutExport.indexOf(\"=\");\n if (eq <= 0) {\n malformed.push({ line: lineNo, text: raw });\n continue;\n }\n\n const key = withoutExport.slice(0, eq).trim();\n if (!KEY_RE.test(key)) {\n malformed.push({ line: lineNo, text: raw });\n continue;\n }\n\n const value = parseValue(withoutExport.slice(eq + 1));\n values[key] = value;\n entries.push({ key, value, line: lineNo });\n }\n\n return { values, entries, malformed };\n}\n\n/**\n * Values may be single-quoted, double-quoted, or bare. Quoted values keep everything inside\n * the quotes verbatim (so `=` and `#` are safe); double-quoted values additionally honor\n * `\\n`, `\\r`, `\\t` and escaped quotes, which is what people expect when pasting a PEM key.\n * Bare values are trimmed and lose an unquoted trailing `# comment`.\n */\nfunction parseValue(rawValue: string): string {\n const v = rawValue.trim();\n if (v === \"\") return \"\";\n\n const quote = v[0];\n if (quote === '\"' || quote === \"'\") {\n const closing = findClosingQuote(v, quote);\n if (closing > 0) {\n const inner = v.slice(1, closing);\n return quote === '\"' ? unescapeDoubleQuoted(inner) : inner;\n }\n // Unterminated quote: treat the remainder literally rather than throwing away a secret.\n return v.slice(1);\n }\n\n const hashIdx = findBareComment(v);\n return (hashIdx >= 0 ? v.slice(0, hashIdx) : v).trim();\n}\n\nfunction findClosingQuote(v: string, quote: string): number {\n for (let i = 1; i < v.length; i++) {\n if (v[i] === \"\\\\\" && quote === '\"') {\n i += 1;\n continue;\n }\n if (v[i] === quote) return i;\n }\n return -1;\n}\n\nfunction unescapeDoubleQuoted(s: string): string {\n return s.replace(/\\\\([nrt\"'\\\\$])/g, (_m, c: string) => {\n switch (c) {\n case \"n\":\n return \"\\n\";\n case \"r\":\n return \"\\r\";\n case \"t\":\n return \"\\t\";\n default:\n return c;\n }\n });\n}\n\n/** A `#` only starts a comment when preceded by whitespace (so `pass#word` survives). */\nfunction findBareComment(v: string): number {\n for (let i = 0; i < v.length; i++) {\n if (v[i] === \"#\" && i > 0 && /\\s/.test(v[i - 1]!)) return i;\n }\n return -1;\n}\n\n/**\n * `env.example` is the committed contract: every key in `env` should appear (valueless) in\n * `env.example` (§4.2). Returns keys present in one file but not the other.\n */\nexport function diffEnvKeys(\n envKeys: string[],\n exampleKeys: string[],\n): { undocumented: string[]; missing: string[] } {\n const exampleSet = new Set(exampleKeys);\n const envSet = new Set(envKeys);\n return {\n undocumented: envKeys.filter((k) => !exampleSet.has(k)),\n missing: exampleKeys.filter((k) => !envSet.has(k)),\n };\n}\n","/**\n * src/secret-refs.ts — just-in-time 1Password references (`op://…`).\n *\n * A reference is a value that has not been fetched yet, never a value the server sees.\n * Resolution happens once, client-side, at the last moment before a value leaves the\n * process. Files keep storing `op://` URIs verbatim; a failed resolve fails the command\n * rather than forwarding the literal string as if it were the secret.\n */\nimport { execFile } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { PiPodError } from \"./errors.js\";\nimport { registerSecret, registerSecrets } from \"./redact.js\";\n\nconst execFileAsync = promisify(execFile);\n\nconst REF_RE = /^op:\\/\\//;\nconst OP_TIMEOUT_MS = 30_000;\nconst TOKEN_TIMEOUT_MS = 15_000;\nconst MAX_BUFFER = 10 * 1024 * 1024;\n\nexport function isSecretRef(value: string): boolean {\n return REF_RE.test(value);\n}\n\nexport function hasSecretRefs(values: Record<string, string>): boolean {\n return Object.values(values).some(isSecretRef);\n}\n\nexport interface SecretResolverConfig {\n type: \"1password\";\n tokenCommand?: string[];\n}\n\nexport interface ResolveSecretRefsOptions {\n home?: string;\n /** Test hook: the `op` argv0, so suites do not have to mutate PATH. */\n opCommand?: string;\n}\n\n/** Pull a `secretResolver` object out of a config layer, or null when the layer never set one. */\nexport function parseSecretResolver(raw: unknown, label = \"secretResolver\"): SecretResolverConfig | null {\n if (raw === undefined || raw === null) return null;\n if (typeof raw !== \"object\" || Array.isArray(raw)) {\n throw new PiPodError(`${label} must be an object`, {\n hint: 'example: { \"type\": \"1password\", \"tokenCommand\": [\"op\", \"whoami\", \"--format\", \"json\"] }',\n });\n }\n const obj = raw as Record<string, unknown>;\n if (obj[\"type\"] !== \"1password\") {\n throw new PiPodError(\n obj[\"type\"] === undefined\n ? `${label}.type is required`\n : `${label}.type must be \"1password\"`,\n {\n hint:\n typeof obj[\"type\"] === \"string\"\n ? `unknown resolver type \"${obj[\"type\"]}\" — only \"1password\" is implemented`\n : 'set type to \"1password\"',\n },\n );\n }\n let tokenCommand: string[] | undefined;\n if (obj[\"tokenCommand\"] !== undefined) {\n const cmd = obj[\"tokenCommand\"];\n if (\n !Array.isArray(cmd) ||\n cmd.length === 0 ||\n !cmd.every((part) => typeof part === \"string\" && part.length > 0)\n ) {\n throw new PiPodError(`${label}.tokenCommand must be a non-empty array of strings`);\n }\n tokenCommand = cmd as string[];\n }\n return tokenCommand ? { type: \"1password\", tokenCommand } : { type: \"1password\" };\n}\n\n/**\n * Project (or org directory) over machine for `type`, but only the machine layer may name\n * a `tokenCommand`: the other layer arrives with a cloned repository or a pulled bundle,\n * and must not choose what runs on this workstation.\n */\nexport function mergeSecretResolver(\n machine: SecretResolverConfig | null,\n project: SecretResolverConfig | null,\n): SecretResolverConfig | null {\n if (project?.tokenCommand) {\n throw new PiPodError(\"secretResolver.tokenCommand is only read from this machine's config\", {\n hint: \"remove it from the project or org config; set it in your pipod user config instead\",\n });\n }\n if (!project) return machine;\n return machine?.tokenCommand\n ? { type: project.type, tokenCommand: machine.tokenCommand }\n : { type: project.type };\n}\n\n/**\n * Resolves every `op://` value in one `op inject` subprocess; literals pass through.\n * No refs → the input object is returned unchanged and nothing is spawned.\n */\nexport async function resolveSecretRefs(\n values: Record<string, string>,\n config: SecretResolverConfig | null,\n opts: ResolveSecretRefsOptions = {},\n): Promise<Record<string, string>> {\n const refs: Record<string, string> = {};\n const literals: Record<string, string> = {};\n for (const [key, value] of Object.entries(values)) {\n if (isSecretRef(value)) refs[key] = value;\n else literals[key] = value;\n }\n if (Object.keys(refs).length === 0) return values;\n\n const token = config?.tokenCommand\n ? await runTokenCommand(config.tokenCommand, opts.home)\n : undefined;\n const resolved = await injectRefs(refs, { token, home: opts.home, opCommand: opts.opCommand });\n const missing = Object.keys(refs).filter((key) => typeof resolved[key] !== \"string\");\n if (missing.length > 0) {\n throw new PiPodError(`1Password did not return ${missing.join(\", \")}`, {\n hint: \"the reference may have been renamed or the vault is not shared with this token\",\n });\n }\n const unresolved = Object.entries(refs)\n .filter(([key]) => isSecretRef(resolved[key]!))\n .map(([key]) => key);\n if (unresolved.length > 0) {\n throw new PiPodError(`1Password left ${unresolved.join(\", \")} unresolved`, {\n hint: \"token expired or vault access revoked? check `op whoami` / `systemd-creds decrypt`\",\n });\n }\n\n const out: Record<string, string> = { ...literals };\n for (const key of Object.keys(refs)) out[key] = resolved[key]!;\n registerSecrets(out);\n return out;\n}\n\n/**\n * Confirm the machinery a refs file needs: `op` on PATH, and `tokenCommand` exits 0\n * when one is configured. Does not resolve any secret.\n */\nexport async function checkSecretResolver(\n config: SecretResolverConfig | null,\n opts: ResolveSecretRefsOptions = {},\n): Promise<void> {\n try {\n await runOp([\"--version\"], { home: opts.home, opCommand: opts.opCommand });\n } catch (error) {\n throw commandFailure(\"1Password CLI (`op`) failed\", error, {\n hint: \"install 1Password CLI (`op`) or remove op:// references\",\n });\n }\n if (config?.tokenCommand) await runTokenCommand(config.tokenCommand, opts.home);\n}\n\nasync function runTokenCommand(command: string[], home?: string): Promise<string> {\n const [file, ...args] = command;\n if (!file) {\n throw new PiPodError(\"secretResolver.tokenCommand must be a non-empty array of strings\");\n }\n let stdout: string;\n try {\n ({ stdout } = await execFileAsync(file, args, {\n encoding: \"utf8\",\n timeout: TOKEN_TIMEOUT_MS,\n maxBuffer: MAX_BUFFER,\n env: processEnv({ home }),\n }));\n } catch (error) {\n throw commandFailure(\"secretResolver.tokenCommand failed\", error, {\n hint: \"token expired or vault access revoked? check `op whoami` / `systemd-creds decrypt`\",\n });\n }\n const token = stdout.trim();\n if (!token) {\n throw new PiPodError(\"secretResolver.tokenCommand produced no token\", {\n hint: \"token expired or vault access revoked? check `op whoami` / `systemd-creds decrypt`\",\n });\n }\n registerSecret(token);\n return token;\n}\n\nasync function injectRefs(\n refs: Record<string, string>,\n opts: { token?: string; home?: string; opCommand?: string },\n): Promise<Record<string, string>> {\n const env = processEnv({ home: opts.home, token: opts.token });\n // `op inject` races an empty stdin when the child starts before the pipe is\n // written; --in-file is the reliable delivery. The file holds references only.\n const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), \"pipod-op-\"));\n const templateFile = path.join(tmpDir, \"template.json\");\n let stdout: string;\n try {\n fs.writeFileSync(templateFile, JSON.stringify(refs), { mode: 0o600 });\n ({ stdout } = await runOp([\"inject\", \"--in-file\", templateFile], {\n env,\n opCommand: opts.opCommand,\n }));\n } catch (error) {\n throw commandFailure(\"1Password CLI (`op inject`) failed\", error, {\n hint: \"token expired or vault access revoked? check `op whoami` / `systemd-creds decrypt`\",\n });\n } finally {\n fs.rmSync(tmpDir, { recursive: true, force: true });\n }\n try {\n const parsed: unknown = JSON.parse(stdout);\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n const out: Record<string, string> = {};\n for (const [key, value] of Object.entries(parsed as Record<string, unknown>)) {\n if (typeof value === \"string\") out[key] = value;\n }\n return out;\n }\n } catch {\n // `op inject` string-replaces and can emit invalid JSON when a secret contains\n // quotes or newlines. Fall back to one `op read` per ref so those values still resolve.\n }\n return readRefsIndividually(refs, env, opts.opCommand);\n}\n\nasync function readRefsIndividually(\n refs: Record<string, string>,\n env: NodeJS.ProcessEnv,\n opCommand?: string,\n): Promise<Record<string, string>> {\n const out: Record<string, string> = {};\n for (const [key, ref] of Object.entries(refs)) {\n let stdout: string;\n try {\n ({ stdout } = await runOp([\"read\", ref], { env, opCommand }));\n } catch (error) {\n throw commandFailure(`1Password CLI (\\`op read\\`) failed for ${key}`, error, {\n hint: \"token expired or vault access revoked? check `op whoami` / `systemd-creds decrypt`\",\n });\n }\n // `op read` terminates stdout with a newline that is not part of the secret.\n out[key] = stdout.endsWith(\"\\n\") ? stdout.slice(0, -1) : stdout;\n }\n return out;\n}\n\nfunction processEnv(opts: { home?: string; token?: string }): NodeJS.ProcessEnv {\n const env = { ...process.env };\n delete env[\"OP_CONNECT_HOST\"];\n delete env[\"OP_CONNECT_TOKEN\"];\n if (opts.home) env[\"HOME\"] = opts.home;\n if (opts.token) env[\"OP_SERVICE_ACCOUNT_TOKEN\"] = opts.token;\n return env;\n}\n\nasync function runOp(\n args: string[],\n opts: { env?: NodeJS.ProcessEnv; input?: string; home?: string; opCommand?: string },\n): Promise<{ stdout: string; stderr: string }> {\n const file = opts.opCommand ?? \"op\";\n const env = opts.env ?? processEnv({ home: opts.home });\n return new Promise((resolve, reject) => {\n const child = execFile(\n file,\n args,\n { encoding: \"utf8\", timeout: OP_TIMEOUT_MS, maxBuffer: MAX_BUFFER, env },\n (error, stdout, stderr) => {\n if (error) {\n const wrapped = error as NodeJS.ErrnoException & { stdout?: string; stderr?: string };\n wrapped.stdout = stdout;\n wrapped.stderr = stderr;\n reject(wrapped);\n return;\n }\n resolve({ stdout, stderr });\n },\n );\n if (opts.input !== undefined) child.stdin?.end(opts.input);\n else child.stdin?.end();\n });\n}\n\nfunction commandFailure(\n message: string,\n error: unknown,\n opts: { hint: string },\n): PiPodError {\n const err = error as NodeJS.ErrnoException & { stderr?: string };\n if (err.code === \"ENOENT\") {\n return new PiPodError(\"1Password CLI (`op`) not found on PATH\", {\n hint: \"install 1Password CLI (`op`) or remove op:// references\",\n cause: error,\n });\n }\n const detail = firstLine(err.stderr) || (error instanceof Error ? error.message : String(error));\n return new PiPodError(`${message}: ${detail}`, { hint: opts.hint, cause: error });\n}\n\nfunction firstLine(text: string | undefined): string {\n if (!text) return \"\";\n return text.trim().split(/\\r?\\n/)[0] ?? \"\";\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { findConfigPath, retiredLocalKeysFound, stripNonBundleKeys, validateConfig, type PiPodConfig } from \"../config.js\";\nimport { PiPodError } from \"../errors.js\";\nimport { parseJsonc } from \"../jsonc.js\";\nimport {\n parseSecretResolver,\n type SecretResolverConfig,\n} from \"../secret-refs.js\";\nimport { displayPath, mergeConfigLayers, userConfigPath } from \"../userconfig.js\";\nimport type { AccountClient } from \"./api.js\";\nimport type { AccountLaunchFlags } from \"./launch-types.js\";\nimport { resolveSeedRoot } from \"./workspace-seed.js\";\n\nexport function readHostConfig(home?: string | undefined): Record<string, unknown> {\n const file = userConfigPath(home);\n if (!file || !fs.existsSync(file)) return {};\n try {\n return parseJsonc(fs.readFileSync(file, \"utf8\"), file) as Record<string, unknown>;\n } catch (e) {\n if (e instanceof PiPodError) throw e;\n throw new PiPodError(`could not parse ${displayPath(file, home)}`, {\n hint: e instanceof Error ? e.message : String(e),\n });\n }\n}\n\n/**\n * Fail closed on retired keys in the machine layer. Only chords/sessionNaming (plus the\n * template pin and secretResolver) are ever read from `~/.pi-pod/config.json`, so a\n * stale path pointer or name list there would otherwise vanish without a word.\n */\nexport function assertMachineConfigCurrent(raw: Record<string, unknown>, home?: string | undefined): void {\n const retired = retiredLocalKeysFound(raw);\n if (retired.length === 0) return;\n const file = userConfigPath(home) ?? \"~/.pi-pod/config.json\";\n throw new PiPodError(\n `${displayPath(file, home)}: retired key${retired.length === 1 ? \"\" : \"s\"} ${retired.map((k) => k.path).join(\", \")}`,\n { hint: retired.map((k) => k.hint).join(\"; \") },\n );\n}\n\n/** Split local-only preferences from pod settings. The remaining keys are source/drift input only. */\nexport function takeClientOnlyKeys(raw: Record<string, unknown>): {\n config: Record<string, unknown>;\n template: string | null;\n secretResolver: SecretResolverConfig | null;\n} {\n const afterTemplate = takeTemplate(raw);\n const afterResolver = takeSecretResolver(afterTemplate.config);\n return {\n config: afterResolver.config,\n template: afterTemplate.template,\n secretResolver: afterResolver.secretResolver,\n };\n}\n\nfunction takeTemplate(raw: Record<string, unknown>): {\n config: Record<string, unknown>;\n template: string | null;\n} {\n if (!Object.hasOwn(raw, \"template\")) return { config: raw, template: null };\n const { template, ...config } = raw;\n if (template === null) return { config, template: \"\" };\n if (typeof template === \"string\" && template.length > 0) return { config, template };\n return { config, template: null };\n}\n\nfunction takeSecretResolver(raw: Record<string, unknown>): {\n config: Record<string, unknown>;\n secretResolver: SecretResolverConfig | null;\n} {\n if (!Object.hasOwn(raw, \"secretResolver\")) return { config: raw, secretResolver: null };\n const { secretResolver, ...config } = raw;\n return { config, secretResolver: parseSecretResolver(secretResolver) };\n}\n\n/** `--template` wins; otherwise the project pin, then the machine pin. An explicit null pin means none. */\nexport function resolveLaunchTemplateRef(\n flags: Pick<AccountLaunchFlags, \"template\">,\n layers: { project: string | null; machine: string | null },\n): string | undefined {\n if (flags.template) return flags.template;\n if (layers.project !== null) return layers.project || undefined;\n if (layers.machine !== null) return layers.machine || undefined;\n return undefined;\n}\n\n/** The client-only subset retained from ~/.pi-pod/config.json. */\nexport function machineClientConfig(raw: Record<string, unknown>): Record<string, unknown> {\n const pi = isPlainObjectValue(raw[\"pi\"]) ? raw[\"pi\"] : {};\n const clientPi = Object.fromEntries(\n Object.entries(pi).filter(([key]) => [\"chords\", \"sessionNaming\"].includes(key)),\n );\n return Object.keys(clientPi).length > 0 ? { pi: clientPi } : {};\n}\n\nfunction isPlainObjectValue(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\n/** Machine then project secret resolvers are retained for push-time env compilation. */\nexport function readSecretResolverLayers(opts: {\n cwd: string;\n home?: string;\n}): { machine: SecretResolverConfig | null; project: SecretResolverConfig | null } {\n const machine = takeClientOnlyKeys(readHostConfig(opts.home)).secretResolver;\n const configPath = findConfigPath(opts.cwd, { home: opts.home });\n const project = configPath\n ? takeClientOnlyKeys(parseJsonc(fs.readFileSync(configPath, \"utf8\"), configPath) as Record<string, unknown>)\n .secretResolver\n : null;\n return { machine, project };\n}\n\n/** Shared by attach/send: recover project context and overlay only machine client preferences. */\nexport async function localConfigView(\n client: AccountClient,\n cwd = process.cwd(),\n opts: { home?: string | undefined; templateId?: string | null } = {},\n): Promise<{ config: PiPodConfig; projectRoot: string | null }> {\n let projectRawFull: Record<string, unknown> = {};\n let projectRoot: string | null = null;\n const configPath = findConfigPath(cwd, { home: opts.home });\n if (configPath !== null) {\n projectRoot = path.dirname(path.dirname(configPath));\n projectRawFull = parseJsonc(fs.readFileSync(configPath, \"utf8\"), configPath) as Record<string, unknown>;\n }\n const machineRaw = readHostConfig(opts.home);\n assertMachineConfigCurrent(machineRaw, opts.home);\n const applyClientPreferences = (raw: unknown): PiPodConfig | null => {\n const serverView = raw !== null && typeof raw === \"object\" && !Array.isArray(raw)\n ? stripNonBundleKeys(raw as Record<string, unknown>)\n : raw;\n const withMachine = mergeConfigLayers(serverView, machineClientConfig(machineRaw));\n const parsed = validateConfig(withMachine as Record<string, unknown>);\n if (parsed.errors.length > 0) return null;\n return parsed.config;\n };\n const resolved = await client.resolve({\n ...(opts.templateId ? { templateId: opts.templateId } : {}),\n checkImage: false,\n }).catch(() => null);\n const serverView = resolved ? applyClientPreferences(resolved.config) : null;\n if (serverView) return { config: serverView, projectRoot };\n\n // Attach remains possible through a transient/old-server resolve failure, but local pod\n // source keys are not resurrected as a launch-local layer.\n const fallback = applyClientPreferences({}) ?? validateConfig({}).config;\n return { config: fallback, projectRoot };\n}\n\n/** A template pinned by the current project, or null outside one or when no pin is set. */\nexport function currentProjectTemplateRef(cwd = process.cwd(), home?: string | undefined): string | null {\n const configPath = findConfigPath(cwd, { home });\n if (configPath === null) return null;\n try {\n const raw = parseJsonc(fs.readFileSync(configPath, \"utf8\"), configPath) as Record<string, unknown>;\n const template = raw[\"template\"];\n return typeof template === \"string\" && template.length > 0 ? template : null;\n } catch {\n // Preserve project-scoped listing when local config cannot supply a usable template pin.\n return null;\n }\n}\n\n/**\n * The project a directory belongs to, by name: its config's `name`, else the directory holding\n * `.pi-pod/`; without config, the git repository's root directory, else the directory itself —\n * the same root a launch seeds from. Launches record it on the pod; lists, the default pod of\n * stop/attach, and --reuse go by it. Null in the home directory and at /, which are no project.\n */\nexport function currentProjectName(cwd = process.cwd(), home?: string | undefined): string | null {\n const configPath = findConfigPath(cwd, { home });\n if (configPath === null) {\n const root = resolveSeedRoot(cwd, home ? { home } : undefined);\n return root.ok ? path.basename(root.root) : null;\n }\n try {\n const raw = parseJsonc(fs.readFileSync(configPath, \"utf8\"), configPath) as Record<string, unknown>;\n const name = raw[\"name\"];\n if (typeof name === \"string\" && name.length > 0) return name;\n } catch {\n // A broken project config still scopes by its directory name.\n }\n return path.basename(path.dirname(path.dirname(configPath)));\n}\n","/**\n * src/jsonc.ts — minimal JSONC support (§4.1): comments and trailing commas.\n *\n * The annotated config example in the spec must be valid as written, so config.json is\n * parsed as JSONC. This strips comments and trailing commas with a real tokenizer (string\n * literals and escapes are respected, so a `//` inside a value is left alone) and then\n * hands the result to JSON.parse. Whitespace is preserved in place of stripped text so\n * that parse-error offsets still point at the right line.\n */\n\nexport function stripJsonComments(input: string): string {\n const out: string[] = [];\n let i = 0;\n const n = input.length;\n\n // Byte offsets of commas that may turn out to be trailing.\n const pendingCommas: number[] = [];\n let lastComma = -1;\n\n const push = (s: string) => out.push(s);\n const blank = (s: string) => push(s.replace(/[^\\n\\r]/g, \" \"));\n\n while (i < n) {\n const ch = input[i]!;\n\n if (ch === '\"') {\n // String literal — copy verbatim, honoring escapes.\n let j = i + 1;\n while (j < n) {\n const c = input[j]!;\n if (c === \"\\\\\") {\n j += 2;\n continue;\n }\n if (c === '\"') {\n j += 1;\n break;\n }\n j += 1;\n }\n push(input.slice(i, j));\n lastComma = -1;\n i = j;\n continue;\n }\n\n if (ch === \"/\" && input[i + 1] === \"/\") {\n let j = i;\n while (j < n && input[j] !== \"\\n\" && input[j] !== \"\\r\") j += 1;\n blank(input.slice(i, j));\n i = j;\n continue;\n }\n\n if (ch === \"/\" && input[i + 1] === \"*\") {\n let j = i + 2;\n while (j < n && !(input[j] === \"*\" && input[j + 1] === \"/\")) j += 1;\n j = Math.min(j + 2, n);\n blank(input.slice(i, j));\n i = j;\n continue;\n }\n\n if (ch === \",\") {\n lastComma = out.length;\n pendingCommas.push(out.length);\n push(\",\");\n i += 1;\n continue;\n }\n\n if (ch === \"}\" || ch === \"]\") {\n // Any comma seen since the last significant token was a trailing comma.\n if (lastComma >= 0) out[lastComma] = \" \";\n lastComma = -1;\n push(ch);\n i += 1;\n continue;\n }\n\n if (ch === \" \" || ch === \"\\t\" || ch === \"\\n\" || ch === \"\\r\") {\n push(ch);\n i += 1;\n continue;\n }\n\n lastComma = -1;\n push(ch);\n i += 1;\n }\n\n return out.join(\"\");\n}\n\nexport class JsoncParseError extends Error {\n readonly filePath: string | undefined;\n constructor(message: string, filePath?: string) {\n super(message);\n this.name = \"JsoncParseError\";\n this.filePath = filePath;\n }\n}\n\nexport function parseJsonc(text: string, filePath?: string): unknown {\n const stripped = stripJsonComments(text);\n try {\n return JSON.parse(stripped);\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n throw new JsoncParseError(\n `${filePath ? `${filePath}: ` : \"\"}invalid JSON/JSONC: ${msg}`,\n filePath,\n );\n }\n}\n","/**\n * src/account/workspace-seed.ts — deciding how a source-less launch reaches the pod.\n *\n * A fresh pod workdir starts empty. When the user did not launch from a configured\n * `.pi-pod` project, this module answers \"what would faithfully reproduce this working\n * copy inside the pod?\" with the cheapest lossless answer: clone the origin remote when\n * the pod can reach the exact commit the user is standing on, and otherwise archive the\n * tree over the wire.\n *\n * Clone is the optimization that has to earn its way in. Every failed eligibility check\n * becomes an `archive` with a reason; `copy` exists only as the legacy configured-project\n * transport over `/pods/:id/files` and is never produced here.\n */\nimport { spawnSync } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect } from \"node:util\";\nimport { PiPodError } from \"../errors.js\";\nimport { registerSecret } from \"../redact.js\";\n\nexport type WorkspaceSeedPlan =\n | { kind: \"none\"; reason: string }\n | {\n kind: \"clone\";\n root: string;\n subdir: string;\n url: string;\n branch: string;\n commit: string;\n access: \"anonymous\" | \"credential\";\n host: string;\n }\n | {\n kind: \"archive\";\n root: string;\n subdir: string;\n reason: string;\n includeGit: boolean;\n }\n | { kind: \"copy\"; root: string; reason: string };\n\nexport interface GitRun {\n status: number;\n stdout: string;\n stderr: string;\n}\n\n/** Runs a git command in the project and reports its outcome; never throws. */\nexport type GitRunner = (args: string[], opts?: { stdin?: string; env?: Record<string, string>; timeoutMs?: number }) => GitRun;\n\nconst GIT_TIMEOUT_MS = 10_000;\nconst GIT_NETWORK_TIMEOUT_MS = 20_000;\nconst GH_AUTH_TIMEOUT_MS = 10_000;\nconst FULL_SHA = /^[0-9a-f]{40}$/;\n\nconst GIT_USER_VAR = \"PI_POD_GIT_USER\";\nconst GIT_TOKEN_VAR = \"PI_POD_GIT_TOKEN\";\n\n/** An inline helper is the only way to hand git credentials that never touch the argv or disk. */\nconst CREDENTIAL_HELPER = `!f(){ echo \"username=$${GIT_USER_VAR}\"; echo \"password=$${GIT_TOKEN_VAR}\"; };f`;\n\nexport function makeGitRunner(cwd: string): GitRunner {\n return (args, opts = {}) => {\n const result = spawnSync(\"git\", args, {\n cwd,\n encoding: \"utf8\",\n timeout: opts.timeoutMs ?? GIT_TIMEOUT_MS,\n ...(opts.stdin === undefined ? {} : { input: opts.stdin }),\n env: {\n ...process.env,\n ...opts.env,\n // Nothing here may block on a human. `true` answers every prompt with an empty string,\n // which reads as \"no credentials\" instead of opening a GUI dialog on desktop installs —\n // and unlike `echo`, it does not hand back the prompt text as if it were the answer.\n GIT_TERMINAL_PROMPT: \"0\",\n GIT_ASKPASS: \"true\",\n SSH_ASKPASS: \"true\",\n GIT_SSH_COMMAND: \"ssh -oBatchMode=yes\",\n },\n });\n return {\n status: result.status ?? 1,\n stdout: result.stdout ?? \"\",\n stderr: result.stderr ?? \"\",\n };\n };\n}\n\n/** The server treats a comment-only script as no script at all; the CLI must agree to match it. */\nexport function isEffectivelyEmptyInitScript(script: string): boolean {\n return script\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0 && !line.startsWith(\"#\"))\n .join(\"\\n\").length === 0;\n}\n\nexport function shellQuote(value: string): string {\n return `'${value.replaceAll(\"'\", `'\\\\''`)}'`;\n}\n\n/**\n * Rewrite a remote the pod cannot use into one it can. scp-style and ssh:// remotes need a key\n * the pod does not have, but they name the same repository as an https URL that a token opens.\n */\nexport function httpsRemote(url: string): string | null {\n const scp = /^(?:[^@/]+@)?([^:/]+):(?!\\/)(.+)$/.exec(url);\n if (scp) return `https://${scp[1]}/${scp[2]}`;\n const ssh = /^ssh:\\/\\/(?:[^@/]+@)?([^/]+?)(?::\\d+)?\\/(.+)$/.exec(url);\n if (ssh) return `https://${ssh[1]}/${ssh[2]}`;\n // A token baked into the remote (`https://oauth2:TOKEN@host/…`) is a credential, not part of\n // the address: it must never be printed, sent, or written into a plan. embeddedCredential()\n // recovers it separately so the probe can still offer it for forwarding.\n if (/^https?:\\/\\//.test(url)) return url.replace(/^([a-zA-Z][a-zA-Z0-9+.-]*:\\/\\/)[^/@]*@/, \"$1\");\n return null;\n}\n\n/**\n * The `user:password@` userinfo of an http(s) remote as a git credential, or null when the URL\n * carries none (or only a username, which git would still have to prompt a password for).\n */\nexport function embeddedCredential(url: string): GitCredential | null {\n if (!/^https?:\\/\\//.test(url)) return null;\n try {\n const parsed = new URL(url);\n if (parsed.password === \"\") return null;\n const password = decodeURIComponent(parsed.password);\n const username = parsed.username === \"\" ? \"x-access-token\" : decodeURIComponent(parsed.username);\n return { username, password };\n } catch {\n return null;\n }\n}\n\nexport function remoteHost(url: string): string {\n try {\n return new URL(url).host;\n } catch {\n return url;\n }\n}\n\n/** Resolves where a source-less launch seeds from. Uses `git rev-parse --show-toplevel` when cwd is inside a work tree, else cwd. */\nexport type SeedRootResolution =\n | { ok: true; root: string; subdir: string; git: boolean }\n | { ok: false; reason: string };\n\n/**\n * Compare paths after realpath so a home-directory refusal catches `~` itself (including\n * through symlinks) but not a project nested under it.\n */\nexport function resolveSeedRoot(cwd: string, opts?: { home?: string; git?: GitRunner }): SeedRootResolution {\n const absCwd = path.resolve(cwd);\n if (!pathExists(absCwd)) return { ok: false, reason: `seed root does not exist: ${absCwd}` };\n\n const git = opts?.git ?? makeGitRunner(absCwd);\n const top = git([\"rev-parse\", \"--show-toplevel\"]);\n const fromGit = top.status === 0 && top.stdout.trim() !== \"\";\n const candidate = fromGit ? path.resolve(absCwd, top.stdout.trim()) : absCwd;\n if (!pathExists(candidate)) return { ok: false, reason: `seed root does not exist: ${candidate}` };\n\n const root = realpathOrResolve(candidate);\n const realCwd = realpathOrResolve(absCwd);\n if (root === path.parse(root).root) return { ok: false, reason: \"refusing to seed from /\" };\n\n const home = realpathOrResolve(opts?.home ?? os.homedir());\n if (root === home) return { ok: false, reason: \"refusing to seed from the home directory\" };\n\n return { ok: true, root, subdir: posixSubdir(root, realCwd), git: fromGit };\n}\n\n/** Git-ignored root-relative paths; empty set outside git or on failure. */\nexport function gitIgnoredPaths(root: string, git?: GitRunner): Set<string> {\n const runner = git ?? makeGitRunner(root);\n const listed = runner([\n \"ls-files\",\n \"-z\",\n \"--others\",\n \"--ignored\",\n \"--exclude-standard\",\n \"--directory\",\n ]);\n const paths = new Set<string>();\n if (listed.status !== 0) {\n // Outside a repository there are no ignore rules. Inside one, an empty set would seed\n // exactly what the rules keep out (.env files, keys) into the pod.\n const inside = runner([\"rev-parse\", \"--is-inside-work-tree\"]);\n const repository = inside.status === 0\n ? inside.stdout.trim() === \"true\"\n : fs.existsSync(path.join(root, \".git\")); // git itself failed: assume the rules apply\n if (repository) {\n throw new PiPodError(`could not list the files git ignores in ${root}; nothing was seeded`, {\n hint: \"fix the repository (run `git status` there), or seed explicitly with `pipod send`\",\n });\n }\n return paths;\n }\n for (const raw of listed.stdout.split(\"\\0\")) {\n const relPath = raw.endsWith(\"/\") ? raw.slice(0, -1) : raw;\n if (relPath !== \"\") paths.add(relPath);\n }\n return paths;\n}\n\nexport interface GitCredential { username: string; password: string }\n\n/**\n * A credential that must never be serialized or logged: JSON.stringify omits it, inspect\n * prints `[git credential]`, and the password is registered with the logger's redactor.\n * `use()` hands the raw value to one consumer without exposing a getter.\n */\nexport class SeedCredential {\n readonly username: string;\n readonly #password: string;\n\n constructor(credential: GitCredential) {\n this.username = credential.username;\n this.#password = credential.password;\n registerSecret(credential.password);\n }\n\n use<T>(fn: (credential: GitCredential) => T): T {\n return fn({ username: this.username, password: this.#password });\n }\n\n toJSON(): undefined {\n return undefined;\n }\n\n [inspect.custom](): string {\n return \"[git credential]\";\n }\n}\n\nexport type WorkspaceSeedProbe =\n | { kind: \"archive\"; reason: string; includeGit: boolean }\n | { kind: \"clone\"; url: string; branch: string; commit: string; host: string; access: \"anonymous\" }\n | { kind: \"clone\"; url: string; branch: string; commit: string; host: string; access: \"credential\"; credential: SeedCredential }\n | { kind: \"private\"; url: string; branch: string; commit: string; host: string };\n\nexport interface ProbeWorkspaceSeedOptions {\n root: string;\n git: GitRunner;\n /** \"probe\" reads and verifies host credentials; \"skip\" (dry-run / doctor) never reads them and answers `private`. */\n credentials: \"probe\" | \"skip\";\n /** Optional egress gate from the resolved pod config: false → archive with reason naming the host and `egress.allow`. */\n egressAllows?: (host: string) => boolean;\n /** GitHub CLI fallback; default runs `gh auth token --hostname <host>`. Return null when unavailable. */\n ghAuthToken?: (host: string) => string | null;\n}\n\nexport async function probeWorkspaceSeed(opts: ProbeWorkspaceSeedOptions): Promise<WorkspaceSeedProbe> {\n const { git, root } = opts;\n const archive = (reason: string): WorkspaceSeedProbe => ({\n kind: \"archive\",\n reason,\n includeGit: gitDirIsDirectory(root),\n });\n\n if (git([\"rev-parse\", \"--is-inside-work-tree\"]).status !== 0) return archive(\"not a git repository\");\n\n const origin = git([\"remote\", \"get-url\", \"origin\"]);\n if (origin.status !== 0 || origin.stdout.trim() === \"\") return archive(\"no origin remote\");\n const rawUrl = origin.stdout.trim();\n\n const branchOut = git([\"symbolic-ref\", \"--quiet\", \"--short\", \"HEAD\"]);\n const branch = branchOut.stdout.trim();\n if (branchOut.status !== 0 || branch === \"\") return archive(\"detached HEAD\");\n\n // A status that fails or times out (a huge tree, a locked index) must read as \"unknown\",\n // never as \"clean\": a clone chosen on empty output would silently drop uncommitted work.\n const status = git([\"status\", \"--porcelain\", \"--untracked-files=all\"]);\n if (status.status !== 0) return archive(\"cannot tell whether the working tree is clean\");\n if (status.stdout.trim() !== \"\") {\n return archive(\"uncommitted changes would be lost by a clone\");\n }\n\n const upstream = git([\"rev-parse\", \"--abbrev-ref\", \"@{u}\"]);\n if (upstream.status !== 0) return archive(`${branch} is not pushed`);\n const ahead = git([\"rev-list\", \"@{u}..HEAD\"]);\n if (ahead.status !== 0 || ahead.stdout.trim() !== \"\") return archive(`${branch} has unpushed commits`);\n\n const url = httpsRemote(rawUrl);\n if (url === null) return archive(`origin ${rawUrl} is not a URL the pod can clone`);\n\n const submodules = git([\"submodule\", \"status\"]);\n if (hasInitializedSubmodule(submodules.stdout)) return archive(\"initialized submodules are not cloned\");\n\n const lfs = git([\"ls-files\", \"-z\", \"--\", \":(attr:filter=lfs)\"]);\n if (hasListedPaths(lfs.stdout)) return archive(\"Git LFS objects would not be cloned\");\n\n const host = remoteHost(url);\n if (opts.egressAllows?.(host) === false) {\n return archive(`egress policy does not allow ${host} (add it to egress.allow)`);\n }\n\n const head = git([\"rev-parse\", \"HEAD\"]).stdout.trim();\n if (!FULL_SHA.test(head)) return archive(\"cannot read HEAD\");\n const commit = head;\n\n const anonymous = lsRemote(git, url, branch);\n if (anonymous.status === 0) {\n const remoteSha = shaForBranch(anonymous.stdout, branch);\n if (remoteSha === commit) {\n return { kind: \"clone\", url, branch, commit, host, access: \"anonymous\" };\n }\n return archive(mismatchReason(branch, remoteSha, commit));\n }\n\n if (opts.credentials === \"skip\") {\n return { kind: \"private\", url, branch, commit, host };\n }\n\n const ghAuthToken = opts.ghAuthToken ?? defaultGhAuthToken;\n const resolved = embeddedCredential(rawUrl) ?? readCredential(git, url) ?? tokenFromGh(ghAuthToken, host);\n if (!resolved) return archive(`no git credentials for ${host}`);\n registerSecret(resolved.password);\n\n const authenticated = lsRemote(git, url, branch, {\n [GIT_USER_VAR]: resolved.username,\n [GIT_TOKEN_VAR]: resolved.password,\n });\n if (authenticated.status !== 0) return archive(`git credentials for ${host} do not open ${url}`);\n const authedSha = shaForBranch(authenticated.stdout, branch);\n if (authedSha !== commit) return archive(mismatchReason(branch, authedSha, commit));\n\n return {\n kind: \"clone\",\n url,\n branch,\n commit,\n host,\n access: \"credential\",\n credential: new SeedCredential(resolved),\n };\n}\n\nexport interface PlanWorkspaceSeedOptions extends ProbeWorkspaceSeedOptions {\n subdir: string;\n /** Asked once, only for a verified private-remote credential; never called otherwise. */\n confirmCredentialForwarding: (host: string) => Promise<boolean>;\n}\n\n/**\n * probe + consent. The credential rides beside the plan, never inside it. A `private` probe\n * (`credentials: \"skip\"`) becomes a clone plan with access `\"credential\"` and no credential —\n * the caller knows it is a dry-run prediction.\n */\nexport async function planWorkspaceSeed(\n opts: PlanWorkspaceSeedOptions,\n): Promise<{ plan: WorkspaceSeedPlan; credential?: SeedCredential }> {\n const probed = await probeWorkspaceSeed(opts);\n const { root, subdir } = opts;\n\n if (probed.kind === \"archive\") {\n return { plan: { kind: \"archive\", root, subdir, reason: probed.reason, includeGit: probed.includeGit } };\n }\n\n if (probed.kind === \"private\") {\n return {\n plan: {\n kind: \"clone\",\n root,\n subdir,\n url: probed.url,\n branch: probed.branch,\n commit: probed.commit,\n access: \"credential\",\n host: probed.host,\n },\n };\n }\n\n if (probed.access === \"anonymous\") {\n return {\n plan: {\n kind: \"clone\",\n root,\n subdir,\n url: probed.url,\n branch: probed.branch,\n commit: probed.commit,\n access: \"anonymous\",\n host: probed.host,\n },\n };\n }\n\n if (!(await opts.confirmCredentialForwarding(probed.host))) {\n return {\n plan: {\n kind: \"archive\",\n root,\n subdir,\n reason: \"credential forwarding declined\",\n includeGit: gitDirIsDirectory(root),\n },\n };\n }\n\n return {\n plan: {\n kind: \"clone\",\n root,\n subdir,\n url: probed.url,\n branch: probed.branch,\n commit: probed.commit,\n access: \"credential\",\n host: probed.host,\n },\n credential: probed.credential,\n };\n}\n\nexport function describeWorkspaceSeed(plan: WorkspaceSeedPlan): string {\n switch (plan.kind) {\n case \"none\":\n return plan.reason;\n case \"clone\": {\n const base = `clone ${plan.url} at ${plan.branch} (${plan.commit.slice(0, 12)})`;\n return plan.access === \"credential\" ? `${base} with forwarded ${plan.host} credentials` : base;\n }\n case \"archive\":\n return `archive ${plan.root}${plan.includeGit ? \" with .git history\" : \"\"} (${plan.reason})`;\n case \"copy\":\n return `copy ${plan.root} (${plan.reason})`;\n }\n}\n\nfunction gitDirIsDirectory(root: string): boolean {\n try {\n return fs.lstatSync(path.join(root, \".git\")).isDirectory();\n } catch {\n return false;\n }\n}\n\nfunction pathExists(p: string): boolean {\n try {\n return fs.statSync(p).isDirectory();\n } catch {\n return false;\n }\n}\n\nfunction realpathOrResolve(p: string): string {\n try {\n return fs.realpathSync(p);\n } catch {\n return path.resolve(p);\n }\n}\n\nfunction posixSubdir(root: string, cwd: string): string {\n if (root === cwd) return \"\";\n const rel = path.relative(root, cwd);\n if (rel === \"\" || rel.startsWith(\"..\") || path.isAbsolute(rel)) return \"\";\n return rel.split(path.sep).join(\"/\");\n}\n\nfunction hasInitializedSubmodule(stdout: string): boolean {\n for (const line of stdout.split(\"\\n\")) {\n const row = line.replace(/\\r$/, \"\");\n if (row === \"\") continue;\n const flag = row[0];\n if (flag !== undefined && flag !== \"-\") return true;\n }\n return false;\n}\n\nfunction hasListedPaths(stdout: string): boolean {\n return stdout.split(\"\\0\").some((entry) => entry !== \"\");\n}\n\nfunction lsRemote(\n git: GitRunner,\n url: string,\n branch: string,\n env?: Record<string, string>,\n): GitRun {\n const args = env\n ? [\"-c\", \"credential.helper=\", \"-c\", `credential.helper=${CREDENTIAL_HELPER}`, \"ls-remote\", url, `refs/heads/${branch}`]\n : [\"-c\", \"credential.helper=\", \"ls-remote\", url, `refs/heads/${branch}`];\n return git(args, { ...(env ? { env } : {}), timeoutMs: GIT_NETWORK_TIMEOUT_MS });\n}\n\nfunction shaForBranch(stdout: string, branch: string): string | null {\n const want = `refs/heads/${branch}`;\n for (const line of stdout.split(\"\\n\")) {\n const row = line.replace(/\\r$/, \"\");\n if (row === \"\") continue;\n const tab = row.indexOf(\"\\t\");\n if (tab === -1) continue;\n const sha = row.slice(0, tab).trim();\n const ref = row.slice(tab + 1).trim();\n if (ref === want) return sha;\n }\n return null;\n}\n\nfunction mismatchReason(branch: string, remoteSha: string | null, localSha: string): string {\n const remote = remoteSha && remoteSha.length > 0 ? remoteSha.slice(0, 12) : \"missing\";\n return `remote ${branch} is at ${remote}, not the local ${localSha.slice(0, 12)}`;\n}\n\nfunction credentialKeyForm(url: string): string {\n const parsed = new URL(url);\n const protocol = parsed.protocol.replace(/:$/, \"\");\n const host = parsed.host;\n const repoPath = parsed.pathname.replace(/^\\/+/, \"\");\n return `protocol=${protocol}\\nhost=${host}\\npath=${repoPath}\\n\\n`;\n}\n\nfunction readCredential(git: GitRunner, url: string): GitCredential | null {\n const filled = git([\"credential\", \"fill\"], { stdin: credentialKeyForm(url) });\n if (filled.status !== 0) return null;\n let username = \"\";\n let password = \"\";\n for (const line of filled.stdout.split(\"\\n\")) {\n const row = line.replace(/\\r$/, \"\");\n if (row.startsWith(\"username=\")) username = row.slice(\"username=\".length).trim();\n else if (row.startsWith(\"password=\")) password = row.slice(\"password=\".length).trim();\n }\n if (password === \"\") return null;\n return { username: username === \"\" ? \"x-access-token\" : username, password };\n}\n\nfunction tokenFromGh(ghAuthToken: (host: string) => string | null, host: string): GitCredential | null {\n const token = ghAuthToken(host);\n if (token === null || token.trim() === \"\") return null;\n return { username: \"x-access-token\", password: token.trim() };\n}\n\nfunction defaultGhAuthToken(host: string): string | null {\n const result = spawnSync(\"gh\", [\"auth\", \"token\", \"--hostname\", host], {\n encoding: \"utf8\",\n timeout: GH_AUTH_TIMEOUT_MS,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: {\n ...process.env,\n GIT_TERMINAL_PROMPT: \"0\",\n GIT_ASKPASS: \"true\",\n SSH_ASKPASS: \"true\",\n GIT_SSH_COMMAND: \"ssh -oBatchMode=yes\",\n },\n });\n if (result.error || (result.status ?? 1) !== 0) return null;\n const token = (result.stdout ?? \"\").trim();\n return token === \"\" ? null : token;\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { findConfigPath, PROJECT_ENV_FILE, nonBundleKeysFound, retiredLocalKeysFound, retiredProviderConfigKeysFound, RETIRED_PROVIDER_CONFIG_KEYS, stripNonBundleKeys, validateConfig, type PiPodConfig } from \"../config.js\";\nimport { parseDotenv } from \"../dotenv.js\";\nimport { PiPodError } from \"../errors.js\";\nimport { parseJsonc } from \"../jsonc.js\";\nimport { confirm } from \"../prompt.js\";\nimport { legacyUserEnvWarning, mergeConfigLayers } from \"../userconfig.js\";\nimport { toOutgoingBundleConfig } from \"./bundle-source.js\";\nimport { assertMachineConfigCurrent, currentProjectName } from \"./launch-overlays.js\";\nimport type { AccountClient, ApiTemplate, PiLaunchOverrides, ResolveReport } from \"./api.js\";\nimport { PI_RESOURCE_KEYS, sameResourceList } from \"./launch-resources.js\";\nimport type { AccountLaunchFlags, AccountLaunchPlan } from \"./launch-types.js\";\nimport {\n machineClientConfig,\n readHostConfig,\n resolveLaunchTemplateRef,\n takeClientOnlyKeys,\n} from \"./launch-overlays.js\";\nimport { egressAllowsHost } from \"./launch-seed.js\";\nimport {\n withWorkstationWait,\n workstationDemandOf,\n workstationHeadline,\n workstationHint,\n type WorkstationCycleTracker,\n} from \"./workstation.js\";\nimport {\n makeGitRunner,\n planWorkspaceSeed,\n probeWorkspaceSeed,\n resolveSeedRoot,\n type SeedCredential,\n type WorkspaceSeedPlan,\n} from \"./workspace-seed.js\";\n\nexport interface PlanAccountLaunchOptions {\n /** False after bootstrap is declined: resolve org/user defaults without a request-local preview. */\n bootstrapPreview?: boolean;\n /** Shared with the later launch wait so two stopped cycles count once per invocation. */\n cycles?: WorkstationCycleTracker;\n}\n\n/** Resolve the server-resident chain; local project config is sent only for bootstrap preview. */\nexport async function planAccountLaunch(\n client: AccountClient,\n flags: AccountLaunchFlags,\n cwd = process.cwd(),\n piOverrides?: PiLaunchOverrides,\n options: PlanAccountLaunchOptions = {},\n): Promise<AccountLaunchPlan> {\n const configPath = findConfigPath(cwd, { home: flags.home });\n const projectRoot = configPath === null ? null : path.dirname(path.dirname(configPath));\n // No `.pi-pod/config.json` above cwd: nothing configured describes this directory, so the\n // launch seeds the pod from the directory itself (clone when exact, archive otherwise).\n const isSourceLessLaunch = configPath === null;\n const projectRawFull = configPath\n ? (parseJsonc(fs.readFileSync(configPath, \"utf8\"), configPath) as Record<string, unknown>)\n : {};\n const retiredLocal = retiredLocalKeysFound(projectRawFull);\n if (retiredLocal.length > 0) {\n throw new PiPodError(\n `${configPath}: retired config key${retiredLocal.length === 1 ? \"\" : \"s\"} ${retiredLocal.map((k) => k.path).join(\", \")}`,\n { hint: retiredLocal.map((k) => k.hint).join(\"; \") },\n );\n }\n const machineRaw = readHostConfig(flags.home);\n assertMachineConfigCurrent(machineRaw, flags.home);\n // Retired provider-selection keys warn-and-ignore on every local layer: old files keep\n // running with a migration warning instead of failing the launch.\n const retiredProviderWarnings = [\n ...retiredProviderConfigKeysFound(projectRawFull).map((key) => `${key}: ${RETIRED_PROVIDER_CONFIG_KEYS[key]!}`),\n ...retiredProviderConfigKeysFound(machineRaw).map((key) => `${key}: ${RETIRED_PROVIDER_CONFIG_KEYS[key]!}`),\n ];\n const projectTaken = takeClientOnlyKeys(projectRawFull);\n const machineTaken = takeClientOnlyKeys(machineRaw);\n const projectConfig = podSourceConfig(projectTaken.config);\n const templateRef = resolveLaunchTemplateRef(flags, {\n project: projectTaken.template,\n machine: machineTaken.template,\n });\n const template = templateRef ? await resolveTemplate(client, templateRef) : undefined;\n const templateId = template?.id;\n const bootstrapPreview = templateId === undefined && projectRoot !== null && options.bootstrapPreview !== false;\n\n const report = await resolveOrFail(client, {\n ...(templateId ? { templateId } : {}),\n ...(bootstrapPreview ? { projectConfig } : {}),\n ...(piOverrides ? { piOverrides } : {}),\n ...(flags.forkFrom ? { forkFrom: flags.forkFrom } : {}),\n checkImage: flags.dryRun === true,\n }, piOverrides, {\n // A dry run and doctor must report a sleeping workstation, not sit in the launch wait.\n wait: flags.dryRun !== true,\n ...(options.cycles ? { cycles: options.cycles } : {}),\n });\n confirmPiOverridesEcho(report, piOverrides);\n\n const clientViewRaw = mergeConfigLayers(stripNonBundleKeys(report.config), machineClientConfig(machineRaw));\n const merged = validateConfig(clientViewRaw as Record<string, unknown>);\n if (merged.errors.length > 0) {\n throw new PiPodError(\n `invalid configuration from server resolve:\\n${merged.errors.map((e, i) => ` ${merged.errorPaths[i]}: ${e}`).join(\"\\n\")}`,\n { hint: \"the server-resolved org/template/user/policy chain is authoritative; machine client preferences apply locally\" },\n );\n }\n const config = {\n ...merged.config,\n template: templateRef ?? null,\n };\n const warnings = [...report.warnings, ...merged.warnings, ...retiredProviderWarnings];\n // Resolve also includes default UI preferences; they are not stored bundle drift,\n // and pushing cannot remove them. The client silently supplies its own preferences.\n // Retired provider keys are the same case: the server strips them from every stored\n // layer before merging, so any that arrive here are server-computed, not pushable drift.\n const droppedServer = nonBundleKeysFound(report.config).filter(\n (key) =>\n key !== \"pi.chords\" &&\n key !== \"pi.sessionNaming\" &&\n !Object.hasOwn(RETIRED_PROVIDER_CONFIG_KEYS, key),\n );\n if (droppedServer.length > 0) {\n warnings.push(\n `the server bundle still carries non-bundle keys (${droppedServer.join(\", \")}) — they are ignored; run \\`pipod push\\` to clear them`,\n );\n }\n const legacyEnv = legacyUserEnvWarning(flags.home);\n if (legacyEnv) warnings.push(legacyEnv);\n\n if (projectRoot !== null) {\n const envPath = path.join(projectRoot, PROJECT_ENV_FILE);\n if (fs.existsSync(envPath)) {\n const count = parseDotenv(fs.readFileSync(envPath, \"utf8\")).entries.length;\n if (count > 0) {\n warnings.push(\n `.pi-pod/env contains ${count} entr${count === 1 ? \"y\" : \"ies\"}; launch-time project env is retired — ` +\n \"apply values through template/user secrets custody with `pipod push --with-secrets` or `pipod secrets set`\",\n );\n }\n }\n if (!bootstrapPreview && templateId === undefined && Object.keys(projectConfig).length > 0) {\n warnings.push(\n \"project pod settings apply only through a template now — run `pipod push` or approve the launch bootstrap prompt\",\n );\n }\n }\n\n // Workspace seeding is transport, not a settings layer. It is performed after provisioning,\n // so none of its generated material enters resolve or launch bodies.\n let workspaceSeed: WorkspaceSeedPlan | undefined;\n let workspaceSeedCredential: SeedCredential | undefined;\n let seedRoot: string | null = null;\n if (isSourceLessLaunch) {\n const planned = await planSourceLessSeed(cwd, flags, config.egress);\n workspaceSeed = planned.plan;\n workspaceSeedCredential = planned.credential;\n seedRoot = planned.plan.kind === \"none\" ? null : planned.plan.root;\n } else if (templateId === undefined && projectRoot !== null && !flags.forkFrom) {\n // A configured project keeps its established transport: the tree is copied over\n // `/pods/:id/files` after provisioning. The git probe only explains the copy; it never\n // reads credentials, because nothing here would forward them.\n workspaceSeed = await planConfiguredProjectSeed(projectRoot);\n seedRoot = projectRoot;\n }\n\n const projectName = currentProjectName(cwd, flags.home) ?? undefined;\n return {\n ...(projectName ? { projectName } : {}),\n ...(templateId ? { templateId, templateScope: template?.scope ?? \"org\" } : {}),\n bootstrapPreview,\n config,\n projectRoot,\n warnings,\n resolve: report,\n ...(workspaceSeed ? { workspaceSeed } : {}),\n ...(workspaceSeedCredential ? { workspaceSeedCredential } : {}),\n seedRoot,\n };\n}\n\n/**\n * Decide how a directory with no `.pi-pod/config.json` reaches the pod. Forks, co-location and\n * `--no-seed` opt out before any probe runs; a dry run probes locally and anonymously but never\n * reads or forwards credentials, so `--dry-run` can be scripted without a prompt.\n */\nasync function planSourceLessSeed(\n cwd: string,\n flags: AccountLaunchFlags,\n egress: PiPodConfig[\"egress\"],\n): Promise<{ plan: WorkspaceSeedPlan; credential?: SeedCredential }> {\n if (flags.seed === false) return { plan: { kind: \"none\", reason: \"--no-seed\" } };\n if (flags.forkFrom) return { plan: { kind: \"none\", reason: \"fork copies the conversation, not the workspace\" } };\n if (flags.on) return { plan: { kind: \"none\", reason: \"a co-located pod shares its host's workdir\" } };\n const root = resolveSeedRoot(cwd, { home: flags.home });\n if (!root.ok) return { plan: { kind: \"none\", reason: root.reason } };\n return planWorkspaceSeed({\n root: root.root,\n subdir: root.subdir,\n git: makeGitRunner(root.root),\n credentials: flags.dryRun ? \"skip\" : \"probe\",\n egressAllows: (host) => egressAllowsHost(egress, host),\n confirmCredentialForwarding: (host) =>\n confirm(\n `forward your git credentials for ${host} so the pod can clone this private repository? ` +\n \"(they are used for one clone and never stored; declining sends an archive instead)\",\n { nonInteractiveDefault: false, assumeYes: flags.yes },\n ),\n });\n}\n\n/** The legacy `/files` copy every configured project without an init script has always received. */\nasync function planConfiguredProjectSeed(projectRoot: string): Promise<WorkspaceSeedPlan> {\n const probe = await probeWorkspaceSeed({ root: projectRoot, git: makeGitRunner(projectRoot), credentials: \"skip\" });\n const reason = probe.kind === \"archive\" ? probe.reason : `cloneable from ${probe.url} at ${probe.branch}`;\n return { kind: \"copy\", root: projectRoot, reason };\n}\n\n/** Strip client metadata from the one request that may preview project pod settings. */\nfunction podSourceConfig(raw: Record<string, unknown>): Record<string, unknown> {\n return toOutgoingBundleConfig(raw);\n}\n\n/** Resolve on the server and fail closed when it is unavailable or incompatible. */\nasync function resolveOrFail(\n client: AccountClient,\n body: Parameters<AccountClient[\"resolve\"]>[0],\n piOverrides?: PiLaunchOverrides,\n wait: { wait: boolean; cycles?: WorkstationCycleTracker } = { wait: true },\n): Promise<ResolveReport> {\n let resolved: ResolveReport | null;\n try {\n // Preflight is the FIRST thing a cold launch does, so on the SaaS edition it is also the\n // first call to meet a sleeping personal workstation: resolving a launch has to place it,\n // and placing it starts it. A real launch waits here. A dry run only reports the demand.\n // Resolve creates no pod row, so retrying it does not create a second pod.\n const attempt = () => client.resolve(body);\n if (!wait.wait) {\n try {\n resolved = await attempt();\n } catch (error) {\n const demand = workstationDemandOf(error);\n if (demand) {\n throw new PiPodError(workstationHeadline(demand), {\n hint: workstationHint(demand),\n status: 503,\n code: demand.reason,\n cause: error,\n });\n }\n throw error;\n }\n } else {\n resolved = await withWorkstationWait(client, attempt, {\n ...(wait.cycles ? { cycles: wait.cycles } : {}),\n });\n }\n } catch (error) {\n if (error instanceof PiPodError && error.status === 400) {\n if (\n piOverrides &&\n /(?:unrecognized|unknown)[^\\n]*piOverrides|piOverrides[^\\n]*(?:unrecognized|unknown)/i.test(error.message)\n ) {\n throw new PiPodError(\"the account server does not support per-launch Pi overrides\", {\n hint: \"deploy the matching pi pod server before setting --model, --thinking, --extension, --skill, or --prompt-template per launch\",\n cause: error,\n });\n }\n if (body.forkFrom && /(?:unrecognized|unknown|unexpected)[^\\n]*forkFrom|forkFrom[^\\n]*(?:unrecognized|unknown|unexpected)/i.test(error.message)) {\n throw new PiPodError(\"the account server does not support forking a session into a new pod\", {\n hint: \"deploy the matching pi pod server before using `pipod fork`\",\n cause: error,\n });\n }\n // Production scrubs schema errors to this generic message, including old\n // servers rejecting the new nested keys. Keep the refusal, not an invented\n // diagnosis, but give resource callers an actionable compatibility hint.\n if (piOverrides && PI_RESOURCE_KEYS.some((key) => (piOverrides[key]?.length ?? 0) > 0) && /validation failed/i.test(error.message)) {\n throw new PiPodError(error.message, {\n status: error.status,\n hint: \"check the launch settings and pod-local paths; resource selection requires a server supporting per-launch --extension, --skill and --prompt-template — upgrade an older server\",\n cause: error,\n });\n }\n }\n throw error;\n }\n if (!resolved) {\n throw new PiPodError(\"the account server is too old for CLI launches\", {\n hint: \"deploy the matching pi pod server before launching\",\n });\n }\n return resolved;\n}\n\n/**\n * Fail closed when the server did not echo the requested overrides back. A server that\n * predates a field answers without it — launching anyway would bill a pod whose Pi boots\n * without the requested model or resources, which reads as success until the first prompt.\n * Empty resource arrays are an additive no-op and need no echo; every requested entry must\n * come back exactly, order included.\n */\nfunction confirmPiOverridesEcho(resolved: ResolveReport, piOverrides?: PiLaunchOverrides): void {\n if (!piOverrides) return;\n const echoed = resolved.piOverrides;\n const confirmed =\n echoed !== null &&\n echoed !== undefined &&\n echoed.model === piOverrides.model &&\n echoed.thinking === piOverrides.thinking &&\n PI_RESOURCE_KEYS.every(\n (key) => (piOverrides[key] ?? []).length === 0 || sameResourceList(piOverrides[key], echoed[key]),\n );\n if (!confirmed) {\n throw new PiPodError(\"the account server did not confirm the per-launch Pi overrides\", {\n hint: \"deploy the matching pi pod server before setting --model, --thinking, --extension, --skill, or --prompt-template per launch\",\n });\n }\n}\n\n/** Resolve a visible template by id or name; personal templates shadow org names. */\nexport async function resolveTemplate(client: AccountClient, ref: string): Promise<ApiTemplate> {\n const { templates } = await client.listTemplates();\n const byId = templates.find((template) => template.id === ref);\n const named = templates\n .filter((template) => template.name.toLowerCase() === ref.toLowerCase())\n .sort((a, b) => (a.scope === \"user\" ? 0 : 1) - (b.scope === \"user\" ? 0 : 1));\n const found = byId ?? named[0];\n if (!found) {\n const names = templates.map((template) => template.name);\n throw new PiPodError(`template not found: ${ref}`, {\n hint: names.length > 0 ? `templates: ${names.join(\", \")}` : \"this organization has no templates\",\n });\n }\n return found;\n}\n\nexport async function resolveTemplateId(client: AccountClient, ref: string): Promise<string> {\n return (await resolveTemplate(client, ref)).id;\n}\n","/**\n * src/prompt.ts — interactive confirmations.\n *\n * Every prompt has a non-interactive answer baked in, because the launcher must behave\n * predictably in CI: warnings that require confirmation abort when there is no TTY (§7.1),\n * while warnings that are purely informational proceed (§9).\n */\nimport * as readline from \"node:readline/promises\";\nimport { Writable } from \"node:stream\";\nimport { color, warn } from \"./log.js\";\n\nexport function isInteractive(): boolean {\n return process.stdin.isTTY === true && process.stderr.isTTY === true;\n}\n\n/**\n * Reads a secret without echoing it. Terminals show what you type by default, and a\n * credential typed at a prompt would otherwise sit in the scrollback of a shared screen.\n */\nexport async function promptSecret(question: string, signal?: AbortSignal): Promise<string> {\n // The prompt is written directly and the interface is given an output stream that throws\n // every byte away, so line editing still works while nothing is echoed. Muting through\n // readline's internals instead would depend on `_writeToOutput`, which the promises API\n // does not have.\n process.stderr.write(question);\n const discard = new Writable({\n write(_chunk, _encoding, callback) {\n callback();\n },\n });\n const rl = readline.createInterface({ input: process.stdin, output: discard, terminal: true });\n try {\n const closed = new Promise<null>((resolve) => rl.once(\"close\", () => resolve(null)));\n const question = signal ? rl.question(\"\", { signal }) : rl.question(\"\");\n const answer = await Promise.race([question, closed]);\n return typeof answer === \"string\" ? answer.trim() : \"\";\n } catch {\n return \"\";\n } finally {\n rl.close();\n process.stderr.write(\"\\n\");\n }\n}\n\nexport interface ConfirmOptions {\n /** Answer used when there is no TTY. */\n nonInteractiveDefault: boolean;\n /** Skip the prompt entirely and return this. */\n assumeYes?: boolean;\n}\n\nexport async function confirm(question: string, opts: ConfirmOptions): Promise<boolean> {\n if (opts.assumeYes) return true;\n if (!isInteractive()) {\n // Declining unseen would make the command fail without a word about why.\n if (!opts.nonInteractiveDefault) {\n warn(`${question} — no: there is no terminal to answer${\"assumeYes\" in opts ? \" (pass --yes to answer yes)\" : \"\"}`);\n }\n return opts.nonInteractiveDefault;\n }\n\n const rl = readline.createInterface({ input: process.stdin, output: process.stderr });\n try {\n // Two ways the answer never arrives, and they surface differently. A Ctrl-D keystroke is\n // an EOT byte that readline rejects the pending question over; stdin closing outright\n // just ends the interface, leaving that promise to sit unsettled forever. Racing the\n // close event covers the second — awaiting the question alone hangs the launcher.\n const closed = new Promise<null>((resolve) => rl.once(\"close\", () => resolve(null)));\n const answer = await Promise.race([rl.question(`${color.yellow(\"?\")} ${question} [y/N] `), closed]);\n if (answer === null) {\n process.stderr.write(\"\\n\");\n return false;\n }\n return /^y(es)?$/i.test(answer.trim());\n } catch {\n // Ctrl-D at the prompt closes stdin, which rejects the pending question. That is a\n // declined answer, not a crash — without this the launcher dies on an AbortError and\n // prints a Node stack trace over the very warning it was asking about.\n //\n // Deliberately `false` rather than `nonInteractiveDefault`: the two differ for the\n // teardown prompt, whose non-interactive default is to delete so CI reaps its pods.\n // A human who just read \"modified file(s) will be destroyed\" and hit Ctrl-D is answering\n // the `[y/N]` they were shown, and N is the side that keeps their work.\n process.stderr.write(\"\\n\");\n return false;\n } finally {\n rl.close();\n }\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { CONFIG_DIR, findConfigPath, PROJECT_BAKE_SCRIPT, PROJECT_ENV_FILE, PROJECT_INIT_SCRIPT, nonBundleKeysFound, stripNonBundleKeys, validateConfig } from \"../config.js\";\nimport { parseDotenv } from \"../dotenv.js\";\nimport { PiPodError } from \"../errors.js\";\nimport { HOST_PI_AGENT_SUBPATH, filterSettings, hostHome, sanitizeModelsForTransport } from \"../hostconfig.js\";\nimport { parseJsonc } from \"../jsonc.js\";\nimport { isProviderCredentialVar } from \"../providers/registry.js\";\nimport { mergeSecretResolver, resolveSecretRefs, type SecretResolverConfig } from \"../secret-refs.js\";\nimport { mergeConfigLayers, userConfigPath } from \"../userconfig.js\";\nimport type { ApiSettingsBundle, ApiTemplate, PiSettingsFilesBody } from \"./api.js\";\nimport {\n readHostConfig,\n readSecretResolverLayers,\n takeClientOnlyKeys,\n} from \"./launch-overlays.js\";\n\nexport type BundleSourceKind = \"project\" | \"user-dir\" | \"org-dir\";\nexport type EnvSnapshot = Record<string, { value: string; source: string }>;\n\n/** Where each source kind keeps its Pi files, relative to the source root. */\nconst PI_SUBPATH: Record<BundleSourceKind, string> = {\n // Project scope is `<repo>/.pi/` (Pi's project tree). User-directory scope is\n // `~/.pi/agent/` (Pi's global tree). `$HOME/.pi/settings.json` is not a path Pi reads.\n project: \".pi\",\n \"user-dir\": HOST_PI_AGENT_SUBPATH,\n \"org-dir\": \"pi\",\n};\n\nexport const ORG_SOURCE_SUBDIR = path.join(\".pi-pod\", \"org\");\n\nexport interface CompiledBundleSource {\n kind: BundleSourceKind;\n config: Record<string, unknown>;\n initScript: string;\n bakeScript: string;\n piFiles: PiSettingsFilesBody;\n env: EnvSnapshot;\n warnings: string[];\n name: string;\n templateRef: string | null;\n projectRoot: string | null;\n /** The directory the source files were read from: project root, home, or the org dir. */\n root: string;\n configPath: string;\n}\n\nfunction parseConfig(file: string): Record<string, unknown> {\n if (!fs.existsSync(file)) return {};\n const parsed = parseJsonc(fs.readFileSync(file, \"utf8\"), file);\n if (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new PiPodError(`${file} is not a JSON object`);\n }\n return parsed as Record<string, unknown>;\n}\n\n/** `~/.pi-pod/org/` unless the caller keeps the org source elsewhere (say, in a repo). */\nexport function orgSourceDir(args: { dir?: string | undefined; home?: string | undefined }): string {\n if (args.dir) return path.resolve(args.dir);\n const home = hostHome(args.home);\n if (!home) throw new PiPodError(\"cannot locate ~/.pi-pod/org: HOME is unset\", { hint: \"pass --dir <path>\" });\n return path.join(home, ORG_SOURCE_SUBDIR);\n}\n\nfunction safePiDir(root: string, subpath: string): string | null {\n const directory = path.join(root, subpath);\n let stat: fs.Stats;\n try {\n stat = fs.lstatSync(directory);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return null;\n throw error;\n }\n if (stat.isSymbolicLink() || !stat.isDirectory()) {\n throw new PiPodError(`${directory} must be a real directory, not a symlink`);\n }\n return directory;\n}\n\nfunction safePiFile(\n root: string,\n subpath: string,\n name: \"settings.json\" | \"models.json\" | \"mcporter.json\" | \"subagents.json\",\n): string | null {\n const directory = safePiDir(root, subpath);\n if (!directory) return null;\n const file = path.join(directory, name);\n let stat: fs.Stats;\n try {\n stat = fs.lstatSync(file);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return null;\n throw error;\n }\n if (stat.isSymbolicLink() || !stat.isFile()) throw new PiPodError(`${file} must be a regular file, not a symlink`);\n const realRoot = fs.realpathSync(root);\n const relative = path.relative(realRoot, fs.realpathSync(file));\n if (relative === \"..\" || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {\n throw new PiPodError(`${file} resolves outside the source directory`);\n }\n return file;\n}\n\n/** Read regular UTF-8 agent files without following symlinks. */\nfunction readPiAgentsDirectory(\n directory: string,\n label: string,\n): { files: Record<string, string>; warnings: string[] } | undefined {\n let root: fs.Stats;\n try {\n root = fs.lstatSync(directory);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw error;\n }\n if (root.isSymbolicLink() || !root.isDirectory()) {\n throw new PiPodError(`${directory} must be a real directory, not a symlink`);\n }\n const files: Record<string, string> = {};\n const warnings: string[] = [];\n const decoder = new TextDecoder(\"utf-8\", { fatal: true });\n const walk = (current: string): void => {\n for (const entry of fs.readdirSync(current, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {\n const file = path.join(current, entry.name);\n const relative = path.relative(directory, file).split(path.sep).join(\"/\");\n const stat = fs.lstatSync(file);\n if (stat.isSymbolicLink()) warnings.push(`${label} agents/${relative} is a symlink — skipped`);\n else if (stat.isDirectory()) walk(file);\n else if (stat.isFile()) {\n try {\n files[relative] = decoder.decode(fs.readFileSync(file));\n } catch {\n throw new PiPodError(`${file} must contain valid UTF-8 text`);\n }\n } else warnings.push(`${label} agents/${relative} is not a regular file — skipped`);\n }\n };\n walk(directory);\n return { files, warnings };\n}\n\n/**\n * The single deep boundary for every outgoing server-bundle config: client-only\n * metadata (template pin, secretResolver, $schema, chords/sessionNaming) and every\n * key the bundle-write contract rejects never reach the server.\n */\nexport function toOutgoingBundleConfig(raw: Record<string, unknown>): Record<string, unknown> {\n const taken = takeClientOnlyKeys(raw);\n return stripNonBundleKeys({ ...taken.config });\n}\n\n/** The persistent server bundle never receives launcher UI/preferences metadata. */\nfunction podConfigOnly(raw: Record<string, unknown>): ReturnType<typeof takeClientOnlyKeys> {\n const taken = takeClientOnlyKeys(raw);\n return { ...taken, config: toOutgoingBundleConfig(raw) };\n}\n\nfunction checkedConfig(raw: Record<string, unknown>, file: string) {\n const report = validateConfig(raw);\n if (report.errors.length > 0) {\n throw new PiPodError(`${file}: ${report.errors.join(\"; \")}`);\n }\n return report;\n}\n\nfunction readScript(root: string, relative: string): string {\n const file = path.resolve(root, relative);\n return fs.existsSync(file) ? fs.readFileSync(file, \"utf8\") : \"\";\n}\n\n/**\n * A dotenv file as push/diff input. `names` keeps values empty: a diff only compares secret\n * names, so it never resolves `op://` references or otherwise needs the values.\n */\nasync function readEnvSnapshot(\n envPath: string,\n mode: true | \"names\",\n resolver: SecretResolverConfig | null,\n home: string | undefined,\n): Promise<EnvSnapshot> {\n const env: EnvSnapshot = {};\n if (!fs.existsSync(envPath)) return env;\n const parsed = parseDotenv(fs.readFileSync(envPath, \"utf8\"));\n if (mode === \"names\") {\n for (const name of Object.keys(parsed.values)) env[name] = { value: \"\", source: envPath };\n return env;\n }\n const values = await resolveSecretRefs(parsed.values, resolver, { home });\n for (const [name, value] of Object.entries(values)) env[name] = { value, source: envPath };\n return env;\n}\n\n/** Compile one local source layer verbatim; no org/user/template defaults are merged in. */\nexport async function compileBundleSource(args: {\n source: BundleSourceKind;\n cwd?: string;\n home?: string;\n /** `false` skips env files entirely; `\"names\"` reads keys without resolving values. */\n includeEnv?: boolean | \"names\";\n /** org-dir only: where the org source lives instead of ~/.pi-pod/org. */\n dir?: string;\n}): Promise<CompiledBundleSource> {\n const cwd = args.cwd ?? process.cwd();\n const envMode = args.includeEnv === false ? false : args.includeEnv === \"names\" ? \"names\" : true;\n if (args.source === \"project\") {\n const configPath = findConfigPath(cwd, { home: args.home });\n if (!configPath) {\n throw new PiPodError(\"no project .pi-pod/config.json found\", {\n hint: \"run `pipod init`, or name the `user` or `org` layer to work outside a project\",\n });\n }\n const root = path.dirname(path.dirname(configPath));\n const raw = parseConfig(configPath);\n const taken = podConfigOnly(raw);\n const report = checkedConfig(raw, configPath);\n const localPi = readPiFiles(root, report.config, \"project\");\n let env: EnvSnapshot = {};\n if (envMode) {\n const resolvers = readSecretResolverLayers({ cwd: root, home: args.home });\n env = await readEnvSnapshot(\n path.join(root, PROJECT_ENV_FILE),\n envMode,\n mergeSecretResolver(resolvers.machine, resolvers.project),\n args.home,\n );\n }\n const rawName = raw[\"name\"];\n return {\n kind: \"project\",\n config: taken.config,\n initScript: readScript(root, PROJECT_INIT_SCRIPT),\n bakeScript: readScript(root, PROJECT_BAKE_SCRIPT),\n piFiles: localPi.files,\n env,\n warnings: [...report.warnings, ...localPi.warnings],\n name: typeof rawName === \"string\" && rawName.trim() ? rawName : path.basename(root),\n templateRef: taken.template,\n projectRoot: root,\n root,\n configPath,\n };\n }\n\n if (args.source === \"org-dir\") {\n const root = orgSourceDir({ dir: args.dir, home: args.home });\n if (!fs.existsSync(root)) {\n throw new PiPodError(`no org source directory at ${root}`, {\n hint: \"run `pipod pull org` to create it from the server bundle, or pass --dir <path>\",\n });\n }\n const configPath = path.join(root, \"config.json\");\n const raw = parseConfig(configPath);\n const taken = podConfigOnly(raw);\n const report = checkedConfig(raw, configPath);\n const localPi = readPiFiles(root, report.config, \"org-dir\");\n let env: EnvSnapshot = {};\n if (envMode) {\n // Machine resolver first, then the org dir's own `secretResolver`, like project env files.\n const machine = takeClientOnlyKeys(readHostConfig(args.home)).secretResolver;\n env = await readEnvSnapshot(\n path.join(root, ORG_ENV_FILE),\n envMode,\n mergeSecretResolver(machine, taken.secretResolver),\n args.home,\n );\n }\n return {\n kind: \"org-dir\",\n config: taken.config,\n initScript: readScript(root, ORG_SCRIPTS.init),\n bakeScript: readScript(root, ORG_SCRIPTS.bake),\n piFiles: localPi.files,\n env,\n warnings: [...report.warnings, ...localPi.warnings],\n name: \"org settings\",\n templateRef: taken.template,\n projectRoot: null,\n root,\n configPath,\n };\n }\n\n const configPath = userConfigPath(args.home);\n if (!configPath) throw new PiPodError(\"cannot locate ~/.pi-pod/config.json: HOME is unset\");\n const raw = readHostConfig(args.home);\n const taken = podConfigOnly(raw);\n const report = checkedConfig(raw, configPath);\n const home = path.dirname(path.dirname(configPath));\n const piFiles = readPiFiles(home, report.config, \"user-dir\");\n return {\n kind: \"user-dir\",\n config: taken.config,\n initScript: \"\",\n bakeScript: \"\",\n piFiles: piFiles.files,\n env: {},\n warnings: [...report.warnings, ...piFiles.warnings],\n name: \"user settings\",\n templateRef: taken.template,\n projectRoot: null,\n root: home,\n configPath,\n };\n}\n\n/** The org source dir is flat: scripts and env sit next to config.json. */\nconst ORG_SCRIPTS = { init: \"init.sh\", bake: \"bake.sh\" } as const;\nconst ORG_ENV_FILE = \"env\";\n\n/** Push-time-only Pi source compilation and sanitization. Launches never call this. */\nfunction readPiFiles(\n root: string,\n config: ReturnType<typeof validateConfig>[\"config\"],\n kind: BundleSourceKind,\n): { files: PiSettingsFilesBody; warnings: string[] } {\n const files: PiSettingsFilesBody = {};\n const warnings: string[] = [];\n const scope = kind === \"user-dir\" ? \"user\" : kind === \"org-dir\" ? \"org\" : \"project\";\n const relative = PI_SUBPATH[kind];\n const settingsPath = safePiFile(root, relative, \"settings.json\");\n if (settingsPath) {\n const filtered = filterSettings(fs.readFileSync(settingsPath, \"utf8\"), settingsPath, {\n packages: config.pi.hostConfig.packages,\n });\n if (Object.keys(filtered.settings).length > 0) files.settings = filtered.settings;\n if (filtered.dropped.length > 0) warnings.push(`local Pi ${scope} settings omitted host-coupled keys: ${filtered.dropped.join(\", \")}`);\n }\n const modelsPath = safePiFile(root, relative, \"models.json\");\n if (modelsPath) {\n const raw = parseConfig(modelsPath);\n const sanitized = sanitizeModelsForTransport(raw);\n if (Object.keys(sanitized.models).length > 0) files.models = sanitized.models;\n if (sanitized.dropped.length > 0) warnings.push(`local Pi models omitted credential values: ${sanitized.dropped.join(\", \")}`);\n }\n for (const [fileName, key] of [[\"mcporter.json\", \"mcporter\"], [\"subagents.json\", \"subagents\"]] as const) {\n const file = safePiFile(root, relative, fileName);\n if (file) files[key] = parseConfig(file);\n }\n const piDir = safePiDir(root, relative);\n const agents = piDir ? readPiAgentsDirectory(path.join(piDir, \"agents\"), `local Pi ${scope}`) : undefined;\n if (agents) {\n files.agents = agents.files;\n warnings.push(...agents.warnings);\n }\n const bytes = Buffer.byteLength(JSON.stringify(files));\n if (bytes > 256 * 1024) throw new PiPodError(`${scope} Pi settings bundle exceeds 262144 bytes`);\n return { files, warnings };\n}\n\n/** Exposed for push-source validation tests; launch planning never calls it. */\nexport function readProjectPiSourceFiles(args: {\n projectRoot: string;\n config: ReturnType<typeof validateConfig>[\"config\"];\n}): { files: PiSettingsFilesBody; warnings: string[] } {\n return readPiFiles(args.projectRoot, args.config, \"project\");\n}\n\n/** Normalize flat P1 template files and legacy {user,project} files for cheap compatibility. */\nexport function flatPiSettings(value: unknown, preferred?: \"user\" | \"project\"): PiSettingsFilesBody {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) return {};\n const raw = value as Record<string, unknown>;\n const flatKeys = [\"settings\", \"models\", \"mcporter\", \"subagents\", \"agents\"];\n if (flatKeys.some((key) => Object.hasOwn(raw, key))) return raw as PiSettingsFilesBody;\n if (preferred) return flatPiSettings(raw[preferred]);\n const user = flatPiSettings(raw[\"user\"]);\n const project = flatPiSettings(raw[\"project\"]);\n const merged = mergeConfigLayers(user, project);\n return (merged && typeof merged === \"object\" && !Array.isArray(merged) ? merged : {}) as PiSettingsFilesBody;\n}\n\nexport interface BundleDiff {\n changed: boolean;\n lines: string[];\n}\n\nfunction stable(value: unknown): string {\n if (Array.isArray(value)) return `[${value.map(stable).join(\",\")}]`;\n if (value !== null && typeof value === \"object\") {\n return `{${Object.keys(value as Record<string, unknown>).sort().map((key) => `${JSON.stringify(key)}:${stable((value as Record<string, unknown>)[key])}`).join(\",\")}}`;\n }\n return JSON.stringify(value) ?? \"undefined\";\n}\n\nfunction configLeaves(value: unknown, prefix = \"\", out = new Map<string, unknown>()): Map<string, unknown> {\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) {\n const entries = Object.entries(value as Record<string, unknown>);\n if (entries.length > 0) for (const [key, child] of entries) configLeaves(child, prefix ? `${prefix}.${key}` : key, out);\n else if (prefix) out.set(prefix, value);\n } else if (prefix) out.set(prefix, value);\n return out;\n}\n\nexport function diffBundle(\n source: Pick<CompiledBundleSource, \"config\" | \"initScript\" | \"bakeScript\" | \"piFiles\" | \"env\">,\n destination: { config: Record<string, unknown>; initScript?: string | null; bakeScript?: string | null; piFiles?: unknown },\n destinationSecretNames: string[] = [],\n): BundleDiff {\n const lines: string[] = [];\n let changed = false;\n const before = configLeaves(stripNonBundleKeys(destination.config ?? {}));\n const after = configLeaves(stripNonBundleKeys(source.config));\n for (const key of [...new Set([...before.keys(), ...after.keys()])].sort()) {\n if (stable(before.get(key)) === stable(after.get(key)) && before.has(key) === after.has(key)) continue;\n changed = true;\n const oldValue = before.has(key) ? stable(before.get(key)) : \"(absent)\";\n const newValue = after.has(key) ? stable(after.get(key)) : \"(absent)\";\n lines.push(`config ${key}: ${oldValue} → ${newValue}`);\n }\n for (const [label, local, remote] of [\n [\"init script\", source.initScript, destination.initScript ?? \"\"],\n [\"bake script\", source.bakeScript, destination.bakeScript ?? \"\"],\n ] as const) {\n if (local === remote) continue;\n lines.push(`${label}: changed`);\n changed = true;\n }\n const currentPi = flatPiSettings(destination.piFiles ?? {});\n for (const key of [\"settings\", \"models\", \"mcporter\", \"subagents\"] as const) {\n if (stable(source.piFiles[key]) === stable(currentPi[key])) continue;\n lines.push(`Pi ${key}.json: changed`);\n changed = true;\n }\n const localAgents = source.piFiles.agents ?? {};\n const remoteAgents = currentPi.agents ?? {};\n const agentPaths = [...new Set([...Object.keys(localAgents), ...Object.keys(remoteAgents)])].sort();\n for (const agentPath of agentPaths) {\n const same = Object.hasOwn(localAgents, agentPath) && Object.hasOwn(remoteAgents, agentPath) &&\n localAgents[agentPath] === remoteAgents[agentPath];\n if (same) continue;\n lines.push(`Pi agents/${agentPath}: changed`);\n changed = true;\n }\n const localNames = Object.keys(source.env).filter((name) => !isProviderCredentialVar(name)).sort();\n const remoteNames = [...destinationSecretNames].sort();\n for (const name of [...new Set([...localNames, ...remoteNames])].sort()) {\n const state = localNames.includes(name) ? (remoteNames.includes(name) ? \"present (value hidden)\" : \"add\") : \"destination only\";\n lines.push(`secret ${name}: ${state}`);\n }\n return { changed, lines };\n}\n\nexport function templateBundle(template: ApiTemplate) {\n return {\n config: template.config ?? {},\n initScript: template.initScript ?? \"\",\n bakeScript: template.bakeScript ?? \"\",\n piFiles: flatPiSettings(template.piSettings ?? {}),\n };\n}\n\nexport function settingsBundle(settings: ApiSettingsBundle) {\n return { ...settings, piFiles: settings.piFiles ?? {} };\n}\n\nexport interface ServerBundle {\n config: Record<string, unknown>;\n initScript: string;\n bakeScript: string;\n piFiles: PiSettingsFilesBody;\n}\n\nexport interface BundleWriteResult {\n /** Paths relative to the layer root. */\n written: string[];\n removed: string[];\n warnings: string[];\n root: string;\n}\n\n/** Keys the launcher owns locally; a pulled config never replaces them. */\nconst CLIENT_ONLY_TOP_KEYS = [\"$schema\", \"template\", \"secretResolver\"] as const;\nconst CLIENT_ONLY_PI_KEYS = [\"chords\", \"sessionNaming\"] as const;\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction pick(source: Record<string, unknown>, keys: readonly string[]): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const key of keys) if (Object.hasOwn(source, key)) out[key] = source[key];\n return out;\n}\n\n/** A pulled config wrapped around the client-only keys the local file already had. */\nfunction mergePulledConfig(existing: Record<string, unknown>, pulled: Record<string, unknown>): Record<string, unknown> {\n const pod = podConfigOnly(pulled).config;\n const top = pick(existing, CLIENT_ONLY_TOP_KEYS);\n const next: Record<string, unknown> = {\n ...(\"$schema\" in top ? { $schema: top[\"$schema\"] } : {}),\n ...pod,\n ...(\"template\" in top ? { template: top[\"template\"] } : {}),\n ...(\"secretResolver\" in top ? { secretResolver: top[\"secretResolver\"] } : {}),\n };\n const clientPi = isPlainObject(existing[\"pi\"]) ? pick(existing[\"pi\"], CLIENT_ONLY_PI_KEYS) : {};\n const pi = { ...(isPlainObject(pod[\"pi\"]) ? pod[\"pi\"] : {}), ...clientPi };\n if (Object.keys(pi).length > 0) next[\"pi\"] = pi;\n return next;\n}\n\n/** Copy credential values the transport dropped back into the pulled models at the same paths. */\nfunction restoreModelCredentials(existing: Record<string, unknown>, pulled: Record<string, unknown>): Record<string, unknown> {\n const result = structuredClone(pulled);\n const at = (target: unknown, parts: string[]): unknown => {\n let cursor = target;\n for (const part of parts) {\n if (cursor === null || typeof cursor !== \"object\") return undefined;\n cursor = (cursor as Record<string, unknown>)[part];\n }\n return cursor;\n };\n for (const dotted of sanitizeModelsForTransport(existing).dropped) {\n const parts = dotted.split(\".\");\n const parent = at(result, parts.slice(0, -1));\n if (parent === null || typeof parent !== \"object\") continue;\n (parent as Record<string, unknown>)[parts.at(-1)!] = at(existing, parts);\n }\n return result;\n}\n\nfunction refuseSymlink(file: string): fs.Stats | null {\n let stat: fs.Stats;\n try {\n stat = fs.lstatSync(file);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return null;\n throw error;\n }\n if (stat.isSymbolicLink()) throw new PiPodError(`${file} is a symlink — pull refuses to write through it`);\n return stat;\n}\n\nclass LayerWriter {\n readonly written: string[] = [];\n readonly removed: string[] = [];\n readonly warnings: string[] = [];\n /**\n * `confined`: every directory between the root and a written file must be a real one. A\n * project root is a checkout, and its author can make any of them a symlink elsewhere.\n */\n constructor(readonly root: string, private readonly confined = false) {}\n\n /** `null` content removes the file. Identical content is left untouched. */\n put(file: string, content: string | null): void {\n if (this.confined) {\n let ancestor = this.root;\n for (const part of path.relative(this.root, path.dirname(file)).split(path.sep).filter(Boolean)) {\n if (part === \"..\") throw new PiPodError(`${file} is outside ${this.root}`);\n ancestor = path.join(ancestor, part);\n const stat = refuseSymlink(ancestor);\n if (stat && !stat.isDirectory()) throw new PiPodError(`${ancestor} must be a directory`);\n }\n }\n const stat = refuseSymlink(file);\n const relative = path.relative(this.root, file);\n if (content === null) {\n if (!stat) return;\n fs.rmSync(file);\n this.removed.push(relative);\n return;\n }\n if (stat && fs.readFileSync(file, \"utf8\") === content) return;\n fs.mkdirSync(path.dirname(file), { recursive: true });\n fs.writeFileSync(file, content);\n this.written.push(relative);\n }\n\n json(file: string, value: Record<string, unknown> | null): void {\n this.put(file, value === null ? null : `${JSON.stringify(value, null, 2)}\\n`);\n }\n\n /** Comments cannot survive a JSON rewrite; say so once per file, only when it is rewritten. */\n noteComments(file: string): void {\n if (!fs.existsSync(file)) return;\n try {\n JSON.parse(fs.readFileSync(file, \"utf8\"));\n } catch {\n this.warnings.push(`${file} had comments; pull rewrites it as plain JSON`);\n }\n }\n}\n\nfunction writePulledAgents(writer: LayerWriter, piDir: string, agents: Record<string, string> | undefined): void {\n const directory = path.join(piDir, \"agents\");\n const keep = new Set<string>();\n refuseSymlink(directory);\n for (const [relative, content] of Object.entries(agents ?? {})) {\n const parts = relative.split(\"/\");\n if (path.isAbsolute(relative) || parts.some((part) => part === \"\" || part === \".\" || part === \"..\")) {\n throw new PiPodError(`server agents/${relative} is not a safe relative path`);\n }\n keep.add(parts.join(path.sep));\n // The server names the subdirectories; one that is a symlink in this checkout would\n // carry the write outside it.\n let ancestor = directory;\n for (const part of parts.slice(0, -1)) {\n ancestor = path.join(ancestor, part);\n const stat = refuseSymlink(ancestor);\n if (stat && !stat.isDirectory()) throw new PiPodError(`${ancestor} must be a directory`);\n }\n writer.put(path.join(directory, ...parts), content);\n }\n const stat = refuseSymlink(directory);\n if (!stat) return;\n if (!stat.isDirectory()) throw new PiPodError(`${directory} must be a directory`);\n const prune = (current: string): void => {\n for (const entry of fs.readdirSync(current, { withFileTypes: true })) {\n const file = path.join(current, entry.name);\n const entryStat = fs.lstatSync(file);\n if (entryStat.isSymbolicLink()) writer.warnings.push(`${file} is a symlink — left alone`);\n else if (entryStat.isDirectory()) {\n prune(file);\n if (fs.readdirSync(file).length === 0) fs.rmdirSync(file);\n } else if (entryStat.isFile() && !keep.has(path.relative(directory, file))) writer.put(file, null);\n }\n };\n prune(directory);\n}\n\n/**\n * Write a server bundle into a layer's local files. Everything the launcher owns locally\n * survives: client-only config keys, host-coupled Pi settings, and model credential values.\n * Secrets are write-only on the server and are never written here.\n */\nexport function writeBundleSource(args: {\n kind: BundleSourceKind;\n bundle: ServerBundle;\n cwd?: string;\n home?: string;\n dir?: string;\n}): BundleWriteResult {\n const { kind, bundle } = args;\n let root: string;\n let configPath: string;\n if (kind === \"project\") {\n const found = findConfigPath(args.cwd ?? process.cwd(), { home: args.home });\n if (!found) throw new PiPodError(\"no project .pi-pod/config.json found\", { hint: \"run `pipod init` first\" });\n configPath = found;\n root = path.dirname(path.dirname(found));\n } else if (kind === \"org-dir\") {\n root = orgSourceDir({ dir: args.dir, home: args.home });\n configPath = path.join(root, \"config.json\");\n } else {\n const userPath = userConfigPath(args.home);\n if (!userPath) throw new PiPodError(\"cannot locate ~/.pi-pod/config.json: HOME is unset\");\n configPath = userPath;\n root = path.dirname(path.dirname(userPath));\n }\n const writer = new LayerWriter(root, kind === \"project\");\n const retired = nonBundleKeysFound(bundle.config);\n if (retired.length > 0) {\n writer.warnings.push(`the server bundle still carries non-bundle keys (${retired.join(\", \")}) — they are dropped, not written`);\n }\n const existingConfig = parseConfig(configPath);\n const nextConfig = mergePulledConfig(existingConfig, bundle.config);\n const report = checkedConfig(nextConfig, `${kind} bundle config`);\n // A JSONC file never matches its JSON rendering byte for byte, so rewriting on any textual\n // difference would flatten a commented file on a pull that changed no pod setting at all.\n const podChanged = stable(podConfigOnly(existingConfig).config) !== stable(podConfigOnly(bundle.config).config);\n if (podChanged || !fs.existsSync(configPath)) {\n writer.noteComments(configPath);\n writer.json(configPath, nextConfig);\n }\n\n if (kind === \"project\") {\n writer.put(path.resolve(root, PROJECT_INIT_SCRIPT), bundle.initScript || null);\n writer.put(path.resolve(root, PROJECT_BAKE_SCRIPT), bundle.bakeScript || null);\n } else if (kind === \"org-dir\") {\n writer.put(path.join(root, ORG_SCRIPTS.init), bundle.initScript || null);\n writer.put(path.join(root, ORG_SCRIPTS.bake), bundle.bakeScript || null);\n } else if (bundle.initScript || bundle.bakeScript) {\n writer.warnings.push(\"the user bundle's scripts have no local file and were not written\");\n }\n\n const piDir = path.join(root, PI_SUBPATH[kind]);\n refuseSymlink(piDir);\n const piFiles = flatPiSettings(bundle.piFiles);\n const settingsPath = path.join(piDir, \"settings.json\");\n const localOnly = refuseSymlink(settingsPath)\n ? (() => {\n const filtered = filterSettings(fs.readFileSync(settingsPath, \"utf8\"), settingsPath, {\n packages: report.config.pi.hostConfig.packages,\n });\n const raw = JSON.parse(fs.readFileSync(settingsPath, \"utf8\")) as Record<string, unknown>;\n return pick(raw, filtered.dropped);\n })()\n : {};\n const nextSettings = { ...localOnly, ...piFiles.settings };\n writer.json(settingsPath, Object.keys(nextSettings).length > 0 ? nextSettings : null);\n\n const modelsPath = path.join(piDir, \"models.json\");\n if (piFiles.models) {\n const existingModels = refuseSymlink(modelsPath) ? parseConfig(modelsPath) : {};\n const nextModels = restoreModelCredentials(existingModels, piFiles.models);\n if (stable(existingModels) !== stable(nextModels)) writer.noteComments(modelsPath);\n writer.json(modelsPath, nextModels);\n } else writer.json(modelsPath, null);\n\n writer.json(path.join(piDir, \"mcporter.json\"), piFiles.mcporter ?? null);\n writer.json(path.join(piDir, \"subagents.json\"), piFiles.subagents ?? null);\n writePulledAgents(writer, piDir, piFiles.agents);\n return { written: writer.written, removed: writer.removed, warnings: writer.warnings, root };\n}\n","/**\n * src/providers/meta.ts — one table used by the registry (credential custody,\n * pre-load error hints) and each adapter (injection env names, keepalive credentialEnvName,\n * dashboard URLs in auth errors). A static registry copy used to drift from adapters'\n * declarations and keeping them in step was a unit test's job — the table is the declaration.\n * SDK-free on purpose (D4).\n */\n\nexport interface ProviderMeta {\n /** Host env var holding this provider's credential (§7.3). */\n credentialEnv: string;\n /** Where a key is created, for the error that fires before any adapter could load. */\n dashboardUrl: string;\n}\n\nexport const PROVIDER_META = {\n sandbox: {\n credentialEnv: \"PI_POD_SANDBOX_TOKEN\",\n dashboardUrl: \"https://github.com/pi-pod/pipod/tree/main/sandbox#readme\",\n },\n} as const satisfies Record<string, ProviderMeta>;\n\nexport type BuiltinProviderName = keyof typeof PROVIDER_META;\n","import { PROVIDER_META } from \"./meta.js\";\n\nexport const PROVIDER_CREDENTIAL_VARS: Record<string, string> = Object.fromEntries(\n Object.entries(PROVIDER_META).map(([name, meta]) => [name, meta.credentialEnv]),\n);\n\n/**\n * Credential names stay reserved after an adapter is retired. Otherwise an old project env\n * can silently turn a former control-plane key into an ordinary secret injected into a pod.\n */\nexport const RETIRED_PROVIDER_CREDENTIAL_VARS = [\"BOAT_API_KEY\", \"E2B_API_KEY\", \"DAYTONA_API_KEY\"] as const;\n\nconst providerCredentialVars = new Set<string>([\n ...Object.values(PROVIDER_CREDENTIAL_VARS),\n ...RETIRED_PROVIDER_CREDENTIAL_VARS,\n]);\n\nexport function isProviderCredentialVar(name: string): boolean {\n return providerCredentialVars.has(name);\n}\n\nexport const DEFAULT_PROVIDER = \"sandbox\";\n\nexport function supportedProviders(): string[] {\n const names = Object.keys(PROVIDER_META);\n return [DEFAULT_PROVIDER, ...names.filter((name) => name !== DEFAULT_PROVIDER).sort()];\n}\n\nexport function isSupportedProvider(name: string): boolean {\n return Object.hasOwn(PROVIDER_META, name);\n}\n","/**\n * src/account/launch-resources.ts — per-launch Pi resources (`piOverrides` arrays).\n *\n * A launch may add Pi resources — extensions, skills, prompt templates — to the pod's\n * configured set for that launch only. The CLI spells them exactly as Pi does after `--`\n * (`-e/--extension PATH`, `--skill PATH`, `--prompt-template PATH`, each repeatable);\n * the request carries bare path lists. The server places their flag/path pairs before\n * the untouched configured `pi.args`, so an existing `--` cannot swallow new options.\n *\n * Every path names a file or directory *inside the pod* as an absolute POSIX path. It is\n * never stat'ed on this machine: the workstation that launches and the pod that boots are\n * different filesystems, so a local readability check would both lie and leak. Validation\n * here is purely lexical — the per-launch API's shape, bounds, and normalization.\n * Existing Pi configuration retains Pi's own path/package semantics; these request fields\n * use absolute paths, allow spaces and arbitrary names, and reject ambiguous spelling.\n */\nimport { PiPodError } from \"../errors.js\";\nimport type { PiLaunchOverrides } from \"./api.js\";\n\n/** Longest single resource path a launch request carries. */\nexport const MAX_RESOURCE_PATH_LENGTH = 4096;\n\n/** Bound per-request resource selection; large stable sets can use existing bundles. */\nexport const MAX_RESOURCES_PER_KIND = 64;\n\nexport type PiResourceKey = \"extensions\" | \"skills\" | \"promptTemplates\";\n\n/** Every resource array the resolve echo must confirm, in canonical order. */\nexport const PI_RESOURCE_KEYS: readonly PiResourceKey[] = [\"extensions\", \"skills\", \"promptTemplates\"];\n\n/** The Pi flag each resource array uses, in canonical (long) spelling. */\nexport const PI_RESOURCE_FLAGS: Record<PiResourceKey, string> = {\n extensions: \"--extension\",\n skills: \"--skill\",\n promptTemplates: \"--prompt-template\",\n};\n\n/** The CLI spellings each resource array is collected from after `--` (`-e` is Pi's own alias). */\nexport const PI_RESOURCE_CLI_FLAGS: Record<PiResourceKey, readonly string[]> = {\n extensions: [\"--extension\", \"-e\"],\n skills: [\"--skill\"],\n promptTemplates: [\"--prompt-template\"],\n};\n\nconst CONTROL = /[\\u0000-\\u001f\\u007f]/;\n\n/**\n * Validate one pod-local resource path lexically. Returns the path unchanged — it is stored\n * and echoed verbatim so the resolve confirmation compares exactly what was requested.\n */\nexport function parseResourcePath(flag: string, value: string): string {\n if (value === \"\") {\n throw new PiPodError(`${flag} requires a path`, {\n hint: \"name a file or directory inside the pod, for example: pipod -- --skill /workspace/skills/review\",\n });\n }\n if (value.length > MAX_RESOURCE_PATH_LENGTH) {\n throw new PiPodError(`${flag} path is longer than ${MAX_RESOURCE_PATH_LENGTH} characters`, {\n hint: \"name the resource by its pod-absolute path, without a redundant prefix\",\n });\n }\n if (!value.startsWith(\"/\")) {\n throw new PiPodError(`${flag} ${JSON.stringify(value)} is not an absolute path`, {\n hint: \"resource paths live on the pod, not this machine — pass the pod-absolute path, for example: pipod -- --skill /workspace/skills/review\",\n });\n }\n if (CONTROL.test(value)) {\n throw new PiPodError(`${flag} path must not contain control characters`, {\n hint: \"pass the pod-absolute path exactly as it appears on the pod\",\n });\n }\n if (value.endsWith(\"/\")) {\n throw new PiPodError(`${flag} ${JSON.stringify(value)} must not end with a slash`, {\n hint: \"drop the trailing slash; files and directories are both accepted as written\",\n });\n }\n const segments = value.split(\"/\");\n const normalized = segments.every((segment, index) =>\n index === 0 ? segment === \"\" : segment !== \"\" && segment !== \".\" && segment !== \"..\",\n );\n if (!normalized) {\n throw new PiPodError(\n `${flag} ${JSON.stringify(value)} must be normalized: no empty, \".\" or \"..\" segments`,\n { hint: \"pass the absolute path exactly as it appears on the pod\" },\n );\n }\n return value;\n}\n\n/** True when two requested/echoed resource arrays agree exactly, order included. */\nexport function sameResourceList(requested: string[] | undefined, echoed: string[] | undefined): boolean {\n const want = requested ?? [];\n const got = echoed ?? [];\n return want.length === got.length && want.every((path, index) => got[index] === path);\n}\n\n/**\n * The canonical `--flag path` pairs for `piOverrides`, in `PI_RESOURCE_KEYS` order.\n * Empty arrays contribute nothing: they are an additive no-op, never a clearing.\n */\nexport function resourceArgsFor(overrides: PiLaunchOverrides): string[] {\n const args: string[] = [];\n for (const key of PI_RESOURCE_KEYS) {\n for (const path of overrides[key] ?? []) {\n args.push(PI_RESOURCE_FLAGS[key], path);\n }\n }\n return args;\n}\n","/**\n * src/account/launch-seed.ts — executing a workspace seed plan against a freshly provisioned pod.\n *\n * The plan (see workspace-seed.ts) says *what* faithfully reproduces the launch directory;\n * this module is the state machine that carries it out and degrades gracefully:\n *\n * clone plan → clone succeeds → done\n * → workspace already populated → skip\n * → clone fails / endpoint missing → archive\n * archive plan → tar + stream → done\n * → too large with .git → retry without history\n * → endpoint missing → legacy `/files` copy when small enough\n * → anything else → warn and leave a usable empty pod\n *\n * Nothing here may fail the launch: the pod has already provisioned, and an empty workspace\n * that `pipod send` can fill is strictly better than a billed pod nobody attaches to.\n */\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { randomBytes } from \"node:crypto\";\nimport type { EgressConfig } from \"../config.js\";\nimport { CancelledError, PiPodError } from \"../errors.js\";\nimport { color, debug, info, step, warn } from \"../log.js\";\nimport { SEND_MAX_BYTES, collectSendEntries } from \"../send.js\";\nimport {\n TarballLimitError,\n createTarball,\n seedExclusionRule,\n type CreateTarballOptions,\n type TarballSummary,\n} from \"../tarball.js\";\nimport type { AccountClient, ApiPod, WorkspaceSeedResult } from \"./api.js\";\nimport { displayRef } from \"./ref.js\";\nimport { gitIgnoredPaths, type SeedCredential, type WorkspaceSeedPlan } from \"./workspace-seed.js\";\n\n/** The project env file never travels: its values live in server-custodied secrets now. */\nexport const SEED_ENV_FILE = \".pi-pod/env\";\n\n/** What the seed step did, for the caller's summary line and for tests. */\nexport type SeedOutcome =\n | { kind: \"none\"; reason: string }\n | { kind: \"skipped\"; reason: string }\n | { kind: \"clone\"; commit: string; credentialed: boolean }\n | { kind: \"archive\"; bytes: number; entries: number; includedGit: boolean }\n | { kind: \"copy\"; entries: number }\n | { kind: \"failed\"; reason: string };\n\nexport interface SeedWorkspaceOptions {\n client: AccountClient;\n pod: ApiPod;\n plan: WorkspaceSeedPlan | undefined;\n credential?: SeedCredential | undefined;\n /** A reused pod keeps its warm workspace; seeding would clobber the previous session's work. */\n reused: boolean;\n /** A co-located pod's workdir is its host's — seeding would overwrite the host's files. */\n coLocated: boolean;\n /**\n * The launch armed the server's seed gate, so Pi waits for this seed. A successful clone or\n * archive opens it on the server; every other ending must release it explicitly, or the pod\n * sits idle until the gate times out.\n */\n gated?: boolean;\n /** Ctrl-C: stops tar generation and the upload as soon as they notice. */\n signal?: AbortSignal | undefined;\n /** Test seam: the tar writer; the real one streams to disk. */\n tarball?: (opts: CreateTarballOptions) => Promise<TarballSummary>;\n /** Where the temporary archive lives; defaults to the OS temp directory. */\n tmpDir?: string;\n}\n\n/** Stable failure codes the server uses on the workspace routes; see the plan's §6. */\nconst WORKSPACE_NOT_EMPTY = \"workspace_not_empty\";\n\nexport async function seedWorkspace(opts: SeedWorkspaceOptions): Promise<SeedOutcome> {\n const outcome = await runSeed(opts);\n if (opts.gated && !seededOnServer(outcome)) await releaseSeedGate(opts, outcome);\n return outcome;\n}\n\nasync function runSeed(opts: SeedWorkspaceOptions): Promise<SeedOutcome> {\n const { plan } = opts;\n if (!plan || plan.kind === \"none\") return { kind: \"none\", reason: plan?.reason ?? \"nothing to seed\" };\n if (opts.coLocated) {\n warn(\n \"workspace seed skipped — a co-located pod shares its host's workdir and must not overwrite it; \" +\n \"carry files with an init script or `pipod send` instead\",\n );\n return { kind: \"skipped\", reason: \"co-located pod\" };\n }\n if (opts.reused) {\n info(\"reusing this pod's warm workspace — nothing copied\");\n return { kind: \"skipped\", reason: \"reused pod\" };\n }\n switch (plan.kind) {\n case \"copy\":\n return copyWorkspaceIntoPod(opts, plan.root);\n case \"clone\":\n return cloneIntoPod(opts, plan);\n case \"archive\":\n return archiveIntoPod(opts, plan);\n }\n}\n\n/** The clone and archive routes record `seeded` and open the gate themselves. */\nfunction seededOnServer(outcome: SeedOutcome): boolean {\n return outcome.kind === \"clone\" || outcome.kind === \"archive\";\n}\n\n/**\n * Tell the server Pi may start without a seed. Best-effort: the gate times out on its own,\n * so a failed release costs the user a wait, never the pod.\n */\nasync function releaseSeedGate(opts: SeedWorkspaceOptions, outcome: SeedOutcome): Promise<void> {\n const reason = \"reason\" in outcome ? outcome.reason : outcome.kind;\n try {\n await opts.client.seedWorkspaceSkip(opts.pod.id, reason);\n debug(`released the workspace seed gate (${reason})`);\n } catch (error) {\n if (opts.signal?.aborted) return;\n warn(\n `could not tell the server to start without a seed: ${describeError(error)} — ` +\n \"Pi starts once the seed gate times out on the server\",\n );\n }\n}\n\n/**\n * Whether the pod's egress policy lets it reach a git host. Only `allowlist` mode restricts\n * anything, and only `egress.allow` admits a git host: `builtins` derives model-provider and\n * base-URL endpoints, never the checkout's remote, and the server's clone route checks the\n * same `allow` list with the same wildcard rule (`*.example.com` covers the apex too). A wrong\n * \"yes\" costs one failed clone that falls back to an archive.\n */\nexport function egressAllowsHost(egress: EgressConfig, host: string): boolean {\n if (egress.mode !== \"allowlist\") return true;\n const bare = host.replace(/:\\d+$/, \"\").toLowerCase();\n return egress.allow.some((entry) => {\n const pattern = entry.trim().toLowerCase();\n if (pattern === \"\") return false;\n if (pattern.startsWith(\"*.\")) {\n const base = pattern.slice(2);\n return bare === base || bare.endsWith(`.${base}`);\n }\n return pattern === bare;\n });\n}\n\n// --- clone ---------------------------------------------------------------------------------\n\nasync function cloneIntoPod(\n opts: SeedWorkspaceOptions,\n plan: Extract<WorkspaceSeedPlan, { kind: \"clone\" }>,\n): Promise<SeedOutcome> {\n const ref = displayRef(opts.pod.id, \"pod\");\n const credentialed = plan.access === \"credential\";\n if (credentialed && !opts.credential) {\n // A dry-run prediction reached a real launch: nothing was probed, so nothing is forwarded.\n return archiveIntoPod(opts, {\n kind: \"archive\",\n root: plan.root,\n subdir: plan.subdir,\n reason: `no verified git credentials for ${plan.host}`,\n includeGit: isRealGitDir(plan.root),\n });\n }\n step(\n \"seed\",\n `cloning ${plan.url} at ${plan.branch} (${plan.commit.slice(0, 12)}) → pod ${ref}` +\n (credentialed ? ` with forwarded ${plan.host} credentials` : \"\"),\n );\n const body = {\n url: plan.url,\n branch: plan.branch,\n commit: plan.commit,\n ...(credentialed && opts.credential\n ? { credential: opts.credential.use((c) => ({ username: c.username, password: c.password })) }\n : {}),\n };\n try {\n const result = await opts.client.seedWorkspaceClone(opts.pod.id, body, { signal: opts.signal });\n info(`workspace seeded: cloned ${plan.branch} at ${(result.commit ?? plan.commit).slice(0, 12)}${timing(result)}`);\n return { kind: \"clone\", commit: result.commit ?? plan.commit, credentialed };\n } catch (error) {\n throwIfCancelled(opts, error);\n if (isWorkspaceNotEmpty(error)) {\n info(\"workspace already populated (an init script filled it) — leaving it in place\");\n return { kind: \"skipped\", reason: \"workspace not empty\" };\n }\n const reason = describeError(error);\n if (isMissingRoute(error)) {\n info(\"this server predates workspace cloning — sending an archive instead\");\n } else {\n warn(`clone failed: ${reason} — falling back to an archive of the local tree`);\n }\n return archiveIntoPod(\n opts,\n {\n kind: \"archive\",\n root: plan.root,\n subdir: plan.subdir,\n reason: isMissingRoute(error) ? \"server lacks the clone route\" : `clone failed: ${reason}`,\n includeGit: isRealGitDir(plan.root),\n },\n { legacyServer: isMissingRoute(error) },\n );\n }\n}\n\n// --- archive -------------------------------------------------------------------------------\n\nasync function archiveIntoPod(\n opts: SeedWorkspaceOptions,\n plan: Extract<WorkspaceSeedPlan, { kind: \"archive\" }>,\n flags: { legacyServer?: boolean } = {},\n): Promise<SeedOutcome> {\n if (flags.legacyServer) return copyWorkspaceIntoPod(opts, plan.root);\n const ref = displayRef(opts.pod.id, \"pod\");\n const ignored = gitIgnoredPaths(plan.root);\n const tmpDir = opts.tmpDir ?? os.tmpdir();\n const archivePath = path.join(tmpDir, `pi-pod-seed-${randomBytes(8).toString(\"hex\")}.tar.gz`);\n const write = opts.tarball ?? createTarball;\n try {\n let summary: TarballSummary;\n let includeGit = plan.includeGit;\n step(\"seed\", `archiving ${plan.root}${includeGit ? \" with .git history\" : \"\"} (${plan.reason})`);\n try {\n summary = await write(tarballOptions(opts, plan.root, archivePath, ignored, includeGit));\n } catch (error) {\n throwIfCancelled(opts, error);\n if (!(error instanceof TarballLimitError) || !includeGit) throw error;\n // History is the one optional part of the tree: drop it before giving up on the seed.\n warn(`${error.message} — retrying without .git history`);\n includeGit = false;\n summary = await write(tarballOptions(opts, plan.root, archivePath, ignored, includeGit));\n }\n if (summary.entries === 0) {\n info(\"nothing to seed — the local directory is empty\");\n return { kind: \"none\", reason: \"empty directory\" };\n }\n reportSkipped(summary.skipped.map((entry) => entry.relPath), opts.client.isPodToken);\n step(\n \"seed\",\n `uploading ${formatBytes(summary.compressedBytes)} archive (${summary.entries} entr${summary.entries === 1 ? \"y\" : \"ies\"}, ` +\n `${formatBytes(summary.bytes)} uncompressed) → pod ${ref}`,\n );\n try {\n const result = await opts.client.seedWorkspaceArchive(\n opts.pod.id,\n { filePath: archivePath, bytes: summary.compressedBytes },\n { signal: opts.signal, onProgress: uploadProgress(summary.compressedBytes) },\n );\n info(`workspace seeded from archive${summary.includedGit ? \" with .git history\" : \"\"}${timing(result)}`);\n if (plan.subdir !== \"\") {\n info(color.dim(`launched from ${plan.subdir}/ — the pod's workspace root is the repository root`));\n }\n return { kind: \"archive\", bytes: summary.compressedBytes, entries: summary.entries, includedGit: summary.includedGit };\n } catch (error) {\n throwIfCancelled(opts, error);\n if (isWorkspaceNotEmpty(error)) {\n info(\"workspace already populated (an init script filled it) — leaving it in place\");\n return { kind: \"skipped\", reason: \"workspace not empty\" };\n }\n if (isMissingRoute(error)) {\n if (summary.bytes <= SEND_MAX_BYTES) {\n info(\"this server predates workspace archives — copying files individually instead\");\n return copyWorkspaceIntoPod(opts, plan.root);\n }\n warn(\n `could not seed the workspace: this server predates workspace archives and the tree ` +\n `(${formatBytes(summary.bytes)}) exceeds the ${Math.floor(SEND_MAX_BYTES / (1024 * 1024))} MB send limit — ` +\n \"the pod starts empty; `pipod send <path>` copies in what it needs\",\n );\n return { kind: \"failed\", reason: \"server lacks the archive route and the tree exceeds the send limit\" };\n }\n throw error;\n }\n } catch (error) {\n throwIfCancelled(opts, error);\n const reason = describeError(error);\n warn(`could not seed the workspace: ${reason} — the pod starts empty; \\`pipod send <path>\\` copies in what it needs`);\n return { kind: \"failed\", reason };\n } finally {\n fs.rmSync(archivePath, { force: true });\n }\n}\n\nfunction tarballOptions(\n opts: SeedWorkspaceOptions,\n root: string,\n outputPath: string,\n ignored: ReadonlySet<string>,\n includeGit: boolean,\n): CreateTarballOptions {\n const exclude = seedExclusionRule({ ignored, includeGit });\n let lastReported = 0;\n return {\n root,\n outputPath,\n includeGit,\n skipSymlinks: opts.client.isPodToken,\n exclude: (name, relPath) => relPath === SEED_ENV_FILE || exclude(name, relPath),\n ...(opts.signal ? { signal: opts.signal } : {}),\n onProgress: ({ entries, bytes }) => {\n // Progress belongs in the debug stream at a coarse pace: a launch is a narrative, not a meter.\n if (bytes - lastReported < 64 * 1024 * 1024) return;\n lastReported = bytes;\n debug(`seed archive: ${entries} entries, ${formatBytes(bytes)} so far`);\n },\n };\n}\n\n/** A line at each quarter of an upload big enough to wait for; a small one is done before it helps. */\nfunction uploadProgress(total: number): (sent: number) => void {\n const marks = [0.25, 0.5, 0.75];\n let next = 0;\n return (sent) => {\n if (total < 8 * 1024 * 1024) return;\n let crossed = false;\n while (next < marks.length && sent >= total * marks[next]!) {\n next += 1;\n crossed = true;\n }\n if (crossed) info(color.dim(`upload ${Math.round((sent / total) * 100)}% (${formatBytes(sent)} of ${formatBytes(total)})`));\n };\n}\n\n// --- legacy copy ---------------------------------------------------------------------------\n\n/** Trees that belong to the host machine, never to the pod's copy of the workspace. */\nconst NEVER_SEEDED = new Set([\".git\", \"node_modules\"]);\n\n/**\n * Place the local tree in a fresh pod's workdir one JSON entry at a time. This is the transport\n * configured projects have always used, and the fallback for servers without the archive route.\n * Best-effort by design: an oversized or rejected copy leaves a usable session with an empty\n * workspace, which `pipod send` can still fill.\n */\nasync function copyWorkspaceIntoPod(opts: SeedWorkspaceOptions, projectRoot: string): Promise<SeedOutcome> {\n const { client, pod } = opts;\n try {\n const ignored = gitIgnoredPaths(projectRoot);\n const { entries, skippedSymlinks } = collectSendEntries(projectRoot, {\n relBase: \"\",\n label: projectRoot,\n skipSymlinks: client.isPodToken,\n exclude: (name, relPath) => NEVER_SEEDED.has(name) || relPath === SEED_ENV_FILE || ignored.has(relPath),\n });\n if (entries.length === 0) {\n info(\"nothing to seed — the local directory is empty\");\n return { kind: \"none\", reason: \"empty directory\" };\n }\n step(\"seed\", `copying ${entries.length} entr${entries.length === 1 ? \"y\" : \"ies\"} → pod ${displayRef(pod.id, \"pod\")}`);\n await client.request(`/pods/${pod.id}/files`, { method: \"POST\", body: { entries }, signal: opts.signal });\n reportSkipped(skippedSymlinks, true);\n info(\"workspace seeded\");\n return { kind: \"copy\", entries: entries.length };\n } catch (error) {\n throwIfCancelled(opts, error);\n const reason = describeError(error);\n warn(`could not seed the workspace: ${reason} — the pod starts empty; \\`pipod send <path>\\` copies in what it needs`);\n return { kind: \"failed\", reason };\n }\n}\n\n// --- helpers -------------------------------------------------------------------------------\n\nfunction reportSkipped(paths: string[], podToken: boolean): void {\n if (paths.length === 0) return;\n const shown = paths.slice(0, 5).join(\", \") + (paths.length > 5 ? `, … (${paths.length} total)` : \"\");\n warn(\n podToken\n ? `skipped ${paths.length} symlink(s) this server will not accept from a pod: ${shown}`\n : `skipped ${paths.length} entr${paths.length === 1 ? \"y\" : \"ies\"} that cannot travel (special files or symlinks leaving the tree): ${shown}`,\n );\n}\n\nfunction isRealGitDir(root: string): boolean {\n try {\n return fs.lstatSync(path.join(root, \".git\")).isDirectory();\n } catch {\n return false;\n }\n}\n\nfunction isMissingRoute(error: unknown): boolean {\n return error instanceof PiPodError && error.status === 404;\n}\n\nfunction isWorkspaceNotEmpty(error: unknown): boolean {\n if (!(error instanceof PiPodError) || error.status !== 409) return false;\n return error.code === WORKSPACE_NOT_EMPTY || error.message.includes(WORKSPACE_NOT_EMPTY);\n}\n\nfunction throwIfCancelled(opts: SeedWorkspaceOptions, error: unknown): void {\n if (error instanceof CancelledError) throw error;\n if (opts.signal?.aborted) throw new CancelledError(\"interrupted\");\n}\n\nfunction describeError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction timing(result: WorkspaceSeedResult): string {\n return typeof result.durationMs === \"number\" && result.durationMs >= 100\n ? color.dim(` (${(result.durationMs / 1000).toFixed(1)}s on the server)`)\n : \"\";\n}\n\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KiB`;\n if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MiB`;\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GiB`;\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { EXIT, PiPodError } from \"./errors.js\";\n\nexport const SEND_MAX_BYTES = 24 * 1024 * 1024;\n\nexport function sendLimitError(sourcePath: string): PiPodError {\n return new PiPodError(`${sourcePath} exceeds the ${Math.floor(SEND_MAX_BYTES / (1024 * 1024))} MB send limit`, {\n hint: \"split the tree and send the pieces you need\",\n exitCode: EXIT.USAGE,\n });\n}\n\nexport interface SendEntry {\n relPath: string;\n kind: \"file\" | \"dir\" | \"symlink\";\n contents?: string;\n mode?: number;\n target?: string;\n}\n\nexport interface CollectSendEntriesOptions {\n /** Path every entry is placed under; \"\" lands the tree's contents at the destination root. */\n relBase?: string;\n /** Path named in the size-limit error, when it differs from the resolved source. */\n label?: string;\n /** Called per child with its name and destination-relative path; true drops it and its subtree. */\n exclude?: (name: string, relPath: string) => boolean;\n /** Servers reject symlinks from pod tokens, so those callers collect the rest and report them. */\n skipSymlinks?: boolean;\n}\n\nexport interface WalkEntry {\n relPath: string;\n absPath: string;\n kind: \"file\" | \"dir\" | \"symlink\" | \"other\";\n stat: fs.Stats;\n}\n\nexport interface WalkTreeOptions {\n /** Path every entry is placed under; \"\" lands the tree's contents at the destination root. */\n relBase?: string;\n /** Called per child with its name and destination-relative path; true drops it and its subtree. */\n exclude?: (name: string, relPath: string) => boolean;\n}\n\nfunction entryKind(stat: fs.Stats): WalkEntry[\"kind\"] {\n if (stat.isSymbolicLink()) return \"symlink\";\n if (stat.isDirectory()) return \"dir\";\n if (stat.isFile()) return \"file\";\n return \"other\";\n}\n\n/**\n * Depth-first walk used by `pipod send` and seed tarball creation.\n *\n * Directories are yielded before their children (readdir order). The root directory itself\n * is yielded only when `relBase !== \"\"`, matching collectSendEntries. Symlinks are never\n * followed. An unreadable child is skipped rather than failing the whole walk — missing\n * source at the root still throws, so callers that passed a bad path find out.\n */\nexport function* walkTree(source: string, opts?: WalkTreeOptions): Generator<WalkEntry> {\n const relBase = opts?.relBase ?? path.basename(source);\n const exclude = opts?.exclude;\n\n function* visit(absPath: string, relPath: string, isRoot: boolean): Generator<WalkEntry> {\n let stat: fs.Stats;\n try {\n stat = fs.lstatSync(absPath);\n } catch (error) {\n if (isRoot) throw error;\n return;\n }\n const kind = entryKind(stat);\n if (kind === \"dir\") {\n if (relPath !== \"\") yield { relPath, absPath, kind, stat };\n let names: string[];\n try {\n names = fs.readdirSync(absPath);\n } catch (error) {\n if (isRoot) throw error;\n return;\n }\n for (const name of names) {\n const childRel = relPath === \"\" ? name : path.posix.join(relPath, name);\n if (exclude?.(name, childRel)) continue;\n yield* visit(path.join(absPath, name), childRel, false);\n }\n return;\n }\n yield { relPath, absPath, kind, stat };\n }\n\n yield* visit(source, relBase, true);\n}\n\nexport function collectSendEntries(\n source: string,\n opts: CollectSendEntriesOptions = {},\n): { entries: SendEntry[]; skippedSymlinks: string[] } {\n const relBase = opts.relBase ?? path.basename(source);\n const label = opts.label ?? source;\n const entries: SendEntry[] = [];\n const skippedSymlinks: string[] = [];\n let bytes = 0;\n\n for (const entry of walkTree(source, { relBase, exclude: opts.exclude })) {\n if (entry.kind === \"symlink\") {\n if (opts.skipSymlinks) {\n skippedSymlinks.push(entry.relPath);\n continue;\n }\n entries.push({ relPath: entry.relPath, kind: \"symlink\", target: fs.readlinkSync(entry.absPath) });\n continue;\n }\n if (entry.kind === \"dir\") {\n entries.push({ relPath: entry.relPath, kind: \"dir\" });\n continue;\n }\n if (entry.kind !== \"file\") continue;\n bytes += entry.stat.size;\n if (bytes > SEND_MAX_BYTES) throw sendLimitError(label);\n entries.push({\n relPath: entry.relPath,\n kind: \"file\",\n contents: fs.readFileSync(entry.absPath).toString(\"base64\"),\n mode: entry.stat.mode & 0o777,\n });\n }\n\n return { entries, skippedSymlinks };\n}\n","/**\n * Streaming POSIX ustar+gzip writer used to seed a pod workspace.\n *\n * Hand-rolled so we can stream (never buffer a whole file), enforce compressed /\n * uncompressed / entry caps as bytes come out, rewrite `.git/config` remote URLs,\n * and skip escaping/absolute/special entries without adding a tar dependency.\n *\n * Uncompressed accounting is every 512-byte header (including PAX) plus file\n * content padded to 512-byte blocks, plus the two trailing EOF blocks.\n */\nimport { once } from \"node:events\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { Transform, type TransformCallback } from \"node:stream\";\nimport { finished } from \"node:stream/promises\";\nimport * as zlib from \"node:zlib\";\nimport { CancelledError, PiPodError } from \"./errors.js\";\nimport { walkTree, type WalkEntry } from \"./send.js\";\n\nconst BLOCK = 512;\nconst USTAR_NAME = 100;\nconst USTAR_PREFIX = 155;\nconst USTAR_LINK = 100;\n/** 11 octal digits overflow at 8 GiB; store those sizes in a PAX `size` record. */\nconst USTAR_MAX_SIZE = 0o100000000000;\nconst PROGRESS_BYTES = 8 * 1024 * 1024;\nconst MiB = 1024 * 1024;\n\nexport interface TarballLimits {\n maxCompressedBytes: number;\n maxUncompressedBytes: number;\n maxEntries: number;\n}\n\n/** 256 MiB gzip output, 2 GiB uncompressed headers+padding, 200_000 tar members. */\nexport const DEFAULT_TARBALL_LIMITS: TarballLimits = {\n maxCompressedBytes: 256 * MiB,\n maxUncompressedBytes: 2 * 1024 * MiB,\n maxEntries: 200_000,\n};\n\nexport type TarballSkipReason =\n | \"special-file\"\n | \"absolute-symlink\"\n | \"escaping-symlink\"\n | \"symlink\"\n | \"output-file\"\n | \"unreadable\";\n\nexport interface TarballSkip {\n relPath: string;\n reason: TarballSkipReason;\n}\n\nexport interface CreateTarballOptions {\n /** Directory whose CONTENTS become the archive root (entries are \"src/app.ts\", never \"./x\"). */\n root: string;\n /** Destination .tar.gz path. Created with mode 0o600. Parent dir must exist. */\n outputPath: string;\n /** Called per child with its name and root-relative POSIX path; true drops it and its subtree. */\n exclude?: (name: string, relPath: string) => boolean;\n /**\n * Include the top-level `.git` when it is a REAL directory (a `.git` FILE — linked\n * worktree / submodule — is always skipped). When included, `.git/config` contents\n * are rewritten through sanitizeGitConfig(). Default false.\n */\n includeGit?: boolean;\n /** Skip every symlink (pod-token callers; servers reject symlinks from them). Default false. */\n skipSymlinks?: boolean;\n limits?: Partial<TarballLimits>;\n /** Called periodically (at least every 256 entries or 8 MiB of file bytes) with running totals. */\n onProgress?: (progress: { entries: number; bytes: number }) => void;\n signal?: AbortSignal;\n}\n\nexport interface TarballSummary {\n entries: number;\n bytes: number;\n compressedBytes: number;\n skipped: TarballSkip[];\n includedGit: boolean;\n}\n\nfunction formatMiB(bytes: number): string {\n return `${bytes / MiB} MiB`;\n}\n\nexport class TarballLimitError extends PiPodError {\n readonly limit: \"compressed\" | \"uncompressed\" | \"entries\";\n\n constructor(limit: \"compressed\" | \"uncompressed\" | \"entries\", max: number) {\n super(\n limit === \"entries\"\n ? `archive exceeds the ${max} entry limit`\n : `archive exceeds the ${formatMiB(max)} ${limit} limit`,\n { hint: \"narrow the tree or raise the seed archive cap\" },\n );\n this.name = \"TarballLimitError\";\n this.limit = limit;\n }\n}\n\n/**\n * Strip userinfo (user:token@ or token@) from every `url` / `pushurl` / `proxy` value, and\n * drop `extraheader` lines that carry an Authorization header (the shape `actions/checkout`\n * and CI runners persist a token in). scp-style `git@host:path` has no scheme:// and is\n * left untouched. Everything else is copied byte-identical.\n */\nexport function sanitizeGitConfig(text: string): string {\n return text\n .replace(\n /(^|\\n)([ \\t]*(?:url|pushurl|proxy)[ \\t]*=[ \\t]*)([^\\n]*)/gi,\n (_all, lead: string, prefix: string, value: string) => `${lead}${prefix}${stripUrlUserinfo(value)}`,\n )\n .replace(/^[ \\t]*extraheader[ \\t]*=[ \\t]*(?:\"[ \\t]*)?authorization[ \\t]*:[^\\n]*(?:\\n|$)/gim, \"\");\n}\n\nfunction stripUrlUserinfo(value: string): string {\n return value.replace(/^([a-zA-Z][a-zA-Z0-9+.-]*:\\/\\/)[^/@]+@/, \"$1\");\n}\n\n/**\n * Shared launch-time seed filter: drop `node_modules` at any depth, `.pi-pod/env`\n * at the archive root, git-ignored root-relative paths, and `.git` unless includeGit.\n *\n * `ignored` comes from `git ls-files --others --ignored --directory`, which names each\n * ignored file and the top-most ignored directory. An exact match is enough: the walker\n * never descends into an excluded directory, so nothing below it is ever asked about.\n */\nexport function seedExclusionRule(opts: {\n ignored: ReadonlySet<string>;\n includeGit: boolean;\n}): (name: string, relPath: string) => boolean {\n const ignored = opts.ignored;\n return (name, relPath) => {\n if (name === \"node_modules\") return true;\n if (relPath === \".pi-pod/env\") return true;\n if (!opts.includeGit && name === \".git\") return true;\n return ignored.has(relPath);\n };\n}\n\nexport async function createTarball(opts: CreateTarballOptions): Promise<TarballSummary> {\n if (opts.signal?.aborted) throw cancelled();\n\n const limits: TarballLimits = { ...DEFAULT_TARBALL_LIMITS, ...opts.limits };\n const includeGit = opts.includeGit === true;\n const rootReal = fs.realpathSync(opts.root);\n const outputPath = path.resolve(opts.outputPath);\n const outputReal = realpathForOutput(outputPath);\n const outputInsideRoot = isInsideDir(rootReal, outputReal);\n\n const exclude = (name: string, relPath: string): boolean => {\n if (opts.exclude?.(name, relPath)) return true;\n // Don't descend into `.git` when it will never be emitted.\n if (!includeGit && name === \".git\") return true;\n return false;\n };\n\n let out: fs.WriteStream | undefined;\n let gzip: zlib.Gzip | undefined;\n let limiter: CompressedByteLimit | undefined;\n let success = false;\n const skipped: TarballSkip[] = [];\n\n try {\n out = fs.createWriteStream(outputPath, { flags: \"w\", mode: 0o600 });\n await once(out, \"open\");\n try {\n fs.chmodSync(outputPath, 0o600);\n } catch {\n /* mode is best-effort; umask already applied at create */\n }\n const outStat = fs.statSync(outputPath);\n\n gzip = zlib.createGzip();\n limiter = new CompressedByteLimit(limits.maxCompressedBytes);\n gzip.pipe(limiter).pipe(out);\n\n const sink = new TarGzipSink({ gzip, limiter, out, limits, signal: opts.signal });\n\n if (opts.signal) {\n const abort = (): void => sink.destroy(cancelled());\n if (opts.signal.aborted) abort();\n else opts.signal.addEventListener(\"abort\", abort, { once: true });\n }\n\n let entries = 0;\n let bytes = 0;\n let includedGit = false;\n\n const reportProgress = (): void => {\n if (opts.onProgress) {\n try {\n opts.onProgress({ entries, bytes });\n } catch {\n /* progress is advisory — a throwing callback must not abort the archive */\n }\n }\n sink.throwIfAborted();\n };\n\n const countEntry = (): void => {\n if (entries + 1 > limits.maxEntries) throw new TarballLimitError(\"entries\", limits.maxEntries);\n entries += 1;\n };\n\n for (const entry of walkTree(rootReal, { relBase: \"\", exclude })) {\n sink.throwIfAborted();\n\n if (outputInsideRoot && sameOutputFile(entry, outStat, outputReal)) {\n skipped.push({ relPath: entry.relPath, reason: \"output-file\" });\n continue;\n }\n\n if (skipGitEntry(entry, includeGit)) continue;\n if (entry.relPath === \".git\" && entry.kind === \"dir\") includedGit = true;\n\n if (entry.kind === \"other\") {\n skipped.push({ relPath: entry.relPath, reason: \"special-file\" });\n continue;\n }\n\n if (entry.kind === \"symlink\") {\n if (opts.skipSymlinks) {\n skipped.push({ relPath: entry.relPath, reason: \"symlink\" });\n continue;\n }\n let target: string;\n try {\n target = fs.readlinkSync(entry.absPath);\n } catch {\n skipped.push({ relPath: entry.relPath, reason: \"unreadable\" });\n continue;\n }\n const reason = symlinkSkipReason(entry.relPath, target);\n if (reason) {\n skipped.push({ relPath: entry.relPath, reason });\n continue;\n }\n countEntry();\n await sink.writeSymlink(entry, target);\n reportProgress();\n continue;\n }\n\n if (entry.kind === \"dir\") {\n countEntry();\n await sink.writeDirectory(entry);\n reportProgress();\n continue;\n }\n\n const sanitized = shouldSanitizeGitConfig(entry.relPath);\n if (sanitized) {\n let body: Buffer;\n try {\n body = Buffer.from(sanitizeGitConfig(fs.readFileSync(entry.absPath, \"utf8\")), \"utf8\");\n } catch {\n skipped.push({ relPath: entry.relPath, reason: \"unreadable\" });\n continue;\n }\n countEntry();\n await sink.writeBufferFile(entry, body);\n bytes += body.length;\n reportProgress();\n continue;\n }\n\n let stream: fs.ReadStream | undefined;\n const size = entry.stat.size;\n try {\n if (size > 0) {\n stream = fs.createReadStream(entry.absPath, { start: 0, end: size - 1 });\n await once(stream, \"open\");\n } else {\n fs.accessSync(entry.absPath, fs.constants.R_OK);\n }\n } catch {\n stream?.destroy();\n skipped.push({ relPath: entry.relPath, reason: \"unreadable\" });\n continue;\n }\n\n countEntry();\n await sink.writeFileHeader(entry, size);\n if (stream) {\n let copied = 0;\n await sink.copyFileStream(stream, size, (n) => {\n copied += n;\n if (Math.floor((copied - n) / PROGRESS_BYTES) !== Math.floor(copied / PROGRESS_BYTES)) {\n reportProgress();\n }\n });\n }\n bytes += size;\n reportProgress();\n }\n\n await sink.finish();\n success = true;\n const compressedBytes = fs.statSync(outputPath).size;\n return { entries, bytes, compressedBytes, skipped, includedGit };\n } catch (error) {\n if (opts.signal?.aborted) throw cancelled();\n throw error;\n } finally {\n if (!success) {\n gzip?.destroy();\n limiter?.destroy();\n out?.destroy();\n await Promise.allSettled([\n gzip ? finished(gzip).catch(() => undefined) : Promise.resolve(),\n limiter ? finished(limiter).catch(() => undefined) : Promise.resolve(),\n out ? finished(out).catch(() => undefined) : Promise.resolve(),\n ]);\n try {\n fs.unlinkSync(outputPath);\n } catch {\n /* gone, or never created */\n }\n }\n }\n}\n\nfunction cancelled(): CancelledError {\n return new CancelledError(\"cancelled\");\n}\n\nfunction realpathForOutput(outputPath: string): string {\n try {\n return fs.realpathSync(outputPath);\n } catch {\n return path.join(fs.realpathSync(path.dirname(outputPath)), path.basename(outputPath));\n }\n}\n\nfunction isInsideDir(rootReal: string, fileReal: string): boolean {\n const rel = path.relative(rootReal, fileReal);\n return rel === \"\" || (rel !== \"..\" && !rel.startsWith(`..${path.sep}`) && !path.isAbsolute(rel));\n}\n\nfunction sameOutputFile(entry: WalkEntry, outStat: fs.Stats, outputReal: string): boolean {\n if (entry.kind === \"file\" && entry.stat.dev === outStat.dev && entry.stat.ino === outStat.ino) return true;\n try {\n return entry.kind === \"file\" && fs.realpathSync(entry.absPath) === outputReal;\n } catch {\n return path.resolve(entry.absPath) === outputReal;\n }\n}\n\n/** Only the ROOT `.git` file is always skipped; nested `.git` dirs follow includeGit. */\nfunction skipGitEntry(entry: WalkEntry, includeGit: boolean): boolean {\n const parts = entry.relPath.split(\"/\");\n const idx = parts.indexOf(\".git\");\n if (idx === -1) return false;\n const isGitNode = idx === parts.length - 1;\n if (isGitNode && entry.kind !== \"dir\") return true;\n if (!includeGit) return true;\n return false;\n}\n\nfunction shouldSanitizeGitConfig(relPath: string): boolean {\n return relPath === \".git/config\" || relPath.endsWith(\"/.git/config\");\n}\n\nfunction symlinkSkipReason(relPath: string, target: string): TarballSkipReason | undefined {\n if (path.posix.isAbsolute(target) || path.win32.isAbsolute(target)) return \"absolute-symlink\";\n const dir = path.posix.dirname(relPath);\n const resolved = path.posix.normalize(path.posix.join(dir, target));\n if (resolved === \"..\" || resolved.startsWith(\"../\")) return \"escaping-symlink\";\n return undefined;\n}\n\nclass CompressedByteLimit extends Transform {\n bytes = 0;\n constructor(private readonly maxBytes: number) {\n super();\n }\n override _transform(chunk: Buffer, _encoding: BufferEncoding, callback: TransformCallback): void {\n this.bytes += chunk.length;\n if (this.bytes > this.maxBytes) {\n callback(new TarballLimitError(\"compressed\", this.maxBytes));\n return;\n }\n callback(null, chunk);\n }\n}\n\nclass TarGzipSink {\n private uncompressed = 0;\n private paxSeq = 0;\n private failed: Error | undefined;\n\n constructor(\n private readonly io: {\n gzip: zlib.Gzip;\n limiter: CompressedByteLimit;\n out: fs.WriteStream;\n limits: TarballLimits;\n signal?: AbortSignal;\n },\n ) {\n const fail = (err: Error): void => {\n this.failed = this.failed ?? err;\n if (!io.gzip.destroyed) io.gzip.destroy(err);\n if (!io.limiter.destroyed) io.limiter.destroy();\n if (!io.out.destroyed) io.out.destroy();\n };\n io.gzip.on(\"error\", fail);\n io.limiter.on(\"error\", fail);\n io.out.on(\"error\", fail);\n }\n\n throwIfAborted(): void {\n if (this.io.signal?.aborted) throw cancelled();\n if (this.failed) throw this.failed;\n }\n\n destroy(err: Error): void {\n this.failed = this.failed ?? err;\n this.io.gzip.destroy(err);\n this.io.limiter.destroy();\n this.io.out.destroy();\n }\n\n async writeDirectory(entry: WalkEntry): Promise<void> {\n const name = tarDirName(entry.relPath);\n await this.writeMember({\n name,\n typeflag: \"5\",\n size: 0,\n mode: entry.stat.mode,\n mtime: mtimeSec(entry.stat),\n linkname: \"\",\n });\n }\n\n async writeSymlink(entry: WalkEntry, target: string): Promise<void> {\n await this.writeMember({\n name: entry.relPath,\n typeflag: \"2\",\n size: 0,\n mode: entry.stat.mode,\n mtime: mtimeSec(entry.stat),\n linkname: target,\n });\n }\n\n async writeFileHeader(entry: WalkEntry, size: number): Promise<void> {\n await this.writeMember({\n name: entry.relPath,\n typeflag: \"0\",\n size,\n mode: entry.stat.mode,\n mtime: mtimeSec(entry.stat),\n linkname: \"\",\n });\n }\n\n async writeBufferFile(entry: WalkEntry, body: Buffer): Promise<void> {\n await this.writeMember({\n name: entry.relPath,\n typeflag: \"0\",\n size: body.length,\n mode: entry.stat.mode,\n mtime: mtimeSec(entry.stat),\n linkname: \"\",\n });\n if (body.length > 0) await this.write(body);\n await this.padToBlock(body.length);\n }\n\n async copyFileStream(stream: fs.ReadStream, size: number, onBytes: (n: number) => void): Promise<void> {\n let remaining = size;\n try {\n for await (const chunk of stream) {\n this.throwIfAborted();\n if (remaining <= 0) break;\n const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n const slice = buf.length > remaining ? buf.subarray(0, remaining) : buf;\n await this.write(slice);\n remaining -= slice.length;\n onBytes(slice.length);\n }\n } catch (error) {\n this.rethrowFatal(error);\n if (remaining > 0) {\n await this.write(Buffer.alloc(remaining));\n remaining = 0;\n }\n } finally {\n stream.destroy();\n }\n if (remaining > 0) await this.write(Buffer.alloc(remaining));\n await this.padToBlock(size);\n }\n\n async finish(): Promise<void> {\n try {\n await this.write(Buffer.alloc(BLOCK * 2));\n await new Promise<void>((resolve, reject) => {\n this.io.gzip.end((err?: Error | null) => {\n if (err) reject(err);\n else resolve();\n });\n });\n await finished(this.io.out);\n } catch (error) {\n this.rethrowFatal(error);\n throw error;\n }\n this.throwIfAborted();\n }\n\n private async writeMember(member: {\n name: string;\n typeflag: \"0\" | \"2\" | \"5\";\n size: number;\n mode: number;\n mtime: number;\n linkname: string;\n }): Promise<void> {\n const pax: Record<string, string> = {};\n if (needsPaxPath(member.name)) pax[\"path\"] = member.name;\n if (member.linkname && needsPaxLink(member.linkname)) pax[\"linkpath\"] = member.linkname;\n if (member.size >= USTAR_MAX_SIZE) pax[\"size\"] = String(member.size);\n\n if (Object.keys(pax).length > 0) {\n const body = buildPaxBody(pax);\n this.paxSeq += 1;\n const paxName = `PaxHeader/${this.paxSeq}`;\n await this.write(\n encodeUstarHeader({\n name: paxName,\n prefix: \"\",\n typeflag: \"x\",\n size: body.length,\n mode: 0o644,\n mtime: member.mtime,\n linkname: \"\",\n }),\n );\n await this.write(body);\n await this.padToBlock(body.length);\n }\n\n const split = ustarNameFields(member.name);\n const link = member.linkname.length <= USTAR_LINK ? member.linkname : member.linkname.slice(0, USTAR_LINK);\n const ustarSize = member.size >= USTAR_MAX_SIZE ? 0 : member.size;\n await this.write(\n encodeUstarHeader({\n name: split.name,\n prefix: split.prefix,\n typeflag: member.typeflag,\n size: ustarSize,\n mode: member.mode,\n mtime: member.mtime,\n linkname: link,\n }),\n );\n }\n\n private async padToBlock(size: number): Promise<void> {\n const pad = (BLOCK - (size % BLOCK)) % BLOCK;\n if (pad > 0) await this.write(Buffer.alloc(pad));\n }\n\n private rethrowFatal(error: unknown): void {\n if (this.io.signal?.aborted) throw cancelled();\n if (this.failed) throw this.failed;\n if (error instanceof TarballLimitError || error instanceof CancelledError) throw error;\n }\n\n private async write(data: Buffer): Promise<void> {\n this.throwIfAborted();\n if (data.length === 0) return;\n this.uncompressed += data.length;\n if (this.uncompressed > this.io.limits.maxUncompressedBytes) {\n throw new TarballLimitError(\"uncompressed\", this.io.limits.maxUncompressedBytes);\n }\n await new Promise<void>((resolve, reject) => {\n const gzip = this.io.gzip;\n if (gzip.destroyed || gzip.writableEnded) {\n reject(this.failed ?? new Error(\"tar sink closed\"));\n return;\n }\n const onError = (err: Error): void => reject(this.failed ?? err);\n gzip.once(\"error\", onError);\n try {\n gzip.write(data, (err) => {\n gzip.off(\"error\", onError);\n if (err) reject(this.failed ?? err);\n else if (this.failed) reject(this.failed);\n else resolve();\n });\n } catch (err) {\n gzip.off(\"error\", onError);\n reject(this.failed ?? err);\n }\n });\n this.throwIfAborted();\n }\n}\n\nfunction tarDirName(relPath: string): string {\n return relPath.endsWith(\"/\") ? relPath : `${relPath}/`;\n}\n\nfunction mtimeSec(stat: fs.Stats): number {\n return Math.max(0, Math.floor(stat.mtimeMs / 1000));\n}\n\nfunction isAscii(value: string): boolean {\n for (let i = 0; i < value.length; i++) {\n if ((value.charCodeAt(i) ?? 0) > 127) return false;\n }\n return true;\n}\n\nfunction needsPaxPath(name: string): boolean {\n if (!isAscii(name)) return true;\n return splitUstarPath(name) === undefined;\n}\n\nfunction needsPaxLink(linkname: string): boolean {\n return !isAscii(linkname) || Buffer.byteLength(linkname, \"utf8\") > USTAR_LINK;\n}\n\nfunction splitUstarPath(name: string): { name: string; prefix: string } | undefined {\n if (name.length <= USTAR_NAME) return { name, prefix: \"\" };\n let slash = name.lastIndexOf(\"/\");\n while (slash >= 0) {\n const prefix = name.slice(0, slash);\n const rest = name.slice(slash + 1);\n if (prefix.length <= USTAR_PREFIX && rest.length <= USTAR_NAME && rest.length > 0) {\n return { name: rest, prefix };\n }\n slash = name.lastIndexOf(\"/\", slash - 1);\n }\n return undefined;\n}\n\nfunction ustarNameFields(full: string): { name: string; prefix: string } {\n const split = splitUstarPath(full);\n if (split) return split;\n const ascii = full.replace(/[^\\x20-\\x7E]/g, \"_\");\n const truncated = ascii.length <= USTAR_NAME ? ascii : ascii.slice(ascii.length - USTAR_NAME);\n return { name: truncated || \"entry\", prefix: \"\" };\n}\n\nfunction paxRecord(keyword: string, value: string): Buffer {\n const payload = Buffer.from(`${keyword}=${value}\\n`, \"utf8\");\n let digits = 1;\n for (;;) {\n const total = digits + 1 + payload.length;\n const lenStr = String(total);\n if (lenStr.length === digits) return Buffer.concat([Buffer.from(`${lenStr} `, \"ascii\"), payload]);\n digits = lenStr.length;\n }\n}\n\nfunction buildPaxBody(attrs: Record<string, string>): Buffer {\n const parts: Buffer[] = [];\n for (const [keyword, value] of Object.entries(attrs)) {\n parts.push(paxRecord(keyword, value));\n }\n return Buffer.concat(parts);\n}\n\nfunction writeOctal(buf: Buffer, offset: number, width: number, value: number): void {\n const n = Math.max(0, Math.floor(value));\n const digits = n.toString(8).padStart(width - 1, \"0\");\n if (digits.length > width - 1) {\n buf.fill(0x30, offset, offset + width - 1);\n buf[offset + width - 1] = 0;\n return;\n }\n buf.write(digits, offset, width - 1, \"ascii\");\n buf[offset + width - 1] = 0;\n}\n\nfunction setChecksum(header: Buffer): void {\n header.fill(0x20, 148, 156);\n let sum = 0;\n for (let i = 0; i < BLOCK; i++) sum += header[i] ?? 0;\n const oct = sum.toString(8).padStart(6, \"0\");\n header.write(oct, 148, 6, \"ascii\");\n header[154] = 0;\n header[155] = 0x20;\n}\n\nfunction encodeUstarHeader(opts: {\n name: string;\n prefix: string;\n typeflag: string;\n size: number;\n mode: number;\n mtime: number;\n linkname: string;\n}): Buffer {\n const buf = Buffer.alloc(BLOCK);\n writeStringField(buf, 0, USTAR_NAME, opts.name);\n writeOctal(buf, 100, 8, opts.mode & 0o7777);\n writeOctal(buf, 108, 8, 0);\n writeOctal(buf, 116, 8, 0);\n writeOctal(buf, 124, 12, opts.size);\n writeOctal(buf, 136, 12, opts.mtime);\n buf.write(opts.typeflag, 156, 1, \"ascii\");\n writeStringField(buf, 157, USTAR_LINK, opts.linkname);\n buf.write(\"ustar\\0\", 257, 6, \"latin1\");\n buf.write(\"00\", 263, 2, \"ascii\");\n writeStringField(buf, 345, USTAR_PREFIX, opts.prefix);\n setChecksum(buf);\n return buf;\n}\n\nfunction writeStringField(buf: Buffer, offset: number, width: number, value: string): void {\n if (value.length === 0) return;\n const bytes = Buffer.from(value, \"utf8\");\n bytes.copy(buf, offset, 0, Math.min(width, bytes.length));\n}\n","import { PiPodError } from \"../errors.js\";\n\nconst FULL_UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nconst HEX = /^[0-9a-f]+$/i;\nconst DISPLAY_TAIL_LENGTH = 10;\nconst MIN_REF_LENGTH = 4;\n\n/** A complete UUID names one resource outright, so callers can fetch it instead of listing. */\nexport function isFullUuid(value: string): boolean {\n return FULL_UUID.test(value);\n}\n\n/** Stable, copyable reference derived from the random tail of a pod or job UUID. */\nexport function displayRef(id: string, kind: \"pod\" | \"job\"): string {\n const tail = id.replaceAll(\"-\", \"\").slice(-DISPLAY_TAIL_LENGTH).toLowerCase();\n return `${kind === \"pod\" ? \"p\" : \"j\"}-${tail}`;\n}\n\n/** Match full UUIDs, prefixed tail refs, and legacy bare leading prefixes. */\nexport function matchesRef(id: string, ref: string): boolean {\n const normalizedId = id.toLowerCase();\n const normalizedRef = ref.toLowerCase();\n if (FULL_UUID.test(normalizedRef)) return normalizedId === normalizedRef;\n\n const prefixed = /^[pj]-(.*)$/i.exec(normalizedRef);\n if (prefixed) {\n const tail = prefixed[1]!;\n assertUsableHexRef(ref, tail);\n return normalizedId.replaceAll(\"-\", \"\").endsWith(tail);\n }\n\n if (!HEX.test(normalizedRef)) return false;\n assertUsableHexRef(ref, normalizedRef);\n return normalizedId.startsWith(normalizedRef) || normalizedId.replaceAll(\"-\", \"\").endsWith(normalizedRef);\n}\n\nfunction assertUsableHexRef(ref: string, hex: string): void {\n if (!HEX.test(hex)) {\n throw new PiPodError(`invalid short ref \"${ref}\"`, {\n hint: \"short refs contain only hexadecimal characters\",\n });\n }\n if (hex.length < MIN_REF_LENGTH) {\n throw new PiPodError(`short ref \"${ref}\" is too short`, {\n hint: `use at least ${MIN_REF_LENGTH} hexadecimal characters`,\n });\n }\n}\n","/**\n * src/account/capacity-errors.ts — actionable presentation for quota/capacity refusals.\n *\n * The server owns admission, placement, and the 20-concurrent policy; this module only\n * translates the refusals the server already sends into copy a person can act on. It keys\n * on stable signals (typed `detail.reason`/`code`, the two concurrency sentences, known\n * fleet capacity sentences) plus an allowlisted future typed detail — never on a bare\n * HTTP status, arbitrary provider error strings, URLs, or secrets. Numbers shown come\n * from validated captures only.\n */\n\nimport { PiPodError } from \"../errors.js\";\nimport { workstationDemandOf } from \"./workstation.js\";\n\nexport type CapacityErrorKind =\n | \"concurrency-user\"\n | \"concurrency-org\"\n | \"fleet-capacity\"\n | \"temporarily-unavailable\"\n | \"unsupported-shape\"\n | \"restore-required\"\n /** The account's own billing state stopped this: a spend cap, an ended trial, a payment. */\n | \"billing-blocked\";\n\nexport interface ClassifiedCapacityError {\n kind: CapacityErrorKind;\n /** True when retrying shortly (after a slot frees / capacity appears) can succeed. */\n retryable: boolean;\n /** Safe, actionable copy. No provider text, URLs, or secrets. */\n hint: string;\n}\n\n/** Product policy: up to 20 concurrent provider-backed sandboxes per platform user. */\nexport const PRODUCT_CONCURRENCY_POLICY = 20;\n\n/** Standard sandbox shape documented by the cost-control plan (shared vCPU, capped memory/disk). */\nexport const PRODUCT_STANDARD_SHAPE = \"2 shared vCPU / 4 GiB memory / 20 GiB writable disk\";\n\nfunction typedDetail(error: unknown): Record<string, unknown> | null {\n if (!(error instanceof PiPodError) || error.detail === null || typeof error.detail !== \"object\") return null;\n if (Array.isArray(error.detail)) return null;\n return error.detail as Record<string, unknown>;\n}\n\nfunction detailReason(error: unknown): string | null {\n const detail = typedDetail(error);\n const reason = detail?.[\"reason\"];\n return typeof reason === \"string\" ? reason : null;\n}\n\nfunction messageOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * Classify a launch/wake/restore refusal. Returns null when the error is not a recognized\n * capacity/quota shape — callers then surface the original error unchanged.\n *\n * Deliberately narrow: a bare HTTP status (including 503) without a typed capacity\n * reason/code or a known fleet sentence is NOT fleet pressure — it could be database,\n * auth, or upstream trouble, and claiming \"fleet full\" would misdirect the operator.\n * Likewise a resource \"supports at most … — using …\" message describes a CLAMP the server\n * applied, so it must never map to the not-clamped shape refusal.\n */\nexport function classifyCapacityError(error: unknown): ClassifiedCapacityError | null {\n const message = messageOf(error);\n const reason = detailReason(error);\n const code = error instanceof PiPodError ? error.code : undefined;\n\n // A personal workstation that is asleep or starting is not capacity pressure and has no\n // fleet to blame: nobody registers a workstation, and telling its owner to ask someone for\n // capacity sends them after a person who does not exist. `account/workstation.ts` owns that\n // path, so it deliberately leaves here unclassified.\n if (workstationDemandOf(error) !== null) return null;\n\n // Billing refusals are terminal decisions about money, not waits. They must never enter a\n // retry loop and never render as \"retry shortly\".\n const billing = classifyBillingRefusal(error);\n if (billing !== null) return billing;\n\n // Future typed contract (tolerated, never required): reason + code survive via\n // PiPodError.detail/code. Unknown reasons fall through to sentence matching below.\n // Reason set: capacity contract §1–2 (memory/cpu/disk/transition/network_capacity,\n // memory_debt, fairness_degraded, fleet_capacity, unsupported_shape).\n if (reason !== null) {\n switch (reason) {\n case \"disk_capacity\":\n case \"memory_capacity\":\n case \"transition_capacity\":\n case \"cpu_capacity\":\n case \"network_capacity\":\n case \"memory_debt\":\n case \"fleet_capacity\":\n case \"fairness_degraded\":\n return {\n kind: \"fleet-capacity\",\n retryable: true,\n hint: capacityReasonHint(reason),\n };\n case \"unsupported_shape\":\n return {\n kind: \"unsupported-shape\",\n retryable: false,\n hint: capacityHint(\"shape\"),\n };\n default:\n break;\n }\n }\n // Stable typed error codes name the refusal without message parsing. `admission_denied`\n // is by construction a capacity refusal; anything else falls through to sentences.\n if (code === \"admission_denied\") {\n return {\n kind: \"fleet-capacity\",\n retryable: true,\n hint: capacityHint(\"fleet\"),\n };\n }\n if (code === \"unsupported_shape\") {\n return {\n kind: \"unsupported-shape\",\n retryable: false,\n hint: capacityHint(\"shape\"),\n };\n }\n\n if (/restore the pod/i.test(message)) {\n return {\n kind: \"restore-required\",\n retryable: false,\n hint: \"restore the pod first (`pipod restore <pod>`), then retry — attach restarts its sandbox when needed\",\n };\n }\n const userCap = /caps concurrent pods per user at (\\d+)/i.exec(message);\n if (userCap) {\n const cap = Number(userCap[1]);\n const shown = Number.isFinite(cap) ? ` ${cap}` : \"\";\n return {\n kind: \"concurrency-user\",\n retryable: true,\n hint:\n `you are at the concurrent-sandbox limit${shown} (product policy: up to ${PRODUCT_CONCURRENCY_POLICY} per user). ` +\n \"Stop a running pod (`pipod stop <pod>`) or wait for idle sleep under your idle policy, then retry\",\n };\n }\n const orgCap = /org policy caps concurrent pods at (\\d+)/i.exec(message);\n if (orgCap) {\n const cap = Number(orgCap[1]);\n const shown = Number.isFinite(cap) ? ` ${cap}` : \"\";\n return {\n kind: \"concurrency-org\",\n retryable: true,\n hint:\n `your organization is at its concurrent-sandbox limit${shown}. ` +\n \"Stop a running pod or wait for idle sleep under your idle policy, then retry — or ask an owner to raise the org policy\",\n };\n }\n if (\n /fleet is at capacity|no sandbox host .* room for a sandbox|every active sandbox host refused/i.test(message)\n ) {\n return {\n kind: \"fleet-capacity\",\n retryable: true,\n hint: capacityHint(\"fleet\"),\n };\n }\n if (/pod is temporarily unavailable; retry shortly/i.test(message)) {\n return {\n kind: \"temporarily-unavailable\",\n retryable: true,\n hint: \"the pod is mid-transition (starting, stopping, or restoring) — retry shortly without creating a new pod\",\n };\n }\n // A genuine shape refusal names itself unsupported. A \"supports at most … — using …\"\n // message is the opposite — a clamp the server applied — and must not map here.\n if (/unsupported/i.test(message) && /shape|memory|disk|cpu|8 ?gi?b/i.test(message)) {\n return {\n kind: \"unsupported-shape\",\n retryable: false,\n hint: capacityHint(\"shape\"),\n };\n }\n return null;\n}\n\n/**\n * Billing refusals: a required subscription, an ended trial, an exhausted trial grant, a\n * payment past its grace, and a reached spend cap.\n *\n * These are exactly the five reasons the server's `StartBlockedReason` can name, and the\n * server's own sentence is the anchor — the copy says the same thing, then adds only what to\n * do and the reassurance that nothing was deleted. Every number comes from a validated field\n * the server actually sent in the 402 `detail`; when it sent none the copy still works, it\n * just carries no figure. The client never names a price, a plan or a policy of its own: it\n * does not know them, and a wrong figure about money is worse than no figure.\n */\nfunction classifyBillingRefusal(error: unknown): ClassifiedCapacityError | null {\n const detail = typedDetail(error);\n const reason = detailReason(error) ?? (error instanceof PiPodError ? error.code ?? null : null);\n if (reason === null) return null;\n switch (reason) {\n case \"subscription_required\":\n return { kind: \"billing-blocked\", retryable: false, hint: subscriptionHint() };\n case \"trial_expired\":\n return { kind: \"billing-blocked\", retryable: false, hint: trialExpiredHint() };\n case \"trial_hours_exhausted\":\n return { kind: \"billing-blocked\", retryable: false, hint: trialHoursHint(detail) };\n case \"payment_past_due\":\n return { kind: \"billing-blocked\", retryable: false, hint: paymentHint() };\n case \"spend_cap_reached\":\n return { kind: \"billing-blocked\", retryable: false, hint: spendCapHint(detail) };\n default:\n return null;\n }\n}\n\n/** The one reassurance every refusal may give: a start being blocked is not data loss. */\nconst RETAINED = \"every workspace stays on the workstation's disk in the meantime\";\n\n/** A finite, non-negative number the server sent, or null. Nothing here is ever computed. */\nfunction billingAmount(detail: Record<string, unknown> | null, key: string): number | null {\n const value = detail?.[key];\n return typeof value === \"number\" && Number.isFinite(value) && value >= 0 ? value : null;\n}\n\nfunction billingDay(detail: Record<string, unknown> | null, key: string): string | null {\n const value = detail?.[key];\n if (typeof value !== \"string\" || value.length > 40) return null;\n const parsed = Date.parse(value);\n return Number.isFinite(parsed) ? new Date(parsed).toISOString().slice(0, 10) : null;\n}\n\n/** `$40.00` — the server's own spend-cap sentence always quotes cents to two places. */\nfunction capMoney(cents: number): string {\n return `$${(cents / 100).toFixed(2)}`;\n}\n\n/** `60`, `12.4` — a whole grant stays whole; a stub grant keeps its one decimal. */\nfunction capHours(value: number): string {\n return Number.isInteger(value) ? String(value) : value.toFixed(1);\n}\n\nfunction subscriptionHint(): string {\n return \"your workstation needs an active subscription before it can start — subscribe to start it again; \" + RETAINED;\n}\n\nfunction trialExpiredHint(): string {\n return \"your trial has ended, so your workstation will not start again — subscribe to start it again; \" + RETAINED;\n}\n\nfunction trialHoursHint(detail: Record<string, unknown> | null): string {\n const included = billingAmount(detail, \"includedActiveHours\");\n const grant =\n included !== null\n ? `includes ${capHours(included)} active hours and they are used up`\n : \"active hours have been used up\";\n return `your trial ${grant}, so your workstation will not start again — subscribe to continue; ${RETAINED}`;\n}\n\nfunction paymentHint(): string {\n return (\n \"your last payment failed and the grace period has ended, so your workstation cannot start — \" +\n `update your payment method to start it again; ${RETAINED}`\n );\n}\n\nfunction spendCapHint(detail: Record<string, unknown> | null): string {\n const cap = billingAmount(detail, \"spendCapUsdCents\");\n const resets = billingDay(detail, \"currentPeriodEnd\");\n const reached =\n cap !== null ? `your monthly spend cap of ${capMoney(cap)} is reached` : \"your monthly spend cap is reached\";\n const until = resets !== null ? ` It resets on ${resets}.` : \"\";\n return (\n `${reached}, so your workstation will not start again.${until} ` +\n `Raise the cap or wait for the period to reset — ${RETAINED}`\n );\n}\n\nfunction capacityHint(which: \"fleet\" | \"shape\"): string {\n if (which === \"shape\") {\n return (\n \"that worker shape is not available on a qualified host (8 GiB is gated opt-in; standard is 4 GiB). \" +\n \"The request was not silently clamped — retry at the standard shape or wait for qualified capacity\"\n );\n }\n return (\n \"the fleet has no room for a new sandbox right now. Retry shortly — stopped pods keep their files \" +\n \"and archived pods restore later, so do not create duplicates. If this persists, ask an owner to register capacity\"\n );\n}\n\n/**\n * Reason-specific fleet copy (capacity contract §1–2). Falls back to the generic fleet\n * hint for plain resource pressures; degraded-fairness and drain states name themselves\n * so a retry pause reads as temporary rather than broken.\n */\nexport function capacityReasonHint(reason: string): string {\n switch (reason) {\n case \"fairness_degraded\":\n return (\n \"CPU fairness is temporarily degraded — existing sandboxes keep running; \" +\n \"retry shortly without creating duplicates\"\n );\n case \"memory_debt\":\n return (\n \"hosts are draining pre-upgrade workloads — retry shortly without creating duplicates\"\n );\n default:\n return capacityHint(\"fleet\");\n }\n}\n\n/** Short resource noun for wait-progress lines; unknown reasons stay generic. */\nexport function capacityReasonShort(reason: string | null): string {\n switch (reason) {\n case \"memory_capacity\":\n case \"memory_debt\":\n return \"memory\";\n case \"disk_capacity\":\n return \"disk\";\n case \"cpu_capacity\":\n return \"CPU\";\n case \"transition_capacity\":\n return \"transition\";\n case \"network_capacity\":\n return \"network\";\n case \"fairness_degraded\":\n return \"fair CPU share\";\n case \"fleet_capacity\":\n return \"fleet\";\n default:\n return \"capacity\";\n }\n}\n\n/**\n * Terminal wait-state copy. `expired` is FINAL for this wait — but the backend is\n * ambiguous (the server may have admitted late), so no copy may claim nothing was\n * created or tell the user to unconditionally launch again. Every remedy routes\n * through checking THIS pod's status first, with no duplicates. `cancelled` means\n * someone (or pod deletion) ended the wait; only a wake-kind cancel may call the\n * pre-existing workspace untouched, since a create-kind wait may have a backend the\n * client has not observed yet.\n */\nexport function capacityWaitTerminalHint(\n state: \"expired\" | \"cancelled\",\n reason: string | null,\n kind?: string | null,\n): string {\n const wake = kind === \"wake\";\n if (state === \"cancelled\") {\n return wake\n ? \"the capacity wait was cancelled — check the pod's status before retrying; the existing workspace is untouched\"\n : \"cancellation requested — check this pod's status before retrying; do not assume no backend was created and do not duplicate the row\";\n }\n const what = reason !== null ? `no room for ${capacityReasonShort(reason)}` : \"no room\";\n return wake\n ? `${what} before the capacity deadline — this wait is over; check the pod's status, then restore or retry this pod — do not create duplicates or launch a new pod`\n : `${what} before the capacity deadline — this wait is over and nothing was admitted in time; check this pod's status first (it may have been admitted late), then retry — do not launch a duplicate`;\n}\n\n/**\n * Attach the actionable hint to a capacity/quota refusal, preserving status/code/transient\n * EXACTLY so transport retry behavior never changes. This wrapper is presentation-only:\n * `retryable` messaging lives in the hint text, never in the transport retry flag —\n * promoting a 409 quota refusal to transient would send the launch blip-recovery path into\n * a 90-second reconnect loop and could duplicate operations. Non-capacity errors pass\n * through untouched.\n */\nexport function withCapacityHint(error: unknown): unknown {\n const classified = classifyCapacityError(error);\n if (!classified || !(error instanceof PiPodError)) return error;\n if (error.hint?.includes(classified.hint)) return error;\n const hint = error.hint ? `${error.hint}\\n${classified.hint}` : classified.hint;\n return new PiPodError(error.message, {\n hint,\n exitCode: error.exitCode,\n ...(error.status !== undefined ? { status: error.status } : {}),\n ...(error.code !== undefined ? { code: error.code } : {}),\n transient: error.transient,\n ...(error.detail !== undefined ? { detail: error.detail } : {}),\n cause: error,\n });\n}\n\n/**\n * One-line summary for launch/wake failure footers. Null when there is nothing\n * capacity-specific to add — callers keep the original message alone.\n */\nexport function capacityFailureSummary(error: unknown): string | null {\n const classified = classifyCapacityError(error);\n if (!classified) return null;\n switch (classified.kind) {\n case \"concurrency-user\":\n return `at the per-user concurrent-sandbox limit (policy: ${PRODUCT_CONCURRENCY_POLICY}); free a slot and retry`;\n case \"concurrency-org\":\n return \"at the organization concurrent-sandbox limit; free a slot and retry\";\n case \"fleet-capacity\":\n return \"fleet at capacity; retry shortly without duplicating the request\";\n case \"temporarily-unavailable\":\n return \"pod mid-transition; retry shortly\";\n case \"unsupported-shape\":\n return \"shape unavailable on qualified hosts; not clamped — retry at standard size\";\n case \"restore-required\":\n return \"restore the pod first, then retry\";\n case \"billing-blocked\":\n return \"blocked by this account's billing state; retrying will not change it\";\n }\n}\n","import { CancelledError, PiPodError } from \"../errors.js\";\nimport {\n capacityReasonHint,\n capacityReasonShort,\n capacityWaitTerminalHint,\n} from \"./capacity-errors.js\";\nimport { color, debug, info, step, warn } from \"../log.js\";\nimport { withWorkstationWait, type WorkstationWaitOptions } from \"./workstation.js\";\nimport type { AccountClient, ApiPod, LaunchReport } from \"./api.js\";\nimport type { AccountLaunchPlan } from \"./launch-types.js\";\nimport { displayRef } from \"./ref.js\";\n\nexport function printLaunchReport(report: LaunchReport, pod: ApiPod): void {\n for (const clamp of report.clamps) {\n warn(`org policy: ${clamp.path} ${JSON.stringify(clamp.from)} → ${JSON.stringify(clamp.to)} (${clamp.reason})`);\n }\n const configProvenance = report.configProvenance ?? pod.resolvedConfig.configProvenance ?? [];\n if (configProvenance.length > 0) {\n info(\"settings provenance (later layers win):\");\n for (const entry of configProvenance) {\n const contested = entry.over.length > 0\n ? color.dim(` (over ${entry.over.map(displayReportLayer).join(\", \")})`)\n : \"\";\n info(` ${entry.path} ← ${displayReportLayer(entry.winner)}${contested}`);\n }\n }\n if (report.secretKeys.length > 0) {\n const scopes = report.secretScopes ?? pod.resolvedConfig.secretScopes ?? {};\n const shadows = report.secretShadows ?? pod.resolvedConfig.secretShadows ?? {};\n const labeled = report.secretKeys.map((key) => {\n const scoped = scopes[key] ? `${key}(${scopes[key]})` : key;\n const lost = shadows[key];\n return lost?.length ? `${scoped}[over ${lost.join(\",\")}]` : scoped;\n });\n info(`secrets traveling: ${labeled.join(\", \")}`);\n }\n for (const warning of report.warnings) warn(warning);\n const action = pod.preparationPhase === \"preparing-image\" ? \"preparing its runtime image\" : \"provisioning\";\n info(`pod ${color.bold(displayRef(pod.id, \"pod\"))} (${pod.provider}) ${action}…`);\n}\n\n/**\n * The pod is already provisioning on the server, so a blip on the polling connection says\n * nothing about the launch. Give up on it only once the server has been unreachable long\n * enough to be a real outage, rather than abandoning a healthy pod on one bad response.\n */\nfunction displayReportLayer(layer: string): string {\n if (layer === \"org\") return \"org defaults\";\n if (layer === \"user\") return \"user defaults\";\n if (layer === \"project\") return \"project preview\";\n if (layer === \"policy\" || layer === \"org-policy\") return \"org policy\";\n return layer;\n}\n\nexport const PROVISION_BLIP_GRACE_MS = 90_000;\n\n/** How long a supporting server may hold one readiness poll open before answering. */\nexport const READINESS_LONG_POLL_MS = 20_000;\n\n/**\n * Hint for the `capacity_wait_expired` paths. An expired wait never acquired\n * compute, so the row converges to provider_state=gone: hidden from\n * `pipod list` (only includeGone paths such as `gc` see it) and needing no\n * cleanup. The generic `stateReason` throw below keeps its listable-copy hint.\n */\nexport const CAPACITY_WAIT_EXPIRED_HINT =\n \"the pod never acquired compute and is hidden from `pipod list`; retry the launch when capacity frees (`pipod gc` reports hidden rows)\";\n\n/** Poll provider-agnostic readiness while narrating init progress. */\nexport async function watchProvisioning(\n client: AccountClient,\n podId: string,\n timing: {\n pollMs?: number;\n retryMs?: number;\n blipGraceMs?: number;\n waitMs?: number;\n timeoutMs?: number;\n cancelled?: () => boolean;\n } = {},\n): Promise<ApiPod> {\n const pollMs = timing.pollMs ?? 1000;\n const retryMs = timing.retryMs ?? 2000;\n const blipGraceMs = timing.blipGraceMs ?? PROVISION_BLIP_GRACE_MS;\n let reportedWaiting = false;\n const reported = new Set<string>();\n // Last announced capacity-wait reason: re-announce only when the reason changes, so a\n // 60-second wait narrates once instead of once per poll. Progress re-renders at most\n // every 5s (the server's bounded wait with validated reason/numbers/deadlineAt)\n // so a 60s wait is visibly alive, not stalled output.\n let announcedWaitReason: string | null = null;\n let lastWaitLogAt = 0;\n let lastWaitAttempts = -1;\n const deadline = Date.now() + 30 * 60 * 1000;\n let blipSince: number | null = null;\n let reportedBlip = false;\n for (;;) {\n if (timing.cancelled?.()) throw new CancelledError(\"interrupted\");\n let pod: ApiPod;\n const polledAt = Date.now();\n try {\n // A supporting server holds the request until the pod changes (long poll), so\n // progress lands the moment it happens instead of on the next tick.\n pod = await client.getPod(podId, {\n waitMs: timing.waitMs ?? READINESS_LONG_POLL_MS,\n ...(timing.timeoutMs !== undefined ? { timeoutMs: timing.timeoutMs } : {}),\n });\n if (timing.cancelled?.()) throw new CancelledError(\"interrupted\");\n if (blipSince !== null) {\n if (reportedBlip) step(\"launch\", \"server is back\");\n blipSince = null;\n reportedBlip = false;\n }\n } catch (e) {\n if (timing.cancelled?.()) throw new CancelledError(\"interrupted\");\n const transient = e instanceof PiPodError && e.transient;\n if (!transient) throw e;\n const now = Date.now();\n blipSince ??= now;\n if (now - blipSince > blipGraceMs) {\n const ref = displayRef(podId, \"pod\");\n throw new PiPodError(\n `lost contact with the server while pod ${ref} was still provisioning`,\n {\n hint: `provisioning continues on the server — reattach with \\`pipod attach ${ref}\\``,\n transient: true,\n cause: e,\n },\n );\n }\n if (!reportedBlip) {\n reportedBlip = true;\n warn(`lost contact with the server — the pod keeps provisioning; still watching (${e.message})`);\n }\n await new Promise((r) => setTimeout(r, retryMs));\n continue;\n }\n const phase = pod.preparationPhase;\n if (phase === \"preparing-image\" && !reported.has(phase)) {\n reported.add(phase);\n reportedWaiting = true;\n const ref = pod.resolvedConfig.image ?? \"the updated runtime\";\n step(\"image\", `preparing ${ref} (first launch after this runtime update; usually a few minutes)`);\n } else if (phase === \"provisioning-sandbox\" && !reported.has(phase)) {\n reported.add(phase);\n reportedWaiting = true;\n step(\"launch\", \"runtime image is ready; preparing the sandbox\");\n } else if (!phase && !pod.ready && !reportedWaiting) {\n // Backward compatibility with servers that predate preparationPhase.\n reportedWaiting = true;\n step(\"launch\", \"sandbox is getting ready\");\n }\n for (const s of pod.resolvedConfig.initSteps ?? []) {\n const key = `${s.scope}:${s.status}`;\n if (s.status !== \"pending\" && !reported.has(key)) {\n reported.add(key);\n step(\"init\", `${s.scope} init script: ${s.status}`);\n }\n }\n if (pod.ready) return pod;\n // Bounded capacity wait (capacity contract §1): the request is\n // valid and entitled, holding one concurrency slot but no host reservation.\n // Older servers omit the field — that reads exactly like no wait and flows\n // through today's path. New servers send preparationPhase `waiting-for-capacity`\n // with validated reason|required|available|unit|deadlineAt|waitedSeconds plus\n // terminal stateReasonCode `capacity_wait_expired`.\n const wait = pod.capacityWait ?? null;\n const waitingPhase = phase === \"waiting-for-capacity\";\n if (wait !== null && wait.state === \"waiting\") {\n const key = wait.reason ?? \"capacity\";\n const now = Date.now();\n if (announcedWaitReason !== key) {\n announcedWaitReason = key;\n lastWaitLogAt = now;\n lastWaitAttempts = wait.attempts;\n reportedWaiting = true;\n // Contract copy: [launch] waiting for fleet\n // capacity: <reason> (needs X, free Y) — up to Ns, with a\n // countdown. The trailing `waiting for capacity` keeps the legacy\n // copy greppable (older tooling/tests match it exactly once per reason).\n step(\"launch\", `waiting for fleet capacity: ${describeCapacityWaitLine(wait)} (waiting for capacity)`);\n } else if (\n now - lastWaitLogAt >= 5000 &&\n wait.attempts >= lastWaitAttempts + 5\n ) {\n lastWaitLogAt = now;\n lastWaitAttempts = wait.attempts;\n step(\"launch\", `still waiting for fleet capacity: ${describeCapacityWaitLine(wait)} (waiting for capacity)`);\n } else if (now - lastWaitLogAt >= 5000 && wait.attempts === lastWaitAttempts) {\n // Heartbeat countdown even when attempts stall (long-poll holds): at most every 5s.\n lastWaitLogAt = now;\n step(\"launch\", `still waiting for fleet capacity: ${describeCapacityWaitLine(wait)} (waiting for capacity)`);\n }\n } else if (waitingPhase && wait === null) {\n // New phase without a wait view (should not happen; server always sends\n // both) — render the phase label additively, never as raw provider text.\n const now = Date.now();\n if (announcedWaitReason !== \"fleet_capacity\") {\n announcedWaitReason = \"fleet_capacity\";\n lastWaitLogAt = now;\n reportedWaiting = true;\n step(\"launch\", \"waiting for fleet capacity: fleet_capacity — up to 60s (~60s left) (waiting for capacity)\");\n } else if (now - lastWaitLogAt >= 5000) {\n lastWaitLogAt = now;\n step(\"launch\", \"still waiting for fleet capacity: fleet_capacity — up to 60s (~60s left) (waiting for capacity)\");\n }\n } else if (wait !== null && wait.state === \"admitted\" && announcedWaitReason !== null) {\n announcedWaitReason = null;\n step(\"capacity\", \"capacity found — provisioning continues\");\n } else if (wait !== null && (wait.state === \"expired\" || wait.state === \"cancelled\")) {\n // Terminal wait states are FINAL for this operation: never transient (no blip\n // retry), never a duplicate launch — a new launch may be tried by hand. A wake\n // ends on an existing workspace, so its copy must never say \"launch again\".\n // Typed expiry (server stateReasonCode) reads as retry-later copy.\n if (wait.state === \"expired\" && (pod as ApiPod).stateReasonCode === \"capacity_wait_expired\") {\n throw new PiPodError(describeLaunchFailure(pod), {\n hint: CAPACITY_WAIT_EXPIRED_HINT,\n transient: false,\n });\n }\n const wake = wait.kind === \"wake\";\n const operation = wake ? \"wake\" : \"launch\";\n throw new PiPodError(\n wait.state === \"expired\"\n ? `${operation} failed: capacity wait expired (${capacityReasonShort(wait.reason)} pressure)`\n : `${operation} failed: capacity wait was cancelled`,\n {\n hint: capacityWaitTerminalHint(wait.state, wait.reason, wait.kind),\n transient: false,\n },\n );\n }\n // A refused reuse ends this watch — the pod went back to stopped and the caller owes a\n // fresh launch; waiting longer would time out on a pod that will never become ready.\n if (pod.resolvedConfig.reuseRefused) return pod;\n if ((pod as ApiPod).stateReasonCode === \"capacity_wait_expired\") {\n throw new PiPodError(describeLaunchFailure(pod), {\n hint: CAPACITY_WAIT_EXPIRED_HINT,\n });\n }\n if (pod.stateReason) {\n throw new PiPodError(`launch failed: ${pod.stateReason}`, { hint: await launchFailureHint(client, pod) });\n }\n if (Date.now() > deadline) throw new PiPodError(\"launch timed out after 30 minutes\");\n // Pace only what the server answered immediately — an older server that ignores the\n // long poll, or a change that returned at once. A held request needs no extra sleep.\n const elapsed = Date.now() - polledAt;\n if (elapsed < pollMs) await new Promise((r) => setTimeout(r, pollMs - elapsed));\n }\n}\n\n/**\n * What to do about a failed launch. A full host is the common case on a self-hosted server:\n * every running pod holds its whole memory ceiling until it stops, so name the caller's own.\n */\nasync function launchFailureHint(client: AccountClient, failed: ApiPod): Promise<string> {\n if (!/admission_denied\\b.*\\bat capacity\\b/.test(failed.stateReason ?? \"\")) {\n return \"`pipod list` shows the pod; delete it with `pipod gc --delete` once diagnosed\";\n }\n const { pods } = await client.listPods({ mine: true }).catch(() => ({ pods: [] as ApiPod[] }));\n const running = pods.filter(\n (p) => p.id !== failed.id && p.state === \"active\" && p.ready && p.sandboxState !== \"stopped\" && p.sandboxState !== \"archived\",\n );\n if (running.length === 0) return \"the server is full with other people's pods; try again when one stops\";\n const names = running.map((p) => `${displayRef(p.id, \"pod\")} (${p.name})`).join(\", \");\n return `the server is full; stop a pod you are not using — ${names} — with \\`pipod stop <pod>\\`, then launch again`;\n}\n\n/** Translate compatibility errors for request features that require a matching server. */\nasync function launchWithCompatibilityErrors(\n client: AccountClient,\n body: Parameters<AccountClient[\"launch\"]>[0],\n): Promise<{ pod: ApiPod; report: LaunchReport }> {\n try {\n return await client.launch(body);\n } catch (error) {\n if (\n body.workspaceSeed &&\n error instanceof PiPodError &&\n error.status === 400 &&\n /(?:unrecognized|unknown|unexpected)[^\\n]*workspaceSeed|workspaceSeed[^\\n]*(?:unrecognized|unknown|unexpected)/i.test(error.message)\n ) {\n // The seed gate is an optimization, not a requirement: a server that predates it starts\n // Pi immediately and the seed lands afterwards, exactly as configured projects always did.\n debug(\"the server predates the workspace seed gate — launching without it\");\n const { workspaceSeed: _gate, ...ungated } = body;\n return await client.launch(ungated);\n }\n if (\n body.placement &&\n error instanceof PiPodError &&\n error.status === 400 &&\n /(?:unrecognized|unknown|unexpected)[^\\n]*placement|placement[^\\n]*(?:unrecognized|unknown|unexpected)/i.test(error.message)\n ) {\n throw new PiPodError(\"the pi pod server does not support co-located pods\", {\n hint: \"deploy the matching pi pod server before using `--on`\",\n cause: error,\n status: error.status,\n });\n }\n if (\n body.forkFrom &&\n error instanceof PiPodError &&\n error.status === 400 &&\n /(?:unrecognized|unknown|unexpected)[^\\n]*forkFrom|forkFrom[^\\n]*(?:unrecognized|unknown|unexpected)/i.test(error.message)\n ) {\n throw new PiPodError(\"the pi pod server does not support forking a session into a new pod\", {\n hint: \"deploy the matching pi pod server before using `pipod fork`\",\n cause: error,\n status: error.status,\n });\n }\n throw error;\n }\n}\n\n/**\n * A launch that dies on the wire leaves two possibilities — the request never arrived, or it\n * arrived and the answer was lost on the way back — and only the first may be retried blindly.\n * The server goes away for a few seconds on every deploy, which is too little to throw away a\n * launch over and more than enough to lose a reply, so neither giving up nor relaunching is\n * right on its own.\n *\n * The pod list settles it. Ids taken before the attempt turn \"did my launch land?\" into a\n * question the server can answer once it is back: a pod that was not there before is the lost\n * launch, adopted as if its reply had arrived, and only its absence sends a second request.\n * The cost is one extra call per launch, paid against the alternative of a duplicate pod that\n * bills until someone notices it.\n */\nexport const LAUNCH_BLIP_GRACE_MS = 90_000;\n\nexport async function launchRidingOutBlips(\n client: AccountClient,\n plan: AccountLaunchPlan,\n body: Parameters<AccountClient[\"launch\"]>[0],\n timing: {\n retryMs?: number;\n blipGraceMs?: number;\n cancelled?: () => boolean;\n /** Test seam for the workstation wait; production uses its own measured bounds. */\n workstation?: WorkstationWaitOptions;\n } = {},\n): Promise<{ pod: ApiPod; report: LaunchReport }> {\n const retryMs = timing.retryMs ?? 2000;\n const blipGraceMs = timing.blipGraceMs ?? LAUNCH_BLIP_GRACE_MS;\n const before = await podsForThisLaunch(client, plan, body.project?.name ?? null);\n const knownIds = before ? new Set(before.map((pod) => pod.id)) : null;\n let blipSince: number | null = null;\n let announced = false;\n for (;;) {\n if (timing.cancelled?.()) throw new CancelledError(\"interrupted\");\n try {\n // A personal workstation that is asleep or coming up refuses the launch with a typed\n // 503 before any pod row exists, so asking again is free and creates nothing twice.\n // It has to be handled here rather than below: the refusal is a 503, which the blip\n // path would read as a lost connection and narrate as \"lost contact with the server\"\n // for ninety seconds before failing a launch that was only ever waiting on a machine.\n return await withWorkstationWait(\n client,\n () => launchWithCompatibilityErrors(client, body),\n {\n ...(timing.cancelled ? { cancelled: timing.cancelled } : {}),\n ...timing.workstation,\n // A lost launch reply is not a typed 503. Do not issue the POST again from here.\n replayTransport: false,\n },\n );\n } catch (error) {\n // Without a before-picture there is no way to tell a lost launch from one that never\n // happened, and guessing wrong costs a pod — so one bad connection stays fatal.\n if (!(error instanceof PiPodError) || !error.transient || !knownIds) throw error;\n blipSince ??= Date.now();\n const deadline = blipSince + blipGraceMs;\n if (!announced) {\n announced = true;\n warn(`lost contact with the server while launching — asking whether the pod was created (${error.message})`);\n }\n let landed: ApiPod[] | null = null;\n while (!landed) {\n // `>=`, not `>`: the deadline is the instant the window closes, and a zero window has\n // to mean zero retries. With `>` a whole pass could run inside one millisecond tick\n // and buy itself a retry the grace period never granted.\n if (Date.now() >= deadline) throw error;\n await new Promise((resolve) => setTimeout(resolve, retryMs));\n landed = await podsForThisLaunch(client, plan, body.project?.name ?? null);\n }\n const fresh = landed.filter((pod) => !knownIds.has(pod.id));\n if (fresh.length === 1) {\n const pod = fresh[0]!;\n step(\"launch\", `the launch landed before the connection dropped — continuing with pod ${color.bold(displayRef(pod.id, \"pod\"))}`);\n // The launch-time warnings went down with the reply; the pod carries the rest.\n return { pod, report: { clamps: pod.resolvedConfig.clamps, secretKeys: pod.resolvedConfig.secretKeys, warnings: [] } };\n }\n if (fresh.length > 1) {\n throw new PiPodError(\"the server gained more than one pod for this project while the launch was in flight\", {\n hint: `pick one with \\`pipod attach\\` rather than launch again: ${fresh.map((pod) => displayRef(pod.id, \"pod\")).join(\", \")}`,\n cause: error,\n });\n }\n if (timing.cancelled?.()) throw new CancelledError(\"interrupted\");\n // An empty list is not proof the original POST cannot still commit. Do not issue another.\n throw new PiPodError(\"the launch request did not return, and the server does not show a pod from it\", {\n hint: \"the request may still be committing; do not launch again until you confirm no pod was created\",\n code: \"launch_unresolved\",\n transient: false,\n cause: error,\n });\n }\n }\n}\n\n/** This launch's identity among the caller's pods, or null when the server cannot say. */\nasync function podsForThisLaunch(client: AccountClient, plan: AccountLaunchPlan, project: string | null): Promise<ApiPod[] | null> {\n try {\n const { pods } = await client.listPods({\n mine: true,\n state: \"active\",\n });\n return pods.filter((pod) => pod.templateId === (plan.templateId ?? null) && pod.project === project);\n } catch (e) {\n debug(`could not list this project's pods: ${e instanceof Error ? e.message : String(e)}`);\n return null;\n }\n}\n\n/**\n * §6.5: pick this project's most recently active stopped pod and ask the server to\n * relaunch onto its warm disk. Any refusal — no candidate, an older server without the\n * endpoint, an ineligible pod (409) — answers null and the caller launches fresh.\n */\nexport async function tryAccountReuse(\n client: AccountClient,\n plan: AccountLaunchPlan,\n body: Parameters<AccountClient[\"launch\"]>[0],\n timing: { workstation?: WorkstationWaitOptions } = {},\n): Promise<{ pod: ApiPod; report: LaunchReport } | null> {\n let candidate: ApiPod | undefined;\n try {\n const { pods } = await client.listPods({\n mine: true,\n state: \"active\",\n });\n // This project's own stopped pod: another project's disk holds another project's work.\n candidate = pods.find(\n (p) =>\n p.templateId === (plan.templateId ?? null) &&\n p.project === (plan.projectName ?? null) &&\n !p.ready &&\n !p.initializing &&\n p.stateReason === null,\n );\n } catch (e) {\n debug(`could not list pods for reuse: ${e instanceof Error ? e.message : String(e)}`);\n return null;\n }\n if (!candidate) {\n debug(\"no stopped pod to reuse for this project — launching fresh\");\n return null;\n }\n step(\"reuse\", `relaunching onto stopped pod ${color.bold(displayRef(candidate.id, \"pod\"))}'s warm disk`);\n try {\n // A warm disk keeps its workspace; a reuse never seeds, so it never arms the seed gate.\n const { workspaceSeed: _gate, placement: _placement, forkFrom: _fork, ...reuseBody } = body;\n // Waiting for the workstation here rather than falling through: the warm disk is the\n // whole point of a reuse, and \"not reusable\" would be a false verdict on a pod whose\n // machine simply had not finished starting.\n return await withWorkstationWait(client, () => client.reusePod(candidate!.id, reuseBody), {\n ...timing.workstation,\n replayTransport: false,\n });\n } catch (error) {\n // Only a definitive \"this pod cannot be reused\" answer may fall through to a fresh launch.\n // A lost reply, a start-guard, or a cancel must not be rewritten into another mutation.\n if (error instanceof PiPodError && (error.status === 404 || error.status === 409)) {\n const reason = error.message.replace(/^the pi pod server refused \\S+ \\S+: /, \"\");\n info(`pod ${displayRef(candidate.id, \"pod\")} not reusable (${reason}); launching a fresh pod`);\n return null;\n }\n throw error;\n }\n}\n\n/** One progress line for a queued launch/wake: reason plus time left on the final deadline. */\nexport function capacityWaitProgress(wait: {\n reason: string | null;\n deadlineInMs: number;\n attempts: number;\n detail?: { retryable?: boolean } | null;\n}): string {\n const what = capacityReasonShort(wait.reason);\n const secondsLeft = Math.max(0, Math.ceil(wait.deadlineInMs / 1000));\n const tries = wait.attempts > 0 ? ` (attempt ${wait.attempts + 1})` : \"\";\n const reasonCopy = wait.reason !== null ? capacityReasonHint(wait.reason) : null;\n const why = reasonCopy !== null && reasonCopy !== \"\" ? ` — ${reasonCopy}` : \"\";\n return `no room for ${what} yet; retrying until the deadline (~${secondsLeft}s left)${tries}${why}`;\n}\n\n/** Human amounts for the wait view's validated numbers (bytes → GiB, else raw with unit). */\nexport function describeCapacityAmounts(wait: {\n required?: number;\n available?: number;\n unit?: string | null;\n}): string {\n if (wait.required === undefined || wait.available === undefined) return \"\";\n const format = (value: number): string =>\n wait.unit === \"bytes\" && value >= 1024 ** 3\n ? `${(value / 1024 ** 3).toFixed(1)} GiB`\n : `${value}${wait.unit ? ` ${wait.unit}` : \"\"}`;\n return ` (needs ${format(wait.required)}, free ${format(wait.available)})`;\n}\n\n/**\n * One-line wait copy from the server's validated wait view:\n * `<reason> (needs X, free Y) — up to Ns (~Ns left)`.\n * Never renders raw provider text — reason is the validated enum, numbers are\n * finite non-negative validated fields. Older servers omit the amount fields and\n * render as `<reason> — up to Ns (~Ns left)`.\n */\nexport function describeCapacityWaitLine(wait: {\n reason: string | null;\n deadlineInMs: number;\n required?: number;\n available?: number;\n unit?: string | null;\n deadlineAt?: string | null;\n}): string {\n let remaining = Math.max(0, Math.ceil(wait.deadlineInMs / 1000));\n if (!Number.isFinite(remaining) && typeof wait.deadlineAt === \"string\") {\n const parsed = Date.parse(wait.deadlineAt);\n if (Number.isFinite(parsed)) remaining = Math.max(0, Math.ceil((parsed - Date.now()) / 1000));\n }\n if (!Number.isFinite(remaining)) remaining = 60;\n const reason = wait.reason ?? \"fleet_capacity\";\n return `${reason}${describeCapacityAmounts(wait)} — up to ${remaining}s (~${remaining}s left)`;\n}\n\n/**\n * Typed capacity expiry (server stateReasonCode `capacity_wait_expired`):\n * `launch failed: the fleet is still at capacity (waited Ns for <reason>); retry shortly`.\n * Falls back to the opaque stateReason when the code or wait view is absent\n * (older servers render exactly as before).\n */\nexport function describeLaunchFailure(pod: ApiPod): string {\n if ((pod as ApiPod).stateReasonCode === \"capacity_wait_expired\") {\n const wait = pod.capacityWait as unknown as\n | { reason?: string | null; waitedSeconds?: number | null } | null | undefined;\n const reason = (wait?.reason ?? \"fleet_capacity\") as string;\n const waited =\n typeof wait?.waitedSeconds === \"number\" && Number.isFinite(wait.waitedSeconds)\n ? ` (waited ${Math.max(0, Math.round(wait.waitedSeconds))}s for ${reason})`\n : ` (${reason})`;\n return `launch failed: the fleet is still at capacity${waited}; retry shortly`;\n }\n return `launch failed: ${pod.stateReason}`;\n}\n\n/** One line naming total launch wall time and the server's per-phase provisioning cost. */\nexport function podReadySummary(pod: ApiPod, totalMs: number): string {\n const total = `pod ready in ${(totalMs / 1000).toFixed(1)}s`;\n const timings = pod.resolvedConfig.timings;\n if (!timings) return total;\n const order = [\"create\", \"start\", \"prep\", \"clone\", \"materialize\", \"init\"];\n const parts = order\n .filter((name) => (timings[name] ?? 0) >= 100)\n .map((name) => `${name} ${((timings[name] ?? 0) / 1000).toFixed(1)}s`);\n return parts.length > 0 ? `${total} (${parts.join(\" · \")})` : total;\n}\n","import type { TuiMode } from \"../client/headless.js\";\nimport { PiPodError } from \"../errors.js\";\nimport type { PiLaunchOverrides } from \"./api.js\";\nimport {\n MAX_RESOURCES_PER_KIND,\n PI_RESOURCE_CLI_FLAGS,\n PI_RESOURCE_FLAGS,\n parseResourcePath,\n type PiResourceKey,\n} from \"./launch-resources.js\";\n\nconst ACCOUNT_THINKING_LEVELS = [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const;\n\n/** Which `piOverrides` resource array a CLI spelling after `--` collects into. */\nfunction resourceKeyFor(flag: string): PiResourceKey | undefined {\n for (const [key, spellings] of Object.entries(PI_RESOURCE_CLI_FLAGS) as Array<[PiResourceKey, readonly string[]]>) {\n if (spellings.includes(flag)) return key;\n }\n return undefined;\n}\n\n/** Split a `--flag=value` token; null for anything else (plain `--flag` needs no split). */\nfunction splitInlineValue(arg: string): { flag: string; value: string } | null {\n if (!arg.startsWith(\"--\")) return null;\n const equals = arg.indexOf(\"=\");\n if (equals < 0) return null;\n return { flag: arg.slice(0, equals), value: arg.slice(equals + 1) };\n}\n\n/** Parse server-side model/resource overrides plus the local-only TUI layout override. */\nexport function parseAccountLaunchPiArgs(piArgs: string[]): {\n prompt: string | undefined;\n piOverrides: PiLaunchOverrides | undefined;\n extraArgs: string[];\n tuiMode?: TuiMode;\n} {\n const positionals: string[] = [];\n const extraArgs: string[] = [];\n const piOverrides: PiLaunchOverrides = {};\n let tuiMode: TuiMode | undefined;\n let rejecting = false;\n\n const takeResource = (key: PiResourceKey, flag: string, inline: string | undefined, index: { i: number }): void => {\n let value = inline;\n if (value === undefined) {\n value = piArgs[++index.i];\n if (value === undefined) {\n throw new PiPodError(`${flag} requires a path`, {\n hint: \"name a file or directory inside the pod, for example: pipod -- --skill /workspace/skills/review\",\n });\n }\n }\n const paths = (piOverrides[key] ??= []);\n if (paths.length >= MAX_RESOURCES_PER_KIND) {\n throw new PiPodError(`${flag} accepts at most ${MAX_RESOURCES_PER_KIND} paths per launch`, {\n hint: \"bundle rarely-changed resources into configuration instead of the launch request\",\n });\n }\n paths.push(parseResourcePath(flag, value));\n };\n\n const cursor = { i: 0 };\n for (; cursor.i < piArgs.length; cursor.i++) {\n const arg = piArgs[cursor.i]!;\n if (!rejecting && arg === \"--\") {\n positionals.push(...piArgs.slice(cursor.i + 1));\n break;\n }\n // Resource flags accept `--flag value` and `--flag=value`; model/thinking/tui-mode\n // keep Pi's exact space-separated spelling, as before.\n const inline = !rejecting ? splitInlineValue(arg) : null;\n const resourceFlag = inline ? inline.flag : arg;\n const key = !rejecting ? resourceKeyFor(resourceFlag) : undefined;\n if (key) {\n takeResource(key, resourceFlag, inline?.value, cursor);\n continue;\n }\n if (!rejecting && (arg === \"--model\" || arg === \"--thinking\" || arg === \"--tui-mode\")) {\n const flag = arg;\n const value = piArgs[++cursor.i];\n if (value === undefined || value.length === 0 || value.trim() !== value || value.startsWith(\"-\")) {\n throw new PiPodError(`${flag} requires a non-empty value that does not start with \"-\"`);\n }\n if (flag === \"--model\") {\n piOverrides.model = value;\n } else if (flag === \"--thinking\") {\n if (!ACCOUNT_THINKING_LEVELS.includes(value as (typeof ACCOUNT_THINKING_LEVELS)[number])) {\n throw new PiPodError(\n `invalid thinking level ${JSON.stringify(value)}; use ${ACCOUNT_THINKING_LEVELS.join(\", \")}`,\n );\n }\n piOverrides.thinking = value as PiLaunchOverrides[\"thinking\"];\n } else {\n if (value !== \"regular\" && value !== \"fullscreen\") {\n throw new PiPodError(`invalid TUI mode ${JSON.stringify(value)}; use regular or fullscreen`);\n }\n tuiMode = value;\n }\n continue;\n }\n if (!rejecting && arg.startsWith(\"-\")) rejecting = true;\n if (rejecting) extraArgs.push(arg);\n else positionals.push(arg);\n }\n\n return {\n prompt: positionals.length > 0 ? positionals.join(\" \") : undefined,\n piOverrides: Object.keys(piOverrides).length > 0 ? piOverrides : undefined,\n extraArgs,\n ...(tuiMode ? { tuiMode } : {}),\n };\n}\n\n/** Positional words become the startup prompt; --tui-mode is a local UI-only attach option. */\nexport function splitPiArgs(piArgs: string[]): {\n prompt: string | undefined;\n extraArgs: string[];\n tuiMode?: TuiMode;\n} {\n const parsed = parseAccountLaunchPiArgs(piArgs);\n const managedArgs: string[] = [];\n if (parsed.piOverrides?.model) managedArgs.push(\"--model\", parsed.piOverrides.model);\n if (parsed.piOverrides?.thinking) managedArgs.push(\"--thinking\", parsed.piOverrides.thinking);\n // Launch-only resources are re-emitted canonically rather than dropped: attach refuses\n // every per-launch Pi option it cannot honor, and a silently swallowed --skill that never\n // loads would read as success.\n if (parsed.piOverrides) {\n for (const [key, paths] of Object.entries(parsed.piOverrides) as Array<[keyof PiLaunchOverrides, unknown]>) {\n if (key === \"model\" || key === \"thinking\") continue;\n const flag = PI_RESOURCE_FLAGS[key as PiResourceKey];\n if (!flag || !Array.isArray(paths)) continue;\n for (const path of paths) managedArgs.push(flag, path);\n }\n }\n return {\n prompt: parsed.prompt,\n extraArgs: [...managedArgs, ...parsed.extraArgs],\n ...(parsed.tuiMode ? { tuiMode: parsed.tuiMode } : {}),\n };\n}\n","import type { PiConfig } from \"./config.js\";\n\nexport const PROJECT_TRUST_ARGS = new Set([\"--approve\", \"-a\", \"--no-approve\", \"-na\"]);\n\nexport function buildPiArgv(\n config: Pick<PiConfig, \"command\" | \"args\"> & Partial<Pick<PiConfig, \"model\" | \"thinking\">>,\n ...argGroups: string[][]\n): string[] {\n const configuredSelection = [\n ...(config.model != null ? [\"--model\", config.model] : []),\n ...(config.thinking != null ? [\"--thinking\", config.thinking] : []),\n ];\n const args = [...config.args, ...configuredSelection, ...argGroups.flat()];\n const trustArgs = args.some((arg) => PROJECT_TRUST_ARGS.has(arg)) ? [] : [\"--approve\"];\n return [config.command, ...trustArgs, ...args];\n}\n","/**\n * src/account/session.ts — the account-mode session driver (account-mode-spec §6.2).\n *\n * The same shape as src/client/session.ts's interactive path — pi's real InteractiveMode\n * over the remote runtime — with the transport swapped for {@link GatewayRpcClient} and the\n * pod-coupled pieces replaced by their server-side equivalents: recovery is internal to the\n * WebSocket client, `/pod shell` has no provider PTY to offer, and `/pod switch` re-targets\n * another server pod by re-attaching the same client.\n *\n * Ending policy is account policy (§6.2): detaching leaves the pod to the server's reaper;\n * an explicit leave-with-action or a quit maps onto server lifecycle commands.\n */\nimport { isKeyRelease, isKeyRepeat, matchesKey, type KeyId } from \"@earendil-works/pi-tui\";\nimport type { PiPodConfig } from \"../config.js\";\nimport {\n isWakeableAsleepReason,\n isWorkstationAsleepReason,\n PiPodError,\n WAKEABLE_ASLEEP_REASONS,\n} from \"../errors.js\";\nimport { info, warn } from \"../log.js\";\nimport { confirm } from \"../prompt.js\";\nimport { buildPodStatusLines } from \"../client/podinfo.js\";\nimport { shimCompatibilityWarning } from \"../client/compat.js\";\nimport { runHeadless, tuiModeFromArgv, type TuiMode } from \"../client/headless.js\";\nimport { installPodTerminalTitle } from \"../client/pod-title.js\";\nimport {\n attestedPackages,\n installAttestedPackages,\n trustAttestedPackages,\n unattestedPackageNotice,\n type AttestedPackage,\n} from \"../client/runtime/attested-extensions.js\";\nimport { installPodCommandOverrides } from \"../client/runtime/pod-command-overrides.js\";\nimport { preparePromptImages } from \"../client/runtime/local-images.js\";\nimport {\n createDerivedPodConfig,\n defaultHostAgentDir,\n defaultPodCacheRoot,\n loadPodThemeLoader,\n type DerivedPodConfig,\n} from \"../client/runtime/pod-derived-config.js\";\nimport { createPodConfigSync, podConfigSyncNotice, type PodConfigSync } from \"./pod-config-sync.js\";\nimport { createRemoteRuntime, type RemoteRuntime } from \"../client/runtime/remote-runtime.js\";\nimport type { UsageTotals } from \"../client/runtime/state.js\";\nimport type { RemoteAuthInteraction } from \"../client/runtime/auth-bridge.js\";\nimport type { HostUiContext } from \"../client/runtime/bridge.js\";\nimport type { PodCommandHost } from \"../client/runtime/pod-commands.js\";\nimport { type ApiPod, type AccountClient } from \"./api.js\";\nimport { runCredentialLogin } from \"./credential-login.js\";\nimport { GatewayRpcClient, type ConnectionState } from \"./gateway-rpc.js\";\nimport { ensureExactPi } from \"./pi-readiness.js\";\nimport { bindAsleepWake } from \"./asleep-wake.js\";\nimport { podStatusLabel } from \"./pod-status.js\";\nimport { displayRef, matchesRef } from \"./ref.js\";\n\nexport interface AccountSessionOptions {\n client: AccountClient;\n pod: ApiPod;\n /** Direct context for launches, which have already resolved it during preflight. */\n config?: PiPodConfig;\n hostCwd?: string;\n /** Attach can resolve local UI config while the gateway connection opens. */\n loadContext?: () => Promise<{ config: PiPodConfig; hostCwd: string }>;\n startupPrompt?: string | undefined;\n /** Per-invocation UI-only override; never mutates the shared pod session. */\n tuiMode?: TuiMode | undefined;\n /**\n * Extension command names that execute in the launcher's local extension host\n * instead of the pod (see RemoteRuntimeOptions.localCommands). Default: none —\n * the pod owns every slash command; use `/pod local <name>` for one-off runs.\n */\n localCommands?: string[] | undefined;\n /** Verified shim hello boundary: Pi is running, so launch cancellation must stop deleting. */\n onPiStarted?: (() => void) | undefined;\n stdin?: NodeJS.ReadStream | undefined;\n stdout?: NodeJS.WriteStream | undefined;\n stderr?: NodeJS.WriteStream | undefined;\n}\n\nexport interface AccountSessionResult {\n exitCode: number;\n /** What the ending asked of the pod; the caller reports, the server executes. */\n podAction: \"none\" | \"stopped\" | \"archived\";\n}\n\n/** User-facing explanation for an unexpected account-session ending. */\nexport function accountSessionLossNotice(podId: string, serverReason: string | null): string[] {\n const podRef = displayRef(podId, \"pod\");\n if (serverReason === \"idle_stop\") {\n return [\n `pod ${podRef} was stopped after inactivity; its filesystem is preserved`,\n `resume with: pipod attach ${podRef}`,\n ];\n }\n if (serverReason === \"restore_required\" || serverReason === \"archived\") {\n return [`pod ${podRef} was archived — \\`pipod attach ${podRef}\\` restores it`];\n }\n return [\n ...(serverReason === null ? [] : [`session ended by the server: ${serverReason}`]),\n `connection lost — pod ${podRef} keeps running; \\`pipod attach\\` to reattach`,\n ];\n\n}\n\nfunction isArchivedAsleepReason(reason: string): boolean {\n return reason === \"archived\" || reason === \"archive\" || reason === \"provider_archived\" || reason === \"restore_required\";\n\n}\n\n/** One-shot toast on each visit to asleep. */\nexport function asleepCompletionNotice(reason: string): string | null {\n if (!isWakeableAsleepReason(reason)) return null;\n // The whole machine went down, not just this pod. Saying \"stopped after going idle\" would\n // be true of the pod and useless about the wait: starting a workstation took minutes every\n // time it was measured.\n if (isWorkstationAsleepReason(reason)) {\n return \"your workstation stopped — transcript above is complete; press Enter to start it (several minutes; your files are retained)\";\n }\n if (isArchivedAsleepReason(reason)) {\n return \"pod was archived — press Enter to restore & reattach\";\n }\n return \"pod stopped after going idle — transcript above is complete; press Enter to wake\";\n\n}\n\n/** Status-line copy for the account-mode connection indicator. */\nexport function connectionStatusText(state: ConnectionState, podRef?: string): string {\n const name = podRef ? `pod ${podRef}` : \"pod\";\n switch (state.kind) {\n case \"connected\":\n return `${name} connected`;\n case \"reconnecting\":\n return `connection lost — reconnecting (attempt ${state.attempt}; q, Esc, or Ctrl-C to quit)…`;\n case \"asleep\": {\n if (isWorkstationAsleepReason(state.reason)) {\n return \"workstation stopped — press Enter to start it (several minutes), /quit to exit\";\n }\n if (isWakeableAsleepReason(state.reason)) {\n const why = isArchivedAsleepReason(state.reason) ? \"archived\" : \"idle\";\n const wake = isArchivedAsleepReason(state.reason)\n ? \"press Enter to restore & reattach\"\n : \"press Enter or type to wake\";\n return `${name} stopped (${why}) — ${wake}, /quit to exit`;\n }\n return state.reason\n ? `${name} stopped (${state.reason}) — /quit to exit`\n : `${name} stopped — /quit to exit`;\n }\n case \"lost\":\n return \"connection lost — still retrying (q, Esc, or Ctrl-C to quit)\";\n case \"ended\":\n if (state.reason === \"restore_required\" || state.reason === \"archived\") {\n return podRef\n ? `${name} was archived — pipod attach ${podRef} restores it`\n : `${name} was archived — pipod attach restores it`;\n }\n return state.reason ? `session ended — ${state.reason}` : \"session ended\";\n }\n\n}\n\nexport function connectionAllowsQuit(state: ConnectionState | null): boolean {\n return state?.kind === \"reconnecting\" || state?.kind === \"lost\";\n}\n\n/** Account-only escape hatch while Pi's ordinary input path has no usable transport. */\nexport function disconnectedQuitInput(\n data: string,\n disconnected: boolean,\n onQuit: () => void,\n): { consume: true } | undefined {\n if (!disconnected || isKeyRelease(data) || isKeyRepeat(data)) return undefined;\n const quitKeys: KeyId[] = [\"q\", \"escape\", \"ctrl+c\"];\n if (!quitKeys.some((key) => matchesKey(data, key))) return undefined;\n onQuit();\n return { consume: true };\n}\n\nexport function wireDisconnectedQuit(\n bridge: {\n ui: HostUiContext | null;\n setIntent(intent: { kind: \"quit\" }): boolean;\n notify(message: string, type?: \"info\" | \"warning\" | \"error\"): void;\n requestShutdown(): void;\n },\n isDisconnected: () => boolean,\n): () => void {\n return bridge.ui?.onTerminalInput?.((data) =>\n disconnectedQuitInput(data, isDisconnected(), () => {\n if (!bridge.setIntent({ kind: \"quit\" })) return;\n bridge.notify(\"leaving the disconnected session…\", \"info\");\n bridge.requestShutdown();\n }),\n ) ?? (() => {});\n}\n\n/**\n * `/pod status`, account edition (§5.4): the same report local mode prints, sourced from the\n * pod row instead of the provider — the server owns the control plane here, and\n * `resolved_config` is the merge the pod actually ran under.\n *\n * Provider state is not exposed in account mode, so readiness comes from the API's\n * provider-agnostic `ready` flag and is spelled in the vocabulary the shared renderer\n * already understands.\n */\nexport function accountPodStatusLines(pod: ApiPod): string[] {\n const resolved = pod.resolvedConfig;\n const archiveAfterMinutes =\n resolved.archiveTransition?.kind === \"same-as-stop\"\n ? null\n : resolved.archiveAfterMinutes !== undefined\n ? resolved.archiveAfterMinutes\n : resolved.archiveAfterDays !== undefined\n ? resolved.archiveAfterDays * 24 * 60\n : null;\n return buildPodStatusLines({\n podId: pod.id,\n provider: pod.provider,\n state: pod.ready ? \"started\" : \"starting\",\n project: pod.project ?? pod.name,\n image: resolved.image ?? \"(server default)\",\n egress: resolved.egress.description,\n idleTimeoutMinutes: resolved.idleTimeoutMinutes ?? 0,\n archiveAfterMinutes,\n ...(resolved.archiveTransition ? { archiveTransition: resolved.archiveTransition } : {}),\n createdAtMs: Date.parse(pod.createdAt),\n });\n}\n\nexport async function runAccountSession(opts: AccountSessionOptions): Promise<AccountSessionResult> {\n const stdin = opts.stdin ?? process.stdin;\n const stdout = opts.stdout ?? process.stdout;\n const interactive = stdin.isTTY === true && stdout.isTTY === true;\n\n return interactive ? runAccountInteractive(opts) : runAccountHeadless(opts);\n}\n\nasync function connectClient(\n opts: AccountSessionOptions,\n callbacks: {\n onRecovered?: () => void | Promise<void>;\n onLost?: () => void;\n onSessionEnded?: (reason: string) => void;\n onConnectionState?: (state: ConnectionState) => void;\n },\n readiness: { interactive: boolean; approve?: (question: string) => Promise<boolean> },\n) : Promise<GatewayRpcClient> {\n let interrupted = false;\n const onInterrupt = (): void => {\n interrupted = true;\n };\n process.on(\"SIGINT\", onInterrupt);\n let rpc: GatewayRpcClient;\n try {\n rpc = await GatewayRpcClient.connect({\n client: opts.client,\n podId: opts.pod.id,\n onRecovered: callbacks.onRecovered,\n onLost: callbacks.onLost,\n onSessionEnded: callbacks.onSessionEnded,\n onConnectionState: callbacks.onConnectionState,\n workstationWait: { cancelled: () => interrupted },\n });\n } finally {\n process.off(\"SIGINT\", onInterrupt);\n }\n const hello = rpc.helloInfo;\n if (!hello) {\n rpc.close();\n throw new PiPodError(\"the server session carried no pod handshake\", {\n hint: \"the pod may still be starting — retry in a moment, or check `pipod list`\",\n });\n }\n await ensureExactPi({\n client: opts.client,\n pod: opts.pod,\n rpc,\n interactive: readiness.interactive,\n ...(readiness.approve ? { approve: readiness.approve } : {}),\n });\n try {\n opts.onPiStarted?.();\n } catch (error) {\n rpc.close();\n throw error;\n }\n return rpc;\n}\n\n// ---------------------------------------------------------------------------\n// Interactive: pi's real InteractiveMode, gateway transport (§6.2)\n// ---------------------------------------------------------------------------\n\nfunction applyConnectionStatus(\n ui: HostUiContext | null | undefined,\n state: ConnectionState,\n podId: string,\n) : void {\n ui?.setStatus?.(\"pod-connection\", connectionStatusText(state, displayRef(podId, \"pod\")));\n}\n\ninterface FooterSession {\n sessionManager: { getCwd(): string; getEntries?(): unknown[] };\n}\n\ninterface AccountFooterInternals {\n session?: FooterSession;\n footer?: { setSession(session: FooterSession): void };\n footerDataProvider?: {\n setCwd(cwd: string): void;\n getGitBranch(): string | null;\n };\n}\n\n/**\n * The footer sums usage over the full session log, but the remote cache holds only the\n * active context branch. This entry carries the difference (pre-compaction messages,\n * abandoned branches) in the one shape the footer already adds to its totals — and it is\n * visible to the footer alone, so the transcript, tree, and fork picker never see it.\n */\nfunction hiddenUsageEntry(hidden: UsageTotals): unknown {\n return {\n type: \"branch_summary\",\n id: \"pi-pod:hidden-usage\",\n parentId: null,\n timestamp: \"\",\n fromId: \"\",\n summary: \"\",\n usage: {\n input: hidden.input,\n output: hidden.output,\n cacheRead: hidden.cacheRead,\n cacheWrite: hidden.cacheWrite,\n cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: hidden.cost },\n },\n };\n}\n\n/** Keep Pi's built-in footer, but feed its location row from the remote pod only. */\nexport function bindAccountFooterContext(\n mode: AccountFooterInternals,\n initialWorkdir: string,\n hiddenUsage?: () => UsageTotals | null,\n): { setWorkdir(workdir: string): void } {\n let workdir = initialWorkdir;\n const footer = mode.footer;\n const session = mode.session;\n if (!footer || !session) return { setWorkdir: (next) => { workdir = next; } };\n\n const wrapSession = (nextSession: FooterSession): FooterSession =>\n new Proxy(nextSession, {\n get(target, property, receiver) {\n if (property !== \"sessionManager\") return Reflect.get(target, property, receiver);\n return new Proxy(target.sessionManager, {\n get(manager, managerProperty, managerReceiver) {\n if (managerProperty === \"getCwd\") return () => workdir;\n if (managerProperty === \"getEntries\" && hiddenUsage) {\n const real = Reflect.get(manager, managerProperty, managerReceiver) as\n | (() => unknown[])\n | undefined;\n if (typeof real === \"function\") {\n return () => {\n const entries = real.call(manager) ?? [];\n const hidden = hiddenUsage();\n return hidden ? [...entries, hiddenUsageEntry(hidden)] : entries;\n };\n }\n }\n return Reflect.get(manager, managerProperty, managerReceiver);\n },\n });\n },\n });\n const setSession = footer.setSession.bind(footer);\n footer.setSession = (nextSession) => setSession(wrapSession(nextSession));\n footer.setSession(session);\n\n const provider = mode.footerDataProvider;\n if (provider) {\n // An absolute non-workspace path prevents Pi's branch watcher from inspecting the host checkout.\n provider.setCwd(\"/proc/pi-pod-account-footer\");\n provider.getGitBranch = () => null;\n }\n\n return {\n setWorkdir: (next) => { workdir = next; },\n };\n}\n\nasync function runAccountInteractive(opts: AccountSessionOptions): Promise<AccountSessionResult> {\n let runtimeRef: RemoteRuntime | null = null;\n let modeUi: { stop(): void; start(): void; requestRender?(force?: boolean): void } | null = null;\n let rpc: GatewayRpcClient | undefined;\n let readinessPod = opts.pod;\n const approvePiUpdate = async (question: string): Promise<boolean> => {\n const ui = runtimeRef?.bridge.ui;\n if (ui?.confirm) return ui.confirm(\"Update Pi in pod\", question);\n return confirm(question, { nonInteractiveDefault: false });\n };\n const asleepWake = bindAsleepWake({\n stdin: opts.stdin ?? process.stdin,\n wake: () => {\n void rpc?.wake().catch(() => {});\n },\n wakeableReasons: WAKEABLE_ASLEEP_REASONS,\n });\n\n let lastAsleepKey: string | null = null;\n let pendingAsleepNotice: string | null = null;\n const noteAsleep = (state: ConnectionState): void => {\n asleepWake.onConnectionState(state);\n if (state.kind !== \"asleep\") {\n lastAsleepKey = null;\n return;\n }\n runtimeRef?.cache.forceIdle();\n modeUi?.requestRender?.(true);\n if (lastAsleepKey === state.reason) return;\n lastAsleepKey = state.reason;\n const notice = asleepCompletionNotice(state.reason);\n if (!notice) return;\n if (!runtimeRef) {\n pendingAsleepNotice = notice;\n return;\n }\n const notify = () => runtimeRef?.bridge.notify(notice, \"info\");\n if (runtimeRef.bridge.ui) notify();\n else runtimeRef.bridge.onUiBound(notify);\n };\n\n let serverEndReason: string | null = null;\n let pendingConnectionState: ConnectionState | null = null;\n let latestConnectionState: ConnectionState | null = null;\n const rpcPromise = connectClient(opts, {\n onRecovered: async () => {\n if (!rpc) throw new PiPodError(\"the recovered session has no transport\");\n await ensureExactPi({\n client: opts.client,\n pod: readinessPod,\n rpc,\n interactive: true,\n approve: approvePiUpdate,\n });\n // Outcome-valued and serialized; a sync failure must not read as a failed recovery.\n if (podSync) {\n const outcome = await podSync.sync(\"reconnect\");\n if (outcome.kind === \"applied\" && outcome.changed) {\n runtimeRef?.bridge.notify(\"pod settings changed while disconnected — refreshed\", \"info\");\n }\n if (outcome.kind === \"applied\" && outcome.drift) {\n runtimeRef?.bridge.notify(\n \"pod config changed on disk after pi started — the agent's process may run older config until it restarts\",\n \"warning\",\n );\n }\n }\n await runtimeRef?.recoverAfterReconnect();\n modeUi?.requestRender?.(true);\n runtimeRef?.bridge.notify(\"connection dropped — reconnected to the pi session\", \"info\");\n },\n onLost: () => {\n // Stay in the TUI so the account-side lost-state keys can end the unusable session.\n },\n onSessionEnded: (reason) => {\n // Preserve the semantic reason until the TUI has shut down, when terminal output is stable.\n serverEndReason = reason;\n // Paint the reason on the last frame, then tear down as today.\n const state: ConnectionState = { kind: \"ended\", reason };\n if (runtimeRef) applyConnectionStatus(runtimeRef.bridge.ui, state, rpc?.podId ?? opts.pod.id);\n else pendingConnectionState = state;\n runtimeRef?.bridge.setIntent({ kind: \"transportLost\" });\n runtimeRef?.bridge.requestShutdown();\n },\n onConnectionState: (state) => {\n latestConnectionState = state;\n noteAsleep(state);\n if (runtimeRef) {\n const paint = () => applyConnectionStatus(runtimeRef?.bridge.ui, state, rpc?.podId ?? opts.pod.id);\n if (runtimeRef.bridge.ui) paint();\n else runtimeRef.bridge.onUiBound(paint);\n if (state.kind === \"lost\") {\n runtimeRef.bridge.notify(\n state.reason ? `could not reconnect: ${state.reason}` : \"connection lost\",\n \"error\",\n );\n // Stay alive: do not set transportLost or request shutdown.\n }\n } else {\n pendingConnectionState = state;\n }\n },\n }, { interactive: true, approve: approvePiUpdate });\n const contextPromise = opts.loadContext\n ? opts.loadContext()\n : Promise.resolve({ config: opts.config!, hostCwd: opts.hostCwd! });\n let context: { config: PiPodConfig; hostCwd: string };\n try {\n [rpc, context] = await Promise.all([rpcPromise, contextPromise]);\n } catch (error) {\n asleepWake.dispose();\n void rpcPromise.then((connected) => connected.close(), () => {});\n throw error;\n }\n if (!rpc) throw new Error(\"account session connected without a transport\");\n\n let ending: {\n kind: \"quit\" | \"leave\" | \"hangup\" | \"transportLost\";\n action: \"keep\" | \"archive\" | null;\n exitCode: number | null;\n } | null = null;\n let resolveEnding!: () => void;\n const endingPromise = new Promise<void>((resolve) => {\n resolveEnding = resolve;\n });\n\n // --- pod-derived TUI config (data channel): sync before the runtime binds settings ------\n let derived: DerivedPodConfig | null = null;\n let podSync: PodConfigSync | null = null;\n let attachOutcome: import(\"./pod-config-sync.js\").PodConfigSyncOutcome | null = null;\n let attachSyncNotice: { message: string; type: \"info\" | \"warning\" } | null = null;\n let themesDir: string | null = null;\n let podThemeLoader: Awaited<ReturnType<typeof loadPodThemeLoader>> = null;\n const cacheRoot = defaultPodCacheRoot();\n if (cacheRoot) {\n let candidate: DerivedPodConfig | null = null;\n try {\n candidate = createDerivedPodConfig({ cacheRoot, hostAgentDir: defaultHostAgentDir() });\n const sync = createPodConfigSync({\n rpc,\n derived: candidate,\n cacheRoot,\n serverHost: new URL(opts.client.serverUrl).host,\n });\n const outcome = await sync.sync(\"attach\");\n attachOutcome = outcome;\n attachSyncNotice = podConfigSyncNotice(outcome);\n if (outcome.kind === \"applied\") {\n derived = candidate;\n podSync = sync;\n themesDir = candidate.themesDir;\n podThemeLoader = await loadPodThemeLoader();\n } else {\n // Fall back to today's exact behavior: host settings, host project merge included.\n candidate.dispose();\n }\n } catch (error) {\n candidate?.dispose();\n derived = null;\n podSync = null;\n attachSyncNotice = {\n message: `pod settings sync failed: ${error instanceof Error ? error.message : String(error)}; using host settings`,\n type: \"warning\",\n };\n }\n }\n\n // --- pod-derived TUI config (code channel): server-attested extension rendering ----------\n // Specs come only from the launch-resolved set the server recorded; the packages are\n // downloaded from the registry by this client. Pod-disk state can never join this set.\n let attestedSpecs: AttestedPackage[] = [];\n let attestedPaths: string[] = [];\n const attestedNotices: Array<{ message: string; type: \"info\" | \"warning\" }> = [];\n if (derived && cacheRoot) {\n const attested = attestedPackages(opts.pod.resolvedConfig.piSettings);\n attestedSpecs = attested.specs;\n for (const refusal of attested.refused) {\n attestedNotices.push({ message: `pod extension not run locally: ${refusal}`, type: \"warning\" });\n }\n const { trusted, declined } = await trustAttestedPackages(attested.specs, {\n cacheRoot,\n ask: (question) => confirm(question, { nonInteractiveDefault: false }),\n });\n if (declined.length > 0) {\n attestedNotices.push({\n message: `pod extensions not run locally (not trusted on this machine): ${declined.map((spec) => `${spec.name}@${spec.version}`).join(\", \")}`,\n type: \"info\",\n });\n }\n if (trusted.length > 0) {\n try {\n const installed = await installAttestedPackages(trusted, { cacheRoot });\n attestedPaths = installed.paths;\n for (const warning of installed.warnings) attestedNotices.push({ message: warning, type: \"warning\" });\n } catch (error) {\n attestedNotices.push({\n message: `pod extension install failed: ${error instanceof Error ? error.message : String(error)} — rendering stays generic`,\n type: \"warning\",\n });\n }\n }\n if (attachOutcome?.kind === \"applied\") {\n const warning = unattestedPackageNotice(attachOutcome.extensions, attested.specs);\n if (warning) attestedNotices.push({ message: warning, type: \"warning\" });\n }\n }\n let localRenderingActive = attestedPaths.length > 0;\n\n const podHost: PodCommandHost = {\n // Read fresh rather than reporting the pod as it was at attach: readiness and the idle\n // policy are exactly what someone runs /pod status to check, and `rpc.podId` follows a\n // switch.\n status: async () => accountPodStatusLines(await opts.client.getPod(rpc.podId)),\n list: async () => switchPod(undefined),\n switchPod: async (id?: string) => switchPod(id),\n sync: async () => {\n if (!podSync || !runtimeRef) {\n runtimeRef?.bridge.notify(\n \"pod-derived settings are not active in this session — reattach once the pod runs a current shim\",\n \"warning\",\n );\n return;\n }\n const outcome = await podSync.sync(\"manual\");\n if (outcome.kind === \"applied\") {\n runtimeRef.bridge.notify(\n `pod settings synced (${outcome.digest.slice(0, 8)}${outcome.changed ? \"\" : \", unchanged\"}` +\n `${outcome.drift ? \"; pi may run older config until it restarts\" : \"\"})`,\n \"info\",\n );\n } else {\n const notice = podConfigSyncNotice(outcome);\n if (notice) runtimeRef.bridge.notify(notice.message, notice.type);\n }\n },\n };\n\n const accountAuthSupported = async (providerId: string, authType?: \"oauth\" | \"api_key\"): Promise<boolean> => {\n const provider = (await opts.client.modelCredentials()).providers.find((candidate) => candidate.id === providerId);\n if (!provider?.brokerSupported) return false;\n if (authType === \"oauth\") return provider.oauth !== null;\n if (authType === \"api_key\") return provider.apiKey;\n return provider.oauth !== null || provider.apiKey;\n };\n\n const runtime: RemoteRuntime = createRemoteRuntime({\n rpc,\n cwd: context.hostCwd,\n ...(derived ? { agentDir: derived.agentDir, settingsCwd: derived.settingsCwd } : {}),\n ...(themesDir && podThemeLoader\n ? {\n getLocalThemes: () => podThemeLoader!.load(themesDir!),\n }\n : {}),\n getAvailableThinkingLevels: async () => (await rpc.getModels()).thinkingLevels,\n // Auxiliary completions: the pod's authenticated registry executes them turn-externally.\n auxComplete: (request, opts) => rpc.auxComplete(request, opts),\n // Local command ownership is explicit: empty by default (the pod owns every slash\n // command); `/pod local <name>` always works without any setting.\n ...(opts.localCommands?.length ? { localCommands: opts.localCommands } : {}),\n // `@` completion: the pod's workspace is the only one whose paths the agent can act on.\n listPodFiles: async (query) => {\n const frame = await rpc.getFiles(query);\n return { entries: frame.entries, complete: frame.complete };\n },\n ...(!opts.client.isPodToken ? {\n accountAuthSupported,\n accountLogin: (providerId: string, authType: \"oauth\" | \"api_key\", interaction: RemoteAuthInteraction) => runCredentialLogin({\n client: opts.client,\n providerId,\n authType,\n podId: rpc.podId,\n interaction,\n }),\n accountLogout: (providerId: string) => opts.client.deleteModelCredential(providerId),\n } : {}),\n podHost,\n ...(attestedPaths.length > 0 ? { attestedExtensionPaths: attestedPaths } : {}),\n waitForRemoteExitOnQuit: () => latestConnectionState?.kind !== \"lost\",\n onPodCommandSubmit: () => {\n modeEditor?.setText(\"\");\n modeUi?.requestRender?.();\n },\n onEnding: async (runtimeEnding) => {\n if (ending) return;\n ending = {\n kind: runtimeEnding.intent.kind,\n action: runtimeEnding.intent.kind === \"leave\" ? runtimeEnding.intent.action : null,\n exitCode: runtimeEnding.exitCode,\n };\n // The transport is ours alone; closing it detaches this client and nothing else.\n rpc.close();\n derived?.dispose();\n resolveEnding();\n },\n });\n runtimeRef = runtime;\n podSync?.setOnAfterApply(() => runtime.reloadSettings());\n if (attachSyncNotice) {\n const notice = attachSyncNotice;\n runtime.bridge.onUiBound(() => runtime.bridge.notify(notice.message, notice.type));\n }\n if (pendingConnectionState) {\n const buffered = pendingConnectionState;\n noteAsleep(buffered);\n runtime.bridge.onUiBound(() => applyConnectionStatus(runtime.bridge.ui, buffered, rpc.podId));\n pendingConnectionState = null;\n }\n if (pendingAsleepNotice) {\n const notice = pendingAsleepNotice;\n pendingAsleepNotice = null;\n runtime.bridge.onUiBound(() => runtime.bridge.notify(notice, \"info\"));\n }\n for (const notice of attestedNotices) {\n runtime.bridge.onUiBound(() => runtime.bridge.notify(notice.message, notice.type));\n }\n const initialCompatibilityWarning = shimCompatibilityWarning(rpc.helloInfo?.shimVersion ?? \"\");\n if (initialCompatibilityWarning) {\n runtime.bridge.onUiBound(() => runtime.bridge.notify(initialCompatibilityWarning, \"warning\"));\n }\n let modeEditor: { setText(text: string): void } | null = null;\n\n rpc.onControl((event) => {\n if (event.event === \"pi_exit\") {\n runtime.bridge.setIntent({ kind: \"quit\" });\n runtime.bridge.requestShutdown();\n } else if (event.event === \"event_replay_gap\") {\n runtime.bridge.notify(\"some output was skipped\", \"warning\");\n }\n });\n const onHangUp = () => runtime.bridge.setHangupIntent();\n\n let footerContext: { setWorkdir(workdir: string): void } | null = null;\n\n // --- /pod switch, server-side (§6.2) --------------------------------------\n let switching = false;\n const switchPod = async (id: string | undefined): Promise<void> => {\n if (switching) return;\n switching = true;\n try {\n const { pods } = await opts.client.listPods({ mine: true, limit: 50 });\n const candidates = pods.filter((p) => p.state === \"active\");\n let target: ApiPod | undefined;\n if (id !== undefined) {\n target = candidates.find((pod) => pod.id.toLowerCase() === id.toLowerCase());\n const named = target ? [] : candidates.filter((pod) => pod.name === id);\n const referenced = target || named.length > 0 ? [] : candidates.filter((pod) => matchesRef(pod.id, id));\n const matches = target ? [target] : named.length > 0 ? named : referenced;\n if (matches.length > 1) {\n const refs = matches.map((pod) => displayRef(pod.id, \"pod\"));\n const counts = new Map<string, number>();\n for (const ref of refs) counts.set(ref, (counts.get(ref) ?? 0) + 1);\n const choices = matches.map((pod, index) => {\n const ref = refs[index]!;\n return ` ${counts.get(ref)! > 1 ? pod.id : ref} ${pod.name} (${pod.state})`;\n });\n runtime.bridge.notify(\n `\"${id}\" matches ${matches.length} pods — use a longer ref:\\n${choices.join(\"\\n\")}`,\n \"warning\",\n );\n return;\n }\n target = matches[0];\n if (!target) {\n runtime.bridge.notify(`no pod matches \"${id}\"`, \"warning\");\n return;\n }\n } else {\n if (candidates.length === 0) {\n runtime.bridge.notify(\"no pods to switch to\", \"info\");\n return;\n }\n const refs = candidates.map((pod) => displayRef(pod.id, \"pod\"));\n const counts = new Map<string, number>();\n for (const ref of refs) counts.set(ref, (counts.get(ref) ?? 0) + 1);\n const labels = candidates.map((p, index) => {\n const ref = refs[index]!;\n const label = `${counts.get(ref)! > 1 ? p.id : ref} ${p.name} ${podStatusLabel(p)}`;\n return p.id === rpc.podId ? `${label} (current)` : label;\n });\n const choice = await runtime.bridge.ui?.select?.(\"Switch to pod\", labels);\n if (choice === undefined) return;\n target = candidates[labels.indexOf(choice)];\n if (!target) return;\n }\n if (target.id === rpc.podId) {\n runtime.bridge.notify(\"already attached to that pod\", \"info\");\n return;\n }\n runtime.bridge.notify(`switching to pod ${displayRef(target.id, \"pod\")}…`, \"info\");\n try {\n await rpc.switchTo(target.id);\n readinessPod = target;\n await ensureExactPi({\n client: opts.client,\n pod: target,\n rpc,\n interactive: true,\n approve: approvePiUpdate,\n });\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n runtime.bridge.notify(\n /staying on/.test(message) ? message : `${message} — reattach with \\`pipod attach\\``,\n \"error\",\n );\n if (rpc.podId === target.id) {\n rpc.close();\n runtime.bridge.setIntent({ kind: \"transportLost\" });\n runtime.bridge.requestShutdown();\n }\n return;\n }\n // Notices staged until after the reseed: refreshAfterReplacement rebuilds the\n // transcript and erases anything notified before it.\n const postSwitchNotices: Array<{ message: string; type: \"info\" | \"warning\" }> = [];\n if (podSync) {\n // Sync the target before the TUI reseeds; on any non-applied outcome the pipeline\n // has already fallen back to host-only settings — never pod A's against pod B.\n const outcome = await podSync.sync(\"switch\");\n const notice = podConfigSyncNotice(outcome);\n if (notice) postSwitchNotices.push(notice);\n if (localRenderingActive) {\n // Loaded code cannot be unloaded; a differing attested set stops being consulted.\n const targetAttested = attestedPackages(target.resolvedConfig.piSettings).specs;\n const sameSet =\n targetAttested.length === attestedSpecs.length &&\n targetAttested.every((spec) =>\n attestedSpecs.some((a) => a.name === spec.name && a.version === spec.version),\n );\n if (!sameSet) {\n localRenderingActive = false;\n await runtime.disableLocalExtensions();\n postSwitchNotices.push({\n message: \"the new pod's extension set differs — pod extension rendering is off until you reattach\",\n type: \"info\",\n });\n }\n }\n if (outcome.kind === \"applied\" && localRenderingActive) {\n const message = unattestedPackageNotice(outcome.extensions, attestedSpecs);\n if (message) postSwitchNotices.push({ message, type: \"warning\" });\n }\n }\n footerContext?.setWorkdir(target.resolvedConfig.workdir ?? \"remote pod workdir\");\n await runtime.refreshAfterReplacement();\n modeUi?.requestRender?.(true);\n if (postSwitchNotices.length > 0) {\n // Notified on a short delay: anything sent while the reseed is still repainting\n // lands in a surface the rebind throws away (the pre-switch \"switching to\" notice\n // has always been lost this way).\n setTimeout(() => {\n for (const notice of postSwitchNotices) runtime.bridge.notify(notice.message, notice.type);\n modeUi?.requestRender?.(true);\n }, 750);\n }\n const compatibilityWarning = shimCompatibilityWarning(rpc.helloInfo?.shimVersion ?? \"\");\n if (compatibilityWarning) runtime.bridge.notify(compatibilityWarning, \"warning\");\n runtime.bridge.notify(`switched to pod ${displayRef(target.id, \"pod\")} (${target.project ?? target.name})`, \"info\");\n } catch (e) {\n runtime.bridge.notify(`switch failed: ${e instanceof Error ? e.message : String(e)}`, \"error\");\n } finally {\n switching = false;\n }\n };\n\n let unwireChords: () => void = () => {};\n let unwireDisconnectedQuit: () => void = () => {};\n let mode: InstanceType<typeof import(\"@earendil-works/pi-coding-agent\").InteractiveMode>;\n // Seeding and building the TUI is the one stretch with a live socket and nothing to close\n // it: no UI has bound, so no ending can fire, and an unreported failure here would leave\n // the process alive on an open gateway connection long after the error was printed.\n try {\n await runtime.init();\n\n const { InteractiveMode } = await import(\"@earendil-works/pi-coding-agent\");\n const { wirePodChords } = await import(\"../client/runtime/chords.js\");\n\n const chords = context.config.pi.chords;\n runtime.bridge.setOnUiBound(() => {\n unwireChords();\n unwireDisconnectedQuit();\n unwireChords = wirePodChords(runtime.bridge, runtime.router, chords);\n unwireDisconnectedQuit = wireDisconnectedQuit(\n runtime.bridge,\n () => connectionAllowsQuit(latestConnectionState),\n );\n });\n\n const tuiMode = opts.tuiMode ?? tuiModeFromArgv(context.config.pi.args);\n // This pi is the one pi pod bundles, pinned to the server's: \"run pi update\" cannot apply.\n // `pipod update` is the upgrade path.\n process.env[\"PI_SKIP_VERSION_CHECK\"] ??= \"1\";\n mode = new InteractiveMode(runtime.runtimeHost as never, {\n ...(opts.startupPrompt !== undefined ? { initialMessage: opts.startupPrompt } : {}),\n ...(tuiMode ? { tuiMode } : {}),\n });\n installPodTerminalTitle(mode as never);\n installPodCommandOverrides(\n mode,\n runtime,\n rpc,\n () => readinessPod.resolvedConfig.workdir ?? context.config.workdir,\n );\n const modeInternals = mode as unknown as AccountFooterInternals & {\n ui?: { stop(): void; start(): void; requestRender?(force?: boolean): void };\n editor?: { setText(text: string): void };\n };\n footerContext = bindAccountFooterContext(\n modeInternals,\n opts.pod.resolvedConfig.workdir ?? context.config.workdir,\n () => runtime.cache.hiddenUsage,\n );\n modeUi = modeInternals.ui ?? null;\n runtime.cache.onRefreshed = () => modeUi?.requestRender?.();\n modeEditor = modeInternals.editor ?? null;\n await runtime.healStreamingRenderer();\n } catch (error) {\n asleepWake.dispose();\n runtime.bridge.setOnUiBound(null);\n unwireChords();\n unwireDisconnectedQuit();\n rpc.close();\n derived?.dispose();\n throw error;\n }\n\n // Same exit interception as the local path: InteractiveMode ends in process.exit(0), but\n // the launcher still has server lifecycle calls to make and an exit code to report.\n const realExit = process.exit.bind(process) as (code?: number) => never;\n const patchedExit = ((code?: number) => {\n if (ending) return undefined as never;\n return realExit(code);\n }) as typeof process.exit;\n process.exit = patchedExit;\n\n try {\n const modeRun = mode.run();\n process.prependListener(\"SIGHUP\", onHangUp);\n process.prependListener(\"SIGTERM\", onHangUp);\n void modeRun.catch((e: unknown) => {\n warn(`the TUI failed: ${e instanceof Error ? e.message : String(e)}`);\n runtime.bridge.setIntent({ kind: \"transportLost\" });\n runtime.bridge.requestShutdown();\n });\n await endingPromise;\n } finally {\n asleepWake.dispose();\n if (!ending) process.exit = realExit;\n runtime.bridge.setOnUiBound(null);\n unwireChords();\n unwireDisconnectedQuit();\n process.off(\"SIGHUP\", onHangUp);\n process.off(\"SIGTERM\", onHangUp);\n }\n\n const result = await applyEnding(opts, context.config, ending!, serverEndReason, rpc.podId);\n // InteractiveMode counts on the process.exit(0) this launcher swallows to collect the\n // TUI handles its shutdown leaks (the custom-themes FSWatcher, raw stdin), so the event\n // loop never drains on its own — flush the goodbye lines and exit explicitly.\n if (process.stdout.writableLength > 0) {\n await new Promise((resolve) => process.stdout.once(\"drain\", resolve));\n }\n if (process.stderr.writableLength > 0) {\n await new Promise((resolve) => process.stderr.once(\"drain\", resolve));\n }\n return realExit(result.exitCode);\n}\n\nasync function applyEnding(\n opts: AccountSessionOptions,\n config: PiPodConfig,\n ending: { kind: string; action: \"keep\" | \"archive\" | null; exitCode: number | null },\n serverEndReason: string | null,\n activePodId: string,\n): Promise<AccountSessionResult> {\n const podRef = displayRef(activePodId, \"pod\");\n switch (ending.kind) {\n case \"leave\": {\n if (ending.action === \"archive\") {\n const archived = await opts.client.podCommand(activePodId, \"archive\");\n info(\n archived.message ??\n `pod ${podRef} hidden from active lists; provider compute and durable archival follow the configured idle/retention policy`,\n );\n info(`restore to active lists with: pipod restore ${podRef}`);\n return { exitCode: 0, podAction: \"archived\" };\n }\n info(`detached — pod ${podRef} keeps running (\\`pipod attach\\` to return; the server reaps idle pods)`);\n return { exitCode: 0, podAction: \"none\" };\n }\n case \"quit\":\n return applyAccountQuitPolicy({ activePodId, exitCode: ending.exitCode ?? 0 });\n case \"hangup\":\n return { exitCode: 0, podAction: \"none\" };\n default:\n for (const line of accountSessionLossNotice(activePodId, serverEndReason)) info(line);\n return { exitCode: 1, podAction: \"none\" };\n }\n}\n\n/**\n * Quit is a detach, never a lifecycle event: the pod keeps processing and the server's idle\n * policy (or an explicit `pipod stop`) reclaims it. What used to be `autoStopOnExit` /\n * `--keep` is retired — a host running co-located workers must never die because one client\n * closed its terminal.\n */\nexport function applyAccountQuitPolicy(opts: {\n activePodId: string;\n exitCode: number;\n}): AccountSessionResult {\n const podRef = displayRef(opts.activePodId, \"pod\");\n info(`session ended — pod ${podRef} keeps running (the server reaps idle pods; \\`pipod stop ${podRef}\\` stops it now)`);\n info(`return with: pipod attach ${podRef}`);\n return { exitCode: opts.exitCode, podAction: \"none\" };\n}\n\n// ---------------------------------------------------------------------------\n// Headless: `pipod send` and piped launches (§7)\n// ---------------------------------------------------------------------------\n\nasync function runAccountHeadless(opts: AccountSessionOptions): Promise<AccountSessionResult> {\n let lost = false;\n let hangup = false;\n let serverEndReason: string | null = null;\n let resolveGone!: () => void;\n const gone = new Promise<null>((resolve) => {\n resolveGone = () => resolve(null);\n });\n // A settle event can land while the gateway is being replaced. Reconcile Pi's current\n // state after reconnect so a completed one-shot cannot wait forever for the missed event.\n let resolveRecoveredIdle!: () => void;\n const recoveredIdle = new Promise<null>((resolve) => {\n resolveRecoveredIdle = () => resolve(null);\n });\n let rpc!: GatewayRpcClient;\n rpc = await connectClient(opts, {\n onRecovered: async () => {\n await ensureExactPi({ client: opts.client, pod: opts.pod, rpc, interactive: false });\n const state = await rpc.getState();\n if (!state.isStreaming && !state.isCompacting) resolveRecoveredIdle();\n },\n onLost: () => {\n lost = true;\n resolveGone();\n },\n onSessionEnded: (reason) => {\n // Idle-stop / archive is not a terminal loss: a send is an explicit user action, so\n // the transport wakes rather than exiting. Only unavailable endings abort the one-shot.\n if (reason === \"pi_exit\") {\n serverEndReason = reason;\n resolveGone();\n return;\n }\n serverEndReason = reason;\n resolveGone();\n },\n onConnectionState: (state) => {\n if (state.kind === \"asleep\") void rpc.wake().catch(() => {});\n },\n }, { interactive: false });\n\n const onHangUp = () => {\n hangup = true;\n rpc.close();\n resolveGone();\n };\n process.on(\"SIGHUP\", onHangUp);\n process.on(\"SIGTERM\", onHangUp);\n try {\n if (opts.startupPrompt === undefined) {\n // Nothing to send and nothing to render: connecting proved the pod answers.\n info(\"connected; nothing to send (pass a prompt) — detaching\");\n return { exitCode: 0, podAction: \"none\" };\n }\n const loaded = opts.config && opts.hostCwd ? undefined : await opts.loadContext?.();\n const config = opts.config ?? loaded?.config;\n if (!config) throw new Error(\"account session has no resolved config\");\n // One-shot prompts name host files the pod cannot see; attach them inline like the\n // TUI path does. Omission warnings go to stderr — there is no TUI to notify.\n const hostCwd = opts.hostCwd ?? loaded?.hostCwd ?? process.cwd();\n const prepared = await preparePromptImages(opts.startupPrompt, {\n cwd: hostCwd,\n notify: (message) => (opts.stderr ?? process.stderr).write(`${message}\\n`),\n });\n const completion = await Promise.race([\n runHeadless({\n rpc,\n prompt: prepared.text,\n images: prepared.images,\n stdout: opts.stdout ?? process.stdout,\n stderr: opts.stderr ?? process.stderr,\n }).then(\n (exitCode) => ({ kind: \"exit\", exitCode } as const),\n (error: unknown) => ({ kind: \"error\", error } as const),\n ),\n gone.then(() => ({ kind: \"gone\" } as const)),\n recoveredIdle.then(() => ({ kind: \"recoveredIdle\" } as const)),\n ]);\n if (serverEndReason !== null) {\n for (const line of accountSessionLossNotice(rpc.podId, serverEndReason)) info(line);\n }\n if (lost || serverEndReason !== null) return { exitCode: 1, podAction: \"none\" };\n if (completion.kind === \"error\") throw completion.error;\n if (hangup || completion.kind === \"gone\") return { exitCode: 0, podAction: \"none\" };\n return applyAccountQuitPolicy({\n activePodId: rpc.podId,\n exitCode: completion.kind === \"exit\" ? (completion.exitCode ?? 0) : 0,\n });\n } finally {\n process.off(\"SIGHUP\", onHangUp);\n process.off(\"SIGTERM\", onHangUp);\n rpc.close();\n }\n}\n\nexport async function waitForPodReady(\n client: AccountClient,\n podId: string,\n timeoutMs: number,\n): Promise<ApiPod> {\n const deadline = Date.now() + timeoutMs;\n for (;;) {\n const polledAt = Date.now();\n const pod = await client.getPod(podId, { waitMs: 20_000 });\n if (pod.ready) return pod;\n if (pod.stateReason) {\n throw new PiPodError(`pod ${displayRef(podId, \"pod\")} failed: ${pod.stateReason}`);\n }\n if (Date.now() > deadline) {\n throw new PiPodError(`pod ${displayRef(podId, \"pod\")} did not become ready in time`);\n }\n // Older servers ignore the long poll and answer at once; only they need pacing.\n const elapsed = Date.now() - polledAt;\n if (elapsed < 1000) await new Promise((r) => setTimeout(r, 1000 - elapsed));\n }\n}\n","/**\n * src/client/podinfo.ts — the lines `/pod status` shows (§5.4).\n *\n * Client-side facts from the provider control plane and the session plan — the counterpart\n * of the pod-side `/pod:info`, which tells the *agent* the same story from inside.\n */\n\nexport interface PodStatusFacts {\n podId: string;\n provider: string;\n /** Internal provider state; rendered only as provider-agnostic readiness. */\n state: string;\n project: string;\n image: string;\n egress: string;\n /** Effective values, after provider capability clamping (§3.2). */\n idleTimeoutMinutes: number;\n archiveAfterMinutes: number | null;\n /** When present, status renders this instead of inferring from archiveAfterMinutes. */\n archiveTransition?:\n | { kind: \"same-as-stop\"; expiryDays: null }\n | { kind: \"after-stop\"; maxDelayDays: number };\n createdAtMs?: number | undefined;\n}\n\nexport function buildPodStatusLines(facts: PodStatusFacts): string[] {\n const lines = [\n \"pi pod session\",\n ` pod id ${facts.podId}`,\n ` provider ${facts.provider}`,\n ` readiness ${facts.state === \"started\" ? \"ready\" : [\"provisioning\", \"starting\"].includes(facts.state) ? \"initializing\" : \"unavailable\"}`,\n ` project ${facts.project}`,\n ` image ${facts.image}`,\n ` egress ${facts.egress}`,\n ];\n\n lines.push(\n facts.idleTimeoutMinutes === 0\n ? \" retention provider auto-stop off; `pipod gc` is the fallback\"\n : ` retention provider auto-stop after ${facts.idleTimeoutMinutes} min without activity`,\n );\n const sameAsStop = facts.archiveTransition?.kind === \"same-as-stop\" || facts.archiveAfterMinutes === null;\n const storageWindow =\n sameAsStop || facts.archiveAfterMinutes === null\n ? null\n : facts.archiveAfterMinutes < 24 * 60\n ? `${facts.archiveAfterMinutes} min`\n : `${facts.archiveAfterMinutes / (24 * 60)} day(s)`;\n lines.push(\n sameAsStop\n ? \" storage stop is already at-rest; no provider expiry is documented\"\n : ` storage may compact after ${storageWindow}; access restores automatically`,\n );\n lines.push(\" archive logical /pod archive is separate from provider storage compaction\");\n\n if (facts.createdAtMs !== undefined) {\n lines.push(` uptime ${formatUptime(Date.now() - facts.createdAtMs)}`);\n }\n return lines;\n}\n\nfunction formatUptime(ms: number): string {\n const minutes = Math.floor(ms / 60_000);\n if (minutes < 1) return \"less than a minute\";\n const hours = Math.floor(minutes / 60);\n if (hours < 1) return `${minutes}m`;\n const days = Math.floor(hours / 24);\n if (days < 1) return `${hours}h ${minutes % 60}m`;\n return `${days}d ${hours % 24}h`;\n}\n","// Server agentd v13 adds the tui_manifest control command without changing the C/E/S\n// protocol seen by clients. Keep one previous generation attachable.\nexport const SHIM_VERSION = \"13\";\nexport const PREVIOUS_SHIM_VERSION = \"12\";\nexport const SHIM_PATH = \"/tmp/pi-pod-agentd.cjs\";\nexport const SHIM_LOG_PATH = \"/tmp/pi-pod-agentd.log\";\n","export const POD_EXTENSION_VERSION = 11;\n\nexport const TREE_BRIDGE_PROTOCOL_VERSION = 1 as const;\nexport const TREE_BRIDGE_NAVIGATE_COMMAND = \"pod:_tree-navigate-v1\";\n/** Same request as v1, but the acknowledgement carries the target's full editor text. */\nexport const TREE_BRIDGE_NAVIGATE_V2_COMMAND = \"pod:_tree-navigate-v2\";\nexport const TREE_BRIDGE_LABEL_COMMAND = \"pod:_tree-label-v1\";\nexport const TREE_BRIDGE_NOTIFICATION_PREFIX = \"pi-pod-internal/tree-v1:\";\nexport const POD_INTERNAL_COMMAND_PREFIX = \"pod:_\";\n\n/** Auxiliary completions for locally rendered extensions, executed pod-side with real auth. */\nexport const AUX_BRIDGE_PROTOCOL_VERSION = 1 as const;\nexport const AUX_COMPLETE_COMMAND = \"pod:_aux-complete-v1\";\nexport const AUX_CANCEL_COMMAND = \"pod:_aux-cancel-v1\";\nexport const AUX_NOTIFICATION_PREFIX = \"pi-pod-internal/aux-v1:\";\n/** First pod extension version serving aux completions; older pods get honest errors. */\nexport const AUX_EXTENSION_VERSION = 11;\nexport const AUX_MAX_ENCODED_REQUEST_BYTES = 256 * 1024;\nexport const AUX_MAX_ENCODED_RESPONSE_BYTES = 256 * 1024;\nexport const TREE_BRIDGE_MAX_ENCODED_REQUEST_BYTES = 16 * 1024;\nexport const TREE_BRIDGE_MAX_ENCODED_RESPONSE_BYTES = 256 * 1024;\nexport const TREE_BRIDGE_MAX_ID_LENGTH = 128;\nexport const TREE_BRIDGE_MAX_ENTRY_ID_LENGTH = 512;\nexport const TREE_BRIDGE_MAX_LABEL_LENGTH = 256;\n\nexport const APPEND_ENTRY_COMMAND = \"pod:_append-entry-v1\";\nexport const APPEND_ENTRY_PROTOCOL_VERSION = 1 as const;\nexport const APPEND_ENTRY_MAX_CUSTOM_TYPE_LENGTH = 256;\n\nexport const AUTH_BRIDGE_PROTOCOL_VERSION = 1 as const;\nexport const AUTH_BRIDGE_COMMAND = \"pod:_auth-v1\";\nexport const AUTH_BRIDGE_NOTIFICATION_PREFIX = \"pi-pod-internal/auth-v1:\";\nexport const AUTH_BRIDGE_DIALOG_PREFIX = \"pi-pod-internal/auth-dialog-v1:\";\nexport const AUTH_BRIDGE_MAX_PROVIDER_ID_LENGTH = 256;\nexport const AUTH_BRIDGE_MAX_ENCODED_RESPONSE_BYTES = 64 * 1024;\n\n/** Read-only attach seed: active branch entries plus a flat tree summary. */\nexport const SEED_BRIDGE_PROTOCOL_VERSION = 1 as const;\nexport const SEED_CONTEXT_COMMAND = \"pod:_get-context-v1\";\nexport const SEED_TREE_SUMMARY_COMMAND = \"pod:_get-tree-summary-v1\";\nexport const SEED_BRIDGE_NOTIFICATION_PREFIX = \"pi-pod-internal/seed-v1:\";\nexport const SEED_CHUNK_CONTEXT_COMMAND = \"pod:_get-context-chunked-v1\";\nexport const SEED_CHUNK_TREE_SUMMARY_COMMAND = \"pod:_get-tree-summary-chunked-v1\";\nexport const SEED_CHUNK_NOTIFICATION_PREFIX = \"pi-pod-internal/seed-chunk-v1:\";\nexport const SEED_CHUNK_MAX_PART_CHARS = 200_000;\nexport const SEED_CHUNK_MAX_CHUNKS = 4096;\nexport const SEED_CHUNK_MAX_JSON_BYTES = 64 * 1024 * 1024;\n/** Branch content can be megabytes; stay under the 64 MiB frame drop. */\nexport const SEED_BRIDGE_MAX_ENCODED_RESPONSE_BYTES = 32 * 1024 * 1024;\n\n/** Read-only pod session catalog + naive search over on-disk JSONL. */\nexport const SESSION_CATALOG_PROTOCOL_VERSION = 1 as const;\nexport const SESSION_LIST_COMMAND = \"pod:_list-sessions-v1\";\nexport const SESSION_SEARCH_COMMAND = \"pod:_search-sessions-v1\";\n","export const FRAME_PROTO_VERSION = 1;\n\nexport interface ShimHello {\n event: \"hello\";\n proto: number;\n piVersion: string;\n shimVersion: string;\n extensionVersion?: number;\n piRunning: boolean;\n eventSeq?: number;\n}\n\nexport interface ShimPiExit {\n event: \"pi_exit\";\n code: number | null;\n}\n\nexport interface ShimPiStderr {\n event: \"pi_stderr\";\n data: string;\n}\n\nexport interface ShimMirrorData {\n event: \"mirror_data\";\n path: string;\n offset: number;\n data: string;\n}\n\nexport interface ShimStreamSnapshot {\n event: \"stream_snapshot\";\n message: Record<string, unknown> | null;\n}\n\nexport interface ShimBackgroundWork {\n event: \"background_work\";\n active: boolean;\n count: number;\n}\n\nexport interface ShimEventReplayGap {\n event: \"event_replay_gap\";\n fromSeq: number;\n toSeq: number;\n}\n\nexport interface ShimEventReplayEnd {\n event: \"event_replay_end\";\n lastSeq: number;\n}\n\nexport type ShimControlEvent =\n | ShimHello\n | ShimPiExit\n | ShimPiStderr\n | ShimMirrorData\n | ShimStreamSnapshot\n | ShimBackgroundWork\n | ShimEventReplayGap\n | ShimEventReplayEnd;\n","import { PiPodError } from \"../errors.js\";\nimport { warn } from \"../log.js\";\nimport { PREVIOUS_SHIM_VERSION, SHIM_LOG_PATH, SHIM_VERSION } from \"../shim/agentd.js\";\nimport { POD_EXTENSION_VERSION } from \"../shim/pi-pod-ext.js\";\nimport { bundledPiVersion, comparePiVersions, describeVersionSkew } from \"./piversion.js\";\nimport { FRAME_PROTO_VERSION, type ShimHello } from \"./protocol.js\";\n\n/** Oldest generated extension this launcher can attach to. */\nexport const MIN_EXTENSION_VERSION = 4;\n\nexport const RECOVERY_FLAP_LIMIT = 3;\nexport const RECOVERY_FLAP_WINDOW_MS = 60_000;\n\nexport function shimCompatibilityWarning(shimVersion: string): string | null {\n if (shimVersion !== PREVIOUS_SHIM_VERSION) return null;\n return (\n `the pod runs previous shim ${shimVersion}; this pi pod uses shim ${SHIM_VERSION} — ` +\n \"continuing in compatibility mode, but newer shim features are unavailable until Pi restarts\"\n );\n}\n\nexport function extensionCompatibilityWarning(extensionVersion: number | undefined): string | null {\n if (extensionVersion === undefined || extensionVersion < MIN_EXTENSION_VERSION) return null;\n if (extensionVersion === POD_EXTENSION_VERSION) return null;\n return (\n `the pod runs extension ${extensionVersion}; this pi pod uses extension ${POD_EXTENSION_VERSION} — ` +\n \"continuing, but launcher and extension behavior may differ until Pi restarts\"\n );\n}\n\n/** Validate every handshake field except Pi's version, which readiness may repair. */\nexport function verifyHelloEnvelope(hello: ShimHello, session: { close(): void }): void {\n if (hello.proto !== FRAME_PROTO_VERSION) {\n session.close();\n throw new PiPodError(\n `the pod shim speaks frame protocol ${hello.proto}; this pi pod speaks ${FRAME_PROTO_VERSION}`,\n { hint: \"exit the existing Pi session or wait for automatic idle retention, then attach again\" },\n );\n }\n if (hello.shimVersion !== SHIM_VERSION && hello.shimVersion !== PREVIOUS_SHIM_VERSION) {\n session.close();\n throw new PiPodError(\n `pod shim version skew: pod has ${hello.shimVersion}; this pi pod supports ${PREVIOUS_SHIM_VERSION} or ${SHIM_VERSION}`,\n { hint: \"exit the existing Pi session or wait for automatic idle retention, then attach again\" },\n );\n }\n if (!hello.piRunning) {\n session.close();\n throw new PiPodError(\"the pod shim could not start pi\", { hint: `check the shim log in the pod: ${SHIM_LOG_PATH}` });\n }\n\n if (hello.extensionVersion === undefined || hello.extensionVersion < MIN_EXTENSION_VERSION) {\n session.close();\n const podVersion =\n hello.extensionVersion === undefined ? \"an unversioned extension\" : `extension ${hello.extensionVersion}`;\n throw new PiPodError(`the pod runs ${podVersion}; this pi pod requires extension ${MIN_EXTENSION_VERSION} or newer`, {\n hint: \"exit the existing Pi session or wait for automatic idle retention, then attach again\",\n });\n }\n const extensionWarning = extensionCompatibilityWarning(hello.extensionVersion);\n if (extensionWarning) warn(extensionWarning);\n const compatibilityWarning = shimCompatibilityWarning(hello.shimVersion);\n if (compatibilityWarning) warn(compatibilityWarning);\n}\n\n/** Runtime boundary: only the launcher's exact installed Pi may reach InteractiveMode/RPC prompts. */\nexport function verifyHello(hello: ShimHello, session: { close(): void }): void {\n verifyHelloEnvelope(hello, session);\n const bundled = bundledPiVersion();\n if (hello.piVersion === bundled) return;\n\n session.close();\n const comparison = comparePiVersions(hello.piVersion, bundled);\n const base = describeVersionSkew(hello.piVersion, bundled);\n if (comparison !== null && comparison > 0) {\n throw new PiPodError(\"pi version skew: the pod runs a newer pi than this launcher\", {\n hint: `${base} — run \\`pipod update\\`, then attach again; pi pod will not downgrade the pod`,\n });\n }\n throw new PiPodError(\"pi version skew between this launcher and the pod\", {\n hint:\n comparison === null\n ? `${base} — the reported version is unknown or malformed, so the session is refused`\n : `${base} — the session is refused until the pod is updated automatically`,\n });\n}\n","/**\n * src/client/headless.ts — non-TTY output (§5.5).\n *\n * When stdout is not a TTY (piped/scripted runs, --prompt one-shots), the same\n * The RPC client feeds this line printer instead of the TUI: text deltas to stdout, tool\n * activity to stderr, done after agent_settled. Same transport, same protocol, one renderer\n * swapped.\n */\nimport type { ImageContent, RpcClientBase } from \"./rpc.js\";\n\n/** Pi flags that consume a value, so prompt extraction never eats a flag argument. */\nconst VALUE_FLAGS = new Set([\n \"--model\", \"-m\", \"--provider\", \"--session\", \"--session-id\", \"--session-dir\", \"--thinking\",\n \"--extension\", \"-e\", \"--mode\", \"--resume\", \"-r\", \"--fork\", \"--export\", \"--api-key\", \"--tui-mode\",\n]);\n\nexport type TuiMode = \"regular\" | \"fullscreen\";\n\n/** Match Pi's last-option-wins parsing for the local InteractiveMode renderer. */\nexport function tuiModeFromArgv(argv: string[]): TuiMode | undefined {\n let mode: TuiMode | undefined;\n for (let i = 0; i < argv.length; i++) {\n if (argv[i] !== \"--tui-mode\") continue;\n const value = argv[++i];\n if (value === \"regular\" || value === \"fullscreen\") mode = value;\n }\n return mode;\n}\n\n/**\n * Split a Pi RPC invocation into its startup prompt and the arguments Pi should still see.\n * Positional startup messages do not run automatically under `--mode rpc`, so every renderer\n * submits them as a `prompt` command instead. `-p/--print` is likewise implemented by the\n * non-TTY renderer and must not reach the long-lived Pi process.\n */\nexport function extractStartupPrompt(piArgs: string[]): { prompt: string | undefined; args: string[] } {\n const args: string[] = [];\n const positionals: string[] = [];\n for (let i = 0; i < piArgs.length; i++) {\n const arg = piArgs[i]!;\n if (arg === \"-p\" || arg === \"--print\") continue;\n if (arg.startsWith(\"-\")) {\n args.push(arg);\n if (VALUE_FLAGS.has(arg) && i + 1 < piArgs.length) args.push(piArgs[++i]!);\n continue;\n }\n positionals.push(arg);\n }\n return { prompt: positionals.length > 0 ? positionals.join(\" \") : undefined, args };\n}\n\nexport interface HeadlessOptions {\n rpc: RpcClientBase;\n /** Prompt to send once connected; omitted means \"render whatever pi is already doing\". */\n prompt?: string | undefined;\n /** Inline image attachments for the prompt, prepared by the caller (see local-images). */\n images?: ImageContent[] | undefined;\n stdout: NodeJS.WritableStream;\n stderr: NodeJS.WritableStream;\n}\n\ninterface StreamEvent {\n type?: string;\n assistantMessageEvent?: { type?: string; delta?: string };\n toolName?: string;\n args?: unknown;\n code?: number | null;\n}\n\n/**\n * Render one agent run as plain lines. Resolves with pi's exit code when pi exits, or null\n * after the run settles with pi still up (the caller then quits it via the shim).\n */\nexport function runHeadless(opts: HeadlessOptions): Promise<number | null> {\n const { rpc, stdout, stderr } = opts;\n\n return new Promise((resolve, reject) => {\n let settled = false;\n let outputEndsWithNewline = false;\n const finish = (code: number | null) => {\n if (settled) return;\n settled = true;\n offEvents();\n offControl();\n resolve(code);\n };\n\n const offEvents = rpc.onEvent((event) => {\n const e = event as StreamEvent;\n switch (e.type) {\n case \"message_update\":\n if (e.assistantMessageEvent?.type === \"text_delta\" && e.assistantMessageEvent.delta) {\n stdout.write(e.assistantMessageEvent.delta);\n outputEndsWithNewline = e.assistantMessageEvent.delta.endsWith(\"\\n\");\n }\n break;\n case \"tool_execution_start\":\n stderr.write(`[tool] ${e.toolName ?? \"unknown\"}\\n`);\n break;\n case \"agent_settled\":\n if (!outputEndsWithNewline) stdout.write(\"\\n\");\n finish(null);\n break;\n }\n });\n\n const offControl = rpc.onControl((event) => {\n if (event.event === \"pi_exit\") {\n finish(event.code);\n } else if (event.event === \"pi_stderr\") {\n stderr.write(Buffer.from(event.data, \"base64\"));\n }\n });\n\n if (opts.prompt !== undefined) {\n rpc.prompt(opts.prompt, opts.images).catch((e: unknown) => {\n offEvents();\n offControl();\n reject(e instanceof Error ? e : new Error(String(e)));\n });\n }\n });\n}\n","/** A single-column marker that distinguishes a pi pod tab from an ordinary Pi session. */\nexport const POD_TITLE_MARKER = \"◉\";\n\n/** Preserve the title Pi (or an extension) chose while replacing its ordinary Pi marker. */\nexport function podTerminalTitle(title: string): string {\n return title.replaceAll(\"π\", POD_TITLE_MARKER);\n}\n\ninterface TerminalTitleMode {\n ui?: {\n terminal?: {\n setTitle?: (title: string) => void;\n };\n };\n}\n\nconst patchedTerminals = new WeakSet<object>();\n\n/**\n * Keep every local InteractiveMode retitle pod-branded, including renames and session switches.\n * The raw remote-TUI path is branded by the generated pod extension instead.\n */\nexport function installPodTerminalTitle(mode: TerminalTitleMode): void {\n const terminal = mode.ui?.terminal;\n if (!terminal || typeof terminal.setTitle !== \"function\" || patchedTerminals.has(terminal)) return;\n\n const setTitle = terminal.setTitle.bind(terminal);\n terminal.setTitle = (title) => setTitle(podTerminalTitle(title));\n patchedTerminals.add(terminal);\n}\n","/**\n * src/client/runtime/attested-extensions.ts — the code channel.\n *\n * The laptop executes extension code only when its spec came from server-custodied config:\n * the launch-resolved `resolvedPackages` set the server recorded on the pod row. The client\n * never receives executable bytes from the pod — it downloads the attested specs from the\n * registry itself, into a shared content-addressed store. Spec-shape guardrails allow only\n * exact versions of plainly named npm packages: no git URLs, tarballs, paths, ranges, or\n * tags, which are pod- or third-party-chosen bytes by reference. Nothing installed by the\n * agent mid-session can enter this set, structurally.\n */\nimport { execFile } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { debug } from \"../../log.js\";\nimport { extensionEntriesOf } from \"./local-extensions.js\";\n\nconst execFileAsync = promisify(execFile);\n\nexport const MAX_ATTESTED_PACKAGES = 32;\nconst NPM_NAME = /^(@[a-z0-9~][a-z0-9._~-]*\\/)?[a-z0-9~][a-z0-9._~-]*$/;\nconst EXACT_SEMVER = /^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?(?:\\+[0-9A-Za-z.-]+)?$/;\nconst INSTALL_TIMEOUT_MS = 120_000;\nconst LOCK_STALE_MS = 10 * 60 * 1000;\nconst LOCK_WAIT_MS = 60_000;\n\nexport interface AttestedPackage {\n name: string;\n version: string;\n source: string;\n}\n\n/**\n * The attested set from a pod row's launch report, guardrails applied. Entries that fail a\n * shape check are dropped (fail closed) and named in `refused` so the session can say why\n * rendering stays generic.\n */\nexport function attestedPackages(\n piSettings:\n | { resolvedPackages?: Array<{ name?: unknown; version?: unknown; source?: unknown }> }\n | null\n | undefined,\n): { specs: AttestedPackage[]; refused: string[] } {\n const specs: AttestedPackage[] = [];\n const refused: string[] = [];\n for (const entry of (piSettings?.resolvedPackages ?? []).slice(0, MAX_ATTESTED_PACKAGES)) {\n const name = typeof entry.name === \"string\" ? entry.name : \"\";\n const version = typeof entry.version === \"string\" ? entry.version : \"\";\n const source = typeof entry.source === \"string\" ? entry.source : \"\";\n const label = name || source || \"(unnamed)\";\n if (!source.startsWith(\"npm:\")) {\n refused.push(`${label}: only npm registry sources run locally`);\n continue;\n }\n if (!NPM_NAME.test(name) || name.length > 214) {\n refused.push(`${label}: not a plain npm package name`);\n continue;\n }\n if (!EXACT_SEMVER.test(version) || version.length > 64) {\n refused.push(`${label}: resolved version ${JSON.stringify(version).slice(0, 32)} is not exact`);\n continue;\n }\n specs.push({ name, version, source });\n }\n return { specs, refused };\n}\n\n/**\n * The attested set says which packages the server recorded, not that this person agreed to\n * run them: a template someone else edits, or one a pod wrote, chooses them. Each exact\n * package runs locally only once its user has said yes to it on this machine; without a\n * terminal to ask, rendering stays generic.\n */\nexport async function trustAttestedPackages(\n specs: AttestedPackage[],\n opts: { cacheRoot: string; ask: (question: string) => Promise<boolean> },\n): Promise<{ trusted: AttestedPackage[]; declined: AttestedPackage[] }> {\n const file = path.join(opts.cacheRoot, \"trusted-extensions.json\");\n const key = (spec: AttestedPackage) => `${spec.name}@${spec.version}`;\n let known: string[] = [];\n try {\n const parsed: unknown = JSON.parse(fs.readFileSync(file, \"utf8\"));\n if (Array.isArray(parsed)) known = parsed.filter((entry): entry is string => typeof entry === \"string\");\n } catch {\n // No decisions yet.\n }\n const unknown = specs.filter((spec) => !known.includes(key(spec)));\n if (unknown.length === 0) return { trusted: specs, declined: [] };\n const yes = await opts.ask(\n `This pod renders with Pi extensions that would run on this machine as you: ${unknown.map(key).join(\", \")}. Run them?`,\n );\n if (!yes) return { trusted: specs.filter((spec) => !unknown.includes(spec)), declined: unknown };\n fs.mkdirSync(opts.cacheRoot, { recursive: true, mode: 0o700 });\n fs.writeFileSync(file, `${JSON.stringify([...known, ...unknown.map(key)], null, 2)}\\n`, { mode: 0o600 });\n return { trusted: specs, declined: [] };\n}\n\nfunction storeSegment(spec: AttestedPackage): string {\n return `${spec.name.replace(\"/\", \"__\")}@${spec.version}`.replace(/[^A-Za-z0-9._@~-]/g, \"_\");\n}\n\nasync function withInstallLock<T>(entryDir: string, run: () => Promise<T>): Promise<T> {\n const lock = `${entryDir}.lock`;\n fs.mkdirSync(path.dirname(entryDir), { recursive: true, mode: 0o700 });\n const deadline = Date.now() + LOCK_WAIT_MS;\n for (;;) {\n try {\n fs.mkdirSync(lock, { recursive: false });\n break;\n } catch {\n try {\n if (Date.now() - fs.statSync(lock).mtimeMs > LOCK_STALE_MS) {\n fs.rmdirSync(lock);\n continue;\n }\n } catch {\n // The holder finished between the mkdir failure and the stat; retry after the pause.\n }\n if (Date.now() > deadline) throw new Error(\"timed out waiting for a concurrent install\");\n await new Promise((resolve) => setTimeout(resolve, 250));\n }\n }\n try {\n return await run();\n } finally {\n try {\n fs.rmdirSync(lock);\n } catch {\n // Already released.\n }\n }\n}\n\nexport interface AttestedInstallResult {\n /** Extension entry files for pi's loader, in spec order. */\n paths: string[];\n /** Human lines for specs that could not produce a locally renderable extension. */\n warnings: string[];\n}\n\n/**\n * Materialize the attested set in the shared store (`<cacheRoot>/npm/<name>@<version>/`).\n * Idempotent per entry (completion marker), safe under concurrent launchers (lock +\n * marker), and always `--ignore-scripts`: the code runs inside the TUI process later, but\n * install-time script execution is not part of the deal.\n */\nexport async function installAttestedPackages(\n specs: AttestedPackage[],\n opts: { cacheRoot: string; npmCommand?: string[] },\n): Promise<AttestedInstallResult> {\n const paths: string[] = [];\n const warnings: string[] = [];\n for (const spec of specs) {\n const entryDir = path.join(opts.cacheRoot, \"npm\", storeSegment(spec));\n const packageDir = path.join(entryDir, \"node_modules\", ...spec.name.split(\"/\"));\n try {\n await withInstallLock(entryDir, async () => {\n if (fs.existsSync(path.join(entryDir, \"complete\"))) return;\n fs.mkdirSync(entryDir, { recursive: true, mode: 0o700 });\n const [npmBin, ...npmArgs] = opts.npmCommand ?? [\"npm\"];\n await execFileAsync(\n npmBin!,\n [\n ...npmArgs,\n \"install\",\n `${spec.name}@${spec.version}`,\n \"--prefix\",\n entryDir,\n \"--ignore-scripts\",\n \"--no-audit\",\n \"--no-fund\",\n \"--omit=dev\",\n \"--legacy-peer-deps\",\n ],\n { timeout: INSTALL_TIMEOUT_MS },\n );\n if (!fs.existsSync(packageDir)) throw new Error(\"npm reported success but the package is missing\");\n fs.writeFileSync(path.join(entryDir, \"complete\"), \"\", { mode: 0o600 });\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n debug(`attested install failed for ${spec.name}@${spec.version}: ${message}`);\n warnings.push(\n `pod extension ${spec.name}@${spec.version} could not be installed locally (${message.split(\"\\n\")[0]}) — its rendering stays generic`,\n );\n continue;\n }\n const entries = extensionEntriesOf(packageDir);\n if (entries.length === 0) {\n // Not every settings package is an extension (themes/skills/prompts ride the same\n // list); nothing to run locally is the normal case, not a failure.\n debug(`attested package ${spec.name}@${spec.version} declares no extension entry`);\n continue;\n }\n paths.push(...entries);\n }\n return { paths, warnings };\n}\n\n/** One actionable notice for pod package identities the exact launch attestation cannot vouch for. */\nexport function unattestedPackageNotice(\n podPackages: Array<{ name: string; version: string }>,\n specs: AttestedPackage[],\n): string | null {\n const identity = (entry: { name: string; version: string }): string => `${entry.name}@${entry.version}`;\n const attested = new Set(specs.map(identity));\n const mismatches = [...new Set(podPackages.map(identity).filter((entry) => !attested.has(entry)))].sort();\n if (mismatches.length === 0) return null;\n\n const shown = mismatches.slice(0, 3).map((entry) => `\\`${entry}\\``);\n const remainder = mismatches.length - shown.length;\n const examples = `${shown.join(\", \")}${remainder > 0 ? `, and ${remainder} more` : \"\"}`;\n const noun = mismatches.length === 1 ? \"package\" : \"packages\";\n return (\n `pod reports ${mismatches.length} configured ${noun} outside its exact launch-attested set: ${examples}; ` +\n `extension rendering from ${mismatches.length === 1 ? \"that package is\" : \"those packages is\"} unavailable locally — ` +\n `land intentional top-level Pi packages in your bundle's settings.json \"packages\" ` +\n `(pipod push, or a settings proposal); do not add transitive dependencies`\n );\n}\n","/**\n * src/client/runtime/local-extensions.ts — the local extension host (the code channel's\n * runner).\n *\n * Server-attested pod extensions run *in the launcher process too*, where pi's real\n * `InteractiveMode` and pi-tui classes live, because their rendering hooks (entry/message\n * renderers, markdown transformers, prototype patches) cannot cross the JSON/RPC boundary.\n * The same extension executes in the pod; locally its registrations are filtered for\n * *correctness*, not security (the code is trusted by custody): commands and tools the pod\n * already serves are not re-registered — the pod copies stay authoritative — while\n * rendering hooks stay active. (`pi.clientExtensions` is retired; attestation via the\n * bundle's `packages` is the only path to locally executed extension code.)\n *\n * The genuine `ExtensionRunner` runs here, over pi's genuine loader. The loader is a deep\n * file import rather than a package import because pi's public entry does not re-export\n * `loadExtensions` — the resolved file is the same module instance pi's own dist imports, so\n * jiti's bundled-package aliases (and therefore prototype patches against pi-tui classes)\n * hit the launcher's own copies. The surface canary (scripts/check-runtime-surface.ts)\n * asserts these internals on every lint run, so a pi upgrade that moves them fails loudly.\n */\nimport { randomUUID } from \"node:crypto\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { SessionEntry } from \"@earendil-works/pi-coding-agent\";\nimport { debug } from \"../../log.js\";\nimport {\n APPEND_ENTRY_COMMAND,\n APPEND_ENTRY_MAX_CUSTOM_TYPE_LENGTH,\n APPEND_ENTRY_PROTOCOL_VERSION,\n TREE_BRIDGE_MAX_ENCODED_REQUEST_BYTES,\n} from \"../../shim/pi-pod-ext.js\";\nimport type { RpcClientBase } from \"../rpc.js\";\nimport type { HostBridge } from \"./bridge.js\";\nimport { findTreeNode, type RemoteStateCache } from \"./state.js\";\n\n// ---------------------------------------------------------------------------\n// Resolution: package directories → loadable entry files\n// ---------------------------------------------------------------------------\n\n/**\n * A directory's extension entry files, the way pi's own discovery resolves them: the\n * package.json `pi.extensions` manifest first, else an `index.ts`/`index.js`. Mirrored here\n * because pi exposes this resolution only inside `discoverAndLoadExtensions`, whose\n * project/agent-dir sweep would drag in extensions nobody listed; `loadExtensions` itself\n * loads files and fails outright on a directory.\n */\nexport function extensionEntriesOf(dir: string): string[] {\n const manifestPath = path.join(dir, \"package.json\");\n if (fs.existsSync(manifestPath)) {\n try {\n const manifest = JSON.parse(fs.readFileSync(manifestPath, \"utf8\")) as {\n pi?: { extensions?: unknown };\n };\n const declared = Array.isArray(manifest.pi?.extensions) ? manifest.pi.extensions : [];\n const entries = declared\n .filter((entry): entry is string => typeof entry === \"string\")\n .map((entry) => path.resolve(dir, entry))\n .filter((entry) => fs.existsSync(entry));\n if (entries.length > 0) return entries;\n } catch {\n // Malformed manifest: fall through to the index convention.\n }\n }\n for (const index of [\"index.ts\", \"index.js\"]) {\n const candidate = path.join(dir, index);\n if (fs.existsSync(candidate)) return [candidate];\n }\n return [];\n}\n\n// ---------------------------------------------------------------------------\n// Pi internals: the loader and runner, deep-imported (see module docs)\n// ---------------------------------------------------------------------------\n\n/** The slice of pi's ExtensionRunner the host touches; canary-guarded, duck-typed. */\nexport interface LocalExtensionRunner {\n bindCore(actions: unknown, contextActions: unknown, providerActions?: unknown): void;\n bindCommandContext(actions?: unknown): void;\n setUIContext(uiContext?: unknown, mode?: string): void;\n getAllRegisteredTools(): unknown[];\n getRegisteredCommands(): ResolvedLocalCommand[];\n getCommand(name: string): ResolvedLocalCommand | undefined;\n getCommandDiagnostics(): unknown[];\n getShortcuts(resolvedKeybindings: unknown): Map<string, unknown>;\n getShortcutDiagnostics(): unknown[];\n getEntryRenderer(customType: string): unknown;\n getMessageRenderer(customType: string): unknown;\n getMarkdownTransformers(): unknown[];\n createCommandContext(): unknown;\n hasHandlers(eventType: string): boolean;\n emit(event: unknown): Promise<unknown>;\n emitError(error: { extensionPath: string; event: string; error: string }): void;\n onError(listener: (error: { extensionPath: string; event: string; error: string }) => void): () => void;\n invalidate(message?: string): void;\n}\n\nexport interface ResolvedLocalCommand {\n name: string;\n invocationName: string;\n description?: string;\n sourceInfo: unknown;\n getArgumentCompletions?: (prefix: string) => unknown;\n handler: (args: string, ctx: unknown) => Promise<void>;\n}\n\ninterface LoadedExtension {\n path: string;\n resolvedPath: string;\n tools: Map<string, unknown>;\n handlers: Map<string, unknown[]>;\n}\n\ninterface PiExtensionInternals {\n loadExtensions(\n paths: string[],\n cwd: string,\n eventBus?: unknown,\n runtime?: unknown,\n ): Promise<{\n extensions: LoadedExtension[];\n errors: Array<{ path: string; error: string }>;\n runtime: {\n pendingProviderRegistrations: Array<{ extensionPath: string }>;\n pendingNativeProviderRegistrations: Array<{ extensionPath: string }>;\n };\n }>;\n createExtensionRuntime(): unknown;\n}\n\n/**\n * Pi's loader module, by file path. The URL resolves to the same file pi's own\n * `dist/index.js` imports, so Node's module cache guarantees one shared instance —\n * which is what makes the loader's bundled-package aliases point at the launcher's pi.\n */\nexport async function loadPiExtensionInternals(): Promise<PiExtensionInternals> {\n // import.meta.resolve rather than require.resolve: pi's exports map declares only the\n // \"import\" condition, so a CJS-style resolve has no entry to find.\n const entryUrl = import.meta.resolve(\"@earendil-works/pi-coding-agent\");\n const loader = (await import(new URL(\"core/extensions/loader.js\", entryUrl).href)) as Partial<PiExtensionInternals>;\n if (typeof loader.loadExtensions !== \"function\" || typeof loader.createExtensionRuntime !== \"function\") {\n throw new Error(\n \"pi's extension loader no longer exposes loadExtensions/createExtensionRuntime — \" +\n \"pi pod needs an update for this pi version\",\n );\n }\n return loader as PiExtensionInternals;\n}\n\n// ---------------------------------------------------------------------------\n// The host\n// ---------------------------------------------------------------------------\n\n/** What createLocalExtensionHost needs from the remote runtime; everything else is the cache's. */\nexport interface LocalExtensionHostOptions {\n paths: string[];\n hostCwd: string;\n cache: RemoteStateCache;\n bridge: HostBridge;\n rpc: RpcClientBase;\n /** Live values owned by the remote runtime (scope edits, CLI overrides). */\n getScopedModels(): readonly unknown[];\n /** Session actions that already exist on the runtime's 57-member session surface. */\n prompt(text: string, opts?: { streamingBehavior?: \"steer\" | \"followUp\" }): Promise<void>;\n setModel(model: { provider: string; id: string }): Promise<unknown>;\n setThinkingLevel(level: unknown): Promise<unknown>;\n setSessionName(name: string): unknown;\n setLabel(entryId: string, label: string | undefined): void;\n getContextUsage(): unknown;\n abort(): void;\n compact(customInstructions?: string): Promise<unknown>;\n waitForIdle(timeoutMs?: number): Promise<void>;\n /** The runtime's model facade, handed to extensions as ctx.modelRegistry. */\n modelRegistry: object;\n /** Merged command list for pi.getCommands() — the same view the TUI autocomplete gets. */\n getCommands(): unknown[];\n /** Test seam: substitute pi internals. */\n internals?: PiExtensionInternals;\n}\n\nexport interface LocalExtensionHost {\n runner: LocalExtensionRunner;\n /** Extension display names, for launch reporting. */\n names: string[];\n /** Run `/name args` when a local extension registered it. False when no command matches. */\n runCommand(text: string): Promise<boolean>;\n /**\n * Run one locally registered command by name with the real TUI context. Returns\n * false when nothing local registered the name (the caller keeps pod ownership).\n * Throws — running nothing — when several local registrations share the name, so a\n * collision never silently picks a winner: the error lists each claimant's\n * sourceInfo for explicit disambiguation.\n */\n runLocalCommand(name: string, args: string): Promise<boolean>;\n /** Forward one already-healed RPC event to local handlers; results are ignored. */\n emitAgentEvent(event: unknown): void;\n /**\n * Deliver a runner-local lifecycle event (today: the synthesized `session_tree`, which pi\n * emits via the ExtensionRunner only and never puts on the wire). Blocking hooks stay\n * pod-side; results are ignored.\n */\n emitLifecycle(event: unknown): void;\n sessionStart(\n reason: \"startup\" | \"new\" | \"resume\" | \"fork\",\n opts?: { previousSessionFile?: string },\n ): Promise<void>;\n sessionShutdown(\n reason: \"quit\" | \"new\" | \"resume\" | \"fork\",\n opts?: { targetSessionFile?: string },\n ): Promise<void>;\n dispose(): Promise<void>;\n}\n\n/**\n * Events client-side handlers may observe: the RPC stream restores their in-process\n * cumulative shape (StreamHeal), and none of them can alter agent behavior — blocking hooks\n * (`tool_call`, `context`, `before_agent_start`) run pod-side and are not in the stream.\n * `session_tree` is deliberately absent: pi emits it via the ExtensionRunner only, never on\n * the wire, so the runtime synthesizes it locally after tree navigation instead.\n */\nconst FORWARDED_EVENTS = new Set([\n \"agent_start\",\n \"agent_end\",\n \"agent_settled\",\n \"turn_start\",\n \"turn_end\",\n \"message_start\",\n \"message_update\",\n \"message_end\",\n \"tool_execution_start\",\n \"tool_execution_update\",\n \"tool_execution_end\",\n]);\n\n/** A human name for an extension: its npm package when installed as one, else the file. */\nfunction extensionDisplayName(extensionPath: string): string {\n const marker = `node_modules${path.sep}`;\n const index = extensionPath.lastIndexOf(marker);\n if (index !== -1) {\n const rest = extensionPath.slice(index + marker.length).split(path.sep);\n return rest[0]?.startsWith(\"@\") ? `${rest[0]}/${rest[1] ?? \"\"}` : (rest[0] ?? extensionPath);\n }\n return path.basename(extensionPath);\n}\n\nfunction unavailable(what: string, use?: string): () => never {\n return () => {\n throw new Error(\n `${what} is not available to locally rendered pod extensions` + (use ? ` — ${use}` : \"\"),\n );\n };\n}\n\n/** Root-to-target entry chain, the way pi's SessionManager.getBranch reads. */\nfunction branchOf(entries: SessionEntry[], fromId: string | null): SessionEntry[] {\n if (fromId === null) return [];\n const byId = new Map(entries.map((entry) => [entry.id, entry]));\n const out: SessionEntry[] = [];\n let current = byId.get(fromId);\n const seen = new Set<string>();\n while (current && !seen.has(current.id)) {\n seen.add(current.id);\n out.push(current);\n current =\n current.parentId !== null && current.parentId !== current.id ? byId.get(current.parentId) : undefined;\n }\n return out.reverse();\n}\n\n/**\n * Load the listed extensions and stand up a real ExtensionRunner over the RPC-backed session.\n * Returns null when nothing loads — the caller stays on the zero-cost stub path. Load\n * failures degrade to a warning: a session without a cosmetic extension beats no session.\n */\nexport async function createLocalExtensionHost(\n opts: LocalExtensionHostOptions,\n): Promise<LocalExtensionHost | null> {\n if (opts.paths.length === 0) return null;\n const { cache, bridge, rpc } = opts;\n const notifyWhenBound = (message: string, type: \"info\" | \"warning\" | \"error\") => {\n bridge.onUiBound(() => bridge.notify(message, type));\n };\n\n let internals: PiExtensionInternals;\n let ExtensionRunnerClass: new (...args: never[]) => unknown;\n try {\n internals = opts.internals ?? (await loadPiExtensionInternals());\n ExtensionRunnerClass = (await import(\"@earendil-works/pi-coding-agent\"))\n .ExtensionRunner as unknown as new (...args: never[]) => unknown;\n } catch (error) {\n notifyWhenBound(\n `pod extension rendering unavailable: ${error instanceof Error ? error.message : String(error)}`,\n \"warning\",\n );\n return null;\n }\n\n const runtime = internals.createExtensionRuntime();\n const loaded = await internals.loadExtensions(opts.paths, opts.hostCwd, undefined, runtime);\n for (const failure of loaded.errors) {\n notifyWhenBound(\n `pod extension failed to load locally (${extensionDisplayName(failure.path)}): ${failure.error}`,\n \"warning\",\n );\n }\n\n // --- correctness filtering, not a security gate (the code is trusted by custody) --------\n // The same extensions execute in the pod, which stays authoritative: tools are not\n // re-registered locally (cleared here so the runner never advertises them), and queued\n // provider registrations never flush at bindCore time. Rendering hooks stay active.\n const kept: LoadedExtension[] = loaded.extensions;\n for (const extension of kept) extension.tools.clear();\n loaded.runtime.pendingProviderRegistrations.length = 0;\n loaded.runtime.pendingNativeProviderRegistrations.length = 0;\n if (kept.length === 0) return null;\n\n // --- session/model facades -------------------------------------------------\n const throwMutator = (name: string) =>\n unavailable(`sessionManager.${name}`, \"session files live in the pod\");\n const sessionManagerFacade = {\n getCwd: () => opts.hostCwd,\n getSessionDir: () => opts.hostCwd,\n usesDefaultSessionDir: () => true,\n isPersisted: () => cache.state.sessionFile !== undefined,\n getSessionId: () => cache.state.sessionId,\n getSessionFile: () => cache.state.sessionFile,\n getSessionName: () => cache.state.sessionName,\n getLeafId: () => cache.leafId,\n getLeafEntry: () => cache.entries.find((entry) => entry.id === cache.leafId),\n getEntry: (id: string) => cache.entries.find((entry) => entry.id === id),\n getChildren: (parentId: string) => cache.entries.filter((entry) => entry.parentId === parentId),\n getEntries: () => cache.entries,\n getTree: () => cache.tree,\n getLabel: (id: string) => findTreeNode(cache.tree, id)?.label,\n getBranch: (fromId?: string) => branchOf(cache.entries, fromId ?? cache.leafId),\n buildContextEntries: () => cache.entries,\n // Mutators throw: the pod's session file is authoritative, and a silent local write\n // would fork the transcript.\n appendMessage: throwMutator(\"appendMessage\"),\n appendCustomEntry: throwMutator(\"appendCustomEntry\"),\n appendSessionInfo: throwMutator(\"appendSessionInfo\"),\n appendThinkingLevelChange: throwMutator(\"appendThinkingLevelChange\"),\n appendModelChange: throwMutator(\"appendModelChange\"),\n appendLabelChange: throwMutator(\"appendLabelChange\"),\n setSessionFile: throwMutator(\"setSessionFile\"),\n newSession: throwMutator(\"newSession\"),\n branch: throwMutator(\"branch\"),\n branchWithSummary: throwMutator(\"branchWithSummary\"),\n createBranchedSession: throwMutator(\"createBranchedSession\"),\n resetLeaf: throwMutator(\"resetLeaf\"),\n };\n\n const runner = new (ExtensionRunnerClass as new (\n extensions: unknown,\n runtime: unknown,\n cwd: string,\n sessionManager: unknown,\n modelRegistry: unknown,\n ) => LocalExtensionRunner)(kept, runtime, opts.hostCwd, sessionManagerFacade, opts.modelRegistry);\n\n // --- appendEntry bridge (phase 4): durable entries land in the pod's JSONL ---\n let appendEntryWarned = false;\n const appendEntryUnavailable = (reason: string) => {\n if (appendEntryWarned) return;\n appendEntryWarned = true;\n notifyWhenBound(`pod extension appendEntry: ${reason} — the entry was not recorded`, \"warning\");\n };\n const supportsAppendEntry = () =>\n cache.commands.some((command) => {\n const candidate = command as { name?: unknown; source?: unknown };\n return candidate.name === APPEND_ENTRY_COMMAND && candidate.source === \"extension\";\n });\n const sendAppendEntry = (customType: string, data?: unknown): void => {\n if (typeof customType !== \"string\" || customType.length === 0 || customType.length > APPEND_ENTRY_MAX_CUSTOM_TYPE_LENGTH) {\n appendEntryUnavailable(`invalid custom type ${JSON.stringify(customType).slice(0, 64)}`);\n return;\n }\n if (!supportsAppendEntry()) {\n appendEntryUnavailable(\"this pod runs an older pi pod extension (restart Pi in the pod to update it)\");\n return;\n }\n const request = {\n v: APPEND_ENTRY_PROTOCOL_VERSION,\n id: randomUUID(),\n op: \"append-entry\",\n customType,\n ...(data !== undefined ? { data } : {}),\n };\n let encoded: string;\n try {\n encoded = Buffer.from(JSON.stringify(request), \"utf8\").toString(\"base64url\");\n } catch (error) {\n appendEntryUnavailable(`entry data is not serializable (${error instanceof Error ? error.message : String(error)})`);\n return;\n }\n if (Buffer.byteLength(encoded, \"utf8\") > TREE_BRIDGE_MAX_ENCODED_REQUEST_BYTES) {\n appendEntryUnavailable(\"entry data exceeds the bridge size limit\");\n return;\n }\n void rpc\n .prompt(`/${APPEND_ENTRY_COMMAND} ${encoded}`)\n .then(() => cache.refreshTree().then(() => undefined))\n .catch((error: unknown) => {\n appendEntryUnavailable(error instanceof Error ? error.message : String(error));\n debug(`append-entry bridge failed: ${error instanceof Error ? error.message : String(error)}`);\n });\n };\n\n // --- bindCore: the extension-facing pi.* actions --------------------------\n const actions = {\n sendMessage: unavailable(\"pi.sendMessage\", \"conversation context is built in the pod\"),\n sendUserMessage: (content: unknown, sendOptions?: { streamingBehavior?: \"steer\" | \"followUp\" }) => {\n const text =\n typeof content === \"string\"\n ? content\n : (content as Array<{ text?: string }>).map((part) => part.text ?? \"\").join(\"\");\n void opts\n .prompt(text, sendOptions?.streamingBehavior ? { streamingBehavior: sendOptions.streamingBehavior } : undefined)\n .catch((error: unknown) =>\n bridge.notify(\n `extension sendUserMessage failed: ${error instanceof Error ? error.message : String(error)}`,\n \"error\",\n ),\n );\n },\n appendEntry: (customType: string, data?: unknown) => sendAppendEntry(customType, data),\n setSessionName: (name: string) => void opts.setSessionName(name),\n getSessionName: () => cache.state.sessionName,\n setLabel: (entryId: string, label: string | undefined) => opts.setLabel(entryId, label),\n getActiveTools: () => [],\n getAllTools: () => [],\n setActiveTools: unavailable(\"pi.setActiveTools\", \"tools execute in the pod\"),\n refreshTools: () => {},\n getCommands: () => opts.getCommands(),\n setModel: async (model: { provider: string; id: string }) => {\n await opts.setModel(model);\n return true;\n },\n getThinkingLevel: () => cache.state.thinkingLevel,\n setThinkingLevel: (level: unknown) => void opts.setThinkingLevel(level),\n };\n const contextActions = {\n getModel: () => cache.state.model,\n getScopedModels: () => opts.getScopedModels(),\n isIdle: () => !cache.state.isStreaming && !cache.state.isCompacting,\n // The pod session runs with the workspace trusted (--approve is pi pod's default).\n isProjectTrusted: () => true,\n getSignal: () => undefined,\n abort: () => opts.abort(),\n hasPendingMessages: () => cache.state.pendingMessageCount > 0,\n shutdown: () => bridge.requestShutdown(),\n getContextUsage: () => opts.getContextUsage(),\n compact: (compactOptions?: { customInstructions?: string }) =>\n void opts.compact(compactOptions?.customInstructions).catch((error: unknown) =>\n bridge.notify(`compaction failed: ${error instanceof Error ? error.message : String(error)}`, \"error\"),\n ),\n getSystemPrompt: () => \"\",\n };\n const providerActions = {\n registerProvider: unavailable(\"pi.registerProvider\", \"providers execute in the pod\"),\n registerNativeProvider: unavailable(\"pi.registerProvider\", \"providers execute in the pod\"),\n unregisterProvider: unavailable(\"pi.unregisterProvider\", \"providers execute in the pod\"),\n };\n runner.bindCore(actions, contextActions, providerActions);\n runner.bindCommandContext({\n waitForIdle: () => opts.waitForIdle(),\n newSession: unavailable(\"ctx.newSession\", \"run /new in the session instead\"),\n fork: unavailable(\"ctx.fork\", \"run /fork in the session instead\"),\n navigateTree: unavailable(\"ctx.navigateTree\", \"run /tree in the session instead\"),\n switchSession: unavailable(\"ctx.switchSession\", \"run /resume in the session instead\"),\n reload: unavailable(\"ctx.reload\", \"run /reload in the session instead\"),\n });\n runner.onError((error) =>\n bridge.notify(`pod extension error (${extensionDisplayName(error.extensionPath)}): ${error.error}`, \"error\"),\n );\n\n // The real local UI context (theme included) — rebound on every session replacement,\n // because InteractiveMode hands over a fresh context each time it rebinds.\n const unbindUi = bridge.onEveryUiBound((ui) => runner.setUIContext(ui as never, \"tui\"));\n\n const emitLifecycle = async (event: { type: string; reason: string }): Promise<void> => {\n if (!runner.hasHandlers(event.type)) return;\n await runner.emit(event).catch((error: unknown) => {\n debug(`client extension ${event.type} handler failed: ${error instanceof Error ? error.message : String(error)}`);\n });\n };\n\n const emitObservational = (event: unknown): void => {\n if (disposed || !started) return;\n const type = (event as { type?: string }).type ?? \"\";\n if (!runner.hasHandlers(type)) return;\n void runner.emit(event).catch((error: unknown) => {\n debug(`client extension ${type} handler failed: ${error instanceof Error ? error.message : String(error)}`);\n });\n };\n\n /** Invoke one local command by bare name; shared with runCommand's slash parsing. */\n const invokeLocalCommand = async (name: string, args: string): Promise<\"ran\" | \"missing\"> => {\n const bare = name.startsWith(\"/\") ? name.slice(1) : name;\n if (bare === \"\") return \"missing\";\n const direct = runner.getCommand(bare);\n if (direct) {\n try {\n await direct.handler(args, runner.createCommandContext());\n } catch (error) {\n runner.emitError({\n extensionPath: `command:${bare}`,\n event: \"command\",\n error: error instanceof Error ? error.message : String(error),\n });\n }\n return \"ran\";\n }\n return \"missing\";\n };\n\n let disposed = false;\n // In-process pi guarantees session_start precedes every agent event (it fires after the\n // UI binds, so handlers can use dialogs). Events that arrive before the deferred startup\n // session_start — a reattach to a mid-stream session — are dropped rather than delivered\n // out of order; the transcript itself is rebuilt from components, not from these hooks.\n let started = false;\n return {\n runner,\n names: kept.map((extension) => extensionDisplayName(extension.path)),\n runCommand: async (text: string): Promise<boolean> => {\n const trimmed = text.trimStart();\n if (!trimmed.startsWith(\"/\")) return false;\n const space = trimmed.indexOf(\" \");\n const name = space === -1 ? trimmed.slice(1) : trimmed.slice(1, space);\n const args = space === -1 ? \"\" : trimmed.slice(space + 1).trim();\n return (await invokeLocalCommand(name, args)) === \"ran\";\n },\n runLocalCommand: async (name: string, args: string): Promise<boolean> => {\n const bare = name.startsWith(\"/\") ? name.slice(1) : name;\n if (bare === \"\") return false;\n // Same-name registrations from different extensions collide: pi's runner\n // resolves getCommand() its own way, so refuse to guess and report every\n // claimant's sourceInfo instead of silently picking a winner.\n const claimants = runner\n .getRegisteredCommands()\n .filter((c) => c.name === bare || c.invocationName === bare);\n const sources = new Set(claimants.map((c) => JSON.stringify(c.sourceInfo ?? null)));\n if (sources.size > 1) {\n throw new Error(\n `/${bare} is registered by several local extensions (${[...sources].join(\"; \")}) — disambiguate explicitly`,\n );\n }\n return (await invokeLocalCommand(bare, args)) === \"ran\";\n },\n emitAgentEvent: (event: unknown): void => {\n if (disposed || !started) return;\n const type = (event as { type?: string }).type ?? \"\";\n if (!FORWARDED_EVENTS.has(type) || !runner.hasHandlers(type)) return;\n void runner.emit(event).catch((error: unknown) => {\n debug(`client extension ${type} handler failed: ${error instanceof Error ? error.message : String(error)}`);\n });\n },\n emitLifecycle: emitObservational,\n sessionStart: (reason, opts) => {\n started = true;\n return emitLifecycle({\n type: \"session_start\",\n reason,\n ...(opts?.previousSessionFile !== undefined\n ? { previousSessionFile: opts.previousSessionFile }\n : {}),\n });\n },\n sessionShutdown: async (reason, opts) => {\n await emitLifecycle({\n type: \"session_shutdown\",\n reason,\n ...(opts?.targetSessionFile !== undefined ? { targetSessionFile: opts.targetSessionFile } : {}),\n });\n // Between shutdown and the next start the runner has no live session: drop stray\n // agent events rather than delivering them out of order to the replacement session.\n started = false;\n },\n dispose: async (): Promise<void> => {\n if (disposed) return;\n disposed = true;\n unbindUi();\n runner.invalidate(\"This client-side extension context is stale: the pi pod session has ended.\");\n },\n };\n}\n","/**\n * Synchronous cache backing Pi's local InteractiveMode while the authoritative session\n * lives in the pod.\n *\n * `entries` is the active context branch (what `buildContextEntries` returns), not the\n * session log. `tree` is folded from the pod's flat summary rows so `/tree` still sees\n * the whole DAG without shipping every entry's content.\n */\nimport { sessionEntryToContextMessages } from \"@earendil-works/pi-coding-agent\";\nimport type { RpcSessionState, SessionEntry, SessionStats, SessionTreeNode } from \"@earendil-works/pi-coding-agent\";\nimport type { RpcClientBase, ThinkingLevel } from \"../rpc.js\";\nimport type {\n SeedContextData,\n SeedTreeSummaryData,\n SeedTreeSummaryNode,\n SessionSeedBridge,\n} from \"./pod-extension-bridge.js\";\n\nconst SNAPSHOT_ATTEMPTS = 3;\nconst NO_EXPECTED_LEAF = Symbol(\"no-expected-leaf\");\ntype ExpectedLeaf = string | null | typeof NO_EXPECTED_LEAF;\n\ninterface LabelMutation {\n label: string | null;\n timestamp: string;\n}\n\ninterface LabelState {\n revision: number;\n confirmedLabel: string | null;\n confirmedTimestamp: string | undefined;\n pendingMutations: Map<number, LabelMutation>;\n}\n\nexport interface ReconciledSessionSnapshot {\n leafId: string | null;\n tree: SessionTreeNode[];\n}\n\n/** The token/cost sums pi's footer accumulates: message usage plus summary-generation usage. */\nexport interface UsageTotals {\n input: number;\n output: number;\n cacheRead: number;\n cacheWrite: number;\n cost: number;\n}\n\nexport class RemoteStateCache {\n state: RpcSessionState = {\n thinkingLevel: \"off\",\n isStreaming: false,\n isCompacting: false,\n steeringMode: \"all\",\n followUpMode: \"one-at-a-time\",\n sessionId: \"\",\n autoCompactionEnabled: true,\n messageCount: 0,\n pendingMessageCount: 0,\n };\n messages: unknown[] = [];\n /** Active context branch, not the full session log. */\n entries: SessionEntry[] = [];\n tree: SessionTreeNode[] = [];\n /** Authoritative active branch leaf. This is intentionally not the replay cursor. */\n leafId: string | null = null;\n /** Compactions in the full session log; branch-only entries cannot reconstruct this. */\n compactionCount = 0;\n /** User messages across the whole DAG, for the fork picker. Null until first seed. */\n forkMessages: Array<{ entryId: string; text: string }> | null = null;\n availableModels: unknown[] = [];\n /** Semantic gateway answer for the active model; null means use the compatibility fallback. */\n availableThinkingLevels: ThinkingLevel[] | null = null;\n /** Raw remote command list, including private capability commands. */\n commands: unknown[] = [];\n isBashRunning = false;\n /**\n * Usage in the pod's full session log that the cached branch entries cannot see —\n * pre-compaction messages and abandoned branches. Pi's footer sums the whole log, so\n * without this overlay a pod session's cumulative totals silently shrink at every\n * compaction. Null until the first stats fetch, and whenever the branch already\n * accounts for everything.\n */\n hiddenUsage: UsageTotals | null = null;\n /** Last authoritative full-log stats from the pod; null until the first boundary fetch. */\n sessionStats: SessionStats | null = null;\n /** Repaint hook: async refreshes land after the event that triggered the last render. */\n onRefreshed: (() => void) | null = null;\n\n /**\n * Pi's InteractiveMode calls getSessionStats() synchronously (its /session handler\n * destructures the result), so the RPC promise cannot cross this surface. Serve the\n * cached full-log stats, or derive branch-only stats before the first fetch lands.\n */\n sessionStatsSnapshot(): SessionStats {\n return this.sessionStats ?? branchSessionStats(this.entries, this.state);\n }\n\n /**\n * Forget locally-cached turn flags after the pod sleeps. A stale `isCompacting`\n * makes InteractiveMode queue the next submit locally (no RPC, so no wake); a\n * stale `isStreaming` steers instead of prompting. Truth is re-seeded on wake.\n */\n forceIdle(): void {\n this.state.isStreaming = false;\n this.state.isCompacting = false;\n this.isBashRunning = false;\n }\n\n\n private sessionRefreshPromise: Promise<ReconciledSessionSnapshot> | null = null;\n private sessionRefreshRequested = false;\n private expectedRefreshLeaf: ExpectedLeaf = NO_EXPECTED_LEAF;\n private cacheGeneration = 0;\n private replacementInProgress = false;\n private readonly labelStates = new Map<string, LabelState>();\n private seedBridge: SessionSeedBridge | null = null;\n\n constructor(private readonly rpc: RpcClientBase) {}\n\n bindSeedBridge(bridge: SessionSeedBridge): void {\n this.seedBridge = bridge;\n }\n\n private usesSeedBridge(): boolean {\n return this.seedBridge?.supportsSeedBridge(this.commands) === true;\n }\n\n /** Re-seed as one strict cache generation; failure leaves the previous generation intact. */\n async reset(): Promise<void> {\n const generation = ++this.cacheGeneration;\n this.replacementInProgress = true;\n let succeeded = false;\n try {\n if (this.sessionRefreshPromise) await this.sessionRefreshPromise.catch(() => {});\n await this.seed(generation);\n succeeded = true;\n } finally {\n if (generation === this.cacheGeneration) {\n this.replacementInProgress = false;\n // A successful seed already published a coherent generation. A refresh requested\n // against the replaced cache would only duplicate work on a retired in-flight loop.\n if (succeeded) this.sessionRefreshRequested = false;\n else this.sessionRefreshRequested = false;\n }\n }\n }\n\n /** Seed every synchronous surface, including tree and raw commands, as one generation. */\n async init(_strict = false): Promise<void> {\n const generation = ++this.cacheGeneration;\n if (this.sessionRefreshPromise) await this.sessionRefreshPromise.catch(() => {});\n await this.seed(generation);\n }\n\n private async seed(generation: number): Promise<void> {\n const assertCurrent = (): void => {\n if (generation !== this.cacheGeneration) throw new Error(\"session cache replacement was superseded\");\n };\n const [state, commands] = await Promise.all([this.rpc.getState(), this.rpc.getCommands()] as const);\n assertCurrent();\n this.commands = commands;\n if (!this.usesSeedBridge()) {\n throw new Error(\n \"This running pod uses an older pi pod extension. Exit Pi, then attach again so pi pod can load the updated extension.\",\n );\n }\n const [context, summary] = await Promise.all([\n this.seedBridge!.getContext(),\n this.seedBridge!.getTreeSummary(),\n ] as const);\n assertCurrent();\n this.applySeedSnapshot(state, context, summary);\n void this.refreshModels();\n }\n\n private applySeedSnapshot(\n state: RpcSessionState,\n context: SeedContextData,\n summary: SeedTreeSummaryData,\n ): void {\n this.state = state;\n this.entries = dedupeEntries(context.entries);\n // Derived, not fetched: a full get_messages reply is one unbounded frame that a long\n // session can push past the transport's 64 MiB line drop (the 2026-08 attach outages).\n // pi rebuilds its own message list the same way: buildContextEntries().flatMap(convert).\n this.messages = deriveMessages(this.entries);\n this.compactionCount = context.compactionCount;\n this.leafId = context.leafId;\n this.reconcileTree(foldTreeSummary(summary.nodes));\n this.resetLabelStatesFromTree();\n // The old session's overlay and stats must not survive into a replacement's totals.\n this.hiddenUsage = null;\n this.sessionStats = null;\n void this.refreshForkMessages();\n void this.refreshHiddenUsage();\n }\n\n /** Keep streaming/compaction flags live and reconcile at every completion boundary. */\n wire(): () => void {\n return this.rpc.onEvent((event) => {\n const type = (event as { type?: string }).type;\n switch (type) {\n case \"agent_start\":\n this.state.isStreaming = true;\n break;\n case \"compaction_start\":\n this.state.isCompacting = true;\n break;\n case \"bash_execution_start\":\n this.isBashRunning = true;\n break;\n case \"bash_execution_end\":\n this.isBashRunning = false;\n break;\n case \"agent_end\":\n this.state.isStreaming = false;\n void this.refreshState();\n void this.refreshTree().catch(() => {});\n break;\n case \"compaction_end\":\n this.state.isCompacting = false;\n void this.refreshState();\n void this.refreshTree().catch(() => {});\n break;\n case \"agent_settled\":\n this.state.isStreaming = false;\n this.state.isCompacting = false;\n void this.refreshState();\n void this.refreshTree().catch(() => {});\n break;\n case \"entry_appended\":\n this.applyEntryAppended((event as { entry: SessionEntry }).entry);\n break;\n case \"session_info_changed\":\n // Applied synchronously as well as refreshed: the host InteractiveMode handles this\n // same event by reading the name back through this cache to retitle the terminal, so\n // an async-only refresh would leave the tab title one rename behind.\n this.state.sessionName = (event as { name?: string }).name;\n void this.refreshState();\n break;\n }\n });\n }\n\n async refreshState(): Promise<void> {\n if (this.replacementInProgress) return;\n const generation = this.cacheGeneration;\n try {\n const state = await this.rpc.getState();\n if (generation === this.cacheGeneration && !this.replacementInProgress) {\n this.state = state;\n this.onRefreshed?.();\n }\n } catch {\n // The session driver owns transport reporting; retain the last coherent state.\n }\n }\n\n /**\n * Recompute the hidden-usage overlay from the pod's authoritative full-log totals.\n * The delta is frozen against the branch entries current at fetch time: usage appended\n * afterwards grows the branch and the log equally, so branch + delta stays correct\n * between completion boundaries.\n */\n private async refreshHiddenUsage(): Promise<void> {\n const generation = this.cacheGeneration;\n try {\n const stats = await this.rpc.getSessionStats();\n if (generation !== this.cacheGeneration || this.replacementInProgress) return;\n this.sessionStats = stats;\n const branch = branchUsageTotals(this.entries);\n const hidden: UsageTotals = {\n input: Math.max(0, stats.tokens.input - branch.input),\n output: Math.max(0, stats.tokens.output - branch.output),\n cacheRead: Math.max(0, stats.tokens.cacheRead - branch.cacheRead),\n cacheWrite: Math.max(0, stats.tokens.cacheWrite - branch.cacheWrite),\n cost: Math.max(0, stats.cost - branch.cost),\n };\n const empty =\n hidden.input === 0 && hidden.output === 0 && hidden.cacheRead === 0 &&\n hidden.cacheWrite === 0 && hidden.cost < 1e-9;\n this.hiddenUsage = empty ? null : hidden;\n this.onRefreshed?.();\n } catch {\n // Totals keep the previous overlay; the next boundary refresh retries.\n }\n }\n\n\n /** Compatibility name: entry refreshes now reconcile entries, tree, messages, and leaf together. */\n refreshEntries(): Promise<void> {\n return this.refreshTree().then(() => undefined);\n }\n\n /** Await the refresh an event listener already started, or start one if none is active. */\n reconcileTreeAfterEvent(): Promise<ReconciledSessionSnapshot> {\n return this.sessionRefreshPromise ?? this.refreshTree();\n }\n\n /** Coalesce session refreshes. Each pass re-pulls context + summary. */\n refreshTree(expectedLeaf?: string | null): Promise<ReconciledSessionSnapshot> {\n this.sessionRefreshRequested = true;\n if (arguments.length > 0) this.expectedRefreshLeaf = expectedLeaf ?? null;\n if (this.replacementInProgress) {\n return Promise.resolve({ leafId: this.leafId, tree: cloneTree(this.tree) });\n }\n if (this.sessionRefreshPromise) {\n const active = this.sessionRefreshPromise;\n return active.then((result) => (this.sessionRefreshRequested ? this.refreshTree() : result));\n }\n this.sessionRefreshPromise = this.runSessionRefreshLoop().finally(() => {\n this.sessionRefreshPromise = null;\n });\n return this.sessionRefreshPromise;\n }\n\n private async runSessionRefreshLoop(): Promise<ReconciledSessionSnapshot> {\n let result: ReconciledSessionSnapshot = { leafId: this.leafId, tree: cloneTree(this.tree) };\n while (this.sessionRefreshRequested) {\n if (this.replacementInProgress) return result;\n this.sessionRefreshRequested = false;\n const expected = this.expectedRefreshLeaf;\n this.expectedRefreshLeaf = NO_EXPECTED_LEAF;\n result = await this.refreshSessionOnce(expected);\n }\n return result;\n }\n\n private async refreshSessionOnce(expected: ExpectedLeaf): Promise<ReconciledSessionSnapshot> {\n if (!this.usesSeedBridge()) {\n throw new Error(\n \"This running pod uses an older pi pod extension. Exit Pi, then attach again so pi pod can load the updated extension.\",\n );\n }\n return this.refreshFromSeedBridge(expected);\n }\n\n private async refreshFromSeedBridge(expected: ExpectedLeaf): Promise<ReconciledSessionSnapshot> {\n const generation = this.cacheGeneration;\n let lastError: Error | null = null;\n for (let attempt = 1; attempt <= SNAPSHOT_ATTEMPTS; attempt++) {\n try {\n const [context, summary] = await Promise.all([\n this.seedBridge!.getContext(),\n this.seedBridge!.getTreeSummary(),\n ] as const);\n if (expected !== NO_EXPECTED_LEAF && context.leafId !== expected) {\n lastError = new Error(\n `pod session refresh did not reconcile (ack ${String(expected)}, context ${String(context.leafId)})`,\n );\n continue;\n }\n if (generation !== this.cacheGeneration || this.replacementInProgress) {\n throw new Error(\"session cache refresh was superseded\");\n }\n if (this.expectedRefreshLeaf !== NO_EXPECTED_LEAF) {\n this.sessionRefreshRequested = true;\n return { leafId: this.leafId, tree: cloneTree(this.tree) };\n }\n const nextTree = foldTreeSummary(summary.nodes);\n this.entries = dedupeEntries(context.entries);\n this.messages = deriveMessages(this.entries);\n this.compactionCount = context.compactionCount;\n this.leafId = context.leafId;\n this.reconcileTree(nextTree);\n this.synchronizeConfirmedLabels(nextTree);\n this.reapplyLabelOverlays();\n void this.refreshForkMessages();\n void this.refreshHiddenUsage();\n this.onRefreshed?.();\n return { leafId: context.leafId, tree: nextTree };\n } catch (error) {\n if (generation !== this.cacheGeneration || this.replacementInProgress) throw error;\n lastError = error instanceof Error ? error : new Error(String(error));\n }\n }\n throw lastError ?? new Error(\"pod session refresh could not be reconciled\");\n }\n\n async refreshModels(): Promise<void> {\n try {\n this.availableModels = await this.rpc.getAvailableModels();\n } catch {\n // Catalog stays stale.\n }\n }\n\n async refreshCommands(): Promise<void> {\n try {\n this.commands = await this.rpc.getCommands();\n } catch {\n // Capability list stays stale and callers fail closed.\n }\n }\n\n private async refreshForkMessages(): Promise<void> {\n try {\n this.forkMessages = await this.rpc.getForkMessages();\n } catch {\n if (this.forkMessages === null) this.forkMessages = deriveForkMessages(this.entries);\n }\n }\n\n private applyEntryAppended(entry: SessionEntry): void {\n if (!entry || typeof entry.id !== \"string\") return;\n if (!this.entries.some((existing) => existing.id === entry.id)) this.entries.push(entry);\n if (!findTreeNode(this.tree, entry.id)) {\n const node: SessionTreeNode = { entry, children: [] };\n const parent = entry.parentId ? findTreeNode(this.tree, entry.parentId) : undefined;\n if (parent) parent.children.push(node);\n else this.tree.push(node);\n }\n if (entry.type === \"label\") {\n const target = findTreeNode(this.tree, entry.targetId);\n if (target) {\n if (entry.label) {\n target.label = entry.label;\n target.labelTimestamp = entry.timestamp;\n } else {\n delete target.label;\n delete target.labelTimestamp;\n }\n }\n }\n this.leafId = entry.id;\n if (entry.type === \"compaction\") this.compactionCount += 1;\n if (entry.type === \"message\" && entry.message?.role === \"user\") {\n const text = forkText(entry);\n if (text !== undefined) {\n const messages = this.forkMessages ?? [];\n if (!messages.some((item) => item.entryId === entry.id)) {\n this.forkMessages = [...messages, { entryId: entry.id, text }];\n }\n }\n }\n }\n\n beginLabelMutation(entryId: string, label: string | null): number {\n const state = this.labelStates.get(entryId) ?? this.createLabelState(entryId);\n const revision = ++state.revision;\n state.pendingMutations.set(revision, { label, timestamp: new Date().toISOString() });\n this.applyLabelState(entryId, state);\n return revision;\n }\n\n completeLabelMutation(\n entryId: string,\n revision: number,\n outcome:\n | { ok: false }\n | { ok: true; label: string | null; labelTimestamp: string | undefined },\n ): void {\n const state = this.labelStates.get(entryId);\n if (!state || !state.pendingMutations.has(revision)) return;\n state.pendingMutations.delete(revision);\n if (outcome.ok) {\n state.confirmedLabel = outcome.label;\n state.confirmedTimestamp = outcome.labelTimestamp;\n }\n this.applyLabelState(entryId, state);\n }\n\n private createLabelState(entryId: string): LabelState {\n const node = findTreeNode(this.tree, entryId);\n const state: LabelState = {\n revision: 0,\n confirmedLabel: node?.label ?? null,\n confirmedTimestamp: node?.labelTimestamp,\n pendingMutations: new Map(),\n };\n this.labelStates.set(entryId, state);\n return state;\n }\n\n private resetLabelStatesFromTree(): void {\n this.labelStates.clear();\n }\n\n private synchronizeConfirmedLabels(authoritativeTree: SessionTreeNode[]): void {\n for (const [entryId, state] of this.labelStates) {\n if (state.pendingMutations.size > 0) continue;\n const node = findTreeNode(authoritativeTree, entryId);\n state.confirmedLabel = node?.label ?? null;\n state.confirmedTimestamp = node?.labelTimestamp;\n }\n }\n\n private reapplyLabelOverlays(): void {\n for (const [entryId, state] of this.labelStates) this.applyLabelState(entryId, state);\n }\n\n private applyLabelState(entryId: string, state: LabelState): void {\n const node = findTreeNode(this.tree, entryId);\n if (!node) return;\n const latest = [...state.pendingMutations.entries()].at(-1)?.[1];\n const label = latest ? latest.label : state.confirmedLabel;\n const timestamp = latest?.timestamp ?? state.confirmedTimestamp;\n if (label) {\n node.label = label;\n node.labelTimestamp = timestamp;\n } else {\n delete node.label;\n delete node.labelTimestamp;\n }\n }\n\n /** Reconcile nodes in place so an already-open TreeSelector keeps authoritative objects. */\n private reconcileTree(authoritative: SessionTreeNode[]): void {\n const existing = new Map<string, SessionTreeNode>();\n walkTree(this.tree, (node) => existing.set(node.entry.id, node));\n const adopt = (source: SessionTreeNode): SessionTreeNode => {\n const target = existing.get(source.entry.id) ?? { entry: source.entry, children: [] };\n target.entry = source.entry;\n if (source.label !== undefined) target.label = source.label;\n else delete target.label;\n if (source.labelTimestamp !== undefined) target.labelTimestamp = source.labelTimestamp;\n else delete target.labelTimestamp;\n return target;\n };\n const roots = authoritative.map(adopt);\n const stack = authoritative.map((source, index) => ({ source, target: roots[index]! }));\n while (stack.length > 0) {\n const { source, target } = stack.pop()!;\n const children = source.children.map(adopt);\n target.children.splice(0, target.children.length, ...children);\n source.children.forEach((child, index) => stack.push({ source: child, target: children[index]! }));\n }\n this.tree.splice(0, this.tree.length, ...roots);\n }\n}\n\n/** Branch-only stand-in for pi's getSessionStats(), used until the pod's totals arrive. */\nfunction branchSessionStats(entries: SessionEntry[], state: RpcSessionState): SessionStats {\n const totals = branchUsageTotals(entries);\n let userMessages = 0;\n let assistantMessages = 0;\n let toolResults = 0;\n let totalMessages = 0;\n let toolCalls = 0;\n for (const entry of entries) {\n if (entry.type !== \"message\") continue;\n totalMessages += 1;\n const message = entry.message as { role?: string; content?: unknown };\n if (message.role === \"user\") userMessages += 1;\n else if (message.role === \"toolResult\") toolResults += 1;\n else if (message.role === \"assistant\") {\n assistantMessages += 1;\n if (Array.isArray(message.content)) {\n toolCalls += message.content.filter((part: { type?: string }) => part.type === \"toolCall\").length;\n }\n }\n }\n return {\n sessionFile: state.sessionFile,\n sessionId: state.sessionId,\n userMessages,\n assistantMessages,\n toolCalls,\n toolResults,\n totalMessages,\n tokens: {\n input: totals.input,\n output: totals.output,\n cacheRead: totals.cacheRead,\n cacheWrite: totals.cacheWrite,\n total: totals.input + totals.output + totals.cacheRead + totals.cacheWrite,\n },\n cost: totals.cost,\n };\n}\n\n/** The same buckets pi's footer sums: assistant + toolResult message usage, summary usage. */\nfunction branchUsageTotals(entries: SessionEntry[]): UsageTotals {\n const totals: UsageTotals = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0 };\n for (const entry of entries) {\n let usage: { input?: number; output?: number; cacheRead?: number; cacheWrite?: number; cost?: { total?: number } } | undefined;\n if (entry.type === \"message\") {\n const message = entry.message as { role?: string; usage?: typeof usage };\n if (message.role === \"assistant\" || message.role === \"toolResult\") usage = message.usage;\n } else if (entry.type === \"compaction\" || entry.type === \"branch_summary\") {\n usage = (entry as { usage?: typeof usage }).usage;\n }\n if (!usage) continue;\n totals.input += usage.input ?? 0;\n totals.output += usage.output ?? 0;\n totals.cacheRead += usage.cacheRead ?? 0;\n totals.cacheWrite += usage.cacheWrite ?? 0;\n totals.cost += usage.cost?.total ?? 0;\n }\n return totals;\n}\n\nfunction dedupeEntries(entries: SessionEntry[]): SessionEntry[] {\n const seen = new Set<string>();\n return entries.filter((entry) => {\n if (seen.has(entry.id)) return false;\n seen.add(entry.id);\n return true;\n });\n}\n\n/** Fold the pod's flat summary rows into SessionTreeNode[]. Orphans become roots. */\nexport function foldTreeSummary(nodes: SeedTreeSummaryNode[]): SessionTreeNode[] {\n const byId = new Map<string, SessionTreeNode>();\n for (const row of nodes) {\n byId.set(row.id, {\n entry: stubEntry(row),\n children: [],\n ...(row.label ? { label: row.label, labelTimestamp: row.labelTimestamp } : {}),\n });\n }\n const roots: SessionTreeNode[] = [];\n for (const row of nodes) {\n const node = byId.get(row.id)!;\n const parent =\n row.parentId === null || row.parentId === row.id ? undefined : byId.get(row.parentId);\n if (parent) parent.children.push(node);\n else roots.push(node);\n }\n return roots;\n}\n\nfunction stubEntry(row: SeedTreeSummaryNode): SessionEntry {\n const base = { id: row.id, parentId: row.parentId, timestamp: row.timestamp };\n switch (row.type) {\n case \"message\": {\n const role = row.role ?? \"user\";\n if (role === \"toolResult\") {\n return { ...base, type: \"message\", message: { role, content: [], toolName: row.toolName } } as unknown as SessionEntry;\n }\n if (role === \"bashExecution\") {\n return { ...base, type: \"message\", message: { role, command: row.preview } } as unknown as SessionEntry;\n }\n return { ...base, type: \"message\", message: { role, content: row.preview } } as unknown as SessionEntry;\n }\n case \"compaction\":\n return { ...base, type: \"compaction\", summary: row.preview, firstKeptEntryId: \"\", tokensBefore: row.tokensBefore ?? 0 } as SessionEntry;\n case \"branch_summary\":\n return { ...base, type: \"branch_summary\", fromId: \"\", summary: row.preview } as SessionEntry;\n case \"custom_message\":\n return { ...base, type: \"custom_message\", customType: row.customType ?? \"\", content: row.preview, display: true } as SessionEntry;\n case \"custom\":\n return { ...base, type: \"custom\", customType: row.customType ?? \"\" } as SessionEntry;\n case \"label\":\n return { ...base, type: \"label\", targetId: row.parentId ?? row.id, label: row.preview || undefined } as SessionEntry;\n case \"model_change\":\n return { ...base, type: \"model_change\", provider: \"\", modelId: row.modelId ?? row.preview } as SessionEntry;\n case \"thinking_level_change\":\n return { ...base, type: \"thinking_level_change\", thinkingLevel: row.thinkingLevel ?? row.preview } as SessionEntry;\n case \"session_info\":\n return { ...base, type: \"session_info\", name: row.name ?? row.preview } as SessionEntry;\n default:\n return { ...base, type: \"custom\", customType: row.type } as SessionEntry;\n }\n}\n\n/** The same projection pi applies in buildSessionContext(); tolerant of stub entries. */\nfunction deriveMessages(entries: SessionEntry[]): unknown[] {\n const messages: unknown[] = [];\n for (const entry of entries) {\n try {\n messages.push(...sessionEntryToContextMessages(entry));\n } catch {\n // A malformed entry loses its message, never the whole seed.\n }\n }\n return messages;\n}\n\nfunction deriveForkMessages(entries: SessionEntry[]): Array<{ entryId: string; text: string }> {\n const messages: Array<{ entryId: string; text: string }> = [];\n for (const entry of entries) {\n const text = forkText(entry);\n if (text !== undefined) messages.push({ entryId: entry.id, text });\n }\n return messages;\n}\n\nfunction forkText(entry: SessionEntry): string | undefined {\n if (entry.type !== \"message\" || entry.message?.role !== \"user\") return undefined;\n const content = (entry.message as { content?: unknown }).content;\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n return content.map((part: { text?: string }) => part.text ?? \"\").join(\"\");\n}\n\nfunction walkTree(tree: SessionTreeNode[], visit: (node: SessionTreeNode) => void): void {\n const stack = [...tree];\n while (stack.length > 0) {\n const node = stack.pop()!;\n visit(node);\n stack.push(...node.children);\n }\n}\n\nexport function findTreeNode(tree: SessionTreeNode[], entryId: string): SessionTreeNode | undefined {\n let found: SessionTreeNode | undefined;\n walkTree(tree, (node) => {\n if (!found && node.entry.id === entryId) found = node;\n });\n return found;\n}\n\nfunction cloneTree(tree: SessionTreeNode[]): SessionTreeNode[] {\n const copy = (node: SessionTreeNode): SessionTreeNode => ({\n ...node,\n entry: { ...node.entry } as SessionEntry,\n children: [],\n });\n const roots = tree.map(copy);\n const stack = tree.map((source, index) => ({ source, target: roots[index]! }));\n while (stack.length > 0) {\n const { source, target } = stack.pop()!;\n for (const child of source.children) {\n const clone = copy(child);\n target.children.push(clone);\n stack.push({ source: child, target: clone });\n }\n }\n return roots;\n}\n","import * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport {\n CURRENT_SESSION_VERSION,\n getPackageDir,\n SessionManager,\n SessionSelectorComponent,\n type SessionEntry,\n type SessionInfo,\n} from \"@earendil-works/pi-coding-agent\";\nimport type {\n GatewayRpcClient,\n SessionCatalogEntry,\n SessionsFrame,\n} from \"../../account/gateway-rpc.js\";\nimport type { RemoteRuntime } from \"./remote-runtime.js\";\n\nconst SESSION_CATALOG_UNAVAILABLE =\n \"Pod session list needs an updated server/pod. Exit Pi, then attach again after the server is updated.\";\nconst TRUST_FIXED = \"Pod trust is fixed at pod creation and cannot be changed from a pod session.\";\nconst RELOAD_UNAVAILABLE =\n \"Pod resource reload isn't available in this pod session; exit and re-attach to pick up resource changes. Launcher chords remain available.\";\n\ninterface PodInteractiveMode {\n session: {\n isStreaming: boolean;\n isCompacting: boolean;\n reload(options?: unknown): Promise<void>;\n modelRuntime: unknown;\n state: unknown;\n };\n ui: {\n requestRender(force?: boolean): void;\n };\n editorContainer: unknown;\n editor: unknown;\n keybindings: unknown;\n showSelector(create: (done: () => void) => { component: unknown; focus: unknown }): void;\n handleResumeSession(path: string): Promise<unknown>;\n getPathCommandArgument(text: string, command: string): string | undefined;\n showStatus(message: string): void;\n showWarning(message: string): void;\n showError(message: string): void;\n shutdown(): Promise<void>;\n showSessionSelector(): void;\n showTrustSelector(): void;\n handleExportCommand(text: string): Promise<void>;\n handleShareCommand(): Promise<void>;\n handleReloadCommand(): Promise<void>;\n}\n\nexport interface MaterializedSession {\n sessionId: string;\n cwd: string;\n entries: readonly SessionEntry[];\n timestamp?: string;\n}\n\ninterface ExportFromFile {\n (inputPath: string, options?: { outputPath?: string; themeName?: string }): Promise<string>;\n}\n\ninterface ShareSession {\n (context: {\n session: unknown;\n ui: unknown;\n editorContainer: unknown;\n editor: unknown;\n showStatus(message: string): void;\n showError(message: string): void;\n }): Promise<void>;\n}\n\n/** Convert the server catalog into Pi's picker shape without reviving any local sessions. */\nexport function catalogToSessionInfo(entries: readonly SessionCatalogEntry[]): SessionInfo[] {\n const pathById = new Map(\n entries.flatMap((entry) => entry.path ? [[entry.id, entry.path] as const] : []),\n );\n return entries.flatMap((entry) => {\n if (!entry.path) return [];\n const parentSessionPath = entry.parentSessionId ? pathById.get(entry.parentSessionId) : undefined;\n return [{\n path: entry.path,\n id: entry.id,\n cwd: entry.cwd ?? \"\",\n ...(entry.name !== undefined ? { name: entry.name } : {}),\n ...(parentSessionPath !== undefined ? { parentSessionPath } : {}),\n created: new Date(entry.createdAt),\n modified: new Date(entry.modified ?? entry.createdAt),\n messageCount: entry.messageCount ?? 0,\n firstMessage: entry.firstMessage ?? \"\",\n // Search remains metadata-only in v1; transcript text stays beside the pod-side index.\n allMessagesText: \"\",\n }];\n });\n}\n\n/** Loader pair used by SessionSelectorComponent: exact pod-workdir matches vs the full catalog. */\nexport function catalogLoaders(frame: SessionsFrame): {\n current(): Promise<SessionInfo[]>;\n all(): Promise<SessionInfo[]>;\n} {\n const all = catalogToSessionInfo(frame.sessions);\n const current = all.filter((session) => session.cwd === frame.workdir);\n return {\n current: async () => current,\n all: async () => all,\n };\n}\n\n/** Deterministic branch materialization in Pi's native version-3 JSONL format. */\nexport function materializeSessionJsonl(session: MaterializedSession): string {\n const timestamp = session.timestamp ?? new Date().toISOString();\n const header = {\n type: \"session\" as const,\n version: CURRENT_SESSION_VERSION,\n id: session.sessionId,\n timestamp,\n cwd: session.cwd,\n };\n let parentId: string | null = null;\n const entries = session.entries.map((entry) => {\n const linear = { ...entry, parentId };\n parentId = entry.id;\n return linear;\n });\n return [...[header], ...entries].map((entry) => JSON.stringify(entry)).join(\"\\n\") + \"\\n\";\n}\n\nexport function writeMaterializedSession(filePath: string, session: MaterializedSession): string {\n const resolved = path.resolve(filePath);\n fs.mkdirSync(path.dirname(resolved), { recursive: true });\n fs.writeFileSync(resolved, materializeSessionJsonl(session), \"utf8\");\n return resolved;\n}\n\nasync function loadPiCommandInternals(): Promise<{ exportFromFile: ExportFromFile; shareSession: ShareSession }> {\n const packageDir = getPackageDir();\n const exporter = await import(pathToFileURL(path.join(packageDir, \"dist/core/export-html/index.js\")).href) as {\n exportFromFile: ExportFromFile;\n };\n const sharing = await import(pathToFileURL(path.join(packageDir, \"dist/modes/interactive/session-share.js\")).href) as {\n shareSession: ShareSession;\n };\n return { exportFromFile: exporter.exportFromFile, shareSession: sharing.shareSession };\n}\n\nasync function withMaterializedSession<T>(\n session: MaterializedSession,\n run: (inputPath: string) => Promise<T>,\n): Promise<T> {\n const dir = fs.mkdtempSync(path.join(os.tmpdir(), \"pi-pod-session-\"));\n const safeId = session.sessionId.replace(/[^A-Za-z0-9._-]/g, \"-\") || \"current\";\n const inputPath = path.join(dir, `session-${safeId}.jsonl`);\n try {\n writeMaterializedSession(inputPath, session);\n return await run(inputPath);\n } finally {\n fs.rmSync(dir, { recursive: true, force: true });\n }\n}\n\nexport async function exportMaterializedSessionToHtml(\n session: MaterializedSession,\n outputPath?: string,\n themeName?: string,\n): Promise<string> {\n return withMaterializedSession(session, async (inputPath) => {\n const { exportFromFile } = await loadPiCommandInternals();\n return exportFromFile(inputPath, {\n ...(outputPath !== undefined ? { outputPath } : {}),\n ...(themeName !== undefined ? { themeName } : {}),\n });\n });\n}\n\n/** Install the one temporary InteractiveMode shim deleted by the upstream runtime-service seam. */\nexport function installPodCommandOverrides(\n modeValue: InstanceType<typeof import(\"@earendil-works/pi-coding-agent\").InteractiveMode>,\n runtime: Pick<RemoteRuntime, \"cache\" | \"treeBridge\" | \"refreshAfterReplacement\">,\n gateway: Pick<GatewayRpcClient, \"getSessions\" | \"searchSessions\" | \"reloadResources\">,\n getPodWorkdir: () => string,\n): void {\n const mode = modeValue as unknown as PodInteractiveMode;\n\n mode.showSessionSelector = () => {\n void gateway.getSessions().then((frame) => {\n if (frame.unsupported) {\n mode.showWarning(SESSION_CATALOG_UNAVAILABLE);\n return;\n }\n const loaders = catalogLoaders(frame);\n if (!frame.complete) mode.showWarning(\"Showing the most recent pod sessions; the catalog was capped.\");\n mode.showSelector((done) => {\n const selector = new SessionSelectorComponent(\n loaders.current,\n loaders.all,\n async (sessionPath) => {\n done();\n await mode.handleResumeSession(sessionPath);\n },\n () => {\n done();\n mode.ui.requestRender();\n },\n () => { void mode.shutdown(); },\n () => mode.ui.requestRender(),\n { showRenameHint: false, keybindings: mode.keybindings as never },\n runtime.cache.state.sessionFile,\n );\n return { component: selector, focus: selector };\n });\n }).catch((error: unknown) => {\n mode.showWarning(`${SESSION_CATALOG_UNAVAILABLE} (${error instanceof Error ? error.message : String(error)})`);\n });\n };\n\n mode.showTrustSelector = () => {\n mode.showWarning(TRUST_FIXED);\n };\n\n mode.handleExportCommand = async (text) => {\n const outputPath = mode.getPathCommandArgument(text, \"/export\");\n if (outputPath?.endsWith(\".jsonl\")) {\n mode.showWarning(\"/export JSONL is not available in pod sessions; use HTML export instead.\");\n return;\n }\n try {\n await runtime.cache.refreshTree();\n const filePath = await exportMaterializedSessionToHtml({\n sessionId: runtime.cache.state.sessionId,\n cwd: getPodWorkdir(),\n entries: runtime.cache.entries,\n }, outputPath);\n mode.showStatus(`Session exported to: ${filePath}`);\n } catch (error) {\n mode.showError(`Failed to export session: ${error instanceof Error ? error.message : \"Unknown error\"}`);\n }\n };\n\n mode.handleShareCommand = async () => {\n try {\n await runtime.cache.refreshTree();\n await withMaterializedSession({\n sessionId: runtime.cache.state.sessionId,\n cwd: getPodWorkdir(),\n entries: runtime.cache.entries,\n }, async (inputPath) => {\n const manager = SessionManager.open(inputPath);\n const { exportFromFile, shareSession } = await loadPiCommandInternals();\n const shareFacade = new Proxy(mode.session as object, {\n get(target, property, receiver) {\n if (property === \"sessionManager\") return manager;\n if (property === \"exportToHtml\") {\n return (outputPath?: string, options?: { themeName?: string }) =>\n exportFromFile(inputPath, {\n ...(outputPath !== undefined ? { outputPath } : {}),\n ...(options?.themeName !== undefined ? { themeName: options.themeName } : {}),\n });\n }\n return Reflect.get(target, property, receiver);\n },\n });\n await shareSession({\n session: shareFacade,\n ui: mode.ui,\n editorContainer: mode.editorContainer,\n editor: mode.editor,\n showStatus: (message) => mode.showStatus(message),\n showError: (message) => mode.showError(message),\n });\n });\n } catch (error) {\n mode.showError(`Failed to share session: ${error instanceof Error ? error.message : \"Unknown error\"}`);\n }\n };\n\n mode.handleReloadCommand = async () => {\n if (mode.session.isStreaming) {\n mode.showWarning(\"Wait for the current response to finish before reloading.\");\n return;\n }\n if (mode.session.isCompacting) {\n mode.showWarning(\"Wait for compaction to finish before reloading.\");\n return;\n }\n const result = await gateway.reloadResources();\n if (result.unsupported) {\n await mode.session.reload();\n mode.showWarning(RELOAD_UNAVAILABLE);\n return;\n }\n if (!result.ok) {\n mode.showError(\"Pod resource reload failed.\");\n return;\n }\n try {\n await runtime.refreshAfterReplacement();\n await mode.session.reload();\n mode.showStatus(\"Reloaded pod resources and refreshed the session\");\n } catch (error) {\n mode.showError(`Reload failed: ${error instanceof Error ? error.message : String(error)}`);\n }\n };\n}\n","/**\n * src/client/runtime/local-images.ts — local image attachments for remote prompts.\n *\n * The TUI runs on this machine while the agent runs in the pod. A prompt that names a\n * host-side image — a clipboard paste (pi writes host /tmp and inserts the path), a\n * drag-dropped file, an `@screenshot.png` mention, a typed relative path — would otherwise\n * cross the wire as bare text pointing at a file the pod cannot see, and the pod-side\n * `read` of that path fails. This module finds those references, reads and processes the\n * bytes locally with pi's own image pipeline, and returns them as inline `ImageContent`\n * for the existing `prompt` / `steer` / `follow_up` RPC `images` field. No new RPC method,\n * no gateway change: the semantic protocol already carries images verbatim.\n *\n * Bounds mirror the gateway (`stream-fanout.ts validatePromptImages`) so a prompt this\n * module builds is never rejected server-side: at most {@link MAX_PROMPT_IMAGES} images\n * per prompt *including* already-attached ones the caller passes in, at most\n * {@link MAX_IMAGE_BASE64_CHARS} base64 chars per image (8 MiB decoded), and at most\n * {@link MAX_PROMPT_IMAGES_TOTAL_BASE64_CHARS} base64 chars total. Anything over budget is\n * left as plain text with an `[Image omitted: …]` marker and a user-visible warning — a\n * rejected prompt sends nothing at all, so degrading to text is strictly more useful.\n *\n * Only paths that resolve to a regular local file with an image suffix (or an `@` mention\n * of one) are read — never directories, devices, or wildcards. Reads are bounded: one\n * open, one stat, one capped read, so a file that grows between calls cannot blow up the\n * host. Anything that does not resolve locally is left byte-identical so pod-side `@`\n * references and pod paths keep working.\n */\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport {\n convertToPng,\n formatDimensionNote,\n resizeImage,\n} from \"@earendil-works/pi-coding-agent\";\nimport { debug } from \"../../log.js\";\nimport type { ImageContent } from \"../rpc.js\";\n\n/** Suffixes this module will consider. Detection is by content sniff, not by suffix. */\nconst IMAGE_SUFFIXES = new Set([\"png\", \"jpg\", \"jpeg\", \"gif\", \"webp\", \"bmp\"]);\n/** Inline provider images: anything else (bmp, undecodable) gets one PNG conversion attempt. */\nconst INLINE_MIME_TYPES = new Set([\"image/png\", \"image/jpeg\", \"image/gif\", \"image/webp\"]);\n/**\n * At most this many local images ride one prompt, *including* images the caller already\n * attached (extension-supplied parts). Matches the gateway's MAX_PROMPT_IMAGES.\n */\nexport const MAX_PROMPT_IMAGES = 8;\n/** Max base64 chars per sent image (8 MiB decoded). Matches the gateway's per-image cap. */\nexport const MAX_IMAGE_BASE64_CHARS = 11_184_812;\n/**\n * Max base64 chars across every image on one prompt (32 MiB, ~24 MiB decoded). Matches\n * the gateway's total cap; the C-frame base64-expands the RPC JSON again, so this is what\n * keeps the turn under the 64 MiB transport line limit.\n */\nexport const MAX_PROMPT_IMAGES_TOTAL_BASE64_CHARS = 32 * 1024 * 1024;\n/**\n * Raw on-disk read bound per image. Well above what the pipeline emits (pi resizes to\n * ~4.5 MB), purely a host-side DoS cap so a huge file never fully loads into memory.\n */\nexport const MAX_IMAGE_FILE_BYTES = 24 * 1024 * 1024;\n/** Same path sanity cap as the `@` file-listing channel. */\nexport const MAX_IMAGE_PATH_CHARS = 1024;\n\nexport interface PreparedPromptImages {\n /** Original text plus one `<file name=\"…\">` marker line per attached/omitted image. */\n text: string;\n /** Inline attachments for the RPC `images` field; undefined when nothing attached. */\n images: ImageContent[] | undefined;\n /** Absolute host paths that became inline attachments, in prompt order. */\n attached: string[];\n /** References that named a real local file but could not be attached. */\n omitted: Array<{ path: string; message: string }>;\n}\n\nexport interface PreparePromptImagesOptions {\n /** Host working directory bare relative paths resolve against. */\n cwd: string;\n /** Warn the user about detected-but-unusable images; silent otherwise. */\n notify?: ((message: string, type: \"info\" | \"warning\" | \"error\") => void) | undefined;\n /**\n * Images the caller already attached (e.g. extension-supplied parts sent alongside the\n * prompt). They share the per-prompt count/total budget: scanning stops before the\n * combined turn could exceed what the gateway accepts, so the prompt is never rejected\n * wholesale for an oversized `images` array.\n */\n existingImages?: ImageContent[] | undefined;\n}\n\n/**\n * Scan prompt text for local image references and attach what resolves.\n *\n * Never throws: every filesystem or image-pipeline failure degrades to leaving the text\n * untouched (or appending an omit note when the file provably exists locally). Callers\n * send `result.text` with `[...(existing ?? []), ...(result.images ?? [])]` on the\n * existing prompt path.\n */\nexport async function preparePromptImages(\n text: string,\n opts: PreparePromptImagesOptions,\n): Promise<PreparedPromptImages> {\n const candidates = collectImageCandidates(text);\n const attached: string[] = [];\n const omitted: Array<{ path: string; message: string }> = [];\n const images: ImageContent[] = [];\n const markers: string[] = [];\n const seen = new Set<string>();\n\n const existing = opts.existingImages ?? [];\n let totalBase64Chars = 0;\n for (const image of existing) {\n if (typeof image?.data === \"string\") totalBase64Chars += image.data.length;\n }\n let slotsLeft = MAX_PROMPT_IMAGES - existing.length;\n const overBudgetAlready =\n existing.length > MAX_PROMPT_IMAGES || totalBase64Chars > MAX_PROMPT_IMAGES_TOTAL_BASE64_CHARS;\n if (overBudgetAlready && candidates.length > 0) {\n opts.notify?.(\n `prompt already carries ${existing.length} attached image${existing.length === 1 ? \"\" : \"s\"}; local file references were left as text so the turn stays within the image budget`,\n \"warning\",\n );\n }\n\n for (const candidate of candidates) {\n const absPath = resolveCandidate(candidate, opts.cwd);\n if (!absPath || seen.has(absPath)) continue;\n seen.add(absPath);\n if (overBudgetAlready || slotsLeft <= 0) {\n omitted.push({ path: absPath, message: `more than ${MAX_PROMPT_IMAGES} images in one prompt` });\n continue;\n }\n const outcome = await attachImage(absPath);\n if (outcome.kind === \"missing\") continue; // A pod-side path: leave the text alone.\n if (outcome.kind === \"omitted\") {\n omitted.push({ path: absPath, message: outcome.message });\n markers.push(`<file name=\"${markerName(absPath)}\">${outcome.message}</file>`);\n continue;\n }\n if (outcome.image.data.length > MAX_IMAGE_BASE64_CHARS) {\n const message = \"[Image omitted: the processed image exceeds the 8 MiB per-image limit.]\";\n omitted.push({ path: absPath, message });\n markers.push(`<file name=\"${markerName(absPath)}\">${message}</file>`);\n continue;\n }\n if (totalBase64Chars + outcome.image.data.length > MAX_PROMPT_IMAGES_TOTAL_BASE64_CHARS) {\n const message = \"[Image omitted: attaching it would exceed the total image budget for one prompt.]\";\n omitted.push({ path: absPath, message });\n markers.push(`<file name=\"${markerName(absPath)}\">${message}</file>`);\n continue;\n }\n totalBase64Chars += outcome.image.data.length;\n slotsLeft -= 1;\n images.push(outcome.image);\n attached.push(absPath);\n markers.push(\n `<file name=\"${markerName(absPath)}\">${outcome.hints.length > 0 ? outcome.hints.join(\"\\n\") : \"\"}</file>`,\n );\n }\n\n for (const skipped of omitted) {\n debug(`local image not attached (${skipped.path}): ${skipped.message}`);\n }\n if (omitted.length > 0) {\n const names = omitted.map((entry) => path.basename(entry.path)).join(\", \");\n opts.notify?.(\n `could not attach local image${omitted.length === 1 ? \"\" : \"s\"} (${names}); the prompt was sent with text references only`,\n \"warning\",\n );\n }\n return {\n text: markers.length > 0 ? `${text}\\n${markers.join(\"\\n\")}` : text,\n images: images.length > 0 ? images : undefined,\n attached,\n omitted,\n };\n}\n\ntype AttachOutcome =\n | { kind: \"missing\" }\n | { kind: \"omitted\"; message: string }\n | { kind: \"attached\"; image: ImageContent; hints: string[] };\n\n/**\n * One open, one stat, one bounded read: a file that grows (or is swapped) mid-call can at\n * most cost MAX_IMAGE_FILE_BYTES + 1 of memory, and the sniff runs on the bytes actually\n * read rather than on a second open that could see a different file.\n */\nasync function attachImage(absPath: string): Promise<AttachOutcome> {\n let handle: fs.promises.FileHandle | null = null;\n try {\n try {\n handle = await fs.promises.open(absPath, \"r\");\n } catch {\n return { kind: \"missing\" };\n }\n const stat = await handle.stat().catch(() => null);\n if (!stat || !stat.isFile()) return { kind: \"missing\" };\n if (stat.size === 0) {\n return { kind: \"omitted\", message: \"[Image omitted: the file is empty.]\" };\n }\n if (stat.size > MAX_IMAGE_FILE_BYTES) {\n return {\n kind: \"omitted\",\n message: `[Image omitted: the file exceeds the ${Math.floor(MAX_IMAGE_FILE_BYTES / (1024 * 1024))} MB per-image limit.]`,\n };\n }\n // Cap the read one byte past the limit so growth between stat and read is detected\n // rather than loaded.\n const cap = Math.min(stat.size, MAX_IMAGE_FILE_BYTES) + 1;\n const buffer = Buffer.alloc(cap);\n const { bytesRead } = await handle.read(buffer, 0, cap, 0).catch(() => ({ bytesRead: -1 }));\n if (bytesRead < 0) {\n return { kind: \"omitted\", message: \"[Image omitted: the file could not be read.]\" };\n }\n if (bytesRead > MAX_IMAGE_FILE_BYTES) {\n return {\n kind: \"omitted\",\n message: `[Image omitted: the file exceeds the ${Math.floor(MAX_IMAGE_FILE_BYTES / (1024 * 1024))} MB per-image limit.]`,\n };\n }\n const bytes = buffer.subarray(0, bytesRead);\n if (bytes.length === 0) {\n return { kind: \"omitted\", message: \"[Image omitted: the file is empty.]\" };\n }\n return await processImageBytes(bytes);\n } finally {\n await handle?.close().catch(() => {});\n }\n}\n\n/**\n * The suffix only nominates; this sniff decides — the same rule as pi's own @file\n * attachments. Magic bytes only (pi's mime.ts semantics: JPEG, still PNG, GIF, WebP go\n * inline; BMP and anything else gets one PNG conversion attempt first).\n */\nfunction sniffImageMimeType(bytes: Uint8Array): string | null {\n if (bytes.length >= 3 && bytes[0] === 0xff && bytes[1] === 0xd8 && bytes[2] === 0xff) {\n return bytes[3] === 0xf7 ? null : \"image/jpeg\";\n }\n if (\n bytes.length >= 8 &&\n bytes[0] === 0x89 && bytes[1] === 0x50 && bytes[2] === 0x4e && bytes[3] === 0x47 &&\n bytes[4] === 0x0d && bytes[5] === 0x0a && bytes[6] === 0x1a && bytes[7] === 0x0a\n ) {\n return isAnimatedPng(bytes) ? null : \"image/png\";\n }\n if (bytes.length >= 3 && bytes[0] === 0x47 && bytes[1] === 0x49 && bytes[2] === 0x46) {\n return \"image/gif\";\n }\n if (\n bytes.length >= 12 &&\n bytes[0] === 0x52 && bytes[1] === 0x49 && bytes[2] === 0x46 && bytes[3] === 0x46 &&\n bytes[8] === 0x57 && bytes[9] === 0x45 && bytes[10] === 0x42 && bytes[11] === 0x50\n ) {\n return \"image/webp\";\n }\n if (bytes.length >= 2 && bytes[0] === 0x42 && bytes[1] === 0x4d) {\n return \"image/bmp\";\n }\n return null;\n}\n\n/** Animated PNGs are not inline-eligible (pi declines them at the sniff too). */\nfunction isAnimatedPng(bytes: Uint8Array): boolean {\n let offset = 8;\n const readU32BE = (at: number): number =>\n (bytes[at] ?? 0) * 0x1000000 +\n ((bytes[at + 1] ?? 0) << 16) +\n ((bytes[at + 2] ?? 0) << 8) +\n (bytes[at + 3] ?? 0);\n const asciiAt = (at: number, text: string): boolean => {\n for (let i = 0; i < text.length; i++) {\n if ((bytes[at + i] ?? -1) !== text.charCodeAt(i)) return false;\n }\n return true;\n };\n while (offset + 8 <= bytes.length) {\n const chunkLength = readU32BE(offset);\n const chunkType = offset + 4;\n if (asciiAt(chunkType, \"acTL\")) return true;\n if (asciiAt(chunkType, \"IDAT\")) return false;\n const next = offset + 8 + chunkLength + 4;\n if (next <= offset || next > bytes.length) return false;\n offset = next;\n }\n return false;\n}\n\nasync function processImageBytes(bytes: Uint8Array): Promise<AttachOutcome> {\n const mimeType = sniffImageMimeType(bytes);\n try {\n if (mimeType && INLINE_MIME_TYPES.has(mimeType)) {\n const resized = await resizeImage(bytes, mimeType);\n if (!resized) {\n return { kind: \"omitted\", message: \"[Image omitted: could not be resized below the inline image size limit.]\" };\n }\n const hints: string[] = [];\n const note = formatDimensionNote(resized);\n if (note) hints.push(note);\n return { kind: \"attached\", image: { type: \"image\", data: resized.data, mimeType: resized.mimeType }, hints };\n }\n // bmp, animated PNG, and anything the sniff declines: one PNG conversion attempt\n // through the same backend pi's read tool uses, then the standard resize.\n const converted = await convertToPng(Buffer.from(bytes).toString(\"base64\"), mimeType ?? \"image/png\");\n if (!converted) {\n return { kind: \"omitted\", message: \"[Image omitted: could not be converted to a supported inline image format.]\" };\n }\n const resized = await resizeImage(new Uint8Array(Buffer.from(converted.data, \"base64\")), converted.mimeType);\n if (!resized) {\n return { kind: \"omitted\", message: \"[Image omitted: could not be resized below the inline image size limit.]\" };\n }\n const hints = [\n mimeType && mimeType !== converted.mimeType\n ? `[Image converted from ${mimeType} to ${converted.mimeType}.]`\n : \"[Image converted to image/png.]\",\n ];\n const note = formatDimensionNote(resized);\n if (note) hints.push(note);\n return { kind: \"attached\", image: { type: \"image\", data: resized.data, mimeType: resized.mimeType }, hints };\n } catch (error) {\n return {\n kind: \"omitted\",\n message: `[Image omitted: image processing failed (${error instanceof Error ? error.message : String(error)}).]`,\n };\n }\n}\n\n/**\n * What goes in the `name` of the `<file>` marker: the basename, XML-escaped. The marker is\n * a label for a turn whose bytes already ride the `images` field — the pod can never open\n * the host path, so sending the full path would only leak the host's directory layout\n * into the persisted transcript.\n */\nfunction markerName(absPath: string): string {\n return escapeXml(path.basename(absPath));\n}\n\nfunction escapeXml(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\n/** Expand `~`, resolve against the host cwd, and reject non-paths. */\nfunction resolveCandidate(candidate: string, cwd: string): string | null {\n if (candidate.length === 0 || candidate.length > MAX_IMAGE_PATH_CHARS) return null;\n if (candidate.includes(\"\\0\") || candidate.includes(\"\\n\")) return null;\n if (/^[a-zA-Z][a-zA-Z0-9+.-]*:\\/\\//.test(candidate)) return null; // URL, not a file.\n if (/^data:/i.test(candidate)) return null;\n let expanded = candidate;\n if (expanded === \"~\" || expanded.startsWith(\"~/\")) {\n expanded = path.join(os.homedir(), expanded.slice(1));\n }\n const absPath = path.isAbsolute(expanded) ? path.normalize(expanded) : path.resolve(cwd, expanded);\n return absPath;\n}\n\n/**\n * Candidate spans in prompt order: `@path` mentions first-class (they name pod *or* local\n * files; only local hits attach), then quoted paths, then bare tokens. A span must carry\n * an image suffix to nominate — content sniffing, not the suffix, makes the decision.\n *\n * Bare absolute paths stay eligible on purpose: that is exactly what clipboard pastes and\n * drag-drops insert (pi writes the image under the host /tmp and puts the bare path in\n * the editor). Prose-shaped tokens stay out — only `@` mentions name a file on purpose.\n */\n/**\n * Pure, synchronous pre-scan: candidate path spans in prompt order. Exported so the\n * prompt hot path can skip the filesystem entirely when there is nothing to attach —\n * imageless prompts then transmit exactly as before.\n */\nexport function collectImageCandidates(text: string): string[] {\n const candidates: string[] = [];\n const push = (raw: string, explicit: boolean): void => {\n const cleaned = cleanSpan(raw, explicit);\n if (cleaned && hasImageSuffix(cleaned)) candidates.push(cleaned);\n };\n\n for (const match of text.matchAll(/(^|[\\s(\\[{])@(\"[^\"\\n]+\"|'[^'\\n]+'|[^\\s\"'`()[\\]{}<>|;!?*]+)/g)) {\n // An `@path` mention is an explicit file reference, so even a bare name\n // resolves against the host cwd — unlike prose tokens.\n push(match[2]!, true);\n }\n for (const match of text.matchAll(/\"([^\"\\n]+)\"|'([^'\\n]+)'/g)) {\n push(match[1] ?? match[2]!, false);\n }\n for (const match of text.matchAll(/[^\\s\"'`()[\\]{}<>|;]+/g)) {\n push(match[0]!, false);\n }\n return candidates;\n}\n\nfunction cleanSpan(raw: string, explicit: boolean): string | null {\n let span = raw.trim();\n if (span.startsWith(\"@\")) span = span.slice(1);\n if (\n (span.startsWith('\"') && span.endsWith('\"') && span.length >= 2) ||\n (span.startsWith(\"'\") && span.endsWith(\"'\") && span.length >= 2)\n ) {\n span = span.slice(1, -1);\n }\n if (span.toLowerCase().startsWith(\"file://\")) span = span.slice(\"file://\".length);\n // Pasted prose leaves punctuation on the path: \"see (shot.png),\" names shot.png.\n span = span.replace(/^[(\\[{<]+/, \"\").replace(/[)\\]}>.,;:!?]+$/, \"\");\n if (span.length === 0 || span.length > MAX_IMAGE_PATH_CHARS) return null;\n // Bare tokens need a path shape — absolute, ~/-, ./-, ../-led, or containing a slash —\n // so prose like \"a.png\" as a version string does not stat the world. Explicit `@`\n // mentions skip this: the user named a file on purpose.\n if (!explicit && !path.isAbsolute(span) && !span.startsWith(\"~\") && !span.startsWith(\"./\") && !span.startsWith(\"../\") && !span.includes(\"/\")) {\n return null;\n }\n return span;\n}\n\nfunction hasImageSuffix(span: string): boolean {\n const dot = span.lastIndexOf(\".\");\n if (dot < 0) return false;\n return IMAGE_SUFFIXES.has(span.slice(dot + 1).toLowerCase());\n}\n","/**\n * src/client/runtime/pod-derived-config.ts — file-based materialization of pod TUI config.\n *\n * Two layers, per the pod-derived-tui-config plan: an immutable digest-keyed raw cache\n * shared by every launcher on this machine, and a throwaway per-launcher derived agent dir\n * that pi's own `SettingsManager.create(cwd, agentDir)` and theme loader read. The boundary\n * with pi stays at the filesystem: no proxies, no reach into pi's storage classes. Writes pi\n * makes (settings changes, model defaults) land in the derived dir and die with the session,\n * which is what makes them session-local.\n */\nimport * as crypto from \"node:crypto\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { HOST_PI_AGENT_SUBPATH, hostHome } from \"../../hostconfig.js\";\nimport { SAFE_THEME_NAME, validatePodTuiManifest, type PodTuiManifest } from \"./pod-manifest.js\";\n\nconst CACHED_MANIFEST_MAX_BYTES = 1024 * 1024;\n\nexport function defaultPodCacheRoot(home?: string): string | null {\n const resolved = hostHome(home);\n return resolved ? path.join(resolved, \".pi\", \"pod-cache\") : null;\n}\n\nexport function defaultHostAgentDir(home?: string): string | null {\n const resolved = hostHome(home);\n return resolved ? path.join(resolved, HOST_PI_AGENT_SUBPATH) : null;\n}\n\n/** One safe path segment for cache layout; never trusts server host or pod id spelling. */\nexport function sanitizeCacheSegment(value: string): string {\n const cleaned = value.replace(/[^A-Za-z0-9._-]/g, \"_\").replace(/^\\.+/, \"_\");\n return (cleaned.length === 0 ? \"_\" : cleaned).slice(0, 128);\n}\n\nexport function manifestCacheDir(cacheRoot: string, serverHost: string, podId: string): string {\n return path.join(cacheRoot, sanitizeCacheSegment(serverHost), sanitizeCacheSegment(podId), \"manifest\");\n}\n\nfunction writeFileAtomic(target: string, contents: string): void {\n const tmp = `${target}.${process.pid}-${crypto.randomBytes(4).toString(\"hex\")}.tmp`;\n fs.writeFileSync(tmp, contents, { mode: 0o600 });\n fs.renameSync(tmp, target);\n}\n\n/**\n * Write-once: a digest entry that already carries its completion marker is never rewritten,\n * so concurrent launchers on the same pod can share the cache without coordination.\n */\nexport function writeManifestCache(dir: string, manifest: PodTuiManifest): void {\n const entry = path.join(dir, sanitizeCacheSegment(manifest.digest));\n fs.mkdirSync(entry, { recursive: true, mode: 0o700 });\n const done = path.join(entry, \"complete\");\n if (!fs.existsSync(done)) {\n writeFileAtomic(path.join(entry, \"manifest.json\"), JSON.stringify(manifest));\n writeFileAtomic(done, \"\");\n }\n writeFileAtomic(path.join(dir, \"latest\"), manifest.digest);\n}\n\n/** Read a completed cache entry back, re-validating: cache contents are still just files. */\nexport function readManifestCache(dir: string, digest?: string): PodTuiManifest | null {\n try {\n let wanted = digest;\n if (wanted === undefined) {\n const latest = fs.readFileSync(path.join(dir, \"latest\"), \"utf8\").trim();\n if (latest.length === 0) return null;\n wanted = latest;\n }\n const entry = path.join(dir, sanitizeCacheSegment(wanted));\n if (!fs.existsSync(path.join(entry, \"complete\"))) return null;\n const target = path.join(entry, \"manifest.json\");\n const stat = fs.lstatSync(target);\n if (!stat.isFile() || stat.size > CACHED_MANIFEST_MAX_BYTES) return null;\n const parsed = JSON.parse(fs.readFileSync(target, \"utf8\")) as PodTuiManifest;\n return validatePodTuiManifest({\n digest: parsed.digest,\n manifest: {\n bootDigest: parsed.bootDigest,\n launchArgv: parsed.launchArgv,\n uiSettings: parsed.uiSettings,\n themes: parsed.themes,\n extensions: parsed.extensions,\n diagnostics: parsed.diagnostics,\n },\n });\n } catch {\n return null;\n }\n}\n\nexport interface DerivedPodConfig {\n /** Per-launcher agent dir for `SettingsManager.create` — pod projection over host prefs. */\n agentDir: string;\n /** Synthetic empty project dir: kills the implicit host-project settings merge. */\n settingsCwd: string;\n /** Where validated pod theme JSON lands for pi's theme loader. */\n themesDir: string;\n /** Rewrite contents in place (paths never change); null falls back to host-only settings. */\n refresh(manifest: PodTuiManifest | null): void;\n dispose(): void;\n}\n\nfunction readHostSettings(hostAgentDir: string | null): Record<string, unknown> {\n if (hostAgentDir === null) return {};\n try {\n const parsed = JSON.parse(fs.readFileSync(path.join(hostAgentDir, \"settings.json\"), \"utf8\")) as unknown;\n return parsed !== null && typeof parsed === \"object\" && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : {};\n } catch {\n return {};\n }\n}\n\n/**\n * Create the per-launcher derived agent dir. The settings file is the host's global\n * settings with the pod's validated `uiSettings` projection layered on top: host-only\n * concerns (externalEditor and friends — the *user's* own values) survive, pod display\n * preferences win, and hostile pod values can never reach the host-only keys because the\n * projection schema has no such fields.\n */\nexport function createDerivedPodConfig(opts: {\n cacheRoot: string;\n hostAgentDir: string | null;\n}): DerivedPodConfig {\n const agentDir = path.join(\n opts.cacheRoot,\n \"derived\",\n `${process.pid}-${crypto.randomBytes(4).toString(\"hex\")}`,\n );\n const themesDir = path.join(agentDir, \"themes\");\n const settingsCwd = path.join(agentDir, \"project\");\n fs.mkdirSync(themesDir, { recursive: true, mode: 0o700 });\n fs.mkdirSync(settingsCwd, { recursive: true, mode: 0o700 });\n fs.chmodSync(agentDir, 0o700);\n\n const refresh = (manifest: PodTuiManifest | null): void => {\n const host = readHostSettings(opts.hostAgentDir);\n const merged = manifest ? { ...host, ...manifest.uiSettings } : host;\n writeFileAtomic(path.join(agentDir, \"settings.json\"), `${JSON.stringify(merged, null, 2)}\\n`);\n\n const wanted = new Map((manifest?.themes ?? []).map((theme) => [`${theme.name}.json`, theme]));\n for (const existing of fs.readdirSync(themesDir)) {\n if (!wanted.has(existing)) fs.rmSync(path.join(themesDir, existing), { force: true });\n }\n for (const [file, theme] of wanted) {\n if (!SAFE_THEME_NAME.test(theme.name)) continue;\n writeFileAtomic(path.join(themesDir, file), `${JSON.stringify(theme.theme, null, 2)}\\n`);\n }\n };\n\n return {\n agentDir,\n settingsCwd,\n themesDir,\n refresh,\n dispose: () => {\n fs.rmSync(agentDir, { recursive: true, force: true });\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Pod themes through pi's own loader\n// ---------------------------------------------------------------------------\n\ninterface ThemeDiagnostic {\n type: \"error\";\n message: string;\n path?: string;\n}\n\nexport interface PodThemeLoader {\n load(themesDir: string): { themes: unknown[]; diagnostics: ThemeDiagnostic[] };\n}\n\n/**\n * Pi's `loadThemeFromPath` parses and constructs a Theme exactly the way pi itself does,\n * defaults and validation included. It is not re-exported from pi's public entry, so this is\n * a deep import of the same module instance pi's dist uses — asserted by the surface canary\n * (scripts/check-runtime-surface.ts) so a pi upgrade that moves it fails loudly at lint.\n */\nexport async function loadPodThemeLoader(): Promise<PodThemeLoader | null> {\n try {\n const entryUrl = import.meta.resolve(\"@earendil-works/pi-coding-agent\");\n const themeModule = (await import(new URL(\"modes/interactive/theme/theme.js\", entryUrl).href)) as {\n loadThemeFromPath?: (themePath: string) => unknown;\n };\n const loadThemeFromPath = themeModule.loadThemeFromPath;\n if (typeof loadThemeFromPath !== \"function\") return null;\n return {\n load: (themesDir) => {\n const themes: unknown[] = [];\n const diagnostics: ThemeDiagnostic[] = [];\n let files: string[] = [];\n try {\n files = fs.readdirSync(themesDir).filter((file) => file.endsWith(\".json\")).sort();\n } catch {\n return { themes, diagnostics };\n }\n for (const file of files) {\n const full = path.join(themesDir, file);\n try {\n themes.push(loadThemeFromPath(full));\n } catch (error) {\n diagnostics.push({\n type: \"error\",\n message: `pod theme ${file}: ${error instanceof Error ? error.message : String(error)}`,\n path: full,\n });\n }\n }\n return { themes, diagnostics };\n },\n };\n } catch {\n return null;\n }\n}\n","/**\n * src/client/runtime/pod-manifest.ts — LocalTuiManifestV1 validation.\n *\n * The pod's manifest is agent-writable data: everything here is validated as untrusted\n * input before it can influence the local TUI. The `uiSettings` schema below IS the\n * filtering — there is no separate allowlist subsystem. Command-, path-, and code-valued\n * pi settings keys (externalEditor, shellPath, shellCommandPrefix, npmCommand, packages,\n * hooks, MCP config) are simply not fields, so they never cross, whatever the pod sends.\n * New pi settings default to not-synced; adding one here is a value-shape review.\n */\n\nexport const POD_MANIFEST_MAX_THEMES = 20;\nexport const POD_MANIFEST_MAX_EXTENSIONS = 100;\nexport const POD_MANIFEST_MAX_DIAGNOSTICS = 50;\nexport const POD_MANIFEST_MAX_ARGV = 64;\n\n/** A theme file name the derived agent dir will write: one safe path segment, no dotfiles. */\nexport const SAFE_THEME_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;\n\nexport interface PodThemeFile {\n name: string;\n theme: Record<string, unknown>;\n}\n\n/** Directly configured npm package identity; the wire key remains `extensions` for compatibility. */\nexport interface PodExtensionIdentity {\n name: string;\n version: string;\n}\n\nexport interface PodTuiManifest {\n digest: string;\n bootDigest: string | null;\n launchArgv: string[];\n /** The validated display-key projection, ready to overlay on host settings. */\n uiSettings: Record<string, unknown>;\n themes: PodThemeFile[];\n /** Direct package identities used to detect extension-rendering drift. */\n extensions: PodExtensionIdentity[];\n diagnostics: string[];\n}\n\ntype FieldValidator = (value: unknown) => unknown;\n\nfunction hasControlChars(value: string): boolean {\n for (let i = 0; i < value.length; i++) {\n const code = value.charCodeAt(i);\n if (code < 0x20 || code === 0x7f) return true;\n }\n return false;\n}\n\nfunction cleanString(max: number): FieldValidator {\n return (value) =>\n typeof value === \"string\" && value.length > 0 && value.length <= max && !hasControlChars(value)\n ? value\n : undefined;\n}\n\nconst bool: FieldValidator = (value) => (value === true || value === false ? value : undefined);\n\nfunction intIn(min: number, max: number): FieldValidator {\n return (value) =>\n typeof value === \"number\" && Number.isInteger(value) && value >= min && value <= max\n ? value\n : undefined;\n}\n\nfunction oneOf(...allowed: unknown[]): FieldValidator {\n return (value) => (allowed.includes(value) ? value : undefined);\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction subObject(fields: Record<string, FieldValidator>): FieldValidator {\n return (value) => {\n if (!isPlainObject(value)) return undefined;\n const out: Record<string, unknown> = {};\n for (const [key, validate] of Object.entries(fields)) {\n if (value[key] === undefined) continue;\n const sanitized = validate(value[key]);\n if (sanitized !== undefined) out[key] = sanitized;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n };\n}\n\n/**\n * The display-safe projection of pi's Settings, field by field. Every value shape is pinned:\n * a pod cannot smuggle an object where a boolean belongs or an unbounded string anywhere.\n */\nconst UI_SETTINGS_SCHEMA: Record<string, FieldValidator> = {\n // May be a plain name or pi's \"light/dark\" auto pair.\n theme: cleanString(128),\n hideThinkingBlock: bool,\n showCacheMissNotices: bool,\n quietStartup: bool,\n collapseChangelog: bool,\n showHardwareCursor: bool,\n doubleEscapeAction: oneOf(\"fork\", \"tree\", \"none\"),\n treeFilterMode: oneOf(\"default\", \"no-tools\", \"user-only\", \"labeled-only\", \"all\"),\n editorPaddingX: intIn(0, 32),\n outputPad: oneOf(0, 1),\n autocompleteMaxVisible: intIn(1, 50),\n markdown: subObject({\n codeBlockIndent: (value) =>\n typeof value === \"string\" && value.length <= 8 && /^[ \\t]*$/.test(value) ? value : undefined,\n mermaid: oneOf(\"off\", \"final\", \"streaming\"),\n }),\n terminal: subObject({\n showImages: bool,\n imageWidthCells: intIn(1, 500),\n clearOnShrink: bool,\n showTerminalProgress: bool,\n }),\n images: subObject({ autoResize: bool, blockImages: bool }),\n warnings: subObject({ anthropicExtraUsage: bool }),\n tuiMode: oneOf(\"regular\", \"fullscreen\"),\n fullscreenExitOutput: oneOf(\"transcript\", \"resume-hint\"),\n fullscreenScrollbar: oneOf(\"hidden\", \"auto\", \"always\"),\n};\n\nexport function validateUiSettings(value: unknown): Record<string, unknown> {\n if (!isPlainObject(value)) return {};\n const out: Record<string, unknown> = {};\n for (const [key, validate] of Object.entries(UI_SETTINGS_SCHEMA)) {\n if (value[key] === undefined) continue;\n const sanitized = validate(value[key]);\n if (sanitized !== undefined) out[key] = sanitized;\n }\n return out;\n}\n\nconst MAX_THEME_ENTRIES = 120;\nconst themeValue: FieldValidator = (value) => {\n if (typeof value === \"string\") return cleanString(64)(value);\n if (typeof value === \"number\") return Number.isInteger(value) && value >= 0 && value <= 255 ? value : undefined;\n return undefined;\n};\n\nfunction sanitizeThemeMap(value: unknown, keyPattern: RegExp): Record<string, unknown> | null {\n if (!isPlainObject(value)) return null;\n const entries = Object.entries(value);\n if (entries.length > MAX_THEME_ENTRIES) return null;\n const out: Record<string, unknown> = {};\n for (const [key, raw] of entries) {\n if (!keyPattern.test(key)) return null;\n const sanitized = themeValue(raw);\n if (sanitized === undefined) return null;\n out[key] = sanitized;\n }\n return out;\n}\n\n/**\n * A theme is pure data: `{name, colors, vars?}` per pi's theme file format. Anything that\n * fails a shape check drops the whole theme — a partially-hostile theme has no safe half.\n */\nexport function validatePodTheme(name: unknown, theme: unknown): PodThemeFile | null {\n if (typeof name !== \"string\" || !SAFE_THEME_NAME.test(name)) return null;\n if (!isPlainObject(theme)) return null;\n const colors = sanitizeThemeMap(theme[\"colors\"], /^[A-Za-z][A-Za-z0-9]{0,63}$/);\n if (colors === null || Object.keys(colors).length === 0) return null;\n const sanitized: Record<string, unknown> = { name, colors };\n if (theme[\"vars\"] !== undefined) {\n const vars = sanitizeThemeMap(theme[\"vars\"], /^[A-Za-z_][A-Za-z0-9_-]{0,63}$/);\n if (vars === null) return null;\n if (Object.keys(vars).length > 0) sanitized[\"vars\"] = vars;\n }\n return { name, theme: sanitized };\n}\n\nconst DIGEST_PATTERN = /^[A-Za-z0-9]{8,64}$/;\n\nfunction validateDigest(value: unknown): string | null {\n return typeof value === \"string\" && DIGEST_PATTERN.test(value) ? value : null;\n}\n\nconst extensionName = cleanString(214);\nconst extensionVersion = cleanString(64);\n\n/**\n * Validate one `tui_manifest` gateway frame into a typed manifest. Returns null when the\n * frame cannot be a manifest at all; individually malformed entries degrade to local\n * diagnostics instead of discarding the rest.\n */\nexport function validatePodTuiManifest(frame: {\n digest?: string | undefined;\n manifest?: Record<string, unknown> | undefined;\n}): PodTuiManifest | null {\n const digest = validateDigest(frame.digest);\n if (digest === null || !isPlainObject(frame.manifest)) return null;\n const raw = frame.manifest;\n\n const diagnostics: string[] = [];\n if (Array.isArray(raw[\"diagnostics\"])) {\n for (const entry of raw[\"diagnostics\"].slice(0, POD_MANIFEST_MAX_DIAGNOSTICS)) {\n if (typeof entry === \"string\" && !hasControlChars(entry)) diagnostics.push(entry.slice(0, 300));\n }\n }\n\n const launchArgv: string[] = [];\n if (Array.isArray(raw[\"launchArgv\"])) {\n for (const entry of raw[\"launchArgv\"].slice(0, POD_MANIFEST_MAX_ARGV)) {\n if (typeof entry === \"string\" && entry.length <= 4096) launchArgv.push(entry);\n }\n }\n\n const themes: PodThemeFile[] = [];\n const seenThemeNames = new Set<string>();\n if (Array.isArray(raw[\"themes\"])) {\n for (const entry of raw[\"themes\"].slice(0, POD_MANIFEST_MAX_THEMES)) {\n if (!isPlainObject(entry)) continue;\n const theme = validatePodTheme(entry[\"name\"], entry[\"theme\"]);\n if (theme === null) {\n diagnostics.push(`theme ${JSON.stringify(entry[\"name\"]).slice(0, 80)} failed validation and was dropped`);\n continue;\n }\n if (seenThemeNames.has(theme.name)) continue;\n seenThemeNames.add(theme.name);\n themes.push(theme);\n }\n }\n\n const extensions: PodExtensionIdentity[] = [];\n if (Array.isArray(raw[\"extensions\"])) {\n for (const entry of raw[\"extensions\"].slice(0, POD_MANIFEST_MAX_EXTENSIONS)) {\n if (!isPlainObject(entry)) continue;\n const name = extensionName(entry[\"name\"]);\n const version = extensionVersion(entry[\"version\"]);\n if (name === undefined || version === undefined) continue;\n if (/\\s/.test(name as string) || /\\s/.test(version as string)) continue;\n extensions.push({ name: name as string, version: version as string });\n }\n }\n\n return {\n digest,\n bootDigest: validateDigest(raw[\"bootDigest\"]),\n launchArgv,\n uiSettings: validateUiSettings(raw[\"uiSettings\"]),\n themes,\n extensions,\n diagnostics,\n };\n}\n","/**\n * src/account/pod-config-sync.ts — the pod-derived TUI config sync pipeline.\n *\n * One serialized, generation-aware pipeline for every sync trigger: attach, reconnect,\n * `/pod switch`, and manual `/pod sync`. Outcomes are values, never exceptions — reconnect\n * runs inside `onRecovered`, where a throw reads as a failed recovery. A switch that cannot\n * produce the target pod's manifest rewrites the derived dir to host-only settings, so pod\n * A's settings are never left active against pod B.\n */\nimport type { ShimHello } from \"../client/protocol.js\";\nimport type { DerivedPodConfig } from \"../client/runtime/pod-derived-config.js\";\nimport { manifestCacheDir, readManifestCache, writeManifestCache } from \"../client/runtime/pod-derived-config.js\";\nimport {\n validatePodTuiManifest,\n type PodExtensionIdentity,\n type PodTuiManifest,\n} from \"../client/runtime/pod-manifest.js\";\nimport { debug } from \"../log.js\";\nimport type { TuiManifestFrame } from \"./gateway-rpc.js\";\n\n/** First shim generation that answers `tui_manifest`; older pods skip the request entirely. */\nexport const MIN_MANIFEST_SHIM_VERSION = 13;\n\nexport type PodConfigSyncReason = \"attach\" | \"reconnect\" | \"switch\" | \"manual\";\n\nexport type PodConfigSyncOutcome =\n | {\n kind: \"applied\";\n podId: string;\n digest: string;\n /** False when the digest matches what this session last applied. */\n changed: boolean;\n /** The pod's disk drifted from what pi loaded at boot. */\n drift: boolean;\n themeCount: number;\n /** On-disk extension identities, for the attested-set diff (agent-era installs). */\n extensions: PodExtensionIdentity[];\n diagnostics: string[];\n }\n | { kind: \"unsupported\"; reason: string }\n | { kind: \"invalid\" }\n | { kind: \"failed\"; message: string }\n | { kind: \"stale\" };\n\nexport interface PodConfigSyncRpc {\n readonly podId: string;\n readonly helloInfo: ShimHello | null;\n getTuiManifest(knownDigest?: string): Promise<TuiManifestFrame>;\n}\n\nexport interface PodConfigSyncDeps {\n rpc: PodConfigSyncRpc;\n derived: DerivedPodConfig;\n cacheRoot: string | null;\n serverHost: string;\n}\n\nexport interface PodConfigSync {\n sync(reason: PodConfigSyncReason): Promise<PodConfigSyncOutcome>;\n /** Bound after the runtime exists: applies a refreshed derived dir (settings reload). */\n setOnAfterApply(callback: (() => Promise<void>) | null): void;\n}\n\nexport function manifestCapable(hello: ShimHello | null): boolean {\n const version = Number.parseInt(hello?.shimVersion ?? \"\", 10);\n return Number.isFinite(version) && version >= MIN_MANIFEST_SHIM_VERSION;\n}\n\nexport function createPodConfigSync(deps: PodConfigSyncDeps): PodConfigSync {\n let tail: Promise<unknown> = Promise.resolve();\n let onAfterApply: (() => Promise<void>) | null = null;\n const appliedDigests = new Map<string, string>();\n\n const fallBackToHost = async (): Promise<void> => {\n try {\n deps.derived.refresh(null);\n await onAfterApply?.();\n } catch (error) {\n debug(`pod config host fallback failed: ${error instanceof Error ? error.message : String(error)}`);\n }\n };\n\n const run = async (reason: PodConfigSyncReason): Promise<PodConfigSyncOutcome> => {\n const podId = deps.rpc.podId;\n if (!manifestCapable(deps.rpc.helloInfo)) {\n // A switch to a pre-manifest pod must not keep the previous pod's settings active.\n if (reason === \"switch\") await fallBackToHost();\n const shimVersion = deps.rpc.helloInfo?.shimVersion ?? \"unknown\";\n return { kind: \"unsupported\", reason: `the pod runs shim ${shimVersion}, which predates pod-derived settings` };\n }\n const cacheDir = deps.cacheRoot ? manifestCacheDir(deps.cacheRoot, deps.serverHost, podId) : null;\n const cached = cacheDir ? readManifestCache(cacheDir) : null;\n try {\n let frame = await deps.rpc.getTuiManifest(cached?.digest);\n if (deps.rpc.podId !== podId) return { kind: \"stale\" };\n if (frame.unsupported) {\n if (reason === \"switch\") await fallBackToHost();\n return { kind: \"unsupported\", reason: \"the server predates pod-derived settings\" };\n }\n let manifest: PodTuiManifest | null = null;\n if (frame.unchanged === true) {\n manifest = cached;\n if (manifest === null) {\n // The unchanged short-circuit answered a digest whose cache entry is gone; re-ask.\n frame = await deps.rpc.getTuiManifest();\n if (deps.rpc.podId !== podId) return { kind: \"stale\" };\n if (frame.unsupported || frame.unchanged === true) {\n if (reason === \"switch\") await fallBackToHost();\n return { kind: \"failed\", message: \"the pod answered without a manifest\" };\n }\n }\n }\n manifest ??= validatePodTuiManifest(frame);\n if (manifest === null) {\n await fallBackToHost();\n return { kind: \"invalid\" };\n }\n if (cacheDir) {\n try {\n writeManifestCache(cacheDir, manifest);\n } catch (error) {\n debug(`pod manifest cache write failed: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n deps.derived.refresh(manifest);\n const changed = appliedDigests.get(podId) !== manifest.digest;\n appliedDigests.set(podId, manifest.digest);\n await onAfterApply?.();\n if (deps.rpc.podId !== podId) return { kind: \"stale\" };\n return {\n kind: \"applied\",\n podId,\n digest: manifest.digest,\n changed,\n drift: manifest.bootDigest !== null && manifest.bootDigest !== manifest.digest,\n themeCount: manifest.themes.length,\n extensions: manifest.extensions,\n diagnostics: manifest.diagnostics,\n };\n } catch (error) {\n if (reason === \"switch\") await fallBackToHost();\n return { kind: \"failed\", message: error instanceof Error ? error.message : String(error) };\n }\n };\n\n return {\n sync: (reason) => {\n const result = tail.then(\n () => run(reason),\n () => run(reason),\n );\n tail = result.then(\n () => undefined,\n () => undefined,\n );\n return result;\n },\n setOnAfterApply: (callback) => {\n onAfterApply = callback;\n },\n };\n}\n\n/** The user-facing line for a non-applied outcome; null when nothing is worth saying. */\nexport function podConfigSyncNotice(outcome: PodConfigSyncOutcome): { message: string; type: \"info\" | \"warning\" } | null {\n switch (outcome.kind) {\n case \"applied\":\n return outcome.drift\n ? {\n message:\n \"pod config changed on disk after pi started — the agent's process may run older config until it restarts\",\n type: \"warning\",\n }\n : null;\n case \"unsupported\":\n return { message: `pod-derived settings unavailable (${outcome.reason}); using host settings`, type: \"info\" };\n case \"invalid\":\n return { message: \"the pod's settings manifest failed validation; using host settings\", type: \"warning\" };\n case \"failed\":\n return { message: `pod settings sync failed: ${outcome.message}; using host settings`, type: \"warning\" };\n case \"stale\":\n return null;\n }\n}\n","/**\n * src/client/runtime/remote-runtime.ts — RemoteAgentSessionRuntime (§5.2).\n *\n * The local client IS pi's client: the launcher imports pi's real `InteractiveMode` and hands\n * its constructor this duck-typed runtime host. Nominal typing on the concrete class is a\n * compile-time concern only; at runtime the object must satisfy the member surface\n * InteractiveMode actually touches — measured from pi's shipped dist, and guarded by the\n * surface canary (scripts/check-runtime-surface.ts, §13).\n *\n * The split: sync getters are served from a client-side {@link RemoteStateCache}; methods map\n * ~1:1 onto RPC commands; the settings manager is the real local one (themes, hotkeys and\n * editor preferences are host concerns); pod-side services are backed by their RPC commands.\n */\nimport {\n SettingsManager,\n calculateContextTokens,\n resolveModelScopeWithDiagnostics,\n type AgentSessionEvent,\n type ScopedModel,\n type SessionEntry,\n} from \"@earendil-works/pi-coding-agent\";\nimport { PiPodError } from \"../../errors.js\";\nimport { debug, warn } from \"../../log.js\";\nimport type { ImageContent, RpcClientBase, ThinkingLevel } from \"../rpc.js\";\nimport { POD_INTERNAL_COMMAND_PREFIX } from \"../../shim/pi-pod-ext.js\";\nimport {\n createLocalExtensionHost,\n type LocalExtensionHost,\n type ResolvedLocalCommand,\n} from \"./local-extensions.js\";\nimport { HostBridge, type EndingIntent, type HostUiContext } from \"./bridge.js\";\nimport {\n wrapWithPodFiles,\n FILE_LIST_UNAVAILABLE,\n type AutocompleteProviderLike,\n type FileListData,\n} from \"./pod-file-completion.js\";\nimport { AuthBridge, type RemoteAuthInteraction, type RemoteAuthType } from \"./auth-bridge.js\";\nimport { type DialogInvalidation, wireExtensionUi } from \"./extension-ui.js\";\nimport { preparePromptImages, collectImageCandidates } from \"./local-images.js\";\nimport { PodExtensionBridge } from \"./pod-extension-bridge.js\";\nimport {\n createExtensionModelRegistry,\n type AuxCatalogModel,\n type AuxCompleteRequest,\n type AuxCompleteResult,\n} from \"./extension-model-registry.js\";\nimport { PodCommandRouter, type PodCommandHost } from \"./pod-commands.js\";\nimport { RemoteUiBridge } from \"./remote-ui.js\";\nimport { findTreeNode, RemoteStateCache } from \"./state.js\";\nimport { StreamHeal } from \"./stream-heal.js\";\n\n/** What dispose reports to the session driver — the input to §6.2's ending classification. */\nexport interface RuntimeEnding {\n intent: EndingIntent;\n /** True when InteractiveMode asked to quit (Ctrl-C Ctrl-C, Ctrl-D, or /quit). */\n quitRequested: boolean;\n /** pi's exit code, when the ending was a quit and pi_exit arrived in time. */\n exitCode: number | null;\n /** Tail of pi's stderr, for crash reports (§12). */\n stderrTail: string;\n}\n\nexport interface RemoteRuntimeOptions {\n rpc: RpcClientBase;\n /** Host-side working directory (the repo root) — file autocomplete and settings live here. */\n cwd: string;\n /** Override for pi's agent dir (settings); undefined means pi's default. */\n agentDir?: string | undefined;\n /**\n * Settings-manager cwd override. Pod-derived sessions pass a synthetic empty dir so the\n * host project's `.pi/settings.json` never merges over pod values; file autocomplete and\n * everything else keeps the real `cwd`.\n */\n settingsCwd?: string | undefined;\n /** Pod-derived themes, served through pi's own directory loader; absent means none. */\n getLocalThemes?: (() => { themes: unknown[]; diagnostics: unknown[] }) | undefined;\n /** CLI --models patterns, which take precedence over enabledModels in settings. */\n modelPatterns?: string[] | undefined;\n /**\n * The current pod's own enabledModels patterns (§5.2). RPC exposes no scoped-model list,\n * so without this the seed falls back to the host's settings — a different machine's\n * opinion of the scope. A thunk rather than a value so /pod switch reads the new pod.\n */\n getPodModelPatterns?: (() => Promise<string[] | undefined>) | undefined;\n /** Semantic gateway query for the active model's thinking levels. */\n getAvailableThinkingLevels?: (() => Promise<ThinkingLevel[]>) | undefined;\n /**\n * Semantic gateway query backing `@` completion. Absent means no suggestions — which is\n * the honest answer, and never the host's own files (§5.2).\n */\n listPodFiles?: ((query: string) => Promise<FileListData>) | undefined;\n /** Hooks for /pod subcommands beyond the leave family (§5.4). */\n podHost?: PodCommandHost;\n /** The TUI accepted a typed /pod command; clear its editor before the local action runs. */\n onPodCommandSubmit?: (() => void) | undefined;\n /**\n * Entry files of the server-attested pod extensions (the code channel): loaded by the\n * launcher's own ExtensionRunner for rendering hooks only — commands and tools stay\n * pod-authoritative. Empty/absent costs nothing.\n */\n attestedExtensionPaths?: string[] | undefined;\n /** A lost transport cannot receive shutdown or pi_exit; skip that bounded wait on local quit. */\n waitForRemoteExitOnQuit?: (() => boolean) | undefined;\n /** Account-mode provider capability check; absent in local-mode runtimes. */\n accountAuthSupported?: ((provider: string, type?: RemoteAuthType) => Promise<boolean>) | undefined;\n /** Connect a broker-supported provider in account custody instead of inside this pod. */\n accountLogin?: ((provider: string, type: RemoteAuthType, interaction: RemoteAuthInteraction) => Promise<unknown>) | undefined;\n /** Remove a broker-supported provider from account custody. */\n accountLogout?: ((provider: string) => Promise<void>) | undefined;\n /**\n * Semantic aux-completion transport (the gateway's `aux_complete` message). Absent on\n * transports without aux support — `complete()` then fails with an honest error.\n */\n auxComplete?:\n | ((request: AuxCompleteRequest, opts?: { signal?: AbortSignal }) => Promise<AuxCompleteResult>)\n | undefined;\n /**\n * Extension command names (without the slash) that execute in the launcher's local\n * extension host instead of the pod — e.g. `[\"transcript\"]` so an unchanged\n * TUI-gated extension's UI commands run with the real TUI context. Default: empty,\n * the pod owns every slash command (the pre-bridge behavior). Anything not listed\n * — and every unknown command — crosses the wire exactly once; local execution\n * never falls back to a second remote run. Local commands are always reachable\n * explicitly via `/pod local <name> [args]`, with no allowlist needed.\n */\n localCommands?: readonly string[] | undefined;\n /** Called from `runtimeHost.dispose()` after the ending is settled; teardown lives here. */\n onEnding: (ending: RuntimeEnding) => Promise<void>;\n}\n\nexport interface RemoteRuntime {\n /** Duck-typed AgentSessionRuntime for `new InteractiveMode(runtimeHost)`. */\n runtimeHost: Record<string, unknown>;\n bridge: HostBridge;\n cache: RemoteStateCache;\n router: PodCommandRouter;\n treeBridge: PodExtensionBridge;\n /** Seed the caches; call before constructing InteractiveMode. */\n init(): Promise<void>;\n /** The session behind the runtime was replaced (§8, §6.4): re-seed and rebind the TUI. */\n refreshAfterReplacement(): Promise<void>;\n /**\n * The transport dropped and came back onto the same session: re-seed like a replacement,\n * but keep the dialogs the pod is still blocked on and put them back on screen (§5.3).\n */\n recoverAfterReconnect(): Promise<void>;\n /** Rebuild InteractiveMode's streaming component from the transport's cumulative snapshot. */\n healStreamingRenderer(): Promise<void>;\n /**\n * Re-read the settings files in place (pod-derived sync rewrote them; the paths never\n * change, so pi's own reload suffices — no rebinding).\n */\n reloadSettings(): Promise<void>;\n /**\n * Stop serving attested-extension rendering hooks (loaded code cannot be unloaded, but it\n * can stop being consulted) — the `/pod switch` path when the target's attested set\n * differs.\n */\n disableLocalExtensions(): Promise<void>;\n}\n\n/** How long dispose waits for pi_exit after sending the shutdown frame (§6.2). */\nconst QUIT_TIMEOUT_MS = 15_000;\nconst FALLBACK_THINKING_LEVELS: ThinkingLevel[] = [\"off\", \"minimal\", \"low\", \"medium\", \"high\"];\n/** How pi spells a skill in `get_commands`; its own loader re-adds this to the bare name. */\nconst SKILL_COMMAND_PREFIX = \"skill:\";\n\n/** Remote slash command shape from get_commands (§5.4, phase 3 merges these). */\ninterface RemoteCommand {\n name: string;\n description?: string;\n source: \"extension\" | \"prompt\" | \"skill\";\n sourceInfo: { path: string; source: string; scope: string; origin: string };\n}\n\ntype RemoteModel = ScopedModel[\"model\"];\n\n/** Provider metadata crosses the wire, while auth implementations and stored credentials do not. */\ninterface RemoteProviderFacade {\n id: string;\n name: string;\n auth: {\n apiKey?: { name: string; login?: () => Promise<never> };\n oauth?: { name: string; loginLabel?: string; login: () => Promise<never> };\n };\n}\n\nfunction isUnsupportedCredentialProvider(error: unknown): boolean {\n return error instanceof PiPodError && error.code === \"credential_provider_unsupported\";\n}\n\nexport function createRemoteRuntime(opts: RemoteRuntimeOptions): RemoteRuntime {\n const { rpc, cwd } = opts;\n const bridge = new HostBridge();\n const cache = new RemoteStateCache(rpc);\n const refreshThinkingLevels = async (): Promise<void> => {\n cache.availableThinkingLevels = null;\n if (!opts.getAvailableThinkingLevels) return;\n try {\n const levels = await opts.getAvailableThinkingLevels();\n cache.availableThinkingLevels = levels.length > 0 ? [...levels] : null;\n } catch {\n // Old gateways never answer get_models; old pod shims answer with an empty list.\n }\n };\n // Explicit local-command routing: the pod owns every slash command by default.\n const localCommandAllowlist = new Set(\n (opts.localCommands ?? [])\n .map((name) => (typeof name === \"string\" ? name.replace(/^\\/+/, \"\").trim() : \"\"))\n .filter((name) => name.length > 0),\n );\n const runLocalCommandByName = async (name: string, args: string): Promise<boolean> => {\n if (!localHost) return false;\n return localHost.runLocalCommand(name, args);\n };\n const runPodLocalNamespace = async (arg: string): Promise<void> => {\n const trimmed = arg.trim();\n if (trimmed === \"\") {\n const names = (localHost?.runner.getRegisteredCommands() ?? [])\n .map((c) => c.name)\n .filter((name) => name !== \"pod\");\n bridge.notify(\n names.length > 0\n ? `locally rendered commands: ${names.join(\", \")} — run one as /pod local <name> [args]`\n : \"no locally rendered pod extensions in this session — every slash command runs in the pod\",\n );\n return;\n }\n const space = trimmed.search(/\\s/);\n const name = space === -1 ? trimmed : trimmed.slice(0, space);\n const args = space === -1 ? \"\" : trimmed.slice(space + 1).trim();\n try {\n if (await runLocalCommandByName(name, args)) return;\n } catch (error) {\n bridge.notify(\n `/pod local: ${error instanceof Error ? error.message : String(error)}`,\n \"error\",\n );\n return;\n }\n // Strict namespace: an unregistered name errors honestly — it never falls\n // through to the pod, so one input can never execute in both places.\n bridge.notify(`/pod local: no locally registered command /${name.replace(/^\\/+/, \"\")} here — the pod owns /${name.replace(/^\\/+/, \"\")}`, \"warning\");\n };\n const treeBridge = new PodExtensionBridge(rpc, {\n getCommands: () => cache.commands,\n onAmbiguousFailure: () => cache.refreshTree().then(() => undefined),\n });\n cache.bindSeedBridge(treeBridge);\n const authBridge = new AuthBridge(rpc, { getCommands: () => cache.commands });\n const remoteUiBridge = new RemoteUiBridge(rpc, bridge);\n const router = new PodCommandRouter(bridge, { ...opts.podHost, runLocalCommand: runPodLocalNamespace });\n\n /**\n * Pi-tui completes `@` by walking the host's disk, but the files the agent can act on are\n * the pod's. Re-registered on every UI bind because pi drops its wrappers each time.\n */\n const installPodFileCompletion = (ui: HostUiContext): void => {\n ui.addAutocompleteProvider?.((base) =>\n wrapWithPodFiles(base as AutocompleteProviderLike, async (query) =>\n (await opts.listPodFiles?.(query)) ?? FILE_LIST_UNAVAILABLE,\n ),\n );\n };\n bridge.onEveryUiBound(installPodFileCompletion);\n const settingsManager = SettingsManager.create(opts.settingsCwd ?? cwd, opts.agentDir);\n const remoteSettingsManager = new Proxy(settingsManager, {\n get(target, property) {\n if (property === \"getBranchSummarySkipPrompt\") return () => true;\n const value = Reflect.get(target, property, target) as unknown;\n return typeof value === \"function\" ? value.bind(target) : value;\n },\n set(target, property, value) {\n return Reflect.set(target, property, value, target);\n },\n });\n\n // RPC 0.82.1 does not expose the pod session's scoped-model list. Keep the TUI's copy\n // locally, seeded from the same CLI/settings patterns pi used in the pod. Model changes\n // still cross the wire through set_model, so the pod remains authoritative for execution.\n let scopedModels: ScopedModel[] = [];\n const findCachedModel = (provider: string, id: string): RemoteModel | undefined =>\n (cache.availableModels as RemoteModel[]).find((model) => model.provider === provider && model.id === id);\n const rehydrateScopedModels = (): void => {\n scopedModels = scopedModels.flatMap((scoped) => {\n const model = findCachedModel(scoped.model.provider, scoped.model.id);\n return model ? [{ ...scoped, model }] : [];\n });\n };\n\n const listeners = new Set<(event: unknown) => void>();\n const abortController = new AbortController();\n const streamHeal = new StreamHeal();\n // Pi 0.84 emits bash output updates but no start/end event, so local requests own this state.\n const activeBashRequests = new Set<string>();\n\n // Attested pod extensions (rendering hooks): loaded in init(), null for everyone else.\n let localHost: LocalExtensionHost | null = null;\n\n // The cache subscribes first, and deliberately so: listeners run in registration order, and\n // InteractiveMode answers events by reading this cache back synchronously — session_info_changed\n // retitles the terminal from `sessionManager.getSessionName()`. Fanning out first would hand\n // the TUI the state as it was *before* the event it is handling.\n const unwireCache = cache.wire();\n\n const fanOutEvent = (event: AgentSessionEvent): void => {\n // The RPC boundary restores cumulative snapshots; StreamHeal supplies the message_start\n // InteractiveMode discarded during a renderer/session rebind (§6.3). Before anyone\n // subscribes — the attach burst on a fresh mid-turn attach — expansion must not run:\n // it would spend the one synthetic message_start on an event nobody renders, and the\n // first post-subscription assistant event could no longer heal the stream.\n for (const expanded of listeners.size > 0 ? streamHeal.expand(event) : [event]) {\n for (const l of listeners) l(expanded);\n // After the cache listener (registration order guarantees the cache is current) and\n // after StreamHeal expansion, so local handlers see the in-process cumulative shape.\n localHost?.emitAgentEvent(expanded);\n }\n };\n\n // Pi appends the compaction entry before emitting a successful compaction_end. In-process\n // InteractiveMode therefore reads the new entry synchronously while handling that event.\n // The remote cache only learns it through the seed bridge, so hold this event (and every\n // event behind it) until the same invariant is true locally. Without this barrier the TUI\n // throws \"Completed compaction is missing from the session context\" and exits.\n const heldEvents: AgentSessionEvent[] = [];\n let reconcilingCompaction = false;\n const drainHeldEvents = (): void => {\n if (reconcilingCompaction) return;\n while (heldEvents.length > 0) {\n const event = heldEvents.shift()!;\n if (event.type !== \"compaction_end\" || event.aborted || !event.result) {\n fanOutEvent(event);\n continue;\n }\n\n reconcilingCompaction = true;\n void cache.reconcileTreeAfterEvent().then(() => {\n const entry = cache.entries[0];\n const result = event.result!;\n if (\n entry?.type !== \"compaction\" ||\n entry.summary !== result.summary ||\n entry.firstKeptEntryId !== result.firstKeptEntryId ||\n entry.tokensBefore !== result.tokensBefore\n ) {\n throw new Error(\"the refreshed session context does not contain the completed compaction\");\n }\n fanOutEvent(event);\n }).catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n debug(`completed compaction context refresh failed: ${message}`);\n bridge.notify(`Compaction completed, but the local transcript could not be refreshed: ${message}`, \"error\");\n // Still clear InteractiveMode's compaction state and flush its queued input, but omit\n // the result that makes it synchronously consume a compaction entry we do not have.\n fanOutEvent({ ...event, result: undefined });\n }).finally(() => {\n reconcilingCompaction = false;\n drainHeldEvents();\n });\n return;\n }\n };\n\n rpc.onEvent((event) => {\n const typedEvent = event as { type?: string; entry?: { type?: string } };\n const type = typedEvent.type ?? \"\";\n if (\n type === \"model_changed\" ||\n (type === \"entry_appended\" && typedEvent.entry?.type === \"model_change\")\n ) {\n void refreshThinkingLevels();\n }\n // Responses were correlated upstream; extension-UI requests are mapped separately (§5.3).\n if (type === \"response\" || type.startsWith(\"extension_ui\")) return;\n heldEvents.push(event);\n drainHeldEvents();\n });\n\n const extensionUi = wireExtensionUi(\n rpc,\n bridge,\n (request) =>\n treeBridge.consumeExtensionNotification(request) ||\n authBridge.consumeExtensionRequest(request) ||\n remoteUiBridge.consumeExtensionRequest(request),\n );\n\n // Session-replacement callbacks InteractiveMode registers at construction (§5.2).\n let rebindSession: (() => Promise<void>) | null = null;\n let beforeSessionInvalidate: (() => void) | null = null;\n\n /** Arm after a renderer binds, then recover the shim/gateway's latest cumulative partial. */\n const healStreamingRenderer = async (): Promise<void> => {\n streamHeal.arm(cache.state.isStreaming);\n if (cache.state.isStreaming) {\n // InteractiveMode shows its working indicator only on a live agent_start, which a\n // mid-turn attach never sees — a running tool call looks idle. setWorkingVisible\n // re-derives from session.isStreaming, so this is a no-op once the turn has ended.\n bridge.onUiBound(() => bridge.ui?.setWorkingVisible?.(true));\n await rpc.refreshStreamingSnapshot();\n }\n };\n\n /** A pod-side session replacement succeeded: re-seed the cache, then let the TUI rebind. */\n const applySessionReplacement = async (\n reseedScope = false,\n dialogs: DialogInvalidation = \"drop\",\n reason: \"new\" | \"resume\" | \"fork\" = \"resume\",\n ): Promise<void> => {\n // Cancel locally queued aux waits BEFORE refresh/rebind: their late replies\n // correlate to the old session and must never land in the replacement one.\n // In-flight pod executions are the gateway's to cancel; this never aborts the turn.\n extensionModelRegistry.discardPending(`the pi pod session was replaced (${reason})`);\n const previousSessionFile = cache.state.sessionFile ?? undefined;\n // Both calls destroy the on-screen dialog surfaces, and must stay in the same tick: a\n // surface that answers as it is disposed would beat the abandon flag otherwise.\n beforeSessionInvalidate?.();\n extensionUi.invalidateDialogs(dialogs);\n await cache.reset();\n await refreshThinkingLevels();\n await authBridge.refresh();\n // A same-pod replacement keeps live /scoped-models edits; a pod switch re-seeds from\n // the new pod's settings, because the old scope was another pod's opinion.\n if (reseedScope) await seedScopedModels();\n else rehydrateScopedModels();\n await rebindSession?.();\n await healStreamingRenderer();\n // Covers /pod switch and pod-side session replacement (/new, /fork, /resume): local\n // extensions observe the same shutdown/start pair an in-process session emits, with\n // pi's own reasons (native: new/resume/fork) so mode-gated capabilities reset correctly.\n if (localHost) {\n const targetSessionFile = cache.state.sessionFile ?? undefined;\n await localHost.sessionShutdown(\n reason,\n targetSessionFile !== undefined ? { targetSessionFile } : undefined,\n );\n await localHost.sessionStart(\n reason,\n previousSessionFile !== undefined ? { previousSessionFile } : undefined,\n );\n }\n };\n\n // --- /pod: an ordinary client-side command source in pi's autocomplete (§5.4) ------------\n const podSubcommands = router.available();\n const podCommand = {\n name: \"pod\",\n invocationName: \"pod\",\n description: `pi pod: ${podSubcommands.map((c) => c.name).join(\", \")}`,\n sourceInfo: { path: \"pi-pod\", source: \"pi-pod\", scope: \"user\", origin: \"top-level\" },\n getArgumentCompletions: (prefix: string) => {\n const value = prefix.trim();\n // `/pod local <name>`: complete locally registered command names so the\n // explicit-local namespace stays discoverable without shadowing pod listings.\n if (value === \"local\" || value.startsWith(\"local \")) {\n const needle = value === \"local\" ? \"\" : value.slice(\"local \".length).trimStart();\n const names = (localHost?.runner.getRegisteredCommands() ?? [])\n .map((c) => c.name)\n .filter((name) => name !== \"pod\" && name.startsWith(needle));\n if (names.length === 0 || (names.length === 1 && names[0] === needle)) return null;\n return names.map((name) => ({ value: `local ${name}`, label: name, description: \"run locally\" }));\n }\n // Returning the exact argument makes Enter keep accepting the same completion forever\n // instead of submitting `/pod shell` (and every other completed subcommand).\n if (podSubcommands.some((c) => c.name === value)) return null;\n const matches = podSubcommands.filter((c) => c.name.startsWith(value));\n if (matches.length === 0) return null;\n return matches.map((c) => ({ value: c.name, label: c.name, description: c.description }));\n },\n };\n\n /** Raw commands retain private capabilities; only the filtered view reaches Pi's UI. */\n const remoteCommands = (): RemoteCommand[] => cache.commands as RemoteCommand[];\n const visibleRemoteCommands = (): RemoteCommand[] =>\n remoteCommands().filter((command) => !command.name.startsWith(POD_INTERNAL_COMMAND_PREFIX));\n\n // The pod owns every slash command by default (the pre-bridge behavior): the same\n // attested extensions execute in the pod, so the pod's copy of every command stays\n // the one autocomplete lists and prompt() executes. Local execution is explicit —\n // the localCommands allowlist or the `/pod local <name>` namespace — and therefore\n // needs no shadowing rules and can never double-execute.\n const registeredCommands = () => [\n podCommand,\n ...visibleRemoteCommands()\n .filter((c) => c.source === \"extension\")\n .map((c) => ({\n name: c.name,\n invocationName: c.name,\n description: c.description ?? \"\",\n sourceInfo: c.sourceInfo,\n })),\n ];\n\n // --- prompt interception: /pod runs locally, everything else crosses the wire ------------\n // Local image references (clipboard pastes, drag-drops, `@shot.png`, typed paths) name\n // host files the pod cannot see, so they are read and processed here and ride the\n // existing RPC `images` field. Extraction runs after the local-command checks: /pod and\n // pod-internal commands never name user files. `extraImages` (extension-supplied parts)\n // share the per-prompt budget, so the combined turn always fits the gateway's caps.\n const withLocalImages = async (\n text: string,\n extraImages?: unknown[],\n ): Promise<{ message: string; images: unknown[] | undefined }> => {\n const prepared = await preparePromptImages(text, {\n cwd,\n notify: (message, type) => bridge.notify(message, type),\n existingImages: extraImages as ImageContent[] | undefined,\n });\n const images = [...(extraImages ?? []), ...(prepared.images ?? [])];\n return { message: prepared.text, images: images.length > 0 ? images : undefined };\n };\n const prompt = async (\n text: string,\n promptOpts?: { images?: unknown[]; streamingBehavior?: \"steer\" | \"followUp\"; skipLocalScan?: boolean },\n ): Promise<void> => {\n if (router.matches(text)) {\n opts.onPodCommandSubmit?.();\n await router.handle(text);\n return;\n }\n const slashName = /^\\/([^\\s]+)/.exec(text.trimStart())?.[1];\n if (slashName?.startsWith(POD_INTERNAL_COMMAND_PREFIX)) {\n throw new Error(\"pi pod internal commands cannot be invoked from the editor\");\n }\n // Command ownership: the pod owns every slash command unless the caller opted a\n // name into local execution via the localCommands allowlist (generic, no hardcoded\n // extension names). An allowlisted name with no local registration falls through\n // to the pod — the same extension runs there, so behavior is preserved with a\n // single owner and never a duplicate or fallback second run. `/pod local <name>`\n // (handled above by the router) is the strict explicit route.\n if (slashName && localCommandAllowlist.has(slashName)) {\n const afterName = text.trimStart().slice(slashName.length + 1);\n if (await runLocalCommandByName(slashName, afterName.trim())) return;\n }\n // Imageless prompts skip the async scan: the rpc.request below runs in this tick,\n // exactly as before image support existed. (This call must stay textually inside\n // `prompt`: the classic-architecture freeze counts RPC call sites, and `prompt:prompt`\n // is the one allotted slot for the prompt tunnel.)\n let message = text;\n let images = promptOpts?.images?.length ? [...promptOpts.images] : undefined;\n if (!promptOpts?.skipLocalScan && collectImageCandidates(text).length > 0) {\n const prepared = await withLocalImages(text, promptOpts?.images);\n message = prepared.message;\n images = prepared.images;\n }\n const streamingBehavior = promptOpts?.streamingBehavior;\n // Pi's editor invokes its async onSubmit callback without observing the returned promise.\n // A transport drop while steering would therefore escape as an uncaught rejection and kill\n // the local TUI. Report delivery failures here, at the RPC boundary, instead. The gateway\n // still owns reconnect-or-shutdown; never replay automatically because the pod may have\n // accepted the prompt before the acknowledgement was lost.\n return rpc.request({\n type: \"prompt\",\n message,\n ...(images?.length ? { images: images as never } : {}),\n ...(streamingBehavior ? { streamingBehavior } : {}),\n }).catch((error: unknown) => {\n bridge.notify(\n `Prompt delivery was interrupted: ${error instanceof Error ? error.message : String(error)}; check the session before retrying`,\n \"error\",\n );\n return null;\n }).then((response) => {\n if (!response) return;\n if (!response.success) throw new Error(response.error);\n void cache.refreshState();\n });\n };\n\n /** Run a mutating command, then refresh the state cache so sync getters agree (§5.2). */\n const mutate = async <T>(run: () => Promise<T>): Promise<T> => {\n const result = await run();\n await cache.refreshState();\n return result;\n };\n const setRemoteModel = async <T>(run: () => Promise<T>): Promise<T> => {\n const result = await mutate(run);\n await refreshThinkingLevels();\n return result;\n };\n\n // --- services (real settings; RPC-backed model runtime; empty local resources) -----------\n const unavailableLogin = async (): Promise<never> => {\n throw new Error(\"authentication runs in the pod\");\n };\n const remoteProviders = (): RemoteProviderFacade[] => {\n if (!authBridge.supportsAuthBridge()) {\n // A live process from an older launcher has no metadata command. Still advertise its\n // known model providers so /login reaches the bridge's actionable restart error rather\n // than falsely claiming that no subscription providers exist.\n return [...new Set((cache.availableModels as Array<{ provider: string }>).map(({ provider }) => provider))]\n .map((id) => ({\n id,\n name: id,\n auth: {\n apiKey: { name: \"API key\", login: unavailableLogin },\n oauth: { name: \"Subscription\", login: unavailableLogin },\n },\n }));\n }\n return authBridge.snapshot.providers.map((provider) => ({\n id: provider.id,\n name: provider.name,\n auth: {\n ...(provider.auth.apiKey\n ? {\n apiKey: {\n name: provider.auth.apiKey.name,\n // InteractiveMode uses presence of login only to distinguish an interactive\n // key flow from ambient setup. The actual function runs pod-side via login().\n ...(provider.auth.apiKey.interactive ? { login: unavailableLogin } : {}),\n },\n }\n : {}),\n ...(provider.auth.oauth\n ? {\n oauth: {\n name: provider.auth.oauth.name,\n ...(provider.auth.oauth.loginLabel ? { loginLabel: provider.auth.oauth.loginLabel } : {}),\n login: unavailableLogin,\n },\n }\n : {}),\n },\n }));\n };\n const refreshRemoteModels = async (): Promise<RemoteModel[]> => {\n const models = await rpc.getAvailableModels();\n cache.availableModels = models;\n rehydrateScopedModels();\n return models as RemoteModel[];\n };\n const modelRuntime = {\n getAvailable: refreshRemoteModels,\n getAvailableSnapshot: () => cache.availableModels as RemoteModel[],\n getModels: () => cache.availableModels as RemoteModel[],\n getModel: (provider: string, id: string) => findCachedModel(provider, id),\n getProviders: remoteProviders,\n getProvider: (provider: string) => remoteProviders().find(({ id }) => id === provider),\n getProviderAuthStatus: (provider: string) =>\n authBridge.snapshot.providers.find(({ id }) => id === provider)?.status ?? { configured: false },\n listCredentials: async () => authBridge.snapshot.credentials,\n checkAuth: async () => ({ ok: true }),\n getAuth: () => undefined,\n isUsingOAuth: (provider: string) =>\n authBridge.snapshot.providers.find(({ id }) => id === provider)?.usingOAuth ?? false,\n // 0.84 footer calls isUsingSubscription; 0.83 pods only had isUsingOAuth. Provide a polyfill so\n // an older pod does not crash the host TUI when attached from a newer launcher (§10). For 0.83\n // pods isSubscription is not reported, so any OAuth is treated as possible subscription —\n // strictly more (sub) labels, but never a crash. 0.84+ pods will correctly distinguish.\n isUsingSubscription: (provider: string) =>\n authBridge.snapshot.providers.find(({ id }) => id === provider)?.usingOAuth ?? false,\n getError: () => undefined,\n refresh: async () => {\n await Promise.all([refreshRemoteModels(), authBridge.refresh()]);\n return { aborted: false, errors: new Map() };\n },\n login: async (provider: string, type: RemoteAuthType, interaction: RemoteAuthInteraction) => {\n const accountSupported = opts.accountLogin &&\n (opts.accountAuthSupported ? await opts.accountAuthSupported(provider, type) : true);\n if (accountSupported) {\n try {\n await opts.accountLogin!(provider, type, interaction);\n } catch (error) {\n if (!isUnsupportedCredentialProvider(error)) throw error;\n await authBridge.login(provider, type, interaction);\n }\n } else {\n await authBridge.login(provider, type, interaction);\n }\n await refreshRemoteModels();\n return { type };\n },\n logout: async (provider: string) => {\n const accountSupported = opts.accountLogout &&\n (opts.accountAuthSupported ? await opts.accountAuthSupported(provider) : true);\n if (accountSupported) {\n warn(`signing out of ${provider} removes that account credential for every pod`);\n try {\n await opts.accountLogout!(provider);\n } catch (error) {\n if (!isUnsupportedCredentialProvider(error)) throw error;\n await authBridge.logout(provider);\n }\n } else {\n await authBridge.logout(provider);\n }\n await refreshRemoteModels();\n },\n };\n\n /** Resolve the initial local scope: CLI patterns, then the pod's settings, then the host's. */\n const seedScopedModels = async (): Promise<void> => {\n const podPatterns = await opts.getPodModelPatterns?.().catch(() => undefined);\n const patterns = opts.modelPatterns ?? podPatterns ?? settingsManager.getEnabledModels();\n if (!patterns?.length) {\n scopedModels = [];\n return;\n }\n const resolved = await resolveModelScopeWithDiagnostics(patterns, {\n getAvailable: async () => cache.availableModels,\n } as never);\n scopedModels = resolved.scopedModels;\n };\n\n /**\n * Cycle locally so direction and live /scoped-models edits work despite RPC's cycle_model\n * command having neither a direction nor a scoped-model setter.\n */\n const cycleModel = async (direction: \"forward\" | \"backward\" = \"forward\") => {\n const isScoped = scopedModels.length > 0;\n const candidates: ScopedModel[] = isScoped\n ? scopedModels\n : (cache.availableModels as RemoteModel[]).map((model) => ({ model }));\n if (candidates.length <= 1) return undefined;\n\n const current = cache.state.model as RemoteModel | undefined;\n let currentIndex = candidates.findIndex(\n ({ model }) => model.provider === current?.provider && model.id === current?.id,\n );\n if (currentIndex === -1) currentIndex = 0;\n const delta = direction === \"backward\" ? -1 : 1;\n const next = candidates[(currentIndex + delta + candidates.length) % candidates.length]!;\n\n await rpc.setModel(next.model.provider, next.model.id);\n cache.state.model = next.model as never;\n if (next.thinkingLevel !== undefined) {\n await rpc.setThinkingLevel(next.thinkingLevel);\n cache.state.thinkingLevel = next.thinkingLevel;\n }\n settingsManager.setDefaultModelAndProvider(next.model.provider, next.model.id);\n await cache.refreshState();\n await refreshThinkingLevels();\n return {\n model: cache.state.model ?? next.model,\n thinkingLevel: cache.state.thinkingLevel,\n isScoped,\n };\n };\n\n const resourceLoader = {\n getThemes: () => opts.getLocalThemes?.() ?? { themes: [], diagnostics: [] },\n getPrompts: () => ({ prompts: [], diagnostics: [] }),\n // Pi re-adds the `skill:` prefix when it builds the command, so hand back the bare name.\n getSkills: () => ({\n skills: visibleRemoteCommands()\n .filter((c) => c.source === \"skill\" && c.name.startsWith(SKILL_COMMAND_PREFIX))\n .map((c) => ({\n name: c.name.slice(SKILL_COMMAND_PREFIX.length),\n description: c.description ?? \"\",\n // The pod-side path: only ever displayed, but the loaded-resources banner keys on it.\n filePath: c.sourceInfo?.path ?? `pod:${c.name}`,\n sourceInfo: c.sourceInfo,\n })),\n diagnostics: [],\n }),\n getAgentsFiles: () => ({ agentsFiles: [] }),\n getExtensions: () => ({ extensions: [], errors: [] }),\n // Resources live in the pod, which holds the real loader; the local TUI only asks these\n // to render prompt-source information, and the honest local answer is \"none here\" —\n // the same emptiness the collections above already return.\n getSystemPromptSource: () => undefined,\n getAppendSystemPromptSources: () => [],\n };\n\n // What ctx.modelRegistry offers locally rendered extensions: metadata from the\n // client-side catalog/auth snapshot, completions executed pod-side with real auth.\n // Secret-bearing and provider-mutating methods throw explained errors — pod\n // credentials never cross to the launcher (see extension-model-registry.ts).\n const extensionModelRegistry = createExtensionModelRegistry({\n getModels: () => cache.availableModels as AuxCatalogModel[],\n isProviderConfigured: (provider) =>\n authBridge.snapshot.providers.find(({ id }) => id === provider)?.status.configured ?? false,\n getProviderDisplayName: (provider) =>\n authBridge.snapshot.providers.find(({ id }) => id === provider)?.name ??\n remoteProviders().find(({ id }) => id === provider)?.name ??\n provider,\n isUsingOAuth: (provider) =>\n authBridge.snapshot.providers.find(({ id }) => id === provider)?.usingOAuth ?? false,\n auxComplete: opts.auxComplete,\n getExtensionVersion: () => rpc.helloInfo?.extensionVersion ?? undefined,\n });\n\n // The local extension host (attested pod extensions) serves the renderer/transformer\n // hooks when it exists; the stubs below are the zero-cost answer for everyone else.\n // The command listing stays pod-authoritative (pod ownership is the default); local\n // commands are discovered through `/pod local` completion below, not shadowing.\n const extensionRunner = {\n getRegisteredCommands: registeredCommands,\n getCommand: (name: string) =>\n name === \"pod\"\n ? podCommand\n : visibleRemoteCommands().find((c) => c.source === \"extension\" && c.name === name),\n getCommands: () => new Map(registeredCommands().map((c) => [c.name, c])),\n getRegisteredShortcuts: () => [],\n getShortcuts: (resolvedKeybindings?: unknown) =>\n localHost?.runner.getShortcuts(resolvedKeybindings) ?? new Map(),\n getEntryRenderer: (customType: string) => localHost?.runner.getEntryRenderer(customType),\n getMessageRenderer: (customType: string) => localHost?.runner.getMessageRenderer(customType),\n // Display transforms are functions and cannot cross JSON/RPC. Built-in local transforms\n // (including Mermaid) still compose — InteractiveMode appends these to its own chain.\n // Pod extension transforms remain honestly unavailable; client extensions supply theirs here.\n getMarkdownTransformers: () => localHost?.runner.getMarkdownTransformers() ?? [],\n getCommandDiagnostics: () => localHost?.runner.getCommandDiagnostics() ?? [],\n getShortcutDiagnostics: () => localHost?.runner.getShortcutDiagnostics() ?? [],\n getModelRegistry: () => (localHost ? extensionModelRegistry : undefined),\n emitUserBash: async () => undefined,\n };\n\n const agent = {\n abort: () => void rpc.abort().catch(() => {}),\n signal: abortController.signal,\n /** Written by the /transport toggle; meaningless off-pod, accepted so the write lands. */\n transport: undefined as unknown,\n };\n\n let treeMutationTail: Promise<void> = Promise.resolve();\n const serializeTreeMutation = <T>(run: () => Promise<T>): Promise<T> => {\n const result = treeMutationTail.then(run, run);\n treeMutationTail = result.then(\n () => undefined,\n () => undefined,\n );\n return result;\n };\n\n const trackLabelMutation = (entryId: string, labelValue: string | undefined): void => {\n if (!findTreeNode(cache.tree, entryId)) {\n bridge.notify(\"Could not update label: the selected entry is no longer available\", \"error\");\n return;\n }\n const label = labelValue ? labelValue : null;\n const revision = cache.beginLabelMutation(entryId, label);\n void serializeTreeMutation(async () => {\n const acknowledgement = await treeBridge.setLabel(entryId, label);\n const snapshot = await cache.refreshTree(acknowledgement.leafId);\n const authoritative = findTreeNode(snapshot.tree, entryId);\n cache.completeLabelMutation(entryId, revision, {\n ok: true,\n label: authoritative?.label ?? null,\n labelTimestamp: authoritative?.labelTimestamp,\n });\n }).catch((error) => {\n cache.completeLabelMutation(entryId, revision, { ok: false });\n bridge.notify(`Could not save label: ${error instanceof Error ? error.message : String(error)}`, \"error\");\n });\n };\n\n // --- sessionManager: cache-backed branch entries and folded tree (§5.2) ---\n const sessionManager = {\n getCwd: () => cwd,\n getEntries: () => cache.entries,\n getLeafId: () => cache.leafId ?? undefined,\n getSessionDir: () => cwd,\n getSessionFile: () => cache.state.sessionFile,\n getSessionName: () => cache.state.sessionName,\n getSessionId: () => cache.state.sessionId,\n getTree: () => cache.tree,\n usesDefaultSessionDir: () => true,\n isPersisted: () => cache.state.sessionFile !== undefined,\n appendLabelChange: (entryId: string, label?: string) => trackLabelMutation(entryId, label),\n buildContextEntries: () => cache.entries,\n };\n\n // --- the 57-member session surface ---------------------------------------------------------\n const session = {\n // sync getters from the cache\n get state() {\n return {\n messages: cache.messages,\n tools: [],\n model: cache.state.model,\n thinkingLevel: cache.state.thinkingLevel,\n };\n },\n get model() {\n return cache.state.model;\n },\n get thinkingLevel() {\n return cache.state.thinkingLevel;\n },\n get isStreaming() {\n return cache.state.isStreaming;\n },\n get isIdle() {\n return !cache.state.isStreaming && !cache.state.isCompacting;\n },\n get isCompacting() {\n return cache.state.isCompacting;\n },\n get isBashRunning() {\n return activeBashRequests.size > 0 || cache.isBashRunning;\n },\n get isRetrying() {\n return false;\n },\n get autoRetryEnabled() {\n return true;\n },\n get retryAttempt() {\n return 0;\n },\n get messages() {\n return cache.messages;\n },\n get systemPrompt() {\n return \"\";\n },\n get steeringMode() {\n return cache.state.steeringMode;\n },\n get followUpMode() {\n return cache.state.followUpMode;\n },\n get sessionFile() {\n return cache.state.sessionFile;\n },\n get sessionId() {\n return cache.state.sessionId;\n },\n get sessionName() {\n return cache.state.sessionName;\n },\n get scopedModels() {\n return scopedModels;\n },\n get promptTemplates() {\n return visibleRemoteCommands()\n .filter((c) => c.source === \"prompt\")\n .map((c) => ({\n name: c.name,\n description: c.description ?? \"\",\n // The pod-side path: only ever displayed, but the loaded-resources banner sorts by it.\n filePath: c.sourceInfo?.path ?? `pod:${c.name}`,\n sourceInfo: c.sourceInfo,\n }));\n },\n get pendingMessageCount() {\n return cache.state.pendingMessageCount;\n },\n get autoCompactionEnabled() {\n return cache.state.autoCompactionEnabled;\n },\n get hasPendingBashMessages() {\n return false;\n },\n\n // local-by-nature services\n settingsManager: remoteSettingsManager,\n sessionManager,\n agent,\n modelRuntime,\n resourceLoader,\n extensionRunner,\n\n // event stream\n subscribe(listener: (event: unknown) => void) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n\n // delegated commands\n prompt,\n steer: async (text: string, images?: unknown[]) => {\n const prepared = await withLocalImages(text, images);\n await rpc.steer(prepared.message, prepared.images as ImageContent[] | undefined);\n },\n followUp: async (text: string, images?: unknown[]) => {\n const prepared = await withLocalImages(text, images);\n await rpc.followUp(prepared.message, prepared.images as ImageContent[] | undefined);\n },\n sendUserMessage: (content: unknown) => {\n if (typeof content === \"string\") return prompt(content);\n // Extension-supplied parts (attested local extensions only — InteractiveMode's\n // editor path calls prompt() directly). Forwarded with the scan skipped: scanning\n // here would read host files the extension merely mentioned in prose. pi joins\n // text parts with newlines, which this matches.\n const parts = content as Array<{ type?: string; text?: string }>;\n const text = parts\n .filter((part) => part?.type === \"text\")\n .map((part) => part?.text ?? \"\")\n .join(\"\\n\");\n const carried = parts.filter((part) => part?.type === \"image\");\n return prompt(text, { ...(carried.length > 0 ? { images: carried } : {}), skipLocalScan: true });\n },\n abort: () => rpc.abort(),\n waitForIdle: (timeoutMs?: number) => rpc.waitForIdle(timeoutMs),\n setModel: (model: { provider: string; id: string }) =>\n setRemoteModel(() => rpc.setModel(model.provider, model.id)),\n cycleModel,\n setThinkingLevel: (level: never) => mutate(() => rpc.setThinkingLevel(level)),\n cycleThinkingLevel: async () => {\n const result = await mutate(() => rpc.cycleThinkingLevel());\n return result?.level;\n },\n getAvailableThinkingLevels: () => [\n ...(cache.availableThinkingLevels ?? FALLBACK_THINKING_LEVELS),\n ],\n supportsThinking: () => (cache.state.model as { reasoning?: boolean } | undefined)?.reasoning ?? false,\n setSteeringMode: (mode: \"all\" | \"one-at-a-time\") => mutate(() => rpc.setSteeringMode(mode)),\n setFollowUpMode: (mode: \"all\" | \"one-at-a-time\") => mutate(() => rpc.setFollowUpMode(mode)),\n compact: (customInstructions?: string) => mutate(() => rpc.compact(customInstructions)),\n abortCompaction: () => {},\n // Unreachable: the remote settings facade always skips branch summaries.\n abortBranchSummary: () => {},\n setAutoCompactionEnabled: (enabled: boolean) => mutate(() => rpc.setAutoCompaction(enabled)),\n setAutoRetryEnabled: (enabled: boolean) => mutate(() => rpc.setAutoRetry(enabled)),\n abortRetry: () => rpc.abortRetry(),\n\n /** `!command` bash: streamed chunks arrive as bash_execution_update events with our id (§8). */\n executeBash: async (command: string, onChunk?: (chunk: string) => void) => {\n const id = rpc.newRequestId();\n activeBashRequests.add(id);\n let rendered = \"\";\n const off = rpc.onEvent((event) => {\n const e = event as { type?: string; id?: string; delta?: string };\n if (e.type === \"bash_execution_update\" && e.id === id && e.delta) {\n rendered += e.delta;\n onChunk?.(e.delta);\n }\n });\n try {\n const response = await rpc.request({ type: \"bash\", command, id });\n if (!response.success) throw new Error(response.error);\n const data = (response as { data?: { output?: string; truncated?: boolean } }).data;\n const output = typeof data?.output === \"string\" ? data.output : \"\";\n if (output.length > rendered.length && output.startsWith(rendered)) {\n const suffix = output.slice(rendered.length);\n if (suffix) onChunk?.(suffix);\n } else if (rendered.length === 0 && output) {\n onChunk?.(output);\n }\n return data;\n } finally {\n activeBashRequests.delete(id);\n off();\n }\n },\n recordBashResult: () => {},\n abortBash: () => rpc.abortBash(),\n\n setSessionName: (name: string) => {\n // InteractiveMode's /name reads the name straight back after this call to decide whether\n // pi normalized it, and retitles the terminal from the same read. Over RPC neither the\n // round trip nor session_info_changed has happened by then, so without this every rename\n // in a pod warns that it was \"normalized\" to the *previous* name and the title lags one\n // rename behind. The event carries pi's authoritative spelling and overwrites this.\n cache.state.sessionName = name;\n return mutate(() => rpc.setSessionName(name));\n },\n navigateTree: async (\n targetId: string,\n navigateOptions?: { summarize?: boolean },\n ): Promise<{ cancelled: boolean; editorText?: string }> => {\n if (navigateOptions?.summarize) {\n throw new Error(\"Branch summaries are unavailable in remote pi pod sessions\");\n }\n if (!treeBridge.supportsTreeBridge()) {\n throw new Error(\n \"This running pod uses an older pi pod extension. Exit Pi, then attach again so pi pod can load the updated extension.\",\n );\n }\n if (!findTreeNode(cache.tree, targetId)) throw new Error(`Tree entry ${targetId} is no longer available`);\n // session_tree is runner-local in pi (never on the wire): synthesize it after a\n // successful local navigation so TUI-mode capabilities rescan, like in-process pi.\n const oldLeafId = cache.leafId ?? null;\n return serializeTreeMutation(async () => {\n try {\n const acknowledgement = await treeBridge.navigate(targetId);\n await cache.refreshTree(acknowledgement.leafId);\n // Older pods answer without editorText; their tree stubs carry only a whitespace-flattened,\n // truncated preview, so restored text loses newlines until the pod's extension is updated.\n let editorText = acknowledgement.editorText;\n if (editorText === undefined) {\n const entry = cache.entries.find((candidate) => candidate.id === targetId) ?? findTreeNode(cache.tree, targetId)?.entry;\n editorText = entry ? editorTextForEntry(entry) : undefined;\n }\n const result = {\n cancelled: acknowledgement.cancelled,\n ...(editorText !== undefined ? { editorText } : {}),\n };\n if (!result.cancelled) {\n localHost?.emitLifecycle({\n type: \"session_tree\",\n newLeafId: acknowledgement.leafId,\n oldLeafId,\n fromExtension: false,\n });\n }\n return result;\n } catch (error) {\n await cache.refreshTree().catch(() => {});\n throw error;\n }\n });\n },\n getUserMessagesForForking: () => cache.forkMessages ?? [],\n // Sync by contract: InteractiveMode's /session destructures the result immediately,\n // so the RPC promise must never cross this surface (it crashed the TUI as stats.tokens\n // === undefined). The cache refreshes from the pod at every completion boundary.\n getSessionStats: () => cache.sessionStatsSnapshot(),\n /** The footer's context gauge, computed from cached messages the way pi's session does. */\n getContextUsage: () => {\n const model = cache.state.model as { contextWindow?: number } | undefined;\n const contextWindow = model?.contextWindow ?? 0;\n if (contextWindow <= 0) return undefined;\n for (let i = cache.messages.length - 1; i >= 0; i--) {\n const message = cache.messages[i] as {\n role?: string;\n stopReason?: string;\n usage?: Record<string, number>;\n };\n if (message.role !== \"assistant\" || !message.usage) continue;\n if (message.stopReason === \"aborted\" || message.stopReason === \"error\") continue;\n const tokens = calculateContextTokens(message.usage as never);\n if (tokens > 0) return { tokens, contextWindow, percent: (tokens / contextWindow) * 100 };\n }\n return { tokens: null, contextWindow, percent: null };\n },\n getSteeringMessages: () => [],\n getFollowUpMessages: () => [],\n clearQueue: () => ({ steering: [], followUp: [] }),\n getToolDefinition: () => undefined,\n getLastAssistantText: () => rpc.getLastAssistantText(),\n exportToHtml: async (outputPath?: string) => (await rpc.exportHtml(outputPath)).path ?? \"\",\n exportToJsonl: () => {\n throw new Error(\"session files live in the pod — use /export html instead\");\n },\n\n /** InteractiveMode hands the runtime its UI context and shutdown requester here (§5.3). */\n bindExtensions: async (bindOpts: {\n uiContext?: Record<string, unknown>;\n shutdownHandler?: () => void;\n }) => {\n bridge.bindUi(\n (bindOpts.uiContext ?? {}) as never,\n bindOpts.shutdownHandler ?? null,\n );\n },\n // Nothing to reload here — resources live in the pod. But /reload clears every extension\n // terminal-input listener and autocomplete wrapper on its way in and rebinds nothing, so\n // the chords and pod file completion are ours to put back.\n reload: async () => {\n bridge.rewireUi();\n if (bridge.ui) installPodFileCompletion(bridge.ui);\n },\n createReplacedSessionContext: () => ({}),\n hasExtensionHandlers: () => false,\n setActiveToolsByName: () => {},\n getActiveToolNames: () => [],\n getAllTools: () => [],\n setScopedModels: (models: ScopedModel[]) => {\n scopedModels = [...models];\n },\n dispose: () => {},\n };\n\n // --- runtime host (9 members) -------------------------------------------------------------\n const services = {\n cwd,\n agentDir: opts.agentDir,\n modelRuntime,\n settingsManager: remoteSettingsManager,\n resourceLoader,\n diagnostics: [],\n };\n\n const runtimeHost: Record<string, unknown> = {\n session,\n services,\n setRebindSession: (callback?: () => Promise<void>) => {\n rebindSession = callback ?? null;\n },\n setBeforeSessionInvalidate: (callback?: () => void) => {\n beforeSessionInvalidate = callback ?? null;\n },\n\n // Session replacement flows (§8): the pod replaces its session; the client re-seeds\n // its cache and lets InteractiveMode rebind. Session files stay pod-side throughout.\n newSession: async (flowOpts?: { parentSession?: string }) => {\n const result = await rpc.newSession(flowOpts?.parentSession);\n if (!result.cancelled) await applySessionReplacement(false, \"drop\", \"new\");\n return { cancelled: result.cancelled };\n },\n switchSession: async (sessionPath: string) => {\n const result = await rpc.switchSession(sessionPath);\n if (!result.cancelled) await applySessionReplacement(false, \"drop\", \"resume\");\n return { cancelled: result.cancelled };\n },\n fork: async (entryId: string) => {\n const result = await rpc.fork(entryId);\n if (!result.cancelled) await applySessionReplacement(false, \"drop\", \"fork\");\n return { cancelled: result.cancelled, selectedText: result.text };\n },\n importFromJsonl: async () => {\n bridge.notify(\"/import is not available over RPC — session files live in the pod\", \"warning\");\n return { cancelled: true };\n },\n\n /**\n * The one exit everything funnels through (§6.2): InteractiveMode awaits this before its\n * own process.exit, for quits, /pod leaves and signal shutdowns alike. Quitting pi sends\n * the shim shutdown frame and waits for pi_exit; leaving does not touch pi at all.\n */\n dispose: async () => {\n // No prior intent means InteractiveMode initiated shutdown: Ctrl-C Ctrl-C, Ctrl-D, or\n // /quit. A spontaneous remote pi_exit records the same quit intent before requesting\n // shutdown, so remember the distinction before filling in the implicit intent.\n const quitRequested = bridge.intent === null;\n bridge.setIntent({ kind: \"quit\" }); // no-op when pi, a /pod command, or a signal got there first\n const intent = bridge.intent!;\n // Abandon locally queued aux waits; in-flight pod executions are the gateway's to\n // cancel, and their late replies correlate to nothing.\n extensionModelRegistry.discardPending(\"the pi pod session ended\");\n // Extensions hear the shutdown while the UI and caches are still live, then go stale.\n if (localHost) {\n await localHost.sessionShutdown(\"quit\").catch(() => {});\n await localHost.dispose();\n }\n unwireCache();\n extensionUi.dispose();\n treeBridge.dispose();\n authBridge.dispose();\n remoteUiBridge.dispose();\n\n let exitCode: number | null = null;\n if (intent.kind === \"quit\" && (opts.waitForRemoteExitOnQuit?.() ?? true)) {\n exitCode = await quitPi(rpc);\n }\n\n await opts.onEnding({\n intent,\n quitRequested,\n exitCode,\n stderrTail: rpc.getStderr(),\n });\n },\n };\n\n return {\n runtimeHost,\n bridge,\n cache,\n router,\n treeBridge,\n init: async () => {\n await cache.init();\n await refreshThinkingLevels();\n await authBridge.refresh();\n await seedScopedModels();\n if (opts.attestedExtensionPaths?.length) {\n try {\n localHost = await createLocalExtensionHost({\n paths: opts.attestedExtensionPaths,\n hostCwd: cwd,\n cache,\n bridge,\n rpc,\n getScopedModels: () => scopedModels,\n prompt,\n setModel: (model) => setRemoteModel(() => rpc.setModel(model.provider, model.id)),\n setThinkingLevel: (level) => mutate(() => rpc.setThinkingLevel(level as never)),\n setSessionName: (name) => session.setSessionName(name),\n setLabel: (entryId, label) => trackLabelMutation(entryId, label),\n getContextUsage: () => session.getContextUsage(),\n abort: () => void rpc.abort().catch(() => {}),\n compact: (customInstructions) => mutate(() => rpc.compact(customInstructions)),\n waitForIdle: (timeoutMs) => rpc.waitForIdle(timeoutMs),\n modelRegistry: extensionModelRegistry,\n getCommands: () => registeredCommands(),\n });\n // Deferred to the first UI bind, matching in-process pi: InteractiveMode starts its\n // UI before initializing extensions, \"so session_start handlers can use interactive\n // dialogs\" — and so ctx.ui carries the real theme when session_start fires.\n bridge.onUiBound(() => void localHost?.sessionStart(\"startup\"));\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n bridge.onUiBound(() => bridge.notify(`pod extension rendering failed to start: ${message}`, \"warning\"));\n debug(`local extension host failed: ${message}`);\n }\n }\n },\n refreshAfterReplacement: () => applySessionReplacement(true),\n recoverAfterReconnect: () => applySessionReplacement(true, \"redisplay\"),\n healStreamingRenderer,\n reloadSettings: () => settingsManager.reload(),\n disableLocalExtensions: async () => {\n if (!localHost) return;\n const host = localHost;\n localHost = null;\n await host.sessionShutdown(\"resume\").catch(() => {});\n await host.dispose();\n },\n };\n}\n\nfunction editorTextForEntry(entry: SessionEntry): string | undefined {\n if (entry.type === \"message\" && entry.message.role === \"user\") return textContent(entry.message.content);\n if (entry.type === \"custom_message\") return textContent(entry.content);\n return undefined;\n}\n\nfunction textContent(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n return content\n .filter((part): part is { type: \"text\"; text: string } =>\n part !== null &&\n typeof part === \"object\" &&\n (part as { type?: unknown }).type === \"text\" &&\n typeof (part as { text?: unknown }).text === \"string\",\n )\n .map((part) => part.text)\n .join(\"\");\n}\n\n/** Send the shutdown frame and wait (bounded) for pi_exit; null when it never came (§6.2). */\nexport async function quitPi(rpc: RpcClientBase): Promise<number | null> {\n if (rpc.exitCode !== undefined) return rpc.exitCode;\n\n return new Promise<number | null>((resolve) => {\n const timer = setTimeout(() => {\n off();\n resolve(rpc.exitCode ?? null);\n }, QUIT_TIMEOUT_MS);\n const off = rpc.onControl((event) => {\n if (event.event === \"pi_exit\") {\n clearTimeout(timer);\n off();\n resolve(event.code);\n }\n });\n rpc.shutdown();\n });\n}\n","/**\n * src/client/runtime/bridge.ts — shared state between InteractiveMode's callbacks, the /pod\n * command router, and the session driver (§5.2, §5.4, §6.2).\n *\n * InteractiveMode hands the runtime two things the pi pod host needs to reach later: the\n * extension-UI context (via `session.bindExtensions`) and a shutdown requester. The bridge\n * holds them, plus the one fact every ending path must agree on — what the user asked to\n * happen to the pod on the way out.\n */\n\nexport type PodLeaveAction = \"keep\" | \"archive\";\n\n/**\n * How the session is ending, decided by whichever path got there first (§6.2).\n *\n * quit — the user quit pi (double Ctrl+C, /quit): shutdown frame ⇒ pi_exit ⇒ teardown policy\n * leave — /pod detach|archive: pi keeps running; archive changes logical state only\n * hangup — SIGHUP/SIGTERM: the client went away; the pod is kept\n * transportLost — the channel dropped and could not be recovered; the pod is kept\n */\nexport type EndingIntent =\n | { kind: \"quit\" }\n | { kind: \"leave\"; action: PodLeaveAction }\n | { kind: \"hangup\" }\n | { kind: \"transportLost\" };\n\n/**\n * A raw terminal-input listener, as pi's TUI defines it: it runs ahead of the focused\n * component, and may consume the keystroke or rewrite the data passed downstream (§3).\n */\nexport type TerminalInputHandler = (data: string) => { consume?: boolean; data?: string } | undefined;\n\n/**\n * The slice of pi's ExtensionUIContext the runtime keeps a handle on — captured from\n * `bindExtensions`, used by the extension-UI mapping (§5.3), /pod notices and the chords.\n */\nexport interface HostUiContext {\n select?(title: string, options: string[], opts?: unknown): Promise<string | undefined>;\n confirm?(title: string, message: string, opts?: unknown): Promise<boolean>;\n input?(title: string, placeholder?: string, opts?: unknown): Promise<string | undefined>;\n editor?(title: string, prefill?: string): Promise<string | undefined>;\n notify?(message: string, type?: \"info\" | \"warning\" | \"error\"): void;\n setStatus?(key: string, text: string | undefined): void;\n setWidget?(\n key: string,\n content: string[] | ((tui: unknown, theme: unknown) => unknown) | undefined,\n options?: unknown,\n ): void;\n setFooter?(factory: ((tui: unknown, theme: unknown, footerData: unknown) => unknown) | undefined): void;\n setHeader?(factory: ((tui: unknown, theme: unknown) => unknown) | undefined): void;\n custom?<T>(\n factory: (tui: unknown, theme: unknown, keybindings: unknown, done: (result: T) => void) => unknown,\n options?: unknown,\n ): Promise<T>;\n setWorkingMessage?(message?: string): void;\n setWorkingVisible?(visible: boolean): void;\n setWorkingIndicator?(options?: unknown): void;\n setHiddenThinkingLabel?(label?: string): void;\n setToolsExpanded?(expanded: boolean): void;\n setEditorComponent?(factory: ((tui: unknown, theme: unknown, keybindings: unknown) => unknown) | undefined): void;\n setTitle?(title: string): void;\n setEditorText?(text: string): void;\n onTerminalInput?(handler: TerminalInputHandler): () => void;\n /**\n * Wrap the autocomplete provider InteractiveMode built. Pod sessions use this to resolve\n * `@` against the pod's workspace instead of the host's disk (§5.2). Registrations are\n * dropped whenever pi clears its extension UI, so this is re-run on every UI bind.\n */\n addAutocompleteProvider?(factory: (base: never) => unknown): void;\n}\n\nexport class HostBridge {\n /** Set exactly once, by the first ending path to fire; later writers lose. */\n private endingIntent: EndingIntent | null = null;\n\n private uiContext: HostUiContext | null = null;\n private uiWaiters: Array<() => void> = [];\n private shutdownHandler: (() => void) | null = null;\n private uiBoundHandler: (() => void) | null = null;\n private readonly uiBoundListeners = new Set<(ui: HostUiContext) => void>();\n\n get intent(): EndingIntent | null {\n return this.endingIntent;\n }\n\n /** Record how the session is ending. First writer wins; returns whether it stuck. */\n setIntent(intent: EndingIntent): boolean {\n if (this.endingIntent) return false;\n this.endingIntent = intent;\n return true;\n }\n\n /** Signals outrank dispose's implicit quit, but never overwrite an explicit pod leave. */\n setHangupIntent(): boolean {\n if (this.endingIntent && this.endingIntent.kind !== \"quit\") return false;\n this.endingIntent = { kind: \"hangup\" };\n return true;\n }\n\n /**\n * Runs on every {@link bindUi}. InteractiveMode drops every listener registered through\n * `onTerminalInput` on session rebind and shutdown, so whatever this wires must expect to\n * be wired again from scratch.\n */\n setOnUiBound(handler: (() => void) | null): void {\n this.uiBoundHandler = handler;\n }\n\n /** Re-run that hook against the current context, for paths that clear listeners in place. */\n rewireUi(): void {\n this.uiBoundHandler?.();\n }\n\n /** Captured from `session.bindExtensions` — pi's own dialog/notify/widget surface (§5.3). */\n bindUi(uiContext: HostUiContext, shutdownHandler: (() => void) | null): void {\n this.uiContext = uiContext;\n this.shutdownHandler = shutdownHandler;\n // Chord listeners first: they must exist before a replayed dialog can render over them.\n this.rewireUi();\n for (const listener of this.uiBoundListeners) listener(uiContext);\n const waiters = this.uiWaiters;\n this.uiWaiters = [];\n for (const waiter of waiters) waiter();\n // An ending that arrived before the TUI could register (pi crashing during boot) must\n // still shut the session down — replay it now that someone can act on it.\n if (this.endingIntent && shutdownHandler) shutdownHandler();\n }\n\n /** Run `cb` once a UI context is bound — immediately when one already is. */\n onUiBound(cb: () => void): void {\n if (this.uiContext) cb();\n else this.uiWaiters.push(cb);\n }\n\n /** Subscribe to every UI bind, including session replacement; immediately receives a live bind. */\n onEveryUiBound(cb: (ui: HostUiContext) => void): () => void {\n this.uiBoundListeners.add(cb);\n if (this.uiContext) cb(this.uiContext);\n return () => this.uiBoundListeners.delete(cb);\n }\n\n get ui(): HostUiContext | null {\n return this.uiContext;\n }\n\n notify(message: string, type: \"info\" | \"warning\" | \"error\" = \"info\"): void {\n this.uiContext?.notify?.(message, type);\n }\n\n /**\n * Leave the session via a /pod command (§5.4): record the action, then ask InteractiveMode\n * to shut down cleanly — it restores the terminal and awaits `runtimeHost.dispose()`,\n * where the recorded intent tells dispose to leave pi running.\n */\n requestLeave(action: PodLeaveAction): void {\n this.setIntent({ kind: \"leave\", action });\n this.requestShutdown();\n }\n\n requestShutdown(): void {\n this.shutdownHandler?.();\n }\n\n get canShutdown(): boolean {\n return this.shutdownHandler !== null;\n }\n}\n","/**\n * src/client/runtime/pod-file-completion.ts — `@` completion against the pod's workspace.\n *\n * The launcher embeds pi's own `InteractiveMode`, so pi-tui's `CombinedAutocompleteProvider`\n * resolves `@` by walking `basePath` — the *host's* cwd — with the host's `fd`. Every path\n * the agent can act on lives in the pod, so those suggestions name files that need not\n * exist there. This wraps the provider pi built (`ui.addAutocompleteProvider`) and answers\n * the `@` case from the pod instead, leaving `/` commands and their argument completions to\n * the provider underneath.\n *\n * Prefix parsing and completion-value construction mirror pi-tui's own private helpers: the\n * wrapper has to agree with the `applyCompletion` it delegates back to, byte for byte.\n */\nimport { fuzzyFilter } from \"@earendil-works/pi-tui\";\n\nexport type FileListEntry = { path: string; dir: boolean };\n\nexport type FileListData = {\n entries: FileListEntry[];\n /** False when a pod-side cap cut the walk short, or when the pod could not answer at all. */\n complete: boolean;\n};\n\n/**\n * What an old pod, a timeout, or a malformed reply all yield: no suggestions. Never the\n * host's own files — a wrong path that looks right is worse than no completion.\n */\nexport const FILE_LIST_UNAVAILABLE: FileListData = { entries: [], complete: false };\n\n/** The slice of pi-tui's AutocompleteProvider this wrapper has to satisfy. */\nexport interface AutocompleteItem {\n value: string;\n label: string;\n description?: string;\n}\n\nexport interface AutocompleteSuggestions {\n items: AutocompleteItem[];\n prefix: string;\n}\n\nexport interface AutocompleteProviderLike {\n triggerCharacters?: string[];\n getSuggestions(\n lines: string[],\n cursorLine: number,\n cursorCol: number,\n options: { signal: AbortSignal; force?: boolean },\n ): Promise<AutocompleteSuggestions | null>;\n applyCompletion(\n lines: string[],\n cursorLine: number,\n cursorCol: number,\n item: AutocompleteItem,\n prefix: string,\n ): { lines: string[]; cursorLine: number; cursorCol: number };\n shouldTriggerFileCompletion?(lines: string[], cursorLine: number, cursorCol: number): boolean;\n}\n\n/** pi-tui's own token delimiters (autocomplete.js): a token starts after one of these. */\nconst PATH_DELIMITERS = new Set([\" \", \"\\t\", '\"', \"'\", \"=\"]);\n/** How many suggestions pi-tui shows for `@`; matching it keeps the list the same size. */\nconst MAX_SUGGESTIONS = 20;\n\nfunction findLastDelimiter(text: string): number {\n for (let i = text.length - 1; i >= 0; i -= 1) {\n if (PATH_DELIMITERS.has(text[i] ?? \"\")) return i;\n }\n return -1;\n}\n\nfunction findUnclosedQuoteStart(text: string): number | null {\n let inQuotes = false;\n let quoteStart = -1;\n for (let i = 0; i < text.length; i += 1) {\n if (text[i] === '\"') {\n inQuotes = !inQuotes;\n if (inQuotes) quoteStart = i;\n }\n }\n return inQuotes ? quoteStart : null;\n}\n\nfunction isTokenStart(text: string, index: number): boolean {\n return index === 0 || PATH_DELIMITERS.has(text[index - 1] ?? \"\");\n}\n\n/** The `@…` token under the cursor, or null when the cursor is not in one. */\nexport function extractAtPrefix(text: string): string | null {\n const quoteStart = findUnclosedQuoteStart(text);\n if (quoteStart !== null) {\n if (quoteStart > 0 && text[quoteStart - 1] === \"@\") {\n return isTokenStart(text, quoteStart - 1) ? text.slice(quoteStart - 1) : null;\n }\n // An unclosed quote that is not an `@` attachment belongs to the base provider.\n return null;\n }\n const lastDelimiterIndex = findLastDelimiter(text);\n const tokenStart = lastDelimiterIndex === -1 ? 0 : lastDelimiterIndex + 1;\n return text[tokenStart] === \"@\" ? text.slice(tokenStart) : null;\n}\n\nfunction buildCompletionValue(path: string, isQuotedPrefix: boolean): string {\n return isQuotedPrefix || path.includes(\" \") ? `@\"${path}\"` : `@${path}`;\n}\n\nfunction basename(path: string): string {\n const trimmed = path.endsWith(\"/\") ? path.slice(0, -1) : path;\n const cut = trimmed.lastIndexOf(\"/\");\n return cut === -1 ? trimmed : trimmed.slice(cut + 1);\n}\n\nexport function podFileSuggestions(prefix: string, listing: FileListData): AutocompleteItem[] {\n const isQuotedPrefix = prefix.startsWith('@\"');\n const rawPrefix = prefix.slice(isQuotedPrefix ? 2 : 1);\n return fuzzyFilter(listing.entries, rawPrefix, (entry) => entry.path)\n .slice(0, MAX_SUGGESTIONS)\n .map((entry) => ({\n value: buildCompletionValue(entry.path, isQuotedPrefix),\n // applyCompletion keys the \"keep completing into this directory\" behaviour off the\n // label's trailing slash, so it has to survive here.\n label: basename(entry.path) + (entry.dir ? \"/\" : \"\"),\n description: entry.path,\n }));\n}\n\n/**\n * Wrap the provider pi built so `@` resolves in the pod. Everything else — slash commands,\n * their argument completions, bare path completion, `applyCompletion` — stays with `base`.\n */\nexport function wrapWithPodFiles(\n base: AutocompleteProviderLike,\n listFiles: (query: string) => Promise<FileListData>,\n): AutocompleteProviderLike {\n return {\n ...(base.triggerCharacters ? { triggerCharacters: base.triggerCharacters } : {}),\n\n async getSuggestions(lines, cursorLine, cursorCol, options) {\n const textBeforeCursor = (lines[cursorLine] ?? \"\").slice(0, cursorCol);\n const prefix = extractAtPrefix(textBeforeCursor);\n if (prefix === null) return base.getSuggestions(lines, cursorLine, cursorCol, options);\n\n const isQuotedPrefix = prefix.startsWith('@\"');\n const listing = await listFiles(prefix.slice(isQuotedPrefix ? 2 : 1));\n if (options.signal.aborted) return null;\n const items = podFileSuggestions(prefix, listing);\n return items.length > 0 ? { items, prefix } : null;\n },\n\n applyCompletion: (lines, cursorLine, cursorCol, item, prefix) =>\n base.applyCompletion(lines, cursorLine, cursorCol, item, prefix),\n\n ...(base.shouldTriggerFileCompletion\n ? {\n shouldTriggerFileCompletion: (lines: string[], cursorLine: number, cursorCol: number) =>\n base.shouldTriggerFileCompletion!(lines, cursorLine, cursorCol),\n }\n : {}),\n };\n}\n","import { randomUUID } from \"node:crypto\";\nimport type { RpcClientBase } from \"../rpc.js\";\nimport {\n AUTH_BRIDGE_COMMAND,\n AUTH_BRIDGE_DIALOG_PREFIX,\n AUTH_BRIDGE_MAX_ENCODED_RESPONSE_BYTES,\n AUTH_BRIDGE_MAX_PROVIDER_ID_LENGTH,\n AUTH_BRIDGE_NOTIFICATION_PREFIX,\n AUTH_BRIDGE_PROTOCOL_VERSION,\n TREE_BRIDGE_MAX_ENCODED_REQUEST_BYTES,\n TREE_BRIDGE_MAX_ID_LENGTH,\n} from \"../../shim/pi-pod-ext.js\";\nimport { decodeWireJson, encodeWireJson, isBoundedString, isPlainObject } from \"../../wire-codec.js\";\n\nexport type RemoteAuthType = \"oauth\" | \"api_key\";\n\nexport interface RemoteAuthPrompt {\n type: \"text\" | \"secret\" | \"manual_code\" | \"select\";\n message: string;\n placeholder?: string;\n options?: Array<{ id: string; label: string; description?: string }>;\n signal?: AbortSignal;\n}\n\nexport type RemoteAuthEvent =\n | { type: \"info\"; message: string; links?: Array<{ url: string; label?: string }> }\n | { type: \"auth_url\"; url: string; instructions?: string }\n | { type: \"device_code\"; userCode: string; verificationUri: string; intervalSeconds?: number; expiresInSeconds?: number }\n | { type: \"progress\"; message: string };\n\nexport interface RemoteAuthInteraction {\n signal?: AbortSignal;\n prompt(prompt: RemoteAuthPrompt): Promise<string>;\n notify(event: RemoteAuthEvent): void;\n}\n\nexport interface RemoteProviderSnapshot {\n id: string;\n name: string;\n auth: {\n apiKey?: { name: string; interactive: boolean };\n oauth?: { name: string; loginLabel?: string };\n };\n status: { configured: boolean; source?: string; label?: string };\n usingOAuth: boolean;\n}\n\nexport interface RemoteAuthSnapshot {\n providers: RemoteProviderSnapshot[];\n credentials: Array<{ providerId: string; type: RemoteAuthType }>;\n}\n\ninterface ExtensionUiRequest {\n type?: unknown;\n id?: unknown;\n method?: unknown;\n title?: unknown;\n message?: unknown;\n}\n\ntype AuthOperation = \"providers\" | \"login\" | \"logout\";\n\ntype AuthRequest =\n | { v: 1; id: string; op: \"providers\" }\n | { v: 1; id: string; op: \"login\"; providerId: string; authType: RemoteAuthType }\n | { v: 1; id: string; op: \"logout\"; providerId: string };\n\ninterface PendingAuthRequest {\n op: AuthOperation;\n interaction?: RemoteAuthInteraction;\n resolve(snapshot: RemoteAuthSnapshot): void;\n reject(error: Error): void;\n cleanup(): void;\n cancelRequestId?: string;\n}\n\nexport interface AuthBridgeOptions {\n getCommands: () => unknown[];\n timeoutMs?: number;\n}\n\nconst AUTH_BRIDGE_TIMEOUT_MS = 15_000;\n\nexport class AuthBridgeError extends Error {\n constructor(message: string, readonly code: string) {\n super(message);\n this.name = \"AuthBridgeError\";\n }\n}\n\nexport function supportsAuthBridge(commands: unknown[]): boolean {\n return commands.some((command) => {\n const candidate = command as { name?: unknown; source?: unknown };\n return candidate.name === AUTH_BRIDGE_COMMAND && candidate.source === \"extension\";\n });\n}\n\n/** Relays Pi's native LoginDialog interaction to the authoritative pod ModelRuntime. */\nexport class AuthBridge {\n private readonly pending = new Map<string, PendingAuthRequest>();\n private disposedError: Error | null = null;\n private readonly unwireLifecycle: () => void;\n private readonly timeoutMs: number;\n snapshot: RemoteAuthSnapshot = { providers: [], credentials: [] };\n\n constructor(\n private readonly rpc: RpcClientBase,\n private readonly options: AuthBridgeOptions,\n ) {\n this.timeoutMs = options.timeoutMs ?? AUTH_BRIDGE_TIMEOUT_MS;\n this.unwireLifecycle = rpc.onLifecycleInvalidated((error) => this.failAll(error));\n }\n\n supportsAuthBridge(commands: unknown[] = this.options.getCommands()): boolean {\n return supportsAuthBridge(commands);\n }\n\n async refresh(): Promise<RemoteAuthSnapshot> {\n if (!this.supportsAuthBridge()) return this.snapshot;\n return this.invoke({ op: \"providers\" });\n }\n\n login(providerId: string, authType: RemoteAuthType, interaction: RemoteAuthInteraction): Promise<RemoteAuthSnapshot> {\n validateProviderId(providerId);\n return this.invoke({ op: \"login\", providerId, authType }, interaction);\n }\n\n logout(providerId: string): Promise<RemoteAuthSnapshot> {\n validateProviderId(providerId);\n return this.invoke({ op: \"logout\", providerId });\n }\n\n /** Consume reserved auth notifications and dialogs before the generic extension UI sees them. */\n consumeExtensionRequest(request: ExtensionUiRequest): boolean {\n if (request.type !== \"extension_ui_request\") return false;\n\n if (request.method === \"notify\" && typeof request.message === \"string\" && request.message.startsWith(AUTH_BRIDGE_NOTIFICATION_PREFIX)) {\n let message: unknown;\n try {\n message = decodeWire(request.message.slice(AUTH_BRIDGE_NOTIFICATION_PREFIX.length));\n this.consumeNotification(message);\n } catch (error) {\n const id = isPlainObject(message) && typeof message.id === \"string\" ? message.id : undefined;\n if (id) this.pending.get(id)?.reject(error instanceof Error ? error : new Error(String(error)));\n // Uncorrelated malformed reserved traffic is consumed rather than shown in the UI.\n }\n return true;\n }\n\n if (typeof request.title !== \"string\" || !request.title.startsWith(AUTH_BRIDGE_DIALOG_PREFIX)) return false;\n const extensionRequestId = typeof request.id === \"string\" ? request.id : \"\";\n try {\n const message = decodeWire(request.title.slice(AUTH_BRIDGE_DIALOG_PREFIX.length));\n this.consumeDialog(extensionRequestId, request.method, message);\n } catch {\n if (extensionRequestId) this.rpc.respondExtensionUi({ type: \"extension_ui_response\", id: extensionRequestId, cancelled: true });\n }\n return true;\n }\n\n dispose(error = new Error(\"auth bridge was disposed\")): void {\n if (this.disposedError) return;\n this.disposedError = error;\n this.unwireLifecycle();\n this.failAll(error);\n }\n\n private consumeNotification(value: unknown): void {\n if (!isPlainObject(value) || value.v !== AUTH_BRIDGE_PROTOCOL_VERSION || !isBoundedString(value.id, TREE_BRIDGE_MAX_ID_LENGTH)) return;\n const waiter = this.pending.get(value.id);\n if (value.kind === \"event\") {\n if (waiter?.interaction && isAuthEvent(value.event)) waiter.interaction.notify(value.event);\n return;\n }\n if (value.kind !== \"response\" || !isAuthOperation(value.op) || typeof value.ok !== \"boolean\") {\n waiter?.reject(new AuthBridgeError(\"invalid auth bridge response\", \"invalid_response\"));\n return;\n }\n if (!waiter) return;\n if (waiter.op !== value.op) {\n waiter.reject(new AuthBridgeError(\"auth bridge response operation did not match its request\", \"invalid_response\"));\n return;\n }\n if (!value.ok) {\n const error = isPlainObject(value.error) ? value.error : {};\n waiter.reject(new AuthBridgeError(typeof error.message === \"string\" ? error.message : \"pod authentication failed\", typeof error.code === \"string\" ? error.code : \"operation_failed\"));\n return;\n }\n const snapshot = validateSnapshot(value.data);\n this.snapshot = snapshot;\n waiter.resolve(snapshot);\n }\n\n private consumeDialog(extensionRequestId: string, method: unknown, value: unknown): void {\n if (!extensionRequestId || !isPlainObject(value) || value.v !== AUTH_BRIDGE_PROTOCOL_VERSION || !isBoundedString(value.id, TREE_BRIDGE_MAX_ID_LENGTH)) {\n if (extensionRequestId) this.rpc.respondExtensionUi({ type: \"extension_ui_response\", id: extensionRequestId, cancelled: true });\n return;\n }\n const waiter = this.pending.get(value.id);\n if (value.kind === \"cancel\" && method === \"confirm\") {\n const signal = waiter?.interaction?.signal;\n if (!waiter || signal?.aborted) {\n this.rpc.respondExtensionUi({ type: \"extension_ui_response\", id: extensionRequestId, confirmed: true });\n } else if (signal) {\n waiter.cancelRequestId = extensionRequestId;\n }\n // With no signal this deliberately stays pending until the login completes pod-side;\n // its AbortController then removes the RPC dialog without requiring a response.\n return;\n }\n if (value.kind !== \"prompt\" || (method !== \"input\" && method !== \"select\") || !waiter?.interaction) {\n this.rpc.respondExtensionUi({ type: \"extension_ui_response\", id: extensionRequestId, cancelled: true });\n return;\n }\n let prompt: RemoteAuthPrompt;\n try {\n prompt = validatePrompt(value.prompt);\n } catch {\n this.rpc.respondExtensionUi({ type: \"extension_ui_response\", id: extensionRequestId, cancelled: true });\n return;\n }\n if (waiter.interaction.signal) prompt.signal = waiter.interaction.signal;\n void waiter.interaction.prompt(prompt).then(\n (answer) => {\n const wireAnswer = answer;\n if (wireAnswer === undefined) this.rpc.respondExtensionUi({ type: \"extension_ui_response\", id: extensionRequestId, cancelled: true });\n else this.rpc.respondExtensionUi({ type: \"extension_ui_response\", id: extensionRequestId, value: wireAnswer });\n },\n () => this.rpc.respondExtensionUi({ type: \"extension_ui_response\", id: extensionRequestId, cancelled: true }),\n );\n }\n\n private invoke(\n request: Omit<Extract<AuthRequest, { op: \"providers\" }>, \"v\" | \"id\"> | Omit<Extract<AuthRequest, { op: \"login\" }>, \"v\" | \"id\"> | Omit<Extract<AuthRequest, { op: \"logout\" }>, \"v\" | \"id\">,\n interaction?: RemoteAuthInteraction,\n ): Promise<RemoteAuthSnapshot> {\n if (this.disposedError) return Promise.reject(this.disposedError);\n if (!this.supportsAuthBridge()) {\n return Promise.reject(new AuthBridgeError(\n \"This running pod uses an older pi pod extension. Exit Pi, then attach again before using /login.\",\n \"auth_bridge_unavailable\",\n ));\n }\n const id = randomUUID();\n const envelope = { v: AUTH_BRIDGE_PROTOCOL_VERSION, id, ...request } as AuthRequest;\n const encoded = encodeWireJson(envelope);\n if (Buffer.byteLength(encoded, \"utf8\") > TREE_BRIDGE_MAX_ENCODED_REQUEST_BYTES) {\n return Promise.reject(new AuthBridgeError(\"auth bridge request exceeded the configured limit\", \"payload_too_large\"));\n }\n\n return new Promise<RemoteAuthSnapshot>((resolve, reject) => {\n let settled = false;\n let timer: NodeJS.Timeout | null = null;\n const onAbort = () => {\n const cancelRequestId = this.pending.get(id)?.cancelRequestId;\n if (cancelRequestId) {\n this.rpc.respondExtensionUi({ type: \"extension_ui_response\", id: cancelRequestId, confirmed: true });\n }\n finish({ error: new AuthBridgeError(\"Login cancelled\", \"cancelled\") });\n };\n const cleanup = () => {\n if (timer) clearTimeout(timer);\n timer = null;\n this.pending.delete(id);\n interaction?.signal?.removeEventListener(\"abort\", onAbort);\n };\n const finish = (outcome: { snapshot: RemoteAuthSnapshot } | { error: Error }) => {\n if (settled) return;\n settled = true;\n cleanup();\n if (\"snapshot\" in outcome) resolve(outcome.snapshot);\n else reject(outcome.error);\n };\n this.pending.set(id, {\n op: request.op,\n interaction,\n resolve: (snapshot) => finish({ snapshot }),\n reject: (error) => finish({ error }),\n cleanup,\n });\n if (interaction?.signal?.aborted) return onAbort();\n interaction?.signal?.addEventListener(\"abort\", onAbort, { once: true });\n if (request.op !== \"login\") {\n timer = setTimeout(() => {\n finish({ error: new AuthBridgeError(`auth bridge ${request.op} timed out after ${this.timeoutMs}ms`, \"timeout\") });\n }, this.timeoutMs);\n }\n this.rpc.prompt(\n `/${AUTH_BRIDGE_COMMAND} ${encoded}`,\n undefined,\n interaction?.signal ? { signal: interaction.signal } : undefined,\n ).catch((error) => {\n finish({ error: error instanceof Error ? error : new Error(String(error)) });\n });\n });\n }\n\n private failAll(error: Error): void {\n for (const waiter of [...this.pending.values()]) waiter.reject(error);\n }\n}\n\nfunction validateProviderId(value: string): void {\n if (!isBoundedString(value, AUTH_BRIDGE_MAX_PROVIDER_ID_LENGTH)) throw new AuthBridgeError(\"invalid provider id\", \"invalid_provider\");\n}\n\nfunction decodeWire(encoded: string): unknown {\n const decoded = decodeWireJson(encoded, AUTH_BRIDGE_MAX_ENCODED_RESPONSE_BYTES);\n if (!decoded.ok) {\n if (decoded.reason === \"non_canonical\") {\n throw new AuthBridgeError(\"non-canonical auth bridge message\", \"invalid_response\");\n }\n if (decoded.reason === \"invalid_utf8_json\") {\n throw new AuthBridgeError(\"invalid auth bridge JSON\", \"invalid_response\");\n }\n throw new AuthBridgeError(\"invalid auth bridge message\", \"invalid_response\");\n }\n return decoded.value;\n}\n\nfunction validateSnapshot(value: unknown): RemoteAuthSnapshot {\n if (!isPlainObject(value) || !Array.isArray(value.providers) || !Array.isArray(value.credentials)) throw new AuthBridgeError(\"invalid provider snapshot\", \"invalid_response\");\n const providers = value.providers.map((candidate) => {\n if (!isPlainObject(candidate) || !isBoundedString(candidate.id, AUTH_BRIDGE_MAX_PROVIDER_ID_LENGTH) || typeof candidate.name !== \"string\" || !isPlainObject(candidate.auth) || !isPlainObject(candidate.status) || typeof candidate.status.configured !== \"boolean\" || typeof candidate.usingOAuth !== \"boolean\") {\n throw new AuthBridgeError(\"invalid provider metadata\", \"invalid_response\");\n }\n const auth: RemoteProviderSnapshot[\"auth\"] = {};\n if (candidate.auth.apiKey !== undefined) {\n if (!isPlainObject(candidate.auth.apiKey) || typeof candidate.auth.apiKey.name !== \"string\" || typeof candidate.auth.apiKey.interactive !== \"boolean\") throw new AuthBridgeError(\"invalid API key metadata\", \"invalid_response\");\n auth.apiKey = { name: candidate.auth.apiKey.name, interactive: candidate.auth.apiKey.interactive };\n }\n if (candidate.auth.oauth !== undefined) {\n if (!isPlainObject(candidate.auth.oauth) || typeof candidate.auth.oauth.name !== \"string\" || (candidate.auth.oauth.loginLabel !== undefined && typeof candidate.auth.oauth.loginLabel !== \"string\")) throw new AuthBridgeError(\"invalid OAuth metadata\", \"invalid_response\");\n auth.oauth = { name: candidate.auth.oauth.name, ...(candidate.auth.oauth.loginLabel ? { loginLabel: candidate.auth.oauth.loginLabel } : {}) };\n }\n return {\n id: candidate.id,\n name: candidate.name,\n auth,\n status: {\n configured: candidate.status.configured,\n ...(typeof candidate.status.source === \"string\" ? { source: candidate.status.source } : {}),\n ...(typeof candidate.status.label === \"string\" ? { label: candidate.status.label } : {}),\n },\n usingOAuth: candidate.usingOAuth,\n };\n });\n const credentials = value.credentials.map((candidate) => {\n if (!isPlainObject(candidate) || !isBoundedString(candidate.providerId, AUTH_BRIDGE_MAX_PROVIDER_ID_LENGTH) || (candidate.type !== \"oauth\" && candidate.type !== \"api_key\")) throw new AuthBridgeError(\"invalid credential metadata\", \"invalid_response\");\n return { providerId: candidate.providerId, type: candidate.type as RemoteAuthType };\n });\n return { providers, credentials };\n}\n\nfunction validatePrompt(value: unknown): RemoteAuthPrompt {\n if (!isPlainObject(value) || ![\"text\", \"secret\", \"manual_code\", \"select\"].includes(String(value.type)) || typeof value.message !== \"string\" || (value.placeholder !== undefined && typeof value.placeholder !== \"string\")) throw new AuthBridgeError(\"invalid auth prompt\", \"invalid_response\");\n const type = value.type as RemoteAuthPrompt[\"type\"];\n if (type === \"select\") {\n if (!Array.isArray(value.options)) throw new AuthBridgeError(\"invalid auth options\", \"invalid_response\");\n const options = value.options.map((option) => {\n if (!isPlainObject(option) || typeof option.id !== \"string\" || typeof option.label !== \"string\" || (option.description !== undefined && typeof option.description !== \"string\")) throw new AuthBridgeError(\"invalid auth option\", \"invalid_response\");\n return { id: option.id, label: option.label, ...(option.description ? { description: option.description } : {}) };\n });\n return { type, message: value.message, options };\n }\n return { type, message: value.message, ...(typeof value.placeholder === \"string\" ? { placeholder: value.placeholder } : {}) };\n}\n\nfunction isAuthEvent(value: unknown): value is RemoteAuthEvent {\n if (!isPlainObject(value) || typeof value.type !== \"string\") return false;\n if (value.type === \"auth_url\") {\n return isSafeAuthUrl(value.url) && (value.instructions === undefined || typeof value.instructions === \"string\");\n }\n if (value.type === \"device_code\") {\n return typeof value.userCode === \"string\" && isSafeAuthUrl(value.verificationUri);\n }\n if (value.type === \"info\") {\n return typeof value.message === \"string\" && (\n value.links === undefined || (\n Array.isArray(value.links) && value.links.every((link) =>\n isPlainObject(link) && isSafeAuthUrl(link.url) && (link.label === undefined || typeof link.label === \"string\"),\n )\n )\n );\n }\n return value.type === \"progress\" && typeof value.message === \"string\";\n}\n\nfunction isSafeAuthUrl(value: unknown): value is string {\n if (typeof value !== \"string\") return false;\n try {\n const url = new URL(value);\n return url.protocol === \"https:\" || (url.protocol === \"http:\" && (url.hostname === \"localhost\" || url.hostname === \"127.0.0.1\" || url.hostname === \"::1\"));\n } catch {\n return false;\n }\n}\n\nfunction isAuthOperation(value: unknown): value is AuthOperation {\n return value === \"providers\" || value === \"login\" || value === \"logout\";\n}\n\n","/**\n * src/wire-codec.ts — one canonical base64url-JSON codec for client-side wire payloads.\n *\n * Several bridges (remote UI, auth bridge, pod-extension bridge) all need the same encode,\n * decode-with-size-cap, and canonical round-trip verification. Keeping one copy means the\n * alphabet, the strictness of the round-trip check, and the UTF-8 JSON parse rules cannot\n * drift between them. Each caller still owns its size cap, domain validation, and how a\n * failure is reported.\n */\n\nexport function encodeWireJson(value: unknown): string {\n return Buffer.from(JSON.stringify(value), \"utf8\").toString(\"base64url\");\n}\n\nexport type DecodeWireJsonFailure =\n | \"empty\"\n | \"oversized\"\n | \"alphabet\"\n | \"non_canonical\"\n | \"invalid_utf8_json\";\n\nexport type DecodeWireJsonResult =\n | { ok: true; value: unknown }\n | { ok: false; reason: DecodeWireJsonFailure };\n\nexport function decodeWireJson(encoded: string, maxBytes: number): DecodeWireJsonResult {\n if (encoded.length === 0) return { ok: false, reason: \"empty\" };\n if (Buffer.byteLength(encoded, \"utf8\") > maxBytes) return { ok: false, reason: \"oversized\" };\n if (!/^[A-Za-z0-9_-]+$/.test(encoded)) return { ok: false, reason: \"alphabet\" };\n const bytes = Buffer.from(encoded, \"base64url\");\n if (bytes.toString(\"base64url\") !== encoded) return { ok: false, reason: \"non_canonical\" };\n try {\n const value = JSON.parse(new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes)) as unknown;\n return { ok: true, value };\n } catch {\n return { ok: false, reason: \"invalid_utf8_json\" };\n }\n}\n\nexport function isBoundedString(value: unknown, max: number): value is string {\n return typeof value === \"string\" && value.length > 0 && value.length <= max;\n}\n\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n","/**\n * src/client/runtime/extension-ui.ts — the extension-UI sub-protocol, client side (§5.3).\n *\n * Extensions run pod-side, inside pi; their UI reaches the user through pi's documented\n * `extension_ui_request` / `extension_ui_response` protocol, arriving here as ordinary E\n * frames. Dialogs render through InteractiveMode's own extension components (captured via\n * `bindExtensions`, see bridge.ts) and answer back over the wire; fire-and-forget methods\n * map straight onto the local surface.\n */\nimport type { RpcClientBase } from \"../rpc.js\";\nimport type { HostBridge } from \"./bridge.js\";\n\ninterface ExtensionUiRequest {\n type: \"extension_ui_request\";\n id: string;\n method: string;\n title?: string;\n message?: string;\n options?: string[];\n placeholder?: string;\n prefill?: string;\n timeout?: number;\n notifyType?: \"info\" | \"warning\" | \"error\";\n statusKey?: string;\n statusText?: string;\n widgetKey?: string;\n widgetLines?: string[];\n widgetPlacement?: \"aboveEditor\" | \"belowEditor\";\n text?: string;\n}\n\n/** Bound in case a wedged pod streams dialog requests during a long startup. */\nconst MAX_PENDING_REQUESTS = 64;\n\nconst DIALOG_METHODS = new Set([\"select\", \"confirm\", \"input\", \"editor\"]);\nconst FIRE_AND_FORGET_METHODS = new Set([\"notify\", \"setStatus\", \"setWidget\", \"setTitle\", \"set_editor_text\"]);\n\n/** A method that blocks the agent until this client answers it (§5.3, §12). */\nfunction isDialogMethod(request: ExtensionUiRequest): boolean {\n return (\n DIALOG_METHODS.has(request.method) ||\n (!FIRE_AND_FORGET_METHODS.has(request.method) && request.timeout === undefined)\n );\n}\n\n/** The local surface went away before the user answered; the pod is still waiting. */\nconst ABANDONED = Symbol(\"abandoned\");\n\ninterface LiveDialog {\n request: ExtensionUiRequest;\n /** Unblocks the `await` on a surface that will never resolve, without answering the pod. */\n abandon: () => void;\n abandoned: boolean;\n}\n\n/** Displayed or already answered, keyed by request id; \"settled\" holds the answered ids. */\ntype DialogEntry = LiveDialog | \"settled\";\n\n/** What a session invalidation does to the dialogs currently on screen. */\nexport type DialogInvalidation =\n /** The transport dropped: the pod still holds these requests, so show them again. */\n | \"redisplay\"\n /** Another session or pod owns them now: nothing will replay them, and nobody may answer. */\n | \"drop\";\n\nexport interface ExtensionUiWiring {\n /** Stop routing; anything still queued is cancelled rather than left hanging. */\n dispose(): void;\n /**\n * InteractiveMode is about to destroy its dialog surfaces (`resetExtensionUI`). Answering\n * for the user would wrongly reject a tool approval nobody saw, so abandon each dialog\n * instead: the pod-side request stays pending, and `redisplay` renders it again on the\n * next UI bind. Must be called synchronously with the reset, before any await, so a\n * surface that resolves on dispose cannot answer on its way out.\n */\n invalidateDialogs(fate: DialogInvalidation): void;\n}\n\n/**\n * Route extension-UI requests into the local TUI.\n *\n * Requests that arrive before InteractiveMode binds its UI context are queued and replayed\n * on bind, so a dialog or notification raised while the TUI is still booting is shown\n * rather than silently declined. Once bound, dialogs whose local surface is missing (a\n * method the context does not offer) are cancelled rather than left hanging — the agent\n * side also auto-resolves on its own timeout, so neither side ever blocks forever (§12).\n *\n * Delivery is not resolution: a blocking dialog stays pending pod-side until its response,\n * so both transports re-deliver it after a reconnect (shim `ui_replay`, gateway attach).\n * The registry below keeps that idempotent — at most one surface and one response per\n * request id, however many copies arrive.\n */\nexport function wireExtensionUi(\n rpc: RpcClientBase,\n bridge: HostBridge,\n intercept?: (request: ExtensionUiRequest) => boolean,\n): ExtensionUiWiring {\n /** Requests held for the TUI; null once the queue has flushed. */\n let pending: ExtensionUiRequest[] | null = [];\n const dialogs = new Map<string, DialogEntry>();\n /** Abandoned dialogs waiting for a UI context to render them onto again. */\n let redisplay: ExtensionUiRequest[] = [];\n\n const remember = (id: string, entry: DialogEntry): void => {\n dialogs.delete(id);\n dialogs.set(id, entry);\n while (dialogs.size > MAX_PENDING_REQUESTS) {\n const oldest = dialogs.keys().next().value;\n if (oldest === undefined) break;\n dialogs.delete(oldest);\n }\n };\n\n const respond = (\n dialog: LiveDialog,\n answer: { value: string } | { confirmed: boolean } | { cancelled: true },\n ): void => {\n if (dialog.abandoned) return;\n remember(dialog.request.id, \"settled\");\n rpc.respondExtensionUi({ type: \"extension_ui_response\", id: dialog.request.id, ...answer });\n };\n\n const dispatch = async (request: ExtensionUiRequest): Promise<void> => {\n if (!isDialogMethod(request)) {\n dispatchFireAndForget(bridge, request);\n return;\n }\n // A second copy of a dialog already on screen (or already answered) is the replay\n // machinery doing its job; rendering it twice would put two surfaces on one request.\n if (dialogs.has(request.id)) return;\n\n const dialog: LiveDialog = { request, abandon: () => {}, abandoned: false };\n const surfaceGone = new Promise<typeof ABANDONED>((resolve) => {\n dialog.abandon = () => {\n dialog.abandoned = true;\n resolve(ABANDONED);\n };\n });\n remember(request.id, dialog);\n // `resetExtensionUI` disposes a dialog component without settling its promise, so the\n // abandon signal — not the surface — is what releases this await.\n const settle = <T>(surface: Promise<T> | undefined): Promise<T | undefined | typeof ABANDONED> =>\n surface === undefined ? Promise.resolve(undefined) : Promise.race([surface, surfaceGone]);\n\n const ui = bridge.ui;\n const cancel = () => respond(dialog, { cancelled: true });\n try {\n switch (request.method) {\n case \"select\": {\n const value = await settle(ui?.select?.(request.title ?? \"\", request.options ?? []));\n if (value === ABANDONED) return;\n if (value === undefined) cancel();\n else respond(dialog, { value });\n return;\n }\n case \"confirm\": {\n if (!ui?.confirm) return cancel();\n const confirmed = await settle(ui.confirm(request.title ?? \"\", request.message ?? \"\"));\n if (confirmed === ABANDONED) return;\n respond(dialog, { confirmed: confirmed ?? false });\n return;\n }\n case \"input\": {\n const value = await settle(ui?.input?.(request.title ?? \"\", request.placeholder));\n if (value === ABANDONED) return;\n if (value === undefined) cancel();\n else respond(dialog, { value });\n return;\n }\n case \"editor\": {\n const value = await settle(ui?.editor?.(request.title ?? \"\", request.prefill));\n if (value === ABANDONED) return;\n if (value === undefined) cancel();\n else respond(dialog, { value });\n return;\n }\n default:\n // A blocking method this client does not know. It must not hang the agent.\n cancel();\n return;\n }\n } catch {\n cancel();\n }\n };\n\n /** Cancel a request that will never render — but never answer a fire-and-forget. */\n const cancelUnrenderable = (request: ExtensionUiRequest): void => {\n if (!isDialogMethod(request) || dialogs.has(request.id)) return;\n remember(request.id, \"settled\");\n rpc.respondExtensionUi({ type: \"extension_ui_response\", id: request.id, cancelled: true });\n };\n\n bridge.onUiBound(() => {\n const queued = pending ?? [];\n pending = null;\n for (const request of queued) void dispatch(request);\n });\n // Every bind, not just the first: a reconnect rebinds the session, and that is exactly\n // when the dialogs abandoned above need a surface again.\n const unbind = bridge.onEveryUiBound(() => {\n const again = redisplay;\n redisplay = [];\n for (const request of again) void dispatch(request);\n });\n const off = rpc.onEvent((event) => {\n const request = event as unknown as ExtensionUiRequest;\n if (request.type !== \"extension_ui_request\") return;\n if (intercept?.(request)) return;\n if (pending !== null) {\n if (pending.length < MAX_PENDING_REQUESTS) pending.push(request);\n else cancelUnrenderable(request);\n return;\n }\n void dispatch(request);\n });\n\n return {\n dispose: () => {\n const queued = pending ?? [];\n pending = null;\n redisplay = [];\n for (const request of queued) cancelUnrenderable(request);\n unbind();\n off();\n },\n invalidateDialogs: (fate) => {\n for (const [id, entry] of dialogs) {\n if (entry === \"settled\") continue;\n dialogs.delete(id);\n entry.abandon();\n if (fate === \"redisplay\") redisplay.push(entry.request);\n }\n if (fate === \"drop\") {\n // Ids of a session this client is leaving; keeping them could only shadow a later one.\n dialogs.clear();\n redisplay = [];\n }\n },\n };\n}\n\nfunction dispatchFireAndForget(bridge: HostBridge, request: ExtensionUiRequest): void {\n const ui = bridge.ui;\n switch (request.method) {\n case \"notify\":\n ui?.notify?.(request.message ?? \"\", request.notifyType ?? \"info\");\n return;\n case \"setStatus\":\n ui?.setStatus?.(request.statusKey ?? \"\", request.statusText);\n return;\n case \"setWidget\":\n // String lines only (§5.3): component factories cannot cross the wire.\n ui?.setWidget?.(\n request.widgetKey ?? \"\",\n request.widgetLines,\n request.widgetPlacement ? { placement: request.widgetPlacement } : undefined,\n );\n return;\n case \"setTitle\":\n ui?.setTitle?.(request.title ?? \"\");\n return;\n case \"set_editor_text\":\n ui?.setEditorText?.(request.text ?? \"\");\n return;\n default:\n // A method this client does not know, carrying a timeout: the agent side resolves it.\n return;\n }\n}\n","import { randomUUID } from \"node:crypto\";\nimport { gunzipSync } from \"node:zlib\";\nimport type { SessionEntry } from \"@earendil-works/pi-coding-agent\";\nimport type { RpcClientBase } from \"../rpc.js\";\nimport {\n SEED_BRIDGE_MAX_ENCODED_RESPONSE_BYTES,\n SEED_BRIDGE_NOTIFICATION_PREFIX,\n SEED_BRIDGE_PROTOCOL_VERSION,\n SEED_CHUNK_CONTEXT_COMMAND,\n SEED_CHUNK_MAX_CHUNKS,\n SEED_CHUNK_MAX_JSON_BYTES,\n SEED_CHUNK_MAX_PART_CHARS,\n SEED_CHUNK_NOTIFICATION_PREFIX,\n SEED_CHUNK_TREE_SUMMARY_COMMAND,\n SEED_CONTEXT_COMMAND,\n SEED_TREE_SUMMARY_COMMAND,\n TREE_BRIDGE_LABEL_COMMAND,\n TREE_BRIDGE_MAX_ENCODED_REQUEST_BYTES,\n TREE_BRIDGE_MAX_ENCODED_RESPONSE_BYTES,\n TREE_BRIDGE_MAX_ENTRY_ID_LENGTH,\n TREE_BRIDGE_MAX_ID_LENGTH,\n TREE_BRIDGE_MAX_LABEL_LENGTH,\n TREE_BRIDGE_NAVIGATE_COMMAND,\n TREE_BRIDGE_NAVIGATE_V2_COMMAND,\n TREE_BRIDGE_NOTIFICATION_PREFIX,\n TREE_BRIDGE_PROTOCOL_VERSION,\n} from \"../../shim/pi-pod-ext.js\";\nimport { decodeWireJson, encodeWireJson, isBoundedString, isPlainObject } from \"../../wire-codec.js\";\n\nexport const TREE_BRIDGE_TIMEOUT_MS = 15_000;\nexport const SEED_BRIDGE_TIMEOUT_MS = 60_000;\n\nexport type TreeBridgeOperation = \"navigate\" | \"label\";\n\nexport type TreeBridgeRequest =\n | { v: 1; id: string; op: \"navigate\"; targetId: string }\n | { v: 1; id: string; op: \"label\"; entryId: string; label: string | null };\n\nexport type TreeBridgeSuccess = {\n v: 1;\n id: string;\n op: TreeBridgeOperation;\n ok: true;\n data: { cancelled?: boolean; leafId: string | null; editorText?: string };\n};\n\nexport type TreeBridgeFailure = {\n v: 1;\n id: string;\n op: TreeBridgeOperation;\n ok: false;\n error: { code: string; message: string };\n};\n\nexport type TreeBridgeResponse = TreeBridgeSuccess | TreeBridgeFailure;\n\ninterface PendingAcknowledgement {\n op: TreeBridgeOperation;\n accept(response: TreeBridgeResponse): void;\n fail(error: Error, ambiguous?: boolean): void;\n}\n\nexport interface PodExtensionBridgeOptions {\n getCommands: () => unknown[];\n timeoutMs?: number;\n seedTimeoutMs?: number;\n onAmbiguousFailure?: () => void | Promise<void>;\n}\n\nexport class PodExtensionBridgeError extends Error {\n constructor(\n message: string,\n readonly code: string,\n ) {\n super(message);\n this.name = \"PodExtensionBridgeError\";\n }\n}\n\nfunction extensionCommandNames(commands: unknown[]): Set<string> {\n return new Set(\n commands.flatMap((command) => {\n const candidate = command as { name?: unknown; source?: unknown };\n return typeof candidate.name === \"string\" && candidate.source === \"extension\" ? [candidate.name] : [];\n }),\n );\n}\n\nexport function supportsNavigateEditorText(commands: unknown[]): boolean {\n return extensionCommandNames(commands).has(TREE_BRIDGE_NAVIGATE_V2_COMMAND);\n}\n\nexport function supportsTreeBridge(commands: unknown[]): boolean {\n const names = extensionCommandNames(commands);\n return names.has(TREE_BRIDGE_NAVIGATE_COMMAND) && names.has(TREE_BRIDGE_LABEL_COMMAND);\n}\n\nexport function supportsSeedBridge(commands: unknown[]): boolean {\n const names = extensionCommandNames(commands);\n return names.has(SEED_CONTEXT_COMMAND) && names.has(SEED_TREE_SUMMARY_COMMAND);\n}\n\nexport function supportsSeedBridgeChunks(commands: unknown[]): boolean {\n const names = extensionCommandNames(commands);\n return names.has(SEED_CHUNK_CONTEXT_COMMAND) && names.has(SEED_CHUNK_TREE_SUMMARY_COMMAND);\n}\n\nexport type SeedBridgeOperation = \"get-context\" | \"get-tree-summary\";\n\nexport type SeedContextData = {\n entries: SessionEntry[];\n leafId: string | null;\n compactionCount: number;\n};\n\nexport type SeedTreeSummaryNode = {\n id: string;\n parentId: string | null;\n type: string;\n timestamp: string;\n preview: string;\n role?: string | null;\n label?: string;\n labelTimestamp?: string;\n customType?: string;\n tokensBefore?: number;\n modelId?: string;\n thinkingLevel?: string;\n name?: string;\n toolName?: string;\n};\n\nexport type SeedTreeSummaryData = {\n leafId: string | null;\n nodes: SeedTreeSummaryNode[];\n};\n\nexport interface SessionSeedBridge {\n supportsSeedBridge(commands?: unknown[]): boolean;\n getContext(): Promise<SeedContextData>;\n getTreeSummary(): Promise<SeedTreeSummaryData>;\n}\n\ntype SeedBridgeSuccess<T> = { v: 1; id: string; op: SeedBridgeOperation; ok: true; data: T };\ntype SeedBridgeFailure = { v: 1; id: string; op: SeedBridgeOperation; ok: false; error: { code: string; message: string } };\ntype SeedBridgeResponse<T> = SeedBridgeSuccess<T> | SeedBridgeFailure;\n\ninterface PendingSeedAcknowledgement {\n op: SeedBridgeOperation;\n chunked: boolean;\n previousSeq: number;\n total: number | null;\n encoding: \"gz\" | \"raw\" | null;\n parts: string[];\n encodedLength: number;\n resetTimeout(): void;\n accept(response: SeedBridgeResponse<unknown>): void;\n fail(error: Error, ambiguous?: boolean): void;\n}\n\nexport class PodExtensionBridge implements SessionSeedBridge {\n private readonly pending = new Map<string, PendingAcknowledgement>();\n private readonly pendingSeed = new Map<string, PendingSeedAcknowledgement>();\n private readonly timeoutMs: number;\n private readonly seedTimeoutMs: number;\n private mutationTail: Promise<void> = Promise.resolve();\n private disposedError: Error | null = null;\n private readonly unwireLifecycle: () => void;\n\n constructor(\n private readonly rpc: RpcClientBase,\n private readonly options: PodExtensionBridgeOptions,\n ) {\n this.timeoutMs = options.timeoutMs ?? TREE_BRIDGE_TIMEOUT_MS;\n this.seedTimeoutMs = options.seedTimeoutMs ?? SEED_BRIDGE_TIMEOUT_MS;\n this.unwireLifecycle = rpc.onLifecycleInvalidated((error) => {\n for (const waiter of [...this.pending.values()]) waiter.fail(error, true);\n for (const waiter of [...this.pendingSeed.values()]) waiter.fail(error, true);\n });\n }\n\n supportsTreeBridge(commands: unknown[] = this.options.getCommands()): boolean {\n return supportsTreeBridge(commands);\n }\n\n supportsSeedBridge(commands: unknown[] = this.options.getCommands()): boolean {\n return supportsSeedBridge(commands);\n }\n\n supportsSeedBridgeChunks(commands: unknown[] = this.options.getCommands()): boolean {\n return supportsSeedBridgeChunks(commands);\n }\n\n supportsNavigateEditorText(commands: unknown[] = this.options.getCommands()): boolean {\n return supportsNavigateEditorText(commands);\n }\n\n consumeExtensionNotification(request: unknown): boolean {\n const event = request as { type?: unknown; method?: unknown; message?: unknown };\n if (event.type !== \"extension_ui_request\" || typeof event.message !== \"string\") return false;\n if (event.message.startsWith(SEED_CHUNK_NOTIFICATION_PREFIX)) {\n this.consumeSeedChunkNotification(event.method, event.message.slice(SEED_CHUNK_NOTIFICATION_PREFIX.length));\n return true;\n }\n if (event.message.startsWith(SEED_BRIDGE_NOTIFICATION_PREFIX)) {\n this.consumeSeedNotification(event.method, event.message.slice(SEED_BRIDGE_NOTIFICATION_PREFIX.length));\n return true;\n }\n if (!event.message.startsWith(TREE_BRIDGE_NOTIFICATION_PREFIX)) return false;\n\n const encoded = event.message.slice(TREE_BRIDGE_NOTIFICATION_PREFIX.length);\n let candidate: unknown;\n try {\n candidate = decodeResponse(encoded);\n if (event.method !== \"notify\") {\n throw new PodExtensionBridgeError(\"reserved tree bridge traffic used an invalid UI method\", \"invalid_response\");\n }\n const response = validateResponse(candidate);\n const waiter = this.pending.get(response.id);\n if (!waiter) return true;\n if (response.op !== waiter.op) {\n waiter.fail(new PodExtensionBridgeError(\"tree bridge response operation did not match its request\", \"invalid_response\"));\n } else {\n waiter.accept(response);\n }\n } catch (error) {\n const id = extractCandidateId(candidate);\n if (id) {\n this.pending.get(id)?.fail(\n error instanceof Error ? error : new PodExtensionBridgeError(String(error), \"invalid_response\"),\n );\n }\n }\n return true;\n }\n\n navigate(targetId: string): Promise<{ cancelled: boolean; leafId: string | null; editorText?: string }> {\n if (!isBoundedString(targetId, TREE_BRIDGE_MAX_ENTRY_ID_LENGTH)) {\n return Promise.reject(new PodExtensionBridgeError(\"invalid tree navigation target\", \"invalid_target\"));\n }\n return this.serialize(async () => {\n const result = await this.invoke({ op: \"navigate\", targetId });\n return {\n cancelled: result.cancelled === true,\n leafId: result.leafId,\n ...(typeof result.editorText === \"string\" ? { editorText: result.editorText } : {}),\n };\n });\n }\n\n setLabel(entryId: string, label: string | null): Promise<{ leafId: string | null }> {\n if (!isBoundedString(entryId, TREE_BRIDGE_MAX_ENTRY_ID_LENGTH)) {\n return Promise.reject(new PodExtensionBridgeError(\"invalid tree label entry\", \"invalid_entry\"));\n }\n if (label !== null && (typeof label !== \"string\" || label.length > TREE_BRIDGE_MAX_LABEL_LENGTH)) {\n return Promise.reject(new PodExtensionBridgeError(\"tree label exceeds the configured limit\", \"invalid_label\"));\n }\n return this.serialize(async () => {\n const result = await this.invoke({ op: \"label\", entryId, label });\n return { leafId: result.leafId };\n });\n }\n\n getContext(): Promise<SeedContextData> {\n return this.invokeSeed(\"get-context\");\n }\n\n getTreeSummary(): Promise<SeedTreeSummaryData> {\n return this.invokeSeed(\"get-tree-summary\");\n }\n\n dispose(error = new Error(\"tree bridge was disposed\")): void {\n if (this.disposedError) return;\n this.disposedError = error;\n this.unwireLifecycle();\n for (const waiter of [...this.pending.values()]) waiter.fail(error);\n for (const waiter of [...this.pendingSeed.values()]) waiter.fail(error);\n this.pending.clear();\n this.pendingSeed.clear();\n }\n\n private consumeSeedNotification(method: unknown, encoded: string): void {\n let candidate: unknown;\n try {\n candidate = decodeSeedResponse(encoded);\n if (method !== \"notify\") {\n throw new PodExtensionBridgeError(\"reserved seed bridge traffic used an invalid UI method\", \"invalid_response\");\n }\n const response = validateSeedResponse(candidate);\n const waiter = this.pendingSeed.get(response.id);\n if (!waiter) return;\n if (waiter.chunked) {\n waiter.fail(new PodExtensionBridgeError(\"seed bridge returned a single-shot response for a chunked request\", \"invalid_response\"));\n } else if (response.op !== waiter.op) {\n waiter.fail(new PodExtensionBridgeError(\"seed bridge response operation did not match its request\", \"invalid_response\"));\n } else {\n waiter.accept(response);\n }\n } catch (error) {\n const id = extractCandidateId(candidate);\n if (id) {\n this.pendingSeed.get(id)?.fail(\n error instanceof Error ? error : new PodExtensionBridgeError(String(error), \"invalid_response\"),\n );\n }\n }\n }\n\n private consumeSeedChunkNotification(method: unknown, payload: string): void {\n const fields = payload.split(\" \");\n const id = fields[0];\n if (!isBoundedString(id, TREE_BRIDGE_MAX_ID_LENGTH)) return;\n const waiter = this.pendingSeed.get(id);\n if (!waiter) return;\n\n try {\n if (fields.length !== 5) {\n throw new PodExtensionBridgeError(\"invalid seed chunk header\", \"invalid_response\");\n }\n if (method !== \"notify\") {\n throw new PodExtensionBridgeError(\"reserved seed chunk traffic used an invalid UI method\", \"invalid_response\");\n }\n if (!waiter.chunked) {\n throw new PodExtensionBridgeError(\"seed bridge returned chunks for a single-shot request\", \"invalid_response\");\n }\n\n const [, seqText, totalText, encoding, part] = fields;\n if (!/^[0-9]{1,7}$/.test(seqText!) || !/^[0-9]{1,7}$/.test(totalText!)) {\n throw new PodExtensionBridgeError(\"invalid seed chunk sequence\", \"invalid_response\");\n }\n const seq = Number(seqText);\n const total = Number(totalText);\n if (seq < 1 || seq > total || total > SEED_CHUNK_MAX_CHUNKS || seq !== waiter.previousSeq + 1) {\n throw new PodExtensionBridgeError(\"invalid seed chunk sequence\", \"invalid_response\");\n }\n if (encoding !== \"gz\" && encoding !== \"raw\") {\n throw new PodExtensionBridgeError(\"invalid seed chunk encoding\", \"invalid_response\");\n }\n if (waiter.total !== null && waiter.total !== total) {\n throw new PodExtensionBridgeError(\"seed chunk total changed during response\", \"invalid_response\");\n }\n if (waiter.encoding !== null && waiter.encoding !== encoding) {\n throw new PodExtensionBridgeError(\"seed chunk encoding changed during response\", \"invalid_response\");\n }\n if (!part || part.length > SEED_CHUNK_MAX_PART_CHARS || !/^[A-Za-z0-9_-]+$/.test(part)) {\n throw new PodExtensionBridgeError(\"invalid seed chunk payload\", \"invalid_response\");\n }\n const encodedLength = waiter.encodedLength + part.length;\n if (encodedLength > SEED_BRIDGE_MAX_ENCODED_RESPONSE_BYTES) {\n throw new PodExtensionBridgeError(\"seed chunk response exceeded the configured limit\", \"invalid_response\");\n }\n\n waiter.previousSeq = seq;\n waiter.total = total;\n waiter.encoding = encoding;\n waiter.parts.push(part);\n waiter.encodedLength = encodedLength;\n waiter.resetTimeout();\n\n if (seq !== total) return;\n const candidate = decodeSeedChunkResponse(waiter.parts.join(\"\"), encoding);\n const response = validateSeedResponse(candidate);\n if (response.id !== id) {\n throw new PodExtensionBridgeError(\"seed chunk response id did not match its request\", \"invalid_response\");\n }\n if (response.op !== waiter.op) {\n throw new PodExtensionBridgeError(\"seed bridge response operation did not match its request\", \"invalid_response\");\n }\n waiter.accept(response);\n } catch (error) {\n waiter.fail(error instanceof Error ? error : new PodExtensionBridgeError(String(error), \"invalid_response\"));\n }\n }\n\n private invokeSeed<T>(op: SeedBridgeOperation): Promise<T> {\n if (this.disposedError) return Promise.reject(this.disposedError);\n const commands = this.options.getCommands();\n const chunked = this.supportsSeedBridgeChunks(commands);\n if (!chunked && !this.supportsSeedBridge(commands)) {\n return Promise.reject(\n new PodExtensionBridgeError(\n \"This running pod uses an older pi pod extension. Exit Pi, then attach again so pi pod can load the updated extension.\",\n \"seed_bridge_unavailable\",\n ),\n );\n }\n const id = randomUUID();\n if (!isBoundedString(id, TREE_BRIDGE_MAX_ID_LENGTH)) {\n return Promise.reject(new PodExtensionBridgeError(\"failed to generate a valid seed bridge request id\", \"invalid_id\"));\n }\n const encoded = encodeWireJson({ v: SEED_BRIDGE_PROTOCOL_VERSION, id, op });\n if (Buffer.byteLength(encoded, \"utf8\") > TREE_BRIDGE_MAX_ENCODED_REQUEST_BYTES) {\n return Promise.reject(new PodExtensionBridgeError(\"seed bridge request exceeded the configured limit\", \"payload_too_large\"));\n }\n const command = chunked\n ? op === \"get-context\"\n ? SEED_CHUNK_CONTEXT_COMMAND\n : SEED_CHUNK_TREE_SUMMARY_COMMAND\n : op === \"get-context\"\n ? SEED_CONTEXT_COMMAND\n : SEED_TREE_SUMMARY_COMMAND;\n return new Promise<T>((resolve, reject) => {\n const abortController = new AbortController();\n let timer: NodeJS.Timeout | null = null;\n let settled = false;\n let promptDone = false;\n let acknowledgement: T | null = null;\n const cleanup = () => {\n if (timer) clearTimeout(timer);\n timer = null;\n this.pendingSeed.delete(id);\n };\n const fail = (error: Error) => {\n if (settled) return;\n settled = true;\n cleanup();\n abortController.abort(error);\n reject(error);\n };\n const timeoutMessage = chunked\n ? `seed bridge ${op} acknowledgement timed out after ${this.seedTimeoutMs}ms`\n : `seed bridge ${op} acknowledgement timed out after ${this.seedTimeoutMs}ms; the pod is running an older pi pod extension that cannot deliver large sessions — exit Pi in the pod (or run pipod stop <id>) and attach again to load the updated extension`;\n const resetTimeout = () => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n fail(new PodExtensionBridgeError(timeoutMessage, \"timeout\"));\n }, this.seedTimeoutMs);\n };\n const maybeResolve = () => {\n if (settled || !promptDone || acknowledgement === null) return;\n settled = true;\n cleanup();\n resolve(acknowledgement);\n };\n this.pendingSeed.set(id, {\n op,\n chunked,\n previousSeq: 0,\n total: null,\n encoding: null,\n parts: [],\n encodedLength: 0,\n resetTimeout,\n accept: (response) => {\n if (response.ok === false) {\n fail(new PodExtensionBridgeError(response.error.message, response.error.code));\n return;\n }\n acknowledgement = response.data as T;\n maybeResolve();\n },\n fail: (error) => fail(error),\n });\n resetTimeout();\n this.rpc\n .prompt(`/${command} ${encoded}`, undefined, { signal: abortController.signal })\n .then(() => {\n promptDone = true;\n maybeResolve();\n })\n .catch((error) => {\n fail(error instanceof Error ? error : new Error(String(error)));\n });\n });\n }\n\n private serialize<T>(run: () => Promise<T>): Promise<T> {\n const result = this.mutationTail.then(run, run);\n this.mutationTail = result.then(\n () => undefined,\n () => undefined,\n );\n return result;\n }\n\n private invoke(request: Omit<Extract<TreeBridgeRequest, { op: \"navigate\" }>, \"v\" | \"id\"> | Omit<Extract<TreeBridgeRequest, { op: \"label\" }>, \"v\" | \"id\">): Promise<TreeBridgeSuccess[\"data\"]> {\n if (this.disposedError) return Promise.reject(this.disposedError);\n if (!this.supportsTreeBridge()) {\n return Promise.reject(\n new PodExtensionBridgeError(\n \"This running pod uses an older pi pod extension. Exit Pi, then attach again so pi pod can load the updated extension.\",\n \"tree_bridge_unavailable\",\n ),\n );\n }\n\n const id = randomUUID();\n if (!isBoundedString(id, TREE_BRIDGE_MAX_ID_LENGTH)) {\n return Promise.reject(new PodExtensionBridgeError(\"failed to generate a valid tree bridge request id\", \"invalid_id\"));\n }\n const envelope = { v: TREE_BRIDGE_PROTOCOL_VERSION, id, ...request } as TreeBridgeRequest;\n const encoded = encodeWireJson(envelope);\n if (Buffer.byteLength(encoded, \"utf8\") > TREE_BRIDGE_MAX_ENCODED_REQUEST_BYTES) {\n return Promise.reject(new PodExtensionBridgeError(\"tree bridge request exceeded the configured limit\", \"payload_too_large\"));\n }\n const command =\n request.op === \"navigate\"\n ? this.supportsNavigateEditorText()\n ? TREE_BRIDGE_NAVIGATE_V2_COMMAND\n : TREE_BRIDGE_NAVIGATE_COMMAND\n : TREE_BRIDGE_LABEL_COMMAND;\n\n return new Promise<TreeBridgeSuccess[\"data\"]>((resolve, reject) => {\n const abortController = new AbortController();\n let timer: NodeJS.Timeout | null = null;\n let settled = false;\n let promptDone = false;\n let acknowledgement: TreeBridgeSuccess[\"data\"] | null = null;\n\n const cleanup = () => {\n if (timer) clearTimeout(timer);\n timer = null;\n this.pending.delete(id);\n };\n const recover = () => {\n try {\n void Promise.resolve(this.options.onAmbiguousFailure?.()).catch(() => {});\n } catch {\n // Recovery is deliberately best effort; preserve the original failure.\n }\n };\n const fail = (error: Error, ambiguous: boolean) => {\n if (settled) return;\n settled = true;\n cleanup();\n abortController.abort(error);\n if (ambiguous) recover();\n reject(error);\n };\n const maybeResolve = () => {\n if (settled || !promptDone || !acknowledgement) return;\n settled = true;\n cleanup();\n resolve(acknowledgement);\n };\n\n this.pending.set(id, {\n op: request.op,\n accept: (response) => {\n if (response.ok === false) {\n fail(new PodExtensionBridgeError(response.error.message, response.error.code), false);\n return;\n }\n acknowledgement = response.data;\n maybeResolve();\n },\n fail: (error, ambiguous = false) => fail(error, ambiguous),\n });\n\n timer = setTimeout(() => {\n fail(\n new PodExtensionBridgeError(\n `tree bridge ${request.op} acknowledgement timed out after ${this.timeoutMs}ms; the final pod state is uncertain`,\n \"timeout\",\n ),\n true,\n );\n }, this.timeoutMs);\n\n this.rpc\n .prompt(`/${command} ${encoded}`, undefined, { signal: abortController.signal })\n .then(() => {\n promptDone = true;\n maybeResolve();\n })\n .catch((error) => {\n fail(error instanceof Error ? error : new Error(String(error)), true);\n });\n });\n }\n}\n\nfunction hasExactKeys(value: Record<string, unknown>, expected: string[]): boolean {\n const actual = Object.keys(value).sort();\n const wanted = [...expected].sort();\n return actual.length === wanted.length && actual.every((key, index) => key === wanted[index]);\n}\n\nfunction decodeResponse(encoded: string): unknown {\n const decoded = decodeWireJson(encoded, TREE_BRIDGE_MAX_ENCODED_RESPONSE_BYTES);\n if (!decoded.ok) {\n if (decoded.reason === \"non_canonical\") {\n throw new PodExtensionBridgeError(\"tree bridge response is not canonical base64url\", \"invalid_response\");\n }\n if (decoded.reason === \"invalid_utf8_json\") {\n throw new PodExtensionBridgeError(\"tree bridge response is not valid UTF-8 JSON\", \"invalid_response\");\n }\n throw new PodExtensionBridgeError(\"invalid or oversized tree bridge response\", \"invalid_response\");\n }\n return decoded.value;\n}\n\nfunction validateResponse(value: unknown): TreeBridgeResponse {\n if (!isPlainObject(value)) throw new PodExtensionBridgeError(\"tree bridge response must be an object\", \"invalid_response\");\n if (value.v !== TREE_BRIDGE_PROTOCOL_VERSION) {\n throw new PodExtensionBridgeError(\"unsupported tree bridge response version\", \"invalid_response\");\n }\n if (!isBoundedString(value.id, TREE_BRIDGE_MAX_ID_LENGTH)) {\n throw new PodExtensionBridgeError(\"invalid tree bridge response id\", \"invalid_response\");\n }\n if (value.op !== \"navigate\" && value.op !== \"label\") {\n throw new PodExtensionBridgeError(\"invalid tree bridge response operation\", \"invalid_response\");\n }\n\n if (value.ok === true) {\n if (!hasExactKeys(value, [\"v\", \"id\", \"op\", \"ok\", \"data\"]) || !isPlainObject(value.data)) {\n throw new PodExtensionBridgeError(\"invalid tree bridge success response\", \"invalid_response\");\n }\n const data = value.data;\n const validKeys =\n hasExactKeys(data, [\"leafId\"]) ||\n (value.op === \"navigate\" &&\n (hasExactKeys(data, [\"cancelled\", \"leafId\"]) || hasExactKeys(data, [\"cancelled\", \"leafId\", \"editorText\"])));\n if (!validKeys) {\n throw new PodExtensionBridgeError(\"invalid tree bridge success data\", \"invalid_response\");\n }\n if (data.editorText !== undefined && typeof data.editorText !== \"string\") {\n throw new PodExtensionBridgeError(\"invalid tree bridge editor text\", \"invalid_response\");\n }\n if (data.leafId !== null && !isBoundedString(data.leafId, TREE_BRIDGE_MAX_ENTRY_ID_LENGTH)) {\n throw new PodExtensionBridgeError(\"invalid tree bridge response leaf\", \"invalid_response\");\n }\n if (value.op === \"navigate\" && data.cancelled !== undefined && typeof data.cancelled !== \"boolean\") {\n throw new PodExtensionBridgeError(\"invalid tree bridge cancellation result\", \"invalid_response\");\n }\n return value as unknown as TreeBridgeSuccess;\n }\n\n if (value.ok === false) {\n if (!hasExactKeys(value, [\"v\", \"id\", \"op\", \"ok\", \"error\"]) || !isPlainObject(value.error)) {\n throw new PodExtensionBridgeError(\"invalid tree bridge failure response\", \"invalid_response\");\n }\n if (\n !hasExactKeys(value.error, [\"code\", \"message\"]) ||\n !isBoundedString(value.error.code, 128) ||\n !isBoundedString(value.error.message, 1024)\n ) {\n throw new PodExtensionBridgeError(\"invalid tree bridge remote error\", \"invalid_response\");\n }\n return value as unknown as TreeBridgeFailure;\n }\n\n throw new PodExtensionBridgeError(\"tree bridge response lacks a boolean result\", \"invalid_response\");\n}\n\nfunction extractCandidateId(value: unknown): string | null {\n if (!isPlainObject(value)) return null;\n return isBoundedString(value.id, TREE_BRIDGE_MAX_ID_LENGTH) ? value.id : null;\n}\n\n\nfunction decodeSeedResponse(encoded: string): unknown {\n const decoded = decodeWireJson(encoded, SEED_BRIDGE_MAX_ENCODED_RESPONSE_BYTES);\n if (!decoded.ok) {\n if (decoded.reason === \"non_canonical\") {\n throw new PodExtensionBridgeError(\"seed bridge response is not canonical base64url\", \"invalid_response\");\n }\n if (decoded.reason === \"invalid_utf8_json\") {\n throw new PodExtensionBridgeError(\"seed bridge response is not valid UTF-8 JSON\", \"invalid_response\");\n }\n throw new PodExtensionBridgeError(\"invalid or oversized seed bridge response\", \"invalid_response\");\n }\n return decoded.value;\n}\n\nfunction decodeSeedChunkResponse(encoded: string, encoding: \"gz\" | \"raw\"): unknown {\n const bytes = Buffer.from(encoded, \"base64url\");\n if (bytes.toString(\"base64url\") !== encoded) {\n throw new PodExtensionBridgeError(\"seed chunk response is not canonical base64url\", \"invalid_response\");\n }\n try {\n const jsonBytes =\n encoding === \"gz\" ? gunzipSync(bytes, { maxOutputLength: SEED_CHUNK_MAX_JSON_BYTES }) : bytes;\n const json = new TextDecoder(\"utf-8\", { fatal: true }).decode(jsonBytes);\n return JSON.parse(json) as unknown;\n } catch {\n throw new PodExtensionBridgeError(\"seed chunk response is not valid compressed UTF-8 JSON\", \"invalid_response\");\n }\n}\n\nfunction validateSeedResponse(value: unknown): SeedBridgeResponse<unknown> {\n if (!isPlainObject(value)) throw new PodExtensionBridgeError(\"seed bridge response must be an object\", \"invalid_response\");\n if (value.v !== SEED_BRIDGE_PROTOCOL_VERSION) {\n throw new PodExtensionBridgeError(\"unsupported seed bridge response version\", \"invalid_response\");\n }\n if (!isBoundedString(value.id, TREE_BRIDGE_MAX_ID_LENGTH)) {\n throw new PodExtensionBridgeError(\"invalid seed bridge response id\", \"invalid_response\");\n }\n if (value.op !== \"get-context\" && value.op !== \"get-tree-summary\") {\n throw new PodExtensionBridgeError(\"invalid seed bridge response operation\", \"invalid_response\");\n }\n if (value.ok === true) {\n if (!hasExactKeys(value, [\"v\", \"id\", \"op\", \"ok\", \"data\"]) || !isPlainObject(value.data)) {\n throw new PodExtensionBridgeError(\"invalid seed bridge success response\", \"invalid_response\");\n }\n if (value.op === \"get-context\") validateSeedContextData(value.data);\n else validateSeedTreeSummaryData(value.data);\n return value as unknown as SeedBridgeSuccess<unknown>;\n }\n if (value.ok === false) {\n if (!hasExactKeys(value, [\"v\", \"id\", \"op\", \"ok\", \"error\"]) || !isPlainObject(value.error)) {\n throw new PodExtensionBridgeError(\"invalid seed bridge failure response\", \"invalid_response\");\n }\n if (\n !hasExactKeys(value.error, [\"code\", \"message\"]) ||\n !isBoundedString(value.error.code, 128) ||\n !isBoundedString(value.error.message, 1024)\n ) {\n throw new PodExtensionBridgeError(\"invalid seed bridge remote error\", \"invalid_response\");\n }\n return value as unknown as SeedBridgeFailure;\n }\n throw new PodExtensionBridgeError(\"seed bridge response lacks a boolean result\", \"invalid_response\");\n}\n\nfunction validateSeedContextData(data: Record<string, unknown>): void {\n if (!Array.isArray(data.entries) || typeof data.compactionCount !== \"number\" || !Number.isFinite(data.compactionCount)) {\n throw new PodExtensionBridgeError(\"invalid seed context data\", \"invalid_response\");\n }\n if (data.leafId !== null && !isBoundedString(data.leafId, TREE_BRIDGE_MAX_ENTRY_ID_LENGTH)) {\n throw new PodExtensionBridgeError(\"invalid seed context leaf\", \"invalid_response\");\n }\n}\n\nfunction validateSeedTreeSummaryData(data: Record<string, unknown>): void {\n if (!Array.isArray(data.nodes)) {\n throw new PodExtensionBridgeError(\"invalid seed tree summary data\", \"invalid_response\");\n }\n if (data.leafId !== null && !isBoundedString(data.leafId, TREE_BRIDGE_MAX_ENTRY_ID_LENGTH)) {\n throw new PodExtensionBridgeError(\"invalid seed tree summary leaf\", \"invalid_response\");\n }\n for (const node of data.nodes) {\n if (!isPlainObject(node) || !isBoundedString(node.id, TREE_BRIDGE_MAX_ENTRY_ID_LENGTH) || typeof node.type !== \"string\" || typeof node.preview !== \"string\") {\n throw new PodExtensionBridgeError(\"invalid seed tree summary node\", \"invalid_response\");\n }\n if (node.parentId !== null && node.parentId !== undefined && !isBoundedString(node.parentId, TREE_BRIDGE_MAX_ENTRY_ID_LENGTH)) {\n throw new PodExtensionBridgeError(\"invalid seed tree summary parent\", \"invalid_response\");\n }\n }\n}\n","/**\n * src/client/runtime/extension-model-registry.ts — the launcher-side `ctx.modelRegistry`.\n *\n * Native pi hands extensions a `ModelRegistry` facade over the session's authenticated\n * `ModelRuntime` (same instance the agent uses). A pod session's credentials live in the\n * pod, so the launcher cannot hold that instance. This module builds a native-compatible\n * facade instead:\n *\n * - Metadata reads (`find`, `getAvailable`, `getProvider`, `hasConfiguredAuth`, …) are\n * served from the client-side model catalog and the auth-bridge snapshot. They are\n * honest but point-in-time: the pod stays authoritative and the snapshot refreshes on\n * the same boundaries as the model catalog.\n * - `complete` executes pod-side through the semantic `aux_complete` gateway message,\n * where the pod's own authenticated registry runs it as a turn-external call: no\n * conversation entries, no main-model change, no prompt-cache interaction\n * (`cacheRetention: \"none\"`). Secrets never cross to the launcher. `complete()`\n * accepts `cacheRetention: \"none\"` because unchanged callers (notably\n * pi-lightweight-llm) always pass it; any other value is rejected — the bridge\n * always runs turn-external with no prompt-cache interaction.\n *\n * Text-only contract (explicit, not full native parity): only `{systemPrompt,\n * messages}` cross, with user/assistant text content. Anything else — `tools`,\n * sampling options (`temperature`, `samplingParams`, …), transports, headers, env,\n * image/audio/tool-result content, thinking blocks — is rejected with an explained\n * error, never silently dropped. The pod runs the call through its real\n * `ModelRegistry.complete` with the native `reasoningEffort` thinking option passed\n * through verbatim (including \"off\"), so thinking semantics are exactly the pod's\n * native per-API behavior — provider-specific, with no bridge-level translation\n * and no universal guarantee. Empty-text non-terminal outcomes (toolUse/deferred/pending) are\n * reported as failures, never fabricated successes.\n * - Anything that would leak pod credentials (`getApiKeyAndHeaders`, `getProviderAuth`,\n * `getApiKeyForProvider`) or mutate pod-side providers (`registerProvider`, …) throws\n * an explained error. Arbitrary API transparency is impossible across this boundary;\n * the facade says exactly where the boundary is instead of half-working.\n *\n * Ownership/limits: at most {@link AUX_CLIENT_CONCURRENCY} aux completions are in flight\n * per launcher session (fast `aux_busy` failure, never silent queueing); every call has\n * its own deadline (default 60s, cap 5min) and its own AbortSignal, which cancels only\n * that call — never the main turn. Disconnect and session replacement reject/abandon\n * pending calls through the transport's lifecycle invalidation; the gateway owns the\n * pod-side cancel. Payloads are bounded (system prompt, message count/size, max tokens)\n * so a rogue extension cannot turn the pod into an open relay.\n */\nimport { PiPodError } from \"../../errors.js\";\nimport { AUX_EXTENSION_VERSION } from \"../../shim/pi-pod-ext.js\";\nimport type { ThinkingLevel } from \"../rpc.js\";\n\nexport type AuxRole = \"user\" | \"assistant\";\n\nexport interface AuxMessage {\n role: AuxRole;\n content: string;\n}\n\nexport interface AuxCompleteRequest {\n provider: string;\n model: string;\n systemPrompt?: string | undefined;\n messages: AuxMessage[];\n thinkingLevel?: ThinkingLevel | undefined;\n maxTokens?: number | undefined;\n timeoutMs?: number | undefined;\n}\n\nexport interface AuxCompleteResult {\n text: string;\n stopReason: string;\n usage: unknown;\n}\n\n/** Minimal structural read of a catalog model — provider/id are the whole wire identity. */\nexport interface AuxCatalogModel {\n provider: string;\n id: string;\n api?: string | undefined;\n reasoning?: boolean | undefined;\n [key: string]: unknown;\n}\n\nexport interface ExtensionModelRegistryDeps {\n /** Live point-in-time catalog (the client-side available-models cache). */\n getModels(): readonly AuxCatalogModel[];\n /** Live point-in-time auth state (the auth-bridge snapshot). */\n isProviderConfigured(provider: string): boolean;\n /** Display name for a provider id, for getProviderDisplayName. */\n getProviderDisplayName(provider: string): string;\n /** Whether the provider authenticates via OAuth (for isUsingOAuth/isUsingSubscription). */\n isUsingOAuth(provider: string): boolean;\n /** Transport-level aux execution (the semantic gateway message). */\n auxComplete: ((request: AuxCompleteRequest, opts?: { signal?: AbortSignal }) => Promise<AuxCompleteResult>) | undefined;\n /** Pod extension version from the shim hello, for honest older-pod errors. */\n getExtensionVersion(): number | undefined;\n}\n\nexport const AUX_CLIENT_CONCURRENCY = 4;\nexport const AUX_DEFAULT_TIMEOUT_MS = 60_000;\nexport const AUX_MAX_TIMEOUT_MS = 300_000;\nexport const AUX_DEFAULT_MAX_TOKENS = 2048;\nexport const AUX_MAX_MAX_TOKENS = 4096;\nexport const AUX_MAX_SYSTEM_PROMPT_CHARS = 16_384;\nexport const AUX_MAX_MESSAGES = 16;\nexport const AUX_MAX_MESSAGE_CHARS = 65_536;\n\nconst THINKING_LEVELS = new Set([\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"]);\n\nfunction auxError(code: string, message: string): PiPodError {\n return new PiPodError(message, { code });\n}\n\nfunction unavailable(what: string, why: string): () => never {\n return () => {\n throw auxError(\"aux_unsupported\", `${what} is not available to locally rendered pod extensions — ${why}`);\n };\n}\n\nfunction checkModelShape(model: unknown): asserts model is AuxCatalogModel {\n if (\n typeof model !== \"object\" ||\n model === null ||\n typeof (model as AuxCatalogModel).provider !== \"string\" ||\n typeof (model as AuxCatalogModel).id !== \"string\"\n ) {\n throw auxError(\"invalid_model\", \"complete() needs the model object returned by find()\");\n }\n}\n\nconst CONTEXT_KEYS = new Set([\"systemPrompt\", \"messages\"]);\n\nfunction checkContext(context: unknown): { systemPrompt?: string; messages: AuxMessage[] } {\n if (typeof context !== \"object\" || context === null) {\n throw auxError(\"invalid_context\", \"complete() needs a context with a messages array\");\n }\n for (const key of Object.keys(context)) {\n if (!CONTEXT_KEYS.has(key)) {\n throw auxError(\n \"unsupported_option\",\n `complete() context key ${JSON.stringify(key)} cannot cross the aux bridge — only systemPrompt and text-only messages are supported`,\n );\n }\n }\n const { systemPrompt, messages } = context as { systemPrompt?: unknown; messages?: unknown };\n if (systemPrompt !== undefined && typeof systemPrompt !== \"string\") {\n throw auxError(\"invalid_context\", \"complete() systemPrompt must be a string\");\n }\n if (typeof systemPrompt === \"string\" && systemPrompt.length > AUX_MAX_SYSTEM_PROMPT_CHARS) {\n throw auxError(\n \"context_too_large\",\n `complete() systemPrompt exceeds ${AUX_MAX_SYSTEM_PROMPT_CHARS} characters`,\n );\n }\n if (!Array.isArray(messages) || messages.length === 0 || messages.length > AUX_MAX_MESSAGES) {\n throw auxError(\n \"invalid_context\",\n `complete() messages must be 1..${AUX_MAX_MESSAGES} entries (text-only user/assistant)`,\n );\n }\n return {\n ...(systemPrompt !== undefined ? { systemPrompt } : {}),\n messages: messages.map((entry, index) => {\n if (typeof entry !== \"object\" || entry === null) {\n throw auxError(\"invalid_context\", `complete() messages[${index}] must be an object`);\n }\n const { role, content, timestamp } = entry as {\n role?: unknown;\n content?: unknown;\n timestamp?: unknown;\n };\n void timestamp;\n if (role !== \"user\" && role !== \"assistant\") {\n throw auxError(\n \"unsupported_role\",\n `complete() messages[${index}] has role ${JSON.stringify(role)} — only user/assistant text messages cross the aux bridge`,\n );\n }\n if (typeof content === \"string\") {\n if (content.length > AUX_MAX_MESSAGE_CHARS) {\n throw auxError(\n \"context_too_large\",\n `complete() messages[${index}] exceeds ${AUX_MAX_MESSAGE_CHARS} characters`,\n );\n }\n return { role, content };\n }\n if (!Array.isArray(content)) {\n throw auxError(\"invalid_context\", `complete() messages[${index}].content must be text`);\n }\n const text = content\n .map((part) => {\n if (typeof part !== \"object\" || part === null || (part as { type?: unknown }).type !== \"text\") {\n throw auxError(\n \"unsupported_content\",\n `complete() messages[${index}] carries non-text content — only text crosses the aux bridge`,\n );\n }\n return String((part as { text?: unknown }).text ?? \"\");\n })\n .join(\"\");\n if (text.length > AUX_MAX_MESSAGE_CHARS) {\n throw auxError(\n \"context_too_large\",\n `complete() messages[${index}] exceeds ${AUX_MAX_MESSAGE_CHARS} characters`,\n );\n }\n return { role, content: text };\n }),\n };\n}\n\nfunction checkOptions(options: unknown): {\n signal?: AbortSignal;\n thinkingLevel?: ThinkingLevel;\n maxTokens: number;\n timeoutMs: number;\n} {\n if (options === undefined) {\n return { maxTokens: AUX_DEFAULT_MAX_TOKENS, timeoutMs: AUX_DEFAULT_TIMEOUT_MS };\n }\n if (typeof options !== \"object\" || options === null) {\n throw auxError(\"invalid_options\", \"complete() options must be an object\");\n }\n // Reject — never silently drop — anything outside the text-only aux contract.\n // Native complete() accepts per-API sampling/transport/tools options; none of\n // those cross this bridge. cacheRetention: \"none\" is accepted because unchanged\n // callers always pass it and the bridge enforces no-cache behavior anyway.\n const OPTION_KEYS = new Set([\"signal\", \"thinkingLevel\", \"reasoningEffort\", \"maxTokens\", \"timeoutMs\", \"cacheRetention\"]);\n for (const key of Object.keys(options)) {\n if (!OPTION_KEYS.has(key)) {\n throw auxError(\n \"unsupported_option\",\n `complete() option ${JSON.stringify(key)} cannot cross the aux bridge — supported options are signal, thinkingLevel, maxTokens, timeoutMs, cacheRetention: \"none\"`,\n );\n }\n }\n const { cacheRetention } = options as { cacheRetention?: unknown };\n if (cacheRetention !== undefined && cacheRetention !== \"none\") {\n throw auxError(\n \"unsupported_option\",\n `complete() cacheRetention ${JSON.stringify(cacheRetention)} cannot cross the aux bridge — auxiliary completions always run with no prompt-cache interaction`,\n );\n }\n const { signal, thinkingLevel, reasoningEffort, maxTokens, timeoutMs } = options as {\n signal?: unknown;\n thinkingLevel?: unknown;\n reasoningEffort?: unknown;\n maxTokens?: unknown;\n timeoutMs?: unknown;\n };\n if (signal !== undefined && !(signal instanceof AbortSignal)) {\n throw auxError(\"invalid_options\", \"complete() signal must be an AbortSignal\");\n }\n const level = thinkingLevel ?? reasoningEffort;\n if (level !== undefined && (typeof level !== \"string\" || !THINKING_LEVELS.has(level))) {\n throw auxError(\n \"invalid_options\",\n \"complete() thinkingLevel must be one of off/minimal/low/medium/high/xhigh/max\",\n );\n }\n const checkedLevel = level as ThinkingLevel | undefined;\n const tokens = maxTokens === undefined ? AUX_DEFAULT_MAX_TOKENS : maxTokens;\n if (typeof tokens !== \"number\" || !Number.isInteger(tokens) || tokens < 1 || tokens > AUX_MAX_MAX_TOKENS) {\n throw auxError(\"invalid_options\", `complete() maxTokens must be 1..${AUX_MAX_MAX_TOKENS}`);\n }\n const timeout = timeoutMs === undefined ? AUX_DEFAULT_TIMEOUT_MS : timeoutMs;\n if (typeof timeout !== \"number\" || !Number.isFinite(timeout) || timeout < 1000 || timeout > AUX_MAX_TIMEOUT_MS) {\n throw auxError(\"invalid_options\", `complete() timeoutMs must be 1000..${AUX_MAX_TIMEOUT_MS}`);\n }\n return {\n ...(signal ? { signal } : {}),\n ...(checkedLevel !== undefined ? { thinkingLevel: checkedLevel } : {}),\n maxTokens: tokens,\n timeoutMs: timeout,\n };\n}\n\nfunction zeroUsage(): Record<string, number> {\n return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0 };\n}\n\n/** Native-shaped assistant message returned by complete(). */\nexport interface AuxAssistantMessage {\n role: \"assistant\";\n content: Array<{ type: \"text\"; text: string }>;\n api: string;\n provider: string;\n model: string;\n usage: unknown;\n stopReason: string;\n timestamp: number;\n}\n\n/**\n * Build the launcher-side model registry. `getModels`/`isProviderConfigured` are thunks so\n * every call reads the live cache/snapshot rather than a stale copy.\n */\nexport function createExtensionModelRegistry(deps: ExtensionModelRegistryDeps): ExtensionModelRegistry {\n let inFlight = 0;\n const activeControllers = new Set<AbortController>();\n\n const find = (provider: string, modelId: string): AuxCatalogModel | undefined =>\n deps.getModels().find((model) => model.provider === provider && model.id === modelId);\n\n const hasConfiguredAuth = (model: AuxCatalogModel): boolean => {\n if (!model || typeof model.provider !== \"string\") return false;\n return deps.isProviderConfigured(model.provider);\n };\n\n const complete = async (\n model: unknown,\n context: unknown,\n options?: unknown,\n ): Promise<AuxAssistantMessage> => {\n checkModelShape(model);\n const checked = checkContext(context);\n const opts = checkOptions(options);\n // An already-aborted caller signal fails before any transport use.\n opts.signal?.throwIfAborted();\n if (!deps.auxComplete) {\n throw auxError(\n \"aux_unsupported\",\n \"auxiliary completions need a gateway session with aux support — this transport has none\",\n );\n }\n const extensionVersion = deps.getExtensionVersion();\n if (extensionVersion !== undefined && extensionVersion < AUX_EXTENSION_VERSION) {\n throw auxError(\n \"aux_unsupported\",\n \"this pod runs an older pi pod extension without auxiliary completions — restart Pi in the pod and reattach\",\n );\n }\n if (inFlight >= AUX_CLIENT_CONCURRENCY) {\n throw auxError(\n \"aux_busy\",\n `too many concurrent auxiliary completions (>${AUX_CLIENT_CONCURRENCY}) — retry when one settles`,\n );\n }\n if (!hasConfiguredAuth(model)) {\n throw auxError(\n \"auth_unconfigured\",\n `no configured authentication for ${model.provider} — run /login ${model.provider} in the pod session`,\n );\n }\n if (!find(model.provider, model.id)) {\n throw auxError(\"unknown_model\", `unknown model ${model.provider}/${model.id} in this pod session`);\n }\n\n inFlight += 1;\n const controller = new AbortController();\n activeControllers.add(controller);\n const onCallerAbort = (): void => {\n controller.abort(opts.signal?.reason);\n };\n opts.signal?.addEventListener(\"abort\", onCallerAbort, { once: true });\n const timer = setTimeout(() => {\n controller.abort(new Error(`auxiliary completion timed out after ${Math.round(opts.timeoutMs / 1000)}s`));\n }, opts.timeoutMs);\n timer.unref?.();\n try {\n const result = await deps.auxComplete(\n {\n provider: model.provider,\n model: model.id,\n ...(checked.systemPrompt !== undefined ? { systemPrompt: checked.systemPrompt } : {}),\n messages: checked.messages,\n ...(opts.thinkingLevel !== undefined ? { thinkingLevel: opts.thinkingLevel } : {}),\n maxTokens: opts.maxTokens,\n timeoutMs: opts.timeoutMs,\n },\n { signal: controller.signal },\n );\n // A late reply after caller abort, timeout, or session invalidation is never\n // returned as a success: the caller already observed the cancellation.\n controller.signal.throwIfAborted();\n if (typeof result.text !== \"string\") {\n throw auxError(\"aux_malformed\", \"auxiliary completion reply carried no text\");\n }\n if (result.text === \"\" && result.stopReason !== \"stop\" && result.stopReason !== \"length\") {\n throw auxError(\n \"completion_failed\",\n `auxiliary completion ended without text (stopReason ${JSON.stringify(result.stopReason)}) — the text-only bridge cannot serve tool-use or deferred outcomes`,\n );\n }\n // A native-shaped assistant message: the caller's contract (stopReason/usage/content)\n // is the same one ModelRegistry.complete returns in-process. Usage passes through\n // untouched (including cost); the pod never fabricates it.\n return {\n role: \"assistant\",\n content: [{ type: \"text\", text: result.text }],\n api: model.api ?? \"unknown\",\n provider: model.provider,\n model: model.id,\n usage: result.usage ?? zeroUsage(),\n stopReason: result.stopReason,\n timestamp: Date.now(),\n };\n } finally {\n clearTimeout(timer);\n opts.signal?.removeEventListener(\"abort\", onCallerAbort);\n activeControllers.delete(controller);\n inFlight -= 1;\n }\n };\n\n return {\n find,\n hasConfiguredAuth,\n complete,\n getAll: () => [...deps.getModels()],\n getAvailable: () => [...deps.getModels()],\n getProviderDisplayName: (provider: string) => deps.getProviderDisplayName(provider),\n isUsingOAuth: (model: AuxCatalogModel) =>\n typeof model?.provider === \"string\" && deps.isUsingOAuth(model.provider),\n isUsingSubscription: (model: AuxCatalogModel) =>\n typeof model?.provider === \"string\" && deps.isUsingOAuth(model.provider),\n getError: () => undefined,\n // Provider credentials live in the pod; the launcher must never see them.\n getApiKeyAndHeaders: unavailable(\n \"modelRegistry.getApiKeyAndHeaders\",\n \"pod credentials never cross to the launcher — run the completion pod-side via complete()\",\n ),\n getProviderAuth: unavailable(\n \"modelRegistry.getProviderAuth\",\n \"pod credentials never cross to the launcher — run the completion pod-side via complete()\",\n ),\n getApiKeyForProvider: unavailable(\n \"modelRegistry.getApiKeyForProvider\",\n \"pod credentials never cross to the launcher — run the completion pod-side via complete()\",\n ),\n // Providers execute in the pod; local registration would fork the catalog.\n registerProvider: unavailable(\n \"modelRegistry.registerProvider\",\n \"providers execute in the pod — configure them there\",\n ),\n unregisterProvider: unavailable(\n \"modelRegistry.unregisterProvider\",\n \"providers execute in the pod — configure them there\",\n ),\n getRegisteredProviderConfig: unavailable(\n \"modelRegistry.getRegisteredProviderConfig\",\n \"providers execute in the pod\",\n ),\n getRegisteredNativeProvider: unavailable(\n \"modelRegistry.getRegisteredNativeProvider\",\n \"providers execute in the pod\",\n ),\n getRegisteredProviderIds: () => [] as string[],\n /**\n * Abort locally queued aux waits (session replacement/dispose). In-flight pod\n * executions are the gateway's to cancel (the transport aborts on our signal);\n * late pod replies correlate to nothing and are discarded by the post-await\n * abort check in complete(). Never aborts the main turn.\n */\n discardPending: (reason = \"the pi pod session was replaced\") => {\n const error = new Error(reason);\n for (const controller of activeControllers) {\n try {\n controller.abort(error);\n } catch {\n // Aborting never fails usefully; the finally in complete() still runs.\n }\n }\n activeControllers.clear();\n },\n };\n}\n\nexport type ExtensionModelRegistry = {\n find(provider: string, modelId: string): AuxCatalogModel | undefined;\n hasConfiguredAuth(model: AuxCatalogModel): boolean;\n complete(\n model: unknown,\n context: unknown,\n options?: unknown,\n ): Promise<AuxAssistantMessage>;\n getAll(): AuxCatalogModel[];\n getAvailable(): AuxCatalogModel[];\n getProviderDisplayName(provider: string): string;\n isUsingOAuth(model: AuxCatalogModel): boolean;\n isUsingSubscription(model: AuxCatalogModel): boolean;\n getError(): undefined;\n getApiKeyAndHeaders(): never;\n getProviderAuth(): never;\n getApiKeyForProvider(): never;\n registerProvider(): never;\n unregisterProvider(): never;\n getRegisteredProviderConfig(): never;\n getRegisteredNativeProvider(): never;\n getRegisteredProviderIds(): string[];\n discardPending(reason?: string): void;\n};\n","/**\n * Generic client half of remote extension UI. Extension component code executes in the pod;\n * this module mounts a structural proxy in the local InteractiveMode and forwards only\n * rendered lines, input, resize, and lifecycle messages.\n */\nimport { truncateToWidth, visibleWidth } from \"@earendil-works/pi-tui\";\nimport type { RpcClientBase } from \"../rpc.js\";\nimport {\n REMOTE_UI_INPUT_PREFIX,\n REMOTE_UI_MAX_LINE_LENGTH,\n REMOTE_UI_MAX_LINES,\n REMOTE_UI_MAX_SURFACES,\n REMOTE_UI_NOTIFICATION_PREFIX,\n REMOTE_UI_PROTOCOL_VERSION,\n decodeRemoteUiPayload,\n encodeRemoteUiPayload,\n type RemoteUiControlFrame,\n type RemoteUiFrame,\n type RemoteUiInput,\n type RemoteUiSurfaceFrame,\n} from \"../../remote-ui-protocol.js\";\nimport type { HostBridge, HostUiContext } from \"./bridge.js\";\n\nexport interface RemoteUiExtensionRequest {\n type: \"extension_ui_request\";\n id: string;\n method: string;\n title?: string;\n message?: string;\n}\n\ninterface TuiLike {\n terminal?: { rows?: number };\n requestRender?(force?: boolean): void;\n}\n\ntype Done = (value: unknown) => void;\n\nclass RemoteSurfaceComponent {\n focused = true;\n wantsKeyRelease = true;\n onSubmit?: (text: string) => void;\n onChange?: (text: string) => void;\n private tui: TuiLike | null = null;\n private done: Done | null = null;\n private lastWidth = 0;\n private lastHeight = 0;\n private lastEditorSubmitId = 0;\n\n constructor(private readonly owner: RemoteSurface) {}\n\n bind(tui: TuiLike, done?: Done): this {\n this.tui = tui;\n this.done = done ?? null;\n this.owner.flush();\n return this;\n }\n\n render(width: number): string[] {\n const height = Math.max(1, Number(this.tui?.terminal?.rows ?? 24));\n if (width !== this.lastWidth || height !== this.lastHeight) {\n this.lastWidth = width;\n this.lastHeight = height;\n queueMicrotask(() => this.owner.resize(width, height));\n }\n // Frames are rendered in the pod and lag a resize round trip behind the local terminal,\n // so after a shrink the newest lines are still the old, wider ones — and a line wider than\n // the component's width aborts pi's renderer.\n return this.owner.lines.map((line) => (visibleWidth(line) > width ? truncateToWidth(line, width, \"\") : line));\n }\n\n handleInput(data: string): void {\n this.owner.input(data, Math.max(1, this.lastWidth || 80), Math.max(1, this.lastHeight || 24));\n }\n\n getText(): string {\n return this.owner.editorText;\n }\n\n getExpandedText(): string {\n return this.owner.editorText;\n }\n\n setText(text: string): void {\n this.owner.setEditorText(text, Math.max(1, this.lastWidth || 80), Math.max(1, this.lastHeight || 24));\n }\n\n insertTextAtCursor(text: string): void {\n this.setText(this.owner.editorText + text);\n }\n\n addToHistory(): void {}\n setAutocompleteProvider(): void {}\n setPaddingX(): void {}\n setAutocompleteMaxVisible(): void {}\n\n applyEditorFrame(text: string | undefined, submit: string | undefined, submitId: number | undefined): void {\n if (text !== undefined && text !== this.owner.editorText) {\n this.owner.editorText = text;\n this.onChange?.(text);\n }\n if (submit !== undefined && submitId !== undefined && submitId > this.lastEditorSubmitId) {\n this.lastEditorSubmitId = submitId;\n this.onSubmit?.(submit);\n }\n }\n\n invalidate(): void {}\n\n requestRender(): void {\n this.tui?.requestRender?.();\n }\n\n finish(): void {\n this.done?.(undefined);\n this.done = null;\n }\n\n dispose(): void {\n this.owner.localDisposed();\n }\n}\n\nclass RemoteSurface {\n readonly component = new RemoteSurfaceComponent(this);\n lines: string[] = [];\n editorText = \"\";\n revision = -1;\n pendingRequestId: string | null = null;\n mounted = false;\n remoteClosing = false;\n private localHandle: { focus(): void; unfocus(): void } | null = null;\n private appliedFocus: boolean | null = null;\n private inputSequence = 0;\n private readonly queuedInputs: Array<{\n kind: \"input\" | \"setText\";\n data: string;\n width: number;\n height: number;\n }> = [];\n private size = { width: 0, height: 0 };\n\n constructor(\n readonly frame: RemoteUiSurfaceFrame,\n private readonly manager: RemoteUiBridge,\n ) {}\n\n apply(frame: RemoteUiSurfaceFrame, requestId?: string): void {\n if (frame.revision >= this.revision) {\n this.revision = frame.revision;\n this.lines = sanitizeLines(frame.lines ?? []);\n Object.assign(this.frame, frame);\n this.component.requestRender();\n this.component.applyEditorFrame(frame.editorText, frame.editorSubmit, frame.editorSubmitId);\n }\n if (requestId) {\n this.pendingRequestId = requestId;\n this.flush();\n }\n this.applyFocus();\n }\n\n bindLocalHandle(handle: { focus(): void; unfocus(): void }): void {\n this.localHandle = handle;\n // A remount (session replacement) makes a fresh, unfocused local overlay; reapply.\n this.appliedFocus = null;\n this.applyFocus();\n }\n\n /**\n * Extension component code runs in the pod, so its handle.focus()/unfocus() calls act on\n * the pod's virtual TUI. Non-capturing overlays receive input only when focused, so the\n * pod mirrors that handle state through frames and it is replayed onto the local handle\n * here — otherwise a remote non-capturing overlay could never accept input at all.\n */\n private applyFocus(): void {\n const want = this.frame.focused;\n if (want === undefined || !this.localHandle || this.appliedFocus === want) return;\n this.appliedFocus = want;\n if (want) this.localHandle.focus();\n else this.localHandle.unfocus();\n }\n\n flush(): void {\n if (!this.pendingRequestId) return;\n if (this.size.width > 0) {\n const { width, height } = this.size;\n this.size = { width: 0, height: 0 };\n this.send(\"resize\", width, height);\n return;\n }\n const queued = this.queuedInputs.shift();\n if (!queued) return;\n if (queued.kind === \"input\") {\n const events = [queued.data];\n while (events.length < 64 && this.queuedInputs[0]?.kind === \"input\") {\n events.push(this.queuedInputs.shift()!.data);\n }\n this.send(\"input\", queued.width, queued.height, undefined, events);\n return;\n }\n this.send(queued.kind, queued.width, queued.height, queued.data);\n }\n\n resize(width: number, height: number): void {\n if (width <= 0 || height <= 0) return;\n if (!this.pendingRequestId) {\n this.size = { width, height };\n return;\n }\n this.send(\"resize\", width, height);\n }\n\n input(data: string, width: number, height: number): void {\n const chunks: string[] = [];\n if (data.length === 0) chunks.push(\"\");\n for (let offset = 0; offset < data.length; offset += REMOTE_UI_MAX_LINE_LENGTH) {\n chunks.push(data.slice(offset, offset + REMOTE_UI_MAX_LINE_LENGTH));\n }\n if (!this.pendingRequestId) {\n for (const chunk of chunks) this.queueInput({ kind: \"input\", data: chunk, width, height });\n return;\n }\n this.send(\"input\", width, height, chunks.shift()!);\n for (const chunk of chunks) this.queueInput({ kind: \"input\", data: chunk, width, height });\n }\n\n setEditorText(text: string, width: number, height: number): void {\n this.editorText = text;\n if (!this.pendingRequestId) {\n // Only the newest unsent absolute text replacement matters; raw key events retain order.\n for (let i = this.queuedInputs.length - 1; i >= 0; i--) {\n if (this.queuedInputs[i]!.kind === \"setText\") this.queuedInputs.splice(i, 1);\n }\n this.queueInput({ kind: \"setText\", data: text, width, height });\n return;\n }\n this.send(\"setText\", width, height, text);\n }\n\n private queueInput(input: { kind: \"input\" | \"setText\"; data: string; width: number; height: number }): void {\n // A bounded FIFO preserves normal typing across network round trips without unbounded\n // memory growth if a surface stops answering entirely.\n if (this.queuedInputs.length >= 1024) this.queuedInputs.shift();\n this.queuedInputs.push(input);\n }\n\n localDisposed(): void {\n if (this.remoteClosing) return;\n this.send(\"close\", Math.max(1, this.size.width || 80), Math.max(1, this.size.height || 24));\n this.manager.forget(this.frame.surfaceId);\n }\n\n closeFromRemote(): void {\n this.remoteClosing = true;\n this.pendingRequestId = null;\n this.manager.unmount(this);\n }\n\n private send(\n kind: RemoteUiInput[\"kind\"],\n width: number,\n height: number,\n data?: string,\n events?: string[],\n ): void {\n const id = this.pendingRequestId;\n if (!id) return;\n this.pendingRequestId = null;\n const input: RemoteUiInput = {\n v: REMOTE_UI_PROTOCOL_VERSION,\n kind,\n surfaceId: this.frame.surfaceId,\n sequence: ++this.inputSequence,\n width: Math.max(1, Math.min(1000, Math.floor(width))),\n height: Math.max(1, Math.min(1000, Math.floor(height))),\n ...(data !== undefined ? { data } : {}),\n ...(events?.length ? { events } : {}),\n };\n this.manager.respond(id, input);\n }\n}\n\nexport class RemoteUiBridge {\n private readonly surfaces = new Map<string, RemoteSurface>();\n private readonly slots = new Map<string, string>();\n private ui: HostUiContext | null = null;\n private disposed = false;\n private warnedUnavailable = false;\n private activeContextRevision = 0;\n private readonly offUiBound: () => void;\n private readonly offLifecycle: () => void;\n\n constructor(\n private readonly rpc: RpcClientBase,\n private readonly bridge: HostBridge,\n ) {\n this.offUiBound = bridge.onEveryUiBound((ui) => {\n if (this.ui && this.ui !== ui) {\n // InteractiveMode clears extension-owned components during session replacement.\n // Release the old local mounts without closing the still-live remote surfaces, then\n // mount their latest snapshots into the fresh context.\n for (const surface of this.surfaces.values()) {\n if (!surface.mounted) continue;\n surface.remoteClosing = true;\n this.unmount(surface);\n surface.remoteClosing = false;\n surface.mounted = false;\n }\n }\n this.ui = ui;\n for (const surface of this.surfaces.values()) this.mount(surface);\n });\n this.offLifecycle = rpc.onLifecycleInvalidated(() => {\n // Transport replacement may also mean a different pod. Context revisions are scoped to\n // one Pi process, so discard both the old namespace and mounts before replay/attach.\n this.activeContextRevision = 0;\n this.reset();\n });\n }\n\n /** Intercept reserved input/notify requests before ordinary extension UI dispatch. */\n consumeExtensionRequest(request: RemoteUiExtensionRequest): boolean {\n const encoded =\n request.method === \"input\" && request.title?.startsWith(REMOTE_UI_INPUT_PREFIX)\n ? request.title.slice(REMOTE_UI_INPUT_PREFIX.length)\n : request.method === \"notify\" && request.message?.startsWith(REMOTE_UI_NOTIFICATION_PREFIX)\n ? request.message.slice(REMOTE_UI_NOTIFICATION_PREFIX.length)\n : null;\n if (encoded === null) return false;\n\n const frame = decodeRemoteUiPayload(encoded) as RemoteUiFrame | null;\n if (!frame || frame.v !== REMOTE_UI_PROTOCOL_VERSION) {\n if (request.method === \"input\") {\n this.rpc.respondExtensionUi({ type: \"extension_ui_response\", id: request.id, cancelled: true });\n }\n return true;\n }\n if (frame.contextRevision !== undefined) {\n if (frame.contextRevision < this.activeContextRevision) {\n if (request.method === \"input\") this.respondClose(request.id, frame.kind === \"control\" ? \"stale\" : frame.surfaceId);\n return true;\n }\n if (frame.contextRevision > this.activeContextRevision) {\n this.reset();\n this.activeContextRevision = frame.contextRevision;\n }\n }\n if (frame.kind === \"control\") {\n this.applyControl(frame);\n return true;\n }\n if (frame.kind === \"close\") {\n this.surfaces.get(frame.surfaceId)?.closeFromRemote();\n this.forget(frame.surfaceId);\n return true;\n }\n\n let surface = this.surfaces.get(frame.surfaceId);\n if (!surface) {\n if (this.surfaces.size >= REMOTE_UI_MAX_SURFACES) {\n if (request.method === \"input\") this.respondClose(request.id, frame.surfaceId);\n return true;\n }\n surface = new RemoteSurface({ ...frame }, this);\n this.surfaces.set(frame.surfaceId, surface);\n }\n surface.apply(frame, request.method === \"input\" ? request.id : undefined);\n this.mount(surface);\n return true;\n }\n\n respond(id: string, input: RemoteUiInput): void {\n try {\n this.rpc.respondExtensionUi({\n type: \"extension_ui_response\",\n id,\n value: REMOTE_UI_INPUT_PREFIX + encodeRemoteUiPayload(input),\n } as never);\n } catch {\n // Recovery replays the still-pending request; retaining the surface is correct.\n }\n }\n\n forget(surfaceId: string): void {\n this.surfaces.delete(surfaceId);\n for (const [slot, id] of this.slots) if (id === surfaceId) this.slots.delete(slot);\n }\n\n unmount(surface: RemoteSurface): void {\n const ui = this.ui;\n if (!ui) return;\n switch (surface.frame.role) {\n case \"custom\":\n surface.component.finish();\n break;\n case \"widget\":\n if (surface.frame.widgetKey && this.owns(`widget:${surface.frame.widgetKey}`, surface)) {\n ui.setWidget?.(surface.frame.widgetKey, undefined);\n }\n break;\n case \"header\":\n if (this.owns(\"header\", surface)) ui.setHeader?.(undefined);\n break;\n case \"footer\":\n if (this.owns(\"footer\", surface)) ui.setFooter?.(undefined);\n break;\n case \"editor\":\n if (this.owns(\"editor\", surface)) ui.setEditorComponent?.(undefined);\n break;\n }\n }\n\n reset(): void {\n for (const surface of this.surfaces.values()) {\n surface.remoteClosing = true;\n this.unmount(surface);\n }\n this.surfaces.clear();\n this.slots.clear();\n }\n\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n for (const surface of this.surfaces.values()) surface.localDisposed();\n this.reset();\n this.offUiBound();\n this.offLifecycle();\n }\n\n private mount(surface: RemoteSurface): void {\n if (surface.mounted || this.disposed || !this.ui) return;\n const ui = this.ui;\n const proxy = surface.component;\n switch (surface.frame.role) {\n case \"custom\": {\n if (!ui.custom) return this.unavailable(surface);\n surface.mounted = true;\n void ui\n .custom(\n (tui, _theme, _keybindings, done) => proxy.bind(tui as TuiLike, done as Done),\n {\n overlay: surface.frame.overlay,\n ...(surface.frame.overlayOptions ? { overlayOptions: surface.frame.overlayOptions } : {}),\n onHandle: (handle: { focus(): void; unfocus(): void }) => surface.bindLocalHandle(handle),\n },\n )\n .catch(() => surface.localDisposed());\n break;\n }\n case \"widget\": {\n if (!ui.setWidget || !surface.frame.widgetKey) return this.unavailable(surface);\n surface.mounted = true;\n const slot = `widget:${surface.frame.widgetKey}`;\n this.slots.set(slot, surface.frame.surfaceId);\n ui.setWidget(\n surface.frame.widgetKey,\n (tui) => proxy.bind(tui as TuiLike),\n surface.frame.placement ? { placement: surface.frame.placement } : undefined,\n );\n break;\n }\n case \"header\":\n if (!ui.setHeader) return this.unavailable(surface);\n surface.mounted = true;\n this.slots.set(\"header\", surface.frame.surfaceId);\n ui.setHeader((tui) => proxy.bind(tui as TuiLike));\n break;\n case \"footer\":\n if (!ui.setFooter) return this.unavailable(surface);\n surface.mounted = true;\n this.slots.set(\"footer\", surface.frame.surfaceId);\n ui.setFooter((tui) => proxy.bind(tui as TuiLike));\n break;\n case \"editor\":\n if (!ui.setEditorComponent) return this.unavailable(surface);\n surface.mounted = true;\n this.slots.set(\"editor\", surface.frame.surfaceId);\n ui.setEditorComponent((tui) => proxy.bind(tui as TuiLike));\n break;\n }\n }\n\n private unavailable(surface: RemoteSurface): void {\n if (!this.warnedUnavailable) {\n this.warnedUnavailable = true;\n this.bridge.notify(\"This local Pi version cannot mount remote extension components\", \"warning\");\n }\n if (surface.pendingRequestId) this.respondClose(surface.pendingRequestId, surface.frame.surfaceId);\n this.forget(surface.frame.surfaceId);\n }\n\n private respondClose(id: string, surfaceId: string): void {\n this.respond(id, {\n v: REMOTE_UI_PROTOCOL_VERSION,\n kind: \"close\",\n surfaceId,\n sequence: 1,\n width: 80,\n height: 24,\n });\n }\n\n private owns(slot: string, surface: RemoteSurface): boolean {\n return this.slots.get(slot) === surface.frame.surfaceId;\n }\n\n private applyControl(frame: RemoteUiControlFrame): void {\n const ui = this.ui;\n if (!ui) return;\n switch (frame.action) {\n case \"setWorkingMessage\":\n ui.setWorkingMessage?.(typeof frame.value === \"string\" ? frame.value : undefined);\n break;\n case \"setWorkingVisible\":\n ui.setWorkingVisible?.(Boolean(frame.value));\n break;\n case \"setWorkingIndicator\":\n ui.setWorkingIndicator?.(frame.value);\n break;\n case \"setHiddenThinkingLabel\":\n ui.setHiddenThinkingLabel?.(typeof frame.value === \"string\" ? frame.value : undefined);\n break;\n case \"setToolsExpanded\":\n ui.setToolsExpanded?.(Boolean(frame.value));\n break;\n }\n }\n}\n\nfunction sanitizeLines(lines: string[]): string[] {\n return lines.slice(0, REMOTE_UI_MAX_LINES).map((line) => sanitizeLine(String(line)));\n}\n\nfunction sanitizeLine(line: string): string {\n const cursorMarker = \"\\x1b_pi:c\\x07\";\n let safe = \"\";\n for (let i = 0; i < line.length && safe.length < REMOTE_UI_MAX_LINE_LENGTH; ) {\n const code = line.charCodeAt(i);\n if (code !== 0x1b) {\n // Keep printable text and tabs; component lines must not carry raw terminal controls.\n if (code === 0x09 || (code >= 0x20 && code !== 0x7f)) safe += line[i];\n i += 1;\n continue;\n }\n if (line.startsWith(cursorMarker, i)) {\n if (safe.length + cursorMarker.length <= REMOTE_UI_MAX_LINE_LENGTH) safe += cursorMarker;\n i += cursorMarker.length;\n continue;\n }\n if (line[i + 1] === \"[\") {\n let end = i + 2;\n while (end < line.length && !(line.charCodeAt(end) >= 0x40 && line.charCodeAt(end) <= 0x7e)) end += 1;\n if (end < line.length) {\n const sequence = line.slice(i, end + 1);\n if (line[end] === \"m\" && /^\\x1b\\[[0-9;:]*m$/.test(sequence) && safe.length + sequence.length <= REMOTE_UI_MAX_LINE_LENGTH) {\n safe += sequence;\n }\n i = end + 1;\n continue;\n }\n break;\n }\n if (line[i + 1] === \"]\" || line[i + 1] === \"P\" || line[i + 1] === \"_\" || line[i + 1] === \"^\" || line[i + 1] === \"X\") {\n let end = i + 2;\n while (end < line.length && line.charCodeAt(end) !== 0x07 && !(line[end] === \"\\\\\" && line.charCodeAt(end - 1) === 0x1b)) end += 1;\n i = Math.min(line.length, end + 1);\n continue;\n }\n // Drop a complete ESC sequence (RIS, save/restore cursor, index, charset, etc.).\n let end = i + 1;\n while (end < line.length && line.charCodeAt(end) >= 0x20 && line.charCodeAt(end) <= 0x2f) end += 1;\n if (end < line.length && line.charCodeAt(end) >= 0x30 && line.charCodeAt(end) <= 0x7e) end += 1;\n i = Math.max(i + 1, end);\n }\n return safe;\n}\n","/**\n * Versioned wire format for extension-owned TUI components that execute in the pod and\n * render inside the client's real InteractiveMode. The extension itself never crosses the\n * trust boundary: only rendered lines, layout metadata, and terminal input do.\n */\n\nimport { decodeWireJson, encodeWireJson, isPlainObject } from \"./wire-codec.js\";\n\nexport const REMOTE_UI_PROTOCOL_VERSION = 1 as const;\nexport const REMOTE_UI_INSTALL_SYMBOL = \"pi-pod.remote-ui-v1.install\";\nexport const REMOTE_UI_NOTIFICATION_PREFIX = \"pi-pod-internal/remote-ui-v1:\";\nexport const REMOTE_UI_INPUT_PREFIX = \"pi-pod-internal/remote-ui-input-v1:\";\nexport const REMOTE_UI_MAX_ENCODED_BYTES = 2 * 1024 * 1024;\nexport const REMOTE_UI_MAX_SURFACES = 32;\nexport const REMOTE_UI_MAX_LINES = 2_000;\nexport const REMOTE_UI_MAX_LINE_LENGTH = 32_768;\n\nexport type RemoteUiRole = \"custom\" | \"widget\" | \"header\" | \"footer\" | \"editor\";\n\nexport interface RemoteUiOverlayOptions {\n width?: number | `${number}%`;\n minWidth?: number;\n maxHeight?: number | `${number}%`;\n anchor?: string;\n offsetX?: number;\n offsetY?: number;\n row?: number | `${number}%`;\n col?: number | `${number}%`;\n margin?: number | { top?: number; right?: number; bottom?: number; left?: number };\n nonCapturing?: boolean;\n}\n\nexport interface RemoteUiSurfaceFrame {\n v: typeof REMOTE_UI_PROTOCOL_VERSION;\n kind: \"open\" | \"frame\" | \"close\";\n surfaceId: string;\n revision: number;\n role: RemoteUiRole;\n contextRevision?: number;\n lines?: string[];\n widgetKey?: string;\n placement?: \"aboveEditor\" | \"belowEditor\";\n overlay?: boolean;\n overlayOptions?: RemoteUiOverlayOptions;\n /** Mirrored overlay-handle focus: the pod extension called handle.focus()/unfocus(). */\n focused?: boolean;\n editorText?: string;\n editorSubmit?: string;\n editorSubmitId?: number;\n error?: string;\n}\n\nexport interface RemoteUiControlFrame {\n v: typeof REMOTE_UI_PROTOCOL_VERSION;\n kind: \"control\";\n contextRevision?: number;\n action:\n | \"setWorkingMessage\"\n | \"setWorkingVisible\"\n | \"setWorkingIndicator\"\n | \"setHiddenThinkingLabel\"\n | \"setToolsExpanded\";\n value?: unknown;\n}\n\nexport type RemoteUiFrame = RemoteUiSurfaceFrame | RemoteUiControlFrame;\n\nexport interface RemoteUiInput {\n v: typeof REMOTE_UI_PROTOCOL_VERSION;\n kind: \"input\" | \"resize\" | \"setText\" | \"close\";\n surfaceId: string;\n sequence: number;\n width: number;\n height: number;\n data?: string;\n events?: string[];\n}\n\nexport function encodeRemoteUiPayload(value: RemoteUiFrame | RemoteUiInput): string {\n return encodeWireJson(value);\n}\n\nexport function decodeRemoteUiPayload(encoded: string): RemoteUiFrame | RemoteUiInput | null {\n const decoded = decodeWireJson(encoded, REMOTE_UI_MAX_ENCODED_BYTES);\n if (!decoded.ok) return null;\n if (!isRemoteUiFrame(decoded.value) && !isRemoteUiInput(decoded.value)) return null;\n return decoded.value as RemoteUiFrame | RemoteUiInput;\n}\n\nexport function remoteUiFrameFromExtensionRequest(request: {\n method?: string;\n title?: string;\n message?: string;\n}): RemoteUiFrame | null {\n const encoded =\n request.method === \"input\" && request.title?.startsWith(REMOTE_UI_INPUT_PREFIX)\n ? request.title.slice(REMOTE_UI_INPUT_PREFIX.length)\n : request.method === \"notify\" && request.message?.startsWith(REMOTE_UI_NOTIFICATION_PREFIX)\n ? request.message.slice(REMOTE_UI_NOTIFICATION_PREFIX.length)\n : null;\n if (encoded === null) return null;\n const decoded = decodeRemoteUiPayload(encoded);\n if (!decoded || !isRemoteUiFrame(decoded)) return null;\n return decoded as RemoteUiFrame;\n}\n\nexport function remoteUiInputFromResponse(response: { value?: unknown }): RemoteUiInput | null {\n if (typeof response.value !== \"string\" || !response.value.startsWith(REMOTE_UI_INPUT_PREFIX)) return null;\n const decoded = decodeRemoteUiPayload(response.value.slice(REMOTE_UI_INPUT_PREFIX.length));\n if (!decoded || !isRemoteUiInput(decoded)) return null;\n return decoded as RemoteUiInput;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return isPlainObject(value);\n}\n\nconst REMOTE_UI_ROLES = new Set<RemoteUiRole>([\"custom\", \"widget\", \"header\", \"footer\", \"editor\"]);\nconst REMOTE_UI_CONTROL_ACTIONS = new Set<RemoteUiControlFrame[\"action\"]>([\n \"setWorkingMessage\",\n \"setWorkingVisible\",\n \"setWorkingIndicator\",\n \"setHiddenThinkingLabel\",\n \"setToolsExpanded\",\n]);\n\nfunction isRemoteUiFrame(value: unknown): value is RemoteUiFrame {\n if (!isRecord(value) || value.v !== REMOTE_UI_PROTOCOL_VERSION) return false;\n if (value.kind === \"control\") {\n if (value.contextRevision !== undefined && (!Number.isInteger(value.contextRevision) || (value.contextRevision as number) < 1)) return false;\n return typeof value.action === \"string\" &&\n REMOTE_UI_CONTROL_ACTIONS.has(value.action as RemoteUiControlFrame[\"action\"]);\n }\n if (value.kind !== \"open\" && value.kind !== \"frame\" && value.kind !== \"close\") return false;\n if (typeof value.surfaceId !== \"string\" || value.surfaceId.length === 0 || value.surfaceId.length > 256) return false;\n if (!Number.isInteger(value.revision) || (value.revision as number) < 0) return false;\n if (typeof value.role !== \"string\" || !REMOTE_UI_ROLES.has(value.role as RemoteUiRole)) return false;\n if (value.contextRevision !== undefined && (!Number.isInteger(value.contextRevision) || (value.contextRevision as number) < 1)) return false;\n if (value.focused !== undefined && typeof value.focused !== \"boolean\") return false;\n if (value.lines !== undefined) {\n if (!Array.isArray(value.lines) || value.lines.length > REMOTE_UI_MAX_LINES) return false;\n if (!value.lines.every((line) => typeof line === \"string\" && line.length <= REMOTE_UI_MAX_LINE_LENGTH)) return false;\n }\n return true;\n}\n\nfunction isRemoteUiInput(value: unknown): value is RemoteUiInput {\n if (!isRecord(value) || value.v !== REMOTE_UI_PROTOCOL_VERSION) return false;\n if (value.kind !== \"input\" && value.kind !== \"resize\" && value.kind !== \"setText\" && value.kind !== \"close\") return false;\n if (typeof value.surfaceId !== \"string\" || value.surfaceId.length === 0 || value.surfaceId.length > 256) return false;\n if (!Number.isInteger(value.sequence) || (value.sequence as number) < 0) return false;\n if (!Number.isInteger(value.width) || (value.width as number) < 1 || (value.width as number) > 1000) return false;\n if (!Number.isInteger(value.height) || (value.height as number) < 1 || (value.height as number) > 1000) return false;\n if (value.data !== undefined && (typeof value.data !== \"string\" || value.data.length > REMOTE_UI_MAX_LINE_LENGTH)) return false;\n if (value.events !== undefined) {\n if (!Array.isArray(value.events) || value.events.length > 64) return false;\n if (!value.events.every((event) => typeof event === \"string\" && event.length <= REMOTE_UI_MAX_LINE_LENGTH)) return false;\n }\n return true;\n}\n","/**\n * Mid-stream reattach self-heal for InteractiveMode (§6.3).\n *\n * After reconnect/rebind, InteractiveMode clears its private `streamingComponent` and rebuilds\n * from completed session entries only. Live `message_update` / `message_end` events only paint\n * when that component already exists — and it is created solely on `message_start`. The\n * in-flight assistant generation never re-emits `message_start`, so without this adapter the\n * TUI freezes until the user aborts and starts a new turn.\n *\n * Pi 0.84 no longer sends cumulative updates. RpcClientBase restores them from deltas during\n * ordinary streaming, while shim v7 retains one cumulative snapshot across a detached gap.\n * This adapter synthesizes the missing `message_start` from that recovered snapshot (or from\n * a terminal `message_end` if the generation finished during the rebind gap).\n */\nexport class StreamHeal {\n private needsHeal = false;\n\n /** True after a rebind that found the pod still mid-turn, until the first heal or a boundary. */\n get armed(): boolean {\n return this.needsHeal;\n }\n\n /**\n * Arm after the TUI has rebound. Only `isStreaming` matters: compaction uses different\n * events, and completed assistant steps are already in the session snapshot.\n */\n arm(isStreaming: boolean): void {\n this.needsHeal = isStreaming;\n }\n\n /** Disarm without emitting — used when a natural stream boundary arrives. */\n disarm(): void {\n this.needsHeal = false;\n }\n\n /**\n * Expand one inbound agent event into the events the TUI should see.\n * At most one synthetic `message_start` is ever prepended per arm cycle.\n */\n expand(event: unknown): unknown[] {\n const typed = event as { type?: string; message?: { role?: string } } | null;\n const type = typed?.type;\n if (typeof type !== \"string\") return [event];\n\n if (type === \"message_start\" && typed?.message?.role === \"assistant\") {\n this.needsHeal = false;\n return [event];\n }\n\n // A new turn or a settled/ended turn owns its own start; drop a stale arm.\n if (type === \"agent_start\" || type === \"agent_end\" || type === \"agent_settled\") {\n this.needsHeal = false;\n return [event];\n }\n\n if (\n this.needsHeal &&\n (type === \"message_update\" || type === \"message_end\") &&\n typed?.message?.role === \"assistant\"\n ) {\n this.needsHeal = false;\n return [{ type: \"message_start\", message: typed.message }, event];\n }\n\n return [event];\n }\n}\n","import WebSocket, { type RawData } from \"ws\";\nimport { CancelledError, PiPodError } from \"../errors.js\";\nimport type {\n RemoteAuthEvent,\n RemoteAuthInteraction,\n RemoteAuthPrompt,\n RemoteAuthType,\n} from \"../client/runtime/auth-bridge.js\";\nimport {\n credentialProtocolError,\n type AccountClient,\n type CredentialStatus,\n} from \"./api.js\";\n\nexport interface RunCredentialLoginOptions {\n client: AccountClient;\n providerId: string;\n authType: RemoteAuthType;\n podId?: string;\n interaction: RemoteAuthInteraction;\n createWebSocket?: (url: string) => WebSocket;\n}\n\n/** Run one provider-scoped account login over its one-shot WebSocket ticket. */\nexport async function runCredentialLogin(\n opts: RunCredentialLoginOptions,\n): Promise<CredentialStatus> {\n if (opts.interaction.signal?.aborted) throw new CancelledError(\"Credential login cancelled\");\n const ticket = await opts.client.createCredentialLoginTicket(opts.providerId, {\n authType: opts.authType,\n ...(opts.podId ? { podId: opts.podId } : {}),\n });\n const url = opts.client.credentialLoginWsUrl(opts.providerId, ticket.ticket);\n let socket: WebSocket;\n try {\n socket = (opts.createWebSocket ?? ((target) => new WebSocket(target)))(url);\n } catch (error) {\n throw new PiPodError(`could not open the ${opts.providerId} credential login`, {\n cause: error,\n transient: true,\n });\n }\n\n return new Promise<CredentialStatus>((resolve, reject) => {\n let settled = false;\n let completed = false;\n let processing = Promise.resolve();\n\n const cleanup = (): void => {\n opts.interaction.signal?.removeEventListener(\"abort\", onAbort);\n };\n const finish = (outcome: { status: CredentialStatus } | { error: Error }): void => {\n if (settled) return;\n settled = true;\n cleanup();\n if (\"status\" in outcome) resolve(outcome.status);\n else reject(outcome.error);\n };\n const closeSocket = (): void => {\n try {\n socket.close();\n } catch {\n // A socket that failed while connecting is already unusable.\n }\n };\n const sendCancel = (): void => {\n if (socket.readyState !== WebSocket.OPEN) return;\n try {\n socket.send(JSON.stringify({ type: \"cancel\" }));\n } catch {\n // Closing the socket has the same cancellation semantics.\n }\n };\n const fail = (error: unknown): void => {\n if (settled) return;\n sendCancel();\n finish({ error: error instanceof Error ? error : new PiPodError(String(error)) });\n closeSocket();\n };\n const onAbort = (): void => {\n if (settled) return;\n sendCancel();\n finish({ error: new CancelledError(\"Credential login cancelled\") });\n closeSocket();\n };\n\n const handleFrame = async (raw: RawData): Promise<void> => {\n if (settled) return;\n const frame = parseFrame(raw);\n if (frame.type === \"prompt\") {\n const prompt: RemoteAuthPrompt = {\n ...frame.prompt,\n ...(opts.interaction.signal ? { signal: opts.interaction.signal } : {}),\n };\n const value = await opts.interaction.prompt(prompt);\n if (settled) return;\n socket.send(JSON.stringify({ type: \"response\", id: frame.id, value }));\n return;\n }\n if (frame.type === \"event\") {\n // Match the in-pod auth bridge: unsafe URL-bearing events are consumed, never shown.\n if (frame.event) opts.interaction.notify(frame.event);\n return;\n }\n completed = true;\n if (frame.ok) {\n finish({ status: frame.status });\n } else {\n finish({\n error: frame.error.code === \"cancelled\"\n ? new CancelledError(frame.error.message ?? \"Credential login cancelled\")\n : credentialProtocolError(\n frame.error.code,\n frame.error.message,\n opts.providerId,\n ),\n });\n }\n closeSocket();\n };\n\n socket.on(\"message\", (raw) => {\n processing = processing.then(() => handleFrame(raw)).catch(fail);\n });\n socket.on(\"error\", (error) => {\n fail(new PiPodError(`the ${opts.providerId} credential login connection failed`, {\n cause: error,\n transient: true,\n }));\n });\n socket.on(\"close\", (code) => {\n void processing.finally(() => {\n if (!settled && !completed) {\n fail(new PiPodError(\n code === 4001\n ? \"the credential login ticket was invalid or expired\"\n : `the ${opts.providerId} credential login closed before it completed`,\n { transient: code !== 4001 },\n ));\n }\n });\n });\n\n if (opts.interaction.signal?.aborted) onAbort();\n else opts.interaction.signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\ntype LoginFrame =\n | { type: \"prompt\"; id: string; prompt: RemoteAuthPrompt }\n | { type: \"event\"; event: RemoteAuthEvent | null }\n | { type: \"done\"; ok: true; status: CredentialStatus }\n | { type: \"done\"; ok: false; error: { code: string; message?: string } };\n\nfunction parseFrame(raw: RawData): LoginFrame {\n let value: unknown;\n try {\n value = JSON.parse(raw.toString());\n } catch {\n throw new PiPodError(\"the credential login server sent invalid JSON\");\n }\n if (!isRecord(value) || typeof value[\"type\"] !== \"string\") {\n throw new PiPodError(\"the credential login server sent an invalid frame\");\n }\n if (value[\"type\"] === \"prompt\") {\n if (typeof value[\"id\"] !== \"string\") throw new PiPodError(\"the credential login server sent an invalid prompt id\");\n return { type: \"prompt\", id: value[\"id\"], prompt: parsePrompt(value[\"prompt\"]) };\n }\n if (value[\"type\"] === \"event\") {\n return { type: \"event\", event: parseEvent(value[\"event\"]) };\n }\n if (value[\"type\"] === \"done\") {\n if (value[\"ok\"] === true) {\n return { type: \"done\", ok: true, status: parseCredentialStatus(value[\"status\"]) };\n }\n if (value[\"ok\"] === false && isRecord(value[\"error\"]) && typeof value[\"error\"][\"code\"] === \"string\") {\n const message = value[\"error\"][\"message\"];\n if (message !== undefined && typeof message !== \"string\") {\n throw new PiPodError(\"the credential login server sent an invalid error\");\n }\n return {\n type: \"done\",\n ok: false,\n error: {\n code: value[\"error\"][\"code\"],\n ...(typeof message === \"string\" ? { message } : {}),\n },\n };\n }\n }\n throw new PiPodError(\"the credential login server sent an invalid frame\");\n}\n\nfunction parsePrompt(value: unknown): RemoteAuthPrompt {\n if (!isRecord(value) || ![\"text\", \"secret\", \"manual_code\", \"select\"].includes(String(value[\"type\"])) || typeof value[\"message\"] !== \"string\") {\n throw new PiPodError(\"the credential login server sent an invalid prompt\");\n }\n if (value[\"placeholder\"] !== undefined && typeof value[\"placeholder\"] !== \"string\") {\n throw new PiPodError(\"the credential login server sent an invalid prompt placeholder\");\n }\n const type = value[\"type\"] as RemoteAuthPrompt[\"type\"];\n if (type === \"select\") {\n if (!Array.isArray(value[\"options\"])) throw new PiPodError(\"the credential login server sent invalid select options\");\n const options = value[\"options\"].map((option) => {\n if (!isRecord(option) || typeof option[\"id\"] !== \"string\" || typeof option[\"label\"] !== \"string\" || (option[\"description\"] !== undefined && typeof option[\"description\"] !== \"string\")) {\n throw new PiPodError(\"the credential login server sent invalid select options\");\n }\n return {\n id: option[\"id\"],\n label: option[\"label\"],\n ...(typeof option[\"description\"] === \"string\" ? { description: option[\"description\"] } : {}),\n };\n });\n return { type, message: value[\"message\"], options };\n }\n return {\n type,\n message: value[\"message\"],\n ...(typeof value[\"placeholder\"] === \"string\" ? { placeholder: value[\"placeholder\"] } : {}),\n };\n}\n\nfunction parseEvent(value: unknown): RemoteAuthEvent | null {\n if (!isRecord(value) || typeof value[\"type\"] !== \"string\") {\n throw new PiPodError(\"the credential login server sent an invalid event\");\n }\n if (value[\"type\"] === \"auth_url\") {\n if (!isSafeAuthUrl(value[\"url\"])) return null;\n if (value[\"instructions\"] !== undefined && typeof value[\"instructions\"] !== \"string\") throw new PiPodError(\"the credential login server sent invalid instructions\");\n return {\n type: \"auth_url\",\n url: value[\"url\"],\n ...(typeof value[\"instructions\"] === \"string\" ? { instructions: value[\"instructions\"] } : {}),\n };\n }\n if (value[\"type\"] === \"device_code\") {\n if (typeof value[\"userCode\"] !== \"string\" || !isSafeAuthUrl(value[\"verificationUri\"])) return null;\n if (value[\"intervalSeconds\"] !== undefined && typeof value[\"intervalSeconds\"] !== \"number\") throw new PiPodError(\"the credential login server sent an invalid device code\");\n if (value[\"expiresInSeconds\"] !== undefined && typeof value[\"expiresInSeconds\"] !== \"number\") throw new PiPodError(\"the credential login server sent an invalid device code\");\n return {\n type: \"device_code\",\n userCode: value[\"userCode\"],\n verificationUri: value[\"verificationUri\"],\n ...(typeof value[\"intervalSeconds\"] === \"number\" ? { intervalSeconds: value[\"intervalSeconds\"] } : {}),\n ...(typeof value[\"expiresInSeconds\"] === \"number\" ? { expiresInSeconds: value[\"expiresInSeconds\"] } : {}),\n };\n }\n if (value[\"type\"] === \"info\") {\n if (typeof value[\"message\"] !== \"string\") throw new PiPodError(\"the credential login server sent an invalid info event\");\n if (value[\"links\"] === undefined) return { type: \"info\", message: value[\"message\"] };\n if (!Array.isArray(value[\"links\"])) throw new PiPodError(\"the credential login server sent invalid links\");\n const links: Array<{ url: string; label?: string }> = [];\n for (const link of value[\"links\"]) {\n if (!isRecord(link) || (link[\"label\"] !== undefined && typeof link[\"label\"] !== \"string\")) throw new PiPodError(\"the credential login server sent invalid links\");\n if (!isSafeAuthUrl(link[\"url\"])) return null;\n links.push({\n url: link[\"url\"],\n ...(typeof link[\"label\"] === \"string\" ? { label: link[\"label\"] } : {}),\n });\n }\n return { type: \"info\", message: value[\"message\"], links };\n }\n if (value[\"type\"] === \"progress\" && typeof value[\"message\"] === \"string\") {\n return { type: \"progress\", message: value[\"message\"] };\n }\n throw new PiPodError(\"the credential login server sent an invalid event\");\n}\n\nfunction parseCredentialStatus(value: unknown): CredentialStatus {\n if (!isRecord(value) || typeof value[\"providerId\"] !== \"string\" || (value[\"type\"] !== \"oauth\" && value[\"type\"] !== \"api_key\") || typeof value[\"revision\"] !== \"number\") {\n throw new PiPodError(\"the credential login server sent an invalid credential status\");\n }\n const base: Pick<CredentialStatus, \"providerId\" | \"type\" | \"revision\"> = {\n providerId: value[\"providerId\"],\n type: value[\"type\"],\n revision: value[\"revision\"],\n };\n if (value[\"state\"] === \"ready\") {\n if ((value[\"expiresAt\"] !== undefined && typeof value[\"expiresAt\"] !== \"string\") || (value[\"lastRefreshAt\"] !== undefined && typeof value[\"lastRefreshAt\"] !== \"string\")) throw new PiPodError(\"the credential login server sent an invalid ready status\");\n return {\n ...base,\n state: \"ready\",\n ...(typeof value[\"expiresAt\"] === \"string\" ? { expiresAt: value[\"expiresAt\"] } : {}),\n ...(typeof value[\"lastRefreshAt\"] === \"string\" ? { lastRefreshAt: value[\"lastRefreshAt\"] } : {}),\n };\n }\n if (value[\"state\"] === \"reconnect_required\" && [\"revoked\", \"invalid_grant\", \"missing_refresh_token\", \"migration_required\"].includes(String(value[\"reason\"]))) {\n return { ...base, state: \"reconnect_required\", reason: value[\"reason\"] as \"revoked\" | \"invalid_grant\" | \"missing_refresh_token\" | \"migration_required\" };\n }\n if (value[\"state\"] === \"temporarily_unavailable\") {\n if (value[\"retryAfter\"] !== undefined && typeof value[\"retryAfter\"] !== \"string\") throw new PiPodError(\"the credential login server sent an invalid temporary status\");\n return {\n ...base,\n state: \"temporarily_unavailable\",\n ...(typeof value[\"retryAfter\"] === \"string\" ? { retryAfter: value[\"retryAfter\"] } : {}),\n };\n }\n throw new PiPodError(\"the credential login server sent an invalid credential status\");\n}\n\nfunction isSafeAuthUrl(value: unknown): value is string {\n if (typeof value !== \"string\") return false;\n try {\n const url = new URL(value);\n return url.protocol === \"https:\" || (url.protocol === \"http:\" && (url.hostname === \"localhost\" || url.hostname === \"127.0.0.1\" || url.hostname === \"::1\" || url.hostname === \"[::1]\"));\n } catch {\n return false;\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n","/**\n * src/account/gateway-rpc.ts — GatewayRpcClient (account-mode-spec §6).\n *\n * The account-mode transport for pi's RPC surface: instead of terminating pod frames\n * itself, the CLI multiplexes through the gateway's single RPC connection over the same\n * JSON WebSocket iOS uses, extended with a generic `rpc`/`rpc_result` passthrough. Full TUI\n * fidelity comes from three facts: commands keep this client's unique-prefixed ids (so\n * id-correlated event streams line up), every agent event is fanned out verbatim, and shim\n * control events (pi exit, stderr) are forwarded live.\n *\n * Reconnects are internal: an abnormal socket drop re-mints a ticket and re-attaches\n * through one backoff loop, then reports through `onRecovered` so the runtime can re-sync\n * state. Connection *state* is reported separately via `onConnectionState` so the session\n * driver can render it; the transport itself never writes to the screen.\n */\nimport { randomBytes, randomUUID } from \"node:crypto\";\nimport WebSocket from \"ws\";\nimport type { RpcCommand, RpcExtensionUIResponse } from \"@earendil-works/pi-coding-agent\";\nimport { RECOVERY_FLAP_LIMIT, RECOVERY_FLAP_WINDOW_MS, verifyHelloEnvelope } from \"../client/compat.js\";\nimport { bundledPiVersion } from \"../client/piversion.js\";\nimport type { ShimControlEvent, ShimHello } from \"../client/protocol.js\";\nimport { RpcClientBase, type RpcRequestOptions, type ThinkingLevel } from \"../client/rpc.js\";\nimport { isRestoreRequiredError, PiPodError, PodAsleepError } from \"../errors.js\";\nimport { debug, step } from \"../log.js\";\nimport {\n ASLEEP_REASONS,\n asleepReasonFromError,\n classifyAttachError,\n connectionStateKey,\n CONNECT_NOTICE_MS,\n CONNECT_TIMEOUT_MS,\n DROP_RECOVERY_MS,\n DROP_RETRY_DELAY_MS,\n GATEWAY_RESTART_RECOVERY_MS,\n GATEWAY_RESTART_RETRY_DELAY_MS,\n INITIAL_ATTACH_RETRY_BUDGET_MS,\n INITIAL_ATTACH_RETRY_DELAY_MS,\n INITIAL_ATTACH_RETRY_MAX_DELAY_MS,\n isAsleepClose,\n isGatewayRestartClose,\n isPiExitClose,\n isSupersededError,\n isWakeTrigger,\n KEEP_RETRYING_INTERVAL_MS,\n LEASE_RETRY_DELAY_MS,\n PING_INTERVAL_MS,\n PONG_DEADLINE_MS,\n RECOVERY_RETRY_MAX_MS,\n SEMANTIC_REQUEST_TIMEOUT_MS,\n SYNTHETIC_EVENT_KINDS,\n type ConnectionState,\n type GatewayRpcOptions,\n type RecoverCause,\n type ServerHello,\n} from \"./gateway-rpc-codec.js\";\nimport { displayRef } from \"./ref.js\";\nimport {\n isWorkstationCloseReason,\n withWorkstationWait,\n workstationCloseError,\n workstationDemandOf,\n workstationErrorFromSessionMessage,\n} from \"./workstation.js\";\n\nexport {\n ASLEEP_CLOSE_CODE,\n ASLEEP_REASONS,\n classifyAttachError,\n CONNECT_TIMEOUT_MS,\n DROP_RECOVERY_MS,\n GATEWAY_HELLO_BUDGET_MS,\n GATEWAY_PROVIDER_START_BUDGET_MS,\n GATEWAY_RESTART_RECOVERY_MS,\n GATEWAY_RESTART_RETRY_DELAY_MS,\n INITIAL_ATTACH_RETRY_BUDGET_MS,\n INITIAL_ATTACH_RETRY_DELAY_MS,\n INITIAL_ATTACH_RETRY_MAX_DELAY_MS,\n isAsleepClose,\n isGatewayRestartClose,\n isPiExitClose,\n isRetryableAttachError,\n isRetryableGatewayRestartError,\n KEEP_RETRYING_INTERVAL_MS,\n PING_INTERVAL_MS,\n PI_EXIT_CLOSE_CODE,\n PONG_DEADLINE_MS,\n RECOVERY_RETRY_MAX_MS,\n} from \"./gateway-rpc-codec.js\";\nexport type { AttachErrorClass, ConnectionState, GatewayRpcOptions, RecoverCause } from \"./gateway-rpc-codec.js\";\n\n/** A compatibility probe must not hold startup for the classic RPC query's full minute. */\nexport const GATEWAY_MODELS_TIMEOUT_MS = 5_000;\n\nexport interface GatewayModelsSnapshot {\n models: unknown[];\n current: unknown;\n thinkingLevel: ThinkingLevel;\n thinkingLevels: ThinkingLevel[];\n}\n\nexport interface SessionCatalogEntry {\n id: string;\n createdAt: number;\n cwd?: string;\n parentSessionId?: string;\n name?: string;\n modified?: number;\n messageCount?: number;\n firstMessage?: string;\n /** Pod-side session file path; a legacy switch handle, not durable identity. */\n path?: string;\n}\n\nexport interface SessionSearchHit {\n sessionId: string;\n score?: number;\n top?: { entryId?: string; snippet?: string; timestamp: number };\n}\n\nexport interface SessionsFrame {\n sessions: SessionCatalogEntry[];\n workdir: string;\n complete: boolean;\n unsupported?: true;\n}\n\nexport interface SessionHitsFrame {\n hits: SessionSearchHit[];\n unsupported?: true;\n}\n\nexport interface ResourcesReloadedFrame {\n ok: boolean;\n unsupported?: true;\n}\n\n/** Mirrors the pod's own result cap; a longer list is a peer not honouring the v1 contract. */\nexport const FILE_LIST_MAX_ENTRIES = 50;\n/** Long enough for any real path, short enough that one cannot flood the editor. */\nexport const FILE_LIST_MAX_PATH_LENGTH = 1024;\n/** Matches the pod's query cap, so an over-long query is refused before it reaches the wire. */\nexport const FILE_LIST_MAX_QUERY_LENGTH = 512;\n\nexport interface FileListEntry {\n path: string;\n dir: boolean;\n}\n\nexport interface FilesFrame {\n entries: FileListEntry[];\n complete: boolean;\n unsupported?: true;\n}\n\n/** The pod's local-TUI config manifest, still untrusted: pod-manifest.ts validates it. */\nexport interface TuiManifestFrame {\n digest?: string;\n unchanged?: true;\n manifest?: Record<string, unknown>;\n unsupported?: true;\n}\n\n/** One auxiliary completion: a turn-external model call executed pod-side with real auth. */\nexport interface AuxCompleteWireRequest {\n provider: string;\n model: string;\n systemPrompt?: string;\n messages: Array<{ role: \"user\" | \"assistant\"; content: string }>;\n thinkingLevel?: ThinkingLevel;\n maxTokens?: number;\n /** Caller deadline; the gateway answers by it (ok or timeout error). */\n timeoutMs?: number;\n}\n\nexport interface AuxCompleteWireResult {\n text: string;\n stopReason: string;\n usage: unknown;\n}\n\n/** Hard ceiling: the gateway answers by min(timeoutMs, AUX_GATEWAY_TIMEOUT_CAP_MS). */\nexport const AUX_GATEWAY_TIMEOUT_CAP_MS = 120_000;\n/**\n * Client-side backstop past the caller's own deadline. The gateway always answers first\n * (its timer fires at timeoutMs), so this only covers a broken gateway — small enough\n * that an old server without aux support fails in ~timeoutMs, not minutes.\n */\nexport const AUX_CLIENT_SLACK_MS = 2_000;\n\ntype SemanticReplyType = \"sessions\" | \"session_hits\" | \"resources_reloaded\" | \"files\" | \"tui_manifest\";\n\ninterface PendingSemanticReply {\n timer: NodeJS.Timeout;\n accept(value: unknown): void;\n}\n\ninterface PendingAux {\n resolve(value: AuxCompleteWireResult): void;\n reject(error: Error): void;\n timer: NodeJS.Timeout;\n signal?: AbortSignal;\n onAbort?: () => void;\n}\n\nfunction clearPendingAux(map: Map<string, PendingAux>, id: string): PendingAux | undefined {\n const pending = map.get(id);\n if (!pending) return undefined;\n map.delete(id);\n clearTimeout(pending.timer);\n if (pending.signal && pending.onAbort) pending.signal.removeEventListener(\"abort\", pending.onAbort);\n return pending;\n}\n\nexport class GatewayRpcClient extends RpcClientBase {\n private currentPodId: string;\n private ws: WebSocket | null = null;\n private readonly connectingSockets = new Set<WebSocket>();\n private serverHello: ServerHello | null = null;\n private pingTimer: NodeJS.Timeout | null = null;\n private lastActivityAt = 0;\n private keepRetrying = false;\n private keepRetryKick: (() => void) | null = null;\n private lastSeq = 0;\n private lastSessionId: string | null = null;\n private readonly seenSeqs = new Set<number>();\n private replayHold: Promise<void> = Promise.resolve();\n private lastMutation: { requestId: string; command: Record<string, unknown>; sessionId: string } | null = null;\n private userClosed = false;\n private recovering = false;\n private waking = false;\n private queuedRecovery: {\n code: number;\n reason: string;\n cause: RecoverCause;\n generation: number;\n podId: string;\n } | null = null;\n private connectionGeneration = 0;\n private recoveredAt: number[] = [];\n private connectionState: ConnectionState | null = null;\n private asleepReason: string | null = null;\n /** False between adopting a skewed hello and readiness replacing it; ordinary RPC is gated. */\n private piVersionReady = false;\n private readonly idPrefix = `cli-${randomBytes(4).toString(\"hex\")}-`;\n private modelsRequest: {\n promise: Promise<GatewayModelsSnapshot>;\n resolve: (snapshot: GatewayModelsSnapshot) => void;\n reject: (error: Error) => void;\n timer: NodeJS.Timeout;\n } | null = null;\n private readonly pendingSemantic = new Map<SemanticReplyType, PendingSemanticReply>();\n /** Auxiliary completions multiplex by caller id — unlike single-slot semantic queries. */\n private readonly pendingAux = new Map<string, PendingAux>();\n\n private constructor(private readonly opts: GatewayRpcOptions) {\n super();\n this.currentPodId = opts.podId;\n }\n\n /** Session id on the server, for transcripts and diagnostics. */\n get sessionId(): string | null {\n return this.serverHello?.sessionId ?? null;\n }\n\n get podId(): string {\n return this.currentPodId;\n }\n\n /** Pi this gateway will treat as current. Null when the server omitted it (older gateways). */\n get serverPiVersion(): string | null {\n const value = this.serverHello?.serverPiVersion;\n return typeof value === \"string\" && value.length > 0 ? value : null;\n }\n\n get currentConnectionState(): ConnectionState | null {\n return this.connectionState;\n }\n\n /**\n * Re-target this client at another server pod (account-mode-spec §6.2): the runtime keeps\n * its rpc reference, only the socket underneath changes. A transient failure on the target\n * reattaches to the previous pod so the TUI is never left detached.\n */\n async switchTo(podId: string): Promise<void> {\n const previousPodId = this.currentPodId;\n this.connectionGeneration += 1;\n this.asleepReason = null;\n this.keepRetrying = false;\n for (const socket of this.connectingSockets) {\n try {\n socket.close(1000, \"switch\");\n } catch {\n // Still opening or already gone.\n }\n }\n const previous = this.ws;\n this.ws = null; // The close handler ignores sockets it no longer owns.\n try {\n previous?.close(1000, \"switch\");\n } catch {\n // Already gone.\n }\n this.rejectPending(new Error(\"connection to the pi session was replaced\"));\n this.rejectModelsRequest(new Error(\"connection to the pi session was replaced\"));\n this.rejectAuxRequests(new Error(\"connection to the pi session was replaced\"));\n this.emitLifecycleInvalidation(new Error(\"connection to the pi session was replaced\"));\n this.resetHandshakeState(podId);\n try {\n await this.attachWithBudget({\n generation: this.connectionGeneration,\n podId,\n budgetMs: this.initialAttachBudget(),\n initialDelayMs: this.initialAttachDelay(),\n maxDelayMs: this.initialAttachMaxDelay(),\n });\n } catch (e) {\n const error = e instanceof Error ? e : new Error(String(e));\n if (isSupersededError(error) || this.userClosed) throw error;\n await this.reattachAfterFailedSwitch(previousPodId, error);\n }\n const hello = this.helloInfo;\n if (!hello) throw new PiPodError(\"the server session carried no pod handshake\");\n this.emitConnectionState({ kind: \"connected\" });\n }\n\n\n static async connect(opts: GatewayRpcOptions): Promise<GatewayRpcClient> {\n const client = new GatewayRpcClient(opts);\n await client.attachWithBudget({\n generation: client.connectionGeneration,\n podId: client.currentPodId,\n budgetMs: client.initialAttachBudget(),\n initialDelayMs: client.initialAttachDelay(),\n maxDelayMs: client.initialAttachMaxDelay(),\n // Cold launch can spend minutes waking a provider; later attempts and reattach cap to remaining budget.\n longFirstHello: true,\n });\n client.emitConnectionState({ kind: \"connected\" });\n client.startPingWatchdog();\n return client;\n }\n\n /** Stop and reattach this instance, invalidating the old socket before the lifecycle change. */\n async restartAfterStop(stop: () => Promise<void>): Promise<ShimHello> {\n const podId = this.currentPodId;\n this.connectionGeneration += 1;\n this.asleepReason = null;\n this.keepRetrying = false;\n for (const socket of this.connectingSockets) {\n try {\n socket.close(1000, \"pi update\");\n } catch {\n // Still opening or already gone.\n }\n }\n const previous = this.ws;\n this.ws = null;\n try {\n previous?.close(1000, \"pi update\");\n } catch {\n // Already gone.\n }\n this.rejectPending(new Error(\"the pi session is restarting after an update\"));\n this.rejectModelsRequest(new Error(\"the pi session is restarting after an update\"));\n this.rejectAuxRequests(new Error(\"the pi session is restarting after an update\"));\n this.emitLifecycleInvalidation(new Error(\"the pi session is restarting after an update\"));\n this.resetHandshakeState(podId);\n await stop();\n await this.attachWithBudget({\n generation: this.connectionGeneration,\n podId,\n budgetMs: this.initialAttachBudget(),\n initialDelayMs: this.initialAttachDelay(),\n maxDelayMs: this.initialAttachMaxDelay(),\n longFirstHello: true,\n });\n const hello = this.helloInfo;\n if (!hello) throw new PiPodError(\"the restarted session carried no pod handshake\");\n this.emitConnectionState({ kind: \"connected\" });\n return hello;\n }\n\n\n /**\n * Ids must be unique across every client sharing the pi session — the gateway forwards\n * them verbatim (account-mode-spec §6.1), so a bare counter would collide with the\n * gateway's own or another CLI's.\n */\n protected override requestIdPrefix(): string {\n return this.idPrefix;\n }\n\n protected askForHello(): void {\n // The server pushes the shim hello inside its own hello message; nothing to ask.\n }\n\n /** Quitting pi from one surface would kill the session for every other; detach instead. */\n shutdown(): void {\n debug(\"gateway-rpc: shutdown() ignored — account-mode sessions detach; lifecycle is server-owned\");\n }\n\n respondExtensionUi(response: RpcExtensionUIResponse): void {\n this.wsSend({ type: \"ui_response\", response });\n }\n\n /** Query the gateway's semantic model surface; old servers time out without blocking forever. */\n getModels(timeoutMs = GATEWAY_MODELS_TIMEOUT_MS): Promise<GatewayModelsSnapshot> {\n if (this.modelsRequest) return this.modelsRequest.promise;\n\n let resolve!: (snapshot: GatewayModelsSnapshot) => void;\n let reject!: (error: Error) => void;\n const promise = new Promise<GatewayModelsSnapshot>((onResolve, onReject) => {\n resolve = onResolve;\n reject = onReject;\n });\n const timer = setTimeout(\n () => this.rejectModelsRequest(new Error(\"timed out waiting for the gateway model catalog\")),\n timeoutMs,\n );\n this.modelsRequest = { promise, resolve, reject, timer };\n try {\n this.wsSend({ type: \"get_models\" });\n } catch (error) {\n this.rejectModelsRequest(error instanceof Error ? error : new Error(String(error)));\n }\n return promise;\n }\n\n /** List pod-side sessions. A timeout or unsupported marker is an absent capability. */\n getSessions(): Promise<SessionsFrame> {\n const absent: SessionsFrame = { sessions: [], workdir: \"\", complete: false, unsupported: true };\n return this.semanticRequest(\"sessions\", { type: \"get_sessions\" }, absent);\n }\n\n /** Search remains pod-side so transcript text never crosses the catalog boundary. */\n searchSessions(text: string, limit?: number): Promise<SessionHitsFrame> {\n const absent: SessionHitsFrame = { hits: [], unsupported: true };\n return this.semanticRequest(\n \"session_hits\",\n { type: \"search_sessions\", text, ...(limit !== undefined ? { limit } : {}) },\n absent,\n );\n }\n\n /**\n * Complete an `@` path against the pod's workspace. Superseding rather than coalescing:\n * each keystroke asks a different question, so an in-flight answer to the previous prefix\n * is not an answer to this one. Never rejects — an absent capability, a slow pod and a\n * malformed reply all mean \"no suggestions\", which is what the caller renders.\n */\n getFiles(query: string): Promise<FilesFrame> {\n const absent: FilesFrame = { entries: [], complete: false, unsupported: true };\n if (query.length > FILE_LIST_MAX_QUERY_LENGTH) return Promise.resolve(absent);\n return this.semanticRequest(\"files\", { type: \"get_files\", query }, absent, { supersede: true });\n }\n\n /** Ask the pod runtime to re-resolve extensions, skills, prompts, themes, and context files. */\n reloadResources(): Promise<ResourcesReloadedFrame> {\n const absent: ResourcesReloadedFrame = { ok: false, unsupported: true };\n return this.semanticRequest(\"resources_reloaded\", { type: \"reload_resources\" }, absent);\n }\n\n /**\n * Fetch the pod's local-TUI config manifest (shim v13). Callers gate on the shim version\n * before asking, so an old deployment never burns the semantic timeout here.\n */\n getTuiManifest(knownDigest?: string): Promise<TuiManifestFrame> {\n const absent: TuiManifestFrame = { unsupported: true };\n return this.semanticRequest(\n \"tui_manifest\",\n { type: \"get_tui_manifest\", ...(knownDigest !== undefined ? { knownDigest } : {}) },\n absent,\n );\n }\n\n /**\n * Run one turn-external completion pod-side (semantic gateway message `aux_complete`).\n * The pod's authenticated registry executes it: no transcript entries, no model change,\n * no Tripwire on the main turn. Each call has its own id, deadline and AbortSignal —\n * aborting sends `aux_cancel` and fails only this call. An old gateway that never\n * answers surfaces as a timeout with an actionable message, never a hang.\n */\n auxComplete(request: AuxCompleteWireRequest, opts: { signal?: AbortSignal } = {}): Promise<AuxCompleteWireResult> {\n const id = randomUUID();\n if (opts.signal?.aborted) {\n return Promise.reject(this.auxAbortError(id, opts.signal.reason));\n }\n const timeoutMs = Math.min(request.timeoutMs ?? 60_000, AUX_GATEWAY_TIMEOUT_CAP_MS);\n return new Promise<AuxCompleteWireResult>((resolve, reject) => {\n const fail = (error: Error): void => {\n const pending = clearPendingAux(this.pendingAux, id);\n if (!pending) return;\n reject(error);\n };\n const onAbort = (): void => {\n try {\n this.wsSend({ type: \"aux_cancel\", id });\n } catch {\n // The transport is already gone; the gateway cleans up session-side instead.\n }\n fail(this.auxAbortError(id, opts.signal?.reason));\n };\n const timer = setTimeout(() => {\n try {\n this.wsSend({ type: \"aux_cancel\", id });\n } catch {\n // Best effort: the gateway's own deadline answers anyway.\n }\n fail(\n new PiPodError(\n `auxiliary completion timed out after ${Math.round((timeoutMs + AUX_CLIENT_SLACK_MS) / 1000)}s` +\n ` — the server may predate aux support (update the server) or the pod may be unreachable`,\n { code: \"aux_timeout\" },\n ),\n );\n }, timeoutMs + AUX_CLIENT_SLACK_MS);\n timer.unref?.();\n this.pendingAux.set(id, {\n resolve,\n reject,\n timer,\n ...(opts.signal ? { signal: opts.signal, onAbort } : {}),\n });\n opts.signal?.addEventListener(\"abort\", onAbort, { once: true });\n if (opts.signal?.aborted) {\n onAbort();\n return;\n }\n try {\n this.wsSend({\n type: \"aux_complete\",\n id,\n provider: request.provider,\n model: request.model,\n ...(request.systemPrompt !== undefined ? { systemPrompt: request.systemPrompt } : {}),\n messages: request.messages,\n ...(request.thinkingLevel !== undefined ? { thinkingLevel: request.thinkingLevel } : {}),\n ...(request.maxTokens !== undefined ? { maxTokens: request.maxTokens } : {}),\n timeoutMs,\n });\n } catch (error) {\n fail(error instanceof Error ? error : new Error(String(error)));\n }\n });\n }\n\n private auxAbortError(id: string, reason: unknown): Error {\n void id;\n if (reason instanceof Error) return reason;\n const error = new Error(typeof reason === \"string\" ? reason : \"auxiliary completion was aborted\");\n error.name = \"AbortError\";\n return error;\n }\n\n private acceptAuxResult(message: Record<string, unknown>): void {\n const id = message[\"id\"];\n if (typeof id !== \"string\") return;\n const pending = clearPendingAux(this.pendingAux, id);\n if (!pending) return;\n if (message[\"ok\"] === true) {\n const text = message[\"text\"];\n if (typeof text !== \"string\") {\n pending.reject(new PiPodError(\"auxiliary completion reply was malformed\", { code: \"aux_malformed\" }));\n return;\n }\n pending.resolve({\n text,\n stopReason: typeof message[\"stopReason\"] === \"string\" ? (message[\"stopReason\"] as string) : \"stop\",\n usage: message[\"usage\"] ?? null,\n });\n return;\n }\n const code = typeof message[\"code\"] === \"string\" ? (message[\"code\"] as string) : \"aux_failed\";\n const detail = typeof message[\"error\"] === \"string\" ? (message[\"error\"] as string) : \"auxiliary completion failed\";\n pending.reject(new PiPodError(detail, { code }));\n }\n\n private rejectAuxRequests(error: Error): void {\n if (this.pendingAux.size === 0) return;\n const ids = [...this.pendingAux.keys()];\n for (const id of ids) clearPendingAux(this.pendingAux, id)?.reject(error);\n }\n\n protected transmitCommand(command: RpcCommand & { id: string }): void {\n const outgoing = this.tagMutation(command);\n this.wsSend({ type: \"rpc\", id: String(outgoing[\"id\"]), command: outgoing });\n }\n\n private tagMutation(command: RpcCommand & { id: string }): Record<string, unknown> {\n if (!isWakeTrigger(command)) return command as unknown as Record<string, unknown>;\n const requestId = randomUUID();\n const tagged = { ...command, client_request_id: requestId } as unknown as Record<string, unknown>;\n this.lastMutation = {\n requestId,\n command: tagged,\n sessionId: this.serverHello?.sessionId ?? this.lastSessionId ?? \"\",\n };\n return tagged;\n }\n\n /** Readiness's two pre-runtime commands bypass the skew gate; no other caller can. */\n async readinessGetState(): Promise<import(\"@earendil-works/pi-coding-agent\").RpcSessionState> {\n const response = await super.request({ type: \"get_state\" });\n if (!response.success) throw new Error(response.error);\n return (response as { data: import(\"@earendil-works/pi-coding-agent\").RpcSessionState }).data;\n }\n\n async readinessBash(command: string): Promise<unknown> {\n const response = await super.request({ type: \"bash\", command, excludeFromContext: true });\n if (!response.success) throw new Error(response.error);\n const data = (response as { data?: { exitCode?: unknown; output?: unknown } }).data;\n if (typeof data?.exitCode !== \"number\" || data.exitCode !== 0) {\n const output = typeof data?.output === \"string\" ? data.output.trim().split(\"\\n\").at(-1) : undefined;\n throw new Error(`pi update command failed${output ? `: ${output}` : \"\"}`);\n }\n return data;\n }\n\n /** A prompt (or steer/follow-up) is an explicit user action: wake a sleeping pod and replay. */\n override async request(command: RpcCommand, options?: RpcRequestOptions) {\n if (this.shouldWakeFor(command)) await this.wake();\n if (!this.piVersionReady) {\n throw new PiPodError(\"pi version skew: the adopted pod handshake has not passed readiness\");\n }\n if (this.shouldKickLostReconnect(command)) {\n this.kickReconnect();\n await this.waitUntilConnected();\n }\n try {\n return await super.request(command, options);\n } catch (error) {\n if (this.shouldWakeFor(command) || (isWakeTrigger(command) && error instanceof PodAsleepError && !this.userClosed)) {\n await this.wake();\n return super.request(command, options);\n }\n throw error;\n }\n }\n\n private shouldKickLostReconnect(command: RpcCommand): boolean {\n return isWakeTrigger(command) && !this.userClosed && this.connectionState?.kind === \"lost\";\n }\n\n /** An explicit user action while lost skips the keep-trying sleep. */\n kickReconnect(): void {\n this.keepRetryKick?.();\n }\n\n\n private shouldWakeFor(command: RpcCommand): boolean {\n return isWakeTrigger(command) && !this.userClosed && this.asleepReason !== null;\n }\n\n protected override connectionClosedError(): Error {\n if (this.asleepReason !== null) return new PodAsleepError(this.asleepReason);\n return super.connectionClosedError();\n }\n\n /**\n * Reattach after a 4420 (or equivalent) sleep. The server wakes the sandbox on attach,\n * so this is the same path as a reconnect — just user-initiated, with wake-sized patience.\n */\n override async wake(): Promise<void> {\n if (this.userClosed) throw new PiPodError(\"connection to the pi session was closed\");\n if (!this.closed && this.ws?.readyState === WebSocket.OPEN) return;\n if (this.waking) {\n await this.waitUntilConnected();\n return;\n }\n this.waking = true;\n const generation = this.connectionGeneration;\n const podId = this.currentPodId;\n try {\n this.emitConnectionState({ kind: \"reconnecting\", attempt: 1, cause: \"drop\" });\n await this.attachWithBudget({\n generation,\n podId,\n // Archived sandboxes can take minutes; a stopped pod is usually seconds.\n budgetMs: this.opts.dropRecoveryMs ?? DROP_RECOVERY_MS,\n initialDelayMs: this.opts.dropRetryDelayMs ?? DROP_RETRY_DELAY_MS,\n maxDelayMs: RECOVERY_RETRY_MAX_MS,\n });\n if (!this.hasRecoveryAuthority(generation, podId)) {\n throw new Error(\"connection attempt was superseded\");\n }\n this.asleepReason = null;\n this.emitConnectionState({ kind: \"connected\" });\n await this.opts.onRecovered?.();\n } catch (e) {\n let error = e instanceof Error ? e : new Error(String(e));\n if (isRestoreRequiredError(error)) {\n try {\n await this.opts.client.podCommand(podId, \"restore\");\n } catch (restoreErr) {\n this.emitConnectionState({ kind: \"ended\", reason: \"restore_required\" });\n this.opts.onSessionEnded?.(\"restore_required\");\n throw restoreErr instanceof Error ? restoreErr : error;\n }\n try {\n await this.attachWithBudget({\n generation,\n podId,\n budgetMs: this.opts.dropRecoveryMs ?? DROP_RECOVERY_MS,\n initialDelayMs: this.opts.dropRetryDelayMs ?? DROP_RETRY_DELAY_MS,\n maxDelayMs: RECOVERY_RETRY_MAX_MS,\n });\n if (!this.hasRecoveryAuthority(generation, podId)) {\n throw new Error(\"connection attempt was superseded\");\n }\n this.asleepReason = null;\n this.emitConnectionState({ kind: \"connected\" });\n await this.opts.onRecovered?.();\n return;\n } catch (retryErr) {\n error = retryErr instanceof Error ? retryErr : new Error(String(retryErr));\n if (isRestoreRequiredError(error)) {\n this.emitConnectionState({ kind: \"ended\", reason: \"restore_required\" });\n this.opts.onSessionEnded?.(\"restore_required\");\n throw error;\n }\n }\n }\n const kind = classifyAttachError(error);\n if (kind === \"asleep\" || this.asleepReason !== null) {\n const reason = this.asleepReason ?? asleepReasonFromError(error);\n this.enterAsleep(reason);\n throw new PodAsleepError(reason);\n }\n const reason = error.message;\n this.emitConnectionState({ kind: \"lost\", reason });\n this.opts.onLost?.();\n throw error;\n } finally {\n this.waking = false;\n }\n }\n\n close(): void {\n this.userClosed = true;\n this.keepRetrying = false;\n this.keepRetryKick?.();\n this.keepRetryKick = null;\n this.connectionGeneration += 1;\n this.asleepReason = null;\n if (this.pingTimer) clearInterval(this.pingTimer);\n this.pingTimer = null;\n for (const socket of this.connectingSockets) {\n try {\n socket.close(1000, \"detach\");\n } catch {\n // Still opening or already gone.\n }\n }\n try {\n this.ws?.close(1000, \"detach\");\n } catch {\n // Already gone.\n }\n if (!this.closed) {\n this.closed = true;\n const error = new Error(\"connection to the pi session was closed\");\n this.rejectPending(error);\n this.rejectModelsRequest(error);\n this.rejectAuxRequests(error);\n }\n }\n\n // --- socket lifecycle -----------------------------------------------------\n\n /** Test seam: the live socket, so tests can inject post-hello faults. */\n get underlyingSocket(): WebSocket | null {\n return this.ws;\n }\n\n private initialAttachBudget(): number {\n return this.opts.initialAttachRetryBudgetMs ?? INITIAL_ATTACH_RETRY_BUDGET_MS;\n }\n private initialAttachDelay(): number {\n return this.opts.initialAttachRetryDelayMs ?? INITIAL_ATTACH_RETRY_DELAY_MS;\n }\n private initialAttachMaxDelay(): number {\n return this.opts.initialAttachRetryMaxDelayMs ?? INITIAL_ATTACH_RETRY_MAX_DELAY_MS;\n }\n\n private now(): number {\n return this.opts.now ? this.opts.now() : Date.now();\n }\n\n private noteActivity(): void {\n this.lastActivityAt = this.now();\n }\n\n private startPingWatchdog(): void {\n if (this.pingTimer) clearInterval(this.pingTimer);\n const intervalMs = this.opts.pingIntervalMs ?? PING_INTERVAL_MS;\n this.pingTimer = setInterval(() => this.pingWatchdogTick(), intervalMs);\n this.pingTimer.unref?.();\n }\n\n private pingWatchdogTick(): void {\n const ws = this.ws;\n if (!ws || ws.readyState !== WebSocket.OPEN) return;\n const deadlineMs = this.opts.pongDeadlineMs ?? PONG_DEADLINE_MS;\n if (this.now() - this.lastActivityAt > deadlineMs) {\n debug(\"gateway-rpc: pong deadline exceeded; terminating half-open socket\");\n try {\n ws.terminate();\n } catch {\n // The close handler owns recovery.\n }\n return;\n }\n try {\n this.wsSend({ type: \"ping\" });\n } catch {\n // The close handler owns reconnection.\n }\n }\n\n private resetHandshakeState(podId: string): void {\n this.currentPodId = podId;\n this.hello = null;\n this.piExitCode = undefined;\n this.stderrTailBuf = \"\";\n this.serverHello = null;\n this.closed = true;\n this.piVersionReady = false;\n this.lastSeq = 0;\n this.lastSessionId = null;\n this.seenSeqs.clear();\n this.lastMutation = null;\n }\n\n private async reattachAfterFailedSwitch(previousPodId: string, switchError: Error): Promise<void> {\n this.resetHandshakeState(previousPodId);\n this.connectionGeneration += 1;\n try {\n await this.attachWithBudget({\n generation: this.connectionGeneration,\n podId: previousPodId,\n budgetMs: this.initialAttachBudget(),\n initialDelayMs: this.initialAttachDelay(),\n maxDelayMs: this.initialAttachMaxDelay(),\n });\n } catch (fallback) {\n const fallbackError = fallback instanceof Error ? fallback : new Error(String(fallback));\n if (isSupersededError(fallbackError) || this.userClosed) throw fallbackError;\n throw new PiPodError(\n `switch failed: ${switchError.message} — also could not return to ${displayRef(previousPodId, \"pod\")}: ${fallbackError.message}`,\n { hint: \"reattach with `pipod attach`\" },\n );\n }\n this.emitConnectionState({ kind: \"connected\" });\n throw new PiPodError(`switch failed, staying on ${displayRef(previousPodId, \"pod\")}`, {\n hint: switchError.message,\n });\n }\n\n private async attachWithBudget(args: {\n generation: number;\n podId: string;\n budgetMs: number;\n initialDelayMs: number;\n maxDelayMs: number;\n /** First attempt of a fresh launch may wait the full provider+hello path. */\n longFirstHello?: boolean;\n }): Promise<void> {\n const startedAt = this.now();\n // Attempt cap is a frozen-clock safety rail; wall time is the primary budget.\n const maxAttempts = Math.max(\n 1,\n Math.floor(args.budgetMs / Math.max(1, args.initialDelayMs)) + 2,\n );\n let delayMs = args.initialDelayMs;\n let attempt = 0;\n for (;;) {\n attempt += 1;\n const remainingMs = Math.max(0, args.budgetMs - (this.now() - startedAt));\n const helloTimeoutMs =\n attempt === 1 && args.longFirstHello\n ? CONNECT_TIMEOUT_MS\n : Math.min(CONNECT_TIMEOUT_MS, Math.max(1, remainingMs || 1));\n try {\n await this.attachOnce(args.generation, args.podId, helloTimeoutMs);\n return;\n } catch (e) {\n const lastError = e instanceof Error ? e : new Error(String(e));\n // The user's whole machine being down is not what this budget is for. It exists to\n // ride out a gateway lease settling in seconds; a workstation start measured 243 to\n // 708 seconds in production. Hand it to the shared wait, which stays until the server\n // admits the attach, the user cancels, or the attachment is superseded.\n const demand = workstationDemandOf(lastError);\n if (demand) {\n await withWorkstationWait(\n this.opts.client,\n () => this.attachOnce(args.generation, args.podId, CONNECT_TIMEOUT_MS),\n {\n ...this.opts.workstationWait,\n from: demand,\n cancelled: this.workstationCancelled(args.generation, args.podId),\n },\n );\n // Minutes may have passed inside the wait; only the generation that asked may return.\n if (args.generation !== this.connectionGeneration || args.podId !== this.currentPodId || this.userClosed) {\n throw new Error(\"connection attempt was superseded\");\n }\n return;\n }\n if (isSupersededError(lastError) || classifyAttachError(lastError) !== \"retryable\") throw lastError;\n if (args.generation !== this.connectionGeneration || args.podId !== this.currentPodId || this.userClosed) {\n throw new Error(\"connection attempt was superseded\");\n }\n if (attempt >= maxAttempts || this.now() - startedAt >= args.budgetMs) throw lastError;\n const waitMs = Math.max(0, args.budgetMs - (this.now() - startedAt));\n await new Promise((r) => setTimeout(r, Math.min(delayMs, waitMs)));\n if (args.generation !== this.connectionGeneration || args.podId !== this.currentPodId || this.userClosed) {\n throw new Error(\"connection attempt was superseded\");\n }\n if (this.now() - startedAt >= args.budgetMs) throw lastError;\n delayMs = Math.min(delayMs * 2, args.maxDelayMs);\n }\n }\n }\n\n private async attach(\n generation = this.connectionGeneration,\n podId = this.currentPodId,\n retryDelayMs = LEASE_RETRY_DELAY_MS,\n helloTimeoutMs = CONNECT_TIMEOUT_MS,\n ): Promise<void> {\n let lastError: Error | null = null;\n for (let attempt = 0; attempt < 2; attempt++) {\n try {\n await this.attachOnce(generation, podId, helloTimeoutMs);\n return;\n } catch (e) {\n lastError = e instanceof Error ? e : new Error(String(e));\n if (isSupersededError(lastError) || classifyAttachError(lastError) !== \"retryable\") break;\n if (generation !== this.connectionGeneration || podId !== this.currentPodId || this.userClosed) {\n lastError = new Error(\"connection attempt was superseded\");\n break;\n }\n await new Promise((r) => setTimeout(r, retryDelayMs));\n if (generation !== this.connectionGeneration || podId !== this.currentPodId || this.userClosed) {\n lastError = new Error(\"connection attempt was superseded\");\n break;\n }\n }\n }\n throw lastError ?? new Error(\"could not attach to the pod session\");\n }\n\n private attachOnce(generation: number, podId: string, helloTimeoutMs = CONNECT_TIMEOUT_MS): Promise<void> {\n return new Promise((resolve, reject) => {\n void (async () => {\n const { ticket } = await this.opts.client.wsTicket(podId);\n if (this.userClosed || generation !== this.connectionGeneration || podId !== this.currentPodId) {\n throw new Error(\"connection attempt was superseded\");\n }\n const url = this.opts.client.sessionWsUrl(podId, {\n ticket,\n ...(this.lastSessionId\n ? { fromSeq: this.lastSeq, fromSession: this.lastSessionId }\n : {}),\n });\n const create = this.opts.createWebSocket ?? ((wsUrl: string) => new WebSocket(wsUrl));\n const ws = create(url);\n this.connectingSockets.add(ws);\n let settled = false;\n const timers: NodeJS.Timeout[] = [];\n const done = () => {\n for (const t of timers) clearTimeout(t);\n timers.length = 0;\n this.connectingSockets.delete(ws);\n };\n const fail = (error: Error) => {\n if (settled) return;\n settled = true;\n done();\n try {\n ws.close();\n } catch {\n // Never opened.\n }\n reject(error);\n };\n timers.push(\n setTimeout(\n () =>\n fail(\n new PiPodError(\"timed out waiting for the session hello\", {\n hint: \"the pod may still be starting pi — `pipod attach` retries without relaunching\",\n }),\n ),\n helloTimeoutMs,\n ),\n setTimeout(() => {\n if (!settled) step(\"attach\", \"waiting for the pi session in the pod to come up\");\n }, Math.min(CONNECT_NOTICE_MS, helloTimeoutMs)),\n );\n\n ws.on(\"message\", (raw) => {\n this.noteActivity();\n let message: Record<string, unknown>;\n try {\n message = JSON.parse(String(raw)) as Record<string, unknown>;\n } catch {\n return;\n }\n if (!settled) {\n if (message[\"type\"] === \"hello\") {\n if (this.userClosed || generation !== this.connectionGeneration || podId !== this.currentPodId) {\n fail(new Error(\"connection attempt was superseded\"));\n return;\n }\n const serverHello = message as unknown as ServerHello;\n if (serverHello.shim) {\n try {\n verifyHelloEnvelope(serverHello.shim, { close: () => ws.close() });\n } catch (error) {\n fail(error instanceof Error ? error : new Error(String(error)));\n return;\n }\n }\n settled = true;\n done();\n this.adopt(ws, serverHello);\n resolve();\n } else if (message[\"type\"] === \"error\") {\n const workstation = workstationErrorFromSessionMessage(message);\n if (workstation) {\n fail(workstation);\n return;\n }\n const code = typeof message[\"code\"] === \"string\" ? message[\"code\"] : undefined;\n const text =\n typeof message[\"message\"] === \"string\" && message[\"message\"]\n ? message[\"message\"]\n : \"the session refused to start\";\n fail(\n new PiPodError(code ? `${code}: ${text}` : text, {\n ...(code ? { code } : {}),\n ...(typeof message[\"status\"] === \"number\" ? { status: message[\"status\"] } : {}),\n ...(message[\"detail\"] !== undefined ? { detail: message[\"detail\"] } : {}),\n }),\n );\n }\n return;\n }\n void this.dispatchSettledMessage(message);\n });\n ws.on(\"error\", (e) => {\n const error = e instanceof Error ? e : new Error(String(e));\n if (!settled) {\n fail(error);\n return;\n }\n debug(`gateway-rpc: socket error after hello: ${error.message}`);\n try {\n ws.terminate();\n } catch {\n // The close handler owns recovery.\n }\n });\n ws.on(\"close\", (code, reason) => {\n if (!settled) {\n const why = reason.toString();\n // 4420 is also the ordinary \"this pod went to sleep\" code, so the reason is what\n // separates an idle pod (seconds, woken by a keystroke) from a whole personal\n // workstation that is not up (minutes, and no keystroke makes it faster).\n if (isWorkstationCloseReason(why)) {\n fail(workstationCloseError(why));\n return;\n }\n fail(new Error(`the session socket closed before hello (${code} ${why})`));\n return;\n }\n if (this.ws === ws) this.handleSocketClosed(code, reason.toString());\n });\n })().catch((e: unknown) => reject(e instanceof Error ? e : new Error(String(e))));\n });\n }\n\n private adopt(ws: WebSocket, hello: ServerHello): void {\n const previous = this.ws;\n this.ws = ws;\n if (this.lastSessionId && this.lastSessionId !== hello.sessionId) {\n this.seenSeqs.clear();\n this.lastSeq = 0;\n }\n this.serverHello = hello;\n this.lastSessionId = hello.sessionId;\n this.closed = false;\n this.asleepReason = null;\n this.keepRetrying = false;\n this.noteActivity();\n if (hello.shim) {\n this.acceptHello(hello.shim);\n this.piVersionReady = hello.shim.piVersion === bundledPiVersion();\n } else {\n this.piVersionReady = false;\n }\n if (previous && previous !== ws) {\n try {\n previous.close(1000, \"replaced\");\n } catch {\n // Already gone.\n }\n }\n if (this.piVersionReady) void this.resubmitLastMutation();\n }\n\n\n private async dispatchSettledMessage(message: Record<string, unknown>): Promise<void> {\n if (message[\"type\"] === \"replay_gap\") {\n this.replayHold = this.backfillReplayGap(message);\n await this.replayHold;\n return;\n }\n await this.replayHold;\n this.handleMessage(message);\n }\n\n private async backfillReplayGap(message: Record<string, unknown>): Promise<void> {\n const fromSeq = Number(message[\"fromSeq\"]);\n const toSeq = Number(message[\"toSeq\"]);\n const sessionId = this.lastSessionId;\n if (!sessionId || !Number.isFinite(fromSeq) || !Number.isFinite(toSeq) || toSeq < fromSeq) {\n debug(`gateway-rpc: replay_gap ${String(message[\"fromSeq\"])}..${String(message[\"toSeq\"])}; some events were skipped`);\n return;\n }\n try {\n let after = fromSeq - 1;\n while (after < toSeq) {\n const page = await this.opts.client.sessionEvents(sessionId, { afterSeq: after, limit: 500 });\n if (page.events.length === 0) break;\n for (const event of page.events) {\n if (event.seq < fromSeq || event.seq > toSeq) continue;\n this.handleMessage({\n type: \"event\",\n seq: event.seq,\n kind: event.kind,\n payload: event.payload,\n ts: event.createdAt,\n });\n after = event.seq;\n }\n if (page.events.length < 500) break;\n }\n } catch (e) {\n debug(\n `gateway-rpc: replay_gap ${fromSeq}..${toSeq} backfill failed (${e instanceof Error ? e.message : e}); falling back to state re-seed`,\n );\n }\n }\n\n private async resubmitLastMutation(): Promise<void> {\n const pending = this.lastMutation;\n if (!pending || this.userClosed || this.closed) return;\n if (!this.lastSessionId || pending.sessionId !== this.lastSessionId) return;\n try {\n this.wsSend({ type: \"rpc\", id: (pending.command as { id: string }).id, command: pending.command });\n } catch {\n // Recover loop will try again if the socket drops.\n }\n }\n\n private noteDurableSeq(seq: unknown): boolean {\n if (typeof seq !== \"number\" || !Number.isFinite(seq)) return true;\n if (this.seenSeqs.has(seq)) return false;\n this.seenSeqs.add(seq);\n this.lastSeq = Math.max(this.lastSeq, seq);\n if (this.seenSeqs.size > 2000) {\n for (const old of this.seenSeqs) {\n if (old < this.lastSeq - 1500) this.seenSeqs.delete(old);\n }\n }\n return true;\n }\n\n private handleMessage(message: Record<string, unknown>): void {\n // A skewed hello is usable only for the two readiness RPC responses. Do not let its\n // events mutate classic, advance replay cursors, or resubmit user work before replacement.\n if (\n !this.piVersionReady &&\n (message[\"type\"] === \"event\" || message[\"type\"] === \"ephemeral\" || message[\"type\"] === \"control\")\n ) {\n return;\n }\n switch (message[\"type\"]) {\n case \"event\": {\n if (!this.noteDurableSeq(message[\"seq\"])) break;\n const kind = String(message[\"kind\"] ?? \"\");\n if (kind === \"control\") {\n this.handleControlEvent(message[\"payload\"] as ShimControlEvent);\n } else if (!SYNTHETIC_EVENT_KINDS.has(kind)) {\n this.emitEvent(message[\"payload\"] as never);\n }\n break;\n }\n case \"ephemeral\":\n this.emitEvent(message[\"payload\"] as never);\n break;\n case \"control\":\n this.handleControlEvent(message[\"payload\"] as ShimControlEvent);\n break;\n case \"rpc_result\":\n this.lastMutation = null;\n this.handleResponse(message[\"response\"] as never);\n break;\n case \"pod_state\":\n debug(`gateway-rpc: pod_state ${String(message[\"state\"])} (${String(message[\"reason\"] ?? \"\")})`);\n break;\n case \"pod_updated\":\n debug(`gateway-rpc: pod_updated ${String(message[\"id\"])} ${String(message[\"name\"] ?? \"\")}`);\n break;\n case \"models\":\n this.resolveModelsRequest({\n models: Array.isArray(message[\"models\"]) ? message[\"models\"] : [],\n current: message[\"current\"] ?? null,\n thinkingLevel: isThinkingLevel(message[\"thinkingLevel\"]) ? message[\"thinkingLevel\"] : \"off\",\n thinkingLevels: Array.isArray(message[\"thinkingLevels\"])\n ? message[\"thinkingLevels\"].filter(isThinkingLevel)\n : [],\n });\n break;\n case \"sessions\": {\n const frame = decodeSessionsFrame(message);\n if (frame) this.acceptSemantic(\"sessions\", frame);\n break;\n }\n case \"session_hits\": {\n const frame = decodeSessionHitsFrame(message);\n if (frame) this.acceptSemantic(\"session_hits\", frame);\n break;\n }\n case \"resources_reloaded\": {\n const frame = decodeResourcesReloadedFrame(message);\n if (frame) this.acceptSemantic(\"resources_reloaded\", frame);\n break;\n }\n case \"files\": {\n const frame = decodeFilesFrame(message);\n if (frame) this.acceptSemantic(\"files\", frame);\n break;\n }\n case \"tui_manifest\": {\n const frame = decodeTuiManifestFrame(message);\n if (frame) this.acceptSemantic(\"tui_manifest\", frame);\n break;\n }\n case \"aux_complete_result\":\n this.acceptAuxResult(message);\n break;\n case \"dialog_closed\":\n case \"replay_gap\":\n case \"pong\":\n break;\n case \"error\":\n debug(`gateway-rpc: server error ${String(message[\"code\"])}: ${String(message[\"message\"])}`);\n break;\n }\n }\n\n private handleSocketClosed(code: number, reason: string): void {\n if (this.userClosed || this.piExitCode !== undefined) return;\n\n if (isAsleepClose(code, reason)) {\n // A 4420 with a host reason is the whole workstation being down (minutes), not an idle\n // pod (seconds): it recovers on its own through the shared wait, with the keystroke path\n // kept as a backup rather than the only recovery.\n if (isWorkstationCloseReason(reason)) {\n void this.recoverWorkstation(reason);\n return;\n }\n this.enterAsleep(reason || \"idle_stop\");\n return;\n }\n\n if (isPiExitClose(code, reason)) {\n if (this.piExitCode === undefined) this.handleControlEvent({ event: \"pi_exit\", code: null });\n this.enterEnded(reason || \"pi_exit\");\n return;\n }\n\n // A planned gateway replacement is orderly at the WebSocket layer but transient at the\n // application layer. New servers use 1012; the exact reason keeps old servers compatible.\n if (isGatewayRestartClose(code, reason)) {\n void this.recover(code, reason, \"gateway_restart\");\n return;\n }\n\n // Other 1000 closes are terminal lifecycle actions: delete/gone.\n if (code === 1000) {\n this.enterEnded(reason || \"the server ended the session\");\n return;\n }\n\n // Unknown 4xxx codes degrade to the retryable path (older/newer server compatibility).\n void this.recover(code, reason, \"drop\");\n }\n\n private enterAsleep(reason: string): void {\n this.asleepReason = reason;\n this.closed = true;\n const error = new PodAsleepError(reason);\n this.rejectPending(error);\n this.rejectModelsRequest(error);\n this.rejectAuxRequests(error);\n this.emitLifecycleInvalidation(error);\n this.emitConnectionState({ kind: \"asleep\", reason });\n }\n\n /**\n * Recover from a post-hello 4420 with a host reason without waiting for a keystroke. The\n * session keeps its honest asleep copy — a keystroke still wakes through the normal path\n * and joins this wait via `waking` — but the client also re-attaches on the workstation\n * schedule on its own. Only the server admitting the attach ends the wait.\n */\n private async recoverWorkstation(reason: string): Promise<void> {\n const generation = this.connectionGeneration;\n const podId = this.currentPodId;\n if (!this.hasRecoveryAuthority(generation, podId) || this.waking) return;\n this.waking = true;\n try {\n this.enterAsleep(reason);\n await withWorkstationWait(\n this.opts.client,\n () => this.attachOnce(generation, podId, CONNECT_TIMEOUT_MS),\n {\n ...this.opts.workstationWait,\n from: workstationCloseError(reason).demand,\n cancelled: this.workstationCancelled(generation, podId),\n },\n );\n // Minutes may have passed inside the wait; adopt already cleared the asleep state on a\n // successful attach, so only finish recovery when nothing superseded it underneath.\n if (!this.hasRecoveryAuthority(generation, podId)) return;\n this.asleepReason = null;\n this.emitConnectionState({ kind: \"connected\" });\n await this.opts.onRecovered?.();\n } catch (error) {\n // The wait's own budget or a terminal reason ends it; the asleep copy stays, so a later\n // keystroke is still a recovery rather than a dead end.\n debug(`gateway-rpc: workstation wait ended without attaching: ${error instanceof Error ? error.message : String(error)}`);\n } finally {\n this.waking = false;\n }\n }\n\n private enterEnded(reason: string): void {\n this.closed = true;\n this.asleepReason = null;\n const why = reason || \"the server ended the session\";\n this.rejectPending(new Error(why));\n this.rejectModelsRequest(new Error(why));\n this.rejectAuxRequests(new Error(why));\n this.emitLifecycleInvalidation(new Error(why));\n this.emitConnectionState({ kind: \"ended\", reason: why });\n this.opts.onSessionEnded?.(why);\n }\n\n private async recover(\n code: number,\n reason: string,\n cause: RecoverCause,\n generation = this.connectionGeneration,\n podId = this.currentPodId,\n ): Promise<void> {\n if (this.recovering) {\n this.queuedRecovery = {\n code, reason, cause, generation: this.connectionGeneration, podId: this.currentPodId,\n };\n return;\n }\n if (!this.hasRecoveryAuthority(generation, podId)) return;\n this.recovering = true;\n this.closed = true;\n this.asleepReason = null;\n const disconnectedError = new Error(\n cause === \"gateway_restart\"\n ? \"the gateway restarted; an in-flight RPC outcome may be unknown\"\n : \"connection to the pi session was lost\",\n );\n this.rejectPending(disconnectedError);\n this.rejectModelsRequest(disconnectedError);\n this.rejectAuxRequests(disconnectedError);\n try {\n const recovered = await this.recoverLoop(cause, generation, podId);\n if (recovered || !this.hasRecoveryAuthority(generation, podId) || this.queuedRecovery) return;\n this.emitLifecycleInvalidation(new Error(\"connection to the pi session was lost\"));\n this.emitConnectionState({ kind: \"lost\", reason: reason || null });\n this.opts.onLost?.();\n } finally {\n this.recovering = false;\n const queued = this.queuedRecovery;\n this.queuedRecovery = null;\n if (queued && this.hasRecoveryAuthority(queued.generation, queued.podId)) {\n void this.recover(\n queued.code, queued.reason, queued.cause, queued.generation, queued.podId,\n );\n }\n }\n }\n\n private async recoverLoop(cause: RecoverCause, generation: number, podId: string): Promise<boolean> {\n const budgetMs =\n cause === \"gateway_restart\"\n ? (this.opts.gatewayRestartRecoveryMs ?? GATEWAY_RESTART_RECOVERY_MS)\n : (this.opts.dropRecoveryMs ?? DROP_RECOVERY_MS);\n const deadline = this.now() + budgetMs;\n let retryDelayMs =\n cause === \"gateway_restart\"\n ? (this.opts.gatewayRestartRetryDelayMs ?? GATEWAY_RESTART_RETRY_DELAY_MS)\n : (this.opts.dropRetryDelayMs ?? DROP_RETRY_DELAY_MS);\n let attempt = 0;\n debug(`gateway-rpc: ${cause} (${budgetMs}ms budget); reconnecting`);\n const initialDelay =\n cause === \"gateway_restart\"\n ? (this.opts.gatewayRestartRetryDelayMs ?? GATEWAY_RESTART_RETRY_DELAY_MS)\n : (this.opts.dropRetryDelayMs ?? DROP_RETRY_DELAY_MS);\n const maxAttempts = Math.max(1, Math.floor(budgetMs / Math.max(1, initialDelay)) + 2);\n let announcedKeepTrying = false;\n\n while (this.hasRecoveryAuthority(generation, podId)) {\n attempt += 1;\n if (!announcedKeepTrying) {\n this.emitConnectionState({ kind: \"reconnecting\", attempt, cause });\n }\n const remainingMs = Math.max(1, deadline - this.now());\n const helloTimeoutMs = announcedKeepTrying\n ? Math.min(CONNECT_TIMEOUT_MS, this.opts.keepRetryingIntervalMs ?? KEEP_RETRYING_INTERVAL_MS)\n : Math.min(CONNECT_TIMEOUT_MS, remainingMs);\n try {\n await this.attach(generation, podId, retryDelayMs, helloTimeoutMs);\n if (!this.hasRecoveryAuthority(generation, podId)) return false;\n this.noteSuccessfulRecovery();\n this.keepRetrying = false;\n this.emitConnectionState({ kind: \"connected\" });\n await this.opts.onRecovered?.();\n return this.hasRecoveryAuthority(generation, podId);\n } catch (e) {\n if (!this.hasRecoveryAuthority(generation, podId)) return false;\n const error = e instanceof Error ? e : new Error(String(e));\n const kind = classifyAttachError(error);\n if (kind === \"asleep\") {\n this.enterAsleep(asleepReasonFromError(error));\n return true;\n }\n if (kind === \"fatal\") {\n debug(`gateway-rpc: recovery aborted: ${error.message}`);\n return false;\n }\n if (!announcedKeepTrying && (attempt >= maxAttempts || this.now() >= deadline)) {\n debug(`gateway-rpc: recovery budget exhausted: ${error.message}; keep trying`);\n this.keepRetrying = true;\n this.emitConnectionState({ kind: \"lost\", reason: error.message });\n this.opts.onLost?.();\n announcedKeepTrying = true;\n } else if (!announcedKeepTrying) {\n debug(`gateway-rpc: not ready: ${error.message}`);\n }\n const delay = announcedKeepTrying\n ? (this.opts.keepRetryingIntervalMs ?? KEEP_RETRYING_INTERVAL_MS)\n : this.flapping()\n ? RECOVERY_RETRY_MAX_MS\n : retryDelayMs;\n const waitCap = announcedKeepTrying ? delay : Math.max(0, deadline - this.now());\n await this.waitForRetry(Math.min(delay, waitCap || delay));\n if (!announcedKeepTrying) retryDelayMs = Math.min(retryDelayMs * 2, RECOVERY_RETRY_MAX_MS);\n }\n }\n return false;\n }\n\n private waitForRetry(ms: number): Promise<void> {\n return new Promise((resolve) => {\n const timer = setTimeout(() => {\n this.keepRetryKick = null;\n resolve();\n }, ms);\n this.keepRetryKick = () => {\n clearTimeout(timer);\n this.keepRetryKick = null;\n resolve();\n };\n });\n }\n\n\n private noteSuccessfulRecovery(): void {\n const now = this.now();\n this.recoveredAt = this.recoveredAt.filter((at) => now - at < RECOVERY_FLAP_WINDOW_MS);\n this.recoveredAt.push(now);\n }\n\n /** Tight drop/recover cycles sit at the slow end of the backoff instead of exiting. */\n private flapping(): boolean {\n const now = this.now();\n this.recoveredAt = this.recoveredAt.filter((at) => now - at < RECOVERY_FLAP_WINDOW_MS);\n return this.recoveredAt.length >= RECOVERY_FLAP_LIMIT;\n }\n\n private hasRecoveryAuthority(generation: number, podId: string): boolean {\n return (\n !this.userClosed &&\n this.piExitCode === undefined &&\n generation === this.connectionGeneration &&\n podId === this.currentPodId\n );\n }\n\n /** Ends a workstation wait that no longer belongs to the live attachment. */\n private workstationCancelled(generation: number, podId: string): () => boolean {\n return () =>\n this.opts.workstationWait?.cancelled?.() === true || !this.hasRecoveryAuthority(generation, podId);\n }\n\n private emitConnectionState(state: ConnectionState): void {\n const key = connectionStateKey(state);\n if (this.connectionState && connectionStateKey(this.connectionState) === key) return;\n this.connectionState = state;\n this.opts.onConnectionState?.(state);\n }\n\n private async waitUntilConnected(): Promise<void> {\n const deadline = this.now() + (this.opts.dropRecoveryMs ?? DROP_RECOVERY_MS);\n while (this.now() < deadline) {\n if (!this.closed && this.ws?.readyState === WebSocket.OPEN) return;\n if (this.userClosed) throw new Error(\"connection to the pi session was closed\");\n await new Promise((r) => setTimeout(r, 50));\n }\n throw new PiPodError(\"timed out waiting for the pod to wake\");\n }\n\n private resolveModelsRequest(snapshot: GatewayModelsSnapshot): void {\n const request = this.modelsRequest;\n if (!request) return;\n this.modelsRequest = null;\n clearTimeout(request.timer);\n request.resolve(snapshot);\n }\n\n private rejectModelsRequest(error: Error): void {\n const request = this.modelsRequest;\n if (!request) return;\n this.modelsRequest = null;\n clearTimeout(request.timer);\n request.reject(error);\n }\n\n private semanticRequest<T>(\n replyType: SemanticReplyType,\n request: Record<string, unknown>,\n absent: T,\n options: { supersede?: boolean } = {},\n ): Promise<T> {\n const active = this.pendingSemantic.get(replyType);\n if (active && options.supersede) {\n // The reply channel carries no request id, so only one question of a type can be in\n // flight. Retire the older one rather than answering it with this one's reply. Its\n // own accept clears the timer and vacates the slot, so nothing is removed here.\n active.accept(absent);\n } else if (active) {\n return new Promise<T>((resolve) => {\n const previousAccept = active.accept;\n active.accept = (value) => {\n previousAccept(value);\n resolve(value as T);\n };\n });\n }\n return new Promise<T>((resolve) => {\n const finish = (value: T) => {\n const pending = this.pendingSemantic.get(replyType);\n if (!pending) return;\n clearTimeout(pending.timer);\n this.pendingSemantic.delete(replyType);\n resolve(value);\n };\n const timer = setTimeout(\n () => finish(absent),\n this.opts.semanticRequestTimeoutMs ?? SEMANTIC_REQUEST_TIMEOUT_MS,\n );\n this.pendingSemantic.set(replyType, { timer, accept: (value) => finish(value as T) });\n try {\n this.wsSend(request);\n } catch {\n finish(absent);\n }\n });\n }\n\n private acceptSemantic(replyType: SemanticReplyType, value: unknown): void {\n this.pendingSemantic.get(replyType)?.accept(value);\n }\n\n private wsSend(message: Record<string, unknown>): void {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n throw this.connectionClosedError();\n }\n this.ws.send(JSON.stringify(message));\n }\n}\n\nfunction isThinkingLevel(value: unknown): value is ThinkingLevel {\n return value === \"off\" || value === \"minimal\" || value === \"low\" || value === \"medium\" ||\n value === \"high\" || value === \"xhigh\" || value === \"max\";\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction optionalString(value: unknown): value is string | undefined {\n return value === undefined || typeof value === \"string\";\n}\n\nfunction optionalFiniteNumber(value: unknown): value is number | undefined {\n return value === undefined || (typeof value === \"number\" && Number.isFinite(value));\n}\n\nfunction decodeCatalogEntry(value: unknown): SessionCatalogEntry | null {\n if (!isRecord(value) || typeof value[\"id\"] !== \"string\") return null;\n if (typeof value[\"createdAt\"] !== \"number\" || !Number.isFinite(value[\"createdAt\"])) return null;\n if (\n !optionalString(value[\"cwd\"]) ||\n !optionalString(value[\"parentSessionId\"]) ||\n !optionalString(value[\"name\"]) ||\n !optionalFiniteNumber(value[\"modified\"]) ||\n !optionalFiniteNumber(value[\"messageCount\"]) ||\n !optionalString(value[\"firstMessage\"]) ||\n !optionalString(value[\"path\"])\n ) return null;\n return value as unknown as SessionCatalogEntry;\n}\n\nexport function decodeSessionsFrame(message: unknown): SessionsFrame | null {\n if (!isRecord(message) || message[\"type\"] !== \"sessions\" || !Array.isArray(message[\"sessions\"])) return null;\n if (typeof message[\"workdir\"] !== \"string\" || typeof message[\"complete\"] !== \"boolean\") return null;\n if (message[\"unsupported\"] !== undefined && message[\"unsupported\"] !== true) return null;\n const sessions: SessionCatalogEntry[] = [];\n for (const value of message[\"sessions\"]) {\n const entry = decodeCatalogEntry(value);\n if (!entry) return null;\n sessions.push(entry);\n }\n return {\n sessions,\n workdir: message[\"workdir\"],\n complete: message[\"complete\"],\n ...(message[\"unsupported\"] === true ? { unsupported: true as const } : {}),\n };\n}\n\nfunction decodeSearchHit(value: unknown): SessionSearchHit | null {\n if (!isRecord(value) || typeof value[\"sessionId\"] !== \"string\" || !optionalFiniteNumber(value[\"score\"])) return null;\n const top = value[\"top\"];\n if (top !== undefined) {\n if (!isRecord(top) || !optionalString(top[\"entryId\"]) || !optionalString(top[\"snippet\"])) return null;\n if (typeof top[\"timestamp\"] !== \"number\" || !Number.isFinite(top[\"timestamp\"])) return null;\n }\n return value as unknown as SessionSearchHit;\n}\n\nexport function decodeSessionHitsFrame(message: unknown): SessionHitsFrame | null {\n if (!isRecord(message) || message[\"type\"] !== \"session_hits\" || !Array.isArray(message[\"hits\"])) return null;\n if (message[\"unsupported\"] !== undefined && message[\"unsupported\"] !== true) return null;\n const hits: SessionSearchHit[] = [];\n for (const value of message[\"hits\"]) {\n const hit = decodeSearchHit(value);\n if (!hit) return null;\n hits.push(hit);\n }\n return { hits, ...(message[\"unsupported\"] === true ? { unsupported: true as const } : {}) };\n}\n\nexport function decodeResourcesReloadedFrame(message: unknown): ResourcesReloadedFrame | null {\n if (!isRecord(message) || message[\"type\"] !== \"resources_reloaded\" || typeof message[\"ok\"] !== \"boolean\") return null;\n if (message[\"unsupported\"] !== undefined && message[\"unsupported\"] !== true) return null;\n return {\n ok: message[\"ok\"],\n ...(message[\"unsupported\"] === true ? { unsupported: true as const } : {}),\n };\n}\n\nexport function decodeFilesFrame(message: unknown): FilesFrame | null {\n if (!isRecord(message) || message[\"type\"] !== \"files\") return null;\n if (message[\"unsupported\"] !== undefined && message[\"unsupported\"] !== true) return null;\n if (typeof message[\"complete\"] !== \"boolean\") return null;\n const rawEntries = message[\"entries\"];\n if (!Array.isArray(rawEntries)) return null;\n const entries: FileListEntry[] = [];\n for (const candidate of rawEntries.slice(0, FILE_LIST_MAX_ENTRIES)) {\n if (!isRecord(candidate)) continue;\n const filePath = candidate[\"path\"];\n if (typeof filePath !== \"string\" || filePath.length === 0) continue;\n if (filePath.length > FILE_LIST_MAX_PATH_LENGTH) continue;\n // A path is pasted straight into the editor; a control character would rewrite the line.\n // eslint-disable-next-line no-control-regex\n if (/[\\u0000-\\u001f\\u007f]/.test(filePath)) continue;\n entries.push({ path: filePath, dir: candidate[\"dir\"] === true });\n }\n return {\n entries,\n complete: message[\"complete\"],\n ...(message[\"unsupported\"] === true ? { unsupported: true as const } : {}),\n };\n}\n\nexport function decodeTuiManifestFrame(message: unknown): TuiManifestFrame | null {\n if (!isRecord(message) || message[\"type\"] !== \"tui_manifest\") return null;\n if (message[\"unsupported\"] !== undefined && message[\"unsupported\"] !== true) return null;\n if (message[\"unchanged\"] !== undefined && message[\"unchanged\"] !== true) return null;\n if (!optionalString(message[\"digest\"])) return null;\n const manifest = message[\"manifest\"];\n if (manifest !== undefined && !isRecord(manifest)) return null;\n return {\n ...(message[\"digest\"] !== undefined ? { digest: message[\"digest\"] } : {}),\n ...(message[\"unchanged\"] === true ? { unchanged: true as const } : {}),\n ...(manifest !== undefined ? { manifest } : {}),\n ...(message[\"unsupported\"] === true ? { unsupported: true as const } : {}),\n };\n}\n","import type { AgentSessionEvent, JsonAgentSessionEvent } from \"@earendil-works/pi-coding-agent\";\n\ntype MessageStart = Extract<AgentSessionEvent, { type: \"message_start\" }>;\ntype AssistantMessage = Extract<MessageStart[\"message\"], { role: \"assistant\" }>;\ntype AssistantContent = AssistantMessage[\"content\"][number];\ntype WireEvent = AgentSessionEvent | JsonAgentSessionEvent;\n\ntype DeltaEvent = {\n type?: string;\n contentIndex?: number;\n delta?: string;\n content?: string;\n contentSignature?: string;\n toolCall?: Extract<AssistantContent, { type: \"toolCall\" }>;\n partial?: AssistantMessage;\n};\n\nfunction clone<T>(value: T): T {\n return structuredClone(value);\n}\n\nfunction assistantMessage(value: unknown): AssistantMessage | null {\n if (!value || typeof value !== \"object\" || (value as { role?: unknown }).role !== \"assistant\") return null;\n const message = value as AssistantMessage;\n return Array.isArray(message.content) ? message : null;\n}\n\n/**\n * Pi 0.84's JSON/RPC protocol removes cumulative assistant snapshots from message_update.\n * Pi's in-process AgentSessionEvent consumers (including InteractiveMode) still require them,\n * so every remote transport normalizes its wire events through this reducer.\n */\nexport class CumulativeAgentEventReducer {\n private current: AssistantMessage | null = null;\n /** Tool-call starts no longer carry identity on the 0.84 wire; retain JSON until the end does. */\n private readonly pendingToolJson = new Map<number, string>();\n\n get streamingMessage(): AssistantMessage | null {\n return this.current ? clone(this.current) : null;\n }\n\n reset(): void {\n this.current = null;\n this.pendingToolJson.clear();\n }\n\n /** Seed a stream recovered from the pod shim or gateway's reconnect snapshot. */\n adopt(message: unknown): AgentSessionEvent | null {\n const assistant = assistantMessage(message);\n if (!assistant) return null;\n this.current = clone(assistant);\n this.pendingToolJson.clear();\n return { type: \"message_update\", message: clone(this.current) } as AgentSessionEvent;\n }\n\n normalize(event: WireEvent): AgentSessionEvent {\n const value = event as AgentSessionEvent & {\n message?: unknown;\n assistantMessageEvent?: DeltaEvent;\n };\n\n if (value.type === \"agent_start\") this.reset();\n\n if (value.type === \"message_start\") {\n const assistant = assistantMessage(value.message);\n if (assistant) {\n this.current = clone(assistant);\n this.pendingToolJson.clear();\n }\n return event as AgentSessionEvent;\n }\n\n if (value.type === \"message_end\") {\n const result = event as AgentSessionEvent;\n if (assistantMessage(value.message)) this.reset();\n return result;\n }\n\n if (value.type !== \"message_update\") return event as AgentSessionEvent;\n\n // Pi <=0.83 and pp's stable gateway protocol already carry a cumulative message.\n const cumulative = assistantMessage(value.message) ?? assistantMessage(value.assistantMessageEvent?.partial);\n if (cumulative) {\n this.current = clone(cumulative);\n return event as AgentSessionEvent;\n }\n\n if (!this.current || !value.assistantMessageEvent) return event as AgentSessionEvent;\n this.apply(value.assistantMessageEvent);\n const snapshot = clone(this.current);\n return {\n ...value,\n message: snapshot,\n assistantMessageEvent: { ...value.assistantMessageEvent, partial: snapshot },\n } as AgentSessionEvent;\n }\n\n private apply(event: DeltaEvent): void {\n if (!this.current || typeof event.contentIndex !== \"number\" || event.contentIndex < 0) return;\n const index = event.contentIndex;\n\n switch (event.type) {\n case \"text_start\":\n this.current.content[index] = { type: \"text\", text: \"\" };\n break;\n case \"text_delta\": {\n const block = this.current.content[index];\n if (block?.type === \"text\") block.text += event.delta ?? \"\";\n else this.current.content[index] = { type: \"text\", text: event.delta ?? \"\" };\n break;\n }\n case \"text_end\":\n this.current.content[index] = {\n type: \"text\",\n text: event.content ?? (this.current.content[index]?.type === \"text\" ? this.current.content[index].text : \"\"),\n ...(event.contentSignature ? { textSignature: event.contentSignature } : {}),\n };\n break;\n case \"thinking_start\":\n this.current.content[index] = { type: \"thinking\", thinking: \"\" };\n break;\n case \"thinking_delta\": {\n const block = this.current.content[index];\n if (block?.type === \"thinking\") block.thinking += event.delta ?? \"\";\n else this.current.content[index] = { type: \"thinking\", thinking: event.delta ?? \"\" };\n break;\n }\n case \"thinking_end\":\n this.current.content[index] = {\n type: \"thinking\",\n thinking:\n event.content ??\n (this.current.content[index]?.type === \"thinking\" ? this.current.content[index].thinking : \"\"),\n ...(event.contentSignature ? { thinkingSignature: event.contentSignature } : {}),\n };\n break;\n case \"toolcall_start\":\n this.pendingToolJson.set(index, \"\");\n break;\n case \"toolcall_delta\":\n this.pendingToolJson.set(index, (this.pendingToolJson.get(index) ?? \"\") + (event.delta ?? \"\"));\n break;\n case \"toolcall_end\":\n if (event.toolCall) this.current.content[index] = clone(event.toolCall);\n this.pendingToolJson.delete(index);\n break;\n }\n }\n}\n","/** Transport-neutral RPC client used by the account gateway. */\nimport type {\n AgentSessionEvent,\n JsonAgentSessionEvent,\n RpcCommand,\n RpcExtensionUIResponse,\n RpcResponse,\n RpcSessionState,\n SessionStats,\n} from \"@earendil-works/pi-coding-agent\";\nimport type { ShimControlEvent, ShimHello } from \"./protocol.js\";\nimport { CumulativeAgentEventReducer } from \"./stream-events.js\";\n\n/** pi ships its dependencies bundled, so these two types are structural stand-ins. */\nexport type ThinkingLevel = \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\";\nexport interface ImageContent {\n type: \"image\";\n data: string;\n mimeType: string;\n}\n\nexport type RpcEventListener = (event: AgentSessionEvent) => void;\nexport type ControlListener = (event: ShimControlEvent) => void;\nexport type RpcLifecycleListener = (error: Error) => void;\n\n\nexport interface RpcRequestOptions {\n signal?: AbortSignal;\n /**\n * Fail the request rather than wait forever. Defaults to {@link QUERY_TIMEOUT_MS} for the\n * read-only `get_*` commands and to no deadline for everything else — a prompt runs for as\n * long as the agent takes, and a client that timed one out would be lying about the turn.\n */\n timeoutMs?: number | undefined;\n}\n\ninterface PendingRpcRequest {\n resolve: (response: RpcResponse) => void;\n reject: (error: Error) => void;\n cleanup: () => void;\n}\n\n/** How much of pi's stderr the client keeps for crash reports (§12). */\nconst STDERR_TAIL_BYTES = 64 * 1024;\n\n/**\n * How long a read-only query may go unanswered before the client calls it lost.\n *\n * Every `get_*` is a question about state the pod already holds, so the only thing between\n * asking and answering is transport. Generous enough for a multi-megabyte transcript over a\n * slow link, and short enough that a reply which will never arrive surfaces as an error the\n * session can report instead of a caller parked on a promise for the life of the process.\n */\nexport const QUERY_TIMEOUT_MS = 60_000;\n\n/** Read-only by construction: pi answers from state it already has (§6.1). */\nfunction isQueryCommand(command: RpcCommand): boolean {\n return typeof command.type === \"string\" && command.type.startsWith(\"get_\");\n}\n\nfunction abortError(reason: unknown): Error {\n if (reason instanceof Error) return reason;\n const error = new Error(typeof reason === \"string\" ? reason : \"RPC request was aborted\");\n error.name = \"AbortError\";\n return error;\n}\n\n/**\n * Everything a pi RPC client is, minus the transport. Subclasses supply three things: how a\n * command travels ({@link transmitCommand}), how to nudge the far side for a hello\n * ({@link askForHello}), and what closing means. Inbound traffic re-enters through\n * {@link handleControlEvent}, {@link handleResponse} and {@link emitEvent}.\n */\nexport abstract class RpcClientBase {\n protected readonly eventListeners = new Set<RpcEventListener>();\n protected readonly controlListeners = new Set<ControlListener>();\n protected readonly lifecycleListeners = new Set<RpcLifecycleListener>();\n protected readonly pending = new Map<string, PendingRpcRequest>();\n /** Recently completed ids stay retired so duplicate/late responses never fan out as events. */\n protected readonly retiredRequestIds = new Set<string>();\n /** Converts Pi's delta-only JSON/RPC stream back to the in-process cumulative event shape. */\n protected readonly eventReducer = new CumulativeAgentEventReducer();\n private requestId = 0;\n protected hello: ShimHello | null = null;\n protected helloWaiters: Array<(h: ShimHello) => void> = [];\n protected stderrTailBuf = \"\";\n protected piExitCode: number | null | undefined;\n protected closed = false;\n\n // --- handshake (§4.3) -----------------------------------------------------\n\n /**\n * Resolve once the shim's hello frame arrives, or reject after the bound. The caller\n * verifies proto and pi version; no hello means the pod is running something other than\n * the shim — most likely a pre-RPC pi pod session (§11).\n */\n waitForHello(timeoutMs: number): Promise<ShimHello> {\n if (this.hello) return Promise.resolve(this.hello);\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n this.helloWaiters = this.helloWaiters.filter((w) => w !== onHello);\n reject(new Error(`no hello from the pod shim within ${Math.round(timeoutMs / 1000)}s`));\n }, timeoutMs);\n const onHello = (h: ShimHello) => {\n clearTimeout(timer);\n resolve(h);\n };\n this.helloWaiters.push(onHello);\n });\n }\n\n /** The last hello seen, if any — a reattach re-emits one (§6.3). */\n get helloInfo(): ShimHello | null {\n return this.hello;\n }\n\n /**\n * Obtain a hello by asking for one, repeatedly, until the bound expires (§4.3).\n *\n * Waiting passively is not enough on a real provider: the shim emits its startup hello the\n * moment it boots, which can be before the provider has wired the client's output stream —\n * the frame is simply dropped by the relay. The shim answers `S {\"cmd\":\"hello\"}` at any\n * time, so an active ask-and-retry loop converges as soon as both directions are live.\n */\n async ensureHello(timeoutMs: number, opts: { discardCached?: boolean } = {}): Promise<ShimHello> {\n if (opts.discardCached) this.hello = null;\n if (this.hello) return this.hello;\n\n const deadline = Date.now() + timeoutMs;\n for (;;) {\n const remaining = deadline - Date.now();\n if (remaining <= 0) {\n throw new Error(`no hello from the pod shim within ${Math.round(timeoutMs / 1000)}s`);\n }\n this.askForHello();\n try {\n return await this.waitForHello(Math.min(1000, remaining));\n } catch {\n // Ask again: either side of the channel may not have been live yet.\n }\n }\n }\n\n /** Nudge the far side to (re-)emit its hello; a transport that pushes one unprompted no-ops. */\n protected abstract askForHello(): void;\n\n protected acceptHello(hello: ShimHello): void {\n this.hello = hello;\n const waiters = this.helloWaiters;\n this.helloWaiters = [];\n for (const waiter of waiters) waiter(hello);\n }\n\n // --- inbound --------------------------------------------------------------\n\n /** A shim control event arrived, whatever carried it: bookkeeping first, listeners after. */\n protected handleControlEvent(event: ShimControlEvent): void {\n if (event.event === \"hello\") {\n this.acceptHello(event);\n } else if (event.event === \"pi_stderr\") {\n this.stderrTailBuf = (this.stderrTailBuf + Buffer.from(event.data, \"base64\").toString(\"utf8\")).slice(\n -STDERR_TAIL_BYTES,\n );\n } else if (event.event === \"pi_exit\") {\n this.piExitCode = event.code;\n this.closed = true;\n const error = new Error(`pi exited${event.code === null ? \"\" : ` with code ${event.code}`}`);\n this.rejectPending(error);\n this.emitLifecycleInvalidation(error);\n }\n\n for (const l of this.controlListeners) l(event);\n }\n\n /** A correlated response arrived. Unknown/duplicate/retired ids are consumed silently. */\n protected handleResponse(response: RpcResponse & { id?: string }): void {\n if (response.id !== undefined) this.finishPending(response.id, { response });\n }\n\n protected emitEvent(event: AgentSessionEvent | JsonAgentSessionEvent): void {\n const normalized = this.eventReducer.normalize(event);\n for (const l of this.eventListeners) l(normalized);\n }\n\n /** Fan out a cumulative snapshot recovered after a transport or renderer gap. */\n protected emitRecoveredStreamSnapshot(message: unknown): boolean {\n const event = this.eventReducer.adopt(message);\n if (!event) return false;\n for (const listener of this.eventListeners) listener(event);\n return true;\n }\n\n /** Gateway transports already receive a cumulative reconnect snapshot from the server. */\n async refreshStreamingSnapshot(): Promise<boolean> {\n const message = this.eventReducer.streamingMessage;\n return message ? this.emitRecoveredStreamSnapshot(message) : false;\n }\n\n // --- lifecycle ------------------------------------------------------------\n\n /** Why a command cannot be sent: overridden when the pod is asleep rather than lost. */\n protected connectionClosedError(): Error {\n return new Error(\"connection to the pi session was lost\");\n }\n\n /**\n * Reattach after the pod went to sleep (account-mode 4420). Local transports no-op;\n * {@link GatewayRpcClient} wakes the sandbox by attaching again.\n */\n wake(): Promise<void> {\n return Promise.resolve();\n }\n\n\n protected rejectPending(error: Error): void {\n for (const id of [...this.pending.keys()]) this.finishPending(id, { error });\n }\n\n protected emitLifecycleInvalidation(error: Error): void {\n for (const listener of this.lifecycleListeners) listener(error);\n }\n\n private retireRequestId(id: string): void {\n this.retiredRequestIds.add(id);\n if (this.retiredRequestIds.size > 1024) {\n const oldest = this.retiredRequestIds.values().next().value as string | undefined;\n if (oldest !== undefined) this.retiredRequestIds.delete(oldest);\n }\n }\n\n protected finishPending(id: string, outcome: { response: RpcResponse } | { error: Error }): boolean {\n const waiter = this.pending.get(id);\n if (!waiter) return false;\n this.pending.delete(id);\n waiter.cleanup();\n this.retireRequestId(id);\n if (\"response\" in outcome) waiter.resolve(outcome.response);\n else waiter.reject(outcome.error);\n return true;\n }\n\n abstract close(): void;\n\n // --- subscriptions ---------------------------------------------------------\n\n onEvent(listener: RpcEventListener): () => void {\n this.eventListeners.add(listener);\n return () => this.eventListeners.delete(listener);\n }\n\n onControl(listener: ControlListener): () => void {\n this.controlListeners.add(listener);\n return () => this.controlListeners.delete(listener);\n }\n\n /** Notify lifecycle-bound brokers when the current RPC session can no longer answer. */\n onLifecycleInvalidated(listener: RpcLifecycleListener): () => void {\n this.lifecycleListeners.add(listener);\n return () => this.lifecycleListeners.delete(listener);\n }\n\n /** Tail of pi's stderr, for crash reports (§12). */\n getStderr(): string {\n return this.stderrTailBuf;\n }\n\n /** pi's exit code once a pi_exit control frame has arrived; undefined before that. */\n get exitCode(): number | null | undefined {\n return this.piExitCode;\n }\n\n // --- outbound --------------------------------------------------------------\n\n /** Ask the shim to SIGTERM pi — how the client expresses \"quit pi\" (§6.2). */\n abstract shutdown(): void;\n\n /** Answer an extension-UI dialog (§5.3). */\n abstract respondExtensionUi(response: RpcExtensionUIResponse): void;\n\n /** Deliver a command that already carries its correlation id. */\n protected abstract transmitCommand(command: RpcCommand & { id: string }): void;\n\n /** A fresh correlation id — callers pass it in a command to tie streamed events to it. */\n newRequestId(): string {\n return `${this.requestIdPrefix()}${++this.requestId}`;\n }\n\n /** Override to keep ids globally unique when several clients share one pi session (§6.1). */\n protected requestIdPrefix(): string {\n return \"pp-\";\n }\n\n /** Send a command and await its correlated response (which may be `success: false`). */\n request(command: RpcCommand, options: RpcRequestOptions = {}): Promise<RpcResponse> {\n if (this.closed) return Promise.reject(this.connectionClosedError());\n const id = command.id ?? this.newRequestId();\n if (this.pending.has(id) || this.retiredRequestIds.has(id)) {\n return Promise.reject(new Error(`RPC request id is already in use or retired: ${id}`));\n }\n if (options.signal?.aborted) return Promise.reject(abortError(options.signal.reason));\n\n const timeoutMs = options.timeoutMs ?? (isQueryCommand(command) ? QUERY_TIMEOUT_MS : undefined);\n const promise = new Promise<RpcResponse>((resolve, reject) => {\n const onAbort = () => {\n this.finishPending(id, { error: abortError(options.signal?.reason) });\n };\n let timer: NodeJS.Timeout | null = null;\n if (timeoutMs !== undefined) {\n timer = setTimeout(() => {\n this.finishPending(id, {\n error: new Error(\n `the pod did not answer ${command.type} within ${Math.round(timeoutMs / 1000)}s`,\n ),\n });\n }, timeoutMs);\n timer.unref?.();\n }\n const cleanup = () => {\n if (timer) clearTimeout(timer);\n timer = null;\n options.signal?.removeEventListener(\"abort\", onAbort);\n };\n this.pending.set(id, { resolve, reject, cleanup });\n options.signal?.addEventListener(\"abort\", onAbort, { once: true });\n if (options.signal?.aborted) onAbort();\n });\n\n if (!this.pending.has(id)) return promise;\n try {\n this.transmitCommand({ ...command, id });\n } catch (error) {\n this.finishPending(id, { error: error instanceof Error ? error : new Error(String(error)) });\n }\n return promise;\n }\n\n /** `request()`, unwrapped: throws on `success: false`, returns `data` otherwise. */\n protected async send<T = unknown>(command: RpcCommand, options?: RpcRequestOptions): Promise<T> {\n const response = await this.request(command, options);\n if (!response.success) throw new Error(response.error);\n return (response as { data?: T }).data as T;\n }\n\n // --- typed helpers, mirroring pi's RpcClient -------------------------------\n\n async prompt(message: string, images?: ImageContent[], options?: RpcRequestOptions): Promise<void> {\n await this.send({ type: \"prompt\", message, ...(images ? { images: images as never } : {}) }, options);\n }\n\n async steer(message: string, images?: ImageContent[]): Promise<void> {\n await this.send({ type: \"steer\", message, ...(images ? { images: images as never } : {}) });\n }\n\n async followUp(message: string, images?: ImageContent[]): Promise<void> {\n await this.send({ type: \"follow_up\", message, ...(images ? { images: images as never } : {}) });\n }\n\n async abort(): Promise<void> {\n await this.send({ type: \"abort\" });\n }\n\n newSession(parentSession?: string): Promise<{ cancelled: boolean }> {\n return this.send({ type: \"new_session\", ...(parentSession ? { parentSession } : {}) });\n }\n\n getState(): Promise<RpcSessionState> {\n return this.send({ type: \"get_state\" });\n }\n\n setModel(provider: string, modelId: string): Promise<unknown> {\n return this.send({ type: \"set_model\", provider, modelId });\n }\n\n cycleModel(): Promise<{ model: unknown; thinkingLevel: ThinkingLevel; isScoped: boolean } | null> {\n return this.send({ type: \"cycle_model\" });\n }\n\n async getAvailableModels(): Promise<unknown[]> {\n const data = await this.send<{ models: unknown[] }>({ type: \"get_available_models\" });\n return data.models;\n }\n\n async setThinkingLevel(level: ThinkingLevel): Promise<void> {\n await this.send({ type: \"set_thinking_level\", level });\n }\n\n cycleThinkingLevel(): Promise<{ level: ThinkingLevel } | null> {\n return this.send({ type: \"cycle_thinking_level\" });\n }\n\n async getAvailableThinkingLevels(): Promise<ThinkingLevel[]> {\n const data = await this.send<{ levels: ThinkingLevel[] }>({ type: \"get_available_thinking_levels\" });\n return data.levels;\n }\n\n async setSteeringMode(mode: \"all\" | \"one-at-a-time\"): Promise<void> {\n await this.send({ type: \"set_steering_mode\", mode });\n }\n\n async setFollowUpMode(mode: \"all\" | \"one-at-a-time\"): Promise<void> {\n await this.send({ type: \"set_follow_up_mode\", mode });\n }\n\n compact(customInstructions?: string): Promise<unknown> {\n return this.send({ type: \"compact\", ...(customInstructions ? { customInstructions } : {}) });\n }\n\n async setAutoCompaction(enabled: boolean): Promise<void> {\n await this.send({ type: \"set_auto_compaction\", enabled });\n }\n\n async setAutoRetry(enabled: boolean): Promise<void> {\n await this.send({ type: \"set_auto_retry\", enabled });\n }\n\n async abortRetry(): Promise<void> {\n await this.send({ type: \"abort_retry\" });\n }\n\n bash(command: string, opts?: { excludeFromContext?: boolean }): Promise<unknown> {\n return this.send({\n type: \"bash\",\n command,\n ...(opts?.excludeFromContext !== undefined ? { excludeFromContext: opts.excludeFromContext } : {}),\n });\n }\n\n async abortBash(): Promise<void> {\n await this.send({ type: \"abort_bash\" });\n }\n\n getSessionStats(): Promise<SessionStats> {\n return this.send({ type: \"get_session_stats\" });\n }\n\n exportHtml(outputPath?: string): Promise<{ path: string }> {\n return this.send({ type: \"export_html\", ...(outputPath ? { outputPath } : {}) });\n }\n\n switchSession(sessionPath: string): Promise<{ cancelled: boolean }> {\n return this.send({ type: \"switch_session\", sessionPath });\n }\n\n fork(entryId: string): Promise<{ text: string; cancelled: boolean }> {\n return this.send({ type: \"fork\", entryId });\n }\n\n clone(): Promise<{ cancelled: boolean }> {\n return this.send({ type: \"clone\" });\n }\n\n async getForkMessages(): Promise<Array<{ entryId: string; text: string }>> {\n const data = await this.send<{ messages: Array<{ entryId: string; text: string }> }>({\n type: \"get_fork_messages\",\n });\n return data.messages;\n }\n\n async getLastAssistantText(): Promise<string | null> {\n const data = await this.send<{ text: string | null }>({ type: \"get_last_assistant_text\" });\n return data.text;\n }\n\n async setSessionName(name: string): Promise<void> {\n await this.send({ type: \"set_session_name\", name });\n }\n\n async getCommands(): Promise<unknown[]> {\n const data = await this.send<{ commands: unknown[] }>({ type: \"get_commands\" });\n return data.commands;\n }\n\n /** Resolves on the next `agent_settled` event — pi's \"everything drained\" point. */\n waitForIdle(timeoutMs?: number): Promise<void> {\n return new Promise((resolve, reject) => {\n let timer: NodeJS.Timeout | null = null;\n const unsubscribe = this.onEvent((event) => {\n if ((event as { type?: string }).type === \"agent_settled\") {\n if (timer) clearTimeout(timer);\n unsubscribe();\n resolve();\n }\n });\n if (timeoutMs !== undefined) {\n timer = setTimeout(() => {\n unsubscribe();\n reject(new Error(`agent did not settle within ${timeoutMs}ms`));\n }, timeoutMs);\n }\n });\n }\n}\n","import type { RpcCommand } from \"@earendil-works/pi-coding-agent\";\nimport type WebSocket from \"ws\";\nimport type { ShimHello } from \"../client/protocol.js\";\nimport { PiPodError, PodAsleepError } from \"../errors.js\";\nimport type { AccountClient } from \"./api.js\";\nimport type { WorkstationWaitOptions } from \"./workstation.js\";\n\n/**\n * The gateway can spend five minutes waking a provider sandbox before it starts its own\n * 60-second shim handshake. Giving up first abandons that in-flight wake, and the next attach\n * only sees the gateway lease as `pod_unavailable`. Keep the client beyond the whole server\n * path so the user receives the provider's precise failure instead of a misleading hello\n * timeout. The final minute is scheduling and database headroom.\n */\nexport const GATEWAY_PROVIDER_START_BUDGET_MS = 5 * 60_000;\nexport const GATEWAY_HELLO_BUDGET_MS = 60_000;\nexport const CONNECT_TIMEOUT_MS = GATEWAY_PROVIDER_START_BUDGET_MS + GATEWAY_HELLO_BUDGET_MS + 60_000;\n/** A cold pod is still installing pi, so say so rather than going silent for a minute. */\nexport const CONNECT_NOTICE_MS = 10_000;\nexport const PING_INTERVAL_MS = 15_000;\n/** Two missed ping intervals, plus a little slack, before a silent socket is treated as dead. */\nexport const PONG_DEADLINE_MS = 40_000;\n/** Old gateways ignore semantic capability requests; absence is established by this bound. */\nexport const SEMANTIC_REQUEST_TIMEOUT_MS = 10_000;\n/** After the drop-recovery budget, keep probing this often instead of sitting permanently lost. */\nexport const KEEP_RETRYING_INTERVAL_MS = 15_000;\n/** A 4409 means the pod's gateway lease is settling (or the pod's session is being replaced); brief retry. */\nexport const LEASE_RETRY_DELAY_MS = 2_000;\n/** Attach retries across transient session replacements and gateway lease hand-offs. */\nexport const INITIAL_ATTACH_RETRY_BUDGET_MS = 30_000;\nexport const INITIAL_ATTACH_RETRY_DELAY_MS = 500;\nexport const INITIAL_ATTACH_RETRY_MAX_DELAY_MS = 2_000;\n/** Long enough to outlive the server's 60-second stale gateway lease after an unclean restart. */\nexport const GATEWAY_RESTART_RECOVERY_MS = 120_000;\nexport const GATEWAY_RESTART_RETRY_DELAY_MS = 500;\n/** How long a plain drop keeps retrying before the transport reports `lost`. */\nexport const DROP_RECOVERY_MS = 10 * 60_000;\n/** Shared backoff cap for the unified recover loop (flapping links sit here instead of exiting). */\nexport const RECOVERY_RETRY_MAX_MS = 15_000;\n/** First retry delay for a plain drop; gateway restart keeps GATEWAY_RESTART_RETRY_DELAY_MS. */\nexport const DROP_RETRY_DELAY_MS = 500;\n\n/** Server close 4420, or a 1000 + one of these reasons on an older server. */\nexport const ASLEEP_CLOSE_CODE = 4420;\nexport const PI_EXIT_CLOSE_CODE = 4421;\nexport const ASLEEP_REASONS = new Set([\n \"idle_stop\",\n \"archived\",\n \"archive\",\n \"provider_stopped\",\n \"provider_archived\",\n]);\n\nexport type ConnectionState =\n | { kind: \"connected\" }\n | { kind: \"reconnecting\"; attempt: number; cause: \"drop\" | \"gateway_restart\" }\n | { kind: \"asleep\"; reason: string }\n | { kind: \"lost\"; reason: string | null }\n | { kind: \"ended\"; reason: string };\n\nexport type RecoverCause = \"drop\" | \"gateway_restart\";\n\nexport type AttachErrorClass = \"retryable\" | \"fatal\" | \"asleep\";\n\n/**\n * Transient attach failures are anything the recover loop would retry: network errors,\n * 5xx ticket fetches, lease settling, a missing shim hello, or an abnormal pre-hello close.\n * Version skew and other fatal classifications never become retryable by waiting.\n */\nexport function isRetryableAttachError(error: Error): boolean {\n return classifyAttachError(error) === \"retryable\";\n}\n\n/** Both the new 1012 contract and the legacy reason identify a planned gateway replacement. */\nexport function isGatewayRestartClose(code: number, reason: string): boolean {\n return code === 1012 || reason === \"gateway_shutdown\";\n}\n\nexport function isAsleepClose(code: number, reason: string): boolean {\n return code === ASLEEP_CLOSE_CODE || ASLEEP_REASONS.has(reason);\n}\n\nexport function isPiExitClose(code: number, reason: string): boolean {\n return code === PI_EXIT_CLOSE_CODE || reason === \"pi_exit\";\n}\n\n/**\n * Classify an attach/ticket failure for the recover loop. Fatal errors abort immediately;\n * everything else (including unknown 4xxx close leftovers) stays retryable so an older or\n * newer server never strands the client on a single shot.\n */\nexport function classifyAttachError(error: Error): AttachErrorClass {\n if (error instanceof PodAsleepError) return \"asleep\";\n if (isAsleepErrorMessage(error.message)) return \"asleep\";\n if (/provider_resource_exhausted|PTY slots are exhausted/i.test(error.message)) return \"fatal\";\n if (error instanceof PiPodError) {\n if (error.transient) return \"retryable\";\n if (error.status === 401 || error.status === 403) return \"fatal\";\n if (error.status === 404 || error.status === 410) return \"fatal\";\n if (error.status !== undefined && error.status >= 400 && error.status < 500) return \"fatal\";\n }\n if (\n /pod_not_found|unauthorized|forbidden|session has expired|proto|version skew|speaks frame protocol|pod is archived|deleted|stalled on an oversized frame|this pi pod bundles pi|did not report its pi pin/i.test(\n error.message,\n )\n ) {\n return \"fatal\";\n }\n return \"retryable\";\n}\n\n/** Planned replacement retries transport/server failures, but never permanent pod/auth errors. */\nexport function isRetryableGatewayRestartError(error: Error): boolean {\n return classifyAttachError(error) === \"retryable\";\n}\n\nfunction isAsleepErrorMessage(message: string): boolean {\n return /idle_stop|provider_stopped|provider_archived|\\basleep\\b|\\barchived\\b/.test(message);\n}\n\nexport function connectionStateKey(state: ConnectionState): string {\n switch (state.kind) {\n case \"connected\":\n return \"connected\";\n case \"reconnecting\":\n return `reconnecting:${state.cause}:${state.attempt}`;\n case \"asleep\":\n return `asleep:${state.reason}`;\n case \"lost\":\n return `lost:${state.reason ?? \"\"}`;\n case \"ended\":\n return `ended:${state.reason}`;\n }\n}\n\n/** Server-persisted kinds that are not agent events; everything else is pi's own stream. */\nexport const SYNTHETIC_EVENT_KINDS = new Set([\n \"user_prompt\",\n \"session_started\",\n \"session_ended\",\n // Recorded by servers that kept approvals; still present in older transcripts.\n \"interaction_resolved\",\n \"control\",\n]);\n\nexport interface ServerHello {\n sessionId: string;\n podId: string;\n latestSeq: number;\n state: unknown;\n shim: ShimHello | null;\n /** Gateway's own pi pin. Absent on older servers; the CLI must not upgrade past this. */\n serverPiVersion?: string;\n}\n\nexport interface GatewayRpcOptions {\n client: AccountClient;\n podId: string;\n /** The transport dropped and came back: re-sync runtime state. */\n onRecovered?: (() => void | Promise<void>) | undefined;\n /** Recovery is exhausted or the failure is non-retryable. */\n onLost?: (() => void) | undefined;\n /** The server deliberately ended the pod session for a terminal lifecycle reason. */\n onSessionEnded?: ((reason: string) => void) | undefined;\n /** Continuous connection state for the session driver to render. Deduped on kind+attempt. */\n onConnectionState?: ((state: ConnectionState) => void) | undefined;\n /** Test seams; production uses the bounded replacement recovery constants above. */\n gatewayRestartRecoveryMs?: number | undefined;\n gatewayRestartRetryDelayMs?: number | undefined;\n /** Test seam for the drop-recovery budget; production uses DROP_RECOVERY_MS. */\n dropRecoveryMs?: number | undefined;\n dropRetryDelayMs?: number | undefined;\n /** Test seams for initial attach; production uses INITIAL_ATTACH_* constants. */\n initialAttachRetryBudgetMs?: number | undefined;\n initialAttachRetryDelayMs?: number | undefined;\n initialAttachRetryMaxDelayMs?: number | undefined;\n /** Test seams for the ping watchdog; production uses PING_INTERVAL_MS / PONG_DEADLINE_MS. */\n pingIntervalMs?: number | undefined;\n pongDeadlineMs?: number | undefined;\n /** After the drop budget, how often keep-trying mode probes; production uses KEEP_RETRYING_INTERVAL_MS. */\n keepRetryingIntervalMs?: number | undefined;\n /** Test seam for semantic capability discovery; production waits ten seconds for old servers. */\n semanticRequestTimeoutMs?: number | undefined;\n /** Deterministic clock for retry tests. */\n now?: (() => number) | undefined;\n /** Test seam: inject a socket (or a factory) so tests can emit post-hello errors. */\n createWebSocket?: ((url: string) => WebSocket) | undefined;\n /**\n * Timing overrides for the workstation wait a post-hello 4420 starts; production uses the\n * server's own schedule (retryAfterMs clamped to [5s, 60s]). Tests inject a fast sleep.\n */\n workstationWait?: WorkstationWaitOptions | undefined;\n}\n\nexport function isSupersededError(error: Error): boolean {\n return /superseded/.test(error.message);\n}\n\nexport function isWakeTrigger(command: RpcCommand): boolean {\n const type = command.type;\n return type === \"prompt\" || type === \"steer\" || type === \"follow_up\";\n}\n\nexport function asleepReasonFromError(error: Error): string {\n if (error instanceof PodAsleepError) return error.reason;\n for (const reason of ASLEEP_REASONS) {\n if (error.message.includes(reason)) return reason;\n }\n return \"idle_stop\";\n}\n","/** Enforce exact launcher/pod Pi lockstep before classic's unversioned RPC surface is used. */\nimport { execFile } from \"node:child_process\";\nimport { createHash, randomUUID } from \"node:crypto\";\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { verifyHello, verifyHelloEnvelope } from \"../client/compat.js\";\nimport { bundledPiVersion, comparePiVersions, installedPiPackage } from \"../client/piversion.js\";\nimport type { ShimHello } from \"../client/protocol.js\";\nimport { PiPodError } from \"../errors.js\";\nimport { info } from \"../log.js\";\nimport { SEND_MAX_BYTES, type SendEntry } from \"../send.js\";\nimport { shellQuote } from \"./workspace-seed.js\";\nimport type { AccountClient, ApiPod } from \"./api.js\";\n\nconst execFileAsync = promisify(execFile);\n\n/** Base64 JSON overhead stays below the server's existing 24 MB decoded send bound. */\nexport const PI_DELIVERY_CHUNK_BYTES = Math.floor(SEND_MAX_BYTES * 2 / 3);\nconst INSTALL_ROOT = \"/opt/pi-pod/pi\";\n\nexport interface PiDeliveryArchive {\n version: string;\n /** Package-declared executable, relative to the archived package root. */\n bin: string;\n digest: string;\n chunks: Buffer[];\n cleanup(): void;\n}\n\n/** Tar only the package this process imported, including its package-local node_modules. */\nexport async function createPiDeliveryArchive(): Promise<PiDeliveryArchive> {\n const installed = installedPiPackage();\n const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), \"pi-pod-pi-\"));\n const archive = path.join(tempDir, \"pi.tar.gz\");\n try {\n await execFileAsync(\"tar\", [\"-czf\", archive, \"-C\", installed.root, \".\"]);\n const bytes = fs.readFileSync(archive);\n const chunks: Buffer[] = [];\n for (let offset = 0; offset < bytes.length; offset += PI_DELIVERY_CHUNK_BYTES) {\n chunks.push(bytes.subarray(offset, Math.min(offset + PI_DELIVERY_CHUNK_BYTES, bytes.length)));\n }\n if (chunks.length === 0) chunks.push(Buffer.alloc(0));\n return {\n version: installed.version,\n bin: installed.bin,\n digest: createHash(\"sha256\").update(bytes).digest(\"hex\"),\n chunks,\n cleanup: () => fs.rmSync(tempDir, { recursive: true, force: true }),\n };\n } catch (error) {\n fs.rmSync(tempDir, { recursive: true, force: true });\n throw error;\n }\n}\n\nexport function buildPiInstallCommand(input: {\n version: string;\n bin: string;\n digest: string;\n chunkPaths: string[];\n workdir: string;\n}): string {\n const normalizedBin = path.posix.normalize(input.bin);\n if (path.posix.isAbsolute(normalizedBin) || normalizedBin === \"..\" || normalizedBin.startsWith(\"../\")) {\n throw new Error(\"the bundled pi executable must stay inside its package root\");\n }\n const version = shellQuote(input.version);\n const targetPath = `${INSTALL_ROOT}/${input.version}`;\n const target = shellQuote(targetPath);\n const targetBin = shellQuote(path.posix.join(targetPath, normalizedBin));\n const archive = shellQuote(path.posix.join(input.workdir, `.pi-pod-pi-${input.version}.tar.gz`));\n const chunks = input.chunkPaths.map(shellQuote);\n const chunkList = chunks.join(\" \");\n return [\n \"set -euo pipefail\",\n `# pi-pod-install-version: ${input.version}`,\n \"umask 022\",\n `archive=${archive}`,\n `target=${target}`,\n 'stage=\"\"',\n 'linktmp=\"/usr/local/bin/.pi-pod-pi.$$\"',\n `cleanup() { rm -f \"$archive\" \"$linktmp\" ${chunkList}; if [ -n \"$stage\" ]; then rm -rf \"$stage\"; fi; }`,\n \"trap cleanup EXIT\",\n `cat ${chunkList} > \"$archive\"`,\n `printf '%s %s\\\\n' ${shellQuote(input.digest)} \"$archive\" | sha256sum -c - >/dev/null`,\n `mkdir -p ${shellQuote(INSTALL_ROOT)}`,\n 'if [ ! -d \"$target\" ]; then',\n ` stage=\"$(mktemp -d ${shellQuote(`${INSTALL_ROOT}/.${input.version}.XXXXXX`)})\"`,\n ' tar -xzf \"$archive\" -C \"$stage\"',\n ` test \"$(node \"$stage\"/${shellQuote(normalizedBin)} --version)\" = ${version}`,\n ` chmod 0755 \"$stage\"/${shellQuote(normalizedBin)}`,\n ' mv -T \"$stage\" \"$target\"',\n ' stage=\"\"',\n \"fi\",\n `test \"$(node ${targetBin} --version)\" = ${version}`,\n `ln -s ${targetBin} \"$linktmp\"`,\n 'mv -Tf \"$linktmp\" /usr/local/bin/pi',\n `test \"$(/usr/local/bin/pi --version)\" = ${version}`,\n ].join(\"\\n\");\n}\n\ninterface ReadinessState {\n isStreaming: boolean;\n isCompacting: boolean;\n}\n\ninterface ReadinessRpc {\n readonly helloInfo: ShimHello | null;\n readonly podId: string;\n /** Gateway's own pi pin. Null when the server omitted it (older gateways). */\n readonly serverPiVersion: string | null;\n readinessGetState(): Promise<ReadinessState>;\n readinessBash(command: string): Promise<unknown>;\n restartAfterStop(stop: () => Promise<void>): Promise<ShimHello>;\n close(): void;\n}\n\nexport interface EnsureExactPiOptions {\n client: Pick<AccountClient, \"request\" | \"podCommand\">;\n pod: { id: string; connection?: ApiPod[\"connection\"]; resolvedConfig: { workdir?: string } };\n rpc: ReadinessRpc;\n interactive: boolean;\n approve?: (question: string) => Promise<boolean>;\n createArchive?: () => Promise<PiDeliveryArchive>;\n}\n\nfunction refusalHint(): string {\n return \"wait for the current session to become idle and attach again, or start a fresh pod on the current image without `--reuse`\";\n}\n\nfunction failClosed(rpc: ReadinessRpc, message: string, cause?: unknown): never {\n rpc.close();\n throw new PiPodError(message, {\n hint: updateFailureHint(cause),\n ...(cause !== undefined ? { cause } : {}),\n });\n}\n\nfunction updateFailureHint(cause: unknown): string {\n const message = cause instanceof Error ? cause.message : String(cause ?? \"\");\n if (/version skew/i.test(message)) {\n return \"this launcher is newer than the server; attach again after the server is upgraded — retrying will not help\";\n }\n if (cause instanceof PiPodError && cause.hint) return cause.hint;\n return \"the skewed session was detached; retry attach, or start a fresh pod on the current image without `--reuse`\";\n}\n\n/** True when installing this launcher's pi would make the pod newer than the gateway's pin. */\nfunction cannotUpgradePodToLauncherPin(bundled: string, serverPi: string | null): boolean {\n if (serverPi === null) return true;\n const order = comparePiVersions(bundled, serverPi);\n return order === null || order > 0;\n}\n\nfunction throwUnsafeUpgrade(\n rpc: ReadinessRpc,\n bundled: string,\n serverPi: string | null,\n podPi: string,\n): never {\n rpc.close();\n const message = serverPi\n ? `this pi pod bundles pi ${bundled}; the server runs pi ${serverPi}`\n : `this pi pod bundles pi ${bundled}; the pod runs pi ${podPi}`;\n throw new PiPodError(message, {\n hint: \"this launcher is newer than the server; attach again after the server is upgraded — the pod was not changed\",\n });\n}\n\nfunction isRetryablePiUpdateError(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error);\n return !/version skew|server runs pi|did not report its pi pin/i.test(message);\n}\n\nfunction updateWouldDisturb(_connection: ApiPod[\"connection\"], state: ReadinessState): boolean {\n // ApiPod.connection describes the server↔pod gateway lease, not attached user clients;\n // a fresh launch may already report connected. Only observable live work needs approval.\n return state.isStreaming || state.isCompacting;\n}\n\nasync function deliverArchive(\n opts: EnsureExactPiOptions,\n archive: PiDeliveryArchive,\n): Promise<void> {\n const workdir = opts.pod.resolvedConfig.workdir ?? \"/workspace\";\n const nonce = randomUUID();\n const names = archive.chunks.map((_, index) => `.pi-pod-pi-${nonce}.part-${String(index).padStart(3, \"0\")}`);\n const remotePaths = names.map((name) => path.posix.join(workdir, name));\n try {\n for (let index = 0; index < archive.chunks.length; index += 1) {\n const entry: SendEntry = {\n relPath: names[index]!,\n kind: \"file\",\n contents: archive.chunks[index]!.toString(\"base64\"),\n mode: 0o600,\n };\n await opts.client.request(`/pods/${opts.pod.id}/files`, { method: \"POST\", body: { entries: [entry] } });\n }\n await opts.rpc.readinessBash(\n buildPiInstallCommand({\n version: archive.version,\n bin: archive.bin,\n digest: archive.digest,\n chunkPaths: remotePaths,\n workdir,\n }),\n );\n } catch (error) {\n const cleanup = `rm -f ${remotePaths.map(shellQuote).join(\" \")}`;\n try {\n await opts.rpc.readinessBash(cleanup);\n } catch {\n // The session may already be gone; the next successful install uses unique names.\n }\n throw error;\n }\n}\n\n/** Return only after this same RPC client has adopted an exact replacement hello. */\nexport async function ensureExactPi(opts: EnsureExactPiOptions): Promise<void> {\n const hello = opts.rpc.helloInfo;\n if (!hello) failClosed(opts.rpc, \"the server session carried no pod handshake\");\n verifyHelloEnvelope(hello, { close: () => opts.rpc.close() });\n\n const bundled = bundledPiVersion();\n if (hello.piVersion === bundled) {\n verifyHello(hello, { close: () => opts.rpc.close() });\n return;\n }\n\n const comparison = comparePiVersions(hello.piVersion, bundled);\n if (comparison === null) {\n failClosed(opts.rpc, `the pod reported an unknown or malformed pi version (${hello.piVersion})`);\n }\n if (comparison > 0) {\n opts.rpc.close();\n throw new PiPodError(\"pi version skew: the pod runs a newer pi than this launcher\", {\n hint: \"run `pipod update`, then attach again — the pod will not be downgraded\",\n });\n }\n\n // The gateway refuses pods newer than *its* pin. Installing this launcher's pi is only\n // safe when that pin is known and at least as new as we are about to install.\n if (cannotUpgradePodToLauncherPin(bundled, opts.rpc.serverPiVersion)) {\n throwUnsafeUpgrade(opts.rpc, bundled, opts.rpc.serverPiVersion, hello.piVersion);\n }\n\n const state = await opts.rpc.readinessGetState();\n if (updateWouldDisturb(opts.pod.connection, state)) {\n if (!opts.interactive) {\n opts.rpc.close();\n throw new PiPodError(\"updating pi would interrupt a live pod session\", { hint: refusalHint() });\n }\n const approved = await opts.approve?.(\n `pod pi ${hello.piVersion} must update to ${bundled}; another client or active turn may be interrupted. Continue?`,\n );\n if (!approved) {\n opts.rpc.close();\n throw new PiPodError(\"pi update declined; the skewed session was detached\", { hint: refusalHint() });\n }\n }\n\n info(`updating pi in pod ${hello.piVersion} → ${bundled}`);\n const createArchive = opts.createArchive ?? createPiDeliveryArchive;\n let archive: PiDeliveryArchive;\n try {\n archive = await createArchive();\n } catch (error) {\n failClosed(opts.rpc, `could not prepare bundled pi for the pod: ${error instanceof Error ? error.message : String(error)}`, error);\n }\n if (archive.version !== bundled) {\n archive.cleanup();\n failClosed(opts.rpc, \"the prepared pi bundle does not match this launcher's installed pi\");\n }\n\n try {\n const attempts = opts.interactive ? 2 : 1;\n for (let attempt = 1; attempt <= attempts; attempt += 1) {\n try {\n await deliverArchive(opts, archive);\n const replacement = await opts.rpc.restartAfterStop(async () => {\n await opts.client.podCommand(opts.pod.id, \"stop\");\n });\n verifyHello(replacement, { close: () => opts.rpc.close() });\n return;\n } catch (error) {\n if (attempt === attempts || !isRetryablePiUpdateError(error)) throw error;\n const retry = await opts.approve?.(\n `pi update failed (${error instanceof Error ? error.message : String(error)}). Retry once?`,\n );\n if (!retry) throw error;\n }\n }\n } catch (error) {\n failClosed(opts.rpc, `could not update pi in the pod: ${error instanceof Error ? error.message : String(error)}`, error);\n } finally {\n archive.cleanup();\n }\n}\n","/**\n * Account-mode wake-on-intent: while the gateway connection is asleep, the next\n * real keystroke asks the transport to wake. InteractiveMode keeps its own stdin\n * listener — Node broadcasts `data` to every subscriber, so this does not steal\n * bytes. Detach/quit chords and Ctrl+C-family bytes are ignored so those exits\n * do not force a provider start.\n */\nimport { CHORD_WINDOW_MS } from \"../client/runtime/chords.js\";\nimport type { ConnectionState } from \"./gateway-rpc.js\";\n\n/** Ctrl+\\ — the default chord prefix (`ctrl+\\\\`). */\nconst DEFAULT_CHORD_PREFIX_BYTE = 0x1c;\n\nexport function isIgnoredAsleepWakeInput(\n chunk: string | Buffer,\n opts: { prefixByte?: number; chordPending?: boolean } = {},\n): boolean {\n const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, \"binary\");\n if (buf.length === 0) return true;\n const first = buf[0]!;\n if (first === 0x03 || first === 0x04) return true;\n if (first === (opts.prefixByte ?? DEFAULT_CHORD_PREFIX_BYTE)) return true;\n if (opts.chordPending) return true;\n return false;\n}\n\nexport function attachAsleepWakeListener(\n stdin: NodeJS.ReadableStream,\n wake: () => void,\n opts: { prefixByte?: number; windowMs?: number; now?: () => number } = {},\n): () => void {\n const prefixByte = opts.prefixByte ?? DEFAULT_CHORD_PREFIX_BYTE;\n const windowMs = opts.windowMs ?? CHORD_WINDOW_MS;\n const now = opts.now ?? Date.now;\n let pendingUntil = 0;\n let woken = false;\n\n const onData = (chunk: string | Buffer) => {\n const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, \"binary\");\n const t = now();\n const first = buf.length > 0 ? buf[0]! : undefined;\n if (first === prefixByte) {\n pendingUntil = t + windowMs;\n return;\n }\n const chordPending = t < pendingUntil;\n if (chordPending) pendingUntil = 0;\n if (isIgnoredAsleepWakeInput(buf, { prefixByte, chordPending })) return;\n if (woken) return;\n woken = true;\n wake();\n };\n\n stdin.on(\"data\", onData);\n return () => {\n stdin.off(\"data\", onData);\n };\n}\n\nexport interface AsleepWakeBinding {\n onConnectionState(state: ConnectionState): void;\n dispose(): void;\n}\n\n/**\n * Attach a one-shot stdin wake listener for each visit to `asleep`, and drop it\n * as soon as the connection leaves that state.\n */\nexport function bindAsleepWake(opts: {\n stdin: NodeJS.ReadableStream;\n wake: () => void;\n /** When set, only these asleep reasons arm the listener. Omit to arm for every asleep. */\n wakeableReasons?: ReadonlySet<string>;\n}): AsleepWakeBinding {\n let detach: (() => void) | null = null;\n\n const release = () => {\n detach?.();\n detach = null;\n };\n\n return {\n onConnectionState(state: ConnectionState) {\n if (state.kind !== \"asleep\") {\n release();\n return;\n }\n if (opts.wakeableReasons && !opts.wakeableReasons.has(state.reason)) {\n release();\n return;\n }\n if (detach) return;\n detach = attachAsleepWakeListener(opts.stdin, opts.wake);\n },\n dispose: release,\n };\n}\n","import type { ApiPod } from \"./api.js\";\n\n/**\n * Storage-aware status vocabulary (cost-control plan §3.4). The logical state keeps its\n * hide semantics — `state=archived` stays hidden from active listings — while the label\n * names the physical truth the server reports in `sandboxState`:\n *\n * - `stopped`: active row, stopped sandbox, files on local disk. `attach` restarts it.\n * - `stopped · cold storage`: provider-archived sandbox under an active row. Attach\n * downloads and unpacks it first, which takes longer the bigger the workspace.\n * - `archived …`: a logically archived row (`list --archived` shows it), with the same\n * cold-storage suffix when the server reports it.\n * - `failed`: a launch or start that ended with a reason and no running sandbox.\n *\n * A cold-storage claim needs sandbox-confirmed archive (`sandboxState=archived`);\n * a bare logically-hidden row claims nothing about storage.\n *\n * `sandboxState` is optional: older servers omit it and fall back to the logical state.\n */\nexport type PodStorageKind =\n | \"running\"\n | \"starting\"\n | \"failed\"\n | \"stopped-retained\"\n | \"provider-archived\"\n | \"archived-hidden\"\n | \"archived-hidden-retained\"\n | \"archived-hidden-cold\";\n\nexport function podStorageKind(pod: ApiPod): PodStorageKind {\n if (pod.preparationPhase === \"failed\") return \"failed\";\n if (pod.initializing) return \"starting\";\n const sandbox = pod.sandboxState ?? null;\n if (pod.state === \"archived\") {\n if (sandbox === \"stopped\") return \"archived-hidden-retained\";\n if (sandbox === \"archived\") return \"archived-hidden-cold\";\n return \"archived-hidden\";\n }\n if (sandbox === \"stopped\") return \"stopped-retained\";\n if (sandbox === \"archived\") return \"provider-archived\";\n if (!pod.ready && pod.stateReason) return \"failed\";\n return \"running\";\n}\n\nexport function podStatusLabel(pod: ApiPod): string {\n if (pod.preparationPhase === \"failed\") return \"failed\";\n if (pod.preparationPhase === \"waiting-for-capacity\") return \"waiting for capacity\";\n if (pod.initializing) return pod.preparationPhase ?? \"preparing\";\n switch (podStorageKind(pod)) {\n case \"stopped-retained\":\n return \"stopped\";\n case \"provider-archived\":\n return \"stopped · cold storage\";\n case \"archived-hidden-retained\":\n case \"archived-hidden\":\n return \"archived\";\n case \"archived-hidden-cold\":\n return \"archived · cold storage\";\n case \"failed\":\n return \"failed\";\n case \"starting\":\n return pod.preparationPhase ?? \"preparing\";\n case \"running\":\n return \"running\";\n }\n}\n","/**\n * src/account/pods.ts — pod management, account edition (account-mode-spec §7).\n *\n * Thin clients over the server's REST surface with the local commands' selection rules:\n * listings scope to the current project's pinned template, then its project identity, unless\n * --all; a bare `attach`/`send` means the repo's most recently active pod, and a pod names\n * itself by full id, short ref, legacy prefix, or name. Outside a repository the scope is\n * naturally the whole account.\n */\nimport * as path from \"node:path\";\nimport { CancelledError, EXIT, PiPodError } from \"../errors.js\";\nimport { withCapacityHint } from \"./capacity-errors.js\";\nimport { color, info, out, warn } from \"../log.js\";\nimport { confirm } from \"../prompt.js\";\nimport type { AccountClient, ApiPod, ApiTemplate } from \"./api.js\";\nimport {\n currentProjectName,\n currentProjectTemplateRef,\n localConfigView,\n resolveTemplate,\n runAccountLaunch,\n splitPiArgs,\n type AccountLaunchFlags,\n} from \"./launch.js\";\nimport { podStatusLabel, podStorageKind } from \"./pod-status.js\";\nimport { runAccountSession } from \"./session.js\";\nimport { displayRef, isFullUuid, matchesRef } from \"./ref.js\";\nimport { withWorkstationWait } from \"./workstation.js\";\nimport { billingSummaryLine, type AccountBilling } from \"./billing.js\";\nimport { collectSendEntries } from \"../send.js\";\n\nexport interface AccountPodFlags {\n all: boolean;\n quiet: boolean;\n archived: boolean;\n yes: boolean;\n /** `list`/`archive --template <name|id>`: only the pods launched from that template. */\n template?: string | undefined;\n /** `archive --idle <duration>`: only pods whose last activity is older than this. */\n idle?: string | undefined;\n /** `archive --dry-run`: print the pods that would be archived; change nothing. */\n dryRun?: boolean | undefined;\n}\n\nconst PAGE_LIMIT = 200;\n\n/**\n * Every pod the query matches, not just the newest page. The server answers newest activity\n * first and caps a page at 200, so the pods that fall off a single page are exactly the ones\n * a stale ref or an idle sweep is after. `before` walks back by activity time; a full page\n * whose cursor stops moving ends the walk instead of looping on it.\n */\nasync function listAllPods(\n client: AccountClient,\n query: { project?: string | undefined; templateId?: string | undefined; includeGone?: boolean | undefined },\n): Promise<{ pods: ApiPod[] }> {\n const pods: ApiPod[] = [];\n let before: string | undefined;\n for (;;) {\n const page = await client.listPods({ mine: true, limit: PAGE_LIMIT, before, ...query });\n pods.push(...page.pods);\n if (page.pods.length < PAGE_LIMIT) return { pods };\n const cursor = activityStamp(page.pods.at(-1)!);\n if (cursor === before) return { pods };\n before = cursor;\n }\n}\n\n/**\n * The pods of the project this directory belongs to, or of the whole account with `all`.\n * `widen` answers with the account's pods when the project has none — older pods recorded no\n * project, and a list or a pick that comes up empty there helps nobody. `project` names the\n * scope the answer actually came from.\n */\nasync function podsInScope(\n client: AccountClient,\n flags: { all: boolean; templateId?: string | undefined; includeGone?: boolean | undefined; widen?: boolean },\n cwd?: string,\n): Promise<{ pods: ApiPod[]; project: string | null }> {\n const query = {\n ...(flags.templateId ? { templateId: flags.templateId } : {}),\n ...(flags.includeGone ? { includeGone: true } : {}),\n };\n const project = flags.all ? null : currentProjectName(cwd);\n if (project) {\n const scoped = await listAllPods(client, { ...query, project });\n if (scoped.pods.length > 0 || !flags.widen) return { pods: scoped.pods, project };\n }\n return { pods: (await listAllPods(client, query)).pods, project: null };\n}\n\n/** When the pod last did something; creation stands in until it has. */\nfunction activityStamp(pod: ApiPod): string {\n return pod.lastActivityAt ?? pod.createdAt;\n}\n\nconst IDLE_UNIT_MS: Record<string, number> = { m: 60_000, h: 3_600_000, d: 86_400_000 };\n\n/** `--idle 4h` → milliseconds. One whole number, one unit; anything else is a usage error. */\nexport function parseIdleDuration(text: string): number {\n const match = /^(\\d+)([mhd])$/i.exec(text);\n const count = match ? Number(match[1]) : 0;\n if (!match || count <= 0) {\n throw new PiPodError(`invalid --idle duration \"${text}\"`, {\n hint: \"use a whole number with one unit: 30m, 4h, 2d\",\n exitCode: EXIT.USAGE,\n });\n }\n return count * IDLE_UNIT_MS[match[2]!.toLowerCase()]!;\n}\n\n/** A pod with an unreadable timestamp is not provably idle, so a sweep leaves it alone. */\nfunction idleLongerThan(pod: ApiPod, idleMs: number, now: number): boolean {\n const activity = Date.parse(activityStamp(pod));\n return Number.isFinite(activity) && activity < now - idleMs;\n}\n\n/** Oldest activity first; missing activity falls back to creation time. */\nexport function sortPodsByActivity(pods: ApiPod[]): ApiPod[] {\n const activityTime = (pod: ApiPod): number => {\n const parsed = Date.parse(activityStamp(pod));\n return Number.isFinite(parsed) ? parsed : Number.POSITIVE_INFINITY;\n };\n return [...pods].sort((a, b) => activityTime(a) - activityTime(b));\n}\n\n/**\n * Listing order with nesting: roots and siblings are oldest-activity-first, and every pod\n * follows the pod it belongs to. The grouping edge prefers the machine (hostPodId) over the\n * launcher (parentPodId): co-located pods sit under the pod whose machine they share, which\n * is also the group's only real-provider member. A pod whose group anchor is not in the\n * listing (a project-scoped `ls`, or an older server) is shown as a root rather than hidden.\n */\nexport function orderPodsAsTree(pods: ApiPod[]): Array<{ pod: ApiPod; depth: number }> {\n const sorted = sortPodsByActivity(pods);\n const present = new Set(sorted.map((pod) => pod.id));\n const childrenOf = new Map<string, ApiPod[]>();\n const roots: ApiPod[] = [];\n for (const pod of sorted) {\n const anchorId = pod.hostPodId ?? pod.parentPodId ?? null;\n const anchor = anchorId && present.has(anchorId) ? anchorId : null;\n if (anchor === null) roots.push(pod);\n else childrenOf.set(anchor, [...(childrenOf.get(anchor) ?? []), pod]);\n }\n const ordered: Array<{ pod: ApiPod; depth: number }> = [];\n const visit = (pod: ApiPod, depth: number): void => {\n ordered.push({ pod, depth });\n for (const child of childrenOf.get(pod.id) ?? []) visit(child, depth + 1);\n };\n for (const root of roots) visit(root, 0);\n return ordered;\n}\n\n/** List output is command data, not a diagnostic, so pipelines receive it on stdout. */\nfunction listOut(msg: string): void {\n out(`${color.cyan(\"pi pod\")} ${msg}`);\n}\n\nexport async function runAccountList(\n client: AccountClient,\n flags: AccountPodFlags,\n podRef?: string,\n): Promise<number> {\n if (podRef) return runAccountGroupList(client, flags, podRef);\n // A project template pin is the default list scope. `--all` deliberately suppresses that\n // implicit filter, while an explicit `--template` remains authoritative alongside --all.\n const templateRef = flags.template ?? (flags.all ? null : currentProjectTemplateRef());\n const template = templateRef ? await resolveTemplate(client, templateRef) : null;\n // The plan line is SaaS-only and never worth a round trip of its own: ask for the\n // workstation block beside the pods, and let a server that has no such thing answer nothing.\n // A template belongs to the account, not to a repo, so naming one asks about the account:\n // the project the terminal happens to be sitting in does not narrow the answer further.\n const [scoped, billing] = await Promise.all([\n podsInScope(client, {\n all: flags.all || template !== null,\n ...(template ? { templateId: template.id } : {}),\n widen: true,\n }),\n flags.quiet ? Promise.resolve(null) : client.accountBilling(),\n ]);\n // `/v1/me` is the only route that carries the block; absence hides the footer silently.\n let pods = scoped.pods;\n // A server that predates the filter ignores the query and answers with everything, which\n // would read as \"every pod uses this template\". The pods say who launched them; believe them.\n if (template) pods = pods.filter((pod) => pod.templateId === template.id);\n if (!flags.archived) pods = pods.filter((p) => p.state !== \"archived\");\n pods = sortPodsByActivity(pods);\n if (flags.quiet) {\n for (const pod of pods) out(pod.id);\n return 0;\n }\n if (pods.length === 0) {\n listOut(template ? `no pods from template ${template.name}` : \"no pods\");\n renderBillingLine(billing);\n return 0;\n }\n listOut(\n template\n ? `pods from template ${template.name} on ${client.serverUrl}:`\n : scoped.project\n ? `pods for ${scoped.project} on ${client.serverUrl} (--all for every pod):`\n : `pods on ${client.serverUrl}:`,\n );\n renderPodLines(pods);\n renderBillingLine(billing);\n return 0;\n}\n\n/**\n * The account's plan, active hours and spend cap — or nothing at all.\n *\n * This is the edition boundary in one function. The SaaS server meters a personal workstation\n * per user and reports it; the self-hosted server runs on hardware its operator already pays\n * for and reports none of it. Absence therefore prints nothing: no zeroes, no \"unknown\", no\n * empty heading. A self-hosted operator must never be shown a spend cap they do not have.\n */\nfunction renderBillingLine(billing: AccountBilling | null): void {\n const line = billingSummaryLine(billing);\n if (line !== null) listOut(` ${color.dim(line)}`);\n}\n\n/** `pipod list <pod>`: one machine's group — the pod and everything co-located on it. */\nasync function runAccountGroupList(\n client: AccountClient,\n flags: AccountPodFlags,\n podRef: string,\n): Promise<number> {\n const named = await selectAccountPod(client, podRef, \"list\");\n const anchorId = named.hostPodId ?? named.id;\n const pods = (await listAllPods(client, {})).pods;\n const group = pods.filter(\n (pod) => (pod.id === anchorId || pod.hostPodId === anchorId) && (flags.archived || pod.state !== \"archived\"),\n );\n if (flags.quiet) {\n for (const pod of sortPodsByActivity(group)) out(pod.id);\n return 0;\n }\n const anchor = pods.find((pod) => pod.id === anchorId);\n listOut(`pods on ${anchor ? anchor.name : displayRef(anchorId, \"pod\")}'s machine:`);\n renderPodLines(group);\n return 0;\n}\n\nfunction renderPodLines(pods: ApiPod[]): void {\n const rows = orderPodsAsTree(pods);\n // Where a pod lives matters only for co-located pods (`on <host>`); every other pod has a\n // machine of its own, and naming the provider there says nothing.\n const located = rows.some(({ pod }) => pod.hostPodId);\n const line = (ref: string, name: string, status: string, where: string, when: string) =>\n ` ${pad(ref, 12)} ${pad(name, 34)} ${pad(status, 24)} ${located ? `${pad(where, 16)} ` : \"\"}${when}`;\n listOut(color.dim(line(\"POD\", \"NAME\", \"STATUS\", \"ON\", \"ACTIVE\")));\n for (const { pod, depth } of rows) {\n const when = pod.lastActivityAt ?? pod.createdAt;\n const status = podStatusLabel(pod);\n // Only a running pod has a session to be connected to; for any other the status says it all.\n const connection =\n podStorageKind(pod) === \"running\" && pod.connection && pod.connection !== \"connected\" ? ` ${pod.connection}` : \"\";\n const indent = depth === 0 ? \"\" : `${\" \".repeat(depth - 1)}└ `;\n // The session name is the pod's mutable identity (rename and Pi's session naming update\n // it). Keep the immutable project visible when it adds context, but never substitute it\n // for the name: that made renamed pods look as though the rename had not happened.\n const label = pod.project && pod.project !== pod.name ? `${pod.name} (${pod.project})` : pod.name;\n const where = pod.hostPodId ? (pod.location ?? \"\") : \"\";\n listOut(line(color.bold(pad(displayRef(pod.id, \"pod\"), 12)), fit(indent + label, 34), status + connection, where, ago(when)));\n }\n}\n\n\n/** Wake/restore cost hint for the pod's current storage state, or null when generic. */\nexport function podRestoreHint(pod: ApiPod): string | null {\n switch (podStorageKind(pod)) {\n case \"stopped-retained\":\n return \"attach restarts it in seconds\";\n case \"provider-archived\":\n case \"archived-hidden-retained\":\n case \"archived-hidden-cold\":\n case \"archived-hidden\":\n return \"restore downloads it on next use (seconds-to-minutes depending on workspace size)\";\n default:\n return null;\n }\n}\n\n/** Full id, short ref, legacy prefix, or name — or this scope's only pod when omitted. */\nexport async function selectAccountPod(\n client: AccountClient,\n podRef: string | undefined,\n action: string,\n cwd?: string,\n): Promise<ApiPod> {\n if (podRef) {\n // A full id needs no listing: the server answers by id no matter how many pods have been\n // active more recently, so an old pod stays reachable by the ref `list` once printed.\n if (isFullUuid(podRef)) return client.getPod(podRef.toLowerCase());\n const pods = (await listAllPods(client, {})).pods;\n\n const named = pods.filter((pod) => pod.name === podRef);\n if (named.length === 1) return named[0]!;\n if (named.length > 1) throw ambiguousPodRef(podRef, named);\n\n const matches = pods.filter((pod) => matchesRef(pod.id, podRef));\n if (matches.length === 1) return matches[0]!;\n if (matches.length > 1) throw ambiguousPodRef(podRef, matches);\n throw new PiPodError(`no pod matches \"${podRef}\"`, { hint: \"see `pipod list --all`\" });\n }\n const scoped = await podsInScope(client, { all: false, widen: true }, cwd);\n const project = scoped.project;\n // The pod meant is a live one — an archived one only for `restore`, or when there is no other.\n const wanted = scoped.pods.filter((pod) => (pod.state === \"archived\") === (action === \"restore\"));\n const pods = wanted.length > 0 ? wanted : scoped.pods;\n if (pods.length === 0) {\n throw new PiPodError(`no pod to ${action}`, {\n hint: \"launch one with `pipod`\",\n });\n }\n if (pods.length > 1) {\n throw new PiPodError(`${project ?? \"this account\"} has ${pods.length} pods; name the one to ${action}`, {\n hint: `choose a ref from:\\n${podChoiceLines(pods)}`,\n });\n }\n return pods[0]!;\n}\n\nfunction ambiguousPodRef(ref: string, pods: ApiPod[]): PiPodError {\n return new PiPodError(`\"${ref}\" matches ${pods.length} pods`, {\n hint: `use a longer ref:\\n${podChoiceLines(pods)}`,\n });\n}\n\nfunction podChoiceLines(pods: ApiPod[]): string {\n const refs = pods.map((pod) => displayRef(pod.id, \"pod\"));\n const counts = new Map<string, number>();\n for (const ref of refs) counts.set(ref, (counts.get(ref) ?? 0) + 1);\n return pods\n .map((pod, index) => {\n const ref = refs[index]!;\n const unambiguousRef = counts.get(ref)! > 1 ? pod.id : ref;\n return ` ${unambiguousRef} ${pod.name} (${pod.state})`;\n })\n .join(\"\\n\");\n}\n\nexport async function runAccountPodAction(\n client: AccountClient,\n args: string[],\n flags: AccountPodFlags,\n action: \"archive\" | \"restore\",\n): Promise<number> {\n // The parser fills these flags for restore too; only archive sweeps and dry-runs, so restore\n // reads none of them and keeps `--all` as its single bulk selector.\n const idleMs = action === \"archive\" && flags.idle !== undefined ? parseIdleDuration(flags.idle) : null;\n const dryRun = action === \"archive\" && flags.dryRun === true;\n const filtered = action === \"archive\" && (flags.template !== undefined || idleMs !== null);\n if (flags.all && args.length > 0) {\n throw new PiPodError(`--all ${action}s every pod, so it cannot be combined with pod ids`, {\n hint: `drop --all to ${action} just the pods you named`,\n });\n }\n if (filtered && args.length > 0) {\n throw new PiPodError(\"--template and --idle choose the pods to archive, so they cannot be combined with pod ids\", {\n hint: \"drop the pod ids to archive whatever matches, or drop the filters to archive just the pods you named\",\n exitCode: EXIT.USAGE,\n });\n }\n const targets: ApiPod[] = [];\n if (flags.all || filtered) {\n const { pods, empty } = action === \"archive\"\n ? await archiveSweep(client, flags, idleMs)\n : await restoreSweep(client);\n if (pods.length === 0) {\n empty();\n return 0;\n }\n targets.push(...pods);\n if (!dryRun) {\n const ok = await confirm(`${action} ${targets.length} pod(s)?`, {\n nonInteractiveDefault: true,\n assumeYes: flags.yes,\n });\n if (!ok) return 1;\n }\n } else if (args.length > 0) {\n const resolved = await Promise.all(args.map((ref) => selectAccountPod(client, ref, action)));\n const seen = new Set<string>();\n for (const pod of resolved) {\n if (!seen.has(pod.id)) targets.push(pod);\n seen.add(pod.id);\n }\n } else {\n targets.push(await selectAccountPod(client, undefined, action));\n }\n if (dryRun) {\n renderPodLines(targets);\n listOut(`would archive ${targets.length} pod(s)`);\n return 0;\n }\n for (const pod of targets) {\n let result: { state: string; cascaded?: string[] };\n try {\n result = await client.podCommand(pod.id, action);\n } catch (error) {\n throw withCapacityHint(error);\n }\n const { state, cascaded } = result;\n const group =\n cascaded && cascaded.length > 0\n ? ` (and ${cascaded.length} co-located pod${cascaded.length === 1 ? \"\" : \"s\"})`\n : \"\";\n const ref = displayRef(pod.id, \"pod\");\n if (action === \"archive\") {\n info(`archived ${ref}${group}: hidden from \\`pipod list\\`, files kept; \\`pipod restore ${ref}\\` brings it back`);\n } else {\n info(`restored ${ref}${group} (${state}); \\`pipod attach ${ref}\\` starts it`);\n }\n }\n return 0;\n}\n\n/**\n * `archive --all/--template/--idle`: the pods a sweep would archive, oldest activity first so\n * a dry-run reads like `list`. The scope is list's own rule — explicit template, else the\n * project's pin, else the project, with `--all` widening to the account — rather than a\n * second policy that could drift from what `list` just showed. Already-archived pods are\n * never targets, so an empty answer names the filter that came up empty.\n */\nasync function archiveSweep(\n client: AccountClient,\n flags: AccountPodFlags,\n idleMs: number | null,\n): Promise<{ pods: ApiPod[]; empty: () => void }> {\n const templateRef = flags.template ?? (flags.all ? null : currentProjectTemplateRef());\n const template = templateRef ? await resolveTemplate(client, templateRef) : null;\n const { pods: scopedPods, project } = await podsInScope(client, {\n all: flags.all || template !== null,\n ...(template ? { templateId: template.id } : {}),\n });\n let pods = scopedPods;\n if (template) pods = pods.filter((pod) => pod.templateId === template.id);\n pods = pods.filter((pod) => pod.state !== \"archived\");\n const now = Date.now();\n if (idleMs !== null) pods = pods.filter((pod) => idleLongerThan(pod, idleMs, now));\n const scope = template\n ? ` from template ${template.name}`\n : project\n ? ` for ${project}`\n : \"\";\n const empty = (): void => {\n if (idleMs !== null) listOut(`no pods${scope} idle longer than ${flags.idle}`);\n else if (template) listOut(`no pods${scope}`);\n else info(\"every pod is already archived\");\n };\n return { pods: sortPodsByActivity(pods), empty };\n}\n\n/** `restore --all`: every archived pod on the account. */\nasync function restoreSweep(client: AccountClient): Promise<{ pods: ApiPod[]; empty: () => void }> {\n const scope = (await podsInScope(client, { all: true })).pods;\n return {\n pods: scope.filter((pod) => pod.state !== \"active\"),\n empty: () => info(\"every pod is already active\"),\n };\n}\n\n/** `pipod stop`: release compute now; the filesystem survives and attach restarts the pod. */\nexport async function runAccountStop(\n client: AccountClient,\n args: string[],\n flags: AccountPodFlags,\n): Promise<number> {\n const targets: ApiPod[] = [];\n if (args.length > 0) {\n const resolved = await Promise.all(args.map((ref) => selectAccountPod(client, ref, \"stop\")));\n const seen = new Set<string>();\n for (const pod of resolved) {\n if (!seen.has(pod.id)) targets.push(pod);\n seen.add(pod.id);\n }\n } else {\n targets.push(await selectAccountPod(client, undefined, \"stop\"));\n }\n for (const pod of targets) {\n if (pod.state !== \"active\") {\n info(`pod ${displayRef(pod.id, \"pod\")} is archived — nothing to stop`);\n continue;\n }\n let state: string;\n try {\n ({ state } = await client.podCommand(pod.id, \"stop\"));\n } catch (error) {\n throw withCapacityHint(error);\n }\n const ref = displayRef(pod.id, \"pod\");\n info(`${state} ${ref}: files kept; \\`pipod attach ${ref}\\` restarts it`);\n }\n return 0;\n}\n\nexport async function runAccountFork(\n client: AccountClient,\n args: string[],\n flags: AccountLaunchFlags & { session?: string },\n piArgs: string[],\n): Promise<number> {\n if (args.length !== 1) {\n throw new PiPodError(\"usage: pipod fork <pod> [launch options]\", { exitCode: EXIT.USAGE });\n }\n const source = await selectAccountPod(client, args[0], \"fork\");\n return runAccountLaunch({\n client,\n flags: {\n ...flags,\n reuse: false,\n forkFrom: {\n podId: source.id,\n ...(flags.session ? { sessionPath: flags.session } : {}),\n },\n },\n piArgs,\n });\n}\n\nexport async function runAccountRename(client: AccountClient, args: string[]): Promise<number> {\n if (args.length !== 2) {\n throw new PiPodError(\"usage: pipod rename <pod> <new-name>\");\n }\n const pod = await selectAccountPod(client, args[0], \"rename\");\n await client.renamePod(pod.id, args[1]!);\n info(`pod ${displayRef(pod.id, \"pod\")} renamed to ${args[1]}`);\n return 0;\n}\n\n/** The server's worker owns retention (§7); gc surfaces state and offers the delete half. */\nexport async function runAccountGc(\n client: AccountClient,\n flags: AccountPodFlags & { destroy: boolean },\n): Promise<number> {\n // includeGone: failed launches that never acquired compute converge to\n // archived+gone, which default listings omit — gc must still offer them.\n const pods = (await podsInScope(client, { all: true, includeGone: true })).pods;\n // A deleted pod stays as history: archived, its sandbox gone, no failure to report. There is\n // nothing left of it to reclaim, so it is not offered again.\n const archived = pods.filter((p) => p.state === \"archived\" && !(p.sandboxState === \"gone\" && p.stateReason === null));\n const unavailable = pods.filter(\n (p) => p.state === \"active\" && !p.ready && !p.initializing && p.stateReason !== null,\n );\n if (archived.length === 0 && unavailable.length === 0) {\n info(\"nothing archived or unavailable to clean up\");\n return 0;\n }\n if (!flags.destroy) {\n for (const pod of [...archived, ...unavailable]) {\n info(` ${displayRef(pod.id, \"pod\")} ${pad(pod.project ?? pod.name, 30)} ${pod.state}`);\n }\n info(\"`pipod gc --delete` deletes them for good\");\n return 0;\n }\n const targets = [...archived, ...unavailable];\n const ok = await confirm(`delete ${targets.length} pod(s) permanently?`, {\n nonInteractiveDefault: false,\n assumeYes: flags.yes,\n });\n if (!ok) return 1;\n // Deepest first, so reclaiming a whole tree never trips the server's refusal to orphan a\n // pod's live children on the pods it is about to delete anyway.\n const deepestFirst = [...targets].sort((a, b) => (b.lineageDepth ?? 0) - (a.lineageDepth ?? 0));\n for (const pod of deepestFirst) {\n try {\n await client.deletePod(pod.id);\n } catch (e) {\n // A live child outside this cleanup is somebody's running work: keep it, do not cascade.\n if (e instanceof PiPodError && e.status === 409) {\n warn(`kept pod ${displayRef(pod.id, \"pod\")}: pods it launched are still running`);\n continue;\n }\n throw e;\n }\n info(`deleted pod ${displayRef(pod.id, \"pod\")}`);\n }\n return 0;\n}\n\nexport interface AccountAttachFlags {\n yes?: boolean;\n}\n\nexport async function runAccountAttach(\n client: AccountClient,\n args: string[],\n piArgs: string[],\n flags: AccountAttachFlags,\n): Promise<number> {\n const { prompt, extraArgs, tuiMode } = splitPiArgs(piArgs);\n if (extraArgs.length > 0) {\n throw new PiPodError(`pi flags are not configurable per-attach in account mode: ${extraArgs.join(\" \")}`, {\n hint: \"the session is shared across surfaces; set Pi options in config (`pi` key)\",\n });\n }\n const pod = await selectAccountPod(client, args[0], \"attach\");\n if (pod.state === \"archived\") {\n const ok = await confirm(`pod ${displayRef(pod.id, \"pod\")} is archived — restore and attach?`, {\n nonInteractiveDefault: true,\n assumeYes: flags.yes,\n });\n if (!ok) throw new CancelledError(\"attach cancelled\");\n try {\n // A restore needs the workstation the workspace lives on, so it is a wake in disguise.\n await withWorkstationWait(client, () => client.podCommand(pod.id, \"restore\"));\n } catch (error) {\n throw withCapacityHint(error);\n }\n }\n const result = await runAccountSession({\n client,\n pod,\n loadContext: async () => {\n const { config, projectRoot } = await localConfigView(client, process.cwd(), {\n templateId: pod.templateId ?? null,\n });\n return { config, hostCwd: projectRoot ?? process.cwd() };\n },\n startupPrompt: prompt,\n ...(tuiMode ? { tuiMode } : {}),\n });\n return result.exitCode;\n}\n\n\nexport async function runAccountSend(\n client: AccountClient,\n args: string[],\n flags: { yes?: boolean } = {},\n) : Promise<number> {\n const [podRef, sourcePath] = args.length >= 2 ? [args[0], args[1]!] : [undefined, args[0]];\n if (!sourcePath) {\n throw new PiPodError(\"usage: pipod send [pod] <path>\");\n }\n const source = path.resolve(sourcePath);\n const sourceName = path.basename(source);\n if (sourceName === \"\") {\n throw new PiPodError(`cannot send the filesystem root ${source}`, {\n hint: \"name a file or directory inside it instead\",\n });\n }\n\n const pod = await selectAccountPod(client, podRef, \"send\");\n if (pod.state === \"archived\") {\n const ok = await confirm(`pod ${displayRef(pod.id, \"pod\")} is archived — restore and send?`, {\n nonInteractiveDefault: false,\n assumeYes: flags.yes,\n });\n if (!ok) throw new CancelledError(\"send cancelled\");\n try {\n await withWorkstationWait(client, () => client.podCommand(pod.id, \"restore\"));\n } catch (error) {\n throw withCapacityHint(error);\n }\n }\n\n const { entries } = collectSendEntries(source, { relBase: sourceName, label: sourcePath });\n\n info(`sending ${entries.length} entr${entries.length === 1 ? \"y\" : \"ies\"} → pod ${displayRef(pod.id, \"pod\")}`);\n try {\n // A send is what wakes a sleeping personal workstation; the refusal arrives before any\n // byte is written, so the same request is safe to make again once the machine is up.\n await withWorkstationWait(client, () =>\n client.request(`/pods/${pod.id}/files`, { method: \"POST\", body: { entries } }),\n );\n } catch (e) {\n if (e instanceof PiPodError && e.status === 403 && /pod token|send files/i.test(e.message)) {\n throw new PiPodError(\n \"this server rejects pod-token file send; seed files in the project launch overlay or use a user-authenticated host\",\n { status: 403, cause: e },\n );\n }\n throw e;\n }\n info(\"sent\");\n return 0;\n}\n\n/** `s` cut to `width` characters, an ellipsis marking the cut, so columns stay aligned. */\nfunction fit(s: string, width: number): string {\n return s.length > width ? `${s.slice(0, width - 1)}…` : s;\n}\n\nfunction pad(s: string, width: number): string {\n return s.length >= width ? s : s + \" \".repeat(width - s.length);\n}\n\nfunction ago(iso: string): string {\n const ms = Date.now() - new Date(iso).getTime();\n if (!Number.isFinite(ms) || ms < 0) return \"\";\n const minutes = Math.floor(ms / 60_000);\n if (minutes < 1) return \"just now\";\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 48) return `${hours}h ago`;\n return `${Math.floor(hours / 24)}d ago`;\n}\n","import * as fs from \"node:fs\";\nimport type { AccountClient, ApiSettingsBundle, ApiTemplate } from \"./api.js\";\nimport { compileBundleSource, diffBundle, settingsBundle, templateBundle, type CompiledBundleSource } from \"./bundle-source.js\";\nimport { findTemplate } from \"./template-ref.js\";\nimport { stripJsonComments } from \"../jsonc.js\";\nimport { PiPodError } from \"../errors.js\";\nimport { confirm } from \"../prompt.js\";\n\nexport async function bootstrapProjectTemplate(args: {\n client: AccountClient;\n cwd: string;\n home?: string;\n confirmCreate?: (question: string) => Promise<boolean>;\n}): Promise<ApiTemplate | null> {\n const source = await compileBundleSource({ source: \"project\", cwd: args.cwd, home: args.home });\n if (source.templateRef) return null;\n const question = `create template \\`${source.name}\\` from this project's config and pin it in .pi-pod/config.json?`;\n const approved = args.confirmCreate\n ? await args.confirmCreate(question)\n : await confirm(question, { nonInteractiveDefault: false });\n if (!approved) return null;\n const created = await args.client.createTemplate({\n name: source.name,\n config: source.config,\n initScript: source.initScript,\n bakeScript: source.bakeScript,\n piSettings: source.piFiles,\n });\n try {\n pinTemplateRef(source.configPath, created.name);\n } catch (error) {\n throw new PiPodError(`created template ${created.name}, but could not pin it in ${source.configPath}`, {\n hint: `add \\\"template\\\": ${JSON.stringify(created.name)} to that file`,\n cause: error,\n });\n }\n return created;\n}\n\n/** Insert a top-level JSONC property while retaining comments/spacing whenever the object is ordinary. */\nexport function pinTemplateRef(configPath: string, template: string): void {\n const text = fs.readFileSync(configPath, \"utf8\");\n const stripped = stripJsonComments(text);\n const close = stripped.lastIndexOf(\"}\");\n if (close < 0 || stripped.slice(close + 1).trim() !== \"\") {\n throw new PiPodError(`cannot pin template in ${configPath}: expected a top-level JSON object`);\n }\n const prefix = text.slice(0, close);\n // Add a sentinel before comment stripping so the JSONC tokenizer does not erase an\n // existing trailing comma as though the closing brace immediately followed it.\n const before = stripJsonComments(`${prefix}null`).slice(0, -4).trimEnd();\n const last = before.at(-1);\n const separator = last === \"{\" || last === \",\" ? \"\" : \",\";\n const entry = ` \"template\": ${JSON.stringify(template)}\\n`;\n const trimmed = prefix.trimEnd();\n // A trailing line comment would swallow anything appended after it; the sentinel probe\n // says whether the last significant line can safely take the separator inline.\n const canInline = stripJsonComments(`${trimmed}null`).trimEnd().endsWith(\"null\");\n const needsNewline = prefix.length > 0 && !prefix.endsWith(\"\\n\");\n const body = canInline\n ? `${trimmed}${separator}\\n${entry}`\n : `${prefix}${separator}${needsNewline ? \"\\n\" : \"\"}${entry}`;\n fs.writeFileSync(configPath, `${body}${text.slice(close)}`);\n}\n\nexport async function projectTemplateStaleness(args: {\n client: AccountClient;\n cwd: string;\n home?: string;\n}): Promise<string | null> {\n const source = await compileBundleSource({ source: \"project\", cwd: args.cwd, home: args.home, includeEnv: false });\n if (!source.templateRef) return null;\n const template = await findTemplate(args.client, source.templateRef);\n const drift = diffBundle(source, templateBundle(template));\n if (!drift.changed) return null;\n const version = template.version !== undefined ? ` v${template.version}` : \"\";\n return `local config differs from template ${template.name}${version} — ` +\n \"run `pipod push` to upload or `pipod pull` to adopt the template\";\n}\n\n/** Name the differing parts of a diff, at most four of them, for a one-line drift warning. */\nfunction driftSummary(lines: string[]): string {\n const labels: string[] = [];\n for (const line of lines) {\n if (line.startsWith(\"config \")) labels.push(line.slice(0, line.indexOf(\": \")));\n else if (line.endsWith(\": changed\")) labels.push(line.slice(0, -\": changed\".length));\n }\n return labels.length > 4 ? `${labels.slice(0, 4).join(\", \")}, …` : labels.join(\", \");\n}\n\n/**\n * `~/.pi-pod/config.json` + `~/.pi/agent/` are the user layer's local source now, so a launch\n * says when they and the server bundle have drifted apart. A missing source reads as empty.\n */\nexport async function userLayerStaleness(args: {\n client: AccountClient;\n home?: string;\n}): Promise<string | null> {\n let source: CompiledBundleSource;\n try {\n source = await compileBundleSource({ source: \"user-dir\", home: args.home, includeEnv: false });\n } catch (error) {\n // A drift check is advisory; an unreadable local file must not take the launch down.\n if (error instanceof PiPodError) return `user settings source: ${error.message}`;\n throw error;\n }\n let current: ApiSettingsBundle;\n try {\n current = await args.client.getUserSettings();\n } catch (error) {\n // Pod tokens may launch but cannot read the user bundle; the advisory check has no answer.\n if (error instanceof PiPodError && error.status === 403) return null;\n throw error;\n }\n const drift = diffBundle(source, settingsBundle(current));\n if (!drift.changed) return null;\n return `local user settings differ from the server user bundle v${current.version} ` +\n `(${driftSummary(drift.lines)}) — ` +\n \"run `pipod push user` to upload or `pipod pull user` to adopt the server copy\";\n}\n","/**\n * src/account/template-ref.ts — resolve a template by id or name.\n *\n * Shared by `pipod templates` and `pipod jobs push`, so name lookup is the same\n * everywhere: id match first, then case-insensitive name, user scope winning.\n */\nimport type { AccountClient, ApiTemplate } from \"./api.js\";\nimport { PiPodError } from \"../errors.js\";\n\n/** Servers that predate scoping omit the field; everything they hold is org-wide. */\nexport function scopeOf(t: Pick<ApiTemplate, \"scope\">): \"user\" | \"org\" {\n return t.scope ?? \"org\";\n}\n\n/** Templates are addressed by name in the CLI; uuids still work for scripts. */\nexport async function findTemplate(client: AccountClient, which: string | undefined): Promise<ApiTemplate> {\n if (!which) throw new PiPodError(\"which template?\", { hint: \"list them with `pipod templates`\" });\n const { templates } = await client.listTemplates();\n // Your personal template may share a name with an org one; yours wins, like at launch.\n const named = templates.filter((t) => t.name.toLowerCase() === which.toLowerCase());\n const match =\n templates.find((t) => t.id === which) ??\n named.find((t) => scopeOf(t) === \"user\") ??\n named[0];\n if (!match) {\n throw new PiPodError(`no template named \"${which}\" in this org`, {\n hint: templates.length ? `have: ${templates.map((t) => t.name).join(\", \")}` : \"this org has no templates yet\",\n });\n }\n return match;\n}\n","import { buildPiArgv } from \"../piargv.js\";\nimport { CancelledError, PiPodError } from \"../errors.js\";\nimport { color, info, step, warn } from \"../log.js\";\nimport type { AccountClient, ApiPod } from \"./api.js\";\nimport { parseAccountLaunchPiArgs } from \"./launch-args.js\";\nimport { planAccountLaunch } from \"./launch-preflight.js\";\nimport {\n launchRidingOutBlips,\n podReadySummary,\n printLaunchReport,\n tryAccountReuse,\n watchProvisioning,\n} from \"./launch-provision.js\";\nimport type {\n AccountLaunchFlags,\n AccountLaunchPlan,\n RunAccountLaunchOptions,\n} from \"./launch-types.js\";\nimport { seedWorkspace } from \"./launch-seed.js\";\nimport { runAccountSession } from \"./session.js\";\nimport { describeWorkspaceSeed } from \"./workspace-seed.js\";\nimport { displayRef } from \"./ref.js\";\nimport { withCapacityHint } from \"./capacity-errors.js\";\nimport { selectAccountPod } from \"./pods.js\";\nimport { bootstrapProjectTemplate, projectTemplateStaleness, userLayerStaleness } from \"./bundle-bootstrap.js\";\nimport { createWorkstationCycleTracker } from \"./workstation.js\";\n\n\n/** `--on <pod|self>`: validate the combination and resolve the ref to a placement body. */\nasync function resolvePlacementFlag(\n client: RunAccountLaunchOptions[\"client\"],\n flags: AccountLaunchFlags,\n): Promise<{ host: string } | undefined> {\n if (!flags.on) return undefined;\n if (flags.forkFrom) {\n throw new PiPodError(\"forking into a co-located pod is not supported yet\", {\n hint: \"fork without --on, or launch a plain co-located pod\",\n });\n }\n if (flags.dryRun) {\n throw new PiPodError(\"--dry-run does not support --on yet\", {\n hint: \"resolve without --on to preview the config layers\",\n });\n }\n if (flags.on === \"self\") {\n if (!client.isPodToken) {\n throw new PiPodError('--on self is only meaningful inside a pod', {\n hint: \"from your machine, name the pod to share: pipod --on <pod>\",\n });\n }\n return { host: \"self\" };\n }\n const host = await selectAccountPod(client, flags.on, \"place a pod on\");\n return { host: host.id };\n}\n\nexport async function runAccountLaunch(opts: RunAccountLaunchOptions): Promise<number> {\n const { client, flags } = opts;\n const { prompt, piOverrides, extraArgs, tuiMode } = parseAccountLaunchPiArgs(opts.piArgs);\n if (extraArgs.length > 0) {\n throw new PiPodError(\n `only --model, --thinking, -e/--extension, --skill, --prompt-template, and --tui-mode can be set per-launch in account mode: ${extraArgs.join(\" \")}`,\n { hint: \"set other Pi options in config (`pi.args`); resource paths name files or directories inside the pod\" },\n );\n }\n\n const hostCwd = opts.cwd ?? process.cwd();\n const cycles = createWorkstationCycleTracker();\n const placement = await resolvePlacementFlag(client, flags);\n let plan = await planAccountLaunch(\n client,\n { ...flags, home: flags.home ?? opts.home },\n hostCwd,\n piOverrides,\n { cycles },\n );\n const emittedWarnings = new Set<string>();\n const emitPlanWarnings = (): void => {\n for (const warning of plan.warnings) {\n if (emittedWarnings.has(warning)) continue;\n emittedWarnings.add(warning);\n warn(warning);\n }\n };\n emitPlanWarnings();\n announceSettingsChain(plan);\n announceWorkspaceSeed(plan);\n\n if (plan.projectRoot && plan.templateId) {\n const stale = await projectTemplateStaleness({ client, cwd: hostCwd, home: flags.home ?? opts.home });\n if (stale) warn(stale);\n }\n const userStale = await userLayerStaleness({ client, home: flags.home ?? opts.home });\n if (userStale) warn(userStale);\n\n let bootstrapWorkspaceSeed: AccountLaunchPlan[\"workspaceSeed\"];\n if (\n plan.projectRoot && !plan.templateId && !flags.template &&\n !flags.forkFrom && !flags.dryRun\n ) {\n info(\n `resolve preview: provider ${plan.resolve.provider}; image ${plan.resolve.image}; ` +\n `egress ${plan.resolve.egress.mode}; template none`,\n );\n const created = await bootstrapProjectTemplate({ client, cwd: hostCwd, home: flags.home ?? opts.home });\n if (created) {\n bootstrapWorkspaceSeed = plan.workspaceSeed;\n info(`created and pinned template ${created.name}`);\n }\n }\n\n // A projectConfig resolve is only the bootstrap preview. Whether creation was declined or\n // skipped, the real launch must be planned from server-custodied org/user settings alone.\n if (!flags.dryRun && plan.bootstrapPreview) {\n plan = await planAccountLaunch(\n client,\n { ...flags, home: flags.home ?? opts.home },\n hostCwd,\n piOverrides,\n { bootstrapPreview: false, cycles },\n );\n if (plan.templateId && !plan.workspaceSeed && bootstrapWorkspaceSeed) {\n // The just-created template may have no authored init script. Preserve the preview's\n // one-time workspace transport without turning it into a template/project settings body.\n plan.workspaceSeed = bootstrapWorkspaceSeed;\n }\n emitPlanWarnings();\n announceSettingsChain(plan);\n announceWorkspaceSeed(plan);\n }\n\n if (flags.dryRun) {\n printAccountDryRun(client, plan);\n return 0;\n }\n\n if (flags.forkFrom) {\n warn(\"fork copies the conversation, not the workspace — commit and push before forking if the new pod needs those changes\");\n }\n warnNoModelProvider(plan.resolve);\n const target = plan.resolve.template\n ? `${plan.resolve.template.name} template`\n : plan.projectName\n ? `project ${plan.projectName} (server defaults)`\n : \"server defaults\";\n const where = placement\n ? placement.host === \"self\"\n ? \" co-located on this pod's machine\"\n : ` co-located on ${displayRef(placement.host, \"pod\")}'s machine`\n : \"\";\n step(\"launch\", `${target} via ${client.serverUrl} (account mode)${where}`);\n const launchStartedAt = Date.now();\n // A source-less clone/archive asks the server to hold Pi until the workdir is seeded, so the\n // first session already sees the project's AGENTS.md and .pi/. Forks and co-located pods\n // are never seeded; the legacy configured-project copy keeps its post-start timing.\n const armsSeedGate =\n plan.workspaceSeed !== undefined &&\n (plan.workspaceSeed.kind === \"clone\" || plan.workspaceSeed.kind === \"archive\") &&\n !flags.forkFrom &&\n !placement;\n const launchBody = {\n ...(plan.templateId ? { templateId: plan.templateId } : {}),\n // A fork continues another pod's conversation, which belongs to that pod's project, not\n // to wherever the command happens to run.\n ...(plan.projectName && !flags.forkFrom ? { project: { name: plan.projectName } } : {}),\n ...(piOverrides ? { piOverrides } : {}),\n ...(flags.forkFrom ? { forkFrom: flags.forkFrom } : {}),\n ...(placement ? { placement } : {}),\n ...(armsSeedGate ? { workspaceSeed: true } : {}),\n };\n // A co-located pod has no machine of its own to reuse; a fresh one on the host is as fast.\n // Fresh pods are the default — only an explicit --reuse reuses a stopped project pod.\n const wantReuse = !flags.forkFrom && !placement && flags.reuse === true;\n let cancellation: CancelledError | null = null;\n let freshPodId: string | null = null;\n // Last preparationPhase seen for the fresh pod. The interrupt cleanup re-reads the\n // pod, but this is the fallback when that read fails (server unreachable mid-blip).\n let lastPhase: ApiPod[\"preparationPhase\"] | undefined;\n let piStarted = false;\n let cleanupPromise: Promise<void> | null = null;\n // Seeding streams an archive that may take minutes; Ctrl-C has to reach it mid-flight.\n const seedAbort = new AbortController();\n\n const deleteCancelledPod = (): Promise<void> => {\n if (!freshPodId) return Promise.resolve();\n cleanupPromise ??= (async () => {\n const podId = freshPodId!;\n // Re-read the pod before deleting: interrupting during seedWorkspace (or any\n // post-wait phase) means the pod is already live, and deleting it would destroy\n // work. Only a pod still queued in a bounded capacity wait is safe to delete;\n // anything else is left running with its id printed for `pipod attach` / `gc`.\n let phase = lastPhase;\n try {\n phase = (await client.getPod(podId)).preparationPhase;\n lastPhase = phase;\n } catch {\n // Fall back to the last observed phase when the re-read fails.\n }\n // End a bounded capacity wait first so the server finishes it as\n // `cancelled` instead of running it to `expired` (best-effort:\n // older servers 404 and the pod delete below still ends the wait).\n await client.cancelCapacityWait(podId).then(\n () => undefined,\n () => undefined,\n );\n if (phase === \"waiting-for-capacity\") {\n await client.deletePod(podId).then(\n () => info(`deleted canceled pod ${displayRef(podId, \"pod\")}`),\n (error: unknown) => {\n warn(\n `could not delete canceled pod ${displayRef(podId, \"pod\")}: ` +\n `${error instanceof Error ? error.message : String(error)} — delete it with \\`pipod gc --delete\\``,\n );\n },\n );\n } else {\n info(\n `interrupted — leaving pod ${displayRef(podId, \"pod\")} as is; ` +\n `reattach with \\`pipod attach ${displayRef(podId, \"pod\")}\\` or delete it with \\`pipod gc --delete\\``,\n );\n }\n })();\n return cleanupPromise;\n };\n const noteFreshPod = (pod: ApiPod): void => {\n freshPodId = pod.id;\n lastPhase = pod.preparationPhase;\n if (cancellation) void deleteCancelledPod();\n };\n const throwIfCancelled = (): void => {\n if (cancellation) throw cancellation;\n };\n const onInterrupt = (): void => {\n if (piStarted || cancellation) return;\n cancellation = new CancelledError(\"interrupted\");\n seedAbort.abort();\n warn(\n freshPodId\n ? `interrupted — checking pod ${displayRef(freshPodId, \"pod\")} before exit`\n : \"interrupted — checking whether the launch created a pod before exit\",\n );\n void deleteCancelledPod();\n };\n process.on(\"SIGINT\", onInterrupt);\n\n try {\n const workstation = { cycles, cancelled: () => cancellation !== null };\n let launched = wantReuse ? await tryAccountReuse(client, plan, launchBody, { workstation }) : null;\n let reused = launched !== null;\n throwIfCancelled();\n if (!launched) {\n launched = await launchRidingOutBlips(client, plan, launchBody, { cancelled: () => cancellation !== null, workstation });\n noteFreshPod(launched.pod);\n throwIfCancelled();\n }\n printLaunchReport(launched.report, launched.pod);\n let started = await watchProvisioning(client, launched.pod.id, { cancelled: () => cancellation !== null });\n lastPhase = started.preparationPhase;\n throwIfCancelled();\n if (started.resolvedConfig.reuseRefused) {\n // The candidate went back to stopped exactly as it was; this launch still owes a pod.\n info(`pod ${displayRef(launched.pod.id, \"pod\")} not reused — ${started.resolvedConfig.reuseRefused}; launching a fresh pod`);\n launched = await launchRidingOutBlips(client, plan, launchBody, { cancelled: () => cancellation !== null, workstation });\n noteFreshPod(launched.pod);\n reused = false;\n throwIfCancelled();\n printLaunchReport(launched.report, launched.pod);\n started = await watchProvisioning(client, launched.pod.id, { cancelled: () => cancellation !== null });\n lastPhase = started.preparationPhase;\n throwIfCancelled();\n }\n info(color.dim(podReadySummary(started, Date.now() - launchStartedAt)));\n\n // Only a pod this launch created owes a workspace; a reused one already has one, and\n // overwriting it would clobber work the previous session left behind. A co-located\n // child never owes one either: its \"pod workspace\" is the host's workdir, and seeding\n // into a shared filesystem would overwrite the host's own files.\n await seedWorkspace({\n client,\n pod: started,\n plan: plan.workspaceSeed,\n credential: plan.workspaceSeedCredential,\n reused,\n coLocated: placement !== undefined,\n // Only the server knows whether it honored the gate: an older one rejected the flag and\n // started Pi already, and a reused pod never armed one.\n gated: !reused && started.resolvedConfig.workspaceSeed?.status === \"pending\",\n signal: seedAbort.signal,\n });\n throwIfCancelled();\n\n const result = await runAccountSession({\n client,\n pod: started,\n config: plan.config,\n hostCwd: plan.projectRoot ?? hostCwd,\n startupPrompt: prompt,\n onPiStarted: () => {\n throwIfCancelled();\n piStarted = true;\n process.off(\"SIGINT\", onInterrupt);\n },\n ...(tuiMode ? { tuiMode } : {}),\n });\n return result.exitCode;\n } catch (error) {\n if (!piStarted && (cancellation || error instanceof CancelledError)) {\n await deleteCancelledPod();\n throw cancellation ?? error;\n }\n // Quota/capacity refusals arrive as plain server errors; add the actionable hint here so\n // launch, reuse-refusal relaunch, wake-on-attach, and seed paths all present the same copy.\n throw withCapacityHint(error);\n } finally {\n process.off(\"SIGINT\", onInterrupt);\n }\n}\n\nfunction announceSettingsChain(plan: AccountLaunchPlan): void {\n info(`settings chain: ${formatSettingsChain(plan)}`);\n}\n\n/** One line naming the transport before the pod exists, so a surprise is caught before it bills. */\nfunction announceWorkspaceSeed(plan: AccountLaunchPlan): void {\n const seed = plan.workspaceSeed;\n if (!seed) return;\n switch (seed.kind) {\n case \"none\":\n info(`workspace seed: none (${seed.reason})`);\n return;\n case \"copy\":\n info(`workspace transport: this directory will be copied into the pod (${seed.reason})`);\n return;\n case \"clone\":\n info(\n `workspace seed: the pod will clone ${seed.url} at ${seed.branch} (${seed.commit.slice(0, 12)})` +\n (seed.access === \"credential\" ? ` with forwarded ${seed.host} credentials` : \"\"),\n );\n break;\n case \"archive\":\n info(\n `workspace seed: ${seed.root} will be archived into the pod` +\n `${seed.includeGit ? \" with .git history\" : \"\"} (${seed.reason})`,\n );\n break;\n }\n if (seed.subdir !== \"\") {\n info(color.dim(`launched from ${seed.subdir}/ — the whole repository seeds the pod's workspace root`));\n }\n}\n\n\nexport function formatSettingsChain(plan: AccountLaunchPlan): string {\n const order = plan.resolve.layerOrder;\n if (!order) {\n return `org defaults${plan.templateId ? ` → template (${plan.templateScope ?? \"org\"})` : \"\"}` +\n `${plan.bootstrapPreview ? \" → project preview\" : \"\"} → org policy`;\n }\n const rendered = order.map((layer, index) => {\n if (layer !== \"template\") return displaySettingsLayer(layer, plan);\n const userIndex = order.indexOf(\"user\");\n const scope = plan.templateScope ?? (userIndex >= 0 && index > userIndex ? \"user\" : \"org\");\n return `template (${scope})`;\n });\n rendered.push(\"org policy\");\n return rendered.join(\" → \");\n}\n\nfunction displaySettingsLayer(layer: string, plan: AccountLaunchPlan): string {\n switch (layer) {\n case \"org\": return \"org defaults\";\n case \"user\": return \"user defaults\";\n case \"template\": return `template (${plan.templateScope ?? \"org\"})`;\n case \"project\": return plan.bootstrapPreview ? \"project preview\" : \"project\";\n case \"policy\":\n case \"org-policy\": return \"org policy\";\n default: return layer;\n }\n}\n\nfunction printAccountDryRun(client: AccountClient, plan: AccountLaunchPlan): void {\n info(`account mode dry-run via ${client.serverUrl} — nothing created`);\n if (plan.resolve.forkFrom) {\n const session = plan.resolve.forkFrom.sessionPath ? ` session ${plan.resolve.forkFrom.sessionPath}` : \"\";\n info(`fork from: ${plan.resolve.forkFrom.podId}${session}`);\n info(\"fork copies the conversation, not the workspace — commit and push before forking if the new pod needs those changes\");\n }\n if (plan.projectName) info(`project: ${plan.projectName}`);\n info(`template: ${plan.resolve.template?.name ?? \"none\"}`);\n info(`settings chain: ${formatSettingsChain(plan)}`);\n if (plan.bootstrapPreview) info(\"project config: bootstrap preview only; it will not travel in a launch request\");\n const r = plan.resolve;\n info(`provider: ${r.provider}`);\n info(\n `credential: ${r.credential.envVar} ${r.credential.available ? `available (${r.credential.source})` : \"MISSING\"}`,\n );\n info(`image: ${r.image}${r.imageStatus ? ` (${r.imageStatus})` : \"\"}`);\n info(`egress: ${r.egress.mode}`);\n info(`workdir: ${r.workdir}`);\n if (plan.workspaceSeed) {\n info(`workspace seed: ${describeWorkspaceSeed(plan.workspaceSeed)}`);\n if (plan.workspaceSeed.kind === \"clone\" && plan.workspaceSeed.access === \"credential\") {\n info(\n ` the remote is private: at launch, git credentials for ${plan.workspaceSeed.host} are read from ` +\n \"the credential helper or GitHub CLI, verified, and forwarded only if you approve; otherwise an archive is sent\",\n );\n }\n if ((plan.workspaceSeed.kind === \"clone\" || plan.workspaceSeed.kind === \"archive\") && plan.workspaceSeed.subdir !== \"\") {\n info(` launched from ${plan.workspaceSeed.subdir}/ inside the seed root`);\n }\n }\n info(`pi command: ${buildPiArgv(plan.config.pi).join(\" \")}`);\n const configProvenance = r.configProvenance ?? r.provenance;\n if (configProvenance && configProvenance.length > 0) {\n info(\"settings provenance (later layers win):\");\n for (const p of configProvenance) {\n const contested = p.over.length > 0\n ? color.dim(` (over ${p.over.map((layer) => displaySettingsLayer(layer, plan)).join(\", \")})`)\n : \"\";\n info(` ${p.path} ← ${displaySettingsLayer(p.winner, plan)}${contested}`);\n }\n }\n if (r.secretKeys.length > 0) {\n const scopes = r.secretScopes ?? {};\n const shadows = r.secretShadows ?? {};\n const labeled = r.secretKeys.map((k) => {\n const scope = scopes[k] ? `${k}(${scopes[k]})` : k;\n const lost = shadows[k];\n return lost?.length ? `${scope}[over ${lost.join(\",\")}]` : scope;\n });\n info(`secrets that would travel: ${labeled.join(\", \")}`);\n }\n const initScopes = r.initSteps.map((s) => displaySettingsLayer(s.scope, plan));\n if (initScopes.length > 0) info(`init steps: ${initScopes.join(\" → \")}`);\n if (r.piAuthProviders.length > 0) info(`pi auth providers: ${r.piAuthProviders.join(\", \")}`);\n if (r.piSettings) {\n info(`Pi settings: ${r.piSettings.files.join(\", \")} (${r.piSettings.packageCount} package(s))`);\n }\n for (const clamp of r.clamps) {\n warn(`org policy: ${clamp.path} ${JSON.stringify(clamp.from)} → ${JSON.stringify(clamp.to)} (${clamp.reason})`);\n }\n for (const warning of r.warnings) warn(warning);\n if (!r.credential.available) {\n warn(`launch would fail: no ${r.provider} credential — store org secret ${r.credential.envVar} or set it on the server`);\n }\n}\n\n/**\n * A pod signed in to no model provider has nothing to talk to, and pi's own advice there —\n * `/login` inside the pod — would keep the sign-in in that one pod. Say what works, up front.\n */\nexport function warnNoModelProvider(resolve: { piAuthProviders: string[] }): void {\n if (resolve.piAuthProviders.length > 0) return;\n warn(\"no model provider is connected, so pi in the pod has no model to use\");\n info(\" `pipod credentials connect` connects the ones your local pi uses; `pipod credentials` lists the rest\");\n}\n","/**\n * src/account/jobs.ts — `pipod jobs`, account edition only.\n *\n * Jobs are scheduled prompts the server runs for you: at each cron tick or specified time it\n * launches a pod from the job's template, starts a session with the job's model, and sends the prompt.\n * They live on the server because the schedule needs something always-on to fire it — the\n * laptop CLI manages them but never executes them. Local files in `.pi-pod/jobs/` are the\n * reviewable source; `jobs push` promotes them to the server.\n */\nimport * as path from \"node:path\";\nimport { findTemplate } from \"./template-ref.js\";\nimport type { AccountClient, ApiJob, ApiJobTrigger, ApiTemplate } from \"./api.js\";\nimport { PiPodError } from \"../errors.js\";\nimport {\n loadLocalJob,\n loadLocalJobs,\n projectJobsDirForWrite,\n triggersEqual,\n writeLocalJob,\n type JobTrigger,\n type LocalJobSpec,\n} from \"../jobfiles.js\";\nimport { color, info, out, warn } from \"../log.js\";\nimport { confirm } from \"../prompt.js\";\nimport { displayRef, matchesRef } from \"./ref.js\";\n\nexport interface AccountJobFlags {\n quiet: boolean;\n yes: boolean;\n project?: boolean;\n /** Create org jobs or promote matching user jobs during push. */\n org?: boolean;\n home?: string;\n cwd?: string;\n}\n\nexport async function runAccountJobs(\n client: AccountClient,\n args: string[],\n flags: AccountJobFlags,\n): Promise<number> {\n const action = args[0] ?? \"list\";\n if (flags.org && action !== \"push\") {\n throw new PiPodError(\"--org is only supported by `pipod jobs push`\");\n }\n switch (action) {\n case \"list\":\n assertArgCount(args, args.length === 0 ? 0 : 1, \"pipod jobs [list]\");\n return listJobs(client, flags);\n case \"show\":\n assertArgCount(args, 2, \"pipod jobs show <job>\");\n return showJob(client, await selectJob(client, args[1]!, action));\n case \"runs\":\n assertArgCount(args, 2, \"pipod jobs runs <job>\");\n return listRuns(client, await selectJob(client, args[1]!, action));\n case \"activate\":\n case \"pause\":\n case \"resume\": {\n assertArgCount(args, 2, `pipod jobs ${action} <job>`);\n const job = await selectJob(client, args[1]!, action);\n const { status } = await client.jobCommand(job.id, action);\n info(`job ${job.name}: ${status}`);\n return 0;\n }\n case \"run\": {\n assertArgCount(args, 2, \"pipod jobs run <job>\");\n const job = await selectJob(client, args[1]!, action);\n await client.jobCommand(job.id, \"run\");\n info(`job ${job.name}: starting a run now — \\`pipod jobs runs ${job.name}\\` shows it within a minute`);\n return 0;\n }\n case \"rm\": {\n assertArgCount(args, 2, \"pipod jobs rm <job>\");\n const job = await selectJob(client, args[1]!, action);\n const ok = await confirm(`remove job \"${job.name}\"? Its schedule stops firing.`, {\n nonInteractiveDefault: false,\n assumeYes: flags.yes,\n });\n if (!ok) return 1;\n await client.deleteJob(job.id);\n info(`job ${job.name} removed`);\n return 0;\n }\n case \"push\":\n return pushJobs(client, args.slice(1), flags);\n case \"pull\":\n if (args.length !== 2) throw new PiPodError(\"usage: pipod jobs pull <job> [--project]\");\n return pullJob(client, args[1]!, flags);\n case \"diff\":\n return diffJobs(client, args.slice(1), flags);\n default:\n throw new PiPodError(`unknown jobs action \"${action}\"`, {\n hint: \"one of: list, show, runs, run, activate, pause, resume, rm, push, pull, diff — see `pipod jobs --help`\",\n });\n }\n}\n\nasync function listJobs(client: AccountClient, flags: AccountJobFlags): Promise<number> {\n const jobs = await allJobs(client);\n if (flags.quiet) {\n for (const job of jobs) out(job.id);\n return 0;\n }\n if (jobs.length === 0) {\n info(\"no jobs — add one in .pi-pod/jobs/ and `pipod jobs push`, or ask the agent inside a pod\");\n return 0;\n }\n info(`jobs on ${client.serverUrl}:`);\n for (const job of jobs) {\n const next = job.status === \"active\" && job.nextRunAt ? `next ${ago(job.nextRunAt) || job.nextRunAt}` : \"\";\n info(\n ` ${color.bold(pad(displayRef(job.id, \"job\"), 12))} ${pad(job.name, 24)} ${pad(job.scope ?? \"user\", 5)} ${pad(job.status, 9)} ${pad(shortSchedule(job.trigger), 24)} ${next}`,\n );\n }\n return 0;\n}\n\nasync function showJob(client: AccountClient, job: ApiJob): Promise<number> {\n info(`${color.bold(job.name)} (${job.id})`);\n if (job.description) info(` ${job.description}`);\n // Old servers may still return \"draft\"; render it as-is and let `activate` handle it.\n info(` scope: ${job.scope ?? \"user\"}`);\n info(` status: ${job.status}`);\n if (job.trigger.type === \"cron\") {\n info(` schedule: cron \"${job.trigger.cron}\" (UTC)`);\n } else {\n info(` schedule: ${job.trigger.times.length === 1 ? \"once\" : `${job.trigger.times.length} times`} (absolute times)`);\n for (const time of job.trigger.times) info(` ${time}`);\n }\n info(` template: ${job.templateId ? await templateName(client, job.templateId) : \"default\"}`);\n info(` model: ${job.model}`);\n info(` next run: ${job.nextRunAt ?? \"—\"}`);\n info(` last run: ${job.lastRunAt ?? \"never\"}`);\n info(` prompt:`);\n for (const line of job.prompt.split(\"\\n\")) info(` ${line}`);\n return 0;\n}\n\nasync function listRuns(client: AccountClient, job: ApiJob): Promise<number> {\n const { runs } = await client.jobRuns(job.id);\n if (runs.length === 0) {\n info(`no runs yet for ${job.name}`);\n return 0;\n }\n info(`runs of ${job.name}:`);\n for (const run of runs) {\n const pod = run.podId ? `pod ${displayRef(run.podId, \"pod\")}` : \"\";\n const error = run.error ? ` — ${run.error}` : \"\";\n info(` ${pad(ago(run.startedAt) || run.startedAt, 12)} ${pad(run.status, 10)} ${pod}${error}`);\n }\n return 0;\n}\n\ninterface JobPlan {\n local: LocalJobSpec;\n server: ApiJob | undefined;\n templateId: string | null;\n templateLabel: string;\n changes: FieldChange[];\n staleServer: boolean;\n desiredScope: \"user\" | \"org\";\n}\n\ninterface FieldChange {\n field: string;\n summary: string;\n patch?: Record<string, unknown>;\n}\n\nasync function selectLocals(names: string[], flags: AccountJobFlags): Promise<LocalJobSpec[]> {\n const opts = { cwd: flags.cwd, home: flags.home };\n if (names.length === 0) return loadLocalJobs(opts);\n return names.map((name) => loadLocalJob(name, opts));\n}\n\nasync function planJobs(client: AccountClient, locals: LocalJobSpec[], promoteToOrg: boolean): Promise<JobPlan[]> {\n const serverJobs = await allJobs(client);\n const byName = new Map(serverJobs.map((job) => [job.name, job]));\n const templates = await client.listTemplates().catch(() => ({ templates: [] as ApiTemplate[] }));\n const plans: JobPlan[] = [];\n for (const local of locals) {\n const templateId = local.template ? (await findTemplate(client, local.template)).id : null;\n const server = byName.get(local.name);\n const templateLabel = templateDisplay(templateId, templates.templates);\n const desiredScope: \"user\" | \"org\" = promoteToOrg ? \"org\" : (server?.scope ?? \"user\");\n const changes = server\n ? diffFields(local, server, templateId, templates.templates, desiredScope)\n : [{ field: \"(new)\", summary: `create as ${desiredScope}-scoped on the server`, patch: undefined }];\n const staleServer = Boolean(\n server && local.mtimeMs > 0 && Date.parse(server.updatedAt) > local.mtimeMs,\n );\n plans.push({ local, server, templateId, templateLabel, changes, staleServer, desiredScope });\n }\n return plans;\n}\n\nfunction templateDisplay(id: string | null, templates: ApiTemplate[]): string {\n if (!id) return \"default\";\n return templates.find((t) => t.id === id)?.name ?? id;\n}\n\nfunction diffFields(\n local: LocalJobSpec,\n server: ApiJob,\n templateId: string | null,\n templates: ApiTemplate[],\n desiredScope: \"user\" | \"org\",\n): FieldChange[] {\n const changes: FieldChange[] = [];\n if ((server.scope ?? \"user\") !== desiredScope) {\n changes.push({\n field: \"scope\",\n summary: `${server.scope ?? \"user\"} → ${desiredScope} (one-way promotion; the user layer will no longer apply)`,\n patch: { scope: desiredScope },\n });\n }\n const localDescription = local.description ?? null;\n if ((localDescription ?? \"\") !== (server.description ?? \"\")) {\n changes.push({\n field: \"description\",\n summary: `${fmt(server.description)} → ${fmt(localDescription)}`,\n patch: { description: local.description ?? \"\" },\n });\n }\n if (!triggersEqual(local.trigger, server.trigger)) {\n changes.push({\n field: \"trigger\",\n summary: `${shortSchedule(server.trigger)} → ${shortSchedule(local.trigger)}`,\n patch: { trigger: local.trigger },\n });\n }\n if ((server.templateId ?? null) !== templateId) {\n changes.push({\n field: \"template\",\n summary: `${templateDisplay(server.templateId, templates)} → ${templateDisplay(templateId, templates)}`,\n patch: { templateId },\n });\n }\n if (local.model !== server.model) {\n changes.push({\n field: \"model\",\n summary: `${server.model} → ${local.model}`,\n patch: { model: local.model },\n });\n }\n if (local.prompt !== server.prompt) {\n changes.push({\n field: \"prompt\",\n summary: unifiedTextDiff(server.prompt, local.prompt),\n patch: { prompt: local.prompt },\n });\n }\n return changes;\n}\n\nfunction fmt(value: string | null | undefined): string {\n return value ? JSON.stringify(value) : \"(none)\";\n}\n\nfunction printPlan(plan: JobPlan): void {\n const layer = plan.local.layer === \"project\" ? \"project .pi-pod/jobs/\" : \"~/.pi-pod/jobs/\";\n const dest = plan.server ? `server ${displayRef(plan.server.id, \"job\")} (${plan.server.status})` : \"new on the server\";\n info(`${color.bold(plan.local.name)} ${color.dim(`${layer} → ${dest}`)}`);\n // A run moves the server's timestamp too; it matters only when the specs differ.\n if (plan.staleServer && plan.server && plan.changes.length > 0) {\n warn(\n `server copy of \"${plan.local.name}\" was updated more recently than the local file (server ${plan.server.updatedAt})`,\n );\n }\n if (plan.changes.length === 0) {\n info(\" in sync\");\n return;\n }\n for (const change of plan.changes) {\n if (change.field === \"prompt\") {\n info(\" prompt:\");\n for (const line of change.summary.split(\"\\n\")) info(` ${line}`);\n } else {\n info(` ${change.field}: ${change.summary}`);\n }\n }\n}\n\nfunction printUnmanaged(serverJobs: ApiJob[], locals: LocalJobSpec[]): void {\n const localNames = new Set(locals.map((job) => job.name));\n const unmanaged = serverJobs.filter((job) => !localNames.has(job.name));\n if (unmanaged.length === 0) return;\n info(\"server-only (unmanaged) — `jobs pull` to adopt, `jobs rm` to archive:\");\n for (const job of unmanaged) {\n info(` ${job.name} ${job.scope ?? \"user\"} ${job.status} ${shortSchedule(job.trigger)}`);\n }\n}\n\nasync function pushJobs(client: AccountClient, names: string[], flags: AccountJobFlags): Promise<number> {\n const locals = await selectLocals(names, flags);\n if (locals.length === 0) {\n info(\"no local job files — nothing to push\");\n printUnmanaged(await allJobs(client), locals);\n return 0;\n }\n const plans = await planJobs(client, locals, flags.org === true);\n for (const plan of plans) printPlan(plan);\n printUnmanaged(await allJobs(client), names.length === 0 ? locals : await loadLocalJobs({ cwd: flags.cwd, home: flags.home }));\n\n const dirty = plans.filter((plan) => plan.changes.length > 0);\n if (dirty.length === 0) {\n info(\"everything named is in sync\");\n return 0;\n }\n const ok = await confirm(`push ${dirty.length} job(s)? New jobs become active immediately.`, {\n nonInteractiveDefault: false,\n assumeYes: flags.yes,\n });\n if (!ok) return 1;\n\n for (const plan of dirty) {\n if (!plan.server) {\n const created = await client.createJob({\n name: plan.local.name,\n ...(plan.local.description !== undefined ? { description: plan.local.description } : {}),\n trigger: plan.local.trigger,\n templateId: plan.templateId,\n model: plan.local.model,\n prompt: plan.local.prompt,\n ...(plan.desiredScope === \"org\" ? { scope: \"org\" as const } : {}),\n });\n info(\n `created ${created.name} (${created.status}) next run ${created.nextRunAt ?? \"—\"}`,\n );\n continue;\n }\n const patch: Record<string, unknown> = {};\n for (const change of plan.changes) Object.assign(patch, change.patch ?? {});\n const updated = await client.patchJob(plan.server.id, patch);\n if (updated.status === \"paused\") {\n info(`updated ${updated.name} — still paused (status is not changed by push)`);\n } else {\n info(`updated ${updated.name} (${updated.status})`);\n }\n }\n return 0;\n}\n\nasync function diffJobs(client: AccountClient, names: string[], flags: AccountJobFlags): Promise<number> {\n const locals = await selectLocals(names, flags);\n if (locals.length === 0) {\n info(\"no local job files\");\n printUnmanaged(await allJobs(client), locals);\n return 0;\n }\n const plans = await planJobs(client, locals, false);\n let drifted = false;\n for (const plan of plans) {\n printPlan(plan);\n if (plan.changes.length > 0) drifted = true;\n }\n printUnmanaged(\n await allJobs(client),\n names.length === 0 ? locals : await loadLocalJobs({ cwd: flags.cwd, home: flags.home }),\n );\n return drifted ? 1 : 0;\n}\n\n/** A template's name, or its id when it cannot be found (deleted, or not visible to you). */\nasync function templateName(client: AccountClient, id: string): Promise<string> {\n try {\n return (await findTemplate(client, id)).name;\n } catch {\n return id;\n }\n}\n\nasync function pullJob(client: AccountClient, ref: string, flags: AccountJobFlags): Promise<number> {\n const job = await selectJob(client, ref, \"pull\");\n const template = job.templateId ? await templateName(client, job.templateId) : null;\n const written = writeLocalJob(\n {\n name: job.name,\n description: job.description,\n trigger: job.trigger,\n template,\n model: job.model,\n prompt: job.prompt,\n },\n {\n cwd: flags.cwd,\n home: flags.home,\n project: flags.project,\n overwrite: flags.yes,\n },\n );\n const dest = flags.project ? projectJobsDirForWrite(flags.cwd ?? process.cwd(), flags.home) : path.dirname(written.jsonPath);\n info(`wrote ${path.relative(dest, written.jsonPath) || written.jsonPath} and ${path.basename(written.promptPath)}`);\n return 0;\n}\n\n/** Full id, short ref, legacy prefix, or name. Exact UUIDs avoid a paginated list. */\nasync function selectJob(client: AccountClient, ref: string, _action: string): Promise<ApiJob> {\n if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(ref)) {\n return client.getJob(ref.toLowerCase());\n }\n const jobs = await allJobs(client);\n const named = jobs.filter((job) => job.name === ref);\n if (named.length === 1) return named[0]!;\n if (named.length > 1) throw ambiguousJobRef(ref, named);\n\n const matches = jobs.filter((job) => matchesRef(job.id, ref));\n if (matches.length === 1) return matches[0]!;\n if (matches.length > 1) throw ambiguousJobRef(ref, matches);\n throw new PiPodError(`no job matches \"${ref}\"`, { hint: \"see `pipod jobs`\" });\n}\n\nfunction ambiguousJobRef(ref: string, jobs: ApiJob[]): PiPodError {\n const refs = jobs.map((job) => displayRef(job.id, \"job\"));\n const counts = new Map<string, number>();\n for (const display of refs) counts.set(display, (counts.get(display) ?? 0) + 1);\n const choices = jobs\n .map((job, index) => {\n const display = refs[index]!;\n const unambiguousRef = counts.get(display)! > 1 ? job.id : display;\n return ` ${unambiguousRef} ${job.name} (${job.status})`;\n })\n .join(\"\\n\");\n return new PiPodError(`\"${ref}\" matches ${jobs.length} jobs`, {\n hint: `use a longer ref:\\n${choices}`,\n });\n}\n\nasync function allJobs(client: AccountClient): Promise<ApiJob[]> {\n const jobs: ApiJob[] = [];\n let before: string | undefined;\n let beforeId: string | undefined;\n for (;;) {\n const page = await client.listJobs({ limit: 200, before, beforeId });\n jobs.push(...page.jobs);\n if (page.jobs.length < 200) return jobs;\n const last = page.jobs.at(-1);\n if (!last || (last.createdAt === before && last.id === beforeId)) return jobs;\n before = last.createdAt;\n beforeId = last.id;\n }\n}\n\nfunction assertArgCount(args: string[], expected: number, usage: string): void {\n if (args.length !== expected) throw new PiPodError(`usage: ${usage}`);\n}\n\nfunction shortSchedule(trigger: ApiJobTrigger | JobTrigger): string {\n if (trigger.type === \"cron\") return trigger.cron;\n return trigger.times.length === 1 ? `once ${trigger.times[0]}` : `${trigger.times.length} scheduled times`;\n}\n\nfunction pad(s: string, width: number): string {\n return s.length >= width ? s : s + \" \".repeat(width - s.length);\n}\n\n/** Relative time in either direction: \"3h ago\" for the past, \"in 3h\" for the future. */\nfunction ago(iso: string): string {\n const ms = Date.now() - new Date(iso).getTime();\n if (!Number.isFinite(ms)) return \"\";\n const minutes = Math.floor(Math.abs(ms) / 60_000);\n const spell = (n: number) => {\n if (n < 1) return \"now\";\n if (n < 60) return `${n}m`;\n const hours = Math.floor(n / 60);\n if (hours < 48) return `${hours}h`;\n return `${Math.floor(hours / 24)}d`;\n };\n const word = spell(minutes);\n if (word === \"now\") return ms >= 0 ? \"just now\" : \"now\";\n return ms >= 0 ? `${word} ago` : `in ${word}`;\n}\n\n/** Compact unified text diff for prompts. Identical strings return an empty string. */\nexport function unifiedTextDiff(from: string, to: string): string {\n const a = from.split(\"\\n\");\n const b = to.split(\"\\n\");\n const lcs = longestCommonSubsequence(a, b);\n const lines: string[] = [\"--- server\", \"+++ local\"];\n let i = 0;\n let j = 0;\n let k = 0;\n while (i < a.length || j < b.length) {\n if (k < lcs.length && i < a.length && a[i] === lcs[k]) {\n if (j < b.length && b[j] === lcs[k]) {\n lines.push(` ${a[i]}`);\n i += 1;\n j += 1;\n k += 1;\n } else {\n lines.push(`+${b[j] ?? \"\"}`);\n j += 1;\n }\n } else if (k < lcs.length && j < b.length && b[j] === lcs[k]) {\n lines.push(`-${a[i] ?? \"\"}`);\n i += 1;\n } else if (i < a.length && (j >= b.length || a[i] !== b[j])) {\n lines.push(`-${a[i]}`);\n i += 1;\n } else if (j < b.length) {\n lines.push(`+${b[j]}`);\n j += 1;\n }\n }\n return lines.join(\"\\n\");\n}\n\nfunction longestCommonSubsequence(a: string[], b: string[]): string[] {\n const n = a.length;\n const m = b.length;\n const dp: number[][] = Array.from({ length: n + 1 }, () => Array<number>(m + 1).fill(0));\n for (let i = 1; i <= n; i += 1) {\n for (let j = 1; j <= m; j += 1) {\n dp[i]![j] = a[i - 1] === b[j - 1] ? dp[i - 1]![j - 1]! + 1 : Math.max(dp[i - 1]![j]!, dp[i]![j - 1]!);\n }\n }\n const out: string[] = [];\n let i = n;\n let j = m;\n while (i > 0 && j > 0) {\n if (a[i - 1] === b[j - 1]) {\n out.push(a[i - 1]!);\n i -= 1;\n j -= 1;\n } else if (dp[i - 1]![j]! >= dp[i]![j - 1]!) {\n i -= 1;\n } else {\n j -= 1;\n }\n }\n return out.reverse();\n}\n","/**\n * src/jobfiles.ts — local job specs in `~/.pi-pod/jobs/` and the project's `.pi-pod/jobs/`.\n *\n * Files hold the declarative spec only (trigger, template, model, prompt). Status,\n * next_run_at, and run history stay on the server — the server is the only thing that\n * fires schedules. Project files win on a name collision; push prints which layer\n * supplied each job.\n */\nimport { CronExpressionParser } from \"cron-parser\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { CONFIG_DIR, findConfigPath } from \"./config.js\";\nimport { PiPodError } from \"./errors.js\";\nimport { parseJsonc } from \"./jsonc.js\";\nimport { userConfigDir } from \"./userconfig.js\";\n\nexport const MIN_INTERVAL_MINUTES = 5;\nexport const MAX_AT_TIMES = 100;\nexport const MAX_PROMPT_BYTES = 64 * 1024;\nexport const MAX_NAME_LENGTH = 100;\nexport const JOBS_SUBDIR = \"jobs\";\n\nexport type JobLayer = \"user\" | \"project\";\n\nexport interface CronJobTrigger {\n type: \"cron\";\n cron: string;\n}\n\nexport interface AtJobTrigger {\n type: \"at\";\n times: string[];\n}\n\nexport type JobTrigger = CronJobTrigger | AtJobTrigger;\n\nexport interface LocalJobSpec {\n name: string;\n description?: string;\n trigger: JobTrigger;\n template?: string;\n model: string;\n prompt: string;\n sourcePath: string;\n promptPath?: string;\n layer: JobLayer;\n mtimeMs: number;\n}\n\nexport interface JobsDirOptions {\n cwd?: string;\n home?: string;\n}\n\nexport interface ResolvedJobsDirs {\n userDir: string | null;\n projectDir: string | null;\n}\n\nfunction realpathOr(p: string): string {\n try {\n return fs.realpathSync(p);\n } catch {\n return path.resolve(p);\n }\n}\n\nfunction samePath(a: string, b: string): boolean {\n return a === b || realpathOr(a) === realpathOr(b);\n}\n\nfunction fail(source: string, field: string, message: string): never {\n throw new PiPodError(`${source}: ${field}: ${message}`);\n}\n\nexport function userJobsDir(home?: string): string | null {\n const root = userConfigDir(home);\n return root ? path.join(root, JOBS_SUBDIR) : null;\n}\n\n/** Existing project `.pi-pod/jobs/` walking up from cwd, or null when there is none. */\nexport function findProjectJobsDir(cwd: string, home?: string): string | null {\n const userDir = userConfigDir(home);\n const homeDir = userDir ? path.dirname(userDir) : null;\n let dir = path.resolve(cwd);\n for (;;) {\n const configDir = path.join(dir, CONFIG_DIR);\n const jobsDir = path.join(configDir, JOBS_SUBDIR);\n const isUser = userDir !== null && samePath(configDir, userDir);\n if (!isUser && fs.existsSync(jobsDir) && fs.statSync(jobsDir).isDirectory()) {\n return jobsDir;\n }\n if (homeDir !== null && samePath(dir, homeDir)) return null;\n const parent = path.dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n\n/**\n * Where `jobs pull --project` writes. Prefers an existing jobs dir, then the project\n * `.pi-pod/` that owns config.json, then `cwd/.pi-pod/jobs`.\n */\nexport function projectJobsDirForWrite(cwd: string, home?: string): string {\n const existing = findProjectJobsDir(cwd, home);\n if (existing) return existing;\n const configPath = findConfigPath(cwd, { home });\n if (configPath) return path.join(path.dirname(configPath), JOBS_SUBDIR);\n return path.join(path.resolve(cwd), CONFIG_DIR, JOBS_SUBDIR);\n}\n\nexport function resolveJobsDirs(opts: JobsDirOptions = {}): ResolvedJobsDirs {\n const cwd = opts.cwd ?? process.cwd();\n const userDir = userJobsDir(opts.home);\n return {\n userDir: userDir && fs.existsSync(userDir) && fs.statSync(userDir).isDirectory() ? userDir : null,\n projectDir: findProjectJobsDir(cwd, opts.home),\n };\n}\n\nexport function parseModelRef(model: string, source = \"job\", field = \"model\"): { provider: string; id: string } {\n const slash = model.indexOf(\"/\");\n if (slash <= 0 || slash === model.length - 1) {\n fail(source, field, `invalid model \"${model}\" — use \"provider/model-id\", e.g. \"anthropic/claude-opus-4-7\"`);\n }\n return { provider: model.slice(0, slash), id: model.slice(slash + 1) };\n}\n\nexport function normalizeJobTrigger(\n trigger: { type: string; cron?: string; times?: string[] },\n source = \"job\",\n field = \"trigger\",\n): JobTrigger {\n if (trigger.type === \"cron\") {\n if (!trigger.cron) fail(source, field, \"a cron trigger needs a cron expression\");\n const cron = trigger.cron.trim();\n const fields = cron.split(/\\s+/);\n if (fields.length !== 5) {\n fail(\n source,\n `${field}.cron`,\n `invalid cron expression \"${trigger.cron}\" — use exactly 5 fields: minute hour day-of-month month day-of-week`,\n );\n }\n let expr: ReturnType<typeof CronExpressionParser.parse>;\n try {\n expr = CronExpressionParser.parse(cron, { tz: \"UTC\" });\n } catch (e) {\n fail(\n source,\n `${field}.cron`,\n `invalid cron expression \"${trigger.cron}\": ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n\n const minutes = [...expr.fields.minute.values];\n const hours = [...expr.fields.hour.values];\n const times = hours.flatMap((hour) => minutes.map((minute) => hour * 60 + minute)).sort((a, b) => a - b);\n const intradayTooClose = times.slice(0, -1).some((time, index) => times[index + 1]! - time < MIN_INTERVAL_MINUTES);\n const midnightGap = times[0]! + 24 * 60 - times.at(-1)!;\n const tooClose =\n intradayTooClose || (midnightGap < MIN_INTERVAL_MINUTES && calendarCanMatchConsecutiveDays(fields.slice(2)));\n if (tooClose) {\n fail(\n source,\n `${field}.cron`,\n `cron \"${trigger.cron}\" fires more often than every ${MIN_INTERVAL_MINUTES} minutes — each run launches a pod, so schedule accordingly`,\n );\n }\n return { type: \"cron\", cron };\n }\n\n if (trigger.type !== \"at\") {\n fail(source, field, `unsupported trigger type \"${trigger.type}\" — use \"cron\" or \"at\"`);\n }\n if (!trigger.times || trigger.times.length === 0) {\n fail(source, `${field}.times`, \"an at trigger needs at least one timestamp\");\n }\n if (trigger.times.length > MAX_AT_TIMES) {\n fail(source, `${field}.times`, `an at trigger supports at most ${MAX_AT_TIMES} timestamps`);\n }\n\n const times = trigger.times.map((timestamp, index) =>\n normalizeTimestamp(timestamp, source, `${field}.times[${index}]`),\n );\n times.sort();\n for (let index = 1; index < times.length; index += 1) {\n const previous = Date.parse(times[index - 1]!);\n const current = Date.parse(times[index]!);\n if (current === previous) {\n fail(source, `${field}.times`, `at trigger contains duplicate timestamp \"${times[index]}\"`);\n }\n if (current - previous < MIN_INTERVAL_MINUTES * 60_000) {\n fail(\n source,\n `${field}.times`,\n `at trigger timestamps must be at least ${MIN_INTERVAL_MINUTES} minutes apart — each run launches a pod`,\n );\n }\n }\n return { type: \"at\", times };\n}\n\nconst ISO_INSTANT = /^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})$/;\n\nfunction normalizeTimestamp(timestamp: string, source: string, field: string): string {\n const match = ISO_INSTANT.exec(timestamp);\n const parsed = Date.parse(timestamp);\n if (!match || !Number.isFinite(parsed)) {\n fail(source, field, `invalid at timestamp \"${timestamp}\" — use ISO 8601 with an explicit timezone`);\n }\n const [, year, month, day, hour, minute, second] = match;\n if (Number(hour) > 23 || Number(minute) > 59 || Number(second) > 59) {\n fail(source, field, `invalid at timestamp \"${timestamp}\"`);\n }\n const calendarDate = new Date(`${year}-${month}-${day}T00:00:00.000Z`);\n if (!Number.isFinite(calendarDate.getTime()) || calendarDate.toISOString().slice(0, 10) !== `${year}-${month}-${day}`) {\n fail(source, field, `invalid at timestamp \"${timestamp}\"`);\n }\n return new Date(parsed).toISOString();\n}\n\nfunction calendarCanMatchConsecutiveDays(dateFields: string[]): boolean {\n const start = new Date(\"2000-01-01T00:00:00Z\");\n const end = new Date(\"2400-01-01T00:00:00Z\");\n const days = CronExpressionParser.parse(`0 12 ${dateFields.join(\" \")}`, {\n tz: \"UTC\",\n currentDate: start,\n endDate: end,\n });\n let previous: number | null = null;\n for (;;) {\n try {\n const current = days.next().getTime();\n if (previous !== null && current - previous === 24 * 60 * 60_000) return true;\n previous = current;\n } catch {\n return false;\n }\n }\n}\n\nconst ALLOWED_KEYS = new Set([\"description\", \"trigger\", \"template\", \"model\", \"prompt\", \"promptFile\"]);\n\nfunction asRecord(value: unknown, source: string): Record<string, unknown> {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n fail(source, \"(root)\", \"job file must be a JSON object\");\n }\n return value as Record<string, unknown>;\n}\n\nfunction readString(raw: Record<string, unknown>, key: string, source: string): string | undefined {\n if (!(key in raw)) return undefined;\n const value = raw[key];\n if (typeof value !== \"string\") fail(source, key, \"must be a string\");\n return value;\n}\n\nexport function parseJobFile(text: string, sourcePath: string, layer: JobLayer): LocalJobSpec {\n const source = sourcePath;\n const name = path.basename(sourcePath, \".json\");\n if (!name || name.length > MAX_NAME_LENGTH) {\n fail(source, \"name\", `job name (filename stem) must be 1–${MAX_NAME_LENGTH} characters`);\n }\n\n const raw = asRecord(parseJsonc(text, sourcePath), source);\n for (const key of Object.keys(raw)) {\n if (!ALLOWED_KEYS.has(key)) fail(source, key, `unknown field — expected one of ${[...ALLOWED_KEYS].join(\", \")}`);\n }\n\n const description = readString(raw, \"description\", source);\n const template = readString(raw, \"template\", source);\n const model = readString(raw, \"model\", source);\n if (!model || !model.trim()) fail(source, \"model\", \"required\");\n parseModelRef(model, source, \"model\");\n\n if (!raw.trigger || typeof raw.trigger !== \"object\" || Array.isArray(raw.trigger)) {\n fail(source, \"trigger\", \"required object with type \\\"cron\\\" or \\\"at\\\"\");\n }\n const triggerRaw = raw.trigger as { type?: unknown; cron?: unknown; times?: unknown };\n if (typeof triggerRaw.type !== \"string\") fail(source, \"trigger.type\", \"required\");\n const trigger = normalizeJobTrigger(\n {\n type: triggerRaw.type,\n cron: typeof triggerRaw.cron === \"string\" ? triggerRaw.cron : undefined,\n times: Array.isArray(triggerRaw.times) ? triggerRaw.times.map((time) => String(time)) : undefined,\n },\n source,\n \"trigger\",\n );\n\n const prompt = readString(raw, \"prompt\", source);\n const promptFile = readString(raw, \"promptFile\", source);\n if (prompt !== undefined && promptFile !== undefined) {\n fail(source, \"prompt\", \"prompt and promptFile are mutually exclusive\");\n }\n if (prompt === undefined && promptFile === undefined) {\n fail(source, \"prompt\", \"set prompt or promptFile\");\n }\n\n let resolvedPrompt = prompt ?? \"\";\n let promptPath: string | undefined;\n if (promptFile !== undefined) {\n if (!promptFile.trim()) fail(source, \"promptFile\", \"must not be empty\");\n // A job file arrives with a checkout and its prompt is uploaded: it may name only a file\n // beside it, never one elsewhere on this machine.\n if (promptFile !== path.basename(promptFile) || promptFile === \".\" || promptFile === \"..\") {\n fail(source, \"promptFile\", \"must be a file name in the same directory as the job file\");\n }\n promptPath = path.join(path.dirname(sourcePath), promptFile);\n if (!fs.existsSync(promptPath)) fail(source, \"promptFile\", `file not found: ${promptPath}`);\n if (!fs.lstatSync(promptPath).isFile()) fail(source, \"promptFile\", \"must be a regular file, not a symlink\");\n resolvedPrompt = fs.readFileSync(promptPath, \"utf8\");\n }\n if (!resolvedPrompt.trim()) fail(source, promptFile !== undefined ? \"promptFile\" : \"prompt\", \"prompt must not be empty\");\n if (Buffer.byteLength(resolvedPrompt, \"utf8\") > MAX_PROMPT_BYTES) {\n fail(\n source,\n promptFile !== undefined ? \"promptFile\" : \"prompt\",\n `prompt must be at most ${MAX_PROMPT_BYTES} bytes`,\n );\n }\n\n let mtimeMs = 0;\n try {\n mtimeMs = fs.statSync(sourcePath).mtimeMs;\n } catch {\n // Parse-only callers (tests with no file) leave mtime at 0.\n }\n\n return {\n name,\n ...(description !== undefined ? { description } : {}),\n trigger,\n ...(template !== undefined && template.trim() ? { template: template.trim() } : {}),\n model: model.trim(),\n prompt: resolvedPrompt,\n sourcePath,\n ...(promptPath ? { promptPath } : {}),\n layer,\n mtimeMs,\n };\n}\n\nfunction listJsonFiles(dir: string): string[] {\n return fs\n .readdirSync(dir, { withFileTypes: true })\n .filter((entry) => entry.isFile() && entry.name.endsWith(\".json\") && !entry.name.startsWith(\".\"))\n .map((entry) => path.join(dir, entry.name))\n .sort();\n}\n\nfunction loadDir(dir: string, layer: JobLayer): LocalJobSpec[] {\n return listJsonFiles(dir).map((file) => parseJobFile(fs.readFileSync(file, \"utf8\"), file, layer));\n}\n\n/**\n * User jobs first, then project jobs overwrite by name. The returned list is sorted by name.\n */\nexport function loadLocalJobs(opts: JobsDirOptions = {}): LocalJobSpec[] {\n const dirs = resolveJobsDirs(opts);\n const byName = new Map<string, LocalJobSpec>();\n if (dirs.userDir) {\n for (const job of loadDir(dirs.userDir, \"user\")) byName.set(job.name, job);\n }\n if (dirs.projectDir) {\n for (const job of loadDir(dirs.projectDir, \"project\")) byName.set(job.name, job);\n }\n return [...byName.values()].sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport function loadLocalJob(name: string, opts: JobsDirOptions = {}): LocalJobSpec {\n const jobs = loadLocalJobs(opts);\n const match = jobs.find((job) => job.name === name);\n if (!match) {\n throw new PiPodError(`no local job file named \"${name}\"`, {\n hint: jobs.length ? `have: ${jobs.map((job) => job.name).join(\", \")}` : \"no files in ~/.pi-pod/jobs/ or .pi-pod/jobs/\",\n });\n }\n return match;\n}\n\nexport function promptFileName(name: string): string {\n return `${name}.prompt.md`;\n}\n\nexport function jobFileName(name: string): string {\n return `${name}.json`;\n}\n\nexport interface WrittenJobFiles {\n jsonPath: string;\n promptPath: string;\n}\n\nexport function serializeJobFile(spec: {\n name: string;\n description?: string | null;\n trigger: JobTrigger;\n template?: string | null;\n model: string;\n}): string {\n const body: Record<string, unknown> = {};\n if (spec.description) body.description = spec.description;\n body.trigger = spec.trigger;\n if (spec.template) body.template = spec.template;\n body.model = spec.model;\n body.promptFile = promptFileName(spec.name);\n return `${JSON.stringify(body, null, 2)}\\n`;\n}\n\nexport function writeLocalJob(\n spec: {\n name: string;\n description?: string | null;\n trigger: JobTrigger;\n template?: string | null;\n model: string;\n prompt: string;\n },\n opts: JobsDirOptions & { project?: boolean; overwrite?: boolean } = {},\n): WrittenJobFiles {\n // The name comes from the server, where any member can name a shared job: it must stay\n // a plain file name inside the jobs directory.\n if (!/^[A-Za-z0-9][A-Za-z0-9._ -]*$/.test(spec.name) || spec.name.includes(\"..\")) {\n throw new PiPodError(`job name \"${spec.name}\" cannot be a local file name`, {\n hint: \"rename the job on the server (letters, digits, '.', '_', '-', spaces), then pull again\",\n });\n }\n const cwd = opts.cwd ?? process.cwd();\n const dir = opts.project ? projectJobsDirForWrite(cwd, opts.home) : (userJobsDir(opts.home) ?? path.join(path.resolve(cwd), CONFIG_DIR, JOBS_SUBDIR));\n fs.mkdirSync(dir, { recursive: true });\n const jsonPath = path.join(dir, jobFileName(spec.name));\n const promptPath = path.join(dir, promptFileName(spec.name));\n const nextJson = serializeJobFile(spec);\n for (const [file, next] of [[jsonPath, nextJson], [promptPath, spec.prompt]] as const) {\n const existing = fs.lstatSync(file, { throwIfNoEntry: false });\n if (!existing) continue;\n if (!existing.isFile()) {\n throw new PiPodError(`refusing to write ${file} — it is not a regular file`, {\n hint: \"remove it (a symlink is never followed), then pull again\",\n });\n }\n if (!opts.overwrite && fs.readFileSync(file, \"utf8\") !== next) {\n throw new PiPodError(`refusing to overwrite ${file} — it differs from the server copy`, {\n hint: \"pass -y to overwrite, or `pipod jobs diff` to see the drift\",\n });\n }\n }\n fs.writeFileSync(jsonPath, nextJson);\n fs.writeFileSync(promptPath, spec.prompt);\n return { jsonPath, promptPath };\n}\n\nexport function triggersEqual(a: JobTrigger, b: JobTrigger): boolean {\n if (a.type !== b.type) return false;\n if (a.type === \"cron\" && b.type === \"cron\") return a.cron === b.cron;\n if (a.type === \"at\" && b.type === \"at\") return a.times.length === b.times.length && a.times.every((time, i) => time === b.times[i]);\n return false;\n }\n","/**\n * Authenticated Stripe checkout and portal entrypoints.\n *\n * The server owns entitlement. Return pages (`/billing/success` etc.) are\n * landing copy only — a query string never grants a plan. `trial: true` is\n * the request for a trial; a closed public-trial gate refuses it. Paid\n * subscribe is explicit `trial: false`.\n */\nimport { spawn } from \"node:child_process\";\nimport { EXIT, PiPodError } from \"../errors.js\";\nimport { info } from \"../log.js\";\nimport { confirm } from \"../prompt.js\";\nimport type { AccountClient } from \"./api.js\";\nimport {\n formatUsdCents,\n type BillingAccountPlan,\n type BillingPlanKey,\n type PlanChangeQuoteView,\n} from \"./billing.js\";\n\nconst HTTPS = /^https:\\/\\//i;\nconst PLANS = new Set([\"standard\", \"pro\"]);\n\nfunction openBrowser(url: string): void {\n const command = process.platform === \"darwin\" ? \"open\" : process.platform === \"linux\" ? \"xdg-open\" : null;\n if (!command) return;\n try {\n const child = spawn(command, [url], { detached: true, stdio: \"ignore\" });\n child.on(\"error\", () => {});\n child.unref();\n } catch {\n // URL already printed.\n }\n}\n\nfunction requireHttpsUrl(value: unknown, what: string): string {\n if (typeof value !== \"string\" || !HTTPS.test(value) || value.length > 2048) {\n throw new PiPodError(`the server did not return a usable ${what} URL`);\n }\n return value;\n}\n\nexport async function runBillingCommand(client: AccountClient, args: string[], deps: BillingCommandDeps = {}): Promise<number> {\n const [verb, ...rest] = args;\n if (!verb || verb === \"help\" || verb === \"--help\") {\n info(`Usage: pipod billing checkout [--plan standard|pro] [--trial]\n pipod billing portal\n pipod billing change --plan standard|pro [--yes]\n pipod billing change preview --plan standard|pro\n pipod billing change confirm --quote <quoteId> [--yes]\n\ncheckout Open Stripe Checkout (authenticated). Sends trial:false (paid)\n unless --trial. Closed public trial refuses --trial with 402.\nportal Open the Stripe billing portal for the existing subscription.\nchange Preview a Standard<->Pro plan change and, after an explicit yes,\n confirm it. Upgrades bill proration immediately; downgrades take\n effect at the end of the current period. Offered only when the\n server reports the account can change plans. When a confirm is lost\n (canChangePlan false with an applying open quote), resume the same\n quote id instead of previewing again.\npreview Show the priced quote without confirming anything.\nconfirm Confirm a previously previewed quote by id. After a 5xx, a network\n loss, or a 409 plan_change_effect_unknown retry the SAME quote id\n even if its expiresAt passed; after a 402 card_declined/\n authentication_required the quote failed, so fix the card in the\n portal and preview again (never replay the key).\n\nReturning from Checkout or the portal does not change your plan by itself —\nrefresh against the server. Do not infer entitlement from URL query strings.\nA plan change never takes effect without your explicit yes, and a stale or\nexpired quote is never auto-confirmed: preview again instead.\n\nInstall: GitHub release tarball or a git clone + npm run build. Public npm 404\nis not a supported distribution path.`);\n return EXIT.OK;\n }\n try {\n if (verb === \"checkout\") return await runCheckout(client, rest);\n if (verb === \"portal\") return await runPortal(client);\n if (verb === \"change\") return await runPlanChange(client, rest, deps);\n } catch (error) {\n // A server without billing routes is a self-hosted one: there is nothing to pay for.\n if (error instanceof PiPodError && error.status === 404 && /\\bRoute \\S+ not found\\b/.test(error.message)) {\n throw new PiPodError(`${client.serverUrl} has no billing`, {\n hint: \"plans and payment belong to the hosted service at pipod.dev\",\n });\n }\n throw error;\n }\n throw new PiPodError(`unknown billing command ${verb}`, {\n hint: \"pipod billing checkout | pipod billing portal | pipod billing change --plan pro\",\n exitCode: EXIT.USAGE,\n });\n}\n\nasync function runCheckout(client: AccountClient, args: string[]): Promise<number> {\n let plan: \"standard\" | \"pro\" = \"standard\";\n let trial = false;\n for (let i = 0; i < args.length; i++) {\n const a = args[i]!;\n if (a === \"--plan\") {\n const v = args[++i];\n if (!v || !PLANS.has(v)) throw new PiPodError(\"usage: --plan standard|pro\", { exitCode: EXIT.USAGE });\n plan = v as \"standard\" | \"pro\";\n } else if (a === \"--trial\") trial = true;\n else if (a === \"--paid\") trial = false;\n else throw new PiPodError(`unknown checkout flag ${a}`, { exitCode: EXIT.USAGE });\n }\n const session = await client.createCheckoutSession({ plan, trial });\n const url = requireHttpsUrl(session.url, \"checkout\");\n info(`opening Stripe Checkout (${session.trial ? \"trial requested\" : \"paid\"})`);\n info(\"return pages do not grant a plan; the server is the source of truth after webhook/refresh\");\n openBrowser(url);\n return EXIT.OK;\n}\n\nasync function runPortal(client: AccountClient): Promise<number> {\n const session = await client.createPortalSession();\n const url = requireHttpsUrl(session.url, \"portal\");\n info(\"opening the billing portal\");\n info(\"return pages do not grant a plan; the server is the source of truth\");\n openBrowser(url);\n return EXIT.OK;\n}\n\n// --- plan change (M5; quotes from POST /v1/billing/plan-change/*) -----------------\n\n/** Test seam: the default asks the terminal; tests inject answers. */\nexport interface BillingCommandDeps {\n ask?: (question: string) => Promise<boolean>;\n}\n\ntype PlanChangeForm =\n | { kind: \"flow\"; plan: BillingPlanKey; yes: boolean }\n | { kind: \"preview\"; plan: BillingPlanKey }\n | { kind: \"confirm\"; quoteId: string; yes: boolean };\n\nconst UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nconst CHANGE_USAGE = \"pipod billing change --plan standard|pro [--yes]\";\nconst CHANGE_PREVIEW_USAGE = \"pipod billing change preview --plan standard|pro\";\nconst CHANGE_CONFIRM_USAGE = \"pipod billing change confirm --quote <quoteId> [--yes]\";\n\nfunction usageError(message: string, usage: string): PiPodError {\n return new PiPodError(message, { hint: `usage: ${usage}`, exitCode: EXIT.USAGE });\n}\n\nfunction parseChangeArgs(args: string[]): PlanChangeForm {\n let form: \"flow\" | \"preview\" | \"confirm\" = \"flow\";\n let plan: BillingPlanKey | undefined;\n let quoteId: string | undefined;\n let yes = false;\n for (let i = 0; i < args.length; i++) {\n const a = args[i]!;\n if (a === \"preview\" && form === \"flow\" && plan === undefined && quoteId === undefined) {\n form = \"preview\";\n } else if (a === \"confirm\" && form === \"flow\" && plan === undefined && quoteId === undefined) {\n form = \"confirm\";\n } else if (a === \"--plan\") {\n const v = args[++i];\n if (!v || (v !== \"standard\" && v !== \"pro\")) throw usageError(\"usage: --plan standard|pro\", CHANGE_USAGE);\n plan = v;\n } else if (a === \"--quote\") {\n const v = args[++i];\n if (!v || !UUID.test(v)) throw usageError(\"usage: --quote <quoteId> (the id from a preview)\", CHANGE_CONFIRM_USAGE);\n quoteId = v;\n } else if (a === \"--yes\") {\n yes = true;\n } else {\n throw usageError(\n `unknown change flag ${a}`,\n form === \"confirm\" ? CHANGE_CONFIRM_USAGE : form === \"preview\" ? CHANGE_PREVIEW_USAGE : CHANGE_USAGE,\n );\n }\n }\n if (form === \"preview\") {\n if (!plan || quoteId !== undefined || yes) throw usageError(\"preview takes only --plan\", CHANGE_PREVIEW_USAGE);\n return { kind: \"preview\", plan };\n }\n if (form === \"confirm\") {\n if (!quoteId || plan !== undefined) throw usageError(\"confirm takes only --quote\", CHANGE_CONFIRM_USAGE);\n return { kind: \"confirm\", quoteId, yes };\n }\n if (!plan || quoteId !== undefined) throw usageError(\"change takes --plan\", CHANGE_USAGE);\n return { kind: \"flow\", plan, yes };\n}\n\nfunction money(cents: number, currency: string): string {\n if (currency === \"usd\") return formatUsdCents(cents);\n return `${(cents / 100).toFixed(2)} ${currency.toUpperCase()}`;\n}\n\nfunction day(iso: string): string {\n return iso.slice(0, 10);\n}\n\nfunction renewalPrice(account: BillingAccountPlan, target: BillingPlanKey): string | null {\n const entry = account.planPrices.find((p) => p.key === target);\n if (!entry || entry.priceUsdCents === undefined) return null;\n return formatUsdCents(entry.priceUsdCents);\n}\n\n/**\n * Due-now versus period-end/recurring. On an immediate upgrade the quote's\n * `recurringAmountCents` is the target licensed base (e.g. $50) and\n * `nextPeriodAmountCents` equals it — never 0, never \"next month free\". A\n * zero next-period on an immediate quote is stale bookkeeping, never a free\n * month. The renewal is named from the quote's recurring amount; the\n * account's plan prices are only a fallback when they agree.\n */\nfunction printQuote(quote: PlanChangeQuoteView, account: BillingAccountPlan): void {\n const direction = `${quote.currentPlan} → ${quote.targetPlan}`;\n if (quote.timing === \"immediate\") {\n const renewal = renewalPrice(account, quote.targetPlan);\n const recurring = money(quote.recurringAmountCents, quote.currency);\n const next = money(quote.nextPeriodAmountCents, quote.currency);\n const renewalNote =\n quote.currentPeriodEnd !== null\n ? `Renews at the ${quote.targetPlan} plan price (${recurring}) starting ${day(quote.currentPeriodEnd)}. Next period ${next} ${quote.currency.toUpperCase()}.`\n : `Renews at the ${quote.targetPlan} plan price (${recurring}). Next period ${next} ${quote.currency.toUpperCase()}.`;\n info(`plan change ${direction} (immediate): due now ${money(quote.amountDueNowCents, quote.currency)} ${quote.currency.toUpperCase()}`);\n info(renewalNote);\n if (renewal !== null && renewal !== recurring) {\n info(`(account lists the ${quote.targetPlan} plan price as ${renewal}.)`);\n }\n info(\"Recurring and next-period amounts come from the quote — never a free month.\");\n } else {\n const effective = quote.effectiveAt ?? quote.currentPeriodEnd;\n info(`plan change ${direction} (at period end): due now ${money(quote.amountDueNowCents, quote.currency)} ${quote.currency.toUpperCase()}`);\n info(\n effective !== null\n ? `Takes effect ${day(effective)}; next period ${money(quote.nextPeriodAmountCents, quote.currency)} ${quote.currency.toUpperCase()}.`\n : `Next period ${money(quote.nextPeriodAmountCents, quote.currency)} ${quote.currency.toUpperCase()}.`,\n );\n }\n info(`Quote ${quote.quoteId} expires ${day(quote.expiresAt)}.`);\n}\n\nfunction printAccountContext(account: BillingAccountPlan): void {\n if (account.pendingPlanKey) info(`A change to ${account.pendingPlanKey} is already pending.`);\n if (account.pendingScheduleUnreadable) info(\"The pending schedule could not be read; the portal has the details.\");\n if (account.cancelAtPeriodEnd) info(\"This subscription is set to cancel at the end of the current period.\");\n}\n\n/** A lost confirm is applying server-side: resume it instead of previewing again. */\nfunction applyingResumeError(account: BillingAccountPlan): PiPodError {\n const quoteId = account.openPlanChange?.quoteId;\n return new PiPodError(\n quoteId\n ? `a plan change is already being applied (quote ${quoteId}); resume it instead of starting a new preview`\n : \"a plan change is already being applied; resume it instead of starting a new preview\",\n {\n hint: quoteId\n ? `retry the same quote even if it expired: \\`pipod billing change confirm --quote ${quoteId}\\``\n : \"re-read the account and confirm the open quote id\",\n code: \"open_plan_change_applying\",\n },\n );\n}\n\nfunction cannotChangeError(account: BillingAccountPlan): PiPodError {\n const reasons: string[] = [];\n if (account.status === \"trialing\") reasons.push(\"trial subscriptions cannot change plans\");\n if (account.pendingPlanKey) reasons.push(`a change to ${account.pendingPlanKey} is already pending`);\n if (account.cancelAtPeriodEnd) reasons.push(\"the subscription is set to cancel at period end\");\n return new PiPodError(\n reasons.length > 0\n ? `this subscription cannot change plans: ${reasons.join(\"; \")}`\n : \"this subscription cannot change plans (an active paid subscription is required)\",\n { hint: \"manage the subscription in the billing portal: `pipod billing portal`\" },\n );\n}\n\n/**\n * True while the account holds an applying open quote: the only state that\n * resumes. Reads the explicit `canResumePlanChange` flag when the server sends\n * it, falling back to `openPlanChange.state === \"applying\"` (CONTRACT-NOTES.md).\n */\nfunction canResumeAccount(account: BillingAccountPlan): boolean {\n if (account.canResumePlanChange === true) return true;\n return account.openPlanChange?.state === \"applying\";\n}\n\n/**\n * The gate for minting a fresh preview: static backends have no `/v1/billing`\n * (null account) and the surface stays omitted; otherwise only `canChangePlan`\n * proceeds. When `canChangePlan` is false because the open quote is `applying`\n * (or `canResumePlanChange` is true), the caller must resume the SAME quote id\n * — never preview again.\n */\nasync function requireChangeableAccount(client: AccountClient): Promise<BillingAccountPlan> {\n const account = await client.billingAccountPlan();\n if (!account) {\n info(\"plan changes are not available on this server (self-hosted installs have no plans to change)\");\n throw new PlanChangeOmitted();\n }\n if (!account.canChangePlan) {\n if (canResumeAccount(account)) throw applyingResumeError(account);\n throw cannotChangeError(account);\n }\n return account;\n}\n\n/**\n * The gate for `confirm --quote`: a lost confirm resumes the same quote even\n * when `canChangePlan` is now false and even when `expiresAt` passed. Only a\n * non-applying refusal still blocks.\n */\nasync function requireConfirmableAccount(client: AccountClient): Promise<BillingAccountPlan> {\n const account = await client.billingAccountPlan();\n if (!account) {\n info(\"plan changes are not available on this server (self-hosted installs have no plans to change)\");\n throw new PlanChangeOmitted();\n }\n if (!account.canChangePlan && !canResumeAccount(account)) {\n throw cannotChangeError(account);\n }\n return account;\n}\n\n/** Control flow: the surface is omitted, which is a clean exit, not a failure. */\nclass PlanChangeOmitted extends Error {}\n\n/**\n * Friendly copy for the quote/confirm refusals; the server `code` stays on the\n * error. 402 `card_declined`/`authentication_required` means the quote FAILED:\n * new preview after the portal, never a replay of the failed key. 5xx and\n * timeouts are unknown: the quote stays `applying`, so retry the SAME quote\n * id even if `expiresAt` passed. 409 `plan_change_effect_unknown` is UNKNOWN\n * possible paid effect (not `quote_stale`): keep the SAME quote id, never\n * clear it, mint a new preview, or require new consent. No payment URL is\n * ever printed or hinted here.\n */\nfunction planChangeRefusal(error: unknown, quoteId: string | null, currentPlan: string | null): PiPodError {\n if (!(error instanceof PiPodError)) {\n const message = error instanceof Error ? error.message : String(error);\n if (/timeout|timed out|abort|fetch failed|network|ECONN|EAI_AGAIN|socket hang up|not get a clear/i.test(message)) {\n return new PiPodError(\n \"the plan change result is unconfirmed and may already have applied; retry the same quote to learn the outcome\",\n {\n hint: quoteId\n ? `the quote stays applying — retry the same quote even if it expired: \\`pipod billing change confirm --quote ${quoteId}\\``\n : \"re-read the account and confirm the open quote id\",\n code: \"confirm_unknown\",\n transient: true,\n },\n );\n }\n throw error instanceof Error ? error : new Error(String(error));\n }\n switch (error.code) {\n case \"plan_change_in_flight\": {\n // While applying, preview answers 409 with `{ quoteId, state }`: resume\n // that id instead of minting a fresh preview. Confirm collisions carry\n // the same id the caller just sent — retry it even if it expired.\n const resumeId = resumeQuoteId(error.detail, quoteId);\n return new PiPodError(\n resumeId\n ? `a plan change is already being applied (quote ${resumeId}); resume it instead of starting a new preview`\n : \"a plan change is already being applied; resume it instead of starting a new preview\",\n {\n hint: resumeId\n ? `retry the same quote even if it expired: \\`pipod billing change confirm --quote ${resumeId}\\``\n : \"re-read the account and confirm the open quote id\",\n code: error.code,\n status: error.status,\n },\n );\n }\n case \"plan_change_effect_unknown\": {\n // UNKNOWN possible paid effect — not `quote_stale`. Keep the SAME quote\n // id (detail.quoteId or in-hand) and retry even if it expired or\n // `canChangePlan` is now false. Never clear, preview again, or require\n // new consent. No payment URL is ever printed here.\n const retryId = resumeQuoteId(error.detail, quoteId);\n return new PiPodError(\n \"the plan change effect is unknown and may already have applied; the result is unconfirmed — retry the same quote to learn the outcome\",\n {\n hint: retryId\n ? `the effect is unknown — retry the same quote even if it expired: \\`pipod billing change confirm --quote ${retryId}\\``\n : \"re-read the account and confirm the open quote id\",\n code: error.code,\n status: error.status,\n transient: true,\n },\n );\n }\n case \"quote_stale\":\n case \"quote_expired\":\n return new PiPodError(\n \"the quote changed or expired since the preview; nothing was confirmed and nothing was charged\",\n { hint: \"preview again and confirm the new quote\", code: error.code, status: error.status },\n );\n case \"cap_below_new_base\":\n return new PiPodError(\n \"the spend cap is below the new plan's base price, so the change was refused and the cap was left alone\",\n { hint: \"raise the spend cap first, then preview again (the client never raises it for you)\", code: error.code, status: error.status },\n );\n case \"trial_plan_change_unavailable\":\n return new PiPodError(\"trial subscriptions cannot change plans\", {\n hint: \"manage the subscription in the billing portal: `pipod billing portal`\",\n code: error.code,\n status: error.status,\n });\n case \"card_declined\":\n case \"authentication_required\":\n return new PiPodError(\n currentPlan\n ? `payment ${error.code === \"card_declined\" ? \"was declined\" : \"needs authentication\"}; the quote failed with no pending invoice and the plan did not change (still ${currentPlan}) — Pro was not granted`\n : `payment ${error.code === \"card_declined\" ? \"was declined\" : \"needs authentication\"}; the quote failed with no pending invoice and the plan did not change — Pro was not granted`,\n {\n // Failed quotes are never replayed: fix the card in the portal, then\n // mint a fresh preview. No payment URL is ever printed here.\n hint: \"fix the card in the portal (`pipod billing portal`), then preview again — do not retry the failed quote\",\n code: error.code,\n status: error.status,\n },\n );\n case \"plan_change_not_applied\":\n return new PiPodError(\n currentPlan\n ? `the plan change was not applied; the plan did not change (still ${currentPlan}) and Pro was not granted`\n : \"the plan change was not applied; the plan did not change and Pro was not granted\",\n {\n hint: \"preview again and confirm the new quote\",\n code: error.code,\n status: error.status,\n },\n );\n default:\n if (error.status === 402) {\n return new PiPodError(\n currentPlan\n ? `payment failed; the quote failed with no pending invoice and the plan did not change (still ${currentPlan}) — Pro was not granted`\n : \"payment failed; the quote failed with no pending invoice and the plan did not change — Pro was not granted\",\n {\n // Any 402 is a failed quote: portal, then a new preview. Never\n // replay the failed key. No payment URL is ever printed here.\n hint: \"fix the card in the portal (`pipod billing portal`), then preview again — do not retry the failed quote\",\n code: error.code,\n status: error.status,\n },\n );\n }\n if (error.status === 404) {\n return new PiPodError(\"plan changes are not available on this server\", {\n hint: \"self-hosted installs have no plans to change\",\n status: error.status,\n });\n }\n if (error.transient || (error.status !== undefined && error.status >= 500)) {\n return new PiPodError(\n \"the plan change result is unconfirmed — the quote stays applying and may already have applied; retry the same quote to learn the outcome\",\n {\n hint: quoteId\n ? `retry the same quote even if it expired: \\`pipod billing change confirm --quote ${quoteId}\\``\n : \"re-read the account and confirm the open quote id\",\n code: error.code,\n status: error.status,\n transient: true,\n },\n );\n }\n return error;\n }\n}\n\n/** Resume id from a `plan_change_in_flight` detail, falling back to the in-hand id. */\nfunction resumeQuoteId(detail: unknown, fallback: string | null): string | null {\n if (detail !== null && typeof detail === \"object\" && !Array.isArray(detail)) {\n const raw = (detail as Record<string, unknown>)[\"quoteId\"];\n if (typeof raw === \"string\") {\n const trimmed = raw.trim();\n if (trimmed.length > 0 && trimmed.length <= 64 && !/[\\u0000-\\u001f\\u007f\\s]/.test(trimmed)) {\n return trimmed;\n }\n }\n }\n return fallback;\n}\n\n/**\n * A confirm 200 is `{ applied, ...quote, account }`: success is `applied === true`\n * AND the returned account showing the target — `planKey` for an immediate\n * change, `pendingPlanKey` for a period-end downgrade. Either signal alone\n * grants nothing: `applied:true` leaving the old plan, or the target plan\n * without `applied:true`, is `plan_change_not_applied` (retry the same id:\n * it stays applying). A missing `applied` is never success.\n */\nfunction requireAppliedGrant(\n applied: boolean,\n account: BillingAccountPlan | null,\n target: BillingPlanKey,\n currentPlan: string | null,\n): void {\n if (applied === true && (account?.planKey === target || account?.pendingPlanKey === target)) return;\n throw new PiPodError(\n currentPlan\n ? `the plan change was not applied; the plan did not change (still ${currentPlan}) and Pro was not granted`\n : \"the plan change was not applied; the plan did not change and Pro was not granted\",\n { hint: \"preview again and confirm the new quote\", code: \"plan_change_not_applied\" },\n );\n}\n\nasync function askYes(deps: BillingCommandDeps, question: string, assumeYes: boolean): Promise<boolean> {\n if (assumeYes) return true;\n if (deps.ask) return deps.ask(question);\n return confirm(question, { nonInteractiveDefault: false });\n}\n\n/** The outcome is read off a freshly fetched account — never off the quote echo. */\nasync function printChangeResult(client: AccountClient, target: BillingPlanKey): Promise<void> {\n let account: BillingAccountPlan | null = null;\n try {\n account = await client.billingAccountPlan();\n } catch {\n account = null;\n }\n if (!account) {\n info(`plan change confirmed for ${target}; the account could not be re-read — check the portal`);\n return;\n }\n printAccountContext(account);\n if (account.pendingPlanKey) {\n info(`plan change recorded: ${account.pendingPlanKey} takes effect at the end of the current period`);\n } else if (account.planKey) {\n info(`current plan: ${account.planKey}`);\n } else {\n info(`plan change confirmed for ${target}`);\n }\n}\n\nasync function runPlanChange(client: AccountClient, args: string[], deps: BillingCommandDeps): Promise<number> {\n const form = parseChangeArgs(args);\n if (form.kind === \"confirm\") return runPlanChangeConfirm(client, form.quoteId, form.yes, deps);\n\n let account: BillingAccountPlan;\n try {\n account = await requireChangeableAccount(client);\n } catch (error) {\n if (error instanceof PlanChangeOmitted) return EXIT.OK;\n throw error;\n }\n let quote: PlanChangeQuoteView;\n try {\n quote = await client.previewPlanChange(form.plan);\n } catch (error) {\n throw planChangeRefusal(error, null, null);\n }\n printAccountContext(account);\n printQuote(quote, account);\n if (form.kind === \"preview\") {\n info(`to confirm this quote: \\`pipod billing change confirm --quote ${quote.quoteId}\\``);\n return EXIT.OK;\n }\n const question =\n quote.timing === \"immediate\"\n ? `Change ${quote.currentPlan} → ${quote.targetPlan} now, ${money(quote.amountDueNowCents, quote.currency)} ${quote.currency.toUpperCase()} due now?`\n : `Change ${quote.currentPlan} → ${quote.targetPlan} at period end?`;\n if (!(await askYes(deps, question, form.yes))) {\n info(\"not confirmed — nothing was changed\");\n return EXIT.OK;\n }\n // The confirm body is the quote id only — never a caller-selected plan — and a\n // stale/expired quote is never auto-confirmed: a 409 means preview again.\n // The 200 body is `{ applied, ...quote, account }`: success is `applied === true`\n // AND the returned account showing the target (planKey, or pendingPlanKey for a\n // period-end downgrade). A missing `applied` never grants Pro.\n try {\n const result = await client.confirmPlanChange(quote.quoteId);\n requireAppliedGrant(result.applied, result.account, quote.targetPlan, quote.currentPlan);\n } catch (error) {\n throw planChangeRefusal(error, quote.quoteId, quote.currentPlan);\n }\n await printChangeResult(client, quote.targetPlan);\n return EXIT.OK;\n}\n\nasync function runPlanChangeConfirm(client: AccountClient, quoteId: string, yes: boolean, deps: BillingCommandDeps): Promise<number> {\n // Restart recovery reads the account first but never mints a fresh quote:\n // an applying open quote resumes here even when `canChangePlan` is false\n // and even when `expiresAt` passed.\n let resumeAccount: BillingAccountPlan | null = null;\n try {\n resumeAccount = await requireConfirmableAccount(client);\n } catch (error) {\n if (error instanceof PlanChangeOmitted) return EXIT.OK;\n throw error;\n }\n const resumePlan = resumeAccount.planKey ?? null;\n // Blind by design: no endpoint replays a quote's amounts, so the yes below\n // re-affirms the preview just approved. Overcharge is still impossible by\n // accident — the server re-previews on confirm and refuses drift as 409.\n if (!(await askYes(deps, `Confirm the previewed plan change for quote ${quoteId}? Answer yes only for the preview you just approved.`, yes))) {\n info(\"not confirmed — nothing was changed\");\n return EXIT.OK;\n }\n let target: BillingPlanKey;\n try {\n const result = await client.confirmPlanChange(quoteId);\n requireAppliedGrant(result.applied, result.account, result.quote.targetPlan, result.quote.currentPlan ?? resumePlan);\n target = result.quote.targetPlan;\n } catch (error) {\n throw planChangeRefusal(error, quoteId, resumePlan);\n }\n await printChangeResult(client, target);\n return EXIT.OK;\n}\n","/**\n * src/account/login.ts — `pipod login|logout|whoami` plus Account/Admin Console links.\n *\n * The browser flow is loopback PKCE against Zitadel directly. The CLI discovers\n * OIDC endpoints, opens the authorization endpoint with the Zitadel resource-owner\n * and project-role scopes, and exchanges the code itself. The server never sees a code, verifier, or refresh token.\n */\nimport * as http from \"node:http\";\nimport { spawn } from \"node:child_process\";\nimport { PiPodError } from \"../errors.js\";\nimport { hint, info } from \"../log.js\";\nimport { AccountClient } from \"./api.js\";\nimport {\n accountConsoleUrl,\n adminConsoleUrl,\n authorizeUrl,\n createNonce,\n createPkce,\n createState,\n discover,\n endSessionUrl,\n exchangeCode,\n organizationFromAccessToken,\n revokeToken,\n timingSafeEqualString,\n DEFAULT_CLIENT_ID,\n DEFAULT_ISSUER,\n OIDC_NETWORK_TIMEOUT_MS,\n} from \"./oidc.js\";\nimport {\n accountAuthPath,\n clearAccountAuth,\n readAccountAuth,\n readPodTokenAuth,\n writeAccountAuth,\n type AccountAuth,\n} from \"./store.js\";\n\n/** Fixed, small: each `http://127.0.0.1:<port>/callback` must be allowlisted on `pipod-cli`. */\nexport const LOOPBACK_PORTS = [43117, 43118, 43119, 43120, 43121, 43122, 43123, 43124, 43125, 43126];\n/** Production control plane — used when neither --server, a prior session, nor PI_POD_ACCOUNT_URL is set. */\nexport const DEFAULT_ACCOUNT_SERVER_URL = \"https://api.pipod.dev\";\nconst LOGIN_TIMEOUT_MS = 5 * 60 * 1000;\n\nexport interface LoginFlags {\n server?: string | undefined;\n org?: string | undefined;\n token?: string | undefined;\n issuer?: string | undefined;\n home?: string | undefined;\n}\n\nexport async function runLogin(flags: LoginFlags): Promise<number> {\n const stored = safeReadAuth(flags.home);\n const serverUrl = normalizeServerUrl(\n flags.server ?? stored?.serverUrl ?? process.env[\"PI_POD_ACCOUNT_URL\"] ?? DEFAULT_ACCOUNT_SERVER_URL,\n );\n // A session with another server says nothing about this one's identity provider.\n const previous = stored?.serverUrl === serverUrl ? stored : null;\n const published = await fetchSignInConfig(serverUrl);\n const issuerInput =\n flags.issuer ??\n process.env[\"PI_POD_ISSUER\"] ??\n published?.issuer ??\n previous?.issuer ??\n defaultIssuerForServer(serverUrl);\n if (!issuerInput) {\n throw new PiPodError(`no identity provider is known for ${serverUrl}`, {\n hint: \"pass --issuer <url> (the ZITADEL_ISSUER of that server); this server does not publish one\",\n });\n }\n const issuer = normalizeIssuerInput(issuerInput);\n const clientId =\n process.env[\"PI_POD_OIDC_CLIENT_ID\"] ?? published?.cliClientId ?? previous?.clientId ?? DEFAULT_CLIENT_ID;\n\n let accessToken: string;\n let refreshToken: string | undefined;\n let idToken: string | undefined;\n if (flags.token) {\n accessToken = flags.token;\n } else {\n const pair = await browserLogin({ issuer, clientId, orgAlias: flags.org });\n accessToken = pair.accessToken;\n refreshToken = pair.refreshToken;\n idToken = pair.idToken;\n }\n\n const tokenOrg = organizationFromAccessToken(accessToken);\n const probe = new AccountClient(\n {\n serverUrl,\n accessToken,\n ...(refreshToken ? { refreshToken } : {}),\n ...(idToken ? { idToken } : {}),\n issuer,\n clientId,\n user: { id: \"\", email: \"\" },\n orgId: tokenOrg?.id ?? \"\",\n },\n { home: flags.home },\n );\n let me: Awaited<ReturnType<AccountClient[\"me\"]>>;\n try {\n me = await probe.me();\n } catch (e) {\n // A 401 on the very token we just minted is not an expired session — the server trusts\n // someone else. Saying \"run `pipod login`\" here would send the user round the same loop.\n if (e instanceof PiPodError && e.status === 401) {\n throw new PiPodError(`${serverUrl} rejected the token issued by ${issuer}`, {\n hint: \"the server trusts a different identity provider or audience: check --issuer against the server's ZITADEL_ISSUER, and ZITADEL_API_AUDIENCE on the server\",\n cause: e,\n });\n }\n throw e;\n }\n\n // Zitadel's access tokens carry no email, so the server rarely knows it; the ID token does.\n const email = me.user.email ?? emailFromIdToken(idToken) ?? \"\";\n const orgId = me.currentOrgId || tokenOrg?.id || \"\";\n const orgName = me.organization?.name ?? tokenOrg?.name ?? orgId;\n const pending = !orgId || (me.permissions ?? []).length === 0;\n\n const auth: AccountAuth = {\n serverUrl,\n accessToken,\n ...(refreshToken ? { refreshToken } : {}),\n ...(idToken ? { idToken } : {}),\n issuer,\n clientId,\n user: { id: me.user.id, email },\n orgId,\n ...(me.organization?.alias || tokenOrg?.alias\n ? { orgAlias: me.organization?.alias ?? tokenOrg?.alias }\n : {}),\n };\n const file = writeAccountAuth(auth, flags.home);\n\n if (pending) {\n info(`signed in to ${serverUrl} as ${email || me.user.id}`);\n info(\"access is pending Zitadel organization membership or role grants\");\n info(`manage account: ${me.accountConsoleUrl ?? accountConsoleUrl(issuer)}`);\n hint(\"an administrator invites you and grants `member` (or another bundle) in the Zitadel Console\");\n } else {\n info(`signed in to ${serverUrl} as ${email || me.user.id} (org: ${orgName})`);\n }\n info(`signed-in session stored in ${file}; pod operations now use this server`);\n return 0;\n}\n\nexport async function runLogout(flags: { home?: string | undefined }): Promise<number> {\n let auth: AccountAuth | null;\n try {\n auth = readAccountAuth(flags.home);\n } catch {\n if (clearAccountAuth(flags.home)) {\n info(\"signed out — the unsupported local session was removed\");\n return 0;\n }\n info(\"not signed in\");\n return 0;\n }\n if (!auth) {\n if (readPodTokenAuth()) {\n throw new PiPodError(\"a pod-scoped server token is not a revocable login session\");\n }\n info(\"not signed in\");\n return 0;\n }\n if (auth.podToken) {\n throw new PiPodError(\"a pod-scoped server token is not a revocable login session\");\n }\n if (auth.issuer && !auth.podToken) {\n try {\n const meta = await discover(auth.issuer);\n const clientId = auth.clientId ?? DEFAULT_CLIENT_ID;\n if (auth.refreshToken) {\n await revokeToken(meta, { clientId, token: auth.refreshToken, tokenTypeHint: \"refresh_token\" });\n }\n const url = endSessionUrl(meta, { idToken: auth.idToken, clientId });\n if (url) {\n const endpoint = new URL(url);\n info(`ending the identity-provider session:\\n ${endpoint.origin}${endpoint.pathname}`);\n openBrowser(url);\n }\n } catch {\n // Local truth is the file.\n }\n }\n clearAccountAuth(flags.home);\n info(`signed out of ${auth.serverUrl}; sign back in with \\`pipod login --server ${auth.serverUrl}\\``);\n return 0;\n}\n\nexport async function runWhoami(flags: { home?: string | undefined }): Promise<number> {\n const auth = safeReadAuth(flags.home);\n if (!auth) {\n info(\"not signed in\");\n hint(\"sign in with `pipod login`\");\n return 1;\n }\n const client = new AccountClient(auth, { home: flags.home });\n const me = await client.me();\n info(`server ${auth.serverUrl}`);\n if (auth.issuer) info(`issuer ${auth.issuer}`);\n info(`user ${me.user.email ?? (auth.user.email || \"(no email)\")} (${me.user.id})`);\n const perms = me.permissions ?? [];\n info(`perms ${perms.length ? perms.join(\", \") : \"(none)\"}`);\n if (me.organization) {\n info(`org ${me.organization.name ?? me.organization.alias ?? me.organization.id} — ${me.organization.id}`);\n } else {\n info(\"org (none) — access is pending Zitadel membership\");\n }\n info(`account ${me.accountConsoleUrl ?? (auth.issuer ? accountConsoleUrl(auth.issuer) : \"\")}`);\n info(`org-admin ${me.adminConsoleUrl ?? (auth.issuer ? adminConsoleUrl(auth.issuer) : \"\")}`);\n return 0;\n}\n\nexport async function runOpenAccount(flags: { home?: string | undefined }): Promise<number> {\n return openConsole(flags, \"account\");\n}\n\nexport async function runOpenOrgAdmin(flags: { home?: string | undefined }): Promise<number> {\n return openConsole(flags, \"admin\");\n}\n\nasync function openConsole(flags: { home?: string | undefined }, which: \"account\" | \"admin\"): Promise<number> {\n const auth = safeReadAuth(flags.home);\n if (!auth?.issuer) {\n throw new PiPodError(\"not signed in to an identity provider\", { hint: \"run `pipod login`\" });\n }\n const url = which === \"account\" ? accountConsoleUrl(auth.issuer) : adminConsoleUrl(auth.issuer);\n info(which === \"account\" ? `opening Account Console:\\n ${url}` : `opening Admin Console:\\n ${url}`);\n openBrowser(url);\n return 0;\n}\n\nasync function browserLogin(args: {\n issuer: string;\n clientId: string;\n orgAlias?: string;\n}): Promise<{ accessToken: string; refreshToken?: string; idToken?: string }> {\n const meta = await discover(args.issuer);\n const pkce = createPkce();\n const state = createState();\n const nonce = createNonce();\n\n const { server, port } = await bindLoopback();\n try {\n const redirectUri = `http://127.0.0.1:${port}/callback`;\n const url = authorizeUrl(meta, {\n clientId: args.clientId,\n redirectUri,\n challenge: pkce.challenge,\n state,\n nonce,\n orgAlias: args.orgAlias,\n });\n\n info(\"opening your browser to sign in…\");\n info(`if nothing opens, visit:\\n ${url}`);\n openBrowser(url);\n\n const code = await waitForCallback(server, state);\n return exchangeCode(meta, {\n clientId: args.clientId,\n code,\n verifier: pkce.verifier,\n redirectUri,\n nonce,\n });\n } finally {\n server.close();\n }\n}\n\nfunction bindLoopback(): Promise<{ server: http.Server; port: number }> {\n return new Promise((resolve, reject) => {\n const tryPort = (index: number): void => {\n if (index >= LOOPBACK_PORTS.length) {\n reject(\n new PiPodError(\"no loopback port available for the sign-in redirect\", {\n hint: `free one of ports ${LOOPBACK_PORTS[0]}–${LOOPBACK_PORTS[LOOPBACK_PORTS.length - 1]} and retry`,\n }),\n );\n return;\n }\n const server = http.createServer();\n server.once(\"error\", () => tryPort(index + 1));\n server.listen(LOOPBACK_PORTS[index], \"127.0.0.1\", () => {\n server.removeAllListeners(\"error\");\n resolve({ server, port: LOOPBACK_PORTS[index]! });\n });\n };\n tryPort(0);\n });\n}\n\nfunction waitForCallback(server: http.Server, expectedState: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n reject(new PiPodError(\"sign-in timed out after 5 minutes\"));\n }, LOGIN_TIMEOUT_MS);\n server.on(\"request\", (req, res) => {\n const url = new URL(req.url ?? \"/\", \"http://127.0.0.1\");\n if (url.pathname !== \"/callback\") {\n res.writeHead(404).end();\n return;\n }\n const state = url.searchParams.get(\"state\") ?? \"\";\n const code = url.searchParams.get(\"code\");\n if (!timingSafeEqualString(state, expectedState) || !code) {\n res.writeHead(400, { \"content-type\": \"text/html; charset=utf-8\" }).end(\"<h3>Sign-in failed — return to the terminal.</h3>\");\n clearTimeout(timer);\n reject(new PiPodError(\"the sign-in redirect did not match this login attempt\"));\n return;\n }\n res\n .writeHead(200, { \"content-type\": \"text/html; charset=utf-8\" })\n .end(\"<h3>Signed in — you can close this tab and return to the terminal.</h3>\");\n clearTimeout(timer);\n resolve(code);\n });\n });\n}\n\nfunction openBrowser(url: string): void {\n const command =\n process.platform === \"darwin\" ? \"open\" : process.platform === \"win32\" ? \"start\" : \"xdg-open\";\n try {\n const child = spawn(command, [url], { stdio: \"ignore\", detached: true });\n child.on(\"error\", () => {});\n child.unref();\n } catch {\n // The URL is printed either way.\n }\n}\n\n/**\n * The sign-in settings a server publishes at GET /v1/auth/config; null from a server that\n * predates it. Failing to reach the server at all stops the login here, before the browser.\n */\nasync function fetchSignInConfig(serverUrl: string): Promise<{ issuer?: string; cliClientId?: string } | null> {\n let res: Response;\n try {\n res = await fetch(`${serverUrl}/v1/auth/config`, {\n redirect: \"error\",\n signal: AbortSignal.timeout(OIDC_NETWORK_TIMEOUT_MS),\n });\n } catch (e) {\n throw new PiPodError(`cannot reach the pi pod server at ${serverUrl}`, {\n hint: e instanceof Error && e.cause instanceof Error ? e.cause.message : \"check --server and that the server is running\",\n });\n }\n if (!res.ok) return null;\n const body = (await res.json().catch(() => null)) as { issuer?: unknown; cliClientId?: unknown } | null;\n const issuer = typeof body?.issuer === \"string\" ? body.issuer : undefined;\n // A token from the hosted service's identity provider is good at api.pipod.dev: no other\n // server gets to ask for one.\n if (issuer && normalizeIssuerInput(issuer) === DEFAULT_ISSUER && new URL(serverUrl).hostname !== \"api.pipod.dev\") {\n throw new PiPodError(`${serverUrl} asks you to sign in to pipod.dev, which is not its identity provider`, {\n hint: \"pass --issuer <url> if you really mean to sign in there\",\n });\n }\n return {\n ...(issuer ? { issuer } : {}),\n ...(typeof body?.cliClientId === \"string\" ? { cliClientId: body.cliClientId } : {}),\n };\n}\n\nfunction normalizeServerUrl(raw: string | undefined): string {\n if (!raw) {\n throw new PiPodError(\"no pi pod server to sign in to\", {\n hint: `pass --server <url>, set PI_POD_ACCOUNT_URL, or use the default ${DEFAULT_ACCOUNT_SERVER_URL}`,\n });\n }\n let url: URL;\n try {\n url = new URL(raw);\n } catch {\n throw new PiPodError(`--server is not a URL: ${raw}`);\n }\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n throw new PiPodError(`--server must be http(s), got ${url.protocol}`);\n }\n // Every request carries a bearer token; only loopback may carry it in cleartext.\n if (url.protocol === \"http:\" && !isLoopbackHost(url.hostname)) {\n throw new PiPodError(\"--server must use HTTPS except for loopback development\", {\n hint: \"put the server behind TLS, or reach it through an SSH tunnel to 127.0.0.1\",\n });\n }\n return url.origin;\n}\n\nfunction normalizeIssuerInput(raw: string): string {\n try {\n const url = new URL(raw);\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n throw new PiPodError(`--issuer must be http(s), got ${url.protocol}`);\n }\n if (url.protocol === \"http:\" && !isLoopbackHost(url.hostname)) {\n throw new PiPodError(\"--issuer must use HTTPS except for loopback development\");\n }\n if (url.username || url.password || url.hash || url.search) {\n throw new PiPodError(\"--issuer must not contain credentials, a query, or a fragment\");\n }\n return url.toString().replace(/\\/+$/, \"\");\n } catch (e) {\n if (e instanceof PiPodError) throw e;\n throw new PiPodError(`--issuer is not a URL: ${raw}`);\n }\n}\n\nfunction isLoopbackHost(hostname: string): boolean {\n return (\n hostname === \"127.0.0.1\" || hostname === \"localhost\" || hostname === \"::1\" || hostname === \"[::1]\"\n );\n}\n\n/**\n * Only two deployments have a knowable identity provider: the hosted control plane and a\n * loopback dev stack. Guessing for anyone else opens a stranger's IdP and mints a token the\n * self-hosted server will reject — null instead, so the caller asks for `--issuer`.\n */\nfunction defaultIssuerForServer(serverUrl: string): string | null {\n const url = new URL(serverUrl);\n if (url.hostname === \"api.pipod.dev\") return DEFAULT_ISSUER;\n if (isLoopbackHost(url.hostname)) return \"http://127.0.0.1:8081\";\n return null;\n}\n\n/** The `email` claim of an ID token this login already verified, if it has one. */\nfunction emailFromIdToken(idToken: string | undefined): string | undefined {\n if (!idToken) return undefined;\n try {\n const claims = JSON.parse(Buffer.from(idToken.split(\".\")[1] ?? \"\", \"base64url\").toString(\"utf8\")) as { email?: unknown };\n return typeof claims.email === \"string\" && claims.email ? claims.email : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction safeReadAuth(home?: string | undefined): AccountAuth | null {\n try {\n return readAccountAuth(home);\n } catch {\n return null;\n }\n}\n\nexport { accountAuthPath };\n","/** Download one pod workdir-relative file tree to the current local directory. */\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { CancelledError, PiPodError } from \"../errors.js\";\nimport { info } from \"../log.js\";\nimport { confirm } from \"../prompt.js\";\nimport type { AccountClient } from \"./api.js\";\nimport { selectAccountPod } from \"./pods.js\";\nimport { displayRef } from \"./ref.js\";\nimport { withWorkstationWait } from \"./workstation.js\";\n\nconst RECEIVE_MAX_ENTRIES = 10_000;\nconst RECEIVE_MAX_BYTES = 24 * 1024 * 1024;\nconst RECEIVE_TIMEOUT_MS = 11 * 60 * 1000;\n\nexport interface ReceivedEntry {\n relPath: string;\n kind: \"file\" | \"dir\" | \"symlink\";\n mode: number;\n size?: number;\n target?: string;\n contents?: string;\n}\n\ninterface ReceiveResponse {\n id: string;\n source: string;\n entries: ReceivedEntry[];\n}\n\nexport async function runAccountReceive(\n client: AccountClient,\n args: string[],\n flags: { yes?: boolean } = {},\n): Promise<number> {\n if (args.length < 1 || args.length > 2) {\n throw new PiPodError(\"usage: pipod receive [pod] <path>\");\n }\n const [podRef, requested] = args.length === 2 ? [args[0], args[1]!] : [undefined, args[0]!];\n const pod = await selectAccountPod(client, podRef, \"receive files from\");\n const source = safeRemotePath(requested, pod.resolvedConfig.workdir);\n const sourceName = path.posix.basename(source);\n const destination = path.resolve(sourceName);\n assertDestinationAbsent(destination);\n if (pod.state === \"archived\") {\n const ok = await confirm(`pod ${displayRef(pod.id, \"pod\")} is archived — restore and receive?`, {\n nonInteractiveDefault: false,\n assumeYes: flags.yes,\n });\n if (!ok) throw new CancelledError(\"receive cancelled\");\n // A restore can itself meet the host-demand 503 when the workstation is down; wait for it\n // the same way the file read below does rather than failing an archived pod's receive.\n await withWorkstationWait(client, () => client.podCommand(pod.id, \"restore\"));\n }\n\n info(`receiving pod ${displayRef(pod.id, \"pod\")}:${source} → ${destination}`);\n // Reading a file is exactly what wakes a sleeping personal workstation, so this is one of\n // the paths that routinely meets the host-demand 503 (it is the call the production M2 run\n // used to drive a resume). Nothing has been written to disk yet, so retrying is free.\n const response = await withWorkstationWait(client, () =>\n client.request<ReceiveResponse>(`/pods/${pod.id}/files`, {\n query: { path: source },\n timeoutMs: RECEIVE_TIMEOUT_MS,\n }),\n );\n materializeReceivedTree(response.entries, destination);\n info(`received ${sourceName}`);\n return 0;\n}\n\n/** Materialize a server-validated tree defensively, staging beside the final destination. */\nexport function materializeReceivedTree(entries: ReceivedEntry[], destination: string): void {\n if (entries.length === 0 || entries.length > RECEIVE_MAX_ENTRIES || entries[0]?.relPath !== \"\") {\n throw new PiPodError(\"server returned an invalid receive manifest\");\n }\n assertDestinationAbsent(destination);\n\n const checked = entries.map(validateEntry);\n const byPath = new Map<string, ReceivedEntry>();\n let bytes = 0;\n for (const entry of checked) {\n if (byPath.has(entry.relPath)) throw new PiPodError(`server returned duplicate path ${entry.relPath || \".\"}`);\n byPath.set(entry.relPath, entry);\n if (entry.kind === \"file\") {\n bytes += entry.size!;\n if (bytes > RECEIVE_MAX_BYTES) throw new PiPodError(\"server response exceeds the 24 MB receive limit\");\n }\n }\n if (checked.length > 1 && checked[0]!.kind !== \"dir\") {\n throw new PiPodError(\"server returned children beneath a non-directory receive root\");\n }\n\n // An entry may only have directory ancestors. This prevents a malicious manifest from first\n // creating a symlink and then using it as a write path for another entry.\n for (const entry of checked) {\n const parts = entry.relPath === \"\" ? [] : entry.relPath.split(\"/\");\n for (let i = 1; i < parts.length; i += 1) {\n const ancestor = byPath.get(parts.slice(0, i).join(\"/\"));\n if (ancestor && ancestor.kind !== \"dir\") {\n throw new PiPodError(`server returned a non-directory parent for ${entry.relPath}`);\n }\n }\n }\n\n const parent = path.dirname(destination);\n const staging = fs.mkdtempSync(path.join(parent, \".pi-pod-receive-\"));\n const root = path.join(staging, \"payload\");\n const localPath = (relPath: string): string =>\n relPath === \"\" ? root : path.join(root, ...relPath.split(\"/\"));\n\n try {\n const directories = checked\n .filter((entry) => entry.kind === \"dir\")\n .sort((a, b) => depth(a.relPath) - depth(b.relPath));\n for (const entry of directories) fs.mkdirSync(localPath(entry.relPath), { recursive: true, mode: 0o700 });\n\n for (const entry of checked.filter((item) => item.kind === \"file\")) {\n const dest = localPath(entry.relPath);\n fs.mkdirSync(path.dirname(dest), { recursive: true, mode: 0o700 });\n const contents = decodeCanonicalBase64(entry.contents!, entry.relPath);\n if (contents.byteLength !== entry.size) throw new PiPodError(`file size changed in transit: ${entry.relPath || \".\"}`);\n fs.writeFileSync(dest, contents, { flag: \"wx\", mode: entry.mode });\n }\n\n // Links are last, after every path that can contain another entry has already been written.\n for (const entry of checked.filter((item) => item.kind === \"symlink\")) {\n const dest = localPath(entry.relPath);\n fs.mkdirSync(path.dirname(dest), { recursive: true, mode: 0o700 });\n fs.symlinkSync(entry.target!, dest);\n }\n\n for (const entry of directories\n .filter((item) => item.relPath !== \"\")\n .sort((a, b) => depth(b.relPath) - depth(a.relPath))) {\n fs.chmodSync(localPath(entry.relPath), entry.mode);\n }\n commitStagedRoot(root, destination, checked[0]!);\n } catch (error) {\n throw error instanceof PiPodError\n ? error\n : new PiPodError(`could not write received files: ${error instanceof Error ? error.message : String(error)}`, { cause: error });\n } finally {\n fs.rmSync(staging, { recursive: true, force: true });\n }\n}\n\nfunction validateEntry(entry: ReceivedEntry): ReceivedEntry {\n if (!entry || typeof entry !== \"object\") throw new PiPodError(\"server returned an invalid receive entry\");\n const relPath = entry.relPath;\n const parts = typeof relPath === \"string\" && relPath !== \"\" ? relPath.split(\"/\") : [];\n if (\n typeof relPath !== \"string\" ||\n relPath.length > 1024 ||\n relPath.startsWith(\"/\") ||\n relPath.includes(\"\\0\") ||\n relPath.includes(\"\\\\\") ||\n parts.some((part) => part === \"\" || part === \".\" || part === \"..\")\n ) {\n throw new PiPodError(`server returned an unsafe receive path: ${String(relPath)}`);\n }\n if (entry.kind !== \"file\" && entry.kind !== \"dir\" && entry.kind !== \"symlink\") {\n throw new PiPodError(`server returned an unsupported entry: ${relPath || \".\"}`);\n }\n if (!Number.isInteger(entry.mode) || entry.mode < 0 || entry.mode > 0o777) {\n throw new PiPodError(`server returned an invalid mode: ${relPath || \".\"}`);\n }\n if (entry.kind === \"file\") {\n if (!Number.isSafeInteger(entry.size) || entry.size! < 0 || typeof entry.contents !== \"string\") {\n throw new PiPodError(`server returned an invalid file: ${relPath || \".\"}`);\n }\n }\n if (entry.kind === \"symlink\") {\n if (typeof entry.target !== \"string\" || entry.target === \"\" || symlinkEscapesRoot(relPath, entry.target)) {\n throw new PiPodError(`server returned an unsafe symlink: ${relPath || \".\"}`);\n }\n }\n return entry;\n}\n\nexport function safeRemotePath(value: string, workdir?: string): string {\n if (value.includes(\"\\0\") || value.includes(\"\\\\\") || value.split(\"/\").includes(\"..\")) {\n throw new PiPodError(`receive path must stay inside the pod workdir and must not contain '..' or backslashes: ${JSON.stringify(value)}`, {\n hint: \"pass a path such as foo or build/output.zip\",\n });\n }\n let relative = value;\n if (value.startsWith(\"/\")) {\n const root = workdir ? path.posix.normalize(workdir).replace(/\\/$/, \"\") : null;\n if (!root || !path.posix.isAbsolute(root) || (value !== root && !value.startsWith(`${root}/`))) {\n throw new PiPodError(`receive path is outside the pod workdir: ${JSON.stringify(value)}`, {\n hint: root ? `choose a path under ${root}` : \"pass a workdir-relative path such as foo\",\n });\n }\n relative = value.slice(root.length).replace(/^\\//, \"\");\n }\n const normalized = path.posix.normalize(relative).replace(/^\\.\\//, \"\").replace(/\\/$/, \"\");\n if (normalized === \"\" || normalized === \".\" || normalized === \"/\") {\n throw new PiPodError(\"receive path must name a file or directory inside the pod workdir\", {\n hint: \"pass a named entry such as foo\",\n });\n }\n return normalized;\n}\n\nfunction commitStagedRoot(root: string, destination: string, rootEntry: ReceivedEntry): void {\n try {\n if (rootEntry.kind === \"file\") {\n // Staging is beside destination, so this atomically creates the final name and fails\n // rather than replacing a destination that appeared while the server was responding.\n fs.linkSync(root, destination);\n return;\n }\n if (rootEntry.kind !== \"dir\") throw new PiPodError(\"server returned an invalid receive root\");\n fs.mkdirSync(destination, { mode: 0o700 });\n try {\n for (const name of fs.readdirSync(root)) {\n fs.renameSync(path.join(root, name), path.join(destination, name));\n }\n fs.chmodSync(destination, rootEntry.mode);\n } catch (error) {\n fs.rmSync(destination, { recursive: true, force: true });\n throw error;\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"EEXIST\") throw destinationExistsError(destination);\n throw error;\n }\n}\n\n\nfunction assertDestinationAbsent(destination: string): void {\n try {\n fs.lstatSync(destination);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return;\n throw new PiPodError(`cannot inspect receive destination ${destination}`, { cause: error });\n }\n throw destinationExistsError(destination);\n}\n\nfunction destinationExistsError(destination: string): PiPodError {\n return new PiPodError(`receive destination already exists: ${destination}`, {\n hint: \"move or remove it, then receive again\",\n });\n}\n\nfunction decodeCanonicalBase64(contents: string, relPath: string): Buffer {\n if (!/^[A-Za-z0-9+/]*={0,2}$/.test(contents) || contents.length % 4 !== 0) {\n throw new PiPodError(`server returned invalid file data: ${relPath || \".\"}`);\n }\n const decoded = Buffer.from(contents, \"base64\");\n if (decoded.toString(\"base64\") !== contents) throw new PiPodError(`server returned invalid file data: ${relPath || \".\"}`);\n return decoded;\n}\n\nfunction symlinkEscapesRoot(relPath: string, target: string): boolean {\n if (relPath === \"\" || target.startsWith(\"/\") || target.includes(\"\\0\") || target.includes(\"\\\\\")) return true;\n const parent = path.posix.dirname(relPath);\n const resolved = path.posix.normalize(path.posix.join(parent === \".\" ? \"\" : parent, target));\n return resolved === \"..\" || resolved.startsWith(\"../\") || path.posix.isAbsolute(resolved);\n}\n\nfunction depth(relPath: string): number {\n return relPath === \"\" ? 0 : relPath.split(\"/\").length;\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as readline from \"node:readline/promises\";\nimport { execFile, spawn } from \"node:child_process\";\nimport type { AccountClient, CredentialStatus } from \"../account/api.js\";\nimport { requireAccountClient } from \"../account/client.js\";\nimport { runCredentialLogin } from \"../account/credential-login.js\";\nimport { installedPiPackage } from \"../client/piversion.js\";\nimport type {\n RemoteAuthEvent,\n RemoteAuthInteraction,\n RemoteAuthPrompt,\n} from \"../client/runtime/auth-bridge.js\";\nimport { CancelledError, PiPodError } from \"../errors.js\";\nimport { info, out, warn } from \"../log.js\";\nimport { confirm, isInteractive, promptSecret } from \"../prompt.js\";\nimport { registerSecret } from \"../redact.js\";\n\nexport interface CredentialsFlags {\n home?: string | undefined;\n yes?: boolean;\n client?: AccountClient;\n /** Test/TUI seam; the command-line default is a small stdin/stderr interaction. */\n interaction?: RemoteAuthInteraction;\n /** Test seam for `--from-pi`; the default runs the bundled pi's `auth print-api-key`. */\n localKeySource?: (providerId: string) => Promise<string>;\n /** Test seam for the bulk sweep; the default runs the bundled pi's `auth check`. */\n localAuthCheck?: (providerId: string) => Promise<LocalAuthCheck>;\n}\n\nfunction clientFor(flags: CredentialsFlags): AccountClient {\n return flags.client ?? requireAccountClient({ home: flags.home });\n}\n\nexport async function runCredentials(args: string[], flags: CredentialsFlags = {}): Promise<number> {\n const [action = \"list\", ...rest] = args;\n switch (action) {\n case \"list\":\n rejectExtra(rest, \"usage: pipod credentials [list]\");\n return listCredentials(clientFor(flags));\n case \"connect\":\n case \"reconnect\":\n // A bare `connect` (at most `--yes`) means every provider, not a usage error.\n return rest.every((arg) => arg === \"--yes\" || arg === \"-y\")\n ? bulkConnect(rest, flags)\n : connectCredential(rest, flags);\n case \"test\":\n return testCredential(rest, clientFor(flags));\n case \"remove\":\n case \"rm\":\n return removeCredential(rest, flags);\n default:\n throw new PiPodError(`unknown \\`pipod credentials\\` action \"${action}\"`, {\n hint: \"actions: list (default), connect [<provider>] [--api-key [--from-pi]] (no provider connects every connectable provider), reconnect <provider>, test <provider>, remove <provider> [--yes]\",\n });\n }\n}\n\nasync function listCredentials(client: AccountClient): Promise<number> {\n const result = await client.modelCredentials();\n if (result.credentials.length === 0) info(\"no account model-provider credentials are saved\");\n for (const credential of result.credentials) out(formatStatus(credential));\n\n const stored = new Set(result.credentials.map((credential) => credential.providerId));\n const connectable = result.providers\n .filter((provider) => provider.brokerSupported && !stored.has(provider.id))\n .map((provider) => provider.id);\n info(`Connectable: ${connectable.length > 0 ? connectable.join(\", \") : \"none\"}`);\n return 0;\n}\n\nconst CONNECT_USAGE = \"usage: pipod credentials connect <provider> [--api-key [--from-pi]]\";\n\nasync function connectCredential(args: string[], flags: CredentialsFlags): Promise<number> {\n let providerId: string | undefined;\n let apiKey = false;\n let fromPi = false;\n for (const arg of args) {\n if (arg === \"--api-key\") apiKey = true;\n else if (arg === \"--from-pi\") fromPi = true;\n else if (arg.startsWith(\"-\")) throw new PiPodError(`unknown pipod credentials option \"${arg}\"`);\n else if (providerId === undefined) providerId = arg;\n else throw new PiPodError(`unexpected argument \"${arg}\"`, { hint: CONNECT_USAGE });\n }\n if (!providerId) throw new PiPodError(CONNECT_USAGE);\n // OAuth grants are machine-bound and never importable; --from-pi always means an API key.\n if (fromPi) apiKey = true;\n\n const terminal = flags.interaction ? null : terminalInteraction();\n try {\n const status = await connectOne(\n clientFor(flags),\n { providerId, authType: apiKey ? \"api_key\" : \"oauth\", importKey: fromPi },\n flags.interaction ?? terminal!.interaction,\n flags,\n );\n info(`connected ${providerId} (${status.type}, ${status.state})`);\n return 0;\n } finally {\n terminal?.dispose();\n }\n}\n\ninterface ConnectPlan {\n providerId: string;\n authType: \"api_key\" | \"oauth\";\n /** Answer the login's secret prompt from local pi instead of asking the user. */\n importKey: boolean;\n}\n\n/** One provider's connect, shared by the single-provider command and the bulk sweep. */\nasync function connectOne(\n client: AccountClient,\n plan: ConnectPlan,\n base: RemoteAuthInteraction,\n flags: CredentialsFlags,\n): Promise<CredentialStatus> {\n let interaction = base;\n if (plan.importKey) {\n const source = flags.localKeySource ?? ((provider: string) => readLocalPiApiKey(provider, flags.home));\n const key = (await source(plan.providerId)).trim();\n if (!key) {\n throw new PiPodError(`local pi has no ${plan.providerId} API key`, {\n hint: `run \\`pi\\` and use /login to store one, or rerun without --from-pi to enter the key directly`,\n });\n }\n registerSecret(key);\n info(`importing your local pi ${plan.providerId} API key into account custody`);\n interaction = withImportedKey(base, key);\n }\n return runCredentialLogin({\n client,\n providerId: plan.providerId,\n authType: plan.authType,\n interaction,\n });\n}\n\ninterface SkippedProvider {\n providerId: string;\n reason: string;\n}\n\n/**\n * `connect` with no provider: give every broker-supported provider an account credential,\n * importing the API keys local pi already resolves and running a fresh login for the rest.\n */\nasync function bulkConnect(args: string[], flags: CredentialsFlags): Promise<number> {\n const yes = flags.yes === true || args.some((arg) => arg === \"--yes\" || arg === \"-y\");\n const client = clientFor(flags);\n const { credentials, providers } = await client.modelCredentials();\n const stored = new Map(credentials.map((credential) => [credential.providerId, credential]));\n const connectable = providers.filter((provider) => provider.brokerSupported);\n const candidates = connectable.filter((provider) => stored.get(provider.id)?.state !== \"ready\");\n if (candidates.length === 0) {\n info(\"all connectable providers already have account credentials\");\n return 0;\n }\n\n const check = flags.localAuthCheck ?? ((provider: string) => checkLocalPiAuth(provider, flags.home));\n const planned: ConnectPlan[] = [];\n const skipped: SkippedProvider[] = connectable\n .filter((provider) => stored.get(provider.id)?.state === \"ready\")\n .map((provider) => ({ providerId: provider.id, reason: \"already connected\" }));\n for (const provider of candidates) {\n const local = await check(provider.id);\n if (local.status === \"invalid\") {\n warn(`local pi could not check ${provider.id}${local.reason ? `: ${local.reason}` : \"\"}`);\n skipped.push({ providerId: provider.id, reason: \"local check failed\" });\n } else if (local.status !== \"ready\") {\n skipped.push({ providerId: provider.id, reason: \"not configured in local pi\" });\n } else if (local.authType === \"api_key\" && provider.apiKey) {\n planned.push({ providerId: provider.id, authType: \"api_key\", importKey: true });\n } else if (provider.oauth) {\n // Local OAuth cannot be copied, and an api-key-only local grant is useless to a\n // broker that wants OAuth: either way a fresh account login is the way to a credential.\n planned.push({ providerId: provider.id, authType: \"oauth\", importKey: false });\n } else {\n skipped.push({ providerId: provider.id, reason: \"no supported login\" });\n }\n }\n\n for (const plan of planned) {\n info(` ${plan.providerId}: ${plan.importKey ? \"import API key from local pi\" : \"fresh OAuth login\"}`);\n }\n for (const skip of skipped) info(` ${skip.providerId}: skipped — ${skip.reason}`);\n if (planned.length === 0) {\n info(\"nothing to connect\");\n return 0;\n }\n\n // Refuse before a ticket exists rather than stranding a half-done sweep at a dead prompt.\n if (planned.some((plan) => plan.authType === \"oauth\") && !flags.interaction && !isInteractive()) {\n throw new PiPodError(\"an OAuth sign-in needs a terminal\", {\n hint: \"rerun `pipod credentials connect` in a terminal, or connect the API-key providers one at a time with `pipod credentials connect <provider> --api-key --from-pi`\",\n });\n }\n const approved = await confirm(`connect ${planned.length} provider credential(s)?`, {\n nonInteractiveDefault: false,\n assumeYes: yes,\n });\n if (!approved) throw new CancelledError(\"Credential connect cancelled\");\n\n const terminal = flags.interaction ? null : terminalInteraction();\n const base = flags.interaction ?? terminal!.interaction;\n const connected: string[] = [];\n const failed: string[] = [];\n try {\n for (const plan of planned) {\n try {\n const status = await connectOne(client, plan, base, flags);\n info(`connected ${plan.providerId} (${status.type}, ${status.state})`);\n connected.push(plan.providerId);\n } catch (error) {\n if (error instanceof CancelledError) throw error;\n warn(`${plan.providerId}: ${error instanceof Error ? error.message : String(error)}`);\n failed.push(plan.providerId);\n }\n }\n } finally {\n terminal?.dispose();\n }\n\n info(`connected: ${connected.join(\", \") || \"none\"}`);\n if (skipped.length > 0) {\n info(`skipped: ${skipped.map((skip) => `${skip.providerId} (${skip.reason})`).join(\", \")}`);\n }\n if (failed.length > 0) warn(`failed: ${failed.join(\", \")}`);\n return failed.length > 0 ? 1 : 0;\n}\n\n/** Answer the login's first secret prompt with the imported key; everything else falls through. */\nfunction withImportedKey(base: RemoteAuthInteraction, key: string): RemoteAuthInteraction {\n let used = false;\n return {\n ...base,\n prompt: (prompt) => {\n if (prompt.type === \"secret\" && !used) {\n used = true;\n return Promise.resolve(key);\n }\n return base.prompt(prompt);\n },\n };\n}\n\n/**\n * The key local pi would actually use — the bundled pi resolves auth.json `!command` and\n * `$ENV` references, so a raw auth.json copy would ship a reference that means nothing in a pod.\n */\nexport async function readLocalPiApiKey(providerId: string, home?: string): Promise<string> {\n const pi = installedPiPackage();\n const cli = path.join(pi.root, pi.bin);\n return new Promise<string>((resolve, reject) => {\n execFile(\n process.execPath,\n [cli, \"auth\", \"print-api-key\", \"--provider\", providerId],\n {\n timeout: 30_000,\n maxBuffer: 64 * 1024,\n env: { ...process.env, ...(home ? { HOME: home } : {}) },\n },\n (error, stdout, stderr) => {\n if (error) {\n reject(\n new PiPodError(`local pi could not print a ${providerId} API key`, {\n hint: (stderr || error.message).trim().split(\"\\n\").at(-1),\n }),\n );\n } else {\n resolve(stdout);\n }\n },\n );\n });\n}\n\nexport interface LocalAuthCheck {\n status: \"ready\" | \"not_ready\" | \"invalid\";\n authType?: \"api_key\" | \"oauth\";\n reason?: string;\n}\n\n/** What local pi itself says about a provider, resolving env-backed keys the same way it would. */\nexport async function checkLocalPiAuth(providerId: string, home?: string): Promise<LocalAuthCheck> {\n const pi = installedPiPackage();\n const cli = path.join(pi.root, pi.bin);\n return new Promise<LocalAuthCheck>((resolve) => {\n execFile(\n process.execPath,\n [cli, \"auth\", \"check\", \"--provider\", providerId, \"--json\", \"--no-refresh\"],\n {\n timeout: 30_000,\n maxBuffer: 64 * 1024,\n env: { ...process.env, ...(home ? { HOME: home } : {}) },\n },\n (error, stdout, stderr) => {\n // pi exits nonzero for every non-ready answer, so the JSON is the result, not the code.\n // One unreadable provider is reported as invalid so it cannot sink the whole sweep.\n resolve(\n parseLocalAuthCheck(stdout) ?? {\n status: \"invalid\",\n reason: (stderr || error?.message || \"no JSON output\").trim().split(\"\\n\").at(-1),\n },\n );\n },\n );\n });\n}\n\nfunction parseLocalAuthCheck(stdout: string): LocalAuthCheck | null {\n let value: unknown;\n try {\n value = JSON.parse(stdout.trim());\n } catch {\n return null;\n }\n if (value === null || typeof value !== \"object\") return null;\n const record = value as Record<string, unknown>;\n const status = record[\"status\"];\n if (status !== \"ready\" && status !== \"not_ready\" && status !== \"invalid\") return null;\n return {\n status,\n ...(record[\"authType\"] === \"api_key\" || record[\"authType\"] === \"oauth\" ? { authType: record[\"authType\"] } : {}),\n ...(typeof record[\"reason\"] === \"string\" ? { reason: record[\"reason\"] } : {}),\n };\n}\n\nasync function testCredential(args: string[], client: AccountClient): Promise<number> {\n rejectProviderArgs(args, \"usage: pipod credentials test <provider>\");\n const providerId = args[0]!;\n const { status } = await client.testModelCredential(providerId);\n out(formatStatus(status));\n if (status.state === \"ready\") return 0;\n info(`\\`pipod credentials reconnect ${providerId}\\` signs in again`);\n return 1;\n}\n\nasync function removeCredential(args: string[], flags: CredentialsFlags): Promise<number> {\n let providerId: string | undefined;\n let yes = flags.yes === true;\n for (const arg of args) {\n if (arg === \"--yes\" || arg === \"-y\") yes = true;\n else if (arg.startsWith(\"-\")) throw new PiPodError(`unknown pipod credentials option \"${arg}\"`);\n else if (providerId === undefined) providerId = arg;\n else throw new PiPodError(`unexpected argument \"${arg}\"`, { hint: \"usage: pipod credentials remove <provider> [--yes]\" });\n }\n if (!providerId) throw new PiPodError(\"usage: pipod credentials remove <provider> [--yes]\");\n if (!yes && !isInteractive()) {\n throw new PiPodError(`refusing to remove the saved ${providerId} sign-in without a terminal`, {\n hint: `rerun with \\`pipod credentials remove ${providerId} --yes\\``,\n });\n }\n const approved = await confirm(\n `Remove the saved ${providerId} sign-in? Pods using it will need a reconnect.`,\n { nonInteractiveDefault: false, assumeYes: yes },\n );\n if (!approved) throw new CancelledError(\"Credential removal cancelled\");\n await clientFor(flags).deleteModelCredential(providerId);\n info(`removed the saved ${providerId} sign-in`);\n return 0;\n}\n\nfunction formatStatus(status: CredentialStatus): string {\n const expires = status.state === \"ready\" && status.expiresAt ? ` (expires ${status.expiresAt})` : \"\";\n return `${status.providerId} ${status.state.replaceAll(\"_\", \" \")}${expires}`;\n}\n\nfunction rejectExtra(args: string[], usage: string): void {\n if (args.length > 0) throw new PiPodError(usage);\n}\n\nfunction rejectProviderArgs(args: string[], usage: string): void {\n if (args.length !== 1 || args[0]!.startsWith(\"-\")) throw new PiPodError(usage);\n}\n\nfunction terminalInteraction(): { interaction: RemoteAuthInteraction; dispose(): void } {\n const controller = new AbortController();\n const onInterrupt = (): void => controller.abort();\n let pipedAnswers: string[] | undefined;\n process.once(\"SIGINT\", onInterrupt);\n return {\n interaction: {\n signal: controller.signal,\n prompt: (prompt) => {\n if (!process.stdin.isTTY && pipedAnswers === undefined) {\n pipedAnswers = fs.readFileSync(0, \"utf8\").split(/\\r?\\n/);\n }\n return promptOnStdin(prompt, controller.signal, pipedAnswers);\n },\n notify: notifyTerminal,\n },\n dispose: () => process.removeListener(\"SIGINT\", onInterrupt),\n };\n}\n\nasync function promptOnStdin(\n prompt: RemoteAuthPrompt,\n signal: AbortSignal,\n pipedAnswers?: string[],\n): Promise<string> {\n if (prompt.type === \"secret\") {\n if (!isInteractive()) warn(\"secret input cannot be hidden because stdin is not a terminal\");\n if (isInteractive()) return promptSecret(`${prompt.message}: `, signal);\n }\n if (!process.stdin.isTTY) {\n if (signal.aborted) throw new CancelledError(\"Credential login cancelled\");\n return (pipedAnswers?.shift() ?? \"\").trim();\n }\n\n if (prompt.type === \"select\") {\n for (const [index, option] of (prompt.options ?? []).entries()) {\n info(` ${index + 1}. ${option.label}${option.description ? ` — ${option.description}` : \"\"}`);\n }\n }\n const rl = readline.createInterface({ input: process.stdin, output: process.stderr });\n try {\n const answer = await rl.question(`${prompt.message}${prompt.placeholder ? ` (${prompt.placeholder})` : \"\"}: `, { signal });\n const trimmed = answer.trim();\n if (prompt.type !== \"select\") return trimmed;\n const index = Number(trimmed);\n if (Number.isInteger(index) && index >= 1 && index <= (prompt.options?.length ?? 0)) {\n return prompt.options![index - 1]!.id;\n }\n return trimmed;\n } catch (error) {\n // A Ctrl-C keystroke reaches readline as a byte, so its AbortError can arrive before\n // the SIGINT that aborts the signal — both mean the same answer.\n if (signal.aborted || (error as { name?: string })?.name === \"AbortError\") {\n throw new CancelledError(\"Credential login cancelled\");\n }\n throw error;\n } finally {\n rl.close();\n }\n}\n\nfunction notifyTerminal(event: RemoteAuthEvent): void {\n switch (event.type) {\n case \"info\":\n info(event.message);\n for (const link of event.links ?? []) info(` ${link.label ? `${link.label}: ` : \"\"}${link.url}`);\n return;\n case \"progress\":\n info(event.message);\n return;\n case \"auth_url\":\n if (event.instructions) info(event.instructions);\n info(event.url);\n openBrowser(event.url);\n return;\n case \"device_code\":\n info(`Open ${event.verificationUri}`);\n info(`User code: ${event.userCode}`);\n openBrowser(event.verificationUri);\n }\n}\n\nfunction openBrowser(url: string): void {\n const command = process.platform === \"darwin\" ? \"open\" : process.platform === \"linux\" ? \"xdg-open\" : null;\n if (!command) return;\n try {\n const child = spawn(command, [url], { detached: true, stdio: \"ignore\" });\n child.on(\"error\", () => {});\n child.unref();\n } catch {\n // The URL has already been printed; browser opening is only a convenience.\n }\n}\n","/**\n * src/commands/secrets.ts — `pipod secrets` (§7).\n *\n * The listing is the point of this command: it answers \"what does the pod see, and who set\n * it\", including the layers that lost. Writes always name their scope as a positional, so\n * there is no default scope to guess wrong about.\n */\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { AccountClient } from \"../account/api.js\";\nimport { requireAccountClient } from \"../account/client.js\";\nimport {\n readHostConfig,\n readSecretResolverLayers,\n resolveLaunchTemplateRef,\n resolveTemplate,\n takeClientOnlyKeys,\n} from \"../account/launch.js\";\nimport { findConfigPath } from \"../config.js\";\nimport { parseDotenv } from \"../dotenv.js\";\nimport { parseJsonc } from \"../jsonc.js\";\nimport { PiPodError } from \"../errors.js\";\nimport { color, info, out, warn } from \"../log.js\";\nimport { isProviderCredentialVar } from \"../providers/registry.js\";\nimport { isInteractive, promptSecret } from \"../prompt.js\";\nimport { mergeSecretResolver, resolveSecretRefs } from \"../secret-refs.js\";\nimport {\n collectSecrets,\n defaultSyncEnvPath,\n isServerScope,\n removeFromDotenv,\n resolveScopeTarget,\n SECRET_SCOPES,\n upsertDotenv,\n type SecretScope,\n} from \"../secrets.js\";\nimport { legacyUserEnvWarning } from \"../userconfig.js\";\n\nexport interface SecretsFlags {\n home?: string | undefined;\n yes?: boolean;\n client?: AccountClient;\n}\n\nfunction clientFor(flags: SecretsFlags): AccountClient {\n return flags.client ?? requireAccountClient({ home: flags.home });\n}\n\nexport async function runSecrets(args: string[], flags: SecretsFlags, cwd = process.cwd()): Promise<number> {\n const rest0 = args.filter((arg) => arg !== \"-y\" && arg !== \"--yes\");\n const effective: SecretsFlags = { ...flags };\n const [action = \"list\", ...rest] = rest0;\n switch (action) {\n case \"list\":\n rejectUnknownOptions(rest);\n return listCmd(effective, cwd);\n case \"set\":\n rejectUnknownOptions(rest);\n return setCmd(rest, effective, cwd);\n case \"rm\":\n case \"remove\":\n case \"unset\":\n rejectUnknownOptions(rest);\n return rmCmd(rest, effective, cwd);\n case \"sync\":\n return syncCmd(rest, effective, cwd);\n default:\n // A bare `pipod secrets <scope>` is a plausible typo for a filtered listing; say so\n // rather than treating an unknown word as a subcommand.\n throw new PiPodError(`unknown \\`pipod secrets\\` action \"${action}\"`, {\n hint: \"actions: list (default), set <scope> <NAME>, rm <scope> <NAME>, sync <scope>\",\n });\n }\n}\n\nfunction rejectUnknownOptions(args: string[]): void {\n const unknownOption = args.find((arg) => arg.startsWith(\"-\"));\n if (unknownOption) throw new PiPodError(`unknown pi pod option \"${unknownOption}\"`);\n}\n\n/** Which template applies here comes from the same resolve the launch uses, not a guess. */\nasync function templateForRepo(\n client: AccountClient,\n flags: SecretsFlags,\n cwd: string,\n): Promise<{ id: string; name: string } | null> {\n const configPath = findConfigPath(cwd, { home: flags.home });\n const projectRaw = configPath\n ? (parseJsonc(fs.readFileSync(configPath, \"utf8\"), configPath) as Record<string, unknown>)\n : {};\n const projectTaken = takeClientOnlyKeys(projectRaw);\n const hostTaken = takeClientOnlyKeys(readHostConfig(flags.home));\n const ref = resolveLaunchTemplateRef({}, {\n project: projectTaken.template,\n machine: hostTaken.template,\n });\n if (!ref) return null;\n try {\n const found = await resolveTemplate(client, ref);\n return { id: found.id, name: found.name };\n } catch {\n return null;\n }\n}\n\nasync function listCmd(flags: SecretsFlags, cwd: string): Promise<number> {\n const client = clientFor(flags);\n const template = await templateForRepo(client, flags, cwd);\n const { rows, layers } = await collectSecrets({ cwd, home: flags.home, client, template });\n\n const legacy = legacyUserEnvWarning(flags.home);\n if (legacy) warn(legacy);\n\n info(`secrets visible to pods launched here (${client.serverUrl})`);\n for (const layer of layers) {\n const state = layer.reachable ? `${layer.count}` : color.yellow(\"no access\");\n info(` ${layer.scope.padEnd(9)} ${String(state).padStart(3)} ${layer.source}`);\n }\n\n if (rows.length === 0) {\n info(\"no secrets in any layer that applies here\");\n return 0;\n }\n\n out(\"\");\n out(`${\"NAME\".padEnd(28)} ${\"WINS FROM\".padEnd(10)} SOURCE`);\n for (const row of rows) {\n const shadow =\n row.shadowed.length > 0\n ? color.dim(` (shadows ${row.shadowed.map((s) => s.scope).join(\", \")})`)\n : \"\";\n out(`${row.name.padEnd(28)} ${row.winner.scope.padEnd(10)} ${row.winner.source}${shadow}`);\n }\n\n const report = await client.resolve(template ? { templateId: template.id } : {}).catch(() => null);\n if (report) {\n const credential = report.credential;\n out(\"\");\n info(\n credential.available\n ? `provider credential ${credential.envVar}: available (${credential.source}) — held by the server`\n : `provider credential ${credential.envVar}: ${color.yellow(\"missing\")} — the server cannot provision until it is set`,\n );\n }\n return 0;\n}\n\n/** Reads naturally in a sentence, unlike the column label the listing uses. */\nfunction describeTarget(target: { scope: string; label: string }): string {\n if (target.scope === \"org\") return \"the org scope — every member's pods\";\n if (target.scope === \"user\") return \"your user scope — your pods on every device\";\n return `the ${target.label} scope`;\n}\n\n/**\n * Secret values never travel as CLI arguments: `ps`, shell history, and hosted-command logs\n * all capture argv. The name rides the command line; the value arrives on stdin (piped) or\n * through a hidden interactive prompt. `NAME=value` is refused outright rather than\n * deprecated — this interface is pre-release and argv exposure is not worth a grace period.\n */\nexport const secretsTestHooks: { readPipedStdin: () => string } = {\n // Test/reset hook (mirrors core/redact.ts): the suite has no TTY to pipe through, so it\n // substitutes this reader instead of inheriting a real fd 0.\n readPipedStdin: () => fs.readFileSync(0, \"utf8\"),\n};\n\n/** `NAME` with the value piped on stdin, or via hidden prompt at a terminal. */\nasync function readValue(name: string, scopeLabel: string): Promise<{ name: string; value: string }> {\n if (name.includes(\"=\")) {\n throw new PiPodError(`pipod secrets set no longer accepts NAME=value — argv is visible to other processes`, {\n hint: `use the hidden prompt, or stdin: pipod secrets set ${scopeLabel} ${name.split(\"=\")[0]} < /path/to/protected-value-file`,\n });\n }\n\n if (!process.stdin.isTTY) {\n const piped = secretsTestHooks.readPipedStdin().replace(/\\n$/, \"\");\n if (!piped) throw new PiPodError(`no value for ${name} on stdin`);\n return { name, value: piped };\n }\n if (!isInteractive()) throw new PiPodError(`no value for ${name}`, { hint: `use stdin: pipod secrets set ${scopeLabel} ${name} < /path/to/protected-value-file` });\n const value = await promptSecret(`value for ${name} (${scopeLabel}), input hidden: `);\n if (!value) throw new PiPodError(`no value for ${name} — nothing was written`);\n return { name, value };\n}\n\nasync function setCmd(args: string[], flags: SecretsFlags, cwd: string): Promise<number> {\n const [scopeToken, spec, extra] = args;\n if (!scopeToken || !spec || extra !== undefined) {\n throw new PiPodError(\"usage: pipod secrets set <scope> <NAME>\", {\n hint: `scopes, lowest precedence first: ${SECRET_SCOPES.join(\", \")}`,\n });\n }\n const client = clientFor(flags);\n const target = await resolveScopeTarget(scopeToken, { client, cwd, home: flags.home });\n const { name, value } = await readValue(spec, scopeToken);\n\n if (target.scope === \"template\" && isProviderCredentialVar(name)) {\n throw new PiPodError(`${name} is a provider credential and can never be stored as a template pod secret`, {\n hint: \"provider credentials belong in server or organization control-plane custody\",\n });\n }\n\n if (isServerScope(target.scope)) {\n const resolved = await resolveSecretRefs({ [name]: value }, resolverConfig(cwd, flags.home), {\n home: flags.home,\n });\n await client.putSecret(target.scope, target.id, name, resolved[name]!);\n info(`stored ${name} in ${describeTarget(target)}`);\n } else {\n const outcome = upsertDotenv(target.id, name, value);\n info(`${outcome === \"created\" ? \"added\" : \"updated\"} ${name} in ${target.label}`);\n }\n await warnIfShadowed(name, target.scope, flags, cwd, client);\n return 0;\n}\n\nasync function rmCmd(args: string[], flags: SecretsFlags, cwd: string): Promise<number> {\n const [scopeToken, name] = args;\n if (!scopeToken || !name) {\n throw new PiPodError(\"usage: pipod secrets rm <scope> <NAME>\", {\n hint: `scopes, lowest precedence first: ${SECRET_SCOPES.join(\", \")}`,\n });\n }\n const client = clientFor(flags);\n const target = await resolveScopeTarget(scopeToken, { client, cwd, home: flags.home });\n\n // Removing what is not there leaves the scope as asked: say so, and succeed.\n if (isServerScope(target.scope)) {\n try {\n await client.deleteSecret(target.scope, target.id, name);\n } catch (e) {\n if (!(e instanceof PiPodError && e.status === 404)) throw e;\n info(`${name} was not set in ${describeTarget(target)} — nothing to remove`);\n return 0;\n }\n info(`removed ${name} from ${describeTarget(target)}`);\n return 0;\n }\n if (!removeFromDotenv(target.id, name)) {\n info(`${name} was not set in ${target.label} — nothing to remove`);\n return 0;\n }\n info(`removed ${name} from ${target.label}`);\n return 0;\n}\n\n/**\n * Writing a value that something else overrides is the exact confusion this command exists\n * to prevent, so it is called out at the moment it happens rather than left to be discovered\n * in a running pod.\n */\nasync function warnIfShadowed(\n name: string,\n scope: SecretScope,\n flags: SecretsFlags,\n cwd: string,\n client: AccountClient,\n): Promise<void> {\n const template = await templateForRepo(client, flags, cwd);\n const { rows } = await collectSecrets({ cwd, home: flags.home, client, template });\n const row = rows.find((r) => r.name === name);\n if (!row || row.winner.scope === scope) return;\n warn(`pods here still see ${name} from the ${row.winner.scope} layer (${row.winner.source}), which outranks ${scope}`);\n}\n\nfunction resolverConfig(cwd: string, home?: string) {\n const layers = readSecretResolverLayers({ cwd, home });\n return mergeSecretResolver(layers.machine, layers.project);\n}\n\ninterface SyncOpts {\n scopeToken: string;\n file?: string;\n prune: boolean;\n dryRun: boolean;\n}\n\nfunction parseSyncArgs(args: string[]): SyncOpts {\n let scopeToken: string | undefined;\n let file: string | undefined;\n let prune = false;\n let dryRun = false;\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n if (arg === \"--file\") {\n const value = args[++i];\n if (value === undefined) throw new PiPodError(\"--file needs a path\");\n file = value;\n } else if (arg.startsWith(\"--file=\")) {\n file = arg.slice(\"--file=\".length);\n if (!file) throw new PiPodError(\"--file needs a path\");\n } else if (arg === \"--prune\") {\n prune = true;\n } else if (arg === \"--dry-run\") {\n dryRun = true;\n } else if (arg.startsWith(\"-\")) {\n throw new PiPodError(`unknown pi pod option \"${arg}\"`, {\n hint: \"usage: pipod secrets sync <org|user|template/<name>> [--file <path>] [--prune] [--dry-run]\",\n });\n } else if (scopeToken === undefined) {\n scopeToken = arg;\n } else {\n throw new PiPodError(`unexpected argument \"${arg}\"`, {\n hint: \"usage: pipod secrets sync <org|user|template/<name>> [--file <path>] [--prune] [--dry-run]\",\n });\n }\n }\n if (!scopeToken) {\n throw new PiPodError(\"usage: pipod secrets sync <org|user|template/<name>> [--file <path>] [--prune] [--dry-run]\", {\n hint: \"default file: ~/.pi-pod/secrets/<scope>.env\",\n });\n }\n return { scopeToken, file, prune, dryRun };\n}\n\nasync function syncCmd(args: string[], flags: SecretsFlags, cwd: string): Promise<number> {\n const opts = parseSyncArgs(args);\n const client = clientFor(flags);\n const target = await resolveScopeTarget(opts.scopeToken, { client, cwd, home: flags.home });\n if (!isServerScope(target.scope)) {\n throw new PiPodError(\"secrets sync only writes server scopes\", {\n hint: \"the project env file is resolved at launch — no sync needed\",\n });\n }\n\n const file = opts.file\n ? path.resolve(cwd, opts.file)\n : defaultSyncEnvPath(opts.scopeToken, flags.home);\n if (!fs.existsSync(file)) {\n throw new PiPodError(`no secrets file at ${file}`, {\n hint: \"create it (mode 600) with KEY=op://vault/item/field lines, or pass --file\",\n });\n }\n\n const parsed = parseDotenv(fs.readFileSync(file, \"utf8\"));\n const values: Record<string, string> = {};\n for (const [name, value] of Object.entries(parsed.values)) {\n if (target.scope === \"template\" && isProviderCredentialVar(name)) {\n warn(`${name} is a provider credential and never travels in a template — the org key upload owns those`);\n continue;\n }\n values[name] = value;\n }\n const names = Object.keys(values);\n const inFile = new Set(Object.keys(parsed.values));\n\n const listed = await client.listSecrets(target.scope, target.id).catch(() => null);\n const stale = listed ? listed.secrets.map((secret) => secret.name).filter((name) => !inFile.has(name)) : [];\n\n if (opts.dryRun) {\n if (names.length === 0) info(`would set nothing on ${describeTarget(target)} from ${file}`);\n else info(`would set ${names.length} secret(s) on ${describeTarget(target)}: ${names.join(\", \")}`);\n if (opts.prune && stale.length > 0) {\n info(`would prune ${stale.length} secret(s) not in the file: ${stale.join(\", \")}`);\n } else if (stale.length > 0) {\n warn(staleWarning(stale, opts.scopeToken, file));\n }\n return 0;\n }\n\n const resolved = await resolveSecretRefs(values, resolverConfig(cwd, flags.home), { home: flags.home });\n const uploaded: string[] = [];\n for (const name of names) {\n const value = resolved[name] ?? \"\";\n if (value.trim() === \"\") {\n warn(`skip empty field: ${name}`);\n continue;\n }\n try {\n await client.putSecret(target.scope, target.id, name, value);\n uploaded.push(name);\n info(`stored ${name} in ${describeTarget(target)}`);\n } catch (error) {\n const remaining = names.filter((n) => !uploaded.includes(n) && n !== name);\n throw new PiPodError(\n `uploaded ${uploaded.length} of ${names.length} secrets; ${[name, ...remaining].join(\", \")} did not make it: ` +\n (error instanceof Error ? error.message : String(error)),\n { hint: `the names already stored are fine — finish with pipod secrets sync ${opts.scopeToken}` },\n );\n }\n }\n\n if (stale.length > 0) {\n if (opts.prune) {\n for (const name of stale) {\n await client.deleteSecret(target.scope, target.id, name);\n info(`removed ${name} from ${describeTarget(target)}`);\n }\n } else {\n warn(staleWarning(stale, opts.scopeToken, file));\n }\n }\n return 0;\n}\n\nfunction staleWarning(stale: string[], scopeToken: string, file: string): string {\n return (\n `secrets on ${scopeToken} not in ${file}: ${stale.join(\", \")} — ` +\n `rerun with --prune to delete them, or remove each with \\`pipod secrets rm ${scopeToken} <NAME>\\``\n );\n}\n","/**\n * src/secrets.ts — the four places a secret can live, and who wins.\n *\n * A secret reaching a pod can come from three server scopes and one file on disk, and the\n * file outranks the server. Someone who sets an org secret and sees a different value in the\n * pod has no way to discover that a repo dotenv beat it, so every command here names the\n * scope it is acting on and the listing attributes each name to the layer that won.\n */\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { AccountClient, ServerSecretScope } from \"./account/api.js\";\nimport { PROJECT_ENV_FILE } from \"./config.js\";\nimport { parseDotenv } from \"./dotenv.js\";\nimport { PiPodError } from \"./errors.js\";\nimport { isSecretRef } from \"./secret-refs.js\";\nimport { userSecretsDir } from \"./userconfig.js\";\n\n/** Lowest precedence first — the order the launch merges them in. */\nexport const SECRET_SCOPES = [\"org\", \"user\", \"template\", \"project\"] as const;\nexport type SecretScope = (typeof SECRET_SCOPES)[number];\n\nconst SERVER_SCOPES: readonly SecretScope[] = [\"org\", \"user\", \"template\"];\n\nexport function isServerScope(scope: SecretScope): scope is ServerSecretScope & SecretScope {\n return SERVER_SCOPES.includes(scope);\n}\n\nexport interface SecretOrigin {\n scope: SecretScope;\n /** File path for `project`, scope id for the server scopes. */\n source: string;\n}\n\nexport interface SecretRow {\n name: string;\n /** The layer whose value the pod actually sees. */\n winner: SecretOrigin;\n /** Layers that set the same name and lost, lowest precedence first. */\n shadowed: SecretOrigin[];\n}\n\nexport interface SecretScopeTarget {\n scope: SecretScope;\n /** Server scope id, or the file path for `project`. */\n id: string;\n label: string;\n}\n\n/** Where the project push-time env source lives, whether or not the file exists yet. */\nexport function projectEnvPath(cwd: string): string {\n return path.resolve(cwd, PROJECT_ENV_FILE);\n}\n\nfunction readFileLayer(file: string | null): { names: string[]; refs: Set<string> } {\n if (!file || !fs.existsSync(file)) return { names: [], refs: new Set() };\n const values = parseDotenv(fs.readFileSync(file, \"utf8\")).values;\n const names = Object.keys(values);\n return { names, refs: new Set(names.filter((name) => isSecretRef(values[name]!))) };\n}\n\n/** Default file for `pipod secrets sync <scope>`: `~/.pi-pod/secrets/<scope>.env`. */\nexport function defaultSyncEnvPath(scopeToken: string, home?: string): string {\n const dir = userSecretsDir(home);\n if (!dir) throw new PiPodError(\"cannot locate ~/.pi-pod/secrets on this machine\");\n const [head, ...rest] = scopeToken.split(\"/\");\n const file =\n head === \"template\" && rest.length > 0 ? `template-${rest.join(\"-\")}.env` : `${head ?? scopeToken}.env`;\n return path.join(dir, file);\n}\n\nexport interface CollectOptions {\n cwd: string;\n home?: string | undefined;\n client: AccountClient;\n /** The selected template, whose server scope sits below the project file. */\n template?: { id: string; name: string } | null;\n}\n\n/**\n * Reads names from every layer that applies here. Values are never fetched: the server's\n * secret API is write-only by design, and printing the local ones would defeat the point.\n */\nexport async function collectSecrets(opts: CollectOptions): Promise<{\n rows: SecretRow[];\n layers: Array<{ scope: SecretScope; source: string; count: number; reachable: boolean }>;\n}> {\n const perScope = new Map<\n SecretScope,\n { source: string; names: string[]; refs?: Set<string>; reachable: boolean }\n >();\n\n const projectFile = projectEnvPath(opts.cwd);\n\n const targets: Array<[SecretScope, string, string]> = [\n [\"org\", opts.client.orgId, \"org\"],\n [\"user\", opts.client.userId, \"you\"],\n ];\n if (opts.template) targets.push([\"template\", opts.template.id, `template ${opts.template.name}`]);\n for (const [scope, id, label] of targets) {\n try {\n const res = await opts.client.listSecrets(scope as ServerSecretScope, id);\n perScope.set(scope, { source: label, names: res.secrets.map((secret) => secret.name), reachable: true });\n } catch {\n perScope.set(scope, { source: label, names: [], reachable: false });\n }\n }\n\n const project = readFileLayer(projectFile);\n perScope.set(\"project\", {\n source: projectFile,\n names: project.names,\n refs: project.refs,\n reachable: true,\n });\n\n const byName = new Map<string, SecretOrigin[]>();\n for (const scope of SECRET_SCOPES) {\n const layer = perScope.get(scope);\n if (!layer) continue;\n for (const name of layer.names) {\n const list = byName.get(name) ?? [];\n const source = layer.refs?.has(name) ? `${layer.source} (ref)` : layer.source;\n list.push({ scope, source });\n byName.set(name, list);\n }\n }\n\n const rows: SecretRow[] = [...byName.entries()]\n .map(([name, origins]) => ({\n name,\n winner: origins[origins.length - 1]!,\n shadowed: origins.slice(0, -1),\n }))\n .sort((a, b) => a.name.localeCompare(b.name));\n\n const layers = SECRET_SCOPES.filter((s) => perScope.has(s)).map((scope) => {\n const l = perScope.get(scope)!;\n return { scope, source: l.source, count: l.names.length, reachable: l.reachable };\n });\n\n return { rows, layers };\n}\n\n/**\n * Resolves a user-supplied scope token. Template scopes carry which template, because\n * \"template\" alone is not an address: `template/web-dev` or `template/<uuid>`.\n */\nexport async function resolveScopeTarget(\n token: string,\n opts: { client: AccountClient; cwd: string; home?: string | undefined },\n): Promise<SecretScopeTarget> {\n const [head, ...rest] = token.split(\"/\");\n if (head === \"machine\") {\n throw new PiPodError(\"the machine secret scope was removed\", {\n hint: \"put the value in ~/.pi-pod/secrets/user.env and `pipod secrets sync user`, or in the project .pi-pod/env\",\n });\n }\n const scope = head as SecretScope;\n if (!(SECRET_SCOPES as readonly string[]).includes(scope)) {\n throw new PiPodError(`unknown secret scope \"${token}\"`, {\n hint: `scopes, lowest precedence first: ${SECRET_SCOPES.join(\", \")} (templates are addressed as template/<name>)`,\n });\n }\n\n if (scope === \"project\") {\n const file = projectEnvPath(opts.cwd);\n return { scope, id: file, label: path.relative(opts.cwd, file) || file };\n }\n\n if (scope === \"org\") return { scope, id: opts.client.orgId, label: \"org\" };\n if (scope === \"user\") return { scope, id: opts.client.userId, label: \"you\" };\n\n const which = rest.join(\"/\");\n if (!which) {\n throw new PiPodError(\"template secrets need a template\", {\n hint: \"address it as `template/<name>` or `template/<id>`\",\n });\n }\n const { templates } = await opts.client.listTemplates();\n const match =\n templates.find((t) => t.id === which) ??\n templates.find((t) => t.name.toLowerCase() === which.toLowerCase());\n if (!match) {\n throw new PiPodError(`no template named \"${which}\" in this org`, {\n hint: \"list them with `pipod templates`\",\n });\n }\n return { scope, id: match.id, label: `template ${match.name}` };\n}\n\n/**\n * Upserts one key in a dotenv file, preserving the rest of it verbatim. These files are\n * hand-edited far more often than they are written by a tool, so comments, ordering and\n * `export ` prefixes all survive a write.\n */\nexport function upsertDotenv(file: string, name: string, value: string): \"created\" | \"updated\" {\n const existed = fs.existsSync(file);\n const text = existed ? fs.readFileSync(file, \"utf8\") : \"\";\n const lines = text.split(\"\\n\");\n const line = `${name}=${quoteIfNeeded(value)}`;\n\n let replaced = false;\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i]!.trim();\n if (trimmed === \"\" || trimmed.startsWith(\"#\")) continue;\n const body = trimmed.startsWith(\"export \") ? trimmed.slice(7).trim() : trimmed;\n const eq = body.indexOf(\"=\");\n if (eq > 0 && body.slice(0, eq).trim() === name) {\n lines[i] = trimmed.startsWith(\"export \") ? `export ${line}` : line;\n replaced = true;\n break;\n }\n }\n if (!replaced) {\n if (lines.length > 0 && lines[lines.length - 1] === \"\") lines.pop();\n lines.push(line, \"\");\n }\n\n fs.mkdirSync(path.dirname(file), { recursive: true });\n fs.writeFileSync(file, lines.join(\"\\n\"), { mode: 0o600 });\n // An existing file may predate the mode argument, which only applies on create.\n fs.chmodSync(file, 0o600);\n return replaced ? \"updated\" : \"created\";\n}\n\nexport function removeFromDotenv(file: string, name: string): boolean {\n if (!fs.existsSync(file)) return false;\n const lines = fs.readFileSync(file, \"utf8\").split(\"\\n\");\n const kept = lines.filter((raw) => {\n const trimmed = raw.trim();\n if (trimmed === \"\" || trimmed.startsWith(\"#\")) return true;\n const body = trimmed.startsWith(\"export \") ? trimmed.slice(7).trim() : trimmed;\n const eq = body.indexOf(\"=\");\n return !(eq > 0 && body.slice(0, eq).trim() === name);\n });\n if (kept.length === lines.length) return false;\n fs.writeFileSync(file, kept.join(\"\\n\"), { mode: 0o600 });\n return true;\n}\n\n/** Values are literal in this format, so anything with whitespace or quotes gets wrapped. */\nfunction quoteIfNeeded(value: string): string {\n if (value === \"\") return '\"\"';\n if (/^[A-Za-z0-9_./:@+-]+$/.test(value)) return value;\n return `\"${value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"').replace(/\\n/g, \"\\\\n\")}\"`;\n}\n","/**\n * src/commands/templates.ts — `pipod templates` (§8.5).\n *\n * Templates default to personal (user-scoped): only their owner sees and launches them.\n * `--org` at creation or `templates share` makes one org-wide, where it sits *below* each\n * member's own settings. They were previously only authorable in the app; this is the\n * same surface from the terminal, addressed by name rather than uuid.\n */\nimport * as fs from \"node:fs\";\nimport type { AccountClient, ApiTemplate, PiSettingsFilesBody } from \"../account/api.js\";\nimport { compileBundleSource, flatPiSettings, toOutgoingBundleConfig, type EnvSnapshot } from \"../account/bundle-source.js\";\nimport { requireAccountClient } from \"../account/client.js\";\nimport { findTemplate, scopeOf } from \"../account/template-ref.js\";\nimport { validateConfig } from \"../config.js\";\nimport { PiPodError } from \"../errors.js\";\nimport { parseJsonc } from \"../jsonc.js\";\nimport { info, out, warn } from \"../log.js\";\nimport { isProviderCredentialVar } from \"../providers/registry.js\";\nimport { confirm } from \"../prompt.js\";\n\nexport interface TemplatesFlags {\n home?: string | undefined;\n yes?: boolean;\n client?: AccountClient;\n}\n\nfunction requireClient(flags: TemplatesFlags): AccountClient {\n return flags.client ?? requireAccountClient({ home: flags.home });\n}\n\nexport async function runTemplates(args: string[], flags: TemplatesFlags): Promise<number> {\n const yes = flags.yes || args.includes(\"-y\") || args.includes(\"--yes\");\n const [action = \"list\", ...rest] = args.filter((a) => a !== \"-y\" && a !== \"--yes\");\n const client = requireClient(flags);\n const effective: TemplatesFlags = { ...flags, yes };\n switch (action) {\n case \"list\":\n return listCmd(client);\n case \"show\":\n return showCmd(client, rest);\n case \"create\":\n return createCmd(client, rest, effective);\n case \"edit\":\n return editCmd(client, rest);\n case \"rm\":\n case \"delete\":\n return rmCmd(client, rest, effective);\n case \"share\":\n return shareCmd(client, rest);\n default:\n throw new PiPodError(`unknown \\`pipod templates\\` action \"${action}\"`, {\n hint: \"actions: list (default), show, create, edit, share, rm\",\n });\n }\n}\n\n\nasync function listCmd(client: AccountClient): Promise<number> {\n const { templates } = await client.listTemplates();\n if (templates.length === 0) {\n info(\"this org has no templates — pods start from the built-in defaults\");\n return 0;\n }\n out(`${\"NAME\".padEnd(24)} ${\"SCOPE\".padEnd(6)} ${\"KEYS\".padEnd(5)} DESCRIPTION`);\n for (const t of templates) {\n const keys = String(Object.keys(t.config ?? {}).length);\n out(`${t.name.padEnd(24)} ${scopeOf(t).padEnd(6)} ${keys.padEnd(5)} ${t.description ?? \"\"}`);\n }\n return 0;\n}\n\nasync function showCmd(client: AccountClient, args: string[]): Promise<number> {\n const t = await findTemplate(client, args[0]);\n info(`${t.name} (${t.id})`);\n info(`scope ${scopeOf(t) === \"user\" ? \"user (only you)\" : \"org\"}`);\n if (t.description) info(`description ${t.description}`);\n if (t.createdFromPod) info(`created by pod ${t.createdFromPod}`);\n info(`updated ${t.updatedAt}`);\n out(\"\");\n out(JSON.stringify(t.config ?? {}, null, 2));\n if (t.initScript) {\n out(\"\");\n info(\"init script:\");\n out(t.initScript);\n }\n if (t.bakeScript) {\n out(\"\");\n info(\"bake script:\");\n out(t.bakeScript);\n }\n if (t.piSettings && Object.keys(t.piSettings).length > 0) {\n info(`Pi settings ${describePiSettings(flatPiSettings(t.piSettings))}`);\n }\n const secrets = await client.listSecrets(\"template\", t.id).catch(() => null);\n if (secrets && secrets.secrets.length > 0) {\n out(\"\");\n info(`template secrets: ${secrets.secrets.map((s) => s.name).join(\", \")}`);\n }\n return 0;\n}\n\ninterface TemplateOpts {\n name?: string;\n description?: string;\n config?: Record<string, unknown>;\n initScript?: string;\n bakeScript?: string;\n fromHere?: boolean;\n withSecrets?: boolean;\n org?: boolean;\n}\n\nfunction describePiSettings(settings: PiSettingsFilesBody): string {\n const names = Object.keys(settings);\n const packages = settings.settings?.[\"packages\"];\n const packageCount = Array.isArray(packages) ? packages.length : 0;\n return `${names.join(\", \") || \"empty\"}${packageCount > 0 ? ` (${packageCount} package(s))` : \"\"}`;\n}\n\nexport async function writeTemplateSnapshot(write: () => Promise<ApiTemplate>): Promise<ApiTemplate> {\n try {\n return await write();\n } catch (error) {\n if (\n error instanceof PiPodError &&\n error.status === 400 &&\n /(?:unrecognized|unknown|unexpected)[^\\n]*piSettings|piSettings[^\\n]*(?:unrecognized|unknown|unexpected)/i.test(error.message)\n ) {\n throw new PiPodError(\"the pi pod server does not support template-owned Pi settings\", {\n hint: \"deploy the matching pi pod server before pushing Pi files with `pipod push`\",\n cause: error,\n status: error.status,\n });\n }\n throw error;\n }\n}\n\n/**\n * Config comes from a file rather than flags: it is the same shape as `.pi-pod/config.json`,\n * and validating it here means a bad template is rejected before it becomes everyone's\n * starting point.\n */\nfunction parseOpts(args: string[]): { rest: string[]; opts: TemplateOpts } {\n const opts: TemplateOpts = {};\n const rest: string[] = [];\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n const next = () => {\n const v = args[++i];\n if (v === undefined) throw new PiPodError(`${arg} needs a value`);\n return v;\n };\n switch (arg) {\n case \"--name\":\n opts.name = next();\n break;\n case \"--description\":\n opts.description = next();\n break;\n case \"--config\": {\n const file = next();\n if (!fs.existsSync(file)) throw new PiPodError(`no such config file: ${file}`);\n const parsed = parseJsonc(fs.readFileSync(file, \"utf8\"), file) as Record<string, unknown>;\n const report = validateConfig(parsed);\n for (const problem of report.errors) throw new PiPodError(`${file}: ${problem}`);\n for (const problem of report.warnings) warn(`${file}: ${problem}`);\n // The bundle boundary drops every local pin, retired key, and UI/preference key.\n opts.config = toOutgoingBundleConfig(parsed);\n break;\n }\n case \"--from-here\":\n opts.fromHere = true;\n break;\n case \"--org\":\n opts.org = true;\n break;\n case \"--with-secrets\":\n opts.withSecrets = true;\n break;\n case \"--init-script\": {\n const file = next();\n if (!fs.existsSync(file)) throw new PiPodError(`no such init script: ${file}`);\n opts.initScript = fs.readFileSync(file, \"utf8\");\n break;\n }\n case \"--bake-script\": {\n const file = next();\n if (!fs.existsSync(file)) throw new PiPodError(`no such bake script: ${file}`);\n opts.bakeScript = fs.readFileSync(file, \"utf8\");\n break;\n }\n default:\n rest.push(arg);\n }\n }\n return { rest, opts };\n}\n\nasync function createCmd(client: AccountClient, args: string[], flags: TemplatesFlags): Promise<number> {\n const { rest, opts } = parseOpts(args);\n const name = opts.name ?? rest[0];\n if (!name) {\n throw new PiPodError(\"usage: pipod templates create <name> [--config <file> | --from-here] [--org] [--description <text>]\", {\n hint: \"--config takes the same shape as .pi-pod/config.json; --from-here stores only this project's authored config, scripts, and sanitized Pi files; templates are personal unless --org\",\n });\n }\n if (opts.fromHere && opts.config) {\n throw new PiPodError(\"--from-here and --config contradict each other\", {\n hint: \"--from-here compiles the project source; --config names one explicitly — drop one of the two\",\n });\n }\n requireFromHereForSecrets(opts);\n let config = opts.config ?? {};\n let initScript = opts.initScript;\n let bakeScript = opts.bakeScript;\n let env: EnvSnapshot = {};\n let piSettings: PiSettingsFilesBody | undefined;\n if (opts.fromHere) {\n // Fail before reading every source file so a name clash stays cheap and actionable.\n const { templates } = await client.listTemplates();\n const targetScope = opts.org ? \"org\" : \"user\";\n const existing = templates.find(\n (t) => t.name.toLowerCase() === name.toLowerCase() && scopeOf(t) === targetScope,\n );\n if (existing) {\n throw new PiPodError(\n targetScope === \"org\"\n ? `a template named \"${existing.name}\" already exists in this org`\n : `you already have a template named \"${existing.name}\"`,\n { hint: `refresh it from this directory instead: pipod push template ${existing.name}` },\n );\n }\n const snapshot = await snapshotFromHere(client, flags);\n config = snapshot.config;\n env = snapshot.env;\n piSettings = snapshot.piSettings;\n if (initScript === undefined) initScript = snapshot.initScript;\n if (bakeScript === undefined) bakeScript = snapshot.bakeScript;\n }\n const create = () => client.createTemplate({\n name,\n config,\n // Omitted for personal templates: the server defaults to user scope, and older\n // servers without scoping would reject the unknown key.\n ...(opts.org ? { scope: \"org\" as const } : {}),\n ...(opts.description ? { description: opts.description } : {}),\n ...(initScript ? { initScript } : {}),\n ...(bakeScript ? { bakeScript } : {}),\n // An explicit refresh is replacement, not merge: an empty project file set clears stale custody.\n ...(opts.fromHere ? { piSettings: piSettings ?? {} } : {}),\n });\n const created = opts.fromHere ? await writeTemplateSnapshot(create) : await create();\n info(`created template ${created.name} (${created.id})`);\n if (scopeOf(created) === \"user\") {\n info(`it is personal — only you see it; share it org-wide with \\`pipod templates share ${created.name}\\``);\n }\n if (opts.fromHere) {\n info(snapshotSummary(piSettings));\n await syncEnvSecrets(client, created, env, { withSecrets: opts.withSecrets ?? false, reportStale: false });\n }\n await hintMissingCredentials(client);\n return 0;\n}\n\n/**\n * Templates never carry model-provider credentials, so a fresh template can still launch\n * pods with nothing to talk to. The nudge is best-effort: never fail a written template over it.\n */\nasync function hintMissingCredentials(client: AccountClient): Promise<void> {\n let result;\n try {\n result = await client.modelCredentials();\n } catch {\n return;\n }\n if (result.credentials.some((c) => c.state === \"ready\")) return;\n info(\"you have no model-provider credential yet — `pipod credentials connect` sets them up\");\n}\n\nfunction requireFromHereForSecrets(opts: TemplateOpts): void {\n if (opts.withSecrets && !opts.fromHere) {\n throw new PiPodError(\"--with-secrets only makes sense with --from-here\", {\n hint: \"it uploads env values from the compiled project source; without --from-here there is nothing to upload\",\n });\n }\n}\n\nfunction snapshotSummary(piSettings: PiSettingsFilesBody | undefined): string {\n return (\n \"the snapshot stores this project's authored config, scripts, and sanitized Pi files verbatim \" +\n `(${describePiSettings(piSettings ?? {})})`\n );\n}\n\n/** Compile only the project-authored source layer; persistent layers are never pre-merged. */\nasync function snapshotFromHere(\n _client: AccountClient,\n flags: TemplatesFlags,\n): Promise<{\n config: Record<string, unknown>;\n env: EnvSnapshot;\n piSettings: PiSettingsFilesBody;\n initScript: string;\n bakeScript: string;\n}> {\n const source = await compileBundleSource({ source: \"project\", home: flags.home });\n for (const warning of source.warnings) warn(warning);\n return {\n config: source.config,\n env: source.env,\n piSettings: source.piFiles,\n initScript: source.initScript,\n bakeScript: source.bakeScript,\n };\n}\n\n/**\n * Uploading project env values is a new act, not a detail of compiling the source, so it\n * needs its own signal: --with-secrets, or a yes at this prompt. -y is\n * deliberately not honored here — it confirms the action the user asked for, not this one.\n */\nexport async function syncEnvSecrets(\n client: AccountClient,\n template: { id: string; name: string; scope?: \"user\" | \"org\" },\n env: EnvSnapshot,\n opts: { withSecrets: boolean; reportStale: boolean },\n): Promise<void> {\n const names = Object.keys(env).filter((n) => {\n if (isProviderCredentialVar(n)) {\n warn(`${n} is a provider credential and never travels in a template — the org key upload owns those`);\n return false;\n }\n return true;\n });\n if (names.length === 0) return;\n const labeled = names.map((n) => `${n} [${env[n]!.source}]`).join(\", \");\n const consented =\n opts.withSecrets ||\n (await confirm(\n `upload ${names.length} env value(s) as secrets on template ${template.name} ` +\n `(${labeled})? they reach ${scopeOf(template) === \"user\" ? \"every pod you launch from it\" : \"every org member's pod launched from it\"}`,\n { nonInteractiveDefault: false },\n ));\n if (!consented) {\n warn(\n `the push did not store these project env values in template custody: ${names.join(\", \")} — ` +\n `they remain local source only; use --with-secrets or \\`pipod secrets set template/${template.name} <NAME>\\` to apply them`,\n );\n return;\n }\n const uploaded: string[] = [];\n for (const name of names) {\n try {\n await client.putSecret(\"template\", template.id, name, env[name]!.value);\n uploaded.push(name);\n } catch (e) {\n const remaining = names.filter((n) => !uploaded.includes(n));\n throw new PiPodError(\n `uploaded ${uploaded.length} of ${names.length} template secrets; ${remaining.join(\", \")} did not make it: ` +\n (e instanceof Error ? e.message : String(e)),\n { hint: `the template itself is fine — finish with pipod push template ${template.name} --with-secrets` },\n );\n }\n }\n info(\n `uploaded ${uploaded.length} template secret(s): ${uploaded.join(\", \")} — ` +\n `values are encrypted server-side; the names show${scopeOf(template) === \"user\" ? \"\" : \" org-wide\"} in templates show`,\n );\n if (opts.reportStale) {\n const listed = await client.listSecrets(\"template\", template.id).catch(() => null);\n const stale = listed ? listed.secrets.map((s) => s.name).filter((n) => !(n in env)) : [];\n if (stale.length > 0) {\n warn(\n `template secrets no longer in your local env files: ${stale.join(\", \")} — ` +\n `remove each with \\`pipod secrets rm template/${template.name} <NAME>\\` if nothing needs them`,\n );\n }\n }\n}\n\nasync function editCmd(client: AccountClient, args: string[]): Promise<number> {\n const { rest, opts } = parseOpts(args);\n // Whole-bundle replacement from the project source is `pipod push`, not an edit.\n if (opts.fromHere || opts.withSecrets) {\n const flag = opts.fromHere ? \"--from-here\" : \"--with-secrets\";\n throw new PiPodError(`${flag} is not an edit option; run \\`pipod push template <name>\\``, {\n hint: \"push replaces the whole bundle with this project's source, after a diff preview\",\n });\n }\n if (opts.org) {\n throw new PiPodError(\"--org is not an edit option; make a template org-wide with `pipod templates share <name>`\", {\n hint: \"templates are personal unless created with --org or shared\",\n });\n }\n const t = await findTemplate(client, rest[0]);\n if (\n opts.name === undefined &&\n opts.description === undefined &&\n !opts.config &&\n opts.initScript === undefined &&\n opts.bakeScript === undefined\n ) {\n throw new PiPodError(\"nothing to change\", {\n hint: \"pass --name, --description, --config <file>, --init-script <file> or --bake-script <file>\",\n });\n }\n const updated = await client.updateTemplate(t.id, {\n // Compare-and-swap against the version just read, like user/org settings writes;\n // servers without template versions get the plain replace they always did.\n ...(t.version !== undefined ? { expectedVersion: t.version } : {}),\n ...(opts.name ? { name: opts.name } : {}),\n ...(opts.description !== undefined ? { description: opts.description } : {}),\n ...(opts.config ? { config: opts.config } : {}),\n ...(opts.initScript !== undefined ? { initScript: opts.initScript } : {}),\n ...(opts.bakeScript !== undefined ? { bakeScript: opts.bakeScript } : {}),\n });\n info(`updated template ${updated.name}`);\n await hintMissingCredentials(client);\n return 0;\n}\n\n/** Hand a personal template to the org. One-way: org templates cannot go private again. */\nasync function shareCmd(client: AccountClient, args: string[]): Promise<number> {\n const t = await findTemplate(client, args[0]);\n if (scopeOf(t) === \"org\") {\n info(`${t.name} is already org-wide`);\n return 0;\n }\n const updated = await client.updateTemplate(t.id, { scope: \"org\" });\n info(`shared ${updated.name} with the org — every member can now see and launch from it`);\n return 0;\n}\n\nasync function rmCmd(client: AccountClient, args: string[], flags: TemplatesFlags): Promise<number> {\n const t = await findTemplate(client, args[0]);\n const ok = await confirm(\n scopeOf(t) === \"user\" ? `delete your template ${t.name}?` : `delete template ${t.name} for the whole org?`,\n {\n nonInteractiveDefault: false,\n assumeYes: flags.yes === true,\n },\n );\n if (!ok) {\n info(\"left it alone\");\n return 1;\n }\n await client.deleteTemplate(t.id);\n info(`deleted template ${t.name}`);\n return 0;\n}\n","/**\n * src/commands/layers.ts — the `push` / `pull` / `diff` grammar shared by the three verbs.\n *\n * Every persistent server bundle has one local directory as its source of truth:\n * template [<name>] → this project (.pi-pod/, .pi/)\n * user → ~/.pi-pod/config.json + ~/.pi/agent/\n * org → ~/.pi-pod/org/ (or --dir <path>)\n * The verbs move a whole bundle between the two, git-style, after a diff preview.\n */\nimport { findConfigPath } from \"../config.js\";\nimport { PiPodError } from \"../errors.js\";\nimport { info, out, warn } from \"../log.js\";\nimport type { AccountClient, ApiTemplate } from \"../account/api.js\";\nimport {\n compileBundleSource,\n diffBundle,\n orgSourceDir,\n settingsBundle,\n templateBundle,\n type BundleSourceKind,\n type CompiledBundleSource,\n type ServerBundle,\n} from \"../account/bundle-source.js\";\nimport { findTemplate } from \"../account/template-ref.js\";\nimport { displayPath } from \"../userconfig.js\";\n\nexport type Layer = { kind: \"template\"; name?: string } | { kind: \"user\" } | { kind: \"org\" };\n\nexport interface LayerFlags {\n client: AccountClient;\n home?: string | undefined;\n cwd?: string | undefined;\n yes?: boolean | undefined;\n}\n\nexport interface ParsedLayerArgs {\n layer: Layer;\n dir?: string;\n yes: boolean;\n withSecrets: boolean;\n}\n\nconst LAYER_USAGE = \"template [<name>], user, or org\";\n\n/** Parse `[template [<name>] | user | org] [--dir <path>] [--with-secrets] [-y]`. */\nexport function parseLayerArgs(\n verb: \"push\" | \"pull\" | \"diff\",\n args: string[],\n opts: { cwd: string; home?: string | undefined },\n): ParsedLayerArgs {\n const positionals: string[] = [];\n let dir: string | undefined;\n let yes = false;\n let withSecrets = false;\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n if (arg === \"--dir\") {\n dir = args[++i];\n if (!dir) throw new PiPodError(\"--dir needs a value\");\n } else if (arg === \"--with-secrets\" && verb === \"push\") withSecrets = true;\n else if ((arg === \"--yes\" || arg === \"-y\") && verb !== \"diff\") yes = true;\n else if (arg.startsWith(\"-\")) throw new PiPodError(`unexpected \\`pipod ${verb}\\` option \"${arg}\"`);\n else positionals.push(arg);\n }\n const [first, second, ...extra] = positionals;\n let layer: Layer;\n if (first === undefined) {\n if (findConfigPath(opts.cwd, { home: opts.home }) === null) {\n throw new PiPodError(`pipod ${verb} needs a layer: ${LAYER_USAGE}`, {\n hint: \"inside a project the default is its pinned template; here there is no project\",\n });\n }\n layer = { kind: \"template\" };\n } else if (first === \"template\") {\n layer = second === undefined ? { kind: \"template\" } : { kind: \"template\", name: second };\n } else if (first === \"user\" || first === \"org\") {\n layer = { kind: first };\n if (second !== undefined) extra.unshift(second);\n } else {\n throw new PiPodError(`unknown layer \"${first}\"`, { hint: `layers: ${LAYER_USAGE}` });\n }\n if (extra.length > 0) throw new PiPodError(`unexpected \\`pipod ${verb}\\` argument(s): ${extra.join(\" \")}`);\n if (dir !== undefined && layer.kind !== \"org\") throw new PiPodError(\"--dir only applies to the org layer\");\n return { layer, ...(dir !== undefined ? { dir } : {}), yes, withSecrets };\n}\n\nexport function sourceKindOf(layer: Layer): BundleSourceKind {\n return layer.kind === \"template\" ? \"project\" : layer.kind === \"user\" ? \"user-dir\" : \"org-dir\";\n}\n\n/** The server side of a layer, read fresh so writes can compare-and-swap against it. */\nexport interface RemoteLayer {\n bundle: ServerBundle;\n version: number | undefined;\n secretNames: string[];\n /** `template <name> v3`, `user settings v2`, `org settings v0` */\n label: string;\n template?: ApiTemplate;\n scope: \"template\" | \"user\" | \"org\";\n scopeId: string;\n}\n\nexport async function fetchRemoteLayer(\n client: AccountClient,\n layer: Layer,\n source: Pick<CompiledBundleSource, \"templateRef\">,\n): Promise<RemoteLayer> {\n if (layer.kind === \"template\") {\n const ref = layer.name ?? source.templateRef;\n if (!ref) {\n throw new PiPodError(\"this project does not pin a template\", {\n hint: \"name one: `pipod push template <name>`; a first launch offers to bootstrap and pin one\",\n });\n }\n const template = await findTemplate(client, ref);\n const listed = await client.listSecrets(\"template\", template.id).catch(() => ({ secrets: [] }));\n const version = template.version;\n return {\n bundle: templateBundle(template),\n version,\n secretNames: listed.secrets.map((entry) => entry.name),\n label: `template ${template.name}${version !== undefined ? ` v${version}` : \"\"}`,\n template,\n scope: \"template\",\n scopeId: template.id,\n };\n }\n const current = layer.kind === \"user\" ? await client.getUserSettings() : await client.getOrgSettings();\n const scopeId = layer.kind === \"user\" ? client.userId : client.orgId;\n const listed = await client.listSecrets(layer.kind, scopeId).catch(() => ({ secrets: [] }));\n return {\n bundle: settingsBundle(current),\n version: current.version,\n secretNames: listed.secrets.map((entry) => entry.name),\n label: `${layer.kind} settings v${current.version}`,\n scope: layer.kind,\n scopeId,\n };\n}\n\n/** How the local side of a layer is named in diff headings and summaries. */\nexport function localLabel(layer: Layer, flags: { home?: string | undefined; dir?: string | undefined }): string {\n if (layer.kind === \"template\") return \"project\";\n if (layer.kind === \"user\") return \"~/.pi-pod + ~/.pi/agent\";\n return displayPath(orgSourceDir({ dir: flags.dir, home: flags.home }), flags.home);\n}\n\nexport function printDiff(heading: string, lines: string[]): void {\n if (lines.length === 0) return;\n info(`${heading}:`);\n for (const line of lines) out(` ${line}`);\n}\n\n/** `pipod diff [layer]`: report only; exit 1 on drift so scripts can gate on it. */\nexport async function runDiff(args: string[], flags: LayerFlags): Promise<number> {\n const cwd = flags.cwd ?? process.cwd();\n const parsed = parseLayerArgs(\"diff\", args, { cwd, home: flags.home });\n const source = await compileBundleSource({\n source: sourceKindOf(parsed.layer),\n cwd,\n home: flags.home,\n includeEnv: \"names\",\n dir: parsed.dir,\n });\n for (const warning of source.warnings) warn(warning);\n const remote = await fetchRemoteLayer(flags.client, parsed.layer, source);\n const diff = diffBundle(source, remote.bundle, remote.secretNames);\n printDiff(`${localLabel(parsed.layer, { home: flags.home, dir: parsed.dir })} vs ${remote.label}`, diff.lines);\n if (!diff.changed) info(`${remote.label} is up to date`);\n return diff.changed ? 1 : 0;\n}\n","import * as fs from \"node:fs\";\nimport { info, warn } from \"../log.js\";\nimport { confirm } from \"../prompt.js\";\nimport {\n compileBundleSource,\n diffBundle,\n orgSourceDir,\n writeBundleSource,\n type CompiledBundleSource,\n} from \"../account/bundle-source.js\";\nimport { displayPath } from \"../userconfig.js\";\nimport {\n fetchRemoteLayer,\n localLabel,\n parseLayerArgs,\n printDiff,\n sourceKindOf,\n type LayerFlags,\n} from \"./layers.js\";\n\nexport type PullFlags = LayerFlags;\n\n/** `pipod pull [layer]`: write the server bundle into the layer's local files. */\nexport async function runPull(args: string[], flags: PullFlags): Promise<number> {\n const cwd = flags.cwd ?? process.cwd();\n const parsed = parseLayerArgs(\"pull\", args, { cwd, home: flags.home });\n const kind = sourceKindOf(parsed.layer);\n let source: CompiledBundleSource;\n let firstPull = false;\n if (kind === \"org-dir\" && !fs.existsSync(orgSourceDir({ dir: parsed.dir, home: flags.home }))) {\n // A first `pull org` has nothing local yet; diff against an empty source and create the dir.\n firstPull = true;\n source = {\n kind, config: {}, initScript: \"\", bakeScript: \"\", piFiles: {}, env: {}, warnings: [],\n name: \"org settings\", templateRef: null, projectRoot: null,\n root: orgSourceDir({ dir: parsed.dir, home: flags.home }), configPath: \"\",\n };\n } else {\n source = await compileBundleSource({ source: kind, cwd, home: flags.home, includeEnv: false, dir: parsed.dir });\n }\n for (const warning of source.warnings) warn(warning);\n const remote = await fetchRemoteLayer(flags.client, parsed.layer, source);\n const local = localLabel(parsed.layer, { home: flags.home, dir: parsed.dir });\n // The diff reads local → remote; pull applies the reverse, so swap the sides for the preview.\n const diff = diffBundle(\n { config: remote.bundle.config, initScript: remote.bundle.initScript, bakeScript: remote.bundle.bakeScript, piFiles: remote.bundle.piFiles, env: {} },\n source,\n );\n printDiff(`${remote.label} → ${local}`, diff.lines);\n if (remote.secretNames.length > 0) {\n info(`${remote.scope} secrets stay on the server (values are write-only): ${remote.secretNames.join(\", \")}`);\n }\n if (!diff.changed && !firstPull) {\n info(`${local} is already up to date with ${remote.label}`);\n return 0;\n }\n const assumeYes = parsed.yes || flags.yes === true;\n if (!(await confirm(\"apply these local changes?\", { nonInteractiveDefault: false, assumeYes }))) return 1;\n const result = writeBundleSource({ kind, bundle: remote.bundle, cwd, home: flags.home, dir: parsed.dir });\n for (const warning of result.warnings) warn(warning);\n const root = displayPath(result.root, flags.home);\n info(`pulled ${remote.label} into ${root}: ${result.written.length} written, ${result.removed.length} removed`);\n for (const file of result.written) info(` wrote ${file}`);\n for (const file of result.removed) info(` removed ${file}`);\n return 0;\n}\n","import { PiPodError } from \"../errors.js\";\nimport { info, warn } from \"../log.js\";\nimport { isProviderCredentialVar } from \"../providers/registry.js\";\nimport { confirm } from \"../prompt.js\";\nimport type { AccountClient } from \"../account/api.js\";\nimport { compileBundleSource, diffBundle, type EnvSnapshot } from \"../account/bundle-source.js\";\nimport { syncEnvSecrets, writeTemplateSnapshot } from \"./templates.js\";\nimport {\n fetchRemoteLayer,\n localLabel,\n parseLayerArgs,\n printDiff,\n sourceKindOf,\n type LayerFlags,\n} from \"./layers.js\";\n\nexport type PushFlags = LayerFlags;\n\n/** `pipod push [layer]`: replace a server bundle with its local source, whole. */\nexport async function runPush(args: string[], flags: PushFlags): Promise<number> {\n const cwd = flags.cwd ?? process.cwd();\n const parsed = parseLayerArgs(\"push\", args, { cwd, home: flags.home });\n const source = await compileBundleSource({ source: sourceKindOf(parsed.layer), cwd, home: flags.home, dir: parsed.dir });\n for (const warning of source.warnings) warn(warning);\n const remote = await fetchRemoteLayer(flags.client, parsed.layer, source);\n const local = localLabel(parsed.layer, { home: flags.home, dir: parsed.dir });\n const diff = diffBundle(source, remote.bundle, remote.secretNames);\n printDiff(`${local} → ${remote.label}`, diff.lines);\n if (!diff.changed && Object.keys(source.env).length === 0) {\n info(`${remote.label} is already up to date`);\n return 0;\n }\n const assumeYes = parsed.yes || flags.yes === true;\n if (!(await confirm(\"apply this bundle replacement?\", { nonInteractiveDefault: false, assumeYes }))) return 1;\n\n if (remote.scope === \"template\") {\n const template = remote.template!;\n const updated = await writeTemplateSnapshot(() => flags.client.updateTemplate(template.id, {\n // The diff above was computed against this version; refuse to clobber a newer one.\n ...(template.version !== undefined ? { expectedVersion: template.version } : {}),\n config: source.config,\n initScript: source.initScript,\n bakeScript: source.bakeScript,\n piSettings: source.piFiles,\n }));\n info(`pushed ${local} to template ${updated.name}`);\n await syncEnvSecrets(flags.client, updated, source.env, { withSecrets: parsed.withSecrets, reportStale: true });\n return 0;\n }\n\n if (remote.version === undefined) throw new PiPodError(`${remote.label} has no version to compare-and-swap against`);\n const body = {\n config: source.config,\n version: remote.version,\n initScript: source.initScript,\n bakeScript: source.bakeScript,\n piFiles: source.piFiles,\n };\n const written = remote.scope === \"user\"\n ? await flags.client.putUserSettings(body)\n : await flags.client.putOrgSettings(body);\n info(`pushed ${local} to ${remote.scope} settings v${written.version}`);\n await syncSettingsSecrets(flags.client, remote.scope, remote.scopeId, source.env, {\n withSecrets: parsed.withSecrets,\n reportStale: true,\n });\n return 0;\n}\n\nasync function syncSettingsSecrets(\n client: AccountClient,\n scope: \"user\" | \"org\",\n scopeId: string,\n env: EnvSnapshot,\n opts: { withSecrets: boolean; reportStale: boolean },\n): Promise<void> {\n const names = Object.keys(env).filter((name) => {\n if (!isProviderCredentialVar(name)) return true;\n warn(`${name} is a provider credential and never travels in a settings bundle`);\n return false;\n });\n if (names.length === 0) return;\n const consented = opts.withSecrets || await confirm(\n `upload ${names.length} env value(s) as ${scope} secrets (${names.join(\", \")})?`,\n { nonInteractiveDefault: false },\n );\n if (!consented) {\n warn(`did not upload secret values: ${names.join(\", \")}`);\n return;\n }\n for (const name of names) await client.putSecret(scope, scopeId, name, env[name]!.value);\n info(`uploaded ${names.length} ${scope} secret(s): ${names.join(\", \")}`);\n if (opts.reportStale) {\n const listed = await client.listSecrets(scope, scopeId).catch(() => null);\n const stale = listed?.secrets.map((entry) => entry.name).filter((name) => !(name in env)) ?? [];\n if (stale.length > 0) warn(`${scope} secrets no longer in this source: ${stale.join(\", \")}`);\n }\n}\n","import * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { spawnSync } from \"node:child_process\";\nimport type { AccountClient, ApiSettingsBundle, PutSettingsBundleBody } from \"../account/api.js\";\nimport { nonBundleKeysFound, validateConfig } from \"../config.js\";\nimport { PiPodError } from \"../errors.js\";\nimport { parseJsonc } from \"../jsonc.js\";\nimport { info, out, warn } from \"../log.js\";\n\nexport interface SettingsFlags {\n client: AccountClient;\n editor?: string;\n}\n\ntype SettingsScope = \"user\" | \"org\";\n\nconst USAGE = \"usage: pipod settings <user|org> [show | edit | set <key> <value> | unset <key>]\";\n\nfunction readBundle(client: AccountClient, scope: SettingsScope): Promise<ApiSettingsBundle> {\n return scope === \"user\" ? client.getUserSettings() : client.getOrgSettings();\n}\n\n/** Config-only writes omit scripts and Pi files so the server leaves them untouched. */\nfunction writeBundle(client: AccountClient, scope: SettingsScope, body: PutSettingsBundleBody): Promise<{ version: number }> {\n return scope === \"user\" ? client.putUserSettings(body) : client.putOrgSettings(body);\n}\n\n/** The bundle-write contract rejects these on the server (400) — fail here with the fix. */\nfunction assertBundleConfigSendable(config: Record<string, unknown>): void {\n const dropped = nonBundleKeysFound(config);\n if (dropped.length > 0) {\n throw new PiPodError(`not sent: the server bundle no longer accepts ${dropped.join(\", \")}`, {\n hint: \"local-only keys stay in local files (`template`, `secretResolver`, `pi.chords`); pass --reuse at launch; retired keys must be deleted\",\n });\n }\n}\n\n/** Validate an edited bundle config locally before it touches the network. */\nfunction assertBundleConfigValid(config: Record<string, unknown>, scope: SettingsScope): void {\n const report = validateConfig(config);\n for (const warning of report.warnings) warn(`${scope} settings: ${warning}`);\n if (report.errors.length > 0) {\n throw new PiPodError(`invalid ${scope} settings config: ${report.errors.join(\"; \")}`, {\n hint: \"fix the config or edit it back — nothing was sent\",\n });\n }\n}\n\nexport async function runSettings(args: string[], flags: SettingsFlags): Promise<number> {\n const [scope = \"user\", action = \"show\", ...rest] = args;\n if (scope !== \"user\" && scope !== \"org\") {\n throw new PiPodError(`unknown settings scope \"${scope}\"`, {\n hint: `${USAGE}; templates are managed with \\`pipod templates\\``,\n });\n }\n if (action === \"show\") {\n if (rest.length > 0) throw new PiPodError(`usage: pipod settings ${scope}`);\n out(JSON.stringify(await readBundle(flags.client, scope), null, 2));\n return 0;\n }\n if (action === \"edit\") return editSettings(scope, flags);\n if (action === \"set\") return setSetting(scope, rest, flags.client);\n if (action === \"unset\") return unsetSetting(scope, rest, flags.client);\n throw new PiPodError(`unknown settings action \"${action}\"`, { hint: \"actions: show, edit, set, unset\" });\n}\n\nasync function editSettings(scope: SettingsScope, flags: SettingsFlags): Promise<number> {\n const current = await readBundle(flags.client, scope);\n const directory = fs.mkdtempSync(path.join(os.tmpdir(), \"pi-pod-settings-\"));\n const file = path.join(directory, \"config.json\");\n try {\n fs.writeFileSync(file, `${JSON.stringify(current.config, null, 2)}\\n`, { mode: 0o600 });\n const editor = flags.editor ?? process.env[\"VISUAL\"] ?? process.env[\"EDITOR\"];\n if (!editor) throw new PiPodError(\"$EDITOR is not set\");\n const edited = spawnSync(\"/bin/sh\", [\"-c\", 'exec $EDITOR \"$1\"', \"pi-pod-settings\", file], {\n stdio: \"inherit\",\n env: { ...process.env, EDITOR: editor },\n });\n if (edited.error) throw new PiPodError(`could not run editor: ${edited.error.message}`);\n if (edited.status !== 0) throw new PiPodError(`editor exited with status ${edited.status ?? \"unknown\"}`);\n const config = readObject(file);\n assertBundleConfigSendable(config);\n assertBundleConfigValid(config, scope);\n const result = await writeBundle(flags.client, scope, { config, version: current.version });\n info(`updated ${scope} settings v${result.version}`);\n return 0;\n } finally {\n fs.rmSync(directory, { recursive: true, force: true });\n }\n}\n\nasync function setSetting(scope: SettingsScope, args: string[], client: AccountClient): Promise<number> {\n const [dotPath, rawValue, ...extra] = args;\n if (!dotPath || rawValue === undefined || extra.length > 0) {\n throw new PiPodError(`usage: pipod settings ${scope} set <key> <value>`);\n }\n // JSON when it parses (2, true, [\"a\"]), otherwise the text itself: `set pi.model a/b`.\n let value: unknown;\n try {\n value = JSON.parse(rawValue);\n } catch {\n value = rawValue;\n }\n const version = await updateConfig(scope, client, (config) => setDotPath(config, dotPath, value));\n info(`set ${scope} setting ${dotPath} (v${version})`);\n return 0;\n}\n\n/** Remove one key, so the layers below decide it again. */\nasync function unsetSetting(scope: SettingsScope, args: string[], client: AccountClient): Promise<number> {\n const [dotPath, ...extra] = args;\n if (!dotPath || extra.length > 0) throw new PiPodError(`usage: pipod settings ${scope} unset <key>`);\n const version = await updateConfig(scope, client, (config) => unsetDotPath(config, dotPath));\n info(`unset ${scope} setting ${dotPath} (v${version})`);\n return 0;\n}\n\n/** Read the config, change it, check it, and write it back against the version read. */\nasync function updateConfig(\n scope: SettingsScope,\n client: AccountClient,\n change: (config: Record<string, unknown>) => void,\n): Promise<number> {\n const current = await readBundle(client, scope);\n const config = structuredClone(current.config);\n change(config);\n assertBundleConfigSendable(config);\n assertBundleConfigValid(config, scope);\n return (await writeBundle(client, scope, { config, version: current.version })).version;\n}\n\n/** Delete a dotted key, and any object it leaves empty. Absent already is fine. */\nfunction unsetDotPath(target: Record<string, unknown>, dotPath: string): void {\n const [head, ...rest] = dotPath.split(\".\");\n const child = target[head!];\n if (rest.length === 0) {\n delete target[head!];\n } else if (child !== null && typeof child === \"object\" && !Array.isArray(child)) {\n unsetDotPath(child as Record<string, unknown>, rest.join(\".\"));\n if (Object.keys(child).length === 0) delete target[head!];\n }\n}\n\nfunction readObject(file: string): Record<string, unknown> {\n const value = parseJsonc(fs.readFileSync(file, \"utf8\"), file);\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) throw new PiPodError(`${file} must contain a JSON object`);\n return value as Record<string, unknown>;\n}\n\nexport function setDotPath(target: Record<string, unknown>, dotPath: string, value: unknown): void {\n const parts = dotPath.split(\".\");\n if (parts.some((part) => !part || [\"__proto__\", \"prototype\", \"constructor\"].includes(part))) {\n throw new PiPodError(`invalid settings key path: ${dotPath}`);\n }\n let cursor = target;\n for (const part of parts.slice(0, -1)) {\n const existing = cursor[part];\n if (existing === undefined) cursor[part] = {};\n else if (existing === null || typeof existing !== \"object\" || Array.isArray(existing)) {\n throw new PiPodError(`cannot set ${dotPath}: ${part} is not an object`);\n }\n cursor = cursor[part] as Record<string, unknown>;\n }\n cursor[parts.at(-1)!] = value;\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { CONFIG_DIR } from \"./config.js\";\nimport { color, info, plain, warn } from \"./log.js\";\n\nexport interface InitOptions {\n projectRoot: string;\n force: boolean;\n}\n\nexport function configTemplate(): string {\n return `{\n // .pi-pod/config.json — optional server-side launch overrides for this project.\n //\n // The server merges organization defaults, an optional selected template, then this\n // project source before push/bootstrap stores it in a template. Uncomment only settings this project\n // must choose for everyone instead of inheriting the org/template default.\n\n // \"resources\": { \"cpu\": 4, \"memoryGB\": 8, \"diskGB\": 10 },\n // \"initTimeoutSeconds\": 1200,\n // \"pi\": { \"model\": \"openai-codex/gpt-5.6-sol\", \"thinking\": \"high\" },\n // \"template\": \"web-dev\"\n //\n // Project file paths are conventional, not configured: secrets in .pi-pod/env,\n // setup in .pi-pod/init.sh, image baking in .pi-pod/bake.sh.\n}\n`;\n}\n\nexport const ENV_EXAMPLE_TEMPLATE = `# .pi-pod/env.example — committed examples of secrets this project may need.\n# Uncomment only the names this project requires. An explicit KEY= is a deliberate blank.\n# ANTHROPIC_API_KEY=\n# GH_TOKEN=\n`;\n\nexport const ENV_TEMPLATE = `# .pi-pod/env — highest-precedence project secrets. Never commit this file.\n# Values may be op://vault/item/field references, resolved at launch. Uncomment only keys\n# this project supplies; an explicit KEY= deliberately overrides lower scopes with a blank.\n# ANTHROPIC_API_KEY=\n# GH_TOKEN=\n`;\n\nexport const INIT_SCRIPT_TEMPLATE = `#!/usr/bin/env bash\n# .pi-pod/init.sh — runs after organization and selected-template init, before pi starts.\n# The workspace starts empty. Populate it here; keep this idempotent and non-interactive.\nset -euo pipefail\n\n# Example:\n# git clone https://github.com/example/project.git .\n# npm ci\n\necho \"init complete\"\n`;\n\nexport interface InitResult {\n created: string[];\n skipped: string[];\n gitignoreUpdated: boolean;\n envCreated: boolean;\n}\n\nexport function scaffold(opts: InitOptions): InitResult {\n const dir = path.join(opts.projectRoot, CONFIG_DIR);\n fs.mkdirSync(dir, { recursive: true });\n const files: Array<{ name: string; contents: string; mode?: number }> = [\n { name: \"config.json\", contents: configTemplate() },\n { name: \"env.example\", contents: ENV_EXAMPLE_TEMPLATE },\n { name: \"init.sh\", contents: INIT_SCRIPT_TEMPLATE, mode: 0o755 },\n ];\n const created: string[] = [];\n const skipped: string[] = [];\n for (const file of files) {\n const target = path.join(dir, file.name);\n if (fs.existsSync(target) && !opts.force) {\n skipped.push(path.join(CONFIG_DIR, file.name));\n continue;\n }\n fs.writeFileSync(target, file.contents, file.mode ? { mode: file.mode } : undefined);\n if (file.mode) fs.chmodSync(target, file.mode);\n created.push(path.join(CONFIG_DIR, file.name));\n }\n\n const gitignoreUpdated = ensureGitignoreEntry(opts.projectRoot, `${CONFIG_DIR}/env`);\n const envPath = path.join(dir, \"env\");\n const envCreated = !fs.existsSync(envPath);\n if (envCreated) {\n fs.writeFileSync(envPath, ENV_TEMPLATE, { mode: 0o600 });\n fs.chmodSync(envPath, 0o600);\n created.push(path.join(CONFIG_DIR, \"env\"));\n }\n return { created, skipped, gitignoreUpdated, envCreated };\n}\n\nexport function ensureGitignoreEntry(projectRoot: string, entry: string): boolean {\n const gitignorePath = path.join(projectRoot, \".gitignore\");\n const existing = fs.existsSync(gitignorePath) ? fs.readFileSync(gitignorePath, \"utf8\") : \"\";\n const alreadyPresent = existing\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .some((line) => line === entry || line === `/${entry}`);\n if (alreadyPresent) return false;\n const prefix = existing === \"\" || existing.endsWith(\"\\n\") ? \"\" : \"\\n\";\n fs.appendFileSync(gitignorePath, `${prefix}\\n# pi pod secrets — never commit\\n${entry}\\n`);\n return true;\n}\n\nexport function printInitResult(result: InitResult, projectRoot: string): void {\n for (const file of result.created) info(`created ${color.bold(file)}`);\n for (const file of result.skipped) warn(`${file} already exists — left untouched (use --force to overwrite)`);\n if (!result.envCreated) warn(`${CONFIG_DIR}/env already exists — left untouched (your keys are safe)`);\n if (result.gitignoreUpdated) info(`added ${color.bold(`${CONFIG_DIR}/env`)} to .gitignore`);\n\n const steps = [\n [`edit ${CONFIG_DIR}/config.json and init.sh`, \"what this project's pods get\"],\n [`edit ${CONFIG_DIR}/env`, \"this project's own keys\"],\n [\"pipod\", `launch a pod for ${path.basename(projectRoot)}; the first launch offers to keep these in a template`],\n ].map(([command, why]) => `${command!.padEnd(40)} ${color.dim(`# ${why}`)}`);\n plain(\"\");\n plain(\"Next steps:\");\n steps.forEach((step, index) => plain(` ${index + 1}. ${step}`));\n plain(\"\");\n}\n","/**\n * src/update.ts — `pipod update`.\n *\n * pi pod can be installed two ways, and they upgrade by completely different means: a git\n * checkout (including the `npm link` case, where the global command is a symlink into a\n * working tree) is upgraded by pulling and rebuilding, while a registry install is upgraded\n * by npm. Asking the user to remember which one they did — and, for a checkout, to remember\n * that `dist/` is a build artifact so a pull alone changes nothing — is the failure this\n * command exists to remove.\n *\n * It is deliberately conservative about the checkout case: that directory is the user's own\n * repository, not private launcher state, so this refuses anything that could disturb work\n * in it rather than trying to be clever.\n */\nimport { spawnSync } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { PiPodError } from \"./errors.js\";\nimport { packageRoot } from \"./image.js\";\nimport { color, info, out, plain, warn } from \"./log.js\";\n\nexport type Install =\n /** A working tree: `npm link`, or a clone run in place. */\n | { kind: \"git\"; root: string }\n /** Unpacked under node_modules by a package manager. */\n | { kind: \"npm\"; root: string; name: string }\n | { kind: \"unknown\"; root: string };\n\ninterface Run {\n ok: boolean;\n out: string;\n}\n\nfunction run(cmd: string, args: string[], cwd: string): Run {\n const r = spawnSync(cmd, args, { cwd, encoding: \"utf8\" });\n return { ok: r.status === 0, out: `${r.stdout ?? \"\"}${r.stderr ?? \"\"}`.trim() };\n}\n\n/** Streams to the terminal — used for the slow steps, where silence looks like a hang. */\nfunction runVisible(cmd: string, args: string[], cwd: string): boolean {\n return spawnSync(cmd, args, { cwd, stdio: \"inherit\" }).status === 0;\n}\n\nexport function detectInstall(root: string = packageRoot()): Install {\n // A submodule's .git is a file, so existence is the test, not isDirectory().\n if (fs.existsSync(path.join(root, \".git\"))) return { kind: \"git\", root };\n // The open-source repository keeps the CLI in its cli/ directory: a working tree that\n // contains this package is a checkout too.\n if (!root.split(path.sep).includes(\"node_modules\") && run(\"git\", [\"rev-parse\", \"--is-inside-work-tree\"], root).out === \"true\") {\n return { kind: \"git\", root };\n }\n\n if (root.split(path.sep).includes(\"node_modules\")) {\n try {\n const pkg = JSON.parse(fs.readFileSync(path.join(root, \"package.json\"), \"utf8\")) as {\n name?: string;\n };\n if (pkg.name) return { kind: \"npm\", root, name: pkg.name };\n } catch {\n // fall through\n }\n }\n return { kind: \"unknown\", root };\n}\n\nfunction versionAt(root: string): string {\n try {\n const pkg = JSON.parse(fs.readFileSync(path.join(root, \"package.json\"), \"utf8\")) as {\n version?: string;\n };\n return pkg.version ?? \"0.0.0\";\n } catch {\n return \"0.0.0\";\n }\n}\n\nexport interface UpdateOptions {\n /** `--dry-run`: report what an update would do, change nothing. */\n dryRun: boolean;\n /** Test seam: which install to act on, instead of the running launcher's own. */\n root?: string;\n}\n\nexport async function runUpdate(opts: UpdateOptions): Promise<void> {\n const install = detectInstall(opts.root ?? packageRoot());\n\n switch (install.kind) {\n case \"git\":\n return updateCheckout(install.root, opts);\n case \"npm\":\n return updateFromRegistry(install.root, install.name, opts);\n default:\n throw new PiPodError(`cannot tell how pi pod was installed (${install.root})`, {\n hint: \"reinstall from a git checkout (npm link) or from the registry, then retry\",\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// git checkout\n// ---------------------------------------------------------------------------\n\nasync function updateCheckout(root: string, opts: UpdateOptions): Promise<void> {\n const before = versionAt(root);\n info(`${color.bold(before)} from a git checkout at ${root}`);\n\n const branch = run(\"git\", [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"], root);\n if (!branch.ok) throw new PiPodError(`not a usable git checkout: ${branch.out}`);\n const head = branch.out;\n\n // The upstream of the current branch, not a guessed origin/main: someone tracking a fork\n // or a release branch must not be silently pulled onto something else.\n const upstream = run(\"git\", [\"rev-parse\", \"--abbrev-ref\", \"--symbolic-full-name\", \"@{upstream}\"], root);\n if (!upstream.ok) {\n throw new PiPodError(`branch \"${head}\" has no upstream to update from`, {\n hint: `set one with: git -C ${root} branch --set-upstream-to origin/${head}`,\n });\n }\n\n if (!run(\"git\", [\"fetch\", \"--quiet\", \"--prune\"], root).ok) {\n // Offline is a normal state, and it is not a reason to touch anything.\n throw new PiPodError(\"could not reach the git remote\", {\n hint: \"check your network; nothing has been changed\",\n });\n }\n\n const local = run(\"git\", [\"rev-parse\", \"HEAD\"], root).out;\n const remote = run(\"git\", [\"rev-parse\", upstream.out], root).out;\n\n if (local === remote) {\n // Still worth a rebuild check: dist/ is generated and can lag the source it came from.\n if (distIsStale(root)) {\n info(`already at the latest commit, but ${color.bold(\"dist/\")} is older than src — rebuilding`);\n if (opts.dryRun) return void info(\"--dry-run: would run npm run build\");\n return rebuild(root, before);\n }\n info(`already up to date (${head} → ${upstream.out})`);\n return;\n }\n\n const behind = run(\"git\", [\"rev-list\", \"--count\", `HEAD..${upstream.out}`], root).out;\n const ahead = run(\"git\", [\"rev-list\", \"--count\", `${upstream.out}..HEAD`], root).out;\n\n if (ahead !== \"0\") {\n throw new PiPodError(`your checkout has ${ahead} commit(s) ${upstream.out} does not`, {\n hint: `push or rebase them yourself — update will not rewrite your history (git -C ${root} status)`,\n });\n }\n\n info(`${behind} new commit(s) on ${upstream.out}:`);\n const log = run(\"git\", [\"log\", \"--oneline\", \"--no-decorate\", `HEAD..${upstream.out}`], root);\n for (const line of log.out.split(\"\\n\").filter(Boolean).slice(0, 10)) plain(` ${line}`);\n\n // A dirty tree is checked only once there is something to pull: refusing to *report*\n // available updates because of unrelated edits would be gratuitous.\n const dirty = run(\"git\", [\"status\", \"--porcelain\", \"--untracked-files=no\"], root);\n if (dirty.out !== \"\") {\n throw new PiPodError(\"your checkout has uncommitted changes\", {\n hint: `commit or stash them first — update will not touch your working tree (git -C ${root} status)`,\n });\n }\n\n if (opts.dryRun) {\n info(`--dry-run: would fast-forward to ${upstream.out}, then npm install && npm run build`);\n return;\n }\n\n // --ff-only so a diverged history is a clean refusal rather than a merge commit in a\n // repository the user did not ask us to write to.\n if (!runVisible(\"git\", [\"merge\", \"--ff-only\", upstream.out], root)) {\n throw new PiPodError(`could not fast-forward to ${upstream.out}`, {\n hint: `resolve it by hand: git -C ${root} status`,\n });\n }\n\n return rebuild(root, before);\n}\n\n/** dist/ is generated, so a pull that changed src leaves the installed command stale. */\nexport function distIsStale(root: string): boolean {\n // Order matters: without sources there is nothing to build, so a missing dist/ means this\n // is not a buildable checkout rather than a stale one. Answering \"stale\" there would send\n // a packaged install into an npm build it cannot run.\n const srcDir = path.join(root, \"src\");\n if (!fs.existsSync(srcDir)) return false;\n\n const dist = path.join(root, \"dist\", \"cli.js\");\n if (!fs.existsSync(dist)) return true;\n const distTime = fs.statSync(dist).mtimeMs;\n\n const newest = (dir: string): number => {\n let max = 0;\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const p = path.join(dir, entry.name);\n max = Math.max(max, entry.isDirectory() ? newest(p) : fs.statSync(p).mtimeMs);\n }\n return max;\n };\n return newest(srcDir) > distTime;\n}\n\nfunction rebuild(root: string, before: string): void {\n // Dependencies move with the source, and a build against stale ones fails confusingly.\n // `npm ci` installs exactly the committed lockfile and never rewrites it: an update that\n // dirtied the checkout would make the next one refuse to run.\n info(\"installing dependencies…\");\n if (!runVisible(\"npm\", [\"ci\", \"--no-audit\", \"--no-fund\"], root)) {\n throw new PiPodError(\"npm ci failed\", { hint: `run it by hand in ${root}` });\n }\n\n info(\"building…\");\n if (!runVisible(\"npm\", [\"run\", \"build\"], root)) {\n throw new PiPodError(\"build failed — the installed pi pod is unchanged\", {\n hint: `run \\`npm run build\\` in ${root} to see the error`,\n });\n }\n\n const after = versionAt(root);\n const head = run(\"git\", [\"rev-parse\", \"--short\", \"HEAD\"], root).out;\n plain(\"\");\n info(after === before ? `now at ${color.bold(after)} (${head})` : `updated ${before} → ${color.bold(after)} (${head})`);\n // The same checkout can also be the one a self-hosted server was deployed from.\n const upgrade = path.join(run(\"git\", [\"rev-parse\", \"--show-toplevel\"], root).out, \"selfhost\", \"upgrade\");\n if (fs.existsSync(upgrade)) out(`if this checkout runs your server, upgrade it to match: ${upgrade}`);\n out(\"run `pipod doctor` to check the new version against this repo\");\n}\n\n// ---------------------------------------------------------------------------\n// registry install\n// ---------------------------------------------------------------------------\n\nasync function updateFromRegistry(root: string, name: string, opts: UpdateOptions): Promise<void> {\n const before = versionAt(root);\n info(`${color.bold(before)} installed from the registry as ${name}`);\n\n const view = run(\"npm\", [\"view\", `${name}@latest`, \"version\"], process.cwd());\n if (!view.ok) {\n throw new PiPodError(`could not reach the npm registry for ${name}`, {\n hint: \"check your network, or update with your package manager directly\",\n });\n }\n\n const latest = view.out.trim();\n if (latest === before) {\n info(`already up to date (${latest})`);\n return;\n }\n\n if (opts.dryRun) {\n info(`--dry-run: would run npm install -g ${name}@${latest}`);\n return;\n }\n\n info(`updating ${before} → ${color.bold(latest)}…`);\n if (!runVisible(\"npm\", [\"install\", \"-g\", `${name}@${latest}`], process.cwd())) {\n // A global install under a root-owned prefix is the usual cause, and telling the user to\n // rerun with sudo is better than leaving them with an opaque EACCES.\n throw new PiPodError(`npm install -g ${name}@${latest} failed`, {\n hint: `if this is a permissions error, run it again yourself with the rights your npm prefix needs`,\n });\n }\n\n plain(\"\");\n info(`updated ${before} → ${color.bold(latest)}`);\n warn(\"open a new shell if your terminal caches command paths\");\n}\n"],"mappings":"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","names":["fs","path","error","fs","out","cached","randomBytes","fs","path","fs","path","error","fs","path","fileURLToPath","fs","path","createHash","fs","path","createHash","fileURLToPath","relative","out","randomBytes","error","resolve","record","error","hint","resolve","cancelled","demand","error","cents","timing","error","record","error","fs","path","fs","path","out","execFile","fs","path","execFile","label","out","error","resolve","fs","path","out","fs","os","path","serverView","fs","path","resolve","question","fs","path","error","relative","label","configPath","raw","taken","report","out","label","CLIENT_ONLY_TOP_KEYS","CLIENT_ONLY_PI_KEYS","isPlainObject","error","stat","relative","path","fs","os","path","randomBytes","fs","path","error","label","fs","path","out","error","fail","resolve","member","pad","error","randomBytes","write","error","error","cents","hint","timing","error","resolve","path","hours","extensionVersion","resolve","execFile","fs","path","promisify","fs","path","error","label","walkTree","clone","out","error","label","opts","execFileAsync","promisify","execFile","label","run","resolve","error","fs","os","path","run","error","fs","os","path","resized","hints","note","error","fs","path","isPlainObject","out","error","error","run","cached","path","basename","randomUUID","isPlainObject","error","isPlainObject","randomUUID","resolve","resolve","randomUUID","error","label","randomUUID","resolve","fail","run","isPlainObject","unavailable","extensionVersion","error","isPlainObject","end","error","name","run","label","resolve","error","resolve","fail","isRecord","isSafeAuthUrl","randomBytes","randomUUID","WebSocket","error","resolve","error","error","randomBytes","error","resolve","randomUUID","fail","WebSocket","reason","isRecord","execFile","createHash","randomUUID","fs","os","path","promisify","execFileAsync","promisify","execFile","createHash","error","randomUUID","error","paint","resolve","opts","label","path","depth","label","pods","error","unavailable","hours","fs","error","error","throwIfCancelled","resolve","error","path","fs","path","realpathOr","samePath","hours","times","day","ago","pad","run","error","hours","i","j","out","error","cents","day","spawn","openBrowser","resolve","spawn","fs","path","error","relative","fs","path","readline","execFile","spawn","error","resolve","execFile","record","openBrowser","spawn","fs","path","fs","path","label","clientFor","error","fs","listCmd","rmCmd","secrets","write","error","listed","fs","fs","os","path","spawnSync","spawnSync","fs","path","step","spawnSync","fs","path","spawnSync"]}
|