import { type LLMCallTraceContext, type LLMToolResult } from '../LLMService.typedefs'; import { type LLMReporterInterface } from '../utilities/reporter'; import { type LLMSchemaInterface } from '../utilities/schema'; import { type LLMToolObservationOptions } from '../utilities/llmTracing'; import { type LLMPromptBinding, type LLMPromptRegistry } from '../client/defineLLMPrompts'; import { type LLMAgentInlineRunOptions, type LLMAgentRunResult } from '../client/agentRun.typedefs'; import { LLMAgent, type LLMAgentDefinition } from '../client/LLMAgent'; import { type LLMAgentCallServices, type LLMPromptResolutionCall } from '../client/agentRunner'; import { type LLMClientCallContext, type LLMClientEngineConfig, type LLMCompilePromptOptions, type LLMGenerateOptions, type LLMGenerateResult, type LLMPlainMessage, type LLMPromptDescription, type LLMProviderServiceScope, type LLMReporterInvocation, type LLMToolResultContext, type LLMTraceContextScope } from '../client/llmClient.typedefs'; import { type LLMVariableValue } from '../client/promptSnapshot.typedefs'; import { type ResolvedPrompt } from '../client/promptRegistry.runtime'; /** * The client's single implementation. `createLLMClient` owns its construction * and exposes only the `LLMClient` surface, so every call path — `generate`, * `countTokens`, `runAgent`, `describePrompt`, `compilePrompt` — shares one * prompt resolution, one credentials lookup, one reporter/trace context, and one * error taxonomy. */ export declare class LLMClientEngine implements LLMAgentCallServices { private readonly gateway; private readonly registry; private readonly runtime; private readonly credentials; private readonly reporter; private readonly buildReporterContextFor; private readonly logger; private readonly staticContext; private readonly mode; private readonly toolResultNormalizer; private readonly agentRunner; constructor(config: LLMClientEngineConfig); generate(prompt: Key, options: LLMGenerateOptions, Schema>): Promise; defineAgent(definition: LLMAgentDefinition, Key>): LLMAgent, Key>; runAgent(promptOrAgent: Key | LLMAgent>, options: LLMAgentInlineRunOptions, Registry, Record>): Promise>>; countTokens(prompt: Key, options: { variables: Record; history?: LLMPlainMessage[]; }): Promise; compilePrompt(prompt: Key, options: LLMCompilePromptOptions>): Promise; describePrompt(prompt: Key): Promise; resolvePrompt(promptName: string, binding: LLMPromptBinding, variables: Record, call: LLMPromptResolutionCall): Promise; /** * The single place a tool's return value becomes what the model reads. The * package's own coercion always runs first, so a client-supplied normalizer * never sees a malformed value and cannot reintroduce one. */ normalizeToolResult(context: LLMToolResultContext): LLMToolResult; withAgentObservation(name: string, input: unknown, fn: () => Promise): Promise; withToolObservation(name: string, input: unknown, fn: () => Promise, options?: LLMToolObservationOptions): Promise; private runCompletion; /** * Builds the provider message envelope from the resolved prompt. A `text` * prompt is one user message. A `chat` prompt preserves the structure the * prompt declares: a leading `system` message maps to `instructions`, the final * `user` message is the request, and any messages between them join the * call-supplied history in order. */ private buildMessageEnvelope; private findLastUserIndex; private callProvider; unwrapResult(resolved: ResolvedPrompt, schema: LLMSchemaInterface | undefined, sendResult: { text?: string; data?: unknown; parseError?: string; }): unknown; toTaxonomyError(error: unknown, resolved: ResolvedPrompt, abortSignal?: AbortSignal): Error; buildAssistanceService(options: LLMProviderServiceScope): Promise>>; getBinding(promptName: string): LLMPromptBinding | undefined; private buildCompletionService; /** * Resolves credentials for the product this call belongs to. The per-call * context wins over the static one: the client is built once per process, so * its static product is only ever the one its builder knew, while a call site * that resolves the product from its own subject knows better. */ private resolveProviderOptions; private buildUserMessage; private buildHistory; private toCompletionMessage; /** * Delegates the reporter's payload to the composition root. The gateway never * shapes it: those fields are a downstream contract (DWH columns and the * dashboards built on their exact values), so inventing a key or a string * here would silently break analytics rather than fail a build. * * The active trace scope's context travels along as `scopeContext`, so the * composition root can fall back to what the surrounding operation declared * when the call itself names nothing. */ buildReporterContext(resolved: ResolvedPrompt, callContext: LLMClientCallContext | undefined, invocation?: LLMReporterInvocation): unknown; /** * Builds the per-call trace context every client path threads into the gateway * service. The structural `prompt` names the observation and carries the * managed prompt version, so the generation the service records on success and * on error is the single one Langfuse links to that prompt — the client never * records a second observation of its own. * * `userId`, `sessionId` and `tags` travel as typed trace fields and never * through `serializeCallContext`, which is the metadata path. The user * therefore appears twice — typed here and, as it always has, inside the * metadata bag the existing dashboards read. */ buildTraceContext(scope: LLMTraceContextScope): LLMCallTraceContext; /** * The call context holds the user as whatever the application uses for its * own ids, while Langfuse holds it as a string. Absent stays absent, so a * call that names no user leaves the trace's user field for the scope to fill. */ private toTraceUserId; private assertOverridesAllowed; private serializeCallContext; private extractStatus; private isRetryableStatus; }