import { Readable, Writable } from 'node:stream';

type Mode = "edit" | "plan" | "auto" | "multi-agent-experimental";

type Role = "system" | "user" | "assistant" | "tool";
interface ToolCall {
    id: string;
    type: "function";
    function: {
        name: string;
        arguments: string;
    };
}
interface TextContentPart {
    type: "text";
    text: string;
}
interface ImageContentPart {
    type: "image_url";
    image_url: {
        url: string;
    };
}
type ContentPart = TextContentPart | ImageContentPart;
interface ChatMessage {
    role: Role;
    content: string | ContentPart[] | null;
    reasoning_content?: string | null;
    tool_calls?: ToolCall[];
    tool_call_id?: string;
    name?: string;
}

interface AiGatewayOptions {
    id: string;
    cacheTtl?: number;
    skipCache?: boolean;
    collectLogPayload?: boolean;
    metadata?: Record<string, string | number | boolean>;
}

type MemoryCategory = "fact" | "event" | "instruction" | "task" | "preference";
interface Memory {
    id: string;
    content: string;
    embedding: Float32Array;
    category: MemoryCategory;
    sourceSessionId: string;
    repoPath: string;
    createdAt: number;
    accessedAt: number;
    importance: number;
    relatedFiles: string[];
    topicKey: string | null;
    supersededBy: string | null;
    forgotten: boolean;
    vectorized: boolean;
    /** Agent role that created this memory (plan, build, general). */
    agentRole: string | null;
}
interface MemoryQuery {
    text: string;
    embedding?: Float32Array;
    repoPath?: string;
    category?: MemoryCategory;
    limit?: number;
    maxAgeDays?: number;
    /** Filter recalled memories by the agent role that created them. */
    agentRole?: string;
}
interface HybridResult {
    memory: Memory;
    ftsScore: number;
    vectorScore: number;
    exactScore: number;
    topicKeyScore: number;
    combinedScore: number;
}
interface MemoryStats {
    totalCount: number;
    dbSizeBytes: number;
    lastCleanupAt: number | null;
    byCategory: Record<MemoryCategory, number>;
}

interface MemoryManagerOpts {
    dbPath: string;
    accountId: string;
    apiToken: string;
    model?: string;
    plumbingModel?: string;
    extractionModel?: string;
    embeddingModel?: string;
    gateway?: AiGatewayOptions;
    maxAgeDays?: number;
    maxEntries?: number;
    redactSecrets?: boolean;
}
interface LlmOpts {
    accountId: string;
    apiToken: string;
    model: string;
    gateway?: AiGatewayOptions;
    signal?: AbortSignal;
}
declare class MemoryManager {
    private db;
    private opts;
    constructor(opts: MemoryManagerOpts);
    open(): void;
    close(): void;
    isOpen(): boolean;
    private get llmOpts();
    private get plumbingLlmOpts();
    private get extractionLlmOpts();
    /** Expose extraction LLM opts so the agent loop can pass them to extractors. */
    getExtractionLlmOpts(): LlmOpts;
    private shouldRedact;
    /**
     * Store a memory with verification, topic-key normalization, hypothetical queries,
     * secret redaction, and supersession.
     */
    remember(content: string, category: MemoryCategory, importance: number, repoPath: string, sessionId: string, signal?: AbortSignal, agentRole?: string, topicKey?: string): Promise<{
        id: string;
        superseded?: string[];
    }>;
    /**
     * Count high-signal memories created since the given timestamp.
     * Used for KIMI.md drift detection (Trigger A: session-start check).
     */
    countHighSignalMemoriesSince(repoPath: string, since: number): number;
    /**
     * Get the timestamp of the most recent KIMI.md refresh memory.
     * Returns 0 if none exists.
     */
    getLastKimiMdRefreshTime(repoPath: string): number;
    /**
     * Record that KIMI.md was refreshed. Creates a lightweight memory
     * so drift detection knows when the snapshot was last updated.
     */
    recordKimiMdRefresh(repoPath: string, sessionId: string): Promise<void>;
    /**
     * Recall memories using the full hybrid retrieval pipeline.
     */
    recall(query: MemoryQuery): Promise<HybridResult[]>;
    /**
     * Recall memories created by a specific agent role.
     */
    recallByRole(query: MemoryQuery, agentRole: string): Promise<HybridResult[]>;
    /**
     * Format recalled memories as a compact context block for injection into messages.
     */
    static formatRecalled(results: HybridResult[]): string;
    /**
     * Synthesize recalled memories into a dense prose paragraph.
     * Uses the lightweight plumbing model (Scout) to keep costs low.
     */
    synthesizeRecalled(results: HybridResult[], signal?: AbortSignal): Promise<string>;
    /**
     * Soft-delete a memory by ID.
     */
    forget(id: string): Promise<boolean>;
    /**
     * Backfill un-vectorized memories at startup.
     */
    backfill(repoPath: string): Promise<number>;
    cleanup(repoPath: string): Promise<{
        oldDeleted: number;
        excessDeleted: number;
        duplicatesMerged: number;
    }>;
    getStats(): MemoryStats | null;
    clearRepo(repoPath: string): number;
    private verifyMemory;
    private normalizeTopicKey;
    private generateHypotheticalQueries;
}

