/** * The ephemeral `opencode serve` process OpencodeAgentRunner drives, plus * the full-access pieces that talk to it (coder mode on every runtime, * plan MM3). Split out of opencode-runner.ts to keep that file under the * project's 500-line cap. * * Full access (`args.access === 'full'`), verified against opencode 1.18.32: * - `OPENCODE_PERMISSION` (JSON) is deep-merged into the loaded config's * `permission` AFTER every other source (global, project opencode.json, * .opencode/, OPENCODE_CONFIG_CONTENT, managed) — so it overrides only * the permission rules and leaves the user's providers, MCP servers, * agents and AGENTS.md alone. A bare `"allow"` string is NOT accepted * there (the served config comes back broken), so the override is an * object: `"*"` plus every built-in permission key, each set to `allow` * so a user's own per-key rule (e.g. `bash: {"rm *": "ask"}`) is * replaced rather than left after the wildcard (rules are last-match- * wins). `question` stays `deny`: a headless turn has nobody to answer * the question tool, which would otherwise block the turn. * - Anything that still asks (an agent's own `permission`, a custom key) * arrives as a `permission.asked` event and is answered `always` by * `replyPermission` below. * - The server is spawned through process-group-spawn.ts: in full mode it * leads its own process group under the turn's `MONOMIND_EXEC_TREE` * marker, so cancel reaches every shell its bash tool started and * agent-exec.ts can report background pids, same as the Claude runner. */ import type { AgentRunArgs } from './agent-runner.js'; export declare const FULL_ACCESS_PERMISSION: Record; /** * #482 `--sandbox restricted`: edits, shell, subagents and paths outside the * project ask — and the runner rejects every ask (`replyPermission`). `ask`, * not `deny`: a denied tool leaves opencode's tool list, and opencode's own * free tier then refuses the request (checked live, opencode 1.18.32). Not * `read-only`: an agent's own `permission` block in the user's or the * project's opencode.json still wins over this override (checked live). */ export declare const RESTRICTED_PERMISSION: Record; /** An attached server (OPENCODE_URL) keeps its own permission rules. */ export declare const RESTRICTED_NEEDS_OWN_SERVER = "opencode --sandbox restricted needs the ephemeral opencode server monomind starts; an attached server (OPENCODE_URL) keeps its own permission rules"; export interface OpencodeServer { url: string; /** SIGTERM the server process itself (not its group): a normal end * leaves background jobs running, like the Claude runner. */ close(): void; /** Cancel target: the whole tracked tree in full mode, else the server. */ target: { kill(signal?: NodeJS.Signals): void; }; /** Stop the full-mode tree sampling; call once when the run ends. */ stop(): void; } /** * Start the ephemeral opencode server WITH THE ROLE'S SESSION ENV (#262). * * The SDK's `createOpencode()`/`createOpencodeServer()` spawn `opencode serve` * with the daemon's `process.env` and take no env option (`ServerOptions` is * `{hostname, port, signal, timeout, config}` — @opencode-ai/sdk 1.18.15), so * `args.env` never reached the process that runs the role's shell: provider * credentials, the #249 MONOMIND_* scoping and the #258 git guard all silently * failed to apply, and that shell had the operator's full git/GitHub access. * Spawning it here is codex-runner.ts's own `{ ...process.env, ...args.env }` * shape. An ATTACHED server (`OPENCODE_URL`) can't get the env — it is the * operator's own process; role-sandbox.ts audits it with `git-guard-unapplied`. */ export declare function startOpencodeServer(args: AgentRunArgs): Promise; /** * Full access: answer one permission request `always` (#482: `reject` under * `--sandbox restricted`, in any access mode). opencode 1.18 emits * `permission.asked` (`{id, sessionID, …}`) answered at * `POST /permission/{id}/reply`; older servers emitted `permission.updated` * answered at `POST /session/{sessionID}/permissions/{id}`. The v1 SDK * client this runner uses only knows the older route, so both go through * fetch. Best-effort: a failed reply leaves the request pending, which the * turn timeout still bounds. */ export declare function replyPermission(baseUrl: string, directory: string, evType: string, props: { id?: string; sessionID?: string; }, reject?: boolean): Promise; /** * `AgentRunArgs.effort` → an opencode model variant (its per-model reasoning * presets — `opencode run --variant`, the prompt body's `variant`). Only a * variant the target model actually lists is returned: the model is * `args.model` or the served config's `model`, looked up in * `config.providers()` (each model's `variants` keys, e.g. low/medium/high/ * xhigh/max). Undefined when the model or the variant can't be resolved — * the turn then runs at the model's default. */ export declare function resolveEffortVariant(client: any, model: string | undefined, effort: string | undefined): Promise; /** Race a promise against a wall-clock timeout. */ export declare function withTimeout(p: Promise, ms: number, label: string): Promise; //# sourceMappingURL=opencode-runner-server.d.ts.map