import { type InboundMediaOptions } from "./inbound-media.js"; import type Relay from "@relaymessenger/sdk"; import { query, type CanUseTool, type PermissionUpdate, type SpawnOptions, type SpawnedProcess } from "@anthropic-ai/claude-agent-sdk"; import type { ClaudeThreadStore } from "./claude-threads.js"; import { type HostedMcp } from "./hosted-mcp.js"; import { type ApprovalChoice, type OwnerApprovals } from "./approvals.js"; export interface ClaudeBridgeInput { client: Pick; media?: Omit; claude: { executable: string; }; cwd: string; /** The platform the executable runs on; this computer's unless a test says otherwise. */ platform?: NodeJS.Platform; threads: ClaudeThreadStore; /** Relay's hosted MCP server and this agent's token (hosted-mcp.ts). */ mcp: HostedMcp; /** Asks the agent's owners, in Relay, whatever Claude Code would ask at its terminal. */ approvals: Pick; signal: AbortSignal; say(line: string): void; query?: typeof query; } /** Resolve the executable connect found, including npm's Windows shim. */ export declare const claudeCommand: (found: string, env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform) => Promise; /** * The only tools Relay lets run without asking: its own messaging tools, * `mcp__relay__*`, the rule that "matches all tools from the server" (Claude * Code permissions, _sources/mcp-tool-design-20260926/ * claude-code-permissions-docs.md:482-483). Relay is the integration, not * the harness, so it adds no allow rule for Claude Code's own tools. * * Inkbox's Claude Code plugin does the opposite: it auto-allows a read-only * set (`DEFAULT_AUTO_ALLOWED_TOOLS`, Read, Glob, Grep, WebFetch, WebSearch and * more; _sources/approvals-inkbox-20260926/ * inkbox-claude-code-plugin-config.py.txt:40-49). Relay does not, because * anyone can message a Relay agent: an allowed Read reads any path on the * owner's computer, and an allowed WebFetch fetches any URL, with nobody * asked. Relay keeps Claude Code's own terminal defaults instead * (claude-code-permissions-docs.md:17-21): a file read needs no approval only * "within the working directory and additional directories"; a web fetch * needs approval "except a built-in set of preapproved documentation * domains"; a web search needs approval. The person's own allow and deny * rules still decide first (`CLAUDE_SETTING_SOURCES`), so whoever wants reads * auto-allowed writes that rule in their own Claude Code settings; what is * left to a prompt goes to the agent's owners (`claudePermission`). */ export declare const CLAUDE_ALLOWED_TOOLS: readonly string[]; /** * The person's own Claude Code settings, user and project, as Inkbox loads * them (`setting_sources=["user","project"]`, sessions.py.txt:1170): the * allow and deny rules they wrote decide first, and only a call those rules * leave to a prompt reaches `canUseTool` (Agent SDK, "Handle approvals and * user input": "The callback never fires for auto-approved tools", * claude-code-agent-sdk-user-input.md:52). */ export declare const CLAUDE_SETTING_SOURCES: readonly ["user", "project"]; /** The three answers, in the Agent SDK's terms: allow, allow with a session rule, deny. */ export declare const CLAUDE_CHOICES: readonly ApprovalChoice[]; /** * The rules that stop Claude Code asking again this session. The SDK hands * `suggestions` for exactly this ("if presenting the user an option 'always * allow' or similar, then this full set of suggestions should be returned as * the `updatedPermissions`", sdk.d.ts `CanUseTool`); each is kept to the * session (`PermissionUpdateDestination` "session") so no settings file of * the person's changes. With no suggestion, the tool itself is allowed for * the session. */ export declare const sessionRules: (toolName: string, suggestions: readonly PermissionUpdate[] | undefined) => PermissionUpdate[]; /** * Claude Code's `canUseTool`, answered by the agent's owners in Relay. * `AskUserQuestion` is a question, not a permission, and nobody sits at this * terminal to pick an option, so Claude is told to ask it in its answer, * which the person reads in the chat. */ export declare const claudePermission: (approvals: Pick) => CanUseTool; /** * How the Agent SDK starts Claude Code. On Windows npm installs `claude` as the * shim `claude.cmd`, and Node refuses to spawn a `.cmd` or `.bat` without a * shell (EINVAL, the fix for CVE-2024-27980; Node docs, "Spawning .bat and * .cmd files on Windows"). The SDK's own spawn passes no shell, so a shim * never starts (the Daytona Windows run of 2026-09-26: `spawn EINVAL`). The SDK * takes `spawnClaudeCodeProcess` for exactly this, a spawn the caller owns * (sdk.d.ts, `Options.spawnClaudeCodeProcess`), and this CLI already starts * every shim through `spawnCommand`, which runs a non-`.exe` through the shell * with each argument escaped (spawn-command.ts). Everything else keeps the * SDK's own spawn. */ export declare const claudeSpawn: (executable: string, platform?: NodeJS.Platform) => { spawn?: (options: SpawnOptions) => SpawnedProcess; stderr(): string; }; /** The spawn itself: `spawnCommand` with the SDK's command, arguments and environment. */ export declare const spawnClaude: (platform: NodeJS.Platform, onStderr: (chunk: string) => void) => (options: SpawnOptions) => SpawnedProcess; /** * One Agent SDK session per Relay chat. A person's newer message cancels the * current turn; an agent's waits for it (`replacesLiveTurn`). */ export declare const runClaudeBridge: (input: ClaudeBridgeInput) => Promise; //# sourceMappingURL=claude-bridge.d.ts.map