interface ToolContext {
    cwd: string;
    signal?: AbortSignal;
    onTasks?: (tasks: Task[]) => void;
    coauthor?: {
        name: string;
        email: string;
    };
    memoryManager?: MemoryManager | null;
    sessionId?: string;
    githubToken?: string;
    /** Shell override for the bash tool. If omitted, the tool auto-detects based on platform. */
    shell?: string;
    /**
     * Intent tier classified for this turn, when known. Carried into
     * hook payloads (PreToolUse / PostToolUse) so user hooks can branch
     * on tier — e.g. skip auto-format for light-tier turns, or audit
     * every heavy-tier action. Optional because code-mode sub-calls
     * and SDK consumers may not have a tier.
     */
    intentTier?: "light" | "medium" | "heavy";
}
interface ToolRender {
    title: string;
    body?: string;
    diff?: {
        path: string;
        before: string;
        after: string;
    };
}
interface ToolOutput {
    content: string;
    rawBytes: number;
    reducedBytes: number;
}
interface ToolSpec<Args = any> {
    name: string;
    description: string;
    parameters: Record<string, unknown>;
    needsPermission: boolean;
    render?: (args: Args) => ToolRender;
    run: (args: Args, ctx: ToolContext) => Promise<string | ToolOutput>;
}
type TaskStatus = "pending" | "in_progress" | "completed";
interface Task {
    id: string;
    title: string;
    status: TaskStatus;
}

