@directive-run/ai 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +26 -31
  2. package/dist/anthropic.cjs +1 -1
  3. package/dist/anthropic.cjs.map +1 -1
  4. package/dist/anthropic.d.cts +5 -9
  5. package/dist/anthropic.d.ts +5 -9
  6. package/dist/anthropic.js +1 -1
  7. package/dist/anthropic.js.map +1 -1
  8. package/dist/gemini.cjs +3 -0
  9. package/dist/gemini.cjs.map +1 -0
  10. package/dist/gemini.d.cts +93 -0
  11. package/dist/gemini.d.ts +93 -0
  12. package/dist/gemini.js +3 -0
  13. package/dist/gemini.js.map +1 -0
  14. package/dist/index.cjs +117 -45
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +1376 -2106
  17. package/dist/index.d.ts +1376 -2106
  18. package/dist/index.js +117 -45
  19. package/dist/index.js.map +1 -1
  20. package/dist/multi-agent-orchestrator-CxL8ycw_.d.cts +2290 -0
  21. package/dist/multi-agent-orchestrator-uMp8bLfV.d.ts +2290 -0
  22. package/dist/ollama.cjs.map +1 -1
  23. package/dist/ollama.d.cts +3 -2
  24. package/dist/ollama.d.ts +3 -2
  25. package/dist/ollama.js.map +1 -1
  26. package/dist/openai.cjs +2 -2
  27. package/dist/openai.cjs.map +1 -1
  28. package/dist/openai.d.cts +4 -8
  29. package/dist/openai.d.ts +4 -8
  30. package/dist/openai.js +2 -2
  31. package/dist/openai.js.map +1 -1
  32. package/dist/semantic-cache-F0psCRuz.d.cts +271 -0
  33. package/dist/semantic-cache-F0psCRuz.d.ts +271 -0
  34. package/dist/testing.cjs +42 -7
  35. package/dist/testing.cjs.map +1 -1
  36. package/dist/testing.d.cts +365 -5
  37. package/dist/testing.d.ts +365 -5
  38. package/dist/testing.js +42 -7
  39. package/dist/testing.js.map +1 -1
  40. package/dist/types-Co4BzMiH.d.cts +1373 -0
  41. package/dist/types-Co4BzMiH.d.ts +1373 -0
  42. package/package.json +7 -2
  43. package/dist/types-Bbar7yKz.d.cts +0 -304
  44. package/dist/types-Bbar7yKz.d.ts +0 -304
package/dist/index.d.cts CHANGED
@@ -1,517 +1,11 @@
1
- import { Requirement, ModuleSchema, Plugin, System } from '@directive-run/core';
2
- import { CircuitState, ObservabilityInstance, TraceSpan, AggregatedMetric, CircuitBreakerConfig, CircuitBreaker, AlertConfig } from '@directive-run/core/plugins';
1
+ import { G as GuardrailFn, I as InputGuardrailData, O as OutputGuardrailData, S as SchemaValidator, T as ToolCallGuardrailData, A as AgentLike, M as Message, a as AdapterHooks, b as AgentRunner, c as ApprovalState, d as AgentState, R as RunOptions, e as RunResult, D as DebugEvent, B as BreakpointState, f as GoalResult } from './types-Co4BzMiH.cjs';
2
+ export { g as AgentCircuitBreakerConfig, h as AgentCompleteEvent, i as AgentErrorEvent, j as AgentHealthState, k as AgentRetryConfig, l as AgentRetryEvent, m as AgentSelectionStrategy, n as AgentStartEvent, o as ApprovalRequest, p as ApprovalRequestEvent, q as ApprovalResponseEvent, r as BreakpointConfig, s as BreakpointContext, t as BreakpointHitEvent, u as BreakpointModifications, v as BreakpointRequest, w as BreakpointResumedEvent, x as BreakpointState, y as BreakpointType, C as Checkpoint, z as CheckpointContext, E as CheckpointDiff, F as CheckpointLocalState, H as CheckpointProgress, J as CheckpointRestoreEvent, K as CheckpointSaveEvent, L as CheckpointStore, N as ConstraintEvaluateEvent, P as CrossAgentDerivationFn, Q as CrossAgentSnapshot, U as DagCheckpointState, V as DagExecutionContext, W as DagNode, X as DagNodeStatus, Y as DagNodeUpdateEvent, Z as DagPattern, _ as DebateCheckpointState, $ as DebateRoundEvent, a0 as DebugEventBase, a1 as DebugEventType, a2 as DerivationUpdateEvent, a3 as GoalCheckpointConfig, a4 as GoalCheckpointState, a5 as GoalMetrics, a6 as GoalNode, a7 as GoalPattern, a8 as GoalStepMetrics, a9 as GuardrailCheckEvent, aa as GuardrailContext, ab as GuardrailError, ac as GuardrailErrorCode, ad as GuardrailResult, ae as GuardrailRetryConfig, af as GuardrailsConfig, ag as HandoffCompleteEvent, ah as HandoffStartEvent, ai as HealthMonitorConfig, aj as InMemoryCheckpointStore, ak as InMemoryCheckpointStoreOptions, al as MAX_BREAKPOINT_HISTORY, am as MultiAgentBreakpointType, an as MultiAgentCheckpointLocalState, ao as MultiAgentLifecycleHooks, ap as MultiAgentSelfHealingConfig, aq as NamedGuardrail, ar as OrchestratorConstraint, as as OrchestratorDebugConfig, at as OrchestratorLifecycleHooks, au as OrchestratorResolver, av as OrchestratorResolverContext, aw as OrchestratorState, ax as PatternCheckpointBase, ay as PatternCheckpointConfig, az as PatternCheckpointState, aA as PatternCompleteEvent, aB as PatternStartEvent, aC as RaceCancelledEvent, aD as RaceStartEvent, aE as RaceWinnerEvent, aF as ReflectCheckpointState, aG as ReflectionIterationEvent, aH as RejectedRequest, aI as RelaxationContext, aJ as RelaxationRecord, aK as RelaxationStrategy, aL as RelaxationTier, aM as RerouteDebugEvent, aN as RerouteEvent, aO as ResolverCompleteEvent, aP as ResolverErrorEvent, aQ as ResolverStartEvent, aR as SchemaValidationResult, aS as Scratchpad, aT as ScratchpadUpdateEvent, aU as SelfHealingConfig, aV as SequentialCheckpointState, aW as SingleAgentCheckpointLocalState, aX as StreamingCallbackRunner, aY as SupervisorCheckpointState, aZ as TokenUsage, a_ as ToolCall, a$ as createBreakpointId, b0 as createCheckpointId, b1 as createInitialBreakpointState, b2 as isGuardrailError, b3 as matchBreakpoint, b4 as validateCheckpoint } from './types-Co4BzMiH.cjs';
3
+ import { E as ExecutionPattern, S as SerializedPattern, A as AgentHealthMetrics, D as DebugTimeline, H as HealthMonitor } from './multi-agent-orchestrator-CxL8ycw_.cjs';
4
+ export { a as AgentMemory, b as AgentMemoryConfig, c as AgentOrchestrator, d as AgentRegistration, e as AgentRegistry, B as BackpressureStrategy, f as DebateConfig, g as DebatePattern, h as DebateResult, i as DebugTimelineListener, j as DebugTimelineOptions, k as DoneChunk, l as ErrorChunk, G as GuardrailTriggeredChunk, m as HandoffRequest, n as HandoffResult, o as HealthCircuitState, M as MemoryManageResult, p as MemoryState, q as MemoryStrategy, r as MemoryStrategyConfig, s as MemoryStrategyResult, t as MergedTaggedStreamResult, u as MessageChunk, v as MessageSummarizer, w as MultiAgentOrchestrator, x as MultiAgentOrchestratorOptions, y as MultiAgentRunCallOptions, z as MultiAgentState, C as MultiplexedStreamChunk, F as MultiplexedStreamResult, O as OrchestratorOptions, I as OrchestratorStreamChunk, J as OrchestratorStreamResult, P as ParallelPattern, K as ProgressChunk, R as RacePattern, L as RaceResult, N as RaceSuccessEntry, Q as ReflectIterationRecord, T as ReflectPattern, U as ReflectionConfig, V as ReflectionContext, W as ReflectionEvaluation, X as ReflectionEvaluator, Y as ReflectionExhaustedError, Z as RunAgentRequirement, _ as RunCallOptions, $ as SafeParseResult, a0 as SafeParseable, a1 as Semaphore, a2 as SequentialPattern, a3 as SerializedDagNode, a4 as SerializedGoalNode, a5 as SpawnOnConditionOptions, a6 as SpawnPoolConfig, a7 as StreamChunk, a8 as StreamRunOptions, a9 as StreamRunner, aa as StreamingGuardrail, ab as StreamingGuardrailResult, ac as StreamingRunResult, ad as StructuredOutputConfig, ae as StructuredOutputError, af as SupervisorPattern, ag as TokenChunk, ah as ToolEndChunk, ai as ToolStartChunk, aj as adaptOutputGuardrail, ak as aggregateTokens, al as allReadyStrategy, am as capabilityRoute, an as collectOutputs, ao as collectTokens, ap as combineStreamingGuardrails, aq as composePatterns, ar as concatResults, as as costEfficientStrategy, at as createAgentMemory, au as createAgentOrchestrator, av as createDebugTimeline, aw as createDebugTimelinePlugin, ax as createHealthMonitor, ay as createHybridStrategy, az as createKeyPointsSummarizer, aA as createLLMSummarizer, aB as createLengthStreamingGuardrail, aC as createMultiAgentOrchestrator, aD as createPatternStreamingGuardrail, aE as createSlidingWindowStrategy, aF as createStreamingRunner, aG as createTokenBasedStrategy, aH as createToxicityStreamingGuardrail, aI as createTruncationSummarizer, aJ as dag, aK as debate, aL as derivedConstraint, aM as diffCheckpoints, aN as extractJsonFromOutput, aO as filterStream, aP as findAgentsByCapability, aQ as forkFromCheckpoint, aR as getCheckpointProgress, aS as getPatternStep, aT as goal, aU as highestImpactStrategy, aV as mapStream, aW as mergeTaggedStreams, aX as parallel, aY as patternFromJSON, aZ as patternToJSON, a_ as pickBestResult, a$ as race, b0 as reflect, b1 as runAgentRequirement, b2 as runDebate, b3 as selectAgent, b4 as sequential, b5 as spawnOnCondition, b6 as spawnPool, b7 as supervisor, b8 as tapStream, b9 as withReflection, ba as withStructuredOutput } from './multi-agent-orchestrator-CxL8ycw_.cjs';
3
5
  export { AggregatedMetric, AlertConfig, AlertEvent, CircuitBreaker, CircuitBreakerConfig, CircuitBreakerOpenError, CircuitBreakerStats, CircuitState, DashboardData, MetricDataPoint, MetricType, OTLPExporter, OTLPExporterConfig, ObservabilityConfig, ObservabilityInstance, TraceSpan, createAgentMetrics, createCircuitBreaker, createOTLPExporter, createObservability } from '@directive-run/core/plugins';
4
- import { M as Message$1, g as RunResult, b as AgentLike, d as GuardrailFn, O as OutputGuardrailData, I as InputGuardrailData, S as SchemaValidator, T as ToolCallGuardrailData, f as AdapterHooks, c as AgentRunner, h as ApprovalState, i as AgentState, j as OrchestratorState, k as OrchestratorConstraint, R as RunOptions, N as NamedGuardrail, l as OrchestratorResolver, A as ApprovalRequest, m as AgentRetryConfig, n as OrchestratorLifecycleHooks, o as GuardrailsConfig } from './types-Bbar7yKz.cjs';
5
- export { e as GuardrailContext, p as GuardrailError, q as GuardrailErrorCode, G as GuardrailResult, r as GuardrailRetryConfig, s as OrchestratorResolverContext, t as RejectedRequest, u as SchemaValidationResult, v as TokenUsage, a as ToolCall, w as isGuardrailError } from './types-Bbar7yKz.cjs';
6
-
7
- /**
8
- * Agent Memory System
9
- *
10
- * Provides sliding window message management and automatic summarization
11
- * for long-running agent conversations.
12
- *
13
- * @example
14
- * ```typescript
15
- * import { createAgentMemory, createSlidingWindowStrategy } from '@directive-run/ai';
16
- *
17
- * const memory = createAgentMemory({
18
- * strategy: createSlidingWindowStrategy({ maxMessages: 50 }),
19
- * summarizer: async (messages) => {
20
- * // Call LLM to summarize older messages
21
- * return await summarizeWithLLM(messages);
22
- * },
23
- * });
24
- *
25
- * // Use with orchestrator
26
- * const orchestrator = createAgentOrchestrator({
27
- * memory,
28
- * runner: run,
29
- * });
30
- * ```
31
- */
32
- /**
33
- * Memory-compatible message type.
34
- * Extends the standard Message type to include system messages for summaries.
35
- */
36
- interface MemoryMessage {
37
- role: "user" | "assistant" | "tool" | "system";
38
- content: string;
39
- toolCallId?: string;
40
- }
41
- type Message = MemoryMessage;
42
- /** Configuration for memory management strategies */
43
- interface MemoryStrategyConfig {
44
- /** Maximum number of messages to keep in active memory */
45
- maxMessages?: number;
46
- /** Maximum total tokens to keep in active memory */
47
- maxTokens?: number;
48
- /** Number of recent messages to always keep (protected from summarization) */
49
- preserveRecentCount?: number;
50
- /** Whether to include system messages in token count */
51
- countSystemMessages?: boolean;
52
- }
53
- /** Result of a memory strategy evaluation */
54
- interface MemoryStrategyResult {
55
- /** Messages to keep in active memory */
56
- keep: Message[];
57
- /** Messages to summarize or discard */
58
- toSummarize: Message[];
59
- /** Estimated token count of kept messages */
60
- estimatedTokens: number;
61
- }
62
- /** Memory management strategy function */
63
- type MemoryStrategy = (messages: Message[], config: MemoryStrategyConfig) => MemoryStrategyResult;
64
- /** Summarizer function to compress older messages */
65
- type MessageSummarizer = (messages: Message[]) => Promise<string>;
66
- /** Agent memory configuration */
67
- interface AgentMemoryConfig {
68
- /** Memory management strategy */
69
- strategy: MemoryStrategy;
70
- /** Optional summarizer for compressing old messages */
71
- summarizer?: MessageSummarizer;
72
- /** Strategy configuration */
73
- strategyConfig?: MemoryStrategyConfig;
74
- /** Whether to auto-manage memory after each interaction */
75
- autoManage?: boolean;
76
- /** Callback when memory is managed */
77
- onMemoryManaged?: (result: MemoryManageResult) => void;
78
- /** Callback when auto-manage encounters an error */
79
- onManageError?: (error: Error) => void;
80
- /** Maximum context window tokens (triggers additional summarization if exceeded) */
81
- maxContextTokens?: number;
82
- }
83
- /** Result of memory management */
84
- interface MemoryManageResult {
85
- /** Number of messages before management */
86
- messagesBefore: number;
87
- /** Number of messages after management */
88
- messagesAfter: number;
89
- /** Number of messages summarized */
90
- messagesSummarized: number;
91
- /** The summary that was generated (if any) */
92
- summary?: string;
93
- /** Estimated tokens before */
94
- estimatedTokensBefore: number;
95
- /** Estimated tokens after */
96
- estimatedTokensAfter: number;
97
- }
98
- /** Memory state for a conversation */
99
- interface MemoryState {
100
- /** Active messages in memory */
101
- messages: Message[];
102
- /** Summaries of older messages */
103
- summaries: Array<{
104
- content: string;
105
- messagesCount: number;
106
- createdAt: number;
107
- }>;
108
- /** Total messages ever processed */
109
- totalMessagesProcessed: number;
110
- /** Estimated current token count */
111
- estimatedTokens: number;
112
- }
113
- /** Agent memory instance */
114
- interface AgentMemory {
115
- /** Get current memory state */
116
- getState(): MemoryState;
117
- /** Add a message to memory */
118
- addMessage(message: Message): void;
119
- /** Check if memory management is currently in progress */
120
- isManaging(): boolean;
121
- /** Add multiple messages to memory */
122
- addMessages(messages: Message[]): void;
123
- /** Get messages for context (includes summaries as system messages) */
124
- getContextMessages(): Message[];
125
- /** Manually trigger memory management */
126
- manage(): Promise<MemoryManageResult>;
127
- /** Clear all memory */
128
- clear(): void;
129
- /** Export memory state for persistence */
130
- export(): MemoryState;
131
- /** Import memory state from persistence */
132
- import(state: MemoryState): void;
133
- }
134
- /**
135
- * Create a sliding window memory strategy.
136
- *
137
- * Keeps the most recent N messages, moving older ones to summarization.
138
- *
139
- * @example
140
- * ```typescript
141
- * const strategy = createSlidingWindowStrategy({
142
- * maxMessages: 50,
143
- * preserveRecentCount: 10,
144
- * });
145
- * ```
146
- */
147
- declare function createSlidingWindowStrategy(defaultConfig?: MemoryStrategyConfig): MemoryStrategy;
148
- /**
149
- * Create a token-based memory strategy.
150
- *
151
- * Keeps messages until a token limit is reached, then moves older ones to summarization.
152
- *
153
- * @example
154
- * ```typescript
155
- * const strategy = createTokenBasedStrategy({
156
- * maxTokens: 4000,
157
- * preserveRecentCount: 5,
158
- * });
159
- * ```
160
- */
161
- declare function createTokenBasedStrategy(defaultConfig?: MemoryStrategyConfig): MemoryStrategy;
162
- /**
163
- * Create a hybrid strategy that combines message count and token limits.
164
- *
165
- * @example
166
- * ```typescript
167
- * const strategy = createHybridStrategy({
168
- * maxMessages: 50,
169
- * maxTokens: 4000,
170
- * preserveRecentCount: 5,
171
- * });
172
- * ```
173
- */
174
- declare function createHybridStrategy(defaultConfig?: MemoryStrategyConfig): MemoryStrategy;
175
- /**
176
- * Create an agent memory instance.
177
- *
178
- * @example
179
- * ```typescript
180
- * const memory = createAgentMemory({
181
- * strategy: createSlidingWindowStrategy({ maxMessages: 50 }),
182
- * summarizer: async (messages) => {
183
- * const response = await openai.chat.completions.create({
184
- * model: 'gpt-4o-mini',
185
- * messages: [
186
- * { role: 'system', content: 'Summarize the following conversation concisely.' },
187
- * ...messages.map(m => ({ role: m.role, content: m.content })),
188
- * ],
189
- * });
190
- * return response.choices[0].message.content;
191
- * },
192
- * autoManage: true,
193
- * });
194
- * ```
195
- */
196
- declare function createAgentMemory(config: AgentMemoryConfig): AgentMemory;
197
- /**
198
- * Create a simple truncation "summarizer" that just returns key points.
199
- * Useful for testing or when LLM summarization isn't needed.
200
- */
201
- declare function createTruncationSummarizer(maxLength?: number): MessageSummarizer;
202
- /**
203
- * Create a summarizer that extracts only user questions and key assistant answers.
204
- */
205
- declare function createKeyPointsSummarizer(): MessageSummarizer;
206
- /**
207
- * Create a summarizer factory for LLM-based summarization.
208
- * You provide the LLM call function, this handles the prompt.
209
- *
210
- * @example
211
- * ```typescript
212
- * const summarizer = createLLMSummarizer(async (prompt) => {
213
- * const response = await openai.chat.completions.create({
214
- * model: 'gpt-4o-mini',
215
- * messages: [{ role: 'user', content: prompt }],
216
- * });
217
- * return response.choices[0].message.content ?? '';
218
- * });
219
- * ```
220
- */
221
- declare function createLLMSummarizer(llmCall: (prompt: string) => Promise<string>, options?: {
222
- maxSummaryLength?: number;
223
- preserveKeyFacts?: boolean;
224
- }): MessageSummarizer;
225
-
226
- /**
227
- * OpenAI Agents Streaming - Token-by-token streaming with backpressure support
228
- *
229
- * Provides async iterators for streaming agent responses with guardrail evaluation
230
- * on partial output and configurable backpressure handling.
231
- *
232
- * @example
233
- * ```typescript
234
- * import { createAgentOrchestrator } from '@directive-run/ai';
235
- * import { createStreamingRunner } from '@directive-run/ai';
236
- *
237
- * const { stream, result } = orchestrator.runStream(agent, input);
238
- *
239
- * for await (const chunk of stream) {
240
- * if (chunk.type === 'token') process.stdout.write(chunk.data);
241
- * if (chunk.type === 'guardrail_triggered') handleGuardrail(chunk);
242
- * }
243
- *
244
- * const finalResult = await result;
245
- * ```
246
- */
247
-
248
- /** Token chunk from streaming response */
249
- interface TokenChunk {
250
- type: "token";
251
- data: string;
252
- /** Running total of tokens received */
253
- tokenCount: number;
254
- }
255
- /** Tool execution started */
256
- interface ToolStartChunk {
257
- type: "tool_start";
258
- tool: string;
259
- toolCallId: string;
260
- arguments: string;
261
- }
262
- /** Tool execution completed */
263
- interface ToolEndChunk {
264
- type: "tool_end";
265
- tool: string;
266
- toolCallId: string;
267
- result: string;
268
- }
269
- /** Message added to conversation */
270
- interface MessageChunk {
271
- type: "message";
272
- message: Message$1;
273
- }
274
- /** Guardrail was triggered during streaming */
275
- interface GuardrailTriggeredChunk {
276
- type: "guardrail_triggered";
277
- guardrailName: string;
278
- reason: string;
279
- /** Partial output at the time of trigger */
280
- partialOutput: string;
281
- /** Whether the stream was stopped */
282
- stopped: boolean;
283
- }
284
- /** Progress update for UI feedback */
285
- interface ProgressChunk {
286
- type: "progress";
287
- phase: "starting" | "generating" | "tool_calling" | "finishing";
288
- /** Percentage complete (0-100), if known */
289
- percent?: number;
290
- /** Human-readable status message */
291
- message?: string;
292
- }
293
- /** Stream completed */
294
- interface DoneChunk {
295
- type: "done";
296
- totalTokens: number;
297
- duration: number;
298
- /** Number of tokens dropped due to backpressure (only with 'drop' strategy) */
299
- droppedTokens: number;
300
- }
301
- /** Error during streaming */
302
- interface ErrorChunk {
303
- type: "error";
304
- error: Error;
305
- /** Partial output before error */
306
- partialOutput?: string;
307
- }
308
- /** Union of all stream chunk types */
309
- type StreamChunk = TokenChunk | ToolStartChunk | ToolEndChunk | MessageChunk | GuardrailTriggeredChunk | ProgressChunk | DoneChunk | ErrorChunk;
310
- /** Backpressure strategy when consumer is slow */
311
- type BackpressureStrategy =
312
- /** Drop tokens when buffer is full (lossy, fast) */
313
- "drop"
314
- /** Block producer when buffer is full (lossless, may slow response) */
315
- | "block"
316
- /** Buffer all tokens (lossless, uses memory) */
317
- | "buffer";
318
- /** Streaming run options */
319
- interface StreamRunOptions {
320
- /** Maximum turns before stopping */
321
- maxTurns?: number;
322
- /** Abort signal for cancellation */
323
- signal?: AbortSignal;
324
- /** Backpressure strategy (default: 'buffer') */
325
- backpressure?: BackpressureStrategy;
326
- /** Buffer size for 'drop' and 'block' strategies */
327
- bufferSize?: number;
328
- /** Evaluate guardrails every N tokens (default: 50) */
329
- guardrailCheckInterval?: number;
330
- /** Stop stream on guardrail trigger (default: true for critical) */
331
- stopOnGuardrail?: boolean | ((chunk: GuardrailTriggeredChunk) => boolean);
332
- }
333
- /** Stream run function type (mirrors OpenAI Agents streaming API) */
334
- type StreamRunner = <T = unknown>(agent: AgentLike, input: string, options?: StreamRunOptions) => StreamingRunResult<T>;
335
- /** Result from a streaming run */
336
- interface StreamingRunResult<T = unknown> {
337
- /** Async iterator for streaming chunks */
338
- stream: AsyncIterable<StreamChunk>;
339
- /** Promise that resolves to the final result */
340
- result: Promise<RunResult<T>>;
341
- /** Abort the stream */
342
- abort: () => void;
343
- }
344
- /** Streaming guardrail that evaluates partial output */
345
- interface StreamingGuardrail {
346
- /** Unique name for this guardrail */
347
- name: string;
348
- /** Check partial output (called every guardrailCheckInterval tokens) */
349
- check: (partialOutput: string, tokenCount: number) => StreamingGuardrailResult | Promise<StreamingGuardrailResult>;
350
- /** Whether to stop the stream on failure (default: true) */
351
- stopOnFail?: boolean;
352
- }
353
- /** Result from a streaming guardrail check */
354
- interface StreamingGuardrailResult {
355
- passed: boolean;
356
- reason?: string;
357
- /** Severity level for UI display */
358
- severity?: "warning" | "error" | "critical";
359
- /** Warning message (guardrail passed but wants to emit a warning) */
360
- warning?: string;
361
- }
362
- /**
363
- * Create a streaming runner that wraps a base run function.
364
- * This is used internally by the orchestrator but can be used standalone.
365
- *
366
- * @param baseRunner - The underlying non-streaming runner
367
- * @param options - Configuration options
368
- */
369
- declare function createStreamingRunner(baseRunner: (agent: AgentLike, input: string, callbacks: {
370
- onToken?: (token: string) => void;
371
- onToolStart?: (tool: string, id: string, args: string) => void;
372
- onToolEnd?: (tool: string, id: string, result: string) => void;
373
- onMessage?: (message: Message$1) => void;
374
- signal?: AbortSignal;
375
- }) => Promise<RunResult<unknown>>, options?: {
376
- streamingGuardrails?: StreamingGuardrail[];
377
- }): StreamRunner;
378
- /**
379
- * Create a streaming guardrail that detects toxic content.
380
- *
381
- * @example
382
- * ```typescript
383
- * const toxicityGuardrail = createToxicityStreamingGuardrail({
384
- * threshold: 0.9,
385
- * checkFn: async (text) => myToxicityModel.score(text),
386
- * });
387
- * ```
388
- */
389
- declare function createToxicityStreamingGuardrail(options: {
390
- /** Toxicity scoring function (returns 0-1) */
391
- checkFn: (text: string) => number | Promise<number>;
392
- /** Threshold above which content is flagged (default: 0.8) */
393
- threshold?: number;
394
- /** Stop the stream on detection (default: true) */
395
- stopOnFail?: boolean;
396
- }): StreamingGuardrail;
397
- /**
398
- * Create a streaming guardrail that limits output length.
399
- *
400
- * @example
401
- * ```typescript
402
- * const lengthGuardrail = createLengthStreamingGuardrail({
403
- * maxTokens: 4000,
404
- * warnAt: 3500,
405
- * });
406
- * ```
407
- */
408
- declare function createLengthStreamingGuardrail(options: {
409
- /** Maximum tokens before stopping */
410
- maxTokens: number;
411
- /** Warn at this token count (optional) */
412
- warnAt?: number;
413
- /** Stop the stream on max (default: true) */
414
- stopOnFail?: boolean;
415
- }): StreamingGuardrail;
416
- /**
417
- * Create a streaming guardrail that detects patterns (regex-based).
418
- *
419
- * @example
420
- * ```typescript
421
- * const piiGuardrail = createPatternStreamingGuardrail({
422
- * patterns: [
423
- * { regex: /\b\d{3}-\d{2}-\d{4}\b/, name: 'SSN' },
424
- * { regex: /\b\d{16}\b/, name: 'Credit Card' },
425
- * ],
426
- * stopOnFail: true,
427
- * });
428
- * ```
429
- */
430
- declare function createPatternStreamingGuardrail(options: {
431
- patterns: Array<{
432
- regex: RegExp;
433
- name: string;
434
- }>;
435
- stopOnFail?: boolean;
436
- }): StreamingGuardrail;
437
- /**
438
- * Combine multiple streaming guardrails into one.
439
- *
440
- * @example
441
- * ```typescript
442
- * const combined = combineStreamingGuardrails([
443
- * createToxicityStreamingGuardrail({ ... }),
444
- * createLengthStreamingGuardrail({ ... }),
445
- * ]);
446
- * ```
447
- */
448
- declare function combineStreamingGuardrails(guardrails: StreamingGuardrail[], options?: {
449
- name?: string;
450
- stopOnFirstFail?: boolean;
451
- }): StreamingGuardrail;
452
- /**
453
- * Convert a regular output guardrail to a streaming guardrail.
454
- * Useful for reusing existing guardrails in streaming context.
455
- *
456
- * @example
457
- * ```typescript
458
- * const streamingPII = adaptOutputGuardrail(
459
- * "pii-streaming",
460
- * createPIIGuardrail({ redact: false }),
461
- * { checkInterval: 100 }
462
- * );
463
- * ```
464
- */
465
- declare function adaptOutputGuardrail(name: string, guardrail: GuardrailFn<OutputGuardrailData>, options?: {
466
- /** Only run after this many tokens (optimization) */
467
- minTokens?: number;
468
- stopOnFail?: boolean;
469
- }): StreamingGuardrail;
470
- /**
471
- * Collect all tokens from a stream into a string.
472
- *
473
- * @example
474
- * ```typescript
475
- * const { stream, result } = orchestrator.runStream(agent, input);
476
- * const fullOutput = await collectTokens(stream);
477
- * ```
478
- */
479
- declare function collectTokens(stream: AsyncIterable<StreamChunk>): Promise<string>;
480
- /**
481
- * Tap into a stream without consuming it.
482
- * Useful for logging or side effects.
483
- *
484
- * @example
485
- * ```typescript
486
- * const { stream } = orchestrator.runStream(agent, input);
487
- * const tapped = tapStream(stream, (chunk) => console.log(chunk));
488
- * for await (const chunk of tapped) { ... }
489
- * ```
490
- */
491
- declare function tapStream(stream: AsyncIterable<StreamChunk>, fn: (chunk: StreamChunk) => void | Promise<void>): AsyncIterable<StreamChunk>;
492
- /**
493
- * Filter stream chunks by type.
494
- *
495
- * @example
496
- * ```typescript
497
- * const tokensOnly = filterStream(stream, ['token']);
498
- * ```
499
- */
500
- declare function filterStream<T extends StreamChunk["type"]>(stream: AsyncIterable<StreamChunk>, types: T[]): AsyncIterable<Extract<StreamChunk, {
501
- type: T;
502
- }>>;
503
- /**
504
- * Transform stream chunks.
505
- *
506
- * @example
507
- * ```typescript
508
- * const upperTokens = mapStream(stream, (chunk) => {
509
- * if (chunk.type === 'token') return { ...chunk, data: chunk.data.toUpperCase() };
510
- * return chunk;
511
- * });
512
- * ```
513
- */
514
- declare function mapStream<R>(stream: AsyncIterable<StreamChunk>, fn: (chunk: StreamChunk) => R | Promise<R>): AsyncIterable<R>;
6
+ import { ModuleSchema, Plugin } from '@directive-run/core';
7
+ import { E as Embedding, a as EmbedderFn } from './semantic-cache-F0psCRuz.cjs';
8
+ export { B as BatchedEmbedder, C as CacheEntry, b as CacheLookupResult, c as CacheStats, S as SemanticCache, d as SemanticCacheConfig, e as SemanticCacheStorage, f as createBatchedEmbedder, g as createInMemoryStorage, h as createSemanticCache, i as createSemanticCacheGuardrail, j as createTestEmbedder } from './semantic-cache-F0psCRuz.cjs';
515
9
 
