import { type IExecutor, type INeedResolver, type LlmComponent } from '@mcp-abap-adt/llm-agent'; export interface CyclicReActExecutorDeps { llm: import('@mcp-abap-adt/llm-agent').ILlm; /** Invoke an MCP tool by name with args; returns the textual result. */ callMcp: (name: string, args: unknown, signal?: AbortSignal) => Promise; component: LlmComponent; maxIterations: number; /** * Always-on unmet-need analyzer. Injected here (NOT only via execute input) * so the context-augmenting loop is STRUCTURALLY always-on: the executor is * built once and shared by every Stepper mode, so a resolver on its deps can * never be left undefined by a forgotten thread-through (the bug this fixes). * `execute` input may still override it (tests / per-call tuning). */ needResolver?: INeedResolver; /** * Optional system-prompt override for the executor. Defaults to the * task-agnostic EXECUTOR_SYSTEM. A consumer can override it via * `coordinator.flow.executor.systemPrompt` (yaml) or the builder — e.g. to * inject domain prerequisites for a cheap executor that lacks a smart planner * above it (cyclic mode). Threading it here, not hard-coding domain text in * EXECUTOR_SYSTEM, keeps the default prompt agnostic. */ systemPrompt?: string; /** * How many CONSECUTIVE unmet-need iterations whose tool re-query surfaces NO * new tool are tolerated before the executor escalates to the consumer * (18.1): analyze answer → find tools → add (preserving existing) → retry; if * after this many rounds nothing new helps, the capability is genuinely * unavailable → throw ClarifySignal (exit, ask the consumer) instead of * returning a silent partial. Default 2 (clamped to ≥ 1). */ maxNoProgressNeeds?: number; /** * Guard 2b — explicit "no capability" error instead of silent hallucination. * When the executor starts with NO tools (empty `input.tools`), the toolsRag * seed + needs search return NOTHING, and there are no external tools, the * tool subsystem yielded zero capability. A model handed an empty toolset for * a task that needs tools will fabricate an answer (observed live: a DAG * worker that hit a dead MCP proxy got 0 tools and invented a review from the * program name, promptTokens=1224 vs 507650 with a live proxy). By default the * executor REFUSES to run toolless and throws ClarifySignal so the consumer * learns the capability is missing. Set `true` only for genuinely tool-free * reasoning steps. Default false. */ allowToolless?: boolean; } /** * Task-agnostic tool-use protocol for the executor. It says NOTHING about the * task type or any specific tool/MCP — only how to behave when a needed * capability is missing or a tool fails. This is what makes the always-on * unmet-need detection (INeedResolver) effective: the model is told to VOICE the * gap instead of guessing or silently finishing, so a no-tool-call "I need X" * utterance is produced, which the tool-definer then turns into a toolsRag * re-query. Keep it generic — the runtime is MCP- and task-agnostic. */ export declare const EXECUTOR_SYSTEM = "You complete the task by calling the available tools. If you need a capability the available tools do not provide, or a tool call fails or returns an error / empty / \"not found\" result, do NOT guess, fabricate, or give a final answer prematurely. Instead, state in ONE sentence the capability you still need (e.g. \"I need a tool to \"). Produce your final answer only once you actually have the data the task requires."; export declare class CyclicReActExecutor implements IExecutor { private readonly deps; readonly name = "cyclic-react"; constructor(deps: CyclicReActExecutorDeps); execute(input: Parameters[0]): ReturnType; } //# sourceMappingURL=cyclic-react-executor.d.ts.map