/** * Cross-battery helpers shared by the configured HTTP tool batteries (SearXNG, Scrapper, …). * * @module @nhtio/adk/batteries/tools/_shared * * @remarks * These are internal building blocks for the *factory-style* tool batteries — the ones that talk * to a configured HTTP instance behind custom auth and expose input/output middleware pipelines. * Rather than each battery carry its own copy, the common machinery lives here: * * - {@link resolveArtifact} / {@link resolveArtifactSync} — turn an {@link ArtifactResolver} * (a constructor, a sync resolver, or an async / dynamic-import resolver) into the **sync** * `() => SpooledArtifactConstructor` that `Tool.artifactConstructor` requires. Mirrors the vector * battery's `resolveClientCtor`. * - {@link resolveHeaders} — collapse a static header object or a (sync/async) resolver into a * plain header record for one request (refreshable-auth friendly). * - {@link runInputPipeline} / {@link runOutputPipeline} — the onion middleware runners (fresh * runner per call, short-circuit + non-terminal detection), generic over the context type. * * This module imports harness primitives only through their specific subpath barrels * (`@nhtio/adk/spooled_artifact`, `@nhtio/adk/forge`, `@nhtio/adk/guards`) per the batteries * barrel-only rule. */ import { Middleware } from '@nhtio/middleware'; import type { NextFn } from '@nhtio/middleware'; import type { SpooledArtifactConstructor } from "../../../forge"; /** A static set of request headers (used for custom instance authentication). */ export type ToolHeaders = Record; /** * A resolver returning request headers, sync or async. Use this form when the auth token is * refreshable — the resolver runs on every request, so a fresh token can be minted per call. */ export type ToolHeadersResolver = () => ToolHeaders | Promise; /** * Resolve the configured headers (a static object or a sync/async resolver) for a single request. * * @param headers - The static header record, the resolver, or `undefined`. * @returns A fresh, owned copy of the resolved headers (`{}` when none supplied). */ export declare const resolveHeaders: (headers: ToolHeaders | ToolHeadersResolver | undefined) => Promise; /** Convenience alias for the spooled-artifact constructor a tool wraps its output in. */ export type SpooledArtifactCtor = SpooledArtifactConstructor; /** * The artifact configuration accepted by a factory: a constructor, a sync resolver, or an async / * dynamic-import resolver (which may yield a module namespace whose `default` is the constructor). * * @remarks * Mirrors the vector battery's `client` resolver and `Tool.artifactConstructor`'s indirection. The * async form lets a consumer `() => import('@nhtio/adk/spooled_artifact').then(m => m.SpooledMarkdownArtifact)` * so the artifact class never enters their static module graph. */ export type ArtifactResolver = SpooledArtifactCtor | (() => SpooledArtifactCtor | { default: SpooledArtifactCtor; }) | (() => Promise); /** The sync subset of {@link ArtifactResolver} — a constructor or a sync resolver (no Promise). */ export type SyncArtifactResolver = SpooledArtifactCtor | (() => SpooledArtifactCtor | { default: SpooledArtifactCtor; }); /** * Resolve an {@link ArtifactResolver} to the **sync** `() => SpooledArtifactCtor` that * `Tool.artifactConstructor` requires (the wrap-site and the construction-time validator both * invoke it synchronously, so an async resolver cannot be passed straight through). * * @remarks * A bare constructor is itself a function, so it is distinguished from a resolver via * `SpooledArtifact.isSpooledArtifactConstructor` (the same duck-typed guard the core validator * uses) rather than by arity. Async because a dynamic-import resolver must be awaited here. * * @param resolver - The artifact configuration. When `undefined`, callers should fall back to * their own default (this function rejects `undefined` so the default lives with the caller). * @param onInvalid - Throws a battery-scoped error; receives a human-readable reason. * @returns A sync `() => SpooledArtifactCtor` suitable for `Tool.artifactConstructor`. */ export declare const resolveArtifact: (resolver: ArtifactResolver, onInvalid: (reason: string) => never) => Promise<() => SpooledArtifactCtor>; /** * Synchronous {@link resolveArtifact}: accepts only the {@link SyncArtifactResolver} subset and * throws (via `onInvalid`) on an async resolver — a runtime guard for JS callers who bypass the * compile-time narrowing. * * @param resolver - A constructor or a sync resolver. * @param onInvalid - Throws a battery-scoped error; receives a human-readable reason. * @returns A sync `() => SpooledArtifactCtor` suitable for `Tool.artifactConstructor`. */ export declare const resolveArtifactSync: (resolver: SyncArtifactResolver, onInvalid: (reason: string) => never) => (() => SpooledArtifactCtor); /** `true` when `value` is the short-circuit sentinel produced by {@link makeShortCircuit}. */ export declare const isShortCircuit: (value: unknown) => value is { result: string; }; /** * Build a `shortCircuit(result)` function for an input-pipeline context. Calling it throws the * internal sentinel, which {@link runInputPipeline} catches and converts into the verbatim result * (skipping the HTTP request entirely — e.g. a cache hit). * * @returns A function that, when called with a result string, throws the short-circuit sentinel. */ export declare const makeShortCircuit: () => ((result: string) => never); /** A generic onion middleware stage over a mutable context `C`. */ export type MiddlewareFn = (ctx: C, next: NextFn) => void | Promise; /** * Run an input pipeline over `ctx`. Returns the short-circuit string when a stage short-circuited, * or `undefined` when the pipeline reached its terminal handler. A non-terminal pipeline (a stage * that neither called `next()` nor short-circuited) throws — the caller converts it to an * `Error:` string. * * @param mw - The `Middleware` instance holding the stages (a fresh `.runner()` is minted here). * @param ctx - The mutable input context handed to each stage. * @param label - Battery name, used in the non-terminal error message. * @returns The short-circuit result string, or `undefined` if the pipeline ran to completion. */ export declare const runInputPipeline: (mw: Middleware>, ctx: C, label: string) => Promise; /** * Run an output pipeline over `ctx`; rethrow any stage error to the caller's try/catch. A * non-terminal pipeline (no `next()`) throws. * * @param mw - The `Middleware` instance holding the stages (a fresh `.runner()` is minted here). * @param ctx - The mutable output context handed to each stage. * @param label - Battery name, used in the non-terminal error message. */ export declare const runOutputPipeline: (mw: Middleware>, ctx: C, label: string) => Promise; /** * Optional per-call gate run before a side-effecting tool executes. Throwing aborts the call * and surfaces through the standard tool-error path (`E_TOOL_DOWNSTREAM_ERROR` with the denial * as `cause`). The canonical implementation awaits `ctx.waitFor({ reason: 'tool_approval', * payload: call })` — the ADK gates primitive — and throws on denial; WHO approves and HOW is * the consumer's contract, this type is the seam. */ export type ToolGateFn = (ctx: unknown, call: { tool: string; args: unknown; }) => void | Promise; /** * Await a configured {@link ToolGateFn} (no-op when absent). Factory batteries call this at * the top of their handlers so the gate runs before any side effect. * * @param gate - The configured gate, if any. * @param ctx - The dispatch context the handler received. * @param tool - The tool name (post-override). * @param args - The validated tool args. */ export declare const runToolGate: (gate: ToolGateFn | undefined, ctx: unknown, tool: string, args: unknown) => Promise;