import { Tool } from "./tool"; import { ENCODE_METHOD, DECODE_METHOD } from "../utils/encoder_symbols"; import type { Registry } from "./registry"; import type { Schema } from '@nhtio/validation'; import type { Tokenizable } from "./tokenizable"; import type { AdkEncodableSnapshot } from "./encodable"; import type { DispatchContext } from "../contracts/dispatch_context"; /** * The execution function for an {@link ArtifactTool}. * * @remarks * Identical to the base tool handler except the return type is narrowed to * `string | Tokenizable | Promise`. Forged artifact-query tools emit * model-visible strings — the ADK wraps a bare-string return into a {@link @nhtio/adk!Tokenizable} * at the result-wrapping site so downstream code can rely on * `ToolCall.results instanceof Tokenizable` for every `ArtifactTool` invocation. */ export type ArtifactToolHandler = (args: unknown, ctx: DispatchContext, meta: Registry) => string | Tokenizable | Promise; /** * Plain input object supplied to {@link ArtifactTool} at construction time. * * @remarks * Mirrors the base `RawTool` except `artifactConstructor` is forbidden — an `ArtifactTool` * emits a {@link @nhtio/adk!Tokenizable} directly into `ToolCall.results` and explicitly opts out of * `SpooledArtifact` wrapping. The forbidden field is enforced by {@link ArtifactTool.schema} * at construction time. */ export interface RawArtifactTool { /** Unique identifier used in LLM tool definitions. Recommend lowercase snake_case. */ name: string; /** Human-readable description passed to the model to explain what the tool does. */ description: string; /** @nhtio/validation schema for the tool's input arguments. */ inputSchema: Schema; /** Execution function. Returns a string or {@link @nhtio/adk!Tokenizable}; the ADK wraps a bare string into a `Tokenizable` at the result-wrapping site. */ handler: ArtifactToolHandler; /** Optional arbitrary metadata for this tool. Defaults to `{}`. */ meta?: Record; /** * When `true`, marks this tool as owned by a specific {@link @nhtio/adk!DispatchContext}. * * @remarks * `ArtifactTool` instances produced by `SpooledArtifact.forgeTools(ctx)` set this to `true` * so that `ToolRegistry.pruneEphemeral()` drops them at ctx-completion. * * @defaultValue `false` */ ephemeral?: boolean; /** * When `true`, declares that this tool's output should be treated as **trusted developer/user * intent** rather than as untrusted third-party text when surfaced to the model. * * @remarks * Forged artifact-query tools default to `false` because their results are derived from * spooled artifact bodies — which may themselves be untrusted upstream tool output. The * trust signal does not promote handle-query results above the trust tier of the underlying * artifact. * * @defaultValue `false` */ trusted?: boolean; /** * Self-declared merge collision policy honoured by `ToolRegistry.merge`. * * @remarks * Forged artifact-query tools set this to `'replace'` so that merging multiple * `Subclass.forgeTools(ctx)` outputs (whose base-method tools overlap by name) resolves * silently — the descriptors, snapshot, and handler behaviour are interchangeable across * subclasses, so replacement is a behavioural no-op. * * @defaultValue `'throw'` */ onCollision?: 'throw' | 'replace' | 'keep'; } /** * A {@link @nhtio/adk!Tool} subclass whose handler return value is wrapped directly in a * {@link @nhtio/adk!Tokenizable} (not a {@link @nhtio/adk!SpooledArtifact}) when it * lands on `ToolCall.results`. * * @remarks * `ArtifactTool` is the canonical producer for **forged artifact-query tools** — the tools * `SpooledArtifact.forgeTools(ctx)` emits so the model can `head`, `tail`, `grep`, `json_get`, * `md_headings` (etc.) an artifact that is already in `ctx.turnToolCalls`. * * The difference from {@link @nhtio/adk!Tool} is structural, not stylistic: * * - A normal `Tool`'s handler returns bytes the ADK wraps in a fresh `SpooledArtifact`. * The artifact lands in `ToolCall.results`, joins `ctx.turnToolCalls`, and is itself a * first-class queryable artifact in the turn. * - An `ArtifactTool`'s handler returns a string that is **already the model-visible answer** * to a query against an existing artifact. The ADK wraps it in a `Tokenizable` rather * than a `SpooledArtifact`; nothing new is queryable on its own. Subsequent * `forgeTools(ctx)` calls exclude `ToolCall`s produced by an `ArtifactTool` from the * `callId` enum (via the `ToolCall.fromArtifactTool` marker) — this is the structural fix * that breaks the otherwise-recursive grep-on-the-grep-result loop. * * Consumers who want to build their own artifact-query tools (e.g. for a domain-specific * spooled subclass not shipped by the ADK) should extend or instantiate this class. */ export declare class ArtifactTool extends Tool { /** * Validator schema that accepts a {@link RawArtifactTool} object. * * @remarks * Differs from {@link @nhtio/adk!Tool.schema} by forbidding `artifactConstructor` — wrapping is * exactly the thing this class opts out of. Typed identically to {@link @nhtio/adk!Tool.schema} so the * subclass relationship `class ArtifactTool extends Tool` remains structurally sound; the * runtime validation rules still differ as declared by `rawArtifactToolSchema`. */ static schema: typeof Tool.schema; /** * Returns `true` if `value` is an {@link ArtifactTool} instance. * * @remarks * Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety — `instanceof` would fail for instances * created in a different module copy or VM context. * * @param value - The value to test. * @returns `true` when `value` is an {@link ArtifactTool} instance. */ static isArtifactTool(value: unknown): value is ArtifactTool; /** * @param raw - Raw tool input validated against {@link ArtifactTool.schema}. * * @throws {@link @nhtio/adk!E_INVALID_INITIAL_TOOL_VALUE} when `raw` does not satisfy * {@link ArtifactTool.schema} (most commonly, when `artifactConstructor` is supplied — it is * explicitly forbidden on this class) or when the base {@link @nhtio/adk!Tool} constructor rejects the * input for any reason. */ constructor(raw: RawArtifactTool); /** * Serialise this ArtifactTool into an `@nhtio/encoder` snapshot. * * @remarks * Reuses the base {@link Tool.[ENCODE_METHOD]} (function-serialised `handler`, validation-encoded * `inputSchema`, plain config) and strips `artifactConstructor` — which {@link ArtifactTool.schema} * forbids. The handler's closure caveat from {@link Tool.[ENCODE_METHOD]} applies here too. * * @returns A {@link RawArtifactTool}-shaped snapshot (with `inputSchema` as an encoded string). */ [ENCODE_METHOD](): AdkEncodableSnapshot; /** * Reconstruct an {@link ArtifactTool} from an {@link ArtifactTool.[ENCODE_METHOD]} snapshot. * * @param data - The snapshot produced by {@link ArtifactTool.[ENCODE_METHOD]}. * @returns A fully-validated {@link ArtifactTool}. */ static [DECODE_METHOD](data: AdkEncodableSnapshot): ArtifactTool; }