type ReasoningEffort = "low" | "medium" | "high";
interface McpServerConfig {
    type: "local" | "remote";
    command?: string[];
    url?: string;
    env?: Record<string, string>;
    headers?: Record<string, string>;
    enabled?: boolean;
    /** Per-call timeout in milliseconds for tool invocations on this server. Default: 60000. */
    timeoutMs?: number;
}
interface LspServerConfig {
    command: string[];
    env?: Record<string, string>;
    enabled?: boolean;
    rootPatterns?: string[];
    /** Per-request timeout in milliseconds for LSP calls. Default: 10000. */
    timeoutMs?: number;
    /** Max auto-restart attempts after a crash. Default: 3. Set 0 to disable. */
    maxRestartAttempts?: number;
}
interface KimiConfig {
    accountId: string;
    apiToken: string;
    model: string;
    aiGatewayId?: string;
    aiGatewayCacheTtl?: number;
    aiGatewaySkipCache?: boolean;
    aiGatewayCollectLogPayload?: boolean;
    aiGatewayMetadata?: Record<string, string | number | boolean>;
    reasoningEffort?: ReasoningEffort;
    coauthor?: boolean;
    coauthorName?: string;
    coauthorEmail?: string;
    mcpServers?: Record<string, McpServerConfig>;
    cacheStablePrompts?: boolean;
    /** Enable compiled context (token-optimized state packet + artifact store). */
    compiledContext?: boolean;
    /** Number of recent user turns to retain image content; older images are dropped. */
    imageHistoryTurns?: number;
    /** Enable local structured memory (SQLite + embeddings). */
    memoryEnabled?: boolean;
    /** Path to memory database. Defaults to .kimiflare/memory.db in repo root, or ~/.local/share/kimiflare/memory.db. */
    memoryDbPath?: string;
    /** Max age of memories in days before cleanup. Default: 90. */
    memoryMaxAgeDays?: number;
    /** Max memories per repo. Default: 1000. */
    memoryMaxEntries?: number;
    /** Embedding model for memory vectors. Default: @cf/baai/bge-base-en-v1.5. */
    memoryEmbeddingModel?: string;
    /** Model for internal plumbing tasks (memory verification, hypothetical queries). Default: @cf/moonshotai/kimi-k2.5. */
    plumbingModel?: string;
    /** Model for auto-extracting high-signal edit events. Default: @cf/moonshotai/kimi-k2.5. */
    memoryExtractionModel?: string;
    /** Enable Code Mode: present tools as a TypeScript API and execute generated code in a sandbox. */
    codeMode?: boolean;
    /** Enable LSP integration. Default: false. */
    lspEnabled?: boolean;
    /** LSP server configurations. */
    lspServers?: Record<string, LspServerConfig>;
    /** Enable cost attribution by task type. Default: false. Once stable for 2 releases, consider defaulting to true. */
    costAttribution?: boolean;
    /** Enable @ file mention picker in chat input. Default: false. */
    filePicker?: boolean;
    /** UI theme name. Default: everforest-dark. */
    theme?: string;
    /** URL of the remote orchestrator Worker. */
    remoteWorkerUrl?: string;
    /** Shared secret for authenticating with the remote Worker. */
    remoteAuthSecret?: string;
    /** Configurable TTL for remote sessions in minutes (default: 30). */
    remoteTtlMinutes?: number;
    /** Max input token budget per remote job (default: 5_000_000). */
    remoteMaxInputTokens?: number;
    /** GitHub OAuth token for remote PR creation. */
    githubOAuthToken?: string;
    /** GitHub refresh token (if available). */
    githubRefreshToken?: string;
    /** GitHub token expiry timestamp. */
    githubTokenExpiry?: number;
    /** Default GitHub repo for remote sessions (owner/repo). */
    githubRepo?: string;
    /** Shell override for the bash tool. "auto" (default) detects the platform, or specify "bash", "cmd", "powershell", or an absolute path. */
    shell?: string;
    /**
     * Preferred interactive UI engine. `"ink"` is the default (stable React/Ink
     * UI); `"camouflage"` is the experimental Rust TUI. The runtime resolution
     * chain is: `--ui` flag → `KIMIFLARE_UI` env var → this field → `"ink"`.
     * Settable from inside either TUI via `/ui ink` or `/ui camouflage`;
     * takes effect on the next launch (the choice is baked at process start).
     */
    uiEngine?: "ink" | "camouflage";
    /** Per-provider API keys forwarded to AI Gateway as cf-aig-authorization for BYOK. */
    providerKeys?: {
        anthropic?: string;
        openai?: string;
        google?: string;
        "openai-compatible"?: string;
    };
    /** When true, models marked billingMode="unified" use Cloudflare's Unified Billing (no BYOK header). */
    unifiedBilling?: boolean;
    /** Non-secret names referencing provider keys stored in Cloudflare Secrets Store with scope: ai_gateway. */
    providerKeyAliases?: {
        anthropic?: string;
        openai?: string;
        google?: string;
        "openai-compatible"?: string;
    };
    /** Id of the Cloudflare Secrets Store kimi-code uses for provider-key BYOK aliases. */
    secretsStoreId?: string;
    /** Worker endpoint URL for spawning standalone research/executor workers. */
    workerEndpoint?: string;
    /** Max cost per worker in USD (default: 1.0). */
    workerBudgetUsd?: number;
    /** Hard ceiling for workerBudgetUsd. Any configured or programmatic value above this is silently capped. Default: 5.0. */
    workerBudgetMaxUsd?: number;
    /** Max workers to spawn in parallel (default: 3). */
    workerMaxParallel?: number;
    /** Timeout per worker in milliseconds (default: 300000 = 5 min). */
    workerTimeoutMs?: number;
    /** Enable multi-agent-experimental mode in the mode cycle. Default: false. */
    multiAgentEnabled?: boolean;
    /** Bearer/secret for the worker endpoint (sent as X-Worker-Api-Key). */
    workerApiKey?: string;
    /** Name of the deployed multi-agent Worker. Used for tear-down. */
    workerName?: string;
    /** When true, after plan workers synthesize, spawn one executor worker
     *  to implement the synthesized plan and open a PR. Off by default. */
    autoExecute?: boolean;
    /** Use shallow clone (`--depth 1`) for sandbox workers. Default: true. */
    workerShallowClone?: boolean;
    /** Enable repo caching / reuse hints for the Commute worker. Default: true. */
    workerRepoCache?: boolean;
    /** Forward memory context to multi-agent workers. Default: true. */
    workerProxyMemory?: boolean;
    /** Forward LSP context to multi-agent workers. Default: false. */
    workerProxyLsp?: boolean;
    /** Forward MCP context to multi-agent workers. Default: false. */
    workerProxyMcp?: boolean;
    /** Model used for LLM-based task decomposition in multi-agent mode.
     *  Default: @cf/moonshotai/kimi-k2.5 (fast and cheap). */
    decompositionModel?: string;
    /** Strategy for decomposing heavy prompts into parallel research tasks.
     *  - "llm": use a lightweight LLM call (default)
     *  - "regex": pure regex heuristic (no LLM, fastest)
     *  - "hybrid": regex for explicit lists, LLM for prose */
    decompositionStrategy?: "llm" | "regex" | "hybrid";
    /** Model for synthesizing multi-agent findings.
     *  Default: @cf/moonshotai/kimi-k2.5 (fast and cheap). */
    synthesisModel?: string;
    /** Strategy for synthesizing worker findings.
     *  - "llm": use a lightweight LLM call (default)
     *  - "heuristic": pure heuristic (no LLM, fastest)
     *  - "hybrid": try LLM, fall back to heuristic on failure */
    synthesisStrategy?: "llm" | "heuristic" | "hybrid";
    /** Explicit opt-out for LLM-based synthesis. When true, always uses heuristic. */
    disableLlmSynthesis?: boolean;
    /** Files to pre-read on the coordinator and inject into every worker's
     *  context. Saves redundant `read` tool calls across workers. Paths are
     *  relative to the repo root. */
    workerPreReadFiles?: string[];
    /** Max characters of pre-read content to inject per worker batch.
     *  Default: 50_000. */
    workerPreReadMaxChars?: number;
}
declare const DEFAULT_MODEL = "@cf/moonshotai/kimi-k2.6";
declare const DEFAULT_REASONING_EFFORT: ReasoningEffort;
declare function loadConfig(): Promise<KimiConfig | null>;
declare function saveConfig(cfg: KimiConfig): Promise<string>;

