@ai-sdk/harness 0.0.0 → 1.0.0-beta.14
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/CHANGELOG.md +110 -0
- package/LICENSE +13 -0
- package/README.md +142 -0
- package/agent/index.ts +47 -0
- package/bridge/index.ts +10 -0
- package/dist/agent/index.d.ts +1521 -0
- package/dist/agent/index.js +2958 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/bridge/index.d.ts +111 -0
- package/dist/bridge/index.js +415 -0
- package/dist/bridge/index.js.map +1 -0
- package/dist/index.d.ts +1536 -0
- package/dist/index.js +15834 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/index.d.ts +225 -0
- package/dist/utils/index.js +12148 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +99 -1
- package/src/agent/harness-agent-session.ts +509 -0
- package/src/agent/harness-agent-settings.ts +131 -0
- package/src/agent/harness-agent-tool-approval-continuation.ts +94 -0
- package/src/agent/harness-agent-types.ts +50 -0
- package/src/agent/harness-agent.ts +819 -0
- package/src/agent/internal/bootstrap-recipe.ts +124 -0
- package/src/agent/internal/bridge-port-registry.ts +52 -0
- package/src/agent/internal/harness-stream-text-result.ts +720 -0
- package/src/agent/internal/lifecycle-state-validation.ts +95 -0
- package/src/agent/internal/permission-mode.ts +50 -0
- package/src/agent/internal/resolve-observability.ts +128 -0
- package/src/agent/internal/run-prompt.ts +813 -0
- package/src/agent/internal/strip-work-dir.ts +68 -0
- package/src/agent/internal/to-harness-stream.ts +75 -0
- package/src/agent/internal/translate-stream-part.ts +221 -0
- package/src/agent/internal/turn-telemetry.ts +359 -0
- package/src/agent/observability/file-reporter.ts +206 -0
- package/src/agent/observability/index.ts +15 -0
- package/src/agent/observability/trace-tree-reporter.ts +122 -0
- package/src/agent/observability/types.ts +86 -0
- package/src/agent/prewarm.ts +47 -0
- package/src/bridge/index.ts +702 -0
- package/src/errors/harness-capability-unsupported-error.ts +41 -0
- package/src/errors/harness-error.ts +22 -0
- package/src/index.ts +3 -0
- package/src/utils/bridge-ready.ts +277 -0
- package/src/utils/classify-disk-log.ts +43 -0
- package/src/utils/index.ts +15 -0
- package/src/utils/sandbox-channel.ts +453 -0
- package/src/v1/harness-v1-bootstrap.ts +46 -0
- package/src/v1/harness-v1-bridge-protocol.ts +310 -0
- package/src/v1/harness-v1-builtin-tool.ts +138 -0
- package/src/v1/harness-v1-call-warning.ts +22 -0
- package/src/v1/harness-v1-diagnostic.ts +66 -0
- package/src/v1/harness-v1-lifecycle-state.ts +65 -0
- package/src/v1/harness-v1-metadata.ts +13 -0
- package/src/v1/harness-v1-network-sandbox-session.ts +123 -0
- package/src/v1/harness-v1-observability.ts +20 -0
- package/src/v1/harness-v1-permission-mode.ts +11 -0
- package/src/v1/harness-v1-prompt-control.ts +41 -0
- package/src/v1/harness-v1-prompt.ts +11 -0
- package/src/v1/harness-v1-sandbox-provider.ts +76 -0
- package/src/v1/harness-v1-session.ts +272 -0
- package/src/v1/harness-v1-skill.ts +36 -0
- package/src/v1/harness-v1-stream-part.ts +363 -0
- package/src/v1/harness-v1-tool-spec.ts +31 -0
- package/src/v1/harness-v1.ts +83 -0
- package/src/v1/index.ts +93 -0
- package/utils/index.ts +1 -0
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
JSONValue,
|
|
3
|
+
LanguageModelV4FinishReason,
|
|
4
|
+
LanguageModelV4ToolApprovalRequest,
|
|
5
|
+
LanguageModelV4ToolCall,
|
|
6
|
+
LanguageModelV4ToolResult,
|
|
7
|
+
LanguageModelV4Usage,
|
|
8
|
+
SharedV4ProviderMetadata,
|
|
9
|
+
} from '@ai-sdk/provider';
|
|
10
|
+
import { z } from 'zod/v4';
|
|
11
|
+
import type { HarnessV1CallWarning } from './harness-v1-call-warning';
|
|
12
|
+
import type { HarnessV1Metadata } from './harness-v1-metadata';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* One event emitted by a harness adapter during a prompt turn.
|
|
16
|
+
*
|
|
17
|
+
* Mirrors `LanguageModelV4StreamPart` on the variants it shares so a
|
|
18
|
+
* `HarnessAgent` can pipe events through to AI SDK consumers with minimal
|
|
19
|
+
* translation. Primitive types from the V4 spec (`LanguageModelV4ToolCall`,
|
|
20
|
+
* `LanguageModelV4ToolResult`, `LanguageModelV4ToolApprovalRequest`,
|
|
21
|
+
* `LanguageModelV4Usage`, `LanguageModelV4FinishReason`) are reused
|
|
22
|
+
* verbatim — type-compat tests assert this stays the case.
|
|
23
|
+
*
|
|
24
|
+
* The metadata field is named `harnessMetadata` (not `providerMetadata`)
|
|
25
|
+
* because a harness is a peer to a provider, not a kind of provider. The
|
|
26
|
+
* agent rebinds it when forwarding to AI SDK consumers.
|
|
27
|
+
*/
|
|
28
|
+
export type HarnessV1StreamPart =
|
|
29
|
+
| {
|
|
30
|
+
type: 'stream-start';
|
|
31
|
+
warnings?: ReadonlyArray<HarnessV1CallWarning>;
|
|
32
|
+
/**
|
|
33
|
+
* The model the runtime actually resolved to for this turn, when the
|
|
34
|
+
* adapter learns it at stream start (e.g. Claude Code's `init` message
|
|
35
|
+
* reports the resolved/default model). Surfaced into telemetry as
|
|
36
|
+
* `gen_ai.request.model`. Omitted when the adapter doesn't know it here.
|
|
37
|
+
*/
|
|
38
|
+
modelId?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Text blocks
|
|
42
|
+
| { type: 'text-start'; id: string; harnessMetadata?: HarnessV1Metadata }
|
|
43
|
+
| {
|
|
44
|
+
type: 'text-delta';
|
|
45
|
+
id: string;
|
|
46
|
+
delta: string;
|
|
47
|
+
harnessMetadata?: HarnessV1Metadata;
|
|
48
|
+
}
|
|
49
|
+
| { type: 'text-end'; id: string; harnessMetadata?: HarnessV1Metadata }
|
|
50
|
+
|
|
51
|
+
// Reasoning blocks
|
|
52
|
+
| { type: 'reasoning-start'; id: string; harnessMetadata?: HarnessV1Metadata }
|
|
53
|
+
| {
|
|
54
|
+
type: 'reasoning-delta';
|
|
55
|
+
id: string;
|
|
56
|
+
delta: string;
|
|
57
|
+
harnessMetadata?: HarnessV1Metadata;
|
|
58
|
+
}
|
|
59
|
+
| { type: 'reasoning-end'; id: string; harnessMetadata?: HarnessV1Metadata }
|
|
60
|
+
|
|
61
|
+
// Tool calls, approvals, results — reuse V4 primitives.
|
|
62
|
+
//
|
|
63
|
+
// `nativeName` is the only harness-only extension on `tool-call`. It lets
|
|
64
|
+
// adapters surface the runtime's native name for a builtin when it differs
|
|
65
|
+
// from the wire `toolName` (e.g. `toolName: 'bash'`, `nativeName: 'Bash'`).
|
|
66
|
+
//
|
|
67
|
+
// Whether the call was executed by the underlying runtime (Claude Code's
|
|
68
|
+
// built-in `Bash`, Codex's `shell`) vs. needs host dispatch is signalled by
|
|
69
|
+
// the standard `providerExecuted` field on `LanguageModelV4ToolCall` —
|
|
70
|
+
// `true` for runtime-executed builtins, false/undefined for host tools.
|
|
71
|
+
| (LanguageModelV4ToolCall & {
|
|
72
|
+
nativeName?: string;
|
|
73
|
+
})
|
|
74
|
+
| LanguageModelV4ToolApprovalRequest
|
|
75
|
+
| LanguageModelV4ToolResult
|
|
76
|
+
|
|
77
|
+
// Step boundary inside a multi-step turn.
|
|
78
|
+
| {
|
|
79
|
+
type: 'finish-step';
|
|
80
|
+
finishReason: LanguageModelV4FinishReason;
|
|
81
|
+
usage: LanguageModelV4Usage;
|
|
82
|
+
harnessMetadata?: HarnessV1Metadata;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Turn end.
|
|
86
|
+
| {
|
|
87
|
+
type: 'finish';
|
|
88
|
+
finishReason: LanguageModelV4FinishReason;
|
|
89
|
+
totalUsage: LanguageModelV4Usage;
|
|
90
|
+
harnessMetadata?: HarnessV1Metadata;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Workspace file mutation that occurred through an opaque underlying
|
|
94
|
+
// mechanism (one with no visible `tool-call` carrying the same data, e.g.
|
|
95
|
+
// Codex's internal `apply_patch`). Emitted per changed path. Path-only by
|
|
96
|
+
// design — when the mutation goes through a visible tool call, the
|
|
97
|
+
// tool-call/tool-result pair already carries the information.
|
|
98
|
+
| {
|
|
99
|
+
type: 'file-change';
|
|
100
|
+
event: 'create' | 'modify' | 'delete';
|
|
101
|
+
path: string;
|
|
102
|
+
harnessMetadata?: HarnessV1Metadata;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Context compaction performed by the underlying runtime (Claude Code's
|
|
106
|
+
// native compaction, Pi's summarization). Observation only — the runtime
|
|
107
|
+
// owns the compaction; the harness neither implements nor schedules it.
|
|
108
|
+
// Emitted once, on completion, since `summary`/`tokensAfter` only exist then.
|
|
109
|
+
| {
|
|
110
|
+
type: 'compaction';
|
|
111
|
+
trigger: 'manual' | 'auto';
|
|
112
|
+
summary: string;
|
|
113
|
+
tokensBefore?: number;
|
|
114
|
+
tokensAfter?: number;
|
|
115
|
+
harnessMetadata?: HarnessV1Metadata;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Errors. Multiple may be emitted in a single turn.
|
|
119
|
+
| { type: 'error'; error: unknown }
|
|
120
|
+
|
|
121
|
+
// Adapter-specific passthrough. Consumers can opt in to receive these via
|
|
122
|
+
// `HarnessAgent` settings; otherwise they are dropped.
|
|
123
|
+
| { type: 'raw'; rawValue: unknown };
|
|
124
|
+
|
|
125
|
+
/*
|
|
126
|
+
* Runtime (Zod) encoding of `HarnessV1StreamPart`.
|
|
127
|
+
*
|
|
128
|
+
* `HarnessV1StreamPart` is a compile-time type built on `LanguageModelV4*`
|
|
129
|
+
* types that ship no runtime validator. Bridge adapters receive these parts as
|
|
130
|
+
* JSON across a trust boundary (the sandbox WebSocket), so they need a runtime
|
|
131
|
+
* schema. These schemas ARE that encoding — one source of truth, kept from
|
|
132
|
+
* diverging from the type by the `_assignable` guard below and the mutual
|
|
133
|
+
* `toEqualTypeOf` assertion in `harness-v1-stream-part.test-d.ts`.
|
|
134
|
+
*
|
|
135
|
+
* Members are exported individually so `harness-v1-bridge-protocol.ts` can
|
|
136
|
+
* compose them into the bridge outbound union alongside the transport frames.
|
|
137
|
+
*/
|
|
138
|
+
|
|
139
|
+
const harnessV1JsonValueSchema: z.ZodType<JSONValue> = z.lazy(() =>
|
|
140
|
+
z.union([
|
|
141
|
+
z.string(),
|
|
142
|
+
z.number(),
|
|
143
|
+
z.boolean(),
|
|
144
|
+
z.null(),
|
|
145
|
+
z.array(harnessV1JsonValueSchema),
|
|
146
|
+
z.record(z.string(), harnessV1JsonValueSchema),
|
|
147
|
+
]),
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
/*
|
|
151
|
+
* Tool-result values. The inferred type is the spec's `NonNullable<JSONValue>`
|
|
152
|
+
* (matching `LanguageModelV4ToolResult`), but the runtime validator
|
|
153
|
+
* deliberately also accepts `null`: adapters emit `result: <value> ?? null` for
|
|
154
|
+
* tools that produced no output, and that `null` must survive the trust
|
|
155
|
+
* boundary unchanged (it reaches consumers exactly as it did before this schema
|
|
156
|
+
* existed, when a cast hid it). Leniency at runtime, strictness in the type.
|
|
157
|
+
*/
|
|
158
|
+
const harnessV1ToolResultValueSchema =
|
|
159
|
+
harnessV1JsonValueSchema as unknown as z.ZodType<NonNullable<JSONValue>>;
|
|
160
|
+
|
|
161
|
+
const harnessV1JsonObjectSchema = z.record(
|
|
162
|
+
z.string(),
|
|
163
|
+
harnessV1JsonValueSchema,
|
|
164
|
+
) as unknown as z.ZodType<Record<string, JSONValue>>;
|
|
165
|
+
|
|
166
|
+
const harnessV1MetadataSchema = z.record(
|
|
167
|
+
z.string(),
|
|
168
|
+
z.record(z.string(), harnessV1JsonValueSchema),
|
|
169
|
+
) as unknown as z.ZodType<HarnessV1Metadata>;
|
|
170
|
+
|
|
171
|
+
const harnessV1ProviderMetadataSchema = z.record(
|
|
172
|
+
z.string(),
|
|
173
|
+
z.record(z.string(), harnessV1JsonValueSchema),
|
|
174
|
+
) as unknown as z.ZodType<SharedV4ProviderMetadata>;
|
|
175
|
+
|
|
176
|
+
const harnessV1CallWarningSchema = z.union([
|
|
177
|
+
z.object({
|
|
178
|
+
type: z.literal('unsupported-setting'),
|
|
179
|
+
setting: z.string(),
|
|
180
|
+
details: z.string().optional(),
|
|
181
|
+
}),
|
|
182
|
+
z.object({
|
|
183
|
+
type: z.literal('unsupported-tool'),
|
|
184
|
+
tool: z.string(),
|
|
185
|
+
details: z.string().optional(),
|
|
186
|
+
}),
|
|
187
|
+
z.object({ type: z.literal('other'), message: z.string() }),
|
|
188
|
+
]) as z.ZodType<HarnessV1CallWarning>;
|
|
189
|
+
|
|
190
|
+
const harnessV1UsageSchema = z.object({
|
|
191
|
+
inputTokens: z.object({
|
|
192
|
+
total: z.number().optional(),
|
|
193
|
+
noCache: z.number().optional(),
|
|
194
|
+
cacheRead: z.number().optional(),
|
|
195
|
+
cacheWrite: z.number().optional(),
|
|
196
|
+
}),
|
|
197
|
+
outputTokens: z.object({
|
|
198
|
+
total: z.number().optional(),
|
|
199
|
+
text: z.number().optional(),
|
|
200
|
+
reasoning: z.number().optional(),
|
|
201
|
+
}),
|
|
202
|
+
raw: harnessV1JsonObjectSchema.optional(),
|
|
203
|
+
}) as unknown as z.ZodType<LanguageModelV4Usage>;
|
|
204
|
+
|
|
205
|
+
const harnessV1FinishReasonSchema = z.object({
|
|
206
|
+
unified: z.enum([
|
|
207
|
+
'stop',
|
|
208
|
+
'length',
|
|
209
|
+
'content-filter',
|
|
210
|
+
'tool-calls',
|
|
211
|
+
'error',
|
|
212
|
+
'other',
|
|
213
|
+
]),
|
|
214
|
+
raw: z.string().optional(),
|
|
215
|
+
}) as unknown as z.ZodType<LanguageModelV4FinishReason>;
|
|
216
|
+
|
|
217
|
+
export const harnessV1StreamStartPartSchema = z.object({
|
|
218
|
+
type: z.literal('stream-start'),
|
|
219
|
+
warnings: z.array(harnessV1CallWarningSchema).readonly().optional(),
|
|
220
|
+
modelId: z.string().optional(),
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
export const harnessV1TextStartPartSchema = z.object({
|
|
224
|
+
type: z.literal('text-start'),
|
|
225
|
+
id: z.string(),
|
|
226
|
+
harnessMetadata: harnessV1MetadataSchema.optional(),
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
export const harnessV1TextDeltaPartSchema = z.object({
|
|
230
|
+
type: z.literal('text-delta'),
|
|
231
|
+
id: z.string(),
|
|
232
|
+
delta: z.string(),
|
|
233
|
+
harnessMetadata: harnessV1MetadataSchema.optional(),
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
export const harnessV1TextEndPartSchema = z.object({
|
|
237
|
+
type: z.literal('text-end'),
|
|
238
|
+
id: z.string(),
|
|
239
|
+
harnessMetadata: harnessV1MetadataSchema.optional(),
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
export const harnessV1ReasoningStartPartSchema = z.object({
|
|
243
|
+
type: z.literal('reasoning-start'),
|
|
244
|
+
id: z.string(),
|
|
245
|
+
harnessMetadata: harnessV1MetadataSchema.optional(),
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
export const harnessV1ReasoningDeltaPartSchema = z.object({
|
|
249
|
+
type: z.literal('reasoning-delta'),
|
|
250
|
+
id: z.string(),
|
|
251
|
+
delta: z.string(),
|
|
252
|
+
harnessMetadata: harnessV1MetadataSchema.optional(),
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
export const harnessV1ReasoningEndPartSchema = z.object({
|
|
256
|
+
type: z.literal('reasoning-end'),
|
|
257
|
+
id: z.string(),
|
|
258
|
+
harnessMetadata: harnessV1MetadataSchema.optional(),
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
export const harnessV1ToolCallPartSchema = z.object({
|
|
262
|
+
type: z.literal('tool-call'),
|
|
263
|
+
toolCallId: z.string(),
|
|
264
|
+
toolName: z.string(),
|
|
265
|
+
input: z.string(),
|
|
266
|
+
providerExecuted: z.boolean().optional(),
|
|
267
|
+
dynamic: z.boolean().optional(),
|
|
268
|
+
providerMetadata: harnessV1ProviderMetadataSchema.optional(),
|
|
269
|
+
nativeName: z.string().optional(),
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
export const harnessV1ToolApprovalRequestPartSchema = z.object({
|
|
273
|
+
type: z.literal('tool-approval-request'),
|
|
274
|
+
approvalId: z.string(),
|
|
275
|
+
toolCallId: z.string(),
|
|
276
|
+
providerMetadata: harnessV1ProviderMetadataSchema.optional(),
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
export const harnessV1ToolResultPartSchema = z.object({
|
|
280
|
+
type: z.literal('tool-result'),
|
|
281
|
+
toolCallId: z.string(),
|
|
282
|
+
toolName: z.string(),
|
|
283
|
+
result: harnessV1ToolResultValueSchema,
|
|
284
|
+
isError: z.boolean().optional(),
|
|
285
|
+
preliminary: z.boolean().optional(),
|
|
286
|
+
dynamic: z.boolean().optional(),
|
|
287
|
+
providerMetadata: harnessV1ProviderMetadataSchema.optional(),
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
export const harnessV1FinishStepPartSchema = z.object({
|
|
291
|
+
type: z.literal('finish-step'),
|
|
292
|
+
finishReason: harnessV1FinishReasonSchema,
|
|
293
|
+
usage: harnessV1UsageSchema,
|
|
294
|
+
harnessMetadata: harnessV1MetadataSchema.optional(),
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
export const harnessV1FinishPartSchema = z.object({
|
|
298
|
+
type: z.literal('finish'),
|
|
299
|
+
finishReason: harnessV1FinishReasonSchema,
|
|
300
|
+
totalUsage: harnessV1UsageSchema,
|
|
301
|
+
harnessMetadata: harnessV1MetadataSchema.optional(),
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
export const harnessV1FileChangePartSchema = z.object({
|
|
305
|
+
type: z.literal('file-change'),
|
|
306
|
+
event: z.enum(['create', 'modify', 'delete']),
|
|
307
|
+
path: z.string(),
|
|
308
|
+
harnessMetadata: harnessV1MetadataSchema.optional(),
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
export const harnessV1CompactionPartSchema = z.object({
|
|
312
|
+
type: z.literal('compaction'),
|
|
313
|
+
trigger: z.enum(['manual', 'auto']),
|
|
314
|
+
summary: z.string(),
|
|
315
|
+
tokensBefore: z.number().optional(),
|
|
316
|
+
tokensAfter: z.number().optional(),
|
|
317
|
+
harnessMetadata: harnessV1MetadataSchema.optional(),
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
export const harnessV1ErrorPartSchema = z.object({
|
|
321
|
+
type: z.literal('error'),
|
|
322
|
+
error: z.unknown(),
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
export const harnessV1RawPartSchema = z.object({
|
|
326
|
+
type: z.literal('raw'),
|
|
327
|
+
rawValue: z.unknown(),
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Assembled discriminated union over every `HarnessV1StreamPart` variant. Left
|
|
332
|
+
* un-annotated so it keeps its precise inferred type — the protocol layer
|
|
333
|
+
* composes the individual member schemas, and the type test asserts the
|
|
334
|
+
* inferred union equals `HarnessV1StreamPart`.
|
|
335
|
+
*/
|
|
336
|
+
export const harnessV1StreamPartSchema = z.discriminatedUnion('type', [
|
|
337
|
+
harnessV1StreamStartPartSchema,
|
|
338
|
+
harnessV1TextStartPartSchema,
|
|
339
|
+
harnessV1TextDeltaPartSchema,
|
|
340
|
+
harnessV1TextEndPartSchema,
|
|
341
|
+
harnessV1ReasoningStartPartSchema,
|
|
342
|
+
harnessV1ReasoningDeltaPartSchema,
|
|
343
|
+
harnessV1ReasoningEndPartSchema,
|
|
344
|
+
harnessV1ToolCallPartSchema,
|
|
345
|
+
harnessV1ToolApprovalRequestPartSchema,
|
|
346
|
+
harnessV1ToolResultPartSchema,
|
|
347
|
+
harnessV1FinishStepPartSchema,
|
|
348
|
+
harnessV1FinishPartSchema,
|
|
349
|
+
harnessV1FileChangePartSchema,
|
|
350
|
+
harnessV1CompactionPartSchema,
|
|
351
|
+
harnessV1ErrorPartSchema,
|
|
352
|
+
harnessV1RawPartSchema,
|
|
353
|
+
]);
|
|
354
|
+
|
|
355
|
+
/*
|
|
356
|
+
* Fail-fast guard at the definition site: the schema's output must be
|
|
357
|
+
* assignable to `HarnessV1StreamPart` (catches a schema variant inventing a
|
|
358
|
+
* shape the type does not allow). The reverse direction — the type being a
|
|
359
|
+
* subset of the schema — is covered by the `toEqualTypeOf` assertion in the
|
|
360
|
+
* type test.
|
|
361
|
+
*/
|
|
362
|
+
const _assignable: z.ZodType<HarnessV1StreamPart> = harnessV1StreamPartSchema;
|
|
363
|
+
void _assignable;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { JSONSchema7 } from '@ai-sdk/provider';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Description of a host-defined tool that the harness should make available
|
|
5
|
+
* to the underlying agent runtime.
|
|
6
|
+
*
|
|
7
|
+
* Adapters translate this into whatever shape their runtime expects (e.g.
|
|
8
|
+
* Claude Code's tool definitions, Codex CLI's tool config, an MCP server
|
|
9
|
+
* exposed to the runtime, …). The adapter does not execute the tool; when
|
|
10
|
+
* the runtime calls it, the adapter emits a `tool-call` event and waits for
|
|
11
|
+
* `submitToolResult` from the caller.
|
|
12
|
+
*/
|
|
13
|
+
export type HarnessV1ToolSpec = {
|
|
14
|
+
/**
|
|
15
|
+
* Tool name the agent runtime sees. Must match the name on incoming
|
|
16
|
+
* `tool-call` events.
|
|
17
|
+
*/
|
|
18
|
+
readonly name: string;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Human-readable description handed to the runtime, used to help the model
|
|
22
|
+
* decide when to call the tool.
|
|
23
|
+
*/
|
|
24
|
+
readonly description?: string;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* JSON Schema describing the expected input for the tool. Optional because
|
|
28
|
+
* some runtimes accept tools without schemas (free-form arguments).
|
|
29
|
+
*/
|
|
30
|
+
readonly inputSchema?: JSONSchema7;
|
|
31
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { FlexibleSchema, ToolSet } from '@ai-sdk/provider-utils';
|
|
2
|
+
import type { HarnessV1Bootstrap } from './harness-v1-bootstrap';
|
|
3
|
+
import type {
|
|
4
|
+
HarnessV1Session,
|
|
5
|
+
HarnessV1StartOptions,
|
|
6
|
+
} from './harness-v1-session';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Versioned specification for a harness adapter — the integration point for
|
|
10
|
+
* one third-party coding-agent runtime (Claude Code, Codex, …).
|
|
11
|
+
*
|
|
12
|
+
* Modelled after `LanguageModelV4`: a tagged spec version, a small set of
|
|
13
|
+
* descriptive fields, and one entry-point method (`doStart`) that yields a
|
|
14
|
+
* session. There is intentionally no static "capabilities" object —
|
|
15
|
+
* optional features are signalled by the presence or absence of optional
|
|
16
|
+
* methods on the prompt-control handle. Adapters that cannot satisfy a request
|
|
17
|
+
* (manual compaction not supported, required port exposure unavailable, …)
|
|
18
|
+
* throw `HarnessCapabilityUnsupportedError` from the method that needs the
|
|
19
|
+
* capability.
|
|
20
|
+
*/
|
|
21
|
+
export type HarnessV1<TBuiltinTools extends ToolSet = ToolSet> = {
|
|
22
|
+
/**
|
|
23
|
+
* Spec version this adapter implements. Always the literal `'harness-v1'`.
|
|
24
|
+
*/
|
|
25
|
+
readonly specificationVersion: 'harness-v1';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Stable identifier for this harness, used as the key inside
|
|
29
|
+
* `HarnessV1Metadata` objects. Conventionally a kebab-case slug matching
|
|
30
|
+
* the package name (`'claude-code'`, `'codex'`).
|
|
31
|
+
*/
|
|
32
|
+
readonly harnessId: string;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Tools the adapter's underlying runtime exposes natively, as a `ToolSet`
|
|
36
|
+
* keyed by what the bridge emits on `tool-call` events
|
|
37
|
+
* (`commonName ?? nativeName`). Each entry is a `HarnessV1BuiltinTool`
|
|
38
|
+
* (a `Tool` plus harness-specific `nativeName` / `commonName` metadata).
|
|
39
|
+
*
|
|
40
|
+
* The agent merges this with consumer-supplied user tools when validating
|
|
41
|
+
* inbound tool calls and when typing the consumer-facing stream.
|
|
42
|
+
*/
|
|
43
|
+
readonly builtinTools: TBuiltinTools;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Whether the adapter can emit approval requests for built-in tools when
|
|
47
|
+
* `permissionMode` is not `'allow-all'`.
|
|
48
|
+
*
|
|
49
|
+
* Custom host-executed tool approvals are handled by `HarnessAgent`, so this
|
|
50
|
+
* only describes adapter-native tool approval support.
|
|
51
|
+
*/
|
|
52
|
+
readonly supportsBuiltinToolApprovals?: boolean;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Optional schema for the adapter-defined `data` payload returned by session
|
|
56
|
+
* lifecycle methods. When present, the adapter promises that exported state
|
|
57
|
+
* validated by this schema can be re-imported in a future
|
|
58
|
+
* `doStart({ resumeFrom })` or `doStart({ continueFrom })` call.
|
|
59
|
+
*/
|
|
60
|
+
readonly lifecycleStateSchema?: FlexibleSchema<unknown>;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Optional bootstrap recipe. When defined, the harness session manager
|
|
64
|
+
* computes a stable identity from the recipe, passes it (along with a
|
|
65
|
+
* one-time recipe-application hook) to the sandbox provider, and applies
|
|
66
|
+
* the recipe idempotently after the provider returns the handle.
|
|
67
|
+
*
|
|
68
|
+
* Adapters with no bootstrap needs omit this. Adapters that need to install
|
|
69
|
+
* deps or ship bridge files into the sandbox declare them here so the
|
|
70
|
+
* provider can cache the result across sessions via snapshots when
|
|
71
|
+
* supported.
|
|
72
|
+
*/
|
|
73
|
+
readonly getBootstrap?: (options?: {
|
|
74
|
+
abortSignal?: AbortSignal;
|
|
75
|
+
}) => PromiseLike<HarnessV1Bootstrap>;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Start a fresh session, resume a parked session via `resumeFrom`, or resume
|
|
79
|
+
* an interrupted turn via `continueFrom`. The host then issues prompts against
|
|
80
|
+
* the returned session, ending with `doDetach`, `doStop`, or `doDestroy`.
|
|
81
|
+
*/
|
|
82
|
+
doStart(options: HarnessV1StartOptions): PromiseLike<HarnessV1Session>;
|
|
83
|
+
};
|
package/src/v1/index.ts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
export type { HarnessV1 } from './harness-v1';
|
|
2
|
+
export type {
|
|
3
|
+
HarnessV1Bootstrap,
|
|
4
|
+
HarnessV1BootstrapCommand,
|
|
5
|
+
HarnessV1BootstrapFile,
|
|
6
|
+
} from './harness-v1-bootstrap';
|
|
7
|
+
export type {
|
|
8
|
+
HarnessV1ContinueTurnOptions,
|
|
9
|
+
HarnessV1PromptTurnOptions,
|
|
10
|
+
HarnessV1Session,
|
|
11
|
+
HarnessV1StartOptions,
|
|
12
|
+
} from './harness-v1-session';
|
|
13
|
+
export type { HarnessV1Observability } from './harness-v1-observability';
|
|
14
|
+
export type { HarnessV1PromptControl } from './harness-v1-prompt-control';
|
|
15
|
+
export type { HarnessV1CallWarning } from './harness-v1-call-warning';
|
|
16
|
+
export type {
|
|
17
|
+
HarnessV1BuiltinTool,
|
|
18
|
+
HarnessV1BuiltinToolName,
|
|
19
|
+
HarnessV1BuiltinToolUseKind,
|
|
20
|
+
} from './harness-v1-builtin-tool';
|
|
21
|
+
export {
|
|
22
|
+
HARNESS_V1_BUILTIN_TOOL_NAMES,
|
|
23
|
+
HARNESS_V1_BUILTIN_TOOLS,
|
|
24
|
+
commonTool,
|
|
25
|
+
} from './harness-v1-builtin-tool';
|
|
26
|
+
export type { HarnessV1Metadata } from './harness-v1-metadata';
|
|
27
|
+
export type { HarnessV1Prompt } from './harness-v1-prompt';
|
|
28
|
+
export type { HarnessV1SandboxProvider } from './harness-v1-sandbox-provider';
|
|
29
|
+
export type {
|
|
30
|
+
HarnessV1ContinueTurnState,
|
|
31
|
+
HarnessV1LifecycleState,
|
|
32
|
+
HarnessV1PendingToolApproval,
|
|
33
|
+
HarnessV1ResumeSessionState,
|
|
34
|
+
} from './harness-v1-lifecycle-state';
|
|
35
|
+
export type {
|
|
36
|
+
HarnessV1NetworkPolicy,
|
|
37
|
+
HarnessV1NetworkSandboxSession,
|
|
38
|
+
} from './harness-v1-network-sandbox-session';
|
|
39
|
+
export type { HarnessV1Skill } from './harness-v1-skill';
|
|
40
|
+
export type { HarnessV1StreamPart } from './harness-v1-stream-part';
|
|
41
|
+
export {
|
|
42
|
+
harnessV1ErrorPartSchema,
|
|
43
|
+
harnessV1FileChangePartSchema,
|
|
44
|
+
harnessV1FinishPartSchema,
|
|
45
|
+
harnessV1FinishStepPartSchema,
|
|
46
|
+
harnessV1RawPartSchema,
|
|
47
|
+
harnessV1ReasoningDeltaPartSchema,
|
|
48
|
+
harnessV1ReasoningEndPartSchema,
|
|
49
|
+
harnessV1ReasoningStartPartSchema,
|
|
50
|
+
harnessV1StreamPartSchema,
|
|
51
|
+
harnessV1StreamStartPartSchema,
|
|
52
|
+
harnessV1TextDeltaPartSchema,
|
|
53
|
+
harnessV1TextEndPartSchema,
|
|
54
|
+
harnessV1TextStartPartSchema,
|
|
55
|
+
harnessV1ToolApprovalRequestPartSchema,
|
|
56
|
+
harnessV1ToolCallPartSchema,
|
|
57
|
+
harnessV1ToolResultPartSchema,
|
|
58
|
+
} from './harness-v1-stream-part';
|
|
59
|
+
export {
|
|
60
|
+
harnessV1BridgeAbortInboundSchema,
|
|
61
|
+
harnessV1BridgeDebugEventSchema,
|
|
62
|
+
harnessV1BridgeDetachInboundSchema,
|
|
63
|
+
harnessV1BridgeDetachSchema,
|
|
64
|
+
harnessV1BridgeHelloSchema,
|
|
65
|
+
harnessV1BridgeInboundCommandSchemas,
|
|
66
|
+
harnessV1BridgeOutboundMessageSchema,
|
|
67
|
+
harnessV1BridgeReadySchema,
|
|
68
|
+
harnessV1BridgeResumeInboundSchema,
|
|
69
|
+
harnessV1BridgeSandboxLogSchema,
|
|
70
|
+
harnessV1BridgeShutdownInboundSchema,
|
|
71
|
+
harnessV1BridgeStartBaseSchema,
|
|
72
|
+
harnessV1BridgeThreadSchema,
|
|
73
|
+
harnessV1BridgeToolApprovalResponseInboundSchema,
|
|
74
|
+
harnessV1BridgeToolResultInboundSchema,
|
|
75
|
+
harnessV1BridgePermissionModeSchema,
|
|
76
|
+
harnessV1BridgeToolWireSchema,
|
|
77
|
+
harnessV1BridgeUserMessageInboundSchema,
|
|
78
|
+
harnessV1DiagnosticFromBridgeFrame,
|
|
79
|
+
type HarnessV1BridgeDebugEvent,
|
|
80
|
+
type HarnessV1BridgeOutboundMessage,
|
|
81
|
+
type HarnessV1BridgeReady,
|
|
82
|
+
type HarnessV1BridgeSandboxLog,
|
|
83
|
+
type HarnessV1BridgeToolWire,
|
|
84
|
+
} from './harness-v1-bridge-protocol';
|
|
85
|
+
export {
|
|
86
|
+
harnessV1DebugConfigSchema,
|
|
87
|
+
harnessV1DebugLevelSchema,
|
|
88
|
+
type HarnessV1DebugConfig,
|
|
89
|
+
type HarnessV1DebugLevel,
|
|
90
|
+
type HarnessV1Diagnostic,
|
|
91
|
+
} from './harness-v1-diagnostic';
|
|
92
|
+
export type { HarnessV1ToolSpec } from './harness-v1-tool-spec';
|
|
93
|
+
export type { HarnessV1PermissionMode } from './harness-v1-permission-mode';
|
package/utils/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../src/utils';
|