@workerdeck/server 3.3.0 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/index.d.mts +40 -2
- package/build/index.mjs +1268 -459
- package/build/index.mjs.map +1 -1
- package/package.json +7 -7
package/build/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["resolvePath","SHELL_REFUSAL","profiles"],"sources":["../src/lifecycle.ts","../src/lib/http.ts","../src/lib/profile-env.ts","../src/lib/reload-plan.ts","../src/routes/queue-ws.ts","../src/lib/parse-route.ts","../src/routes/session-lookup.ts","../src/lib/permissions.ts","../src/services/shell-directory.ts","../src/services/process-tree.ts","../src/lib/atomic-file.ts","../src/services/shell-artifact.ts","../src/services/shell-screen.ts","../src/services/shell-entry.ts","../src/services/shell-env.ts","../src/services/shell-index.ts","../src/services/shells.ts","../src/routes/ws.ts","../src/routes/session-upgrade.ts","../src/lib/machine-id.ts","../src/routes/executions.ts","../src/services/host-files.ts","../src/services/host-file-search.ts","../src/routes/fs.ts","../src/lib/host-only-keys.ts","../src/routes/create-vet.ts","../src/routes/jobs.ts","../src/routes/profiles.ts","../src/routes/sdk-sessions.ts","../src/services/session-store.ts","../src/routes/attachments.ts","../src/routes/mcp.ts","../src/routes/produced-files.ts","../src/services/project-info.ts","../src/routes/project-icon.ts","../src/routes/shells.ts","../src/routes/tool-results.ts","../src/routes/sessions.ts","../src/routes/table.ts","../src/services/attachments.ts","../src/lib/scope.ts","../src/services/auth.ts","../src/services/availability.ts","../src/services/bridge.ts","../src/services/notifications.ts","../src/services/parking.ts","../src/services/produced-files.ts","../src/services/profiles.ts","../src/services/profile-usage.ts","../src/services/spend-ledger.ts","../src/services/peer-relay.ts","../src/services/peers.ts","../src/services/registry.ts","../src/services/session-factory.ts","../src/server.ts","../src/lib/sandboxed-profile.ts","../src/lib/provider-runner.ts","../src/services/profile-store.ts"],"sourcesContent":["import type { Server } from 'node:http'\nimport type { WebSocketServer } from 'ws'\nimport type { JobQueue } from '@workerdeck/queue'\nimport { sessionState } from '@workerdeck/protocol'\nimport type { DiagnosticSink, DrainOptions, DrainReport } from './options.ts'\nimport type { SessionParkManager } from './services/parking.ts'\nimport type { SessionRegistry } from './services/registry.ts'\nimport type { ShellRegistry } from './services/shells.ts'\n\n// How long a client gets to acknowledge the shutdown close frame before its socket is torn down.\nconst SOCKET_CLOSE_GRACE_MS = 250\n\n// The outer bound on close(): it resolves by then whether or not the runtime ever reports the drains complete.\nconst CLOSE_DEADLINE_MS = 1_000\n\nexport type ServerLifecycleDeps = {\n server: Server\n wss: WebSocketServer\n registry: SessionRegistry\n parking: SessionParkManager\n shells: ShellRegistry | null\n queue: JobQueue | undefined\n closeQueueSockets: () => void\n releaseDirectories: () => void\n diagnose: DiagnosticSink\n}\n\nexport type ServerLifecycle = {\n draining: () => boolean\n drain: (options?: DrainOptions) => Promise<DrainReport>\n close: () => Promise<void>\n}\n\nexport function createServerLifecycle(deps: ServerLifecycleDeps): ServerLifecycle {\n let closing: Promise<void> | undefined\n let draining = false\n return {\n draining: () => draining,\n drain: async (options = {}) => {\n draining = true\n deps.queue?.pause()\n return drainSessions(deps.registry, deps.shells, options)\n },\n close: () => {\n closing ??= closeServer(deps)\n return closing\n },\n }\n}\n\n// Split live sessions into \"will finish by itself\" and \"needs a person\".\n//\n// `sessionState` is the vocabulary the dashboard, the session list and `workerdeck guard` already sort by, and it\n// draws exactly the line a drain needs: `working` covers starting/running and running subagents, while `attention`\n// covers a pending approval. Re-spelling that set here is how the two definitions would drift apart.\nfunction surveyDrain(registry: SessionRegistry, shells: ShellRegistry | null): DrainReport {\n const working: string[] = []\n const awaitingHuman: string[] = []\n for (const info of registry.list()) {\n const state = sessionState(info)\n if (state === 'working') {\n working.push(info.id)\n } else if (state === 'attention') {\n awaitingHuman.push(info.id)\n }\n }\n const running = (shells?.running() ?? []).map(({ sessionId, id, label }) => ({ sessionId, id, label }))\n return { working, awaitingHuman, timedOut: false, shells: running }\n}\n\nfunction sameDrain(a: DrainReport, b: DrainReport): boolean {\n return a.working.join() === b.working.join() && a.awaitingHuman.join() === b.awaitingHuman.join()\n}\n\nasync function drainSessions(registry: SessionRegistry, shells: ShellRegistry | null, options: DrainOptions): Promise<DrainReport> {\n const { timeoutMs = 30_000, pollMs = 250, onProgress } = options\n const deadline = Date.now() + timeoutMs\n let report = surveyDrain(registry, shells)\n onProgress?.(report)\n while (report.working.length > 0 && Date.now() < deadline) {\n await new Promise((resolve) => setTimeout(resolve, pollMs))\n const next = surveyDrain(registry, shells)\n // Only speak when something actually changed: a shutdown that reports on its own progress should be\n // readable, not a per-tick redraw of the same two lines.\n if (!sameDrain(next, report)) {\n onProgress?.(next)\n }\n report = next\n }\n report = { ...surveyDrain(registry, shells), timedOut: false }\n report.timedOut = report.working.length > 0\n onProgress?.(report)\n return report\n}\n\nfunction closeServer(deps: ServerLifecycleDeps): Promise<void> {\n const { server, wss, registry, parking, shells, queue } = deps\n return new Promise((resolve) => {\n deps.releaseDirectories()\n queue?.close()\n // Before the runners close: their `session_closed` would settle every shell as `killed`, and a graceful stop is\n // `server_stopped`. The index lands through `flushed` below, ahead of resolving.\n shells?.killAll('server_stopped')\n const flushed = shells?.flush().catch((error: unknown) => deps.diagnose(error, 'shell-flush')) ?? Promise.resolve()\n // Ordering is load-bearing: parking's `#closed` guard must be set before the registry closes runners with\n // reason 'server', or shutdown discards every dormant record. See docs/GOTCHAS.md.\n parking.close()\n registry.closeAll()\n // `wss` is `noServer`, so `wss.close()` only waits for `clients` to empty, and `server.closeAllConnections()`\n // never reaches an upgraded socket: close every client ourselves, then terminate what has not acknowledged.\n for (const ws of wss.clients) {\n ws.close(1001, 'server shutting down')\n }\n deps.closeQueueSockets()\n const force = setTimeout(() => {\n for (const ws of wss.clients) {\n ws.terminate()\n }\n }, SOCKET_CLOSE_GRACE_MS)\n force.unref()\n const finish = (): void => void flushed.then(() => resolve())\n const deadline = setTimeout(finish, CLOSE_DEADLINE_MS)\n deadline.unref()\n const drained = Promise.all([\n new Promise<void>((done) => wss.close(() => done())),\n new Promise<void>((done) => server.close(() => done())),\n ])\n server.closeAllConnections()\n void drained.then(() => {\n clearTimeout(force)\n clearTimeout(deadline)\n finish()\n })\n })\n}\n","import { createHash } from 'node:crypto'\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { Duplex } from 'node:stream'\n\nconst CONTENT_TYPES: Record<string, string> = {\n json: 'application/json; charset=utf-8',\n md: 'text/markdown; charset=utf-8',\n html: 'text/html; charset=utf-8',\n csv: 'text/csv; charset=utf-8',\n xml: 'application/xml; charset=utf-8',\n svg: 'image/svg+xml; charset=utf-8',\n}\n\n// Headers for serving user-controlled bytes (attachments, produced files, sandbox VFS reads):\n// force download and forbid MIME sniffing so a crafted HTML/SVG payload can never execute in the\n// gateway's origin. Every byte-serving route must use this.\nexport function untrustedDownloadHeaders(filename: string, contentType: string, byteLength: number): Record<string, string | number> {\n return {\n 'content-type': contentType,\n 'content-length': byteLength,\n 'content-disposition': `attachment; filename*=UTF-8''${encodeURIComponent(filename)}`,\n 'x-content-type-options': 'nosniff',\n }\n}\n\nexport function json(res: ServerResponse, status: number, body: unknown): void {\n const payload = JSON.stringify(body)\n res.writeHead(status, {\n 'content-type': 'application/json',\n 'content-length': Buffer.byteLength(payload),\n })\n res.end(payload)\n}\n\nexport type Refusal = { status: number; error: string }\n\nexport class HttpError extends Error {\n readonly status: number\n\n constructor(status: number, message: string) {\n super(message)\n this.status = status\n }\n}\n\nexport function fail(status: number, message: string): never {\n throw new HttpError(status, message)\n}\n\nexport function requireMethod(req: IncomingMessage, ...methods: string[]): void {\n if (!methods.includes(req.method ?? '')) {\n fail(405, 'method not allowed')\n }\n}\n\nexport function sendUntrusted(res: ServerResponse, filename: string, contentType: string, bytes: Buffer | string): void {\n res.writeHead(200, untrustedDownloadHeaders(filename, contentType, Buffer.byteLength(bytes)))\n res.end(bytes)\n}\n\nexport function httpErrorStatus(error: unknown): number {\n if (error instanceof HttpError) {\n return error.status\n }\n return error instanceof SyntaxError ? 400 : 500\n}\n\n// A cross-site page can send `text/plain` (or a typeless Blob) without a preflight, so a JSON route that parsed any\n// body would be reachable by a drive-by form post. Only an empty body may omit the header.\nexport async function readJsonBody(req: IncomingMessage, maxBytes: number): Promise<Record<string, unknown>> {\n const mime = mediaTypeOf(req.headers['content-type'])\n if (mime !== undefined && !isJsonMediaType(mime)) {\n throw new HttpError(415, 'expected content-type application/json')\n }\n const body = await readRawBody(req, maxBytes)\n if (body.length === 0) {\n return {}\n }\n if (mime === undefined) {\n throw new HttpError(415, 'expected content-type application/json')\n }\n return JSON.parse(body.toString('utf8')) as Record<string, unknown>\n}\n\nfunction mediaTypeOf(header: string | undefined): string | undefined {\n const mime = header?.split(';')[0].trim().toLowerCase()\n return mime === undefined || mime === '' ? undefined : mime\n}\n\nfunction isJsonMediaType(mime: string): boolean {\n return mime === 'application/json' || (mime.startsWith('application/') && mime.endsWith('+json'))\n}\n\nexport async function readRawBody(req: IncomingMessage, maxBytes: number): Promise<Buffer> {\n const chunks: Buffer[] = []\n let size = 0\n for await (const chunk of req) {\n size += (chunk as Buffer).length\n if (size > maxBytes) {\n throw new HttpError(413, 'request body too large')\n }\n chunks.push(chunk as Buffer)\n }\n return Buffer.concat(chunks)\n}\n\nexport function hashBytes(bytes: Buffer): string {\n return createHash('sha256').update(bytes).digest('hex')\n}\n\n// Decoding never fails in Node - invalid bytes become U+FFFD - so a round trip is the only honest test.\nexport function asUtf8(bytes: Buffer): string | null {\n const text = bytes.toString('utf8')\n return Buffer.from(text, 'utf8').equals(bytes) ? text : null\n}\n\nexport function contentTypeFor(filename: string): string {\n const ext = filename.includes('.') ? filename.split('.').pop()!.toLowerCase() : ''\n return CONTENT_TYPES[ext] ?? 'text/plain; charset=utf-8'\n}\n\nexport function refuseUpgrade(socket: Duplex, status: string): void {\n socket.write(`HTTP/1.1 ${status}\\r\\n\\r\\n`)\n socket.destroy()\n}\n","import { existsSync, readFileSync, readdirSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join, resolve as resolvePath, sep } from 'node:path'\nimport type { ProfileConfigSnapshot, ProfileEngine, ProfileInfo } from '@workerdeck/protocol'\n\nexport function isProviderProfile(profile: ProfileInfo): boolean {\n return profile.engine === 'provider'\n}\n\nexport function engineOf(source: { engine?: ProfileEngine } | undefined): ProfileEngine {\n return source?.engine ?? 'claude'\n}\n\nexport function cliConfigDir(env: Record<string, string | undefined>): string {\n return env.CLAUDE_CONFIG_DIR ?? join(homedir(), '.claude')\n}\n\nexport function codexHomeDir(env: Record<string, string | undefined>): string {\n return env.CODEX_HOME ?? join(homedir(), '.codex')\n}\n\n// Detection is by credential directory, not by binary: a directory that exists is one the operator\n// has already logged into, and a profile pointing at an engine that is not installed reports itself\n// unavailable rather than failing at session start.\nexport function detectDefaultProfiles(env: Record<string, string | undefined> = process.env): ProfileInfo[] {\n const detected: ProfileInfo[] = []\n const claude = cliConfigDir(env)\n if (existsSync(claude)) {\n detected.push({ name: 'default', configDir: claude })\n }\n const codex = codexHomeDir(env)\n if (existsSync(codex)) {\n detected.push({ name: 'codex', engine: 'codex', codexHome: codex })\n }\n return detected\n}\n\nexport function cwdAllowed(cwd: string, roots: string[] | undefined): boolean {\n if (!roots || roots.length === 0) {\n return true\n }\n const resolved = resolvePath(cwd)\n return roots.some((root) => {\n const r = resolvePath(root)\n return resolved === r || resolved.startsWith(r + sep)\n })\n}\n\n// Env var VALUES are never read into this snapshot - names only.\nexport function readProfileConfig(profile: ProfileInfo): ProfileConfigSnapshot {\n const dir = profile.configDir\n if (!dir) {\n return { hasUserMemory: false, skills: [], agents: [], commands: [] }\n }\n const listDirs = (path: string): string[] => {\n try {\n return readdirSync(path, { withFileTypes: true })\n .filter((entry) => entry.isDirectory())\n .map((entry) => entry.name)\n .sort()\n } catch {\n return []\n }\n }\n const listMd = (path: string): string[] => {\n try {\n return readdirSync(path)\n .filter((file) => file.endsWith('.md'))\n .map((file) => file.slice(0, -3))\n .sort()\n } catch {\n return []\n }\n }\n const snapshot: ProfileConfigSnapshot = {\n hasUserMemory: existsSync(join(dir, 'CLAUDE.md')),\n skills: listDirs(join(dir, 'skills')),\n agents: listMd(join(dir, 'agents')),\n commands: listMd(join(dir, 'commands')),\n }\n try {\n const raw = JSON.parse(readFileSync(join(dir, 'settings.json'), 'utf8')) as Record<string, unknown>\n const permissions = (raw.permissions ?? {}) as Record<string, unknown>\n const count = (rules: unknown): number => (Array.isArray(rules) ? rules.length : 0)\n snapshot.settings = {\n model: typeof raw.model === 'string' ? raw.model : undefined,\n defaultPermissionMode: typeof permissions.defaultMode === 'string' ? permissions.defaultMode : undefined,\n permissionRules: {\n allow: count(permissions.allow),\n ask: count(permissions.ask),\n deny: count(permissions.deny),\n },\n envKeys: raw.env && typeof raw.env === 'object' ? Object.keys(raw.env).sort() : undefined,\n hooks: raw.hooks && typeof raw.hooks === 'object' ? Object.keys(raw.hooks).sort() : undefined,\n }\n } catch {}\n return snapshot\n}\n","import type { Runner } from '@workerdeck/core'\nimport { isJobRun } from '@workerdeck/protocol'\n\n// What a hot reload may do with a live session. `carry` hands the runner object itself to the next generation,\n// which is the only way an engine child process, its subagents and its shell grandchildren survive; `persist` is\n// the ordinary restart story through the store; `drop` lets the session end with the generation.\nexport type ReloadPlan = 'carry' | 'persist' | 'drop'\n\nexport function reloadPlan(runner: Runner): ReloadPlan {\n const info = runner.info()\n if (info.status === 'closed' || info.status === 'failed') {\n return 'drop'\n }\n // The queue owns a job's session: a carried one would be a row nothing will ever finalize.\n if (isJobRun(info)) {\n return 'drop'\n }\n // Keyed on the capability, never on the engine name: \"can this session persist itself\" is the actual question,\n // and a runner that can snapshot has in-process executors closed over this generation's bridge hub, which after\n // the swap has no sockets. Carrying one does not orphan a call in flight, it breaks every later bridged call.\n if (runner.snapshot !== undefined) {\n return 'persist'\n }\n return 'carry'\n}\n","import type { IncomingMessage } from 'node:http'\nimport type { Duplex } from 'node:stream'\nimport type { WebSocket, WebSocketServer } from 'ws'\nimport type { JobQueue } from '@workerdeck/queue'\nimport { PROTOCOL_VERSION, type JobEvent, type QueueServerFrame } from '@workerdeck/protocol'\nimport { refuseUpgrade } from '../lib/http.ts'\nimport type { DiagnosticSink } from '../options.ts'\nimport type { AuthService } from '../services/auth.ts'\n\nexport type QueueSocketHub = {\n broadcast: (event: JobEvent) => void\n upgrade: (req: IncomingMessage, socket: Duplex, head: Buffer) => Promise<void>\n clear: () => void\n}\n\nexport type QueueSocketDeps = {\n wss: WebSocketServer\n auth: AuthService\n queue: () => JobQueue | undefined\n diagnose: DiagnosticSink\n}\n\nexport function createQueueSocketHub(deps: QueueSocketDeps): QueueSocketHub {\n const sockets = new Set<WebSocket>()\n\n const broadcast = (event: JobEvent): void => {\n if (sockets.size === 0) {\n return\n }\n for (const ws of sockets) {\n sendQueueFrame(ws, { type: 'job_event', event })\n }\n if (event.type !== 'job_progress') {\n void deps\n .queue()\n ?.stats()\n .then((stats) => {\n for (const ws of sockets) {\n sendQueueFrame(ws, { type: 'queue_stats', stats })\n }\n })\n .catch((error: unknown) => deps.diagnose(error, 'queue-stats'))\n }\n }\n\n const upgrade = async (req: IncomingMessage, socket: Duplex, head: Buffer): Promise<void> => {\n const queue = deps.queue()\n if (!queue) {\n refuseUpgrade(socket, '404 Not Found')\n return\n }\n const auth = await deps.auth.authenticate(req)\n if (!auth.ok) {\n refuseUpgrade(socket, '401 Unauthorized')\n return\n }\n if (!deps.auth.isOperator(auth)) {\n refuseUpgrade(socket, '404 Not Found')\n return\n }\n deps.wss.handleUpgrade(req, socket, head, (ws) => {\n sockets.add(ws)\n ws.on('close', () => sockets.delete(ws))\n void queue\n .stats()\n .then((stats) => sendQueueFrame(ws, { type: 'queue_attached', protocolVersion: PROTOCOL_VERSION, stats }))\n .catch((error: unknown) => deps.diagnose(error, 'queue-stats'))\n })\n }\n\n return { broadcast, upgrade, clear: () => sockets.clear() }\n}\n\nfunction sendQueueFrame(ws: WebSocket, frame: QueueServerFrame): void {\n if (ws.readyState === ws.OPEN) {\n ws.send(JSON.stringify(frame))\n }\n}\n","import { HttpError } from './http.ts'\n\nexport type ShellRouteAction = 'output' | 'kill' | 'agent-write'\n\nexport type SessionItemRoute =\n | { kind: 'session'; id: string }\n | { kind: 'ws'; id: string }\n | { kind: 'permission'; id: string; permissionId: string }\n | { kind: 'attachments'; id: string; attachmentId?: string }\n | { kind: 'produced'; id: string; producedFileId?: string }\n | { kind: 'shells'; id: string; shellId?: string; shellAction?: ShellRouteAction }\n | { kind: 'stop-task'; id: string; stopTaskId: string }\n | { kind: 'project-icon'; id: string }\n | { kind: 'tool-result'; id: string; resultSeq: number }\n | { kind: 'mcp'; id: string; mcpServer?: string }\n | { kind: 'files'; id: string; filePath?: string }\n\nexport type SessionRoute = { kind: 'collection' } | SessionItemRoute\n\nconst SHELL_ACTIONS = new Set<string>(['output', 'kill', 'agent-write'])\n\n// Whole-segment matching: `/sessionsX` is not a session path. A segment that is not valid percent-encoding is a 400,\n// and an empty session id is no route at all, so `/sessions//permissions/x` can never reach the collection.\nexport function parseSessionRoute(basePath: string, url: string): SessionRoute | null {\n const pathname = new URL(url, 'http://internal').pathname\n const prefix = basePath + '/sessions'\n if (pathname !== prefix && !pathname.startsWith(prefix + '/')) {\n return null\n }\n const rest = pathname.slice(prefix.length)\n if (rest === '' || rest === '/') {\n return { kind: 'collection' }\n }\n const parts = rest.slice(1).split('/')\n if (parts[0] === '') {\n return null\n }\n return itemRoute(parts[0]!, parts)\n}\n\nfunction itemRoute(rawId: string, parts: string[]): SessionItemRoute | null {\n const [, section, third, fourth] = parts\n const length = parts.length\n if (length === 1) {\n return { kind: 'session', id: decode(rawId) }\n }\n if (length === 2 && section === 'ws') {\n return { kind: 'ws', id: decode(rawId) }\n }\n if (length === 3 && section === 'permissions') {\n const permissionId = decode(third!)\n return permissionId === '' ? null : { kind: 'permission', id: decode(rawId), permissionId }\n }\n if (length <= 3 && section === 'attachments') {\n return { kind: 'attachments', id: decode(rawId), attachmentId: optional(third) }\n }\n if (length <= 3 && section === 'produced') {\n return { kind: 'produced', id: decode(rawId), producedFileId: optional(third) }\n }\n if (section === 'shells' && length <= 4) {\n if (fourth !== undefined && !SHELL_ACTIONS.has(fourth)) {\n return null\n }\n return { kind: 'shells', id: decode(rawId), shellId: optional(third), shellAction: fourth as ShellRouteAction | undefined }\n }\n if (length === 4 && section === 'tasks' && fourth === 'stop') {\n return { kind: 'stop-task', id: decode(rawId), stopTaskId: decode(third!) }\n }\n if (length === 3 && section === 'project' && third === 'icon') {\n return { kind: 'project-icon', id: decode(rawId) }\n }\n if (length === 4 && section === 'events' && fourth === 'result') {\n const seq = Number(third)\n return Number.isInteger(seq) && seq >= 0 ? { kind: 'tool-result', id: decode(rawId), resultSeq: seq } : null\n }\n if (length <= 3 && section === 'mcp') {\n // MCP server names are opaque and may contain ':' (plugin:gtm:gtm) - one segment, decoded whole.\n return { kind: 'mcp', id: decode(rawId), mcpServer: optional(third) }\n }\n if (length >= 2 && section === 'files') {\n const filePath = parts.slice(2).map(decode).join('/')\n return { kind: 'files', id: decode(rawId), filePath: filePath === '' ? undefined : '/' + filePath }\n }\n return null\n}\n\nfunction optional(segment: string | undefined): string | undefined {\n return segment === undefined ? undefined : decode(segment)\n}\n\nfunction decode(segment: string): string {\n try {\n return decodeURIComponent(segment)\n } catch {\n throw new HttpError(400, 'malformed percent-encoding in path')\n }\n}\n","import type { Runner } from '@workerdeck/core'\nimport type { SessionInfo } from '@workerdeck/protocol'\nimport type { ServerContext } from '../context.ts'\nimport { fail } from '../lib/http.ts'\nimport type { AuthContext } from '../services/auth.ts'\nimport type { StoredSessionRecord } from '../services/session-store.ts'\n\nexport type ResolvedSession = { runner: Runner | undefined; parked: StoredSessionRecord | null; info: SessionInfo }\n\nexport async function sessionInfoOf(ctx: ServerContext, id: string): Promise<SessionInfo | undefined> {\n return ctx.registry.get(id)?.info() ?? (await ctx.parking.get(id))?.info\n}\n\n// Missing and not-visible answer the same 404: whether a session exists outside the caller's scope is not its business.\nexport async function resolveSession(ctx: ServerContext, id: string, auth: AuthContext): Promise<ResolvedSession> {\n const runner = ctx.registry.get(id)\n const parked = runner ? null : await ctx.parking.get(id)\n const info = runner?.info() ?? parked?.info\n if (!info || !ctx.auth.canSee(auth, info)) {\n fail(404, 'session not found')\n }\n return { runner, parked, info }\n}\n\nexport function requireLive(runner: Runner | undefined, why: string): Runner {\n if (!runner) {\n fail(409, `session is parked (${why})`)\n }\n return runner\n}\n","import type { PermissionMode, ResolvePermissionRequest } from '@workerdeck/protocol'\n\nexport type PermissionModePolicy = { operator: boolean; disableBypass?: boolean }\n\nexport type PermissionDecisionInput = {\n behavior: 'allow' | 'deny'\n updatedInput?: Record<string, unknown>\n message?: string\n interrupt?: boolean\n}\n\nexport const OPERATOR_ONLY_MODES: ReadonlySet<PermissionMode> = new Set<PermissionMode>(['bypassPermissions', 'dontAsk'])\n\nexport function refusePermissionMode(mode: PermissionMode | undefined, policy: PermissionModePolicy): string | null {\n if (mode === 'bypassPermissions' && policy.disableBypass) {\n return 'bypassPermissions is disabled on this server (disableBypassPermissions)'\n }\n if (!policy.operator && mode !== undefined && OPERATOR_ONLY_MODES.has(mode)) {\n return `permission mode '${mode}' is reserved to operators`\n }\n return null\n}\n\nexport function permissionDecision(input: PermissionDecisionInput): ResolvePermissionRequest {\n return input.behavior === 'allow'\n ? { behavior: 'allow', updatedInput: input.updatedInput }\n : { behavior: 'deny', message: input.message, interrupt: input.interrupt }\n}\n","import {\n SHELL_REFUSAL,\n agentMayWrite,\n clampShellTail,\n encodeShellKeys,\n shellOwnershipRefusal,\n shellSummary,\n shellTail,\n ttyText,\n type Runner,\n type ShellDirectory,\n type ShellReadResult,\n type ShellView,\n} from '@workerdeck/core'\nimport { SHELL_READ_MAX_LINES, SHELL_WAIT_DEFAULT_MS, SHELL_WAIT_MAX_MS, type ShellInfo } from '@workerdeck/protocol'\nimport type { ShellRegistry, ShellSpawnInput } from './shell-types.ts'\n\n// The directory reaches a live runner only to start a shell for it: the record needs the session's cwd and the runner\n// draws the transcript row, exactly as a `$` from the composer does.\nexport type ShellDirectoryDeps = { runnerFor?: (sessionId: string) => Runner | undefined }\n\nexport type LocalCommandRunner = Runner & Required<Pick<Runner, 'queueLocalCommand'>>\n\ntype ShellSettleOptions = { view?: ShellView; tail?: number; waitFor?: string[]; timeoutMs?: number; since?: number }\n\ntype ShellTaken = { info: ShellInfo; read: Omit<ShellReadResult, 'shell' | 'wait'>; haystack: string }\n\n// The agent's side of the same registry: a session sees its own shells and nothing else, so another session's id\n// reads as missing rather than as a refusal that would name it. Writes and kills are further limited to shells the\n// agent owns (`agentMayWrite`), and that refusal names the rule because the shell does exist.\nexport function createShellDirectory(registry: ShellRegistry, deps: ShellDirectoryDeps = {}): ShellDirectory {\n // One read of the shell as it is now. With `since`, the haystack is only what the process wrote after that byte\n // offset, so a wait that follows a keystroke cannot be satisfied by text that was already on the screen.\n const take = async (from: string, shellId: string, options: ShellSettleOptions): Promise<ShellTaken | undefined> => {\n const info = registry.get(from, shellId)\n if (!info) {\n return undefined\n }\n const view: ShellView = options.view ?? (info.interactive ? 'screen' : 'lines')\n const fresh = options.since === undefined ? undefined : await freshText(from, shellId, info.bytes - options.since)\n if (view === 'screen') {\n const text = await registry.output(from, shellId, { view: 'screen' })\n if (text === undefined) {\n return undefined\n }\n const lines = text === '' ? 0 : text.split('\\n').length\n return { info, read: { view, text, lines, totalLines: lines, truncated: false }, haystack: fresh ?? text }\n }\n const text = await registry.output(from, shellId, { view: 'text' })\n if (text === undefined) {\n return undefined\n }\n return { info, read: shellTail(text, clampShellTail(options.tail)), haystack: fresh ?? shellTail(text, SHELL_READ_MAX_LINES).text }\n }\n const freshText = async (from: string, shellId: string, bytes: number): Promise<string> => {\n if (bytes <= 0) {\n return ''\n }\n const raw = await registry.output(from, shellId, { view: 'raw', tail: bytes })\n return raw === undefined ? '' : ttyText(raw)\n }\n const settle = async (from: string, shellId: string, options: ShellSettleOptions): Promise<ShellReadResult | undefined> => {\n const needles = options.waitFor ?? []\n const started = Date.now()\n const timeoutMs = Math.max(0, Math.min(options.timeoutMs ?? SHELL_WAIT_DEFAULT_MS, SHELL_WAIT_MAX_MS))\n for (;;) {\n const taken = await take(from, shellId, options)\n if (!taken) {\n return undefined\n }\n const result: ShellReadResult = { shell: shellSummary(taken.info), ...taken.read }\n if (needles.length === 0) {\n return result\n }\n const ms = Date.now() - started\n const match = needles.find((needle) => taken.haystack.includes(needle))\n if (match !== undefined) {\n return { ...result, wait: { outcome: 'matched', match, ms } }\n }\n if (taken.info.status !== 'running') {\n return { ...result, wait: { outcome: 'exited', ms } }\n }\n if (ms >= timeoutMs) {\n return { ...result, wait: { outcome: 'timeout', ms } }\n }\n await registry.changed(from, shellId, timeoutMs - ms)\n }\n }\n const writable = (from: string, shellId: string): ShellInfo | undefined => {\n const info = registry.get(from, shellId)\n if (!info) {\n return undefined\n }\n if (!agentMayWrite(info, from)) {\n throw new Error(shellOwnershipRefusal(shellId))\n }\n return info\n }\n return {\n list: async (from) => registry.list(from).map(shellSummary),\n read: (from, shellId, options) => settle(from, shellId, { ...options }),\n run: async (from, options) => {\n const runner = deps.runnerFor?.(from)\n if (!runner || !takesLocalCommands(runner)) {\n throw new Error(SHELL_REFUSAL)\n }\n const shell = await startShell(registry, { runner, command: options.command, owner: 'agent' })\n const result = await settle(from, shell.id, { waitFor: options.waitFor, timeoutMs: options.timeoutMs })\n if (!result) {\n throw new Error(`shell ${shell.id} vanished as it started`)\n }\n return result\n },\n write: async (from, shellId, options) => {\n const info = writable(from, shellId)\n if (!info) {\n return undefined\n }\n if (info.status !== 'running') {\n throw new Error(`shell ${shellId} has already ended; there is nothing to type into`)\n }\n const application = await registry.applicationCursorKeys(from, shellId)\n const data = (options.data ?? '') + encodeShellKeys(options.keys ?? [], { applicationCursorKeys: application })\n if (data.length === 0) {\n throw new Error('nothing to write: give data, keys or both')\n }\n const since = registry.get(from, shellId)?.bytes ?? info.bytes\n registry.write(from, shellId, data)\n return settle(from, shellId, { waitFor: options.waitFor, timeoutMs: options.timeoutMs, since })\n },\n kill: async (from, shellId) => {\n const info = writable(from, shellId)\n if (!info) {\n return undefined\n }\n if (info.status !== 'running') {\n return { shell: shellSummary(info), killed: false }\n }\n const killed = registry.kill(from, shellId, 'killed') ?? info\n return { shell: shellSummary(killed), killed: true }\n },\n grant: async (from, shellId) => {\n const info = registry.get(from, shellId)\n if (!info) {\n return undefined\n }\n if (info.owner === 'agent') {\n return shellSummary(info)\n }\n const granted = registry.setAgentWrite(from, shellId, true)\n return granted ? shellSummary(granted) : undefined\n },\n }\n}\n\nexport function takesLocalCommands(runner: Runner): runner is LocalCommandRunner {\n return typeof runner.queueLocalCommand === 'function'\n}\n\n// queueLocalCommand throws before it pushes, so without the kill the shell would run with no transcript row.\nexport async function startShell(registry: ShellRegistry, input: ShellSpawnInput & { runner: LocalCommandRunner }): Promise<ShellInfo> {\n const { shell, source } = await registry.spawn(input)\n try {\n input.runner.queueLocalCommand(source)\n } catch (error) {\n registry.kill(input.runner.id, shell.id)\n throw error\n }\n return shell\n}\n","import { spawnSync } from 'node:child_process'\n\nexport type ProcessRow = { pid: number; ppid: number; pgid: number }\n\nexport type ProcessTable = () => ProcessRow[] | null\n\nexport type ProcessSignal = 'SIGSTOP' | 'SIGKILL'\n\nexport type TreeKillDeps = { table: ProcessTable; signal: (pid: number, signal: ProcessSignal) => void; self: number }\n\nexport type TreeKillResult = { scanned: boolean; descendants: number; foreign: number[]; unreached: number[] }\n\nconst PS_ARGS = ['-eo', 'pid=,ppid=,pgid=']\nconst PS_TIMEOUT_MS = 2000\nconst PS_MAX_BUFFER = 64 * 1024 * 1024\nconst MAX_ROUNDS = 5\n\nexport function readProcessTable(): ProcessRow[] | null {\n const result = spawnSync('ps', PS_ARGS, {\n encoding: 'utf8',\n timeout: PS_TIMEOUT_MS,\n maxBuffer: PS_MAX_BUFFER,\n stdio: ['ignore', 'pipe', 'ignore'],\n })\n if (result.error || result.status !== 0 || typeof result.stdout !== 'string') {\n return null\n }\n return parseProcessTable(result.stdout)\n}\n\nexport function parseProcessTable(text: string): ProcessRow[] {\n const rows: ProcessRow[] = []\n for (const line of text.split('\\n')) {\n const fields = line.trim().split(/\\s+/)\n if (fields.length !== 3) {\n continue\n }\n const [pid, ppid, pgid] = fields.map(Number) as [number, number, number]\n if (Number.isInteger(pid) && Number.isInteger(ppid) && Number.isInteger(pgid)) {\n rows.push({ pid, ppid, pgid })\n }\n }\n return rows\n}\n\n// Freezes the tree under each root before killing it, so nothing discovered can fork past the scan: scan, SIGSTOP what\n// the scan found, rescan until the closure stops growing, then SIGKILL the closure. A root the table shows under a\n// parent other than us is a recycled pid and is not signalled at all. Without a table it is the group kill alone.\nexport function killProcessTrees(roots: number[], deps: TreeKillDeps): TreeKillResult {\n const { self } = deps\n const signal = (pid: number, name: ProcessSignal): boolean => {\n try {\n deps.signal(pid, name)\n return true\n } catch {\n return false\n }\n }\n const owned = (pid: number): boolean => Number.isInteger(pid) && pid > 1 && pid !== self\n const live = new Set(roots.filter(owned))\n const closure = new Map<number, ProcessRow>()\n const rootRows = new Map<number, ProcessRow>()\n const foreign: number[] = []\n let scanned = false\n let selfPgid: number | undefined\n for (let round = 0; round < MAX_ROUNDS; round++) {\n const table = readTable(deps.table)\n if (table === null) {\n break\n }\n const byPid = new Map<number, ProcessRow>()\n const byParent = new Map<number, ProcessRow[]>()\n for (const row of table) {\n byPid.set(row.pid, row)\n const siblings = byParent.get(row.ppid)\n if (siblings) {\n siblings.push(row)\n } else {\n byParent.set(row.ppid, [row])\n }\n }\n let grew = false\n if (!scanned) {\n scanned = true\n selfPgid = byPid.get(self)?.pgid\n for (const root of live) {\n const row = byPid.get(root)\n if (row === undefined) {\n continue\n }\n if (row.ppid !== self) {\n foreign.push(root)\n live.delete(root)\n continue\n }\n rootRows.set(root, row)\n signal(-root, 'SIGSTOP')\n // The roots were scanned before they were frozen, so the first round always earns a rescan.\n grew = true\n }\n }\n for (const root of rootRows.keys()) {\n const queue = [root]\n const seen = new Set<number>([root])\n while (queue.length > 0) {\n const parent = queue.shift()!\n for (const child of byParent.get(parent) ?? []) {\n if (!owned(child.pid) || seen.has(child.pid)) {\n continue\n }\n seen.add(child.pid)\n queue.push(child.pid)\n if (!closure.has(child.pid)) {\n closure.set(child.pid, child)\n signal(child.pid, 'SIGSTOP')\n grew = true\n }\n }\n }\n }\n if (!grew) {\n break\n }\n }\n const unreached: number[] = []\n const groups = new Set<number>()\n for (const root of live) {\n groups.add(root)\n if (!signal(-root, 'SIGKILL')) {\n unreached.push(root)\n }\n }\n for (const pid of closure.keys()) {\n signal(pid, 'SIGKILL')\n }\n if (selfPgid !== undefined) {\n for (const row of [...rootRows.values(), ...closure.values()]) {\n const group = row.pgid\n if (group <= 1 || group === self || group === selfPgid || groups.has(group)) {\n continue\n }\n groups.add(group)\n signal(-group, 'SIGKILL')\n }\n }\n return { scanned, descendants: closure.size, foreign, unreached }\n}\n\nfunction readTable(table: ProcessTable): ProcessRow[] | null {\n try {\n return table()\n } catch {\n return null\n }\n}\n","import { chmodSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'\nimport { chmod, mkdir, readFile, rename, writeFile } from 'node:fs/promises'\nimport { dirname } from 'node:path'\n\nexport type JsonWriteOptions = { indent?: number; trailingNewline?: boolean }\n\nconst FILE_MODE = 0o600\nconst DIR_MODE = 0o700\n\nexport function isMissing(error: unknown): boolean {\n return (error as NodeJS.ErrnoException | null)?.code === 'ENOENT'\n}\n\n// `writeFile`'s mode applies only on creation, so the chmod is what keeps a temp name left over by an earlier run from\n// handing its looser bits to the renamed file.\nexport async function writeFileAtomic(path: string, data: string | Uint8Array): Promise<void> {\n await mkdir(dirname(path), { recursive: true, mode: DIR_MODE })\n const temp = tempPathFor(path)\n await writeFile(temp, data, { mode: FILE_MODE })\n await chmod(temp, FILE_MODE)\n await rename(temp, path)\n}\n\nexport function writeFileAtomicSync(path: string, data: string | Uint8Array): void {\n mkdirSync(dirname(path), { recursive: true, mode: DIR_MODE })\n const temp = tempPathFor(path)\n writeFileSync(temp, data, { mode: FILE_MODE })\n chmodSync(temp, FILE_MODE)\n renameSync(temp, path)\n}\n\nexport function writeJsonAtomic(path: string, value: unknown, options: JsonWriteOptions = {}): Promise<void> {\n return writeFileAtomic(path, serializeJson(value, options))\n}\n\nexport function writeJsonAtomicSync(path: string, value: unknown, options: JsonWriteOptions = {}): void {\n writeFileAtomicSync(path, serializeJson(value, options))\n}\n\n// Missing, unreadable and corrupt all read as the fallback; a caller that must tell them apart reads the file itself.\nexport async function readJsonOr(path: string, fallback: unknown): Promise<unknown> {\n try {\n return JSON.parse(await readFile(path, 'utf8')) as unknown\n } catch {\n return fallback\n }\n}\n\nexport function readJsonOrSync(path: string, fallback: unknown): unknown {\n try {\n return JSON.parse(readFileSync(path, 'utf8')) as unknown\n } catch {\n return fallback\n }\n}\n\nfunction tempPathFor(path: string): string {\n return `${path}.${process.pid}.tmp`\n}\n\nfunction serializeJson(value: unknown, options: JsonWriteOptions): string {\n const text = JSON.stringify(value, null, options.indent)\n return options.trailingNewline ? `${text}\\n` : text\n}\n","import { mkdir, open, readFile, rm, stat, type FileHandle } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { ttyText } from '@workerdeck/core'\nimport { isMissing, writeFileAtomic } from '../lib/atomic-file.ts'\n\nexport { isMissing }\n\nexport type ArtifactLimits = { spill: number; cap: number; ring: number }\n\nexport type ArtifactPaths = { dir: string; raw: string; tail: string; rel: string }\n\nexport type StoredOutput = { output?: string; artifact?: string }\n\nexport type ShellArtifact = LiveArtifact | StoredArtifact\n\nexport function artifactPaths(base: string, sessionId: string, shellId: string): ArtifactPaths {\n const encoded = encodeURIComponent(sessionId)\n const sessionDir = join(base, encoded)\n return {\n dir: sessionDir,\n raw: join(sessionDir, `${shellId}.raw`),\n tail: join(sessionDir, `${shellId}.tail.raw`),\n rel: `${encoded}/${shellId}.raw`,\n }\n}\n\nexport class LiveArtifact {\n readonly #paths: ArtifactPaths\n readonly #limits: ArtifactLimits\n readonly #onError: (error: unknown) => void\n readonly #ring: Buffer\n #ringAt = 0\n #ringLen = 0\n #chunks: Buffer[] = []\n #chunkBytes = 0\n #bytes = 0\n #spilled = false\n #capped = false\n #closed = false\n #broken = false\n #io: Promise<void> = Promise.resolve()\n #handle: FileHandle | undefined\n #done = ''\n #pending = ''\n #textCache: string | undefined\n\n constructor(paths: ArtifactPaths, limits: ArtifactLimits, onError: (error: unknown) => void) {\n this.#paths = paths\n this.#limits = limits\n this.#onError = onError\n this.#ring = Buffer.alloc(Math.max(0, limits.ring))\n }\n\n get bytes(): number {\n return this.#bytes\n }\n\n get capped(): boolean {\n return this.#capped\n }\n\n append(data: string): boolean {\n const chunk = Buffer.from(data, 'utf8')\n const before = this.#bytes\n this.#bytes += chunk.length\n this.#ringPush(chunk)\n this.#textCache = undefined\n if (this.#capped) {\n return false\n }\n const room = Math.max(0, this.#limits.cap - before)\n const kept = chunk.length <= room ? chunk : chunk.subarray(0, room)\n this.#textAppend(kept === chunk ? data : kept.toString('utf8'))\n let changed = false\n if (this.#spilled) {\n this.#write(kept)\n } else {\n this.#chunks.push(kept)\n this.#chunkBytes += kept.length\n if (this.#chunkBytes > this.#limits.spill) {\n this.#spill()\n changed = true\n }\n }\n if (this.#bytes > this.#limits.cap) {\n this.#capped = true\n changed = true\n }\n return changed\n }\n\n text(): string {\n if (this.#textCache === undefined) {\n let text = this.#done + ttyText(this.#pending)\n if (this.#capped) {\n const after = this.#bytes - this.#limits.cap\n const kept = Math.min(after, this.#ringLen)\n if (kept > 0) {\n text += (after > kept ? '\\n' : '') + ttyText(this.tail(kept).toString('utf8'))\n }\n }\n this.#textCache = text\n }\n return this.#textCache\n }\n\n textView(): Promise<string> {\n return Promise.resolve(this.text())\n }\n\n tail(n: number = this.#ringLen): Buffer {\n const size = this.#ring.length\n const take = Math.max(0, Math.min(n, this.#ringLen))\n const out = Buffer.allocUnsafe(take)\n if (take === 0) {\n return out\n }\n const start = (this.#ringAt - take + size) % size\n const first = Math.min(take, size - start)\n this.#ring.copy(out, 0, start, start + first)\n if (first < take) {\n this.#ring.copy(out, first, 0, take - first)\n }\n return out\n }\n\n replay(max: number): Promise<Buffer> {\n const want = Math.max(0, Math.floor(max))\n if (!this.#spilled) {\n const all = Buffer.concat(this.#chunks, this.#chunkBytes)\n return Promise.resolve(all.subarray(Math.max(0, all.length - want)))\n }\n if (this.#capped || want <= this.#ringLen) {\n return Promise.resolve(this.tail(want))\n }\n const end = this.#bytes\n return this.#io.then(() => readRange(this.#paths.raw, Math.max(0, end - want), end))\n }\n\n async read(tail?: number): Promise<Buffer> {\n if (tail !== undefined) {\n return this.replay(tail)\n }\n if (!this.#spilled) {\n return Buffer.concat(this.#chunks, this.#chunkBytes)\n }\n await this.#io\n return readWhole(this.#paths.raw)\n }\n\n stored(): StoredOutput {\n return this.#spilled ? { artifact: this.#paths.rel } : { output: Buffer.concat(this.#chunks, this.#chunkBytes).toString('utf8') }\n }\n\n writeTail(): void {\n const tail = this.tail()\n this.#queue(() => writeFileAtomic(this.#paths.tail, tail))\n }\n\n close(): void {\n if (this.#closed) {\n return\n }\n this.#closed = true\n if (this.#capped) {\n this.writeTail()\n }\n this.#io = this.#io.then(async () => {\n const handle = this.#handle\n this.#handle = undefined\n await handle?.close().catch(() => {})\n })\n }\n\n idle(): Promise<void> {\n return this.#io\n }\n\n async remove(): Promise<void> {\n this.close()\n await this.#io\n await rm(this.#paths.raw, { force: true })\n await rm(this.#paths.tail, { force: true })\n }\n\n // Only the new chunk is searched: `#pending` holds no newline by construction, and scanning it again per chunk\n // made one long line quadratic.\n #textAppend(data: string): void {\n const newline = data.lastIndexOf('\\n')\n if (newline === -1) {\n this.#pending += data\n return\n }\n this.#done += ttyText(this.#pending + data.slice(0, newline + 1))\n this.#pending = data.slice(newline + 1)\n }\n\n #ringPush(chunk: Buffer): void {\n const size = this.#ring.length\n if (size === 0 || chunk.length === 0) {\n return\n }\n if (chunk.length >= size) {\n chunk.copy(this.#ring, 0, chunk.length - size)\n this.#ringAt = 0\n this.#ringLen = size\n return\n }\n const first = Math.min(chunk.length, size - this.#ringAt)\n chunk.copy(this.#ring, this.#ringAt, 0, first)\n if (first < chunk.length) {\n chunk.copy(this.#ring, 0, first)\n }\n this.#ringAt = (this.#ringAt + chunk.length) % size\n this.#ringLen = Math.min(size, this.#ringLen + chunk.length)\n }\n\n #spill(): void {\n this.#spilled = true\n const buffered = Buffer.concat(this.#chunks, this.#chunkBytes)\n this.#chunks = []\n this.#chunkBytes = 0\n this.#queue(async () => {\n await mkdir(this.#paths.dir, { recursive: true, mode: 0o700 })\n this.#handle = await open(this.#paths.raw, 'w', 0o600)\n await this.#handle.write(buffered)\n })\n }\n\n #write(chunk: Buffer): void {\n if (chunk.length === 0) {\n return\n }\n this.#queue(async () => {\n await this.#handle?.write(chunk)\n })\n }\n\n #queue(task: () => Promise<void>): void {\n this.#io = this.#io.then(async () => {\n if (this.#broken) {\n return\n }\n try {\n await task()\n } catch (error) {\n this.#broken = true\n this.#onError(error)\n }\n })\n }\n}\n\nexport class StoredArtifact {\n readonly #paths: ArtifactPaths\n readonly #bytes: number\n readonly #capped: boolean\n readonly #stored: StoredOutput\n\n constructor(paths: ArtifactPaths, info: { bytes: number; capped?: boolean }, stored: StoredOutput) {\n this.#paths = paths\n this.#bytes = info.bytes\n this.#capped = info.capped === true\n this.#stored = stored.artifact !== undefined ? { artifact: stored.artifact } : { output: stored.output ?? '' }\n }\n\n async read(tail?: number): Promise<Buffer> {\n if (tail !== undefined) {\n return this.replay(tail)\n }\n return this.#head()\n }\n\n async replay(max: number): Promise<Buffer> {\n const want = Math.max(0, Math.floor(max))\n if (this.#capped) {\n const ring = await readWhole(this.#paths.tail)\n return ring.subarray(Math.max(0, ring.length - want))\n }\n if (this.#stored.output !== undefined) {\n const all = Buffer.from(this.#stored.output, 'utf8')\n return all.subarray(Math.max(0, all.length - want))\n }\n const size = await stat(this.#paths.raw).then(\n (s) => s.size,\n () => 0,\n )\n return readRange(this.#paths.raw, Math.max(0, size - want), size)\n }\n\n async textView(): Promise<string> {\n const head = await this.#head()\n let text = ttyText(head.toString('utf8'))\n if (this.#capped) {\n const ring = await readWhole(this.#paths.tail)\n const after = this.#bytes - head.length\n const kept = Math.min(after, ring.length)\n if (kept > 0) {\n text += (after > kept ? '\\n' : '') + ttyText(ring.subarray(ring.length - kept).toString('utf8'))\n }\n }\n return text\n }\n\n stored(): StoredOutput {\n return this.#stored\n }\n\n idle(): Promise<void> {\n return Promise.resolve()\n }\n\n async remove(): Promise<void> {\n await rm(this.#paths.raw, { force: true })\n await rm(this.#paths.tail, { force: true })\n }\n\n #head(): Promise<Buffer> {\n return this.#stored.output !== undefined ? Promise.resolve(Buffer.from(this.#stored.output, 'utf8')) : readWhole(this.#paths.raw)\n }\n}\n\nasync function readWhole(path: string): Promise<Buffer> {\n try {\n return await readFile(path)\n } catch (error) {\n if (isMissing(error)) {\n return Buffer.alloc(0)\n }\n throw error\n }\n}\n\nasync function readRange(path: string, start: number, end: number): Promise<Buffer> {\n const length = Math.max(0, end - start)\n if (length === 0) {\n return Buffer.alloc(0)\n }\n let handle: FileHandle\n try {\n handle = await open(path, 'r')\n } catch (error) {\n if (isMissing(error)) {\n return Buffer.alloc(0)\n }\n throw error\n }\n try {\n const out = Buffer.allocUnsafe(length)\n let got = 0\n while (got < length) {\n const { bytesRead } = await handle.read(out, got, length - got, start + got)\n if (bytesRead === 0) {\n break\n }\n got += bytesRead\n }\n return got === length ? out : out.subarray(0, got)\n } finally {\n await handle.close()\n }\n}\n","import xtermHeadless from '@xterm/headless'\nimport type { Terminal } from '@xterm/headless'\n\n// What the terminal shows right now, kept by a headless emulator fed the same bytes as the artifact. A redrawing\n// program flattens into every frame it ever painted; the screen is the only view of it a reader can use.\nexport class ShellScreen {\n #term: Terminal | undefined\n #closing: Promise<void> | undefined\n #final: string | undefined\n\n constructor(cols: number, rows: number) {\n this.#term = new xtermHeadless.Terminal({ cols, rows, scrollback: 0, allowProposedApi: true })\n }\n\n write(data: string): void {\n this.#term?.write(data)\n }\n\n resize(cols: number, rows: number): void {\n try {\n this.#term?.resize(cols, rows)\n } catch {}\n }\n\n async snapshot(): Promise<string> {\n if (this.#closing) {\n await this.#closing\n }\n if (this.#final !== undefined) {\n return this.#final\n }\n const term = this.#term\n if (!term) {\n return ''\n }\n await drained(term)\n return render(term)\n }\n\n // DECCKM as the program last set it, so a cursor key is encoded the way the program expects to read it.\n async applicationCursorKeys(): Promise<boolean> {\n const term = this.#term\n if (!term) {\n return false\n }\n await drained(term)\n return term.modes.applicationCursorKeysMode\n }\n\n // An exited shell keeps its last screen as a string, not an emulator.\n close(): void {\n const term = this.#term\n if (!term || this.#closing) {\n return\n }\n this.#term = undefined\n this.#closing = drained(term).then(() => {\n this.#final = render(term)\n term.dispose()\n })\n }\n}\n\nexport async function renderScreen(raw: string, cols: number, rows: number): Promise<string> {\n const screen = new ShellScreen(cols, rows)\n screen.write(raw)\n screen.close()\n return screen.snapshot()\n}\n\nfunction drained(term: Terminal): Promise<void> {\n return new Promise((resolve) => term.write('', resolve))\n}\n\nfunction render(term: Terminal): string {\n const buffer = term.buffer.active\n const lines: string[] = []\n for (let y = 0; y < term.rows; y++) {\n lines.push(buffer.getLine(buffer.viewportY + y)?.translateToString(true) ?? '')\n }\n while (lines.length > 0 && lines[lines.length - 1] === '') {\n lines.pop()\n }\n return lines.join('\\n')\n}\n","import { randomBytes } from 'node:crypto'\nimport { TTY_REDRAW_CARRY, ttyRedraws, ttyText, type LocalShellSource } from '@workerdeck/core'\nimport {\n SHELL_ATTACH_REPLAY_BYTES,\n SHELL_COLS,\n SHELL_LABEL_MAX,\n SHELL_ROWS,\n type ShellEndReason,\n type ShellInfo,\n type ShellOwner,\n} from '@workerdeck/protocol'\nimport { killProcessTrees, type TreeKillDeps } from './process-tree.ts'\nimport { LiveArtifact } from './shell-artifact.ts'\nimport { renderScreen } from './shell-screen.ts'\nimport type {\n PtyChild,\n SessionShells,\n ShellAttachment,\n ShellEntry,\n ShellErrorContext,\n ShellErrorReporter,\n ShellOutputQuery,\n ShellSink,\n} from './shell-types.ts'\n\nconst NOTIFY_MS = 250\nconst ID_ALPHABET = 'abcdefghijklmnopqrstuvwxyz234567'\nconst ID_CHARS = 12\n\nexport type ChildHooks = { persist: () => void; notify: () => void; exit: () => void }\n\nexport function newShellInfo(state: SessionShells, sessionId: string, command: string, cwd: string, owner: ShellOwner): ShellInfo {\n return {\n id: mintShellId(),\n sessionId,\n ordinal: state.nextOrdinal++,\n command,\n label: shellLabel(command),\n cwd,\n owner,\n status: 'running',\n startedAt: Date.now(),\n bytes: 0,\n cols: SHELL_COLS,\n rows: SHELL_ROWS,\n }\n}\n\nexport function wireChild(entry: ShellEntry, child: PtyChild, artifact: LiveArtifact, tailFlushMs: number, hooks: ChildHooks): void {\n entry.child = child\n entry.pid = child.pid\n child.onData((data) => {\n if (entry.info.status !== 'running') {\n return\n }\n const changed = artifact.append(data)\n entry.info.bytes = artifact.bytes\n entry.screen?.write(data)\n if (!entry.info.interactive) {\n const scanned = (entry.redrawCarry ?? '') + data\n if (ttyRedraws(scanned)) {\n entry.info.interactive = true\n entry.redrawCarry = undefined\n hooks.persist()\n } else {\n entry.redrawCarry = scanned.slice(-TTY_REDRAW_CARRY)\n }\n }\n if (changed) {\n if (artifact.capped && !entry.info.capped) {\n entry.info.capped = true\n entry.tailTimer = setInterval(() => artifact.writeTail(), tailFlushMs)\n entry.tailTimer.unref()\n }\n hooks.persist()\n }\n for (const sink of entry.sinks) {\n try {\n sink.write(data)\n } catch {\n entry.sinks.delete(sink)\n }\n }\n hooks.notify()\n })\n child.onExit(({ exitCode, signal }) => {\n if (entry.info.status !== 'running') {\n return\n }\n if (signal) {\n entry.info.signal = signal\n } else {\n entry.info.exitCode = exitCode\n }\n hooks.exit()\n })\n}\n\nexport function endEntry(entry: ShellEntry, reason: ShellEndReason): void {\n entry.info.status = 'exited'\n entry.info.endedAt = Date.now()\n entry.info.endReason = reason\n delete entry.info.agentWrite\n clearTimeout(entry.clock)\n clearTimeout(entry.notify)\n clearInterval(entry.tailTimer)\n entry.clock = entry.notify = entry.tailTimer = undefined\n entry.child = undefined\n entry.pid = undefined\n if (entry.artifact instanceof LiveArtifact) {\n entry.artifact.close()\n }\n entry.screen?.close()\n for (const sink of entry.sinks) {\n try {\n sink.end(reason)\n } catch {}\n }\n entry.sinks.clear()\n}\n\nexport function fireListeners(entry: ShellEntry, report: ShellErrorReporter): void {\n for (const listener of entry.listeners) {\n try {\n listener()\n } catch (error) {\n report(error, { op: 'listener', sessionId: entry.info.sessionId, shellId: entry.info.id })\n }\n }\n}\n\nexport function scheduleNotify(entry: ShellEntry, fire: (entry: ShellEntry) => void): void {\n if (entry.notify) {\n return\n }\n entry.notify = setTimeout(() => {\n entry.notify = undefined\n if (entry.info.status === 'running') {\n fire(entry)\n }\n }, NOTIFY_MS)\n entry.notify.unref()\n}\n\nexport function killTrees(entries: ShellEntry[], deps: TreeKillDeps, report: ShellErrorReporter): void {\n const live = entries.flatMap((entry) => (entry.pid === undefined ? [] : [{ entry, pid: entry.pid }]))\n if (live.length === 0) {\n return\n }\n const result = killProcessTrees(\n live.map(({ pid }) => pid),\n deps,\n )\n for (const { entry, pid } of live) {\n if (result.unreached.includes(pid)) {\n try {\n entry.child?.kill('SIGKILL')\n } catch {}\n }\n const context: ShellErrorContext = { op: 'kill', sessionId: entry.info.sessionId, shellId: entry.info.id }\n if (!result.scanned) {\n report(new Error('no process table (ps), only the process group was signalled'), context)\n } else if (result.foreign.includes(pid)) {\n report(new Error(`pid ${pid} is no longer this shell's child and was left alone`), context)\n }\n }\n}\n\nexport function applyAgentWrite(entry: ShellEntry, shellId: string, enabled: boolean): boolean {\n if (enabled) {\n if (entry.info.owner !== 'user') {\n throw new Error(`shell ${shellId} was started by the agent, which may already type into it`)\n }\n if (entry.info.status !== 'running') {\n throw new Error(`shell ${shellId} has already ended; there is nothing to grant`)\n }\n }\n if ((entry.info.agentWrite === true) === enabled) {\n return false\n }\n if (enabled) {\n entry.info.agentWrite = true\n } else {\n delete entry.info.agentWrite\n }\n return true\n}\n\nexport async function attachEntry(entry: ShellEntry, sink: ShellSink): Promise<ShellAttachment> {\n const pending: string[] = []\n let live = false\n let ended: string | undefined\n const proxy: ShellSink = {\n write: (data) => {\n if (live) {\n sink.write(data)\n } else {\n pending.push(data)\n }\n },\n end: (reason) => {\n if (live) {\n sink.end(reason)\n } else {\n ended = reason\n }\n },\n }\n if (entry.info.status === 'running') {\n entry.sinks.add(proxy)\n }\n let replay: Buffer\n try {\n replay = await entry.artifact.replay(SHELL_ATTACH_REPLAY_BYTES)\n } catch (error) {\n entry.sinks.delete(proxy)\n throw error\n }\n live = true\n if (ended !== undefined) {\n const reason = ended\n queueMicrotask(() => sink.end(reason))\n }\n return {\n shell: { ...entry.info },\n scrollback: replay.toString('utf8') + pending.join(''),\n detach: () => {\n entry.sinks.delete(proxy)\n },\n }\n}\n\nexport async function readOutput(entry: ShellEntry, query: ShellOutputQuery): Promise<string> {\n if (query.view === 'screen') {\n if (entry.screen) {\n return entry.screen.snapshot()\n }\n const replay = await entry.artifact.replay(SHELL_ATTACH_REPLAY_BYTES)\n return renderScreen(replay.toString('utf8'), entry.info.cols, entry.info.rows)\n }\n if (query.tail === undefined && query.view === 'text') {\n return entry.artifact.textView()\n }\n const raw = await entry.artifact.read(query.tail)\n const text = raw.toString('utf8')\n return query.view === 'raw' ? text : ttyText(text)\n}\n\nexport function waitForChange(entry: ShellEntry | undefined, timeoutMs: number): Promise<void> {\n if (!entry || entry.info.status !== 'running') {\n return Promise.resolve()\n }\n return new Promise((resolve) => {\n const done = () => {\n clearTimeout(timer)\n entry.listeners.delete(done)\n resolve()\n }\n const timer = setTimeout(done, Math.max(0, timeoutMs))\n timer.unref()\n entry.listeners.add(done)\n })\n}\n\nexport function sourceFor(entry: ShellEntry, artifact: LiveArtifact): LocalShellSource {\n return {\n info: () => entry.info,\n text: () => artifact.text(),\n subscribe: (listener) => {\n entry.listeners.add(listener)\n return () => {\n entry.listeners.delete(listener)\n }\n },\n }\n}\n\nfunction mintShellId(): string {\n const bytes = randomBytes(ID_CHARS)\n let id = 'sh_'\n for (let i = 0; i < ID_CHARS; i++) {\n id += ID_ALPHABET[bytes[i]! & 31]\n }\n return id\n}\n\nfunction shellLabel(command: string): string {\n const first = command.split('\\n')[0] ?? ''\n return first.trim().slice(0, SHELL_LABEL_MAX)\n}\n","import { withoutGatewaySecrets } from '@workerdeck/core'\nimport { SHELL_COLS, SHELL_MAX_COLS, SHELL_MAX_ROWS, SHELL_MIN_COLS, SHELL_MIN_ROWS, SHELL_ROWS } from '@workerdeck/protocol'\nimport type { PtyChild, PtyModule, ShellSize } from './shell-types.ts'\n\nconst TERM = 'xterm-256color'\n// macOS drops a session leader's unread pty output ~600ms after it exits unless its session opened /dev/tty; the\n// login shell execs under the same pid with the command as $1, so nothing is re-quoted.\nconst CTTY_WRAPPER = 'true <>/dev/tty 2>/dev/null; exec \"$0\" -c \"$1\"'\n\nlet ptyModule: PtyModule | null | undefined\n\nexport async function loadPty(): Promise<PtyModule | null> {\n if (ptyModule !== undefined) {\n return ptyModule\n }\n try {\n ptyModule = (await import('@lydell/node-pty')) as unknown as PtyModule\n } catch {\n ptyModule = null\n }\n return ptyModule\n}\n\n// A spawn env replaces the inherited one wholesale, so the copy has to be complete; the gateway's own environment is\n// what the operator's terminal would have given the same command.\nexport function shellChildEnv(base: Record<string, string | undefined>): Record<string, string> {\n const env: Record<string, string> = {}\n for (const [key, value] of Object.entries(withoutGatewaySecrets(base))) {\n if (value !== undefined) {\n env[key] = value\n }\n }\n return env\n}\n\nexport function clampSize(size: ShellSize): ShellSize {\n return {\n cols: clamp(size.cols, SHELL_MIN_COLS, SHELL_MAX_COLS),\n rows: clamp(size.rows, SHELL_MIN_ROWS, SHELL_MAX_ROWS),\n }\n}\n\nexport function loginShell(env: Record<string, string | undefined>): string {\n const shell = env.SHELL\n return shell && shell.startsWith('/') ? shell : '/bin/sh'\n}\n\nexport function spawnShellChild(pty: PtyModule, cwd: string, command: string): PtyChild {\n const env = shellChildEnv(process.env)\n env.TERM = TERM\n env.COLORTERM = 'truecolor'\n env.PWD = cwd\n return pty.spawn('/bin/sh', ['-c', CTTY_WRAPPER, loginShell(process.env), command], {\n name: TERM,\n cols: SHELL_COLS,\n rows: SHELL_ROWS,\n cwd,\n env,\n })\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Number.isFinite(value) ? Math.min(max, Math.max(min, Math.trunc(value))) : min\n}\n","import { readdir, readFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { isMissing, writeJsonAtomic } from '../lib/atomic-file.ts'\nimport { artifactPaths, StoredArtifact } from './shell-artifact.ts'\nimport type { SessionShells, ShellEntry, ShellErrorReporter, StoredShellIndex, StoredShellRecord } from './shell-types.ts'\n\nconst INDEX_SUFFIX = '.json'\nconst INDEX_VERSION = 1\n\nexport type ShellIndexDeps = { dir: string | null; generation: string; report: ShellErrorReporter }\n\nexport function freshSession(sessionId: string): SessionShells {\n return { sessionId, nextOrdinal: 1, entries: new Map(), chain: Promise.resolve(), pending: false }\n}\n\nexport function runningIn(state: SessionShells): ShellEntry[] {\n return [...state.entries.values()].filter((entry) => entry.info.status === 'running')\n}\n\nexport function persistIndex(dir: string | null, state: SessionShells, report: ShellErrorReporter): void {\n if (!dir || state.pending) {\n return\n }\n state.pending = true\n state.chain = state.chain\n .then(async () => {\n state.pending = false\n await writeJsonAtomic(indexPath(dir, state.sessionId), serializeIndex(state))\n })\n .catch((error: unknown) => report(error, { op: 'index', sessionId: state.sessionId }))\n}\n\nexport async function readIndex(deps: ShellIndexDeps, sessionId: string): Promise<SessionShells> {\n const { dir, report } = deps\n const state = freshSession(sessionId)\n if (!dir) {\n return state\n }\n const index = await loadIndexFile(dir, sessionId, report)\n if (!index) {\n return state\n }\n state.nextOrdinal = index.nextOrdinal\n if (restoreEntries(state, index, dir, deps.generation)) {\n persistIndex(dir, state, report)\n }\n return state\n}\n\nexport async function indexedSessions(dir: string, report: ShellErrorReporter): Promise<string[]> {\n let names: string[] = []\n try {\n names = await readdir(dir)\n } catch (error) {\n if (!isMissing(error)) {\n report(error, { op: 'index' })\n }\n }\n const ids: string[] = []\n for (const name of names) {\n if (!name.endsWith(INDEX_SUFFIX)) {\n continue\n }\n try {\n ids.push(decodeURIComponent(name.slice(0, -INDEX_SUFFIX.length)))\n } catch {\n continue\n }\n }\n return ids\n}\n\nexport function serializeIndex(state: SessionShells): StoredShellIndex {\n return {\n version: INDEX_VERSION,\n sessionId: state.sessionId,\n nextOrdinal: state.nextOrdinal,\n shells: [...state.entries.values()].map((entry) => ({ ...entry.info, generation: entry.generation, ...entry.artifact.stored() })),\n }\n}\n\nexport function parseIndex(value: unknown): StoredShellIndex {\n const index = value as Partial<StoredShellIndex> | null\n if (!index || index.version !== INDEX_VERSION || typeof index.sessionId !== 'string' || !Array.isArray(index.shells)) {\n throw new Error('unrecognised shell index')\n }\n const shells = index.shells.filter(\n (record): record is StoredShellRecord =>\n typeof record === 'object' && record !== null && typeof (record as StoredShellRecord).id === 'string',\n )\n const nextOrdinal = typeof index.nextOrdinal === 'number' && index.nextOrdinal > 0 ? index.nextOrdinal : 1\n return { version: INDEX_VERSION, sessionId: index.sessionId, nextOrdinal, shells }\n}\n\nfunction indexPath(dir: string, sessionId: string): string {\n return join(dir, `${encodeURIComponent(sessionId)}${INDEX_SUFFIX}`)\n}\n\nasync function loadIndexFile(dir: string, sessionId: string, report: ShellErrorReporter): Promise<StoredShellIndex | undefined> {\n let raw: string\n try {\n raw = await readFile(indexPath(dir, sessionId), 'utf8')\n } catch (error) {\n if (!isMissing(error)) {\n report(error, { op: 'index', sessionId })\n }\n return undefined\n }\n try {\n return parseIndex(JSON.parse(raw))\n } catch (error) {\n report(error, { op: 'index', sessionId })\n return undefined\n }\n}\n\nfunction restoreEntries(state: SessionShells, index: StoredShellIndex, base: string, generation: string): boolean {\n const now = Date.now()\n let dirty = false\n for (const record of index.shells) {\n const { generation: recordGeneration, output, artifact, ...info } = record\n if (info.status === 'running' && recordGeneration !== generation) {\n info.status = 'exited'\n info.endReason = 'server_restarted'\n info.endedAt = now\n delete info.exitCode\n delete info.signal\n dirty = true\n }\n state.entries.set(info.id, {\n info,\n generation: recordGeneration,\n artifact: new StoredArtifact(artifactPaths(base, state.sessionId, info.id), info, { output, artifact }),\n sinks: new Set(),\n listeners: new Set(),\n })\n }\n return dirty\n}\n","import { mkdtempSync } from 'node:fs'\nimport { rm, stat } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport { SHELL_REFUSAL, type Runner } from '@workerdeck/core'\nimport {\n ENGINE_CAPABILITIES,\n SHELL_ARTIFACT_MAX_BYTES,\n SHELL_ARTIFACT_TTL_MS,\n SHELL_INPUT_MAX,\n SHELL_LINGER_MS,\n SHELL_MAX_RUNNING_PER_SESSION,\n SHELL_MAX_RUNNING_TOTAL,\n SHELL_SPILL_BYTES,\n SHELL_TAIL_FLUSH_MS,\n SHELL_TAIL_RING_BYTES,\n type SessionInfo,\n type ShellEndReason,\n} from '@workerdeck/protocol'\nimport { readProcessTable, type TreeKillDeps } from './process-tree.ts'\nimport { artifactPaths, LiveArtifact, type ArtifactLimits } from './shell-artifact.ts'\nimport {\n applyAgentWrite,\n attachEntry,\n endEntry,\n fireListeners,\n killTrees,\n newShellInfo,\n readOutput,\n scheduleNotify,\n sourceFor,\n waitForChange,\n wireChild,\n} from './shell-entry.ts'\nimport { clampSize, loadPty, spawnShellChild } from './shell-env.ts'\nimport { ShellScreen } from './shell-screen.ts'\nimport { indexedSessions, persistIndex, readIndex, runningIn } from './shell-index.ts'\nimport type {\n KillTarget,\n PtyChild,\n PtyModule,\n SessionShells,\n ShellEntry,\n ShellErrorReporter,\n ShellRegistry,\n ShellRegistryOptions,\n ShellSpawned,\n ShellSpawnInput,\n} from './shell-types.ts'\n\nexport { SHELL_REFUSAL }\nexport { createShellDirectory, startShell, type ShellDirectoryDeps } from './shell-directory.ts'\nexport { clampSize, loadPty, loginShell, shellChildEnv } from './shell-env.ts'\nexport type {\n ShellAttachment,\n ShellErrorContext,\n ShellOutputQuery,\n ShellRegistry,\n ShellRegistryOptions,\n ShellSink,\n ShellSize,\n ShellSpawned,\n ShellSpawnInput,\n StoredShellIndex,\n StoredShellRecord,\n} from './shell-types.ts'\n\nconst SWEEP_INTERVAL_MS = 60 * 60_000\n\nexport function shellPermitted(shells: ShellRegistry | null, runner: Runner, operator: boolean): boolean {\n if (shells === null || !operator) {\n return false\n }\n const info = runner.info()\n const capabilities = info.capabilities ?? (info.engine ? ENGINE_CAPABILITIES[info.engine] : undefined)\n return capabilities?.hostCwd === true\n}\n\nexport function createShellRegistry(options: ShellRegistryOptions): ShellRegistry {\n const { generation } = options\n const dir = options.artifactDir\n const base = dir ?? mkdtempSync(join(tmpdir(), 'workerdeck-shells-'))\n const limits: ArtifactLimits = {\n spill: options.spillBytes ?? SHELL_SPILL_BYTES,\n cap: options.artifactMaxBytes ?? SHELL_ARTIFACT_MAX_BYTES,\n ring: options.tailRingBytes ?? SHELL_TAIL_RING_BYTES,\n }\n const tailFlushMs = options.tailFlushMs ?? SHELL_TAIL_FLUSH_MS\n const ttlMs = options.artifactTtlMs ?? SHELL_ARTIFACT_TTL_MS\n const perSession = options.maxRunningPerSession ?? SHELL_MAX_RUNNING_PER_SESSION\n const total = options.maxRunningTotal ?? SHELL_MAX_RUNNING_TOTAL\n const sweepIntervalMs = options.sweepIntervalMs ?? SWEEP_INTERVAL_MS\n const sessions = new Map<string, SessionShells>()\n const loading = new Map<string, Promise<SessionShells>>()\n let sweeper: NodeJS.Timeout | undefined\n let stopped = false\n\n const report: ShellErrorReporter = (error, context) => options.onError?.(error, context)\n const treeDeps: TreeKillDeps = {\n table: options.processTable ?? readProcessTable,\n signal: (pid, name) => void process.kill(pid, name),\n self: process.pid,\n }\n\n const find = (sessionId: string, id: string): ShellEntry | undefined => sessions.get(sessionId)?.entries.get(id)\n const located = (sessionId: string, shellId: string): KillTarget | undefined => {\n const state = sessions.get(sessionId)\n const entry = state?.entries.get(shellId)\n return state && entry ? { state, entry } : undefined\n }\n const runningAll = (): ShellEntry[] => [...sessions.values()].flatMap(runningIn)\n const persist = (state: SessionShells): void => persistIndex(dir, state, report)\n const fire = (entry: ShellEntry): void => fireListeners(entry, report)\n\n const load = (sessionId: string): Promise<SessionShells> => {\n const held = sessions.get(sessionId)\n if (held) {\n return Promise.resolve(held)\n }\n let inflight = loading.get(sessionId)\n if (!inflight) {\n inflight = readIndex({ dir, generation, report }, sessionId).then((state) => {\n sessions.set(sessionId, state)\n loading.delete(sessionId)\n return state\n })\n loading.set(sessionId, inflight)\n }\n return inflight\n }\n\n const settle = (state: SessionShells, entry: ShellEntry, reason: ShellEndReason): void => {\n if (entry.info.status !== 'running') {\n return\n }\n endEntry(entry, reason)\n persist(state)\n fire(entry)\n }\n\n const killEntries = (targets: KillTarget[], reason: ShellEndReason): number => {\n const running = targets.filter(({ entry }) => entry.info.status === 'running')\n killTrees(\n running.map(({ entry }) => entry),\n treeDeps,\n report,\n )\n for (const { state, entry } of running) {\n settle(state, entry, reason)\n }\n return running.length\n }\n\n const admit = async (runner: Runner): Promise<{ state: SessionShells; cwd: string; pty: PtyModule }> => {\n if (stopped) {\n throw new Error('the gateway is shutting down')\n }\n const state = await load(runner.id)\n const pty = await loadPty()\n if (!pty) {\n throw new Error(SHELL_REFUSAL)\n }\n const cwd = runner.info().cwd\n const dirStat = await stat(cwd).catch(() => undefined)\n if (!dirStat?.isDirectory()) {\n throw new Error(`the session's cwd is not a directory: ${cwd}`)\n }\n const inSession = runningIn(state).length\n if (inSession >= perSession) {\n throw new Error(`this session already has ${inSession} shells running (the limit is ${perSession})`)\n }\n const overall = runningAll().length\n if (overall >= total) {\n throw new Error(`the gateway already has ${overall} shells running (the limit is ${total})`)\n }\n return { state, cwd, pty }\n }\n\n const spawn = async ({ runner, command, owner }: ShellSpawnInput): Promise<ShellSpawned> => {\n const { state, cwd, pty } = await admit(runner)\n const info = newShellInfo(state, runner.id, command, cwd, owner)\n const artifact = new LiveArtifact(artifactPaths(base, info.sessionId, info.id), limits, (error) =>\n report(error, { op: 'artifact', sessionId: info.sessionId, shellId: info.id }),\n )\n const entry: ShellEntry = { info, generation, artifact, sinks: new Set(), listeners: new Set() }\n entry.screen = new ShellScreen(info.cols, info.rows)\n state.entries.set(info.id, entry)\n let child: PtyChild\n try {\n child = spawnShellChild(pty, cwd, command)\n } catch (error) {\n settle(state, entry, 'spawn_failed')\n throw error instanceof Error ? error : new Error('failed to start the shell')\n }\n wireChild(entry, child, artifact, tailFlushMs, {\n persist: () => persist(state),\n notify: () => scheduleNotify(entry, fire),\n exit: () => settle(state, entry, 'exit'),\n })\n if (options.timeoutMs !== undefined && options.timeoutMs > 0) {\n entry.clock = setTimeout(() => killEntries([{ state, entry }], 'timeout'), options.timeoutMs)\n entry.clock.unref()\n }\n persist(state)\n return { shell: { ...info }, source: sourceFor(entry, artifact) }\n }\n\n const sweep = async (): Promise<void> => {\n const now = Date.now()\n for (const state of sessions.values()) {\n let dirty = false\n for (const entry of state.entries.values()) {\n const { status, endedAt } = entry.info\n if (status !== 'exited' || endedAt === undefined || now - endedAt < ttlMs) {\n continue\n }\n state.entries.delete(entry.info.id)\n dirty = true\n try {\n await entry.artifact.remove()\n } catch (error) {\n report(error, { op: 'sweep', sessionId: state.sessionId, shellId: entry.info.id })\n }\n }\n if (dirty) {\n persist(state)\n }\n }\n }\n\n const hydrate = async (): Promise<void> => {\n if (dir) {\n for (const sessionId of await indexedSessions(dir, report)) {\n await load(sessionId)\n }\n }\n await sweep()\n if (!sweeper && !stopped) {\n sweeper = setInterval(() => void sweep(), sweepIntervalMs)\n sweeper.unref()\n }\n }\n\n const existing = (sessionId: string, shellId: string): ShellEntry => {\n const entry = find(sessionId, shellId)\n if (!entry) {\n throw new Error('unknown shell')\n }\n return entry\n }\n\n return {\n spawn,\n get: (sessionId, shellId) => {\n const entry = find(sessionId, shellId)\n return entry ? { ...entry.info } : undefined\n },\n list: (sessionId) => {\n const state = sessions.get(sessionId)\n if (!state) {\n return []\n }\n return [...state.entries.values()].map((entry) => ({ ...entry.info })).sort((a, b) => b.ordinal - a.ordinal)\n },\n running: () => runningAll().map((entry) => ({ ...entry.info })),\n kill: (sessionId, shellId, reason = 'killed') => {\n const target = located(sessionId, shellId)\n if (!target) {\n return undefined\n }\n killEntries([target], reason)\n return { ...target.entry.info }\n },\n setAgentWrite: (sessionId, shellId, enabled) => {\n const target = located(sessionId, shellId)\n if (!target) {\n return undefined\n }\n if (applyAgentWrite(target.entry, shellId, enabled)) {\n persist(target.state)\n fire(target.entry)\n }\n return { ...target.entry.info }\n },\n killAll: (reason) => {\n stopped = true\n if (sweeper) {\n clearInterval(sweeper)\n sweeper = undefined\n }\n return killEntries(\n [...sessions.values()].flatMap((state) => runningIn(state).map((entry) => ({ state, entry }))),\n reason,\n )\n },\n killAllSync: () => {\n killTrees(runningAll(), treeDeps, report)\n },\n attach: async (sessionId, shellId, sink) => attachEntry(existing(sessionId, shellId), sink),\n write: (sessionId, shellId, data) => {\n const entry = existing(sessionId, shellId)\n if (typeof data !== 'string' || data.length > SHELL_INPUT_MAX) {\n throw new Error(`shell input must be a string of at most ${SHELL_INPUT_MAX} characters`)\n }\n if (!entry.child) {\n throw new Error('the shell has exited')\n }\n entry.child.write(data)\n },\n resize: (sessionId, shellId, size) => {\n const entry = existing(sessionId, shellId)\n const next = clampSize(size)\n if (entry.child) {\n try {\n entry.child.resize(next.cols, next.rows)\n } catch {}\n entry.info.cols = next.cols\n entry.info.rows = next.rows\n entry.screen?.resize(next.cols, next.rows)\n }\n return next\n },\n output: async (sessionId, shellId, query) => {\n const entry = find(sessionId, shellId)\n return entry ? readOutput(entry, query) : undefined\n },\n applicationCursorKeys: (sessionId, shellId) => find(sessionId, shellId)?.screen?.applicationCursorKeys() ?? Promise.resolve(false),\n changed: (sessionId, shellId, timeoutMs) => waitForChange(find(sessionId, shellId), timeoutMs),\n hydrate,\n sweep,\n flush: async () => {\n const states = [...sessions.values()]\n await Promise.all(states.flatMap((state) => [...state.entries.values()].map((entry) => entry.artifact.idle())))\n await Promise.all(states.map((state) => state.chain))\n if (!dir && stopped) {\n await rm(base, { recursive: true, force: true }).catch(() => {})\n }\n },\n decorate: (info) => decorateSession(info, sessions.get(info.id)),\n watch: (runner) =>\n runner.subscribe((event) => {\n if (event.type === 'session_closed' || (event.type === 'status_changed' && event.status === 'parked')) {\n const state = sessions.get(runner.id)\n if (state) {\n killEntries(\n runningIn(state).map((entry) => ({ state, entry })),\n 'killed',\n )\n }\n }\n }, runner.info().lastSeq),\n }\n}\n\nfunction decorateSession(info: SessionInfo, state: SessionShells | undefined): SessionInfo {\n if (!state) {\n return info\n }\n const now = Date.now()\n const shells = [...state.entries.values()]\n .filter((entry) => {\n const { status, exitCode, endedAt } = entry.info\n return (\n status === 'running' || (typeof exitCode === 'number' && exitCode !== 0 && endedAt !== undefined && now - endedAt < SHELL_LINGER_MS)\n )\n })\n .map((entry) => ({ ...entry.info }))\n return shells.length > 0 ? { ...info, shells } : info\n}\n","import type { IncomingMessage } from 'node:http'\nimport type { WebSocket } from 'ws'\nimport { isSlashCommand, type Runner } from '@workerdeck/core'\nimport { PROTOCOL_VERSION, SHELL_COMMAND_MAX, type ClientFrame, type ServerFrame } from '@workerdeck/protocol'\nimport type { ServerContext } from '../context.ts'\nimport { permissionDecision, refusePermissionMode } from '../lib/permissions.ts'\nimport { engineOf } from '../lib/profile-env.ts'\nimport { takesLocalCommands } from '../services/shell-directory.ts'\nimport { shellPermitted, SHELL_REFUSAL, startShell, type ShellRegistry, type ShellSink, type ShellSize } from '../services/shells.ts'\n\n// What the upgrade established about the principal; computed once there so the attach never re-authenticates.\nexport type AttachAccess = { operator: boolean }\n\n// One per socket: its send path, its outbound backlog, and the shells it is attached to (shell id to the registry's detach).\ntype Client = { send: (frame: ServerFrame) => void; open: () => boolean; buffered: () => number; shells: Map<string, () => void> }\n\nexport const SHELL_SOCKET_BUFFERED_MAX = 4 * 1024 * 1024\nexport const SHELL_DETACHED_BACKPRESSURE = 'backpressure'\nexport const SESSION_SOCKET_BUFFERED_MAX = 16 * 1024 * 1024\nexport const SESSION_SOCKET_BACKPRESSURE_CODE = 1013\n\nexport function attachClient(ctx: ServerContext, ws: WebSocket, runner: Runner, req: IncomingMessage, access: AttachAccess): void {\n const { bridge, parking } = ctx\n const url = new URL(req.url ?? '/', 'http://internal')\n const afterSeq = Number(url.searchParams.get('afterSeq') ?? '0') || 0\n const truncateResults = url.searchParams.get('truncateResults') === '1'\n const imageRefs = url.searchParams.get('imageRefs') === '1'\n\n const send = (frame: ServerFrame): void => {\n if (ws.readyState === ws.OPEN) {\n ws.send(JSON.stringify(frame))\n }\n }\n const client: Client = { send, open: () => ws.readyState === ws.OPEN, buffered: () => ws.bufferedAmount, shells: new Map() }\n\n send({\n type: 'attached',\n protocolVersion: PROTOCOL_VERSION,\n session: ctx.projects.withProject(runner.info()),\n replayingFrom: afterSeq,\n ...(shellPermitted(ctx.shells, runner, access.operator) ? { shell: true } : {}),\n ...(ctx.pricingOverrides ? { pricingOverrides: ctx.pricingOverrides } : {}),\n })\n let live = false\n const unsubscribe = runner.subscribe(\n (event) => {\n // Replay is exempt: it is bounded by the log, and capping it would refuse every attach to a long session.\n if (live && ws.bufferedAmount > SESSION_SOCKET_BUFFERED_MAX) {\n ws.close(SESSION_SOCKET_BACKPRESSURE_CODE, 'backpressure')\n return\n }\n send({ type: 'event', event })\n },\n afterSeq,\n { coalesceReplay: true, truncateResults, imageRefs },\n )\n live = true\n const detachBridge = bridge.attach(runner.id, send)\n\n // After the replay is wired, so a fresh reading arrives as a live event behind the history rather than racing it.\n // The replay faithfully re-installs whatever this session last heard, which on an idle session can be days old,\n // and until now nothing in an attach asked for a newer one. Throttled inside the runner; failures are silent by\n // design (the control request is experimental, and a missing usage reading is not an attach failure).\n void runner.refreshUsage?.().catch(() => {})\n\n ws.on('message', (data: Buffer) => {\n let frame: ClientFrame\n try {\n frame = JSON.parse(data.toString('utf8')) as ClientFrame\n } catch {\n send({ type: 'protocol_error', message: 'invalid JSON frame' })\n return\n }\n handleCommand(ctx, frame, runner, access, client).catch((error: unknown) => {\n send({\n type: 'protocol_error',\n message: error instanceof Error ? error.message : 'command failed',\n })\n })\n })\n ws.on('close', () => {\n // Detach only. The registry's watch(runner) owns the close and park kills; a socket going away must not end a shell.\n detachShells(client)\n unsubscribe()\n detachBridge()\n parking.onDetach(runner.id)\n })\n}\n\nasync function handleCommand(ctx: ServerContext, frame: ClientFrame, runner: Runner, access: AttachAccess, client: Client): Promise<void> {\n const { attachmentStore, bridge } = ctx\n switch (frame.type) {\n case 'user_message': {\n // The one place `mentions` is ever set: this frame is a person typing. A slash command is\n // matched on the whole message by the CLI, so nothing may be appended to one, and a failure\n // to resolve is silent - a hint must never lose the text it was a hint about.\n const mentions = ctx.peers && !isSlashCommand(frame.text) ? await ctx.peers.mentions(runner.id, frame.text).catch(() => []) : []\n const options = mentions.length > 0 ? { mentions } : undefined\n if (!frame.attachmentIds?.length) {\n runner.sendMessage(frame.text, undefined, options)\n return\n }\n const resolved = attachmentStore.resolve(runner.id, frame.attachmentIds)\n if (!resolved.ok) {\n throw new Error(`unknown attachment(s): ${resolved.missing.join(', ')}`)\n }\n runner.sendMessage(frame.text, resolved.attachments, options)\n return\n }\n case 'permission_decision': {\n runner.resolvePermission(frame.requestId, permissionDecision(frame))\n return\n }\n case 'interrupt': {\n await runner.interrupt()\n return\n }\n case 'clear_context': {\n if (!runner.clearContext) {\n throw new Error(`the ${engineOf(runner.info())} engine cannot clear a conversation`)\n }\n await runner.clearContext()\n return\n }\n case 'set_permission_mode': {\n const refused = refusePermissionMode(frame.mode, { operator: access.operator, disableBypass: ctx.options.disableBypassPermissions })\n if (refused) {\n throw new Error(refused)\n }\n await runner.setPermissionMode(frame.mode)\n return\n }\n case 'set_model': {\n await runner.setModel(frame.model)\n return\n }\n case 'tool_call_result': {\n bridge.resolve(runner.id, frame.executionId, { output: frame.output, logs: frame.logs })\n return\n }\n case 'tool_call_error': {\n bridge.resolve(runner.id, frame.executionId, {\n reason: frame.reason,\n error: frame.error,\n logs: frame.logs,\n })\n return\n }\n case 'shell_command': {\n const shells = permittedShells(ctx, runner, access)\n if (typeof frame.command !== 'string' || frame.command.includes('\\0')) {\n throw new Error('shell command must be a string')\n }\n if (frame.command.length > SHELL_COMMAND_MAX) {\n throw new Error(`shell command exceeds ${SHELL_COMMAND_MAX} characters`)\n }\n if (frame.command.trim() === '') {\n throw new Error('shell command is empty')\n }\n if (!takesLocalCommands(runner)) {\n throw new Error(`the ${engineOf(runner.info())} engine cannot take shell output`)\n }\n await startShell(shells, { runner, command: frame.command, owner: 'user' })\n return\n }\n case 'shell_attach': {\n await attachShell(permittedShells(ctx, runner, access), client, runner.id, frame.shellId, { cols: frame.cols, rows: frame.rows })\n return\n }\n case 'shell_input': {\n permittedShells(ctx, runner, access).write(runner.id, frame.shellId, frame.data)\n return\n }\n case 'shell_resize': {\n permittedShells(ctx, runner, access).resize(runner.id, frame.shellId, { cols: frame.cols, rows: frame.rows })\n return\n }\n case 'shell_detach': {\n detachShell(client, frame.shellId)\n return\n }\n case 'close': {\n runner.close('client')\n return\n }\n default: {\n throw new Error(`unknown command: ${(frame as { type?: string }).type}`)\n }\n }\n}\n\nfunction permittedShells(ctx: ServerContext, runner: Runner, access: AttachAccess): ShellRegistry {\n if (ctx.shells === null || !shellPermitted(ctx.shells, runner, access.operator)) {\n throw new Error(SHELL_REFUSAL)\n }\n return ctx.shells\n}\n\nasync function attachShell(shells: ShellRegistry, client: Client, sessionId: string, shellId: string, size: ShellSize): Promise<void> {\n shells.resize(sessionId, shellId, size)\n let detach: (() => void) | undefined\n const drop = (reason: string): void => {\n if (detach === undefined || client.shells.get(shellId) !== detach) {\n return\n }\n client.shells.delete(shellId)\n detach()\n client.send({ type: 'shell_detached', shellId, reason })\n }\n const sink: ShellSink = {\n write: (data) => {\n if (client.buffered() > SHELL_SOCKET_BUFFERED_MAX) {\n drop(SHELL_DETACHED_BACKPRESSURE)\n return\n }\n client.send({ type: 'shell_output', shellId, data })\n },\n end: drop,\n }\n const attached = await shells.attach(sessionId, shellId, sink)\n if (!client.open()) {\n attached.detach()\n return\n }\n detachShell(client, shellId)\n if (attached.shell.status === 'running') {\n detach = attached.detach\n client.shells.set(shellId, detach)\n }\n const { shell, scrollback } = attached\n client.send({ type: 'shell_attached', shellId, shell, cols: shell.cols, rows: shell.rows, scrollback })\n}\n\nfunction detachShell(client: Client, shellId: string): void {\n client.shells.get(shellId)?.()\n client.shells.delete(shellId)\n}\n\nfunction detachShells(client: Client): void {\n for (const detach of client.shells.values()) {\n detach()\n }\n client.shells.clear()\n}\n","import type { IncomingMessage } from 'node:http'\nimport type { Duplex } from 'node:stream'\nimport type { WebSocketServer } from 'ws'\nimport type { ServerContext } from '../context.ts'\nimport { refuseUpgrade } from '../lib/http.ts'\nimport { parseSessionRoute } from '../lib/parse-route.ts'\nimport { sessionInfoOf } from './session-lookup.ts'\nimport { attachClient } from './ws.ts'\n\n// The scope check runs on what is already known before the wake, because waking rebuilds a runner and reconnects\n// MCP, which is not for someone about to get a 404; and again on the live runner, which is the one being attached.\nexport async function upgradeSession(\n ctx: ServerContext,\n wss: WebSocketServer,\n req: IncomingMessage,\n socket: Duplex,\n head: Buffer,\n): Promise<void> {\n const { auth, parking } = ctx\n const route = parseSessionRoute(ctx.basePath, req.url ?? '/')\n if (route?.kind !== 'ws') {\n socket.destroy()\n return\n }\n const authCtx = await auth.authenticate(req)\n if (!authCtx.ok) {\n refuseUpgrade(socket, '401 Unauthorized')\n return\n }\n const known = await sessionInfoOf(ctx, route.id)\n if (known && !auth.canSee(authCtx, known)) {\n refuseUpgrade(socket, '404 Not Found')\n return\n }\n const runner = await parking.ensureLive(route.id).catch(() => undefined)\n if (!runner || !auth.canSee(authCtx, runner.info())) {\n refuseUpgrade(socket, '404 Not Found')\n return\n }\n wss.handleUpgrade(req, socket, head, (ws) => {\n attachClient(ctx, ws, runner, req, { operator: auth.isOperator(authCtx) })\n })\n}\n","import { createHash } from 'node:crypto'\nimport { arch, homedir, hostname, platform } from 'node:os'\n\nlet cached: string | undefined\n\n// An opaque fingerprint of the machine this process runs on. A client that computes the same\n// string for itself is on the same box as the gateway, which is what lets it open the gateway's\n// paths natively instead of proxying them over `/fs`. Hashed so the answer carries no hostname\n// or home directory, and cached because none of its inputs move within a process.\n//\n// `apps/vscode/src/machine.ts` recomputes this byte for byte. The two must be changed together:\n// a drift only shows up as \"local files stopped opening natively\", never as a failure.\nexport function machineId(): string {\n cached ??= createHash('sha256').update([hostname(), platform(), arch(), homedir()].join('\\0')).digest('hex').slice(0, 32)\n return cached\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { ToolExecutionResult } from '@workerdeck/core'\nimport type { SubmitExecutionResultRequest } from '@workerdeck/protocol'\nimport { fail, json, readJsonBody, requireMethod } from '../lib/http.ts'\nimport type { AuthContext } from '../services/auth.ts'\nimport type { ServerContext } from '../context.ts'\nimport { sessionInfoOf } from './session-lookup.ts'\n\nexport async function handleExecutionResult(\n ctx: ServerContext,\n req: IncomingMessage,\n res: ServerResponse,\n pathname: string,\n auth: AuthContext,\n): Promise<void> {\n const { auth: authSvc, basePath, parking } = ctx\n const rest = pathname.slice((basePath + '/executions/').length).split('/')\n if (rest.length !== 2 || rest[1] !== 'result' || !rest[0]) {\n fail(404, 'not found')\n }\n requireMethod(req, 'POST')\n const executionId = decodeURIComponent(rest[0])\n const body = (await readJsonBody(req, ctx.maxBodyBytes)) as SubmitExecutionResultRequest\n let result: ToolExecutionResult\n if (body?.status === 'ok') {\n if (!body.output || typeof body.output !== 'object') {\n fail(400, \"output is required for status 'ok'\")\n }\n result = { status: 'ok', output: body.output.value, logs: body.logs }\n } else if (body?.status === 'failed') {\n if (typeof body.reason !== 'string' || typeof body.error !== 'string') {\n fail(400, \"reason and error are required for status 'failed'\")\n }\n result = { status: 'failed', reason: body.reason, error: body.error, logs: body.logs }\n } else {\n fail(400, \"status must be 'ok' or 'failed'\")\n }\n if (auth.allowedProfiles || auth.scope || ctx.options.authorizeSession) {\n const owner = parking.sessionFor(executionId)\n const info = owner === undefined ? undefined : await sessionInfoOf(ctx, owner)\n const profile = info?.profile\n // Indistinguishable from an unknown id on purpose: whether an execution exists elsewhere is not this caller's business.\n // A vanished session (`info === undefined`) refuses too - nobody passed canSee, and submitResult would disclose the owner id.\n const refused =\n owner === undefined ||\n info === undefined ||\n (auth.allowedProfiles !== undefined && profile !== undefined && !auth.allowedProfiles.includes(profile)) ||\n !authSvc.canSee(auth, info)\n if (refused) {\n fail(404, 'execution not found')\n }\n }\n const applied = await parking.submitResult(executionId, result)\n if (!applied) {\n fail(404, 'execution not found (unknown id, or its session has ended)')\n }\n json(res, 200, applied)\n}\n","import type { Dirent } from 'node:fs'\nimport { closeSync, constants, fstatSync, ftruncateSync, lstatSync, openSync, readFileSync, realpathSync, writeFileSync } from 'node:fs'\nimport { basename, dirname, isAbsolute, join, relative, sep } from 'node:path'\n\n// win32 lacks O_NOFOLLOW/O_NONBLOCK (undefined at runtime despite the typing): there they contribute 0 and the fstat gates stand alone.\nconst O_NOFOLLOW: number = constants.O_NOFOLLOW ?? 0\nconst O_NONBLOCK: number = constants.O_NONBLOCK ?? 0\n\nexport type HostFileRoot = {\n readonly configured: string\n readonly canonical: string\n}\n\nexport type HostFileRoots = { readonly roots: readonly HostFileRoot[] }\n\nexport function createHostFileRoots(roots: string[]): HostFileRoots {\n return {\n roots: roots.map((configured) => {\n if (invalidRequest(configured)) {\n throw new Error(`createHostFileRoots: root must be an absolute path: ${JSON.stringify(configured)}`)\n }\n let canonical: string\n try {\n canonical = realpathSync(configured)\n } catch {\n throw new Error(`createHostFileRoots: root does not exist: ${configured}`)\n }\n if (!lstatSync(canonical).isDirectory()) {\n throw new Error(`createHostFileRoots: root is not a directory: ${configured}`)\n }\n return { configured, canonical }\n }),\n }\n}\n\nexport type ResolveOutcome =\n | { ok: true; path: string; root: string; kind: 'file' | 'dir' }\n | { ok: false; status: 403 | 404; error: string }\n\ntype Refusal = { ok: false; status: 403 | 404; error: string }\n\nfunction refuse(status: 403 | 404, error: string): Refusal {\n return { ok: false, status, error }\n}\n\nfunction notFound(): Refusal {\n return refuse(404, 'not found')\n}\n\n// NUL is rejected before any fs call: Node throws a TypeError on one, and that must surface as a refusal rather than a 500.\nfunction invalidRequest(requested: string): boolean {\n return requested.length === 0 || requested.includes('\\0') || !isAbsolute(requested)\n}\n\n// A bare prefix check gets the boundary wrong (`/x/app` would swallow `/x/application`); both sides must be realpath output.\nexport function contained(rootCanonical: string, candidate: string): boolean {\n const rel = relative(rootCanonical, candidate)\n return rel === '' || (rel !== '..' && !rel.startsWith(`..${sep}`) && !isAbsolute(rel))\n}\n\nfunction rootContaining(roots: HostFileRoots, canonical: string): HostFileRoot | undefined {\n return roots.roots.find((root) => contained(root.canonical, canonical))\n}\n\nexport function resolveExisting(roots: HostFileRoots, requested: string): ResolveOutcome {\n if (invalidRequest(requested)) {\n return refuse(403, 'invalid path')\n }\n let canonical: string\n try {\n canonical = realpathSync(requested)\n } catch {\n return notFound()\n }\n const root = rootContaining(roots, canonical)\n if (!root) {\n return notFound()\n }\n let target\n try {\n // realpath output cannot name a symlink, so lstat === stat modulo a race - and a swap inside the window then classifies as neither.\n target = lstatSync(canonical)\n } catch {\n return notFound()\n }\n if (target.isFile()) {\n return { ok: true, path: canonical, root: root.canonical, kind: 'file' }\n }\n if (target.isDirectory()) {\n return { ok: true, path: canonical, root: root.canonical, kind: 'dir' }\n }\n return refuse(403, 'not a regular file or directory')\n}\n\n// Only the final component may be new: a missing target canonicalizes its parent, so a dangling symlink sitting there is refused, not created through.\nexport function resolveForWrite(roots: HostFileRoots, requested: string): ResolveOutcome {\n if (invalidRequest(requested)) {\n return refuse(403, 'invalid path')\n }\n try {\n const canonical = realpathSync(requested)\n const root = rootContaining(roots, canonical)\n if (!root) {\n return notFound()\n }\n const target = lstatSync(canonical)\n if (target.isDirectory()) {\n return refuse(403, 'is a directory')\n }\n if (!target.isFile()) {\n return refuse(403, 'not a regular file')\n }\n return { ok: true, path: canonical, root: root.canonical, kind: 'file' }\n } catch {}\n const base = basename(requested)\n if (base === '' || base === '.' || base === '..') {\n return refuse(403, 'invalid path')\n }\n let parent: string\n try {\n parent = realpathSync(dirname(requested))\n } catch {\n return notFound()\n }\n const root = rootContaining(roots, parent)\n if (!root) {\n return notFound()\n }\n try {\n if (!lstatSync(parent).isDirectory()) {\n return notFound()\n }\n } catch {\n return notFound()\n }\n const path = join(parent, base)\n // Redundant by construction (basename() cannot smuggle a separator) - kept because this is the line an escape would have to cross.\n if (!contained(root.canonical, path)) {\n return notFound()\n }\n try {\n lstatSync(path)\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n return { ok: true, path, root: root.canonical, kind: 'file' }\n }\n return notFound()\n }\n return notFound()\n}\n\nexport type HostEntryKind = 'file' | 'dir' | 'symlink' | 'other'\n\nexport function entryKind(entry: Dirent): HostEntryKind {\n if (entry.isSymbolicLink()) {\n return 'symlink'\n }\n if (entry.isFile()) {\n return 'file'\n }\n if (entry.isDirectory()) {\n return 'dir'\n }\n return 'other'\n}\n\nexport type ReadOutcome = { ok: true; data: Buffer } | Refusal\n\nexport function readContained(path: string): ReadOutcome {\n let fd: number\n try {\n fd = openSync(path, constants.O_RDONLY | O_NOFOLLOW | O_NONBLOCK)\n } catch (err) {\n return (err as NodeJS.ErrnoException).code === 'ENOENT' ? notFound() : refuse(403, 'refused')\n }\n try {\n if (!fstatSync(fd).isFile()) {\n return refuse(403, 'not a regular file')\n }\n return { ok: true, data: readFileSync(fd) }\n } catch {\n return refuse(403, 'refused')\n } finally {\n closeSync(fd)\n }\n}\n\nexport type WriteOutcome = { ok: true } | Refusal\n\nexport function writeContained(path: string, data: string | Uint8Array): WriteOutcome {\n let fd: number\n try {\n fd = openSync(path, constants.O_WRONLY | constants.O_CREAT | O_NOFOLLOW | O_NONBLOCK, 0o644)\n } catch (err) {\n return (err as NodeJS.ErrnoException).code === 'ENOENT' ? notFound() : refuse(403, 'refused')\n }\n try {\n if (!fstatSync(fd).isFile()) {\n return refuse(403, 'not a regular file')\n }\n ftruncateSync(fd)\n writeFileSync(fd, data)\n return { ok: true }\n } catch {\n return refuse(403, 'refused')\n } finally {\n closeSync(fd)\n }\n}\n","import { readdirSync } from 'node:fs'\nimport { join, relative } from 'node:path'\nimport { entryKind } from './host-files.ts'\n\nexport const DEFAULT_IGNORED_DIRS = [\n '.git',\n '.hg',\n '.svn',\n 'node_modules',\n '.next',\n '.nuxt',\n '.svelte-kit',\n '.turbo',\n '.cache',\n 'dist',\n 'build',\n 'out',\n 'target',\n '.venv',\n 'venv',\n '__pycache__',\n '.pytest_cache',\n '.gradle',\n 'Pods',\n 'DerivedData',\n // Swift Package Manager: its object files carry the source names, so `@` answers `Transcript.o` before `Transcript.swift` without this.\n '.build',\n]\n\nexport type FoundFile = {\n path: string\n relative: string\n}\n\nexport type SearchResult = {\n matches: FoundFile[]\n truncated: boolean\n}\n\nexport type SearchOptions = {\n query?: string\n limit?: number\n ignore?: readonly string[]\n maxScanned?: number\n}\n\nexport function searchFiles(base: string, options: SearchOptions = {}): SearchResult {\n const limit = options.limit ?? 50\n const maxScanned = options.maxScanned ?? 20_000\n const ignore = new Set(options.ignore ?? DEFAULT_IGNORED_DIRS)\n const needle = (options.query ?? '').toLowerCase()\n\n const found: { file: FoundFile; score: number; depth: number }[] = []\n const queue: { dir: string; depth: number }[] = [{ dir: base, depth: 0 }]\n let scanned = 0\n let exhausted = true\n\n while (queue.length > 0) {\n const { dir, depth } = queue.shift()!\n let entries\n try {\n entries = readdirSync(dir, { withFileTypes: true })\n } catch {\n continue\n }\n for (const entry of entries) {\n if (++scanned > maxScanned) {\n exhausted = false\n queue.length = 0\n break\n }\n const kind = entryKind(entry)\n if (kind === 'dir') {\n if (!ignore.has(entry.name)) {\n queue.push({ dir: join(dir, entry.name), depth: depth + 1 })\n }\n continue\n }\n if (kind !== 'file') {\n continue\n }\n const path = join(dir, entry.name)\n const rel = relative(base, path)\n const score = scoreMatch(rel, entry.name, needle)\n if (score !== null) {\n found.push({ file: { path, relative: rel }, score, depth })\n }\n }\n }\n\n found.sort(\n (a, b) =>\n b.score - a.score ||\n a.depth - b.depth ||\n a.file.relative.length - b.file.relative.length ||\n a.file.relative.localeCompare(b.file.relative),\n )\n return {\n matches: found.slice(0, limit).map((f) => f.file),\n truncated: !exhausted || found.length > limit,\n }\n}\n\nfunction scoreMatch(relativePath: string, name: string, needle: string): number | null {\n if (needle === '') {\n return 0\n }\n const inName = subsequenceScore(name.toLowerCase(), needle)\n if (inName !== null) {\n return inName + 1000\n }\n return subsequenceScore(relativePath.toLowerCase(), needle)\n}\n\nfunction subsequenceScore(haystack: string, needle: string): number | null {\n let score = 0\n let from = 0\n let previous = -2\n for (const char of needle) {\n const at = haystack.indexOf(char, from)\n if (at === -1) {\n return null\n }\n if (at === previous + 1) {\n score += 8\n }\n if (at === 0) {\n score += 4\n }\n from = at + 1\n previous = at\n }\n // Shorter haystacks matched the same needle more tightly.\n return score - haystack.length / 100\n}\n","import { lstatSync, readdirSync, type Dirent } from 'node:fs'\nimport { basename, join } from 'node:path'\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { WriteHostFileRequest } from '@workerdeck/protocol'\nimport { asUtf8, fail, hashBytes, json, readJsonBody, requireMethod } from '../lib/http.ts'\nimport { searchFiles } from '../services/host-file-search.ts'\nimport { entryKind, readContained, resolveExisting, resolveForWrite, writeContained, type HostFileRoots } from '../services/host-files.ts'\nimport type { ServerContext } from '../context.ts'\n\ntype FsCall = { ctx: ServerContext; hostFiles: HostFileRoots; req: IncomingMessage; res: ServerResponse; url: URL }\n\ntype ExistingKind = 'file' | 'dir'\n\nconst KIND_REFUSAL: Record<ExistingKind, string> = { dir: 'not a directory', file: 'not a regular file' }\n\nconst FS_ROUTES = new Map<string, (call: FsCall) => Promise<void> | void>([\n ['roots', handleRoots],\n ['find', handleFind],\n ['list', handleList],\n ['read', handleRead],\n ['write', handleWrite],\n])\n\nfunction kindRank(type: string): number {\n return type === 'dir' ? 0 : 1\n}\n\nexport async function handleHostFiles(ctx: ServerContext, req: IncomingMessage, res: ServerResponse, pathname: string): Promise<void> {\n const { basePath, hostFiles } = ctx\n if (!hostFiles) {\n fail(404, 'host file access is not configured on this server')\n }\n const handler = FS_ROUTES.get(pathname.slice((basePath + '/fs/').length))\n if (!handler) {\n fail(404, 'not found')\n }\n await handler({ ctx, hostFiles, req, res, url: new URL(req.url ?? '/', 'http://internal') })\n}\n\nfunction requireExisting(hostFiles: HostFileRoots, url: URL, kind: ExistingKind): string {\n const requested = url.searchParams.get('path')\n if (!requested) {\n fail(400, 'path is required')\n }\n const resolved = resolveExisting(hostFiles, requested)\n if (!resolved.ok) {\n fail(resolved.status, resolved.error)\n }\n if (resolved.kind !== kind) {\n fail(400, KIND_REFUSAL[kind])\n }\n return resolved.path\n}\n\nfunction handleRoots({ ctx, hostFiles, req, res }: FsCall): void {\n requireMethod(req, 'GET')\n // The canonical spelling, not the operator's: a client round-tripping a root it was given must land on the same tree.\n json(res, 200, {\n roots: hostFiles.roots.map(({ canonical }) => ({\n path: canonical,\n name: basename(canonical) || canonical,\n })),\n canWrite: ctx.hostFilesWritable,\n })\n}\n\nfunction handleFind({ ctx, hostFiles, req, res, url }: FsCall): void {\n requireMethod(req, 'GET')\n const base = requireExisting(hostFiles, url, 'dir')\n // Clamped, not validated: this runs per keystroke from a phone.\n const asked = Number(url.searchParams.get('limit') ?? '')\n const limit = Number.isFinite(asked) && asked > 0 ? Math.min(asked, 200) : 50\n const result = searchFiles(base, {\n query: url.searchParams.get('q') ?? '',\n limit,\n ignore: ctx.options.hostFiles?.ignore,\n })\n json(res, 200, { base, ...result })\n}\n\nfunction handleList({ ctx, hostFiles, req, res, url }: FsCall): void {\n requireMethod(req, 'GET')\n const dir = requireExisting(hostFiles, url, 'dir')\n const { maxHostDirEntries } = ctx\n let names: Dirent[]\n try {\n names = readdirSync(dir, { withFileTypes: true })\n } catch {\n fail(403, 'directory is not readable')\n }\n const truncated = names.length > maxHostDirEntries\n const entries = names.slice(0, maxHostDirEntries).map((entry) => {\n const path = join(dir, entry.name)\n const type = entryKind(entry)\n // Never stat *through* a link: a directory holding a link to a fifo would become unlistable.\n let bytes: number | undefined\n let modifiedAt: number | undefined\n if (type === 'file') {\n try {\n const s = lstatSync(path)\n bytes = s.size\n modifiedAt = s.mtimeMs\n } catch {}\n }\n return { name: entry.name, path, type, bytes, modifiedAt }\n })\n entries.sort((a, b) => kindRank(a.type) - kindRank(b.type) || a.name.localeCompare(b.name))\n json(res, 200, { path: dir, entries, ...(truncated ? { truncated } : {}) })\n}\n\nfunction handleRead({ ctx, hostFiles, req, res, url }: FsCall): void {\n requireMethod(req, 'GET')\n const path = requireExisting(hostFiles, url, 'file')\n const { maxHostFileBytes } = ctx\n const tooLarge = `file is larger than ${maxHostFileBytes} bytes`\n // Advisory pre-check only - the authoritative cap is on the bytes actually read, since the file can grow before the open.\n let stats\n try {\n stats = lstatSync(path)\n } catch {\n fail(404, 'not found')\n }\n if (stats.size > maxHostFileBytes) {\n fail(413, tooLarge)\n }\n const read = readContained(path)\n if (!read.ok) {\n fail(read.status, read.error)\n }\n if (read.data.length > maxHostFileBytes) {\n fail(413, tooLarge)\n }\n const text = asUtf8(read.data)\n json(res, 200, {\n path,\n content: text ?? read.data.toString('base64'),\n encoding: text === null ? 'base64' : 'utf8',\n bytes: read.data.length,\n hash: hashBytes(read.data),\n modifiedAt: stats.mtimeMs,\n })\n}\n\nasync function handleWrite({ ctx, hostFiles, req, res }: FsCall): Promise<void> {\n const { maxHostFileBytes } = ctx\n requireMethod(req, 'PUT')\n if (!ctx.hostFilesWritable) {\n fail(403, 'host file writes are not enabled on this server')\n }\n const body = (await readJsonBody(req, ctx.maxBodyBytes)) as WriteHostFileRequest\n if (!body.path || typeof body.path !== 'string') {\n fail(400, 'path is required')\n }\n if (typeof body.content !== 'string') {\n fail(400, 'content is required')\n }\n if (body.encoding !== undefined && body.encoding !== 'utf8' && body.encoding !== 'base64') {\n fail(400, \"encoding must be 'utf8' or 'base64'\")\n }\n const resolved = resolveForWrite(hostFiles, body.path)\n if (!resolved.ok) {\n fail(resolved.status, resolved.error)\n }\n const next = Buffer.from(body.content, body.encoding ?? 'utf8')\n if (next.length > maxHostFileBytes) {\n fail(413, `content is larger than ${maxHostFileBytes} bytes`)\n }\n // Existence is decided by the read, not a stat: only ENOENT is 404, so anything else refuses rather than being clobbered as a create.\n const current = readContained(resolved.path)\n if (!current.ok && current.status !== 404) {\n fail(current.status, current.error)\n }\n const existing = current.ok ? current.data : null\n if (existing && !body.expectedHash) {\n fail(409, 'file exists - pass expectedHash to overwrite it')\n }\n if (existing && hashBytes(existing) !== body.expectedHash) {\n fail(409, 'file changed on disk since it was read')\n }\n if (!existing && body.expectedHash) {\n fail(409, 'file no longer exists')\n }\n const written = writeContained(resolved.path, next)\n if (!written.ok) {\n fail(written.status, written.error)\n }\n let writtenAt = 0\n try {\n writtenAt = lstatSync(resolved.path).mtimeMs\n } catch {}\n json(res, 200, {\n path: resolved.path,\n bytes: next.length,\n hash: hashBytes(next),\n modifiedAt: writtenAt,\n })\n}\n","import type { AiSdkRunnerConfig, CodexRunnerConfig, SessionRunnerConfig } from '@workerdeck/core'\nimport type { CreateSessionRequest } from '@workerdeck/protocol'\n\ntype HostOnlyKey = Exclude<keyof SessionRunnerConfig | keyof CodexRunnerConfig | keyof AiSdkRunnerConfig, keyof CreateSessionRequest>\n\n// Every runner-config key that is not on the wire type. Typed as a record over that difference so a host-only field\n// added to any engine's config without an entry here fails typecheck, as does an entry since promoted onto\n// CreateSessionRequest. `durable` keys survive into a stored session record; `transient` ones are rederived on rebuild.\nconst HOST_ONLY_KEY_TABLE: Record<HostOnlyKey, 'durable' | 'transient'> = {\n epoch: 'durable',\n pricing: 'transient',\n queryFn: 'transient',\n env: 'transient',\n pathToClaudeCodeExecutable: 'durable',\n extraOptions: 'transient',\n instructions: 'transient',\n defaultApprovalTimeoutMs: 'durable',\n backfillHistory: 'durable',\n historyFn: 'transient',\n sessionInfoFn: 'transient',\n peers: 'transient',\n shells: 'transient',\n shellAgentWrite: 'transient',\n createdByOperator: 'durable',\n fallbackTitle: 'transient',\n connectFn: 'transient',\n codexHome: 'durable',\n codexPathOverride: 'durable',\n languageModel: 'transient',\n tools: 'transient',\n maxSteps: 'durable',\n executor: 'transient',\n executableTools: 'transient',\n vfs: 'transient',\n executionLimits: 'durable',\n executionBackend: 'transient',\n toolTitles: 'transient',\n shouldApprove: 'transient',\n resolveModel: 'transient',\n reportMcpServers: 'transient',\n onClose: 'transient',\n restore: 'transient',\n}\n\nexport const HOST_ONLY_KEYS: ReadonlySet<string> = new Set(Object.keys(HOST_ONLY_KEY_TABLE))\n\nexport const DURABLE_HOST_KEYS: readonly string[] = Object.entries(HOST_ONLY_KEY_TABLE)\n .filter(([, lifetime]) => lifetime === 'durable')\n .map(([key]) => key)\n","import { pickCreateSessionRequest, type CreateSessionRequest, type ProfileInfo } from '@workerdeck/protocol'\nimport type { ServerContext } from '../context.ts'\nimport { HOST_ONLY_KEYS } from '../lib/host-only-keys.ts'\nimport type { Refusal } from '../lib/http.ts'\nimport { refusePermissionMode } from '../lib/permissions.ts'\nimport { engineOf } from '../lib/profile-env.ts'\nimport type { AuthContext } from '../services/auth.ts'\n\nexport { HOST_ONLY_KEYS }\n\nexport type VettedCreateRequest = { ok: true; request: CreateSessionRequest } | { ok: false; status: number; error: string }\n\n// The one create-validation ladder, run by both create doors - `POST /sessions` and the\n// `session` block of `POST /jobs`. The scope design claims the two are indistinguishable, so\n// the order and the refusals have to come from a single place rather than two copies that can\n// drift. The body is untrusted JSON: it is projected onto the wire type, never cast to it, and\n// the projected object is what the ladder mutates (inert fields stripped, profile name pinned)\n// and what the caller must hand on.\nexport function vetCreateRequest(ctx: ServerContext, body: unknown, auth: AuthContext): VettedCreateRequest {\n if (typeof body !== 'object' || body === null || Array.isArray(body)) {\n return { ok: false, status: 400, error: 'request body must be a JSON object' }\n }\n const hostOnly = Object.keys(body).filter((key) => HOST_ONLY_KEYS.has(key))\n if (hostOnly.length > 0) {\n return {\n ok: false,\n status: 400,\n error:\n `host-only runner config is not accepted on a session request: ${hostOnly.join(', ')} ` +\n \"(set it from the gateway's buildRunnerConfig hook)\",\n }\n }\n const req = pickCreateSessionRequest(body as Record<string, unknown>)\n const { availability, factory } = ctx\n const early = factory.applyScope(req, auth) ?? refusal(403, factory.applyBypassPolicy(req))\n if (early) {\n return { ok: false, ...early }\n }\n const resolved = factory.resolveProfile(req.profile, auth.allowedProfiles)\n if (!resolved.ok) {\n return resolved\n }\n const refused =\n refusal(403, refuseHostAuthority(ctx, req, resolved.profile, auth)) ??\n availability.checkAvailable(resolved.profile) ??\n factory.checkCwd(req, resolved.profile) ??\n refusal(400, factory.checkPermissionMode(req.permissionMode, resolved.profile) ?? factory.checkEngineGrants(req, resolved.profile))\n if (refused) {\n return { ok: false, ...refused }\n }\n factory.stripInertFields(req, resolved.profile)\n req.profile = resolved.profile?.name\n return { ok: true, request: req }\n}\n\nfunction refusal(status: number, error: string | null): Refusal | null {\n return error === null ? null : { status, error }\n}\n\n// A non-operator is an embedded end user: nothing on its request may reach past what the profile grants into the\n// gateway's own authority over the host. Operators (the tenant model's one key) are untouched.\nfunction refuseHostAuthority(\n ctx: ServerContext,\n req: CreateSessionRequest,\n profile: ProfileInfo | undefined,\n auth: AuthContext,\n): string | null {\n if (ctx.auth.isOperator(auth)) {\n return null\n }\n const engine = engineOf(profile)\n const name = profile?.name ?? 'default'\n if ((engine === 'claude' || engine === 'codex') && !auth.allowedProfiles?.includes(name)) {\n return `profile '${name}' runs the ${engine} engine on the host; a non-operator caller needs it named in its allowedProfiles`\n }\n const mode = refusePermissionMode(req.permissionMode, { operator: false })\n if (mode) {\n return mode\n }\n if (req.allowDangerouslySkipPermissions) {\n return 'allowDangerouslySkipPermissions is reserved to operators'\n }\n if (req.settingSources !== undefined && req.settingSources.length > 0) {\n return 'settingSources is reserved to operators: it loads hooks and settings from the host'\n }\n const servers = typeof req.mcpServers === 'object' && req.mcpServers !== null ? Object.values(req.mcpServers) : []\n if (!servers.every(isRemoteMcpServer)) {\n return 'a stdio MCP server is reserved to operators: it runs a command on the host'\n }\n if (req.resume !== undefined && !ownsSdkSession(ctx, auth, req.resume)) {\n return 'resume is limited to a live session this caller can see'\n }\n return null\n}\n\nfunction ownsSdkSession(ctx: ServerContext, auth: AuthContext, sdkSessionId: string): boolean {\n return ctx.registry.list().some((info) => info.sdkSessionId === sdkSessionId && ctx.auth.canSee(auth, info))\n}\n\nfunction isRemoteMcpServer(server: unknown): boolean {\n const type = (server as { type?: unknown } | null)?.type\n return type === 'http' || type === 'sse'\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { CreateJobRequest } from '@workerdeck/protocol'\nimport { fail, json, readJsonBody, requireMethod } from '../lib/http.ts'\nimport { vetCreateRequest } from './create-vet.ts'\nimport type { AuthContext } from '../services/auth.ts'\nimport type { ServerContext } from '../context.ts'\n\nexport async function handleJobs(\n ctx: ServerContext,\n req: IncomingMessage,\n res: ServerResponse,\n pathname: string,\n auth: AuthContext,\n): Promise<void> {\n const { auth: authSvc, basePath, queue } = ctx\n if (!queue) {\n fail(404, 'job queue not configured')\n }\n if (pathname === basePath + '/queue') {\n requireMethod(req, 'GET')\n if (!authSvc.isOperator(auth)) {\n fail(404, 'not found')\n }\n json(res, 200, { stats: await queue.stats() })\n return\n }\n const rest = pathname.slice((basePath + '/jobs').length).replace(/^\\//, '')\n if (rest === '') {\n requireMethod(req, 'GET', 'POST')\n if (req.method === 'GET') {\n const jobs = await queue.list()\n json(res, 200, { jobs: jobs.filter((job) => authSvc.canSeeJob(auth, job)) })\n return\n }\n const body = (await readJsonBody(req, ctx.maxBodyBytes)) as CreateJobRequest | null\n if (!body?.session || typeof body.session !== 'object') {\n fail(400, 'session is required')\n }\n const prompt = body.session.prompt\n if (!prompt || typeof prompt !== 'string') {\n fail(400, 'session.prompt is required')\n }\n const vetted = vetCreateRequest(ctx, body.session, auth)\n if (!vetted.ok) {\n fail(vetted.status, vetted.error)\n }\n try {\n // The projected block is what gets stored: the queue spreads the record's session into a runner config later.\n json(res, 201, { job: await queue.submit({ ...body, session: { ...vetted.request, prompt } }) })\n } catch (error) {\n json(res, 400, { error: error instanceof Error ? error.message : 'invalid job' })\n }\n return\n }\n const id = decodeURIComponent(rest)\n if (id.includes('/')) {\n fail(404, 'not found')\n }\n requireMethod(req, 'GET', 'DELETE')\n // Checked before the cancel: a refused caller must not be able to kill a run and then be told it does not exist.\n const existing = await queue.get(id)\n if (!existing || !authSvc.canSeeJob(auth, existing)) {\n fail(404, 'job not found')\n }\n const job = req.method === 'GET' ? existing : await queue.cancel(id)\n if (!job) {\n fail(404, 'job not found')\n }\n json(res, 200, { job })\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { ProfileInfo, UpdateProfileRequest } from '@workerdeck/protocol'\nimport { fail, json, readJsonBody, requireMethod } from '../lib/http.ts'\nimport { readProfileConfig } from '../lib/profile-env.ts'\nimport type { AuthContext } from '../services/auth.ts'\nimport type { ProfileService } from '../services/profiles.ts'\nimport type { ServerContext } from '../context.ts'\n\nexport async function handleProfiles(\n ctx: ServerContext,\n req: IncomingMessage,\n res: ServerResponse,\n pathname: string,\n auth: AuthContext,\n): Promise<void> {\n const { auth: authSvc, availability, basePath, profiles } = ctx\n const rest = pathname.slice((basePath + '/profiles').length).replace(/^\\//, '')\n if (rest === '') {\n requireMethod(req, 'GET', 'POST')\n if (req.method === 'GET') {\n const visible = auth.allowedProfiles ? profiles.all().filter((p) => auth.allowedProfiles!.includes(p.name)) : profiles.all()\n availability.refresh(visible)\n json(res, 200, {\n profiles: visible.map((p) => profiles.forResponse(p)),\n canManage: profiles.manageGuard(auth) === null,\n })\n return\n }\n refuseWith(profiles.manageGuard(auth))\n const body = (await readJsonBody(req, ctx.maxBodyBytes)) as ProfileInfo\n if (!body.name || typeof body.name !== 'string') {\n fail(400, 'name is required')\n }\n if (profiles.get(body.name)) {\n fail(409, `profile already exists: ${body.name}`)\n }\n await saveManaged(profiles, res, body)\n return\n }\n const name = decodeURIComponent(rest)\n const profile = name.includes('/') ? undefined : profiles.get(name)\n if (!profile) {\n fail(404, 'profile not found')\n }\n if (auth.allowedProfiles && !auth.allowedProfiles.includes(profile.name)) {\n fail(403, `profile not allowed: ${profile.name}`)\n }\n requireMethod(req, 'GET', 'PATCH', 'DELETE')\n if (req.method === 'GET') {\n json(res, 200, {\n profile: profiles.forResponse(profile),\n config: authSvc.isOperator(auth) ? readProfileConfig(profile) : undefined,\n })\n return\n }\n refuseWith(profiles.manageGuard(auth) ?? profiles.declaredGuard(profile))\n if (req.method === 'DELETE') {\n await ctx.options.profileStore!.delete(profile.name)\n await profiles.refreshStored()\n res.writeHead(204).end()\n return\n }\n const patch = (await readJsonBody(req, ctx.maxBodyBytes)) as UpdateProfileRequest\n await saveManaged(profiles, res, { ...profile, ...patch, name: profile.name })\n}\n\nfunction refuseWith(refused: { status: number; error: string } | null): void {\n if (refused) {\n fail(refused.status, refused.error)\n }\n}\n\nasync function saveManaged(profiles: ProfileService, res: ServerResponse, incoming: ProfileInfo): Promise<void> {\n const saved = await profiles.saveManaged(incoming)\n if (!saved.ok) {\n fail(saved.status, saved.error)\n }\n json(res, 200, { profile: saved.profile })\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { ProfileInfo, SdkSessionSummary } from '@workerdeck/protocol'\nimport { fail, json, requireMethod } from '../lib/http.ts'\nimport { cwdAllowed, engineOf } from '../lib/profile-env.ts'\nimport type { SdkSessionLister } from '../options.ts'\nimport type { AuthContext } from '../services/auth.ts'\nimport type { ServerContext } from '../context.ts'\n\n// A summary with no `cwd` cannot be shown to be inside the roots, so it is dropped.\nfunction withinRoots(sessions: SdkSessionSummary[], roots: string[], limit?: number, offset = 0): SdkSessionSummary[] {\n const allowed = sessions.filter((s) => s.cwd !== undefined && cwdAllowed(s.cwd, roots)).sort((a, b) => b.lastModified - a.lastModified)\n return limit === undefined ? allowed.slice(offset) : allowed.slice(offset, offset + limit)\n}\n\nexport async function handleSdkSessions(ctx: ServerContext, req: IncomingMessage, res: ServerResponse, auth: AuthContext): Promise<void> {\n const { adapterFor, factory, profiles } = ctx\n requireMethod(req, 'GET')\n const url = new URL(req.url ?? '/', 'http://internal')\n const dir = url.searchParams.get('dir') ?? undefined\n const roots = ctx.options.allowedCwdRoots\n const limit = Number(url.searchParams.get('limit') ?? '') || undefined\n const offset = Number(url.searchParams.get('offset') ?? '') || undefined\n const requested = url.searchParams.get('profile') ?? undefined\n let profile: ProfileInfo | undefined\n if (requested !== undefined) {\n const resolved = factory.resolveProfile(requested, auth.allowedProfiles)\n if (!resolved.ok) {\n fail(resolved.status, resolved.error)\n }\n profile = resolved.profile\n } else {\n // Implicit only when unambiguous AND permitted: a caller scoped away from the one profile falls back to the legacy listing.\n const all = profiles.all()\n if (all.length === 1 && (!auth.allowedProfiles || auth.allowedProfiles.includes(all[0]!.name))) {\n profile = all[0]\n }\n }\n const adapter = adapterFor(profile?.engine)\n if (!adapter.capabilities.listSessions) {\n json(res, 400, {\n error: `profile '${profile?.name ?? 'default'}' runs the ${engineOf(profile)} engine, which has no browsable session store`,\n })\n return\n }\n const lister: SdkSessionLister =\n engineOf(profile) === 'claude' && ctx.listSdkSessions\n ? ctx.listSdkSessions\n : (params) => {\n if (!adapter.listSessions) {\n throw new Error(`the ${engineOf(profile)} engine does not implement session listing`)\n }\n return adapter.listSessions({\n ...params,\n profile,\n env: profile ? factory.sessionEnvFor(profile) : process.env,\n })\n }\n const withinScope = roots !== undefined && roots.length > 0\n if (withinScope && dir && !cwdAllowed(dir, roots)) {\n fail(403, 'dir is outside the allowed roots')\n }\n try {\n if (withinScope && !dir) {\n // A bare listing spans every project on the host, so it filters after listing - which is why the paging is applied here too.\n json(res, 200, { sdkSessions: withinRoots(await lister({}), roots, limit, offset) })\n return\n }\n json(res, 200, { sdkSessions: await lister({ dir, limit, offset }) })\n } catch (error) {\n json(res, 500, { error: error instanceof Error ? error.message : 'failed to list sessions' })\n }\n}\n","import { readFile, readdir, rm } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { CostLedgerState, ParkedExecution, RunnerSnapshot, SessionRunnerConfig } from '@workerdeck/core'\nimport { pickCreateSessionRequest, type SessionInfo } from '@workerdeck/protocol'\nimport { isMissing, writeFileAtomic } from '../lib/atomic-file.ts'\nimport { DURABLE_HOST_KEYS } from '../lib/host-only-keys.ts'\n\nexport type ParkedSessionRecord = {\n kind?: 'parked' | 'live'\n id: string\n info: SessionInfo\n profile?: string\n config: SessionRunnerConfig\n snapshot: RunnerSnapshot\n executions: ParkedExecution[]\n cost?: CostLedgerState\n parkedAt: number\n}\n\nexport function isLiveRecord(record: StoredSessionRecord): boolean {\n return record.kind === 'live'\n}\n\nexport type DormantSessionRecord = {\n kind: 'dormant'\n id: string\n info: SessionInfo\n profile?: string\n config: SessionRunnerConfig\n sdkSessionId: string\n cost?: CostLedgerState\n savedAt: number\n}\n\nexport type StoredSessionRecord = ParkedSessionRecord | DormantSessionRecord\n\nexport function isDormant(record: StoredSessionRecord): record is DormantSessionRecord {\n return record.kind === 'dormant'\n}\n\nexport interface SessionStore {\n save(record: StoredSessionRecord): Promise<void>\n get(id: string): Promise<StoredSessionRecord | null>\n list(): Promise<StoredSessionRecord[]>\n delete(id: string): Promise<boolean>\n}\n\nexport class MemorySessionStore implements SessionStore {\n #records = new Map<string, StoredSessionRecord>()\n\n save(record: StoredSessionRecord): Promise<void> {\n this.#records.set(record.id, record)\n return Promise.resolve()\n }\n\n get(id: string): Promise<StoredSessionRecord | null> {\n return Promise.resolve(this.#records.get(id) ?? null)\n }\n\n list(): Promise<StoredSessionRecord[]> {\n return Promise.resolve([...this.#records.values()])\n }\n\n delete(id: string): Promise<boolean> {\n return Promise.resolve(this.#records.delete(id))\n }\n}\n\nfunction durableConfig(config: SessionRunnerConfig): SessionRunnerConfig {\n const source = config as Record<string, unknown>\n const durable: Record<string, unknown> = { ...pickCreateSessionRequest(source) }\n for (const key of DURABLE_HOST_KEYS) {\n if (source[key] !== undefined) {\n durable[key] = source[key]\n }\n }\n return durable as SessionRunnerConfig\n}\n\nexport function toDurableRecord<T extends StoredSessionRecord>(record: T): T {\n return { ...record, config: durableConfig(record.config) }\n}\n\nconst FORMAT_VERSION = 1\n\nexport type FileSessionStoreOptions = {\n dir?: string\n onError?: (error: unknown, context: { path: string; op: 'save' | 'read' | 'delete' }) => void\n}\n\nexport function createFileSessionStore(options: FileSessionStoreOptions = {}): SessionStore {\n const dir = options.dir ?? join(process.cwd(), '.workerdeck', 'parked')\n // Encoded, not interpolated: an id is a runner-assigned string, and a '/' in one would otherwise write outside `dir`.\n const fileFor = (id: string): string => join(dir, `${encodeURIComponent(id)}.json`)\n\n const read = async (path: string): Promise<StoredSessionRecord | null> => {\n let raw: string\n try {\n raw = await readFile(path, 'utf8')\n } catch (error) {\n // Only absence is \"nothing parked\": reporting an EACCES as one is how a restart guard ends up saying the coast is clear.\n if (isMissing(error)) {\n return null\n }\n options.onError?.(error, { path, op: 'read' })\n return null\n }\n try {\n return parseRecord(JSON.parse(raw))\n } catch (error) {\n options.onError?.(error, { path, op: 'read' })\n return null\n }\n }\n\n return {\n save: async (record) => {\n const path = fileFor(record.id)\n let payload: string\n try {\n payload = JSON.stringify({ version: FORMAT_VERSION, record: toDurableRecord(record) })\n } catch (error) {\n options.onError?.(error, { path, op: 'save' })\n throw new Error(\n `parked session '${record.id}' is not JSON-serializable - a host-injected value ` +\n `reached its config or snapshot: ${String(error)}`,\n { cause: error },\n )\n }\n try {\n await writeFileAtomic(path, payload)\n } catch (error) {\n options.onError?.(error, { path, op: 'save' })\n throw error\n }\n },\n\n get: (id) => read(fileFor(id)),\n\n list: async () => {\n let names: string[]\n try {\n names = await readdir(dir)\n } catch (error) {\n if (isMissing(error)) {\n return []\n }\n options.onError?.(error, { path: dir, op: 'read' })\n throw error\n }\n const records = await Promise.all(\n names\n .filter((name) => name.endsWith('.json'))\n .map(async (name) => {\n const record = await read(join(dir, name))\n if (!record) {\n return null\n }\n // A record only answers `get`/`delete` under the name its id encodes to; one that arrived some other way would be unreachable.\n if (`${encodeURIComponent(record.id)}.json` === name) {\n return record\n }\n options.onError?.(new Error(`parked record '${record.id}' is stored as '${name}' and cannot be read back by id`), {\n path: join(dir, name),\n op: 'read',\n })\n return null\n }),\n )\n return records.filter((record): record is StoredSessionRecord => record !== null)\n },\n\n delete: async (id) => {\n const path = fileFor(id)\n try {\n await rm(path)\n return true\n } catch (error) {\n if (isMissing(error)) {\n return false\n }\n options.onError?.(error, { path, op: 'delete' })\n return false\n }\n },\n }\n}\n\nfunction parseRecord(value: unknown): StoredSessionRecord | null {\n if (!value || typeof value !== 'object') {\n return null\n }\n const envelope = value as { version?: unknown; record?: unknown }\n if (envelope.version !== FORMAT_VERSION) {\n return null\n }\n const record = envelope.record as Partial<StoredSessionRecord> | null\n if (!record || typeof record !== 'object') {\n return null\n }\n if (typeof record.id !== 'string') {\n return null\n }\n if (!record.info || !record.config) {\n return null\n }\n if (record.kind === 'dormant') {\n const dormant = record as Partial<DormantSessionRecord>\n if (typeof dormant.sdkSessionId !== 'string' || typeof dormant.savedAt !== 'number') {\n return null\n }\n return dormant as DormantSessionRecord\n }\n const parked = record as Partial<ParkedSessionRecord>\n if (typeof parked.parkedAt !== 'number' || !parked.snapshot) {\n return null\n }\n if (!Array.isArray(parked.executions)) {\n return null\n }\n return parked as ParkedSessionRecord\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport { attachmentKind } from '@workerdeck/core'\nimport { ENGINE_CAPABILITIES, type SessionInfo } from '@workerdeck/protocol'\nimport { fail, json, readRawBody, sendUntrusted } from '../lib/http.ts'\nimport { engineOf } from '../lib/profile-env.ts'\nimport type { ServerContext } from '../context.ts'\n\nexport async function handleAttachments(\n ctx: ServerContext,\n req: IncomingMessage,\n res: ServerResponse,\n sessionId: string,\n session: SessionInfo,\n attachmentId?: string,\n): Promise<void> {\n const { attachmentStore } = ctx\n if (req.method === 'POST' && attachmentId === undefined) {\n const url = new URL(req.url ?? '/', 'http://internal')\n const mediaType = req.headers['content-type']\n if (!mediaType) {\n fail(400, 'content-type header is required')\n }\n const accepted = (session.capabilities ?? ENGINE_CAPABILITIES[engineOf(session)]).attachments\n const kind = attachmentKind(mediaType)\n if (kind && !accepted.includes(kind === 'document' ? 'pdf' : kind)) {\n fail(415, `the ${engineOf(session)} engine does not accept ${kind} attachments`)\n }\n let body: Buffer\n try {\n body = await readRawBody(req, attachmentStore.maxFileBytes)\n } catch {\n fail(413, 'attachment is larger than the limit')\n }\n const result = attachmentStore.put(sessionId, url.searchParams.get('name') ?? 'attachment', mediaType, body)\n if (!result.ok) {\n const status = result.error.code === 'unsupported_type' ? 415 : result.error.code === 'empty' ? 400 : 413\n fail(status, result.error.message)\n }\n json(res, 201, { attachment: result.attachment })\n return\n }\n if (req.method === 'GET' && attachmentId !== undefined) {\n const found = attachmentStore.get(sessionId, attachmentId)\n if (!found) {\n fail(404, 'attachment not found')\n }\n sendUntrusted(res, found.name, found.mediaType, Buffer.from(found.data, 'base64'))\n return\n }\n json(res, 405, { error: 'method not allowed' })\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { Runner } from '@workerdeck/core'\nimport type { McpServerActionRequest } from '@workerdeck/protocol'\nimport { fail, json, readJsonBody } from '../lib/http.ts'\nimport type { ServerContext } from '../context.ts'\n\nexport async function handleMcp(\n ctx: ServerContext,\n req: IncomingMessage,\n res: ServerResponse,\n runner: Runner,\n serverName?: string,\n): Promise<void> {\n if (req.method === 'GET' && serverName === undefined) {\n await listServers(res, runner)\n return\n }\n if (req.method === 'POST' && serverName !== undefined) {\n const body = (await readJsonBody(req, ctx.maxBodyBytes)) as McpServerActionRequest\n if (body?.action !== 'reconnect' && body?.action !== 'enable' && body?.action !== 'disable') {\n fail(400, \"action must be 'reconnect', 'enable' or 'disable'\")\n }\n const canAct =\n body.action === 'reconnect' ? typeof runner.reconnectMcpServer === 'function' : typeof runner.setMcpServerEnabled === 'function'\n if (!canAct) {\n fail(501, `this session's engine cannot ${body.action} an MCP server`)\n }\n try {\n if (body.action === 'reconnect') {\n await runner.reconnectMcpServer?.(serverName)\n } else {\n await runner.setMcpServerEnabled?.(serverName, body.action === 'enable')\n }\n } catch (error) {\n fail(400, error instanceof Error ? error.message : 'MCP action failed')\n }\n await listServers(res, runner)\n return\n }\n json(res, 405, { error: 'method not allowed' })\n}\n\nasync function listServers(res: ServerResponse, runner: Runner): Promise<void> {\n const servers = await runner.mcpServers?.()\n if (!servers) {\n fail(501, 'this session does not report MCP servers')\n }\n json(res, 200, { servers })\n}\n","import { createReadStream, statSync } from 'node:fs'\nimport { basename } from 'node:path'\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport { contentTypeFor, fail, json, requireMethod, untrustedDownloadHeaders } from '../lib/http.ts'\nimport type { ServerContext } from '../context.ts'\n\nexport async function handleProducedFiles(\n ctx: ServerContext,\n req: IncomingMessage,\n res: ServerResponse,\n sessionId: string,\n fileId?: string,\n): Promise<void> {\n const { producedFiles } = ctx\n requireMethod(req, 'GET')\n if (fileId === undefined) {\n json(res, 200, {\n files: producedFiles.list(sessionId).map(({ fileId: id, path, mediaType, bytes }) => ({\n fileId: id,\n path,\n ...(mediaType ? { mediaType } : {}),\n ...(bytes !== undefined ? { bytes } : {}),\n })),\n })\n return\n }\n const found = producedFiles.get(sessionId, fileId)\n if (!found) {\n fail(404, 'no such produced file')\n }\n // statSync follows symlinks deliberately: a link the engine created is part of what it produced, and there is no root to realpath against.\n let stat\n try {\n stat = statSync(found.path)\n } catch {\n fail(404, 'produced file is no longer on disk')\n }\n if (!stat.isFile()) {\n fail(404, 'produced file is not a regular file')\n }\n const filename = basename(found.path) || 'file'\n res.writeHead(200, untrustedDownloadHeaders(filename, found.mediaType ?? contentTypeFor(filename), stat.size))\n await new Promise<void>((done) => {\n const stream = createReadStream(found.path)\n stream.on('error', () => {\n res.destroy()\n done()\n })\n stream.on('close', () => done())\n stream.pipe(res)\n })\n}\n","import { createHash } from 'node:crypto'\nimport { lstatSync, realpathSync } from 'node:fs'\nimport { basename, dirname, isAbsolute, join, resolve } from 'node:path'\nimport type { ProjectIcon, ProjectInfo, SessionInfo } from '@workerdeck/protocol'\nimport { contained, readContained } from './host-files.ts'\n\nconst PROJECT_FILE = '.workerdeck.json'\nconst MAX_PROJECT_FILE_BYTES = 64 * 1024\nexport const MAX_PROJECT_ICON_BYTES = 512 * 1024\nconst MAX_NAME_CHARS = 80\nconst GLYPH_RE = /^[a-z0-9]+(-[a-z0-9]+)*$/\nconst SHORTCODE_RE = /^[A-Z0-9]{2,5}$/\n\nconst DEFAULT_TTL_MS = 30_000\nconst SWEEP_ABOVE = 256\n\ntype IconMediaType = 'image/png' | 'image/svg+xml'\n\nexport type ResolvedProjectIcon = { path: string; mediaType: IconMediaType; hash: string }\n\ntype Resolution = {\n project?: ProjectInfo\n icon?: ResolvedProjectIcon\n expiresAt: number\n}\n\nexport class ProjectInfoService {\n readonly #ttlMs: number\n readonly #decorate: (info: SessionInfo) => SessionInfo\n readonly #byCwd = new Map<string, Resolution>()\n\n // `decorate` runs after the project lookup on every info this service hands out: `withProject` is the one funnel\n // every SessionInfo leaves the server through, so the shell list rides it rather than a second call at every site.\n constructor(options: { ttlMs?: number; decorate?: (info: SessionInfo) => SessionInfo } = {}) {\n this.#ttlMs = options.ttlMs ?? DEFAULT_TTL_MS\n this.#decorate = options.decorate ?? ((info) => info)\n }\n\n withProject(info: SessionInfo): SessionInfo {\n if (!info.cwd) {\n return this.#decorate(info)\n }\n const project = this.#resolve(info.cwd).project\n return this.#decorate(project ? { ...info, project } : info)\n }\n\n iconFor(cwd: string): ResolvedProjectIcon | undefined {\n if (!cwd) {\n return undefined\n }\n return this.#resolve(cwd).icon\n }\n\n #resolve(cwd: string): Resolution {\n const now = Date.now()\n const held = this.#byCwd.get(cwd)\n if (held && held.expiresAt > now) {\n return held\n }\n if (this.#byCwd.size > SWEEP_ABOVE) {\n for (const [key, entry] of this.#byCwd) {\n if (entry.expiresAt <= now) {\n this.#byCwd.delete(key)\n }\n }\n }\n const fresh = { ...discover(cwd), expiresAt: now + this.#ttlMs }\n this.#byCwd.set(cwd, fresh)\n return fresh\n }\n}\n\nfunction discover(cwd: string): Omit<Resolution, 'expiresAt'> {\n if (!isAbsolute(cwd) || cwd.includes('\\0')) {\n return {}\n }\n let dir: string\n try {\n dir = realpathSync(cwd)\n } catch {\n return {}\n }\n for (;;) {\n const found = tryLoad(join(dir, PROJECT_FILE), dir)\n if (found) {\n return found\n }\n const parent = dirname(dir)\n if (parent === dir) {\n return {}\n }\n dir = parent\n }\n}\n\nfunction tryLoad(file: string, root: string): Omit<Resolution, 'expiresAt'> | undefined {\n let stat\n try {\n stat = lstatSync(file)\n } catch {\n return undefined\n }\n // A symlinked project file is skipped, not followed - the agent writes this tree.\n if (!stat.isFile() || stat.size > MAX_PROJECT_FILE_BYTES) {\n return undefined\n }\n const read = readContained(file)\n if (!read.ok) {\n return undefined\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(read.data.toString('utf8'))\n } catch {\n return undefined\n }\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n return undefined\n }\n const raw = parsed as { name?: unknown; icon?: unknown; shortcode?: unknown }\n const name = typeof raw.name === 'string' && raw.name.trim() ? raw.name.trim().slice(0, MAX_NAME_CHARS) : basename(root)\n const icon = classifyIcon(raw.icon, root)\n const shortcode = classifyShortcode(raw.shortcode)\n return {\n project: { name, root, ...(icon ? { icon: icon.wire } : {}), ...(shortcode ? { shortcode } : {}) },\n ...(icon?.resolved ? { icon: icon.resolved } : {}),\n }\n}\n\nfunction classifyShortcode(value: unknown): string | undefined {\n return typeof value === 'string' && SHORTCODE_RE.test(value) ? value : undefined\n}\n\nfunction classifyIcon(value: unknown, root: string): { wire: ProjectIcon; resolved?: ResolvedProjectIcon } | undefined {\n if (typeof value !== 'string') {\n return undefined\n }\n const declared = value.trim()\n if (!declared || declared.includes('\\0') || declared.length > 512) {\n return undefined\n }\n const lower = declared.toLowerCase()\n const mediaType: IconMediaType | undefined = lower.endsWith('.png') ? 'image/png' : lower.endsWith('.svg') ? 'image/svg+xml' : undefined\n if (!mediaType) {\n if (!GLYPH_RE.test(declared) || declared.length > 64) {\n return undefined\n }\n return { wire: { type: 'glyph', name: declared } }\n }\n if (isAbsolute(declared) || declared.includes('\\\\')) {\n return undefined\n }\n let canonical: string\n try {\n canonical = realpathSync(resolve(root, declared))\n } catch {\n return undefined\n }\n if (!contained(root, canonical)) {\n return undefined\n }\n let stat\n try {\n stat = lstatSync(canonical)\n } catch {\n return undefined\n }\n if (!stat.isFile() || stat.size === 0 || stat.size > MAX_PROJECT_ICON_BYTES) {\n return undefined\n }\n const read = readContained(canonical)\n if (!read.ok || read.data.length > MAX_PROJECT_ICON_BYTES) {\n return undefined\n }\n const hash = createHash('sha256').update(read.data).digest('hex')\n return {\n wire: { type: 'image', mediaType, hash },\n resolved: { path: canonical, mediaType, hash },\n }\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport { fail, requireMethod } from '../lib/http.ts'\nimport { readContained } from '../services/host-files.ts'\nimport { MAX_PROJECT_ICON_BYTES, type ProjectInfoService } from '../services/project-info.ts'\n\nexport function handleProjectIcon(projects: ProjectInfoService, req: IncomingMessage, res: ServerResponse, cwd: string): void {\n requireMethod(req, 'GET')\n const icon = projects.iconFor(cwd)\n if (!icon) {\n fail(404, 'no project icon')\n }\n const etag = `\"${icon.hash}\"`\n if (req.headers['if-none-match'] === etag) {\n res.writeHead(304, { etag })\n res.end()\n return\n }\n const read = readContained(icon.path)\n if (!read.ok || read.data.length > MAX_PROJECT_ICON_BYTES) {\n fail(404, 'no project icon')\n }\n res.writeHead(200, {\n 'content-type': icon.mediaType,\n 'content-length': read.data.length,\n etag,\n 'cache-control': 'private, max-age=300',\n 'content-disposition': 'attachment; filename=\"project-icon\"',\n 'x-content-type-options': 'nosniff',\n })\n res.end(read.data)\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { Runner } from '@workerdeck/core'\nimport { fail, json, readJsonBody, requireMethod, sendUntrusted } from '../lib/http.ts'\nimport type { SessionItemRoute } from '../lib/parse-route.ts'\nimport { shellPermitted, SHELL_REFUSAL, type ShellRegistry } from '../services/shells.ts'\nimport type { ServerContext } from '../context.ts'\n\nconst AGENT_WRITE_BODY_MAX = 1024\n\nexport async function handleShells(\n ctx: ServerContext,\n req: IncomingMessage,\n res: ServerResponse,\n route: Extract<SessionItemRoute, { kind: 'shells' }>,\n runner: Runner | null,\n operator: boolean,\n): Promise<void> {\n const { shells } = ctx\n const sessionId = route.id\n if (!shells) {\n fail(404, SHELL_REFUSAL)\n }\n // Reading a shell is reading host output: the command, the cwd and every byte it printed. `canSee` on the session is\n // not enough, because a scoped principal can see a session an operator ran `$` in. The `hostCwd` leg of\n // `shellPermitted` is about whether a `$` may *run* and needs a live runner, which a parked session has not got, so\n // reads gate on the operator leg alone and the write arms below keep the full check.\n if (!operator) {\n fail(403, SHELL_REFUSAL)\n }\n if (route.shellId === undefined) {\n requireMethod(req, 'GET')\n json(res, 200, { shells: shells.list(sessionId) })\n return\n }\n if (route.shellAction === 'kill') {\n requirePermittedPost(shells, req, runner)\n json(res, 200, { shell: found(shells.kill(sessionId, route.shellId)) })\n return\n }\n if (route.shellAction === 'agent-write') {\n const live = requirePermittedPost(shells, req, runner)\n let body: Record<string, unknown>\n try {\n body = await readJsonBody(req, AGENT_WRITE_BODY_MAX)\n } catch {\n fail(400, 'invalid JSON body')\n }\n if (typeof body.enabled !== 'boolean') {\n fail(400, 'enabled must be a boolean')\n }\n if (body.enabled && live.info().shellAgentWrite === undefined) {\n fail(409, 'the agent has no shell write tools on this session (shell.agentWrite is read-only)')\n }\n let shell\n try {\n shell = shells.setAgentWrite(sessionId, route.shellId, body.enabled)\n } catch (error) {\n fail(409, error instanceof Error ? error.message : String(error))\n }\n json(res, 200, { shell: found(shell) })\n return\n }\n requireMethod(req, 'GET')\n if (route.shellAction === 'output') {\n const url = new URL(req.url ?? '/', 'http://internal')\n const requested = url.searchParams.get('view')\n const view = requested === 'raw' || requested === 'screen' ? requested : 'text'\n const tailParam = url.searchParams.get('tail')\n const tail = tailParam === null ? undefined : Number(tailParam)\n if (tail !== undefined && (!Number.isInteger(tail) || tail <= 0)) {\n fail(400, 'tail must be a positive integer')\n }\n const output = found(await shells.output(sessionId, route.shellId, { view, tail }))\n sendUntrusted(res, `${route.shellId}.txt`, 'text/plain; charset=utf-8', Buffer.from(output, 'utf8'))\n return\n }\n json(res, 200, { shell: found(shells.get(sessionId, route.shellId)) })\n}\n\nfunction requirePermittedPost(shells: ShellRegistry, req: IncomingMessage, runner: Runner | null): Runner {\n requireMethod(req, 'POST')\n if (!runner || !shellPermitted(shells, runner, true)) {\n fail(403, SHELL_REFUSAL)\n }\n return runner\n}\n\nfunction found<T>(value: T | undefined | null): T {\n if (value === undefined || value === null) {\n fail(404, 'shell not found')\n }\n return value\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport { imagePartRef, type SessionEvent, type ToolResultBlock } from '@workerdeck/protocol'\nimport { fail, json, requireMethod, untrustedDownloadHeaders } from '../lib/http.ts'\n\n// The media type is whatever the tool claimed. Only rasters a browser cannot execute keep theirs; SVG and HTML never do.\nconst RASTER_IMAGE_TYPES = new Set(['image/png', 'image/jpeg', 'image/gif', 'image/webp'])\n\nexport type EventLookup = ((seq: number) => SessionEvent | undefined) | undefined\n\nexport function handleToolResult(req: IncomingMessage, res: ServerResponse, lookup: EventLookup, seq: number): void {\n requireMethod(req, 'GET')\n const url = new URL(req.url ?? '/', 'http://internal')\n const toolUseId = url.searchParams.get('toolUseId')\n if (!toolUseId) {\n fail(400, 'toolUseId is required')\n }\n if (!lookup) {\n fail(501, 'engine does not serve stored events')\n }\n const event = lookup(seq)\n if (!event || event.type !== 'user_message' || !Array.isArray(event.message.content)) {\n fail(404, 'no such event')\n }\n const block = event.message.content.find(\n (candidate): candidate is ToolResultBlock =>\n candidate.type === 'tool_result' && (candidate as ToolResultBlock).tool_use_id === toolUseId,\n )\n if (!block) {\n fail(404, 'no such tool result in that event')\n }\n\n const partParam = url.searchParams.get('part')\n if (partParam !== null) {\n const index = Number(partParam)\n const parts = block.content\n const part = Number.isInteger(index) && Array.isArray(parts) ? parts[index] : undefined\n const ref = part ? imagePartRef(part, index) : undefined\n if (!ref) {\n fail(404, 'no such image part in that tool result')\n }\n const source = (part as { source?: { data?: string } }).source\n const bytes = Buffer.from(source?.data ?? '', 'base64')\n const mediaType = ref.media_type.split(';')[0]!.trim().toLowerCase()\n res.writeHead(200, {\n ...untrustedDownloadHeaders(\n `tool-result-${seq}-${index}`,\n RASTER_IMAGE_TYPES.has(mediaType) ? mediaType : 'application/octet-stream',\n bytes.length,\n ),\n 'content-security-policy': \"sandbox; default-src 'none'\",\n })\n res.end(bytes)\n return\n }\n\n const content =\n url.searchParams.get('imageRefs') === '1' && Array.isArray(block.content)\n ? block.content.map((part, index) => imagePartRef(part, index) ?? part)\n : (block.content ?? '')\n json(res, 200, { seq, toolUseId, content, isError: block.is_error === true })\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { ResolvePermissionRequest, SessionInfo, UpdateSessionRequest } from '@workerdeck/protocol'\nimport { contentTypeFor, fail, json, readJsonBody, requireMethod, sendUntrusted } from '../lib/http.ts'\nimport type { SessionItemRoute, SessionRoute } from '../lib/parse-route.ts'\nimport { permissionDecision } from '../lib/permissions.ts'\nimport { engineOf } from '../lib/profile-env.ts'\nimport type { AuthContext } from '../services/auth.ts'\nimport { isDormant } from '../services/session-store.ts'\nimport type { ServerContext } from '../context.ts'\nimport { vetCreateRequest } from './create-vet.ts'\nimport { handleAttachments } from './attachments.ts'\nimport { handleMcp } from './mcp.ts'\nimport { handleProducedFiles } from './produced-files.ts'\nimport { handleProjectIcon } from './project-icon.ts'\nimport { requireLive, resolveSession, type ResolvedSession } from './session-lookup.ts'\nimport { handleShells } from './shells.ts'\nimport { handleToolResult } from './tool-results.ts'\n\ntype ItemKind = SessionItemRoute['kind']\n\ntype SessionCall<K extends ItemKind> = ResolvedSession & {\n ctx: ServerContext\n req: IncomingMessage\n res: ServerResponse\n auth: AuthContext\n route: Extract<SessionItemRoute, { kind: K }>\n}\n\ntype ItemHandlers = { [K in ItemKind]: (call: SessionCall<K>) => Promise<void> | void }\n\nconst ITEM_HANDLERS: ItemHandlers = {\n session: handleSession,\n ws: handleSession,\n attachments: ({ ctx, req, res, route, info }) => handleAttachments(ctx, req, res, route.id, info, route.attachmentId),\n mcp: ({ ctx, req, res, route, runner }) =>\n handleMcp(ctx, req, res, requireLive(runner, 'wake it before asking about MCP'), route.mcpServer),\n files: handleFiles,\n produced: ({ ctx, req, res, route }) => handleProducedFiles(ctx, req, res, route.id, route.producedFileId),\n shells: ({ ctx, req, res, route, runner, auth }) => handleShells(ctx, req, res, route, runner ?? null, ctx.auth.isOperator(auth)),\n 'stop-task': handleStopTask,\n 'project-icon': ({ ctx, req, res, info }) => handleProjectIcon(ctx.projects, req, res, info.cwd),\n 'tool-result': ({ req, res, route, runner, parked }) => {\n const snapshot = parked && !isDormant(parked) ? parked.snapshot.events : undefined\n handleToolResult(\n req,\n res,\n runner?.eventAt?.bind(runner) ?? (snapshot && ((seq: number) => snapshot.find((event) => event.seq === seq))),\n route.resultSeq,\n )\n },\n permission: handlePermission,\n}\n\nexport async function handleSessions(\n ctx: ServerContext,\n req: IncomingMessage,\n res: ServerResponse,\n route: SessionRoute,\n auth: AuthContext,\n): Promise<void> {\n if (route.kind === 'collection') {\n await handleCollection(ctx, req, res, auth)\n return\n }\n const resolved = await resolveSession(ctx, route.id, auth)\n const handler = ITEM_HANDLERS[route.kind] as (call: SessionCall<ItemKind>) => Promise<void> | void\n await handler({ ...resolved, ctx, req, res, auth, route })\n}\n\nasync function handleCollection(ctx: ServerContext, req: IncomingMessage, res: ServerResponse, auth: AuthContext): Promise<void> {\n const { auth: authSvc, factory, parking, projects, registry } = ctx\n requireMethod(req, 'GET', 'POST')\n if (req.method === 'GET') {\n const sessions = [...registry.list(), ...(await parking.listInfo())]\n json(res, 200, {\n sessions: sessions.filter((session) => authSvc.canSee(auth, session)).map((session) => projects.withProject(session)),\n })\n return\n }\n const vetted = vetCreateRequest(ctx, await readJsonBody(req, ctx.maxBodyBytes), auth)\n if (!vetted.ok) {\n fail(vetted.status, vetted.error)\n }\n const runner = await factory.createRunner(factory.buildRunnerConfig(vetted.request, { operator: authSvc.isOperator(auth) }))\n json(res, 201, { session: projects.withProject(runner.info()) })\n}\n\nasync function handleSession({ ctx, req, res, route, runner, parked, info }: SessionCall<'session' | 'ws'>): Promise<void> {\n const { attachmentStore, bridge, parking, producedFiles, projects, registry } = ctx\n requireMethod(req, 'GET', 'PATCH', 'DELETE')\n if (req.method === 'GET') {\n json(res, 200, { session: projects.withProject(info) })\n return\n }\n if (req.method === 'PATCH') {\n const body = (await readJsonBody(req, ctx.maxBodyBytes)) as UpdateSessionRequest\n if (body?.title !== undefined && body.title !== null && typeof body.title !== 'string') {\n fail(400, 'title must be a string or null')\n }\n const title = typeof body?.title === 'string' ? body.title.trim() || undefined : undefined\n if (!runner && parked) {\n const renamed = body?.title === undefined ? parked.info : await parking.retitle(route.id, title)\n json(res, 200, { session: projects.withProject(requireRenamed(renamed)) })\n return\n }\n const live = requireLive(runner, 'wake it before renaming')\n if (body?.title !== undefined) {\n live.setTitle(title)\n parking.touch(live)\n }\n json(res, 200, { session: projects.withProject(live.info()) })\n return\n }\n registry.remove(route.id)\n bridge.remove(route.id)\n await parking.discard(route.id)\n attachmentStore.drop(route.id)\n producedFiles.drop(route.id)\n json(res, 200, {\n session: projects.withProject(runner?.info() ?? { ...parked!.info, status: 'closed' as const }),\n })\n}\n\nfunction handleFiles({ req, res, route, runner, parked }: SessionCall<'files'>): void {\n requireMethod(req, 'GET')\n const snapshotFiles = parked && !isDormant(parked) ? parked.snapshot.vfs : undefined\n const vfs =\n runner?.vfs ??\n (snapshotFiles && {\n list: () => Object.keys(snapshotFiles).sort(),\n read: (path: string) => snapshotFiles[path]!,\n })\n if (!vfs) {\n fail(404, 'session has no file store')\n }\n if (route.filePath === undefined) {\n json(res, 200, { files: vfs.list().map((path) => ({ path, bytes: vfs.read(path)?.length ?? 0 })) })\n return\n }\n const content = vfs.read(route.filePath)\n if (content === undefined) {\n fail(404, `no such file: ${route.filePath}`)\n }\n const filename = route.filePath.split('/').pop() || 'file'\n sendUntrusted(res, filename, contentTypeFor(filename), content)\n}\n\nasync function handleStopTask({ req, res, route, runner }: SessionCall<'stop-task'>): Promise<void> {\n requireMethod(req, 'POST')\n const live = requireLive(runner, 'it has no running tasks')\n if (!live.stopTask) {\n fail(501, `the ${engineOf(live.info())} engine cannot stop a task`)\n }\n if (!(await live.stopTask(route.stopTaskId))) {\n fail(404, 'no running task to stop')\n }\n json(res, 200, { ok: true })\n}\n\nasync function handlePermission({ ctx, req, res, route, runner }: SessionCall<'permission'>): Promise<void> {\n requireMethod(req, 'POST')\n const body = (await readJsonBody(req, ctx.maxBodyBytes)) as ResolvePermissionRequest\n if (body?.behavior !== 'allow' && body?.behavior !== 'deny') {\n fail(400, \"behavior must be 'allow' or 'deny'\")\n }\n const live = requireLive(runner, 'it has no pending permission requests')\n if (!live.resolvePermission(route.permissionId, permissionDecision(body))) {\n fail(404, 'permission request not found (already resolved or expired)')\n }\n json(res, 200, { resolved: true })\n}\n\nfunction requireRenamed(info: SessionInfo | undefined): SessionInfo {\n if (!info) {\n fail(409, 'session woke while renaming; retry')\n }\n return info\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport { PROTOCOL_VERSION } from '@workerdeck/protocol'\nimport type { ServerContext } from '../context.ts'\nimport { json, type Refusal } from '../lib/http.ts'\nimport { machineId } from '../lib/machine-id.ts'\nimport { parseSessionRoute } from '../lib/parse-route.ts'\nimport type { AuthContext } from '../services/auth.ts'\nimport { handleExecutionResult } from './executions.ts'\nimport { handleHostFiles } from './fs.ts'\nimport { handleJobs } from './jobs.ts'\nimport { handleProfiles } from './profiles.ts'\nimport { handleSdkSessions } from './sdk-sessions.ts'\nimport { handleSessions } from './sessions.ts'\n\n// `any` is every authenticated principal; `operator` answers a non-operator with the same 404 as a missing route,\n// because those surfaces describe the gateway itself and there is nothing to filter.\nexport type RouteAuth = 'any' | 'operator'\n\nexport type RouteRefusal = Refusal\n\nexport type RouteSpec<M> = {\n match: (pathname: string, req: IncomingMessage) => M | undefined\n // Runs before authentication, so whatever it answers is answered to anyone.\n refuse?: (req: IncomingMessage, matched: M, draining: boolean) => RouteRefusal | undefined\n auth: RouteAuth\n handler: (req: IncomingMessage, res: ServerResponse, matched: M, auth: AuthContext) => Promise<void> | void\n}\n\nexport type MatchedRoute = {\n auth: RouteAuth\n refuse: (draining: boolean) => RouteRefusal | undefined\n handle: (res: ServerResponse, auth: AuthContext) => Promise<void> | void\n}\n\nexport type HttpRoute = (pathname: string, req: IncomingMessage) => MatchedRoute | undefined\n\nconst SHUTTING_DOWN: RouteRefusal = { status: 503, error: 'server is shutting down' }\nconst NOT_FOUND: RouteRefusal = { status: 404, error: 'not found' }\n\nexport function route<M>(spec: RouteSpec<M>): HttpRoute {\n return (pathname, req) => {\n const matched = spec.match(pathname, req)\n if (matched === undefined) {\n return undefined\n }\n return {\n auth: spec.auth,\n refuse: (draining) => spec.refuse?.(req, matched, draining),\n handle: (res, auth) => spec.handler(req, res, matched, auth),\n }\n }\n}\n\nexport function httpRoutes(ctx: ServerContext): HttpRoute[] {\n const base = ctx.basePath\n const under = (prefix: string) => (pathname: string) => pathname === base + prefix || pathname.startsWith(base + prefix + '/')\n return [\n route({\n match: pathWhere((pathname) => under('/jobs')(pathname) || pathname === base + '/queue'),\n refuse: (req, pathname, draining) => (draining && req.method === 'POST' && pathname === base + '/jobs' ? SHUTTING_DOWN : undefined),\n auth: 'any',\n handler: (req, res, pathname, auth) => handleJobs(ctx, req, res, pathname, auth),\n }),\n route({\n match: pathWhere(under('/profiles')),\n auth: 'any',\n handler: (req, res, pathname, auth) => handleProfiles(ctx, req, res, pathname, auth),\n }),\n route({\n match: pathWhere((pathname) => pathname.startsWith(base + '/executions/')),\n auth: 'any',\n handler: (req, res, pathname, auth) => handleExecutionResult(ctx, req, res, pathname, auth),\n }),\n route({\n match: pathWhere((pathname) => pathname === base + '/sdk-sessions'),\n auth: 'operator',\n handler: (req, res, _, auth) => handleSdkSessions(ctx, req, res, auth),\n }),\n route({\n match: pathWhere((pathname) => pathname === base + '/meta'),\n auth: 'any',\n // Degrades rather than refusing: the fingerprint is only ever acted on by a client that also means to read this\n // machine's files, so it is gated behind the same principal as `/fs`.\n handler: (_, res, __, auth) =>\n json(res, 200, { protocolVersion: PROTOCOL_VERSION, ...(ctx.auth.isOperator(auth) ? { machineId: machineId() } : {}) }),\n }),\n // Authenticated before the 404-when-unconfigured answer: an unauthenticated caller must not learn whether a\n // filesystem is exposed.\n route({\n match: pathWhere((pathname) => pathname.startsWith(base + '/fs/')),\n auth: 'operator',\n handler: (req, res, pathname) => handleHostFiles(ctx, req, res, pathname),\n }),\n route({\n match: (_, req) => {\n const parsed = parseSessionRoute(base, req.url ?? '/')\n return parsed && parsed.kind !== 'ws' ? parsed : undefined\n },\n // Starting a turn we have already promised to stop waiting for would make the drain unable to converge.\n // Existing sessions stay fully controllable, including approvals, which is how an operator unblocks one.\n refuse: (req, parsed, draining) => (draining && req.method === 'POST' && parsed.kind === 'collection' ? SHUTTING_DOWN : undefined),\n auth: 'any',\n handler: (req, res, parsed, auth) => handleSessions(ctx, req, res, parsed, auth),\n }),\n ]\n}\n\nexport async function dispatchRoute(\n ctx: ServerContext,\n routes: HttpRoute[],\n req: IncomingMessage,\n res: ServerResponse,\n draining: boolean,\n): Promise<void> {\n const pathname = new URL(req.url ?? '/', 'http://internal').pathname\n const matched = firstMatch(routes, pathname, req)\n if (!matched) {\n json(res, NOT_FOUND.status, { error: NOT_FOUND.error })\n return\n }\n const refusal = matched.refuse(draining)\n if (refusal) {\n json(res, refusal.status, { error: refusal.error })\n return\n }\n const auth = await ctx.auth.authenticate(req)\n if (!auth.ok) {\n json(res, 401, { error: 'unauthorized' })\n return\n }\n if (matched.auth === 'operator' && !ctx.auth.isOperator(auth)) {\n json(res, NOT_FOUND.status, { error: NOT_FOUND.error })\n return\n }\n await matched.handle(res, auth)\n}\n\nfunction firstMatch(routes: HttpRoute[], pathname: string, req: IncomingMessage): MatchedRoute | undefined {\n for (const candidate of routes) {\n const matched = candidate(pathname, req)\n if (matched) {\n return matched\n }\n }\n return undefined\n}\n\nfunction pathWhere(test: (pathname: string) => boolean): (pathname: string) => string | undefined {\n return (pathname) => (test(pathname) ? pathname : undefined)\n}\n","import { randomUUID } from 'node:crypto'\nimport { attachmentKind, normalizeMediaType, type AttachmentInput } from '@workerdeck/core'\nimport type { MessageAttachment } from '@workerdeck/protocol'\n\nexport type AttachmentStoreOptions = {\n maxFileBytes?: number\n maxSessionBytes?: number\n}\n\nexport type AttachmentRejection =\n | { code: 'too_large'; message: string }\n | { code: 'session_full'; message: string }\n | { code: 'unsupported_type'; message: string }\n | { code: 'empty'; message: string }\n\nexport type PutResult = { ok: true; attachment: MessageAttachment } | { ok: false; error: AttachmentRejection }\n\nconst DEFAULT_MAX_FILE_BYTES = 10 * 1024 * 1024\nconst DEFAULT_MAX_SESSION_BYTES = 64 * 1024 * 1024\n\nexport class AttachmentStore {\n #bySession = new Map<string, Map<string, AttachmentInput>>()\n #maxFileBytes: number\n #maxSessionBytes: number\n\n constructor(options: AttachmentStoreOptions = {}) {\n this.#maxFileBytes = options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES\n this.#maxSessionBytes = options.maxSessionBytes ?? DEFAULT_MAX_SESSION_BYTES\n }\n\n get maxFileBytes(): number {\n return this.#maxFileBytes\n }\n\n put(sessionId: string, name: string, mediaType: string, body: Buffer): PutResult {\n if (body.length === 0) {\n return { ok: false, error: { code: 'empty', message: 'attachment is empty' } }\n }\n if (body.length > this.#maxFileBytes) {\n return {\n ok: false,\n error: {\n code: 'too_large',\n message: `attachment is larger than the ${this.#maxFileBytes}-byte limit`,\n },\n }\n }\n const type = normalizeMediaType(mediaType)\n if (!attachmentKind(type)) {\n return {\n ok: false,\n error: { code: 'unsupported_type', message: `unsupported media type: ${type}` },\n }\n }\n const held = this.#bySession.get(sessionId) ?? new Map<string, AttachmentInput>()\n const heldBytes = [...held.values()].reduce((sum, a) => sum + a.bytes, 0)\n if (heldBytes + body.length > this.#maxSessionBytes) {\n return {\n ok: false,\n error: {\n code: 'session_full',\n message: `session is already holding ${heldBytes} bytes of attachments (limit ${this.#maxSessionBytes})`,\n },\n }\n }\n const attachment: AttachmentInput = {\n id: randomUUID(),\n name: safeName(name),\n mediaType: type,\n bytes: body.length,\n data: body.toString('base64'),\n }\n held.set(attachment.id, attachment)\n this.#bySession.set(sessionId, held)\n return { ok: true, attachment: ref(attachment) }\n }\n\n get(sessionId: string, id: string): AttachmentInput | undefined {\n return this.#bySession.get(sessionId)?.get(id)\n }\n\n resolve(sessionId: string, ids: readonly string[]): { ok: true; attachments: AttachmentInput[] } | { ok: false; missing: string[] } {\n const held = this.#bySession.get(sessionId)\n const attachments: AttachmentInput[] = []\n const missing: string[] = []\n for (const id of ids) {\n const found = held?.get(id)\n if (found) {\n attachments.push(found)\n } else {\n missing.push(id)\n }\n }\n return missing.length ? { ok: false, missing } : { ok: true, attachments }\n }\n\n drop(sessionId: string): void {\n this.#bySession.delete(sessionId)\n }\n}\n\nfunction ref(attachment: AttachmentInput): MessageAttachment {\n return {\n id: attachment.id,\n name: attachment.name,\n mediaType: attachment.mediaType,\n bytes: attachment.bytes,\n }\n}\n\nfunction safeName(name: string): string {\n const leaf = name.split(/[/\\\\]/).pop() ?? ''\n // oxlint-disable-next-line no-control-regex\n const cleaned = leaf.replace(/[\\u0000-\\u001f\\u007f\"<>]/g, '').trim()\n if (cleaned === '' || cleaned === '.' || cleaned === '..') {\n return 'attachment'\n }\n return cleaned.length > 120 ? cleaned.slice(0, 120) : cleaned\n}\n","const MAX_SCOPE_KEYS = 16\nconst MAX_SCOPE_LEN = 200\n\nexport function readScope(value: unknown): Record<string, string> | undefined {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return undefined\n }\n const entries = Object.entries(value as Record<string, unknown>)\n if (entries.some(([, v]) => typeof v !== 'string')) {\n return undefined\n }\n return Object.fromEntries(entries) as Record<string, string>\n}\n\nexport function checkScope(value: unknown): string | null {\n if (value === undefined) {\n return null\n }\n const scope = readScope(value)\n if (!scope) {\n return 'scope must be an object of string values'\n }\n const entries = Object.entries(scope)\n if (entries.length > MAX_SCOPE_KEYS) {\n return `scope may carry at most ${MAX_SCOPE_KEYS} keys`\n }\n for (const [key, val] of entries) {\n if (key.length === 0) {\n return 'scope keys must not be empty'\n }\n if (key.length > MAX_SCOPE_LEN || val.length > MAX_SCOPE_LEN) {\n return `scope keys and values must be at most ${MAX_SCOPE_LEN} characters`\n }\n }\n return null\n}\n\nexport function sameScope(a: Record<string, string> | undefined, b: Record<string, string> | undefined): boolean {\n const left = Object.entries(a ?? {}).sort(([x], [y]) => (x < y ? -1 : 1))\n const right = Object.entries(b ?? {}).sort(([x], [y]) => (x < y ? -1 : 1))\n return left.length === right.length && left.every(([key, value], i) => right[i]![0] === key && right[i]![1] === value)\n}\n\nexport function scopeMatches(principal: Record<string, string> | undefined, session: Record<string, string> | undefined): boolean {\n if (!principal) {\n return true\n }\n return Object.entries(principal).every(([key, value]) => session?.[key] === value)\n}\n","import type { IncomingMessage } from 'node:http'\nimport type { JobInfo, SessionInfo } from '@workerdeck/protocol'\nimport { readScope, scopeMatches } from '../lib/scope.ts'\nimport type { WorkerServerOptions } from '../options.ts'\nimport type { SessionRegistry } from './registry.ts'\n\nexport type AuthContext = {\n ok: boolean\n allowedProfiles?: string[]\n canManageProfiles?: boolean\n principal?: unknown\n scope?: Record<string, string>\n operator?: boolean\n}\n\nexport type AuthService = ReturnType<typeof createAuthService>\n\nexport function createAuthService(deps: {\n options: Pick<WorkerServerOptions, 'authenticate' | 'authorizeSession'>\n registry: SessionRegistry\n}) {\n const { options, registry } = deps\n\n const authenticate = async (req: IncomingMessage): Promise<AuthContext> => {\n if (!options.authenticate) {\n return { ok: true }\n }\n const principal = await options.authenticate(req)\n if (principal === null || principal === undefined || principal === false) {\n return { ok: false }\n }\n const allowed = (principal as { allowedProfiles?: unknown }).allowedProfiles\n const scope = readScope((principal as { scope?: unknown }).scope)\n return {\n ok: true,\n principal,\n scope: scope && Object.keys(scope).length > 0 ? scope : undefined,\n operator:\n typeof (principal as { operator?: unknown }).operator === 'boolean' ? (principal as { operator: boolean }).operator : undefined,\n allowedProfiles: Array.isArray(allowed) && allowed.every((p) => typeof p === 'string') ? (allowed as string[]) : undefined,\n canManageProfiles: (principal as { canManageProfiles?: unknown }).canManageProfiles === true,\n }\n }\n\n const canSee = (auth: AuthContext, session: SessionInfo): boolean => {\n if (!options.authorizeSession) {\n return scopeMatches(auth.scope, session.scope)\n }\n try {\n return options.authorizeSession(auth.principal, session) === true\n } catch {\n return false\n }\n }\n\n const canSeeJob = (auth: AuthContext, job: JobInfo): boolean => {\n const live = job.sessionId ? registry.get(job.sessionId)?.info() : undefined\n if (live) {\n return canSee(auth, live)\n }\n if (!options.authorizeSession) {\n return scopeMatches(auth.scope, job.scope)\n }\n return canSee(auth, {\n id: job.sessionId ?? job.id,\n status: job.status === 'running' ? 'running' : job.status === 'parked' ? 'parked' : job.status === 'queued' ? 'starting' : 'closed',\n cwd: job.cwd,\n profile: job.profile,\n createdAt: job.createdAt,\n lastSeq: 0,\n pendingPermissionCount: 0,\n scope: job.scope,\n })\n }\n\n const isOperator = (auth: AuthContext): boolean => auth.operator ?? (auth.scope === undefined && !options.authorizeSession)\n\n return { authenticate, canSee, canSeeJob, isOperator }\n}\n","import { checkClaudeAuth } from '@workerdeck/core'\nimport type { ClaudeAuthProbe, EngineAdapter, EngineAvailability } from '@workerdeck/core'\nimport type { ProfileEngine, ProfileInfo } from '@workerdeck/protocol'\nimport { engineOf } from '../lib/profile-env.ts'\nimport type { Refusal } from '../lib/http.ts'\n\nconst AVAILABILITY_TTL_MS = 60_000\n\nexport type AvailabilityTrackerOptions = {\n checkCredentials?: boolean | { probe?: ClaudeAuthProbe; timeoutMs?: number }\n requireAvailableProfile?: boolean\n adapterFor: (engine: ProfileEngine | undefined) => EngineAdapter\n sessionEnvFor: (profile: ProfileInfo) => Record<string, string | undefined>\n onError?: (error: unknown) => void\n}\n\nexport class AvailabilityTracker {\n readonly #verdicts = new Map<string, { verdict: EngineAvailability; at: number }>()\n readonly #warned = new Set<string>()\n readonly #opts: AvailabilityTrackerOptions\n\n constructor(opts: AvailabilityTrackerOptions) {\n this.#opts = opts\n }\n\n get(name: string): EngineAvailability | undefined {\n return this.#verdicts.get(name)?.verdict\n }\n\n probe(profile: ProfileInfo): void {\n const { checkCredentials, adapterFor, sessionEnvFor } = this.#opts\n if (!checkCredentials) {\n return\n }\n const conf = checkCredentials === true ? {} : checkCredentials\n // Mark in-flight immediately so concurrent GET /profiles don't re-spawn.\n this.#verdicts.set(profile.name, {\n verdict: this.#verdicts.get(profile.name)?.verdict ?? { available: 'unknown' },\n at: Date.now(),\n })\n const adapter = adapterFor(profile.engine)\n const claudeProbe: ClaudeAuthProbe | undefined =\n engineOf(profile) !== 'claude'\n ? undefined\n : (conf.probe ?? (conf.timeoutMs !== undefined ? (env) => checkClaudeAuth(env, { timeoutMs: conf.timeoutMs }) : undefined))\n const run: Promise<EngineAvailability> = claudeProbe\n ? claudeProbe(sessionEnvFor(profile)).then((status): EngineAvailability =>\n status === 'logged_in'\n ? { available: true }\n : status === 'logged_out'\n ? { available: false, reason: 'no usable Claude credentials for this profile' }\n : { available: 'unknown' },\n )\n : adapter.checkAvailability(profile, sessionEnvFor(profile))\n void run\n .then((verdict) => {\n this.#verdicts.set(profile.name, { verdict, at: Date.now() })\n if (verdict.available === false && !this.#warned.has(profile.name)) {\n this.#warned.add(profile.name)\n console.warn(\n `[workerdeck] Profile '${profile.name}' is unavailable: ${verdict.reason} ` + '(`checkCredentials: false` disables this check)',\n )\n }\n if (verdict.available === true) {\n this.#warned.delete(profile.name)\n }\n })\n .catch((error: unknown) => this.#opts.onError?.(error))\n }\n\n checkAvailable(profile: ProfileInfo | undefined): Refusal | null {\n if (!this.#opts.requireAvailableProfile || !profile) {\n return null\n }\n const verdict = this.get(profile.name)\n if (!verdict || verdict.available !== false) {\n return null\n }\n return {\n status: 503,\n error: `profile '${profile.name}' is unavailable: ${verdict.reason ?? 'no usable credentials'}`,\n }\n }\n\n preflight(profiles: ProfileInfo[]): void {\n for (const profile of profiles) {\n this.probe(profile)\n }\n }\n\n refresh(profiles: ProfileInfo[]): void {\n if (!this.#opts.checkCredentials) {\n return\n }\n const now = Date.now()\n for (const profile of profiles) {\n const cached = this.#verdicts.get(profile.name)\n if (!cached || now - cached.at > AVAILABILITY_TTL_MS) {\n this.probe(profile)\n }\n }\n }\n}\n","import { BrowserBridgeExecutor, type BridgeAnswer, type ToolExecutionResult } from '@workerdeck/core'\nimport type { ServerFrame, ToolCallRequestFrame } from '@workerdeck/protocol'\n\ntype SessionBridge = {\n sockets: Array<(frame: ServerFrame) => void>\n executor: BrowserBridgeExecutor\n}\n\nexport type BridgeHubOptions = {\n timeoutMs?: number\n onResult?: (sessionId: string, executionId: string, result: ToolExecutionResult) => void\n}\n\nexport class BridgeHub {\n #sessions = new Map<string, SessionBridge>()\n #options: BridgeHubOptions\n\n constructor(options: BridgeHubOptions = {}) {\n this.#options = options\n }\n\n executorFor(sessionId: string): BrowserBridgeExecutor {\n return this.#bridge(sessionId).executor\n }\n\n attachedCount(sessionId: string): number {\n return this.#sessions.get(sessionId)?.sockets.length ?? 0\n }\n\n attach(sessionId: string, send: (frame: ServerFrame) => void): () => void {\n const bridge = this.#bridge(sessionId)\n bridge.sockets.push(send)\n return () => {\n const index = bridge.sockets.indexOf(send)\n if (index >= 0) {\n bridge.sockets.splice(index, 1)\n }\n }\n }\n\n resolve(sessionId: string, executionId: string, answer: BridgeAnswer): boolean {\n return this.#sessions.get(sessionId)?.executor.resolve(executionId, answer) ?? false\n }\n\n remove(sessionId: string): void {\n const bridge = this.#sessions.get(sessionId)\n if (!bridge) {\n return\n }\n bridge.executor.registry.cancelAll('session_closed', 'the session was closed')\n this.#sessions.delete(sessionId)\n }\n\n #bridge(sessionId: string): SessionBridge {\n const existing = this.#sessions.get(sessionId)\n if (existing) {\n return existing\n }\n const bridge: SessionBridge = {\n sockets: [],\n executor: new BrowserBridgeExecutor({\n timeoutMs: this.#options.timeoutMs,\n send: (frame: ToolCallRequestFrame) => {\n const target = bridge.sockets[0]\n if (!target) {\n return false\n }\n target(frame)\n return true\n },\n cancel: (executionId, reason) => {\n for (const send of bridge.sockets) {\n send({ type: 'tool_call_canceled', executionId, reason })\n }\n },\n onResult: (executionId, result) => {\n this.#options.onResult?.(sessionId, executionId, result)\n },\n }),\n }\n this.#sessions.set(sessionId, bridge)\n return bridge\n }\n}\n","import type { SessionInfo, SessionNotification, SessionWebhookConfig } from '@workerdeck/protocol'\nimport type { Runner } from '@workerdeck/core'\n\nexport type SessionNotificationOptions = {\n webhook?: SessionWebhookConfig\n onNotification?: (notification: SessionNotification) => void\n attempts?: number\n retryDelayMs?: number\n decorateInfo?: (info: SessionInfo) => SessionInfo\n // A throwing `onNotification`, or a webhook that failed every attempt. Delivery is best-effort either way.\n onError?: (error: unknown, context: NotificationErrorContext) => void\n}\n\nexport type NotificationErrorContext = { op: 'hook' | 'webhook'; sessionId: string }\n\nexport class SessionNotifier {\n readonly #options: SessionNotificationOptions\n readonly #chains = new Map<string, Promise<void>>()\n\n constructor(options: SessionNotificationOptions) {\n this.#options = options\n }\n\n get idle(): boolean {\n return !this.#options.webhook && !this.#options.onNotification\n }\n\n watch(runner: Runner, afterSeq = runner.info().lastSeq): () => void {\n if (this.idle) {\n return () => {}\n }\n return runner.subscribe((event) => {\n switch (event.type) {\n case 'permission_requested': {\n this.#emit(runner, event.seq, event.ts, {\n type: 'permission_requested',\n preview: event.request.title ?? event.request.toolName,\n request: event.request,\n })\n return\n }\n case 'turn_result': {\n this.#emit(runner, event.seq, event.ts, {\n type: 'turn_completed',\n preview: event.isError ? event.errors?.join('\\n') : event.result,\n result: {\n isError: event.isError,\n durationMs: event.durationMs,\n numTurns: event.numTurns,\n totalCostUsd: event.totalCostUsd,\n },\n })\n return\n }\n case 'session_error': {\n this.#emit(runner, event.seq, event.ts, {\n type: 'session_error',\n preview: event.message,\n })\n return\n }\n case 'session_closed': {\n this.#emit(runner, event.seq, event.ts, {\n type: 'session_closed',\n reason: event.reason,\n })\n return\n }\n default: {\n return\n }\n }\n }, afterSeq)\n }\n\n #emit(runner: Runner, seq: number, ts: number, body: Omit<SessionNotification, 'sessionId' | 'session' | 'seq' | 'ts'>): void {\n queueMicrotask(() => this.#send(runner, seq, ts, body))\n }\n\n #send(runner: Runner, seq: number, ts: number, body: Omit<SessionNotification, 'sessionId' | 'session' | 'seq' | 'ts'>): void {\n const webhook = this.#options.webhook\n const wanted = !webhook?.events || webhook.events.includes(body.type)\n if (!webhook && !this.#options.onNotification) {\n return\n }\n\n const notification: SessionNotification = {\n ...body,\n sessionId: runner.id,\n session: (this.#options.decorateInfo ?? ((info) => info))(runner.info()),\n seq,\n ts,\n }\n\n try {\n this.#options.onNotification?.(notification)\n } catch (error) {\n this.#options.onError?.(error, { op: 'hook', sessionId: runner.id })\n }\n\n if (!webhook || !wanted) {\n return\n }\n const previous = this.#chains.get(runner.id) ?? Promise.resolve()\n const next = previous.then(() => this.#deliver(webhook, notification))\n this.#chains.set(runner.id, next)\n void next.then(() => {\n if (this.#chains.get(runner.id) === next) {\n this.#chains.delete(runner.id)\n }\n })\n }\n\n async #deliver(webhook: SessionWebhookConfig, notification: SessionNotification): Promise<void> {\n const attempts = this.#options.attempts ?? 3\n const baseDelay = this.#options.retryDelayMs ?? 500\n let failure: unknown\n for (let attempt = 0; attempt < attempts; attempt++) {\n try {\n const res = await fetch(webhook.url, {\n method: 'POST',\n headers: { 'content-type': 'application/json', ...webhook.headers },\n body: JSON.stringify(notification),\n })\n if (res.ok) {\n return\n }\n failure = new Error(`webhook answered HTTP ${res.status}`)\n } catch (error) {\n failure = error\n }\n if (attempt < attempts - 1) {\n await new Promise((resolve) => setTimeout(resolve, baseDelay * 2 ** attempt))\n }\n }\n if (failure !== undefined) {\n this.#options.onError?.(failure, { op: 'webhook', sessionId: notification.sessionId })\n }\n }\n}\n","import type { ParkedExecution, Runner, SessionRunnerConfig, ToolExecutionResult } from '@workerdeck/core'\nimport { ENGINE_CAPABILITIES, type SessionInfo } from '@workerdeck/protocol'\nimport { engineOf } from '../lib/profile-env.ts'\nimport type { SessionRegistry } from './registry.ts'\nimport {\n isDormant,\n isLiveRecord,\n type DormantSessionRecord,\n type ParkedSessionRecord,\n type SessionStore,\n type StoredSessionRecord,\n} from './session-store.ts'\n\n// The context handed to parking's onError: which session, and which lifecycle step failed.\nexport type ParkErrorContext = { sessionId: string; phase: 'park' | 'remember' | 'resume' | 'discard' }\n\nconst SETTLED_MAX = 4096\n\nexport type SessionParkOptions = {\n registry: SessionRegistry\n store: SessionStore\n rebuild: (record: StoredSessionRecord) => Promise<Runner>\n attachedCount: (sessionId: string) => number\n parkDelayMs?: number\n persistLive?: boolean\n expiredGraceMs?: number\n onParking?: (sessionId: string, executionId: string) => boolean\n onParked?: (sessionId: string, executionId: string) => void\n onResumed?: (sessionId: string, runner: Runner) => void\n onError?: (error: unknown, context: ParkErrorContext) => void\n}\n\nexport class SessionParkManager {\n #options: SessionParkOptions\n #owners = new Map<string, string>()\n #settled = new Map<string, string>()\n #timers = new Map<string, ReturnType<typeof setTimeout>>()\n #resuming = new Map<string, Promise<Runner | undefined>>()\n #detachTimers = new Map<string, ReturnType<typeof setTimeout>>()\n #configs = new Map<string, SessionRunnerConfig>()\n #remembered = new Set<string>()\n #storeOps = new Map<string, Promise<void>>()\n #watches = new Map<string, () => void>()\n #closed = false\n\n constructor(options: SessionParkOptions) {\n this.#options = options\n }\n\n remember(sessionId: string, config: SessionRunnerConfig): void {\n this.#configs.set(sessionId, config)\n }\n\n touch(runner: Runner): void {\n void this.#rememberDormant(runner)\n void this.#persistLive(runner)\n }\n\n async hydrate(): Promise<void> {\n const floor = Date.now() + (this.#options.expiredGraceMs ?? 60_000)\n for (const record of await this.#options.store.list()) {\n if (isDormant(record)) {\n continue\n }\n for (const execution of record.executions) {\n this.#track(record.id, execution, floor)\n }\n }\n }\n\n // The unsubscribe is retained, not merely returned. Every caller drops it, and `#track` has neither the `#closed`\n // guard the writers have nor an ownership check: a deferred dispatch reaching a closed manager still arms a\n // watchdog, and when that fires it rebuilds the session through the registry and factory of a generation that is\n // over. `release()` is the only thing that can take the listener off a runner nobody closed.\n watch(runner: Runner, afterSeq = 0): () => void {\n this.#watches.get(runner.id)?.()\n const unsubscribe = runner.subscribe((event) => {\n switch (event.type) {\n case 'execution_dispatched': {\n if (!event.deferred) {\n return\n }\n this.#track(runner.id, {\n executionId: event.executionId,\n toolName: event.toolName,\n expiresAt: event.expiresAt,\n })\n return\n }\n case 'execution_result':\n case 'execution_failed': {\n this.#forget(event.executionId)\n // One call of a multi-call park settling leaves the session parked on the rest, and no new status_changed will say so.\n if (runner.info().status === 'parked') {\n this.#parkQuietly(runner)\n }\n return\n }\n case 'status_changed': {\n if (event.status === 'parked') {\n this.#parkQuietly(runner)\n } else {\n void this.#rememberDormant(runner)\n }\n return\n }\n case 'turn_result':\n case 'permission_mode_changed':\n case 'model_changed': {\n void this.#persistLive(runner)\n return\n }\n case 'system_init': {\n void this.#rememberDormant(runner)\n return\n }\n case 'conversation_reset': {\n void this.#rememberDormant(runner)\n void this.#persistLive(runner)\n return\n }\n case 'session_closed': {\n if (this.#closed) {\n return\n }\n this.discard(runner.id).catch((error: unknown) => this.#options.onError?.(error, { sessionId: runner.id, phase: 'discard' }))\n return\n }\n default: {\n return\n }\n }\n }, afterSeq)\n const detach = (): void => {\n if (this.#watches.get(runner.id) === detach) {\n this.#watches.delete(runner.id)\n }\n unsubscribe()\n }\n this.#watches.set(runner.id, detach)\n return detach\n }\n\n // Hands a live session to another manager: stops watching it, forgets what this manager knows about it, and\n // returns the one fact the next manager cannot rederive. A durable record strips `env`, `queryFn`, `historyFn`\n // and `extraOptions`, and before `system_init` there is no record at all, so `#configs` is not recoverable from\n // the store. Deliberately leaves the store alone: the record is the point of the handover, not a casualty of it.\n release(sessionId: string): SessionRunnerConfig | undefined {\n this.#watches.get(sessionId)?.()\n const config = this.#configs.get(sessionId)\n this.#forgetSession(sessionId)\n return config\n }\n\n // The order is what `#rememberDormant`'s ownership guard turns into a silent no-write if reversed: `touch()`\n // writes nothing for a runner this manager's registry does not hold, so the register comes first. `#rebuild` does\n // the same four steps for the same reason. `lastSeq`, never 0: replaying a long session's history queues one\n // dormant re-save per historical `status_changed`, and the single `touch()` is what writes the current record.\n adopt(runner: Runner, config?: SessionRunnerConfig): void {\n this.#options.registry.register(runner)\n if (config) {\n this.remember(runner.id, config)\n }\n this.watch(runner, runner.info().lastSeq)\n this.touch(runner)\n }\n\n // `touch()` is fire-and-forget for the PATCH route that has no one to report to. A caller that is about to close\n // this manager, or to let another one write the same files, needs to know the write landed.\n async flush(sessionId?: string): Promise<void> {\n if (sessionId === undefined) {\n await Promise.all(this.#storeOps.values())\n return\n }\n await this.#storeOps.get(sessionId)\n }\n\n onDetach(sessionId: string): void {\n if (this.#closed) {\n return\n }\n const runner = this.#options.registry.get(sessionId)\n if (!runner || runner.info().status !== 'parked') {\n return\n }\n clearTimeout(this.#detachTimers.get(sessionId))\n const timer = setTimeout(() => {\n this.#detachTimers.delete(sessionId)\n this.#parkQuietly(runner)\n }, this.#options.parkDelayMs ?? 2000)\n timer.unref?.()\n this.#detachTimers.set(sessionId, timer)\n }\n\n sessionFor(executionId: string): string | undefined {\n return this.#owners.get(executionId) ?? this.#settled.get(executionId)\n }\n\n get(id: string): Promise<StoredSessionRecord | null> {\n return this.#queue(id, () => this.#options.store.get(id))\n }\n\n // Renamed in place: waking an engine child to change a label is the wrong trade. Undefined once the session is live.\n retitle(id: string, title: string | undefined): Promise<SessionInfo | undefined> {\n return this.#queue(id, async () => {\n const record = await this.#options.store.get(id)\n if (!record || this.#options.registry.get(id)) {\n return undefined\n }\n const { title: previous, ...meta } = record.config.meta ?? {}\n const shown = title ?? (record.info.title === previous ? undefined : record.info.title)\n const info: SessionInfo = { ...record.info, title: shown, meta: title ? { ...record.info.meta, title } : meta }\n const config: SessionRunnerConfig = { ...record.config, meta: title ? { ...meta, title } : meta }\n await this.#options.store.save({ ...record, info, config })\n return info\n })\n }\n\n async listInfo(): Promise<SessionInfo[]> {\n await Promise.all(this.#storeOps.values())\n const records = await this.#options.store.list()\n return records.filter((record) => this.#options.registry.get(record.id) === undefined).map((record) => record.info)\n }\n\n async ensureLive(id: string): Promise<Runner | undefined> {\n const live = this.#options.registry.get(id)\n if (live) {\n return live\n }\n return this.#resume(id)\n }\n\n async submitResult(executionId: string, result: ToolExecutionResult): Promise<{ applied: boolean; sessionId: string } | undefined> {\n const sessionId = this.#owners.get(executionId)\n if (sessionId === undefined) {\n const settled = this.#settled.get(executionId)\n return settled === undefined ? undefined : { applied: false, sessionId: settled }\n }\n const runner = await this.ensureLive(sessionId)\n if (!runner) {\n this.#forget(executionId)\n return undefined\n }\n // Clear the watchdog first: settling re-enters the agent loop, and a timeout firing behind it would fail a call that no longer exists.\n this.#clearTimer(executionId)\n const applied = runner.settleExecution?.(executionId, result) ?? false\n if (applied) {\n this.#forget(executionId)\n }\n return { applied, sessionId }\n }\n\n async discard(sessionId: string): Promise<void> {\n // Dropped rather than run: `discard` is reached from the `session_closed` arm of the very subscription this\n // handle unsubscribes, and the runner drops its subscribers on close anyway.\n this.#forgetSession(sessionId)\n for (const [executionId, owner] of this.#owners) {\n if (owner === sessionId) {\n this.#forget(executionId)\n }\n }\n for (const [executionId, owner] of this.#settled) {\n if (owner === sessionId) {\n this.#settled.delete(executionId)\n }\n }\n await this.#queue(sessionId, () => this.#options.store.delete(sessionId))\n }\n\n close(): void {\n this.#closed = true\n for (const timer of this.#timers.values()) {\n clearTimeout(timer)\n }\n for (const timer of this.#detachTimers.values()) {\n clearTimeout(timer)\n }\n this.#timers.clear()\n this.#detachTimers.clear()\n }\n\n #forgetSession(sessionId: string): void {\n this.#watches.delete(sessionId)\n clearTimeout(this.#detachTimers.get(sessionId))\n this.#detachTimers.delete(sessionId)\n this.#configs.delete(sessionId)\n this.#remembered.delete(sessionId)\n }\n\n // The config of a runner this manager may still write for: open, remembered, and the registry's current object.\n #ownedConfig(runner: Runner): SessionRunnerConfig | undefined {\n if (this.#closed || this.#options.registry.get(runner.id) !== runner) {\n return undefined\n }\n return this.#configs.get(runner.id)\n }\n\n async #rememberDormant(runner: Runner): Promise<void> {\n const config = this.#ownedConfig(runner)\n const info = runner.info()\n if (!config || !(info.capabilities ?? ENGINE_CAPABILITIES[engineOf(info)]).resume) {\n return\n }\n const sdkSessionId = info.sdkSessionId\n if (sdkSessionId === undefined) {\n // Checked last, behind the ownership guard: before the engine has ever named a session there is no record to remove.\n if (this.#remembered.has(runner.id)) {\n await this.#forgetDormant(runner.id)\n }\n return\n }\n const record: DormantSessionRecord = { kind: 'dormant', ...idleRecordBase(runner, config), sdkSessionId, savedAt: Date.now() }\n try {\n // Marked before the write: a queued save already means a record may exist, and a reset arriving mid-write must not skip the forget.\n this.#remembered.add(runner.id)\n await this.#queue(runner.id, () => this.#options.store.save(record))\n } catch (error) {\n this.#options.onError?.(error, { sessionId: runner.id, phase: 'remember' })\n }\n }\n\n async #forgetDormant(sessionId: string): Promise<void> {\n this.#remembered.delete(sessionId)\n try {\n await this.#queue(sessionId, () => this.#options.store.delete(sessionId))\n } catch (error) {\n this.#options.onError?.(error, { sessionId, phase: 'remember' })\n }\n }\n\n async #persistLive(runner: Runner): Promise<void> {\n const config = this.#ownedConfig(runner)\n if (!config || !this.#options.persistLive || !runner.snapshot) {\n return\n }\n try {\n await this.#queue(runner.id, async () => {\n // Re-checked inside the queue: a park's record must not be overwritten by the live copy queued behind it.\n if (this.#closed || this.#options.registry.get(runner.id) !== runner) {\n return\n }\n const snapshot = runner.snapshot?.()\n if (!snapshot) {\n return\n }\n const record: ParkedSessionRecord = {\n kind: 'live',\n ...idleRecordBase(runner, config),\n snapshot,\n executions: snapshot.parked,\n parkedAt: Date.now(),\n }\n await this.#options.store.save(record)\n })\n } catch (error) {\n this.#options.onError?.(error, { sessionId: runner.id, phase: 'remember' })\n }\n }\n\n #parkQuietly(runner: Runner): void {\n this.#park(runner).catch((error: unknown) => this.#options.onError?.(error, { sessionId: runner.id, phase: 'park' }))\n }\n\n async #park(runner: Runner): Promise<void> {\n const config = this.#ownedConfig(runner)\n const id = runner.id\n if (!config || !runner.park || runner.info().status !== 'parked' || this.#options.attachedCount(id) > 0) {\n return\n }\n const executions = [...this.#owners].filter(([, owner]) => owner === id).map(([e]) => e)\n if (executions.length === 0) {\n return\n }\n if (this.#options.onParking && !this.#options.onParking(id, executions[0]!)) {\n return\n }\n const cost = runner.costState?.()\n const snapshot = runner.park()\n if (!snapshot) {\n return\n }\n this.#options.onParked?.(id, executions[0]!)\n const info = { ...runner.info(), status: 'parked' as const }\n this.#options.registry.evict(id)\n const record: ParkedSessionRecord = {\n kind: 'parked',\n id,\n info,\n profile: info.profile,\n config,\n snapshot,\n executions: snapshot.parked,\n cost,\n parkedAt: Date.now(),\n }\n for (const execution of snapshot.parked) {\n this.#track(id, execution)\n }\n try {\n await this.#queue(id, () => this.#options.store.save(record))\n } catch (error) {\n this.#options.onError?.(error, { sessionId: id, phase: 'park' })\n }\n }\n\n async #resume(id: string): Promise<Runner | undefined> {\n const inFlight = this.#resuming.get(id)\n if (inFlight) {\n return inFlight\n }\n const attempt = this.#rebuild(id)\n this.#resuming.set(id, attempt)\n try {\n return await attempt\n } finally {\n this.#resuming.delete(id)\n }\n }\n\n async #rebuild(id: string): Promise<Runner | undefined> {\n const record = await this.#queue(id, () => this.#options.store.get(id))\n if (!record) {\n return undefined\n }\n let runner: Runner\n try {\n runner = await this.#options.rebuild(record)\n } catch (error) {\n this.#options.onError?.(error, { sessionId: id, phase: 'resume' })\n throw error\n }\n if (runner.id !== id) {\n runner.close('error')\n const error = new Error(\n `rebuilt session has id '${runner.id}', expected '${id}' - the engine factory must ` +\n 'forward EngineRunnerContext.restore (or, without a snapshot, the session id) ' +\n 'to the runner config',\n )\n this.#options.onError?.(error, { sessionId: id, phase: 'resume' })\n throw error\n }\n runner.carryCost?.(record.cost ?? { byModel: record.info.usageByModel, reportedCostUsd: record.info.totalCostUsd })\n this.#options.registry.register(runner)\n // The config the runner was actually built with, not the one on the record: a dormant wake\n // bumps the epoch, and the next park must carry the new one rather than resurrect the old.\n this.remember(id, { ...record.config, epoch: runner.info().epoch })\n // A park must not re-arm watchdogs from its own replayed events; a dormant session starts a fresh log, so it has no prior seq to skip.\n this.watch(runner, isDormant(record) ? 0 : record.snapshot.seq)\n this.#options.onResumed?.(id, runner)\n if (!isDormant(record) && !isLiveRecord(record)) {\n await this.#queue(id, () => this.#options.store.delete(id))\n }\n void runner.start()\n return runner\n }\n\n #queue<T>(sessionId: string, op: () => Promise<T>): Promise<T> {\n const previous = this.#storeOps.get(sessionId) ?? Promise.resolve()\n const result = previous.then(op)\n const settled = result.then(\n () => {},\n () => {},\n )\n this.#storeOps.set(sessionId, settled)\n void settled.then(() => {\n if (this.#storeOps.get(sessionId) === settled) {\n this.#storeOps.delete(sessionId)\n }\n })\n return result\n }\n\n #track(sessionId: string, execution: ParkedExecution, notBefore = 0): void {\n this.#owners.set(execution.executionId, sessionId)\n if (execution.expiresAt === undefined || this.#timers.has(execution.executionId)) {\n return\n }\n const expiresAt = Math.max(execution.expiresAt, notBefore)\n const timer = setTimeout(\n () => {\n this.#timers.delete(execution.executionId)\n void this.submitResult(execution.executionId, {\n status: 'failed',\n reason: 'timeout',\n error: `deferred execution '${execution.toolName}' produced no result before its deadline`,\n }).catch((error: unknown) => {\n this.#options.onError?.(error, { sessionId, phase: 'resume' })\n })\n },\n Math.max(0, expiresAt - Date.now()),\n )\n timer.unref?.()\n this.#timers.set(execution.executionId, timer)\n }\n\n #forget(executionId: string): void {\n this.#clearTimer(executionId)\n const owner = this.#owners.get(executionId)\n if (owner !== undefined) {\n this.#settled.set(executionId, owner)\n if (this.#settled.size > SETTLED_MAX) {\n this.#settled.delete(this.#settled.keys().next().value!)\n }\n }\n this.#owners.delete(executionId)\n }\n\n #clearTimer(executionId: string): void {\n const timer = this.#timers.get(executionId)\n if (timer === undefined) {\n return\n }\n clearTimeout(timer)\n this.#timers.delete(executionId)\n }\n}\n\n// What a dormant and a live record share: the session as it would list while nothing runs it, and the config it was\n// built with plus the metadata it has gathered since.\nfunction idleRecordBase(\n runner: Runner,\n config: SessionRunnerConfig,\n): Pick<ParkedSessionRecord, 'id' | 'info' | 'profile' | 'config' | 'cost'> {\n const info = runner.info()\n return {\n id: runner.id,\n info: { ...info, status: 'idle' },\n profile: info.profile,\n config: { ...config, meta: info.meta },\n cost: runner.costState?.(),\n }\n}\n","import type { Runner } from '@workerdeck/core'\n\nexport type ProducedFile = {\n fileId: string\n path: string\n mediaType?: string\n bytes?: number\n sessionId: string\n}\n\nexport class ProducedFileStore {\n #bySession = new Map<string, Map<string, ProducedFile>>()\n\n watch(runner: Runner): () => void {\n return runner.subscribe((event) => {\n if (event.type !== 'file_produced') {\n return\n }\n const held = this.#bySession.get(runner.id) ?? new Map<string, ProducedFile>()\n held.set(event.fileId, {\n fileId: event.fileId,\n path: event.path,\n ...(event.mediaType ? { mediaType: event.mediaType } : {}),\n ...(event.bytes !== undefined ? { bytes: event.bytes } : {}),\n sessionId: runner.id,\n })\n this.#bySession.set(runner.id, held)\n }, 0)\n }\n\n get(sessionId: string, fileId: string): ProducedFile | undefined {\n return this.#bySession.get(sessionId)?.get(fileId)\n }\n\n list(sessionId: string): ProducedFile[] {\n return [...(this.#bySession.get(sessionId)?.values() ?? [])]\n }\n\n drop(sessionId: string): void {\n this.#bySession.delete(sessionId)\n }\n}\n","import { existsSync } from 'node:fs'\nimport { supportsPermissionMode, type ProfileEngine, type ProfileInfo } from '@workerdeck/protocol'\nimport type { EngineAdapter, EngineAvailability } from '@workerdeck/core'\nimport type { Refusal } from '../lib/http.ts'\nimport { cwdAllowed, engineOf, isProviderProfile } from '../lib/profile-env.ts'\nimport type { ProfileStore } from './profile-store.ts'\n\nexport type { Refusal }\n\nexport type ProfileServiceOptions = {\n declared: ProfileInfo[]\n seed?: ProfileInfo[]\n store?: ProfileStore\n allowedConfigDirRoots?: string[]\n disableBypassPermissions?: boolean\n hasEngineRunnerFactory: boolean\n adapterFor: (engine: ProfileEngine | undefined) => EngineAdapter\n decorate: {\n defaultModel: (name: string) => string | undefined\n availability: (name: string) => EngineAvailability | undefined\n usage: (name: string) => ProfileInfo['usage'] | undefined\n spend?: (name: string) => ProfileInfo['spend'] | undefined\n }\n}\n\nexport class ProfileService {\n readonly #declared: ProfileInfo[]\n readonly #declaredByName: Map<string, ProfileInfo>\n readonly #stored = new Map<string, ProfileInfo>()\n readonly #opts: ProfileServiceOptions\n\n constructor(opts: ProfileServiceOptions) {\n this.#opts = opts\n this.#declared = opts.declared\n this.#declaredByName = new Map(opts.declared.map((p) => [p.name, p]))\n if (this.#declaredByName.size !== opts.declared.length) {\n throw new Error('createWorkerServer: duplicate profile names in `profiles`')\n }\n }\n\n validate(p: ProfileInfo): string | null {\n const { adapterFor, disableBypassPermissions, hasEngineRunnerFactory } = this.#opts\n if (isProviderProfile(p)) {\n if (!p.provider?.id) {\n return `provider profile '${p.name}' is missing provider.id`\n }\n if (!hasEngineRunnerFactory) {\n return `profile '${p.name}' uses engine 'provider' but no ` + '`createEngineRunner` was provided to build one'\n }\n } else if (p.engine === 'codex') {\n if (p.codexHome && !existsSync(p.codexHome)) {\n return `profile '${p.name}' codexHome does not exist: ${p.codexHome}`\n }\n } else if (!p.configDir || !existsSync(p.configDir)) {\n return `profile '${p.name}' configDir does not exist: ${p.configDir}`\n }\n if (disableBypassPermissions && p.defaults?.permissionMode === 'bypassPermissions') {\n return `profile '${p.name}' defaults to bypassPermissions but disableBypassPermissions is set`\n }\n const fallbackMode = p.defaults?.permissionMode\n if (fallbackMode && !supportsPermissionMode(p.engine, fallbackMode)) {\n return (\n `profile '${p.name}' defaults to permission mode '${fallbackMode}', which engine ` +\n `'${engineOf(p)}' does not support (supported: ` +\n `${adapterFor(engineOf(p)).capabilities.permissionModes.join(', ')})`\n )\n }\n return null\n }\n\n async refreshStored(): Promise<void> {\n if (!this.#opts.store) {\n return\n }\n this.#stored.clear()\n for (const p of await this.#opts.store.list()) {\n this.#stored.set(p.name, p)\n }\n }\n\n // Auto-detected profiles land in the store, not in `declared`, so the first thing an operator sees\n // is a profile they can rename, retarget or delete. Seeding only an empty store is what keeps it a\n // first-launch act: once a profile exists, detection never writes again.\n async seedStore(): Promise<void> {\n const seed = this.#opts.seed ?? []\n if (!this.#opts.store || seed.length === 0 || this.#stored.size > 0) {\n return\n }\n for (const p of seed) {\n if (this.validate(p) === null) {\n await this.#opts.store.save(p)\n }\n }\n await this.refreshStored()\n }\n\n withManagedFlag(p: ProfileInfo): ProfileInfo {\n return this.#declaredByName.has(p.name) ? p : { ...p, managed: true }\n }\n\n forResponse(p: ProfileInfo): ProfileInfo {\n const { adapterFor, decorate } = this.#opts\n const adapter = adapterFor(p.engine)\n const base: ProfileInfo = {\n ...this.withManagedFlag(p),\n capabilities: adapter.capabilities,\n }\n if (adapter.catalog.models.length > 0) {\n base.models = adapter.catalog.models\n }\n const defaultModel = decorate.defaultModel(p.name)\n if (defaultModel) {\n base.defaultModel = defaultModel\n }\n const probed = decorate.availability(p.name)\n if (probed && probed.available !== 'unknown') {\n base.available = probed.available\n if (probed.available === false) {\n base.unavailableReason = probed.reason\n }\n }\n const usage = decorate.usage(p.name)\n if (usage) {\n base.usage = usage\n }\n const spend = decorate.spend?.(p.name)\n if (spend) {\n base.spend = spend\n }\n return base\n }\n\n all(): ProfileInfo[] {\n return [...this.#declared, ...[...this.#stored.values()].filter((p) => !this.#declaredByName.has(p.name))]\n }\n\n get(name: string): ProfileInfo | undefined {\n return this.#declaredByName.get(name) ?? this.#stored.get(name)\n }\n\n manageGuard(auth: { canManageProfiles?: boolean }): Refusal | null {\n if (!this.#opts.store) {\n return { status: 404, error: 'profile management is not enabled on this server' }\n }\n if (!auth.canManageProfiles) {\n return { status: 403, error: 'not allowed to manage profiles' }\n }\n return null\n }\n\n declaredGuard(profile: ProfileInfo): Refusal | null {\n return this.#declaredByName.has(profile.name)\n ? {\n status: 403,\n error:\n `profile '${profile.name}' is declared in server options and cannot be changed ` +\n 'over the API - edit the `profiles` option instead',\n }\n : null\n }\n\n configDirGuard(profile: ProfileInfo): Refusal | null {\n if (isProviderProfile(profile)) {\n return null\n }\n const codex = engineOf(profile) === 'codex'\n const dir = codex ? profile.codexHome : profile.configDir\n // A codex profile that names no CODEX_HOME runs on the server's own environment, which every\n // session already inherits - there is no separate credential store for the roots to bound.\n if (codex && !dir) {\n return null\n }\n const roots = this.#opts.allowedConfigDirRoots\n if (!roots || roots.length === 0) {\n return {\n status: 403,\n error: 'managed Claude and Codex profiles are disabled: set `allowedConfigDirRoots` to the ' + 'directories they may point at',\n }\n }\n return dir && cwdAllowed(dir, roots)\n ? null\n : { status: 403, error: `${codex ? 'codexHome' : 'configDir'} is outside the allowed roots` }\n }\n\n async saveManaged(incoming: ProfileInfo): Promise<{ ok: true; profile: ProfileInfo } | ({ ok: false } & Refusal)> {\n const { managed: _clientClaim, ...profile } = incoming\n const refused = this.configDirGuard(profile)\n if (refused) {\n return { ok: false, ...refused }\n }\n const invalid = this.validate(profile)\n if (invalid) {\n return { ok: false, status: 400, error: invalid }\n }\n await this.#opts.store!.save(profile)\n await this.refreshStored()\n return { ok: true, profile: this.withManagedFlag(profile) }\n }\n}\n","import type { Runner } from '@workerdeck/core'\nimport type { ProfileUsage, ProfileUsageWindow, RateLimitInfo } from '@workerdeck/protocol'\n\ntype HeldWindow = { info: RateLimitInfo; updatedAt: number }\n\nexport class ProfileUsageTracker {\n #profiles = new Map<string, Map<string, HeldWindow>>()\n\n watch(runner: Runner): () => void {\n const profile = runner.info().profile\n if (!profile) {\n return () => {}\n }\n return runner.subscribe((event) => {\n if (event.type !== 'rate_limit') {\n return\n }\n const type = event.info.rateLimitType\n if (!type) {\n return\n }\n let windows = this.#profiles.get(profile)\n if (!windows) {\n this.#profiles.set(profile, (windows = new Map()))\n }\n const held = windows.get(type)\n if (held && held.updatedAt > event.ts) {\n return\n }\n windows.set(type, { info: event.info, updatedAt: event.ts })\n })\n }\n\n usage(profile: string, now = Date.now()): ProfileUsage | undefined {\n const windows = this.#profiles.get(profile)\n if (!windows || windows.size === 0) {\n return undefined\n }\n const out: ProfileUsage = {}\n for (const [type, held] of windows) {\n out[type] = serveWindow(held, now)\n }\n return out\n }\n}\n\n// `resetsAt` is epoch seconds (protocol contract); `now` is epoch ms.\nfunction serveWindow(held: HeldWindow, now: number): ProfileUsageWindow {\n const resetsAt = held.info.resetsAt\n if (resetsAt !== undefined && resetsAt * 1000 <= now) {\n return {\n info: {\n // The dropped `resetsAt`/`isUsingOverage` describe the window that rolled, not this one.\n status: 'allowed',\n rateLimitType: held.info.rateLimitType,\n utilization: 0,\n },\n updatedAt: held.updatedAt,\n inferredReset: true,\n }\n }\n return { info: held.info, updatedAt: held.updatedAt }\n}\n","import type { Runner } from '@workerdeck/core'\nimport {\n type ByModel,\n type PricingTable,\n type ProfileSpend,\n costOfByModel,\n mergeByModel,\n subscriptionComparison,\n} from '@workerdeck/protocol'\nimport { readJsonOr, writeJsonAtomic } from '../lib/atomic-file.ts'\n\nexport type SpendRecord = { days: Record<string, Record<string, ByModel>> }\n\nexport type SpendStore = {\n load(): Promise<SpendRecord | undefined>\n save(record: SpendRecord): Promise<void>\n}\n\nexport type SpendLedgerOptions = {\n pricing?: PricingTable\n store?: SpendStore\n monthlySubscriptionUsd?: (profile: string) => number | undefined\n retentionDays?: number\n saveDebounceMs?: number\n onError?: (error: unknown) => void\n}\n\nconst DEFAULT_RETENTION_DAYS = 92\n\nconst DEFAULT_SAVE_DEBOUNCE_MS = 2_000\n\nexport function dayKey(at: number): string {\n const d = new Date(at)\n return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`\n}\n\nfunction daysBack(now: number, count: number): string[] {\n const out: string[] = []\n for (let i = 0; i < count; i += 1) {\n out.push(dayKey(now - i * 86_400_000))\n }\n return out\n}\n\nfunction subtract(current: ByModel, previous: ByModel): ByModel {\n const delta: ByModel = {}\n for (const [model, usage] of Object.entries(current)) {\n const was = previous[model]\n const row = {\n input: usage.input - (was?.input ?? 0),\n output: usage.output - (was?.output ?? 0),\n cacheWrite5m: usage.cacheWrite5m - (was?.cacheWrite5m ?? 0),\n cacheWrite1h: usage.cacheWrite1h - (was?.cacheWrite1h ?? 0),\n cacheRead: usage.cacheRead - (was?.cacheRead ?? 0),\n }\n // A negative delta means the session's cumulative figure went backwards, which only happens when the reading\n // we diffed against was not this session's. Recording nothing beats recording a negative day.\n if (Object.values(row).some((value) => value < 0)) {\n continue\n }\n if (Object.values(row).some((value) => value > 0)) {\n delta[model] = row\n }\n }\n return delta\n}\n\n// `turn_result.usageByModel` is session-cumulative, so the ledger records the difference from what this session\n// last contributed. The baseline is seeded from the runner's own info at watch time, which is what keeps a woken\n// session's carried spend from being banked a second time as if it had just been earned.\nexport class SpendLedger {\n #days: Record<string, Record<string, ByModel>> = {}\n #lastBanked = new Map<string, ByModel>()\n #options: SpendLedgerOptions\n #saveTimer: ReturnType<typeof setTimeout> | undefined\n #loaded: Promise<void> | undefined\n\n constructor(options: SpendLedgerOptions = {}) {\n this.#options = options\n }\n\n load(): Promise<void> {\n this.#loaded ??= this.#load()\n return this.#loaded\n }\n\n async #load(): Promise<void> {\n const store = this.#options.store\n if (!store) {\n return\n }\n try {\n const record = await store.load()\n if (record?.days) {\n this.#days = record.days\n }\n } catch (error) {\n this.#options.onError?.(error)\n }\n }\n\n watch(runner: Runner): () => void {\n const info = runner.info()\n const profile = info.profile\n if (!profile) {\n return () => {}\n }\n this.#lastBanked.set(runner.id, info.usageByModel ?? {})\n const unsubscribe = runner.subscribe((event) => {\n if (event.type !== 'turn_result' || !event.usageByModel) {\n return\n }\n this.#bank(profile, event.usageByModel, runner.id, event.ts)\n })\n return () => {\n unsubscribe()\n this.#lastBanked.delete(runner.id)\n }\n }\n\n #bank(profile: string, cumulative: ByModel, sessionId: string, at: number): void {\n const previous = this.#lastBanked.get(sessionId) ?? {}\n const delta = subtract(cumulative, previous)\n this.#lastBanked.set(sessionId, cumulative)\n if (Object.keys(delta).length === 0) {\n return\n }\n const key = dayKey(at)\n const day = (this.#days[key] ??= {})\n day[profile] = mergeByModel(day[profile] ?? {}, delta)\n this.#scheduleSave()\n }\n\n spend(profile: string, now = Date.now()): ProfileSpend | undefined {\n const week = this.#window(profile, daysBack(now, 7))\n const month = this.#window(profile, daysBack(now, 30))\n if (Object.keys(month).length === 0) {\n return undefined\n }\n const weekCost = costOfByModel(week, this.#options.pricing)\n const monthlySubscriptionUsd = this.#options.monthlySubscriptionUsd?.(profile)\n return {\n weekUsd: weekCost.total,\n monthUsd: costOfByModel(month, this.#options.pricing).total,\n weekByModel: week,\n unpricedShare: weekCost.unpricedShare,\n monthlySubscriptionUsd,\n subscription: monthlySubscriptionUsd ? subscriptionComparison(weekCost.total, monthlySubscriptionUsd) : undefined,\n }\n }\n\n #window(profile: string, keys: string[]): ByModel {\n let out: ByModel = {}\n for (const key of keys) {\n const day = this.#days[key]?.[profile]\n if (day) {\n out = mergeByModel(out, day)\n }\n }\n return out\n }\n\n #scheduleSave(): void {\n if (!this.#options.store || this.#saveTimer) {\n return\n }\n this.#saveTimer = setTimeout(() => {\n this.#saveTimer = undefined\n void this.flush()\n }, this.#options.saveDebounceMs ?? DEFAULT_SAVE_DEBOUNCE_MS)\n this.#saveTimer.unref?.()\n }\n\n async flush(): Promise<void> {\n const store = this.#options.store\n if (!store) {\n return\n }\n this.#prune()\n try {\n await store.save({ days: this.#days })\n } catch (error) {\n this.#options.onError?.(error)\n }\n }\n\n #prune(): void {\n const keep = new Set(daysBack(Date.now(), this.#options.retentionDays ?? DEFAULT_RETENTION_DAYS))\n for (const key of Object.keys(this.#days)) {\n if (!keep.has(key)) {\n delete this.#days[key]\n }\n }\n }\n\n close(): void {\n clearTimeout(this.#saveTimer)\n this.#saveTimer = undefined\n }\n}\n\nexport function createFileSpendStore(path: string, onError?: (error: unknown) => void): SpendStore {\n return {\n async load() {\n const parsed = await readJsonOr(path, undefined)\n if (parsed === null || typeof parsed !== 'object' || typeof (parsed as SpendRecord).days !== 'object') {\n return undefined\n }\n return parsed as SpendRecord\n },\n async save(record) {\n try {\n await writeJsonAtomic(path, record)\n } catch (error) {\n onError?.(error)\n }\n },\n }\n}\n","import { readFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport type { PeerDirectory, PeerPeek, PeerSendResult, PeerSessionSummary } from '@workerdeck/core'\nimport type { ChecklistItem } from '@workerdeck/protocol'\nimport {\n connectRelay,\n parseRelayPeerId,\n type RelayConnection,\n type RelayHost,\n type RelayOp,\n type RelayPeek,\n type RelayPeerRow,\n} from '@workerdeck/relay-client'\nimport type { PeerService } from './peers.ts'\n\nexport type RelayLinkOptions = {\n url: string\n gateway: string\n key?: string\n keyFile?: string\n caFile?: string\n // The gateway ceiling. Sessions outside `scope` are never published and never answer a relay-routed request;\n // `allow` is what this gateway accepts from other gateways at all, whatever the relay's rules say.\n expose?: { scope?: Record<string, string>; allow?: RelayOp[] }\n log?: (message: string) => void\n}\n\nexport type RelayLink = {\n directory: PeerDirectory\n nudge(): void\n // Hands the connection to the next module generation instead of closing it (hot reload).\n release(): void\n close(): void\n}\n\ntype Carried = { identity: string; connection: RelayConnection }\n\n// Keyed through `Symbol.for`, so the generation a hot reload builds finds what the old one released.\nconst CARRIED = Symbol.for('workerdeck.relay.carried')\nconst slots = globalThis as { [CARRIED]?: Carried }\n\nconst UNAVAILABLE = 'Remote gateways are unavailable right now; only sessions on this gateway are listed.'\n\nfunction expandHome(path: string): string {\n return path === '~' || path.startsWith('~/') ? `${homedir()}${path.slice(1)}` : path\n}\n\nfunction identityOf(options: RelayLinkOptions): string {\n return JSON.stringify([\n options.url,\n options.gateway,\n options.keyFile ?? '',\n options.key ? 'inline' : '',\n options.caFile ?? '',\n options.expose?.allow ?? null,\n ])\n}\n\nfunction remoteSummary(row: RelayPeerRow): PeerSessionSummary {\n return {\n id: `${row.gateway}:${row.id}`,\n gateway: row.gateway,\n engine: row.engine,\n status: row.status,\n title: row.title,\n project: row.project?.name,\n projectRoot: row.project?.root,\n cwd: row.cwd,\n profile: row.profile,\n model: row.model,\n contextUsage: row.contextUsage,\n lastActivityAt: row.lastActivityAt,\n pendingPermissionCount: row.pendingPermissionCount,\n allow: row.allow,\n }\n}\n\nfunction remotePeek(gateway: string, peek: RelayPeek): PeerPeek {\n const { allow: _allow, ...summary } = remoteSummary({ ...peek, gateway, allow: [] })\n return {\n ...summary,\n live: peek.live,\n checklist: peek.checklistItems as ChecklistItem[] | undefined,\n pendingApprovals: peek.pendingApprovals,\n recent: peek.recent,\n }\n}\n\nexport async function readRelayKey(options: RelayLinkOptions): Promise<string> {\n if (options.key) {\n return options.key\n }\n if (!options.keyFile) {\n throw new Error('relay: set relay.keyFile (or WORKERDECK_RELAY_KEY) to the key `workerdeck relay enroll` printed')\n }\n const key = (await readFile(expandHome(options.keyFile), 'utf8')).trim()\n if (!key) {\n throw new Error(`relay: ${options.keyFile} is empty`)\n }\n return key\n}\n\n// The local peer directory with the relay composed in: bare ids stay local, `gateway:session` ids go to the relay.\n// A scoped session never reaches past its own gateway, because nothing on the wire carries scope tags.\nexport function createRelayLink(options: RelayLinkOptions, peers: PeerService, log: (message: string) => void): RelayLink {\n const identity = identityOf(options)\n const exposed = options.expose?.scope\n let connection: RelayConnection | undefined\n let closed = false\n let released = false\n\n const host: RelayHost = {\n snapshot: () => peers.relayEntries(exposed),\n peek: (_origin, sessionId, recent) => peers.relayPeek(sessionId, recent, exposed),\n send: (origin, sessionId, text) => peers.relaySend(origin, sessionId, text, exposed),\n }\n\n const carried = slots[CARRIED]\n if (carried) {\n delete slots[CARRIED]\n if (carried.identity === identity && carried.connection.state() !== 'stopped') {\n carried.connection.setHost(host)\n connection = carried.connection\n } else {\n carried.connection.close()\n }\n }\n\n if (!connection) {\n void (async () => {\n const key = await readRelayKey(options)\n const ca = options.caFile ? await readFile(expandHome(options.caFile)) : undefined\n if (!closed) {\n connection = connectRelay({ url: options.url, gateway: options.gateway, key, ca, allow: options.expose?.allow, log }, host)\n }\n })().catch((error: unknown) => log(error instanceof Error ? error.message : String(error)))\n }\n\n const remoteTarget = parseRelayPeerId\n\n const reachesRemote = async (from: string): Promise<boolean> => {\n const me = await peers.relaySender(from)\n return me.scope === undefined || Object.keys(me.scope).length === 0\n }\n\n const directory: PeerDirectory = {\n list: async (from) => {\n const local = await peers.list(from)\n if (!connection || connection.state() !== 'online' || !(await reachesRemote(from))) {\n return local\n }\n try {\n return [...local, ...(await connection.list(from)).map(remoteSummary)]\n } catch {\n return local\n }\n },\n notice: async (from) => {\n if (!(await reachesRemote(from))) {\n return undefined\n }\n return connection?.state() === 'online' ? undefined : UNAVAILABLE\n },\n peek: async (from, sessionId, peekOptions) => {\n const target = remoteTarget(sessionId)\n if (!target) {\n return peers.peek(from, sessionId, peekOptions)\n }\n if (!connection || !(await reachesRemote(from))) {\n return undefined\n }\n const peek = await connection.peek(from, target, peekOptions?.recent)\n return peek ? remotePeek(target.gateway, peek) : undefined\n },\n send: async (from, sessionId, text, sendOptions): Promise<PeerSendResult> => {\n const target = remoteTarget(sessionId)\n if (!target) {\n return peers.send(from, sessionId, text, sendOptions)\n }\n if (!(await reachesRemote(from))) {\n return { delivered: false, reason: `no such session: ${sessionId}` }\n }\n if (!connection || connection.state() !== 'online') {\n return { delivered: false, reason: 'remote gateways are unavailable right now; try again later' }\n }\n try {\n const result = await connection.send(from, target, text, sendOptions?.hops ?? peers.relayChain(from))\n return result.delivered ? { ...result, sessionId } : result\n } catch (error) {\n return { delivered: false, reason: error instanceof Error ? error.message : String(error) }\n }\n },\n }\n\n return {\n directory,\n nudge: () => connection?.nudge(),\n release: () => {\n if (connection && !closed) {\n released = true\n slots[CARRIED] = { identity, connection }\n }\n },\n close: () => {\n closed = true\n if (!released) {\n connection?.close()\n }\n connection = undefined\n },\n }\n}\n","import {\n PEER_MESSAGE_MAX_CHARS,\n PEER_RECENT_DEFAULT,\n PEER_RECENT_MAX,\n peerSummary,\n recentLines,\n type PeerDirectory,\n type PeerPeek,\n type PeerSendOptions,\n type PeerSendResult,\n type PeerMention,\n type PeerSessionSummary,\n type Runner,\n} from '@workerdeck/core'\nimport {\n PEER_MENTION_MAX,\n peerMentionKey,\n peerMentionSlug,\n scanPeerMentions,\n type MessageOrigin,\n type SessionEvent,\n type SessionInfo,\n} from '@workerdeck/protocol'\nimport type { RelayOrigin, RelayPeek, RelaySendResult, RelaySessionEntry } from '@workerdeck/relay-client'\nimport { scopeMatches } from '../lib/scope.ts'\nimport type { LateBoundRefs } from '../options.ts'\nimport type { ProjectInfoService } from './project-info.ts'\nimport type { SessionRegistry } from './registry.ts'\n\nexport type PeerServiceOptions = {\n enabled?: boolean\n maxMessageChars?: number\n perMinute?: number\n maxHops?: number\n}\n\nexport type PeerServiceDeps = {\n refs: LateBoundRefs\n projects: ProjectInfoService\n options?: PeerServiceOptions\n}\n\nconst DEFAULT_PER_MINUTE = 10\nconst DEFAULT_MAX_HOPS = 12\nconst WINDOW_MS = 60_000\n\nfunction visible(from: SessionInfo, to: SessionInfo): boolean {\n return to.id !== from.id && scopeMatches(from.scope, to.scope)\n}\n\nexport type PeerService = PeerDirectory & {\n watch(runner: Runner): () => void\n // The `#Name` tokens in a message a person typed, resolved to the peers that session can see.\n mentions(from: string, text: string): Promise<PeerMention[]>\n // The relay half. `exposed` is the gateway ceiling's scope: a session outside it is never published and never\n // answers an inbound request, whatever the relay asks.\n relaySender(from: string): Promise<SessionInfo>\n relayChain(from: string): string[]\n relayEntries(exposed: Record<string, string> | undefined): Promise<RelaySessionEntry[]>\n relayPeek(sessionId: string, recent: number | undefined, exposed: Record<string, string> | undefined): Promise<RelayPeek | undefined>\n relaySend(origin: RelayOrigin, sessionId: string, text: string, exposed: Record<string, string> | undefined): Promise<RelaySendResult>\n}\n\nexport function relayEntry(info: SessionInfo, live: boolean): RelaySessionEntry {\n const items = info.checklist\n return {\n id: info.id,\n engine: info.engine,\n status: info.status,\n title: info.title,\n project: info.project ? { name: info.project.name, root: info.project.root } : undefined,\n cwd: info.cwd,\n profile: info.profile,\n model: info.model,\n permissionMode: info.permissionMode,\n contextUsage: info.contextUsage,\n checklist: items?.length ? { done: items.filter((item) => item.status === 'completed').length, total: items.length } : undefined,\n numTurns: info.numTurns,\n createdAt: info.createdAt,\n lastActivityAt: info.lastActivityAt,\n pendingPermissionCount: info.pendingPermissionCount,\n live,\n }\n}\n\n// Session-to-session messaging inside one gateway. Visibility is the session-scope rule the HTTP routes enforce,\n// applied with the *sender's* scope as the principal: a scoped session sees the sessions a scoped client would.\nexport function createPeerService(deps: PeerServiceDeps): PeerService {\n const perMinute = deps.options?.perMinute ?? DEFAULT_PER_MINUTE\n const maxChars = deps.options?.maxMessageChars ?? PEER_MESSAGE_MAX_CHARS\n const maxHops = deps.options?.maxHops ?? DEFAULT_MAX_HOPS\n const sent = new Map<string, number[]>()\n // The chain of sessions that led to the last peer message each session received, cleared when a human speaks to\n // it: two agents answering each other without a person in the loop is the loop this bounds.\n const inbound = new Map<string, string[]>()\n\n const registry = (): SessionRegistry => {\n const found = deps.refs.registry\n if (!found) {\n throw new Error('peer messaging is not ready')\n }\n return found\n }\n\n const allSessions = async (): Promise<SessionInfo[]> => {\n const live = registry().list()\n const dormant = (await deps.refs.parking?.listInfo()) ?? []\n return [...live, ...dormant].map((info) => deps.projects.withProject(info))\n }\n\n const infoOf = async (id: string): Promise<SessionInfo | undefined> => {\n const live = registry().get(id)?.info()\n if (live) {\n return deps.projects.withProject(live)\n }\n const record = await deps.refs.parking?.get(id)\n return record ? deps.projects.withProject(record.info) : undefined\n }\n\n const sender = async (from: string): Promise<SessionInfo> => {\n const info = await infoOf(from)\n if (!info) {\n throw new Error(`unknown sender session: ${from}`)\n }\n return info\n }\n\n const recentOf = (sessionId: string, recent: number | undefined): { runner: Runner | undefined; lines: string[] } => {\n const limit = Math.min(Math.max(recent ?? PEER_RECENT_DEFAULT, 0), PEER_RECENT_MAX)\n const runner = registry().get(sessionId)\n const events: SessionEvent[] = []\n if (runner && limit > 0) {\n runner.subscribe((event) => events.push(event), 0, { truncateResults: true, imageRefs: true })()\n }\n return { runner, lines: recentLines(events, limit) }\n }\n\n const underRateLimit = (from: string, to: string): boolean => {\n const key = `${from}->${to}`\n const now = Date.now()\n const recent = (sent.get(key) ?? []).filter((at) => now - at < WINDOW_MS)\n if (recent.length >= perMinute) {\n sent.set(key, recent)\n return false\n }\n recent.push(now)\n sent.set(key, recent)\n return true\n }\n\n const list = async (from: string): Promise<PeerSessionSummary[]> => {\n const me = await sender(from)\n return (await allSessions())\n .filter((info) => visible(me, info))\n .sort((a, b) => (b.lastActivityAt ?? b.createdAt) - (a.lastActivityAt ?? a.createdAt))\n .map(peerSummary)\n }\n\n const peek = async (from: string, sessionId: string, options?: { recent?: number }): Promise<PeerPeek | undefined> => {\n const me = await sender(from)\n const info = await infoOf(sessionId)\n if (!info || !visible(me, info)) {\n return undefined\n }\n const { runner, lines } = recentOf(sessionId, options?.recent)\n return {\n ...peerSummary(info),\n live: runner !== undefined,\n checklist: info.checklist,\n pendingApprovals: runner ? runner.pendingApprovals.map((request) => request.title ?? request.toolName) : [],\n recent: lines,\n }\n }\n\n const send = async (from: string, sessionId: string, text: string, options?: PeerSendOptions): Promise<PeerSendResult> => {\n const me = await sender(from)\n if (sessionId === from) {\n return { delivered: false, reason: 'that is this session' }\n }\n if (text.length > maxChars) {\n return {\n delivered: false,\n reason: `message is ${text.length} characters; the limit is ${maxChars}. Write it to a file and send the path.`,\n }\n }\n const target = await infoOf(sessionId)\n if (!target || !visible(me, target)) {\n return { delivered: false, reason: `no such session: ${sessionId}` }\n }\n const hops = [...(options?.hops ?? inbound.get(from) ?? []), from]\n return deliver(target, text, { kind: 'peer', sessionId: from, name: me.title, engine: me.engine, hops }, from)\n }\n\n const deliver = async (target: SessionInfo, text: string, origin: MessageOrigin, rateKey: string): Promise<PeerSendResult> => {\n const sessionId = target.id\n if (target.status === 'closed' || target.status === 'failed') {\n return { delivered: false, reason: `session ${sessionId} is ${target.status}` }\n }\n const hops = origin.hops ?? []\n if (hops.length > maxHops) {\n return {\n delivered: false,\n reason: `${hops.length} messages have passed between sessions without a person speaking; stop and ask your user before continuing.`,\n }\n }\n if (!underRateLimit(rateKey, sessionId)) {\n return { delivered: false, reason: `rate limit: at most ${perMinute} messages a minute to one session. Batch what you have to say.` }\n }\n const runner = (await deps.refs.parking?.ensureLive(sessionId)) ?? registry().get(sessionId)\n if (!runner) {\n return { delivered: false, reason: `session ${sessionId} could not be woken` }\n }\n const before = runner.info().status\n try {\n runner.sendMessage(text, undefined, { origin })\n } catch (error) {\n return { delivered: false, reason: error instanceof Error ? error.message : String(error) }\n }\n inbound.set(sessionId, hops)\n return { delivered: true, sessionId, name: target.title, queued: before === 'running' || before === 'awaiting_approval' }\n }\n\n const exposedInfo = async (sessionId: string, exposed: Record<string, string> | undefined): Promise<SessionInfo | undefined> => {\n const info = await infoOf(sessionId)\n return info && info.status !== 'closed' && scopeMatches(exposed, info.scope) ? info : undefined\n }\n\n const relayEntries = async (exposed: Record<string, string> | undefined): Promise<RelaySessionEntry[]> => {\n const live = new Set(\n registry()\n .list()\n .map((info) => info.id),\n )\n return (await allSessions())\n .filter((info) => info.status !== 'closed' && scopeMatches(exposed, info.scope))\n .map((info) => relayEntry(info, live.has(info.id)))\n }\n\n const relayPeek = async (\n sessionId: string,\n recent: number | undefined,\n exposed: Record<string, string> | undefined,\n ): Promise<RelayPeek | undefined> => {\n const info = await exposedInfo(sessionId, exposed)\n if (!info) {\n return undefined\n }\n const { runner, lines } = recentOf(sessionId, recent)\n return {\n ...relayEntry(info, runner !== undefined),\n checklistItems: info.checklist,\n pendingApprovals: runner ? runner.pendingApprovals.map((request) => request.title ?? request.toolName) : [],\n recent: lines,\n }\n }\n\n const relaySend = async (\n origin: RelayOrigin,\n sessionId: string,\n text: string,\n exposed: Record<string, string> | undefined,\n ): Promise<RelaySendResult> => {\n if (text.length === 0 || text.length > maxChars) {\n return {\n delivered: false,\n reason: `message is ${text.length} characters; the limit is ${maxChars}. Write it to a file and send the path.`,\n }\n }\n const target = await exposedInfo(sessionId, exposed)\n if (!target) {\n return { delivered: false, reason: `no such session: ${sessionId}` }\n }\n const from = `${origin.gateway}:${origin.sessionId}`\n return deliver(\n target,\n text,\n { kind: 'peer', sessionId: from, hostId: origin.gateway, name: origin.name, engine: origin.engine, hops: origin.hops },\n from,\n )\n }\n\n // A session id is a handle a person may paste, so a full id and an unambiguous prefix resolve too.\n const mentions = async (from: string, text: string): Promise<PeerMention[]> => {\n const tokens = scanPeerMentions(text)\n if (tokens.length === 0) {\n return []\n }\n const rows = await list(from)\n const byKey = new Map<string, PeerSessionSummary[]>()\n const add = (key: string, row: PeerSessionSummary) => {\n const held = byKey.get(key)\n if (held) {\n held.push(row)\n } else {\n byKey.set(key, [row])\n }\n }\n for (const row of rows) {\n add(peerMentionKey(peerMentionSlug(row.title, row.id)), row)\n add(peerMentionKey(row.id), row)\n }\n const resolved: PeerMention[] = []\n const seen = new Set<string>()\n for (const token of tokens) {\n const key = peerMentionKey(token.body)\n const exact = byKey.get(key)\n // `list` is newest-first, so a shared title resolves to the session that moved last and the\n // envelope names the others rather than choosing silently.\n const matches = exact ?? (key.length >= 4 ? rows.filter((row) => row.id.startsWith(key)) : [])\n const target = matches[0]\n if (!target || (matches.length > 1 && !exact)) {\n continue\n }\n if (seen.has(target.id)) {\n continue\n }\n seen.add(target.id)\n const others = matches.slice(1, 4).map((row) => row.id)\n resolved.push({\n typed: token.body,\n id: target.id,\n name: target.title,\n engine: target.engine,\n status: target.status,\n cwd: target.cwd,\n ...(others.length ? { ambiguousWith: others } : {}),\n })\n if (resolved.length >= PEER_MENTION_MAX) {\n break\n }\n }\n return resolved\n }\n\n const watch = (runner: Runner): (() => void) =>\n runner.subscribe((event) => {\n if (event.type === 'user_message' && !event.origin && !event.synthetic && event.parentToolUseId == null && !event.replay) {\n inbound.delete(runner.id)\n }\n }, runner.info().lastSeq)\n\n return {\n list,\n peek,\n send,\n mentions,\n watch,\n relaySender: sender,\n relayChain: (from) => [...(inbound.get(from) ?? []), from],\n relayEntries,\n relayPeek,\n relaySend,\n }\n}\n","import { SessionRunner, type Runner, type SessionRunnerConfig } from '@workerdeck/core'\nimport type { SessionInfo } from '@workerdeck/protocol'\n\nexport type SessionRegistryOptions = {\n // A returned function is a detach: run when the runner leaves this registry, whether it was closed or handed to\n // another one. Typed `unknown` rather than `void | (() => void)` on purpose: TypeScript only forgives a\n // non-void return against a bare `void`, so the narrower union would break every embedder whose hook is a\n // one-expression arrow (`(r) => seen.push(r)`). The function check is at the retaining end instead.\n onRegister?: (runner: Runner) => unknown\n}\n\nexport class SessionRegistry {\n #sessions = new Map<string, Runner>()\n #options: SessionRegistryOptions\n #observers = new Set<(runner: Runner) => unknown>()\n // The watchers a registration attached, kept because the objects that attached them are exactly what a hot\n // reload discards: nobody else is in a position to take them off a runner that outlives its generation.\n #detachers = new Map<string, (() => void)[]>()\n\n constructor(options: SessionRegistryOptions = {}) {\n this.#options = options\n }\n\n // `onRegister` for a caller that only has the built server - an embedding host, or the CLI. Replays what is already\n // registered so a late observer cannot miss a session, which is the whole difference from reading the option.\n observe(listener: (runner: Runner) => unknown): () => void {\n this.#observers.add(listener)\n for (const runner of this.#sessions.values()) {\n this.#retain(runner.id, listener(runner))\n }\n return () => void this.#observers.delete(listener)\n }\n\n create(config: SessionRunnerConfig): Runner {\n return this.adopt(new SessionRunner(config))\n }\n\n prepare(config: SessionRunnerConfig): Runner {\n return this.register(new SessionRunner(config))\n }\n\n adopt(runner: Runner): Runner {\n this.register(runner)\n void runner.start()\n return runner\n }\n\n register(runner: Runner): Runner {\n const existing = this.#sessions.get(runner.id)\n this.#sessions.set(runner.id, runner)\n if (existing !== runner) {\n if (existing) {\n this.#detach(runner.id)\n }\n this.#retain(runner.id, this.#options.onRegister?.(runner))\n for (const listener of this.#observers) {\n this.#retain(runner.id, listener(runner))\n }\n }\n return runner\n }\n\n // For a watcher attached outside `onRegister` that must still come off when the runner leaves. Without it a\n // released runner keeps a listener from a discarded generation.\n retain(id: string, detach: () => void): void {\n this.#retain(id, detach)\n }\n\n get(id: string): Runner | undefined {\n return this.#sessions.get(id)\n }\n\n list(): SessionInfo[] {\n return [...this.#sessions.values()].map((r) => r.info())\n }\n\n remove(id: string): boolean {\n const runner = this.#sessions.get(id)\n if (!runner) {\n return false\n }\n runner.close('server')\n this.#detach(id)\n return this.#sessions.delete(id)\n }\n\n evict(id: string): boolean {\n this.#detach(id)\n return this.#sessions.delete(id)\n }\n\n closeAll(): void {\n for (const runner of this.#sessions.values()) {\n runner.close('server')\n }\n }\n\n #retain(id: string, detach: unknown): void {\n if (typeof detach !== 'function') {\n return\n }\n const run = detach as () => void\n const existing = this.#detachers.get(id)\n if (existing) {\n existing.push(run)\n return\n }\n this.#detachers.set(id, [run])\n }\n\n #detach(id: string): void {\n for (const detach of this.#detachers.get(id) ?? []) {\n detach()\n }\n this.#detachers.delete(id)\n }\n}\n","import {\n supportsPermissionMode,\n type CreateSessionRequest,\n type EngineCapabilities,\n type PermissionMode,\n type PricingTable,\n type ProfileEngine,\n type ProfileInfo,\n} from '@workerdeck/protocol'\nimport type { EngineAdapter, PeerDirectory, Runner, RunnerSnapshot, SessionRunnerConfig, ShellDirectory } from '@workerdeck/core'\nimport type { Refusal } from '../lib/http.ts'\nimport { refusePermissionMode } from '../lib/permissions.ts'\nimport { checkScope, sameScope } from '../lib/scope.ts'\nimport { cwdAllowed, engineOf, isProviderProfile } from '../lib/profile-env.ts'\nimport type { EngineRunnerContext, ShellAgentWriteOption } from '../options.ts'\nimport type { BridgeHub } from './bridge.ts'\nimport type { SessionParkManager } from './parking.ts'\nimport type { ProfileService } from './profiles.ts'\nimport type { SessionRegistry } from './registry.ts'\n\nexport type SessionFactoryDeps = {\n adapterFor: (engine: ProfileEngine | undefined) => EngineAdapter\n profiles: ProfileService\n hostBuildRunnerConfig: (req: CreateSessionRequest) => SessionRunnerConfig\n createEngineRunner?: (context: EngineRunnerContext) => Runner | Promise<Runner>\n allowedCwdRoots?: string[]\n disableBypassPermissions?: boolean\n approvalTimeoutMs?: number | null\n requireApiKey?: boolean\n peers?: PeerDirectory\n shells?: ShellDirectory\n shellAgentWrite?: ShellAgentWriteOption\n pricing?: PricingTable\n registry: SessionRegistry\n parking: SessionParkManager\n bridge: BridgeHub\n}\n\n// A dormant rebuild spreads the stored config back in, so the principal's flag can arrive on the request; a create\n// door passes it beside the request instead, because the host's hook and a job record see only the wire type.\nexport type CreateRequestWithPrincipal = CreateSessionRequest & { createdByOperator?: boolean }\n\nexport type SessionPrincipal = { operator: boolean }\n\nexport type SessionFactory = ReturnType<typeof createSessionFactory>\n\ntype EngineGrant = {\n refuses: (req: CreateSessionRequest, caps: EngineCapabilities) => boolean\n error: (engine: string, name: string) => string\n}\n\nconst ENGINE_GRANTS: readonly EngineGrant[] = [\n {\n refuses: (req, caps) => !caps.sessionMcpServers && !!req.mcpServers && Object.keys(req.mcpServers).length > 0,\n error: (engine, name) =>\n `profile '${name}' runs the ${engine} engine, whose MCP servers are declared outside the session request - a request cannot add its own`,\n },\n {\n refuses: (req, caps) => !caps.budgets && (req.maxTurns !== undefined || req.maxBudgetUsd !== undefined),\n error: (engine) => `the ${engine} engine does not honor maxTurns/maxBudgetUsd`,\n },\n {\n refuses: (req, caps) => !caps.settingSources && req.settingSources !== undefined,\n error: (engine) => `the ${engine} engine does not load settingSources`,\n },\n { refuses: (req, caps) => !caps.resume && req.resume !== undefined, error: (engine) => `the ${engine} engine cannot resume a session` },\n {\n refuses: (req, caps) => !!req.forkSession && caps.forkSession !== true,\n error: (engine) => `the ${engine} engine cannot fork a resumed session`,\n },\n {\n refuses: (req, caps) => req.reasoningEffort !== undefined && (!caps.reasoningEfforts || caps.reasoningEfforts.length === 0),\n error: (engine) => `the ${engine} engine does not take a reasoningEffort`,\n },\n]\n\n// Applied after the host's hook for the same reason as scope: the hook may rebuild the config from the request.\nfunction withPrincipal(config: SessionRunnerConfig, operator: boolean | undefined): SessionRunnerConfig {\n return operator === undefined ? config : { ...config, createdByOperator: operator }\n}\n\nexport function createSessionFactory(deps: SessionFactoryDeps) {\n const { adapterFor, profiles, registry, parking, bridge } = deps\n\n const subscriptionNoticeShown = new Set<string>()\n\n const applyBypassPolicy = (req: CreateSessionRequest): string | null => {\n if (!deps.disableBypassPermissions) {\n return null\n }\n const refused = refusePermissionMode(req.permissionMode, { operator: true, disableBypass: true })\n if (refused) {\n return refused\n }\n delete req.allowDangerouslySkipPermissions\n return null\n }\n\n const checkPermissionMode = (mode: PermissionMode | undefined, profile: ProfileInfo | undefined): string | null => {\n if (mode === undefined || supportsPermissionMode(profile?.engine, mode)) {\n return null\n }\n return (\n `permission mode '${mode}' is not supported by profile '${profile!.name}' ` +\n `(engine '${engineOf(profile)}') - supported: ` +\n adapterFor(profile?.engine).capabilities.permissionModes.join(', ')\n )\n }\n\n const checkEngineGrants = (req: CreateSessionRequest, profile: ProfileInfo | undefined): string | null => {\n const caps = adapterFor(profile?.engine).capabilities\n const grant = ENGINE_GRANTS.find((candidate) => candidate.refuses(req, caps))\n if (grant) {\n return grant.error(engineOf(profile), profile?.name ?? 'default')\n }\n if (!profile || !isProviderProfile(profile)) {\n return null\n }\n const granted = profile.session?.capabilities\n if (!req.capabilities || !granted) {\n return null\n }\n const ungranted = req.capabilities.filter((c) => !granted.includes(c))\n if (ungranted.length === 0) {\n return null\n }\n return (\n `profile '${profile.name}' does not grant: ${ungranted.join(', ')} ` +\n `(granted: ${granted.join(', ') || 'none'}) - a request may narrow capabilities, not widen them`\n )\n }\n\n const stripInertFields = (req: CreateSessionRequest, profile: ProfileInfo | undefined): void => {\n if (!adapterFor(profile?.engine).capabilities.interactiveApprovals) {\n delete req.questionBehavior\n }\n }\n\n const applyScope = (req: CreateSessionRequest, auth: { scope?: Record<string, string> }): Refusal | null => {\n const invalid = checkScope(req.scope)\n if (invalid) {\n return { status: 400, error: invalid }\n }\n if (!auth.scope) {\n return null\n }\n const merged: Record<string, string> = { ...req.scope }\n for (const [key, value] of Object.entries(auth.scope)) {\n const claimed = merged[key]\n if (claimed !== undefined && claimed !== value) {\n return { status: 403, error: `scope '${key}' does not match the caller's` }\n }\n merged[key] = value\n }\n const tooBig = checkScope(merged)\n if (tooBig) {\n return { status: 400, error: tooBig }\n }\n req.scope = merged\n return null\n }\n\n const checkCwd = (req: CreateSessionRequest, profile: ProfileInfo | undefined): Refusal | null => {\n if (req.cwd !== undefined && typeof req.cwd !== 'string') {\n return { status: 400, error: 'cwd must be a string' }\n }\n if (!req.cwd) {\n // Absent = true: an engine record that omits the field keeps the always-required behaviour.\n return adapterFor(profile?.engine).capabilities.hostCwd === false ? null : { status: 400, error: 'cwd is required' }\n }\n return cwdAllowed(req.cwd, deps.allowedCwdRoots) ? null : { status: 403, error: 'cwd is outside the allowed roots' }\n }\n\n const withScope = (config: SessionRunnerConfig, scope: Record<string, string> | undefined): SessionRunnerConfig =>\n scope === undefined ? config : { ...config, scope }\n\n // The gateway's default reaches every engine through the config, so a runner rebuilt from a parked\n // record gets the same deadline policy as the one it replaces.\n const withApprovalDefault = (config: SessionRunnerConfig): SessionRunnerConfig =>\n deps.approvalTimeoutMs === undefined ? config : { ...config, defaultApprovalTimeoutMs: deps.approvalTimeoutMs }\n\n const buildRunnerConfig = (req: CreateRequestWithPrincipal, principal?: SessionPrincipal): SessionRunnerConfig => {\n const profile = req.profile !== undefined ? profiles.get(req.profile) : undefined\n const effective = profile\n ? {\n ...req,\n model: req.model ?? profile.defaults?.model ?? profile.provider?.model,\n permissionMode: req.permissionMode ?? profile.defaults?.permissionMode,\n }\n : req\n const config = withApprovalDefault(\n withPrincipal(withScope(deps.hostBuildRunnerConfig(effective), req.scope), principal?.operator ?? req.createdByOperator),\n )\n const sessionEnv = profile ? adapterFor(profile.engine).sessionEnv : undefined\n if (!profile || !sessionEnv) {\n return config\n }\n const base = config.env ?? process.env\n const env = sessionEnv(profile, base)\n // A skipped pin returns `base` itself - leaving the config alone keeps an unset `env` unset, so the SDK spawns on process.env.\n return env === base ? config : { ...config, env }\n }\n\n const sessionEnvFor = (profile: ProfileInfo): Record<string, string | undefined> => {\n try {\n return buildRunnerConfig({ cwd: process.cwd(), profile: profile.name }).env ?? process.env\n } catch {\n return adapterFor(profile.engine).sessionEnv?.(profile, process.env) ?? process.env\n }\n }\n\n const buildRunner = async (built: SessionRunnerConfig, restore?: RunnerSnapshot, id?: string): Promise<Runner> => {\n const name = built.profile\n const profile = name !== undefined ? profiles.get(name) : undefined\n if (name !== undefined && !profile) {\n throw new Error(`unknown profile: ${name}`)\n }\n const capabilities = profile?.capabilities ?? adapterFor(profile?.engine).capabilities\n // Applied here rather than in buildRunnerConfig so a parked record, which stores its config, gets it too. The shell\n // tools are offered only where a shell of this session's could exist at all: enabled on the gateway, host cwd\n // engine. The write tools need, on top, the gateway's say-so and a session an operator created; both are read\n // afresh on every build, so a record never carries a stale grant.\n const config: SessionRunnerConfig = {\n ...built,\n ...(deps.peers ? { peers: deps.peers } : {}),\n ...(deps.pricing ? { pricing: deps.pricing } : {}),\n }\n delete config.shells\n delete config.shellAgentWrite\n if (deps.shells && capabilities.hostCwd === true) {\n config.shells = deps.shells\n const write = deps.shellAgentWrite ?? 'read-only'\n if (write !== 'read-only' && built.createdByOperator === true) {\n config.shellAgentWrite = write\n }\n }\n if (config.instructions !== undefined && capabilities.systemInstructions === false) {\n throw new Error(`the ${engineOf(profile)} engine cannot deliver system instructions`)\n }\n const runner =\n profile && isProviderProfile(profile)\n ? // Non-null: startup refuses a provider profile when no factory was wired.\n await deps.createEngineRunner!({ config, profile, bridge, restore, id })\n : // The in-repo adapters refuse `restore` themselves - neither binary can rebuild a parked session.\n await adapterFor(profile?.engine).createRunner({ config, profile, restore, id })\n const reported = runner.info().scope\n if (!sameScope(reported, config.scope)) {\n throw new Error(\n `runner for session ${runner.id} reports scope ${JSON.stringify(reported)}, ` +\n `expected ${JSON.stringify(config.scope)} - echo config.scope from info()`,\n )\n }\n return runner\n }\n\n const createRunner = async (config: SessionRunnerConfig): Promise<Runner> => {\n const runner = registry.register(await buildRunner(config))\n // Watchers first, then start: a session must not emit anything before the things that persist and account for it are listening.\n parking.remember(runner.id, config)\n parking.watch(runner)\n void runner.start()\n return runner\n }\n\n const resolveProfile = (\n name: unknown,\n allowedProfiles: string[] | undefined,\n ): { ok: true; profile?: ProfileInfo } | { ok: false; status: number; error: string } => {\n if (name !== undefined && typeof name !== 'string') {\n return { ok: false, status: 400, error: 'profile must be a string' }\n }\n const all = profiles.all()\n if (all.length === 0) {\n return name !== undefined ? { ok: false, status: 400, error: 'no profiles are configured on this server' } : { ok: true }\n }\n // One profile needs no naming, and neither does a set that still carries the auto-detected\n // `default` - otherwise choosing is the caller's, because a profile is a credential store.\n const effective = name ?? (all.length === 1 ? all[0]!.name : all.find((p) => p.name === 'default')?.name)\n if (effective === undefined) {\n const available = all.map((p) => p.name).join(', ')\n return { ok: false, status: 400, error: `profile is required (available: ${available})` }\n }\n const profile = profiles.get(effective)\n if (!profile) {\n return { ok: false, status: 400, error: `unknown profile: ${effective}` }\n }\n if (allowedProfiles && !allowedProfiles.includes(profile.name)) {\n return { ok: false, status: 403, error: `profile not allowed: ${profile.name}` }\n }\n return { ok: true, profile }\n }\n\n const watchAuthSource = (runner: Runner): (() => void) => {\n let seen = false\n return runner.subscribe((event) => {\n if (seen || event.type !== 'system_init') {\n return\n }\n seen = true\n if (event.apiKeySource !== 'oauth') {\n return\n }\n if (deps.requireApiKey) {\n runner.fail(\n 'This server requires API-key auth (requireApiKey), but the session initialized ' +\n \"with claude.ai subscription credentials (apiKeySource 'oauth'). Set \" +\n 'ANTHROPIC_API_KEY (or Bedrock/Vertex auth) in the server environment.',\n )\n } else {\n const profileName = runner.info().profile ?? ''\n if (subscriptionNoticeShown.has(profileName)) {\n return\n }\n subscriptionNoticeShown.add(profileName)\n const scope = profileName ? `Sessions under profile '${profileName}'` : 'Sessions'\n console.warn(\n `[workerdeck] ${scope} are using claude.ai subscription credentials ` +\n \"(apiKeySource 'oauth'), not an API key. That is only appropriate for personal, \" +\n 'single-user use of your own account. Unattended/scheduled or multi-user use ' +\n \"requires an API key under Anthropic's terms - set ANTHROPIC_API_KEY in the \" +\n 'server environment, or set requireApiKey: true to fail closed.',\n )\n }\n })\n }\n\n return {\n applyBypassPolicy,\n checkPermissionMode,\n checkEngineGrants,\n stripInertFields,\n applyScope,\n checkCwd,\n buildRunnerConfig,\n sessionEnvFor,\n buildRunner,\n createRunner,\n resolveProfile,\n watchAuthSource,\n }\n}\n","import { randomUUID } from 'node:crypto'\nimport { createServer, type IncomingMessage, type ServerResponse } from 'node:http'\nimport type { Duplex } from 'node:stream'\nimport { WebSocketServer } from 'ws'\nimport { getEngineAdapter, installPeerDirectory, installShellDirectory, peerDirectoryHandle, shellDirectoryHandle } from '@workerdeck/core'\nimport type { EngineAdapter, PeerDirectory, Runner, SessionRunnerConfig } from '@workerdeck/core'\nimport { JobQueue } from '@workerdeck/queue'\nimport { mergePricing, type CreateSessionRequest, type ProfileEngine } from '@workerdeck/protocol'\nimport type { ServerContext } from './context.ts'\nimport { createServerLifecycle } from './lifecycle.ts'\nimport { httpErrorStatus, json } from './lib/http.ts'\nimport { detectDefaultProfiles } from './lib/profile-env.ts'\nimport { reloadPlan } from './lib/reload-plan.ts'\nimport type { DiagnosticSink, WorkerServer, WorkerServerOptions } from './options.ts'\nimport { createQueueSocketHub } from './routes/queue-ws.ts'\nimport { upgradeSession } from './routes/session-upgrade.ts'\nimport { dispatchRoute, httpRoutes } from './routes/table.ts'\nimport { AttachmentStore } from './services/attachments.ts'\nimport { createAuthService } from './services/auth.ts'\nimport { AvailabilityTracker } from './services/availability.ts'\nimport { BridgeHub } from './services/bridge.ts'\nimport { createHostFileRoots } from './services/host-files.ts'\nimport { SessionNotifier } from './services/notifications.ts'\nimport { SessionParkManager } from './services/parking.ts'\nimport { ProducedFileStore } from './services/produced-files.ts'\nimport { ProfileService } from './services/profiles.ts'\nimport { ProfileUsageTracker } from './services/profile-usage.ts'\nimport { SpendLedger } from './services/spend-ledger.ts'\nimport { createRelayLink } from './services/peer-relay.ts'\nimport { createPeerService } from './services/peers.ts'\nimport { ProjectInfoService } from './services/project-info.ts'\nimport { SessionRegistry } from './services/registry.ts'\nimport { createSessionFactory, type SessionFactory } from './services/session-factory.ts'\nimport { createShellDirectory, createShellRegistry, type ShellRegistry } from './services/shells.ts'\nimport { isDormant, MemorySessionStore, type StoredSessionRecord } from './services/session-store.ts'\n\nexport type {\n Authenticator,\n EngineRunnerContext,\n QueueServerOptions,\n SdkSessionLister,\n WorkerServer,\n WorkerServerOptions,\n} from './options.ts'\n\n// How old the account-level rate-limit reading may be before a profiles read asks a live session for a newer one.\n// Generous: the windows move over hours, and the point is to bound staleness at minutes rather than at days.\nconst USAGE_STALE_MS = 5 * 60_000\n\n// Every client frame is a command or a bridged result; images travel over the attachments route, never the socket.\nconst WS_MAX_PAYLOAD_BYTES = 4 * 1024 * 1024\n\nexport function createWorkerServer(options: WorkerServerOptions = {}): WorkerServer {\n if (!options.authenticate && !options.allowUnauthenticated) {\n throw new Error('createWorkerServer: provide `authenticate` or explicitly set `allowUnauthenticated: true`')\n }\n const basePath = options.basePath ?? '/v1'\n const fallback = options.fallback\n const corsOrigins = options.cors?.origins.length ? new Set(options.cors.origins) : undefined\n const maxBodyBytes = options.maxBodyBytes ?? 1024 * 1024\n const diagnose: DiagnosticSink = options.onDiagnostic ?? (() => {})\n const adapterFor = (engine: ProfileEngine | undefined): EngineAdapter => options.engines?.[engine ?? 'claude'] ?? getEngineAdapter(engine)\n\n const pricing = mergePricing(options.pricing?.overrides)\n if (pricing.dropped.length > 0) {\n console.warn(\n `[workerdeck] Ignoring pricing.overrides for ${pricing.dropped.join(', ')}: ` +\n 'each entry needs input, output, cacheWrite5m, cacheWrite1h and cacheRead in USD per million tokens',\n )\n }\n\n const profileDefaultModels = new Map<string, string>()\n const profileUsage = new ProfileUsageTracker()\n const spendLedger = new SpendLedger({\n pricing: pricing.pricing,\n store: options.spend?.store,\n monthlySubscriptionUsd: (name) => options.spend?.monthlySubscriptionUsd?.[name] ?? options.spend?.monthlySubscriptionUsd?.['*'],\n onError: (error) => options.spend?.onError?.(error),\n })\n void spendLedger.load()\n // With a store in play, detection seeds it on first launch instead of declaring anything: a\n // declared profile cannot be edited over the API, and an auto-detected one is exactly the profile\n // an operator most wants to rename or retarget.\n const detected = options.profiles ? [] : detectDefaultProfiles()\n const profiles = new ProfileService({\n declared: options.profiles ?? (options.profileStore ? [] : detected),\n seed: detected,\n store: options.profileStore,\n allowedConfigDirRoots: options.allowedConfigDirRoots,\n disableBypassPermissions: options.disableBypassPermissions,\n hasEngineRunnerFactory: options.createEngineRunner !== undefined,\n adapterFor,\n decorate: {\n defaultModel: (name) => profileDefaultModels.get(name),\n availability: (name) => availability.get(name),\n usage: (name) => {\n refreshStaleUsage(registry, profileUsage, name, diagnose)\n return profileUsage.usage(name)\n },\n spend: (name) => spendLedger.spend(name),\n },\n })\n for (const p of options.profiles ?? []) {\n const invalid = profiles.validate(p)\n if (invalid) {\n throw new Error(`createWorkerServer: ${invalid}`)\n }\n }\n\n const generation = randomUUID()\n const shells = options.shell?.enabled === true ? shellRegistryFor(options.shell, generation) : null\n const projects = new ProjectInfoService({ decorate: (info) => (shells ? shells.decorate(info) : info) })\n\n const notifier = new SessionNotifier({\n ...options.notifications,\n decorateInfo: (info) => projects.withProject(info),\n onError: options.notifications?.onError ?? ((error, context) => diagnose(error, `notification-${context.op}`)),\n })\n const producedFiles = new ProducedFileStore()\n // Built first because everything else holds it. The watchers it attaches read the later-built services only when\n // a runner registers, which no code path does before this function returns.\n const registry = new SessionRegistry({\n // Every watcher here hands back its detach, and the registry runs them when the runner leaves. A hot reload is\n // the case that needs it: the runner outlives this server, and these closures would otherwise keep delivering\n // webhooks and pushes from a generation that is over, one extra copy per reload.\n onRegister: (runner) => {\n const detachers = [\n notifier.watch(runner),\n producedFiles.watch(runner),\n profileUsage.watch(runner),\n spendLedger.watch(runner),\n shells?.watch(runner),\n peers?.watch(runner),\n factory.watchAuthSource(runner),\n ]\n const profile = runner.info().profile\n if (profile) {\n detachers.push(\n runner.subscribe((event) => {\n if (event.type !== 'capabilities' || !event.defaultModel) {\n return\n }\n profileDefaultModels.set(profile, event.defaultModel)\n }),\n )\n }\n return () => {\n for (const detach of detachers) {\n detach?.()\n }\n }\n },\n })\n const attachmentStore = new AttachmentStore(options.attachments)\n const bridge = new BridgeHub({\n ...options.bridge,\n onResult: (sessionId, executionId, result) => {\n registry.get(sessionId)?.settleExecution?.(executionId, result)\n options.bridge?.onResult?.(sessionId, executionId, result)\n },\n })\n const parking = new SessionParkManager({\n registry,\n store: options.parking?.store ?? new MemorySessionStore(),\n parkDelayMs: options.parking?.parkDelayMs,\n expiredGraceMs: options.parking?.expiredGraceMs,\n persistLive: options.parking?.persistLive,\n onError: options.parking?.onError,\n rebuild: (record) => rebuildRunner(factory, record),\n attachedCount: (sessionId) => bridge.attachedCount(sessionId),\n onParking: (sessionId) => queue?.canParkSession(sessionId) ?? true,\n onParked: (sessionId, executionId) => void queue?.onSessionParking(sessionId, executionId),\n onResumed: (sessionId, runner) => queue?.onSessionResumed(sessionId, runner),\n })\n\n const peers =\n options.peers?.enabled === false ? undefined : createPeerService({ refs: { registry, parking }, projects, options: options.peers })\n const shellDirectory = shells ? createShellDirectory(shells, { runnerFor: (id) => registry.get(id) }) : undefined\n // Each runner resolves its own server's directory first and the process-wide slot only once that server has\n // closed, which is the hot-reload handover: a carried runner then reaches whichever generation installed last.\n const relay =\n peers && options.relay\n ? createRelayLink(options.relay, peers, options.relay.log ?? ((message) => diagnose(new Error(message), 'relay')))\n : undefined\n let ownPeers: PeerDirectory | undefined = relay?.directory ?? peers\n let ownShells = shellDirectory\n if (ownPeers) {\n installPeerDirectory(ownPeers)\n }\n installShellDirectory(shellDirectory)\n const factory = createSessionFactory({\n adapterFor,\n profiles,\n hostBuildRunnerConfig: options.buildRunnerConfig ?? ((req: CreateSessionRequest): SessionRunnerConfig => req),\n createEngineRunner: options.createEngineRunner,\n allowedCwdRoots: options.allowedCwdRoots,\n disableBypassPermissions: options.disableBypassPermissions,\n approvalTimeoutMs: options.approvalTimeoutMs,\n requireApiKey: options.requireApiKey,\n peers: peers ? peerDirectoryHandle(() => ownPeers) : undefined,\n shells: shellDirectory ? shellDirectoryHandle(() => ownShells) : undefined,\n shellAgentWrite: options.shell?.agentWrite,\n pricing: pricing.pricing,\n registry,\n parking,\n bridge,\n })\n\n const availability = new AvailabilityTracker({\n checkCredentials: options.checkCredentials,\n requireAvailableProfile: options.requireAvailableProfile,\n adapterFor,\n sessionEnvFor: factory.sessionEnvFor,\n onError: (error) => diagnose(error, 'availability-probe'),\n })\n\n const auth = createAuthService({ options, registry })\n\n const wss = new WebSocketServer({ noServer: true, maxPayload: WS_MAX_PAYLOAD_BYTES })\n const queueSockets = createQueueSocketHub({ wss, auth, queue: () => queue, diagnose })\n\n const queue = options.queue\n ? new JobQueue({\n ...options.queue,\n onEvent: (event) => {\n try {\n options.queue?.onEvent?.(event)\n } finally {\n queueSockets.broadcast(event)\n }\n },\n createRunner: (config) => factory.createRunner(config),\n buildRunnerConfig: factory.buildRunnerConfig,\n discardSession: (sessionId) => parking.discard(sessionId),\n })\n : undefined\n\n const hostFileRootPaths = options.hostFiles?.roots ?? options.allowedCwdRoots\n const hostFiles = hostFileRootPaths?.length ? createHostFileRoots(hostFileRootPaths) : null\n\n const ctx: ServerContext = {\n options,\n basePath,\n maxBodyBytes,\n adapterFor,\n listSdkSessions: options.listSdkSessions,\n profiles,\n availability,\n auth,\n factory,\n registry,\n parking,\n peers,\n bridge,\n projects,\n queue,\n attachmentStore,\n producedFiles,\n hostFiles,\n hostFilesWritable: options.hostFiles?.write === true,\n maxHostFileBytes: options.hostFiles?.maxFileBytes ?? 1024 * 1024,\n maxHostDirEntries: options.hostFiles?.maxEntries ?? 5000,\n shells,\n generation,\n pricingOverrides: Object.keys(pricing.overrides).length > 0 ? pricing.overrides : undefined,\n }\n const routes = httpRoutes(ctx)\n\n const handleRequest = async (req: IncomingMessage, res: ServerResponse): Promise<void> => {\n if (answerCors(req, res, corsOrigins)) {\n return\n }\n const pathname = new URL(req.url ?? '/', 'http://internal').pathname\n if (fallback && pathname !== basePath && !pathname.startsWith(basePath + '/')) {\n await fallback(req, res)\n return\n }\n await dispatchRoute(ctx, routes, req, res, lifecycle.draining())\n }\n\n const server = createServer((req, res) => {\n handleRequest(req, res).catch((error: unknown) => {\n const message = error instanceof Error ? error.message : 'internal error'\n if (!res.headersSent) {\n json(res, httpErrorStatus(error), { error: message })\n } else {\n res.end()\n }\n })\n })\n\n server.on('upgrade', (req: IncomingMessage, socket: Duplex, head: Buffer) => {\n void (async () => {\n const pathname = new URL(req.url ?? '/', 'http://internal').pathname\n if (pathname === basePath + '/queue/ws') {\n await queueSockets.upgrade(req, socket, head)\n return\n }\n await upgradeSession(ctx, wss, req, socket, head)\n })().catch(() => socket.destroy())\n })\n\n const lifecycle = createServerLifecycle({\n server,\n wss,\n registry,\n parking,\n shells,\n queue,\n closeQueueSockets: queueSockets.clear,\n diagnose,\n releaseDirectories: () => {\n relay?.close()\n ownPeers = undefined\n ownShells = undefined\n },\n })\n\n return {\n server,\n registry,\n queue,\n bridge,\n parking,\n shells,\n listen: async (port, host) => {\n await profiles.refreshStored()\n await profiles.seedStore()\n await parking.hydrate()\n await shells?.hydrate()\n return new Promise((resolve, reject) => {\n server.once('error', reject)\n server.listen(port, host, () => {\n availability.preflight(profiles.all())\n const address = server.address()\n resolve({ port: typeof address === 'object' && address ? address.port : port })\n })\n })\n },\n releaseSession: (id) => {\n const runner = registry.get(id)\n if (!runner) {\n return undefined\n }\n const plan = reloadPlan(runner)\n if (plan !== 'carry') {\n throw new Error(`session ${id} cannot be carried by identity (${plan})`)\n }\n const config = parking.release(id)\n registry.evict(id)\n return { runner, config }\n },\n adoptSession: ({ runner, config }) => {\n // Re-checked here, not only at release: a runner held across a failed generation may have ended in the\n // meantime, and adopting a dead one would list a session nothing can answer.\n if (reloadPlan(runner) !== 'carry') {\n return false\n }\n parking.adopt(runner, config)\n return true\n },\n releaseRelay: () => relay?.release(),\n drain: lifecycle.drain,\n close: lifecycle.close,\n }\n}\n\n// The backstop behind the attach-time refresh, for the surface that reads the account number without opening a\n// session at all. Fire and forget: this request still answers with what is known, and the newer reading arrives\n// as a `rate_limit` event moments later. One session per profile is enough - the reading is account-level - and\n// the runner's own throttle is what keeps a page of profiles from becoming a page of control requests.\nfunction refreshStaleUsage(registry: SessionRegistry, profileUsage: ProfileUsageTracker, name: string, diagnose: DiagnosticSink): void {\n const held = profileUsage.usage(name)\n const newest = Math.max(0, ...Object.values(held ?? {}).map((window) => window.updatedAt ?? 0))\n if (Date.now() - newest < USAGE_STALE_MS) {\n return\n }\n for (const info of registry.list()) {\n if (info.profile !== name) {\n continue\n }\n const runner = registry.get(info.id)\n if (runner?.refreshUsage) {\n void runner.refreshUsage().catch((error: unknown) => diagnose(error, 'usage-refresh'))\n return\n }\n }\n}\n\nfunction answerCors(req: IncomingMessage, res: ServerResponse, corsOrigins: Set<string> | undefined): boolean {\n const origin = req.headers.origin\n const originAllowed = typeof origin === 'string' && corsOrigins !== undefined && corsOrigins.has(origin)\n if (originAllowed) {\n res.setHeader('access-control-allow-origin', origin)\n res.setHeader('vary', 'origin')\n }\n if (req.method !== 'OPTIONS' || req.headers['access-control-request-method'] === undefined) {\n return false\n }\n if (!originAllowed) {\n res.writeHead(403)\n res.end()\n return true\n }\n res.setHeader('access-control-allow-methods', 'GET, HEAD, POST, PATCH, PUT, DELETE')\n res.setHeader('access-control-allow-headers', 'authorization, content-type, x-workerdeck-key')\n res.setHeader('access-control-max-age', '600')\n // Chrome's Private Network Access: a public page reaching a private address (a tailnet, a LAN) preflights for this explicitly.\n if (req.headers['access-control-request-private-network'] === 'true') {\n res.setHeader('access-control-allow-private-network', 'true')\n }\n res.writeHead(204)\n res.end()\n return true\n}\n\nfunction shellRegistryFor(shell: NonNullable<WorkerServerOptions['shell']>, generation: string): ShellRegistry {\n return createShellRegistry({\n generation,\n artifactDir: shell.artifactDir ?? null,\n timeoutMs: shell.timeoutMs,\n artifactMaxBytes: shell.artifactMaxBytes,\n artifactTtlMs: shell.artifactTtlMs,\n maxRunningPerSession: shell.maxRunningPerSession,\n onError: (error, context) =>\n console.warn(`[workerdeck] shell ${context.op} error (${context.shellId ?? context.sessionId ?? '-'}): ${String(error)}`),\n })\n}\n\n// A dormant record holds only the config and the SDK id to resume from, so it goes back through the host's hook; a\n// parked one carries its own snapshot.\nfunction rebuildRunner(factory: SessionFactory, record: StoredSessionRecord): Promise<Runner> {\n if (!isDormant(record)) {\n return factory.buildRunner(record.config, record.snapshot)\n }\n return factory.buildRunner(\n {\n ...factory.buildRunnerConfig({\n ...record.config,\n prompt: undefined,\n resume: record.sdkSessionId,\n }),\n // Applied after the host's hook, which is free to rebuild the config from the\n // request and would drop a field it has never heard of.\n epoch: (record.info.epoch ?? 0) + 1,\n fallbackTitle: record.info.title,\n },\n undefined,\n record.id,\n )\n}\n","import type { ProfileInfo, ProviderConfig, SessionCapability } from '@workerdeck/protocol'\n\nexport function sandboxedProviderProfile(\n name: string,\n provider: ProviderConfig,\n options: {\n description?: string\n instructions?: string\n defaults?: ProfileInfo['defaults']\n capabilities?: SessionCapability[]\n mcpServers?: string[]\n } = {},\n): ProfileInfo {\n return {\n name,\n engine: 'provider',\n provider,\n description: options.description ?? 'Sandboxed: no host filesystem, no shell, no egress',\n defaults: options.defaults,\n session: {\n capabilities: options.capabilities ?? [],\n mcpServers: options.mcpServers ?? [],\n instructions: options.instructions,\n },\n }\n}\n","import {\n createEngineSession,\n shellToolNeedsCard,\n type EngineSessionOptions,\n type HostToolDefinition,\n type LanguageModel,\n type McpConnection,\n type SessionInstructions,\n type Runner,\n type ToolExecutionCall,\n type ToolExecutor,\n type ToolSet,\n} from '@workerdeck/core'\nimport type { EngineRunnerContext } from '../options.ts'\n\nexport type ProviderRunnerOptions = {\n model: LanguageModel | ((modelId: string | undefined) => LanguageModel)\n executor: ToolExecutor | 'browser' | ((call: ToolExecutionCall) => ToolExecutor | 'browser')\n capabilities?: EngineSessionOptions['capabilities']\n tools?: Record<string, HostToolDefinition>\n mcp?: McpConnection\n mcpTools?: ToolSet\n instructions?: SessionInstructions\n executionLimits?: { timeoutMs?: number; memoryLimitBytes?: number }\n seedVfs?: Record<string, string>\n shouldApprove?: (call: { toolName: string; input: unknown }) => boolean\n approvalTimeoutMs?: number | null\n // Runs on park as well as close: parking releases the same per-session resources.\n onClose?: () => void | Promise<void>\n}\n\nexport async function createProviderRunner(ctx: EngineRunnerContext, options: ProviderRunnerOptions): Promise<Runner> {\n const { config, profile, bridge, restore, id } = ctx\n const languageModel = typeof options.model === 'function' ? options.model(config.model) : options.model\n const executor = providerExecutor(options.executor, bridge)\n // Under `gated` the agent's shell write tools must raise a card even when the embedder wired no reviewer of its\n // own; `needsApproval` fires only through `shouldApprove`, so the default is supplied here and defers to the\n // embedder's for every other tool.\n const shouldApprove =\n config.shellAgentWrite === undefined\n ? options.shouldApprove\n : (call: { toolName: string; input: unknown }) =>\n shellToolNeedsCard(call.toolName, config.shellAgentWrite) || options.shouldApprove?.(call) === true\n return createEngineSession({\n config: {\n ...config,\n languageModel,\n ...(typeof options.model === 'function' && { resolveModel: options.model }),\n restore,\n onClose: options.onClose,\n },\n id,\n profile,\n resolveModel: () => languageModel,\n selectExecutor: () => executor,\n capabilities: options.capabilities,\n tools: options.tools,\n mcp: options.mcp,\n mcpTools: options.mcpTools,\n instructions: options.instructions,\n executionLimits: options.executionLimits,\n shouldApprove,\n approvalTimeoutMs: config.defaultApprovalTimeoutMs === undefined ? options.approvalTimeoutMs : config.defaultApprovalTimeoutMs,\n seedVfs: options.seedVfs,\n })\n}\n\n// One executor, routed once per call, whose profile names the backend the call went to.\nfunction providerExecutor(executor: ProviderRunnerOptions['executor'], bridge: EngineRunnerContext['bridge']): ToolExecutor {\n const bridged: ToolExecutor = { dispatch: (call) => bridge.executorFor(call.sessionId).dispatch(call) }\n if (typeof executor !== 'function') {\n return executor === 'browser' ? { ...bridged, describe: () => ({ backend: 'browser' }) } : executor\n }\n const route = (call: ToolExecutionCall): { target: ToolExecutor; backend: 'browser' | 'server' } => {\n const raw = executor(call)\n return raw === 'browser' ? { target: bridged, backend: 'browser' } : { target: raw, backend: 'server' }\n }\n return {\n describe: (call) => {\n const { target, backend } = route(call)\n return { ...target.describe?.(call), backend }\n },\n dispatch: (call) => route(call).target.dispatch(call),\n }\n}\n","import { join } from 'node:path'\nimport type { ProfileInfo } from '@workerdeck/protocol'\nimport { readJsonOrSync, writeJsonAtomicSync } from '../lib/atomic-file.ts'\n\nexport type ProfileStore = {\n list(): ProfileInfo[] | Promise<ProfileInfo[]>\n save(profile: ProfileInfo): void | Promise<void>\n delete(name: string): void | Promise<void>\n}\n\nexport function createMemoryProfileStore(seed: ProfileInfo[] = []): ProfileStore {\n const profiles = new Map(seed.map((p) => [p.name, p]))\n return {\n list: () => [...profiles.values()],\n save: (profile) => void profiles.set(profile.name, profile),\n delete: (name) => void profiles.delete(name),\n }\n}\n\nexport function createFileProfileStore(path = join(process.cwd(), '.workerdeck', 'profiles.json')): ProfileStore {\n const read = (): Map<string, ProfileInfo> => {\n const parsed = readJsonOrSync(path, [])\n if (!Array.isArray(parsed)) {\n return new Map()\n }\n const profiles = parsed as ProfileInfo[]\n return new Map(profiles.filter((p) => p && typeof p.name === 'string').map((p) => [p.name, p]))\n }\n const write = (profiles: Map<string, ProfileInfo>): void => writeJsonAtomicSync(path, [...profiles.values()], { indent: 2 })\n return {\n list: () => [...read().values()],\n save: (profile) => {\n const profiles = read()\n profiles.set(profile.name, profile)\n write(profiles)\n },\n delete: (name) => {\n const profiles = read()\n if (profiles.delete(name)) {\n write(profiles)\n }\n },\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["resolvePath","SHELL_REFUSAL","isRecord","agents","profiles"],"sources":["../src/lifecycle.ts","../src/lib/http.ts","../src/lib/profile-env.ts","../src/lib/reload-plan.ts","../src/routes/queue-ws.ts","../src/lib/parse-route.ts","../src/routes/session-lookup.ts","../src/lib/permissions.ts","../src/lib/scope.ts","../src/services/peers.ts","../src/routes/sleep.ts","../src/services/shell-directory.ts","../src/services/process-tree.ts","../src/lib/atomic-file.ts","../src/services/shell-artifact.ts","../src/services/shell-screen.ts","../src/services/shell-entry.ts","../src/services/shell-env.ts","../src/services/shell-index.ts","../src/services/shells.ts","../src/routes/ws.ts","../src/routes/session-upgrade.ts","../src/lib/machine-id.ts","../src/services/agents.ts","../src/lib/host-only-keys.ts","../src/routes/create-vet.ts","../src/routes/agents.ts","../src/routes/executions.ts","../src/services/host-files.ts","../src/services/host-file-search.ts","../src/routes/fs.ts","../src/routes/jobs.ts","../src/routes/profiles.ts","../src/routes/sdk-sessions.ts","../src/services/session-store.ts","../src/routes/attachments.ts","../src/routes/mcp.ts","../src/routes/produced-files.ts","../src/services/project-info.ts","../src/routes/project-icon.ts","../src/routes/shells.ts","../src/routes/tool-results.ts","../src/routes/sessions.ts","../src/routes/table.ts","../src/services/agent-store.ts","../src/services/attachments.ts","../src/services/auth.ts","../src/services/availability.ts","../src/services/engine-sleep.ts","../src/services/context-resets.ts","../src/services/bridge.ts","../src/services/notifications.ts","../src/services/parking.ts","../src/services/produced-files.ts","../src/services/profiles.ts","../src/services/profile-usage.ts","../src/services/spend-ledger.ts","../src/services/peer-relay.ts","../src/services/registry.ts","../src/services/session-factory.ts","../src/server.ts","../src/lib/sandboxed-profile.ts","../src/lib/provider-runner.ts","../src/services/profile-store.ts"],"sourcesContent":["import type { Server } from 'node:http'\nimport type { WebSocketServer } from 'ws'\nimport type { JobQueue } from '@workerdeck/queue'\nimport { sessionState } from '@workerdeck/protocol'\nimport type { DiagnosticSink, DrainOptions, DrainReport } from './options.ts'\nimport type { EngineSleepTimers } from './services/engine-sleep.ts'\nimport type { SessionParkManager } from './services/parking.ts'\nimport type { SessionRegistry } from './services/registry.ts'\nimport type { ShellRegistry } from './services/shells.ts'\n\n// How long a client gets to acknowledge the shutdown close frame before its socket is torn down.\nconst SOCKET_CLOSE_GRACE_MS = 250\n\n// The outer bound on close(): it resolves by then whether or not the runtime ever reports the drains complete.\nconst CLOSE_DEADLINE_MS = 1_000\n\nexport type ServerLifecycleDeps = {\n server: Server\n wss: WebSocketServer\n registry: SessionRegistry\n parking: SessionParkManager\n shells: ShellRegistry | null\n queue: JobQueue | undefined\n engineSleep: EngineSleepTimers\n closeQueueSockets: () => void\n releaseDirectories: () => void\n diagnose: DiagnosticSink\n}\n\nexport type ServerLifecycle = {\n draining: () => boolean\n drain: (options?: DrainOptions) => Promise<DrainReport>\n close: () => Promise<void>\n}\n\nexport function createServerLifecycle(deps: ServerLifecycleDeps): ServerLifecycle {\n let closing: Promise<void> | undefined\n let draining = false\n return {\n draining: () => draining,\n drain: async (options = {}) => {\n draining = true\n deps.queue?.pause()\n return drainSessions(deps.registry, deps.shells, options)\n },\n close: () => {\n closing ??= closeServer(deps)\n return closing\n },\n }\n}\n\n// Split live sessions into \"will finish by itself\" and \"needs a person\".\n//\n// `sessionState` is the vocabulary the dashboard, the session list and `workerdeck guard` already sort by, and it\n// draws exactly the line a drain needs: `working` covers starting/running and running subagents, while `attention`\n// covers a pending approval. Re-spelling that set here is how the two definitions would drift apart.\nfunction surveyDrain(registry: SessionRegistry, shells: ShellRegistry | null): DrainReport {\n const working: string[] = []\n const awaitingHuman: string[] = []\n for (const info of registry.list()) {\n const state = sessionState(info)\n if (state === 'working') {\n working.push(info.id)\n } else if (state === 'attention') {\n awaitingHuman.push(info.id)\n }\n }\n const running = (shells?.running() ?? []).map(({ sessionId, id, label }) => ({ sessionId, id, label }))\n return { working, awaitingHuman, timedOut: false, shells: running }\n}\n\nfunction sameDrain(a: DrainReport, b: DrainReport): boolean {\n return a.working.join() === b.working.join() && a.awaitingHuman.join() === b.awaitingHuman.join()\n}\n\nasync function drainSessions(registry: SessionRegistry, shells: ShellRegistry | null, options: DrainOptions): Promise<DrainReport> {\n const { timeoutMs = 30_000, pollMs = 250, onProgress } = options\n const deadline = Date.now() + timeoutMs\n let report = surveyDrain(registry, shells)\n onProgress?.(report)\n while (report.working.length > 0 && Date.now() < deadline) {\n await new Promise((resolve) => setTimeout(resolve, pollMs))\n const next = surveyDrain(registry, shells)\n // Only speak when something actually changed: a shutdown that reports on its own progress should be\n // readable, not a per-tick redraw of the same two lines.\n if (!sameDrain(next, report)) {\n onProgress?.(next)\n }\n report = next\n }\n report = { ...surveyDrain(registry, shells), timedOut: false }\n report.timedOut = report.working.length > 0\n onProgress?.(report)\n return report\n}\n\nfunction closeServer(deps: ServerLifecycleDeps): Promise<void> {\n const { server, wss, registry, parking, shells, queue } = deps\n return new Promise((resolve) => {\n deps.releaseDirectories()\n queue?.close()\n // Before the runners close: their `session_closed` would settle every shell as `killed`, and a graceful stop is\n // `server_stopped`. The index lands through `flushed` below, ahead of resolving.\n shells?.killAll('server_stopped')\n const flushed = shells?.flush().catch((error: unknown) => deps.diagnose(error, 'shell-flush')) ?? Promise.resolve()\n // Ordering is load-bearing: parking's `#closed` guard must be set before the registry closes runners with\n // reason 'server', or shutdown discards every dormant record. See docs/GOTCHAS.md.\n parking.close()\n deps.engineSleep.close()\n registry.closeAll()\n // `wss` is `noServer`, so `wss.close()` only waits for `clients` to empty, and `server.closeAllConnections()`\n // never reaches an upgraded socket: close every client ourselves, then terminate what has not acknowledged.\n for (const ws of wss.clients) {\n ws.close(1001, 'server shutting down')\n }\n deps.closeQueueSockets()\n const force = setTimeout(() => {\n for (const ws of wss.clients) {\n ws.terminate()\n }\n }, SOCKET_CLOSE_GRACE_MS)\n force.unref()\n const finish = (): void => void flushed.then(() => resolve())\n const deadline = setTimeout(finish, CLOSE_DEADLINE_MS)\n deadline.unref()\n const drained = Promise.all([\n new Promise<void>((done) => wss.close(() => done())),\n new Promise<void>((done) => server.close(() => done())),\n ])\n server.closeAllConnections()\n void drained.then(() => {\n clearTimeout(force)\n clearTimeout(deadline)\n finish()\n })\n })\n}\n","import { createHash } from 'node:crypto'\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { Duplex } from 'node:stream'\n\nconst CONTENT_TYPES: Record<string, string> = {\n json: 'application/json; charset=utf-8',\n md: 'text/markdown; charset=utf-8',\n html: 'text/html; charset=utf-8',\n csv: 'text/csv; charset=utf-8',\n xml: 'application/xml; charset=utf-8',\n svg: 'image/svg+xml; charset=utf-8',\n}\n\n// Headers for serving user-controlled bytes (attachments, produced files, sandbox VFS reads):\n// force download and forbid MIME sniffing so a crafted HTML/SVG payload can never execute in the\n// gateway's origin. Every byte-serving route must use this.\nexport function untrustedDownloadHeaders(filename: string, contentType: string, byteLength: number): Record<string, string | number> {\n return {\n 'content-type': contentType,\n 'content-length': byteLength,\n 'content-disposition': `attachment; filename*=UTF-8''${encodeURIComponent(filename)}`,\n 'x-content-type-options': 'nosniff',\n }\n}\n\nexport function json(res: ServerResponse, status: number, body: unknown): void {\n const payload = JSON.stringify(body)\n res.writeHead(status, {\n 'content-type': 'application/json',\n 'content-length': Buffer.byteLength(payload),\n })\n res.end(payload)\n}\n\nexport type Refusal = { status: number; error: string }\n\nexport class HttpError extends Error {\n readonly status: number\n\n constructor(status: number, message: string) {\n super(message)\n this.status = status\n }\n}\n\nexport function fail(status: number, message: string): never {\n throw new HttpError(status, message)\n}\n\nexport function requireMethod(req: IncomingMessage, ...methods: string[]): void {\n if (!methods.includes(req.method ?? '')) {\n fail(405, 'method not allowed')\n }\n}\n\nexport function sendUntrusted(res: ServerResponse, filename: string, contentType: string, bytes: Buffer | string): void {\n res.writeHead(200, untrustedDownloadHeaders(filename, contentType, Buffer.byteLength(bytes)))\n res.end(bytes)\n}\n\nexport function httpErrorStatus(error: unknown): number {\n if (error instanceof HttpError) {\n return error.status\n }\n return error instanceof SyntaxError ? 400 : 500\n}\n\n// A cross-site page can send `text/plain` (or a typeless Blob) without a preflight, so a JSON route that parsed any\n// body would be reachable by a drive-by form post. Only an empty body may omit the header.\nexport async function readJsonBody(req: IncomingMessage, maxBytes: number): Promise<Record<string, unknown>> {\n const mime = mediaTypeOf(req.headers['content-type'])\n if (mime !== undefined && !isJsonMediaType(mime)) {\n throw new HttpError(415, 'expected content-type application/json')\n }\n const body = await readRawBody(req, maxBytes)\n if (body.length === 0) {\n return {}\n }\n if (mime === undefined) {\n throw new HttpError(415, 'expected content-type application/json')\n }\n return JSON.parse(body.toString('utf8')) as Record<string, unknown>\n}\n\nfunction mediaTypeOf(header: string | undefined): string | undefined {\n const mime = header?.split(';')[0].trim().toLowerCase()\n return mime === undefined || mime === '' ? undefined : mime\n}\n\nfunction isJsonMediaType(mime: string): boolean {\n return mime === 'application/json' || (mime.startsWith('application/') && mime.endsWith('+json'))\n}\n\nexport async function readRawBody(req: IncomingMessage, maxBytes: number): Promise<Buffer> {\n const chunks: Buffer[] = []\n let size = 0\n for await (const chunk of req) {\n size += (chunk as Buffer).length\n if (size > maxBytes) {\n throw new HttpError(413, 'request body too large')\n }\n chunks.push(chunk as Buffer)\n }\n return Buffer.concat(chunks)\n}\n\nexport function hashBytes(bytes: Buffer): string {\n return createHash('sha256').update(bytes).digest('hex')\n}\n\n// Decoding never fails in Node - invalid bytes become U+FFFD - so a round trip is the only honest test.\nexport function asUtf8(bytes: Buffer): string | null {\n const text = bytes.toString('utf8')\n return Buffer.from(text, 'utf8').equals(bytes) ? text : null\n}\n\nexport function contentTypeFor(filename: string): string {\n const ext = filename.includes('.') ? filename.split('.').pop()!.toLowerCase() : ''\n return CONTENT_TYPES[ext] ?? 'text/plain; charset=utf-8'\n}\n\nexport function refuseUpgrade(socket: Duplex, status: string): void {\n socket.write(`HTTP/1.1 ${status}\\r\\n\\r\\n`)\n socket.destroy()\n}\n","import type { ProfileConfigSnapshot, ProfileEngine, ProfileInfo } from '@workerdeck/protocol'\nimport { existsSync, readFileSync, readdirSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join, resolve as resolvePath, sep } from 'node:path'\n\nexport function isProviderProfile(profile: ProfileInfo): boolean {\n return profile.engine === 'provider'\n}\n\nexport function engineOf(source: { engine?: ProfileEngine } | undefined): ProfileEngine {\n return source?.engine ?? 'claude'\n}\n\nexport function cliConfigDir(env: Record<string, string | undefined>): string {\n return env.CLAUDE_CONFIG_DIR ?? join(homedir(), '.claude')\n}\n\nexport function codexHomeDir(env: Record<string, string | undefined>): string {\n return env.CODEX_HOME ?? join(homedir(), '.codex')\n}\n\n// Detection is by credential directory, not by binary: a directory that exists is one the operator\n// has already logged into, and a profile pointing at an engine that is not installed reports itself\n// unavailable rather than failing at session start.\nexport function detectDefaultProfiles(env: Record<string, string | undefined> = process.env): ProfileInfo[] {\n const detected: ProfileInfo[] = []\n const claude = cliConfigDir(env)\n if (existsSync(claude)) {\n detected.push({ name: 'default', configDir: claude })\n }\n const codex = codexHomeDir(env)\n if (existsSync(codex)) {\n detected.push({ name: 'codex', engine: 'codex', codexHome: codex })\n }\n return detected\n}\n\nexport function cwdAllowed(cwd: string, roots: string[] | undefined): boolean {\n if (!roots || roots.length === 0) {\n return true\n }\n const resolved = resolvePath(cwd)\n return roots.some((root) => {\n const r = resolvePath(root)\n return resolved === r || resolved.startsWith(r + sep)\n })\n}\n\nfunction listDirs(path: string): string[] {\n try {\n return readdirSync(path, { withFileTypes: true })\n .filter((entry) => entry.isDirectory())\n .map((entry) => entry.name)\n .sort()\n } catch {\n return []\n }\n}\n\nfunction listMd(path: string): string[] {\n try {\n return readdirSync(path)\n .filter((file) => file.endsWith('.md'))\n .map((file) => file.slice(0, -3))\n .sort()\n } catch {\n return []\n }\n}\n\nfunction count(rules: unknown): number {\n return Array.isArray(rules) ? rules.length : 0\n}\n\n// Env var VALUES are never read into this snapshot - names only.\nexport function readProfileConfig(profile: ProfileInfo): ProfileConfigSnapshot {\n const dir = profile.configDir\n if (!dir) {\n return { hasUserMemory: false, skills: [], agents: [], commands: [] }\n }\n const snapshot: ProfileConfigSnapshot = {\n hasUserMemory: ['CLAUDE.md', 'AGENTS.md'].some((name) => existsSync(join(dir, name))),\n skills: listDirs(join(dir, 'skills')),\n agents: listMd(join(dir, 'agents')),\n commands: listMd(join(dir, 'commands')),\n }\n try {\n const raw = JSON.parse(readFileSync(join(dir, 'settings.json'), 'utf8')) as Record<string, unknown>\n const permissions = (raw.permissions ?? {}) as Record<string, unknown>\n snapshot.settings = {\n model: typeof raw.model === 'string' ? raw.model : undefined,\n defaultPermissionMode: typeof permissions.defaultMode === 'string' ? permissions.defaultMode : undefined,\n permissionRules: {\n allow: count(permissions.allow),\n ask: count(permissions.ask),\n deny: count(permissions.deny),\n },\n envKeys: raw.env && typeof raw.env === 'object' ? Object.keys(raw.env).sort() : undefined,\n hooks: raw.hooks && typeof raw.hooks === 'object' ? Object.keys(raw.hooks).sort() : undefined,\n }\n } catch {}\n return snapshot\n}\n","import type { Runner } from '@workerdeck/core'\nimport { isJobRun } from '@workerdeck/protocol'\n\n// What a hot reload may do with a live session. `carry` hands the runner object itself to the next generation,\n// which is the only way an engine child process, its subagents and its shell grandchildren survive; `persist` is\n// the ordinary restart story through the store; `drop` lets the session end with the generation.\nexport type ReloadPlan = 'carry' | 'persist' | 'drop'\n\nexport function reloadPlan(runner: Runner): ReloadPlan {\n const info = runner.info()\n if (info.status === 'closed' || info.status === 'failed') {\n return 'drop'\n }\n // The queue owns a job's session: a carried one would be a row nothing will ever finalize.\n if (isJobRun(info)) {\n return 'drop'\n }\n // Keyed on the capability, never on the engine name: \"can this session persist itself\" is the actual question,\n // and a runner that can snapshot has in-process executors closed over this generation's bridge hub, which after\n // the swap has no sockets. Carrying one does not orphan a call in flight, it breaks every later bridged call.\n if (runner.snapshot !== undefined) {\n return 'persist'\n }\n return 'carry'\n}\n","import type { IncomingMessage } from 'node:http'\nimport type { Duplex } from 'node:stream'\nimport type { WebSocket, WebSocketServer } from 'ws'\nimport type { JobQueue } from '@workerdeck/queue'\nimport { PROTOCOL_VERSION, type JobEvent, type QueueServerFrame } from '@workerdeck/protocol'\nimport { refuseUpgrade } from '../lib/http.ts'\nimport type { DiagnosticSink } from '../options.ts'\nimport type { AuthService } from '../services/auth.ts'\n\nexport type QueueSocketHub = {\n broadcast: (event: JobEvent) => void\n upgrade: (req: IncomingMessage, socket: Duplex, head: Buffer) => Promise<void>\n clear: () => void\n}\n\nexport type QueueSocketDeps = {\n wss: WebSocketServer\n auth: AuthService\n queue: () => JobQueue | undefined\n diagnose: DiagnosticSink\n}\n\nexport function createQueueSocketHub(deps: QueueSocketDeps): QueueSocketHub {\n const sockets = new Set<WebSocket>()\n\n const broadcast = (event: JobEvent): void => {\n if (sockets.size === 0) {\n return\n }\n for (const ws of sockets) {\n sendQueueFrame(ws, { type: 'job_event', event })\n }\n if (event.type !== 'job_progress') {\n void deps\n .queue()\n ?.stats()\n .then((stats) => {\n for (const ws of sockets) {\n sendQueueFrame(ws, { type: 'queue_stats', stats })\n }\n })\n .catch((error: unknown) => deps.diagnose(error, 'queue-stats'))\n }\n }\n\n const upgrade = async (req: IncomingMessage, socket: Duplex, head: Buffer): Promise<void> => {\n const queue = deps.queue()\n if (!queue) {\n refuseUpgrade(socket, '404 Not Found')\n return\n }\n const auth = await deps.auth.authenticate(req)\n if (!auth.ok) {\n refuseUpgrade(socket, '401 Unauthorized')\n return\n }\n if (!deps.auth.isOperator(auth)) {\n refuseUpgrade(socket, '404 Not Found')\n return\n }\n deps.wss.handleUpgrade(req, socket, head, (ws) => {\n sockets.add(ws)\n ws.on('close', () => sockets.delete(ws))\n void queue\n .stats()\n .then((stats) => sendQueueFrame(ws, { type: 'queue_attached', protocolVersion: PROTOCOL_VERSION, stats }))\n .catch((error: unknown) => deps.diagnose(error, 'queue-stats'))\n })\n }\n\n return { broadcast, upgrade, clear: () => sockets.clear() }\n}\n\nfunction sendQueueFrame(ws: WebSocket, frame: QueueServerFrame): void {\n if (ws.readyState === ws.OPEN) {\n ws.send(JSON.stringify(frame))\n }\n}\n","import { HttpError } from './http.ts'\n\nexport type ShellRouteAction = 'output' | 'kill' | 'agent-write'\n\nexport type SessionItemRoute =\n | { kind: 'session'; id: string }\n | { kind: 'ws'; id: string }\n | { kind: 'permission'; id: string; permissionId: string }\n | { kind: 'attachments'; id: string; attachmentId?: string }\n | { kind: 'produced'; id: string; producedFileId?: string }\n | { kind: 'shells'; id: string; shellId?: string; shellAction?: ShellRouteAction }\n | { kind: 'stop-task'; id: string; stopTaskId: string }\n | { kind: 'background-task'; id: string; backgroundTaskId?: string }\n | { kind: 'project-icon'; id: string }\n | { kind: 'tool-result'; id: string; resultSeq: number }\n | { kind: 'mcp'; id: string; mcpServer?: string }\n | { kind: 'files'; id: string; filePath?: string }\n | { kind: 'peers'; id: string }\n | { kind: 'sleep'; id: string }\n\nexport type SessionRoute = { kind: 'collection' } | SessionItemRoute\n\nconst SHELL_ACTIONS = new Set<string>(['output', 'kill', 'agent-write'])\n\n// Whole-segment matching: `/sessionsX` is not a session path. A segment that is not valid percent-encoding is a 400,\n// and an empty session id is no route at all, so `/sessions//permissions/x` can never reach the collection.\nexport function parseSessionRoute(basePath: string, url: string): SessionRoute | null {\n const pathname = new URL(url, 'http://internal').pathname\n const prefix = basePath + '/sessions'\n if (pathname !== prefix && !pathname.startsWith(prefix + '/')) {\n return null\n }\n const rest = pathname.slice(prefix.length)\n if (rest === '' || rest === '/') {\n return { kind: 'collection' }\n }\n const parts = rest.slice(1).split('/')\n if (parts[0] === '') {\n return null\n }\n return itemRoute(parts[0]!, parts)\n}\n\nfunction itemRoute(rawId: string, parts: string[]): SessionItemRoute | null {\n const [, section, third, fourth] = parts\n const length = parts.length\n if (length === 1) {\n return { kind: 'session', id: decode(rawId) }\n }\n if (length === 2 && section === 'ws') {\n return { kind: 'ws', id: decode(rawId) }\n }\n if (length === 3 && section === 'permissions') {\n const permissionId = decode(third!)\n return permissionId === '' ? null : { kind: 'permission', id: decode(rawId), permissionId }\n }\n if (length <= 3 && section === 'attachments') {\n return { kind: 'attachments', id: decode(rawId), attachmentId: optional(third) }\n }\n if (length <= 3 && section === 'produced') {\n return { kind: 'produced', id: decode(rawId), producedFileId: optional(third) }\n }\n if (section === 'shells' && length <= 4) {\n if (fourth !== undefined && !SHELL_ACTIONS.has(fourth)) {\n return null\n }\n return { kind: 'shells', id: decode(rawId), shellId: optional(third), shellAction: fourth as ShellRouteAction | undefined }\n }\n if (length === 4 && section === 'tasks' && fourth === 'stop') {\n return { kind: 'stop-task', id: decode(rawId), stopTaskId: decode(third!) }\n }\n if (length === 3 && section === 'tasks' && third === 'background') {\n return { kind: 'background-task', id: decode(rawId) }\n }\n if (length === 4 && section === 'tasks' && fourth === 'background') {\n return { kind: 'background-task', id: decode(rawId), backgroundTaskId: decode(third!) }\n }\n if (length === 3 && section === 'project' && third === 'icon') {\n return { kind: 'project-icon', id: decode(rawId) }\n }\n if (length === 4 && section === 'events' && fourth === 'result') {\n const seq = Number(third)\n return Number.isInteger(seq) && seq >= 0 ? { kind: 'tool-result', id: decode(rawId), resultSeq: seq } : null\n }\n if (length === 2 && section === 'sleep') {\n return { kind: 'sleep', id: decode(rawId) }\n }\n if (length === 2 && section === 'peers') {\n return { kind: 'peers', id: decode(rawId) }\n }\n if (length <= 3 && section === 'mcp') {\n // MCP server names are opaque and may contain ':' (plugin:gtm:gtm) - one segment, decoded whole.\n return { kind: 'mcp', id: decode(rawId), mcpServer: optional(third) }\n }\n if (length >= 2 && section === 'files') {\n const filePath = parts.slice(2).map(decode).join('/')\n return { kind: 'files', id: decode(rawId), filePath: filePath === '' ? undefined : '/' + filePath }\n }\n return null\n}\n\nfunction optional(segment: string | undefined): string | undefined {\n return segment === undefined ? undefined : decode(segment)\n}\n\nfunction decode(segment: string): string {\n try {\n return decodeURIComponent(segment)\n } catch {\n throw new HttpError(400, 'malformed percent-encoding in path')\n }\n}\n","import type { Runner } from '@workerdeck/core'\nimport type { SessionInfo } from '@workerdeck/protocol'\nimport type { ServerContext } from '../context.ts'\nimport { fail } from '../lib/http.ts'\nimport type { AuthContext } from '../services/auth.ts'\nimport type { StoredSessionRecord } from '../services/session-store.ts'\n\nexport type ResolvedSession = { runner: Runner | undefined; parked: StoredSessionRecord | null; info: SessionInfo }\n\nexport async function sessionInfoOf(ctx: ServerContext, id: string): Promise<SessionInfo | undefined> {\n return ctx.registry.get(id)?.info() ?? (await ctx.parking.get(id))?.info\n}\n\n// Missing and not-visible answer the same 404: whether a session exists outside the caller's scope is not its business.\nexport async function resolveSession(ctx: ServerContext, id: string, auth: AuthContext): Promise<ResolvedSession> {\n const runner = ctx.registry.get(id)\n const parked = runner ? null : await ctx.parking.get(id)\n const info = runner?.info() ?? parked?.info\n if (!info || !ctx.auth.canSee(auth, info)) {\n fail(404, 'session not found')\n }\n return { runner, parked, info }\n}\n\nexport function requireLive(runner: Runner | undefined, why: string): Runner {\n if (!runner) {\n fail(409, `session is parked (${why})`)\n }\n return runner\n}\n","import type { PermissionMode, ResolvePermissionRequest } from '@workerdeck/protocol'\n\nexport type PermissionModePolicy = { operator: boolean; disableBypass?: boolean }\n\nexport type PermissionDecisionInput = {\n behavior: 'allow' | 'deny'\n updatedInput?: Record<string, unknown>\n message?: string\n interrupt?: boolean\n}\n\nexport const OPERATOR_ONLY_MODES: ReadonlySet<PermissionMode> = new Set<PermissionMode>(['bypassPermissions', 'dontAsk'])\n\nexport function refusePermissionMode(mode: PermissionMode | undefined, policy: PermissionModePolicy): string | null {\n if (mode === 'bypassPermissions' && policy.disableBypass) {\n return 'bypassPermissions is disabled on this server (disableBypassPermissions)'\n }\n if (!policy.operator && mode !== undefined && OPERATOR_ONLY_MODES.has(mode)) {\n return `permission mode '${mode}' is reserved to operators`\n }\n return null\n}\n\nexport function permissionDecision(input: PermissionDecisionInput): ResolvePermissionRequest {\n return input.behavior === 'allow'\n ? { behavior: 'allow', updatedInput: input.updatedInput }\n : { behavior: 'deny', message: input.message, interrupt: input.interrupt }\n}\n","const MAX_SCOPE_KEYS = 16\nconst MAX_SCOPE_LEN = 200\n\nexport function readScope(value: unknown): Record<string, string> | undefined {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return undefined\n }\n const entries = Object.entries(value as Record<string, unknown>)\n if (entries.some(([, v]) => typeof v !== 'string')) {\n return undefined\n }\n return Object.fromEntries(entries) as Record<string, string>\n}\n\nexport function checkScope(value: unknown): string | null {\n if (value === undefined) {\n return null\n }\n const scope = readScope(value)\n if (!scope) {\n return 'scope must be an object of string values'\n }\n const entries = Object.entries(scope)\n if (entries.length > MAX_SCOPE_KEYS) {\n return `scope may carry at most ${MAX_SCOPE_KEYS} keys`\n }\n for (const [key, val] of entries) {\n if (key.length === 0) {\n return 'scope keys must not be empty'\n }\n if (key.length > MAX_SCOPE_LEN || val.length > MAX_SCOPE_LEN) {\n return `scope keys and values must be at most ${MAX_SCOPE_LEN} characters`\n }\n }\n return null\n}\n\nexport function sameScope(a: Record<string, string> | undefined, b: Record<string, string> | undefined): boolean {\n const left = Object.entries(a ?? {}).sort(([x], [y]) => (x < y ? -1 : 1))\n const right = Object.entries(b ?? {}).sort(([x], [y]) => (x < y ? -1 : 1))\n return left.length === right.length && left.every(([key, value], i) => right[i]![0] === key && right[i]![1] === value)\n}\n\nexport function scopeMatches(principal: Record<string, string> | undefined, session: Record<string, string> | undefined): boolean {\n if (!principal) {\n return true\n }\n return Object.entries(principal).every(([key, value]) => session?.[key] === value)\n}\n","import {\n PEER_MESSAGE_MAX_CHARS,\n PEER_RECENT_DEFAULT,\n PEER_RECENT_MAX,\n peerSummary,\n recentLines,\n type PeerDirectory,\n type PeerPeek,\n type PeerSendOptions,\n type PeerSendResult,\n type PeerMention,\n type PeerSessionSummary,\n type Runner,\n} from '@workerdeck/core'\nimport {\n PEER_MENTION_MAX,\n peerMentionKey,\n peerMentionSlug,\n scanPeerMentions,\n teamReaches,\n type MessageOrigin,\n type SessionEvent,\n type SessionInfo,\n} from '@workerdeck/protocol'\nimport type { RelayOrigin, RelayPeek, RelaySendResult, RelaySessionEntry } from '@workerdeck/relay-client'\nimport { scopeMatches } from '../lib/scope.ts'\nimport type { LateBoundRefs } from '../options.ts'\nimport type { ProjectInfoService } from './project-info.ts'\nimport type { SessionRegistry } from './registry.ts'\n\nexport type PeerServiceOptions = {\n enabled?: boolean\n maxMessageChars?: number\n perMinute?: number\n maxHops?: number\n}\n\nexport type PeerServiceDeps = {\n refs: LateBoundRefs\n projects: ProjectInfoService\n options?: PeerServiceOptions\n}\n\nconst DEFAULT_PER_MINUTE = 10\nconst DEFAULT_MAX_HOPS = 12\nconst WINDOW_MS = 60_000\n\nfunction visible(from: SessionInfo, to: SessionInfo): boolean {\n return to.id !== from.id && scopeMatches(from.scope, to.scope) && teamReaches(from.agent, to.agent)\n}\n\nfunction relayable(info: SessionInfo, exposed: Record<string, string> | undefined): boolean {\n return info.status !== 'closed' && info.agent?.lead === undefined && scopeMatches(exposed, info.scope)\n}\n\nexport type PeerService = PeerDirectory & {\n watch(runner: Runner): () => void\n // The `#Name` tokens in a message a person typed, resolved to the peers that session can see.\n // The relay half. `exposed` is the gateway ceiling's scope: a session outside it is never published and never\n // answers an inbound request, whatever the relay asks.\n relaySender(from: string): Promise<SessionInfo>\n relayChain(from: string): string[]\n relayEntries(exposed: Record<string, string> | undefined): Promise<RelaySessionEntry[]>\n relayPeek(sessionId: string, recent: number | undefined, exposed: Record<string, string> | undefined): Promise<RelayPeek | undefined>\n relaySend(origin: RelayOrigin, sessionId: string, text: string, exposed: Record<string, string> | undefined): Promise<RelaySendResult>\n}\n\nexport function relayEntry(info: SessionInfo, live: boolean): RelaySessionEntry {\n const items = info.checklist\n return {\n id: info.id,\n engine: info.engine,\n status: info.status,\n title: info.title,\n project: info.project ? { name: info.project.name, root: info.project.root } : undefined,\n cwd: info.cwd,\n profile: info.profile,\n model: info.model,\n permissionMode: info.permissionMode,\n contextUsage: info.contextUsage,\n checklist: items?.length ? { done: items.filter((item) => item.status === 'completed').length, total: items.length } : undefined,\n numTurns: info.numTurns,\n createdAt: info.createdAt,\n lastActivityAt: info.lastActivityAt,\n pendingPermissionCount: info.pendingPermissionCount,\n live,\n }\n}\n\n// Session-to-session messaging inside one gateway. Visibility is the session-scope rule the HTTP routes enforce,\n// applied with the *sender's* scope as the principal: a scoped session sees the sessions a scoped client would.\nexport function createPeerService(deps: PeerServiceDeps): PeerService {\n const perMinute = deps.options?.perMinute ?? DEFAULT_PER_MINUTE\n const maxChars = deps.options?.maxMessageChars ?? PEER_MESSAGE_MAX_CHARS\n const maxHops = deps.options?.maxHops ?? DEFAULT_MAX_HOPS\n const sent = new Map<string, number[]>()\n // The chain of sessions that led to the last peer message each session received, cleared when a human speaks to\n // it: two agents answering each other without a person in the loop is the loop this bounds.\n const inbound = new Map<string, string[]>()\n\n const registry = (): SessionRegistry => {\n const found = deps.refs.registry\n if (!found) {\n throw new Error('peer messaging is not ready')\n }\n return found\n }\n\n const allSessions = async (): Promise<SessionInfo[]> => {\n const live = registry().list()\n const dormant = (await deps.refs.parking?.listInfo()) ?? []\n return [...live, ...dormant].map((info) => deps.projects.withProject(info))\n }\n\n const infoOf = async (id: string): Promise<SessionInfo | undefined> => {\n const live = registry().get(id)?.info()\n if (live) {\n return deps.projects.withProject(live)\n }\n const record = await deps.refs.parking?.get(id)\n return record ? deps.projects.withProject(record.info) : undefined\n }\n\n const sender = async (from: string): Promise<SessionInfo> => {\n const info = await infoOf(from)\n if (!info) {\n throw new Error(`unknown sender session: ${from}`)\n }\n return info\n }\n\n const recentOf = (sessionId: string, recent: number | undefined): { runner: Runner | undefined; lines: string[] } => {\n const limit = Math.min(Math.max(recent ?? PEER_RECENT_DEFAULT, 0), PEER_RECENT_MAX)\n const runner = registry().get(sessionId)\n const events: SessionEvent[] = []\n if (runner && limit > 0) {\n runner.subscribe((event) => events.push(event), 0, { truncateResults: true, imageRefs: true })()\n }\n return { runner, lines: recentLines(events, limit) }\n }\n\n const underRateLimit = (from: string, to: string): boolean => {\n const key = `${from}->${to}`\n const now = Date.now()\n const recent = (sent.get(key) ?? []).filter((at) => now - at < WINDOW_MS)\n if (recent.length >= perMinute) {\n sent.set(key, recent)\n return false\n }\n recent.push(now)\n sent.set(key, recent)\n return true\n }\n\n const list = async (from: string): Promise<PeerSessionSummary[]> => {\n const me = await sender(from)\n return (await allSessions())\n .filter((info) => visible(me, info))\n .sort((a, b) => (b.lastActivityAt ?? b.createdAt) - (a.lastActivityAt ?? a.createdAt))\n .map(peerSummary)\n }\n\n const peek = async (from: string, sessionId: string, options?: { recent?: number }): Promise<PeerPeek | undefined> => {\n const me = await sender(from)\n const info = await infoOf(sessionId)\n if (!info || !visible(me, info)) {\n return undefined\n }\n const { runner, lines } = recentOf(sessionId, options?.recent)\n return {\n ...peerSummary(info),\n live: runner !== undefined,\n checklist: info.checklist,\n pendingApprovals: runner ? runner.pendingApprovals.map((request) => request.title ?? request.toolName) : [],\n recent: lines,\n }\n }\n\n const send = async (from: string, sessionId: string, text: string, options?: PeerSendOptions): Promise<PeerSendResult> => {\n const me = await sender(from)\n if (sessionId === from) {\n return { delivered: false, reason: 'that is this session' }\n }\n if (text.length > maxChars) {\n return {\n delivered: false,\n reason: `message is ${text.length} characters; the limit is ${maxChars}. Write it to a file and send the path.`,\n }\n }\n const target = await infoOf(sessionId)\n if (!target || !visible(me, target)) {\n return { delivered: false, reason: `no such session: ${sessionId}` }\n }\n const hops = [...(options?.hops ?? inbound.get(from) ?? []), from]\n return deliver(target, text, { kind: 'peer', sessionId: from, name: me.title, engine: me.engine, hops }, from)\n }\n\n const deliver = async (target: SessionInfo, text: string, origin: MessageOrigin, rateKey: string): Promise<PeerSendResult> => {\n const sessionId = target.id\n if (target.status === 'closed' || target.status === 'failed') {\n return { delivered: false, reason: `session ${sessionId} is ${target.status}` }\n }\n const hops = origin.hops ?? []\n if (hops.length > maxHops) {\n return {\n delivered: false,\n reason: `${hops.length} messages have passed between sessions without a person speaking; stop and ask your user before continuing.`,\n }\n }\n if (!underRateLimit(rateKey, sessionId)) {\n return { delivered: false, reason: `rate limit: at most ${perMinute} messages a minute to one session. Batch what you have to say.` }\n }\n const runner = (await deps.refs.parking?.ensureLive(sessionId)) ?? registry().get(sessionId)\n if (!runner) {\n return { delivered: false, reason: `session ${sessionId} could not be woken` }\n }\n const before = runner.info().status\n try {\n runner.sendMessage(text, undefined, { origin })\n } catch (error) {\n return { delivered: false, reason: error instanceof Error ? error.message : String(error) }\n }\n inbound.set(sessionId, hops)\n return { delivered: true, sessionId, name: target.title, queued: before === 'running' || before === 'awaiting_approval' }\n }\n\n const exposedInfo = async (sessionId: string, exposed: Record<string, string> | undefined): Promise<SessionInfo | undefined> => {\n const info = await infoOf(sessionId)\n return info && relayable(info, exposed) ? info : undefined\n }\n\n const relayEntries = async (exposed: Record<string, string> | undefined): Promise<RelaySessionEntry[]> => {\n const live = new Set(\n registry()\n .list()\n .map((info) => info.id),\n )\n return (await allSessions()).filter((info) => relayable(info, exposed)).map((info) => relayEntry(info, live.has(info.id)))\n }\n\n const relayPeek = async (\n sessionId: string,\n recent: number | undefined,\n exposed: Record<string, string> | undefined,\n ): Promise<RelayPeek | undefined> => {\n const info = await exposedInfo(sessionId, exposed)\n if (!info) {\n return undefined\n }\n const { runner, lines } = recentOf(sessionId, recent)\n return {\n ...relayEntry(info, runner !== undefined),\n checklistItems: info.checklist,\n pendingApprovals: runner ? runner.pendingApprovals.map((request) => request.title ?? request.toolName) : [],\n recent: lines,\n }\n }\n\n const relaySend = async (\n origin: RelayOrigin,\n sessionId: string,\n text: string,\n exposed: Record<string, string> | undefined,\n ): Promise<RelaySendResult> => {\n if (text.length === 0 || text.length > maxChars) {\n return {\n delivered: false,\n reason: `message is ${text.length} characters; the limit is ${maxChars}. Write it to a file and send the path.`,\n }\n }\n const target = await exposedInfo(sessionId, exposed)\n if (!target) {\n return { delivered: false, reason: `no such session: ${sessionId}` }\n }\n const from = `${origin.gateway}:${origin.sessionId}`\n return deliver(\n target,\n text,\n { kind: 'peer', sessionId: from, hostId: origin.gateway, name: origin.name, engine: origin.engine, hops: origin.hops },\n from,\n )\n }\n\n const watch = (runner: Runner): (() => void) =>\n runner.subscribe((event) => {\n if (event.type === 'user_message' && !event.origin && !event.synthetic && event.parentToolUseId == null && !event.replay) {\n inbound.delete(runner.id)\n }\n }, runner.info().lastSeq)\n\n return {\n list,\n peek,\n send,\n watch,\n relaySender: sender,\n relayChain: (from) => [...(inbound.get(from) ?? []), from],\n relayEntries,\n relayPeek,\n relaySend,\n }\n}\n\n// A session id is a handle a person may paste, so a full id and an unambiguous prefix resolve too. `rows` is the\n// sender's whole directory, remote sessions included, newest-first.\nexport function resolvePeerMentions(rows: readonly PeerSessionSummary[], text: string): PeerMention[] {\n const tokens = scanPeerMentions(text)\n if (tokens.length === 0) {\n return []\n }\n const byKey = new Map<string, PeerSessionSummary[]>()\n const add = (key: string, row: PeerSessionSummary) => {\n const held = byKey.get(key)\n if (held) {\n held.push(row)\n } else {\n byKey.set(key, [row])\n }\n }\n for (const row of rows) {\n const keys = new Set([peerMentionKey(peerMentionSlug(row.title, row.id)), peerMentionKey(row.id)])\n if (row.agent) {\n keys.add(peerMentionKey(peerMentionSlug(row.agent, row.id)))\n }\n for (const key of keys) {\n add(key, row)\n }\n }\n const resolved: PeerMention[] = []\n const seen = new Set<string>()\n for (const token of tokens) {\n const key = peerMentionKey(token.body)\n const exact = byKey.get(key)\n // Local rows come first, newest-first, so a shared title resolves to the closest session that\n // moved last and the envelope names the others rather than choosing silently.\n const matches = exact ?? (key.length >= 4 ? rows.filter((row) => row.id.startsWith(key)) : [])\n const target = matches[0]\n if (!target || (matches.length > 1 && !exact)) {\n continue\n }\n if (seen.has(target.id)) {\n continue\n }\n seen.add(target.id)\n const others = matches.slice(1, 4).map((row) => row.id)\n resolved.push({\n typed: token.body,\n id: target.id,\n name: target.agent ?? target.title,\n engine: target.engine,\n status: target.status,\n cwd: target.cwd,\n ...(others.length ? { ambiguousWith: others } : {}),\n })\n if (resolved.length >= PEER_MENTION_MAX) {\n break\n }\n }\n return resolved\n}\n\n// Asks the directory only when the text holds a `#` token, so an ordinary message costs no listing.\nexport async function mentionsFor(directory: PeerDirectory, from: string, text: string): Promise<PeerMention[]> {\n return scanPeerMentions(text).length === 0 ? [] : resolvePeerMentions(await directory.list(from), text)\n}\n","import type { Runner } from '@workerdeck/core'\nimport { HttpError } from '../lib/http.ts'\nimport { engineOf } from '../lib/profile-env.ts'\n\nexport async function sleepRunner(runner: Runner): Promise<void> {\n if (!runner.sleep) {\n throw new HttpError(501, `the ${engineOf(runner.info())} engine has no process to put to sleep`)\n }\n const result = await runner.sleep()\n if (!result.ok) {\n throw new HttpError(409, `cannot sleep: ${result.reason}`)\n }\n}\n","import {\n SHELL_REFUSAL,\n agentMayWrite,\n clampShellTail,\n encodeShellKeys,\n shellOwnershipRefusal,\n shellSummary,\n shellTail,\n ttyText,\n type Runner,\n type ShellDirectory,\n type ShellReadResult,\n type ShellView,\n} from '@workerdeck/core'\nimport { SHELL_READ_MAX_LINES, SHELL_WAIT_DEFAULT_MS, SHELL_WAIT_MAX_MS, type ShellInfo } from '@workerdeck/protocol'\nimport type { ShellRegistry, ShellSpawnInput } from './shell-types.ts'\n\n// The directory reaches a live runner only to start a shell for it: the record needs the session's cwd and the runner\n// draws the transcript row, exactly as a `$` from the composer does.\nexport type ShellDirectoryDeps = { runnerFor?: (sessionId: string) => Runner | undefined }\n\nexport type LocalCommandRunner = Runner & Required<Pick<Runner, 'queueLocalCommand'>>\n\ntype ShellSettleOptions = { view?: ShellView; tail?: number; waitFor?: string[]; timeoutMs?: number; since?: number }\n\ntype ShellTaken = { info: ShellInfo; read: Omit<ShellReadResult, 'shell' | 'wait'>; haystack: string }\n\n// The agent's side of the same registry: a session sees its own shells and nothing else, so another session's id\n// reads as missing rather than as a refusal that would name it. Writes and kills are further limited to shells the\n// agent owns (`agentMayWrite`), and that refusal names the rule because the shell does exist.\nexport function createShellDirectory(registry: ShellRegistry, deps: ShellDirectoryDeps = {}): ShellDirectory {\n // One read of the shell as it is now. With `since`, the haystack is only what the process wrote after that byte\n // offset, so a wait that follows a keystroke cannot be satisfied by text that was already on the screen.\n const take = async (from: string, shellId: string, options: ShellSettleOptions): Promise<ShellTaken | undefined> => {\n const info = registry.get(from, shellId)\n if (!info) {\n return undefined\n }\n const view: ShellView = options.view ?? (info.interactive ? 'screen' : 'lines')\n const fresh = options.since === undefined ? undefined : await freshText(from, shellId, info.bytes - options.since)\n if (view === 'screen') {\n const text = await registry.output(from, shellId, { view: 'screen' })\n if (text === undefined) {\n return undefined\n }\n const lines = text === '' ? 0 : text.split('\\n').length\n return { info, read: { view, text, lines, totalLines: lines, truncated: false }, haystack: fresh ?? text }\n }\n const text = await registry.output(from, shellId, { view: 'text' })\n if (text === undefined) {\n return undefined\n }\n return { info, read: shellTail(text, clampShellTail(options.tail)), haystack: fresh ?? shellTail(text, SHELL_READ_MAX_LINES).text }\n }\n const freshText = async (from: string, shellId: string, bytes: number): Promise<string> => {\n if (bytes <= 0) {\n return ''\n }\n const raw = await registry.output(from, shellId, { view: 'raw', tail: bytes })\n return raw === undefined ? '' : ttyText(raw)\n }\n const settle = async (from: string, shellId: string, options: ShellSettleOptions): Promise<ShellReadResult | undefined> => {\n const needles = options.waitFor ?? []\n const started = Date.now()\n const timeoutMs = Math.max(0, Math.min(options.timeoutMs ?? SHELL_WAIT_DEFAULT_MS, SHELL_WAIT_MAX_MS))\n for (;;) {\n const taken = await take(from, shellId, options)\n if (!taken) {\n return undefined\n }\n const result: ShellReadResult = { shell: shellSummary(taken.info), ...taken.read }\n if (needles.length === 0) {\n return result\n }\n const ms = Date.now() - started\n const match = needles.find((needle) => taken.haystack.includes(needle))\n if (match !== undefined) {\n return { ...result, wait: { outcome: 'matched', match, ms } }\n }\n if (taken.info.status !== 'running') {\n return { ...result, wait: { outcome: 'exited', ms } }\n }\n if (ms >= timeoutMs) {\n return { ...result, wait: { outcome: 'timeout', ms } }\n }\n await registry.changed(from, shellId, timeoutMs - ms)\n }\n }\n const writable = (from: string, shellId: string): ShellInfo | undefined => {\n const info = registry.get(from, shellId)\n if (!info) {\n return undefined\n }\n if (!agentMayWrite(info, from)) {\n throw new Error(shellOwnershipRefusal(shellId))\n }\n return info\n }\n return {\n list: async (from) => registry.list(from).map(shellSummary),\n read: (from, shellId, options) => settle(from, shellId, { ...options }),\n run: async (from, options) => {\n const runner = deps.runnerFor?.(from)\n if (!runner || !takesLocalCommands(runner)) {\n throw new Error(SHELL_REFUSAL)\n }\n const shell = await startShell(registry, { runner, command: options.command, owner: 'agent' })\n const result = await settle(from, shell.id, { waitFor: options.waitFor, timeoutMs: options.timeoutMs })\n if (!result) {\n throw new Error(`shell ${shell.id} vanished as it started`)\n }\n return result\n },\n write: async (from, shellId, options) => {\n const info = writable(from, shellId)\n if (!info) {\n return undefined\n }\n if (info.status !== 'running') {\n throw new Error(`shell ${shellId} has already ended; there is nothing to type into`)\n }\n const application = await registry.applicationCursorKeys(from, shellId)\n const data = (options.data ?? '') + encodeShellKeys(options.keys ?? [], { applicationCursorKeys: application })\n if (data.length === 0) {\n throw new Error('nothing to write: give data, keys or both')\n }\n const since = registry.get(from, shellId)?.bytes ?? info.bytes\n registry.write(from, shellId, data)\n return settle(from, shellId, { waitFor: options.waitFor, timeoutMs: options.timeoutMs, since })\n },\n kill: async (from, shellId) => {\n const info = writable(from, shellId)\n if (!info) {\n return undefined\n }\n if (info.status !== 'running') {\n return { shell: shellSummary(info), killed: false }\n }\n const killed = registry.kill(from, shellId, 'killed') ?? info\n return { shell: shellSummary(killed), killed: true }\n },\n grant: async (from, shellId) => {\n const info = registry.get(from, shellId)\n if (!info) {\n return undefined\n }\n if (info.owner === 'agent') {\n return shellSummary(info)\n }\n const granted = registry.setAgentWrite(from, shellId, true)\n return granted ? shellSummary(granted) : undefined\n },\n }\n}\n\nexport function takesLocalCommands(runner: Runner): runner is LocalCommandRunner {\n return typeof runner.queueLocalCommand === 'function'\n}\n\n// queueLocalCommand throws before it pushes, so without the kill the shell would run with no transcript row.\nexport async function startShell(registry: ShellRegistry, input: ShellSpawnInput & { runner: LocalCommandRunner }): Promise<ShellInfo> {\n const { shell, source } = await registry.spawn(input)\n try {\n input.runner.queueLocalCommand(source)\n } catch (error) {\n registry.kill(input.runner.id, shell.id)\n throw error\n }\n return shell\n}\n","import { spawnSync } from 'node:child_process'\n\nexport type ProcessRow = { pid: number; ppid: number; pgid: number }\n\nexport type ProcessTable = () => ProcessRow[] | null\n\nexport type ProcessSignal = 'SIGSTOP' | 'SIGKILL'\n\nexport type TreeKillDeps = { table: ProcessTable; signal: (pid: number, signal: ProcessSignal) => void; self: number }\n\nexport type TreeKillResult = { scanned: boolean; descendants: number; foreign: number[]; unreached: number[] }\n\nconst PS_ARGS = ['-eo', 'pid=,ppid=,pgid=']\nconst PS_TIMEOUT_MS = 2000\nconst PS_MAX_BUFFER = 64 * 1024 * 1024\nconst MAX_ROUNDS = 5\n\nexport function readProcessTable(): ProcessRow[] | null {\n const result = spawnSync('ps', PS_ARGS, {\n encoding: 'utf8',\n timeout: PS_TIMEOUT_MS,\n maxBuffer: PS_MAX_BUFFER,\n stdio: ['ignore', 'pipe', 'ignore'],\n })\n if (result.error || result.status !== 0 || typeof result.stdout !== 'string') {\n return null\n }\n return parseProcessTable(result.stdout)\n}\n\nexport function parseProcessTable(text: string): ProcessRow[] {\n const rows: ProcessRow[] = []\n for (const line of text.split('\\n')) {\n const fields = line.trim().split(/\\s+/)\n if (fields.length !== 3) {\n continue\n }\n const [pid, ppid, pgid] = fields.map(Number) as [number, number, number]\n if (Number.isInteger(pid) && Number.isInteger(ppid) && Number.isInteger(pgid)) {\n rows.push({ pid, ppid, pgid })\n }\n }\n return rows\n}\n\n// Freezes the tree under each root before killing it, so nothing discovered can fork past the scan: scan, SIGSTOP what\n// the scan found, rescan until the closure stops growing, then SIGKILL the closure. A root the table shows under a\n// parent other than us is a recycled pid and is not signalled at all. Without a table it is the group kill alone.\nexport function killProcessTrees(roots: number[], deps: TreeKillDeps): TreeKillResult {\n const { self } = deps\n const signal = (pid: number, name: ProcessSignal): boolean => {\n try {\n deps.signal(pid, name)\n return true\n } catch {\n return false\n }\n }\n const owned = (pid: number): boolean => Number.isInteger(pid) && pid > 1 && pid !== self\n const live = new Set(roots.filter(owned))\n const closure = new Map<number, ProcessRow>()\n const rootRows = new Map<number, ProcessRow>()\n const foreign: number[] = []\n let scanned = false\n let selfPgid: number | undefined\n for (let round = 0; round < MAX_ROUNDS; round++) {\n const table = readTable(deps.table)\n if (table === null) {\n break\n }\n const byPid = new Map<number, ProcessRow>()\n const byParent = new Map<number, ProcessRow[]>()\n for (const row of table) {\n byPid.set(row.pid, row)\n const siblings = byParent.get(row.ppid)\n if (siblings) {\n siblings.push(row)\n } else {\n byParent.set(row.ppid, [row])\n }\n }\n let grew = false\n if (!scanned) {\n scanned = true\n selfPgid = byPid.get(self)?.pgid\n for (const root of live) {\n const row = byPid.get(root)\n if (row === undefined) {\n continue\n }\n if (row.ppid !== self) {\n foreign.push(root)\n live.delete(root)\n continue\n }\n rootRows.set(root, row)\n signal(-root, 'SIGSTOP')\n // The roots were scanned before they were frozen, so the first round always earns a rescan.\n grew = true\n }\n }\n for (const root of rootRows.keys()) {\n const queue = [root]\n const seen = new Set<number>([root])\n while (queue.length > 0) {\n const parent = queue.shift()!\n for (const child of byParent.get(parent) ?? []) {\n if (!owned(child.pid) || seen.has(child.pid)) {\n continue\n }\n seen.add(child.pid)\n queue.push(child.pid)\n if (!closure.has(child.pid)) {\n closure.set(child.pid, child)\n signal(child.pid, 'SIGSTOP')\n grew = true\n }\n }\n }\n }\n if (!grew) {\n break\n }\n }\n const unreached: number[] = []\n const groups = new Set<number>()\n for (const root of live) {\n groups.add(root)\n if (!signal(-root, 'SIGKILL')) {\n unreached.push(root)\n }\n }\n for (const pid of closure.keys()) {\n signal(pid, 'SIGKILL')\n }\n if (selfPgid !== undefined) {\n for (const row of [...rootRows.values(), ...closure.values()]) {\n const group = row.pgid\n if (group <= 1 || group === self || group === selfPgid || groups.has(group)) {\n continue\n }\n groups.add(group)\n signal(-group, 'SIGKILL')\n }\n }\n return { scanned, descendants: closure.size, foreign, unreached }\n}\n\nfunction readTable(table: ProcessTable): ProcessRow[] | null {\n try {\n return table()\n } catch {\n return null\n }\n}\n","import { chmodSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'\nimport { chmod, mkdir, readFile, rename, writeFile } from 'node:fs/promises'\nimport { dirname } from 'node:path'\n\nexport type JsonWriteOptions = { indent?: number; trailingNewline?: boolean }\n\nconst FILE_MODE = 0o600\nconst DIR_MODE = 0o700\n\nexport function isMissing(error: unknown): boolean {\n return (error as NodeJS.ErrnoException | null)?.code === 'ENOENT'\n}\n\n// `writeFile`'s mode applies only on creation, so the chmod is what keeps a temp name left over by an earlier run from\n// handing its looser bits to the renamed file.\nexport async function writeFileAtomic(path: string, data: string | Uint8Array): Promise<void> {\n await mkdir(dirname(path), { recursive: true, mode: DIR_MODE })\n const temp = tempPathFor(path)\n await writeFile(temp, data, { mode: FILE_MODE })\n await chmod(temp, FILE_MODE)\n await rename(temp, path)\n}\n\nexport function writeFileAtomicSync(path: string, data: string | Uint8Array): void {\n mkdirSync(dirname(path), { recursive: true, mode: DIR_MODE })\n const temp = tempPathFor(path)\n writeFileSync(temp, data, { mode: FILE_MODE })\n chmodSync(temp, FILE_MODE)\n renameSync(temp, path)\n}\n\nexport function writeJsonAtomic(path: string, value: unknown, options: JsonWriteOptions = {}): Promise<void> {\n return writeFileAtomic(path, serializeJson(value, options))\n}\n\nexport function writeJsonAtomicSync(path: string, value: unknown, options: JsonWriteOptions = {}): void {\n writeFileAtomicSync(path, serializeJson(value, options))\n}\n\n// Missing, unreadable and corrupt all read as the fallback; a caller that must tell them apart reads the file itself.\nexport async function readJsonOr(path: string, fallback: unknown): Promise<unknown> {\n try {\n return JSON.parse(await readFile(path, 'utf8')) as unknown\n } catch {\n return fallback\n }\n}\n\nexport function readJsonOrSync(path: string, fallback: unknown): unknown {\n try {\n return JSON.parse(readFileSync(path, 'utf8')) as unknown\n } catch {\n return fallback\n }\n}\n\nfunction tempPathFor(path: string): string {\n return `${path}.${process.pid}.tmp`\n}\n\nfunction serializeJson(value: unknown, options: JsonWriteOptions): string {\n const text = JSON.stringify(value, null, options.indent)\n return options.trailingNewline ? `${text}\\n` : text\n}\n","import { mkdir, open, readFile, rm, stat, type FileHandle } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { ttyText } from '@workerdeck/core'\nimport { isMissing, writeFileAtomic } from '../lib/atomic-file.ts'\n\nexport { isMissing }\n\nexport type ArtifactLimits = { spill: number; cap: number; ring: number }\n\nexport type ArtifactPaths = { dir: string; raw: string; tail: string; rel: string }\n\nexport type StoredOutput = { output?: string; artifact?: string }\n\nexport type ShellArtifact = LiveArtifact | StoredArtifact\n\nexport function artifactPaths(base: string, sessionId: string, shellId: string): ArtifactPaths {\n const encoded = encodeURIComponent(sessionId)\n const sessionDir = join(base, encoded)\n return {\n dir: sessionDir,\n raw: join(sessionDir, `${shellId}.raw`),\n tail: join(sessionDir, `${shellId}.tail.raw`),\n rel: `${encoded}/${shellId}.raw`,\n }\n}\n\nexport class LiveArtifact {\n readonly #paths: ArtifactPaths\n readonly #limits: ArtifactLimits\n readonly #onError: (error: unknown) => void\n readonly #ring: Buffer\n #ringAt = 0\n #ringLen = 0\n #chunks: Buffer[] = []\n #chunkBytes = 0\n #bytes = 0\n #spilled = false\n #capped = false\n #closed = false\n #broken = false\n #io: Promise<void> = Promise.resolve()\n #handle: FileHandle | undefined\n #done = ''\n #pending = ''\n #textCache: string | undefined\n\n constructor(paths: ArtifactPaths, limits: ArtifactLimits, onError: (error: unknown) => void) {\n this.#paths = paths\n this.#limits = limits\n this.#onError = onError\n this.#ring = Buffer.alloc(Math.max(0, limits.ring))\n }\n\n get bytes(): number {\n return this.#bytes\n }\n\n get capped(): boolean {\n return this.#capped\n }\n\n append(data: string): boolean {\n const chunk = Buffer.from(data, 'utf8')\n const before = this.#bytes\n this.#bytes += chunk.length\n this.#ringPush(chunk)\n this.#textCache = undefined\n if (this.#capped) {\n return false\n }\n const room = Math.max(0, this.#limits.cap - before)\n const kept = chunk.length <= room ? chunk : chunk.subarray(0, room)\n this.#textAppend(kept === chunk ? data : kept.toString('utf8'))\n let changed = false\n if (this.#spilled) {\n this.#write(kept)\n } else {\n this.#chunks.push(kept)\n this.#chunkBytes += kept.length\n if (this.#chunkBytes > this.#limits.spill) {\n this.#spill()\n changed = true\n }\n }\n if (this.#bytes > this.#limits.cap) {\n this.#capped = true\n changed = true\n }\n return changed\n }\n\n text(): string {\n if (this.#textCache === undefined) {\n let text = this.#done + ttyText(this.#pending)\n if (this.#capped) {\n const after = this.#bytes - this.#limits.cap\n const kept = Math.min(after, this.#ringLen)\n if (kept > 0) {\n text += (after > kept ? '\\n' : '') + ttyText(this.tail(kept).toString('utf8'))\n }\n }\n this.#textCache = text\n }\n return this.#textCache\n }\n\n textView(): Promise<string> {\n return Promise.resolve(this.text())\n }\n\n tail(n: number = this.#ringLen): Buffer {\n const size = this.#ring.length\n const take = Math.max(0, Math.min(n, this.#ringLen))\n const out = Buffer.allocUnsafe(take)\n if (take === 0) {\n return out\n }\n const start = (this.#ringAt - take + size) % size\n const first = Math.min(take, size - start)\n this.#ring.copy(out, 0, start, start + first)\n if (first < take) {\n this.#ring.copy(out, first, 0, take - first)\n }\n return out\n }\n\n replay(max: number): Promise<Buffer> {\n const want = Math.max(0, Math.floor(max))\n if (!this.#spilled) {\n const all = Buffer.concat(this.#chunks, this.#chunkBytes)\n return Promise.resolve(all.subarray(Math.max(0, all.length - want)))\n }\n if (this.#capped || want <= this.#ringLen) {\n return Promise.resolve(this.tail(want))\n }\n const end = this.#bytes\n return this.#io.then(() => readRange(this.#paths.raw, Math.max(0, end - want), end))\n }\n\n async read(tail?: number): Promise<Buffer> {\n if (tail !== undefined) {\n return this.replay(tail)\n }\n if (!this.#spilled) {\n return Buffer.concat(this.#chunks, this.#chunkBytes)\n }\n await this.#io\n return readWhole(this.#paths.raw)\n }\n\n stored(): StoredOutput {\n return this.#spilled ? { artifact: this.#paths.rel } : { output: Buffer.concat(this.#chunks, this.#chunkBytes).toString('utf8') }\n }\n\n writeTail(): void {\n const tail = this.tail()\n this.#queue(() => writeFileAtomic(this.#paths.tail, tail))\n }\n\n close(): void {\n if (this.#closed) {\n return\n }\n this.#closed = true\n if (this.#capped) {\n this.writeTail()\n }\n this.#io = this.#io.then(async () => {\n const handle = this.#handle\n this.#handle = undefined\n await handle?.close().catch(() => {})\n })\n }\n\n idle(): Promise<void> {\n return this.#io\n }\n\n async remove(): Promise<void> {\n this.close()\n await this.#io\n await rm(this.#paths.raw, { force: true })\n await rm(this.#paths.tail, { force: true })\n }\n\n // Only the new chunk is searched: `#pending` holds no newline by construction, and scanning it again per chunk\n // made one long line quadratic.\n #textAppend(data: string): void {\n const newline = data.lastIndexOf('\\n')\n if (newline === -1) {\n this.#pending += data\n return\n }\n this.#done += ttyText(this.#pending + data.slice(0, newline + 1))\n this.#pending = data.slice(newline + 1)\n }\n\n #ringPush(chunk: Buffer): void {\n const size = this.#ring.length\n if (size === 0 || chunk.length === 0) {\n return\n }\n if (chunk.length >= size) {\n chunk.copy(this.#ring, 0, chunk.length - size)\n this.#ringAt = 0\n this.#ringLen = size\n return\n }\n const first = Math.min(chunk.length, size - this.#ringAt)\n chunk.copy(this.#ring, this.#ringAt, 0, first)\n if (first < chunk.length) {\n chunk.copy(this.#ring, 0, first)\n }\n this.#ringAt = (this.#ringAt + chunk.length) % size\n this.#ringLen = Math.min(size, this.#ringLen + chunk.length)\n }\n\n #spill(): void {\n this.#spilled = true\n const buffered = Buffer.concat(this.#chunks, this.#chunkBytes)\n this.#chunks = []\n this.#chunkBytes = 0\n this.#queue(async () => {\n await mkdir(this.#paths.dir, { recursive: true, mode: 0o700 })\n this.#handle = await open(this.#paths.raw, 'w', 0o600)\n await this.#handle.write(buffered)\n })\n }\n\n #write(chunk: Buffer): void {\n if (chunk.length === 0) {\n return\n }\n this.#queue(async () => {\n await this.#handle?.write(chunk)\n })\n }\n\n #queue(task: () => Promise<void>): void {\n this.#io = this.#io.then(async () => {\n if (this.#broken) {\n return\n }\n try {\n await task()\n } catch (error) {\n this.#broken = true\n this.#onError(error)\n }\n })\n }\n}\n\nexport class StoredArtifact {\n readonly #paths: ArtifactPaths\n readonly #bytes: number\n readonly #capped: boolean\n readonly #stored: StoredOutput\n\n constructor(paths: ArtifactPaths, info: { bytes: number; capped?: boolean }, stored: StoredOutput) {\n this.#paths = paths\n this.#bytes = info.bytes\n this.#capped = info.capped === true\n this.#stored = stored.artifact !== undefined ? { artifact: stored.artifact } : { output: stored.output ?? '' }\n }\n\n async read(tail?: number): Promise<Buffer> {\n if (tail !== undefined) {\n return this.replay(tail)\n }\n return this.#head()\n }\n\n async replay(max: number): Promise<Buffer> {\n const want = Math.max(0, Math.floor(max))\n if (this.#capped) {\n const ring = await readWhole(this.#paths.tail)\n return ring.subarray(Math.max(0, ring.length - want))\n }\n if (this.#stored.output !== undefined) {\n const all = Buffer.from(this.#stored.output, 'utf8')\n return all.subarray(Math.max(0, all.length - want))\n }\n const size = await stat(this.#paths.raw).then(\n (s) => s.size,\n () => 0,\n )\n return readRange(this.#paths.raw, Math.max(0, size - want), size)\n }\n\n async textView(): Promise<string> {\n const head = await this.#head()\n let text = ttyText(head.toString('utf8'))\n if (this.#capped) {\n const ring = await readWhole(this.#paths.tail)\n const after = this.#bytes - head.length\n const kept = Math.min(after, ring.length)\n if (kept > 0) {\n text += (after > kept ? '\\n' : '') + ttyText(ring.subarray(ring.length - kept).toString('utf8'))\n }\n }\n return text\n }\n\n stored(): StoredOutput {\n return this.#stored\n }\n\n idle(): Promise<void> {\n return Promise.resolve()\n }\n\n async remove(): Promise<void> {\n await rm(this.#paths.raw, { force: true })\n await rm(this.#paths.tail, { force: true })\n }\n\n #head(): Promise<Buffer> {\n return this.#stored.output !== undefined ? Promise.resolve(Buffer.from(this.#stored.output, 'utf8')) : readWhole(this.#paths.raw)\n }\n}\n\nasync function readWhole(path: string): Promise<Buffer> {\n try {\n return await readFile(path)\n } catch (error) {\n if (isMissing(error)) {\n return Buffer.alloc(0)\n }\n throw error\n }\n}\n\nasync function readRange(path: string, start: number, end: number): Promise<Buffer> {\n const length = Math.max(0, end - start)\n if (length === 0) {\n return Buffer.alloc(0)\n }\n let handle: FileHandle\n try {\n handle = await open(path, 'r')\n } catch (error) {\n if (isMissing(error)) {\n return Buffer.alloc(0)\n }\n throw error\n }\n try {\n const out = Buffer.allocUnsafe(length)\n let got = 0\n while (got < length) {\n const { bytesRead } = await handle.read(out, got, length - got, start + got)\n if (bytesRead === 0) {\n break\n }\n got += bytesRead\n }\n return got === length ? out : out.subarray(0, got)\n } finally {\n await handle.close()\n }\n}\n","import xtermHeadless from '@xterm/headless'\nimport type { Terminal } from '@xterm/headless'\n\n// What the terminal shows right now, kept by a headless emulator fed the same bytes as the artifact. A redrawing\n// program flattens into every frame it ever painted; the screen is the only view of it a reader can use.\nexport class ShellScreen {\n #term: Terminal | undefined\n #closing: Promise<void> | undefined\n #final: string | undefined\n\n constructor(cols: number, rows: number) {\n this.#term = new xtermHeadless.Terminal({ cols, rows, scrollback: 0, allowProposedApi: true })\n }\n\n write(data: string): void {\n this.#term?.write(data)\n }\n\n resize(cols: number, rows: number): void {\n try {\n this.#term?.resize(cols, rows)\n } catch {}\n }\n\n async snapshot(): Promise<string> {\n if (this.#closing) {\n await this.#closing\n }\n if (this.#final !== undefined) {\n return this.#final\n }\n const term = this.#term\n if (!term) {\n return ''\n }\n await drained(term)\n return render(term)\n }\n\n // DECCKM as the program last set it, so a cursor key is encoded the way the program expects to read it.\n async applicationCursorKeys(): Promise<boolean> {\n const term = this.#term\n if (!term) {\n return false\n }\n await drained(term)\n return term.modes.applicationCursorKeysMode\n }\n\n // An exited shell keeps its last screen as a string, not an emulator.\n close(): void {\n const term = this.#term\n if (!term || this.#closing) {\n return\n }\n this.#term = undefined\n this.#closing = drained(term).then(() => {\n this.#final = render(term)\n term.dispose()\n })\n }\n}\n\nexport async function renderScreen(raw: string, cols: number, rows: number): Promise<string> {\n const screen = new ShellScreen(cols, rows)\n screen.write(raw)\n screen.close()\n return screen.snapshot()\n}\n\nfunction drained(term: Terminal): Promise<void> {\n return new Promise((resolve) => term.write('', resolve))\n}\n\nfunction render(term: Terminal): string {\n const buffer = term.buffer.active\n const lines: string[] = []\n for (let y = 0; y < term.rows; y++) {\n lines.push(buffer.getLine(buffer.viewportY + y)?.translateToString(true) ?? '')\n }\n while (lines.length > 0 && lines[lines.length - 1] === '') {\n lines.pop()\n }\n return lines.join('\\n')\n}\n","import { randomBytes } from 'node:crypto'\nimport { TTY_REDRAW_CARRY, ttyRedraws, ttyText, type LocalShellSource } from '@workerdeck/core'\nimport {\n SHELL_ATTACH_REPLAY_BYTES,\n SHELL_COLS,\n SHELL_LABEL_MAX,\n SHELL_ROWS,\n type ShellEndReason,\n type ShellInfo,\n type ShellOwner,\n} from '@workerdeck/protocol'\nimport { killProcessTrees, type TreeKillDeps } from './process-tree.ts'\nimport { LiveArtifact } from './shell-artifact.ts'\nimport { renderScreen } from './shell-screen.ts'\nimport type {\n PtyChild,\n SessionShells,\n ShellAttachment,\n ShellEntry,\n ShellErrorContext,\n ShellErrorReporter,\n ShellOutputQuery,\n ShellSink,\n} from './shell-types.ts'\n\nconst NOTIFY_MS = 250\nconst ID_ALPHABET = 'abcdefghijklmnopqrstuvwxyz234567'\nconst ID_CHARS = 12\n\nexport type ChildHooks = { persist: () => void; notify: () => void; exit: () => void }\n\nexport function newShellInfo(state: SessionShells, sessionId: string, command: string, cwd: string, owner: ShellOwner): ShellInfo {\n return {\n id: mintShellId(),\n sessionId,\n ordinal: state.nextOrdinal++,\n command,\n label: shellLabel(command),\n cwd,\n owner,\n status: 'running',\n startedAt: Date.now(),\n bytes: 0,\n cols: SHELL_COLS,\n rows: SHELL_ROWS,\n }\n}\n\nexport function wireChild(entry: ShellEntry, child: PtyChild, artifact: LiveArtifact, tailFlushMs: number, hooks: ChildHooks): void {\n entry.child = child\n entry.pid = child.pid\n child.onData((data) => {\n if (entry.info.status !== 'running') {\n return\n }\n const changed = artifact.append(data)\n entry.info.bytes = artifact.bytes\n entry.screen?.write(data)\n if (!entry.info.interactive) {\n const scanned = (entry.redrawCarry ?? '') + data\n if (ttyRedraws(scanned)) {\n entry.info.interactive = true\n entry.redrawCarry = undefined\n hooks.persist()\n } else {\n entry.redrawCarry = scanned.slice(-TTY_REDRAW_CARRY)\n }\n }\n if (changed) {\n if (artifact.capped && !entry.info.capped) {\n entry.info.capped = true\n entry.tailTimer = setInterval(() => artifact.writeTail(), tailFlushMs)\n entry.tailTimer.unref()\n }\n hooks.persist()\n }\n for (const sink of entry.sinks) {\n try {\n sink.write(data)\n } catch {\n entry.sinks.delete(sink)\n }\n }\n hooks.notify()\n })\n child.onExit(({ exitCode, signal }) => {\n if (entry.info.status !== 'running') {\n return\n }\n if (signal) {\n entry.info.signal = signal\n } else {\n entry.info.exitCode = exitCode\n }\n hooks.exit()\n })\n}\n\nexport function endEntry(entry: ShellEntry, reason: ShellEndReason): void {\n entry.info.status = 'exited'\n entry.info.endedAt = Date.now()\n entry.info.endReason = reason\n delete entry.info.agentWrite\n clearTimeout(entry.clock)\n clearTimeout(entry.notify)\n clearInterval(entry.tailTimer)\n entry.clock = entry.notify = entry.tailTimer = undefined\n entry.child = undefined\n entry.pid = undefined\n if (entry.artifact instanceof LiveArtifact) {\n entry.artifact.close()\n }\n entry.screen?.close()\n for (const sink of entry.sinks) {\n try {\n sink.end(reason)\n } catch {}\n }\n entry.sinks.clear()\n}\n\nexport function fireListeners(entry: ShellEntry, report: ShellErrorReporter): void {\n for (const listener of entry.listeners) {\n try {\n listener()\n } catch (error) {\n report(error, { op: 'listener', sessionId: entry.info.sessionId, shellId: entry.info.id })\n }\n }\n}\n\nexport function scheduleNotify(entry: ShellEntry, fire: (entry: ShellEntry) => void): void {\n if (entry.notify) {\n return\n }\n entry.notify = setTimeout(() => {\n entry.notify = undefined\n if (entry.info.status === 'running') {\n fire(entry)\n }\n }, NOTIFY_MS)\n entry.notify.unref()\n}\n\nexport function killTrees(entries: ShellEntry[], deps: TreeKillDeps, report: ShellErrorReporter): void {\n const live = entries.flatMap((entry) => (entry.pid === undefined ? [] : [{ entry, pid: entry.pid }]))\n if (live.length === 0) {\n return\n }\n const result = killProcessTrees(\n live.map(({ pid }) => pid),\n deps,\n )\n for (const { entry, pid } of live) {\n if (result.unreached.includes(pid)) {\n try {\n entry.child?.kill('SIGKILL')\n } catch {}\n }\n const context: ShellErrorContext = { op: 'kill', sessionId: entry.info.sessionId, shellId: entry.info.id }\n if (!result.scanned) {\n report(new Error('no process table (ps), only the process group was signalled'), context)\n } else if (result.foreign.includes(pid)) {\n report(new Error(`pid ${pid} is no longer this shell's child and was left alone`), context)\n }\n }\n}\n\nexport function applyAgentWrite(entry: ShellEntry, shellId: string, enabled: boolean): boolean {\n if (enabled) {\n if (entry.info.owner !== 'user') {\n throw new Error(`shell ${shellId} was started by the agent, which may already type into it`)\n }\n if (entry.info.status !== 'running') {\n throw new Error(`shell ${shellId} has already ended; there is nothing to grant`)\n }\n }\n if ((entry.info.agentWrite === true) === enabled) {\n return false\n }\n if (enabled) {\n entry.info.agentWrite = true\n } else {\n delete entry.info.agentWrite\n }\n return true\n}\n\nexport async function attachEntry(entry: ShellEntry, sink: ShellSink): Promise<ShellAttachment> {\n const pending: string[] = []\n let live = false\n let ended: string | undefined\n const proxy: ShellSink = {\n write: (data) => {\n if (live) {\n sink.write(data)\n } else {\n pending.push(data)\n }\n },\n end: (reason) => {\n if (live) {\n sink.end(reason)\n } else {\n ended = reason\n }\n },\n }\n if (entry.info.status === 'running') {\n entry.sinks.add(proxy)\n }\n let replay: Buffer\n try {\n replay = await entry.artifact.replay(SHELL_ATTACH_REPLAY_BYTES)\n } catch (error) {\n entry.sinks.delete(proxy)\n throw error\n }\n live = true\n if (ended !== undefined) {\n const reason = ended\n queueMicrotask(() => sink.end(reason))\n }\n return {\n shell: { ...entry.info },\n scrollback: replay.toString('utf8') + pending.join(''),\n detach: () => {\n entry.sinks.delete(proxy)\n },\n }\n}\n\nexport async function readOutput(entry: ShellEntry, query: ShellOutputQuery): Promise<string> {\n if (query.view === 'screen') {\n if (entry.screen) {\n return entry.screen.snapshot()\n }\n const replay = await entry.artifact.replay(SHELL_ATTACH_REPLAY_BYTES)\n return renderScreen(replay.toString('utf8'), entry.info.cols, entry.info.rows)\n }\n if (query.tail === undefined && query.view === 'text') {\n return entry.artifact.textView()\n }\n const raw = await entry.artifact.read(query.tail)\n const text = raw.toString('utf8')\n return query.view === 'raw' ? text : ttyText(text)\n}\n\nexport function waitForChange(entry: ShellEntry | undefined, timeoutMs: number): Promise<void> {\n if (!entry || entry.info.status !== 'running') {\n return Promise.resolve()\n }\n return new Promise((resolve) => {\n const done = () => {\n clearTimeout(timer)\n entry.listeners.delete(done)\n resolve()\n }\n const timer = setTimeout(done, Math.max(0, timeoutMs))\n timer.unref()\n entry.listeners.add(done)\n })\n}\n\nexport function sourceFor(entry: ShellEntry, artifact: LiveArtifact): LocalShellSource {\n return {\n info: () => entry.info,\n text: () => artifact.text(),\n subscribe: (listener) => {\n entry.listeners.add(listener)\n return () => {\n entry.listeners.delete(listener)\n }\n },\n }\n}\n\nfunction mintShellId(): string {\n const bytes = randomBytes(ID_CHARS)\n let id = 'sh_'\n for (let i = 0; i < ID_CHARS; i++) {\n id += ID_ALPHABET[bytes[i]! & 31]\n }\n return id\n}\n\nfunction shellLabel(command: string): string {\n const first = command.split('\\n')[0] ?? ''\n return first.trim().slice(0, SHELL_LABEL_MAX)\n}\n","import { withoutGatewaySecrets } from '@workerdeck/core'\nimport { SHELL_COLS, SHELL_MAX_COLS, SHELL_MAX_ROWS, SHELL_MIN_COLS, SHELL_MIN_ROWS, SHELL_ROWS } from '@workerdeck/protocol'\nimport type { PtyChild, PtyModule, ShellSize } from './shell-types.ts'\n\nconst TERM = 'xterm-256color'\n// macOS drops a session leader's unread pty output ~600ms after it exits unless its session opened /dev/tty; the\n// login shell execs under the same pid with the command as $1, so nothing is re-quoted.\nconst CTTY_WRAPPER = 'true <>/dev/tty 2>/dev/null; exec \"$0\" -c \"$1\"'\n\nlet ptyModule: PtyModule | null | undefined\n\nexport async function loadPty(): Promise<PtyModule | null> {\n if (ptyModule !== undefined) {\n return ptyModule\n }\n try {\n ptyModule = (await import('@lydell/node-pty')) as unknown as PtyModule\n } catch {\n ptyModule = null\n }\n return ptyModule\n}\n\n// A spawn env replaces the inherited one wholesale, so the copy has to be complete; the gateway's own environment is\n// what the operator's terminal would have given the same command.\nexport function shellChildEnv(base: Record<string, string | undefined>): Record<string, string> {\n const env: Record<string, string> = {}\n for (const [key, value] of Object.entries(withoutGatewaySecrets(base))) {\n if (value !== undefined) {\n env[key] = value\n }\n }\n return env\n}\n\nexport function clampSize(size: ShellSize): ShellSize {\n return {\n cols: clamp(size.cols, SHELL_MIN_COLS, SHELL_MAX_COLS),\n rows: clamp(size.rows, SHELL_MIN_ROWS, SHELL_MAX_ROWS),\n }\n}\n\nexport function loginShell(env: Record<string, string | undefined>): string {\n const shell = env.SHELL\n return shell && shell.startsWith('/') ? shell : '/bin/sh'\n}\n\nexport function spawnShellChild(pty: PtyModule, cwd: string, command: string): PtyChild {\n const env = shellChildEnv(process.env)\n env.TERM = TERM\n env.COLORTERM = 'truecolor'\n env.PWD = cwd\n return pty.spawn('/bin/sh', ['-c', CTTY_WRAPPER, loginShell(process.env), command], {\n name: TERM,\n cols: SHELL_COLS,\n rows: SHELL_ROWS,\n cwd,\n env,\n })\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Number.isFinite(value) ? Math.min(max, Math.max(min, Math.trunc(value))) : min\n}\n","import { readdir, readFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { isMissing, writeJsonAtomic } from '../lib/atomic-file.ts'\nimport { artifactPaths, StoredArtifact } from './shell-artifact.ts'\nimport type { SessionShells, ShellEntry, ShellErrorReporter, StoredShellIndex, StoredShellRecord } from './shell-types.ts'\n\nconst INDEX_SUFFIX = '.json'\nconst INDEX_VERSION = 1\n\nexport type ShellIndexDeps = { dir: string | null; generation: string; report: ShellErrorReporter }\n\nexport function freshSession(sessionId: string): SessionShells {\n return { sessionId, nextOrdinal: 1, entries: new Map(), chain: Promise.resolve(), pending: false }\n}\n\nexport function runningIn(state: SessionShells): ShellEntry[] {\n return [...state.entries.values()].filter((entry) => entry.info.status === 'running')\n}\n\nexport function persistIndex(dir: string | null, state: SessionShells, report: ShellErrorReporter): void {\n if (!dir || state.pending) {\n return\n }\n state.pending = true\n state.chain = state.chain\n .then(async () => {\n state.pending = false\n await writeJsonAtomic(indexPath(dir, state.sessionId), serializeIndex(state))\n })\n .catch((error: unknown) => report(error, { op: 'index', sessionId: state.sessionId }))\n}\n\nexport async function readIndex(deps: ShellIndexDeps, sessionId: string): Promise<SessionShells> {\n const { dir, report } = deps\n const state = freshSession(sessionId)\n if (!dir) {\n return state\n }\n const index = await loadIndexFile(dir, sessionId, report)\n if (!index) {\n return state\n }\n state.nextOrdinal = index.nextOrdinal\n if (restoreEntries(state, index, dir, deps.generation)) {\n persistIndex(dir, state, report)\n }\n return state\n}\n\nexport async function indexedSessions(dir: string, report: ShellErrorReporter): Promise<string[]> {\n let names: string[] = []\n try {\n names = await readdir(dir)\n } catch (error) {\n if (!isMissing(error)) {\n report(error, { op: 'index' })\n }\n }\n const ids: string[] = []\n for (const name of names) {\n if (!name.endsWith(INDEX_SUFFIX)) {\n continue\n }\n try {\n ids.push(decodeURIComponent(name.slice(0, -INDEX_SUFFIX.length)))\n } catch {\n continue\n }\n }\n return ids\n}\n\nexport function serializeIndex(state: SessionShells): StoredShellIndex {\n return {\n version: INDEX_VERSION,\n sessionId: state.sessionId,\n nextOrdinal: state.nextOrdinal,\n shells: [...state.entries.values()].map((entry) => ({ ...entry.info, generation: entry.generation, ...entry.artifact.stored() })),\n }\n}\n\nexport function parseIndex(value: unknown): StoredShellIndex {\n const index = value as Partial<StoredShellIndex> | null\n if (!index || index.version !== INDEX_VERSION || typeof index.sessionId !== 'string' || !Array.isArray(index.shells)) {\n throw new Error('unrecognised shell index')\n }\n const shells = index.shells.filter(\n (record): record is StoredShellRecord =>\n typeof record === 'object' && record !== null && typeof (record as StoredShellRecord).id === 'string',\n )\n const nextOrdinal = typeof index.nextOrdinal === 'number' && index.nextOrdinal > 0 ? index.nextOrdinal : 1\n return { version: INDEX_VERSION, sessionId: index.sessionId, nextOrdinal, shells }\n}\n\nfunction indexPath(dir: string, sessionId: string): string {\n return join(dir, `${encodeURIComponent(sessionId)}${INDEX_SUFFIX}`)\n}\n\nasync function loadIndexFile(dir: string, sessionId: string, report: ShellErrorReporter): Promise<StoredShellIndex | undefined> {\n let raw: string\n try {\n raw = await readFile(indexPath(dir, sessionId), 'utf8')\n } catch (error) {\n if (!isMissing(error)) {\n report(error, { op: 'index', sessionId })\n }\n return undefined\n }\n try {\n return parseIndex(JSON.parse(raw))\n } catch (error) {\n report(error, { op: 'index', sessionId })\n return undefined\n }\n}\n\nfunction restoreEntries(state: SessionShells, index: StoredShellIndex, base: string, generation: string): boolean {\n const now = Date.now()\n let dirty = false\n for (const record of index.shells) {\n const { generation: recordGeneration, output, artifact, ...info } = record\n if (info.status === 'running' && recordGeneration !== generation) {\n info.status = 'exited'\n info.endReason = 'server_restarted'\n info.endedAt = now\n delete info.exitCode\n delete info.signal\n dirty = true\n }\n state.entries.set(info.id, {\n info,\n generation: recordGeneration,\n artifact: new StoredArtifact(artifactPaths(base, state.sessionId, info.id), info, { output, artifact }),\n sinks: new Set(),\n listeners: new Set(),\n })\n }\n return dirty\n}\n","import { mkdtempSync } from 'node:fs'\nimport { rm, stat } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport { SHELL_REFUSAL, type Runner } from '@workerdeck/core'\nimport {\n ENGINE_CAPABILITIES,\n SHELL_ARTIFACT_MAX_BYTES,\n SHELL_ARTIFACT_TTL_MS,\n SHELL_INPUT_MAX,\n SHELL_LINGER_MS,\n SHELL_MAX_RUNNING_PER_SESSION,\n SHELL_MAX_RUNNING_TOTAL,\n SHELL_SPILL_BYTES,\n SHELL_TAIL_FLUSH_MS,\n SHELL_TAIL_RING_BYTES,\n type SessionInfo,\n type ShellEndReason,\n} from '@workerdeck/protocol'\nimport { readProcessTable, type TreeKillDeps } from './process-tree.ts'\nimport { artifactPaths, LiveArtifact, type ArtifactLimits } from './shell-artifact.ts'\nimport {\n applyAgentWrite,\n attachEntry,\n endEntry,\n fireListeners,\n killTrees,\n newShellInfo,\n readOutput,\n scheduleNotify,\n sourceFor,\n waitForChange,\n wireChild,\n} from './shell-entry.ts'\nimport { clampSize, loadPty, spawnShellChild } from './shell-env.ts'\nimport { ShellScreen } from './shell-screen.ts'\nimport { indexedSessions, persistIndex, readIndex, runningIn } from './shell-index.ts'\nimport type {\n KillTarget,\n PtyChild,\n PtyModule,\n SessionShells,\n ShellEntry,\n ShellErrorReporter,\n ShellRegistry,\n ShellRegistryOptions,\n ShellSpawned,\n ShellSpawnInput,\n} from './shell-types.ts'\n\nexport { SHELL_REFUSAL }\nexport { createShellDirectory, startShell, type ShellDirectoryDeps } from './shell-directory.ts'\nexport { clampSize, loadPty, loginShell, shellChildEnv } from './shell-env.ts'\nexport type {\n ShellAttachment,\n ShellErrorContext,\n ShellOutputQuery,\n ShellRegistry,\n ShellRegistryOptions,\n ShellSink,\n ShellSize,\n ShellSpawned,\n ShellSpawnInput,\n StoredShellIndex,\n StoredShellRecord,\n} from './shell-types.ts'\n\nconst SWEEP_INTERVAL_MS = 60 * 60_000\n\nexport function shellPermitted(shells: ShellRegistry | null, runner: Runner, operator: boolean): boolean {\n if (shells === null || !operator) {\n return false\n }\n const info = runner.info()\n const capabilities = info.capabilities ?? (info.engine ? ENGINE_CAPABILITIES[info.engine] : undefined)\n return capabilities?.hostCwd === true\n}\n\nexport function createShellRegistry(options: ShellRegistryOptions): ShellRegistry {\n const { generation } = options\n const dir = options.artifactDir\n const base = dir ?? mkdtempSync(join(tmpdir(), 'workerdeck-shells-'))\n const limits: ArtifactLimits = {\n spill: options.spillBytes ?? SHELL_SPILL_BYTES,\n cap: options.artifactMaxBytes ?? SHELL_ARTIFACT_MAX_BYTES,\n ring: options.tailRingBytes ?? SHELL_TAIL_RING_BYTES,\n }\n const tailFlushMs = options.tailFlushMs ?? SHELL_TAIL_FLUSH_MS\n const ttlMs = options.artifactTtlMs ?? SHELL_ARTIFACT_TTL_MS\n const perSession = options.maxRunningPerSession ?? SHELL_MAX_RUNNING_PER_SESSION\n const total = options.maxRunningTotal ?? SHELL_MAX_RUNNING_TOTAL\n const sweepIntervalMs = options.sweepIntervalMs ?? SWEEP_INTERVAL_MS\n const sessions = new Map<string, SessionShells>()\n const loading = new Map<string, Promise<SessionShells>>()\n let sweeper: NodeJS.Timeout | undefined\n let stopped = false\n\n const report: ShellErrorReporter = (error, context) => options.onError?.(error, context)\n const treeDeps: TreeKillDeps = {\n table: options.processTable ?? readProcessTable,\n signal: (pid, name) => void process.kill(pid, name),\n self: process.pid,\n }\n\n const find = (sessionId: string, id: string): ShellEntry | undefined => sessions.get(sessionId)?.entries.get(id)\n const located = (sessionId: string, shellId: string): KillTarget | undefined => {\n const state = sessions.get(sessionId)\n const entry = state?.entries.get(shellId)\n return state && entry ? { state, entry } : undefined\n }\n const runningAll = (): ShellEntry[] => [...sessions.values()].flatMap(runningIn)\n const persist = (state: SessionShells): void => persistIndex(dir, state, report)\n const fire = (entry: ShellEntry): void => fireListeners(entry, report)\n\n const load = (sessionId: string): Promise<SessionShells> => {\n const held = sessions.get(sessionId)\n if (held) {\n return Promise.resolve(held)\n }\n let inflight = loading.get(sessionId)\n if (!inflight) {\n inflight = readIndex({ dir, generation, report }, sessionId).then((state) => {\n sessions.set(sessionId, state)\n loading.delete(sessionId)\n return state\n })\n loading.set(sessionId, inflight)\n }\n return inflight\n }\n\n const settle = (state: SessionShells, entry: ShellEntry, reason: ShellEndReason): void => {\n if (entry.info.status !== 'running') {\n return\n }\n endEntry(entry, reason)\n persist(state)\n fire(entry)\n }\n\n const killEntries = (targets: KillTarget[], reason: ShellEndReason): number => {\n const running = targets.filter(({ entry }) => entry.info.status === 'running')\n killTrees(\n running.map(({ entry }) => entry),\n treeDeps,\n report,\n )\n for (const { state, entry } of running) {\n settle(state, entry, reason)\n }\n return running.length\n }\n\n const admit = async (runner: Runner): Promise<{ state: SessionShells; cwd: string; pty: PtyModule }> => {\n if (stopped) {\n throw new Error('the gateway is shutting down')\n }\n const state = await load(runner.id)\n const pty = await loadPty()\n if (!pty) {\n throw new Error(SHELL_REFUSAL)\n }\n const cwd = runner.info().cwd\n const dirStat = await stat(cwd).catch(() => undefined)\n if (!dirStat?.isDirectory()) {\n throw new Error(`the session's cwd is not a directory: ${cwd}`)\n }\n const inSession = runningIn(state).length\n if (inSession >= perSession) {\n throw new Error(`this session already has ${inSession} shells running (the limit is ${perSession})`)\n }\n const overall = runningAll().length\n if (overall >= total) {\n throw new Error(`the gateway already has ${overall} shells running (the limit is ${total})`)\n }\n return { state, cwd, pty }\n }\n\n const spawn = async ({ runner, command, owner }: ShellSpawnInput): Promise<ShellSpawned> => {\n const { state, cwd, pty } = await admit(runner)\n const info = newShellInfo(state, runner.id, command, cwd, owner)\n const artifact = new LiveArtifact(artifactPaths(base, info.sessionId, info.id), limits, (error) =>\n report(error, { op: 'artifact', sessionId: info.sessionId, shellId: info.id }),\n )\n const entry: ShellEntry = { info, generation, artifact, sinks: new Set(), listeners: new Set() }\n entry.screen = new ShellScreen(info.cols, info.rows)\n state.entries.set(info.id, entry)\n let child: PtyChild\n try {\n child = spawnShellChild(pty, cwd, command)\n } catch (error) {\n settle(state, entry, 'spawn_failed')\n throw error instanceof Error ? error : new Error('failed to start the shell')\n }\n wireChild(entry, child, artifact, tailFlushMs, {\n persist: () => persist(state),\n notify: () => scheduleNotify(entry, fire),\n exit: () => settle(state, entry, 'exit'),\n })\n if (options.timeoutMs !== undefined && options.timeoutMs > 0) {\n entry.clock = setTimeout(() => killEntries([{ state, entry }], 'timeout'), options.timeoutMs)\n entry.clock.unref()\n }\n persist(state)\n return { shell: { ...info }, source: sourceFor(entry, artifact) }\n }\n\n const sweep = async (): Promise<void> => {\n const now = Date.now()\n for (const state of sessions.values()) {\n let dirty = false\n for (const entry of state.entries.values()) {\n const { status, endedAt } = entry.info\n if (status !== 'exited' || endedAt === undefined || now - endedAt < ttlMs) {\n continue\n }\n state.entries.delete(entry.info.id)\n dirty = true\n try {\n await entry.artifact.remove()\n } catch (error) {\n report(error, { op: 'sweep', sessionId: state.sessionId, shellId: entry.info.id })\n }\n }\n if (dirty) {\n persist(state)\n }\n }\n }\n\n const hydrate = async (): Promise<void> => {\n if (dir) {\n for (const sessionId of await indexedSessions(dir, report)) {\n await load(sessionId)\n }\n }\n await sweep()\n if (!sweeper && !stopped) {\n sweeper = setInterval(() => void sweep(), sweepIntervalMs)\n sweeper.unref()\n }\n }\n\n const existing = (sessionId: string, shellId: string): ShellEntry => {\n const entry = find(sessionId, shellId)\n if (!entry) {\n throw new Error('unknown shell')\n }\n return entry\n }\n\n return {\n spawn,\n get: (sessionId, shellId) => {\n const entry = find(sessionId, shellId)\n return entry ? { ...entry.info } : undefined\n },\n list: (sessionId) => {\n const state = sessions.get(sessionId)\n if (!state) {\n return []\n }\n return [...state.entries.values()].map((entry) => ({ ...entry.info })).sort((a, b) => b.ordinal - a.ordinal)\n },\n running: () => runningAll().map((entry) => ({ ...entry.info })),\n kill: (sessionId, shellId, reason = 'killed') => {\n const target = located(sessionId, shellId)\n if (!target) {\n return undefined\n }\n killEntries([target], reason)\n return { ...target.entry.info }\n },\n setAgentWrite: (sessionId, shellId, enabled) => {\n const target = located(sessionId, shellId)\n if (!target) {\n return undefined\n }\n if (applyAgentWrite(target.entry, shellId, enabled)) {\n persist(target.state)\n fire(target.entry)\n }\n return { ...target.entry.info }\n },\n killAll: (reason) => {\n stopped = true\n if (sweeper) {\n clearInterval(sweeper)\n sweeper = undefined\n }\n return killEntries(\n [...sessions.values()].flatMap((state) => runningIn(state).map((entry) => ({ state, entry }))),\n reason,\n )\n },\n killAllSync: () => {\n killTrees(runningAll(), treeDeps, report)\n },\n attach: async (sessionId, shellId, sink) => attachEntry(existing(sessionId, shellId), sink),\n write: (sessionId, shellId, data) => {\n const entry = existing(sessionId, shellId)\n if (typeof data !== 'string' || data.length > SHELL_INPUT_MAX) {\n throw new Error(`shell input must be a string of at most ${SHELL_INPUT_MAX} characters`)\n }\n if (!entry.child) {\n throw new Error('the shell has exited')\n }\n entry.child.write(data)\n },\n resize: (sessionId, shellId, size) => {\n const entry = existing(sessionId, shellId)\n const next = clampSize(size)\n if (entry.child) {\n try {\n entry.child.resize(next.cols, next.rows)\n } catch {}\n entry.info.cols = next.cols\n entry.info.rows = next.rows\n entry.screen?.resize(next.cols, next.rows)\n }\n return next\n },\n output: async (sessionId, shellId, query) => {\n const entry = find(sessionId, shellId)\n return entry ? readOutput(entry, query) : undefined\n },\n applicationCursorKeys: (sessionId, shellId) => find(sessionId, shellId)?.screen?.applicationCursorKeys() ?? Promise.resolve(false),\n changed: (sessionId, shellId, timeoutMs) => waitForChange(find(sessionId, shellId), timeoutMs),\n hydrate,\n sweep,\n flush: async () => {\n const states = [...sessions.values()]\n await Promise.all(states.flatMap((state) => [...state.entries.values()].map((entry) => entry.artifact.idle())))\n await Promise.all(states.map((state) => state.chain))\n if (!dir && stopped) {\n await rm(base, { recursive: true, force: true }).catch(() => {})\n }\n },\n decorate: (info) => decorateSession(info, sessions.get(info.id)),\n watch: (runner) =>\n runner.subscribe((event) => {\n if (event.type === 'session_closed' || (event.type === 'status_changed' && event.status === 'parked')) {\n const state = sessions.get(runner.id)\n if (state) {\n killEntries(\n runningIn(state).map((entry) => ({ state, entry })),\n 'killed',\n )\n }\n }\n }, runner.info().lastSeq),\n }\n}\n\nfunction decorateSession(info: SessionInfo, state: SessionShells | undefined): SessionInfo {\n if (!state) {\n return info\n }\n const now = Date.now()\n const shells = [...state.entries.values()]\n .filter((entry) => {\n const { status, exitCode, endedAt } = entry.info\n return (\n status === 'running' || (typeof exitCode === 'number' && exitCode !== 0 && endedAt !== undefined && now - endedAt < SHELL_LINGER_MS)\n )\n })\n .map((entry) => ({ ...entry.info }))\n return shells.length > 0 ? { ...info, shells } : info\n}\n","import type { IncomingMessage } from 'node:http'\nimport type { WebSocket } from 'ws'\nimport { isSlashCommand, type Runner } from '@workerdeck/core'\nimport { PROTOCOL_VERSION, SHELL_COMMAND_MAX, type ClientFrame, type ServerFrame } from '@workerdeck/protocol'\nimport type { ServerContext } from '../context.ts'\nimport { permissionDecision, refusePermissionMode } from '../lib/permissions.ts'\nimport { engineOf } from '../lib/profile-env.ts'\nimport { mentionsFor } from '../services/peers.ts'\nimport { sleepRunner } from './sleep.ts'\nimport { takesLocalCommands } from '../services/shell-directory.ts'\nimport { shellPermitted, SHELL_REFUSAL, startShell, type ShellRegistry, type ShellSink, type ShellSize } from '../services/shells.ts'\n\n// What the upgrade established about the principal; computed once there so the attach never re-authenticates.\nexport type AttachAccess = { operator: boolean }\n\n// One per socket: its send path, its outbound backlog, and the shells it is attached to (shell id to the registry's detach).\ntype Client = { send: (frame: ServerFrame) => void; open: () => boolean; buffered: () => number; shells: Map<string, () => void> }\n\nexport const SHELL_SOCKET_BUFFERED_MAX = 4 * 1024 * 1024\nexport const SHELL_DETACHED_BACKPRESSURE = 'backpressure'\nexport const SESSION_SOCKET_BUFFERED_MAX = 16 * 1024 * 1024\nexport const SESSION_SOCKET_BACKPRESSURE_CODE = 1013\n\nexport function attachClient(ctx: ServerContext, ws: WebSocket, runner: Runner, req: IncomingMessage, access: AttachAccess): void {\n const { bridge, parking } = ctx\n const url = new URL(req.url ?? '/', 'http://internal')\n const afterSeq = Number(url.searchParams.get('afterSeq') ?? '0') || 0\n const truncateResults = url.searchParams.get('truncateResults') === '1'\n const imageRefs = url.searchParams.get('imageRefs') === '1'\n\n const send = (frame: ServerFrame): void => {\n if (ws.readyState === ws.OPEN) {\n ws.send(JSON.stringify(frame))\n }\n }\n const client: Client = { send, open: () => ws.readyState === ws.OPEN, buffered: () => ws.bufferedAmount, shells: new Map() }\n\n send({\n type: 'attached',\n protocolVersion: PROTOCOL_VERSION,\n session: ctx.projects.withProject(runner.info()),\n replayingFrom: afterSeq,\n ...(shellPermitted(ctx.shells, runner, access.operator) ? { shell: true } : {}),\n ...(ctx.pricingOverrides ? { pricingOverrides: ctx.pricingOverrides } : {}),\n })\n let live = false\n const unsubscribe = runner.subscribe(\n (event) => {\n // Replay is exempt: it is bounded by the log, and capping it would refuse every attach to a long session.\n if (live && ws.bufferedAmount > SESSION_SOCKET_BUFFERED_MAX) {\n ws.close(SESSION_SOCKET_BACKPRESSURE_CODE, 'backpressure')\n return\n }\n send({ type: 'event', event })\n },\n afterSeq,\n { coalesceReplay: true, truncateResults, imageRefs },\n )\n live = true\n const detachBridge = bridge.attach(runner.id, send)\n\n // After the replay is wired, so a fresh reading arrives as a live event behind the history rather than racing it.\n // The replay faithfully re-installs whatever this session last heard, which on an idle session can be days old,\n // and until now nothing in an attach asked for a newer one. Throttled inside the runner; failures are silent by\n // design (the control request is experimental, and a missing usage reading is not an attach failure).\n void runner.refreshUsage?.().catch(() => {})\n\n ws.on('message', (data: Buffer) => {\n let frame: ClientFrame\n try {\n frame = JSON.parse(data.toString('utf8')) as ClientFrame\n } catch {\n send({ type: 'protocol_error', message: 'invalid JSON frame' })\n return\n }\n handleCommand(ctx, frame, runner, access, client).catch((error: unknown) => {\n send({\n type: 'protocol_error',\n message: error instanceof Error ? error.message : 'command failed',\n })\n })\n })\n ws.on('close', () => {\n // Detach only. The registry's watch(runner) owns the close and park kills; a socket going away must not end a shell.\n detachShells(client)\n unsubscribe()\n detachBridge()\n parking.onDetach(runner.id)\n ctx.engineSleep.onDetach(runner.id)\n })\n}\n\nasync function handleCommand(ctx: ServerContext, frame: ClientFrame, runner: Runner, access: AttachAccess, client: Client): Promise<void> {\n const { attachmentStore, bridge } = ctx\n switch (frame.type) {\n case 'user_message': {\n // The one place `mentions` is ever set: this frame is a person typing. A slash command is\n // matched on the whole message by the CLI, so nothing may be appended to one, and a failure\n // to resolve is silent - a hint must never lose the text it was a hint about.\n const mentions = ctx.peers && !isSlashCommand(frame.text) ? await mentionsFor(ctx.peers, runner.id, frame.text).catch(() => []) : []\n const options = mentions.length > 0 ? { mentions } : undefined\n if (!frame.attachmentIds?.length) {\n runner.sendMessage(frame.text, undefined, options)\n return\n }\n const resolved = attachmentStore.resolve(runner.id, frame.attachmentIds)\n if (!resolved.ok) {\n throw new Error(`unknown attachment(s): ${resolved.missing.join(', ')}`)\n }\n runner.sendMessage(frame.text, resolved.attachments, options)\n return\n }\n case 'permission_decision': {\n runner.resolvePermission(frame.requestId, permissionDecision(frame))\n return\n }\n case 'interrupt': {\n await runner.interrupt()\n return\n }\n case 'sleep': {\n await sleepRunner(runner)\n return\n }\n case 'background_task': {\n if (!runner.backgroundTask) {\n throw new Error(`the ${engineOf(runner.info())} engine cannot move a task to the background`)\n }\n await runner.backgroundTask(frame.toolUseId)\n return\n }\n case 'clear_context': {\n if (!runner.clearContext) {\n throw new Error(`the ${engineOf(runner.info())} engine cannot clear a conversation`)\n }\n await runner.clearContext()\n return\n }\n case 'set_permission_mode': {\n const refused = refusePermissionMode(frame.mode, { operator: access.operator, disableBypass: ctx.options.disableBypassPermissions })\n if (refused) {\n throw new Error(refused)\n }\n await runner.setPermissionMode(frame.mode)\n return\n }\n case 'set_model': {\n await runner.setModel(frame.model)\n return\n }\n case 'set_effort': {\n if (!runner.setEffort) {\n throw new Error(`the ${engineOf(runner.info())} engine cannot change its reasoning effort`)\n }\n if (frame.effort !== undefined && typeof frame.effort !== 'string') {\n throw new Error('effort must be a string')\n }\n await runner.setEffort(frame.effort)\n return\n }\n case 'tool_call_result': {\n bridge.resolve(runner.id, frame.executionId, { output: frame.output, logs: frame.logs })\n return\n }\n case 'tool_call_error': {\n bridge.resolve(runner.id, frame.executionId, {\n reason: frame.reason,\n error: frame.error,\n logs: frame.logs,\n })\n return\n }\n case 'shell_command': {\n const shells = permittedShells(ctx, runner, access)\n if (typeof frame.command !== 'string' || frame.command.includes('\\0')) {\n throw new Error('shell command must be a string')\n }\n if (frame.command.length > SHELL_COMMAND_MAX) {\n throw new Error(`shell command exceeds ${SHELL_COMMAND_MAX} characters`)\n }\n if (frame.command.trim() === '') {\n throw new Error('shell command is empty')\n }\n if (!takesLocalCommands(runner)) {\n throw new Error(`the ${engineOf(runner.info())} engine cannot take shell output`)\n }\n await startShell(shells, { runner, command: frame.command, owner: 'user' })\n return\n }\n case 'shell_attach': {\n await attachShell(permittedShells(ctx, runner, access), client, runner.id, frame.shellId, { cols: frame.cols, rows: frame.rows })\n return\n }\n case 'shell_input': {\n permittedShells(ctx, runner, access).write(runner.id, frame.shellId, frame.data)\n return\n }\n case 'shell_resize': {\n permittedShells(ctx, runner, access).resize(runner.id, frame.shellId, { cols: frame.cols, rows: frame.rows })\n return\n }\n case 'shell_detach': {\n detachShell(client, frame.shellId)\n return\n }\n case 'close': {\n runner.close('client')\n return\n }\n default: {\n throw new Error(`unknown command: ${(frame as { type?: string }).type}`)\n }\n }\n}\n\nfunction permittedShells(ctx: ServerContext, runner: Runner, access: AttachAccess): ShellRegistry {\n if (ctx.shells === null || !shellPermitted(ctx.shells, runner, access.operator)) {\n throw new Error(SHELL_REFUSAL)\n }\n return ctx.shells\n}\n\nasync function attachShell(shells: ShellRegistry, client: Client, sessionId: string, shellId: string, size: ShellSize): Promise<void> {\n shells.resize(sessionId, shellId, size)\n let detach: (() => void) | undefined\n const drop = (reason: string): void => {\n if (detach === undefined || client.shells.get(shellId) !== detach) {\n return\n }\n client.shells.delete(shellId)\n detach()\n client.send({ type: 'shell_detached', shellId, reason })\n }\n const sink: ShellSink = {\n write: (data) => {\n if (client.buffered() > SHELL_SOCKET_BUFFERED_MAX) {\n drop(SHELL_DETACHED_BACKPRESSURE)\n return\n }\n client.send({ type: 'shell_output', shellId, data })\n },\n end: drop,\n }\n const attached = await shells.attach(sessionId, shellId, sink)\n if (!client.open()) {\n attached.detach()\n return\n }\n detachShell(client, shellId)\n if (attached.shell.status === 'running') {\n detach = attached.detach\n client.shells.set(shellId, detach)\n }\n const { shell, scrollback } = attached\n client.send({ type: 'shell_attached', shellId, shell, cols: shell.cols, rows: shell.rows, scrollback })\n}\n\nfunction detachShell(client: Client, shellId: string): void {\n client.shells.get(shellId)?.()\n client.shells.delete(shellId)\n}\n\nfunction detachShells(client: Client): void {\n for (const detach of client.shells.values()) {\n detach()\n }\n client.shells.clear()\n}\n","import type { IncomingMessage } from 'node:http'\nimport type { Duplex } from 'node:stream'\nimport type { WebSocketServer } from 'ws'\nimport type { ServerContext } from '../context.ts'\nimport { refuseUpgrade } from '../lib/http.ts'\nimport { parseSessionRoute } from '../lib/parse-route.ts'\nimport { sessionInfoOf } from './session-lookup.ts'\nimport { attachClient } from './ws.ts'\n\n// The scope check runs on what is already known before the wake, because waking rebuilds a runner and reconnects\n// MCP, which is not for someone about to get a 404; and again on the live runner, which is the one being attached.\nexport async function upgradeSession(\n ctx: ServerContext,\n wss: WebSocketServer,\n req: IncomingMessage,\n socket: Duplex,\n head: Buffer,\n): Promise<void> {\n const { auth, parking } = ctx\n const route = parseSessionRoute(ctx.basePath, req.url ?? '/')\n if (route?.kind !== 'ws') {\n socket.destroy()\n return\n }\n const authCtx = await auth.authenticate(req)\n if (!authCtx.ok) {\n refuseUpgrade(socket, '401 Unauthorized')\n return\n }\n const known = await sessionInfoOf(ctx, route.id)\n if (known && !auth.canSee(authCtx, known)) {\n refuseUpgrade(socket, '404 Not Found')\n return\n }\n const runner = await parking.ensureLive(route.id).catch(() => undefined)\n if (!runner || !auth.canSee(authCtx, runner.info())) {\n refuseUpgrade(socket, '404 Not Found')\n return\n }\n wss.handleUpgrade(req, socket, head, (ws) => {\n attachClient(ctx, ws, runner, req, { operator: auth.isOperator(authCtx) })\n })\n}\n","import { createHash } from 'node:crypto'\nimport { arch, homedir, hostname, platform } from 'node:os'\n\nlet cached: string | undefined\n\n// An opaque fingerprint of the machine this process runs on. A client that computes the same\n// string for itself is on the same box as the gateway, which is what lets it open the gateway's\n// paths natively instead of proxying them over `/fs`. Hashed so the answer carries no hostname\n// or home directory, and cached because none of its inputs move within a process.\n//\n// `apps/vscode/src/machine.ts` recomputes this byte for byte. The two must be changed together:\n// a drift only shows up as \"local files stopped opening natively\", never as a failure.\nexport function machineId(): string {\n cached ??= createHash('sha256').update([hostname(), platform(), arch(), homedir()].join('\\0')).digest('hex').slice(0, 32)\n return cached\n}\n","import { randomUUID } from 'node:crypto'\nimport {\n AGENT_SLEEP_AFTER_MS_DEFAULT,\n agentRef,\n type AgentConfig,\n type AgentInfo,\n type SessionInfo,\n type UpdateAgentRequest,\n} from '@workerdeck/protocol'\nimport type { AgentStore, StoredAgent } from './agent-store.ts'\n\nexport type AgentServiceOptions = {\n store: AgentStore\n basePath: string\n avatars?: boolean\n sleepAfterMs?: number\n now?: () => number\n}\n\nexport type AgentRefusal = { status: number; error: string }\n\nexport type RetireOutcome = { retired: StoredAgent[]; released: StoredAgent[] }\n\nconst NAMES = [\n 'Atlas',\n 'Juno',\n 'Pip',\n 'Rook',\n 'Marlow',\n 'Orbit',\n 'Fern',\n 'Quill',\n 'Sable',\n 'Wren',\n 'Ember',\n 'Moss',\n 'Nova',\n 'Otto',\n 'Pike',\n 'Rune',\n 'Sage',\n 'Tansy',\n 'Vale',\n 'Yarrow',\n 'Basil',\n 'Cedar',\n 'Dune',\n 'Flint',\n 'Hazel',\n 'Iris',\n 'Kestrel',\n 'Lark',\n 'Maple',\n 'Nettle',\n 'Onyx',\n 'Piper',\n 'Reed',\n 'Sorrel',\n 'Thistle',\n 'Umber',\n 'Willow',\n 'Zephyr',\n]\nconst MAX_NAME = 64\nconst MAX_BRIEF = 16_000\nconst CONFIG_KEYS: readonly (keyof AgentConfig)[] = [\n 'cwd',\n 'profile',\n 'model',\n 'reasoningEffort',\n 'permissionMode',\n 'brief',\n 'agentContextReset',\n 'sleepAfterMs',\n]\n\nexport class AgentService {\n #store: AgentStore\n #basePath: string\n #avatars: boolean\n #sleepAfterMs: number\n #now: () => number\n #agents = new Map<string, StoredAgent>()\n\n constructor(options: AgentServiceOptions) {\n this.#store = options.store\n this.#basePath = options.basePath\n this.#avatars = options.avatars ?? false\n this.#sleepAfterMs = options.sleepAfterMs ?? AGENT_SLEEP_AFTER_MS_DEFAULT\n this.#now = options.now ?? Date.now\n }\n\n async hydrate(): Promise<void> {\n this.#agents = new Map((await this.#store.list()).map((agent) => [agent.id, agent]))\n }\n\n list(): AgentInfo[] {\n return [...this.#agents.values()].map((agent) => this.public(agent))\n }\n\n get(id: string): StoredAgent | undefined {\n return this.#agents.get(id)\n }\n\n bySession(sessionId: string): StoredAgent | undefined {\n for (const agent of this.#agents.values()) {\n if (agent.sessionId === sessionId) {\n return agent\n }\n }\n return undefined\n }\n\n decorate(info: SessionInfo): SessionInfo {\n const agent = this.bySession(info.id)\n if (!agent) {\n return info\n }\n const leadName = agent.lead === undefined ? undefined : this.#agents.get(agent.lead)?.name\n return { ...info, agent: agentRef(this.public(agent), { leadName, leads: this.hasMembers(agent.id) }) }\n }\n\n briefFor(sessionId: string | undefined): string | undefined {\n const brief = sessionId === undefined ? undefined : this.bySession(sessionId)?.config.brief?.trim()\n return brief || undefined\n }\n\n sleepAfterFor(sessionId: string): number | undefined {\n const agent = this.bySession(sessionId)\n return agent ? (agent.config.sleepAfterMs ?? this.#sleepAfterMs) : undefined\n }\n\n public(agent: StoredAgent): AgentInfo {\n const { avatarSeed: _seed, avatarRecipe: _recipe, avatar: _avatar, ...info } = agent\n return this.#avatars ? { ...info, avatar: `${this.#basePath}/agents/${agent.id}/avatar.png` } : info\n }\n\n draft(input: { name?: unknown; config?: unknown; lead?: unknown }): StoredAgent | AgentRefusal {\n const config = readConfig(input.config)\n if ('error' in config) {\n return config\n }\n const name = input.name === undefined ? this.#suggestName() : readName(input.name)\n if (typeof name !== 'string') {\n return name\n }\n const id = randomUUID()\n const at = this.#now()\n const agent: StoredAgent = {\n id,\n name,\n createdAt: at,\n updatedAt: at,\n avatarSeed: id,\n pastSessions: [],\n config,\n }\n if (input.lead !== undefined && input.lead !== null) {\n const refused =\n typeof input.lead === 'string' ? this.leadRefusal(agent, input.lead) : { status: 400, error: 'lead must be an agent id' }\n if (refused) {\n return refused\n }\n agent.lead = input.lead as string\n }\n return agent\n }\n\n async save(agent: StoredAgent): Promise<StoredAgent> {\n const stored = { ...agent, updatedAt: this.#now() }\n await this.#store.save(stored)\n this.#agents.set(stored.id, stored)\n return stored\n }\n\n async bind(agent: StoredAgent, sessionId: string): Promise<StoredAgent> {\n const past =\n agent.sessionId !== undefined && agent.sessionId !== sessionId ? [...agent.pastSessions, agent.sessionId] : agent.pastSessions\n return this.save({ ...agent, sessionId, pastSessions: past })\n }\n\n hasMembers(id: string): boolean {\n for (const agent of this.#agents.values()) {\n if (agent.lead === id) {\n return true\n }\n }\n return false\n }\n\n members(id: string): StoredAgent[] {\n return [...this.#agents.values()].filter((agent) => agent.lead === id).sort((a, b) => (a.order ?? 0) - (b.order ?? 0))\n }\n\n // Teams are one level deep: a lead cannot join a team and a member cannot lead one.\n leadRefusal(mover: StoredAgent, leadId: string): AgentRefusal | null {\n if (leadId === mover.id) {\n return { status: 409, error: 'an agent cannot lead its own team' }\n }\n const lead = this.#agents.get(leadId)\n if (!lead) {\n return { status: 404, error: `no such agent: ${leadId}` }\n }\n if (lead.lead !== undefined) {\n return { status: 409, error: `${lead.name} is a member of a team; teams are one level deep` }\n }\n if (this.hasMembers(mover.id)) {\n return { status: 409, error: `${mover.name} leads a team; teams are one level deep` }\n }\n return null\n }\n\n async update(id: string, patch: UpdateAgentRequest): Promise<StoredAgent | AgentRefusal> {\n const agent = this.#agents.get(id)\n if (!agent) {\n return { status: 404, error: `no such agent: ${id}` }\n }\n const next: StoredAgent = { ...agent }\n if (patch.name !== undefined) {\n const name = readName(patch.name)\n if (typeof name !== 'string') {\n return name\n }\n next.name = name\n }\n if (patch.config !== undefined) {\n if (!isRecord(patch.config)) {\n return { status: 400, error: 'config must be an object' }\n }\n const config = readConfig({ ...agent.config, ...patch.config })\n if ('error' in config) {\n return config\n }\n next.config = config\n }\n if (patch.lead === null) {\n delete next.lead\n } else if (patch.lead !== undefined) {\n if (typeof patch.lead !== 'string') {\n return { status: 400, error: 'lead must be an agent id or null' }\n }\n const refused = this.leadRefusal(agent, patch.lead)\n if (refused) {\n return refused\n }\n next.lead = patch.lead\n }\n if (patch.order !== undefined) {\n if (typeof patch.order !== 'number' || !Number.isFinite(patch.order)) {\n return { status: 400, error: 'order must be a number' }\n }\n next.order = patch.order\n }\n return this.save(next)\n }\n\n async retire(id: string, members: 'release' | 'retire'): Promise<RetireOutcome | AgentRefusal> {\n const agent = this.#agents.get(id)\n if (!agent) {\n return { status: 404, error: `no such agent: ${id}` }\n }\n const crew = this.members(id)\n const retired = [agent, ...(members === 'retire' ? crew : [])]\n const released: StoredAgent[] = []\n if (members === 'release') {\n for (const member of crew) {\n const { lead: _lead, ...rest } = member\n released.push(await this.save(rest))\n }\n }\n for (const gone of retired) {\n await this.#store.delete(gone.id)\n this.#agents.delete(gone.id)\n }\n return { retired, released }\n }\n\n #suggestName(): string {\n const taken = new Set([...this.#agents.values()].map((agent) => agent.name.toLowerCase()))\n const free = NAMES.find((name) => !taken.has(name.toLowerCase()))\n if (free) {\n return free\n }\n for (let n = 2; ; n++) {\n const name = `${NAMES[n % NAMES.length]} ${n}`\n if (!taken.has(name.toLowerCase())) {\n return name\n }\n }\n }\n}\n\nexport function isAgentRefusal(value: unknown): value is AgentRefusal {\n return isRecord(value) && typeof value.status === 'number' && typeof value.error === 'string'\n}\n\nfunction readName(value: unknown): string | AgentRefusal {\n if (typeof value !== 'string' || value.trim() === '') {\n return { status: 400, error: 'name must be a non-empty string' }\n }\n const name = value.trim()\n return name.length > MAX_NAME ? { status: 400, error: `name is longer than ${MAX_NAME} characters` } : name\n}\n\nfunction readConfig(value: unknown): AgentConfig | AgentRefusal {\n if (value === undefined) {\n return {}\n }\n if (!isRecord(value)) {\n return { status: 400, error: 'config must be an object' }\n }\n const config: Record<string, unknown> = {}\n for (const key of CONFIG_KEYS) {\n if (value[key] !== undefined) {\n config[key] = value[key]\n }\n }\n for (const key of ['cwd', 'profile', 'model', 'reasoningEffort', 'permissionMode', 'brief'] as const) {\n if (config[key] !== undefined && typeof config[key] !== 'string') {\n return { status: 400, error: `config.${key} must be a string` }\n }\n }\n if (config.agentContextReset !== undefined && typeof config.agentContextReset !== 'boolean') {\n return { status: 400, error: 'config.agentContextReset must be a boolean' }\n }\n const sleep = config.sleepAfterMs\n if (sleep !== undefined && (typeof sleep !== 'number' || !Number.isFinite(sleep) || sleep < 0)) {\n return { status: 400, error: 'config.sleepAfterMs must be a non-negative number' }\n }\n if (typeof config.brief === 'string' && config.brief.length > MAX_BRIEF) {\n return { status: 400, error: `config.brief is longer than ${MAX_BRIEF} characters` }\n }\n return config as AgentConfig\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","import type { AiSdkRunnerConfig, CodexRunnerConfig, SessionRunnerConfig } from '@workerdeck/core'\nimport type { CreateSessionRequest } from '@workerdeck/protocol'\n\ntype HostOnlyKey = Exclude<keyof SessionRunnerConfig | keyof CodexRunnerConfig | keyof AiSdkRunnerConfig, keyof CreateSessionRequest>\n\n// Every runner-config key that is not on the wire type. Typed as a record over that difference so a host-only field\n// added to any engine's config without an entry here fails typecheck, as does an entry since promoted onto\n// CreateSessionRequest. `durable` keys survive into a stored session record; `transient` ones are rederived on rebuild.\nconst HOST_ONLY_KEY_TABLE: Record<HostOnlyKey, 'durable' | 'transient'> = {\n epoch: 'durable',\n pricing: 'transient',\n queryFn: 'transient',\n env: 'transient',\n pathToClaudeCodeExecutable: 'durable',\n extraOptions: 'transient',\n instructions: 'transient',\n defaultApprovalTimeoutMs: 'durable',\n backfillHistory: 'durable',\n historyFn: 'transient',\n sessionInfoFn: 'transient',\n peers: 'transient',\n contextReset: 'transient',\n shells: 'transient',\n shellAgentWrite: 'transient',\n createdByOperator: 'durable',\n fallbackTitle: 'transient',\n startAsleep: 'transient',\n effortDefaults: 'transient',\n connectFn: 'transient',\n codexHome: 'durable',\n codexPathOverride: 'durable',\n languageModel: 'transient',\n tools: 'transient',\n maxSteps: 'durable',\n executor: 'transient',\n executableTools: 'transient',\n vfs: 'transient',\n executionLimits: 'durable',\n executionBackend: 'transient',\n toolTitles: 'transient',\n shouldApprove: 'transient',\n resolveModel: 'transient',\n contextWindow: 'transient',\n reportMcpServers: 'transient',\n onClose: 'transient',\n restore: 'transient',\n}\n\nexport const HOST_ONLY_KEYS: ReadonlySet<string> = new Set(Object.keys(HOST_ONLY_KEY_TABLE))\n\nexport const DURABLE_HOST_KEYS: readonly string[] = Object.entries(HOST_ONLY_KEY_TABLE)\n .filter(([, lifetime]) => lifetime === 'durable')\n .map(([key]) => key)\n","import { pickCreateSessionRequest, type CreateSessionRequest, type ProfileInfo } from '@workerdeck/protocol'\nimport type { ServerContext } from '../context.ts'\nimport { HOST_ONLY_KEYS } from '../lib/host-only-keys.ts'\nimport type { Refusal } from '../lib/http.ts'\nimport { refusePermissionMode } from '../lib/permissions.ts'\nimport { engineOf } from '../lib/profile-env.ts'\nimport type { AuthContext } from '../services/auth.ts'\n\nexport { HOST_ONLY_KEYS }\n\nexport type VettedCreateRequest = { ok: true; request: CreateSessionRequest } | { ok: false; status: number; error: string }\n\n// The one create-validation ladder, run by both create doors - `POST /sessions` and the\n// `session` block of `POST /jobs`. The scope design claims the two are indistinguishable, so\n// the order and the refusals have to come from a single place rather than two copies that can\n// drift. The body is untrusted JSON: it is projected onto the wire type, never cast to it, and\n// the projected object is what the ladder mutates (inert fields stripped, profile name pinned)\n// and what the caller must hand on.\nexport function vetCreateRequest(ctx: ServerContext, body: unknown, auth: AuthContext): VettedCreateRequest {\n if (typeof body !== 'object' || body === null || Array.isArray(body)) {\n return { ok: false, status: 400, error: 'request body must be a JSON object' }\n }\n const hostOnly = Object.keys(body).filter((key) => HOST_ONLY_KEYS.has(key))\n if (hostOnly.length > 0) {\n return {\n ok: false,\n status: 400,\n error:\n `host-only runner config is not accepted on a session request: ${hostOnly.join(', ')} ` +\n \"(set it from the gateway's buildRunnerConfig hook)\",\n }\n }\n const req = pickCreateSessionRequest(body as Record<string, unknown>)\n const { availability, factory } = ctx\n const early = factory.applyScope(req, auth) ?? refusal(403, factory.applyBypassPolicy(req))\n if (early) {\n return { ok: false, ...early }\n }\n const resolved = factory.resolveProfile(req.profile, auth.allowedProfiles)\n if (!resolved.ok) {\n return resolved\n }\n const refused =\n refusal(403, refuseHostAuthority(ctx, req, resolved.profile, auth)) ??\n availability.checkAvailable(resolved.profile) ??\n factory.checkCwd(req, resolved.profile) ??\n refusal(400, factory.checkPermissionMode(req.permissionMode, resolved.profile) ?? factory.checkEngineGrants(req, resolved.profile))\n if (refused) {\n return { ok: false, ...refused }\n }\n factory.stripInertFields(req, resolved.profile)\n req.profile = resolved.profile?.name\n return { ok: true, request: req }\n}\n\nfunction refusal(status: number, error: string | null): Refusal | null {\n return error === null ? null : { status, error }\n}\n\n// A non-operator is an embedded end user: nothing on its request may reach past what the profile grants into the\n// gateway's own authority over the host. Operators (the tenant model's one key) are untouched.\nfunction refuseHostAuthority(\n ctx: ServerContext,\n req: CreateSessionRequest,\n profile: ProfileInfo | undefined,\n auth: AuthContext,\n): string | null {\n if (ctx.auth.isOperator(auth)) {\n return null\n }\n const engine = engineOf(profile)\n const name = profile?.name ?? 'default'\n if ((engine === 'claude' || engine === 'codex') && !auth.allowedProfiles?.includes(name)) {\n return `profile '${name}' runs the ${engine} engine on the host; a non-operator caller needs it named in its allowedProfiles`\n }\n const mode = refusePermissionMode(req.permissionMode, { operator: false })\n if (mode) {\n return mode\n }\n if (req.allowDangerouslySkipPermissions) {\n return 'allowDangerouslySkipPermissions is reserved to operators'\n }\n if (req.settingSources !== undefined && req.settingSources.length > 0) {\n return 'settingSources is reserved to operators: it loads hooks and settings from the host'\n }\n const servers = typeof req.mcpServers === 'object' && req.mcpServers !== null ? Object.values(req.mcpServers) : []\n if (!servers.every(isRemoteMcpServer)) {\n return 'a stdio MCP server is reserved to operators: it runs a command on the host'\n }\n if (req.resume !== undefined && !ownsSdkSession(ctx, auth, req.resume)) {\n return 'resume is limited to a live session this caller can see'\n }\n return null\n}\n\nfunction ownsSdkSession(ctx: ServerContext, auth: AuthContext, sdkSessionId: string): boolean {\n return ctx.registry.list().some((info) => info.sdkSessionId === sdkSessionId && ctx.auth.canSee(auth, info))\n}\n\nfunction isRemoteMcpServer(server: unknown): boolean {\n const type = (server as { type?: unknown } | null)?.type\n return type === 'http' || type === 'sse'\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport type {\n AgentConfig,\n AgentResponse,\n CreateAgentRequest,\n RetireAgentRequest,\n SessionInfo,\n UpdateAgentRequest,\n} from '@workerdeck/protocol'\nimport type { ServerContext } from '../context.ts'\nimport { fail, json, readJsonBody, requireMethod } from '../lib/http.ts'\nimport type { AuthContext } from '../services/auth.ts'\nimport { isAgentRefusal, type AgentService } from '../services/agents.ts'\nimport type { StoredAgent } from '../services/agent-store.ts'\nimport { vetCreateRequest } from './create-vet.ts'\nimport { sessionInfoOf } from './session-lookup.ts'\n\nexport async function handleAgents(\n ctx: ServerContext,\n req: IncomingMessage,\n res: ServerResponse,\n pathname: string,\n auth: AuthContext,\n): Promise<void> {\n const agents = ctx.agents\n const rest = pathname.slice((ctx.basePath + '/agents').length).replace(/^\\//, '')\n if (rest === '') {\n requireMethod(req, 'GET', 'POST')\n if (req.method === 'GET') {\n json(res, 200, { agents: agents.list() })\n return\n }\n await createAgent(ctx, agents, req, res, auth)\n return\n }\n const [id, action, ...extra] = rest.split('/').map(decodeURIComponent)\n const agent = id === undefined ? undefined : agents.get(id)\n if (!agent || extra.length > 0) {\n fail(404, 'agent not found')\n }\n if (action === 'restart') {\n requireMethod(req, 'POST')\n const body = ((await readJsonBody(req, ctx.maxBodyBytes)) ?? {}) as { prompt?: unknown }\n const previous = agent.sessionId === undefined ? undefined : ctx.registry.get(agent.sessionId)\n const created = await startSession(ctx, agent, typeof body.prompt === 'string' ? body.prompt : undefined, auth)\n const status = previous?.info().status\n if (previous && status !== 'closed' && status !== 'failed') {\n previous.close('server')\n }\n await respond(ctx, res, 200, await bindWithAvatar(ctx, agent, created), created)\n return\n }\n if (action === 'avatar.png' || action === 'avatar-busy.png') {\n requireMethod(req, 'GET')\n await sendAvatar(ctx, req, res, agent, action === 'avatar-busy.png')\n return\n }\n if (action !== undefined) {\n fail(404, 'agent not found')\n }\n requireMethod(req, 'GET', 'PATCH', 'DELETE')\n if (req.method === 'GET') {\n await respond(ctx, res, 200, agent)\n return\n }\n if (req.method === 'PATCH') {\n const patch = (await readJsonBody(req, ctx.maxBodyBytes)) as UpdateAgentRequest\n const updated = await agents.update(agent.id, isRecord(patch) ? patch : {})\n if (isAgentRefusal(updated)) {\n fail(updated.status, updated.error)\n }\n await respond(ctx, res, 200, updated)\n return\n }\n const body = ((await readJsonBody(req, ctx.maxBodyBytes)) ?? {}) as RetireAgentRequest\n const members = body.members === 'retire' ? 'retire' : 'release'\n const outcome = await agents.retire(agent.id, members)\n if (isAgentRefusal(outcome)) {\n fail(outcome.status, outcome.error)\n }\n for (const gone of outcome.retired) {\n const runner = gone.sessionId === undefined ? undefined : ctx.registry.get(gone.sessionId)\n const status = runner?.info().status\n if (runner && status !== 'closed' && status !== 'failed') {\n runner.close('client')\n }\n }\n json(res, 200, { retired: outcome.retired.map((a) => a.id), released: outcome.released.map((a) => a.id) })\n}\n\nasync function createAgent(ctx: ServerContext, agents: AgentService, req: IncomingMessage, res: ServerResponse, auth: AuthContext) {\n const body = (await readJsonBody(req, ctx.maxBodyBytes)) as CreateAgentRequest\n if (!isRecord(body)) {\n fail(400, 'request body must be a JSON object')\n }\n if (body.adopt !== undefined) {\n await adoptSession(ctx, agents, res, body)\n return\n }\n const draft = agents.draft(body)\n if (isAgentRefusal(draft)) {\n fail(draft.status, draft.error)\n }\n const created = await startSession(ctx, draft, typeof body.prompt === 'string' ? body.prompt : undefined, auth)\n await respond(ctx, res, 201, await bindWithAvatar(ctx, draft, created), created)\n}\n\nasync function adoptSession(ctx: ServerContext, agents: AgentService, res: ServerResponse, body: CreateAgentRequest) {\n if (typeof body.adopt !== 'string') {\n fail(400, 'adopt must be a session id')\n }\n const info = await sessionInfoOf(ctx, body.adopt)\n if (!info) {\n fail(404, 'session not found')\n }\n if (agents.bySession(info.id)) {\n fail(409, 'that session already belongs to an agent')\n }\n const draft = agents.draft({ name: body.name ?? info.title, config: { ...configOf(info), ...body.config }, lead: body.lead })\n if (isAgentRefusal(draft)) {\n fail(draft.status, draft.error)\n }\n await respond(ctx, res, 201, await bindWithAvatar(ctx, draft, info))\n}\n\nasync function bindWithAvatar(ctx: ServerContext, agent: StoredAgent, session: SessionInfo): Promise<StoredAgent> {\n const recipe = agent.avatarRecipe ?? (await rollAvatar(ctx, agent, session))\n return ctx.agents.bind(recipe === undefined ? agent : { ...agent, avatarRecipe: recipe }, session.id)\n}\n\nasync function rollAvatar(ctx: ServerContext, agent: StoredAgent, session: SessionInfo | undefined): Promise<unknown> {\n if (!ctx.avatars) {\n return undefined\n }\n const project = session ? (ctx.projects.withProject(session).project?.root ?? session.cwd) : undefined\n try {\n return await ctx.avatars.roll(agent.avatarSeed, session?.engine, project || undefined)\n } catch {\n return undefined\n }\n}\n\nasync function sendAvatar(ctx: ServerContext, req: IncomingMessage, res: ServerResponse, agent: StoredAgent, busy: boolean): Promise<void> {\n const avatars = ctx.avatars\n if (!avatars) {\n fail(404, 'this gateway draws no avatars')\n }\n let recipe = agent.avatarRecipe\n if (recipe === undefined) {\n const session = agent.sessionId === undefined ? undefined : await sessionInfoOf(ctx, agent.sessionId)\n recipe = await rollAvatar(ctx, agent, session)\n if (recipe === undefined) {\n fail(503, 'the avatar pack could not be loaded')\n }\n await ctx.agents.save({ ...agent, avatarRecipe: recipe })\n }\n const image = busy ? await avatars.busy(recipe) : await avatars.still(recipe)\n if (!image) {\n fail(404, 'this avatar pack has no busy animation')\n }\n const headers: Record<string, string> = { 'content-type': 'image/png', etag: image.etag, 'cache-control': 'private, max-age=86400' }\n if (image.durations) {\n headers['x-frame-durations'] = image.durations.join(',')\n }\n if (req.headers['if-none-match'] === image.etag) {\n res.writeHead(304, headers).end()\n return\n }\n res.writeHead(200, headers).end(Buffer.from(image.png))\n}\n\nasync function startSession(ctx: ServerContext, agent: StoredAgent, prompt: string | undefined, auth: AuthContext): Promise<SessionInfo> {\n const { config } = agent\n const request = {\n cwd: config.cwd,\n profile: config.profile,\n model: config.model,\n reasoningEffort: config.reasoningEffort,\n permissionMode: config.permissionMode,\n allowDangerouslySkipPermissions: config.permissionMode === 'bypassPermissions' ? true : undefined,\n agentContextReset: config.agentContextReset ?? true,\n prompt,\n }\n const vetted = vetCreateRequest(ctx, stripUndefined(request), auth)\n if (!vetted.ok) {\n fail(vetted.status, vetted.error)\n }\n const runner = await ctx.factory.createRunner(ctx.factory.buildRunnerConfig(vetted.request, { operator: ctx.auth.isOperator(auth) }), {\n brief: config.brief?.trim() || undefined,\n })\n return runner.info()\n}\n\nasync function respond(ctx: ServerContext, res: ServerResponse, status: number, agent: StoredAgent, session?: SessionInfo): Promise<void> {\n const info = session ?? (agent.sessionId === undefined ? undefined : await sessionInfoOf(ctx, agent.sessionId))\n const body: AgentResponse = { agent: ctx.agents.public(agent) }\n if (info) {\n body.session = ctx.projects.withProject(info)\n }\n json(res, status, body)\n}\n\nfunction configOf(info: SessionInfo): AgentConfig {\n return stripUndefined({\n cwd: info.cwd || undefined,\n profile: info.profile,\n model: info.model,\n reasoningEffort: info.effort ?? undefined,\n permissionMode: info.permissionMode,\n })\n}\n\nfunction stripUndefined<T extends Record<string, unknown>>(value: T): T {\n return Object.fromEntries(Object.entries(value).filter(([, v]) => v !== undefined)) as T\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { ToolExecutionResult } from '@workerdeck/core'\nimport type { SubmitExecutionResultRequest } from '@workerdeck/protocol'\nimport { fail, json, readJsonBody, requireMethod } from '../lib/http.ts'\nimport type { AuthContext } from '../services/auth.ts'\nimport type { ServerContext } from '../context.ts'\nimport { sessionInfoOf } from './session-lookup.ts'\n\nexport async function handleExecutionResult(\n ctx: ServerContext,\n req: IncomingMessage,\n res: ServerResponse,\n pathname: string,\n auth: AuthContext,\n): Promise<void> {\n const { auth: authSvc, basePath, parking } = ctx\n const rest = pathname.slice((basePath + '/executions/').length).split('/')\n if (rest.length !== 2 || rest[1] !== 'result' || !rest[0]) {\n fail(404, 'not found')\n }\n requireMethod(req, 'POST')\n const executionId = decodeURIComponent(rest[0])\n const body = (await readJsonBody(req, ctx.maxBodyBytes)) as SubmitExecutionResultRequest\n let result: ToolExecutionResult\n if (body?.status === 'ok') {\n if (!body.output || typeof body.output !== 'object') {\n fail(400, \"output is required for status 'ok'\")\n }\n result = { status: 'ok', output: body.output.value, logs: body.logs }\n } else if (body?.status === 'failed') {\n if (typeof body.reason !== 'string' || typeof body.error !== 'string') {\n fail(400, \"reason and error are required for status 'failed'\")\n }\n result = { status: 'failed', reason: body.reason, error: body.error, logs: body.logs }\n } else {\n fail(400, \"status must be 'ok' or 'failed'\")\n }\n if (auth.allowedProfiles || auth.scope || ctx.options.authorizeSession) {\n const owner = parking.sessionFor(executionId)\n const info = owner === undefined ? undefined : await sessionInfoOf(ctx, owner)\n const profile = info?.profile\n // Indistinguishable from an unknown id on purpose: whether an execution exists elsewhere is not this caller's business.\n // A vanished session (`info === undefined`) refuses too - nobody passed canSee, and submitResult would disclose the owner id.\n const refused =\n owner === undefined ||\n info === undefined ||\n (auth.allowedProfiles !== undefined && profile !== undefined && !auth.allowedProfiles.includes(profile)) ||\n !authSvc.canSee(auth, info)\n if (refused) {\n fail(404, 'execution not found')\n }\n }\n const applied = await parking.submitResult(executionId, result)\n if (!applied) {\n fail(404, 'execution not found (unknown id, or its session has ended)')\n }\n json(res, 200, applied)\n}\n","import type { Dirent } from 'node:fs'\nimport { closeSync, constants, fstatSync, ftruncateSync, lstatSync, openSync, readFileSync, realpathSync, writeFileSync } from 'node:fs'\nimport { basename, dirname, isAbsolute, join, relative, sep } from 'node:path'\n\n// win32 lacks O_NOFOLLOW/O_NONBLOCK (undefined at runtime despite the typing): there they contribute 0 and the fstat gates stand alone.\nconst O_NOFOLLOW: number = constants.O_NOFOLLOW ?? 0\nconst O_NONBLOCK: number = constants.O_NONBLOCK ?? 0\n\nexport type HostFileRoot = {\n readonly configured: string\n readonly canonical: string\n}\n\nexport type HostFileRoots = { readonly roots: readonly HostFileRoot[] }\n\nexport function createHostFileRoots(roots: string[]): HostFileRoots {\n return {\n roots: roots.map((configured) => {\n if (invalidRequest(configured)) {\n throw new Error(`createHostFileRoots: root must be an absolute path: ${JSON.stringify(configured)}`)\n }\n let canonical: string\n try {\n canonical = realpathSync(configured)\n } catch {\n throw new Error(`createHostFileRoots: root does not exist: ${configured}`)\n }\n if (!lstatSync(canonical).isDirectory()) {\n throw new Error(`createHostFileRoots: root is not a directory: ${configured}`)\n }\n return { configured, canonical }\n }),\n }\n}\n\nexport type ResolveOutcome =\n | { ok: true; path: string; root: string; kind: 'file' | 'dir' }\n | { ok: false; status: 403 | 404; error: string }\n\ntype Refusal = { ok: false; status: 403 | 404; error: string }\n\nfunction refuse(status: 403 | 404, error: string): Refusal {\n return { ok: false, status, error }\n}\n\nfunction notFound(): Refusal {\n return refuse(404, 'not found')\n}\n\n// NUL is rejected before any fs call: Node throws a TypeError on one, and that must surface as a refusal rather than a 500.\nfunction invalidRequest(requested: string): boolean {\n return requested.length === 0 || requested.includes('\\0') || !isAbsolute(requested)\n}\n\n// A bare prefix check gets the boundary wrong (`/x/app` would swallow `/x/application`); both sides must be realpath output.\nexport function contained(rootCanonical: string, candidate: string): boolean {\n const rel = relative(rootCanonical, candidate)\n return rel === '' || (rel !== '..' && !rel.startsWith(`..${sep}`) && !isAbsolute(rel))\n}\n\nfunction rootContaining(roots: HostFileRoots, canonical: string): HostFileRoot | undefined {\n return roots.roots.find((root) => contained(root.canonical, canonical))\n}\n\nexport function resolveExisting(roots: HostFileRoots, requested: string): ResolveOutcome {\n if (invalidRequest(requested)) {\n return refuse(403, 'invalid path')\n }\n let canonical: string\n try {\n canonical = realpathSync(requested)\n } catch {\n return notFound()\n }\n const root = rootContaining(roots, canonical)\n if (!root) {\n return notFound()\n }\n let target\n try {\n // realpath output cannot name a symlink, so lstat === stat modulo a race - and a swap inside the window then classifies as neither.\n target = lstatSync(canonical)\n } catch {\n return notFound()\n }\n if (target.isFile()) {\n return { ok: true, path: canonical, root: root.canonical, kind: 'file' }\n }\n if (target.isDirectory()) {\n return { ok: true, path: canonical, root: root.canonical, kind: 'dir' }\n }\n return refuse(403, 'not a regular file or directory')\n}\n\n// Only the final component may be new: a missing target canonicalizes its parent, so a dangling symlink sitting there is refused, not created through.\nexport function resolveForWrite(roots: HostFileRoots, requested: string): ResolveOutcome {\n if (invalidRequest(requested)) {\n return refuse(403, 'invalid path')\n }\n try {\n const canonical = realpathSync(requested)\n const root = rootContaining(roots, canonical)\n if (!root) {\n return notFound()\n }\n const target = lstatSync(canonical)\n if (target.isDirectory()) {\n return refuse(403, 'is a directory')\n }\n if (!target.isFile()) {\n return refuse(403, 'not a regular file')\n }\n return { ok: true, path: canonical, root: root.canonical, kind: 'file' }\n } catch {}\n const base = basename(requested)\n if (base === '' || base === '.' || base === '..') {\n return refuse(403, 'invalid path')\n }\n let parent: string\n try {\n parent = realpathSync(dirname(requested))\n } catch {\n return notFound()\n }\n const root = rootContaining(roots, parent)\n if (!root) {\n return notFound()\n }\n try {\n if (!lstatSync(parent).isDirectory()) {\n return notFound()\n }\n } catch {\n return notFound()\n }\n const path = join(parent, base)\n // Redundant by construction (basename() cannot smuggle a separator) - kept because this is the line an escape would have to cross.\n if (!contained(root.canonical, path)) {\n return notFound()\n }\n try {\n lstatSync(path)\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n return { ok: true, path, root: root.canonical, kind: 'file' }\n }\n return notFound()\n }\n return notFound()\n}\n\nexport type HostEntryKind = 'file' | 'dir' | 'symlink' | 'other'\n\nexport function entryKind(entry: Dirent): HostEntryKind {\n if (entry.isSymbolicLink()) {\n return 'symlink'\n }\n if (entry.isFile()) {\n return 'file'\n }\n if (entry.isDirectory()) {\n return 'dir'\n }\n return 'other'\n}\n\nexport type ReadOutcome = { ok: true; data: Buffer } | Refusal\n\nexport function readContained(path: string): ReadOutcome {\n let fd: number\n try {\n fd = openSync(path, constants.O_RDONLY | O_NOFOLLOW | O_NONBLOCK)\n } catch (err) {\n return (err as NodeJS.ErrnoException).code === 'ENOENT' ? notFound() : refuse(403, 'refused')\n }\n try {\n if (!fstatSync(fd).isFile()) {\n return refuse(403, 'not a regular file')\n }\n return { ok: true, data: readFileSync(fd) }\n } catch {\n return refuse(403, 'refused')\n } finally {\n closeSync(fd)\n }\n}\n\nexport type WriteOutcome = { ok: true } | Refusal\n\nexport function writeContained(path: string, data: string | Uint8Array): WriteOutcome {\n let fd: number\n try {\n fd = openSync(path, constants.O_WRONLY | constants.O_CREAT | O_NOFOLLOW | O_NONBLOCK, 0o644)\n } catch (err) {\n return (err as NodeJS.ErrnoException).code === 'ENOENT' ? notFound() : refuse(403, 'refused')\n }\n try {\n if (!fstatSync(fd).isFile()) {\n return refuse(403, 'not a regular file')\n }\n ftruncateSync(fd)\n writeFileSync(fd, data)\n return { ok: true }\n } catch {\n return refuse(403, 'refused')\n } finally {\n closeSync(fd)\n }\n}\n","import { readdirSync } from 'node:fs'\nimport { join, relative } from 'node:path'\nimport { entryKind } from './host-files.ts'\n\nexport const DEFAULT_IGNORED_DIRS = [\n '.git',\n '.hg',\n '.svn',\n 'node_modules',\n '.next',\n '.nuxt',\n '.svelte-kit',\n '.turbo',\n '.cache',\n 'dist',\n 'build',\n 'out',\n 'target',\n '.venv',\n 'venv',\n '__pycache__',\n '.pytest_cache',\n '.gradle',\n 'Pods',\n 'DerivedData',\n // Swift Package Manager: its object files carry the source names, so `@` answers `Transcript.o` before `Transcript.swift` without this.\n '.build',\n]\n\nexport type FoundFile = {\n path: string\n relative: string\n}\n\nexport type SearchResult = {\n matches: FoundFile[]\n truncated: boolean\n}\n\nexport type SearchOptions = {\n query?: string\n limit?: number\n ignore?: readonly string[]\n maxScanned?: number\n}\n\nexport function searchFiles(base: string, options: SearchOptions = {}): SearchResult {\n const limit = options.limit ?? 50\n const maxScanned = options.maxScanned ?? 20_000\n const ignore = new Set(options.ignore ?? DEFAULT_IGNORED_DIRS)\n const needle = (options.query ?? '').toLowerCase()\n\n const found: { file: FoundFile; score: number; depth: number }[] = []\n const queue: { dir: string; depth: number }[] = [{ dir: base, depth: 0 }]\n let scanned = 0\n let exhausted = true\n\n while (queue.length > 0) {\n const { dir, depth } = queue.shift()!\n let entries\n try {\n entries = readdirSync(dir, { withFileTypes: true })\n } catch {\n continue\n }\n for (const entry of entries) {\n if (++scanned > maxScanned) {\n exhausted = false\n queue.length = 0\n break\n }\n const kind = entryKind(entry)\n if (kind === 'dir') {\n if (!ignore.has(entry.name)) {\n queue.push({ dir: join(dir, entry.name), depth: depth + 1 })\n }\n continue\n }\n if (kind !== 'file') {\n continue\n }\n const path = join(dir, entry.name)\n const rel = relative(base, path)\n const score = scoreMatch(rel, entry.name, needle)\n if (score !== null) {\n found.push({ file: { path, relative: rel }, score, depth })\n }\n }\n }\n\n found.sort(\n (a, b) =>\n b.score - a.score ||\n a.depth - b.depth ||\n a.file.relative.length - b.file.relative.length ||\n a.file.relative.localeCompare(b.file.relative),\n )\n return {\n matches: found.slice(0, limit).map((f) => f.file),\n truncated: !exhausted || found.length > limit,\n }\n}\n\nfunction scoreMatch(relativePath: string, name: string, needle: string): number | null {\n if (needle === '') {\n return 0\n }\n const inName = subsequenceScore(name.toLowerCase(), needle)\n if (inName !== null) {\n return inName + 1000\n }\n return subsequenceScore(relativePath.toLowerCase(), needle)\n}\n\nfunction subsequenceScore(haystack: string, needle: string): number | null {\n let score = 0\n let from = 0\n let previous = -2\n for (const char of needle) {\n const at = haystack.indexOf(char, from)\n if (at === -1) {\n return null\n }\n if (at === previous + 1) {\n score += 8\n }\n if (at === 0) {\n score += 4\n }\n from = at + 1\n previous = at\n }\n // Shorter haystacks matched the same needle more tightly.\n return score - haystack.length / 100\n}\n","import { lstatSync, readdirSync, type Dirent } from 'node:fs'\nimport { basename, join } from 'node:path'\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { WriteHostFileRequest } from '@workerdeck/protocol'\nimport { asUtf8, fail, hashBytes, json, readJsonBody, requireMethod } from '../lib/http.ts'\nimport { searchFiles } from '../services/host-file-search.ts'\nimport { entryKind, readContained, resolveExisting, resolveForWrite, writeContained, type HostFileRoots } from '../services/host-files.ts'\nimport type { ServerContext } from '../context.ts'\n\ntype FsCall = { ctx: ServerContext; hostFiles: HostFileRoots; req: IncomingMessage; res: ServerResponse; url: URL }\n\ntype ExistingKind = 'file' | 'dir'\n\nconst KIND_REFUSAL: Record<ExistingKind, string> = { dir: 'not a directory', file: 'not a regular file' }\n\nconst FS_ROUTES = new Map<string, (call: FsCall) => Promise<void> | void>([\n ['roots', handleRoots],\n ['find', handleFind],\n ['list', handleList],\n ['read', handleRead],\n ['write', handleWrite],\n])\n\nfunction kindRank(type: string): number {\n return type === 'dir' ? 0 : 1\n}\n\nexport async function handleHostFiles(ctx: ServerContext, req: IncomingMessage, res: ServerResponse, pathname: string): Promise<void> {\n const { basePath, hostFiles } = ctx\n if (!hostFiles) {\n fail(404, 'host file access is not configured on this server')\n }\n const handler = FS_ROUTES.get(pathname.slice((basePath + '/fs/').length))\n if (!handler) {\n fail(404, 'not found')\n }\n await handler({ ctx, hostFiles, req, res, url: new URL(req.url ?? '/', 'http://internal') })\n}\n\nfunction requireExisting(hostFiles: HostFileRoots, url: URL, kind: ExistingKind): string {\n const requested = url.searchParams.get('path')\n if (!requested) {\n fail(400, 'path is required')\n }\n const resolved = resolveExisting(hostFiles, requested)\n if (!resolved.ok) {\n fail(resolved.status, resolved.error)\n }\n if (resolved.kind !== kind) {\n fail(400, KIND_REFUSAL[kind])\n }\n return resolved.path\n}\n\nfunction handleRoots({ ctx, hostFiles, req, res }: FsCall): void {\n requireMethod(req, 'GET')\n // The canonical spelling, not the operator's: a client round-tripping a root it was given must land on the same tree.\n json(res, 200, {\n roots: hostFiles.roots.map(({ canonical }) => ({\n path: canonical,\n name: basename(canonical) || canonical,\n })),\n canWrite: ctx.hostFilesWritable,\n })\n}\n\nfunction handleFind({ ctx, hostFiles, req, res, url }: FsCall): void {\n requireMethod(req, 'GET')\n const base = requireExisting(hostFiles, url, 'dir')\n // Clamped, not validated: this runs per keystroke from a phone.\n const asked = Number(url.searchParams.get('limit') ?? '')\n const limit = Number.isFinite(asked) && asked > 0 ? Math.min(asked, 200) : 50\n const result = searchFiles(base, {\n query: url.searchParams.get('q') ?? '',\n limit,\n ignore: ctx.options.hostFiles?.ignore,\n })\n json(res, 200, { base, ...result })\n}\n\nfunction handleList({ ctx, hostFiles, req, res, url }: FsCall): void {\n requireMethod(req, 'GET')\n const dir = requireExisting(hostFiles, url, 'dir')\n const { maxHostDirEntries } = ctx\n let names: Dirent[]\n try {\n names = readdirSync(dir, { withFileTypes: true })\n } catch {\n fail(403, 'directory is not readable')\n }\n const truncated = names.length > maxHostDirEntries\n const entries = names.slice(0, maxHostDirEntries).map((entry) => {\n const path = join(dir, entry.name)\n const type = entryKind(entry)\n // Never stat *through* a link: a directory holding a link to a fifo would become unlistable.\n let bytes: number | undefined\n let modifiedAt: number | undefined\n if (type === 'file') {\n try {\n const s = lstatSync(path)\n bytes = s.size\n modifiedAt = s.mtimeMs\n } catch {}\n }\n return { name: entry.name, path, type, bytes, modifiedAt }\n })\n entries.sort((a, b) => kindRank(a.type) - kindRank(b.type) || a.name.localeCompare(b.name))\n json(res, 200, { path: dir, entries, ...(truncated ? { truncated } : {}) })\n}\n\nfunction handleRead({ ctx, hostFiles, req, res, url }: FsCall): void {\n requireMethod(req, 'GET')\n const path = requireExisting(hostFiles, url, 'file')\n const { maxHostFileBytes } = ctx\n const tooLarge = `file is larger than ${maxHostFileBytes} bytes`\n // Advisory pre-check only - the authoritative cap is on the bytes actually read, since the file can grow before the open.\n let stats\n try {\n stats = lstatSync(path)\n } catch {\n fail(404, 'not found')\n }\n if (stats.size > maxHostFileBytes) {\n fail(413, tooLarge)\n }\n const read = readContained(path)\n if (!read.ok) {\n fail(read.status, read.error)\n }\n if (read.data.length > maxHostFileBytes) {\n fail(413, tooLarge)\n }\n const text = asUtf8(read.data)\n json(res, 200, {\n path,\n content: text ?? read.data.toString('base64'),\n encoding: text === null ? 'base64' : 'utf8',\n bytes: read.data.length,\n hash: hashBytes(read.data),\n modifiedAt: stats.mtimeMs,\n })\n}\n\nasync function handleWrite({ ctx, hostFiles, req, res }: FsCall): Promise<void> {\n const { maxHostFileBytes } = ctx\n requireMethod(req, 'PUT')\n if (!ctx.hostFilesWritable) {\n fail(403, 'host file writes are not enabled on this server')\n }\n const body = (await readJsonBody(req, ctx.maxBodyBytes)) as WriteHostFileRequest\n if (!body.path || typeof body.path !== 'string') {\n fail(400, 'path is required')\n }\n if (typeof body.content !== 'string') {\n fail(400, 'content is required')\n }\n if (body.encoding !== undefined && body.encoding !== 'utf8' && body.encoding !== 'base64') {\n fail(400, \"encoding must be 'utf8' or 'base64'\")\n }\n const resolved = resolveForWrite(hostFiles, body.path)\n if (!resolved.ok) {\n fail(resolved.status, resolved.error)\n }\n const next = Buffer.from(body.content, body.encoding ?? 'utf8')\n if (next.length > maxHostFileBytes) {\n fail(413, `content is larger than ${maxHostFileBytes} bytes`)\n }\n // Existence is decided by the read, not a stat: only ENOENT is 404, so anything else refuses rather than being clobbered as a create.\n const current = readContained(resolved.path)\n if (!current.ok && current.status !== 404) {\n fail(current.status, current.error)\n }\n const existing = current.ok ? current.data : null\n if (existing && !body.expectedHash) {\n fail(409, 'file exists - pass expectedHash to overwrite it')\n }\n if (existing && hashBytes(existing) !== body.expectedHash) {\n fail(409, 'file changed on disk since it was read')\n }\n if (!existing && body.expectedHash) {\n fail(409, 'file no longer exists')\n }\n const written = writeContained(resolved.path, next)\n if (!written.ok) {\n fail(written.status, written.error)\n }\n let writtenAt = 0\n try {\n writtenAt = lstatSync(resolved.path).mtimeMs\n } catch {}\n json(res, 200, {\n path: resolved.path,\n bytes: next.length,\n hash: hashBytes(next),\n modifiedAt: writtenAt,\n })\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { CreateJobRequest } from '@workerdeck/protocol'\nimport { fail, json, readJsonBody, requireMethod } from '../lib/http.ts'\nimport { vetCreateRequest } from './create-vet.ts'\nimport type { AuthContext } from '../services/auth.ts'\nimport type { ServerContext } from '../context.ts'\n\nexport async function handleJobs(\n ctx: ServerContext,\n req: IncomingMessage,\n res: ServerResponse,\n pathname: string,\n auth: AuthContext,\n): Promise<void> {\n const { auth: authSvc, basePath, queue } = ctx\n if (!queue) {\n fail(404, 'job queue not configured')\n }\n if (pathname === basePath + '/queue') {\n requireMethod(req, 'GET')\n if (!authSvc.isOperator(auth)) {\n fail(404, 'not found')\n }\n json(res, 200, { stats: await queue.stats() })\n return\n }\n const rest = pathname.slice((basePath + '/jobs').length).replace(/^\\//, '')\n if (rest === '') {\n requireMethod(req, 'GET', 'POST')\n if (req.method === 'GET') {\n const jobs = await queue.list()\n json(res, 200, { jobs: jobs.filter((job) => authSvc.canSeeJob(auth, job)) })\n return\n }\n const body = (await readJsonBody(req, ctx.maxBodyBytes)) as CreateJobRequest | null\n if (!body?.session || typeof body.session !== 'object') {\n fail(400, 'session is required')\n }\n const prompt = body.session.prompt\n if (!prompt || typeof prompt !== 'string') {\n fail(400, 'session.prompt is required')\n }\n const vetted = vetCreateRequest(ctx, body.session, auth)\n if (!vetted.ok) {\n fail(vetted.status, vetted.error)\n }\n try {\n // The projected block is what gets stored: the queue spreads the record's session into a runner config later.\n json(res, 201, { job: await queue.submit({ ...body, session: { ...vetted.request, prompt } }) })\n } catch (error) {\n json(res, 400, { error: error instanceof Error ? error.message : 'invalid job' })\n }\n return\n }\n const id = decodeURIComponent(rest)\n if (id.includes('/')) {\n fail(404, 'not found')\n }\n requireMethod(req, 'GET', 'DELETE')\n // Checked before the cancel: a refused caller must not be able to kill a run and then be told it does not exist.\n const existing = await queue.get(id)\n if (!existing || !authSvc.canSeeJob(auth, existing)) {\n fail(404, 'job not found')\n }\n const job = req.method === 'GET' ? existing : await queue.cancel(id)\n if (!job) {\n fail(404, 'job not found')\n }\n json(res, 200, { job })\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { ProfileInfo, UpdateProfileRequest } from '@workerdeck/protocol'\nimport { fail, json, readJsonBody, requireMethod } from '../lib/http.ts'\nimport { readProfileConfig } from '../lib/profile-env.ts'\nimport type { AuthContext } from '../services/auth.ts'\nimport type { ProfileService } from '../services/profiles.ts'\nimport type { ServerContext } from '../context.ts'\n\nexport async function handleProfiles(\n ctx: ServerContext,\n req: IncomingMessage,\n res: ServerResponse,\n pathname: string,\n auth: AuthContext,\n): Promise<void> {\n const { auth: authSvc, availability, basePath, profiles } = ctx\n const rest = pathname.slice((basePath + '/profiles').length).replace(/^\\//, '')\n if (rest === '') {\n requireMethod(req, 'GET', 'POST')\n if (req.method === 'GET') {\n const visible = auth.allowedProfiles ? profiles.all().filter((p) => auth.allowedProfiles!.includes(p.name)) : profiles.all()\n availability.refresh(visible)\n json(res, 200, {\n profiles: visible.map((p) => profiles.forResponse(p)),\n canManage: profiles.manageGuard(auth) === null,\n })\n return\n }\n refuseWith(profiles.manageGuard(auth))\n const body = (await readJsonBody(req, ctx.maxBodyBytes)) as ProfileInfo\n if (!body.name || typeof body.name !== 'string') {\n fail(400, 'name is required')\n }\n if (profiles.get(body.name)) {\n fail(409, `profile already exists: ${body.name}`)\n }\n await saveManaged(profiles, res, body)\n return\n }\n const name = decodeURIComponent(rest)\n const profile = name.includes('/') ? undefined : profiles.get(name)\n if (!profile) {\n fail(404, 'profile not found')\n }\n if (auth.allowedProfiles && !auth.allowedProfiles.includes(profile.name)) {\n fail(403, `profile not allowed: ${profile.name}`)\n }\n requireMethod(req, 'GET', 'PATCH', 'DELETE')\n if (req.method === 'GET') {\n json(res, 200, {\n profile: profiles.forResponse(profile),\n config: authSvc.isOperator(auth) ? readProfileConfig(profile) : undefined,\n })\n return\n }\n refuseWith(profiles.manageGuard(auth) ?? profiles.declaredGuard(profile))\n if (req.method === 'DELETE') {\n await ctx.options.profileStore!.delete(profile.name)\n await profiles.refreshStored()\n res.writeHead(204).end()\n return\n }\n const patch = (await readJsonBody(req, ctx.maxBodyBytes)) as UpdateProfileRequest\n await saveManaged(profiles, res, { ...profile, ...patch, name: profile.name })\n}\n\nfunction refuseWith(refused: { status: number; error: string } | null): void {\n if (refused) {\n fail(refused.status, refused.error)\n }\n}\n\nasync function saveManaged(profiles: ProfileService, res: ServerResponse, incoming: ProfileInfo): Promise<void> {\n const saved = await profiles.saveManaged(incoming)\n if (!saved.ok) {\n fail(saved.status, saved.error)\n }\n json(res, 200, { profile: saved.profile })\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { ProfileInfo, SdkSessionSummary } from '@workerdeck/protocol'\nimport { fail, json, requireMethod } from '../lib/http.ts'\nimport { cwdAllowed, engineOf } from '../lib/profile-env.ts'\nimport type { SdkSessionLister } from '../options.ts'\nimport type { AuthContext } from '../services/auth.ts'\nimport type { ServerContext } from '../context.ts'\n\n// A summary with no `cwd` cannot be shown to be inside the roots, so it is dropped.\nfunction withinRoots(sessions: SdkSessionSummary[], roots: string[], limit?: number, offset = 0): SdkSessionSummary[] {\n const allowed = sessions.filter((s) => s.cwd !== undefined && cwdAllowed(s.cwd, roots)).sort((a, b) => b.lastModified - a.lastModified)\n return limit === undefined ? allowed.slice(offset) : allowed.slice(offset, offset + limit)\n}\n\nexport async function handleSdkSessions(ctx: ServerContext, req: IncomingMessage, res: ServerResponse, auth: AuthContext): Promise<void> {\n const { adapterFor, factory, profiles } = ctx\n requireMethod(req, 'GET')\n const url = new URL(req.url ?? '/', 'http://internal')\n const dir = url.searchParams.get('dir') ?? undefined\n const roots = ctx.options.allowedCwdRoots\n const limit = Number(url.searchParams.get('limit') ?? '') || undefined\n const offset = Number(url.searchParams.get('offset') ?? '') || undefined\n const requested = url.searchParams.get('profile') ?? undefined\n let profile: ProfileInfo | undefined\n if (requested !== undefined) {\n const resolved = factory.resolveProfile(requested, auth.allowedProfiles)\n if (!resolved.ok) {\n fail(resolved.status, resolved.error)\n }\n profile = resolved.profile\n } else {\n // Implicit only when unambiguous AND permitted: a caller scoped away from the one profile falls back to the legacy listing.\n const all = profiles.all()\n if (all.length === 1 && (!auth.allowedProfiles || auth.allowedProfiles.includes(all[0]!.name))) {\n profile = all[0]\n }\n }\n const adapter = adapterFor(profile?.engine)\n if (!adapter.capabilities.listSessions) {\n json(res, 400, {\n error: `profile '${profile?.name ?? 'default'}' runs the ${engineOf(profile)} engine, which has no browsable session store`,\n })\n return\n }\n const lister: SdkSessionLister =\n engineOf(profile) === 'claude' && ctx.listSdkSessions\n ? ctx.listSdkSessions\n : (params) => {\n if (!adapter.listSessions) {\n throw new Error(`the ${engineOf(profile)} engine does not implement session listing`)\n }\n return adapter.listSessions({\n ...params,\n profile,\n env: profile ? factory.sessionEnvFor(profile) : process.env,\n })\n }\n const withinScope = roots !== undefined && roots.length > 0\n if (withinScope && dir && !cwdAllowed(dir, roots)) {\n fail(403, 'dir is outside the allowed roots')\n }\n try {\n if (withinScope && !dir) {\n // A bare listing spans every project on the host, so it filters after listing - which is why the paging is applied here too.\n json(res, 200, { sdkSessions: withinRoots(await lister({}), roots, limit, offset) })\n return\n }\n json(res, 200, { sdkSessions: await lister({ dir, limit, offset }) })\n } catch (error) {\n json(res, 500, { error: error instanceof Error ? error.message : 'failed to list sessions' })\n }\n}\n","import { readFile, readdir, rm } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { CostLedgerState, ParkedExecution, RunnerSnapshot, SessionRunnerConfig } from '@workerdeck/core'\nimport { pickCreateSessionRequest, type SessionInfo } from '@workerdeck/protocol'\nimport { isMissing, writeFileAtomic } from '../lib/atomic-file.ts'\nimport { DURABLE_HOST_KEYS } from '../lib/host-only-keys.ts'\n\nexport type ParkedSessionRecord = {\n kind?: 'parked' | 'live'\n id: string\n info: SessionInfo\n profile?: string\n config: SessionRunnerConfig\n snapshot: RunnerSnapshot\n executions: ParkedExecution[]\n cost?: CostLedgerState\n parkedAt: number\n}\n\nexport function isLiveRecord(record: StoredSessionRecord): boolean {\n return record.kind === 'live'\n}\n\nexport type DormantSessionRecord = {\n kind: 'dormant'\n id: string\n info: SessionInfo\n profile?: string\n config: SessionRunnerConfig\n sdkSessionId: string\n cost?: CostLedgerState\n savedAt: number\n}\n\nexport type StoredSessionRecord = ParkedSessionRecord | DormantSessionRecord\n\nexport function isDormant(record: StoredSessionRecord): record is DormantSessionRecord {\n return record.kind === 'dormant'\n}\n\nexport interface SessionStore {\n save(record: StoredSessionRecord): Promise<void>\n get(id: string): Promise<StoredSessionRecord | null>\n list(): Promise<StoredSessionRecord[]>\n delete(id: string): Promise<boolean>\n}\n\nexport class MemorySessionStore implements SessionStore {\n #records = new Map<string, StoredSessionRecord>()\n\n save(record: StoredSessionRecord): Promise<void> {\n this.#records.set(record.id, record)\n return Promise.resolve()\n }\n\n get(id: string): Promise<StoredSessionRecord | null> {\n return Promise.resolve(this.#records.get(id) ?? null)\n }\n\n list(): Promise<StoredSessionRecord[]> {\n return Promise.resolve([...this.#records.values()])\n }\n\n delete(id: string): Promise<boolean> {\n return Promise.resolve(this.#records.delete(id))\n }\n}\n\nfunction durableConfig(config: SessionRunnerConfig): SessionRunnerConfig {\n const source = config as Record<string, unknown>\n const durable: Record<string, unknown> = { ...pickCreateSessionRequest(source) }\n for (const key of DURABLE_HOST_KEYS) {\n if (source[key] !== undefined) {\n durable[key] = source[key]\n }\n }\n return durable as SessionRunnerConfig\n}\n\nexport function toDurableRecord<T extends StoredSessionRecord>(record: T): T {\n return { ...record, config: durableConfig(record.config) }\n}\n\nconst FORMAT_VERSION = 1\n\nexport type FileSessionStoreOptions = {\n dir?: string\n onError?: (error: unknown, context: { path: string; op: 'save' | 'read' | 'delete' }) => void\n}\n\nexport function createFileSessionStore(options: FileSessionStoreOptions = {}): SessionStore {\n const dir = options.dir ?? join(process.cwd(), '.workerdeck', 'parked')\n // Encoded, not interpolated: an id is a runner-assigned string, and a '/' in one would otherwise write outside `dir`.\n const fileFor = (id: string): string => join(dir, `${encodeURIComponent(id)}.json`)\n\n const read = async (path: string): Promise<StoredSessionRecord | null> => {\n let raw: string\n try {\n raw = await readFile(path, 'utf8')\n } catch (error) {\n // Only absence is \"nothing parked\": reporting an EACCES as one is how a restart guard ends up saying the coast is clear.\n if (isMissing(error)) {\n return null\n }\n options.onError?.(error, { path, op: 'read' })\n return null\n }\n try {\n return parseRecord(JSON.parse(raw))\n } catch (error) {\n options.onError?.(error, { path, op: 'read' })\n return null\n }\n }\n\n return {\n save: async (record) => {\n const path = fileFor(record.id)\n let payload: string\n try {\n payload = JSON.stringify({ version: FORMAT_VERSION, record: toDurableRecord(record) })\n } catch (error) {\n options.onError?.(error, { path, op: 'save' })\n throw new Error(\n `parked session '${record.id}' is not JSON-serializable - a host-injected value ` +\n `reached its config or snapshot: ${String(error)}`,\n { cause: error },\n )\n }\n try {\n await writeFileAtomic(path, payload)\n } catch (error) {\n options.onError?.(error, { path, op: 'save' })\n throw error\n }\n },\n\n get: (id) => read(fileFor(id)),\n\n list: async () => {\n let names: string[]\n try {\n names = await readdir(dir)\n } catch (error) {\n if (isMissing(error)) {\n return []\n }\n options.onError?.(error, { path: dir, op: 'read' })\n throw error\n }\n const records = await Promise.all(\n names\n .filter((name) => name.endsWith('.json'))\n .map(async (name) => {\n const record = await read(join(dir, name))\n if (!record) {\n return null\n }\n // A record only answers `get`/`delete` under the name its id encodes to; one that arrived some other way would be unreachable.\n if (`${encodeURIComponent(record.id)}.json` === name) {\n return record\n }\n options.onError?.(new Error(`parked record '${record.id}' is stored as '${name}' and cannot be read back by id`), {\n path: join(dir, name),\n op: 'read',\n })\n return null\n }),\n )\n return records.filter((record): record is StoredSessionRecord => record !== null)\n },\n\n delete: async (id) => {\n const path = fileFor(id)\n try {\n await rm(path)\n return true\n } catch (error) {\n if (isMissing(error)) {\n return false\n }\n options.onError?.(error, { path, op: 'delete' })\n return false\n }\n },\n }\n}\n\nfunction parseRecord(value: unknown): StoredSessionRecord | null {\n if (!value || typeof value !== 'object') {\n return null\n }\n const envelope = value as { version?: unknown; record?: unknown }\n if (envelope.version !== FORMAT_VERSION) {\n return null\n }\n const record = envelope.record as Partial<StoredSessionRecord> | null\n if (!record || typeof record !== 'object') {\n return null\n }\n if (typeof record.id !== 'string') {\n return null\n }\n if (!record.info || !record.config) {\n return null\n }\n if (record.kind === 'dormant') {\n const dormant = record as Partial<DormantSessionRecord>\n if (typeof dormant.sdkSessionId !== 'string' || typeof dormant.savedAt !== 'number') {\n return null\n }\n return dormant as DormantSessionRecord\n }\n const parked = record as Partial<ParkedSessionRecord>\n if (typeof parked.parkedAt !== 'number' || !parked.snapshot) {\n return null\n }\n if (!Array.isArray(parked.executions)) {\n return null\n }\n return parked as ParkedSessionRecord\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport { attachmentKind } from '@workerdeck/core'\nimport { ENGINE_CAPABILITIES, type SessionInfo } from '@workerdeck/protocol'\nimport { fail, json, readRawBody, sendUntrusted } from '../lib/http.ts'\nimport { engineOf } from '../lib/profile-env.ts'\nimport type { ServerContext } from '../context.ts'\n\nexport async function handleAttachments(\n ctx: ServerContext,\n req: IncomingMessage,\n res: ServerResponse,\n sessionId: string,\n session: SessionInfo,\n attachmentId?: string,\n): Promise<void> {\n const { attachmentStore } = ctx\n if (req.method === 'POST' && attachmentId === undefined) {\n const url = new URL(req.url ?? '/', 'http://internal')\n const mediaType = req.headers['content-type']\n if (!mediaType) {\n fail(400, 'content-type header is required')\n }\n const accepted = (session.capabilities ?? ENGINE_CAPABILITIES[engineOf(session)]).attachments\n const kind = attachmentKind(mediaType)\n if (kind && !accepted.includes(kind === 'document' ? 'pdf' : kind)) {\n fail(415, `the ${engineOf(session)} engine does not accept ${kind} attachments`)\n }\n let body: Buffer\n try {\n body = await readRawBody(req, attachmentStore.maxFileBytes)\n } catch {\n fail(413, 'attachment is larger than the limit')\n }\n const result = attachmentStore.put(sessionId, url.searchParams.get('name') ?? 'attachment', mediaType, body)\n if (!result.ok) {\n const status = result.error.code === 'unsupported_type' ? 415 : result.error.code === 'empty' ? 400 : 413\n fail(status, result.error.message)\n }\n json(res, 201, { attachment: result.attachment })\n return\n }\n if (req.method === 'GET' && attachmentId !== undefined) {\n const found = attachmentStore.get(sessionId, attachmentId)\n if (!found) {\n fail(404, 'attachment not found')\n }\n sendUntrusted(res, found.name, found.mediaType, Buffer.from(found.data, 'base64'))\n return\n }\n json(res, 405, { error: 'method not allowed' })\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { Runner } from '@workerdeck/core'\nimport type { McpServerActionRequest } from '@workerdeck/protocol'\nimport { fail, json, readJsonBody } from '../lib/http.ts'\nimport type { ServerContext } from '../context.ts'\n\nexport async function handleMcp(\n ctx: ServerContext,\n req: IncomingMessage,\n res: ServerResponse,\n runner: Runner,\n serverName?: string,\n): Promise<void> {\n if (req.method === 'GET' && serverName === undefined) {\n await listServers(res, runner)\n return\n }\n if (req.method === 'POST' && serverName !== undefined) {\n const body = (await readJsonBody(req, ctx.maxBodyBytes)) as McpServerActionRequest\n if (body?.action !== 'reconnect' && body?.action !== 'enable' && body?.action !== 'disable') {\n fail(400, \"action must be 'reconnect', 'enable' or 'disable'\")\n }\n const canAct =\n body.action === 'reconnect' ? typeof runner.reconnectMcpServer === 'function' : typeof runner.setMcpServerEnabled === 'function'\n if (!canAct) {\n fail(501, `this session's engine cannot ${body.action} an MCP server`)\n }\n try {\n if (body.action === 'reconnect') {\n await runner.reconnectMcpServer?.(serverName)\n } else {\n await runner.setMcpServerEnabled?.(serverName, body.action === 'enable')\n }\n } catch (error) {\n fail(400, error instanceof Error ? error.message : 'MCP action failed')\n }\n await listServers(res, runner)\n return\n }\n json(res, 405, { error: 'method not allowed' })\n}\n\nasync function listServers(res: ServerResponse, runner: Runner): Promise<void> {\n const servers = await runner.mcpServers?.()\n if (!servers) {\n fail(501, 'this session does not report MCP servers')\n }\n json(res, 200, { servers })\n}\n","import { createReadStream, statSync } from 'node:fs'\nimport { basename } from 'node:path'\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport { contentTypeFor, fail, json, requireMethod, untrustedDownloadHeaders } from '../lib/http.ts'\nimport type { ServerContext } from '../context.ts'\n\nexport async function handleProducedFiles(\n ctx: ServerContext,\n req: IncomingMessage,\n res: ServerResponse,\n sessionId: string,\n fileId?: string,\n): Promise<void> {\n const { producedFiles } = ctx\n requireMethod(req, 'GET')\n if (fileId === undefined) {\n json(res, 200, {\n files: producedFiles.list(sessionId).map(({ fileId: id, path, mediaType, bytes }) => ({\n fileId: id,\n path,\n ...(mediaType ? { mediaType } : {}),\n ...(bytes !== undefined ? { bytes } : {}),\n })),\n })\n return\n }\n const found = producedFiles.get(sessionId, fileId)\n if (!found) {\n fail(404, 'no such produced file')\n }\n // statSync follows symlinks deliberately: a link the engine created is part of what it produced, and there is no root to realpath against.\n let stat\n try {\n stat = statSync(found.path)\n } catch {\n fail(404, 'produced file is no longer on disk')\n }\n if (!stat.isFile()) {\n fail(404, 'produced file is not a regular file')\n }\n const filename = basename(found.path) || 'file'\n res.writeHead(200, untrustedDownloadHeaders(filename, found.mediaType ?? contentTypeFor(filename), stat.size))\n await new Promise<void>((done) => {\n const stream = createReadStream(found.path)\n stream.on('error', () => {\n res.destroy()\n done()\n })\n stream.on('close', () => done())\n stream.pipe(res)\n })\n}\n","import { createHash } from 'node:crypto'\nimport { lstatSync, realpathSync } from 'node:fs'\nimport { basename, dirname, isAbsolute, join, resolve } from 'node:path'\nimport type { ProjectIcon, ProjectInfo, SessionInfo } from '@workerdeck/protocol'\nimport { contained, readContained } from './host-files.ts'\n\nconst PROJECT_FILE = '.workerdeck.json'\nconst MAX_PROJECT_FILE_BYTES = 64 * 1024\nexport const MAX_PROJECT_ICON_BYTES = 512 * 1024\nconst MAX_NAME_CHARS = 80\nconst GLYPH_RE = /^[a-z0-9]+(-[a-z0-9]+)*$/\nconst SHORTCODE_RE = /^[A-Z0-9]{2,5}$/\n\nconst DEFAULT_TTL_MS = 30_000\nconst SWEEP_ABOVE = 256\n\ntype IconMediaType = 'image/png' | 'image/svg+xml'\n\nexport type ResolvedProjectIcon = { path: string; mediaType: IconMediaType; hash: string }\n\ntype Resolution = {\n project?: ProjectInfo\n icon?: ResolvedProjectIcon\n expiresAt: number\n}\n\nexport class ProjectInfoService {\n readonly #ttlMs: number\n readonly #decorate: (info: SessionInfo) => SessionInfo\n readonly #byCwd = new Map<string, Resolution>()\n\n // `decorate` runs after the project lookup on every info this service hands out: `withProject` is the one funnel\n // every SessionInfo leaves the server through, so the shell list rides it rather than a second call at every site.\n constructor(options: { ttlMs?: number; decorate?: (info: SessionInfo) => SessionInfo } = {}) {\n this.#ttlMs = options.ttlMs ?? DEFAULT_TTL_MS\n this.#decorate = options.decorate ?? ((info) => info)\n }\n\n withProject(info: SessionInfo): SessionInfo {\n if (!info.cwd) {\n return this.#decorate(info)\n }\n const project = this.#resolve(info.cwd).project\n return this.#decorate(project ? { ...info, project } : info)\n }\n\n iconFor(cwd: string): ResolvedProjectIcon | undefined {\n if (!cwd) {\n return undefined\n }\n return this.#resolve(cwd).icon\n }\n\n #resolve(cwd: string): Resolution {\n const now = Date.now()\n const held = this.#byCwd.get(cwd)\n if (held && held.expiresAt > now) {\n return held\n }\n if (this.#byCwd.size > SWEEP_ABOVE) {\n for (const [key, entry] of this.#byCwd) {\n if (entry.expiresAt <= now) {\n this.#byCwd.delete(key)\n }\n }\n }\n const fresh = { ...discover(cwd), expiresAt: now + this.#ttlMs }\n this.#byCwd.set(cwd, fresh)\n return fresh\n }\n}\n\nfunction discover(cwd: string): Omit<Resolution, 'expiresAt'> {\n if (!isAbsolute(cwd) || cwd.includes('\\0')) {\n return {}\n }\n let dir: string\n try {\n dir = realpathSync(cwd)\n } catch {\n return {}\n }\n for (;;) {\n const found = tryLoad(join(dir, PROJECT_FILE), dir)\n if (found) {\n return found\n }\n const parent = dirname(dir)\n if (parent === dir) {\n return {}\n }\n dir = parent\n }\n}\n\nfunction tryLoad(file: string, root: string): Omit<Resolution, 'expiresAt'> | undefined {\n let stat\n try {\n stat = lstatSync(file)\n } catch {\n return undefined\n }\n // A symlinked project file is skipped, not followed - the agent writes this tree.\n if (!stat.isFile() || stat.size > MAX_PROJECT_FILE_BYTES) {\n return undefined\n }\n const read = readContained(file)\n if (!read.ok) {\n return undefined\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(read.data.toString('utf8'))\n } catch {\n return undefined\n }\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n return undefined\n }\n const raw = parsed as { name?: unknown; icon?: unknown; shortcode?: unknown }\n const name = typeof raw.name === 'string' && raw.name.trim() ? raw.name.trim().slice(0, MAX_NAME_CHARS) : basename(root)\n const icon = classifyIcon(raw.icon, root)\n const shortcode = classifyShortcode(raw.shortcode)\n return {\n project: { name, root, ...(icon ? { icon: icon.wire } : {}), ...(shortcode ? { shortcode } : {}) },\n ...(icon?.resolved ? { icon: icon.resolved } : {}),\n }\n}\n\nfunction classifyShortcode(value: unknown): string | undefined {\n return typeof value === 'string' && SHORTCODE_RE.test(value) ? value : undefined\n}\n\nfunction classifyIcon(value: unknown, root: string): { wire: ProjectIcon; resolved?: ResolvedProjectIcon } | undefined {\n if (typeof value !== 'string') {\n return undefined\n }\n const declared = value.trim()\n if (!declared || declared.includes('\\0') || declared.length > 512) {\n return undefined\n }\n const lower = declared.toLowerCase()\n const mediaType: IconMediaType | undefined = lower.endsWith('.png') ? 'image/png' : lower.endsWith('.svg') ? 'image/svg+xml' : undefined\n if (!mediaType) {\n if (!GLYPH_RE.test(declared) || declared.length > 64) {\n return undefined\n }\n return { wire: { type: 'glyph', name: declared } }\n }\n if (isAbsolute(declared) || declared.includes('\\\\')) {\n return undefined\n }\n let canonical: string\n try {\n canonical = realpathSync(resolve(root, declared))\n } catch {\n return undefined\n }\n if (!contained(root, canonical)) {\n return undefined\n }\n let stat\n try {\n stat = lstatSync(canonical)\n } catch {\n return undefined\n }\n if (!stat.isFile() || stat.size === 0 || stat.size > MAX_PROJECT_ICON_BYTES) {\n return undefined\n }\n const read = readContained(canonical)\n if (!read.ok || read.data.length > MAX_PROJECT_ICON_BYTES) {\n return undefined\n }\n const hash = createHash('sha256').update(read.data).digest('hex')\n return {\n wire: { type: 'image', mediaType, hash },\n resolved: { path: canonical, mediaType, hash },\n }\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport { fail, requireMethod } from '../lib/http.ts'\nimport { readContained } from '../services/host-files.ts'\nimport { MAX_PROJECT_ICON_BYTES, type ProjectInfoService } from '../services/project-info.ts'\n\nexport function handleProjectIcon(projects: ProjectInfoService, req: IncomingMessage, res: ServerResponse, cwd: string): void {\n requireMethod(req, 'GET')\n const icon = projects.iconFor(cwd)\n if (!icon) {\n fail(404, 'no project icon')\n }\n const etag = `\"${icon.hash}\"`\n if (req.headers['if-none-match'] === etag) {\n res.writeHead(304, { etag })\n res.end()\n return\n }\n const read = readContained(icon.path)\n if (!read.ok || read.data.length > MAX_PROJECT_ICON_BYTES) {\n fail(404, 'no project icon')\n }\n res.writeHead(200, {\n 'content-type': icon.mediaType,\n 'content-length': read.data.length,\n etag,\n 'cache-control': 'private, max-age=300',\n 'content-disposition': 'attachment; filename=\"project-icon\"',\n 'x-content-type-options': 'nosniff',\n })\n res.end(read.data)\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { Runner } from '@workerdeck/core'\nimport { fail, json, readJsonBody, requireMethod, sendUntrusted } from '../lib/http.ts'\nimport type { SessionItemRoute } from '../lib/parse-route.ts'\nimport { shellPermitted, SHELL_REFUSAL, type ShellRegistry } from '../services/shells.ts'\nimport type { ServerContext } from '../context.ts'\n\nconst AGENT_WRITE_BODY_MAX = 1024\n\nexport async function handleShells(\n ctx: ServerContext,\n req: IncomingMessage,\n res: ServerResponse,\n route: Extract<SessionItemRoute, { kind: 'shells' }>,\n runner: Runner | null,\n operator: boolean,\n): Promise<void> {\n const { shells } = ctx\n const sessionId = route.id\n if (!shells) {\n fail(404, SHELL_REFUSAL)\n }\n // Reading a shell is reading host output: the command, the cwd and every byte it printed. `canSee` on the session is\n // not enough, because a scoped principal can see a session an operator ran `$` in. The `hostCwd` leg of\n // `shellPermitted` is about whether a `$` may *run* and needs a live runner, which a parked session has not got, so\n // reads gate on the operator leg alone and the write arms below keep the full check.\n if (!operator) {\n fail(403, SHELL_REFUSAL)\n }\n if (route.shellId === undefined) {\n requireMethod(req, 'GET')\n json(res, 200, { shells: shells.list(sessionId) })\n return\n }\n if (route.shellAction === 'kill') {\n requirePermittedPost(shells, req, runner)\n json(res, 200, { shell: found(shells.kill(sessionId, route.shellId)) })\n return\n }\n if (route.shellAction === 'agent-write') {\n const live = requirePermittedPost(shells, req, runner)\n let body: Record<string, unknown>\n try {\n body = await readJsonBody(req, AGENT_WRITE_BODY_MAX)\n } catch {\n fail(400, 'invalid JSON body')\n }\n if (typeof body.enabled !== 'boolean') {\n fail(400, 'enabled must be a boolean')\n }\n if (body.enabled && live.info().shellAgentWrite === undefined) {\n fail(409, 'the agent has no shell write tools on this session (shell.agentWrite is read-only)')\n }\n let shell\n try {\n shell = shells.setAgentWrite(sessionId, route.shellId, body.enabled)\n } catch (error) {\n fail(409, error instanceof Error ? error.message : String(error))\n }\n json(res, 200, { shell: found(shell) })\n return\n }\n requireMethod(req, 'GET')\n if (route.shellAction === 'output') {\n const url = new URL(req.url ?? '/', 'http://internal')\n const requested = url.searchParams.get('view')\n const view = requested === 'raw' || requested === 'screen' ? requested : 'text'\n const tailParam = url.searchParams.get('tail')\n const tail = tailParam === null ? undefined : Number(tailParam)\n if (tail !== undefined && (!Number.isInteger(tail) || tail <= 0)) {\n fail(400, 'tail must be a positive integer')\n }\n const output = found(await shells.output(sessionId, route.shellId, { view, tail }))\n sendUntrusted(res, `${route.shellId}.txt`, 'text/plain; charset=utf-8', Buffer.from(output, 'utf8'))\n return\n }\n json(res, 200, { shell: found(shells.get(sessionId, route.shellId)) })\n}\n\nfunction requirePermittedPost(shells: ShellRegistry, req: IncomingMessage, runner: Runner | null): Runner {\n requireMethod(req, 'POST')\n if (!runner || !shellPermitted(shells, runner, true)) {\n fail(403, SHELL_REFUSAL)\n }\n return runner\n}\n\nfunction found<T>(value: T | undefined | null): T {\n if (value === undefined || value === null) {\n fail(404, 'shell not found')\n }\n return value\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport { imagePartRef, type SessionEvent, type ToolResultBlock } from '@workerdeck/protocol'\nimport { fail, json, requireMethod, untrustedDownloadHeaders } from '../lib/http.ts'\n\n// The media type is whatever the tool claimed. Only rasters a browser cannot execute keep theirs; SVG and HTML never do.\nconst RASTER_IMAGE_TYPES = new Set(['image/png', 'image/jpeg', 'image/gif', 'image/webp'])\n\nexport type EventLookup = ((seq: number) => SessionEvent | undefined) | undefined\n\nexport function handleToolResult(req: IncomingMessage, res: ServerResponse, lookup: EventLookup, seq: number): void {\n requireMethod(req, 'GET')\n const url = new URL(req.url ?? '/', 'http://internal')\n const toolUseId = url.searchParams.get('toolUseId')\n if (!toolUseId) {\n fail(400, 'toolUseId is required')\n }\n if (!lookup) {\n fail(501, 'engine does not serve stored events')\n }\n const event = lookup(seq)\n if (!event || event.type !== 'user_message' || !Array.isArray(event.message.content)) {\n fail(404, 'no such event')\n }\n const block = event.message.content.find(\n (candidate): candidate is ToolResultBlock =>\n candidate.type === 'tool_result' && (candidate as ToolResultBlock).tool_use_id === toolUseId,\n )\n if (!block) {\n fail(404, 'no such tool result in that event')\n }\n\n const partParam = url.searchParams.get('part')\n if (partParam !== null) {\n const index = Number(partParam)\n const parts = block.content\n const part = Number.isInteger(index) && Array.isArray(parts) ? parts[index] : undefined\n const ref = part ? imagePartRef(part, index) : undefined\n if (!ref) {\n fail(404, 'no such image part in that tool result')\n }\n const source = (part as { source?: { data?: string } }).source\n const bytes = Buffer.from(source?.data ?? '', 'base64')\n const mediaType = ref.media_type.split(';')[0]!.trim().toLowerCase()\n res.writeHead(200, {\n ...untrustedDownloadHeaders(\n `tool-result-${seq}-${index}`,\n RASTER_IMAGE_TYPES.has(mediaType) ? mediaType : 'application/octet-stream',\n bytes.length,\n ),\n 'content-security-policy': \"sandbox; default-src 'none'\",\n })\n res.end(bytes)\n return\n }\n\n const content =\n url.searchParams.get('imageRefs') === '1' && Array.isArray(block.content)\n ? block.content.map((part, index) => imagePartRef(part, index) ?? part)\n : (block.content ?? '')\n json(res, 200, { seq, toolUseId, content, isError: block.is_error === true })\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { PeerSessionsResponse, ResolvePermissionRequest, SessionInfo, UpdateSessionRequest } from '@workerdeck/protocol'\nimport { contentTypeFor, fail, json, readJsonBody, requireMethod, sendUntrusted } from '../lib/http.ts'\nimport type { SessionItemRoute, SessionRoute } from '../lib/parse-route.ts'\nimport { permissionDecision } from '../lib/permissions.ts'\nimport { engineOf } from '../lib/profile-env.ts'\nimport type { AuthContext } from '../services/auth.ts'\nimport { isDormant } from '../services/session-store.ts'\nimport type { ServerContext } from '../context.ts'\nimport { vetCreateRequest } from './create-vet.ts'\nimport { handleAttachments } from './attachments.ts'\nimport { handleMcp } from './mcp.ts'\nimport { handleProducedFiles } from './produced-files.ts'\nimport { handleProjectIcon } from './project-icon.ts'\nimport { requireLive, resolveSession, type ResolvedSession } from './session-lookup.ts'\nimport { handleShells } from './shells.ts'\nimport { handleToolResult } from './tool-results.ts'\nimport { sleepRunner } from './sleep.ts'\n\ntype ItemKind = SessionItemRoute['kind']\n\ntype SessionCall<K extends ItemKind> = ResolvedSession & {\n ctx: ServerContext\n req: IncomingMessage\n res: ServerResponse\n auth: AuthContext\n route: Extract<SessionItemRoute, { kind: K }>\n}\n\ntype ItemHandlers = { [K in ItemKind]: (call: SessionCall<K>) => Promise<void> | void }\n\nconst ITEM_HANDLERS: ItemHandlers = {\n session: handleSession,\n ws: handleSession,\n attachments: ({ ctx, req, res, route, info }) => handleAttachments(ctx, req, res, route.id, info, route.attachmentId),\n mcp: ({ ctx, req, res, route, runner }) =>\n handleMcp(ctx, req, res, requireLive(runner, 'wake it before asking about MCP'), route.mcpServer),\n files: handleFiles,\n produced: ({ ctx, req, res, route }) => handleProducedFiles(ctx, req, res, route.id, route.producedFileId),\n shells: ({ ctx, req, res, route, runner, auth }) => handleShells(ctx, req, res, route, runner ?? null, ctx.auth.isOperator(auth)),\n 'stop-task': handleStopTask,\n 'background-task': handleBackgroundTask,\n 'project-icon': ({ ctx, req, res, info }) => handleProjectIcon(ctx.projects, req, res, info.cwd),\n 'tool-result': ({ req, res, route, runner, parked }) => {\n const snapshot = parked && !isDormant(parked) ? parked.snapshot.events : undefined\n handleToolResult(\n req,\n res,\n runner?.eventAt?.bind(runner) ?? (snapshot && ((seq: number) => snapshot.find((event) => event.seq === seq))),\n route.resultSeq,\n )\n },\n permission: handlePermission,\n peers: handlePeers,\n sleep: handleSleep,\n}\n\nexport async function handleSessions(\n ctx: ServerContext,\n req: IncomingMessage,\n res: ServerResponse,\n route: SessionRoute,\n auth: AuthContext,\n): Promise<void> {\n if (route.kind === 'collection') {\n await handleCollection(ctx, req, res, auth)\n return\n }\n const resolved = await resolveSession(ctx, route.id, auth)\n const handler = ITEM_HANDLERS[route.kind] as (call: SessionCall<ItemKind>) => Promise<void> | void\n await handler({ ...resolved, ctx, req, res, auth, route })\n}\n\nasync function handleCollection(ctx: ServerContext, req: IncomingMessage, res: ServerResponse, auth: AuthContext): Promise<void> {\n const { auth: authSvc, factory, parking, projects, registry } = ctx\n requireMethod(req, 'GET', 'POST')\n if (req.method === 'GET') {\n const sessions = [...registry.list(), ...(await parking.listInfo())]\n json(res, 200, {\n sessions: sessions.filter((session) => authSvc.canSee(auth, session)).map((session) => projects.withProject(session)),\n })\n return\n }\n const vetted = vetCreateRequest(ctx, await readJsonBody(req, ctx.maxBodyBytes), auth)\n if (!vetted.ok) {\n fail(vetted.status, vetted.error)\n }\n const runner = await factory.createRunner(factory.buildRunnerConfig(vetted.request, { operator: authSvc.isOperator(auth) }))\n json(res, 201, { session: projects.withProject(runner.info()) })\n}\n\nasync function handleSession({ ctx, req, res, route, runner, parked, info }: SessionCall<'session' | 'ws'>): Promise<void> {\n const { attachmentStore, bridge, parking, producedFiles, projects, registry } = ctx\n requireMethod(req, 'GET', 'PATCH', 'DELETE')\n if (req.method === 'GET') {\n json(res, 200, { session: projects.withProject(info) })\n return\n }\n if (req.method === 'PATCH') {\n const body = (await readJsonBody(req, ctx.maxBodyBytes)) as UpdateSessionRequest\n if (body?.title !== undefined && body.title !== null && typeof body.title !== 'string') {\n fail(400, 'title must be a string or null')\n }\n const title = typeof body?.title === 'string' ? body.title.trim() || undefined : undefined\n if (!runner && parked) {\n const renamed = body?.title === undefined ? parked.info : await parking.retitle(route.id, title)\n json(res, 200, { session: projects.withProject(requireRenamed(renamed)) })\n return\n }\n const live = requireLive(runner, 'wake it before renaming')\n if (body?.title !== undefined) {\n live.setTitle(title)\n parking.touch(live)\n }\n json(res, 200, { session: projects.withProject(live.info()) })\n return\n }\n registry.remove(route.id)\n bridge.remove(route.id)\n await parking.discard(route.id)\n attachmentStore.drop(route.id)\n producedFiles.drop(route.id)\n json(res, 200, {\n session: projects.withProject(runner?.info() ?? { ...parked!.info, status: 'closed' as const }),\n })\n}\n\nasync function handlePeers({ ctx, req, res, route }: SessionCall<'peers'>): Promise<void> {\n requireMethod(req, 'GET')\n if (!ctx.peers) {\n fail(404, 'peer messaging is off on this gateway')\n }\n const peers: PeerSessionsResponse['peers'] = await ctx.peers.list(route.id)\n json(res, 200, { peers })\n}\n\nfunction handleFiles({ req, res, route, runner, parked }: SessionCall<'files'>): void {\n requireMethod(req, 'GET')\n const snapshotFiles = parked && !isDormant(parked) ? parked.snapshot.vfs : undefined\n const vfs =\n runner?.vfs ??\n (snapshotFiles && {\n list: () => Object.keys(snapshotFiles).sort(),\n read: (path: string) => snapshotFiles[path]!,\n })\n if (!vfs) {\n fail(404, 'session has no file store')\n }\n if (route.filePath === undefined) {\n json(res, 200, { files: vfs.list().map((path) => ({ path, bytes: vfs.read(path)?.length ?? 0 })) })\n return\n }\n const content = vfs.read(route.filePath)\n if (content === undefined) {\n fail(404, `no such file: ${route.filePath}`)\n }\n const filename = route.filePath.split('/').pop() || 'file'\n sendUntrusted(res, filename, contentTypeFor(filename), content)\n}\n\nasync function handleStopTask({ req, res, route, runner }: SessionCall<'stop-task'>): Promise<void> {\n requireMethod(req, 'POST')\n const live = requireLive(runner, 'it has no running tasks')\n if (!live.stopTask) {\n fail(501, `the ${engineOf(live.info())} engine cannot stop a task`)\n }\n if (!(await live.stopTask(route.stopTaskId))) {\n fail(404, 'no running task to stop')\n }\n json(res, 200, { ok: true })\n}\n\nasync function handleBackgroundTask({ req, res, route, runner }: SessionCall<'background-task'>): Promise<void> {\n requireMethod(req, 'POST')\n const live = requireLive(runner, 'it has no running tasks')\n if (!live.backgroundTask) {\n fail(501, `the ${engineOf(live.info())} engine cannot move a task to the background`)\n }\n if (!(await live.backgroundTask(route.backgroundTaskId))) {\n fail(404, 'no foreground task to move to the background')\n }\n json(res, 200, { ok: true })\n}\n\n// A session that is not live has no engine child to stop, so asking it to sleep is already true.\nasync function handleSleep({ ctx, req, res, runner, info }: SessionCall<'sleep'>): Promise<void> {\n requireMethod(req, 'POST')\n if (runner) {\n await sleepRunner(runner)\n }\n json(res, 200, { session: ctx.projects.withProject(runner?.info() ?? info) })\n}\n\nasync function handlePermission({ ctx, req, res, route, runner }: SessionCall<'permission'>): Promise<void> {\n requireMethod(req, 'POST')\n const body = (await readJsonBody(req, ctx.maxBodyBytes)) as ResolvePermissionRequest\n if (body?.behavior !== 'allow' && body?.behavior !== 'deny') {\n fail(400, \"behavior must be 'allow' or 'deny'\")\n }\n const live = requireLive(runner, 'it has no pending permission requests')\n if (!live.resolvePermission(route.permissionId, permissionDecision(body))) {\n fail(404, 'permission request not found (already resolved or expired)')\n }\n json(res, 200, { resolved: true })\n}\n\nfunction requireRenamed(info: SessionInfo | undefined): SessionInfo {\n if (!info) {\n fail(409, 'session woke while renaming; retry')\n }\n return info\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport { PROTOCOL_VERSION } from '@workerdeck/protocol'\nimport type { ServerContext } from '../context.ts'\nimport { json, type Refusal } from '../lib/http.ts'\nimport { machineId } from '../lib/machine-id.ts'\nimport { parseSessionRoute } from '../lib/parse-route.ts'\nimport type { AuthContext } from '../services/auth.ts'\nimport { handleAgents } from './agents.ts'\nimport { handleExecutionResult } from './executions.ts'\nimport { handleHostFiles } from './fs.ts'\nimport { handleJobs } from './jobs.ts'\nimport { handleProfiles } from './profiles.ts'\nimport { handleSdkSessions } from './sdk-sessions.ts'\nimport { handleSessions } from './sessions.ts'\n\n// `any` is every authenticated principal; `operator` answers a non-operator with the same 404 as a missing route,\n// because those surfaces describe the gateway itself and there is nothing to filter.\nexport type RouteAuth = 'any' | 'operator'\n\nexport type RouteRefusal = Refusal\n\nexport type RouteSpec<M> = {\n match: (pathname: string, req: IncomingMessage) => M | undefined\n // Runs before authentication, so whatever it answers is answered to anyone.\n refuse?: (req: IncomingMessage, matched: M, draining: boolean) => RouteRefusal | undefined\n auth: RouteAuth\n handler: (req: IncomingMessage, res: ServerResponse, matched: M, auth: AuthContext) => Promise<void> | void\n}\n\nexport type MatchedRoute = {\n auth: RouteAuth\n refuse: (draining: boolean) => RouteRefusal | undefined\n handle: (res: ServerResponse, auth: AuthContext) => Promise<void> | void\n}\n\nexport type HttpRoute = (pathname: string, req: IncomingMessage) => MatchedRoute | undefined\n\nconst SHUTTING_DOWN: RouteRefusal = { status: 503, error: 'server is shutting down' }\nconst NOT_FOUND: RouteRefusal = { status: 404, error: 'not found' }\n\nexport function route<M>(spec: RouteSpec<M>): HttpRoute {\n return (pathname, req) => {\n const matched = spec.match(pathname, req)\n if (matched === undefined) {\n return undefined\n }\n return {\n auth: spec.auth,\n refuse: (draining) => spec.refuse?.(req, matched, draining),\n handle: (res, auth) => spec.handler(req, res, matched, auth),\n }\n }\n}\n\nexport function httpRoutes(ctx: ServerContext): HttpRoute[] {\n const base = ctx.basePath\n const under = (prefix: string) => (pathname: string) => pathname === base + prefix || pathname.startsWith(base + prefix + '/')\n return [\n route({\n match: pathWhere((pathname) => under('/jobs')(pathname) || pathname === base + '/queue'),\n refuse: (req, pathname, draining) => (draining && req.method === 'POST' && pathname === base + '/jobs' ? SHUTTING_DOWN : undefined),\n auth: 'any',\n handler: (req, res, pathname, auth) => handleJobs(ctx, req, res, pathname, auth),\n }),\n route({\n match: pathWhere(under('/profiles')),\n auth: 'any',\n handler: (req, res, pathname, auth) => handleProfiles(ctx, req, res, pathname, auth),\n }),\n route({\n match: pathWhere(under('/agents')),\n auth: 'operator',\n handler: (req, res, pathname, auth) => handleAgents(ctx, req, res, pathname, auth),\n }),\n route({\n match: pathWhere((pathname) => pathname.startsWith(base + '/executions/')),\n auth: 'any',\n handler: (req, res, pathname, auth) => handleExecutionResult(ctx, req, res, pathname, auth),\n }),\n route({\n match: pathWhere((pathname) => pathname === base + '/sdk-sessions'),\n auth: 'operator',\n handler: (req, res, _, auth) => handleSdkSessions(ctx, req, res, auth),\n }),\n route({\n match: pathWhere((pathname) => pathname === base + '/meta'),\n auth: 'any',\n // Degrades rather than refusing: the fingerprint is only ever acted on by a client that also means to read this\n // machine's files, so it is gated behind the same principal as `/fs`.\n handler: (_, res, __, auth) =>\n json(res, 200, { protocolVersion: PROTOCOL_VERSION, ...(ctx.auth.isOperator(auth) ? { machineId: machineId() } : {}) }),\n }),\n // Authenticated before the 404-when-unconfigured answer: an unauthenticated caller must not learn whether a\n // filesystem is exposed.\n route({\n match: pathWhere((pathname) => pathname.startsWith(base + '/fs/')),\n auth: 'operator',\n handler: (req, res, pathname) => handleHostFiles(ctx, req, res, pathname),\n }),\n route({\n match: (_, req) => {\n const parsed = parseSessionRoute(base, req.url ?? '/')\n return parsed && parsed.kind !== 'ws' ? parsed : undefined\n },\n // Starting a turn we have already promised to stop waiting for would make the drain unable to converge.\n // Existing sessions stay fully controllable, including approvals, which is how an operator unblocks one.\n refuse: (req, parsed, draining) => (draining && req.method === 'POST' && parsed.kind === 'collection' ? SHUTTING_DOWN : undefined),\n auth: 'any',\n handler: (req, res, parsed, auth) => handleSessions(ctx, req, res, parsed, auth),\n }),\n ]\n}\n\nexport async function dispatchRoute(\n ctx: ServerContext,\n routes: HttpRoute[],\n req: IncomingMessage,\n res: ServerResponse,\n draining: boolean,\n): Promise<void> {\n const pathname = new URL(req.url ?? '/', 'http://internal').pathname\n const matched = firstMatch(routes, pathname, req)\n if (!matched) {\n json(res, NOT_FOUND.status, { error: NOT_FOUND.error })\n return\n }\n const refusal = matched.refuse(draining)\n if (refusal) {\n json(res, refusal.status, { error: refusal.error })\n return\n }\n const auth = await ctx.auth.authenticate(req)\n if (!auth.ok) {\n json(res, 401, { error: 'unauthorized' })\n return\n }\n if (matched.auth === 'operator' && !ctx.auth.isOperator(auth)) {\n json(res, NOT_FOUND.status, { error: NOT_FOUND.error })\n return\n }\n await matched.handle(res, auth)\n}\n\nfunction firstMatch(routes: HttpRoute[], pathname: string, req: IncomingMessage): MatchedRoute | undefined {\n for (const candidate of routes) {\n const matched = candidate(pathname, req)\n if (matched) {\n return matched\n }\n }\n return undefined\n}\n\nfunction pathWhere(test: (pathname: string) => boolean): (pathname: string) => string | undefined {\n return (pathname) => (test(pathname) ? pathname : undefined)\n}\n","import { join } from 'node:path'\nimport type { AgentInfo } from '@workerdeck/protocol'\nimport { readJsonOrSync, writeJsonAtomicSync } from '../lib/atomic-file.ts'\n\nexport type StoredAgent = AgentInfo & { avatarSeed: string; avatarRecipe?: unknown }\n\nexport type AgentStore = {\n list(): StoredAgent[] | Promise<StoredAgent[]>\n save(agent: StoredAgent): void | Promise<void>\n delete(id: string): void | Promise<void>\n}\n\nexport function createMemoryAgentStore(seed: StoredAgent[] = []): AgentStore {\n const agents = new Map(seed.map((a) => [a.id, a]))\n return {\n list: () => [...agents.values()],\n save: (agent) => void agents.set(agent.id, agent),\n delete: (id) => void agents.delete(id),\n }\n}\n\nexport function createFileAgentStore(path = join(process.cwd(), '.workerdeck', 'agents.json')): AgentStore {\n const read = (): Map<string, StoredAgent> => {\n const parsed = readJsonOrSync(path, [])\n if (!Array.isArray(parsed)) {\n return new Map()\n }\n const agents = parsed as StoredAgent[]\n return new Map(agents.filter((a) => a && typeof a.id === 'string' && typeof a.name === 'string').map((a) => [a.id, a]))\n }\n const write = (agents: Map<string, StoredAgent>): void => writeJsonAtomicSync(path, [...agents.values()], { indent: 2 })\n return {\n list: () => [...read().values()],\n save: (agent) => {\n const agents = read()\n agents.set(agent.id, agent)\n write(agents)\n },\n delete: (id) => {\n const agents = read()\n if (agents.delete(id)) {\n write(agents)\n }\n },\n }\n}\n","import { randomUUID } from 'node:crypto'\nimport { attachmentKind, normalizeMediaType, type AttachmentInput } from '@workerdeck/core'\nimport type { MessageAttachment } from '@workerdeck/protocol'\n\nexport type AttachmentStoreOptions = {\n maxFileBytes?: number\n maxSessionBytes?: number\n}\n\nexport type AttachmentRejection =\n | { code: 'too_large'; message: string }\n | { code: 'session_full'; message: string }\n | { code: 'unsupported_type'; message: string }\n | { code: 'empty'; message: string }\n\nexport type PutResult = { ok: true; attachment: MessageAttachment } | { ok: false; error: AttachmentRejection }\n\nconst DEFAULT_MAX_FILE_BYTES = 10 * 1024 * 1024\nconst DEFAULT_MAX_SESSION_BYTES = 64 * 1024 * 1024\n\nexport class AttachmentStore {\n #bySession = new Map<string, Map<string, AttachmentInput>>()\n #maxFileBytes: number\n #maxSessionBytes: number\n\n constructor(options: AttachmentStoreOptions = {}) {\n this.#maxFileBytes = options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES\n this.#maxSessionBytes = options.maxSessionBytes ?? DEFAULT_MAX_SESSION_BYTES\n }\n\n get maxFileBytes(): number {\n return this.#maxFileBytes\n }\n\n put(sessionId: string, name: string, mediaType: string, body: Buffer): PutResult {\n if (body.length === 0) {\n return { ok: false, error: { code: 'empty', message: 'attachment is empty' } }\n }\n if (body.length > this.#maxFileBytes) {\n return {\n ok: false,\n error: {\n code: 'too_large',\n message: `attachment is larger than the ${this.#maxFileBytes}-byte limit`,\n },\n }\n }\n const type = normalizeMediaType(mediaType)\n if (!attachmentKind(type)) {\n return {\n ok: false,\n error: { code: 'unsupported_type', message: `unsupported media type: ${type}` },\n }\n }\n const held = this.#bySession.get(sessionId) ?? new Map<string, AttachmentInput>()\n const heldBytes = [...held.values()].reduce((sum, a) => sum + a.bytes, 0)\n if (heldBytes + body.length > this.#maxSessionBytes) {\n return {\n ok: false,\n error: {\n code: 'session_full',\n message: `session is already holding ${heldBytes} bytes of attachments (limit ${this.#maxSessionBytes})`,\n },\n }\n }\n const attachment: AttachmentInput = {\n id: randomUUID(),\n name: safeName(name),\n mediaType: type,\n bytes: body.length,\n data: body.toString('base64'),\n }\n held.set(attachment.id, attachment)\n this.#bySession.set(sessionId, held)\n return { ok: true, attachment: ref(attachment) }\n }\n\n get(sessionId: string, id: string): AttachmentInput | undefined {\n return this.#bySession.get(sessionId)?.get(id)\n }\n\n resolve(sessionId: string, ids: readonly string[]): { ok: true; attachments: AttachmentInput[] } | { ok: false; missing: string[] } {\n const held = this.#bySession.get(sessionId)\n const attachments: AttachmentInput[] = []\n const missing: string[] = []\n for (const id of ids) {\n const found = held?.get(id)\n if (found) {\n attachments.push(found)\n } else {\n missing.push(id)\n }\n }\n return missing.length ? { ok: false, missing } : { ok: true, attachments }\n }\n\n drop(sessionId: string): void {\n this.#bySession.delete(sessionId)\n }\n}\n\nfunction ref(attachment: AttachmentInput): MessageAttachment {\n return {\n id: attachment.id,\n name: attachment.name,\n mediaType: attachment.mediaType,\n bytes: attachment.bytes,\n }\n}\n\nfunction safeName(name: string): string {\n const leaf = name.split(/[/\\\\]/).pop() ?? ''\n // oxlint-disable-next-line no-control-regex\n const cleaned = leaf.replace(/[\\u0000-\\u001f\\u007f\"<>]/g, '').trim()\n if (cleaned === '' || cleaned === '.' || cleaned === '..') {\n return 'attachment'\n }\n return cleaned.length > 120 ? cleaned.slice(0, 120) : cleaned\n}\n","import type { IncomingMessage } from 'node:http'\nimport type { JobInfo, SessionInfo } from '@workerdeck/protocol'\nimport { readScope, scopeMatches } from '../lib/scope.ts'\nimport type { WorkerServerOptions } from '../options.ts'\nimport type { SessionRegistry } from './registry.ts'\n\nexport type AuthContext = {\n ok: boolean\n allowedProfiles?: string[]\n canManageProfiles?: boolean\n principal?: unknown\n scope?: Record<string, string>\n operator?: boolean\n}\n\nexport type AuthService = ReturnType<typeof createAuthService>\n\nexport function createAuthService(deps: {\n options: Pick<WorkerServerOptions, 'authenticate' | 'authorizeSession'>\n registry: SessionRegistry\n}) {\n const { options, registry } = deps\n\n const authenticate = async (req: IncomingMessage): Promise<AuthContext> => {\n if (!options.authenticate) {\n return { ok: true }\n }\n const principal = await options.authenticate(req)\n if (principal === null || principal === undefined || principal === false) {\n return { ok: false }\n }\n const allowed = (principal as { allowedProfiles?: unknown }).allowedProfiles\n const scope = readScope((principal as { scope?: unknown }).scope)\n return {\n ok: true,\n principal,\n scope: scope && Object.keys(scope).length > 0 ? scope : undefined,\n operator:\n typeof (principal as { operator?: unknown }).operator === 'boolean' ? (principal as { operator: boolean }).operator : undefined,\n allowedProfiles: Array.isArray(allowed) && allowed.every((p) => typeof p === 'string') ? (allowed as string[]) : undefined,\n canManageProfiles: (principal as { canManageProfiles?: unknown }).canManageProfiles === true,\n }\n }\n\n const canSee = (auth: AuthContext, session: SessionInfo): boolean => {\n if (!options.authorizeSession) {\n return scopeMatches(auth.scope, session.scope)\n }\n try {\n return options.authorizeSession(auth.principal, session) === true\n } catch {\n return false\n }\n }\n\n const canSeeJob = (auth: AuthContext, job: JobInfo): boolean => {\n const live = job.sessionId ? registry.get(job.sessionId)?.info() : undefined\n if (live) {\n return canSee(auth, live)\n }\n if (!options.authorizeSession) {\n return scopeMatches(auth.scope, job.scope)\n }\n return canSee(auth, {\n id: job.sessionId ?? job.id,\n status: job.status === 'running' ? 'running' : job.status === 'parked' ? 'parked' : job.status === 'queued' ? 'starting' : 'closed',\n cwd: job.cwd,\n profile: job.profile,\n createdAt: job.createdAt,\n lastSeq: 0,\n pendingPermissionCount: 0,\n scope: job.scope,\n })\n }\n\n const isOperator = (auth: AuthContext): boolean => auth.operator ?? (auth.scope === undefined && !options.authorizeSession)\n\n return { authenticate, canSee, canSeeJob, isOperator }\n}\n","import { checkClaudeAuth } from '@workerdeck/core'\nimport type { ClaudeAuthProbe, EngineAdapter, EngineAvailability } from '@workerdeck/core'\nimport type { ProfileEngine, ProfileInfo } from '@workerdeck/protocol'\nimport { engineOf } from '../lib/profile-env.ts'\nimport type { Refusal } from '../lib/http.ts'\n\nconst AVAILABILITY_TTL_MS = 60_000\n\nexport type AvailabilityTrackerOptions = {\n checkCredentials?: boolean | { probe?: ClaudeAuthProbe; timeoutMs?: number }\n requireAvailableProfile?: boolean\n adapterFor: (engine: ProfileEngine | undefined) => EngineAdapter\n sessionEnvFor: (profile: ProfileInfo) => Record<string, string | undefined>\n onError?: (error: unknown) => void\n}\n\nexport class AvailabilityTracker {\n readonly #verdicts = new Map<string, { verdict: EngineAvailability; at: number }>()\n readonly #warned = new Set<string>()\n readonly #opts: AvailabilityTrackerOptions\n\n constructor(opts: AvailabilityTrackerOptions) {\n this.#opts = opts\n }\n\n get(name: string): EngineAvailability | undefined {\n return this.#verdicts.get(name)?.verdict\n }\n\n probe(profile: ProfileInfo): void {\n const { checkCredentials, adapterFor, sessionEnvFor } = this.#opts\n if (!checkCredentials) {\n return\n }\n const conf = checkCredentials === true ? {} : checkCredentials\n // Mark in-flight immediately so concurrent GET /profiles don't re-spawn.\n this.#verdicts.set(profile.name, {\n verdict: this.#verdicts.get(profile.name)?.verdict ?? { available: 'unknown' },\n at: Date.now(),\n })\n const adapter = adapterFor(profile.engine)\n const claudeProbe: ClaudeAuthProbe | undefined =\n engineOf(profile) !== 'claude'\n ? undefined\n : (conf.probe ?? (conf.timeoutMs !== undefined ? (env) => checkClaudeAuth(env, { timeoutMs: conf.timeoutMs }) : undefined))\n const run: Promise<EngineAvailability> = claudeProbe\n ? claudeProbe(sessionEnvFor(profile)).then((status): EngineAvailability =>\n status === 'logged_in'\n ? { available: true }\n : status === 'logged_out'\n ? { available: false, reason: 'no usable Claude credentials for this profile' }\n : { available: 'unknown' },\n )\n : adapter.checkAvailability(profile, sessionEnvFor(profile))\n void run\n .then((verdict) => {\n this.#verdicts.set(profile.name, { verdict, at: Date.now() })\n if (verdict.available === false && !this.#warned.has(profile.name)) {\n this.#warned.add(profile.name)\n console.warn(\n `[workerdeck] Profile '${profile.name}' is unavailable: ${verdict.reason} ` + '(`checkCredentials: false` disables this check)',\n )\n }\n if (verdict.available === true) {\n this.#warned.delete(profile.name)\n }\n })\n .catch((error: unknown) => this.#opts.onError?.(error))\n }\n\n checkAvailable(profile: ProfileInfo | undefined): Refusal | null {\n if (!this.#opts.requireAvailableProfile || !profile) {\n return null\n }\n const verdict = this.get(profile.name)\n if (!verdict || verdict.available !== false) {\n return null\n }\n return {\n status: 503,\n error: `profile '${profile.name}' is unavailable: ${verdict.reason ?? 'no usable credentials'}`,\n }\n }\n\n preflight(profiles: ProfileInfo[]): void {\n for (const profile of profiles) {\n this.probe(profile)\n }\n }\n\n refresh(profiles: ProfileInfo[]): void {\n if (!this.#opts.checkCredentials) {\n return\n }\n const now = Date.now()\n for (const profile of profiles) {\n const cached = this.#verdicts.get(profile.name)\n if (!cached || now - cached.at > AVAILABILITY_TTL_MS) {\n this.probe(profile)\n }\n }\n }\n}\n","import type { Runner } from '@workerdeck/core'\n\nexport type EngineSleepOptions = {\n afterMs: number\n afterMsFor?: (sessionId: string) => number | undefined\n attachedCount: (sessionId: string) => number\n onError?: (error: unknown, sessionId: string) => void\n}\n\n// Armed while a live session sits idle and unwatched; one generation's timers, cleared when its server closes.\nexport class EngineSleepTimers {\n #options: EngineSleepOptions\n #timers = new Map<string, ReturnType<typeof setTimeout>>()\n #runners = new Map<string, Runner>()\n #closed = false\n\n constructor(options: EngineSleepOptions) {\n this.#options = options\n }\n\n get enabled(): boolean {\n return this.#options.afterMs > 0 && !this.#closed\n }\n\n watch(runner: Runner): (() => void) | undefined {\n if (this.#closed || !runner.sleep || (!this.enabled && !this.#options.afterMsFor)) {\n return undefined\n }\n this.#runners.set(runner.id, runner)\n const unsubscribe = runner.subscribe((event) => {\n if (event.type === 'status_changed') {\n this.#rearm(runner)\n }\n }, runner.info().lastSeq)\n this.#rearm(runner)\n return () => {\n unsubscribe()\n this.#disarm(runner.id)\n if (this.#runners.get(runner.id) === runner) {\n this.#runners.delete(runner.id)\n }\n }\n }\n\n onDetach(sessionId: string): void {\n const runner = this.#runners.get(sessionId)\n if (runner) {\n this.#rearm(runner)\n }\n }\n\n close(): void {\n this.#closed = true\n for (const timer of this.#timers.values()) {\n clearTimeout(timer)\n }\n this.#timers.clear()\n this.#runners.clear()\n }\n\n #afterMs(sessionId: string): number {\n return this.#closed ? 0 : (this.#options.afterMsFor?.(sessionId) ?? this.#options.afterMs)\n }\n\n #rearm(runner: Runner): void {\n this.#disarm(runner.id)\n const afterMs = this.#afterMs(runner.id)\n if (afterMs <= 0 || !this.#sleepable(runner)) {\n return\n }\n const timer = setTimeout(() => {\n this.#timers.delete(runner.id)\n if (this.#afterMs(runner.id) <= 0 || !this.#sleepable(runner)) {\n return\n }\n // A refusal is silent: the next idle, or the next client leaving, arms the timer again.\n runner.sleep?.().catch((error: unknown) => this.#options.onError?.(error, runner.id))\n }, afterMs)\n timer.unref?.()\n this.#timers.set(runner.id, timer)\n }\n\n #sleepable(runner: Runner): boolean {\n const info = runner.info()\n return info.status === 'idle' && info.engineAsleep !== true && this.#options.attachedCount(runner.id) === 0\n }\n\n #disarm(sessionId: string): void {\n clearTimeout(this.#timers.get(sessionId))\n this.#timers.delete(sessionId)\n }\n}\n","import type { ContextResetDirectory, ContextResetRequest, Runner } from '@workerdeck/core'\nimport type { SessionEvent } from '@workerdeck/protocol'\n\nexport type AgentContextResetOptions = {\n // Whether a session the request and profile say nothing about gets `context_reset`. Off unless set.\n default?: boolean\n minIntervalMs?: number\n maxPerHour?: number\n}\n\nexport type ContextResetServiceOptions = AgentContextResetOptions & {\n onError?: (error: unknown, sessionId: string) => void\n now?: () => number\n resetTimeoutMs?: number\n}\n\nexport const CONTEXT_RESET_MIN_INTERVAL_MS = 10 * 60_000\nexport const CONTEXT_RESET_MAX_PER_HOUR = 3\nconst HOUR_MS = 60 * 60_000\nconst RESET_TIMEOUT_MS = 60_000\n\nexport const CONTEXT_RESET_SCHEDULED =\n 'Reset scheduled. It runs when this turn ends: your conversation is cleared and your prompt becomes the first message of a ' +\n 'fresh one. End your turn now and start no new work. If the turn is interrupted or ends in an error, the reset is cancelled.'\n\n// One gateway generation's agent-requested resets: held until the requesting session's turn ends, then run as clear-then-prompt.\nexport class ContextResetService implements ContextResetDirectory {\n #options: ContextResetServiceOptions\n #runners = new Map<string, Runner>()\n #pending = new Map<string, ContextResetRequest>()\n #running = new Set<string>()\n #history = new Map<string, number[]>()\n #turnFailed = new Set<string>()\n #closed = false\n\n constructor(options: ContextResetServiceOptions = {}) {\n this.#options = options\n }\n\n get defaultEnabled(): boolean {\n return this.#options.default === true\n }\n\n watch(runner: Runner): (() => void) | undefined {\n if (this.#closed) {\n return undefined\n }\n this.#runners.set(runner.id, runner)\n const unsubscribe = runner.subscribe((event) => this.#observe(runner, event), runner.info().lastSeq)\n return () => {\n unsubscribe()\n if (this.#runners.get(runner.id) === runner) {\n this.#runners.delete(runner.id)\n this.#pending.delete(runner.id)\n }\n }\n }\n\n async request(sessionId: string, request: ContextResetRequest): Promise<string> {\n const runner = this.#runners.get(sessionId)\n if (this.#closed || !runner || runner.info().agentContextReset !== true) {\n throw new Error('context reset is not enabled for this session')\n }\n if (!runner.clearContext) {\n throw new Error('this engine cannot clear its conversation')\n }\n if (this.#pending.has(sessionId) || this.#running.has(sessionId)) {\n throw new Error('a reset is already scheduled for this session')\n }\n const refused = this.#rateRefusal(sessionId)\n if (refused) {\n throw new Error(refused)\n }\n this.#pending.set(sessionId, { prompt: request.prompt, reason: request.reason })\n this.#turnFailed.delete(sessionId)\n return CONTEXT_RESET_SCHEDULED\n }\n\n close(): void {\n this.#closed = true\n this.#pending.clear()\n this.#runners.clear()\n }\n\n #rateRefusal(sessionId: string): string | null {\n const now = this.#now()\n const minInterval = this.#options.minIntervalMs ?? CONTEXT_RESET_MIN_INTERVAL_MS\n const maxPerHour = this.#options.maxPerHour ?? CONTEXT_RESET_MAX_PER_HOUR\n const recent = (this.#history.get(sessionId) ?? []).filter((at) => now - at < HOUR_MS)\n const last = recent.at(-1)\n if (last !== undefined && now - last < minInterval) {\n return `refused: the last reset was ${minutes(now - last)} ago and resets need ${minutes(minInterval)} between them; keep working`\n }\n if (maxPerHour <= 0 || recent.length >= maxPerHour) {\n return `refused: this session already reset ${recent.length} time(s) in the last hour (limit ${maxPerHour}); keep working`\n }\n return null\n }\n\n #observe(runner: Runner, event: SessionEvent): void {\n if (!this.#pending.has(runner.id)) {\n return\n }\n if (event.type === 'turn_result' && event.isError) {\n this.#turnFailed.add(runner.id)\n return\n }\n if (event.type === 'session_closed') {\n this.#pending.delete(runner.id)\n return\n }\n if (event.type !== 'status_changed' || event.status !== 'idle') {\n return\n }\n const request = this.#pending.get(runner.id)!\n this.#pending.delete(runner.id)\n if (this.#turnFailed.delete(runner.id)) {\n return\n }\n void this.#run(runner, request)\n }\n\n async #run(runner: Runner, request: ContextResetRequest): Promise<void> {\n this.#running.add(runner.id)\n try {\n const reset = nextReset(runner, this.#options.resetTimeoutMs ?? RESET_TIMEOUT_MS)\n try {\n await runner.clearContext!({ agentReason: request.reason })\n await reset.done\n } finally {\n reset.cancel()\n }\n const history = (this.#history.get(runner.id) ?? []).filter((at) => this.#now() - at < HOUR_MS)\n history.push(this.#now())\n this.#history.set(runner.id, history)\n runner.sendMessage(request.prompt)\n } catch (error) {\n this.#options.onError?.(error, runner.id)\n } finally {\n this.#running.delete(runner.id)\n }\n }\n\n #now(): number {\n return this.#options.now?.() ?? Date.now()\n }\n}\n\nfunction nextReset(runner: Runner, timeoutMs: number): { done: Promise<void>; cancel: () => void } {\n let timer: ReturnType<typeof setTimeout> | undefined\n let unsubscribe: (() => void) | undefined\n const cancel = (): void => {\n clearTimeout(timer)\n unsubscribe?.()\n }\n const done = new Promise<void>((resolve, reject) => {\n timer = setTimeout(() => {\n cancel()\n reject(new Error('the engine did not confirm the reset'))\n }, timeoutMs)\n timer.unref?.()\n unsubscribe = runner.subscribe((event) => {\n if (event.type === 'conversation_reset') {\n cancel()\n resolve()\n }\n }, runner.info().lastSeq)\n })\n return { done, cancel }\n}\n\nfunction minutes(ms: number): string {\n const value = Math.max(1, Math.round(ms / 60_000))\n return `${value} minute${value === 1 ? '' : 's'}`\n}\n","import { BrowserBridgeExecutor, type BridgeAnswer, type ToolExecutionResult } from '@workerdeck/core'\nimport type { ServerFrame, ToolCallRequestFrame } from '@workerdeck/protocol'\n\ntype SessionBridge = {\n sockets: Array<(frame: ServerFrame) => void>\n executor: BrowserBridgeExecutor\n}\n\nexport type BridgeHubOptions = {\n timeoutMs?: number\n onResult?: (sessionId: string, executionId: string, result: ToolExecutionResult) => void\n}\n\nexport class BridgeHub {\n #sessions = new Map<string, SessionBridge>()\n #options: BridgeHubOptions\n\n constructor(options: BridgeHubOptions = {}) {\n this.#options = options\n }\n\n executorFor(sessionId: string): BrowserBridgeExecutor {\n return this.#bridge(sessionId).executor\n }\n\n attachedCount(sessionId: string): number {\n return this.#sessions.get(sessionId)?.sockets.length ?? 0\n }\n\n attach(sessionId: string, send: (frame: ServerFrame) => void): () => void {\n const bridge = this.#bridge(sessionId)\n bridge.sockets.push(send)\n return () => {\n const index = bridge.sockets.indexOf(send)\n if (index >= 0) {\n bridge.sockets.splice(index, 1)\n }\n }\n }\n\n resolve(sessionId: string, executionId: string, answer: BridgeAnswer): boolean {\n return this.#sessions.get(sessionId)?.executor.resolve(executionId, answer) ?? false\n }\n\n remove(sessionId: string): void {\n const bridge = this.#sessions.get(sessionId)\n if (!bridge) {\n return\n }\n bridge.executor.registry.cancelAll('session_closed', 'the session was closed')\n this.#sessions.delete(sessionId)\n }\n\n #bridge(sessionId: string): SessionBridge {\n const existing = this.#sessions.get(sessionId)\n if (existing) {\n return existing\n }\n const bridge: SessionBridge = {\n sockets: [],\n executor: new BrowserBridgeExecutor({\n timeoutMs: this.#options.timeoutMs,\n send: (frame: ToolCallRequestFrame) => {\n const target = bridge.sockets[0]\n if (!target) {\n return false\n }\n target(frame)\n return true\n },\n cancel: (executionId, reason) => {\n for (const send of bridge.sockets) {\n send({ type: 'tool_call_canceled', executionId, reason })\n }\n },\n onResult: (executionId, result) => {\n this.#options.onResult?.(sessionId, executionId, result)\n },\n }),\n }\n this.#sessions.set(sessionId, bridge)\n return bridge\n }\n}\n","import type { SessionInfo, SessionNotification, SessionWebhookConfig } from '@workerdeck/protocol'\nimport type { Runner } from '@workerdeck/core'\n\nexport type SessionNotificationOptions = {\n webhook?: SessionWebhookConfig\n onNotification?: (notification: SessionNotification) => void\n attempts?: number\n retryDelayMs?: number\n decorateInfo?: (info: SessionInfo) => SessionInfo\n // A throwing `onNotification`, or a webhook that failed every attempt. Delivery is best-effort either way.\n onError?: (error: unknown, context: NotificationErrorContext) => void\n}\n\nexport type NotificationErrorContext = { op: 'hook' | 'webhook'; sessionId: string }\n\nexport class SessionNotifier {\n readonly #options: SessionNotificationOptions\n readonly #chains = new Map<string, Promise<void>>()\n\n constructor(options: SessionNotificationOptions) {\n this.#options = options\n }\n\n get idle(): boolean {\n return !this.#options.webhook && !this.#options.onNotification\n }\n\n watch(runner: Runner, afterSeq = runner.info().lastSeq): () => void {\n if (this.idle) {\n return () => {}\n }\n return runner.subscribe((event) => {\n switch (event.type) {\n case 'permission_requested': {\n this.#emit(runner, event.seq, event.ts, {\n type: 'permission_requested',\n preview: event.request.title ?? event.request.toolName,\n request: event.request,\n })\n return\n }\n case 'turn_result': {\n this.#emit(runner, event.seq, event.ts, {\n type: 'turn_completed',\n preview: event.isError ? event.errors?.join('\\n') : event.result,\n result: {\n isError: event.isError,\n durationMs: event.durationMs,\n numTurns: event.numTurns,\n totalCostUsd: event.totalCostUsd,\n },\n })\n return\n }\n case 'session_error': {\n this.#emit(runner, event.seq, event.ts, {\n type: 'session_error',\n preview: event.message,\n })\n return\n }\n case 'session_closed': {\n this.#emit(runner, event.seq, event.ts, {\n type: 'session_closed',\n reason: event.reason,\n })\n return\n }\n default: {\n return\n }\n }\n }, afterSeq)\n }\n\n #emit(runner: Runner, seq: number, ts: number, body: Omit<SessionNotification, 'sessionId' | 'session' | 'seq' | 'ts'>): void {\n queueMicrotask(() => this.#send(runner, seq, ts, body))\n }\n\n #send(runner: Runner, seq: number, ts: number, body: Omit<SessionNotification, 'sessionId' | 'session' | 'seq' | 'ts'>): void {\n const webhook = this.#options.webhook\n const wanted = !webhook?.events || webhook.events.includes(body.type)\n if (!webhook && !this.#options.onNotification) {\n return\n }\n\n const notification: SessionNotification = {\n ...body,\n sessionId: runner.id,\n session: (this.#options.decorateInfo ?? ((info) => info))(runner.info()),\n seq,\n ts,\n }\n\n try {\n this.#options.onNotification?.(notification)\n } catch (error) {\n this.#options.onError?.(error, { op: 'hook', sessionId: runner.id })\n }\n\n if (!webhook || !wanted) {\n return\n }\n const previous = this.#chains.get(runner.id) ?? Promise.resolve()\n const next = previous.then(() => this.#deliver(webhook, notification))\n this.#chains.set(runner.id, next)\n void next.then(() => {\n if (this.#chains.get(runner.id) === next) {\n this.#chains.delete(runner.id)\n }\n })\n }\n\n async #deliver(webhook: SessionWebhookConfig, notification: SessionNotification): Promise<void> {\n const attempts = this.#options.attempts ?? 3\n const baseDelay = this.#options.retryDelayMs ?? 500\n let failure: unknown\n for (let attempt = 0; attempt < attempts; attempt++) {\n try {\n const res = await fetch(webhook.url, {\n method: 'POST',\n headers: { 'content-type': 'application/json', ...webhook.headers },\n body: JSON.stringify(notification),\n })\n if (res.ok) {\n return\n }\n failure = new Error(`webhook answered HTTP ${res.status}`)\n } catch (error) {\n failure = error\n }\n if (attempt < attempts - 1) {\n await new Promise((resolve) => setTimeout(resolve, baseDelay * 2 ** attempt))\n }\n }\n if (failure !== undefined) {\n this.#options.onError?.(failure, { op: 'webhook', sessionId: notification.sessionId })\n }\n }\n}\n","import type { ParkedExecution, Runner, SessionRunnerConfig, ToolExecutionResult } from '@workerdeck/core'\nimport { ENGINE_CAPABILITIES, type SessionInfo } from '@workerdeck/protocol'\nimport { engineOf } from '../lib/profile-env.ts'\nimport type { SessionRegistry } from './registry.ts'\nimport {\n isDormant,\n isLiveRecord,\n type DormantSessionRecord,\n type ParkedSessionRecord,\n type SessionStore,\n type StoredSessionRecord,\n} from './session-store.ts'\n\n// The context handed to parking's onError: which session, and which lifecycle step failed.\nexport type ParkErrorContext = { sessionId: string; phase: 'park' | 'remember' | 'resume' | 'discard' }\n\nconst SETTLED_MAX = 4096\n\nexport type SessionParkOptions = {\n registry: SessionRegistry\n store: SessionStore\n rebuild: (record: StoredSessionRecord) => Promise<Runner>\n attachedCount: (sessionId: string) => number\n parkDelayMs?: number\n persistLive?: boolean\n expiredGraceMs?: number\n onParking?: (sessionId: string, executionId: string) => boolean\n onParked?: (sessionId: string, executionId: string) => void\n onResumed?: (sessionId: string, runner: Runner) => void\n onError?: (error: unknown, context: ParkErrorContext) => void\n}\n\nexport class SessionParkManager {\n #options: SessionParkOptions\n #owners = new Map<string, string>()\n #settled = new Map<string, string>()\n #timers = new Map<string, ReturnType<typeof setTimeout>>()\n #resuming = new Map<string, Promise<Runner | undefined>>()\n #detachTimers = new Map<string, ReturnType<typeof setTimeout>>()\n #configs = new Map<string, SessionRunnerConfig>()\n #remembered = new Set<string>()\n #storeOps = new Map<string, Promise<void>>()\n #watches = new Map<string, () => void>()\n #closed = false\n\n constructor(options: SessionParkOptions) {\n this.#options = options\n }\n\n remember(sessionId: string, config: SessionRunnerConfig): void {\n this.#configs.set(sessionId, config)\n }\n\n touch(runner: Runner): void {\n void this.#rememberDormant(runner)\n void this.#persistLive(runner)\n }\n\n async hydrate(): Promise<void> {\n const floor = Date.now() + (this.#options.expiredGraceMs ?? 60_000)\n for (const record of await this.#options.store.list()) {\n if (isDormant(record)) {\n continue\n }\n for (const execution of record.executions) {\n this.#track(record.id, execution, floor)\n }\n }\n }\n\n // The unsubscribe is retained, not merely returned. Every caller drops it, and `#track` has neither the `#closed`\n // guard the writers have nor an ownership check: a deferred dispatch reaching a closed manager still arms a\n // watchdog, and when that fires it rebuilds the session through the registry and factory of a generation that is\n // over. `release()` is the only thing that can take the listener off a runner nobody closed.\n watch(runner: Runner, afterSeq = 0): () => void {\n this.#watches.get(runner.id)?.()\n const unsubscribe = runner.subscribe((event) => {\n switch (event.type) {\n case 'execution_dispatched': {\n if (!event.deferred) {\n return\n }\n this.#track(runner.id, {\n executionId: event.executionId,\n toolName: event.toolName,\n expiresAt: event.expiresAt,\n })\n return\n }\n case 'execution_result':\n case 'execution_failed': {\n this.#forget(event.executionId)\n // One call of a multi-call park settling leaves the session parked on the rest, and no new status_changed will say so.\n if (runner.info().status === 'parked') {\n this.#parkQuietly(runner)\n }\n return\n }\n case 'status_changed': {\n if (event.status === 'parked') {\n this.#parkQuietly(runner)\n } else {\n void this.#rememberDormant(runner)\n }\n return\n }\n case 'turn_result':\n case 'permission_mode_changed':\n case 'model_changed': {\n void this.#persistLive(runner)\n return\n }\n case 'system_init': {\n void this.#rememberDormant(runner)\n return\n }\n case 'conversation_reset': {\n void this.#rememberDormant(runner)\n void this.#persistLive(runner)\n return\n }\n case 'session_closed': {\n if (this.#closed) {\n return\n }\n this.discard(runner.id).catch((error: unknown) => this.#options.onError?.(error, { sessionId: runner.id, phase: 'discard' }))\n return\n }\n default: {\n return\n }\n }\n }, afterSeq)\n const detach = (): void => {\n if (this.#watches.get(runner.id) === detach) {\n this.#watches.delete(runner.id)\n }\n unsubscribe()\n }\n this.#watches.set(runner.id, detach)\n return detach\n }\n\n // Hands a live session to another manager: stops watching it, forgets what this manager knows about it, and\n // returns the one fact the next manager cannot rederive. A durable record strips `env`, `queryFn`, `historyFn`\n // and `extraOptions`, and before `system_init` there is no record at all, so `#configs` is not recoverable from\n // the store. Deliberately leaves the store alone: the record is the point of the handover, not a casualty of it.\n release(sessionId: string): SessionRunnerConfig | undefined {\n this.#watches.get(sessionId)?.()\n const config = this.#configs.get(sessionId)\n this.#forgetSession(sessionId)\n return config\n }\n\n // The order is what `#rememberDormant`'s ownership guard turns into a silent no-write if reversed: `touch()`\n // writes nothing for a runner this manager's registry does not hold, so the register comes first. `#rebuild` does\n // the same four steps for the same reason. `lastSeq`, never 0: replaying a long session's history queues one\n // dormant re-save per historical `status_changed`, and the single `touch()` is what writes the current record.\n adopt(runner: Runner, config?: SessionRunnerConfig): void {\n this.#options.registry.register(runner)\n if (config) {\n this.remember(runner.id, config)\n }\n this.watch(runner, runner.info().lastSeq)\n this.touch(runner)\n }\n\n // `touch()` is fire-and-forget for the PATCH route that has no one to report to. A caller that is about to close\n // this manager, or to let another one write the same files, needs to know the write landed.\n async flush(sessionId?: string): Promise<void> {\n if (sessionId === undefined) {\n await Promise.all(this.#storeOps.values())\n return\n }\n await this.#storeOps.get(sessionId)\n }\n\n onDetach(sessionId: string): void {\n if (this.#closed) {\n return\n }\n const runner = this.#options.registry.get(sessionId)\n if (!runner || runner.info().status !== 'parked') {\n return\n }\n clearTimeout(this.#detachTimers.get(sessionId))\n const timer = setTimeout(() => {\n this.#detachTimers.delete(sessionId)\n this.#parkQuietly(runner)\n }, this.#options.parkDelayMs ?? 2000)\n timer.unref?.()\n this.#detachTimers.set(sessionId, timer)\n }\n\n sessionFor(executionId: string): string | undefined {\n return this.#owners.get(executionId) ?? this.#settled.get(executionId)\n }\n\n get(id: string): Promise<StoredSessionRecord | null> {\n return this.#queue(id, () => this.#options.store.get(id))\n }\n\n // Renamed in place: waking an engine child to change a label is the wrong trade. Undefined once the session is live.\n retitle(id: string, title: string | undefined): Promise<SessionInfo | undefined> {\n return this.#queue(id, async () => {\n const record = await this.#options.store.get(id)\n if (!record || this.#options.registry.get(id)) {\n return undefined\n }\n const { title: previous, ...meta } = record.config.meta ?? {}\n const shown = title ?? (record.info.title === previous ? undefined : record.info.title)\n const info: SessionInfo = { ...record.info, title: shown, meta: title ? { ...record.info.meta, title } : meta }\n const config: SessionRunnerConfig = { ...record.config, meta: title ? { ...meta, title } : meta }\n await this.#options.store.save({ ...record, info, config })\n return info\n })\n }\n\n async listInfo(): Promise<SessionInfo[]> {\n await Promise.all(this.#storeOps.values())\n const records = await this.#options.store.list()\n return records\n .filter((record) => this.#options.registry.get(record.id) === undefined)\n .map((record) => (isDormant(record) ? { ...record.info, engineAsleep: true } : record.info))\n }\n\n async ensureLive(id: string): Promise<Runner | undefined> {\n const live = this.#options.registry.get(id)\n if (live) {\n return live\n }\n return this.#resume(id)\n }\n\n async submitResult(executionId: string, result: ToolExecutionResult): Promise<{ applied: boolean; sessionId: string } | undefined> {\n const sessionId = this.#owners.get(executionId)\n if (sessionId === undefined) {\n const settled = this.#settled.get(executionId)\n return settled === undefined ? undefined : { applied: false, sessionId: settled }\n }\n const runner = await this.ensureLive(sessionId)\n if (!runner) {\n this.#forget(executionId)\n return undefined\n }\n // Clear the watchdog first: settling re-enters the agent loop, and a timeout firing behind it would fail a call that no longer exists.\n this.#clearTimer(executionId)\n const applied = runner.settleExecution?.(executionId, result) ?? false\n if (applied) {\n this.#forget(executionId)\n }\n return { applied, sessionId }\n }\n\n async discard(sessionId: string): Promise<void> {\n // Dropped rather than run: `discard` is reached from the `session_closed` arm of the very subscription this\n // handle unsubscribes, and the runner drops its subscribers on close anyway.\n this.#forgetSession(sessionId)\n for (const [executionId, owner] of this.#owners) {\n if (owner === sessionId) {\n this.#forget(executionId)\n }\n }\n for (const [executionId, owner] of this.#settled) {\n if (owner === sessionId) {\n this.#settled.delete(executionId)\n }\n }\n await this.#queue(sessionId, () => this.#options.store.delete(sessionId))\n }\n\n close(): void {\n this.#closed = true\n for (const timer of this.#timers.values()) {\n clearTimeout(timer)\n }\n for (const timer of this.#detachTimers.values()) {\n clearTimeout(timer)\n }\n this.#timers.clear()\n this.#detachTimers.clear()\n }\n\n #forgetSession(sessionId: string): void {\n this.#watches.delete(sessionId)\n clearTimeout(this.#detachTimers.get(sessionId))\n this.#detachTimers.delete(sessionId)\n this.#configs.delete(sessionId)\n this.#remembered.delete(sessionId)\n }\n\n // The config of a runner this manager may still write for: open, remembered, and the registry's current object.\n #ownedConfig(runner: Runner): SessionRunnerConfig | undefined {\n if (this.#closed || this.#options.registry.get(runner.id) !== runner) {\n return undefined\n }\n return this.#configs.get(runner.id)\n }\n\n async #rememberDormant(runner: Runner): Promise<void> {\n const config = this.#ownedConfig(runner)\n const info = runner.info()\n if (!config || !(info.capabilities ?? ENGINE_CAPABILITIES[engineOf(info)]).resume) {\n return\n }\n const sdkSessionId = info.sdkSessionId\n if (sdkSessionId === undefined) {\n // Checked last, behind the ownership guard: before the engine has ever named a session there is no record to remove.\n if (this.#remembered.has(runner.id)) {\n await this.#forgetDormant(runner.id)\n }\n return\n }\n const record: DormantSessionRecord = { kind: 'dormant', ...idleRecordBase(runner, config), sdkSessionId, savedAt: Date.now() }\n try {\n // Marked before the write: a queued save already means a record may exist, and a reset arriving mid-write must not skip the forget.\n this.#remembered.add(runner.id)\n await this.#queue(runner.id, () => this.#options.store.save(record))\n } catch (error) {\n this.#options.onError?.(error, { sessionId: runner.id, phase: 'remember' })\n }\n }\n\n async #forgetDormant(sessionId: string): Promise<void> {\n this.#remembered.delete(sessionId)\n try {\n await this.#queue(sessionId, () => this.#options.store.delete(sessionId))\n } catch (error) {\n this.#options.onError?.(error, { sessionId, phase: 'remember' })\n }\n }\n\n async #persistLive(runner: Runner): Promise<void> {\n const config = this.#ownedConfig(runner)\n if (!config || !this.#options.persistLive || !runner.snapshot) {\n return\n }\n try {\n await this.#queue(runner.id, async () => {\n // Re-checked inside the queue: a park's record must not be overwritten by the live copy queued behind it.\n if (this.#closed || this.#options.registry.get(runner.id) !== runner) {\n return\n }\n const snapshot = runner.snapshot?.()\n if (!snapshot) {\n return\n }\n const record: ParkedSessionRecord = {\n kind: 'live',\n ...idleRecordBase(runner, config),\n snapshot,\n executions: snapshot.parked,\n parkedAt: Date.now(),\n }\n await this.#options.store.save(record)\n })\n } catch (error) {\n this.#options.onError?.(error, { sessionId: runner.id, phase: 'remember' })\n }\n }\n\n #parkQuietly(runner: Runner): void {\n this.#park(runner).catch((error: unknown) => this.#options.onError?.(error, { sessionId: runner.id, phase: 'park' }))\n }\n\n async #park(runner: Runner): Promise<void> {\n const config = this.#ownedConfig(runner)\n const id = runner.id\n if (!config || !runner.park || runner.info().status !== 'parked' || this.#options.attachedCount(id) > 0) {\n return\n }\n const executions = [...this.#owners].filter(([, owner]) => owner === id).map(([e]) => e)\n if (executions.length === 0) {\n return\n }\n if (this.#options.onParking && !this.#options.onParking(id, executions[0]!)) {\n return\n }\n const cost = runner.costState?.()\n const snapshot = runner.park()\n if (!snapshot) {\n return\n }\n this.#options.onParked?.(id, executions[0]!)\n const info = { ...runner.info(), status: 'parked' as const }\n this.#options.registry.evict(id)\n const record: ParkedSessionRecord = {\n kind: 'parked',\n id,\n info,\n profile: info.profile,\n config,\n snapshot,\n executions: snapshot.parked,\n cost,\n parkedAt: Date.now(),\n }\n for (const execution of snapshot.parked) {\n this.#track(id, execution)\n }\n try {\n await this.#queue(id, () => this.#options.store.save(record))\n } catch (error) {\n this.#options.onError?.(error, { sessionId: id, phase: 'park' })\n }\n }\n\n async #resume(id: string): Promise<Runner | undefined> {\n const inFlight = this.#resuming.get(id)\n if (inFlight) {\n return inFlight\n }\n const attempt = this.#rebuild(id)\n this.#resuming.set(id, attempt)\n try {\n return await attempt\n } finally {\n this.#resuming.delete(id)\n }\n }\n\n async #rebuild(id: string): Promise<Runner | undefined> {\n const record = await this.#queue(id, () => this.#options.store.get(id))\n if (!record) {\n return undefined\n }\n let runner: Runner\n try {\n runner = await this.#options.rebuild(record)\n } catch (error) {\n this.#options.onError?.(error, { sessionId: id, phase: 'resume' })\n throw error\n }\n if (runner.id !== id) {\n runner.close('error')\n const error = new Error(\n `rebuilt session has id '${runner.id}', expected '${id}' - the engine factory must ` +\n 'forward EngineRunnerContext.restore (or, without a snapshot, the session id) ' +\n 'to the runner config',\n )\n this.#options.onError?.(error, { sessionId: id, phase: 'resume' })\n throw error\n }\n runner.carryCost?.(record.cost ?? { byModel: record.info.usageByModel, reportedCostUsd: record.info.totalCostUsd })\n this.#options.registry.register(runner)\n // The config the runner was actually built with, not the one on the record: a dormant wake\n // bumps the epoch, and the next park must carry the new one rather than resurrect the old.\n this.remember(id, { ...record.config, epoch: runner.info().epoch })\n // A park must not re-arm watchdogs from its own replayed events; a dormant session starts a fresh log, so it has no prior seq to skip.\n this.watch(runner, isDormant(record) ? 0 : record.snapshot.seq)\n this.#options.onResumed?.(id, runner)\n if (!isDormant(record) && !isLiveRecord(record)) {\n await this.#queue(id, () => this.#options.store.delete(id))\n }\n void runner.start()\n return runner\n }\n\n #queue<T>(sessionId: string, op: () => Promise<T>): Promise<T> {\n const previous = this.#storeOps.get(sessionId) ?? Promise.resolve()\n const result = previous.then(op)\n const settled = result.then(\n () => {},\n () => {},\n )\n this.#storeOps.set(sessionId, settled)\n void settled.then(() => {\n if (this.#storeOps.get(sessionId) === settled) {\n this.#storeOps.delete(sessionId)\n }\n })\n return result\n }\n\n #track(sessionId: string, execution: ParkedExecution, notBefore = 0): void {\n this.#owners.set(execution.executionId, sessionId)\n if (execution.expiresAt === undefined || this.#timers.has(execution.executionId)) {\n return\n }\n const expiresAt = Math.max(execution.expiresAt, notBefore)\n const timer = setTimeout(\n () => {\n this.#timers.delete(execution.executionId)\n void this.submitResult(execution.executionId, {\n status: 'failed',\n reason: 'timeout',\n error: `deferred execution '${execution.toolName}' produced no result before its deadline`,\n }).catch((error: unknown) => {\n this.#options.onError?.(error, { sessionId, phase: 'resume' })\n })\n },\n Math.max(0, expiresAt - Date.now()),\n )\n timer.unref?.()\n this.#timers.set(execution.executionId, timer)\n }\n\n #forget(executionId: string): void {\n this.#clearTimer(executionId)\n const owner = this.#owners.get(executionId)\n if (owner !== undefined) {\n this.#settled.set(executionId, owner)\n if (this.#settled.size > SETTLED_MAX) {\n this.#settled.delete(this.#settled.keys().next().value!)\n }\n }\n this.#owners.delete(executionId)\n }\n\n #clearTimer(executionId: string): void {\n const timer = this.#timers.get(executionId)\n if (timer === undefined) {\n return\n }\n clearTimeout(timer)\n this.#timers.delete(executionId)\n }\n}\n\n// What a dormant and a live record share: the session as it would list while nothing runs it, and the config it was\n// built with plus the metadata it has gathered since.\nfunction idleRecordBase(\n runner: Runner,\n config: SessionRunnerConfig,\n): Pick<ParkedSessionRecord, 'id' | 'info' | 'profile' | 'config' | 'cost'> {\n const { engineAsleep: _engineAsleep, ...info } = runner.info()\n return {\n id: runner.id,\n info: { ...info, status: 'idle' },\n profile: info.profile,\n config: { ...config, meta: info.meta },\n cost: runner.costState?.(),\n }\n}\n","import type { Runner } from '@workerdeck/core'\n\nexport type ProducedFile = {\n fileId: string\n path: string\n mediaType?: string\n bytes?: number\n sessionId: string\n}\n\nexport class ProducedFileStore {\n #bySession = new Map<string, Map<string, ProducedFile>>()\n\n watch(runner: Runner): () => void {\n return runner.subscribe((event) => {\n if (event.type !== 'file_produced') {\n return\n }\n const held = this.#bySession.get(runner.id) ?? new Map<string, ProducedFile>()\n held.set(event.fileId, {\n fileId: event.fileId,\n path: event.path,\n ...(event.mediaType ? { mediaType: event.mediaType } : {}),\n ...(event.bytes !== undefined ? { bytes: event.bytes } : {}),\n sessionId: runner.id,\n })\n this.#bySession.set(runner.id, held)\n }, 0)\n }\n\n get(sessionId: string, fileId: string): ProducedFile | undefined {\n return this.#bySession.get(sessionId)?.get(fileId)\n }\n\n list(sessionId: string): ProducedFile[] {\n return [...(this.#bySession.get(sessionId)?.values() ?? [])]\n }\n\n drop(sessionId: string): void {\n this.#bySession.delete(sessionId)\n }\n}\n","import { existsSync } from 'node:fs'\nimport { supportsPermissionMode, type ProfileEngine, type ProfileInfo } from '@workerdeck/protocol'\nimport type { EngineAdapter, EngineAvailability } from '@workerdeck/core'\nimport type { Refusal } from '../lib/http.ts'\nimport { cwdAllowed, engineOf, isProviderProfile } from '../lib/profile-env.ts'\nimport type { ProfileStore } from './profile-store.ts'\n\nexport type { Refusal }\n\nexport type ProfileServiceOptions = {\n declared: ProfileInfo[]\n seed?: ProfileInfo[]\n store?: ProfileStore\n allowedConfigDirRoots?: string[]\n disableBypassPermissions?: boolean\n hasEngineRunnerFactory: boolean\n adapterFor: (engine: ProfileEngine | undefined) => EngineAdapter\n decorate: {\n defaultModel: (name: string) => string | undefined\n availability: (name: string) => EngineAvailability | undefined\n usage: (name: string) => ProfileInfo['usage'] | undefined\n spend?: (name: string) => ProfileInfo['spend'] | undefined\n }\n}\n\nexport class ProfileService {\n readonly #declared: ProfileInfo[]\n readonly #declaredByName: Map<string, ProfileInfo>\n readonly #stored = new Map<string, ProfileInfo>()\n readonly #opts: ProfileServiceOptions\n\n constructor(opts: ProfileServiceOptions) {\n this.#opts = opts\n this.#declared = opts.declared\n this.#declaredByName = new Map(opts.declared.map((p) => [p.name, p]))\n if (this.#declaredByName.size !== opts.declared.length) {\n throw new Error('createWorkerServer: duplicate profile names in `profiles`')\n }\n }\n\n validate(p: ProfileInfo): string | null {\n const { adapterFor, disableBypassPermissions, hasEngineRunnerFactory } = this.#opts\n if (isProviderProfile(p)) {\n if (!p.provider?.id) {\n return `provider profile '${p.name}' is missing provider.id`\n }\n if (!hasEngineRunnerFactory) {\n return `profile '${p.name}' uses engine 'provider' but no ` + '`createEngineRunner` was provided to build one'\n }\n } else if (p.engine === 'codex') {\n if (p.codexHome && !existsSync(p.codexHome)) {\n return `profile '${p.name}' codexHome does not exist: ${p.codexHome}`\n }\n } else if (!p.configDir || !existsSync(p.configDir)) {\n return `profile '${p.name}' configDir does not exist: ${p.configDir}`\n }\n if (disableBypassPermissions && p.defaults?.permissionMode === 'bypassPermissions') {\n return `profile '${p.name}' defaults to bypassPermissions but disableBypassPermissions is set`\n }\n const efforts = p.defaults?.efforts\n if (efforts !== undefined && !isEffortMap(efforts)) {\n return `profile '${p.name}' defaults.efforts must map model names to effort levels`\n }\n const fallbackMode = p.defaults?.permissionMode\n if (fallbackMode && !supportsPermissionMode(p.engine, fallbackMode)) {\n return (\n `profile '${p.name}' defaults to permission mode '${fallbackMode}', which engine ` +\n `'${engineOf(p)}' does not support (supported: ` +\n `${adapterFor(engineOf(p)).capabilities.permissionModes.join(', ')})`\n )\n }\n return null\n }\n\n async refreshStored(): Promise<void> {\n if (!this.#opts.store) {\n return\n }\n this.#stored.clear()\n for (const p of await this.#opts.store.list()) {\n this.#stored.set(p.name, p)\n }\n }\n\n // Auto-detected profiles land in the store, not in `declared`, so the first thing an operator sees\n // is a profile they can rename, retarget or delete. Seeding only an empty store is what keeps it a\n // first-launch act: once a profile exists, detection never writes again.\n async seedStore(): Promise<void> {\n const seed = this.#opts.seed ?? []\n if (!this.#opts.store || seed.length === 0 || this.#stored.size > 0) {\n return\n }\n for (const p of seed) {\n if (this.validate(p) === null) {\n await this.#opts.store.save(p)\n }\n }\n await this.refreshStored()\n }\n\n withManagedFlag(p: ProfileInfo): ProfileInfo {\n return this.#declaredByName.has(p.name) ? p : { ...p, managed: true }\n }\n\n forResponse(p: ProfileInfo): ProfileInfo {\n const { adapterFor, decorate } = this.#opts\n const adapter = adapterFor(p.engine)\n const base: ProfileInfo = {\n ...this.withManagedFlag(p),\n capabilities: adapter.capabilities,\n }\n if (adapter.catalog.models.length > 0) {\n base.models = adapter.catalog.models\n }\n const defaultModel = decorate.defaultModel(p.name)\n if (defaultModel) {\n base.defaultModel = defaultModel\n }\n const probed = decorate.availability(p.name)\n if (probed && probed.available !== 'unknown') {\n base.available = probed.available\n if (probed.available === false) {\n base.unavailableReason = probed.reason\n }\n }\n const usage = decorate.usage(p.name)\n if (usage) {\n base.usage = usage\n }\n const spend = decorate.spend?.(p.name)\n if (spend) {\n base.spend = spend\n }\n return base\n }\n\n all(): ProfileInfo[] {\n return [...this.#declared, ...[...this.#stored.values()].filter((p) => !this.#declaredByName.has(p.name))]\n }\n\n get(name: string): ProfileInfo | undefined {\n return this.#declaredByName.get(name) ?? this.#stored.get(name)\n }\n\n manageGuard(auth: { canManageProfiles?: boolean }): Refusal | null {\n if (!this.#opts.store) {\n return { status: 404, error: 'profile management is not enabled on this server' }\n }\n if (!auth.canManageProfiles) {\n return { status: 403, error: 'not allowed to manage profiles' }\n }\n return null\n }\n\n declaredGuard(profile: ProfileInfo): Refusal | null {\n return this.#declaredByName.has(profile.name)\n ? {\n status: 403,\n error:\n `profile '${profile.name}' is declared in server options and cannot be changed ` +\n 'over the API - edit the `profiles` option instead',\n }\n : null\n }\n\n configDirGuard(profile: ProfileInfo): Refusal | null {\n if (isProviderProfile(profile)) {\n return null\n }\n const codex = engineOf(profile) === 'codex'\n const dir = codex ? profile.codexHome : profile.configDir\n // A codex profile that names no CODEX_HOME runs on the server's own environment, which every\n // session already inherits - there is no separate credential store for the roots to bound.\n if (codex && !dir) {\n return null\n }\n const roots = this.#opts.allowedConfigDirRoots\n if (!roots || roots.length === 0) {\n return {\n status: 403,\n error: 'managed Claude and Codex profiles are disabled: set `allowedConfigDirRoots` to the ' + 'directories they may point at',\n }\n }\n return dir && cwdAllowed(dir, roots)\n ? null\n : { status: 403, error: `${codex ? 'codexHome' : 'configDir'} is outside the allowed roots` }\n }\n\n async saveManaged(incoming: ProfileInfo): Promise<{ ok: true; profile: ProfileInfo } | ({ ok: false } & Refusal)> {\n const { managed: _clientClaim, ...profile } = incoming\n const refused = this.configDirGuard(profile)\n if (refused) {\n return { ok: false, ...refused }\n }\n const invalid = this.validate(profile)\n if (invalid) {\n return { ok: false, status: 400, error: invalid }\n }\n await this.#opts.store!.save(profile)\n await this.refreshStored()\n return { ok: true, profile: this.withManagedFlag(profile) }\n }\n}\n\nexport function isEffortMap(value: unknown): value is Record<string, string> {\n return (\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n Object.entries(value).every(([model, effort]) => model !== '' && typeof effort === 'string' && effort !== '')\n )\n}\n","import type { Runner } from '@workerdeck/core'\nimport type { ProfileUsage, ProfileUsageWindow, RateLimitInfo } from '@workerdeck/protocol'\n\ntype HeldWindow = { info: RateLimitInfo; updatedAt: number }\n\nexport class ProfileUsageTracker {\n #profiles = new Map<string, Map<string, HeldWindow>>()\n\n watch(runner: Runner): () => void {\n const profile = runner.info().profile\n if (!profile) {\n return () => {}\n }\n return runner.subscribe((event) => {\n if (event.type !== 'rate_limit') {\n return\n }\n const type = event.info.rateLimitType\n if (!type) {\n return\n }\n let windows = this.#profiles.get(profile)\n if (!windows) {\n this.#profiles.set(profile, (windows = new Map()))\n }\n const held = windows.get(type)\n if (held && held.updatedAt > event.ts) {\n return\n }\n windows.set(type, { info: event.info, updatedAt: event.ts })\n })\n }\n\n usage(profile: string, now = Date.now()): ProfileUsage | undefined {\n const windows = this.#profiles.get(profile)\n if (!windows || windows.size === 0) {\n return undefined\n }\n const out: ProfileUsage = {}\n for (const [type, held] of windows) {\n out[type] = serveWindow(held, now)\n }\n return out\n }\n}\n\n// `resetsAt` is epoch seconds (protocol contract); `now` is epoch ms.\nfunction serveWindow(held: HeldWindow, now: number): ProfileUsageWindow {\n const resetsAt = held.info.resetsAt\n if (resetsAt !== undefined && resetsAt * 1000 <= now) {\n return {\n info: {\n // The dropped `resetsAt`/`isUsingOverage` describe the window that rolled, not this one.\n status: 'allowed',\n rateLimitType: held.info.rateLimitType,\n utilization: 0,\n },\n updatedAt: held.updatedAt,\n inferredReset: true,\n }\n }\n return { info: held.info, updatedAt: held.updatedAt }\n}\n","import type { Runner } from '@workerdeck/core'\nimport {\n type ByModel,\n type PricingTable,\n type ProfileSpend,\n costOfByModel,\n mergeByModel,\n subscriptionComparison,\n} from '@workerdeck/protocol'\nimport { readJsonOr, writeJsonAtomic } from '../lib/atomic-file.ts'\n\nexport type SpendRecord = { days: Record<string, Record<string, ByModel>> }\n\nexport type SpendStore = {\n load(): Promise<SpendRecord | undefined>\n save(record: SpendRecord): Promise<void>\n}\n\nexport type SpendLedgerOptions = {\n pricing?: PricingTable\n store?: SpendStore\n monthlySubscriptionUsd?: (profile: string) => number | undefined\n retentionDays?: number\n saveDebounceMs?: number\n onError?: (error: unknown) => void\n}\n\nconst DEFAULT_RETENTION_DAYS = 92\n\nconst DEFAULT_SAVE_DEBOUNCE_MS = 2_000\n\nexport function dayKey(at: number): string {\n const d = new Date(at)\n return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`\n}\n\nfunction daysBack(now: number, count: number): string[] {\n const out: string[] = []\n for (let i = 0; i < count; i += 1) {\n out.push(dayKey(now - i * 86_400_000))\n }\n return out\n}\n\nfunction subtract(current: ByModel, previous: ByModel): ByModel {\n const delta: ByModel = {}\n for (const [model, usage] of Object.entries(current)) {\n const was = previous[model]\n const row = {\n input: usage.input - (was?.input ?? 0),\n output: usage.output - (was?.output ?? 0),\n cacheWrite5m: usage.cacheWrite5m - (was?.cacheWrite5m ?? 0),\n cacheWrite1h: usage.cacheWrite1h - (was?.cacheWrite1h ?? 0),\n cacheRead: usage.cacheRead - (was?.cacheRead ?? 0),\n }\n // A negative delta means the session's cumulative figure went backwards, which only happens when the reading\n // we diffed against was not this session's. Recording nothing beats recording a negative day.\n if (Object.values(row).some((value) => value < 0)) {\n continue\n }\n if (Object.values(row).some((value) => value > 0)) {\n delta[model] = row\n }\n }\n return delta\n}\n\n// `turn_result.usageByModel` is session-cumulative, so the ledger records the difference from what this session\n// last contributed. The baseline is seeded from the runner's own info at watch time, which is what keeps a woken\n// session's carried spend from being banked a second time as if it had just been earned.\nexport class SpendLedger {\n #days: Record<string, Record<string, ByModel>> = {}\n #lastBanked = new Map<string, ByModel>()\n #options: SpendLedgerOptions\n #saveTimer: ReturnType<typeof setTimeout> | undefined\n #loaded: Promise<void> | undefined\n\n constructor(options: SpendLedgerOptions = {}) {\n this.#options = options\n }\n\n load(): Promise<void> {\n this.#loaded ??= this.#load()\n return this.#loaded\n }\n\n async #load(): Promise<void> {\n const store = this.#options.store\n if (!store) {\n return\n }\n try {\n const record = await store.load()\n if (record?.days) {\n this.#days = record.days\n }\n } catch (error) {\n this.#options.onError?.(error)\n }\n }\n\n watch(runner: Runner): () => void {\n const info = runner.info()\n const profile = info.profile\n if (!profile) {\n return () => {}\n }\n this.#lastBanked.set(runner.id, info.usageByModel ?? {})\n const unsubscribe = runner.subscribe((event) => {\n if (event.type !== 'turn_result' || !event.usageByModel) {\n return\n }\n this.#bank(profile, event.usageByModel, runner.id, event.ts)\n })\n return () => {\n unsubscribe()\n this.#lastBanked.delete(runner.id)\n }\n }\n\n #bank(profile: string, cumulative: ByModel, sessionId: string, at: number): void {\n const previous = this.#lastBanked.get(sessionId) ?? {}\n const delta = subtract(cumulative, previous)\n this.#lastBanked.set(sessionId, cumulative)\n if (Object.keys(delta).length === 0) {\n return\n }\n const key = dayKey(at)\n const day = (this.#days[key] ??= {})\n day[profile] = mergeByModel(day[profile] ?? {}, delta)\n this.#scheduleSave()\n }\n\n spend(profile: string, now = Date.now()): ProfileSpend | undefined {\n const week = this.#window(profile, daysBack(now, 7))\n const month = this.#window(profile, daysBack(now, 30))\n if (Object.keys(month).length === 0) {\n return undefined\n }\n const weekCost = costOfByModel(week, this.#options.pricing)\n const monthlySubscriptionUsd = this.#options.monthlySubscriptionUsd?.(profile)\n return {\n weekUsd: weekCost.total,\n monthUsd: costOfByModel(month, this.#options.pricing).total,\n weekByModel: week,\n unpricedShare: weekCost.unpricedShare,\n monthlySubscriptionUsd,\n subscription: monthlySubscriptionUsd ? subscriptionComparison(weekCost.total, monthlySubscriptionUsd) : undefined,\n }\n }\n\n #window(profile: string, keys: string[]): ByModel {\n let out: ByModel = {}\n for (const key of keys) {\n const day = this.#days[key]?.[profile]\n if (day) {\n out = mergeByModel(out, day)\n }\n }\n return out\n }\n\n #scheduleSave(): void {\n if (!this.#options.store || this.#saveTimer) {\n return\n }\n this.#saveTimer = setTimeout(() => {\n this.#saveTimer = undefined\n void this.flush()\n }, this.#options.saveDebounceMs ?? DEFAULT_SAVE_DEBOUNCE_MS)\n this.#saveTimer.unref?.()\n }\n\n async flush(): Promise<void> {\n const store = this.#options.store\n if (!store) {\n return\n }\n this.#prune()\n try {\n await store.save({ days: this.#days })\n } catch (error) {\n this.#options.onError?.(error)\n }\n }\n\n #prune(): void {\n const keep = new Set(daysBack(Date.now(), this.#options.retentionDays ?? DEFAULT_RETENTION_DAYS))\n for (const key of Object.keys(this.#days)) {\n if (!keep.has(key)) {\n delete this.#days[key]\n }\n }\n }\n\n close(): void {\n clearTimeout(this.#saveTimer)\n this.#saveTimer = undefined\n }\n}\n\nexport function createFileSpendStore(path: string, onError?: (error: unknown) => void): SpendStore {\n return {\n async load() {\n const parsed = await readJsonOr(path, undefined)\n if (parsed === null || typeof parsed !== 'object' || typeof (parsed as SpendRecord).days !== 'object') {\n return undefined\n }\n return parsed as SpendRecord\n },\n async save(record) {\n try {\n await writeJsonAtomic(path, record)\n } catch (error) {\n onError?.(error)\n }\n },\n }\n}\n","import { readFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport type { PeerDirectory, PeerPeek, PeerSendResult, PeerSessionSummary } from '@workerdeck/core'\nimport type { ChecklistItem } from '@workerdeck/protocol'\nimport {\n connectRelay,\n parseRelayPeerId,\n type RelayConnection,\n type RelayHost,\n type RelayOp,\n type RelayPeek,\n type RelayPeerRow,\n} from '@workerdeck/relay-client'\nimport type { PeerService } from './peers.ts'\n\nexport type RelayLinkOptions = {\n url: string\n gateway: string\n key?: string\n keyFile?: string\n caFile?: string\n // The gateway ceiling. Sessions outside `scope` are never published and never answer a relay-routed request;\n // `allow` is what this gateway accepts from other gateways at all, whatever the relay's rules say.\n expose?: { scope?: Record<string, string>; allow?: RelayOp[] }\n log?: (message: string) => void\n}\n\nexport type RelayLink = {\n directory: PeerDirectory\n nudge(): void\n // Hands the connection to the next module generation instead of closing it (hot reload).\n release(): void\n close(): void\n}\n\ntype Carried = { identity: string; connection: RelayConnection }\n\n// Keyed through `Symbol.for`, so the generation a hot reload builds finds what the old one released.\nconst CARRIED = Symbol.for('workerdeck.relay.carried')\nconst slots = globalThis as { [CARRIED]?: Carried }\n\nconst UNAVAILABLE = 'Remote gateways are unavailable right now; only sessions on this gateway are listed.'\n\nfunction expandHome(path: string): string {\n return path === '~' || path.startsWith('~/') ? `${homedir()}${path.slice(1)}` : path\n}\n\nfunction identityOf(options: RelayLinkOptions): string {\n return JSON.stringify([\n options.url,\n options.gateway,\n options.keyFile ?? '',\n options.key ? 'inline' : '',\n options.caFile ?? '',\n options.expose?.allow ?? null,\n ])\n}\n\nfunction remoteSummary(row: RelayPeerRow): PeerSessionSummary {\n return {\n id: `${row.gateway}:${row.id}`,\n gateway: row.gateway,\n engine: row.engine,\n status: row.status,\n title: row.title,\n project: row.project?.name,\n projectRoot: row.project?.root,\n cwd: row.cwd,\n profile: row.profile,\n model: row.model,\n contextUsage: row.contextUsage,\n lastActivityAt: row.lastActivityAt,\n pendingPermissionCount: row.pendingPermissionCount,\n allow: row.allow,\n }\n}\n\nfunction remotePeek(gateway: string, peek: RelayPeek): PeerPeek {\n const { allow: _allow, ...summary } = remoteSummary({ ...peek, gateway, allow: [] })\n return {\n ...summary,\n live: peek.live,\n checklist: peek.checklistItems as ChecklistItem[] | undefined,\n pendingApprovals: peek.pendingApprovals,\n recent: peek.recent,\n }\n}\n\nexport async function readRelayKey(options: RelayLinkOptions): Promise<string> {\n if (options.key) {\n return options.key\n }\n if (!options.keyFile) {\n throw new Error('relay: set relay.keyFile (or WORKERDECK_RELAY_KEY) to the key `workerdeck relay enroll` printed')\n }\n const key = (await readFile(expandHome(options.keyFile), 'utf8')).trim()\n if (!key) {\n throw new Error(`relay: ${options.keyFile} is empty`)\n }\n return key\n}\n\n// The local peer directory with the relay composed in: bare ids stay local, `gateway:session` ids go to the relay.\n// A scoped session never reaches past its own gateway, because nothing on the wire carries scope tags.\nexport function createRelayLink(options: RelayLinkOptions, peers: PeerService, log: (message: string) => void): RelayLink {\n const identity = identityOf(options)\n const exposed = options.expose?.scope\n let connection: RelayConnection | undefined\n let closed = false\n let released = false\n\n const host: RelayHost = {\n snapshot: () => peers.relayEntries(exposed),\n peek: (_origin, sessionId, recent) => peers.relayPeek(sessionId, recent, exposed),\n send: (origin, sessionId, text) => peers.relaySend(origin, sessionId, text, exposed),\n }\n\n const carried = slots[CARRIED]\n if (carried) {\n delete slots[CARRIED]\n if (carried.identity === identity && carried.connection.state() !== 'stopped') {\n carried.connection.setHost(host)\n connection = carried.connection\n } else {\n carried.connection.close()\n }\n }\n\n if (!connection) {\n void (async () => {\n const key = await readRelayKey(options)\n const ca = options.caFile ? await readFile(expandHome(options.caFile)) : undefined\n if (!closed) {\n connection = connectRelay({ url: options.url, gateway: options.gateway, key, ca, allow: options.expose?.allow, log }, host)\n }\n })().catch((error: unknown) => log(error instanceof Error ? error.message : String(error)))\n }\n\n const remoteTarget = parseRelayPeerId\n\n const reachesRemote = async (from: string): Promise<boolean> => {\n const me = await peers.relaySender(from)\n return (me.scope === undefined || Object.keys(me.scope).length === 0) && me.agent?.lead === undefined\n }\n\n const directory: PeerDirectory = {\n list: async (from) => {\n const local = await peers.list(from)\n if (!connection || connection.state() !== 'online' || !(await reachesRemote(from))) {\n return local\n }\n try {\n return [...local, ...(await connection.list(from)).map(remoteSummary)]\n } catch {\n return local\n }\n },\n notice: async (from) => {\n if (!(await reachesRemote(from))) {\n return undefined\n }\n return connection?.state() === 'online' ? undefined : UNAVAILABLE\n },\n peek: async (from, sessionId, peekOptions) => {\n const target = remoteTarget(sessionId)\n if (!target) {\n return peers.peek(from, sessionId, peekOptions)\n }\n if (!connection || !(await reachesRemote(from))) {\n return undefined\n }\n const peek = await connection.peek(from, target, peekOptions?.recent)\n return peek ? remotePeek(target.gateway, peek) : undefined\n },\n send: async (from, sessionId, text, sendOptions): Promise<PeerSendResult> => {\n const target = remoteTarget(sessionId)\n if (!target) {\n return peers.send(from, sessionId, text, sendOptions)\n }\n if (!(await reachesRemote(from))) {\n return { delivered: false, reason: `no such session: ${sessionId}` }\n }\n if (!connection || connection.state() !== 'online') {\n return { delivered: false, reason: 'remote gateways are unavailable right now; try again later' }\n }\n try {\n const result = await connection.send(from, target, text, sendOptions?.hops ?? peers.relayChain(from))\n return result.delivered ? { ...result, sessionId } : result\n } catch (error) {\n return { delivered: false, reason: error instanceof Error ? error.message : String(error) }\n }\n },\n }\n\n return {\n directory,\n nudge: () => connection?.nudge(),\n release: () => {\n if (connection && !closed) {\n released = true\n slots[CARRIED] = { identity, connection }\n }\n },\n close: () => {\n closed = true\n if (!released) {\n connection?.close()\n }\n connection = undefined\n },\n }\n}\n","import { SessionRunner, type Runner, type SessionRunnerConfig } from '@workerdeck/core'\nimport type { SessionInfo } from '@workerdeck/protocol'\n\nexport type SessionRegistryOptions = {\n // A returned function is a detach: run when the runner leaves this registry, whether it was closed or handed to\n // another one. Typed `unknown` rather than `void | (() => void)` on purpose: TypeScript only forgives a\n // non-void return against a bare `void`, so the narrower union would break every embedder whose hook is a\n // one-expression arrow (`(r) => seen.push(r)`). The function check is at the retaining end instead.\n onRegister?: (runner: Runner) => unknown\n}\n\nexport class SessionRegistry {\n #sessions = new Map<string, Runner>()\n #options: SessionRegistryOptions\n #observers = new Set<(runner: Runner) => unknown>()\n // The watchers a registration attached, kept because the objects that attached them are exactly what a hot\n // reload discards: nobody else is in a position to take them off a runner that outlives its generation.\n #detachers = new Map<string, (() => void)[]>()\n\n constructor(options: SessionRegistryOptions = {}) {\n this.#options = options\n }\n\n // `onRegister` for a caller that only has the built server - an embedding host, or the CLI. Replays what is already\n // registered so a late observer cannot miss a session, which is the whole difference from reading the option.\n observe(listener: (runner: Runner) => unknown): () => void {\n this.#observers.add(listener)\n for (const runner of this.#sessions.values()) {\n this.#retain(runner.id, listener(runner))\n }\n return () => void this.#observers.delete(listener)\n }\n\n create(config: SessionRunnerConfig): Runner {\n return this.adopt(new SessionRunner(config))\n }\n\n prepare(config: SessionRunnerConfig): Runner {\n return this.register(new SessionRunner(config))\n }\n\n adopt(runner: Runner): Runner {\n this.register(runner)\n void runner.start()\n return runner\n }\n\n register(runner: Runner): Runner {\n const existing = this.#sessions.get(runner.id)\n this.#sessions.set(runner.id, runner)\n if (existing !== runner) {\n if (existing) {\n this.#detach(runner.id)\n }\n this.#retain(runner.id, this.#options.onRegister?.(runner))\n for (const listener of this.#observers) {\n this.#retain(runner.id, listener(runner))\n }\n }\n return runner\n }\n\n // For a watcher attached outside `onRegister` that must still come off when the runner leaves. Without it a\n // released runner keeps a listener from a discarded generation.\n retain(id: string, detach: () => void): void {\n this.#retain(id, detach)\n }\n\n get(id: string): Runner | undefined {\n return this.#sessions.get(id)\n }\n\n list(): SessionInfo[] {\n return [...this.#sessions.values()].map((r) => r.info())\n }\n\n remove(id: string): boolean {\n const runner = this.#sessions.get(id)\n if (!runner) {\n return false\n }\n runner.close('server')\n this.#detach(id)\n return this.#sessions.delete(id)\n }\n\n evict(id: string): boolean {\n this.#detach(id)\n return this.#sessions.delete(id)\n }\n\n closeAll(): void {\n for (const runner of this.#sessions.values()) {\n runner.close('server')\n }\n }\n\n #retain(id: string, detach: unknown): void {\n if (typeof detach !== 'function') {\n return\n }\n const run = detach as () => void\n const existing = this.#detachers.get(id)\n if (existing) {\n existing.push(run)\n return\n }\n this.#detachers.set(id, [run])\n }\n\n #detach(id: string): void {\n for (const detach of this.#detachers.get(id) ?? []) {\n detach()\n }\n this.#detachers.delete(id)\n }\n}\n","import {\n supportsPermissionMode,\n type CreateSessionRequest,\n type EngineCapabilities,\n type PermissionMode,\n type PricingTable,\n type ProfileEngine,\n type ProfileInfo,\n} from '@workerdeck/protocol'\nimport { composeInstructions } from '@workerdeck/core'\nimport type {\n ContextResetDirectory,\n EngineAdapter,\n PeerDirectory,\n Runner,\n RunnerSnapshot,\n SessionRunnerConfig,\n ShellDirectory,\n} from '@workerdeck/core'\nimport type { Refusal } from '../lib/http.ts'\nimport { refusePermissionMode } from '../lib/permissions.ts'\nimport { checkScope, sameScope } from '../lib/scope.ts'\nimport { cwdAllowed, engineOf, isProviderProfile } from '../lib/profile-env.ts'\nimport type { EngineRunnerContext, ShellAgentWriteOption } from '../options.ts'\nimport type { BridgeHub } from './bridge.ts'\nimport type { SessionParkManager } from './parking.ts'\nimport type { ProfileService } from './profiles.ts'\nimport type { SessionRegistry } from './registry.ts'\n\nexport type SessionFactoryDeps = {\n adapterFor: (engine: ProfileEngine | undefined) => EngineAdapter\n profiles: ProfileService\n hostBuildRunnerConfig: (req: CreateSessionRequest) => SessionRunnerConfig\n createEngineRunner?: (context: EngineRunnerContext) => Runner | Promise<Runner>\n allowedCwdRoots?: string[]\n disableBypassPermissions?: boolean\n approvalTimeoutMs?: number | null\n effortDefaults?: Record<string, string>\n requireApiKey?: boolean\n peers?: PeerDirectory\n contextReset?: { directory: ContextResetDirectory; defaultEnabled: boolean }\n shells?: ShellDirectory\n shellAgentWrite?: ShellAgentWriteOption\n pricing?: PricingTable\n registry: SessionRegistry\n parking: SessionParkManager\n bridge: BridgeHub\n agentBrief?: (sessionId: string | undefined) => string | undefined\n}\n\nexport type BuildOptions = { brief?: string }\n\n// A dormant rebuild spreads the stored config back in, so the principal's flag can arrive on the request; a create\n// door passes it beside the request instead, because the host's hook and a job record see only the wire type.\nexport type CreateRequestWithPrincipal = CreateSessionRequest & { createdByOperator?: boolean }\n\nexport type SessionPrincipal = { operator: boolean }\n\nexport type SessionFactory = ReturnType<typeof createSessionFactory>\n\ntype EngineGrant = {\n refuses: (req: CreateSessionRequest, caps: EngineCapabilities) => boolean\n error: (engine: string, name: string) => string\n}\n\nconst ENGINE_GRANTS: readonly EngineGrant[] = [\n {\n refuses: (req, caps) => !caps.sessionMcpServers && !!req.mcpServers && Object.keys(req.mcpServers).length > 0,\n error: (engine, name) =>\n `profile '${name}' runs the ${engine} engine, whose MCP servers are declared outside the session request - a request cannot add its own`,\n },\n {\n refuses: (req, caps) => !caps.budgets && (req.maxTurns !== undefined || req.maxBudgetUsd !== undefined),\n error: (engine) => `the ${engine} engine does not honor maxTurns/maxBudgetUsd`,\n },\n {\n refuses: (req, caps) => !caps.settingSources && req.settingSources !== undefined,\n error: (engine) => `the ${engine} engine does not load settingSources`,\n },\n { refuses: (req, caps) => !caps.resume && req.resume !== undefined, error: (engine) => `the ${engine} engine cannot resume a session` },\n {\n refuses: (req, caps) => !!req.forkSession && caps.forkSession !== true,\n error: (engine) => `the ${engine} engine cannot fork a resumed session`,\n },\n {\n refuses: (req, caps) => req.reasoningEffort !== undefined && (!caps.reasoningEfforts || caps.reasoningEfforts.length === 0),\n error: (engine) => `the ${engine} engine does not take a reasoningEffort`,\n },\n]\n\n// Applied after the host's hook for the same reason as scope: the hook may rebuild the config from the request.\nfunction withPrincipal(config: SessionRunnerConfig, operator: boolean | undefined): SessionRunnerConfig {\n return operator === undefined ? config : { ...config, createdByOperator: operator }\n}\n\nexport function createSessionFactory(deps: SessionFactoryDeps) {\n const { adapterFor, profiles, registry, parking, bridge } = deps\n\n const subscriptionNoticeShown = new Set<string>()\n\n const applyBypassPolicy = (req: CreateSessionRequest): string | null => {\n if (!deps.disableBypassPermissions) {\n return null\n }\n const refused = refusePermissionMode(req.permissionMode, { operator: true, disableBypass: true })\n if (refused) {\n return refused\n }\n delete req.allowDangerouslySkipPermissions\n return null\n }\n\n const checkPermissionMode = (mode: PermissionMode | undefined, profile: ProfileInfo | undefined): string | null => {\n if (mode === undefined || supportsPermissionMode(profile?.engine, mode)) {\n return null\n }\n return (\n `permission mode '${mode}' is not supported by profile '${profile!.name}' ` +\n `(engine '${engineOf(profile)}') - supported: ` +\n adapterFor(profile?.engine).capabilities.permissionModes.join(', ')\n )\n }\n\n const checkEngineGrants = (req: CreateSessionRequest, profile: ProfileInfo | undefined): string | null => {\n const caps = adapterFor(profile?.engine).capabilities\n const grant = ENGINE_GRANTS.find((candidate) => candidate.refuses(req, caps))\n if (grant) {\n return grant.error(engineOf(profile), profile?.name ?? 'default')\n }\n if (!profile || !isProviderProfile(profile)) {\n return null\n }\n const granted = profile.session?.capabilities\n if (!req.capabilities || !granted) {\n return null\n }\n const ungranted = req.capabilities.filter((c) => !granted.includes(c))\n if (ungranted.length === 0) {\n return null\n }\n return (\n `profile '${profile.name}' does not grant: ${ungranted.join(', ')} ` +\n `(granted: ${granted.join(', ') || 'none'}) - a request may narrow capabilities, not widen them`\n )\n }\n\n const stripInertFields = (req: CreateSessionRequest, profile: ProfileInfo | undefined): void => {\n if (!adapterFor(profile?.engine).capabilities.interactiveApprovals) {\n delete req.questionBehavior\n }\n }\n\n const applyScope = (req: CreateSessionRequest, auth: { scope?: Record<string, string> }): Refusal | null => {\n const invalid = checkScope(req.scope)\n if (invalid) {\n return { status: 400, error: invalid }\n }\n if (!auth.scope) {\n return null\n }\n const merged: Record<string, string> = { ...req.scope }\n for (const [key, value] of Object.entries(auth.scope)) {\n const claimed = merged[key]\n if (claimed !== undefined && claimed !== value) {\n return { status: 403, error: `scope '${key}' does not match the caller's` }\n }\n merged[key] = value\n }\n const tooBig = checkScope(merged)\n if (tooBig) {\n return { status: 400, error: tooBig }\n }\n req.scope = merged\n return null\n }\n\n const checkCwd = (req: CreateSessionRequest, profile: ProfileInfo | undefined): Refusal | null => {\n if (req.cwd !== undefined && typeof req.cwd !== 'string') {\n return { status: 400, error: 'cwd must be a string' }\n }\n if (!req.cwd) {\n // Absent = true: an engine record that omits the field keeps the always-required behaviour.\n return adapterFor(profile?.engine).capabilities.hostCwd === false ? null : { status: 400, error: 'cwd is required' }\n }\n return cwdAllowed(req.cwd, deps.allowedCwdRoots) ? null : { status: 403, error: 'cwd is outside the allowed roots' }\n }\n\n const withScope = (config: SessionRunnerConfig, scope: Record<string, string> | undefined): SessionRunnerConfig =>\n scope === undefined ? config : { ...config, scope }\n\n // The gateway's default reaches every engine through the config, so a runner rebuilt from a parked\n // record gets the same deadline policy as the one it replaces.\n const withApprovalDefault = (config: SessionRunnerConfig): SessionRunnerConfig =>\n deps.approvalTimeoutMs === undefined ? config : { ...config, defaultApprovalTimeoutMs: deps.approvalTimeoutMs }\n\n const buildRunnerConfig = (req: CreateRequestWithPrincipal, principal?: SessionPrincipal): SessionRunnerConfig => {\n const profile = req.profile !== undefined ? profiles.get(req.profile) : undefined\n const effective = profile\n ? {\n ...req,\n model: req.model ?? profile.defaults?.model ?? profile.provider?.model,\n permissionMode: req.permissionMode ?? profile.defaults?.permissionMode,\n }\n : req\n const config = withApprovalDefault(\n withPrincipal(withScope(deps.hostBuildRunnerConfig(effective), req.scope), principal?.operator ?? req.createdByOperator),\n )\n const sessionEnv = profile ? adapterFor(profile.engine).sessionEnv : undefined\n if (!profile || !sessionEnv) {\n return config\n }\n const base = config.env ?? process.env\n const env = sessionEnv(profile, base)\n // A skipped pin returns `base` itself - leaving the config alone keeps an unset `env` unset, so the SDK spawns on process.env.\n return env === base ? config : { ...config, env }\n }\n\n const sessionEnvFor = (profile: ProfileInfo): Record<string, string | undefined> => {\n try {\n return buildRunnerConfig({ cwd: process.cwd(), profile: profile.name }).env ?? process.env\n } catch {\n return adapterFor(profile.engine).sessionEnv?.(profile, process.env) ?? process.env\n }\n }\n\n const buildRunner = async (\n built: SessionRunnerConfig,\n restore?: RunnerSnapshot,\n id?: string,\n options?: BuildOptions,\n ): Promise<Runner> => {\n const name = built.profile\n const profile = name !== undefined ? profiles.get(name) : undefined\n if (name !== undefined && !profile) {\n throw new Error(`unknown profile: ${name}`)\n }\n const capabilities = profile?.capabilities ?? adapterFor(profile?.engine).capabilities\n // Applied here rather than in buildRunnerConfig so a parked record, which stores its config, gets it too. The shell\n // tools are offered only where a shell of this session's could exist at all: enabled on the gateway, host cwd\n // engine. The write tools need, on top, the gateway's say-so and a session an operator created; both are read\n // afresh on every build, so a record never carries a stale grant.\n const config: SessionRunnerConfig = {\n ...built,\n ...(deps.peers ? { peers: deps.peers } : {}),\n ...(deps.pricing ? { pricing: deps.pricing } : {}),\n }\n delete config.contextReset\n delete config.shells\n delete config.shellAgentWrite\n delete config.effortDefaults\n const efforts = { ...deps.effortDefaults, ...profile?.defaults?.efforts }\n if (Object.keys(efforts).length > 0) {\n config.effortDefaults = efforts\n }\n if (deps.contextReset && (built.agentContextReset ?? profile?.defaults?.agentContextReset ?? deps.contextReset.defaultEnabled)) {\n config.contextReset = deps.contextReset.directory\n }\n if (deps.shells && capabilities.hostCwd === true) {\n config.shells = deps.shells\n const write = deps.shellAgentWrite ?? 'read-only'\n if (write !== 'read-only' && built.createdByOperator === true) {\n config.shellAgentWrite = write\n }\n }\n const brief = options?.brief ?? deps.agentBrief?.(id ?? restore?.id)\n if (brief) {\n config.instructions = composeInstructions(config.instructions, brief)\n }\n if (config.instructions !== undefined && capabilities.systemInstructions === false) {\n throw new Error(`the ${engineOf(profile)} engine cannot deliver system instructions`)\n }\n const runner =\n profile && isProviderProfile(profile)\n ? // Non-null: startup refuses a provider profile when no factory was wired.\n await deps.createEngineRunner!({ config, profile, bridge, restore, id })\n : // The in-repo adapters refuse `restore` themselves - neither binary can rebuild a parked session.\n await adapterFor(profile?.engine).createRunner({ config, profile, restore, id })\n const reported = runner.info().scope\n if (!sameScope(reported, config.scope)) {\n throw new Error(\n `runner for session ${runner.id} reports scope ${JSON.stringify(reported)}, ` +\n `expected ${JSON.stringify(config.scope)} - echo config.scope from info()`,\n )\n }\n return runner\n }\n\n const createRunner = async (config: SessionRunnerConfig, options?: BuildOptions): Promise<Runner> => {\n const runner = registry.register(await buildRunner(config, undefined, undefined, options))\n // Watchers first, then start: a session must not emit anything before the things that persist and account for it are listening.\n parking.remember(runner.id, config)\n parking.watch(runner)\n void runner.start()\n return runner\n }\n\n const resolveProfile = (\n name: unknown,\n allowedProfiles: string[] | undefined,\n ): { ok: true; profile?: ProfileInfo } | { ok: false; status: number; error: string } => {\n if (name !== undefined && typeof name !== 'string') {\n return { ok: false, status: 400, error: 'profile must be a string' }\n }\n const all = profiles.all()\n if (all.length === 0) {\n return name !== undefined ? { ok: false, status: 400, error: 'no profiles are configured on this server' } : { ok: true }\n }\n // One profile needs no naming, and neither does a set that still carries the auto-detected\n // `default` - otherwise choosing is the caller's, because a profile is a credential store.\n const effective = name ?? (all.length === 1 ? all[0]!.name : all.find((p) => p.name === 'default')?.name)\n if (effective === undefined) {\n const available = all.map((p) => p.name).join(', ')\n return { ok: false, status: 400, error: `profile is required (available: ${available})` }\n }\n const profile = profiles.get(effective)\n if (!profile) {\n return { ok: false, status: 400, error: `unknown profile: ${effective}` }\n }\n if (allowedProfiles && !allowedProfiles.includes(profile.name)) {\n return { ok: false, status: 403, error: `profile not allowed: ${profile.name}` }\n }\n return { ok: true, profile }\n }\n\n const watchAuthSource = (runner: Runner): (() => void) => {\n let seen = false\n return runner.subscribe((event) => {\n if (seen || event.type !== 'system_init') {\n return\n }\n seen = true\n if (event.apiKeySource !== 'oauth') {\n return\n }\n if (deps.requireApiKey) {\n runner.fail(\n 'This server requires API-key auth (requireApiKey), but the session initialized ' +\n \"with claude.ai subscription credentials (apiKeySource 'oauth'). Set \" +\n 'ANTHROPIC_API_KEY (or Bedrock/Vertex auth) in the server environment.',\n )\n } else {\n const profileName = runner.info().profile ?? ''\n if (subscriptionNoticeShown.has(profileName)) {\n return\n }\n subscriptionNoticeShown.add(profileName)\n const scope = profileName ? `Sessions under profile '${profileName}'` : 'Sessions'\n console.warn(\n `[workerdeck] ${scope} are using claude.ai subscription credentials ` +\n \"(apiKeySource 'oauth'), not an API key. That is only appropriate for personal, \" +\n 'single-user use of your own account. Unattended/scheduled or multi-user use ' +\n \"requires an API key under Anthropic's terms - set ANTHROPIC_API_KEY in the \" +\n 'server environment, or set requireApiKey: true to fail closed.',\n )\n }\n })\n }\n\n return {\n applyBypassPolicy,\n checkPermissionMode,\n checkEngineGrants,\n stripInertFields,\n applyScope,\n checkCwd,\n buildRunnerConfig,\n sessionEnvFor,\n buildRunner,\n createRunner,\n resolveProfile,\n watchAuthSource,\n }\n}\n","import { randomUUID } from 'node:crypto'\nimport { createServer, type IncomingMessage, type ServerResponse } from 'node:http'\nimport type { Duplex } from 'node:stream'\nimport { WebSocketServer } from 'ws'\nimport {\n contextResetDirectoryHandle,\n getEngineAdapter,\n installContextResetDirectory,\n installPeerDirectory,\n installShellDirectory,\n peerDirectoryHandle,\n shellDirectoryHandle,\n} from '@workerdeck/core'\nimport type { EngineAdapter, PeerDirectory, Runner, SessionRunnerConfig } from '@workerdeck/core'\nimport { JobQueue } from '@workerdeck/queue'\nimport { mergePricing, type CreateSessionRequest, type ProfileEngine } from '@workerdeck/protocol'\nimport type { ServerContext } from './context.ts'\nimport { createServerLifecycle } from './lifecycle.ts'\nimport { httpErrorStatus, json } from './lib/http.ts'\nimport { detectDefaultProfiles } from './lib/profile-env.ts'\nimport { reloadPlan } from './lib/reload-plan.ts'\nimport type { DiagnosticSink, WorkerServer, WorkerServerOptions } from './options.ts'\nimport { createQueueSocketHub } from './routes/queue-ws.ts'\nimport { upgradeSession } from './routes/session-upgrade.ts'\nimport { dispatchRoute, httpRoutes } from './routes/table.ts'\nimport { createMemoryAgentStore } from './services/agent-store.ts'\nimport { AgentService } from './services/agents.ts'\nimport { AttachmentStore } from './services/attachments.ts'\nimport { createAuthService } from './services/auth.ts'\nimport { AvailabilityTracker } from './services/availability.ts'\nimport { EngineSleepTimers } from './services/engine-sleep.ts'\nimport { ContextResetService } from './services/context-resets.ts'\nimport { BridgeHub } from './services/bridge.ts'\nimport { createHostFileRoots } from './services/host-files.ts'\nimport { SessionNotifier } from './services/notifications.ts'\nimport { SessionParkManager } from './services/parking.ts'\nimport { ProducedFileStore } from './services/produced-files.ts'\nimport { ProfileService, isEffortMap } from './services/profiles.ts'\nimport { ProfileUsageTracker } from './services/profile-usage.ts'\nimport { SpendLedger } from './services/spend-ledger.ts'\nimport { createRelayLink } from './services/peer-relay.ts'\nimport { createPeerService } from './services/peers.ts'\nimport { ProjectInfoService } from './services/project-info.ts'\nimport { SessionRegistry } from './services/registry.ts'\nimport { createSessionFactory, type SessionFactory } from './services/session-factory.ts'\nimport { createShellDirectory, createShellRegistry, type ShellRegistry } from './services/shells.ts'\nimport { isDormant, MemorySessionStore, type StoredSessionRecord } from './services/session-store.ts'\n\nexport type {\n Authenticator,\n EngineRunnerContext,\n QueueServerOptions,\n SdkSessionLister,\n WorkerServer,\n WorkerServerOptions,\n} from './options.ts'\n\n// How old the account-level rate-limit reading may be before a profiles read asks a live session for a newer one.\n// Generous: the windows move over hours, and the point is to bound staleness at minutes rather than at days.\nconst USAGE_STALE_MS = 5 * 60_000\n\n// Every client frame is a command or a bridged result; images travel over the attachments route, never the socket.\nconst WS_MAX_PAYLOAD_BYTES = 4 * 1024 * 1024\n\nexport function createWorkerServer(options: WorkerServerOptions = {}): WorkerServer {\n if (!options.authenticate && !options.allowUnauthenticated) {\n throw new Error('createWorkerServer: provide `authenticate` or explicitly set `allowUnauthenticated: true`')\n }\n const basePath = options.basePath ?? '/v1'\n const fallback = options.fallback\n const corsOrigins = options.cors?.origins.length ? new Set(options.cors.origins) : undefined\n const maxBodyBytes = options.maxBodyBytes ?? 1024 * 1024\n const diagnose: DiagnosticSink = options.onDiagnostic ?? (() => {})\n const adapterFor = (engine: ProfileEngine | undefined): EngineAdapter => options.engines?.[engine ?? 'claude'] ?? getEngineAdapter(engine)\n\n const pricing = mergePricing(options.pricing?.overrides)\n if (pricing.dropped.length > 0) {\n console.warn(\n `[workerdeck] Ignoring pricing.overrides for ${pricing.dropped.join(', ')}: ` +\n 'each entry needs input, output, cacheWrite5m, cacheWrite1h and cacheRead in USD per million tokens',\n )\n }\n\n const profileDefaultModels = new Map<string, string>()\n const profileUsage = new ProfileUsageTracker()\n const spendLedger = new SpendLedger({\n pricing: pricing.pricing,\n store: options.spend?.store,\n monthlySubscriptionUsd: (name) => options.spend?.monthlySubscriptionUsd?.[name] ?? options.spend?.monthlySubscriptionUsd?.['*'],\n onError: (error) => options.spend?.onError?.(error),\n })\n void spendLedger.load()\n // With a store in play, detection seeds it on first launch instead of declaring anything: a\n // declared profile cannot be edited over the API, and an auto-detected one is exactly the profile\n // an operator most wants to rename or retarget.\n const detected = options.profiles ? [] : detectDefaultProfiles()\n const profiles = new ProfileService({\n declared: options.profiles ?? (options.profileStore ? [] : detected),\n seed: detected,\n store: options.profileStore,\n allowedConfigDirRoots: options.allowedConfigDirRoots,\n disableBypassPermissions: options.disableBypassPermissions,\n hasEngineRunnerFactory: options.createEngineRunner !== undefined,\n adapterFor,\n decorate: {\n defaultModel: (name) => profileDefaultModels.get(name),\n availability: (name) => availability.get(name),\n usage: (name) => {\n refreshStaleUsage(registry, profileUsage, name, diagnose)\n return profileUsage.usage(name)\n },\n spend: (name) => spendLedger.spend(name),\n },\n })\n for (const p of options.profiles ?? []) {\n const invalid = profiles.validate(p)\n if (invalid) {\n throw new Error(`createWorkerServer: ${invalid}`)\n }\n }\n\n const generation = randomUUID()\n const shells = options.shell?.enabled === true ? shellRegistryFor(options.shell, generation) : null\n const agents = new AgentService({\n store: options.agentStore ?? createMemoryAgentStore(),\n basePath,\n avatars: options.avatars !== undefined,\n sleepAfterMs: options.agentSleepAfterMs,\n })\n const projects = new ProjectInfoService({ decorate: (info) => agents.decorate(shells ? shells.decorate(info) : info) })\n\n const notifier = new SessionNotifier({\n ...options.notifications,\n decorateInfo: (info) => projects.withProject(info),\n onError: options.notifications?.onError ?? ((error, context) => diagnose(error, `notification-${context.op}`)),\n })\n const producedFiles = new ProducedFileStore()\n const engineSleep = new EngineSleepTimers({\n afterMs: options.engineSleepAfterMs ?? 0,\n afterMsFor: (sessionId) => agents.sleepAfterFor(sessionId),\n attachedCount: (sessionId) => bridge.attachedCount(sessionId),\n onError: (error) => diagnose(error, 'engine-sleep'),\n })\n const contextResets =\n options.agentContextReset === false\n ? undefined\n : new ContextResetService({ ...options.agentContextReset, onError: (error) => diagnose(error, 'context-reset') })\n let ownContextResets = contextResets\n installContextResetDirectory(contextResets)\n // Built first because everything else holds it. The watchers it attaches read the later-built services only when\n // a runner registers, which no code path does before this function returns.\n const registry = new SessionRegistry({\n // Every watcher here hands back its detach, and the registry runs them when the runner leaves. A hot reload is\n // the case that needs it: the runner outlives this server, and these closures would otherwise keep delivering\n // webhooks and pushes from a generation that is over, one extra copy per reload.\n onRegister: (runner) => {\n const detachers = [\n notifier.watch(runner),\n producedFiles.watch(runner),\n profileUsage.watch(runner),\n spendLedger.watch(runner),\n shells?.watch(runner),\n peers?.watch(runner),\n factory.watchAuthSource(runner),\n engineSleep.watch(runner),\n contextResets?.watch(runner),\n ]\n const profile = runner.info().profile\n if (profile) {\n detachers.push(\n runner.subscribe((event) => {\n if (event.type !== 'capabilities' || !event.defaultModel) {\n return\n }\n profileDefaultModels.set(profile, event.defaultModel)\n }),\n )\n }\n return () => {\n for (const detach of detachers) {\n detach?.()\n }\n }\n },\n })\n const attachmentStore = new AttachmentStore(options.attachments)\n const bridge = new BridgeHub({\n ...options.bridge,\n onResult: (sessionId, executionId, result) => {\n registry.get(sessionId)?.settleExecution?.(executionId, result)\n options.bridge?.onResult?.(sessionId, executionId, result)\n },\n })\n const parking = new SessionParkManager({\n registry,\n store: options.parking?.store ?? new MemorySessionStore(),\n parkDelayMs: options.parking?.parkDelayMs,\n expiredGraceMs: options.parking?.expiredGraceMs,\n persistLive: options.parking?.persistLive,\n onError: options.parking?.onError,\n rebuild: (record) => rebuildRunner(factory, record),\n attachedCount: (sessionId) => bridge.attachedCount(sessionId),\n onParking: (sessionId) => queue?.canParkSession(sessionId) ?? true,\n onParked: (sessionId, executionId) => void queue?.onSessionParking(sessionId, executionId),\n onResumed: (sessionId, runner) => queue?.onSessionResumed(sessionId, runner),\n })\n\n const peers =\n options.peers?.enabled === false ? undefined : createPeerService({ refs: { registry, parking }, projects, options: options.peers })\n const shellDirectory = shells ? createShellDirectory(shells, { runnerFor: (id) => registry.get(id) }) : undefined\n // Each runner resolves its own server's directory first and the process-wide slot only once that server has\n // closed, which is the hot-reload handover: a carried runner then reaches whichever generation installed last.\n const relay =\n peers && options.relay\n ? createRelayLink(options.relay, peers, options.relay.log ?? ((message) => diagnose(new Error(message), 'relay')))\n : undefined\n let ownPeers: PeerDirectory | undefined = relay?.directory ?? peers\n let ownShells = shellDirectory\n if (ownPeers) {\n installPeerDirectory(ownPeers)\n }\n installShellDirectory(shellDirectory)\n if (options.effortDefaults !== undefined && !isEffortMap(options.effortDefaults)) {\n throw new Error('createWorkerServer: `effortDefaults` must map model names to effort levels')\n }\n const factory = createSessionFactory({\n adapterFor,\n profiles,\n hostBuildRunnerConfig: options.buildRunnerConfig ?? ((req: CreateSessionRequest): SessionRunnerConfig => req),\n createEngineRunner: options.createEngineRunner,\n allowedCwdRoots: options.allowedCwdRoots,\n disableBypassPermissions: options.disableBypassPermissions,\n approvalTimeoutMs: options.approvalTimeoutMs,\n effortDefaults: options.effortDefaults,\n requireApiKey: options.requireApiKey,\n peers: peers ? peerDirectoryHandle(() => ownPeers) : undefined,\n contextReset: contextResets\n ? { directory: contextResetDirectoryHandle(() => ownContextResets), defaultEnabled: contextResets.defaultEnabled }\n : undefined,\n shells: shellDirectory ? shellDirectoryHandle(() => ownShells) : undefined,\n shellAgentWrite: options.shell?.agentWrite,\n pricing: pricing.pricing,\n registry,\n parking,\n bridge,\n agentBrief: (sessionId) => agents.briefFor(sessionId),\n })\n\n const availability = new AvailabilityTracker({\n checkCredentials: options.checkCredentials,\n requireAvailableProfile: options.requireAvailableProfile,\n adapterFor,\n sessionEnvFor: factory.sessionEnvFor,\n onError: (error) => diagnose(error, 'availability-probe'),\n })\n\n const auth = createAuthService({ options, registry })\n\n const wss = new WebSocketServer({ noServer: true, maxPayload: WS_MAX_PAYLOAD_BYTES })\n const queueSockets = createQueueSocketHub({ wss, auth, queue: () => queue, diagnose })\n\n const queue = options.queue\n ? new JobQueue({\n ...options.queue,\n onEvent: (event) => {\n try {\n options.queue?.onEvent?.(event)\n } finally {\n queueSockets.broadcast(event)\n }\n },\n createRunner: (config) => factory.createRunner(config),\n buildRunnerConfig: factory.buildRunnerConfig,\n discardSession: (sessionId) => parking.discard(sessionId),\n })\n : undefined\n\n const hostFileRootPaths = options.hostFiles?.roots ?? options.allowedCwdRoots\n const hostFiles = hostFileRootPaths?.length ? createHostFileRoots(hostFileRootPaths) : null\n\n const ctx: ServerContext = {\n options,\n basePath,\n maxBodyBytes,\n adapterFor,\n listSdkSessions: options.listSdkSessions,\n profiles,\n availability,\n auth,\n factory,\n agents,\n avatars: options.avatars,\n registry,\n parking,\n engineSleep,\n peers: peers ? peerDirectoryHandle(() => ownPeers) : undefined,\n bridge,\n projects,\n queue,\n attachmentStore,\n producedFiles,\n hostFiles,\n hostFilesWritable: options.hostFiles?.write === true,\n maxHostFileBytes: options.hostFiles?.maxFileBytes ?? 1024 * 1024,\n maxHostDirEntries: options.hostFiles?.maxEntries ?? 5000,\n shells,\n generation,\n pricingOverrides: Object.keys(pricing.overrides).length > 0 ? pricing.overrides : undefined,\n }\n const routes = httpRoutes(ctx)\n\n const handleRequest = async (req: IncomingMessage, res: ServerResponse): Promise<void> => {\n if (answerCors(req, res, corsOrigins)) {\n return\n }\n const pathname = new URL(req.url ?? '/', 'http://internal').pathname\n if (fallback && pathname !== basePath && !pathname.startsWith(basePath + '/')) {\n await fallback(req, res)\n return\n }\n await dispatchRoute(ctx, routes, req, res, lifecycle.draining())\n }\n\n const server = createServer((req, res) => {\n handleRequest(req, res).catch((error: unknown) => {\n const message = error instanceof Error ? error.message : 'internal error'\n if (!res.headersSent) {\n json(res, httpErrorStatus(error), { error: message })\n } else {\n res.end()\n }\n })\n })\n\n server.on('upgrade', (req: IncomingMessage, socket: Duplex, head: Buffer) => {\n void (async () => {\n const pathname = new URL(req.url ?? '/', 'http://internal').pathname\n if (pathname === basePath + '/queue/ws') {\n await queueSockets.upgrade(req, socket, head)\n return\n }\n await upgradeSession(ctx, wss, req, socket, head)\n })().catch(() => socket.destroy())\n })\n\n const lifecycle = createServerLifecycle({\n server,\n wss,\n registry,\n parking,\n shells,\n queue,\n engineSleep,\n closeQueueSockets: queueSockets.clear,\n diagnose,\n releaseDirectories: () => {\n relay?.close()\n ownPeers = undefined\n ownShells = undefined\n contextResets?.close()\n ownContextResets = undefined\n },\n })\n\n return {\n server,\n registry,\n queue,\n bridge,\n parking,\n shells,\n listen: async (port, host) => {\n await profiles.refreshStored()\n await profiles.seedStore()\n await agents.hydrate()\n await parking.hydrate()\n await shells?.hydrate()\n return new Promise((resolve, reject) => {\n server.once('error', reject)\n server.listen(port, host, () => {\n availability.preflight(profiles.all())\n const address = server.address()\n resolve({ port: typeof address === 'object' && address ? address.port : port })\n })\n })\n },\n releaseSession: (id) => {\n const runner = registry.get(id)\n if (!runner) {\n return undefined\n }\n const plan = reloadPlan(runner)\n if (plan !== 'carry') {\n throw new Error(`session ${id} cannot be carried by identity (${plan})`)\n }\n const config = parking.release(id)\n registry.evict(id)\n return { runner, config }\n },\n adoptSession: ({ runner, config }) => {\n // Re-checked here, not only at release: a runner held across a failed generation may have ended in the\n // meantime, and adopting a dead one would list a session nothing can answer.\n if (reloadPlan(runner) !== 'carry') {\n return false\n }\n parking.adopt(runner, config)\n return true\n },\n releaseRelay: () => relay?.release(),\n drain: lifecycle.drain,\n close: lifecycle.close,\n }\n}\n\n// The backstop behind the attach-time refresh, for the surface that reads the account number without opening a\n// session at all. Fire and forget: this request still answers with what is known, and the newer reading arrives\n// as a `rate_limit` event moments later. One session per profile is enough - the reading is account-level - and\n// the runner's own throttle is what keeps a page of profiles from becoming a page of control requests.\nfunction refreshStaleUsage(registry: SessionRegistry, profileUsage: ProfileUsageTracker, name: string, diagnose: DiagnosticSink): void {\n const held = profileUsage.usage(name)\n const newest = Math.max(0, ...Object.values(held ?? {}).map((window) => window.updatedAt ?? 0))\n if (Date.now() - newest < USAGE_STALE_MS) {\n return\n }\n for (const info of registry.list()) {\n if (info.profile !== name) {\n continue\n }\n const runner = registry.get(info.id)\n if (runner?.refreshUsage) {\n void runner.refreshUsage().catch((error: unknown) => diagnose(error, 'usage-refresh'))\n return\n }\n }\n}\n\nfunction answerCors(req: IncomingMessage, res: ServerResponse, corsOrigins: Set<string> | undefined): boolean {\n const origin = req.headers.origin\n const originAllowed = typeof origin === 'string' && corsOrigins !== undefined && corsOrigins.has(origin)\n if (originAllowed) {\n res.setHeader('access-control-allow-origin', origin)\n res.setHeader('vary', 'origin')\n }\n if (req.method !== 'OPTIONS' || req.headers['access-control-request-method'] === undefined) {\n return false\n }\n if (!originAllowed) {\n res.writeHead(403)\n res.end()\n return true\n }\n res.setHeader('access-control-allow-methods', 'GET, HEAD, POST, PATCH, PUT, DELETE')\n res.setHeader('access-control-allow-headers', 'authorization, content-type, x-workerdeck-key')\n res.setHeader('access-control-max-age', '600')\n // Chrome's Private Network Access: a public page reaching a private address (a tailnet, a LAN) preflights for this explicitly.\n if (req.headers['access-control-request-private-network'] === 'true') {\n res.setHeader('access-control-allow-private-network', 'true')\n }\n res.writeHead(204)\n res.end()\n return true\n}\n\nfunction shellRegistryFor(shell: NonNullable<WorkerServerOptions['shell']>, generation: string): ShellRegistry {\n return createShellRegistry({\n generation,\n artifactDir: shell.artifactDir ?? null,\n timeoutMs: shell.timeoutMs,\n artifactMaxBytes: shell.artifactMaxBytes,\n artifactTtlMs: shell.artifactTtlMs,\n maxRunningPerSession: shell.maxRunningPerSession,\n onError: (error, context) =>\n console.warn(`[workerdeck] shell ${context.op} error (${context.shellId ?? context.sessionId ?? '-'}): ${String(error)}`),\n })\n}\n\n// A dormant record holds only the config and the SDK id to resume from, so it goes back through the host's hook; a\n// parked one carries its own snapshot.\nfunction rebuildRunner(factory: SessionFactory, record: StoredSessionRecord): Promise<Runner> {\n if (!isDormant(record)) {\n return factory.buildRunner(record.config, record.snapshot)\n }\n return factory.buildRunner(\n {\n ...factory.buildRunnerConfig({\n ...record.config,\n prompt: undefined,\n resume: record.sdkSessionId,\n }),\n // Applied after the host's hook, which is free to rebuild the config from the\n // request and would drop a field it has never heard of.\n epoch: (record.info.epoch ?? 0) + 1,\n fallbackTitle: record.info.title,\n startAsleep: true,\n },\n undefined,\n record.id,\n )\n}\n","import type { ProfileInfo, ProviderConfig, SessionCapability } from '@workerdeck/protocol'\n\nexport function sandboxedProviderProfile(\n name: string,\n provider: ProviderConfig,\n options: {\n description?: string\n instructions?: string\n defaults?: ProfileInfo['defaults']\n capabilities?: SessionCapability[]\n mcpServers?: string[]\n } = {},\n): ProfileInfo {\n return {\n name,\n engine: 'provider',\n provider,\n description: options.description ?? 'Sandboxed: no host filesystem, no shell, no egress',\n defaults: options.defaults,\n session: {\n capabilities: options.capabilities ?? [],\n mcpServers: options.mcpServers ?? [],\n instructions: options.instructions,\n },\n }\n}\n","import {\n createEngineSession,\n shellToolNeedsCard,\n type EngineSessionOptions,\n type HostToolDefinition,\n type LanguageModel,\n type McpConnection,\n type SessionInstructions,\n type Runner,\n type ToolExecutionCall,\n type ToolExecutor,\n type ToolSet,\n} from '@workerdeck/core'\nimport type { EngineRunnerContext } from '../options.ts'\n\nexport type ProviderRunnerOptions = {\n model: LanguageModel | ((modelId: string | undefined) => LanguageModel)\n executor: ToolExecutor | 'browser' | ((call: ToolExecutionCall) => ToolExecutor | 'browser')\n capabilities?: EngineSessionOptions['capabilities']\n tools?: Record<string, HostToolDefinition>\n mcp?: McpConnection\n mcpTools?: ToolSet\n instructions?: SessionInstructions\n executionLimits?: { timeoutMs?: number; memoryLimitBytes?: number }\n seedVfs?: Record<string, string>\n shouldApprove?: (call: { toolName: string; input: unknown }) => boolean\n approvalTimeoutMs?: number | null\n // Runs on park as well as close: parking releases the same per-session resources.\n onClose?: () => void | Promise<void>\n}\n\nexport async function createProviderRunner(ctx: EngineRunnerContext, options: ProviderRunnerOptions): Promise<Runner> {\n const { config, profile, bridge, restore, id } = ctx\n const languageModel = typeof options.model === 'function' ? options.model(config.model) : options.model\n const executor = providerExecutor(options.executor, bridge)\n // Under `gated` the agent's shell write tools must raise a card even when the embedder wired no reviewer of its\n // own; `needsApproval` fires only through `shouldApprove`, so the default is supplied here and defers to the\n // embedder's for every other tool.\n const shouldApprove =\n config.shellAgentWrite === undefined\n ? options.shouldApprove\n : (call: { toolName: string; input: unknown }) =>\n shellToolNeedsCard(call.toolName, config.shellAgentWrite) || options.shouldApprove?.(call) === true\n return createEngineSession({\n config: {\n ...config,\n languageModel,\n ...(typeof options.model === 'function' && { resolveModel: options.model }),\n restore,\n onClose: options.onClose,\n },\n id,\n profile,\n resolveModel: () => languageModel,\n selectExecutor: () => executor,\n capabilities: options.capabilities,\n tools: options.tools,\n mcp: options.mcp,\n mcpTools: options.mcpTools,\n instructions: options.instructions,\n executionLimits: options.executionLimits,\n shouldApprove,\n approvalTimeoutMs: config.defaultApprovalTimeoutMs === undefined ? options.approvalTimeoutMs : config.defaultApprovalTimeoutMs,\n seedVfs: options.seedVfs,\n })\n}\n\n// One executor, routed once per call, whose profile names the backend the call went to.\nfunction providerExecutor(executor: ProviderRunnerOptions['executor'], bridge: EngineRunnerContext['bridge']): ToolExecutor {\n const bridged: ToolExecutor = { dispatch: (call) => bridge.executorFor(call.sessionId).dispatch(call) }\n if (typeof executor !== 'function') {\n return executor === 'browser' ? { ...bridged, describe: () => ({ backend: 'browser' }) } : executor\n }\n const route = (call: ToolExecutionCall): { target: ToolExecutor; backend: 'browser' | 'server' } => {\n const raw = executor(call)\n return raw === 'browser' ? { target: bridged, backend: 'browser' } : { target: raw, backend: 'server' }\n }\n return {\n describe: (call) => {\n const { target, backend } = route(call)\n return { ...target.describe?.(call), backend }\n },\n dispatch: (call) => route(call).target.dispatch(call),\n }\n}\n","import { join } from 'node:path'\nimport type { ProfileInfo } from '@workerdeck/protocol'\nimport { readJsonOrSync, writeJsonAtomicSync } from '../lib/atomic-file.ts'\n\nexport type ProfileStore = {\n list(): ProfileInfo[] | Promise<ProfileInfo[]>\n save(profile: ProfileInfo): void | Promise<void>\n delete(name: string): void | Promise<void>\n}\n\nexport function createMemoryProfileStore(seed: ProfileInfo[] = []): ProfileStore {\n const profiles = new Map(seed.map((p) => [p.name, p]))\n return {\n list: () => [...profiles.values()],\n save: (profile) => void profiles.set(profile.name, profile),\n delete: (name) => void profiles.delete(name),\n }\n}\n\nexport function createFileProfileStore(path = join(process.cwd(), '.workerdeck', 'profiles.json')): ProfileStore {\n const read = (): Map<string, ProfileInfo> => {\n const parsed = readJsonOrSync(path, [])\n if (!Array.isArray(parsed)) {\n return new Map()\n }\n const profiles = parsed as ProfileInfo[]\n return new Map(profiles.filter((p) => p && typeof p.name === 'string').map((p) => [p.name, p]))\n }\n const write = (profiles: Map<string, ProfileInfo>): void => writeJsonAtomicSync(path, [...profiles.values()], { indent: 2 })\n return {\n list: () => [...read().values()],\n save: (profile) => {\n const profiles = read()\n profiles.set(profile.name, profile)\n write(profiles)\n },\n delete: (name) => {\n const profiles = read()\n if (profiles.delete(name)) {\n write(profiles)\n }\n },\n }\n}\n"],"mappings":"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"}
|