/**
 * Whether the user said yes or no.
 *
 * NOTE on naming: the legacy `PermissionDecision` string type
 * (`"allow" | "allow_session" | "deny"`) also lives below as a
 * deprecated back-compat alias. New callers should return the typed
 * `PermissionDecisionResult` shape; the executor normalizes either at
 * the boundary so existing SDK callers keep working unchanged.
 */
type PermissionDecisionKind = "allow" | "deny";
/**
 * How broadly an allow applies. M2.1's enum overloaded this with the
 * decision — `"allow_session"` meant "allow + cache for the session" —
 * which made the new `"pattern"` scope from M6.2 impossible to express.
 *
 *   - `once`    — approved this single call. The executor will ask
 *                 again next time the same tool is requested.
 *   - `session` — approved for the rest of the session (existing
 *                 `"allow_session"` behavior).
 *   - `pattern` — approved because the call matched a pre-configured
 *                 glob in settings.json (M6.2). The executor does NOT
 *                 cache pattern-allow decisions — the pattern itself
 *                 is the durable record and lives in the config file.
 *
 * `scope` is meaningful only when `decision === "allow"`; for `deny`
 * it's ignored, but we keep it required so the shape stays uniform.
 */
type PermissionScope = "once" | "session" | "pattern";
interface PermissionDecisionResult {
    decision: PermissionDecisionKind;
    scope: PermissionScope;
}
/**
 * Legacy single-string decision. Kept for SDK back-compat — callers can
 * still return `"allow" | "allow_session" | "deny"` and the executor
 * normalizes via `toPermissionResult`. Prefer
 * `PermissionDecisionResult` in new code.
 *
 * @deprecated since M2.2. Use `PermissionDecisionResult` instead.
 */
type PermissionDecisionLegacy = "allow" | "allow_session" | "deny";
/**
 * Union of the new typed result and the legacy string. Both shapes are
 * accepted by `PermissionAsker`; the executor calls
 * `toPermissionResult` to normalize.
 */
type PermissionDecision = PermissionDecisionLegacy | PermissionDecisionResult;
interface PermissionRequest {
    tool: ToolSpec;
    args: Record<string, unknown>;
    sessionKey: string;
}

