import { ChatContext, FunctionCall, FunctionCallOutput } from '../llm/chat_context.js';
import { type FunctionTool, type JSONObject, type ToolContextEntry, Toolset } from '../llm/tool_context.js';
import type { AgentSession } from './agent_session.js';
import type { PromptTemplate, RunContext, UpdatePromptArgs } from './run_context.js';
export interface DuplicatePromptArgs {
    functionName: string;
    functionCallsJson: string[];
    functionCallsText: string;
}
export interface ReplyPromptArgs {
    callIds: string[];
}
export interface AsyncToolOptions {
    updateTemplate: PromptTemplate<UpdatePromptArgs>;
    duplicateRejectTemplate: PromptTemplate<DuplicatePromptArgs>;
    duplicateConfirmTemplate: PromptTemplate<DuplicatePromptArgs>;
    replyAtTailTemplate: PromptTemplate<ReplyPromptArgs>;
    replyMaybeCoveredTemplate: PromptTemplate<ReplyPromptArgs>;
}
export interface ToolHandlingOptions {
    asyncOptions?: Partial<AsyncToolOptions>;
}
export declare const UPDATE_TEMPLATE: string;
export declare const DUPLICATE_REJECT: string;
export declare const DUPLICATE_CONFIRM: string;
export declare const REPLY_INSTRUCTIONS_AT_TAIL: string;
export declare const REPLY_INSTRUCTIONS_MAYBE_COVERED: string;
export declare function resolveAsyncToolOptions(options?: Partial<AsyncToolOptions>): AsyncToolOptions;
export declare function renderTemplate<Args extends Record<string, unknown>>(template: PromptTemplate<Args>, args: Args): string;
type ToolExecutorAgent = {
    chatCtx: ChatContext;
    updateChatCtx(chatCtx: ChatContext): Promise<void> | void;
};
type ToolExecutorActivity = {
    agent: ToolExecutorAgent;
    waitForIdle(): Promise<void>;
};
export declare const getRunningTasksTool: FunctionTool<Record<string, never>, unknown, import("../llm/tool_context.js").JSONValue[]>;
export declare const cancelTaskTool: FunctionTool<{
    call_id: string;
}, unknown, string>;
export declare class ToolExecutor {
    private runningTasks;
    private duplicateLock;
    private pendingUpdates;
    private _replyTask?;
    private _replyTaskDone;
    toolOptions: AsyncToolOptions;
    constructor({ owningActivity, asyncToolOptions, }?: {
        owningActivity?: ToolExecutorActivity | null;
        asyncToolOptions?: Partial<AsyncToolOptions>;
    });
    private owningActivity;
    get replyTask(): Promise<void> | undefined;
    setOwningActivity(activity: ToolExecutorActivity | null): void;
    setToolOptions(options?: Partial<AsyncToolOptions>): void;
    get hasRunningTasks(): boolean;
    get hasCancellableRunningTasks(): boolean;
    execute<Parameters extends JSONObject, UserData, Result>({ tool, runCtx, rawArguments, abortSignal, }: {
        tool: FunctionTool<Parameters, UserData, Result>;
        runCtx: RunContext<UserData>;
        rawArguments: Parameters;
        abortSignal?: AbortSignal;
    }): Promise<unknown>;
    waitForAll(): Promise<void>;
    cancel(callId: string): Promise<boolean>;
    /**
     * Abort + detach a running task unconditionally. `cancel()` gates on cancellability and
     * interruptibility (LLM/user-initiated path); teardown via `drain()` must skip those guards —
     * the activity is going away, and `cancel()`'s `allowInterruptions` throw would otherwise abort
     * the drain loop and strand the remaining tasks.
     */
    private forceCancelTask;
    /**
     * Fire-and-forget watcher: a cancelled tool whose `execute()` hasn't settled by the
     * deadline is ignoring its abort signal. Surface it so the dev can make execute abortable —
     * abandoning the promise alone leaves the work running invisibly.
     */
    private errorIfCancelledToolKeepsRunning;
    drain(): Promise<void>;
    aclose(): Promise<void>;
    enqueueReply(ctx: RunContext<any>, items: [FunctionCall, FunctionCallOutput]): Promise<void>;
    private runTool;
    private checkDuplicate;
    private deliverReply;
}
export declare function hasCancellableTool(tools: readonly ToolContextEntry[]): boolean;
export declare function buildExecutorMap({ toolsets, defaultExecutor, }: {
    toolsets: readonly Toolset[];
    defaultExecutor: ToolExecutor;
}): Map<string, ToolExecutor>;
export declare function getRunningTasks(session: AgentSession): FunctionCall[];
export {};
//# sourceMappingURL=tool_executor.d.ts.map