/**
 * Tool-agnostic primitives for host tools: request/result envelope, approval
 * shape, per-tool ToolContract, and the host executor contract.
 */
import type { ToolDefinition } from '../core/core-types.js';
import type { PendingHostToolRequests } from '../core/pending-host-tool-requests.js';
export type { PendingHostToolRequests };
/** Coerce any thrown value into a stable string message. */
export declare function errorToMessage(error: unknown): string;
export declare const HostToolResultStatus: {
    readonly Cancelled: "cancelled";
    readonly Failed: "failed";
    readonly Succeeded: "succeeded";
};
export type HostToolResultStatus = (typeof HostToolResultStatus)[keyof typeof HostToolResultStatus];
export interface ApprovalRequirement {
    readonly required: boolean;
    readonly reason?: string;
}
export interface HostToolHeartbeatMeta {
    /** Model-visible tool name, e.g. `execute_code`. */
    readonly toolName?: string;
    /** User-facing status label, e.g. `Running code...`. */
    readonly label?: string;
}
export interface HostToolRequest {
    readonly approval: ApprovalRequirement;
    readonly heartbeat?: HostToolHeartbeatMeta;
    readonly kind: string;
    readonly params: unknown;
    readonly requestId: string;
}
/**
 * Two text channels for a tool's output:
 *
 *   `content` (built by the LLM-tool wrapper, lives on `AgentToolResult`) is
 *   the agent-facing string — what the LLM reads next turn and what
 *   observability logs as the raw failure reason.
 *
 *   `userMessage` (top-level on this result) is the canonical UI-facing
 *   string. It is the single source of truth that ledger, observability, and
 *   tool renderers consume; tools should populate it whenever there is a
 *   user-facing reason to surface (always on Failed/Cancelled, optionally on
 *   Succeeded for tools whose success path has narrative output).
 *
 * Synthetic infra failures (bridge timeout, missing approval gate) populate
 * `userMessage` directly; `details` stays undefined.
 *
 * Some tool contracts also carry a snake_case `user_message` inside their
 * typed `details` payload because the renderer artifact for that tool is
 * structurally part of `details` (e.g. web-search citation-marked body).
 * Those are tool-specific renderer artifacts, not the canonical failure
 * channel — infra code only reads `userMessage`.
 */
export interface HostToolResult {
    readonly details?: unknown;
    readonly kind: string;
    readonly requestId: string;
    readonly runtimeHandoff?: HostToolRuntimeHandoff;
    readonly status: HostToolResultStatus;
    readonly userMessage?: string;
}
export interface HostToolRuntimeHandoff {
    readonly configuration: {
        readonly agentMode?: string;
        readonly systemPrompt: string;
        readonly toolNames: readonly string[];
    };
    readonly kind: string;
}
export interface HostToolRequestOptions {
    readonly signal?: AbortSignal;
}
export interface HostToolExecutor {
    executeHostTool(request: HostToolRequest, options?: HostToolRequestOptions): Promise<HostToolResult>;
}
/** Session-scoped auto-approve toggle. `true` skips the approval gate for write tools. */
export interface ApprovalEvaluationContext {
    readonly autoApprove: boolean;
}
/** Session-scoped provider; queried on every emit so the latest toggle wins. */
export interface HostToolSessionPolicy {
    getApprovalContext(): ApprovalEvaluationContext;
}
/** Shared base for per-tool `createLlmTool` options; tools extend this. */
export interface ToolLlmOptionsBase {
    readonly pendingHostToolRequests: PendingHostToolRequests;
    readonly sessionPolicy: HostToolSessionPolicy;
}
/** Per-tool contract; the registry dispatches by `kind`. */
export interface ToolContract<TParams = unknown, TDetails = unknown, TLlmOptions extends ToolLlmOptionsBase = ToolLlmOptionsBase> {
    readonly kind: string;
    /** Approval is decided runtime-side and travels on `request.approval`. */
    evaluateApproval(params: TParams, context: ApprovalEvaluationContext): ApprovalRequirement;
    validateParams(value: unknown): value is TParams;
    /**
     * Validates the tool-specific result payload. All fields are structurally
     * checked; synthetic infra failures produce results with `details: undefined`
     * (the user-facing reason rides on `HostToolResult.userMessage`), so
     * validators should NOT require any specific field's presence — only
     * enforce the type of fields that are present.
     */
    validateResultDetails(value: unknown): value is TDetails | undefined;
    /** Structured-clone-safe copy for cross-boundary transport. */
    normalizeResultDetails(value: TDetails | undefined): TDetails | undefined;
    /** Safe scalar fields for host-side telemetry. Must not include user output or command text. */
    getResultObservabilityFields?(details: unknown): Record<string, unknown> | undefined;
    /** Build the LLM-facing tool definition once at session boot. */
    createLlmTool(options: TLlmOptions): ToolDefinition;
}
export interface CreateHostToolResultOptions {
    /** Canonical UI-facing string; routed to `HostToolResult.userMessage`. */
    readonly userMessage?: string;
}
/**
 * Build a `HostToolResult` literal. `details` carries the tool's typed
 * payload; `options.userMessage` populates the top-level canonical UI string.
 */
export declare function createHostToolResult<TDetails>(contract: Pick<ToolContract<unknown, TDetails>, 'kind'>, requestId: string, status: HostToolResultStatus, details?: TDetails, options?: CreateHostToolResultOptions): HostToolResult;
/**
 * Build a Failed `HostToolResult` whose user-facing reason rides on the
 * top-level `userMessage` field. For infra-level failures (bridge errors,
 * timeouts) where the tool's typed payload doesn't apply — no signal context,
 * always Failed, no `details`.
 */
export declare function createFailedHostToolResult(kind: string, requestId: string, userMessage: string): HostToolResult;
/**
 * Bridge `HostToolResult.userMessage` (top-level, canonical) into the
 * renderer-shaped artifact's `details.user_message` slot.
 *
 * Renderers read `additional_kwargs.user_message` to display the canonical
 * UI string — that slot is the LangChain `ToolMessage` artifact convention
 * shared with the LangGraph backend. SXL tool contracts must therefore
 * publish their canonical message into `details.user_message` when handing
 * results to the agent loop, even though SXL's own observability/ledger
 * code reads the top-level `userMessage` instead.
 *
 * When `userMessage` is undefined, `details` is returned unchanged (or
 * `{}` if it was undefined). This preserves per-tool fields that
 * legitimately live in `details.user_message` on the success path — e.g.
 * web_search's citation-marked body. Callers that want to overwrite such
 * a field on failure should pass `userMessage` only when `isError` is
 * true.
 */
export declare function buildRendererArtifact<TDetails>(details: TDetails | undefined, userMessage: string | undefined): TDetails;
//# sourceMappingURL=host-tool.d.ts.map