/** * Interaction channel adapter: zcode `interaction/*` server→client requests * ↔ ACP `session/requestPermission`. * * ZCode's `createProtocolInteractionBroker` dispatches server→client requests * by tool. Zed supports `session/requestPermission` natively (the allow/reject * popup) but NOT elicitation, so all three interaction kinds map onto * requestPermission: * - interaction/requestPermission (tool approval) → direct mapping * - interaction/requestUserInput (plan_approval / ExitPlanMode) → approve/reject * - interaction/requestUserInput (AskUserQuestion) → per-question options * (single-select: one popup + Skip; multi-select: per-option Include/Skip) * * `requestPermission` is single-select, so multi-select questions are split * into per-option yes/no popups; the user's Include picks are comma-joined * into the final answer (mirrors the reference impl's `answers[q]: "a, b"`). */ import type { PermissionOption } from "@agentclientprotocol/sdk"; import type { ZcodeInteractionPermissionParams, ZcodeInteractionResponse, ZcodeInteractionUserInputParams } from "../backend/types.js"; export declare function isPermissionRequest(method: string): boolean; export declare function isUserInputRequest(method: string): boolean; export declare function isExitPlanMode(params: unknown): boolean; /** AskUserQuestion = requestUserInput WITHOUT the plan_approval schema. */ export declare function isAskUserQuestion(method: string, params: unknown): boolean; /** * Human one-line summary of a tool's input for a permission popup title. * * The command / file path IS the decision the user is making, and some clients * (martty) render only `toolCall.title` in their approval overlay — without * this summary the popup reads as a bare "tool" and the path is invisible. * Commands keep their head (the binary is the informative part); paths keep * their TAIL (the filename is). Spec-complete clients also render `content`, * which carries the full input (see `inputPopupContent`) — multi-line * commands included. */ export declare function describeToolInput(input: unknown): string | undefined; /** Permission-request details shared by every toolCall builder below. */ interface PermissionToolCall { toolCallId: string; title?: string; content?: Array<{ type: "content"; content: { type: "text"; text: string; }; }>; locations?: Array<{ path: string; }>; rawInput: unknown; } export declare function zcodePermissionToAcp(params: ZcodeInteractionPermissionParams, acpSid: string): { options: PermissionOption[]; sessionId: string; toolCall: PermissionToolCall; } | null; /** Whether the tool is one of the session-always workflow approval tools. */ export declare function isSessionAlwaysTool(toolName: string): boolean; /** The injected option's id — v4's own spelling (broker's session-grant key). */ export declare const SESSION_ALLOW_OPTION_ID = "allowSession"; /** * Inject the "Always allow in this session" option for the session-always * tools when the backend's options carry no always tier (the v3 crop). * Returns the SAME params when nothing is injected. The injected option * carries its own plain-allow `response` — the session grant itself lives * BRIDGE-side (the backend cannot receive it over v3), recorded by the * request handler when the client selects this optionId. */ export declare function enrichPermissionOptions(params: ZcodeInteractionPermissionParams): ZcodeInteractionPermissionParams; /** Is this acp requestPermission response the injected session-always pick? */ export declare function isSessionAllowPick(acpResp: unknown): boolean; /** * Convert an ACP requestPermission response → the zcode interaction response. * * The backend's options each carry the authoritative `response` object * (`zcodePermissionOptionSchema`, zcode-protocol/index.ts:589-597): the * "Always allow in this project" option ships `permissionUpdates` that the * runtime persists (core/src/tool/executor/permission-flow.ts:359-366), and * deny ships the normalized STOP reason. Echoing the selected option's * response verbatim is what the desktop host does * (interaction-broker.ts:70-124) — synthesizing our own {decision} instead * drops the persistent rules and degrades "always allow" to a one-shot allow. * * Options without a `response` (older builds) fall back to the allow-id set. */ export declare function acpPermissionResponseToZcode(acpResp: unknown, options?: ZcodeInteractionPermissionParams["options"]): Extract; /** ExitPlanMode rendered as approve/reject permission options. */ export declare function exitPlanModeToAcpPermission(params: ZcodeInteractionUserInputParams, acpSid: string): { options: PermissionOption[]; sessionId: string; toolCall: PermissionToolCall; }; /** Convert an ACP response → zcode ExitPlanMode response. */ export declare function acpPermissionResponseToExitPlanMode(acpResp: unknown): Extract; /** * Build an elicitation FORM for ExitPlanMode plan approval — the martty * surface (see handleSinglePermission's routing comment; the gate lives * there). martty renders the field's `description` through its full markdown * pipeline in a scrollable detail pane — the COMPLETE plan lives there, not * in a one-line popup title. The decision itself is a required enum field * (approve / reject); a cancelled or declined form maps to decline. The * caller falls back to the requestPermission path when the form channel * fails; that path carries the plan in `toolCall.content` for the same * reason. */ export declare function buildPlanApprovalElicitationForm(params: ZcodeInteractionUserInputParams, acpSid: string, toolCallId?: string): { mode: "form"; sessionId: string; toolCallId?: string; message: string; requestedSchema: { type: "object"; properties: Record; required: string[]; }; }; /** * Parse an elicitation form response → zcode ExitPlanMode response. * Mirrors `acpPermissionResponseToExitPlanMode`: approve → accept with * content.answer_0 (the backend reads answer_0), anything else → decline. */ export declare function parsePlanApprovalElicitationResponse(acpResp: unknown): Extract; export interface AskUserQuestion { question: string; multiSelect: boolean; options: PermissionOption[]; } /** * Split a zcode AskUserQuestion request into per-question descriptors. * * Single-select: one ACP option per label + a trailing Skip. * Multi-select: each label becomes a yes/no pair (optionId `