@directive-run/ai 0.1.1
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.
- package/LICENSE +21 -0
- package/README.md +146 -0
- package/dist/anthropic.cjs +3 -0
- package/dist/anthropic.cjs.map +1 -0
- package/dist/anthropic.d.cts +103 -0
- package/dist/anthropic.d.ts +103 -0
- package/dist/anthropic.js +3 -0
- package/dist/anthropic.js.map +1 -0
- package/dist/index.cjs +78 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +4663 -0
- package/dist/index.d.ts +4663 -0
- package/dist/index.js +78 -0
- package/dist/index.js.map +1 -0
- package/dist/ollama.cjs +3 -0
- package/dist/ollama.cjs.map +1 -0
- package/dist/ollama.d.cts +47 -0
- package/dist/ollama.d.ts +47 -0
- package/dist/ollama.js +3 -0
- package/dist/ollama.js.map +1 -0
- package/dist/openai.cjs +3 -0
- package/dist/openai.cjs.map +1 -0
- package/dist/openai.d.cts +127 -0
- package/dist/openai.d.ts +127 -0
- package/dist/openai.js +3 -0
- package/dist/openai.js.map +1 -0
- package/dist/testing.cjs +14 -0
- package/dist/testing.cjs.map +1 -0
- package/dist/testing.d.cts +345 -0
- package/dist/testing.d.ts +345 -0
- package/dist/testing.js +14 -0
- package/dist/testing.js.map +1 -0
- package/dist/types-BKCdgKC-.d.cts +300 -0
- package/dist/types-BKCdgKC-.d.ts +300 -0
- package/package.json +83 -0
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import { Requirement } from '@directive-run/core';
|
|
2
|
+
|
|
3
|
+
/** Simplified Agent interface */
|
|
4
|
+
interface AgentLike {
|
|
5
|
+
name: string;
|
|
6
|
+
instructions?: string;
|
|
7
|
+
model?: string;
|
|
8
|
+
tools?: unknown[];
|
|
9
|
+
}
|
|
10
|
+
/** Agent run result */
|
|
11
|
+
interface RunResult<T = unknown> {
|
|
12
|
+
output: T;
|
|
13
|
+
messages: Message[];
|
|
14
|
+
toolCalls: ToolCall[];
|
|
15
|
+
totalTokens: number;
|
|
16
|
+
/** Breakdown of input vs output tokens, when available from the provider */
|
|
17
|
+
tokenUsage?: TokenUsage;
|
|
18
|
+
/** True when result was served from semantic cache */
|
|
19
|
+
isCached?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** Breakdown of token usage by input/output */
|
|
22
|
+
interface TokenUsage {
|
|
23
|
+
inputTokens: number;
|
|
24
|
+
outputTokens: number;
|
|
25
|
+
}
|
|
26
|
+
/** Message from agent run */
|
|
27
|
+
interface Message {
|
|
28
|
+
role: "user" | "assistant" | "tool" | "system";
|
|
29
|
+
content: string;
|
|
30
|
+
toolCallId?: string;
|
|
31
|
+
}
|
|
32
|
+
/** Tool call record */
|
|
33
|
+
interface ToolCall {
|
|
34
|
+
id: string;
|
|
35
|
+
name: string;
|
|
36
|
+
arguments: string;
|
|
37
|
+
result?: string;
|
|
38
|
+
}
|
|
39
|
+
/** Run function type */
|
|
40
|
+
type AgentRunner = <T = unknown>(agent: AgentLike, input: string, options?: RunOptions) => Promise<RunResult<T>>;
|
|
41
|
+
/** Run options */
|
|
42
|
+
interface RunOptions {
|
|
43
|
+
maxTurns?: number;
|
|
44
|
+
signal?: AbortSignal;
|
|
45
|
+
onMessage?: (message: Message) => void;
|
|
46
|
+
onToolCall?: (toolCall: ToolCall) => void;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Lifecycle hooks for adapter-level observability.
|
|
50
|
+
*
|
|
51
|
+
* Attach to any adapter (runner or streaming runner) to trace, log,
|
|
52
|
+
* or measure individual LLM calls without modifying application code.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* const runner = createOpenAIRunner({
|
|
57
|
+
* apiKey: process.env.OPENAI_API_KEY!,
|
|
58
|
+
* hooks: {
|
|
59
|
+
* onBeforeCall: ({ agent, input }) => console.log(`→ ${agent.name}`, input.slice(0, 50)),
|
|
60
|
+
* onAfterCall: ({ durationMs, tokenUsage }) => {
|
|
61
|
+
* metrics.track('llm_call', { durationMs, ...tokenUsage });
|
|
62
|
+
* },
|
|
63
|
+
* onError: ({ error }) => Sentry.captureException(error),
|
|
64
|
+
* },
|
|
65
|
+
* });
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
interface AdapterHooks {
|
|
69
|
+
/** Fires before each LLM API call. */
|
|
70
|
+
onBeforeCall?: (event: {
|
|
71
|
+
agent: AgentLike;
|
|
72
|
+
input: string;
|
|
73
|
+
timestamp: number;
|
|
74
|
+
}) => void;
|
|
75
|
+
/** Fires after a successful LLM API call. */
|
|
76
|
+
onAfterCall?: (event: {
|
|
77
|
+
agent: AgentLike;
|
|
78
|
+
input: string;
|
|
79
|
+
output: string;
|
|
80
|
+
totalTokens: number;
|
|
81
|
+
tokenUsage: TokenUsage;
|
|
82
|
+
durationMs: number;
|
|
83
|
+
timestamp: number;
|
|
84
|
+
}) => void;
|
|
85
|
+
/** Fires when an LLM API call fails. */
|
|
86
|
+
onError?: (event: {
|
|
87
|
+
agent: AgentLike;
|
|
88
|
+
input: string;
|
|
89
|
+
error: Error;
|
|
90
|
+
durationMs: number;
|
|
91
|
+
timestamp: number;
|
|
92
|
+
}) => void;
|
|
93
|
+
}
|
|
94
|
+
/** Guardrail function */
|
|
95
|
+
type GuardrailFn<T = unknown> = (data: T, context: GuardrailContext) => GuardrailResult | Promise<GuardrailResult>;
|
|
96
|
+
/** Guardrail context */
|
|
97
|
+
interface GuardrailContext {
|
|
98
|
+
agentName: string;
|
|
99
|
+
input: string;
|
|
100
|
+
facts: Record<string, unknown>;
|
|
101
|
+
}
|
|
102
|
+
/** Guardrail result */
|
|
103
|
+
interface GuardrailResult {
|
|
104
|
+
passed: boolean;
|
|
105
|
+
reason?: string;
|
|
106
|
+
transformed?: unknown;
|
|
107
|
+
}
|
|
108
|
+
/** Input guardrail data */
|
|
109
|
+
interface InputGuardrailData {
|
|
110
|
+
input: string;
|
|
111
|
+
agentName: string;
|
|
112
|
+
}
|
|
113
|
+
/** Output guardrail data */
|
|
114
|
+
interface OutputGuardrailData {
|
|
115
|
+
output: unknown;
|
|
116
|
+
agentName: string;
|
|
117
|
+
input: string;
|
|
118
|
+
messages: Message[];
|
|
119
|
+
}
|
|
120
|
+
/** Tool call guardrail data */
|
|
121
|
+
interface ToolCallGuardrailData {
|
|
122
|
+
toolCall: ToolCall;
|
|
123
|
+
agentName: string;
|
|
124
|
+
input: string;
|
|
125
|
+
}
|
|
126
|
+
/** Retry configuration for guardrails */
|
|
127
|
+
interface GuardrailRetryConfig {
|
|
128
|
+
/** @default 1 */
|
|
129
|
+
attempts?: number;
|
|
130
|
+
/** @default "exponential" */
|
|
131
|
+
backoff?: "exponential" | "linear" | "fixed";
|
|
132
|
+
/** @default 100 */
|
|
133
|
+
baseDelayMs?: number;
|
|
134
|
+
/** @default 5000 */
|
|
135
|
+
maxDelayMs?: number;
|
|
136
|
+
}
|
|
137
|
+
/** Named guardrail for better debugging */
|
|
138
|
+
interface NamedGuardrail<T = unknown> {
|
|
139
|
+
name: string;
|
|
140
|
+
fn: GuardrailFn<T>;
|
|
141
|
+
/** @default true */
|
|
142
|
+
critical?: boolean;
|
|
143
|
+
retry?: GuardrailRetryConfig;
|
|
144
|
+
}
|
|
145
|
+
/** Guardrails configuration */
|
|
146
|
+
interface GuardrailsConfig {
|
|
147
|
+
input?: Array<GuardrailFn<InputGuardrailData> | NamedGuardrail<InputGuardrailData>>;
|
|
148
|
+
output?: Array<GuardrailFn<OutputGuardrailData> | NamedGuardrail<OutputGuardrailData>>;
|
|
149
|
+
toolCall?: Array<GuardrailFn<ToolCallGuardrailData> | NamedGuardrail<ToolCallGuardrailData>>;
|
|
150
|
+
}
|
|
151
|
+
/** Retry configuration for agent runs */
|
|
152
|
+
interface AgentRetryConfig {
|
|
153
|
+
/** @default 1 */
|
|
154
|
+
attempts?: number;
|
|
155
|
+
/** @default "exponential" */
|
|
156
|
+
backoff?: "exponential" | "linear" | "fixed";
|
|
157
|
+
/** @default 1000 */
|
|
158
|
+
baseDelayMs?: number;
|
|
159
|
+
/** @default 30000 */
|
|
160
|
+
maxDelayMs?: number;
|
|
161
|
+
isRetryable?: (error: Error) => boolean;
|
|
162
|
+
onRetry?: (attempt: number, error: Error, delayMs: number) => void;
|
|
163
|
+
}
|
|
164
|
+
/** Agent state in facts */
|
|
165
|
+
interface AgentState {
|
|
166
|
+
status: "idle" | "running" | "paused" | "completed" | "error";
|
|
167
|
+
currentAgent: string | null;
|
|
168
|
+
input: string | null;
|
|
169
|
+
output: unknown | null;
|
|
170
|
+
error: string | null;
|
|
171
|
+
tokenUsage: number;
|
|
172
|
+
turnCount: number;
|
|
173
|
+
startedAt: number | null;
|
|
174
|
+
completedAt: number | null;
|
|
175
|
+
}
|
|
176
|
+
/** Approval state */
|
|
177
|
+
interface ApprovalState {
|
|
178
|
+
pending: ApprovalRequest[];
|
|
179
|
+
approved: string[];
|
|
180
|
+
rejected: RejectedRequest[];
|
|
181
|
+
}
|
|
182
|
+
/** Rejected request with tracking information */
|
|
183
|
+
interface RejectedRequest {
|
|
184
|
+
id: string;
|
|
185
|
+
reason?: string;
|
|
186
|
+
rejectedAt: number;
|
|
187
|
+
}
|
|
188
|
+
/** Approval request */
|
|
189
|
+
interface ApprovalRequest {
|
|
190
|
+
id: string;
|
|
191
|
+
type: "tool_call" | "output" | "handoff";
|
|
192
|
+
agentName: string;
|
|
193
|
+
description: string;
|
|
194
|
+
data: unknown;
|
|
195
|
+
requestedAt: number;
|
|
196
|
+
}
|
|
197
|
+
/** Combined orchestrator state */
|
|
198
|
+
interface OrchestratorState {
|
|
199
|
+
agent: AgentState;
|
|
200
|
+
approval: ApprovalState;
|
|
201
|
+
conversation: Message[];
|
|
202
|
+
toolCalls: ToolCall[];
|
|
203
|
+
}
|
|
204
|
+
/** Constraint for orchestrator */
|
|
205
|
+
interface OrchestratorConstraint<F extends Record<string, unknown>> {
|
|
206
|
+
when: (facts: F & OrchestratorState) => boolean | Promise<boolean>;
|
|
207
|
+
require: Requirement | ((facts: F & OrchestratorState) => Requirement);
|
|
208
|
+
priority?: number;
|
|
209
|
+
}
|
|
210
|
+
/** Resolver context for orchestrator */
|
|
211
|
+
interface OrchestratorResolverContext<F extends Record<string, unknown>> {
|
|
212
|
+
facts: F & OrchestratorState;
|
|
213
|
+
runAgent: <T>(agent: AgentLike, input: string, options?: RunOptions) => Promise<RunResult<T>>;
|
|
214
|
+
signal: AbortSignal;
|
|
215
|
+
}
|
|
216
|
+
/** Resolver for orchestrator */
|
|
217
|
+
interface OrchestratorResolver<F extends Record<string, unknown>, R extends Requirement = Requirement> {
|
|
218
|
+
requirement: (req: Requirement) => req is R;
|
|
219
|
+
key?: (req: R) => string;
|
|
220
|
+
resolve: (req: R, ctx: OrchestratorResolverContext<F>) => void | Promise<void>;
|
|
221
|
+
}
|
|
222
|
+
/** Lifecycle hooks for observability */
|
|
223
|
+
interface OrchestratorLifecycleHooks {
|
|
224
|
+
onAgentStart?: (event: {
|
|
225
|
+
agentName: string;
|
|
226
|
+
input: string;
|
|
227
|
+
timestamp: number;
|
|
228
|
+
}) => void;
|
|
229
|
+
onAgentComplete?: (event: {
|
|
230
|
+
agentName: string;
|
|
231
|
+
input: string;
|
|
232
|
+
output: unknown;
|
|
233
|
+
tokenUsage: number;
|
|
234
|
+
durationMs: number;
|
|
235
|
+
timestamp: number;
|
|
236
|
+
}) => void;
|
|
237
|
+
onAgentError?: (event: {
|
|
238
|
+
agentName: string;
|
|
239
|
+
input: string;
|
|
240
|
+
error: Error;
|
|
241
|
+
durationMs: number;
|
|
242
|
+
timestamp: number;
|
|
243
|
+
}) => void;
|
|
244
|
+
onGuardrailCheck?: (event: {
|
|
245
|
+
guardrailName: string;
|
|
246
|
+
guardrailType: "input" | "output" | "toolCall";
|
|
247
|
+
passed: boolean;
|
|
248
|
+
reason?: string;
|
|
249
|
+
durationMs: number;
|
|
250
|
+
timestamp: number;
|
|
251
|
+
}) => void;
|
|
252
|
+
onAgentRetry?: (event: {
|
|
253
|
+
agentName: string;
|
|
254
|
+
input: string;
|
|
255
|
+
attempt: number;
|
|
256
|
+
error: Error;
|
|
257
|
+
delayMs: number;
|
|
258
|
+
timestamp: number;
|
|
259
|
+
}) => void;
|
|
260
|
+
}
|
|
261
|
+
/** Error codes for guardrail errors */
|
|
262
|
+
type GuardrailErrorCode = "INPUT_GUARDRAIL_FAILED" | "OUTPUT_GUARDRAIL_FAILED" | "TOOL_CALL_GUARDRAIL_FAILED" | "APPROVAL_REJECTED" | "BUDGET_EXCEEDED" | "RATE_LIMIT_EXCEEDED" | "AGENT_ERROR";
|
|
263
|
+
/**
|
|
264
|
+
* Structured error for guardrail failures.
|
|
265
|
+
*
|
|
266
|
+
* **Security:** The `input` and `data` properties are non-enumerable to prevent
|
|
267
|
+
* accidental leakage of sensitive data via JSON.stringify or console.log.
|
|
268
|
+
*/
|
|
269
|
+
declare class GuardrailError extends Error {
|
|
270
|
+
readonly code: GuardrailErrorCode;
|
|
271
|
+
readonly guardrailName: string;
|
|
272
|
+
readonly guardrailType: "input" | "output" | "toolCall";
|
|
273
|
+
readonly userMessage: string;
|
|
274
|
+
readonly data: unknown;
|
|
275
|
+
readonly agentName: string;
|
|
276
|
+
readonly input: string;
|
|
277
|
+
constructor(options: {
|
|
278
|
+
code: GuardrailErrorCode;
|
|
279
|
+
message: string;
|
|
280
|
+
guardrailName: string;
|
|
281
|
+
guardrailType: "input" | "output" | "toolCall";
|
|
282
|
+
userMessage?: string;
|
|
283
|
+
data?: unknown;
|
|
284
|
+
agentName: string;
|
|
285
|
+
input: string;
|
|
286
|
+
cause?: Error;
|
|
287
|
+
});
|
|
288
|
+
toJSON(): Record<string, unknown>;
|
|
289
|
+
}
|
|
290
|
+
/** Check if an error is a GuardrailError. */
|
|
291
|
+
declare function isGuardrailError(error: unknown): error is GuardrailError;
|
|
292
|
+
/** Schema validation result */
|
|
293
|
+
interface SchemaValidationResult {
|
|
294
|
+
valid: boolean;
|
|
295
|
+
errors?: string[];
|
|
296
|
+
}
|
|
297
|
+
/** Schema validator function type */
|
|
298
|
+
type SchemaValidator<_T = unknown> = (value: unknown) => SchemaValidationResult | boolean;
|
|
299
|
+
|
|
300
|
+
export { type ApprovalRequest as A, type GuardrailResult as G, type InputGuardrailData as I, type Message as M, type NamedGuardrail as N, type OutputGuardrailData as O, type RunOptions as R, type SchemaValidator as S, type ToolCallGuardrailData as T, type ToolCall as a, type AgentLike as b, type AgentRunner as c, type GuardrailFn as d, type GuardrailContext as e, type AdapterHooks as f, type RunResult as g, type ApprovalState as h, type AgentState as i, type OrchestratorState as j, type OrchestratorConstraint as k, type OrchestratorResolver as l, type AgentRetryConfig as m, type OrchestratorLifecycleHooks as n, type GuardrailsConfig as o, GuardrailError as p, type GuardrailErrorCode as q, type GuardrailRetryConfig as r, type OrchestratorResolverContext as s, type RejectedRequest as t, type SchemaValidationResult as u, type TokenUsage as v, isGuardrailError as w };
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import { Requirement } from '@directive-run/core';
|
|
2
|
+
|
|
3
|
+
/** Simplified Agent interface */
|
|
4
|
+
interface AgentLike {
|
|
5
|
+
name: string;
|
|
6
|
+
instructions?: string;
|
|
7
|
+
model?: string;
|
|
8
|
+
tools?: unknown[];
|
|
9
|
+
}
|
|
10
|
+
/** Agent run result */
|
|
11
|
+
interface RunResult<T = unknown> {
|
|
12
|
+
output: T;
|
|
13
|
+
messages: Message[];
|
|
14
|
+
toolCalls: ToolCall[];
|
|
15
|
+
totalTokens: number;
|
|
16
|
+
/** Breakdown of input vs output tokens, when available from the provider */
|
|
17
|
+
tokenUsage?: TokenUsage;
|
|
18
|
+
/** True when result was served from semantic cache */
|
|
19
|
+
isCached?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** Breakdown of token usage by input/output */
|
|
22
|
+
interface TokenUsage {
|
|
23
|
+
inputTokens: number;
|
|
24
|
+
outputTokens: number;
|
|
25
|
+
}
|
|
26
|
+
/** Message from agent run */
|
|
27
|
+
interface Message {
|
|
28
|
+
role: "user" | "assistant" | "tool" | "system";
|
|
29
|
+
content: string;
|
|
30
|
+
toolCallId?: string;
|
|
31
|
+
}
|
|
32
|
+
/** Tool call record */
|
|
33
|
+
interface ToolCall {
|
|
34
|
+
id: string;
|
|
35
|
+
name: string;
|
|
36
|
+
arguments: string;
|
|
37
|
+
result?: string;
|
|
38
|
+
}
|
|
39
|
+
/** Run function type */
|
|
40
|
+
type AgentRunner = <T = unknown>(agent: AgentLike, input: string, options?: RunOptions) => Promise<RunResult<T>>;
|
|
41
|
+
/** Run options */
|
|
42
|
+
interface RunOptions {
|
|
43
|
+
maxTurns?: number;
|
|
44
|
+
signal?: AbortSignal;
|
|
45
|
+
onMessage?: (message: Message) => void;
|
|
46
|
+
onToolCall?: (toolCall: ToolCall) => void;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Lifecycle hooks for adapter-level observability.
|
|
50
|
+
*
|
|
51
|
+
* Attach to any adapter (runner or streaming runner) to trace, log,
|
|
52
|
+
* or measure individual LLM calls without modifying application code.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* const runner = createOpenAIRunner({
|
|
57
|
+
* apiKey: process.env.OPENAI_API_KEY!,
|
|
58
|
+
* hooks: {
|
|
59
|
+
* onBeforeCall: ({ agent, input }) => console.log(`→ ${agent.name}`, input.slice(0, 50)),
|
|
60
|
+
* onAfterCall: ({ durationMs, tokenUsage }) => {
|
|
61
|
+
* metrics.track('llm_call', { durationMs, ...tokenUsage });
|
|
62
|
+
* },
|
|
63
|
+
* onError: ({ error }) => Sentry.captureException(error),
|
|
64
|
+
* },
|
|
65
|
+
* });
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
interface AdapterHooks {
|
|
69
|
+
/** Fires before each LLM API call. */
|
|
70
|
+
onBeforeCall?: (event: {
|
|
71
|
+
agent: AgentLike;
|
|
72
|
+
input: string;
|
|
73
|
+
timestamp: number;
|
|
74
|
+
}) => void;
|
|
75
|
+
/** Fires after a successful LLM API call. */
|
|
76
|
+
onAfterCall?: (event: {
|
|
77
|
+
agent: AgentLike;
|
|
78
|
+
input: string;
|
|
79
|
+
output: string;
|
|
80
|
+
totalTokens: number;
|
|
81
|
+
tokenUsage: TokenUsage;
|
|
82
|
+
durationMs: number;
|
|
83
|
+
timestamp: number;
|
|
84
|
+
}) => void;
|
|
85
|
+
/** Fires when an LLM API call fails. */
|
|
86
|
+
onError?: (event: {
|
|
87
|
+
agent: AgentLike;
|
|
88
|
+
input: string;
|
|
89
|
+
error: Error;
|
|
90
|
+
durationMs: number;
|
|
91
|
+
timestamp: number;
|
|
92
|
+
}) => void;
|
|
93
|
+
}
|
|
94
|
+
/** Guardrail function */
|
|
95
|
+
type GuardrailFn<T = unknown> = (data: T, context: GuardrailContext) => GuardrailResult | Promise<GuardrailResult>;
|
|
96
|
+
/** Guardrail context */
|
|
97
|
+
interface GuardrailContext {
|
|
98
|
+
agentName: string;
|
|
99
|
+
input: string;
|
|
100
|
+
facts: Record<string, unknown>;
|
|
101
|
+
}
|
|
102
|
+
/** Guardrail result */
|
|
103
|
+
interface GuardrailResult {
|
|
104
|
+
passed: boolean;
|
|
105
|
+
reason?: string;
|
|
106
|
+
transformed?: unknown;
|
|
107
|
+
}
|
|
108
|
+
/** Input guardrail data */
|
|
109
|
+
interface InputGuardrailData {
|
|
110
|
+
input: string;
|
|
111
|
+
agentName: string;
|
|
112
|
+
}
|
|
113
|
+
/** Output guardrail data */
|
|
114
|
+
interface OutputGuardrailData {
|
|
115
|
+
output: unknown;
|
|
116
|
+
agentName: string;
|
|
117
|
+
input: string;
|
|
118
|
+
messages: Message[];
|
|
119
|
+
}
|
|
120
|
+
/** Tool call guardrail data */
|
|
121
|
+
interface ToolCallGuardrailData {
|
|
122
|
+
toolCall: ToolCall;
|
|
123
|
+
agentName: string;
|
|
124
|
+
input: string;
|
|
125
|
+
}
|
|
126
|
+
/** Retry configuration for guardrails */
|
|
127
|
+
interface GuardrailRetryConfig {
|
|
128
|
+
/** @default 1 */
|
|
129
|
+
attempts?: number;
|
|
130
|
+
/** @default "exponential" */
|
|
131
|
+
backoff?: "exponential" | "linear" | "fixed";
|
|
132
|
+
/** @default 100 */
|
|
133
|
+
baseDelayMs?: number;
|
|
134
|
+
/** @default 5000 */
|
|
135
|
+
maxDelayMs?: number;
|
|
136
|
+
}
|
|
137
|
+
/** Named guardrail for better debugging */
|
|
138
|
+
interface NamedGuardrail<T = unknown> {
|
|
139
|
+
name: string;
|
|
140
|
+
fn: GuardrailFn<T>;
|
|
141
|
+
/** @default true */
|
|
142
|
+
critical?: boolean;
|
|
143
|
+
retry?: GuardrailRetryConfig;
|
|
144
|
+
}
|
|
145
|
+
/** Guardrails configuration */
|
|
146
|
+
interface GuardrailsConfig {
|
|
147
|
+
input?: Array<GuardrailFn<InputGuardrailData> | NamedGuardrail<InputGuardrailData>>;
|
|
148
|
+
output?: Array<GuardrailFn<OutputGuardrailData> | NamedGuardrail<OutputGuardrailData>>;
|
|
149
|
+
toolCall?: Array<GuardrailFn<ToolCallGuardrailData> | NamedGuardrail<ToolCallGuardrailData>>;
|
|
150
|
+
}
|
|
151
|
+
/** Retry configuration for agent runs */
|
|
152
|
+
interface AgentRetryConfig {
|
|
153
|
+
/** @default 1 */
|
|
154
|
+
attempts?: number;
|
|
155
|
+
/** @default "exponential" */
|
|
156
|
+
backoff?: "exponential" | "linear" | "fixed";
|
|
157
|
+
/** @default 1000 */
|
|
158
|
+
baseDelayMs?: number;
|
|
159
|
+
/** @default 30000 */
|
|
160
|
+
maxDelayMs?: number;
|
|
161
|
+
isRetryable?: (error: Error) => boolean;
|
|
162
|
+
onRetry?: (attempt: number, error: Error, delayMs: number) => void;
|
|
163
|
+
}
|
|
164
|
+
/** Agent state in facts */
|
|
165
|
+
interface AgentState {
|
|
166
|
+
status: "idle" | "running" | "paused" | "completed" | "error";
|
|
167
|
+
currentAgent: string | null;
|
|
168
|
+
input: string | null;
|
|
169
|
+
output: unknown | null;
|
|
170
|
+
error: string | null;
|
|
171
|
+
tokenUsage: number;
|
|
172
|
+
turnCount: number;
|
|
173
|
+
startedAt: number | null;
|
|
174
|
+
completedAt: number | null;
|
|
175
|
+
}
|
|
176
|
+
/** Approval state */
|
|
177
|
+
interface ApprovalState {
|
|
178
|
+
pending: ApprovalRequest[];
|
|
179
|
+
approved: string[];
|
|
180
|
+
rejected: RejectedRequest[];
|
|
181
|
+
}
|
|
182
|
+
/** Rejected request with tracking information */
|
|
183
|
+
interface RejectedRequest {
|
|
184
|
+
id: string;
|
|
185
|
+
reason?: string;
|
|
186
|
+
rejectedAt: number;
|
|
187
|
+
}
|
|
188
|
+
/** Approval request */
|
|
189
|
+
interface ApprovalRequest {
|
|
190
|
+
id: string;
|
|
191
|
+
type: "tool_call" | "output" | "handoff";
|
|
192
|
+
agentName: string;
|
|
193
|
+
description: string;
|
|
194
|
+
data: unknown;
|
|
195
|
+
requestedAt: number;
|
|
196
|
+
}
|
|
197
|
+
/** Combined orchestrator state */
|
|
198
|
+
interface OrchestratorState {
|
|
199
|
+
agent: AgentState;
|
|
200
|
+
approval: ApprovalState;
|
|
201
|
+
conversation: Message[];
|
|
202
|
+
toolCalls: ToolCall[];
|
|
203
|
+
}
|
|
204
|
+
/** Constraint for orchestrator */
|
|
205
|
+
interface OrchestratorConstraint<F extends Record<string, unknown>> {
|
|
206
|
+
when: (facts: F & OrchestratorState) => boolean | Promise<boolean>;
|
|
207
|
+
require: Requirement | ((facts: F & OrchestratorState) => Requirement);
|
|
208
|
+
priority?: number;
|
|
209
|
+
}
|
|
210
|
+
/** Resolver context for orchestrator */
|
|
211
|
+
interface OrchestratorResolverContext<F extends Record<string, unknown>> {
|
|
212
|
+
facts: F & OrchestratorState;
|
|
213
|
+
runAgent: <T>(agent: AgentLike, input: string, options?: RunOptions) => Promise<RunResult<T>>;
|
|
214
|
+
signal: AbortSignal;
|
|
215
|
+
}
|
|
216
|
+
/** Resolver for orchestrator */
|
|
217
|
+
interface OrchestratorResolver<F extends Record<string, unknown>, R extends Requirement = Requirement> {
|
|
218
|
+
requirement: (req: Requirement) => req is R;
|
|
219
|
+
key?: (req: R) => string;
|
|
220
|
+
resolve: (req: R, ctx: OrchestratorResolverContext<F>) => void | Promise<void>;
|
|
221
|
+
}
|
|
222
|
+
/** Lifecycle hooks for observability */
|
|
223
|
+
interface OrchestratorLifecycleHooks {
|
|
224
|
+
onAgentStart?: (event: {
|
|
225
|
+
agentName: string;
|
|
226
|
+
input: string;
|
|
227
|
+
timestamp: number;
|
|
228
|
+
}) => void;
|
|
229
|
+
onAgentComplete?: (event: {
|
|
230
|
+
agentName: string;
|
|
231
|
+
input: string;
|
|
232
|
+
output: unknown;
|
|
233
|
+
tokenUsage: number;
|
|
234
|
+
durationMs: number;
|
|
235
|
+
timestamp: number;
|
|
236
|
+
}) => void;
|
|
237
|
+
onAgentError?: (event: {
|
|
238
|
+
agentName: string;
|
|
239
|
+
input: string;
|
|
240
|
+
error: Error;
|
|
241
|
+
durationMs: number;
|
|
242
|
+
timestamp: number;
|
|
243
|
+
}) => void;
|
|
244
|
+
onGuardrailCheck?: (event: {
|
|
245
|
+
guardrailName: string;
|
|
246
|
+
guardrailType: "input" | "output" | "toolCall";
|
|
247
|
+
passed: boolean;
|
|
248
|
+
reason?: string;
|
|
249
|
+
durationMs: number;
|
|
250
|
+
timestamp: number;
|
|
251
|
+
}) => void;
|
|
252
|
+
onAgentRetry?: (event: {
|
|
253
|
+
agentName: string;
|
|
254
|
+
input: string;
|
|
255
|
+
attempt: number;
|
|
256
|
+
error: Error;
|
|
257
|
+
delayMs: number;
|
|
258
|
+
timestamp: number;
|
|
259
|
+
}) => void;
|
|
260
|
+
}
|
|
261
|
+
/** Error codes for guardrail errors */
|
|
262
|
+
type GuardrailErrorCode = "INPUT_GUARDRAIL_FAILED" | "OUTPUT_GUARDRAIL_FAILED" | "TOOL_CALL_GUARDRAIL_FAILED" | "APPROVAL_REJECTED" | "BUDGET_EXCEEDED" | "RATE_LIMIT_EXCEEDED" | "AGENT_ERROR";
|
|
263
|
+
/**
|
|
264
|
+
* Structured error for guardrail failures.
|
|
265
|
+
*
|
|
266
|
+
* **Security:** The `input` and `data` properties are non-enumerable to prevent
|
|
267
|
+
* accidental leakage of sensitive data via JSON.stringify or console.log.
|
|
268
|
+
*/
|
|
269
|
+
declare class GuardrailError extends Error {
|
|
270
|
+
readonly code: GuardrailErrorCode;
|
|
271
|
+
readonly guardrailName: string;
|
|
272
|
+
readonly guardrailType: "input" | "output" | "toolCall";
|
|
273
|
+
readonly userMessage: string;
|
|
274
|
+
readonly data: unknown;
|
|
275
|
+
readonly agentName: string;
|
|
276
|
+
readonly input: string;
|
|
277
|
+
constructor(options: {
|
|
278
|
+
code: GuardrailErrorCode;
|
|
279
|
+
message: string;
|
|
280
|
+
guardrailName: string;
|
|
281
|
+
guardrailType: "input" | "output" | "toolCall";
|
|
282
|
+
userMessage?: string;
|
|
283
|
+
data?: unknown;
|
|
284
|
+
agentName: string;
|
|
285
|
+
input: string;
|
|
286
|
+
cause?: Error;
|
|
287
|
+
});
|
|
288
|
+
toJSON(): Record<string, unknown>;
|
|
289
|
+
}
|
|
290
|
+
/** Check if an error is a GuardrailError. */
|
|
291
|
+
declare function isGuardrailError(error: unknown): error is GuardrailError;
|
|
292
|
+
/** Schema validation result */
|
|
293
|
+
interface SchemaValidationResult {
|
|
294
|
+
valid: boolean;
|
|
295
|
+
errors?: string[];
|
|
296
|
+
}
|
|
297
|
+
/** Schema validator function type */
|
|
298
|
+
type SchemaValidator<_T = unknown> = (value: unknown) => SchemaValidationResult | boolean;
|
|
299
|
+
|
|
300
|
+
export { type ApprovalRequest as A, type GuardrailResult as G, type InputGuardrailData as I, type Message as M, type NamedGuardrail as N, type OutputGuardrailData as O, type RunOptions as R, type SchemaValidator as S, type ToolCallGuardrailData as T, type ToolCall as a, type AgentLike as b, type AgentRunner as c, type GuardrailFn as d, type GuardrailContext as e, type AdapterHooks as f, type RunResult as g, type ApprovalState as h, type AgentState as i, type OrchestratorState as j, type OrchestratorConstraint as k, type OrchestratorResolver as l, type AgentRetryConfig as m, type OrchestratorLifecycleHooks as n, type GuardrailsConfig as o, GuardrailError as p, type GuardrailErrorCode as q, type GuardrailRetryConfig as r, type OrchestratorResolverContext as s, type RejectedRequest as t, type SchemaValidationResult as u, type TokenUsage as v, isGuardrailError as w };
|
package/package.json
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@directive-run/ai",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "AI agent orchestration, guardrails, and multi-agent coordination for Directive.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Jason Comes",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/directive-run/directive",
|
|
10
|
+
"directory": "packages/ai"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://directive.run",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/directive-run/directive/issues"
|
|
15
|
+
},
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public",
|
|
18
|
+
"registry": "https://registry.npmjs.org"
|
|
19
|
+
},
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=18"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"directive",
|
|
25
|
+
"ai",
|
|
26
|
+
"agents",
|
|
27
|
+
"guardrails",
|
|
28
|
+
"orchestration",
|
|
29
|
+
"llm",
|
|
30
|
+
"constraint-driven"
|
|
31
|
+
],
|
|
32
|
+
"sideEffects": false,
|
|
33
|
+
"type": "module",
|
|
34
|
+
"main": "./dist/index.cjs",
|
|
35
|
+
"module": "./dist/index.js",
|
|
36
|
+
"types": "./dist/index.d.ts",
|
|
37
|
+
"exports": {
|
|
38
|
+
".": {
|
|
39
|
+
"types": "./dist/index.d.ts",
|
|
40
|
+
"require": "./dist/index.cjs",
|
|
41
|
+
"import": "./dist/index.js"
|
|
42
|
+
},
|
|
43
|
+
"./testing": {
|
|
44
|
+
"types": "./dist/testing.d.ts",
|
|
45
|
+
"require": "./dist/testing.cjs",
|
|
46
|
+
"import": "./dist/testing.js"
|
|
47
|
+
},
|
|
48
|
+
"./anthropic": {
|
|
49
|
+
"types": "./dist/anthropic.d.ts",
|
|
50
|
+
"require": "./dist/anthropic.cjs",
|
|
51
|
+
"import": "./dist/anthropic.js"
|
|
52
|
+
},
|
|
53
|
+
"./openai": {
|
|
54
|
+
"types": "./dist/openai.d.ts",
|
|
55
|
+
"require": "./dist/openai.cjs",
|
|
56
|
+
"import": "./dist/openai.js"
|
|
57
|
+
},
|
|
58
|
+
"./ollama": {
|
|
59
|
+
"types": "./dist/ollama.d.ts",
|
|
60
|
+
"require": "./dist/ollama.cjs",
|
|
61
|
+
"import": "./dist/ollama.js"
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"files": [
|
|
65
|
+
"dist"
|
|
66
|
+
],
|
|
67
|
+
"peerDependencies": {
|
|
68
|
+
"@directive-run/core": "0.1.1"
|
|
69
|
+
},
|
|
70
|
+
"devDependencies": {
|
|
71
|
+
"@types/node": "^25.2.0",
|
|
72
|
+
"tsup": "^8.3.5",
|
|
73
|
+
"typescript": "^5.7.2",
|
|
74
|
+
"@directive-run/core": "0.1.1"
|
|
75
|
+
},
|
|
76
|
+
"scripts": {
|
|
77
|
+
"build": "tsup",
|
|
78
|
+
"dev": "tsup --watch",
|
|
79
|
+
"test": "vitest run",
|
|
80
|
+
"typecheck": "tsc --noEmit",
|
|
81
|
+
"clean": "rm -rf dist"
|
|
82
|
+
}
|
|
83
|
+
}
|