516
10
  /**
517
11
  * Built-in guardrails for AI adapter — PII, moderation, rate limiting, tool allowlists, schema validation.
@@ -632,7 +126,7 @@ declare function createContentFilterGuardrail(options: {
632
126
  }): GuardrailFn<OutputGuardrailData>;
633
127
 
634
128
  /**
635
- * Helper functions for AI adapter — createRunner, estimateCost, state queries, validation.
129
+ * Agent utilities — createRunner, estimateCost, state queries, URL validation.
636
130
  */
637
131
 
638
132
  /** Check if agent is currently running. */
@@ -664,11 +158,11 @@ interface ParsedResponse {
664
158
  /** Options for creating an AgentRunner from buildRequest/parseResponse */
665
159
  interface CreateRunnerOptions {
666
160
  fetch?: typeof globalThis.fetch;
667
- buildRequest: (agent: AgentLike, input: string, messages: Message$1[]) => {
161
+ buildRequest: (agent: AgentLike, input: string, messages: Message[]) => {
668
162
  url: string;
669
163
  init: RequestInit;
670
164
  };
671
- parseResponse: (response: Response, messages: Message$1[]) => Promise<ParsedResponse>;
165
+ parseResponse: (response: Response, messages: Message[]) => Promise<ParsedResponse>;
672
166
  parseOutput?: <T>(text: string) => T;
673
167
  /** Lifecycle hooks for tracing, logging, and metrics */
674
168
  hooks?: AdapterHooks;
@@ -719,490 +213,124 @@ interface CreateRunnerOptions {
719
213
  declare function createRunner(options: CreateRunnerOptions): AgentRunner;
720
214
 
721
215
  /**
722
- * Constraint Helper FunctionsErgonomic builders for OrchestratorConstraint
216
+ * Middleware composition utilityleft-to-right pipeline for AgentRunner wrappers.
217
+ *
218
+ * Each middleware is a function that takes an `AgentRunner` and returns a new
219
+ * `AgentRunner`. `pipe` applies them left to right, so the first middleware
220
+ * in the list wraps the runner first (innermost), and the last wraps last
221
+ * (outermost).
222
+ *
223
+ * @module
723
224
  *
724
225
  * @example
725
226
  * ```typescript
726
- * import { constraint, when } from '@directive-run/ai';
727
- *
728
- * constraints: {
729
- * // Builder pattern
730
- * escalate: constraint<MyFacts>()
731
- * .when(f => f.confidence < 0.7)
732
- * .require({ type: 'ESCALATE' })
733
- * .priority(50)
734
- * .build(),
735
- *
736
- * // Quick shorthand
737
- * pause: when<MyFacts>(f => f.errors > 3)
738
- * .require({ type: 'PAUSE' }),
739
- * }
227
+ * import { pipe, withRetry, withFallback, withBudget } from '@directive-run/ai';
228
+ *
229
+ * const runner = pipe(
230
+ * baseRunner,
231
+ * withFallback([anthropicRunner, openaiRunner]),
232
+ * withRetry({ maxRetries: 3 }),
233
+ * withBudget({ budgets: [{ window: 'hour', maxCost: 5, pricing }] }),
234
+ * );
740
235
  * ```
741
236
  */
742
237
 
743
- interface ConstraintBuilderWithWhen<F extends Record<string, unknown>> {
744
- require(req: Requirement | ((facts: F & OrchestratorState) => Requirement)): ConstraintBuilderWithRequire<F>;
745
- }
746
- interface ConstraintBuilderWithRequire<F extends Record<string, unknown>> {
747
- priority(p: number): ConstraintBuilderWithRequire<F>;
748
- build(): OrchestratorConstraint<F>;
749
- }
750
- interface ConstraintBuilder<F extends Record<string, unknown>> {
751
- when(condition: (facts: F & OrchestratorState) => boolean | Promise<boolean>): ConstraintBuilderWithWhen<F>;
752
- }
238
+ /** A function that wraps an AgentRunner, returning a new AgentRunner. */
239
+ type RunnerMiddleware = (runner: AgentRunner) => AgentRunner;
753
240
  /**
754
- * Fluent builder for creating orchestrator constraints.
241
+ * Compose middleware left-to-right onto a base runner.
755
242
  *
756
- * @example
757
- * ```typescript
758
- * const myConstraint = constraint<MyFacts>()
759
- * .when(f => f.confidence < 0.7)
760
- * .require({ type: 'ESCALATE' })
761
- * .priority(50)
762
- * .build();
763
- * ```
243
+ * @param runner - The base `AgentRunner` to wrap.
244
+ * @param middlewares - One or more middleware functions to apply in order.
245
+ * @returns A new `AgentRunner` with all middleware applied.
764
246
  */
765
- declare function constraint<F extends Record<string, unknown> = Record<string, never>>(): ConstraintBuilder<F>;
766
- interface WhenResult<F extends Record<string, unknown>> {
767
- require(req: Requirement | ((facts: F & OrchestratorState) => Requirement)): WhenWithRequire<F>;
247
+ declare function pipe(runner: AgentRunner, ...middlewares: RunnerMiddleware[]): AgentRunner;
248
+
249
+ type MermaidDirection = "LR" | "TD" | "TB" | "RL" | "BT";
250
+ interface MermaidNodeShapes {
251
+ /** Shape for agent nodes. @default "square" */
252
+ agent?: "square" | "round" | "stadium" | "hexagon";
253
+ /** Shape for virtual nodes (Input, Output, Merge). @default "circle" */
254
+ virtual?: "circle" | "square" | "round" | "stadium";
768
255
  }
769
- /**
770
- * Result of `when().require()` a valid `OrchestratorConstraint<F>` directly,
771
- * or chain `.withPriority(n)` to get a constraint with priority set.
772
- */
773
- interface WhenWithRequire<F extends Record<string, unknown>> extends OrchestratorConstraint<F> {
774
- /** Return a new constraint with the given priority */
775
- withPriority(p: number): OrchestratorConstraint<F>;
256
+ interface MermaidOptions {
257
+ /** Graph flow direction. @default "LR" */
258
+ direction?: MermaidDirection;
259
+ /** Emits %%{init}%% preamble when set. */
260
+ theme?: "default" | "dark" | "forest" | "neutral";
261
+ /** Node shape overrides. */
262
+ shapes?: MermaidNodeShapes;
776
263
  }
777
264
  /**
778
- * Quick shorthand for creating simple constraints.
779
- * The returned object is a valid `OrchestratorConstraint<F>` — use directly
780
- * or chain `.withPriority(n)` to set priority.
265
+ * Convert an execution pattern to a Mermaid diagram string.
266
+ *
267
+ * Accepts both runtime `ExecutionPattern` (with function callbacks) and
268
+ * pre-serialized `SerializedPattern`. Normalizes internally via `patternToJSON()`
269
+ * when it detects function-valued fields.
781
270
  *
782
271
  * @example
783
272
  * ```typescript
784
- * const myConstraint = when<MyFacts>(f => f.errors > 3)
785
- * .require({ type: 'PAUSE' });
786
- *
787
- * // With priority
788
- * const urgent = when<MyFacts>(f => f.critical)
789
- * .require({ type: 'HALT' })
790
- * .withPriority(100);
273
+ * const p = dag({ fetch: { agent: "fetcher" }, report: { agent: "reporter", deps: ["fetch"] } });
274
+ * console.log(patternToMermaid(p, { direction: "TD" }));
275
+ * // graph TD
276
+ * // fetch[fetcher]
277
+ * // fetch[fetcher] --> report[reporter]
791
278
  * ```
279
+ *
280
+ * @throws {Error} If pattern type is not one of the 8 known types.
792
281
  */
793
- declare function when<F extends Record<string, unknown> = Record<string, never>>(condition: (facts: F & OrchestratorState) => boolean | Promise<boolean>): WhenResult<F>;
282
+ declare function patternToMermaid(pattern: ExecutionPattern<unknown> | SerializedPattern, options?: MermaidOptions): string;
794
283
 
795
284
  /**
796
- * Multi-Agent Orchestration Patterns
285
+ * Agent-to-Agent Communication Protocol
797
286
  *
798
- * Provides patterns for coordinating multiple AI agents:
799
- * - Parallel execution with result merging
800
- * - Sequential pipelines
801
- * - Supervisor patterns with worker delegation
802
- * - Constraint-driven agent selection
287
+ * Provides structured communication channels between agents for coordination,
288
+ * delegation, and knowledge sharing without central orchestration.
803
289
  *
804
290
  * @example
805
291
  * ```typescript
806
- * import { createMultiAgentOrchestrator } from '@directive-run/ai';
292
+ * import { createAgentNetwork, createMessageBus } from '@directive-run/ai';
807
293
  *
808
- * const orchestrator = createMultiAgentOrchestrator({
294
+ * const messageBus = createMessageBus();
295
+ *
296
+ * const network = createAgentNetwork({
297
+ * bus: messageBus,
809
298
  * agents: {
810
- * researcher: { agent: researchAgent, maxConcurrent: 3 },
811
- * writer: { agent: writerAgent, maxConcurrent: 1 },
812
- * reviewer: { agent: reviewerAgent, maxConcurrent: 1 },
813
- * },
814
- * patterns: {
815
- * parallelResearch: {
816
- * type: 'parallel',
817
- * agents: ['researcher', 'researcher', 'researcher'],
818
- * merge: (results) => combineResearch(results),
819
- * },
299
+ * researcher: { capabilities: ['search', 'analyze'] },
300
+ * writer: { capabilities: ['draft', 'edit'] },
301
+ * reviewer: { capabilities: ['review', 'approve'] },
820
302
  * },
821
303
  * });
822
- * ```
823
- */
824
-
825
- /**
826
- * Async semaphore for controlling concurrent access.
827
- * Uses a queue-based approach instead of polling for efficiency.
828
- *
829
- * @example
830
- * ```typescript
831
- * import { Semaphore } from '@directive-run/ai';
832
304
  *
833
- * const sem = new Semaphore(3); // Allow 3 concurrent operations
834
- *
835
- * async function doWork() {
836
- * const release = await sem.acquire();
837
- * try {
838
- * await performWork();
839
- * } finally {
840
- * release();
841
- * }
842
- * }
305
+ * // Agents can send messages to each other
306
+ * await network.send('researcher', 'writer', {
307
+ * type: 'DELEGATION',
308
+ * task: 'Draft an article based on this research',
309
+ * context: { findings: [...] },
310
+ * });
843
311
  * ```
844
312
  */
845
- declare class Semaphore {
846
- private count;
847
- private readonly maxPermits;
848
- private readonly queue;
849
- constructor(max: number);
850
- acquire(): Promise<() => void>;
851
- private release;
852
- /** Get current available permits */
853
- get available(): number;
854
- /** Get number of waiters in queue */
855
- get waiting(): number;
856
- /** Get maximum permits */
857
- get max(): number;
858
- /** Reject all pending waiters with an error and reset permits */
859
- drain(): void;
860
- }
861
- /** Configuration for a registered agent */
862
- interface AgentRegistration {
863
- /** The agent instance */
864
- agent: AgentLike;
865
- /** Maximum concurrent runs for this agent (default: 1) */
866
- maxConcurrent?: number;
867
- /** Timeout for agent runs (ms) */
868
- timeout?: number;
869
- /** Custom run options */
870
- runOptions?: Omit<RunOptions, "signal">;
871
- /** Description for constraint-based selection */
872
- description?: string;
873
- /** Capabilities this agent has */
874
- capabilities?: string[];
875
- /** Per-agent output guardrails (applied in addition to stack-level guardrails) */
876
- guardrails?: {
877
- output?: Array<GuardrailFn<OutputGuardrailData> | NamedGuardrail<OutputGuardrailData>>;
878
- };
879
- }
880
- /** Agent registry configuration */
881
- interface AgentRegistry {
882
- [agentId: string]: AgentRegistration;
883
- }
884
- /** State of a running agent */
885
- interface AgentRunState {
886
- agentId: string;
887
- runId: string;
888
- status: "pending" | "running" | "completed" | "error" | "cancelled";
889
- input: string;
890
- output?: unknown;
891
- error?: Error;
892
- startedAt?: number;
893
- completedAt?: number;
894
- tokens: number;
895
- }
896
- /** Parallel execution pattern - run agents concurrently and merge results */
897
- interface ParallelPattern<T = unknown> {
898
- type: "parallel";
899
- /** Agent IDs to run in parallel (can repeat for multiple instances) */
900
- agents: string[];
901
- /** Function to merge results from all agents */
902
- merge: (results: RunResult<unknown>[]) => T | Promise<T>;
903
- /** Minimum successful results required (default: all) */
904
- minSuccess?: number;
905
- /** Overall timeout (ms) */
906
- timeout?: number;
907
- }
908
- /** Sequential execution pattern - pipeline of agents */
909
- interface SequentialPattern<T = unknown> {
910
- type: "sequential";
911
- /** Agent IDs in execution order */
912
- agents: string[];
913
- /** Transform output to next input (default: stringify) */
914
- transform?: (output: unknown, agentId: string, index: number) => string;
915
- /** Final result extractor */
916
- extract?: (output: unknown) => T;
917
- /** Continue on error (default: false) */
918
- continueOnError?: boolean;
919
- }
920
- /** Supervisor pattern - one agent directs others */
921
- interface SupervisorPattern<T = unknown> {
922
- type: "supervisor";
923
- /** Supervisor agent ID */
924
- supervisor: string;
925
- /** Worker agent IDs */
926
- workers: string[];
927
- /** Maximum delegation rounds */
928
- maxRounds?: number;
929
- /** Extract final result */
930
- extract?: (supervisorOutput: unknown, workerResults: RunResult<unknown>[]) => T;
931
- }
932
- /** Union of all patterns */
933
- type ExecutionPattern<T = unknown> = ParallelPattern<T> | SequentialPattern<T> | SupervisorPattern<T>;
934
- /** Handoff request between agents */
935
- interface HandoffRequest {
313
+ /** Base message structure */
314
+ interface AgentMessage {
936
315
  id: string;
937
- fromAgent: string;
938
- toAgent: string;
939
- input: string;
940
- context?: Record<string, unknown>;
941
- requestedAt: number;
316
+ type: AgentMessageType;
317
+ from: string;
318
+ to: string | string[] | "*";
319
+ timestamp: number;
320
+ correlationId?: string;
321
+ replyTo?: string;
322
+ priority?: "low" | "normal" | "high" | "urgent";
323
+ ttlMs?: number;
324
+ metadata?: Record<string, unknown>;
942
325
  }
943
- /** Handoff result */
944
- interface HandoffResult {
945
- request: HandoffRequest;
946
- result: RunResult<unknown>;
947
- completedAt: number;
948
- }
949
- /** Constraint for agent selection */
950
- interface AgentSelectionConstraint {
951
- when: (facts: Record<string, unknown>) => boolean | Promise<boolean>;
952
- select: string | ((facts: Record<string, unknown>) => string);
953
- input: string | ((facts: Record<string, unknown>) => string);
954
- priority?: number;
955
- }
956
- /** Run agent requirement */
957
- interface RunAgentRequirement extends Requirement {
958
- type: "RUN_AGENT";
959
- agent: string;
960
- input: string;
961
- context?: Record<string, unknown>;
962
- }
963
- /** Multi-agent orchestrator options */
964
- interface MultiAgentOrchestratorOptions {
965
- /** Base run function */
966
- runner: AgentRunner;
967
- /** Registered agents */
968
- agents: AgentRegistry;
969
- /** Execution patterns */
970
- patterns?: Record<string, ExecutionPattern>;
971
- /** Handoff callbacks */
972
- onHandoff?: (request: HandoffRequest) => void;
973
- /** Handoff completion callbacks */
974
- onHandoffComplete?: (result: HandoffResult) => void;
975
- /** Maximum number of handoff results to retain (default: 1000) */
976
- maxHandoffHistory?: number;
977
- /** Debug mode */
978
- debug?: boolean;
979
- }
980
- /** Multi-agent state in facts */
981
- interface MultiAgentState {
982
- /** Namespace for each agent's state */
983
- __agents: Record<string, {
984
- status: "idle" | "running" | "completed" | "error";
985
- lastInput?: string;
986
- lastOutput?: unknown;
987
- lastError?: string;
988
- runCount: number;
989
- totalTokens: number;
990
- }>;
991
- /** Pending handoffs */
992
- __handoffs: HandoffRequest[];
993
- /** Completed handoffs */
994
- __handoffResults: HandoffResult[];
995
- }
996
- /** Multi-agent orchestrator instance */
997
- interface MultiAgentOrchestrator {
998
- /** Run a single agent */
999
- runAgent<T>(agentId: string, input: string, options?: RunOptions): Promise<RunResult<T>>;
1000
- /** Run an execution pattern */
1001
- runPattern<T>(patternId: string, input: string): Promise<T>;
1002
- /** Run agents in parallel */
1003
- runParallel<T>(agentIds: string[], inputs: string | string[], merge: (results: RunResult<unknown>[]) => T | Promise<T>): Promise<T>;
1004
- /** Run agents sequentially */
1005
- runSequential<T>(agentIds: string[], initialInput: string, options?: {
1006
- transform?: (output: unknown, agentId: string, index: number) => string;
1007
- }): Promise<RunResult<T>[]>;
1008
- /** Request a handoff between agents */
1009
- handoff(fromAgent: string, toAgent: string, input: string, context?: Record<string, unknown>): Promise<RunResult<unknown>>;
1010
- /** Get agent state */
1011
- getAgentState(agentId: string): MultiAgentState["__agents"][string] | undefined;
1012
- /** Get all agent states */
1013
- getAllAgentStates(): Record<string, MultiAgentState["__agents"][string]>;
1014
- /** Get pending handoffs */
1015
- getPendingHandoffs(): HandoffRequest[];
1016
- /** Reset all agent states */
1017
- reset(): void;
1018
- /** Dispose of the orchestrator, resetting all state */
1019
- dispose(): void;
1020
- }
1021
- /**
1022
- * Create a multi-agent orchestrator.
1023
- *
1024
- * @example
1025
- * ```typescript
1026
- * const orchestrator = createMultiAgentOrchestrator({
1027
- * runner,
1028
- * agents: {
1029
- * researcher: { agent: researchAgent, maxConcurrent: 3 },
1030
- * writer: { agent: writerAgent },
1031
- * reviewer: { agent: reviewerAgent },
1032
- * },
1033
- * patterns: {
1034
- * research: {
1035
- * type: 'parallel',
1036
- * agents: ['researcher', 'researcher'],
1037
- * merge: (results) => results.map(r => r.output).join('\n\n'),
1038
- * },
1039
- * write: {
1040
- * type: 'sequential',
1041
- * agents: ['writer', 'reviewer'],
1042
- * },
1043
- * },
1044
- * });
1045
- *
1046
- * // Run pattern
1047
- * const research = await orchestrator.runPattern('research', 'What is AI?');
1048
- *
1049
- * // Run parallel
1050
- * const results = await orchestrator.runParallel(
1051
- * ['researcher', 'researcher'],
1052
- * ['Question 1', 'Question 2'],
1053
- * (results) => results.map(r => r.output)
1054
- * );
1055
- *
1056
- * // Handoff
1057
- * const reviewed = await orchestrator.handoff('writer', 'reviewer', draft);
1058
- * ```
1059
- *
1060
- * @throws {Error} If a pattern references an agent that is not in the registry
1061
- */
1062
- declare function createMultiAgentOrchestrator(options: MultiAgentOrchestratorOptions): MultiAgentOrchestrator;
1063
- /**
1064
- * Create a parallel pattern configuration.
1065
- *
1066
- * @example
1067
- * ```typescript
1068
- * const researchPattern = parallel(
1069
- * ['researcher', 'researcher', 'researcher'],
1070
- * (results) => results.map(r => r.output).join('\n')
1071
- * );
1072
- * ```
1073
- */
1074
- declare function parallel<T>(agents: string[], merge: (results: RunResult<unknown>[]) => T | Promise<T>, options?: {
1075
- minSuccess?: number;
1076
- timeout?: number;
1077
- }): ParallelPattern<T>;
1078
- /**
1079
- * Create a sequential pattern configuration.
1080
- *
1081
- * @example
1082
- * ```typescript
1083
- * const writeReviewPattern = sequential(
1084
- * ['writer', 'reviewer'],
1085
- * { transform: (output) => `Review this: ${output}` }
1086
- * );
1087
- * ```
1088
- */
1089
- declare function sequential<T>(agents: string[], options?: {
1090
- transform?: (output: unknown, agentId: string, index: number) => string;
1091
- extract?: (output: unknown) => T;
1092
- continueOnError?: boolean;
1093
- }): SequentialPattern<T>;
1094
- /**
1095
- * Create a supervisor pattern configuration.
1096
- *
1097
- * @example
1098
- * ```typescript
1099
- * const managedPattern = supervisor(
1100
- * 'manager',
1101
- * ['worker1', 'worker2'],
1102
- * { maxRounds: 3 }
1103
- * );
1104
- * ```
1105
- */
1106
- declare function supervisor<T>(supervisorAgent: string, workers: string[], options?: {
1107
- maxRounds?: number;
1108
- extract?: (supervisorOutput: unknown, workerResults: RunResult<unknown>[]) => T;
1109
- }): SupervisorPattern<T>;
1110
- /**
1111
- * Create an agent selection constraint.
1112
- *
1113
- * @example
1114
- * ```typescript
1115
- * const constraints = {
1116
- * routeToExpert: selectAgent(
1117
- * (facts) => facts.complexity > 0.8,
1118
- * 'expert',
1119
- * (facts) => facts.query
1120
- * ),
1121
- * };
1122
- * ```
1123
- */
1124
- declare function selectAgent(when: (facts: Record<string, unknown>) => boolean | Promise<boolean>, agent: string | ((facts: Record<string, unknown>) => string), input: string | ((facts: Record<string, unknown>) => string), priority?: number): AgentSelectionConstraint;
1125
- /**
1126
- * Create a RUN_AGENT requirement.
1127
- *
1128
- * @example
1129
- * ```typescript
1130
- * constraints: {
1131
- * needsResearch: {
1132
- * when: (facts) => facts.hasUnknowns,
1133
- * require: runAgentRequirement('researcher', facts.query),
1134
- * },
1135
- * }
1136
- * ```
1137
- */
1138
- declare function runAgentRequirement(agent: string, input: string, context?: Record<string, unknown>): RunAgentRequirement;
1139
- /**
1140
- * Merge results by concatenating outputs.
1141
- */
1142
- declare function concatResults(results: RunResult<unknown>[], separator?: string): string;
1143
- /**
1144
- * Merge results by picking the best one based on a scoring function.
1145
- */
1146
- declare function pickBestResult<T>(results: RunResult<T>[], score: (result: RunResult<T>) => number): RunResult<T>;
1147
- /**
1148
- * Merge results into an array of outputs.
1149
- */
1150
- declare function collectOutputs<T>(results: RunResult<T>[]): T[];
1151
- /**
1152
- * Aggregate token counts from results.
1153
- */
1154
- declare function aggregateTokens(results: RunResult<unknown>[]): number;
1155
-
1156
- /**
1157
- * Agent-to-Agent Communication Protocol
1158
- *
1159
- * Provides structured communication channels between agents for coordination,
1160
- * delegation, and knowledge sharing without central orchestration.
1161
- *
1162
- * @example
1163
- * ```typescript
1164
- * import { createAgentNetwork, createMessageBus } from '@directive-run/ai';
1165
- *
1166
- * const messageBus = createMessageBus();
1167
- *
1168
- * const network = createAgentNetwork({
1169
- * bus: messageBus,
1170
- * agents: {
1171
- * researcher: { capabilities: ['search', 'analyze'] },
1172
- * writer: { capabilities: ['draft', 'edit'] },
1173
- * reviewer: { capabilities: ['review', 'approve'] },
1174
- * },
1175
- * });
1176
- *
1177
- * // Agents can send messages to each other
1178
- * await network.send('researcher', 'writer', {
1179
- * type: 'DELEGATION',
1180
- * task: 'Draft an article based on this research',
1181
- * context: { findings: [...] },
1182
- * });
1183
- * ```
1184
- */
1185
- /** Base message structure */
1186
- interface AgentMessage {
1187
- id: string;
1188
- type: AgentMessageType;
1189
- from: string;
1190
- to: string | string[] | "*";
1191
- timestamp: number;
1192
- correlationId?: string;
1193
- replyTo?: string;
1194
- priority?: "low" | "normal" | "high" | "urgent";
1195
- ttlMs?: number;
1196
- metadata?: Record<string, unknown>;
1197
- }
1198
- /** Message types for agent communication */
1199
- type AgentMessageType = "REQUEST" | "RESPONSE" | "DELEGATION" | "DELEGATION_RESULT" | "QUERY" | "INFORM" | "SUBSCRIBE" | "UNSUBSCRIBE" | "UPDATE" | "ACK" | "NACK" | "PING" | "PONG" | "CUSTOM";
1200
- /** Request message */
1201
- interface RequestMessage extends AgentMessage {
1202
- type: "REQUEST";
1203
- action: string;
1204
- payload: Record<string, unknown>;
1205
- timeout?: number;
326
+ /** Message types for agent communication */
327
+ type AgentMessageType = "REQUEST" | "RESPONSE" | "DELEGATION" | "DELEGATION_RESULT" | "QUERY" | "INFORM" | "SUBSCRIBE" | "UNSUBSCRIBE" | "UPDATE" | "ACK" | "NACK" | "PING" | "PONG" | "CUSTOM";
328
+ /** Request message */
329
+ interface RequestMessage extends AgentMessage {
330
+ type: "REQUEST";
331
+ action: string;
332
+ payload: Record<string, unknown>;
333
+ timeout?: number;
1206
334
  }
1207
335
  /** Response message */
1208
336
  interface ResponseMessage extends AgentMessage {
@@ -1681,7 +809,7 @@ declare function detectPII(text: string, options?: {
1681
809
  */
1682
810
 
1683
811
  /** Audit event types - 17 total covering all system operations */
1684
- type AuditEventType = "agent.run.start" | "agent.run.complete" | "agent.run.error" | "tool.call.start" | "tool.call.complete" | "tool.call.error" | "approval.requested" | "approval.granted" | "approval.denied" | "requirement.created" | "requirement.met" | "resolver.start" | "resolver.complete" | "resolver.error" | "fact.set" | "fact.batch" | "error.occurred" | "error.recovery";
812
+ type AuditEventType = "agent.run.start" | "agent.run.complete" | "agent.run.error" | "tool.call.start" | "tool.call.complete" | "tool.call.error" | "approval.requested" | "approval.granted" | "approval.denied" | "requirement.created" | "requirement.met" | "resolver.start" | "resolver.complete" | "resolver.error" | "fact.set" | "fact.batch" | "error.occurred" | "error.recovery" | "checkpoint.save" | "checkpoint.restore" | "checkpoint.fork" | "checkpoint.replay";
1685
813
  /** Single audit entry with hash chain linking */
1686
814
  interface AuditEntry {
1687
815
  /** Unique identifier for this entry */
@@ -2326,276 +1454,6 @@ declare function createInMemoryComplianceStorage(): ComplianceStorage;
2326
1454
  */
2327
1455
  declare function createCompliance(config: ComplianceConfig): ComplianceInstance;
2328
1456
 
2329
- /**
2330
- * Semantic Caching Guardrail
2331
- *
2332
- * Caches agent responses based on semantic similarity to reduce redundant LLM calls.
2333
- * Uses vector embeddings to find semantically similar previous queries.
2334
- *
2335
- * @example
2336
- * ```typescript
2337
- * import { createSemanticCacheGuardrail } from '@directive-run/ai';
2338
- *
2339
- * const cacheGuardrail = createSemanticCacheGuardrail({
2340
- * embedder: async (text) => {
2341
- * // Use your embedding model (OpenAI, local model, etc.)
2342
- * return await getEmbedding(text);
2343
- * },
2344
- * similarityThreshold: 0.95,
2345
- * maxCacheSize: 1000,
2346
- * ttlMs: 3600000, // 1 hour
2347
- * });
2348
- *
2349
- * const orchestrator = createAgentOrchestrator({
2350
- * guardrails: {
2351
- * input: [cacheGuardrail],
2352
- * },
2353
- * runner: run,
2354
- * });
2355
- * ```
2356
- */
2357
- /** Vector embedding (array of numbers) */
2358
- type Embedding = number[];
2359
- /** Function to generate embeddings for text */
2360
- type EmbedderFn = (text: string) => Promise<Embedding>;
2361
- /** Cached response entry */
2362
- interface CacheEntry {
2363
- id: string;
2364
- query: string;
2365
- queryEmbedding: Embedding;
2366
- response: string;
2367
- metadata: Record<string, unknown>;
2368
- createdAt: number;
2369
- accessedAt: number;
2370
- accessCount: number;
2371
- agentName?: string;
2372
- }
2373
- /** Cache lookup result */
2374
- interface CacheLookupResult {
2375
- hit: boolean;
2376
- entry?: CacheEntry;
2377
- similarity?: number;
2378
- latencyMs: number;
2379
- }
2380
- /** Semantic cache configuration */
2381
- interface SemanticCacheConfig {
2382
- /** Function to generate embeddings */
2383
- embedder: EmbedderFn;
2384
- /** Similarity threshold (0.0 to 1.0) for cache hits */
2385
- similarityThreshold?: number;
2386
- /** Maximum number of entries to cache */
2387
- maxCacheSize?: number;
2388
- /** Time-to-live in milliseconds for cache entries */
2389
- ttlMs?: number;
2390
- /** Cache namespace for multi-tenant scenarios */
2391
- namespace?: string;
2392
- /** Custom storage backend (defaults to in-memory) */
2393
- storage?: SemanticCacheStorage;
2394
- /** Callback when cache hit occurs */
2395
- onHit?: (entry: CacheEntry, similarity: number) => void;
2396
- /** Callback when cache miss occurs */
2397
- onMiss?: (query: string) => void;
2398
- /** Callback when cache lookup encounters an error */
2399
- onError?: (error: Error) => void;
2400
- /** Whether to include agent name in cache key */
2401
- perAgent?: boolean;
2402
- }
2403
- /** Storage interface for cache backends */
2404
- interface SemanticCacheStorage {
2405
- /** Get all entries for a namespace */
2406
- getEntries(namespace: string): Promise<CacheEntry[]>;
2407
- /** Add an entry to the cache */
2408
- addEntry(namespace: string, entry: CacheEntry): Promise<void>;
2409
- /** Update an entry (e.g., access count) */
2410
- updateEntry(namespace: string, id: string, updates: Partial<CacheEntry>): Promise<void>;
2411
- /** Remove an entry */
2412
- removeEntry(namespace: string, id: string): Promise<void>;
2413
- /** Clear all entries in a namespace */
2414
- clear(namespace: string): Promise<void>;
2415
- }
2416
- /** Semantic cache instance */
2417
- interface SemanticCache {
2418
- /** Look up a query in the cache */
2419
- lookup(query: string, agentName?: string): Promise<CacheLookupResult>;
2420
- /** Store a response in the cache */
2421
- store(query: string, response: string, agentName?: string, metadata?: Record<string, unknown>): Promise<void>;
2422
- /** Invalidate cache entries matching a predicate */
2423
- invalidate(predicate: (entry: CacheEntry) => boolean): Promise<number>;
2424
- /** Clear all cache entries */
2425
- clear(): Promise<void>;
2426
- /** Get cache statistics */
2427
- getStats(): CacheStats;
2428
- /** Export cache entries (for persistence) */
2429
- export(): Promise<CacheEntry[]>;
2430
- /** Import cache entries (from persistence) */
2431
- import(entries: CacheEntry[]): Promise<void>;
2432
- }
2433
- /** Cache statistics */
2434
- interface CacheStats {
2435
- totalEntries: number;
2436
- totalHits: number;
2437
- totalMisses: number;
2438
- hitRate: number;
2439
- avgSimilarityOnHit: number;
2440
- oldestEntry: number | null;
2441
- newestEntry: number | null;
2442
- }
2443
- /**
2444
- * Create an in-memory cache storage backend.
2445
- */
2446
- declare function createInMemoryStorage(): SemanticCacheStorage;
2447
- /**
2448
- * Create a semantic cache instance.
2449
- *
2450
- * @example
2451
- * ```typescript
2452
- * const cache = createSemanticCache({
2453
- * embedder: async (text) => {
2454
- * const response = await openai.embeddings.create({
2455
- * model: 'text-embedding-3-small',
2456
- * input: text,
2457
- * });
2458
- * return response.data[0].embedding;
2459
- * },
2460
- * similarityThreshold: 0.92,
2461
- * maxCacheSize: 500,
2462
- * ttlMs: 3600000, // 1 hour
2463
- * });
2464
- *
2465
- * // Check cache before calling agent
2466
- * const result = await cache.lookup(userQuery);
2467
- * if (result.hit) {
2468
- * return result.entry!.response;
2469
- * }
2470
- *
2471
- * // Call agent and cache response
2472
- * const response = await runAgent(userQuery);
2473
- * await cache.store(userQuery, response);
2474
- * ```
2475
- */
2476
- declare function createSemanticCache(config: SemanticCacheConfig): SemanticCache;
2477
- /** Input guardrail data for semantic cache */
2478
- interface SemanticCacheGuardrailData {
2479
- input: string;
2480
- agentName?: string;
2481
- }
2482
- /**
2483
- * Result of semantic cache guardrail.
2484
- *
2485
- * **Important semantics:**
2486
- * - `passed: false` + `cacheHit: true` = Short-circuit with cached response (not an error!)
2487
- * - `passed: true` + `cacheHit: false` = No cache hit, proceed with agent call
2488
- *
2489
- * The `passed: false` follows guardrail convention where "not passing" stops the flow,
2490
- * but in this case stopping is desirable (returning cached data is good).
2491
- */
2492
- interface SemanticCacheGuardrailResult {
2493
- /**
2494
- * Whether to proceed with the agent call.
2495
- * `false` means short-circuit with cached response (this is good, not an error).
2496
- * `true` means no cache hit, proceed with agent.
2497
- */
2498
- passed: boolean;
2499
- /** Indicates whether this was a cache hit */
2500
- cacheHit: boolean;
2501
- /** Reason for the result */
2502
- reason?: string;
2503
- /** The cached response (only present on cache hit) */
2504
- cachedResponse?: string;
2505
- /** Similarity score (0-1) of the cache hit */
2506
- similarity?: number;
2507
- }
2508
- /**
2509
- * Create a semantic caching input guardrail.
2510
- *
2511
- * **How it works:**
2512
- * - On cache HIT: Returns `{ passed: false, cacheHit: true, cachedResponse: "..." }`
2513
- * The orchestrator should detect `cacheHit: true` and return the cached response.
2514
- * - On cache MISS: Returns `{ passed: true, cacheHit: false }`
2515
- * Proceed with normal agent execution.
2516
- *
2517
- * **Important:** `passed: false` with `cacheHit: true` is SUCCESS, not failure.
2518
- * The guardrail "short-circuits" the flow to return cached data efficiently.
2519
- *
2520
- * @example
2521
- * ```typescript
2522
- * const cacheGuardrail = createSemanticCacheGuardrail({
2523
- * cache: mySemanticCache,
2524
- * });
2525
- *
2526
- * const orchestrator = createAgentOrchestrator({
2527
- * guardrails: {
2528
- * input: [
2529
- * {
2530
- * name: 'semantic-cache',
2531
- * fn: cacheGuardrail,
2532
- * },
2533
- * ],
2534
- * },
2535
- * runner: run,
2536
- * });
2537
- *
2538
- * // In your orchestrator wrapper, check for cache hits:
2539
- * const guardrailResult = await cacheGuardrail({ input: userQuery });
2540
- * if (guardrailResult.cacheHit) {
2541
- * return guardrailResult.cachedResponse; // Fast path!
2542
- * }
2543
- * // Otherwise proceed with agent call...
2544
- * ```
2545
- */
2546
- declare function createSemanticCacheGuardrail(config: {
2547
- cache: SemanticCache;
2548
- }): (data: SemanticCacheGuardrailData) => Promise<SemanticCacheGuardrailResult>;
2549
- /**
2550
- * Create a simple hash-based "embedder" for testing.
2551
- * NOT suitable for production - use a real embedding model.
2552
- */
2553
- declare function createTestEmbedder(dimensions?: number): EmbedderFn;
2554
- /** Batched embedder instance with dispose capability */
2555
- interface BatchedEmbedder {
2556
- /** Embed a single text (batched internally) */
2557
- embed: EmbedderFn;
2558
- /** Flush any pending batch immediately */
2559
- flush(): Promise<void>;
2560
- /** Dispose of the embedder, clearing timers and rejecting pending requests */
2561
- dispose(): void;
2562
- }
2563
- /**
2564
- * Create a batched embedder that groups multiple texts into single API calls.
2565
- *
2566
- * **BREAKING CHANGE:** Previously returned `EmbedderFn` directly. Now returns
2567
- * a `BatchedEmbedder` object with `embed`, `flush`, and `dispose` methods.
2568
- *
2569
- * To migrate: `const embed = createBatchedEmbedder(...)` becomes
2570
- * `const { embed } = createBatchedEmbedder(...)`.
2571
- *
2572
- * @example
2573
- * ```typescript
2574
- * const batchedEmbedder = createBatchedEmbedder({
2575
- * batchSize: 20,
2576
- * embedBatch: async (texts) => {
2577
- * const response = await openai.embeddings.create({
2578
- * model: 'text-embedding-3-small',
2579
- * input: texts,
2580
- * });
2581
- * return response.data.map(d => d.embedding);
2582
- * },
2583
- * maxWaitMs: 50,
2584
- * });
2585
- *
2586
- * // Use the embedder
2587
- * const embedding = await batchedEmbedder.embed("Hello world");
2588
- *
2589
- * // Clean up when done
2590
- * batchedEmbedder.dispose();
2591
- * ```
2592
- */
2593
- declare function createBatchedEmbedder(config: {
2594
- batchSize?: number;
2595
- embedBatch: (texts: string[]) => Promise<Embedding[]>;
2596
- maxWaitMs?: number;
2597
- }): BatchedEmbedder;
2598
-
2599
1457
  /**
2600
1458
  * Approximate Nearest Neighbor (ANN) Index for Semantic Cache
2601
1459
  *
@@ -2820,44 +1678,227 @@ declare function pipeThrough<TIn, TOut>(source: AsyncIterable<TIn>, destination:
2820
1678
  declare function mergeStreams<T>(...sources: AsyncIterable<T>[]): AsyncIterable<T>;
2821
1679
 
2822
1680
  /**
2823
- * P2: Intelligent Retry HTTP-status-aware retry wrapper for AgentRunner.
2824
- *
2825
- * Respects 429 Retry-After headers, uses exponential backoff with jitter for 503,
2826
- * and never retries client errors (400/401/403/404/422).
1681
+ * RAG EnricherComposable retrieval-augmented generation pipeline.
2827
1682
  *
2828
- * @module
1683
+ * Embeds a query, searches a chunk store by cosine similarity, and assembles
1684
+ * an enriched input string (context + history + query) for any agent.
2829
1685
  *
2830
1686
  * @example
2831
1687
  * ```typescript
2832
- * import { withRetry, RetryExhaustedError } from '@directive-run/ai';
1688
+ * import {
1689
+ * createRAGEnricher,
1690
+ * createJSONFileStore,
1691
+ * } from '@directive-run/ai';
2833
1692
  *
2834
- * const runner = withRetry(baseRunner, {
2835
- * maxRetries: 3,
2836
- * baseDelayMs: 1000,
2837
- * maxDelayMs: 30000,
2838
- * onRetry: (attempt, error, delayMs) => {
2839
- * console.log(`Retry ${attempt} in ${delayMs}ms: ${error.message}`);
2840
- * },
1693
+ * const enricher = createRAGEnricher({
1694
+ * embedder: myEmbedder, // Provide your own EmbedderFn
1695
+ * storage: createJSONFileStore({ filePath: './embeddings.json' }),
2841
1696
  * });
2842
1697
  *
2843
- * try {
2844
- * const result = await runner(agent, input);
2845
- * } catch (err) {
2846
- * if (err instanceof RetryExhaustedError) {
2847
- * console.error(`All ${err.retryCount} retries failed:`, err.lastError);
2848
- * }
2849
- * }
1698
+ * const enrichedInput = await enricher.enrich('How do constraints work?', {
1699
+ * prefix: 'User is viewing: /docs/constraints',
1700
+ * history: [{ role: 'user', content: 'Hello' }],
1701
+ * });
2850
1702
  * ```
2851
1703
  */
2852
1704
 
2853
- /**
2854
- * Configuration for the intelligent retry wrapper.
2855
- *
2856
- * @example
2857
- * ```typescript
2858
- * const config: RetryConfig = {
2859
- * maxRetries: 3,
2860
- * baseDelayMs: 1000,
1705
+ /** A document chunk with embedding and metadata */
1706
+ interface RAGChunk {
1707
+ id: string;
1708
+ content: string;
1709
+ embedding: Embedding;
1710
+ metadata: Record<string, unknown>;
1711
+ }
1712
+ /** Pluggable storage backend */
1713
+ interface RAGStorage {
1714
+ getChunks(): Promise<RAGChunk[]>;
1715
+ size(): Promise<number>;
1716
+ /** Optional: optimized vector search (bypasses full getChunks scan) */
1717
+ search?(query: Embedding, topK: number, minSimilarity: number): Promise<Array<RAGChunk & {
1718
+ similarity: number;
1719
+ }>>;
1720
+ /** Reload storage (clear cache, re-read from source) */
1721
+ reload?(): Promise<void>;
1722
+ /** Dispose of resources */
1723
+ dispose?(): void;
1724
+ }
1725
+ interface RAGEnricherConfig {
1726
+ /** Function to generate query embeddings */
1727
+ embedder: EmbedderFn;
1728
+ /** Storage backend for document chunks */
1729
+ storage: RAGStorage;
1730
+ /** Number of top results to return (default: 5) */
1731
+ topK?: number;
1732
+ /** Minimum similarity score to include, clamped to [0, 1] (default: 0.3) */
1733
+ minSimilarity?: number;
1734
+ /** Custom chunk formatter */
1735
+ formatChunk?: (chunk: RAGChunk, similarity: number) => string;
1736
+ /** Custom context block formatter */
1737
+ formatContext?: (formattedChunks: string[], query: string) => string;
1738
+ /** Error callback — embedder/storage errors are non-fatal by default */
1739
+ onError?: (error: Error) => void;
1740
+ }
1741
+ interface RAGEnrichOptions {
1742
+ /** Prefix line (e.g. "User is viewing: /docs/constraints") */
1743
+ prefix?: string;
1744
+ /** Conversation history */
1745
+ history?: Array<{
1746
+ role: string;
1747
+ content: string;
1748
+ }>;
1749
+ /** Per-call topK override */
1750
+ topK?: number;
1751
+ /** Filter chunks before ranking (e.g. by metadata tag or section) */
1752
+ filter?: (chunk: RAGChunk) => boolean;
1753
+ }
1754
+ interface RAGEnricher {
1755
+ /** Retrieve relevant chunks for a query */
1756
+ retrieve(query: string, topK?: number): Promise<Array<RAGChunk & {
1757
+ similarity: number;
1758
+ }>>;
1759
+ /** Retrieve + format into an enriched input string */
1760
+ enrich(input: string, options?: RAGEnrichOptions): Promise<string>;
1761
+ }
1762
+ /**
1763
+ * Create a RAG enricher that retrieves relevant document chunks and
1764
+ * assembles enriched input for an agent.
1765
+ */
1766
+ declare function createRAGEnricher(config: RAGEnricherConfig): RAGEnricher;
1767
+ interface JSONFileStoreOptions {
1768
+ /** Absolute or relative path to the JSON embeddings file */
1769
+ filePath: string;
1770
+ /** Optional transform from raw JSON entries to RAGChunk */
1771
+ mapEntry?: (entry: Record<string, unknown>) => RAGChunk;
1772
+ /** Cache TTL in ms. 0 = cache forever (default) */
1773
+ ttlMs?: number;
1774
+ }
1775
+ /**
1776
+ * Create a RAGStorage backed by a JSON file (lazy-loaded, cached in memory).
1777
+ * Uses dynamic `import('node:fs')` for isomorphic safety.
1778
+ */
1779
+ declare function createJSONFileStore(options: JSONFileStoreOptions): RAGStorage;
1780
+
1781
+ /**
1782
+ * SSE Transport — Wrap a streamable source into an HTTP Server-Sent Events
1783
+ * response.
1784
+ *
1785
+ * Framework-agnostic: uses the WinterCG `Response` constructor (Node 18+,
1786
+ * Deno, Bun, Cloudflare Workers, Next.js).
1787
+ *
1788
+ * @example
1789
+ * ```typescript
1790
+ * import {
1791
+ * createSSETransport,
1792
+ * createAgentOrchestrator,
1793
+ * createStreamingRunner,
1794
+ * } from '@directive-run/ai';
1795
+ *
1796
+ * const transport = createSSETransport({
1797
+ * maxResponseChars: 10_000,
1798
+ * errorMessages: {
1799
+ * INPUT_GUARDRAIL_FAILED: 'Your message was flagged by our safety filter.',
1800
+ * },
1801
+ * });
1802
+ *
1803
+ * // Next.js route handler
1804
+ * export async function POST(req: Request) {
1805
+ * const { message } = await req.json();
1806
+ * return transport.toResponse(streamable, 'docs-qa', message);
1807
+ * }
1808
+ * ```
1809
+ */
1810
+ /** Async iterable of string tokens with result promise and abort */
1811
+ interface SSETokenStream extends AsyncIterable<string> {
1812
+ result: Promise<unknown>;
1813
+ abort(): void;
1814
+ }
1815
+ /** Any object with a .stream() method compatible with SSE transport */
1816
+ interface SSEStreamable {
1817
+ stream(agentId: string, input: string, opts?: {
1818
+ signal?: AbortSignal;
1819
+ }): SSETokenStream;
1820
+ }
1821
+ type SSEEvent = {
1822
+ type: "text";
1823
+ text: string;
1824
+ } | {
1825
+ type: "truncated";
1826
+ text: string;
1827
+ } | {
1828
+ type: "done";
1829
+ } | {
1830
+ type: "error";
1831
+ message: string;
1832
+ } | {
1833
+ type: "heartbeat";
1834
+ timestamp: number;
1835
+ };
1836
+ interface SSETransportConfig {
1837
+ /** Truncate response after this many characters (default: Infinity) */
1838
+ maxResponseChars?: number;
1839
+ /** Message shown when response is truncated */
1840
+ truncationMessage?: string;
1841
+ /** Heartbeat interval in ms (default: 0 = disabled) */
1842
+ heartbeatIntervalMs?: number;
1843
+ /** Map error codes/types to user-facing messages */
1844
+ errorMessages?: Record<string, string> | ((error: unknown) => string);
1845
+ /** Extra headers merged into the SSE response */
1846
+ headers?: Record<string, string>;
1847
+ }
1848
+ interface SSETransport {
1849
+ /** Create a full HTTP Response with SSE headers */
1850
+ toResponse(source: SSEStreamable, agentId: string, input: string, opts?: {
1851
+ signal?: AbortSignal;
1852
+ }): Response;
1853
+ /** Return just the ReadableStream (for Express/Koa `res.write()`) */
1854
+ toStream(source: SSEStreamable, agentId: string, input: string, opts?: {
1855
+ signal?: AbortSignal;
1856
+ }): ReadableStream<Uint8Array>;
1857
+ }
1858
+ /**
1859
+ * Create an SSE transport that converts a token stream into Server-Sent Events.
1860
+ */
1861
+ declare function createSSETransport(config?: SSETransportConfig): SSETransport;
1862
+
1863
+ /**
1864
+ * P2: Intelligent Retry — HTTP-status-aware retry wrapper for AgentRunner.
1865
+ *
1866
+ * Respects 429 Retry-After headers, uses exponential backoff with jitter for 503,
1867
+ * and never retries client errors (400/401/403/404/422).
1868
+ *
1869
+ * @module
1870
+ *
1871
+ * @example
1872
+ * ```typescript
1873
+ * import { withRetry, RetryExhaustedError } from '@directive-run/ai';
1874
+ *
1875
+ * const runner = withRetry(baseRunner, {
1876
+ * maxRetries: 3,
1877
+ * baseDelayMs: 1000,
1878
+ * maxDelayMs: 30000,
1879
+ * onRetry: (attempt, error, delayMs) => {
1880
+ * console.log(`Retry ${attempt} in ${delayMs}ms: ${error.message}`);
1881
+ * },
1882
+ * });
1883
+ *
1884
+ * try {
1885
+ * const result = await runner(agent, input);
1886
+ * } catch (err) {
1887
+ * if (err instanceof RetryExhaustedError) {
1888
+ * console.error(`All ${err.retryCount} retries failed:`, err.lastError);
1889
+ * }
1890
+ * }
1891
+ * ```
1892
+ */
1893
+
1894
+ /**
1895
+ * Configuration for the intelligent retry wrapper.
1896
+ *
1897
+ * @example
1898
+ * ```typescript
1899
+ * const config: RetryConfig = {
1900
+ * maxRetries: 3,
1901
+ * baseDelayMs: 1000,
2861
1902
  * maxDelayMs: 30000,
2862
1903
  * isRetryable: (error) => !error.message.includes("invalid API key"),
2863
1904
  * onRetry: (attempt, error, delayMs) => {
@@ -3212,726 +2253,756 @@ declare function byPattern(pattern: RegExp, model: string): ModelRule;
3212
2253
  declare function withModelSelection(runner: AgentRunner, configOrRules: ModelSelectionConfig | ModelRule[]): AgentRunner;
3213
2254
 
3214
2255
  /**
3215
- * P6: Structured OutputsSchema validation with auto-retry for LLM responses.
3216
- *
3217
- * Turns unreliable text output into typed, validated data. Appends JSON schema
3218
- * instructions to the system prompt and retries with error feedback on parse failure.
2256
+ * P5: Batch QueueApplication-level batching for agent calls.
3219
2257
  *
3220
- * Works with any Zod-compatible schema (any object with a `safeParse` method).
2258
+ * Accumulates calls and flushes them in batches to reduce overhead.
2259
+ * Each `submit()` returns a promise that resolves when its individual call completes.
2260
+ * Batches execute calls in parallel up to a configurable concurrency limit.
3221
2261
  *
3222
2262
  * @module
3223
2263
  *
3224
2264
  * @example
3225
2265
  * ```typescript
3226
- * import { z } from "zod";
3227
- * import { withStructuredOutput, StructuredOutputError } from '@directive-run/ai';
3228
- *
3229
- * const SentimentSchema = z.object({
3230
- * sentiment: z.enum(["positive", "negative", "neutral"]),
3231
- * confidence: z.number().min(0).max(1),
3232
- * });
2266
+ * import { createBatchQueue } from '@directive-run/ai';
3233
2267
  *
3234
- * const runner = withStructuredOutput(baseRunner, {
3235
- * schema: SentimentSchema,
3236
- * maxRetries: 2,
2268
+ * const queue = createBatchQueue(runner, {
2269
+ * maxBatchSize: 20,
2270
+ * maxWaitMs: 5000,
2271
+ * concurrency: 5,
3237
2272
  * });
3238
2273
  *
3239
- * const result = await runner(agent, "Analyze: I love this product!");
3240
- * // result.output is typed as { sentiment: string; confidence: number }
3241
- * ```
3242
- */
3243
-
3244
- /**
3245
- * Zod-compatible schema duck type — any object with a `safeParse` method.
2274
+ * // Submit calls they batch automatically
2275
+ * const [r1, r2, r3] = await Promise.all([
2276
+ * queue.submit(agent, "input 1"),
2277
+ * queue.submit(agent, "input 2"),
2278
+ * queue.submit(agent, "input 3"),
2279
+ * ]);
3246
2280
  *
3247
- * This interface allows structured outputs to work with Zod, Valibot,
3248
- * or any validation library that implements this pattern.
2281
+ * // Force immediate flush
2282
+ * await queue.flush();
3249
2283
  *
3250
- * @example
3251
- * ```typescript
3252
- * import { z } from "zod";
3253
- *
3254
- * // Zod schemas implement SafeParseable automatically
3255
- * const schema = z.object({ name: z.string() });
3256
- *
3257
- * // Custom schema
3258
- * const custom: SafeParseable<{ name: string }> = {
3259
- * safeParse(value) {
3260
- * if (typeof value === "object" && value && "name" in value) {
3261
- * return { success: true, data: value as { name: string } };
3262
- * }
3263
- * return { success: false, error: { message: "Missing name field" } };
3264
- * },
3265
- * };
2284
+ * // Clean up (flushes remaining calls)
2285
+ * await queue.dispose();
3266
2286
  * ```
3267
2287
  */
3268
- interface SafeParseable<T = unknown> {
3269
- safeParse(value: unknown): SafeParseResult<T>;
3270
- /** Optional: schema description injected into the system prompt. */
3271
- description?: string;
3272
- }
3273
- interface SafeParseResult<T> {
3274
- success: boolean;
3275
- data?: T;
3276
- error?: {
3277
- message?: string;
3278
- issues?: Array<{
3279
- message: string;
3280
- }>;
3281
- };
2288
+
2289
+ interface BatchQueueConfig {
2290
+ /** Maximum number of calls per batch. @default 20 */
2291
+ maxBatchSize?: number;
2292
+ /** Maximum time to wait before flushing (ms). @default 5000 */
2293
+ maxWaitMs?: number;
2294
+ /** Number of calls to run in parallel within a batch. @default 5 */
2295
+ concurrency?: number;
3282
2296
  }
3283
- interface StructuredOutputConfig<T = unknown> {
3284
- /** Zod-compatible schema with safeParse. */
3285
- schema: SafeParseable<T>;
3286
- /** Max retries on parse/validation failure. @default 2 */
3287
- maxRetries?: number;
3288
- /** Custom JSON extractor. Default: finds first `{...}` or `[...]` in output. */
3289
- extractJson?: (output: string) => unknown;
3290
- /** Schema description to inject into system prompt. Auto-derived from schema.description if available. */
3291
- schemaDescription?: string;
2297
+ interface BatchQueue {
2298
+ /** Submit a call to the queue. Returns a promise that resolves when the call completes. */
2299
+ submit<T = unknown>(agent: AgentLike, input: string, options?: RunOptions): Promise<RunResult<T>>;
2300
+ /** Flush all pending calls immediately. */
2301
+ flush(): Promise<void>;
2302
+ /** Get the number of pending calls. */
2303
+ readonly pending: number;
2304
+ /** Dispose the queue, flushing remaining calls. */
2305
+ dispose(): Promise<void>;
3292
2306
  }
3293
- /** Default JSON extractor — finds the first `{...}` or `[...]` in output. */
3294
- declare function extractJsonFromOutput(output: string): unknown;
3295
2307
  /**
3296
- * Wrap an AgentRunner with structured output parsing and validation.
2308
+ * Create a batch queue for grouping agent calls.
3297
2309
  *
3298
2310
  * @example
3299
2311
  * ```typescript
3300
- * import { z } from "zod";
3301
- *
3302
- * const SentimentSchema = z.object({
3303
- * sentiment: z.enum(["positive", "negative", "neutral"]),
3304
- * confidence: z.number().min(0).max(1),
2312
+ * const queue = createBatchQueue(runner, {
2313
+ * maxBatchSize: 20,
2314
+ * maxWaitMs: 5000,
2315
+ * concurrency: 5,
3305
2316
  * });
3306
2317
  *
3307
- * const runner = withStructuredOutput(baseRunner, {
3308
- * schema: SentimentSchema,
3309
- * maxRetries: 2,
3310
- * });
2318
+ * // Submit multiple calls — they batch automatically
2319
+ * const [result1, result2, result3] = await Promise.all([
2320
+ * queue.submit(agent, "input 1"),
2321
+ * queue.submit(agent, "input 2"),
2322
+ * queue.submit(agent, "input 3"),
2323
+ * ]);
3311
2324
  *
3312
- * const result = await runner(agent, "Analyze: I love this product!");
3313
- * // result.output is typed as { sentiment: string; confidence: number }
2325
+ * // Clean up
2326
+ * await queue.dispose();
3314
2327
  * ```
3315
2328
  */
3316
- declare function withStructuredOutput<T = unknown>(runner: AgentRunner, config: StructuredOutputConfig<T>): AgentRunner;
3317
- /** Error thrown when structured output parsing fails after all retries. */
3318
- declare class StructuredOutputError extends Error {
3319
- readonly lastResult: RunResult<unknown> | undefined;
3320
- constructor(message: string, lastResult?: RunResult<unknown>);
3321
- }
2329
+ declare function createBatchQueue(runner: AgentRunner, config?: BatchQueueConfig): BatchQueue;
3322
2330
 
3323
2331
  /**
3324
- * Agent Stack Composition API for AI Adapters
2332
+ * P4: Constraint-Driven Provider Routing Directive's unique differentiator.
3325
2333
  *
3326
- * One factory that wires orchestrator, memory, circuit breaker, rate limiter,
3327
- * streaming, multi-agent patterns, semantic cache, observability, OTLP export,
3328
- * and communication bus with sensible defaults.
2334
+ * Uses user-supplied constraints to select providers based on runtime state:
2335
+ * cost, latency, error rates, and compliance regions.
3329
2336
  *
3330
- * @example Basic usage
3331
- * ```typescript
3332
- * import { createAgentStack, parallel } from '@directive-run/ai';
3333
- *
3334
- * const stack = createAgentStack({
3335
- * runner: myAgentRunner,
3336
- * agents: { move: { agent: moveAgent, capabilities: ["move"] } },
3337
- * memory: { maxMessages: 30 },
3338
- * circuitBreaker: { failureThreshold: 3 },
3339
- * cache: { threshold: 0.98, maxSize: 200, ttlMs: 600_000 },
3340
- * observability: { serviceName: "my-app" },
3341
- * });
2337
+ * Tracks per-provider stats (call count, error count, cost, latency) and
2338
+ * exposes them as {@link RoutingFacts} for constraint evaluation.
3342
2339
  *
3343
- * const result = await stack.run("move", input);
3344
- * ```
2340
+ * @module
3345
2341
  *
3346
- * @example Streaming
2342
+ * @example
3347
2343
  * ```typescript
3348
- * const stack = createAgentStack({
3349
- * runner: myAgentRunner,
3350
- * streaming: { runner: myStreamingAgentRunner },
3351
- * agents: { chat: { agent: chatAgent, capabilities: ["chat"] } },
2344
+ * import { createConstraintRouter } from '@directive-run/ai';
2345
+ * import type { ConstraintRouterRunner } from '@directive-run/ai';
2346
+ *
2347
+ * const router = createConstraintRouter({
2348
+ * providers: [
2349
+ * { name: "openai", runner: openaiRunner, pricing: { inputPerMillion: 5, outputPerMillion: 15 } },
2350
+ * { name: "anthropic", runner: anthropicRunner, pricing: { inputPerMillion: 3, outputPerMillion: 15 } },
2351
+ * { name: "ollama", runner: ollamaRunner },
2352
+ * ],
2353
+ * defaultProvider: "openai",
2354
+ * constraints: [
2355
+ * { when: (facts) => facts.totalCost > 100, provider: "ollama", priority: 10 },
2356
+ * { when: (facts) => facts.providers["openai"]?.errorCount > 5, provider: "anthropic" },
2357
+ * ],
2358
+ * preferCheapest: true, // opt-in to cheapest-provider heuristic
2359
+ * onProviderSelected: (name, reason) => console.log(`Using ${name} (${reason})`),
3352
2360
  * });
3353
2361
  *
3354
- * const tokenStream = stack.stream("chat", "Hello!");
3355
- * for await (const token of tokenStream) { process.stdout.write(token); }
3356
- * const finalResult = await tokenStream.result;
2362
+ * // Access runtime stats
2363
+ * console.log(router.facts.totalCost, router.facts.callCount);
3357
2364
  * ```
3358
2365
  */
3359
2366
 
3360
- /** Callback-based streaming run function (e.g. for SSE-based LLM APIs) */
3361
- type StreamingCallbackRunner = (agent: AgentLike, input: string, callbacks: {
3362
- onToken?: (token: string) => void;
3363
- onToolStart?: (tool: string, id: string, args: string) => void;
3364
- onToolEnd?: (tool: string, id: string, result: string) => void;
3365
- onMessage?: (message: Message$1) => void;
3366
- signal?: AbortSignal;
3367
- }) => Promise<RunResult<unknown>>;
3368
- interface AgentStackConfig {
3369
- /** Required: base runner for agent execution */
2367
+ /**
2368
+ * Provider definition for the constraint router.
2369
+ *
2370
+ * Each provider has its own runner, optional pricing (for cost tracking
2371
+ * and cheapest-provider heuristic), and optional region tag.
2372
+ */
2373
+ interface RoutingProvider {
2374
+ /** Unique name for this provider. */
2375
+ name: string;
2376
+ /** The runner to use for this provider. */
3370
2377
  runner: AgentRunner;
3371
- /** Enables stack.stream() when provided */
3372
- streaming?: {
3373
- runner: StreamingCallbackRunner;
3374
- };
3375
- /** Agent registry — required for multi-agent patterns */
3376
- agents?: AgentRegistry;
3377
- /** Named execution patterns (parallel, sequential, supervisor) */
3378
- patterns?: Record<string, ExecutionPattern>;
3379
- memory?: {
3380
- maxMessages?: number;
3381
- preserveRecentCount?: number;
3382
- } | AgentMemory;
3383
- circuitBreaker?: CircuitBreakerConfig | CircuitBreaker;
3384
- rateLimit?: {
3385
- maxPerMinute: number;
3386
- };
3387
- cache?: {
3388
- threshold?: number;
3389
- maxSize?: number;
3390
- ttlMs?: number;
3391
- embedder?: EmbedderFn;
3392
- } | SemanticCache;
3393
- observability?: {
3394
- serviceName: string;
3395
- alerts?: AlertConfig[];
3396
- } | ObservabilityInstance;
3397
- otlp?: {
3398
- endpoint: string;
3399
- intervalMs?: number;
3400
- onError?: (err: Error, type: "metrics" | "traces") => void;
3401
- };
3402
- /** Message bus for agent communication */
3403
- messageBus?: {
3404
- maxHistory?: number;
3405
- } | MessageBus;
3406
- guardrails?: {
3407
- input?: Array<GuardrailFn<InputGuardrailData> | NamedGuardrail<InputGuardrailData>>;
3408
- output?: Array<GuardrailFn<OutputGuardrailData> | NamedGuardrail<OutputGuardrailData>>;
3409
- streaming?: StreamingGuardrail[];
3410
- };
3411
- maxTokenBudget?: number;
3412
- /** Cost per million tokens for cost estimation */
3413
- costPerMillionTokens?: number;
3414
- debug?: boolean;
3415
- constraints?: Record<string, OrchestratorConstraint<Record<string, unknown>>>;
3416
- resolvers?: Record<string, OrchestratorResolver<Record<string, unknown>, Requirement>>;
3417
- approvals?: {
3418
- /** @default true */
3419
- autoApproveToolCalls?: boolean;
3420
- onRequest?: (request: ApprovalRequest) => void;
3421
- /** @default 300_000 */
3422
- timeoutMs?: number;
3423
- };
3424
- retry?: AgentRetryConfig;
3425
- hooks?: OrchestratorLifecycleHooks;
3426
- /** P2: Intelligent retry config for the base runner. */
3427
- intelligentRetry?: RetryConfig;
3428
- /** P0: Fallback runners (tried in order on failure). */
3429
- fallback?: {
3430
- runners: AgentRunner[];
3431
- config?: FallbackConfig;
3432
- };
3433
- /** P1: Cost budget guards. */
3434
- budget?: BudgetConfig;
3435
- /** P3: Model selection rules (first match wins). */
3436
- modelSelection?: ModelRule[];
3437
- /** P6: Structured output config (applied per-agent via agents map, or globally here). */
3438
- structuredOutput?: StructuredOutputConfig;
3439
- }
3440
- interface StackRunOptions {
3441
- /** Override output guardrails for this call */
3442
- guardrails?: {
3443
- output?: Array<GuardrailFn<OutputGuardrailData> | NamedGuardrail<OutputGuardrailData>>;
3444
- };
3445
- /** Set to false to skip cache for this call */
3446
- cache?: false;
3447
- /** AbortSignal for cancellation */
3448
- signal?: AbortSignal;
3449
- }
3450
- interface StackStreamOptions {
3451
- signal?: AbortSignal;
3452
- }
3453
- interface TokenStream<T = string> extends AsyncIterable<string> {
3454
- /** Resolves to the final run result after the stream completes */
3455
- result: Promise<RunResult<T>>;
3456
- /** Abort the stream */
3457
- abort: () => void;
3458
- }
3459
- interface AgentStackState {
3460
- totalTokens: number;
3461
- estimatedCost: number;
3462
- circuitState: CircuitState;
3463
- cacheStats: CacheStats;
3464
- memoryMessageCount: number;
3465
- busMessageCount: number;
3466
- rateLimitRemaining: number | null;
3467
- }
3468
- /** Options for runStructured() */
3469
- interface StructuredRunOptions<_T = unknown> extends StackRunOptions {
3470
- /** Validate the output. Return `true` or `{ valid: true }` on success. */
3471
- validate: (value: unknown) => boolean | {
3472
- valid: boolean;
3473
- errors?: string[];
3474
- };
3475
- /** Number of retry attempts on validation failure @default 1 */
3476
- retries?: number;
3477
- }
3478
- interface AgentStack {
3479
- /** Run a single registered agent by ID */
3480
- run<T = unknown>(agentId: string, input: string, options?: StackRunOptions): Promise<RunResult<T>>;
3481
- /** Run and validate output against a schema, retrying on failure */
3482
- runStructured<T>(agentId: string, input: string, options: StructuredRunOptions<T>): Promise<RunResult<T>>;
3483
- /** Run a named execution pattern */
3484
- runPattern<T = unknown>(patternId: string, input: string, options?: StackRunOptions): Promise<T>;
3485
- /** Stream tokens from a single agent */
3486
- stream<T = string>(agentId: string, input: string, options?: StackStreamOptions): TokenStream<T>;
3487
- /** Stream full rich chunks (token, tool_start, tool_end, etc.) from a single agent */
3488
- streamChunks<T = unknown>(agentId: string, input: string, options?: StackStreamOptions): StreamingRunResult<T>;
3489
- /** Approve a pending approval request */
3490
- approve(requestId: string): void;
3491
- /** Reject a pending approval request */
3492
- reject(requestId: string, reason?: string): void;
3493
- /** Aggregate state across all features */
3494
- getState(): AgentStackState;
3495
- /** Reset all feature state */
3496
- reset(): void;
3497
- /** Dispose all resources */
3498
- dispose(): Promise<void>;
3499
- readonly orchestrator: AgentOrchestrator<Record<string, unknown>>;
3500
- readonly observability: ObservabilityInstance | null;
3501
- readonly messageBus: MessageBus | null;
3502
- readonly coordinator: MultiAgentOrchestrator | null;
3503
- readonly cache: SemanticCache | null;
3504
- readonly memory: AgentMemory | null;
3505
- /** Get observability timeline (spans + metrics) for debugging */
3506
- getTimeline(limit?: number): {
3507
- spans: readonly TraceSpan[];
3508
- metrics: Record<string, AggregatedMetric>;
2378
+ /** Token pricing (cost per million tokens). */
2379
+ pricing?: {
2380
+ inputPerMillion: number;
2381
+ outputPerMillion: number;
3509
2382
  };
2383
+ /** Geographic region (for compliance routing). */
2384
+ region?: string;
3510
2385
  }
3511
2386
  /**
3512
- * Create an agent stack that composes all AI adapter features.
2387
+ * Runtime facts tracked by the router exposed for user constraints.
3513
2388
  *
3514
- * Only `runner` is required. Every other feature activates when its config key
3515
- * is present. Pass a pre-built instance to reuse existing objects, or pass
3516
- * shorthand config to let the stack create them.
2389
+ * Access via the `facts` property on the returned {@link ConstraintRouterRunner}.
3517
2390
  */
3518
- declare function createAgentStack(config: AgentStackConfig): AgentStack;
3519
-
2391
+ interface RoutingFacts {
2392
+ totalCost: number;
2393
+ callCount: number;
2394
+ errorCount: number;
2395
+ lastProvider: string | null;
2396
+ avgLatencyMs: number;
2397
+ /** Per-provider stats. */
2398
+ providers: Record<string, ProviderStats>;
2399
+ }
2400
+ interface ProviderStats {
2401
+ callCount: number;
2402
+ errorCount: number;
2403
+ totalCost: number;
2404
+ avgLatencyMs: number;
2405
+ lastErrorAt: number | null;
2406
+ }
2407
+ /** User-supplied routing constraint. */
2408
+ interface RoutingConstraint {
2409
+ /** When this constraint is active. */
2410
+ when: (facts: RoutingFacts) => boolean;
2411
+ /** The provider to route to. */
2412
+ provider: string;
2413
+ /** Priority — higher wins when multiple constraints match. @default 0 */
2414
+ priority?: number;
2415
+ }
2416
+ interface ConstraintRouterConfig {
2417
+ /** Available providers. */
2418
+ providers: RoutingProvider[];
2419
+ /** Default provider name. */
2420
+ defaultProvider: string;
2421
+ /** User-supplied routing constraints. */
2422
+ constraints?: RoutingConstraint[];
2423
+ /** Called when a provider is selected. */
2424
+ onProviderSelected?: (providerName: string, reason: "constraint" | "cheapest" | "default") => void;
2425
+ /** Error cooldown — skip a provider for this many ms after an error. @default 30000 */
2426
+ errorCooldownMs?: number;
2427
+ /**
2428
+ * When true, automatically prefer the cheapest available provider
2429
+ * (based on pricing) when no user constraint matches.
2430
+ * When false, the default provider is used unless a constraint overrides it.
2431
+ * @default false
2432
+ */
2433
+ preferCheapest?: boolean;
2434
+ }
3520
2435
  /**
3521
- * AI Bridge Syncs AI adapter state into a Directive system.
3522
- *
3523
- * Eliminates manual state sync boilerplate when using createAgentStack()
3524
- * alongside createSystem().
3525
- *
3526
- * @example Using with AgentStack directly
3527
- * ```typescript
3528
- * const syncAI = createAISyncer(stack, (state) => {
3529
- * system.events.chat.updateAIState({
3530
- * totalTokens: state.totalTokens,
3531
- * estimatedCost: state.estimatedCost,
3532
- * circuitState: state.circuitState,
3533
- * });
3534
- * });
3535
- * syncAI();
3536
- * ```
2436
+ * Create a constraint-driven provider router.
3537
2437
  *
3538
- * @example Using with a wrapper that has getState()
2438
+ * @example
3539
2439
  * ```typescript
3540
- * const syncAI = createAISyncer(myAIWrapper, (state) => {
3541
- * system.events.chat.updateAIState({ ... });
2440
+ * const runner = createConstraintRouter({
2441
+ * providers: [
2442
+ * { name: "openai", runner: openaiRunner, pricing: { inputPerMillion: 5, outputPerMillion: 15 } },
2443
+ * { name: "anthropic", runner: anthropicRunner, pricing: { inputPerMillion: 3, outputPerMillion: 15 } },
2444
+ * { name: "ollama", runner: ollamaRunner },
2445
+ * ],
2446
+ * defaultProvider: "openai",
2447
+ * constraints: [
2448
+ * { when: (facts) => facts.totalCost > 100, provider: "ollama", priority: 10 },
2449
+ * { when: (facts) => facts.providers["openai"]?.errorCount > 5, provider: "anthropic" },
2450
+ * ],
3542
2451
  * });
3543
- * syncAI();
3544
2452
  * ```
3545
2453
  */
2454
+ declare function createConstraintRouter(config: ConstraintRouterConfig): ConstraintRouterRunner;
2455
+ /** Helper type for accessing router facts. */
2456
+ type ConstraintRouterRunner = AgentRunner & {
2457
+ readonly facts: RoutingFacts;
2458
+ };
2459
+
3546
2460
  /**
3547
- * Any object with a getState() method.
3548
- * Works with AgentStack, or any wrapper that exposes getState().
3549
- */
3550
- interface Syncable<S> {
3551
- getState(): S;
3552
- }
3553
- /**
3554
- * Create a sync function that reads the latest state from a source and
3555
- * passes it to a callback (typically dispatching events into a Directive system).
2461
+ * DevTools Server WebSocket-based bridge between orchestrators and DevTools UI.
2462
+ *
2463
+ * Streams debug timeline events, health metrics, breakpoint state, and system
2464
+ * snapshots in real-time to connected DevTools clients. Accepts commands from
2465
+ * clients to resume/cancel breakpoints and request snapshots.
3556
2466
  *
3557
- * Call the returned function after any AI operation to push state updates.
2467
+ * Transport-agnostic: works with any WebSocket implementation (ws, Bun, Deno)
2468
+ * via the {@link DevToolsTransport} interface.
2469
+ *
2470
+ * @module
3558
2471
  */
3559
- declare function createAISyncer<S>(source: Syncable<S>, syncFn: (state: S) => void): () => void;
3560
2472
 
2473
+ /** A connected DevTools client */
2474
+ interface DevToolsClient {
2475
+ /** Send a JSON-serializable message to this client */
2476
+ send(data: string): void;
2477
+ /** Close the connection */
2478
+ close(): void;
2479
+ }
3561
2480
  /**
3562
- * RAG Enricher Composable retrieval-augmented generation pipeline.
2481
+ * Transport layer for the DevTools server.
3563
2482
  *
3564
- * Embeds a query, searches a chunk store by cosine similarity, and assembles
3565
- * an enriched input string (context + history + query) for any agent.
2483
+ * Implement this interface to bridge any WebSocket library (ws, Bun.serve, Deno.serve).
3566
2484
  *
3567
- * @example
2485
+ * @example Node.js with `ws`:
3568
2486
  * ```typescript
3569
- * import {
3570
- * createRAGEnricher,
3571
- * createJSONFileStore,
3572
- * } from '@directive-run/ai';
2487
+ * import { WebSocketServer } from "ws";
3573
2488
  *
3574
- * const enricher = createRAGEnricher({
3575
- * embedder: myEmbedder, // Provide your own EmbedderFn
3576
- * storage: createJSONFileStore({ filePath: './embeddings.json' }),
3577
- * });
2489
+ * function createWsTransport(port: number): DevToolsTransport {
2490
+ * const wss = new WebSocketServer({ port });
2491
+ * let onConnect: ((client: DevToolsClient) => void) | null = null;
3578
2492
  *
3579
- * const enrichedInput = await enricher.enrich('How do constraints work?', {
3580
- * prefix: 'User is viewing: /docs/constraints',
3581
- * history: [{ role: 'user', content: 'Hello' }],
3582
- * });
2493
+ * wss.on("connection", (ws) => {
2494
+ * const client: DevToolsClient = {
2495
+ * send: (data) => { if (ws.readyState === ws.OPEN) ws.send(data); },
2496
+ * close: () => ws.close(),
2497
+ * };
2498
+ * ws.on("message", (raw) => {
2499
+ * if (client._onMessage) client._onMessage(raw.toString());
2500
+ * });
2501
+ * ws.on("close", () => {
2502
+ * if (client._onClose) client._onClose();
2503
+ * });
2504
+ * onConnect?.(client);
2505
+ * });
2506
+ *
2507
+ * return {
2508
+ * onConnection(handler) { onConnect = handler; },
2509
+ * close() { wss.close(); },
2510
+ * };
2511
+ * }
3583
2512
  * ```
3584
2513
  */
3585
-
3586
- /** A document chunk with embedding and metadata */
3587
- interface RAGChunk {
3588
- id: string;
3589
- content: string;
3590
- embedding: Embedding;
3591
- metadata: Record<string, unknown>;
3592
- }
3593
- /** Pluggable storage backend */
3594
- interface RAGStorage {
3595
- getChunks(): Promise<RAGChunk[]>;
3596
- size(): Promise<number>;
3597
- /** Optional: optimized vector search (bypasses full getChunks scan) */
3598
- search?(query: Embedding, topK: number, minSimilarity: number): Promise<Array<RAGChunk & {
3599
- similarity: number;
3600
- }>>;
3601
- /** Reload storage (clear cache, re-read from source) */
3602
- reload?(): Promise<void>;
3603
- /** Dispose of resources */
3604
- dispose?(): void;
3605
- }
3606
- interface RAGEnricherConfig {
3607
- /** Function to generate query embeddings */
3608
- embedder: EmbedderFn;
3609
- /** Storage backend for document chunks */
3610
- storage: RAGStorage;
3611
- /** Number of top results to return (default: 5) */
3612
- topK?: number;
3613
- /** Minimum similarity score to include, clamped to [0, 1] (default: 0.3) */
3614
- minSimilarity?: number;
3615
- /** Custom chunk formatter */
3616
- formatChunk?: (chunk: RAGChunk, similarity: number) => string;
3617
- /** Custom context block formatter */
3618
- formatContext?: (formattedChunks: string[], query: string) => string;
3619
- /** Error callback — embedder/storage errors are non-fatal by default */
3620
- onError?: (error: Error) => void;
2514
+ interface DevToolsTransport {
2515
+ /** Register a handler for new client connections */
2516
+ onConnection(handler: (client: DevToolsClient, onMessage: (handler: (data: string) => void) => void, onClose: (handler: () => void) => void) => void): void;
2517
+ /** Shut down the transport */
2518
+ close(): void;
3621
2519
  }
3622
- interface RAGEnrichOptions {
3623
- /** Prefix line (e.g. "User is viewing: /docs/constraints") */
3624
- prefix?: string;
3625
- /** Conversation history */
3626
- history?: Array<{
3627
- role: string;
3628
- content: string;
2520
+ /** Messages sent FROM the server TO clients */
2521
+ type DevToolsServerMessage = {
2522
+ type: "welcome";
2523
+ version: number;
2524
+ sessionId: string;
2525
+ timestamp: number;
2526
+ } | {
2527
+ type: "event";
2528
+ event: DebugEvent;
2529
+ } | {
2530
+ type: "event_batch";
2531
+ events: DebugEvent[];
2532
+ } | {
2533
+ type: "snapshot";
2534
+ data: DevToolsSnapshot;
2535
+ } | {
2536
+ type: "health";
2537
+ metrics: Record<string, AgentHealthMetrics>;
2538
+ } | {
2539
+ type: "breakpoints";
2540
+ state: BreakpointState;
2541
+ } | {
2542
+ type: "pong";
2543
+ timestamp: number;
2544
+ } | {
2545
+ type: "scratchpad_state";
2546
+ data: Record<string, unknown>;
2547
+ } | {
2548
+ type: "scratchpad_update";
2549
+ key: string;
2550
+ value: unknown;
2551
+ } | {
2552
+ type: "derived_state";
2553
+ data: Record<string, unknown>;
2554
+ } | {
2555
+ type: "derived_update";
2556
+ id: string;
2557
+ value: unknown;
2558
+ } | {
2559
+ type: "fork_complete";
2560
+ eventId: number;
2561
+ newEventCount: number;
2562
+ } | {
2563
+ type: "token_stream";
2564
+ agentId: string;
2565
+ tokens: string;
2566
+ tokenCount: number;
2567
+ } | {
2568
+ type: "stream_done";
2569
+ agentId: string;
2570
+ totalTokens: number;
2571
+ } | {
2572
+ type: "error";
2573
+ code: string;
2574
+ message: string;
2575
+ };
2576
+ /** Messages sent FROM clients TO the server */
2577
+ type DevToolsClientMessage = {
2578
+ type: "request_snapshot";
2579
+ } | {
2580
+ type: "request_health";
2581
+ } | {
2582
+ type: "request_events";
2583
+ since?: number;
2584
+ } | {
2585
+ type: "request_breakpoints";
2586
+ } | {
2587
+ type: "resume_breakpoint";
2588
+ breakpointId: string;
2589
+ modifications?: {
2590
+ input?: string;
2591
+ skip?: boolean;
2592
+ };
2593
+ } | {
2594
+ type: "cancel_breakpoint";
2595
+ breakpointId: string;
2596
+ reason?: string;
2597
+ } | {
2598
+ type: "export_session";
2599
+ } | {
2600
+ type: "import_session";
2601
+ data: string;
2602
+ } | {
2603
+ type: "request_scratchpad";
2604
+ } | {
2605
+ type: "request_derived";
2606
+ } | {
2607
+ type: "fork_from_snapshot";
2608
+ eventId: number;
2609
+ } | {
2610
+ type: "ping";
2611
+ };
2612
+ /** System snapshot sent to clients on demand */
2613
+ interface DevToolsSnapshot {
2614
+ timestamp: number;
2615
+ agents: Record<string, {
2616
+ status: string;
2617
+ lastInput?: string;
2618
+ lastOutput?: unknown;
2619
+ totalTokens: number;
2620
+ runCount: number;
3629
2621
  }>;
3630
- /** Per-call topK override */
3631
- topK?: number;
3632
- /** Filter chunks before ranking (e.g. by metadata tag or section) */
3633
- filter?: (chunk: RAGChunk) => boolean;
3634
- }
3635
- interface RAGEnricher {
3636
- /** Retrieve relevant chunks for a query */
3637
- retrieve(query: string, topK?: number): Promise<Array<RAGChunk & {
3638
- similarity: number;
3639
- }>>;
3640
- /** Retrieve + format into an enriched input string */
3641
- enrich(input: string, options?: RAGEnrichOptions): Promise<string>;
2622
+ coordinator?: {
2623
+ globalTokens: number;
2624
+ status: string;
2625
+ };
2626
+ derived?: Record<string, unknown>;
2627
+ eventCount: number;
2628
+ }
2629
+ /** Configuration for the DevTools server */
2630
+ interface DevToolsServerConfig {
2631
+ /** Transport to use for WebSocket connections */
2632
+ transport: DevToolsTransport;
2633
+ /** Debug timeline to subscribe to */
2634
+ timeline: DebugTimeline;
2635
+ /** Health monitor for metrics (optional) */
2636
+ healthMonitor?: HealthMonitor | null;
2637
+ /** Callback to get current agent states for snapshots */
2638
+ getSnapshot?: () => DevToolsSnapshot;
2639
+ /** Callback to get current breakpoint state */
2640
+ getBreakpointState?: () => BreakpointState;
2641
+ /** Callback to resume a breakpoint */
2642
+ onResumeBreakpoint?: (id: string, modifications?: {
2643
+ input?: string;
2644
+ skip?: boolean;
2645
+ }) => void;
2646
+ /** Callback to cancel a breakpoint */
2647
+ onCancelBreakpoint?: (id: string, reason?: string) => void;
2648
+ /** Callback to get current scratchpad state */
2649
+ getScratchpadState?: () => Record<string, unknown>;
2650
+ /** Callback to get current derived state */
2651
+ getDerivedState?: () => Record<string, unknown>;
2652
+ /** Callback to fork from a snapshot event */
2653
+ onForkFromSnapshot?: (eventId: number) => {
2654
+ newEventCount: number;
2655
+ };
2656
+ /** Maximum events to batch before flushing. Default: 1 (no batching) */
2657
+ batchSize?: number;
2658
+ /** Flush interval for batched events (ms). Default: 50 */
2659
+ batchIntervalMs?: number;
2660
+ /** Health metrics push interval (ms). 0 = no auto-push. Default: 0 */
2661
+ healthPushIntervalMs?: number;
2662
+ /** Maximum connected clients. Default: 50 */
2663
+ maxClients?: number;
2664
+ }
2665
+ /** DevTools server instance */
2666
+ interface DevToolsServer {
2667
+ /** Number of connected clients */
2668
+ readonly clientCount: number;
2669
+ /** Broadcast a message to all connected clients */
2670
+ broadcast(message: DevToolsServerMessage): void;
2671
+ /** Push current health metrics to all clients */
2672
+ pushHealth(): void;
2673
+ /** Push current breakpoint state to all clients */
2674
+ pushBreakpoints(): void;
2675
+ /** Push a scratchpad key update to all clients */
2676
+ pushScratchpadUpdate(key: string, value: unknown): void;
2677
+ /** Push a derived value update to all clients */
2678
+ pushDerivedUpdate(id: string, value: unknown): void;
2679
+ /** Push streaming tokens to all clients */
2680
+ pushTokenStream(agentId: string, tokens: string, tokenCount: number): void;
2681
+ /** Signal stream completion to all clients */
2682
+ pushStreamDone(agentId: string, totalTokens: number): void;
2683
+ /** Shut down the server and disconnect all clients */
2684
+ close(): void;
3642
2685
  }
3643
2686
  /**
3644
- * Create a RAG enricher that retrieves relevant document chunks and
3645
- * assembles enriched input for an agent.
2687
+ * Create a DevTools server that bridges orchestrator state to DevTools UI clients.
2688
+ *
2689
+ * @example
2690
+ * ```typescript
2691
+ * const server = createDevToolsServer({
2692
+ * transport: createWsTransport(4040),
2693
+ * timeline: orchestrator.timeline!,
2694
+ * healthMonitor: orchestrator.healthMonitor,
2695
+ * getSnapshot: () => buildSnapshot(orchestrator),
2696
+ * getBreakpointState: () => orchestrator.getBreakpointState(),
2697
+ * onResumeBreakpoint: (id, mods) => orchestrator.resumeBreakpoint(id, mods),
2698
+ * onCancelBreakpoint: (id, reason) => orchestrator.cancelBreakpoint(id, reason),
2699
+ * });
2700
+ * ```
3646
2701
  */
3647
- declare function createRAGEnricher(config: RAGEnricherConfig): RAGEnricher;
3648
- interface JSONFileStoreOptions {
3649
- /** Absolute or relative path to the JSON embeddings file */
3650
- filePath: string;
3651
- /** Optional transform from raw JSON entries to RAGChunk */
3652
- mapEntry?: (entry: Record<string, unknown>) => RAGChunk;
3653
- /** Cache TTL in ms. 0 = cache forever (default) */
3654
- ttlMs?: number;
2702
+ declare function createDevToolsServer(config: DevToolsServerConfig): DevToolsServer;
2703
+ /** Options for connecting DevTools to an orchestrator */
2704
+ interface ConnectDevToolsOptions {
2705
+ /** Port for the WebSocket server. Default: 4040 */
2706
+ port?: number;
2707
+ /** Host to bind to. Default: "localhost" */
2708
+ host?: string;
2709
+ /** Health metrics push interval (ms). Default: 5000 */
2710
+ healthPushIntervalMs?: number;
2711
+ /** Event batching size. Default: 1 (no batching) */
2712
+ batchSize?: number;
2713
+ }
2714
+ /** Minimal orchestrator interface for DevTools connection */
2715
+ interface DevToolsCompatibleOrchestrator {
2716
+ timeline: {
2717
+ subscribe: (listener: (event: DebugEvent) => void) => () => void;
2718
+ getEvents: () => DebugEvent[];
2719
+ import: (json: string) => void;
2720
+ export: () => string;
2721
+ forkFrom?: (eventId: number) => void;
2722
+ } | null;
2723
+ healthMonitor?: {
2724
+ getAllMetrics: () => Record<string, AgentHealthMetrics>;
2725
+ } | null;
2726
+ getPendingBreakpoints?: () => Array<{
2727
+ id: string;
2728
+ type: string;
2729
+ agentId: string;
2730
+ input: string;
2731
+ label?: string;
2732
+ requestedAt: number;
2733
+ }>;
2734
+ resumeBreakpoint?: (id: string, modifications?: {
2735
+ input?: string;
2736
+ skip?: boolean;
2737
+ }) => void;
2738
+ cancelBreakpoint?: (id: string, reason?: string) => void;
2739
+ getAllAgentStates?: () => Record<string, {
2740
+ status: string;
2741
+ lastInput?: string;
2742
+ lastOutput?: unknown;
2743
+ totalTokens: number;
2744
+ runCount: number;
2745
+ }>;
2746
+ /** Get current scratchpad state (multi-agent only) */
2747
+ getScratchpadState?: () => Record<string, unknown>;
2748
+ /** Get current derived values (multi-agent only) */
2749
+ getDerivedState?: () => Record<string, unknown>;
3655
2750
  }
3656
2751
  /**
3657
- * Create a RAGStorage backed by a JSON file (lazy-loaded, cached in memory).
3658
- * Uses dynamic `import('node:fs')` for isomorphic safety.
3659
- */
3660
- declare function createJSONFileStore(options: JSONFileStoreOptions): RAGStorage;
3661
-
3662
- /**
3663
- * SSE Transport — Wrap a Directive AgentStack token stream into an HTTP
3664
- * Server-Sent Events response.
2752
+ * Connect DevTools to an orchestrator instance.
3665
2753
  *
3666
- * Framework-agnostic: uses the WinterCG `Response` constructor (Node 18+,
3667
- * Deno, Bun, Cloudflare Workers, Next.js).
2754
+ * Convenience function that creates a WebSocket transport and DevTools server,
2755
+ * automatically wiring up the orchestrator's timeline, health monitor, and breakpoint system.
2756
+ *
2757
+ * Requires the `ws` package: `npm install ws`
2758
+ *
2759
+ * **Security:** Binding to `0.0.0.0` exposes the server to all network interfaces.
2760
+ * Only do this behind a firewall or with proper authentication.
3668
2761
  *
3669
2762
  * @example
3670
2763
  * ```typescript
3671
- * import { createSSETransport, createAgentStack } from '@directive-run/ai';
2764
+ * const orchestrator = createMultiAgentOrchestrator({ debug: true, ... });
2765
+ * const devtools = await connectDevTools(orchestrator, { port: 4040 });
3672
2766
  *
3673
- * const transport = createSSETransport({
3674
- * maxResponseChars: 10_000,
3675
- * errorMessages: {
3676
- * INPUT_GUARDRAIL_FAILED: 'Your message was flagged by our safety filter.',
3677
- * },
3678
- * });
3679
- *
3680
- * // Next.js route handler
3681
- * export async function POST(req: Request) {
3682
- * const { message } = await req.json();
3683
- * return transport.toResponse(stack, 'docs-qa', message);
3684
- * }
2767
+ * // Later, clean up:
2768
+ * devtools.close();
3685
2769
  * ```
3686
2770
  */
3687
-
3688
- type SSEEvent = {
3689
- type: "text";
3690
- text: string;
3691
- } | {
3692
- type: "truncated";
3693
- text: string;
3694
- } | {
3695
- type: "done";
3696
- } | {
3697
- type: "error";
3698
- message: string;
3699
- } | {
3700
- type: "heartbeat";
3701
- timestamp: number;
3702
- };
3703
- interface SSETransportConfig {
3704
- /** Truncate response after this many characters (default: Infinity) */
3705
- maxResponseChars?: number;
3706
- /** Message shown when response is truncated */
3707
- truncationMessage?: string;
3708
- /** Heartbeat interval in ms (default: 0 = disabled) */
3709
- heartbeatIntervalMs?: number;
3710
- /** Map error codes/types to user-facing messages */
3711
- errorMessages?: Record<string, string> | ((error: unknown) => string);
3712
- /** Extra headers merged into the SSE response */
3713
- headers?: Record<string, string>;
3714
- }
3715
- interface SSETransport {
3716
- /** Create a full HTTP Response with SSE headers */
3717
- toResponse(stack: AgentStack, agentId: string, input: string, opts?: {
3718
- signal?: AbortSignal;
3719
- }): Response;
3720
- /** Return just the ReadableStream (for Express/Koa `res.write()`) */
3721
- toStream(stack: AgentStack, agentId: string, input: string, opts?: {
3722
- signal?: AbortSignal;
3723
- }): ReadableStream<Uint8Array>;
2771
+ declare function connectDevTools(orchestrator: DevToolsCompatibleOrchestrator, options?: ConnectDevToolsOptions): Promise<DevToolsServer>;
2772
+ /**
2773
+ * Configuration for the built-in Node.js `ws` transport.
2774
+ *
2775
+ * Requires the `ws` package to be installed: `npm install ws`
2776
+ */
2777
+ interface WsTransportConfig {
2778
+ /** Port to listen on. Default: 4040 */
2779
+ port?: number;
2780
+ /** Host to bind to. Default: "localhost" */
2781
+ host?: string;
2782
+ /** Maximum incoming message size in bytes. Default: 1048576 (1MB) */
2783
+ maxPayloadBytes?: number;
3724
2784
  }
3725
2785
  /**
3726
- * Create an SSE transport that converts a Directive AgentStack token stream
3727
- * into Server-Sent Events.
2786
+ * Create a DevTools transport using the Node.js `ws` WebSocket library.
2787
+ *
2788
+ * This is a convenience helper — you can implement {@link DevToolsTransport}
2789
+ * with any WebSocket library.
2790
+ *
2791
+ * @example
2792
+ * ```typescript
2793
+ * const transport = await createWsTransport({ port: 4040 });
2794
+ * const server = createDevToolsServer({ transport, timeline });
2795
+ * ```
3728
2796
  */
3729
- declare function createSSETransport(config?: SSETransportConfig): SSETransport;
2797
+ declare function createWsTransport(config?: WsTransportConfig): Promise<DevToolsTransport>;
3730
2798
 
3731
2799
  /**
3732
- * P5: Batch Queue Application-level batching for agent calls.
2800
+ * Standalone utilities for goal planning and validation.
3733
2801
  *
3734
- * Accumulates calls and flushes them in batches to reduce overhead.
3735
- * Each `submit()` returns a promise that resolves when its individual call completes.
3736
- * Batches execute calls in parallel up to a configurable concurrency limit.
3737
- *
3738
- * @module
2802
+ * These functions work with the same `produces` / `requires` agent
2803
+ * declarations used by the goal pattern, without requiring an
2804
+ * orchestrator instance.
3739
2805
  *
3740
2806
  * @example
3741
2807
  * ```typescript
3742
- * import { createBatchQueue } from '@directive-run/ai';
2808
+ * import { validateGoal, planGoal, getDependencyGraph } from '@directive-run/ai';
3743
2809
  *
3744
- * const queue = createBatchQueue(runner, {
3745
- * maxBatchSize: 20,
3746
- * maxWaitMs: 5000,
3747
- * concurrency: 5,
3748
- * });
2810
+ * const agents = {
2811
+ * fetcher: { produces: ['data'], requires: [] },
2812
+ * analyzer: { produces: ['analysis'], requires: ['data'] },
2813
+ * reporter: { produces: ['report'], requires: ['analysis'] },
2814
+ * };
3749
2815
  *
3750
- * // Submit calls they batch automatically
3751
- * const [r1, r2, r3] = await Promise.all([
3752
- * queue.submit(agent, "input 1"),
3753
- * queue.submit(agent, "input 2"),
3754
- * queue.submit(agent, "input 3"),
3755
- * ]);
2816
+ * // Validatecycle detection, missing deps, warnings
2817
+ * const validation = validateGoal(agents);
3756
2818
  *
3757
- * // Force immediate flush
3758
- * await queue.flush();
2819
+ * // Plan dry-run without executing agents
2820
+ * const plan = planGoal(agents, ['query']);
3759
2821
  *
3760
- * // Clean up (flushes remaining calls)
3761
- * await queue.dispose();
2822
+ * // Graph topological order, roots, leaves, edges
2823
+ * const graph = getDependencyGraph(agents);
3762
2824
  * ```
2825
+ *
2826
+ * @module
3763
2827
  */
3764
2828
 
3765
- interface BatchQueueConfig {
3766
- /** Maximum number of calls per batch. @default 20 */
3767
- maxBatchSize?: number;
3768
- /** Maximum time to wait before flushing (ms). @default 5000 */
3769
- maxWaitMs?: number;
3770
- /** Number of calls to run in parallel within a batch. @default 5 */
3771
- concurrency?: number;
2829
+ /** Minimal agent declaration for goal utilities (subset of GoalNode) */
2830
+ interface GoalAgentDeclaration {
2831
+ /** Fact keys this agent writes as output */
2832
+ produces: string[];
2833
+ /** Fact keys this agent reads as input */
2834
+ requires?: string[];
2835
+ }
2836
+ /** Edge in the inferred dependency graph */
2837
+ interface GoalDependencyEdge {
2838
+ from: string;
2839
+ to: string;
2840
+ /** Fact key that creates this dependency */
2841
+ factKey: string;
3772
2842
  }
3773
- interface BatchQueue {
3774
- /** Submit a call to the queue. Returns a promise that resolves when the call completes. */
3775
- submit<T = unknown>(agent: AgentLike, input: string, options?: RunOptions): Promise<RunResult<T>>;
3776
- /** Flush all pending calls immediately. */
3777
- flush(): Promise<void>;
3778
- /** Get the number of pending calls. */
3779
- readonly pending: number;
3780
- /** Dispose the queue, flushing remaining calls. */
3781
- dispose(): Promise<void>;
2843
+ /** Inferred dependency graph from produces/requires analysis */
2844
+ interface GoalDependencyGraph {
2845
+ /** Agent IDs in topological order (roots first) */
2846
+ order: string[];
2847
+ /** Edges between agents */
2848
+ edges: GoalDependencyEdge[];
2849
+ /** Root agents (no unfulfilled requires from other agents) */
2850
+ roots: string[];
2851
+ /** Leaf agents (nothing depends on their produces) */
2852
+ leaves: string[];
2853
+ /** Map of fact key to agent ID that produces it */
2854
+ producers: Map<string, string>;
2855
+ }
2856
+ /** Validation result */
2857
+ interface GoalValidationResult {
2858
+ valid: boolean;
2859
+ errors: string[];
2860
+ warnings: string[];
2861
+ }
2862
+ /** A single step in an execution plan */
2863
+ interface GoalPlanStep {
2864
+ /** Step number (1-based) */
2865
+ step: number;
2866
+ /** Agent IDs that would run in this step (parallel) */
2867
+ agents: string[];
2868
+ /** Fact keys available at the start of this step */
2869
+ availableFacts: string[];
2870
+ /** Fact keys produced after this step completes */
2871
+ producedFacts: string[];
2872
+ }
2873
+ /** Result of a planGoal() dry-run */
2874
+ interface GoalExecutionPlan {
2875
+ /** Ordered steps showing which agents run when */
2876
+ steps: GoalPlanStep[];
2877
+ /** Agents that can never run (requires never satisfiable) */
2878
+ unreachableAgents: string[];
2879
+ /** Required fact keys that no agent produces (must be in initial facts) */
2880
+ externalDeps: string[];
2881
+ /** Whether the plan can potentially reach all agents */
2882
+ feasible: boolean;
3782
2883
  }
3783
2884
  /**
3784
- * Create a batch queue for grouping agent calls.
2885
+ * Get the dependency graph for a set of agent declarations.
2886
+ *
2887
+ * Uses Kahn's algorithm (topological sort) to compute execution order
2888
+ * and detect circular dependencies.
2889
+ *
2890
+ * @throws If agents form a circular dependency or a fact key has multiple producers.
3785
2891
  *
3786
2892
  * @example
3787
2893
  * ```typescript
3788
- * const queue = createBatchQueue(runner, {
3789
- * maxBatchSize: 20,
3790
- * maxWaitMs: 5000,
3791
- * concurrency: 5,
2894
+ * const graph = getDependencyGraph({
2895
+ * fetcher: { produces: ['data'], requires: [] },
2896
+ * analyzer: { produces: ['analysis'], requires: ['data'] },
3792
2897
  * });
3793
2898
  *
3794
- * // Submit multiple calls — they batch automatically
3795
- * const [result1, result2, result3] = await Promise.all([
3796
- * queue.submit(agent, "input 1"),
3797
- * queue.submit(agent, "input 2"),
3798
- * queue.submit(agent, "input 3"),
3799
- * ]);
3800
- *
3801
- * // Clean up
3802
- * await queue.dispose();
2899
+ * console.log(graph.order); // ['fetcher', 'analyzer']
2900
+ * console.log(graph.roots); // ['fetcher']
2901
+ * console.log(graph.leaves); // ['analyzer']
3803
2902
  * ```
3804
2903
  */
3805
- declare function createBatchQueue(runner: AgentRunner, config?: BatchQueueConfig): BatchQueue;
3806
-
2904
+ declare function getDependencyGraph(agents: Record<string, GoalAgentDeclaration>): GoalDependencyGraph;
3807
2905
  /**
3808
- * P4: Constraint-Driven Provider Routing Directive's unique differentiator.
2906
+ * Validate a set of agent declarations for goal execution.
3809
2907
  *
3810
- * Uses user-supplied constraints to select providers based on runtime state:
3811
- * cost, latency, error rates, and compliance regions.
3812
- *
3813
- * Tracks per-provider stats (call count, error count, cost, latency) and
3814
- * exposes them as {@link RoutingFacts} for constraint evaluation.
3815
- *
3816
- * @module
2908
+ * Checks for:
2909
+ * - Circular dependencies
2910
+ * - Duplicate producers (same fact key produced by multiple agents)
2911
+ * - Agents with no `produces` (will never contribute)
2912
+ * - Required fact keys that no agent produces (must be in initial facts)
3817
2913
  *
3818
2914
  * @example
3819
2915
  * ```typescript
3820
- * import { createConstraintRouter } from '@directive-run/ai';
3821
- * import type { ConstraintRouterRunner } from '@directive-run/ai';
3822
- *
3823
- * const router = createConstraintRouter({
3824
- * providers: [
3825
- * { name: "openai", runner: openaiRunner, pricing: { inputPerMillion: 5, outputPerMillion: 15 } },
3826
- * { name: "anthropic", runner: anthropicRunner, pricing: { inputPerMillion: 3, outputPerMillion: 15 } },
3827
- * { name: "ollama", runner: ollamaRunner },
3828
- * ],
3829
- * defaultProvider: "openai",
3830
- * constraints: [
3831
- * { when: (facts) => facts.totalCost > 100, provider: "ollama", priority: 10 },
3832
- * { when: (facts) => facts.providers["openai"]?.errorCount > 5, provider: "anthropic" },
3833
- * ],
3834
- * preferCheapest: true, // opt-in to cheapest-provider heuristic
3835
- * onProviderSelected: (name, reason) => console.log(`Using ${name} (${reason})`),
2916
+ * const result = validateGoal({
2917
+ * fetcher: { produces: ['data'] },
2918
+ * analyzer: { produces: ['analysis'], requires: ['data'] },
3836
2919
  * });
3837
2920
  *
3838
- * // Access runtime stats
3839
- * console.log(router.facts.totalCost, router.facts.callCount);
2921
+ * if (!result.valid) {
2922
+ * console.error(result.errors);
2923
+ * }
3840
2924
  * ```
3841
2925
  */
3842
-
2926
+ declare function validateGoal(agents: Record<string, GoalAgentDeclaration>): GoalValidationResult;
3843
2927
  /**
3844
- * Provider definition for the constraint router.
2928
+ * Dry-run goal execution to preview the plan without running agents.
3845
2929
  *
3846
- * Each provider has its own runner, optional pricing (for cost tracking
3847
- * and cheapest-provider heuristic), and optional region tag.
3848
- */
3849
- interface RoutingProvider {
3850
- /** Unique name for this provider. */
3851
- name: string;
3852
- /** The runner to use for this provider. */
3853
- runner: AgentRunner;
3854
- /** Token pricing (cost per million tokens). */
3855
- pricing?: {
3856
- inputPerMillion: number;
3857
- outputPerMillion: number;
3858
- };
3859
- /** Geographic region (for compliance routing). */
3860
- region?: string;
3861
- }
3862
- /**
3863
- * Runtime facts tracked by the router — exposed for user constraints.
2930
+ * Shows which agents would run in each step, which facts would be produced,
2931
+ * and whether any agents are unreachable.
3864
2932
  *
3865
- * Access via the `facts` property on the returned {@link ConstraintRouterRunner}.
2933
+ * @param agents - Agent declarations with produces/requires
2934
+ * @param initialFactKeys - Fact keys available at the start (not values, just keys)
2935
+ * @param maxSteps - Maximum steps to simulate (default: 50)
2936
+ *
2937
+ * @example
2938
+ * ```typescript
2939
+ * const plan = planGoal(
2940
+ * {
2941
+ * fetcher: { produces: ['data'] },
2942
+ * analyzer: { produces: ['analysis'], requires: ['data'] },
2943
+ * reporter: { produces: ['report'], requires: ['analysis'] },
2944
+ * },
2945
+ * ['query'],
2946
+ * );
2947
+ *
2948
+ * console.log(plan.feasible); // true
2949
+ * console.log(plan.steps); // 3 steps: fetcher → analyzer → reporter
2950
+ * ```
3866
2951
  */
3867
- interface RoutingFacts {
3868
- totalCost: number;
3869
- callCount: number;
3870
- errorCount: number;
3871
- lastProvider: string | null;
3872
- avgLatencyMs: number;
3873
- /** Per-provider stats. */
3874
- providers: Record<string, ProviderStats>;
3875
- }
3876
- interface ProviderStats {
3877
- callCount: number;
3878
- errorCount: number;
3879
- totalCost: number;
3880
- avgLatencyMs: number;
3881
- lastErrorAt: number | null;
3882
- }
3883
- /** User-supplied routing constraint. */
3884
- interface RoutingConstraint {
3885
- /** When this constraint is active. */
3886
- when: (facts: RoutingFacts) => boolean;
3887
- /** The provider to route to. */
3888
- provider: string;
3889
- /** Priority — higher wins when multiple constraints match. @default 0 */
3890
- priority?: number;
3891
- }
3892
- interface ConstraintRouterConfig {
3893
- /** Available providers. */
3894
- providers: RoutingProvider[];
3895
- /** Default provider name. */
3896
- defaultProvider: string;
3897
- /** User-supplied routing constraints. */
3898
- constraints?: RoutingConstraint[];
3899
- /** Called when a provider is selected. */
3900
- onProviderSelected?: (providerName: string, reason: "constraint" | "cheapest" | "default") => void;
3901
- /** Error cooldown — skip a provider for this many ms after an error. @default 30000 */
3902
- errorCooldownMs?: number;
3903
- /**
3904
- * When true, automatically prefer the cheapest available provider
3905
- * (based on pricing) when no user constraint matches.
3906
- * When false, the default provider is used unless a constraint overrides it.
3907
- * @default false
3908
- */
3909
- preferCheapest?: boolean;
2952
+ declare function planGoal(agents: Record<string, GoalAgentDeclaration>, initialFactKeys?: string[], maxSteps?: number): GoalExecutionPlan;
2953
+ /** A single line in a goal execution explanation */
2954
+ interface GoalExplanationStep {
2955
+ step: number;
2956
+ agents: string[];
2957
+ factsProduced: string[];
2958
+ satisfaction: number;
2959
+ satisfactionDelta: number;
2960
+ durationMs: number;
2961
+ tokensConsumed: number;
2962
+ /** Human-readable description of what happened */
2963
+ description: string;
2964
+ }
2965
+ /** Structured explanation of a goal execution */
2966
+ interface GoalExplanation {
2967
+ /** Whether the goal was achieved */
2968
+ achieved: boolean;
2969
+ /** Human-readable summary */
2970
+ summary: string;
2971
+ /** Per-step explanations */
2972
+ steps: GoalExplanationStep[];
2973
+ /** Relaxation events with descriptions */
2974
+ relaxations: Array<{
2975
+ step: number;
2976
+ label: string;
2977
+ strategy: string;
2978
+ description: string;
2979
+ }>;
2980
+ /** Total tokens consumed */
2981
+ totalTokens: number;
2982
+ /** Total duration (ms) */
2983
+ durationMs: number;
3910
2984
  }
3911
2985
  /**
3912
- * Create a constraint-driven provider router.
2986
+ * Generate a human-readable explanation of a goal execution result.
2987
+ *
2988
+ * Takes a `GoalResult` and returns a structured explanation of why each
2989
+ * agent ran, how satisfaction progressed, and what relaxations were applied.
3913
2990
  *
3914
2991
  * @example
3915
2992
  * ```typescript
3916
- * const runner = createConstraintRouter({
3917
- * providers: [
3918
- * { name: "openai", runner: openaiRunner, pricing: { inputPerMillion: 5, outputPerMillion: 15 } },
3919
- * { name: "anthropic", runner: anthropicRunner, pricing: { inputPerMillion: 3, outputPerMillion: 15 } },
3920
- * { name: "ollama", runner: ollamaRunner },
3921
- * ],
3922
- * defaultProvider: "openai",
3923
- * constraints: [
3924
- * { when: (facts) => facts.totalCost > 100, provider: "ollama", priority: 10 },
3925
- * { when: (facts) => facts.providers["openai"]?.errorCount > 5, provider: "anthropic" },
3926
- * ],
3927
- * });
2993
+ * const result = await orchestrator.runGoal(nodes, input, when, options);
2994
+ * const explanation = explainGoal(result);
2995
+ *
2996
+ * console.log(explanation.summary);
2997
+ * // "Goal achieved in 3 steps (1,247 tokens, 892ms). Satisfaction: 0 → 1."
2998
+ *
2999
+ * for (const step of explanation.steps) {
3000
+ * console.log(step.description);
3001
+ * // "Step 1: Ran fetcher. Produced: data. Satisfaction: 0 0.3 (+0.3)."
3002
+ * }
3928
3003
  * ```
3929
3004
  */
3930
- declare function createConstraintRouter(config: ConstraintRouterConfig): ConstraintRouterRunner;
3931
- /** Helper type for accessing router facts. */
3932
- type ConstraintRouterRunner = AgentRunner & {
3933
- readonly facts: RoutingFacts;
3934
- };
3005
+ declare function explainGoal<T = unknown>(result: GoalResult<T>): GoalExplanation;
3935
3006
 
3936
3007
  /**
3937
3008
  * MCP Type Definitions
@@ -4379,273 +3450,472 @@ declare function mcpGetPrompt(server: string, prompt: string, args?: Record<stri
4379
3450
  declare function mcpSyncResources(server?: string, pattern?: string | RegExp): MCPSyncResourcesRequirement;
4380
3451
 
4381
3452
  /**
4382
- * AI Adapter Constraint-driven agent orchestration with guardrails
3453
+ * Evaluation Framework Constraint-driven agent evaluation.
4383
3454
  *
4384
- * Philosophy: "Use Directive WITH any LLM agent framework"
4385
- * - Your framework handles LLM tool execution
4386
- * - Directive adds safety guardrails, approval workflows, state persistence
4387
- *
4388
- * Also available:
4389
- * - `@directive-run/ai/testing` – Mock runners, test orchestrators, assertion helpers
4390
- * - `@directive-run/ai/anthropic` – Anthropic Claude adapter
4391
- * - `@directive-run/ai/openai` – OpenAI / Azure / Together adapter
4392
- * - `@directive-run/ai/ollama` – Local Ollama inference adapter
3455
+ * Define eval criteria as composable functions. Run agents against datasets
3456
+ * and score their outputs across multiple dimensions. Results integrate with
3457
+ * the debug timeline for DevTools visualization.
4393
3458
  *
4394
3459
  * @example
4395
3460
  * ```typescript
4396
- * import { createAgentOrchestrator } from '@directive-run/ai'
4397
- *
4398
- * const orchestrator = createAgentOrchestrator({
4399
- * runner: myAgentRunner,
4400
- * constraints: {
4401
- * needsExpertReview: {
4402
- * when: (facts) => facts.decision.confidence < 0.7,
4403
- * require: { type: 'EXPERT_AGENT', query: facts.userQuery }
4404
- * },
4405
- * budgetLimit: {
4406
- * when: (facts) => facts.tokenUsage > 10000,
4407
- * require: { type: 'PAUSE_AGENTS' }
4408
- * }
3461
+ * const suite = createEvalSuite({
3462
+ * criteria: {
3463
+ * safe: evalSafety({ categories: ["pii"] }),
3464
+ * costEfficient: evalCost({ maxTokensPerRun: 5000 }),
3465
+ * fast: evalLatency({ maxMs: 3000 }),
4409
3466
  * },
4410
- * guardrails: {
4411
- * input: [(data) => validatePII(data.input)],
4412
- * output: [(data) => checkToxicity(data.output)]
4413
- * }
4414
- * })
3467
+ * agents: [researchAgent, writerAgent],
3468
+ * runner: myRunner,
3469
+ * dataset: [
3470
+ * { id: "case-1", input: "What is AI?", expected: "explanation about AI" },
3471
+ * ],
3472
+ * });
3473
+ *
3474
+ * const results = await suite.run();
3475
+ * // results.summary — pass/fail per criterion per agent
3476
+ * // results.details — per-case breakdown
4415
3477
  * ```
3478
+ *
3479
+ * @module
4416
3480
  */
4417
3481
 
4418
- /** Orchestrator options */
4419
- interface OrchestratorOptions<F extends Record<string, unknown>> {
4420
- /** Function to run an agent */
3482
+ /** Single test case in the eval dataset */
3483
+ interface EvalCase {
3484
+ /** Unique identifier for tracking across runs */
3485
+ id?: string;
3486
+ /** Input to feed the agent */
3487
+ input: string;
3488
+ /** Expected output or reference answer (for comparison-based criteria) */
3489
+ expected?: string;
3490
+ /** Reference context for faithfulness evaluation */
3491
+ context?: string;
3492
+ /** Tags for filtering and grouping results */
3493
+ tags?: string[];
3494
+ /** Additional context passed to criteria */
3495
+ metadata?: Record<string, unknown>;
3496
+ }
3497
+ /** Result of evaluating a single criterion on a single case */
3498
+ interface EvalScore {
3499
+ /** Score from 0.0 to 1.0 */
3500
+ score: number;
3501
+ /** Whether this score passes the criterion threshold */
3502
+ passed: boolean;
3503
+ /** Reason for the score */
3504
+ reason?: string;
3505
+ /** Duration of evaluation (ms) */
3506
+ durationMs: number;
3507
+ }
3508
+ /** Context passed to eval criterion functions */
3509
+ interface EvalContext {
3510
+ /** The agent being evaluated */
3511
+ agent: AgentLike;
3512
+ /** The test case */
3513
+ testCase: EvalCase;
3514
+ /** The agent's run result */
3515
+ result: RunResult<unknown>;
3516
+ /** Duration of the agent run (ms) */
3517
+ runDurationMs: number;
3518
+ }
3519
+ /** Eval criterion function — scores an agent's output */
3520
+ type EvalCriterionFn = (context: EvalContext) => EvalScore | Promise<EvalScore>;
3521
+ /** Named eval criterion */
3522
+ interface EvalCriterion {
3523
+ name: string;
3524
+ fn: EvalCriterionFn;
3525
+ /** Score threshold for passing. Default: 0.5 */
3526
+ threshold?: number;
3527
+ /** Weight for aggregation. Default: 1.0 */
3528
+ weight?: number;
3529
+ }
3530
+ /** Per-case detail result */
3531
+ interface EvalCaseResult {
3532
+ /** Test case that was evaluated */
3533
+ testCase: EvalCase;
3534
+ /** Agent that was evaluated */
3535
+ agentName: string;
3536
+ /** Agent run result */
3537
+ runResult: RunResult<unknown>;
3538
+ /** Score per criterion */
3539
+ scores: Record<string, EvalScore>;
3540
+ /** Overall weighted score (0.0-1.0) */
3541
+ overallScore: number;
3542
+ /** Whether all criteria passed */
3543
+ allPassed: boolean;
3544
+ /** Agent run duration (ms) */
3545
+ runDurationMs: number;
3546
+ }
3547
+ /** Per-agent summary */
3548
+ interface EvalAgentSummary {
3549
+ agentName: string;
3550
+ /** Average score per criterion */
3551
+ criterionAverages: Record<string, number>;
3552
+ /** Pass rate per criterion (0.0-1.0) */
3553
+ criterionPassRates: Record<string, number>;
3554
+ /** Overall weighted average score */
3555
+ overallScore: number;
3556
+ /** Overall pass rate */
3557
+ passRate: number;
3558
+ /** Total tokens consumed */
3559
+ totalTokens: number;
3560
+ /** Average latency per run (ms) */
3561
+ avgLatencyMs: number;
3562
+ /** Total cases evaluated */
3563
+ totalCases: number;
3564
+ /** Cases that passed all criteria */
3565
+ passedCases: number;
3566
+ }
3567
+ /** Complete eval suite results */
3568
+ interface EvalResults {
3569
+ /** Summary per agent */
3570
+ summary: Record<string, EvalAgentSummary>;
3571
+ /** Detailed per-case results */
3572
+ details: EvalCaseResult[];
3573
+ /** Total duration (ms) */
3574
+ durationMs: number;
3575
+ /** Total tokens consumed across all agents and cases */
3576
+ totalTokens: number;
3577
+ /** Timestamp when the eval started */
3578
+ startedAt: number;
3579
+ /** Timestamp when the eval completed */
3580
+ completedAt: number;
3581
+ }
3582
+ /** Configuration for createEvalSuite */
3583
+ interface EvalSuiteConfig {
3584
+ /** Named criteria to evaluate */
3585
+ criteria: Record<string, EvalCriterionFn | EvalCriterion>;
3586
+ /** Agents to evaluate */
3587
+ agents: AgentLike[];
3588
+ /** Agent runner function */
4421
3589
  runner: AgentRunner;
4422
- /** Additional facts schema */
4423
- factsSchema?: Record<string, {
4424
- _type: unknown;
4425
- _validators: [];
4426
- }>;
4427
- /** Initialize additional facts */
4428
- init?: (facts: F & OrchestratorState) => void;
4429
- /** Constraints for orchestration */
4430
- constraints?: Record<string, OrchestratorConstraint<F>>;
4431
- /** Resolvers for orchestration */
4432
- resolvers?: Record<string, OrchestratorResolver<F, Requirement>>;
4433
- /** Guardrails */
4434
- guardrails?: GuardrailsConfig;
4435
- /** Callback for approval requests */
4436
- onApprovalRequest?: (request: ApprovalRequest) => void;
4437
- /**
4438
- * Auto-approve tool calls
4439
- * @default true
4440
- */
4441
- autoApproveToolCalls?: boolean;
4442
- /**
4443
- * Maximum token budget across all agent runs.
4444
- *
4445
- * When exceeded, agents are automatically paused with status "paused".
4446
- * Check `facts.agent.tokenUsage` to see current usage.
4447
- *
4448
- * For more sophisticated cost management (per-user budgets, tiered pricing,
4449
- * cost alerts), see the Cost Management section in the documentation.
4450
- *
4451
- * @example
4452
- * ```typescript
4453
- * const orchestrator = createAgentOrchestrator({
4454
- * maxTokenBudget: 10000, // Pause after 10K tokens
4455
- * });
4456
- *
4457
- * // Check if paused due to budget
4458
- * if (orchestrator.facts.agent.status === 'paused') {
4459
- * console.log('Budget exceeded:', orchestrator.facts.agent.tokenUsage);
4460
- * }
4461
- * ```
4462
- */
4463
- maxTokenBudget?: number;
4464
- /** Plugins */
4465
- plugins?: Plugin[];
4466
- /**
4467
- * Enable debugging
4468
- * @default false
4469
- */
4470
- debug?: boolean;
4471
- /**
4472
- * Approval timeout in milliseconds
4473
- * @default 300000 (5 minutes)
4474
- */
4475
- approvalTimeoutMs?: number;
4476
- /** Retry configuration for agent runs (no retries if not specified) */
4477
- agentRetry?: AgentRetryConfig;
4478
- /** Lifecycle hooks for observability */
4479
- hooks?: OrchestratorLifecycleHooks;
4480
- /**
4481
- * Optional memory instance. When provided, context messages are auto-injected
4482
- * into agent instructions before each run, and result messages are auto-stored.
4483
- */
4484
- memory?: AgentMemory;
4485
- /**
4486
- * Optional circuit breaker. Wraps every run() call.
4487
- * When OPEN, throws CircuitBreakerOpenError instead of calling the agent.
4488
- */
4489
- circuitBreaker?: CircuitBreaker;
4490
- }
4491
- /** Streaming run result from orchestrator */
4492
- interface OrchestratorStreamResult<T = unknown> {
4493
- /** Async iterator for streaming chunks */
4494
- stream: AsyncIterable<OrchestratorStreamChunk>;
4495
- /** Promise that resolves to the final result */
4496
- result: Promise<RunResult<T>>;
4497
- /** Abort the stream */
4498
- abort: () => void;
4499
- }
4500
- /** Stream chunk types for orchestrator — extends StreamChunk with approval events */
4501
- type OrchestratorStreamChunk = StreamChunk | {
4502
- type: "approval_required";
4503
- requestId: string;
4504
- toolName: string;
4505
- } | {
4506
- type: "approval_resolved";
4507
- requestId: string;
4508
- approved: boolean;
4509
- };
4510
- /** Per-call options for run() */
4511
- interface RunCallOptions {
4512
- /** Override output guardrails for this call only. Set to [] to skip. */
4513
- outputGuardrails?: Array<GuardrailFn<OutputGuardrailData> | NamedGuardrail<OutputGuardrailData>>;
4514
- /** Override input guardrails for this call only. Set to [] to skip. */
4515
- inputGuardrails?: Array<GuardrailFn<InputGuardrailData> | NamedGuardrail<InputGuardrailData>>;
4516
- /** Signal for abort */
3590
+ /** Dataset of test cases */
3591
+ dataset: EvalCase[];
3592
+ /** Run options passed to the runner */
3593
+ runOptions?: Omit<RunOptions, "signal">;
3594
+ /** Maximum concurrent agent runs. Default: 5 */
3595
+ concurrency?: number;
3596
+ /** Optional debug timeline for recording eval events */
3597
+ timeline?: DebugTimeline;
3598
+ /** Callback fired on each case completion */
3599
+ onCaseComplete?: (result: EvalCaseResult) => void;
3600
+ /** Callback fired on each agent completion */
3601
+ onAgentComplete?: (summary: EvalAgentSummary) => void;
3602
+ /** Abort signal */
4517
3603
  signal?: AbortSignal;
4518
3604
  }
4519
- /** Orchestrator instance */
4520
- interface AgentOrchestrator<F extends Record<string, unknown>> {
4521
- system: System<any>;
4522
- facts: F & OrchestratorState;
4523
- /** Run an agent with guardrails. Pass options to override guardrails per-call. */
4524
- run<T>(agent: AgentLike, input: string, options?: RunCallOptions): Promise<RunResult<T>>;
4525
- /**
4526
- * Run an agent with streaming support.
4527
- * Returns an async iterator for chunks and a promise for the final result.
4528
- *
4529
- * @example
4530
- * ```typescript
4531
- * const { stream, result, abort } = orchestrator.runStream(agent, input);
4532
- *
4533
- * for await (const chunk of stream) {
4534
- * if (chunk.type === 'token') process.stdout.write(chunk.data);
4535
- * if (chunk.type === 'approval_required') showApprovalDialog(chunk);
4536
- * if (chunk.type === 'guardrail_triggered') handleGuardrail(chunk);
4537
- * }
4538
- *
4539
- * const finalResult = await result;
4540
- * ```
4541
- */
4542
- runStream<T>(agent: AgentLike, input: string, options?: {
4543
- signal?: AbortSignal;
4544
- }): OrchestratorStreamResult<T>;
4545
- /** Approve a pending request */
4546
- approve(requestId: string): void;
4547
- /** Reject a pending request */
4548
- reject(requestId: string, reason?: string): void;
4549
- /** Pause all agents */
4550
- pause(): void;
4551
- /** Resume agents */
4552
- resume(): void;
4553
- /** Reset conversation state */
4554
- reset(): void;
4555
- /** Dispose of the orchestrator */
4556
- dispose(): void;
3605
+ /** Eval suite instance */
3606
+ interface EvalSuite {
3607
+ /** Run the full evaluation */
3608
+ run(): Promise<EvalResults>;
3609
+ /** Run evaluation for a specific agent only */
3610
+ runAgent(agentName: string): Promise<EvalAgentSummary>;
3611
+ /** Get the list of agents being evaluated */
3612
+ getAgents(): AgentLike[];
3613
+ /** Get the list of criteria */
3614
+ getCriteria(): string[];
3615
+ /** Get the dataset */
3616
+ getDataset(): EvalCase[];
3617
+ }
3618
+ /** Options for cost evaluation */
3619
+ interface EvalCostOptions {
3620
+ /** Maximum tokens per run */
3621
+ maxTokensPerRun: number;
3622
+ }
3623
+ /**
3624
+ * Evaluate cost efficiency — scores based on token usage relative to a budget.
3625
+ *
3626
+ * Score = 1.0 when tokens <= maxTokensPerRun * 0.5
3627
+ * Score = 0.0 when tokens >= maxTokensPerRun * 2
3628
+ * Linear interpolation between.
3629
+ */
3630
+ declare function evalCost(options: EvalCostOptions): EvalCriterion;
3631
+ /** Options for latency evaluation */
3632
+ interface EvalLatencyOptions {
3633
+ /** Maximum acceptable latency (ms) */
3634
+ maxMs: number;
3635
+ }
3636
+ /**
3637
+ * Evaluate latency — scores based on agent run duration.
3638
+ *
3639
+ * Score = 1.0 when duration <= maxMs * 0.5
3640
+ * Score = 0.0 when duration >= maxMs * 2
3641
+ * Linear interpolation between.
3642
+ */
3643
+ declare function evalLatency(options: EvalLatencyOptions): EvalCriterion;
3644
+ /** Options for output length evaluation */
3645
+ interface EvalOutputLengthOptions {
3646
+ /** Minimum output length (chars) */
3647
+ minLength?: number;
3648
+ /** Maximum output length (chars) */
3649
+ maxLength?: number;
3650
+ }
3651
+ /**
3652
+ * Evaluate output length — ensures output is within an acceptable range.
3653
+ */
3654
+ declare function evalOutputLength(options: EvalOutputLengthOptions): EvalCriterion;
3655
+ /** Options for safety evaluation */
3656
+ interface EvalSafetyOptions {
3657
+ /** Patterns to check for in output (overrides categories) */
3658
+ blockedPatterns?: RegExp[];
3659
+ /** Categories of content to check: "pii", "violence", "self_harm", "illegal" */
3660
+ categories?: Array<"pii" | "violence" | "self_harm" | "illegal">;
3661
+ }
3662
+ /**
3663
+ * Evaluate safety — checks output for blocked patterns or category-based content.
3664
+ *
3665
+ * When `categories` is provided, uses built-in pattern sets for each category.
3666
+ * When `blockedPatterns` is provided, uses those directly (overrides categories).
3667
+ * When neither is provided, defaults to all safety categories.
3668
+ *
3669
+ * Score = 1.0 when no blocked patterns found.
3670
+ * Score = 0.0 when any blocked pattern matches.
3671
+ */
3672
+ declare function evalSafety(options?: EvalSafetyOptions): EvalCriterion;
3673
+ /** Options for output structure evaluation */
3674
+ interface EvalStructureOptions {
3675
+ /** Expected output type */
3676
+ type?: "json" | "string";
3677
+ /** Required keys if type is "json" */
3678
+ requiredKeys?: string[];
3679
+ }
3680
+ /**
3681
+ * Evaluate output structure — checks that output matches an expected format.
3682
+ */
3683
+ declare function evalStructure(options: EvalStructureOptions): EvalCriterion;
3684
+ /**
3685
+ * Evaluate with a custom LLM judge — uses a runner to grade the output.
3686
+ *
3687
+ * The judge agent receives the input, output, and expected answer, and
3688
+ * returns a JSON score.
3689
+ */
3690
+ interface EvalJudgeOptions {
3691
+ /** Runner to use for the judge */
3692
+ runner: AgentRunner;
3693
+ /** Judge agent */
3694
+ judge: AgentLike;
3695
+ /** Custom grading prompt template. {{input}}, {{output}}, {{expected}} are replaced. */
3696
+ promptTemplate?: string;
3697
+ /** Optional abort signal */
3698
+ signal?: AbortSignal;
3699
+ /** Timeout for the judge call in ms. Default: 30_000 */
3700
+ timeoutMs?: number;
3701
+ }
3702
+ declare function evalJudge(options: EvalJudgeOptions): EvalCriterion;
3703
+ /**
3704
+ * Evaluate exact or substring match against expected output.
3705
+ */
3706
+ interface EvalMatchOptions {
3707
+ /** Match mode. Default: "contains" */
3708
+ mode?: "exact" | "contains" | "regex";
3709
+ /** Case-insensitive matching. Default: true */
3710
+ caseInsensitive?: boolean;
3711
+ }
3712
+ declare function evalMatch(options?: EvalMatchOptions): EvalCriterion;
3713
+ /** Options for LLM-based semantic evaluation criteria */
3714
+ interface EvalSemanticOptions {
3715
+ /** Runner to use for the judge LLM */
3716
+ runner: AgentRunner;
3717
+ /** Judge agent (model to use for evaluation) */
3718
+ judge: AgentLike;
3719
+ /** Optional abort signal */
3720
+ signal?: AbortSignal;
3721
+ /** Timeout for the judge call in ms. Default: 30_000 */
3722
+ timeoutMs?: number;
3723
+ }
3724
+ /**
3725
+ * Evaluate faithfulness — whether the output is grounded in the provided context.
3726
+ *
3727
+ * Requires `context` field on the EvalCase. Uses an LLM judge internally
3728
+ * to extract and verify claims against the reference context.
3729
+ */
3730
+ declare function evalFaithfulness(options: EvalSemanticOptions): EvalCriterion;
3731
+ /**
3732
+ * Evaluate relevance — whether the output directly addresses the input question.
3733
+ *
3734
+ * Uses an LLM judge to assess how well the agent's output answers
3735
+ * the original question.
3736
+ */
3737
+ declare function evalRelevance(options: EvalSemanticOptions): EvalCriterion;
3738
+ /**
3739
+ * Evaluate coherence — whether the output is logically consistent and well-structured.
3740
+ *
3741
+ * Uses an LLM judge to assess the internal coherence, logical flow,
3742
+ * and consistency of the output.
3743
+ */
3744
+ declare function evalCoherence(options: EvalSemanticOptions): EvalCriterion;
3745
+ /**
3746
+ * Create an evaluation suite for testing agents against a dataset.
3747
+ *
3748
+ * @example
3749
+ * ```typescript
3750
+ * const suite = createEvalSuite({
3751
+ * criteria: {
3752
+ * fast: evalLatency({ maxMs: 3000 }),
3753
+ * cheap: evalCost({ maxTokensPerRun: 5000 }),
3754
+ * },
3755
+ * agents: [researchAgent, writerAgent],
3756
+ * runner: myRunner,
3757
+ * dataset: [{ input: "What is AI?" }],
3758
+ * });
3759
+ *
3760
+ * const results = await suite.run();
3761
+ * ```
3762
+ */
3763
+ declare function createEvalSuite(config: EvalSuiteConfig): EvalSuite;
3764
+ /** Options for eval assertions in CI */
3765
+ interface EvalAssertOptions {
3766
+ /** Minimum weighted overall score required (0.0-1.0) */
3767
+ minScore?: number;
3768
+ /** Minimum pass rate required (0.0-1.0) */
3769
+ minPassRate?: number;
3770
+ /** Criteria that must achieve 100% pass rate */
3771
+ failOn?: string[];
4557
3772
  }
4558
3773
  /**
4559
- * Create an orchestrator for OpenAI agents with Directive constraints.
3774
+ * Assert eval results meet requirements designed for CI pipelines.
3775
+ *
3776
+ * Throws an error with details if any assertion fails.
3777
+ *
3778
+ * @example
3779
+ * ```typescript
3780
+ * const results = await suite.run();
3781
+ * evalAssert(results, {
3782
+ * minScore: 0.8,
3783
+ * minPassRate: 0.9,
3784
+ * failOn: ["safety"],
3785
+ * });
3786
+ * ```
3787
+ */
3788
+ declare function evalAssert(results: EvalResults, options: EvalAssertOptions): void;
3789
+
3790
+ /**
3791
+ * OpenTelemetry Integration — AI-specific observability spans.
3792
+ *
3793
+ * Auto-instruments agent orchestrators with OpenTelemetry spans for
3794
+ * agent runs, guardrail checks, constraint evaluations, and DAG execution.
3795
+ * Works with any OTEL-compatible collector (Jaeger, Zipkin, Honeycomb, etc.).
3796
+ *
3797
+ * Uses OpenTelemetry GenAI semantic conventions (`gen_ai.*`) for
3798
+ * AI-specific attributes alongside Directive-specific attributes.
4560
3799
  *
4561
3800
  * @example
4562
3801
  * ```typescript
4563
- * import { run as runner } from '@openai/agents'
3802
+ * import { createOtelPlugin } from "@directive-run/ai";
4564
3803
  *
4565
3804
  * const orchestrator = createAgentOrchestrator({
4566
3805
  * runner,
4567
- * constraints: {
4568
- * escalateToExpert: {
4569
- * when: (facts) => facts.agent.output?.confidence < 0.7,
4570
- * require: (facts) => ({
4571
- * type: 'RUN_EXPERT_AGENT',
4572
- * query: facts.agent.input,
4573
- * }),
4574
- * },
4575
- * budgetExceeded: {
4576
- * when: (facts) => facts.agent.tokenUsage > 10000,
4577
- * require: { type: 'PAUSE_AGENTS' },
4578
- * },
4579
- * },
4580
- * guardrails: {
4581
- * input: [
4582
- * async (data) => {
4583
- * const hasPII = await detectPII(data.input);
4584
- * return { passed: !hasPII, reason: hasPII ? 'Contains PII' : undefined };
4585
- * },
4586
- * ],
4587
- * output: [
4588
- * async (data) => {
4589
- * const isToxic = await checkToxicity(data.output);
4590
- * return { passed: !isToxic, reason: isToxic ? 'Toxic content' : undefined };
4591
- * },
4592
- * ],
4593
- * },
3806
+ * plugins: [createOtelPlugin({ serviceName: "my-ai-app" })],
4594
3807
  * });
4595
- *
4596
- * // Run with guardrails and constraint-driven orchestration
4597
- * const result = await orchestrator.run(myAgent, 'Hello, can you help me?');
3808
+ * // Every run() creates spans with: agent name, model, tokens, cost, duration
4598
3809
  * ```
4599
3810
  *
4600
- * @throws {Error} If autoApproveToolCalls is false but no onApprovalRequest callback is provided
3811
+ * @module
4601
3812
  */
4602
- declare function createAgentOrchestrator<F extends Record<string, unknown> = Record<string, never>>(options: OrchestratorOptions<F>): AgentOrchestrator<F>;
4603
- /** Builder for type-safe orchestrator configuration */
4604
- interface OrchestratorBuilder<F extends Record<string, unknown>> {
4605
- /** Add a constraint */
4606
- withConstraint<K extends string>(id: K, constraint: OrchestratorConstraint<F>): OrchestratorBuilder<F>;
4607
- /** Add a resolver */
4608
- withResolver<R extends Requirement>(id: string, resolver: OrchestratorResolver<F, R>): OrchestratorBuilder<F>;
4609
- /** Add an input guardrail */
4610
- withInputGuardrail(nameOrGuardrail: string | NamedGuardrail<InputGuardrailData>, fn?: GuardrailFn<InputGuardrailData>): OrchestratorBuilder<F>;
4611
- /** Add an output guardrail */
4612
- withOutputGuardrail(nameOrGuardrail: string | NamedGuardrail<OutputGuardrailData>, fn?: GuardrailFn<OutputGuardrailData>): OrchestratorBuilder<F>;
4613
- /** Add a tool call guardrail */
4614
- withToolCallGuardrail(nameOrGuardrail: string | NamedGuardrail<ToolCallGuardrailData>, fn?: GuardrailFn<ToolCallGuardrailData>): OrchestratorBuilder<F>;
4615
- /** Add a plugin */
4616
- withPlugin(plugin: Plugin): OrchestratorBuilder<F>;
4617
- /** Set memory instance for auto context injection and message storage */
4618
- withMemory(memory: AgentMemory): OrchestratorBuilder<F>;
4619
- /** Set circuit breaker to wrap all run() calls */
4620
- withCircuitBreaker(cb: CircuitBreaker): OrchestratorBuilder<F>;
4621
- /** Set max token budget */
4622
- withBudget(maxTokens: number): OrchestratorBuilder<F>;
4623
- /** Enable debug mode */
4624
- withDebug(enabled?: boolean): OrchestratorBuilder<F>;
4625
- /** Build the orchestrator */
4626
- build(options: {
4627
- runner: AgentRunner;
4628
- autoApproveToolCalls?: boolean;
4629
- onApprovalRequest?: (request: ApprovalRequest) => void;
4630
- }): AgentOrchestrator<F>;
3813
+
3814
+ /** Minimal span interface compatible with OpenTelemetry API */
3815
+ interface OtelSpan {
3816
+ /** Set an attribute on the span */
3817
+ setAttribute(key: string, value: string | number | boolean): void;
3818
+ /** Add an event to the span */
3819
+ addEvent(name: string, attributes?: Record<string, string | number | boolean>): void;
3820
+ /** Set the span status */
3821
+ setStatus(status: {
3822
+ code: number;
3823
+ message?: string;
3824
+ }): void;
3825
+ /** End the span */
3826
+ end(): void;
3827
+ }
3828
+ /** OTEL status codes as a const object (no enum overhead) */
3829
+ declare const OtelStatusCode: {
3830
+ readonly UNSET: 0;
3831
+ readonly OK: 1;
3832
+ readonly ERROR: 2;
3833
+ };
3834
+ type OtelStatusCode = (typeof OtelStatusCode)[keyof typeof OtelStatusCode];
3835
+ /** Tracer interface compatible with OpenTelemetry API */
3836
+ interface OtelTracer {
3837
+ /** Start a new span */
3838
+ startSpan(name: string, options?: {
3839
+ attributes?: Record<string, string | number | boolean>;
3840
+ }): OtelSpan;
3841
+ }
3842
+ /** Configuration for the OTEL plugin */
3843
+ interface OtelPluginConfig {
3844
+ /** Service name for span attribution */
3845
+ serviceName: string;
3846
+ /** Custom tracer instance. If not provided, uses a no-op tracer for standalone span collection. */
3847
+ tracer?: OtelTracer;
3848
+ /** Span prefix. Default: "directive.ai" */
3849
+ spanPrefix?: string;
3850
+ /** Span processor callback — called for every completed span. Useful for custom exporters. */
3851
+ onSpanEnd?: (spanData: SpanData) => void;
3852
+ /** Event types to instrument. Default: all */
3853
+ instrumentEvents?: Set<string>;
3854
+ /** TTL for active spans in ms. Spans older than this are cleaned up. Default: 300000 (5 min) */
3855
+ spanTtlMs?: number;
3856
+ }
3857
+ /** Serializable span data for export */
3858
+ interface SpanData {
3859
+ name: string;
3860
+ traceId: string;
3861
+ spanId: string;
3862
+ parentSpanId?: string;
3863
+ attributes: Record<string, string | number | boolean>;
3864
+ events: Array<{
3865
+ name: string;
3866
+ attributes?: Record<string, string | number | boolean>;
3867
+ timestamp: number;
3868
+ }>;
3869
+ status: {
3870
+ code: OtelStatusCode;
3871
+ message?: string;
3872
+ };
3873
+ startTime: number;
3874
+ endTime: number;
3875
+ durationMs: number;
3876
+ }
3877
+ /** OTEL Plugin instance */
3878
+ interface OtelPlugin {
3879
+ /** Attach to a debug timeline to auto-instrument */
3880
+ attach(timeline: DebugTimeline): () => void;
3881
+ /** Get all collected spans (when using built-in collector) */
3882
+ getSpans(): SpanData[];
3883
+ /** Clear collected spans */
3884
+ clearSpans(): void;
3885
+ /** Get the underlying tracer */
3886
+ getTracer(): OtelTracer;
3887
+ /** Get count of currently active (in-flight) spans */
3888
+ getActiveSpanCount(): number;
4631
3889
  }
4632
3890
  /**
4633
- * Create a type-safe orchestrator builder.
3891
+ * Create an OpenTelemetry plugin for AI observability.
3892
+ *
3893
+ * Subscribes to a DebugTimeline and creates spans for agent runs,
3894
+ * guardrail checks, constraint evaluations, resolver executions,
3895
+ * and execution patterns (DAG, parallel, sequential, etc.).
3896
+ *
3897
+ * Parent-child relationships:
3898
+ * - Pattern spans are roots
3899
+ * - Agent spans are children of the active pattern span (if any)
3900
+ * - Guardrail/resolver spans within an agent run are children of the agent span
3901
+ * - Constraint evaluations within an agent run are recorded as span events
4634
3902
  *
4635
3903
  * @example
4636
3904
  * ```typescript
4637
- * const orchestrator = createOrchestratorBuilder<MyFacts>()
4638
- * .withConstraint('budget', {
4639
- * when: (facts) => facts.cost > 100,
4640
- * require: { type: 'PAUSE' },
4641
- * })
4642
- * .withInputGuardrail('pii', createPIIGuardrail())
4643
- * .withOutputGuardrail('toxicity', createModerationGuardrail({ ... }))
4644
- * .withBudget(10000)
4645
- * .withDebug()
4646
- * .build({ runner });
3905
+ * // With built-in span collection:
3906
+ * const otel = createOtelPlugin({ serviceName: "my-app" });
3907
+ * const unsub = otel.attach(orchestrator.timeline);
3908
+ * await orchestrator.run(agent, input);
3909
+ * console.log(otel.getSpans()); // All spans from the run
3910
+ *
3911
+ * // With custom OTEL tracer:
3912
+ * import { trace } from "@opentelemetry/api";
3913
+ * const otel = createOtelPlugin({
3914
+ * serviceName: "my-app",
3915
+ * tracer: trace.getTracer("directive-ai"),
3916
+ * });
4647
3917
  * ```
4648
3918
  */
4649
- declare function createOrchestratorBuilder<F extends Record<string, unknown> = Record<string, never>>(): OrchestratorBuilder<F>;
3919
+ declare function createOtelPlugin(config: OtelPluginConfig): OtelPlugin;
4650
3920
 
4651
- export { type ANNIndex, type ANNSearchResult, AdapterHooks, type AgentInfo, AgentLike, type AgentMemory, type AgentMemoryConfig, type AgentMessage, type AgentMessageType, type AgentNetwork, type AgentNetworkConfig, type AgentOrchestrator, type AgentRegistration, type AgentRegistry, AgentRetryConfig, type AgentRunState, AgentRunner, type AgentSelectionConstraint, type AgentStack, type AgentStackConfig, type AgentStackState, AgentState, AllProvidersFailedError, ApprovalRequest, ApprovalState, type AuditInstance, type AuditPluginConfig, type BackpressureStrategy, type BatchQueue, type BatchQueueConfig, type BatchedEmbedder, type BidirectionalStream, type BudgetConfig, type BudgetExceededDetails, BudgetExceededError, type BudgetRunner, type BudgetWindow, type CacheEntry, type CacheLookupResult, type CacheStats, type ComplianceConfig, type ComplianceInstance, type ComplianceStorage, type ConstraintBuilder, type ConstraintRouterConfig, type ConstraintRouterRunner, type CreateRunnerOptions, DEFAULT_INJECTION_PATTERNS, type DelegationMessage, type DelegationResultMessage, type DoneChunk, type EmbedderFn, type Embedding, type EnhancedPIIGuardrailOptions, type ErrorChunk, type ExecutionPattern, type FallbackConfig, GuardrailFn, type GuardrailTriggeredChunk, GuardrailsConfig, type HandoffRequest, type HandoffResult, type InformMessage, InputGuardrailData, type JSONFileStoreOptions, type MCPAdapter, type MCPAdapterConfig, type MCPApprovalRequest, type MCPCallToolRequirement, type MCPGetPromptRequirement, type MCPReadResourceRequirement, type MCPRequirement, type MCPResource, type MCPServerConfig, type MCPSyncResourcesRequirement, type MCPTool, type MCPToolConstraint, type MCPToolResult, type MemoryManageResult, type MemoryState, type MemoryStrategy, type MemoryStrategyConfig, type MemoryStrategyResult, Message$1 as Message, type MessageBus, type MessageBusConfig, type MessageChunk, type MessageFilter, type MessageHandler, type MessageSummarizer, type ModelRule, type ModelSelectionConfig, type MultiAgentOrchestrator, type MultiAgentOrchestratorOptions, type MultiAgentState, NamedGuardrail, type OrchestratorBuilder, OrchestratorConstraint, OrchestratorLifecycleHooks, type OrchestratorOptions, OrchestratorResolver, OrchestratorState, type OrchestratorStreamChunk, type OrchestratorStreamResult, OutputGuardrailData, type ParallelPattern, type ParsedResponse, type ProgressChunk, type PromptInjectionGuardrailOptions, type ProviderStats, type QueryMessage, type RAGChunk, type RAGEnrichOptions, type RAGEnricher, type RAGEnricherConfig, type RAGStorage, type RateLimitGuardrail, type RequestMessage, type ResponseMessage, type RetryConfig, RetryExhaustedError, type RoutingConstraint, type RoutingFacts, type RoutingProvider, type RunAgentRequirement, type RunCallOptions, RunOptions, RunResult, type SSEEvent, type SSETransport, type SSETransportConfig, STRICT_INJECTION_PATTERNS, type SafeParseResult, type SafeParseable, SchemaValidator, type SemanticCache, type SemanticCacheConfig, type SemanticCacheStorage, Semaphore, type SequentialPattern, type StackRunOptions, type StackStreamOptions, type StreamChannel, type StreamChannelConfig, type StreamChannelState, type StreamChunk, type StreamRunOptions, type StreamRunner, type StreamingCallbackRunner, type StreamingGuardrail, type StreamingGuardrailResult, type StreamingRunResult, type StructuredOutputConfig, StructuredOutputError, type StructuredRunOptions, type Subscription, type SupervisorPattern, type TokenChunk, type TokenPricing, type TokenStream, ToolCallGuardrailData, type ToolEndChunk, type ToolStartChunk, type TypedAgentMessage, type UpdateMessage, type VPTreeIndexConfig, type WhenWithRequire, adaptOutputGuardrail, aggregateTokens, byAgentName, byInputLength, byPattern, collectOutputs, collectTokens, combineStreamingGuardrails, concatResults, constraint, convertToolsForLLM, createAISyncer, createAgentAuditHandlers, createAgentMemory, createAgentNetwork, createAgentOrchestrator, createAgentStack, createAuditTrail, createBatchQueue, createBatchedEmbedder, createBidirectionalStream, createBruteForceIndex, createCompliance, createConstraintRouter, createContentFilterGuardrail, createDelegator, createEnhancedPIIGuardrail, createHybridStrategy, createInMemoryComplianceStorage, createInMemoryStorage, createJSONFileStore, createKeyPointsSummarizer, createLLMSummarizer, createLengthGuardrail, createLengthStreamingGuardrail, createMCPAdapter, createMessageBus, createModerationGuardrail, createMultiAgentOrchestrator, createOrchestratorBuilder, createOutputPIIGuardrail, createOutputSchemaGuardrail, createOutputTypeGuardrail, createPIIGuardrail, createPatternStreamingGuardrail, createPromptInjectionGuardrail, createPubSub, createRAGEnricher, createRateLimitGuardrail, createResponder, createRunner, createSSETransport, createSemanticCache, createSemanticCacheGuardrail, createSlidingWindowStrategy, createStreamChannel, createStreamingRunner, createTestEmbedder, createTokenBasedStrategy, createToolGuardrail, createToxicityStreamingGuardrail, createTruncationSummarizer, createUntrustedContentGuardrail, createVPTreeIndex, detectPII, detectPromptInjection, estimateCost, extractJsonFromOutput, filterStream, hasPendingApprovals, isAgentRunning, mapStream, markUntrustedContent, mcpCallTool, mcpGetPrompt, mcpReadResource, mcpSyncResources, mergeStreams, parallel, parseHttpStatus, parseRetryAfter, pickBestResult, pipeThrough, redactPII, runAgentRequirement, sanitizeInjection, selectAgent, sequential, supervisor, tapStream, validateBaseURL, when, withBudget, withFallback, withModelSelection, withRetry, withStructuredOutput };
3921
+ export { type ANNIndex, type ANNSearchResult, AdapterHooks, AgentHealthMetrics, type AgentInfo, AgentLike, type AgentMessage, type AgentMessageType, type AgentNetwork, type AgentNetworkConfig, AgentRunner, AgentState, AllProvidersFailedError, ApprovalState, type AuditEventType, type AuditInstance, type AuditPluginConfig, type BatchQueue, type BatchQueueConfig, type BidirectionalStream, type BudgetConfig, type BudgetExceededDetails, BudgetExceededError, type BudgetRunner, type BudgetWindow, type ComplianceConfig, type ComplianceInstance, type ComplianceStorage, type ConnectDevToolsOptions, type ConstraintRouterConfig, type ConstraintRouterRunner, type CreateRunnerOptions, DEFAULT_INJECTION_PATTERNS, DebugEvent, DebugTimeline, type DelegationMessage, type DelegationResultMessage, type DevToolsClient, type DevToolsClientMessage, type DevToolsCompatibleOrchestrator, type DevToolsServer, type DevToolsServerConfig, type DevToolsServerMessage, type DevToolsSnapshot, type DevToolsTransport, EmbedderFn, Embedding, type EnhancedPIIGuardrailOptions, type EvalAgentSummary, type EvalAssertOptions, type EvalCase, type EvalCaseResult, type EvalContext, type EvalCostOptions, type EvalCriterion, type EvalCriterionFn, type EvalJudgeOptions, type EvalLatencyOptions, type EvalMatchOptions, type EvalOutputLengthOptions, type EvalResults, type EvalSafetyOptions, type EvalScore, type EvalSemanticOptions, type EvalStructureOptions, type EvalSuite, type EvalSuiteConfig, ExecutionPattern, type FallbackConfig, type GoalAgentDeclaration, type GoalDependencyEdge, type GoalDependencyGraph, type GoalExecutionPlan, type GoalExplanation, type GoalExplanationStep, type GoalPlanStep, GoalResult, type GoalValidationResult, GuardrailFn, HealthMonitor, type InformMessage, InputGuardrailData, type JSONFileStoreOptions, type MCPAdapter, type MCPAdapterConfig, type MCPApprovalRequest, type MCPCallToolRequirement, type MCPGetPromptRequirement, type MCPReadResourceRequirement, type MCPRequirement, type MCPResource, type MCPServerConfig, type MCPSyncResourcesRequirement, type MCPTool, type MCPToolConstraint, type MCPToolResult, type MermaidDirection, type MermaidNodeShapes, type MermaidOptions, Message, type MessageBus, type MessageBusConfig, type MessageFilter, type MessageHandler, type ModelRule, type ModelSelectionConfig, type OtelPlugin, type OtelPluginConfig, type OtelSpan, OtelStatusCode, type OtelTracer, OutputGuardrailData, type ParsedResponse, type PromptInjectionGuardrailOptions, type ProviderStats, type QueryMessage, type RAGChunk, type RAGEnrichOptions, type RAGEnricher, type RAGEnricherConfig, type RAGStorage, type RateLimitGuardrail, type RequestMessage, type ResponseMessage, type RetryConfig, RetryExhaustedError, type RoutingConstraint, type RoutingFacts, type RoutingProvider, RunOptions, RunResult, type RunnerMiddleware, type SSEEvent, type SSETransport, type SSETransportConfig, STRICT_INJECTION_PATTERNS, SchemaValidator, SerializedPattern, type SpanData, type StreamChannel, type StreamChannelConfig, type StreamChannelState, type Subscription, type TokenPricing, ToolCallGuardrailData, type TypedAgentMessage, type UpdateMessage, type VPTreeIndexConfig, type WsTransportConfig, byAgentName, byInputLength, byPattern, connectDevTools, convertToolsForLLM, createAgentAuditHandlers, createAgentNetwork, createAuditTrail, createBatchQueue, createBidirectionalStream, createBruteForceIndex, createCompliance, createConstraintRouter, createContentFilterGuardrail, createDelegator, createDevToolsServer, createEnhancedPIIGuardrail, createEvalSuite, createInMemoryComplianceStorage, createJSONFileStore, createLengthGuardrail, createMCPAdapter, createMessageBus, createModerationGuardrail, createOtelPlugin, createOutputPIIGuardrail, createOutputSchemaGuardrail, createOutputTypeGuardrail, createPIIGuardrail, createPromptInjectionGuardrail, createPubSub, createRAGEnricher, createRateLimitGuardrail, createResponder, createRunner, createSSETransport, createStreamChannel, createToolGuardrail, createUntrustedContentGuardrail, createVPTreeIndex, createWsTransport, detectPII, detectPromptInjection, estimateCost, evalAssert, evalCoherence, evalCost, evalFaithfulness, evalJudge, evalLatency, evalMatch, evalOutputLength, evalRelevance, evalSafety, evalStructure, explainGoal, getDependencyGraph, hasPendingApprovals, isAgentRunning, markUntrustedContent, mcpCallTool, mcpGetPrompt, mcpReadResource, mcpSyncResources, mergeStreams, parseHttpStatus, parseRetryAfter, patternToMermaid, pipe, pipeThrough, planGoal, redactPII, sanitizeInjection, validateBaseURL, validateGoal, withBudget, withFallback, withModelSelection, withRetry };