import type { AgentProviderKind } from "../agents/ports/AgentProvider.js";
import type { EffortLevel } from "../agents/adapters/openrouter/optionsAdapter.js";
import type { PermissionResult } from "../agents/adapters/claude-code/types.js";
import { ToolPermissionPolicy } from "../agents/permissions/ToolPermissionPolicy.js";
import { EventEmitter } from "events";
import type { DefaultPermissions } from "shared/types/index.js";
import type { StreamEvent } from "shared/types/index.js";
export type { StreamEvent };
interface PendingRequest {
    toolName: string;
    input: Record<string, unknown>;
    suggestions?: readonly unknown[];
    eventType: "permission_request" | "user_question" | "plan_review";
    eventData: Record<string, unknown>;
    resolve: (result: PermissionResult) => void;
}
interface ActiveSession {
    abortController: AbortController;
    emitter: EventEmitter;
}
export declare function getActiveSession(chatId: string): ActiveSession | undefined;
export declare function hasPendingRequest(chatId: string): boolean;
export declare function getPendingRequest(chatId: string): Omit<PendingRequest, "resolve"> | null;
export declare function respondToPermission(chatId: string, allow: boolean, updatedInput?: Record<string, unknown>, updatedPermissions?: unknown[]): {
    ok: boolean;
    toolName?: string;
};
export declare function stopSession(chatId: string): boolean;
/**
 * Build the canUseTool permission handler for the Claude SDK.
 * Uses a getter function for the tracking ID since it may change mid-session (new chat flow).
 */
export declare function buildCanUseTool(emitter: EventEmitter, toolPermissionPolicy: ToolPermissionPolicy, getTrackingId: () => string, hookAskOverride?: {
    reason: string;
}): (toolName: string, input: Record<string, unknown>, { signal, suggestions }: {
    signal: AbortSignal;
    suggestions?: readonly unknown[];
}) => Promise<PermissionResult>;
/**
 * Host handler for the OpenRouter library's `ask_user_question` tool.
 *
 * The OR tool calls this with a single question + lettered options and awaits a
 * {@link OrUserQuestionResponse}. We reuse callboard's existing question flow:
 * emit the same `user_question` SSE event the Claude path uses (so the
 * FeedbackPanel renders it) and register a pending request keyed by the current
 * tracking id, so the `/permission-response` endpoint → respondToPermission
 * resolves it. The frontend returns answers keyed by question text with the
 * chosen option's *label*; we map that back to the option id the library wants.
 *
 * The OR library single-question shape can't express Claude's multi-question /
 * multi-select form — we wrap the one question into a length-1 questions array.
 * The library enforces its own timeout (≤10 min), so no timeout is added here;
 * abort cleanup resolves the promise so the run can't hang on a stale pending.
 */
type OrUserQuestionRequest = {
    questionId: string;
    question: string;
    options: Array<{
        id: string;
        label: string;
        preview?: string;
    }>;
    allowFreeText?: boolean;
};
type OrUserQuestionResponse = {
    questionId: string;
    selectedOptionId?: string;
    freeTextAnswer?: string;
};
export declare function buildOnAskUserQuestion(emitter: EventEmitter, getTrackingId: () => string, signal: AbortSignal): (req: OrUserQuestionRequest) => Promise<OrUserQuestionResponse>;
interface SendMessageOptions {
    prompt: string | any;
    imageMetadata?: {
        buffer: Buffer;
        mimeType: string;
    }[];
    activePlugins?: string[];
    /** For existing chats: the chat ID to continue */
    chatId?: string;
    /** For new chats: the working directory (used as cwd for the SDK, also stored with chat) */
    folder?: string;
    /** For new chats: initial permission settings */
    defaultPermissions?: DefaultPermissions;
    /** Maximum number of agent turns before stopping (default: 200) */
    maxTurns?: number;
    /** Agent identity prompt — appended to Claude Code's preset system prompt */
    systemPrompt?: string;
    /** Agent alias — when set, injects Callboard custom tools MCP server into the session */
    agentAlias?: string;
    /** Whether this chat was triggered by an automated system (cron, trigger, heartbeat, etc.) */
    triggered?: boolean;
    /** How this chat was triggered — stored in metadata for icon distinction */
    triggeredBy?: "cron" | "event" | "trigger" | "tool" | "job";
    /**
     * Set by the job runner when this session executes a job step. Tags the
     * chat metadata (jobRunId/jobStepId) and injects the job-tools MCP server
     * (complete_job_step) unless the session is advisory.
     */
    jobContext?: import("./job-runner.js").JobContext;
    /**
     * Which agent provider runs this chat. Only honored for new chats —
     * existing chats route by the `provider` field already in their metadata.
     * Defaults to `"claude-code"` when omitted; `"openrouter"` is rejected at
     * the sendMessage boundary if OPENROUTER_API_KEY isn't configured.
     */
    provider?: AgentProviderKind;
    /**
     * OpenRouter reasoning-effort level. Only honored for new chats with
     * `provider: "openrouter"` — written into chat metadata so existing-chat
     * follow-ups reuse the same setting without the caller having to thread
     * it through. Omitted from the OR API call entirely when undefined
     * (preserves each model's default behavior). Ignored when paired with
     * any non-openrouter provider.
     */
    effort?: EffortLevel;
    /**
     * Model for this chat. Only honored for new chats — written into chat
     * metadata so existing-chat follow-ups reuse it.
     *
     * For `provider: "openrouter"`: an OR slug (e.g. "anthropic/claude-opus-4.7")
     * or an alias like "~anthropic/claude-sonnet-latest". Falls back to the
     * global `agentSettings.openRouterModel` when omitted.
     *
     * For `provider: "claude-code"` (or omitted provider): an Anthropic model
     * alias ("opus", "sonnet", "haiku", "opusplan") or full model ID (e.g.
     * "claude-sonnet-4-6"), passed to the SDK as `options.model`. When omitted,
     * the SDK default applies — including the global ANTHROPIC_MODEL env
     * override from Settings → API.
     */
    model?: string;
    /**
     * When true, the session is not considered done until it explicitly calls
     * a completion tool: objective_complete (injected for this run) for normal
     * sessions, or complete_job_step for job-step sessions. If the message
     * stream ends without that call, the session is resumed with a nudge
     * prompt — up to `maxNudges` times — before giving up with done reason
     * "objective_incomplete". Persisted into chat metadata for new chats so
     * follow-up messages inherit it; pass an explicit boolean on an existing
     * chat to override for that message only. Default: false (current
     * behavior — the session ends when the stream ends).
     */
    requireExplicitCompletion?: boolean;
    /**
     * Max nudge re-prompts per message when requireExplicitCompletion is set
     * (default: 3).
     */
    maxNudges?: number;
}
/**
 * Unified message sending function.
 * Handles both existing chats (provide chatId) and new chats (provide folder).
 * For new chats, creates the chat record when session_id arrives from the SDK
 * and emits a "chat_created" event so the frontend can navigate.
 */
export declare function sendMessage(opts: SendMessageOptions): Promise<EventEmitter>;
//# sourceMappingURL=claude.d.ts.map