import { AnyTool } from '@tanstack/ai';
import { PermissionCallDecision, PermissionMode } from '@tanstack/ai-harness';
import { CodeModeTool, CodeModeToolConfig } from './types.js';
export interface CodeModePluginOptions extends Omit<CodeModeToolConfig, 'tools' | 'aroundCalls'> {
    /**
     * Which tools move into code mode. Default: every server tool that does
     * not need approval, that has no permission checks (`PermissionResources`),
     * and that `permissions()` allows in plan mode (so no edits, no commands,
     * nothing that asks first). Without `permissions()`, the rules of tool
     * plugins decide. A safe tool with `metadata.codeMode: true`, for example
     * a tool of an `mcp()` server with `codeMode: true`, moves even when
     * `include` does not pick it.
     *
     * `include` can also pick a tool with permission checks or an `ask` rule,
     * for example the coding tools of `workspaceTools()`. Each call of such a
     * tool in a program gets the same decision as a direct tool call: it
     * runs, it throws, or the program waits for the user to approve it.
     * `include` cannot move a tool with `needsApproval`, or a tool that the
     * rules deny: such a tool stays a normal tool call, and code mode warns
     * once to the host logger for each one that `include` picks. The rules
     * decide in the permission mode of the session at each turn, so in plan
     * mode a tool that edits stays a normal tool call.
     */
    include?: (tool: CodeModeTool) => boolean;
    /**
     * Make each tool that moves into code mode lazy. The prompt then lists only
     * the tool names, and `lazyToolsConfig.includeDescription` adds part of
     * each description. The model calls `discover_tools` for the signatures of
     * the tools it needs, then calls them in `execute_typescript`. This saves
     * tokens on each turn when there are many tools. Default `false`.
     */
    lazy?: boolean;
    /**
     * What happens to the tools that move into code mode. `'remove'`
     * (default): they leave the model's tool list, and the model calls them
     * only in programs. `'keep'`: the model can also call them directly. The
     * session setting `directCalls` changes it while the session runs, for
     * example `session.setPluginSetting({ key: 'directCalls', value: 'keep' })`.
     * A change applies at the next turn.
     */
    directCalls?: 'remove' | 'keep';
    /**
     * The timeout of a program in milliseconds. Default: 30000, or 600000
     * (10 minutes) when a tool with permission checks moved, so that a
     * program can wait for the user to approve a call.
     */
    timeout?: number;
}
/**
 * A harness plugin that gives the model an `execute_typescript` tool. The
 * model writes one TypeScript program that calls several tools, and the
 * program runs in the isolate of `driver` (any `@tanstack/ai-isolate-*`
 * driver). The tools it calls leave the model's tool list, including tools
 * that plugins find at run time, such as MCP tools after `/connect`.
 *
 * By default, only tools that are safe to run without a question move into
 * code mode. The other tools stay normal tool calls. A tool with
 * `metadata.codeMode: true` moves even when `include` does not pick it, but
 * only when it is safe in the same way.
 *
 * `include` can pick more tools, also tools with permission checks, such as
 * the coding tools of `workspaceTools()`. Each call of such a tool in a
 * program gets the same decision as a direct tool call from `permissions()`:
 * it runs, it throws an error with the reason, or the program waits for the
 * user to approve it (a question that `session.answer` answers). The log
 * keeps the result of each such call, so after a stop the next host runs
 * the program again without running a finished call twice. `include` never
 * moves a tool with `needsApproval`, or a tool that the rules deny.
 *
 * With `lazy: true`, the model gets only the names of the moved tools and
 * asks `discover_tools` for the signatures. With `directCalls: 'keep'`, the
 * model can still call the moved tools directly.
 *
 * @example
 * ```ts
 * import { codeMode } from '@tanstack/ai-code-mode/harness'
 * import { createQuickJSIsolateDriver } from '@tanstack/ai-isolate-quickjs'
 *
 * defineHarness({
 *   name: 'acme/agent',
 *   adapter,
 *   plugins: () => [codeMode({ driver: createQuickJSIsolateDriver() })],
 * })
 * ```
 */
export declare function codeMode(options: CodeModePluginOptions): import('@tanstack/ai-harness').HarnessPlugin<NoInfer<{
    readonly name: "tanstack/code-mode";
    readonly optionalRequires: readonly [import('@tanstack/ai').Capability<(tool: string, mode: PermissionMode, resources?: import('@tanstack/ai-harness').CallResources) => import('@tanstack/ai-harness').PermissionDecision, "tanstack/permission-decision">, import('@tanstack/ai').Capability<(call: {
        tool: string;
        args: unknown;
    }) => Promise<PermissionCallDecision>, "tanstack/permission-call">];
    readonly setup: (ctx: import('@tanstack/ai-harness').PluginSetupContext<Record<string, unknown>>) => {
        config: {
            directCalls: {
                type: "select";
                options: ReadonlyArray<string>;
                default: string;
                description?: string;
                category?: string;
            };
        };
        prompts: {
            id: string;
            text: () => string;
        }[];
        contribute: import('@tanstack/ai-harness').ExtensionItem<import('@tanstack/ai-harness').PermissionRule>[];
        prepareTools: ({ tools }: {
            tools: ReadonlyArray<AnyTool>;
            model: string;
            run: import('@tanstack/ai-harness').RunContext;
        }) => readonly AnyTool[] | (import('@tanstack/ai').ServerTool<import('@tanstack/ai').SchemaInput, import('@tanstack/ai').SchemaInput, string, unknown, false, undefined> | AnyTool)[];
    };
}>, Record<string, unknown>>;
