API Reference¶
Complete reference for every public type, class, function, and constant exported by the Tepa framework. Organized by package, then alphabetically within each section.
Packages covered:
@tepa/core | @tepa/types | @tepa/tools | @tepa/provider-core | @tepa/provider-anthropic | @tepa/provider-openai | @tepa/provider-gemini | @tepa/observability-llmvantage
@tepa/core¶
The main orchestration package. Provides the Tepa class, configuration utilities, prompt parsing, the event bus, and all error classes.
Tepa¶
The top-level pipeline orchestrator. Runs the Plan-Execute-Evaluate loop until the evaluator passes, limits are reached, or an error occurs.
Constructor¶
| Parameter | Type | Description |
|---|---|---|
options.provider |
LLMProvider |
LLM provider used by all pipeline components |
options.tools |
ToolDefinition[] |
Tools available to the Planner and Executor |
options.config |
DeepPartial<TepaConfig> |
Optional partial config, merged with defaults |
options.events |
EventMap |
Optional event hook callbacks |
run()¶
Executes the full pipeline loop. Returns a structured result — never throws TepaError subclasses (they are caught and returned as { status: "fail" }). Other errors propagate.
| Return status | Condition |
|---|---|
"pass" |
Evaluator returned verdict: "pass" |
"fail" |
Max cycles exhausted or unrecoverable TepaError |
"terminated" |
Token budget exceeded (TepaTokenBudgetExceeded) |
TepaOptions¶
interface TepaOptions {
config?: DeepPartial<TepaConfig>;
tools: ToolDefinition[];
provider: LLMProvider;
events?: EventMap;
}
defineConfig()¶
import { defineConfig } from "@tepa/core";
function defineConfig(partial?: DeepPartial<TepaConfig>): TepaConfig;
Deep-merges a partial configuration object with DEFAULT_CONFIG and validates the result with Zod. Throws TepaConfigError if the merged config is invalid.
DEFAULT_CONFIG¶
const DEFAULT_CONFIG: TepaConfig = {
model: {
planner: "claude-sonnet-4-6",
evaluator: "claude-sonnet-4-6",
executor: {
low: "claude-haiku-4-5",
high: "claude-sonnet-4-6",
},
},
limits: {
maxCycles: 5,
maxTokens: 64_000,
toolTimeout: 30_000,
retryAttempts: 1,
},
tools: [],
logging: {
level: "info",
},
};
loadConfig()¶
import { loadConfig } from "@tepa/core";
async function loadConfig(filePath: string): Promise<TepaConfig>;
Reads a .yaml, .yml, or .json file, parses it, and passes it through defineConfig(). Throws TepaConfigError on read/parse failure or unsupported format.
validateModelConfig()¶
import { validateModelConfig } from "@tepa/core";
function validateModelConfig(providerModels: ModelInfo[], modelConfig: ModelConfig): void;
Validates that every model ID referenced by modelConfig — planner, evaluator, executor.low, and executor.high — exists in the provider's catalog. Throws TepaConfigError on invalid model references, naming the offending field. Called internally by Tepa.run() but exported for programmatic use.
parsePromptFile()¶
import { parsePromptFile } from "@tepa/core";
async function parsePromptFile(filePath: string): Promise<TepaPrompt>;
Loads and validates a prompt from a YAML or JSON file. Throws TepaPromptError on failure.
validatePrompt()¶
Validates that data conforms to the TepaPrompt structure. Returns the validated prompt or throws TepaPromptError.
EventBus¶
Manages event callback registration and execution. Callbacks run in registration order; each can transform the data passed to the next.
Constructor¶
run()¶
Executes all callbacks registered for eventName, passing data through each handler in sequence. If a handler returns a non-null/non-undefined value, it replaces data for subsequent handlers. Returns the final (potentially transformed) data.
Error behavior depends on the registration:
EventCallback(bare function): errors propagate immediatelyEventRegistrationwithcontinueOnError: true: errors are swallowed, pre-error data is preserved
Scratchpad¶
In-memory key-value store that persists across execution steps within a pipeline run.
| Method | Signature | Description |
|---|---|---|
read |
read(key: string): unknown |
Get a value by key |
has |
has(key: string): boolean |
Check if a key exists |
write |
write(key: string, value: unknown): void |
Set a key-value pair |
entries |
entries(): Record<string, unknown> |
Get all stored entries |
clear |
clear(): void |
Remove all entries |
TokenTracker¶
Tracks token usage against a budget.
| Method | Signature | Description |
|---|---|---|
constructor |
new TokenTracker(budget: number) |
Create tracker with a token budget |
add |
add(tokens: number): void |
Add tokens. Throws TepaTokenBudgetExceeded if budget exceeded |
getUsed |
getUsed(): number |
Total tokens consumed so far |
getBudget |
getBudget(): number |
The configured budget |
getRemaining |
getRemaining(): number |
Math.max(0, budget - used) |
isExhausted |
isExhausted(): boolean |
true if used >= budget |
TepaLogger (Interface)¶
The logging interface that all loggers must satisfy. Pass any compatible logger (pino, winston, console, or custom) via TepaOptions.logger:
interface TepaLogger {
debug(msg: string, meta?: Record<string, unknown>): void;
info(msg: string, meta?: Record<string, unknown>): void;
warn(msg: string, meta?: Record<string, unknown>): void;
error(msg: string, meta?: Record<string, unknown>): void;
}
Most popular logging libraries already satisfy this interface out of the box.
createConsoleLogger()¶
Factory for the built-in console logger. Used as the default when no external logger is provided.
| Level | Output |
|---|---|
"debug" |
Everything: token counts, output previews, budget percentages |
"info" |
Pipeline banners, stage summaries, step progress |
"warn" |
Warnings only |
"error" |
Errors only |
LogEntryCollector¶
Collects structured LogEntry records in memory for result.logs. Independent of the TepaLogger — always collects regardless of log level.
| Method | Signature | Description |
|---|---|---|
add |
add(entry: Omit<LogEntry, "timestamp">) |
Add an entry with auto-timestamp |
getEntries |
getEntries(): LogEntry[] |
Returns a defensive copy of all entries |
Planner¶
Constructor¶
new Planner(
provider: LLMProvider,
registry: ToolRegistry,
model: string,
modelCatalog: ModelInfo[],
defaultModelId: string
)
plan()¶
async plan(
prompt: TepaPrompt,
feedback?: string,
scratchpad?: Scratchpad
): Promise<{ plan: Plan; tokensUsed: number }>
Generates a plan from a prompt, optionally incorporating evaluator feedback and scratchpad state. Retries once with a simplified prompt on parse failure. Throws TepaCycleError if both attempts fail.
Executor¶
Constructor¶
execute()¶
async execute(
plan: Plan,
context: ExecutionContext,
eventBus?: EventBus,
cycleMeta?: CycleMetadata
): Promise<ExecutorOutput>
Executes a plan step-by-step. Steps are topologically sorted by dependencies using Kahn's algorithm. Throws TepaCycleError on circular dependencies.
ExecutionContext¶
interface ExecutionContext {
prompt: TepaPrompt;
cycle: number;
scratchpad: Scratchpad;
previousResults?: ExecutionResult[];
}
| Field | Description |
|---|---|
prompt |
The original prompt driving this pipeline run |
cycle |
Current cycle number (1-based) |
scratchpad |
Shared scratchpad persisting across steps |
previousResults |
Results from previous cycles, if any |
ExecutorOutput¶
Evaluator¶
Constructor¶
evaluate()¶
async evaluate(
prompt: TepaPrompt,
executionResults: ExecutionResult[],
scratchpad: Scratchpad
): Promise<EvaluationResult>
Evaluates execution results against the prompt's expected output. Retries once on parse failure. Returns a synthetic fail (confidence: 0) if both attempts fail.
Event Input Types¶
These types describe the data passed to event callbacks at each lifecycle point.
PlannerInput¶
Passed to prePlanner / postPlanner callbacks.
ExecutorInput¶
interface ExecutorInput {
plan: Plan;
prompt: TepaPrompt;
cycle: number;
scratchpad: Scratchpad;
previousResults?: ExecutionResult[];
}
Passed to preExecutor / postExecutor callbacks.
EvaluatorInput¶
interface EvaluatorInput {
prompt: TepaPrompt;
results: ExecutionResult[];
scratchpad: Scratchpad;
}
Passed to preEvaluator / postEvaluator callbacks.
Error Classes¶
All errors extend Error and set their name property for easy identification in catch blocks.
TepaError¶
Base error for all Tepa-specific errors.
TepaConfigError¶
Thrown by defineConfig() and loadConfig() when configuration is invalid.
TepaPromptError¶
Thrown by validatePrompt() and parsePromptFile() when prompt data is malformed.
TepaToolError¶
Thrown when tool registration or execution fails.
TepaCycleError¶
Thrown on pipeline cycle failures such as plan parse errors or circular dependencies.
TepaTokenBudgetExceeded¶
class TepaTokenBudgetExceeded extends TepaError {
public readonly tokensUsed: number;
public readonly tokenBudget: number;
constructor(tokensUsed: number, tokenBudget: number);
// message: "Token budget exceeded: used {tokensUsed} of {tokenBudget} tokens"
}
Thrown by TokenTracker.add() when accumulated usage exceeds the budget. Caught by Tepa.run() and returned as { status: "terminated" }.
@tepa/types¶
Pure type definitions shared across all Tepa packages. No runtime code — import freely without adding bundle weight.
Config Types¶
TepaConfig¶
interface TepaConfig {
model: ModelConfig;
limits: LimitsConfig;
tools: string[];
logging: LoggingConfig;
}
ModelConfig¶
interface ExecutorTiers {
low: string;
high: string;
}
interface ModelConfig {
planner: string;
evaluator: string;
executor: ExecutorTiers;
}
Assigns a model identifier to each pipeline phase. Values are provider-specific model strings (e.g., "claude-sonnet-4-6", "gpt-5-mini"). The executor is a two-tier object — the Planner picks "low" or "high" per step. See Configuration — Per-Step Tier Selection.
ModelInfo¶
interface ModelInfo {
id: string;
description: string;
tier: "fast" | "balanced" | "advanced";
capabilities?: string[];
cost?: ModelPricing;
}
Metadata describing a model available from a provider. Returned by LLMProvider.getModels() and rendered in the Planner's system prompt to guide per-step model selection. The optional cost field carries per-1M-token pricing — provider packages may ship best-effort defaults; verify against the current provider pricing page for production billing.
LimitsConfig¶
interface LimitsConfig {
maxCycles: number;
maxTokens: number;
toolTimeout: number;
retryAttempts: number;
}
| Field | Default | Description |
|---|---|---|
maxCycles |
5 |
Maximum Plan-Execute-Evaluate cycles before returning "fail" |
maxTokens |
64000 |
Total token budget across all LLM calls |
toolTimeout |
30000 |
Timeout per tool execution in milliseconds |
retryAttempts |
1 |
Number of retries on parse failures (planner/evaluator) |
LogLevel¶
LoggingConfig¶
DeepPartial<T>¶
Recursively makes all properties optional. Used by defineConfig() so you only need to specify overrides.
Prompt Types¶
TepaPrompt¶
interface TepaPrompt {
goal: string;
context: Record<string, unknown>;
expectedOutput: string | ExpectedOutput[];
}
| Field | Description |
|---|---|
goal |
What the pipeline should accomplish |
context |
Arbitrary key-value data available to all pipeline components |
expectedOutput |
Criteria for the evaluator — a string description or structured array |
ExpectedOutput¶
| Field | Description |
|---|---|
path |
Optional file path or artifact location |
description |
What this output should contain |
criteria |
Specific quality checks the evaluator should verify |
Plan Types¶
Plan¶
PlanStep¶
interface PlanStep {
id: string;
description: string;
tools: string[];
expectedOutcome: string;
dependencies: string[];
tier?: "low" | "high";
}
| Field | Description |
|---|---|
id |
Unique step identifier |
description |
What this step does |
tools |
Tool names to invoke. Empty array = reasoning step (pure LLM text) |
expectedOutcome |
What success looks like for this step |
dependencies |
IDs of steps that must complete first |
tier |
Optional executor tier ("low" or "high"). Defaults to "low" if omitted |
Execution Types¶
ExecutionResult¶
interface ExecutionResult {
stepId: string;
status: "success" | "failure";
output: unknown;
error?: string;
tokensUsed: number;
durationMs: number;
}
Evaluation Types¶
EvaluationResult¶
interface EvaluationResult {
verdict: "pass" | "fail";
confidence: number;
feedback?: string;
summary?: string;
tokensUsed: number;
}
| Field | Description |
|---|---|
verdict |
"pass" ends the pipeline; "fail" triggers re-planning |
confidence |
0–1 score indicating evaluator certainty |
feedback |
On "fail", guidance fed back to the Planner for re-planning |
summary |
On "pass", human-readable summary of what was accomplished |
Tool Types¶
ToolDefinition¶
interface ToolDefinition {
name: string;
description: string;
parameters: Record<string, ParameterDef>;
execute: (params: Record<string, unknown>) => Promise<unknown>;
}
ParameterDef¶
interface ParameterDef {
type: "string" | "number" | "boolean" | "object" | "array";
description: string;
required?: boolean;
default?: unknown;
}
ToolRegistry¶
interface ToolRegistry {
register(tool: ToolDefinition): void;
get(name: string): ToolDefinition | undefined;
list(): ToolDefinition[];
toSchema(): ToolSchema[];
}
ToolSchema¶
interface ToolSchema {
name: string;
description: string;
parameters: Record<string, ParameterDef>;
}
The read-only subset of ToolDefinition (without execute) sent to LLM providers for native tool calling.
LLM Types¶
LLMProvider¶
interface LLMProvider {
complete(messages: LLMMessage[], options: LLMRequestOptions): Promise<LLMResponse>;
getModels(): ModelInfo[];
}
The core interface that all provider implementations must satisfy. getModels() returns the provider's model catalog — used by the pipeline to populate the Planner's system prompt and validate per-step model assignments.
LLMMessage¶
LLMRequestOptions¶
interface LLMRequestOptions {
model: string;
maxTokens?: number;
temperature?: number;
systemPrompt?: string;
tools?: ToolSchema[];
}
LLMResponse¶
interface LLMResponse {
text: string;
tokensUsed: LLMTokensUsed;
finishReason: "end_turn" | "max_tokens" | "stop_sequence" | "tool_use";
toolUse?: LLMToolUseBlock[];
}
| Field | Description |
|---|---|
text |
The text content of the model's response |
tokensUsed |
Token counts (see LLMTokensUsed) |
finishReason |
Why the model stopped generating |
toolUse |
Tool call requests (present when finishReason is "tool_use") |
LLMTokensUsed¶
| Field | Description |
|---|---|
input |
Total input tokens billed by the provider |
output |
Total output tokens billed by the provider |
cacheRead |
Cached input tokens reused from a prompt cache (Anthropic, OpenAI, Gemini all report this when prompt caching is active) |
cacheWrite |
Tokens written to a prompt cache. Anthropic only (cache_creation_input_tokens) |
ModelPricing¶
interface ModelPricing {
inputPer1M: number;
outputPer1M: number;
cacheReadPer1M?: number;
cacheWritePer1M?: number;
currency?: string;
}
Per-1M-tokens pricing attached to a ModelInfo (via the optional cost field) or supplied to @tepa/observability-llmvantage. currency defaults to "USD" when omitted.
LLMToolUseBlock¶
| Field | Description |
|---|---|
id |
Provider-assigned ID for correlating tool results |
name |
Name of the tool the LLM wants to call |
input |
Parsed input parameters for the tool |
LLMLogEntry¶
interface LLMLogEntry {
timestamp: string;
provider: string;
status: LLMLogStatus;
durationMs: number;
attempt: number;
request: {
model: string;
messageCount: number;
totalCharLength: number;
promptPreview: string;
maxTokens?: number;
temperature?: number;
hasSystemPrompt: boolean;
hasTools?: boolean;
messages?: LLMMessage[];
systemPrompt?: string;
};
response?: {
text: string;
tokensUsed: LLMTokensUsed;
finishReason: string;
toolUseCount?: number;
};
error?: {
message: string;
retryable: boolean;
};
}
The messages and systemPrompt fields in request are only populated when includeContent: true is set in provider options.
LLMLogStatus¶
LLMLogCallback¶
Event Types¶
EventName¶
type EventName =
| "prePlanner"
| "postPlanner"
| "preExecutor"
| "postExecutor"
| "preEvaluator"
| "postEvaluator"
| "preStep"
| "postStep";
EventCallback¶
type EventCallback<TData = unknown> = (
data: TData,
cycle: CycleMetadata,
) => TData | void | Promise<TData | void>;
A handler function that receives event data and cycle metadata. Return a value to transform the data for subsequent handlers; return void to pass through unchanged. Supports async/Promise for operations like human-in-the-loop pausing.
EventRegistration¶
interface EventRegistration<TData = unknown> {
handler: EventCallback<TData>;
continueOnError?: boolean;
}
Wraps an EventCallback with error handling options. When continueOnError is true, errors in this handler are swallowed and the pre-error data snapshot is preserved.
EventMap¶
The event configuration object passed to the Tepa constructor. Each event point accepts an array of callbacks or registrations.
CycleMetadata¶
PreStepPayload¶
Data passed to preStep event callbacks.
PostStepPayload¶
Data passed to postStep event callbacks.
Result Types¶
TepaResult¶
interface TepaResult {
status: "pass" | "fail" | "terminated";
cycles: number;
tokensUsed: number;
outputs: OutputArtifact[];
logs: LogEntry[];
feedback: string;
}
| Field | Description |
|---|---|
status |
Final pipeline outcome |
cycles |
Number of Plan-Execute-Evaluate cycles completed |
tokensUsed |
Total tokens consumed across all LLM calls |
outputs |
Artifacts produced by the pipeline |
logs |
Detailed execution log entries |
feedback |
Evaluator feedback (on fail) or summary (on pass) |
OutputArtifact¶
LogEntry¶
interface LogEntry {
timestamp: number;
cycle: number;
step?: string;
tool?: string;
message: string;
durationMs?: number;
tokensUsed?: number;
}
@tepa/tools¶
Tool definitions, the registry implementation, and validation utilities. Ships all built-in tools ready to use.
defineTool()¶
import { defineTool } from "@tepa/tools";
function defineTool(definition: {
name: string;
description: string;
parameters: Record<string, ParameterDef>;
execute: (params: Record<string, unknown>) => Promise<unknown>;
}): ToolDefinition;
Creates a validated ToolDefinition. Validates the schema with Zod at creation time. Throws Error with message "Invalid tool definition: ..." if the schema is malformed.
ToolRegistryImpl¶
Concrete implementation of the ToolRegistry interface.
| Method | Description |
|---|---|
register(tool) |
Register a tool. Throws if tool.name is already registered |
get(name) |
Retrieve a tool by name, or undefined |
list() |
Return all registered tools |
toSchema() |
Return all tools as ToolSchema[] (without execute) |
validateParams()¶
import { validateParams } from "@tepa/tools";
function validateParams(
params: Record<string, unknown>,
parameters: Record<string, ParameterDef>,
): Record<string, unknown>;
Validates params against a parameter schema. Returns the validated (and potentially defaulted) params. Throws Error with message "Parameter validation failed: ..." on failure.
buildZodSchema()¶
import { buildZodSchema } from "@tepa/tools";
function buildZodSchema(
parameters: Record<string, ParameterDef>,
): z.ZodObject<Record<string, z.ZodTypeAny>>;
Converts a Record<string, ParameterDef> into a Zod schema. Type mapping:
ParameterDef.type |
Zod type |
|---|---|
"string" |
z.string() |
"number" |
z.number() |
"boolean" |
z.boolean() |
"object" |
z.record(z.unknown()) |
"array" |
z.array(z.unknown()) |
If required is falsy and no default is set, the field becomes .optional(). If default is defined, .default(value) is applied.
Built-in Tools¶
All built-in tools are exported as named constants and created via defineTool().
import {
fileReadTool,
fileWriteTool,
directoryListTool,
fileSearchTool,
shellExecuteTool,
httpRequestTool,
webSearchTool,
dataParseTool,
scratchpadTool,
logObserveTool,
} from "@tepa/tools";
file_read¶
Reads a file and returns its contents.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
path |
string |
Yes | — | File path to read |
encoding |
string |
No | "utf-8" |
File encoding |
file_write¶
Writes content to a file, creating directories as needed.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
path |
string |
Yes | — | File path to write |
content |
string |
Yes | — | Content to write |
directory_list¶
Lists files and directories at a path.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
path |
string |
Yes | — | Directory path |
maxDepth |
number |
No | 1 |
Maximum recursion depth |
file_search¶
Searches for files matching a glob pattern.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
pattern |
string |
Yes | — | Glob pattern to match |
cwd |
string |
No | "." |
Working directory for the search |
shell_execute¶
Runs a shell command and returns its output.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
command |
string |
Yes | — | Command to execute |
cwd |
string |
No | — | Working directory |
timeout |
number |
No | 30000 |
Timeout in milliseconds |
http_request¶
Makes an HTTP request and returns the response.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
url |
string |
Yes | — | Request URL |
method |
string |
No | "GET" |
HTTP method |
headers |
object |
No | — | Request headers |
queryParams |
object |
No | — | URL query parameters |
body |
string |
No | — | Request body |
timeout |
number |
No | 30000 |
Timeout in milliseconds |
web_search¶
Performs a web search via an external search API.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
query |
string |
Yes | — | Search query |
endpoint |
string |
Yes | — | Search API endpoint URL |
count |
number |
No | 5 |
Number of results to return |
data_parse¶
Parses structured data (CSV, JSON, YAML, etc.).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
input |
string |
Yes | — | Data string or file path (if fromFile is true) |
format |
string |
Yes | — | Data format (e.g., "csv", "json", "yaml") |
fromFile |
boolean |
No | false |
Whether input is a file path |
preview |
number |
No | — | Limit output to first N records |
scratchpad¶
Reads from or writes to the pipeline's shared scratchpad.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
action |
string |
Yes | — | "read" or "write" |
key |
string |
Yes | — | Scratchpad key |
value |
string |
No | — | Value to write (required for "write" action) |
log_observe¶
Writes an observation message to the pipeline log.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
message |
string |
Yes | — | Message to log |
level |
string |
No | "info" |
Log level |
clearScratchpad()¶
Clears all scratchpad data. Primarily useful in testing.
@tepa/provider-core¶
Base class and logging utilities shared by all LLM provider implementations. Use this package when building a custom provider.
BaseLLMProvider¶
Abstract base class implementing retry logic, exponential backoff, rate limit handling, and logging for LLM providers.
Constructor¶
Abstract Members (must be implemented by subclasses)¶
| Member | Signature | Description |
|---|---|---|
providerName |
protected abstract readonly providerName: string |
Identifier used in log entries |
models |
protected abstract readonly models: ModelInfo[] |
Model catalog this provider supports |
doComplete |
protected abstract doComplete(messages: LLMMessage[], options: LLMRequestOptions): Promise<LLMResponse> |
The actual API call |
isRetryable |
protected abstract isRetryable(error: unknown): boolean |
Whether an error should trigger a retry |
isRateLimitError |
protected abstract isRateLimitError(error: unknown): boolean |
Whether an error is a rate limit (uses longer backoff) |
getRetryAfterMs |
protected abstract getRetryAfterMs(error: unknown): number \| null |
Extract retry-after from error, or null |
Public Methods¶
| Method | Signature | Description |
|---|---|---|
complete |
async complete(messages: LLMMessage[], options: LLMRequestOptions): Promise<LLMResponse> |
Call with retry logic. Delegates to doComplete |
getModels |
getModels(): ModelInfo[] |
Return the model catalog (defensive copy) |
onLog |
onLog(callback: LLMLogCallback): void |
Register an additional log listener |
getLogEntries |
getLogEntries(): LLMLogEntry[] |
Get a copy of accumulated log history |
getLogFilePath |
getLogFilePath(): string \| undefined |
Path to the JSONL log file, if file logging is enabled |
Retry Behavior¶
- Up to
maxRetriesattempts (default:3) - Standard backoff:
retryBaseDelayMs * 2^attempt(default base:1000ms) - Rate limit backoff:
retryBaseDelayMs * 30 * 2^attempt - Explicit
retry-afterheaders from the provider take precedence
BaseLLMProviderOptions¶
interface BaseLLMProviderOptions {
maxRetries?: number;
retryBaseDelayMs?: number;
defaultLog?: boolean;
logDir?: string;
includeContent?: boolean;
}
| Field | Default | Description |
|---|---|---|
maxRetries |
3 |
Maximum retries on transient/rate-limit errors |
retryBaseDelayMs |
1000 |
Base delay for exponential backoff (ms) |
defaultLog |
true |
Enable automatic JSONL file logging |
logDir |
".tepa/logs" |
Directory for log files |
includeContent |
false |
Include full message content in log entries (privacy control) |
consoleLogCallback()¶
import { consoleLogCallback } from "@tepa/provider-core";
function consoleLogCallback(entry: LLMLogEntry): void;
Prints log entries to the console in the format: [HH:MM:SS.mmm][status][provider] durationMs | detail
Use with provider.onLog(consoleLogCallback) to add console output alongside file logging.
createFileLogWriter()¶
import { createFileLogWriter } from "@tepa/provider-core";
function createFileLogWriter(dir?: string): FileLogWriter;
Creates a JSONL file logger. Files are named llm-{ISO-timestamp}.jsonl in the specified directory (default: ".tepa/logs").
FileLogWriter¶
| Field | Description |
|---|---|
callback |
The log callback to pass to provider.onLog() |
filePath |
Absolute path to the generated log file |
@tepa/provider-anthropic¶
Anthropic Claude provider implementation.
AnthropicProvider¶
Extends BaseLLMProvider. Uses the Anthropic Messages API.
Constructor¶
AnthropicProviderOptions¶
| Field | Default | Description |
|---|---|---|
apiKey |
process.env.ANTHROPIC_API_KEY |
Anthropic API key |
Default model: "claude-haiku-4-5" | Default max tokens: 64000
AnthropicModels¶
Type-safe model ID constants:
| Constant | Value |
|---|---|
Claude_Haiku_4_5 |
"claude-haiku-4-5" |
Claude_Sonnet_4_6 |
"claude-sonnet-4-6" |
Claude_Opus_4_6 |
"claude-opus-4-6" |
ANTHROPIC_MODEL_CATALOG¶
The full ModelInfo[] catalog array used internally by AnthropicProvider.getModels(). Exported for inspection or testing.
createProvider()¶
import { createProvider } from "@tepa/provider-anthropic";
function createProvider(name: ProviderName, options?: AnthropicProviderOptions): LLMProvider;
Factory function. Currently only supports name: "anthropic".
@tepa/provider-openai¶
OpenAI provider implementation using the Responses API.
OpenAIProvider¶
Extends BaseLLMProvider.
Constructor¶
OpenAIProviderOptions¶
| Field | Default | Description |
|---|---|---|
apiKey |
process.env.OPENAI_API_KEY |
OpenAI API key |
Default model: "gpt-5-mini" | Default max tokens: 64000
OpenAIModels¶
| Constant | Value |
|---|---|
GPT_5_Mini |
"gpt-5-mini" |
GPT_5 |
"gpt-5" |
OPENAI_MODEL_CATALOG¶
The full ModelInfo[] catalog array. Exported for inspection or testing.
@tepa/provider-gemini¶
Google Gemini provider implementation.
GeminiProvider¶
Extends BaseLLMProvider.
Constructor¶
GeminiProviderOptions¶
| Field | Default | Description |
|---|---|---|
apiKey |
process.env.GEMINI_API_KEY or process.env.GOOGLE_API_KEY |
Gemini API key |
Default model: "gemini-3-flash-preview" | Default max tokens: 64000
GeminiModels¶
| Constant | Value |
|---|---|
Gemini_3_Flash_Preview |
"gemini-3-flash-preview" |
Gemini_3_Pro_Preview |
"gemini-3-pro-preview" |
GEMINI_MODEL_CATALOG¶
The full ModelInfo[] catalog array. Exported for inspection or testing.
@tepa/observability-llmvantage¶
Optional adapter that turns Tepa's onLog stream into cost rollups and provides an llmvantage plugin that tags raw fetch events with cost. Install alongside llmvantage:
llmvantage is declared as an optional peer dependency; the bridge works without it, the tagCost plugin requires it at runtime.
createLlmvantageBridge()¶
import { createLlmvantageBridge } from "@tepa/observability-llmvantage";
const bridge = createLlmvantageBridge(opts?: BridgeOptions): Bridge;
BridgeOptions:
| Field | Type | Default | Description |
|---|---|---|---|
pricing |
PricingTable |
undefined |
Provider → model → ModelPricing. Merged on top of defaultPricing (per-provider object replaces). |
currency |
string |
"USD" |
Label used in RunSummary.cost.currency. Does not convert values. |
ignoreDefaultPricing |
boolean |
false |
Skip merging with defaultPricing and use pricing alone. |
Bridge:
| Member | Signature | Description |
|---|---|---|
callback |
(entry: LLMLogEntry) => void |
Wire with provider.onLog(bridge.callback). |
summary() |
() => RunSummary |
Snapshot of cost and token totals across entries seen so far. |
costFor(e) |
(entry: LLMLogEntry) => number |
Per-call cost using the bridge's pricing resolution. |
reset() |
() => void |
Discard accumulated entries. |
RunSummary:
interface RunSummary {
calls: number;
retries: number;
errors: number;
tokens: { input: number; output: number; cacheRead: number; cacheWrite: number };
cost: { total: number; currency: string };
byModel: Record<string, ModelSummary>; // keyed by `${provider}:${model}`
byProvider: Record<string, ModelSummary>; // keyed by provider id
pricingMissing: string[]; // provider:model pairs with no pricing entry
}
tagCost()¶
import { tagCost } from "@tepa/observability-llmvantage";
observer.use(tagCost(opts?: CostTagOptions)).pipe(sink);
llmvantage plugin that parses Anthropic / OpenAI / Gemini response bodies, extracts token counts (including cache fields), looks up pricing, and appends { tokens, cost: { value, currency, pricingKnown } } to each event before sinks see it.
CostTagOptions: same pricing, currency, and ignoreDefaultPricing as BridgeOptions.
costFor() / costForTokens()¶
Pure helpers — usable standalone without the bridge.
import { costFor, costForTokens } from "@tepa/observability-llmvantage";
costFor(entry: LLMLogEntry, pricing?: ModelPricing): number;
costForTokens(tokens: LLMTokensUsed, pricing?: ModelPricing): number;
Returns 0 when pricing is undefined. cacheRead falls back to inputPer1M when cacheReadPer1M is not set; cacheWrite falls back similarly. This is a conservative default so unknown cache pricing never under-counts cost.
lookupPricing()¶
lookupPricing(table: PricingTable | undefined, provider: string, model: string): ModelPricing | undefined;
Safe nested lookup. Returns undefined for any missing level.
defaultPricing¶
Best-effort USD/1M-tokens snapshot covering the models in ANTHROPIC_MODEL_CATALOG, OPENAI_MODEL_CATALOG, and GEMINI_MODEL_CATALOG. Pricing changes; verify against each provider's pricing page before relying on these for billing. Last reviewed: 2026-05.
PricingTable¶
Keyed provider id → model id → ModelPricing. ModelPricing is re-exported from @tepa/types.