@purista/harness 1.0.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.
- package/LICENSE +201 -0
- package/README.md +23 -0
- package/dist/agents/index.d.ts +34 -0
- package/dist/agents/index.js +301 -0
- package/dist/errors/catalog.d.ts +185 -0
- package/dist/errors/catalog.js +144 -0
- package/dist/errors/harness-error.d.ts +64 -0
- package/dist/errors/harness-error.js +58 -0
- package/dist/errors/index.d.ts +3 -0
- package/dist/errors/index.js +3 -0
- package/dist/errors/redaction.d.ts +5 -0
- package/dist/errors/redaction.js +64 -0
- package/dist/harness/defineHarness.d.ts +640 -0
- package/dist/harness/defineHarness.js +176 -0
- package/dist/harness/errors.d.ts +62 -0
- package/dist/harness/errors.js +67 -0
- package/dist/harness/types.d.ts +27 -0
- package/dist/harness/types.js +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +12 -0
- package/dist/logger/index.d.ts +2 -0
- package/dist/logger/index.js +2 -0
- package/dist/logger/json-logger.d.ts +31 -0
- package/dist/logger/json-logger.js +65 -0
- package/dist/logger/logger.d.ts +31 -0
- package/dist/logger/logger.js +1 -0
- package/dist/models/json.d.ts +6 -0
- package/dist/models/json.js +1 -0
- package/dist/models/registry.d.ts +112 -0
- package/dist/models/registry.js +286 -0
- package/dist/models/state.d.ts +64 -0
- package/dist/models/state.js +1 -0
- package/dist/ports/base-model-provider.d.ts +56 -0
- package/dist/ports/base-model-provider.js +343 -0
- package/dist/ports/capabilities.d.ts +70 -0
- package/dist/ports/capabilities.js +38 -0
- package/dist/ports/feedback.d.ts +29 -0
- package/dist/ports/feedback.js +1 -0
- package/dist/ports/harness-context.d.ts +20 -0
- package/dist/ports/harness-context.js +1 -0
- package/dist/ports/index.d.ts +6 -0
- package/dist/ports/index.js +6 -0
- package/dist/ports/model-provider.d.ts +280 -0
- package/dist/ports/model-provider.js +1 -0
- package/dist/ports/state.d.ts +72 -0
- package/dist/ports/state.js +24 -0
- package/dist/runtime/durable.d.ts +134 -0
- package/dist/runtime/durable.js +185 -0
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.js +2 -0
- package/dist/runtime/steps.d.ts +22 -0
- package/dist/runtime/steps.js +51 -0
- package/dist/sandbox/index.d.ts +111 -0
- package/dist/sandbox/index.js +165 -0
- package/dist/sessions/index.d.ts +23 -0
- package/dist/sessions/index.js +718 -0
- package/dist/skills/index.d.ts +8 -0
- package/dist/skills/index.js +88 -0
- package/dist/state/in-memory.d.ts +35 -0
- package/dist/state/in-memory.js +140 -0
- package/dist/telemetry/index.d.ts +1 -0
- package/dist/telemetry/index.js +1 -0
- package/dist/telemetry/shim.d.ts +26 -0
- package/dist/telemetry/shim.js +120 -0
- package/dist/testing/capabilities.d.ts +11 -0
- package/dist/testing/capabilities.js +20 -0
- package/dist/testing/fakeModelProvider.d.ts +25 -0
- package/dist/testing/fakeModelProvider.js +79 -0
- package/dist/testing/feedback.d.ts +10 -0
- package/dist/testing/feedback.js +24 -0
- package/dist/testing/fixtures/mcp/fake-http-server.d.ts +8 -0
- package/dist/testing/fixtures/mcp/fake-http-server.js +95 -0
- package/dist/testing/index.d.ts +8 -0
- package/dist/testing/index.js +11 -0
- package/dist/testing/sandboxContract.d.ts +4 -0
- package/dist/testing/sandboxContract.js +74 -0
- package/dist/testing/sandboxSnapshot.d.ts +7 -0
- package/dist/testing/sandboxSnapshot.js +201 -0
- package/dist/testing/stateStoreContract.d.ts +2 -0
- package/dist/testing/stateStoreContract.js +109 -0
- package/dist/tools/index.d.ts +9 -0
- package/dist/tools/index.js +123 -0
- package/dist/tools/mcp/http.d.ts +2 -0
- package/dist/tools/mcp/http.js +109 -0
- package/dist/tools/mcp/index.d.ts +2 -0
- package/dist/tools/mcp/index.js +2 -0
- package/dist/tools/mcp/runner.d.ts +74 -0
- package/dist/tools/mcp/runner.js +238 -0
- package/dist/tools/mcp/schema.d.ts +41 -0
- package/dist/tools/mcp/schema.js +251 -0
- package/dist/tools/mcp/stdio.d.ts +2 -0
- package/dist/tools/mcp/stdio.js +122 -0
- package/dist/ulid/index.d.ts +6 -0
- package/dist/ulid/index.js +35 -0
- package/dist/workflows/index.d.ts +8 -0
- package/dist/workflows/index.js +26 -0
- package/package.json +75 -0
|
@@ -0,0 +1,640 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type Logger } from '../logger/index.js';
|
|
3
|
+
import type { ModelAlias, ModelCapability, TokenUsage } from '../ports/model-provider.js';
|
|
4
|
+
import type { StateStore } from '../ports/state.js';
|
|
5
|
+
import type { TelemetryShim } from '../telemetry/index.js';
|
|
6
|
+
import type { HarnessAdapterContext } from '../ports/harness-context.js';
|
|
7
|
+
import type { JsonValue } from '../models/json.js';
|
|
8
|
+
import type { Message } from '../models/state.js';
|
|
9
|
+
import type { HarnessError } from '../errors/harness-error.js';
|
|
10
|
+
import { type Sandbox } from '../sandbox/index.js';
|
|
11
|
+
import type { ModelHandle } from '../models/registry.js';
|
|
12
|
+
import { type AdapterCapability, type DurableRuntimeAdapter, type HarnessInspection } from '../ports/capabilities.js';
|
|
13
|
+
/** Stable harness version string for diagnostics and generated documentation. */
|
|
14
|
+
export declare const HARNESS_VERSION = "0.0.0";
|
|
15
|
+
/** OpenTelemetry capture controls used by the harness. */
|
|
16
|
+
export interface TelemetryOptions {
|
|
17
|
+
/**
|
|
18
|
+
* When `true`, emitted telemetry may include full prompt/message content.
|
|
19
|
+
* The default is `false` to avoid accidental sensitive-content capture.
|
|
20
|
+
*/
|
|
21
|
+
captureContent?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/** Default harness budgets and execution behavior. */
|
|
24
|
+
export interface HarnessDefaults {
|
|
25
|
+
/** Default maximum iterations for the built-in agent loop. Default: `16`. */
|
|
26
|
+
agentMaxIterations?: number;
|
|
27
|
+
/** Per-run timeout in milliseconds. `0` disables. Default: `600_000`. */
|
|
28
|
+
runTimeoutMs?: number;
|
|
29
|
+
/** Per-tool timeout in milliseconds. Default: `120_000`. */
|
|
30
|
+
toolTimeoutMs?: number;
|
|
31
|
+
/** Per-skill timeout in milliseconds. Default: `60_000`. */
|
|
32
|
+
skillTimeoutMs?: number;
|
|
33
|
+
/** Per-model timeout in milliseconds. Default: `300_000`. */
|
|
34
|
+
modelTimeoutMs?: number;
|
|
35
|
+
/**
|
|
36
|
+
* Max non-system messages forwarded into model calls.
|
|
37
|
+
* `undefined` keeps all history, `0` keeps only system messages.
|
|
38
|
+
*/
|
|
39
|
+
historyWindow?: number;
|
|
40
|
+
}
|
|
41
|
+
/** Top-level harness options passed to {@link defineHarness}. */
|
|
42
|
+
export interface HarnessOptions {
|
|
43
|
+
/** Optional harness name for logs, telemetry, and diagnostics. Default: `agent-harness`. */
|
|
44
|
+
name?: string;
|
|
45
|
+
}
|
|
46
|
+
/** Shared invoke options for workflow and agent execution. */
|
|
47
|
+
export interface InvokeOptions {
|
|
48
|
+
/** Abort signal used to cooperatively cancel the call. */
|
|
49
|
+
signal?: AbortSignal;
|
|
50
|
+
/** Optional timeout override in milliseconds. `0` disables. */
|
|
51
|
+
timeoutMs?: number;
|
|
52
|
+
/** Optional history-window override for this call only. */
|
|
53
|
+
historyWindow?: number;
|
|
54
|
+
}
|
|
55
|
+
/** Canonical built-in tool names provided by the harness. */
|
|
56
|
+
export type BuiltinToolName = 'bash' | 'read' | 'write' | 'edit' | 'glob' | 'grep' | 'list';
|
|
57
|
+
/** Permission modes for sandbox-mutating tools. */
|
|
58
|
+
export type PermissionMode = 'allow' | 'ask' | 'deny';
|
|
59
|
+
/** Structured permission policy for a single tool family. */
|
|
60
|
+
export interface PermissionPolicy {
|
|
61
|
+
/** Base decision mode for the tool family. */
|
|
62
|
+
mode: PermissionMode;
|
|
63
|
+
/** Optional allowlist evaluated by harness-specific policy hooks. */
|
|
64
|
+
allow?: readonly string[];
|
|
65
|
+
/** Optional denylist evaluated by harness-specific policy hooks. */
|
|
66
|
+
deny?: readonly string[];
|
|
67
|
+
}
|
|
68
|
+
/** Per-agent permission configuration for built-in mutating tools. */
|
|
69
|
+
export interface AgentPermissions {
|
|
70
|
+
/** Permission mode or policy for the `bash` built-in tool. */
|
|
71
|
+
bash?: PermissionMode | PermissionPolicy;
|
|
72
|
+
/** Permission mode or policy for the `write` built-in tool. */
|
|
73
|
+
write?: PermissionMode | PermissionPolicy;
|
|
74
|
+
/** Permission mode or policy for the `edit` built-in tool. */
|
|
75
|
+
edit?: PermissionMode | PermissionPolicy;
|
|
76
|
+
}
|
|
77
|
+
/** Context passed to custom permission hooks. */
|
|
78
|
+
export interface PermissionContext {
|
|
79
|
+
/** Tool name under evaluation. */
|
|
80
|
+
toolName: string;
|
|
81
|
+
/** Raw input proposed for the tool call. */
|
|
82
|
+
input: unknown;
|
|
83
|
+
/** Current agent id. */
|
|
84
|
+
agentId: string;
|
|
85
|
+
/** Current run id. */
|
|
86
|
+
runId: string;
|
|
87
|
+
/** Current session id. */
|
|
88
|
+
sessionId: string;
|
|
89
|
+
}
|
|
90
|
+
/** Final decision returned from a permission hook. */
|
|
91
|
+
export type PermissionDecision = 'allow' | 'deny';
|
|
92
|
+
/** Async permission hook used for interactive approvals or custom policy engines. */
|
|
93
|
+
export type OnPermission = (ctx: PermissionContext) => Promise<PermissionDecision>;
|
|
94
|
+
/** Mounted skill metadata after frontmatter parsing. */
|
|
95
|
+
export interface ResolvedSkill {
|
|
96
|
+
/** Public skill id. */
|
|
97
|
+
name: string;
|
|
98
|
+
/** Short user-facing description from frontmatter. */
|
|
99
|
+
description: string;
|
|
100
|
+
/** Optional skill version. */
|
|
101
|
+
version?: string;
|
|
102
|
+
/** Absolute directory mounted into `/skills/<name>`. */
|
|
103
|
+
directory: string;
|
|
104
|
+
}
|
|
105
|
+
/** Sandbox-backed per-session memory facade. */
|
|
106
|
+
export interface SessionMemory {
|
|
107
|
+
/** Reads `/memory/<key>.json` and returns the parsed JSON value if present. */
|
|
108
|
+
read<T = JsonValue>(key: string): Promise<T | undefined>;
|
|
109
|
+
/** Writes JSON-serializable data to `/memory/<key>.json`. */
|
|
110
|
+
write(key: string, value: JsonValue): Promise<void>;
|
|
111
|
+
/** Deletes `/memory/<key>.json` if it exists. */
|
|
112
|
+
delete(key: string): Promise<void>;
|
|
113
|
+
/** Lists known memory keys without the `.json` suffix. */
|
|
114
|
+
list(): Promise<string[]>;
|
|
115
|
+
}
|
|
116
|
+
/** Conversation history accessor for a single session thread. */
|
|
117
|
+
export interface ConversationHistory {
|
|
118
|
+
/** Returns persisted conversation messages for the session. */
|
|
119
|
+
list(opts?: {
|
|
120
|
+
limit?: number;
|
|
121
|
+
before?: string;
|
|
122
|
+
}): Promise<Message[]>;
|
|
123
|
+
}
|
|
124
|
+
/** Context provided to custom TypeScript tools. */
|
|
125
|
+
export interface ToolHandlerContext {
|
|
126
|
+
signal: AbortSignal;
|
|
127
|
+
sandbox: import('../sandbox/index.js').SandboxSession;
|
|
128
|
+
logger: Logger;
|
|
129
|
+
telemetry: TelemetryShim;
|
|
130
|
+
runId: string;
|
|
131
|
+
sessionId: string;
|
|
132
|
+
agentId: string;
|
|
133
|
+
toolId: string;
|
|
134
|
+
}
|
|
135
|
+
/** TypeScript-native tool definition. */
|
|
136
|
+
export interface TsToolDefinition<I extends z.ZodTypeAny = z.ZodTypeAny, O extends z.ZodTypeAny = z.ZodTypeAny> {
|
|
137
|
+
/** Tool kind discriminator. Defaults to `ts`. */
|
|
138
|
+
kind?: 'ts';
|
|
139
|
+
/** Short model-facing description. */
|
|
140
|
+
description: string;
|
|
141
|
+
/** Input schema validated before handler invocation. */
|
|
142
|
+
input: I;
|
|
143
|
+
/** Output schema validated after handler invocation. */
|
|
144
|
+
output: O;
|
|
145
|
+
/** Async tool implementation running inside the current session sandbox. */
|
|
146
|
+
handler: (ctx: ToolHandlerContext, input: z.infer<I>) => Promise<z.infer<O>>;
|
|
147
|
+
/** Optional adapter hook for inheriting harness logger, telemetry, and defaults. */
|
|
148
|
+
configureHarnessContext?: (context: HarnessAdapterContext) => void;
|
|
149
|
+
}
|
|
150
|
+
/** MCP-over-stdio tool definition. */
|
|
151
|
+
export interface McpStdioToolDefinition {
|
|
152
|
+
kind: 'mcp_stdio';
|
|
153
|
+
description: string;
|
|
154
|
+
command: string;
|
|
155
|
+
args?: readonly string[];
|
|
156
|
+
env?: Record<string, string>;
|
|
157
|
+
/** Optional bootstrap command executed inside the sandbox before the MCP server is called. */
|
|
158
|
+
install?: {
|
|
159
|
+
command: string;
|
|
160
|
+
cwd?: string;
|
|
161
|
+
env?: Record<string, string>;
|
|
162
|
+
timeoutMs?: number;
|
|
163
|
+
};
|
|
164
|
+
tool: string;
|
|
165
|
+
inputAdapter?: (input: unknown) => unknown;
|
|
166
|
+
outputAdapter?: (output: unknown) => unknown;
|
|
167
|
+
configureHarnessContext?: (context: HarnessAdapterContext) => void;
|
|
168
|
+
}
|
|
169
|
+
/** Supported MCP auth kinds. */
|
|
170
|
+
export type McpAuth =
|
|
171
|
+
/** No authentication. */
|
|
172
|
+
{
|
|
173
|
+
kind: 'none';
|
|
174
|
+
}
|
|
175
|
+
/** Bearer token authentication. */
|
|
176
|
+
| {
|
|
177
|
+
kind: 'bearer';
|
|
178
|
+
token: string;
|
|
179
|
+
}
|
|
180
|
+
/** OAuth2 access token authentication. */
|
|
181
|
+
| {
|
|
182
|
+
kind: 'oauth2';
|
|
183
|
+
accessToken: string;
|
|
184
|
+
}
|
|
185
|
+
/** API key authentication. */
|
|
186
|
+
| {
|
|
187
|
+
kind: 'api_key';
|
|
188
|
+
header: string;
|
|
189
|
+
value: string;
|
|
190
|
+
}
|
|
191
|
+
/** Basic authentication. */
|
|
192
|
+
| {
|
|
193
|
+
kind: 'basic';
|
|
194
|
+
username: string;
|
|
195
|
+
password: string;
|
|
196
|
+
};
|
|
197
|
+
/** MCP-over-HTTP tool definition. */
|
|
198
|
+
export interface McpHttpToolDefinition {
|
|
199
|
+
kind: 'mcp_http';
|
|
200
|
+
description: string;
|
|
201
|
+
url: string;
|
|
202
|
+
tool: string;
|
|
203
|
+
auth?: McpAuth;
|
|
204
|
+
headers?: Record<string, string>;
|
|
205
|
+
inputAdapter?: (input: unknown) => unknown;
|
|
206
|
+
outputAdapter?: (output: unknown) => unknown;
|
|
207
|
+
configureHarnessContext?: (context: HarnessAdapterContext) => void;
|
|
208
|
+
}
|
|
209
|
+
/** Any tool definition accepted by `.tools(...)`. */
|
|
210
|
+
export type ToolDefinition = TsToolDefinition | McpStdioToolDefinition | McpHttpToolDefinition;
|
|
211
|
+
/** Full tool registry shape. */
|
|
212
|
+
export type ToolsConfig = Record<string, ToolDefinition>;
|
|
213
|
+
/** Skill definition registered on the harness builder. */
|
|
214
|
+
export interface SkillDefinition {
|
|
215
|
+
/** Absolute path to the directory containing `SKILL.md`. */
|
|
216
|
+
directory: string;
|
|
217
|
+
}
|
|
218
|
+
/** Full skill registry shape. */
|
|
219
|
+
export type SkillsConfig = Record<string, SkillDefinition>;
|
|
220
|
+
/** Alias map passed to `.models(...)`. */
|
|
221
|
+
export type ModelsConfig = Record<string, ModelAlias>;
|
|
222
|
+
/** Builder-state accumulator used for type propagation across the fluent harness builder. */
|
|
223
|
+
export interface BuilderState {
|
|
224
|
+
models?: ModelsConfig;
|
|
225
|
+
tools?: ToolsConfig;
|
|
226
|
+
skills?: SkillsConfig;
|
|
227
|
+
agents?: Record<string, AgentDefinition<any, any, any>>;
|
|
228
|
+
workflows?: Record<string, WorkflowDefinition<any, any, any>>;
|
|
229
|
+
}
|
|
230
|
+
type InferSchemaOrString<T> = T extends z.ZodTypeAny ? z.infer<T> : string;
|
|
231
|
+
type DefinitionInput<D> = D extends {
|
|
232
|
+
input: infer I;
|
|
233
|
+
} ? InferSchemaOrString<I> : D extends {
|
|
234
|
+
input?: infer I;
|
|
235
|
+
} ? InferSchemaOrString<I> : string;
|
|
236
|
+
type DefinitionOutput<D> = D extends {
|
|
237
|
+
output: infer O;
|
|
238
|
+
} ? InferSchemaOrString<O> : D extends {
|
|
239
|
+
output?: infer O;
|
|
240
|
+
} ? InferSchemaOrString<O> : string;
|
|
241
|
+
/** Helper to infer workflow input type from a workflow definition. */
|
|
242
|
+
export type WorkflowInput<S extends BuilderState, K extends keyof NonNullable<S['workflows']>> = DefinitionInput<NonNullable<S['workflows']>[K]>;
|
|
243
|
+
/** Helper to infer workflow output type from a workflow definition. */
|
|
244
|
+
export type WorkflowOutput<S extends BuilderState, K extends keyof NonNullable<S['workflows']>> = DefinitionOutput<NonNullable<S['workflows']>[K]>;
|
|
245
|
+
/** Helper to infer agent input type from an agent definition. */
|
|
246
|
+
export type AgentInput<S extends BuilderState, K extends keyof NonNullable<S['agents']>> = DefinitionInput<NonNullable<S['agents']>[K]>;
|
|
247
|
+
/** Helper to infer agent output type from an agent definition. */
|
|
248
|
+
export type AgentOutput<S extends BuilderState, K extends keyof NonNullable<S['agents']>> = DefinitionOutput<NonNullable<S['agents']>[K]>;
|
|
249
|
+
/** Capability-filtered model handles keyed by configured model alias. */
|
|
250
|
+
export type ModelHandles<S extends BuilderState> = {
|
|
251
|
+
readonly [K in keyof NonNullable<S['models']>]: NonNullable<S['models']>[K] extends {
|
|
252
|
+
capabilities: readonly ModelCapability[];
|
|
253
|
+
} ? ModelHandle<NonNullable<S['models']>[K]> : never;
|
|
254
|
+
};
|
|
255
|
+
/** Minimal context available when deriving dynamic agent instructions. */
|
|
256
|
+
export interface AgentContextMinimal<S extends BuilderState, I> {
|
|
257
|
+
input: I;
|
|
258
|
+
sessionId: string;
|
|
259
|
+
runId: string;
|
|
260
|
+
history: ConversationHistory;
|
|
261
|
+
memory: SessionMemory;
|
|
262
|
+
}
|
|
263
|
+
/** Full context passed to workflow handlers. */
|
|
264
|
+
export interface WorkflowContext<S extends BuilderState, I, O> {
|
|
265
|
+
input: I;
|
|
266
|
+
agents: {
|
|
267
|
+
[K in keyof NonNullable<S['agents']>]: (input: AgentInput<S, K>, opts?: InvokeOptions) => Promise<AgentOutput<S, K>>;
|
|
268
|
+
};
|
|
269
|
+
models: ModelHandles<S>;
|
|
270
|
+
signal: AbortSignal;
|
|
271
|
+
runId: string;
|
|
272
|
+
sessionId: string;
|
|
273
|
+
output?: O;
|
|
274
|
+
}
|
|
275
|
+
/** Full context passed to custom agent handlers. */
|
|
276
|
+
export interface AgentContext<S extends BuilderState, I, O> extends AgentContextMinimal<S, I> {
|
|
277
|
+
models: ModelHandles<S>;
|
|
278
|
+
signal: AbortSignal;
|
|
279
|
+
output?: O;
|
|
280
|
+
}
|
|
281
|
+
/** Agent definition registered inline within `.agents(...)`. */
|
|
282
|
+
export interface AgentDefinition<S extends BuilderState, I extends z.ZodTypeAny = z.ZodTypeAny, O extends z.ZodTypeAny = z.ZodTypeAny> {
|
|
283
|
+
input?: I;
|
|
284
|
+
output?: O;
|
|
285
|
+
model: keyof NonNullable<S['models']> & string;
|
|
286
|
+
instructions: string | ((ctx: AgentContextMinimal<S, z.infer<I>>) => string);
|
|
287
|
+
tools?: readonly (keyof NonNullable<S['tools']> & string)[];
|
|
288
|
+
builtinTools?: readonly BuiltinToolName[] | false;
|
|
289
|
+
skills?: readonly (keyof NonNullable<S['skills']> & string)[];
|
|
290
|
+
permissions?: AgentPermissions;
|
|
291
|
+
onPermission?: OnPermission;
|
|
292
|
+
maxSteps?: number;
|
|
293
|
+
handler?: (ctx: AgentContext<S, z.infer<I>, z.infer<O>>) => Promise<z.infer<O>>;
|
|
294
|
+
}
|
|
295
|
+
/** Workflow definition registered inline within `.workflows(...)`. */
|
|
296
|
+
export interface WorkflowDefinition<S extends BuilderState, I extends z.ZodTypeAny = z.ZodTypeAny, O extends z.ZodTypeAny = z.ZodTypeAny> {
|
|
297
|
+
input?: I;
|
|
298
|
+
output?: O;
|
|
299
|
+
handler: (ctx: WorkflowContext<S, z.infer<I>, z.infer<O>>) => Promise<z.infer<O>>;
|
|
300
|
+
}
|
|
301
|
+
type AgentSchemaFields = {
|
|
302
|
+
input?: z.ZodTypeAny;
|
|
303
|
+
output?: z.ZodTypeAny;
|
|
304
|
+
};
|
|
305
|
+
type AgentDefinitionResolved<S extends BuilderState, I extends z.ZodTypeAny, O extends z.ZodTypeAny> = {
|
|
306
|
+
input?: I;
|
|
307
|
+
output?: O;
|
|
308
|
+
model: keyof NonNullable<S['models']> & string;
|
|
309
|
+
instructions: string | ((ctx: AgentContextMinimal<S, z.infer<I>>) => string);
|
|
310
|
+
tools?: readonly (keyof NonNullable<S['tools']> & string)[];
|
|
311
|
+
builtinTools?: readonly BuiltinToolName[] | false;
|
|
312
|
+
skills?: readonly (keyof NonNullable<S['skills']> & string)[];
|
|
313
|
+
permissions?: AgentPermissions;
|
|
314
|
+
onPermission?: OnPermission;
|
|
315
|
+
maxSteps?: number;
|
|
316
|
+
handler?: (ctx: AgentContext<S, z.infer<I>, z.infer<O>>) => Promise<z.infer<O>>;
|
|
317
|
+
};
|
|
318
|
+
type AgentDefinitionFor<S extends BuilderState, D> = D extends {
|
|
319
|
+
input: infer I extends z.ZodTypeAny;
|
|
320
|
+
output: infer O extends z.ZodTypeAny;
|
|
321
|
+
} ? AgentDefinitionResolved<S, I, O> : D extends {
|
|
322
|
+
input: infer I extends z.ZodTypeAny;
|
|
323
|
+
} ? AgentDefinitionResolved<S, I, z.ZodString> : D extends {
|
|
324
|
+
output: infer O extends z.ZodTypeAny;
|
|
325
|
+
} ? AgentDefinitionResolved<S, z.ZodString, O> : AgentDefinitionResolved<S, z.ZodString, z.ZodString>;
|
|
326
|
+
type AgentsConfigFromSchemaMaps<S extends BuilderState, A extends {
|
|
327
|
+
[K in keyof A]: {
|
|
328
|
+
input: z.ZodTypeAny;
|
|
329
|
+
output: z.ZodTypeAny;
|
|
330
|
+
};
|
|
331
|
+
}> = {
|
|
332
|
+
[K in keyof A]: A[K] & AgentDefinitionResolved<S, A[K]['input'], A[K]['output']>;
|
|
333
|
+
};
|
|
334
|
+
type WorkflowSchemaFields = {
|
|
335
|
+
input?: z.ZodTypeAny;
|
|
336
|
+
output?: z.ZodTypeAny;
|
|
337
|
+
};
|
|
338
|
+
type WorkflowDefinitionResolved<S extends BuilderState, I extends z.ZodTypeAny, O extends z.ZodTypeAny> = {
|
|
339
|
+
input?: I;
|
|
340
|
+
output?: O;
|
|
341
|
+
handler: (ctx: WorkflowContext<S, z.infer<I>, z.infer<O>>) => Promise<z.infer<O>>;
|
|
342
|
+
};
|
|
343
|
+
type WorkflowDefinitionFor<S extends BuilderState, D> = D extends {
|
|
344
|
+
input: infer I extends z.ZodTypeAny;
|
|
345
|
+
output: infer O extends z.ZodTypeAny;
|
|
346
|
+
} ? WorkflowDefinitionResolved<S, I, O> : D extends {
|
|
347
|
+
input: infer I extends z.ZodTypeAny;
|
|
348
|
+
} ? WorkflowDefinitionResolved<S, I, z.ZodString> : D extends {
|
|
349
|
+
output: infer O extends z.ZodTypeAny;
|
|
350
|
+
} ? WorkflowDefinitionResolved<S, z.ZodString, O> : WorkflowDefinitionResolved<S, z.ZodString, z.ZodString>;
|
|
351
|
+
type WorkflowsConfigFromSchemaMaps<S extends BuilderState, W extends {
|
|
352
|
+
[K in keyof W]: {
|
|
353
|
+
input: z.ZodTypeAny;
|
|
354
|
+
output: z.ZodTypeAny;
|
|
355
|
+
};
|
|
356
|
+
}> = {
|
|
357
|
+
[K in keyof W]: W[K] & WorkflowDefinitionResolved<S, W[K]['input'], W[K]['output']>;
|
|
358
|
+
};
|
|
359
|
+
export interface AgentDefinitionHelpers<S extends BuilderState> {
|
|
360
|
+
agent<const I extends z.ZodTypeAny, const O extends z.ZodTypeAny>(definition: AgentDefinitionResolved<S, I, O> & {
|
|
361
|
+
input: I;
|
|
362
|
+
output: O;
|
|
363
|
+
}): AgentDefinitionResolved<S, I, O> & {
|
|
364
|
+
input: I;
|
|
365
|
+
output: O;
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
export interface WorkflowDefinitionHelpers<S extends BuilderState> {
|
|
369
|
+
workflow<const I extends z.ZodTypeAny, const O extends z.ZodTypeAny>(definition: WorkflowDefinitionResolved<S, I, O> & {
|
|
370
|
+
input: I;
|
|
371
|
+
output: O;
|
|
372
|
+
}): WorkflowDefinitionResolved<S, I, O> & {
|
|
373
|
+
input: I;
|
|
374
|
+
output: O;
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
/** Agent registry shape constrained by the previously declared models/tools/skills. */
|
|
378
|
+
export type AgentsConfig<S extends BuilderState, A extends {
|
|
379
|
+
[K in keyof A]: AgentSchemaFields;
|
|
380
|
+
} = Record<string, AgentSchemaFields>> = {
|
|
381
|
+
[K in keyof A]: A[K] & AgentDefinitionFor<S, A[K]>;
|
|
382
|
+
};
|
|
383
|
+
/** Workflow registry shape constrained by the previously declared agents. */
|
|
384
|
+
export type WorkflowsConfig<S extends BuilderState, W extends {
|
|
385
|
+
[K in keyof W]: WorkflowSchemaFields;
|
|
386
|
+
} = Record<string, WorkflowSchemaFields>> = {
|
|
387
|
+
[K in keyof W]: W[K] & WorkflowDefinitionFor<S, W[K]>;
|
|
388
|
+
};
|
|
389
|
+
/** Typed workflow invoker available under `session.workflows.<id>`. */
|
|
390
|
+
export interface WorkflowInvoker<S extends BuilderState, K extends keyof NonNullable<S['workflows']>> {
|
|
391
|
+
/** Runs the workflow to completion and resolves its validated output. */
|
|
392
|
+
prompt(input: WorkflowInput<S, K>, opts?: InvokeOptions): Promise<WorkflowOutput<S, K>>;
|
|
393
|
+
/** Streams run events while the workflow executes. */
|
|
394
|
+
stream(input: WorkflowInput<S, K>, opts?: InvokeOptions): AsyncIterable<RunEvent>;
|
|
395
|
+
}
|
|
396
|
+
/** Typed agent invoker available under `session.agents.<id>`. */
|
|
397
|
+
export interface AgentInvoker<S extends BuilderState, K extends keyof NonNullable<S['agents']>> {
|
|
398
|
+
/** Runs the agent to completion and resolves its validated output. */
|
|
399
|
+
prompt(input: AgentInput<S, K>, opts?: InvokeOptions): Promise<AgentOutput<S, K>>;
|
|
400
|
+
/** Streams run events while the agent executes. */
|
|
401
|
+
stream(input: AgentInput<S, K>, opts?: InvokeOptions): AsyncIterable<RunEvent>;
|
|
402
|
+
}
|
|
403
|
+
/** Compile-time-only namespace exposed as `harness.$infer`. */
|
|
404
|
+
export type InferTypes<S extends BuilderState> = {
|
|
405
|
+
models: keyof NonNullable<S['models']>;
|
|
406
|
+
tools: keyof NonNullable<S['tools']>;
|
|
407
|
+
skills: keyof NonNullable<S['skills']>;
|
|
408
|
+
agents: {
|
|
409
|
+
[K in keyof NonNullable<S['agents']>]: {
|
|
410
|
+
input: AgentInput<S, K>;
|
|
411
|
+
output: AgentOutput<S, K>;
|
|
412
|
+
};
|
|
413
|
+
};
|
|
414
|
+
workflows: {
|
|
415
|
+
[K in keyof NonNullable<S['workflows']>]: {
|
|
416
|
+
input: WorkflowInput<S, K>;
|
|
417
|
+
output: WorkflowOutput<S, K>;
|
|
418
|
+
};
|
|
419
|
+
};
|
|
420
|
+
};
|
|
421
|
+
/** Harness handle returned from `build()`. */
|
|
422
|
+
export interface Harness<S extends BuilderState> {
|
|
423
|
+
/** Opens or creates a fresh session facade bound to `id`. */
|
|
424
|
+
getSession(id: string): Promise<Session<S>>;
|
|
425
|
+
/** Returns a synchronous, data-only snapshot of resolved adapter setup. */
|
|
426
|
+
inspect(): HarnessInspection;
|
|
427
|
+
/** Closes harness-owned adapters and returns any shutdown errors. */
|
|
428
|
+
shutdown(): Promise<{
|
|
429
|
+
errors: HarnessError[];
|
|
430
|
+
}>;
|
|
431
|
+
/** Phantom inference handle. Harness value is always the literal `{}`. */
|
|
432
|
+
readonly $infer: InferTypes<S>;
|
|
433
|
+
}
|
|
434
|
+
/** Session-scoped operational API. */
|
|
435
|
+
export interface Session<S extends BuilderState> {
|
|
436
|
+
readonly id: string;
|
|
437
|
+
readonly agents: {
|
|
438
|
+
readonly [K in keyof NonNullable<S['agents']>]: AgentInvoker<S, K>;
|
|
439
|
+
};
|
|
440
|
+
readonly workflows: {
|
|
441
|
+
readonly [K in keyof NonNullable<S['workflows']>]: WorkflowInvoker<S, K>;
|
|
442
|
+
};
|
|
443
|
+
memory: SessionMemory;
|
|
444
|
+
history: ConversationHistory;
|
|
445
|
+
clearHistory(): Promise<void>;
|
|
446
|
+
replaceHistory(messages: ReadonlyArray<Omit<Message, 'id' | 'timestamp'>>): Promise<void>;
|
|
447
|
+
close(): Promise<void>;
|
|
448
|
+
}
|
|
449
|
+
/** Structured run-event error payload. */
|
|
450
|
+
export interface SerializedError {
|
|
451
|
+
code: string;
|
|
452
|
+
category: string;
|
|
453
|
+
retriable: boolean;
|
|
454
|
+
message: string;
|
|
455
|
+
meta?: Record<string, unknown>;
|
|
456
|
+
}
|
|
457
|
+
/** Harness streaming events emitted from `session.workflows.<id>.stream(...)`. */
|
|
458
|
+
export type RunEvent = {
|
|
459
|
+
type: 'run.started';
|
|
460
|
+
runId: string;
|
|
461
|
+
at: string;
|
|
462
|
+
} | {
|
|
463
|
+
type: 'run.finished';
|
|
464
|
+
runId: string;
|
|
465
|
+
at: string;
|
|
466
|
+
output?: JsonValue;
|
|
467
|
+
error?: SerializedError;
|
|
468
|
+
} | {
|
|
469
|
+
type: 'agent.started';
|
|
470
|
+
runId: string;
|
|
471
|
+
agentId: string;
|
|
472
|
+
at: string;
|
|
473
|
+
} | {
|
|
474
|
+
type: 'agent.finished';
|
|
475
|
+
runId: string;
|
|
476
|
+
agentId: string;
|
|
477
|
+
at: string;
|
|
478
|
+
output?: JsonValue;
|
|
479
|
+
error?: SerializedError;
|
|
480
|
+
} | {
|
|
481
|
+
type: 'model.delta';
|
|
482
|
+
runId: string;
|
|
483
|
+
agentId: string;
|
|
484
|
+
delta: string;
|
|
485
|
+
} | {
|
|
486
|
+
type: 'tool.started';
|
|
487
|
+
runId: string;
|
|
488
|
+
agentId: string;
|
|
489
|
+
toolId: string;
|
|
490
|
+
callId: string;
|
|
491
|
+
input: JsonValue;
|
|
492
|
+
} | {
|
|
493
|
+
type: 'tool.finished';
|
|
494
|
+
runId: string;
|
|
495
|
+
agentId: string;
|
|
496
|
+
toolId: string;
|
|
497
|
+
callId: string;
|
|
498
|
+
output?: JsonValue;
|
|
499
|
+
error?: SerializedError;
|
|
500
|
+
} | {
|
|
501
|
+
type: 'model.message';
|
|
502
|
+
runId: string;
|
|
503
|
+
agentId: string;
|
|
504
|
+
message: Message;
|
|
505
|
+
} | {
|
|
506
|
+
type: 'model.object.partial';
|
|
507
|
+
runId: string;
|
|
508
|
+
agentId?: string;
|
|
509
|
+
partial: JsonValue;
|
|
510
|
+
} | {
|
|
511
|
+
type: 'model.object';
|
|
512
|
+
runId: string;
|
|
513
|
+
agentId?: string;
|
|
514
|
+
object: JsonValue;
|
|
515
|
+
} | {
|
|
516
|
+
type: 'model.embedding.completed';
|
|
517
|
+
runId: string;
|
|
518
|
+
agentId?: string;
|
|
519
|
+
count: number;
|
|
520
|
+
dimensions?: number;
|
|
521
|
+
usage?: TokenUsage;
|
|
522
|
+
} | {
|
|
523
|
+
type: 'model.rerank.completed';
|
|
524
|
+
runId: string;
|
|
525
|
+
agentId?: string;
|
|
526
|
+
count: number;
|
|
527
|
+
topN?: number;
|
|
528
|
+
usage?: TokenUsage;
|
|
529
|
+
} | {
|
|
530
|
+
type: 'stream.overflow';
|
|
531
|
+
runId: string;
|
|
532
|
+
at: string;
|
|
533
|
+
dropped: number;
|
|
534
|
+
};
|
|
535
|
+
/** Fluent builder contract for composing a harness. */
|
|
536
|
+
export interface HarnessBuilder<S extends BuilderState = {}> {
|
|
537
|
+
telemetry(opts: TelemetryOptions): HarnessBuilder<S>;
|
|
538
|
+
logger(logger: Logger): HarnessBuilder<S>;
|
|
539
|
+
state(store: StateStore): HarnessBuilder<S>;
|
|
540
|
+
sandbox(sandbox?: Sandbox<any>): HarnessBuilder<S>;
|
|
541
|
+
runtime(runtime: DurableRuntimeAdapter): HarnessBuilder<S>;
|
|
542
|
+
requires(capabilities: readonly AdapterCapability[]): HarnessBuilder<S>;
|
|
543
|
+
defaults(defaults: HarnessDefaults): HarnessBuilder<S>;
|
|
544
|
+
models<const M extends ModelsConfig>(models: M): HarnessBuilder<S & {
|
|
545
|
+
models: M;
|
|
546
|
+
}>;
|
|
547
|
+
tools<const T extends ToolsConfig>(tools: T): HarnessBuilder<S & {
|
|
548
|
+
tools: T;
|
|
549
|
+
}>;
|
|
550
|
+
skills<const K extends SkillsConfig>(skills: K): HarnessBuilder<S & {
|
|
551
|
+
skills: K;
|
|
552
|
+
}>;
|
|
553
|
+
agents<const A extends {
|
|
554
|
+
[K in keyof A]: AgentDefinition<any, any, any>;
|
|
555
|
+
}>(agents: (helpers: AgentDefinitionHelpers<S & {
|
|
556
|
+
models: NonNullable<S['models']>;
|
|
557
|
+
tools: NonNullable<S['tools']>;
|
|
558
|
+
skills: NonNullable<S['skills']>;
|
|
559
|
+
}>) => A): HarnessBuilder<S & {
|
|
560
|
+
agents: A;
|
|
561
|
+
}>;
|
|
562
|
+
agents<const A extends {
|
|
563
|
+
[K in keyof A]: {
|
|
564
|
+
input: z.ZodTypeAny;
|
|
565
|
+
output: z.ZodTypeAny;
|
|
566
|
+
};
|
|
567
|
+
}>(agents: AgentsConfigFromSchemaMaps<S & {
|
|
568
|
+
models: NonNullable<S['models']>;
|
|
569
|
+
tools: NonNullable<S['tools']>;
|
|
570
|
+
skills: NonNullable<S['skills']>;
|
|
571
|
+
}, A>): HarnessBuilder<S & {
|
|
572
|
+
agents: AgentsConfigFromSchemaMaps<S & {
|
|
573
|
+
models: NonNullable<S['models']>;
|
|
574
|
+
tools: NonNullable<S['tools']>;
|
|
575
|
+
skills: NonNullable<S['skills']>;
|
|
576
|
+
}, A>;
|
|
577
|
+
}>;
|
|
578
|
+
agents<const A extends {
|
|
579
|
+
[K in keyof A]: AgentDefinitionFor<S & {
|
|
580
|
+
models: NonNullable<S['models']>;
|
|
581
|
+
tools: NonNullable<S['tools']>;
|
|
582
|
+
skills: NonNullable<S['skills']>;
|
|
583
|
+
}, A[K]>;
|
|
584
|
+
}>(agents: A): HarnessBuilder<S & {
|
|
585
|
+
agents: A;
|
|
586
|
+
}>;
|
|
587
|
+
workflows<const W extends {
|
|
588
|
+
[K in keyof W]: WorkflowDefinition<any, any, any>;
|
|
589
|
+
}>(workflows: (helpers: WorkflowDefinitionHelpers<S & {
|
|
590
|
+
agents: NonNullable<S['agents']>;
|
|
591
|
+
}>) => W): HarnessBuilder<S & {
|
|
592
|
+
workflows: W;
|
|
593
|
+
}>;
|
|
594
|
+
workflows<const W extends {
|
|
595
|
+
[K in keyof W]: {
|
|
596
|
+
input: z.ZodTypeAny;
|
|
597
|
+
output: z.ZodTypeAny;
|
|
598
|
+
};
|
|
599
|
+
}>(workflows: WorkflowsConfigFromSchemaMaps<S & {
|
|
600
|
+
agents: NonNullable<S['agents']>;
|
|
601
|
+
}, W>): HarnessBuilder<S & {
|
|
602
|
+
workflows: WorkflowsConfigFromSchemaMaps<S & {
|
|
603
|
+
agents: NonNullable<S['agents']>;
|
|
604
|
+
}, W>;
|
|
605
|
+
}>;
|
|
606
|
+
workflows<const W extends {
|
|
607
|
+
[K in keyof W]: WorkflowDefinitionFor<S & {
|
|
608
|
+
agents: NonNullable<S['agents']>;
|
|
609
|
+
}, W[K]>;
|
|
610
|
+
}>(workflows: W): HarnessBuilder<S & {
|
|
611
|
+
workflows: W;
|
|
612
|
+
}>;
|
|
613
|
+
build(): Harness<S>;
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* Creates the chainable harness builder used to define a harness system.
|
|
617
|
+
*
|
|
618
|
+
* Application code should compose models, tools, skills, agents, and workflows here,
|
|
619
|
+
* build the harness, and then execute work exclusively through `harness.getSession(...)`.
|
|
620
|
+
*
|
|
621
|
+
* @example
|
|
622
|
+
* ```ts
|
|
623
|
+
* const harness = defineHarness()
|
|
624
|
+
* .models({ fast: { provider, model: 'gpt-4.1-mini', capabilities: ['object'] } })
|
|
625
|
+
* .agents({ summarize: { model: 'fast', instructions: 'Summarize the input.' } })
|
|
626
|
+
* .workflows({
|
|
627
|
+
* summarize_ticket: {
|
|
628
|
+
* input: z.object({ ticket: z.string() }),
|
|
629
|
+
* output: z.string(),
|
|
630
|
+
* handler: (ctx) => ctx.agents.summarize(ctx.input.ticket)
|
|
631
|
+
* }
|
|
632
|
+
* })
|
|
633
|
+
* .build()
|
|
634
|
+
*
|
|
635
|
+
* const session = await harness.getSession('ticket-123')
|
|
636
|
+
* const summary = await session.workflows.summarize_ticket.prompt({ ticket: 'Cannot log in' })
|
|
637
|
+
* ```
|
|
638
|
+
*/
|
|
639
|
+
export declare function defineHarness(opts?: HarnessOptions): HarnessBuilder<{}>;
|
|
640
|
+
export {};
|