interface CreateSessionOptions {
    /** Working directory for the agent. Defaults to process.cwd(). */
    cwd?: string;
    /** Override config. If omitted, loads from ~/.config/kimiflare/config.json */
    config?: Partial<KimiConfig>;
    /** Session ID for persistence. If omitted, creates a new session. */
    sessionId?: string;
    /** Which tools to enable. Defaults to ALL_TOOLS. */
    tools?: ToolSpec[];
    /** Enable local structured memory. Defaults to config value. */
    memoryEnabled?: boolean;
    /** Enable LSP integration. Defaults to config value. */
    lspEnabled?: boolean;
    /** Enable cost attribution. Defaults to config value. */
    costAttribution?: boolean;
    /** Cloudflare AI Gateway options. */
    gateway?: AiGatewayOptions;
    /** Custom permission handler. Defaults to auto-deny in plan mode, ask callback in edit mode. */
    permissionHandler?: PermissionHandler;
    /** Called when the agent detects KIMI.md drift. */
    onKimiMdStale?: () => void;
    /**
     * M6.1: enable user-configured lifecycle hooks loaded from
     * `~/.config/kimiflare/settings.json` + `<cwd>/.kimiflare/settings.json`.
     * Default `false` (SDK is a primitive; opt in if you want the
     * TUI's hook behavior).
     */
    enableHooks?: boolean;
}
interface PromptOptions {
    /** Attach images to the prompt. */
    images?: Array<{
        path: string;
    } | {
        data: string;
        mimeType: string;
    }>;
    /** Override mode for this prompt only. */
    mode?: "plan" | "edit" | "auto";
    /** Override max tool iterations for this prompt only. */
    maxToolIterations?: number;
}
type SessionEvent = {
    type: "session.start";
    sessionId: string;
    cwd: string;
} | {
    type: "session.end";
    reason: "complete" | "aborted" | "error";
    error?: string;
} | {
    type: "message.start";
    messageId: string;
    role: "user" | "assistant";
} | {
    type: "message.delta";
    messageId: string;
    text: string;
} | {
    type: "message.reasoning";
    messageId: string;
    text: string;
} | {
    type: "message.end";
    messageId: string;
} | {
    type: "tool.start";
    toolCallId: string;
    toolName: string;
    args: unknown;
} | {
    type: "tool.result";
    toolCallId: string;
    toolName: string;
    result: string;
    isError: boolean;
} | {
    type: "usage";
    inputTokens: number;
    outputTokens: number;
    reasoningTokens?: number;
    cost?: number;
} | {
    type: "permission.request";
    requestId: string;
    toolName: string;
    args: unknown;
} | {
    type: "permission.resolved";
    requestId: string;
    decision: PermissionDecision;
} | {
    type: "tasks.update";
    tasks: Task[];
} | {
    type: "warning";
    message: string;
} | {
    type: "status";
    status: "idle" | "streaming" | "tool_executing" | "compacting" | "error";
};
interface SessionUsage {
    totalInputTokens: number;
    totalOutputTokens: number;
    totalCost: number;
    turnCount: number;
}
interface SessionStatus {
    isStreaming: boolean;
    isCompacting: boolean;
    pendingSteer: string[];
    pendingFollowUp: string[];
    currentMode: Mode;
}
type PermissionHandler = (req: PermissionRequest) => Promise<PermissionDecision>;
interface KimiFlareSession {
    readonly sessionId: string;
    readonly cwd: string;
    readonly isStreaming: boolean;
    readonly messages: ChatMessage[];
    prompt(text: string, options?: PromptOptions): Promise<void>;
    steer(text: string): Promise<void>;
    followUp(text: string): Promise<void>;
    abort(): Promise<void>;
    setModel(modelId: string): void;
    setMode(mode: "plan" | "edit" | "auto"): void;
    setReasoningEffort(level: "low" | "medium" | "high"): void;
    resolvePermission(requestId: string, decision: PermissionDecision): void;
    subscribe(listener: (event: SessionEvent) => void): () => void;
    getUsage(): SessionUsage;
    getStatus(): SessionStatus;
    save(): Promise<void>;
    dispose(): void;
}

declare function createAgentSession(opts: CreateSessionOptions): Promise<{
    session: KimiFlareSession;
}>;

declare function createDefaultPermissionHandler(options: {
    mode: Mode;
    onRequest?: (req: PermissionRequest) => void;
}): PermissionHandler;

declare function startRpcServer(input?: Readable, output?: Writable): Promise<void>;

declare function resolveSdkConfig(opts: CreateSessionOptions): Promise<KimiConfig>;

export { type ChatMessage, type CreateSessionOptions, DEFAULT_MODEL, DEFAULT_REASONING_EFFORT, type KimiConfig, type KimiFlareSession, type PermissionDecision, type PermissionHandler, type PermissionRequest, type PromptOptions, type SessionEvent, type SessionStatus, type SessionUsage, type Task, type ToolSpec, createAgentSession, createDefaultPermissionHandler, loadConfig, resolveSdkConfig, saveConfig, startRpcServer };
