@ai-sdk/harness-deepagents 1.0.132 → 1.0.134

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/dist/index.js CHANGED
@@ -1,960 +1,787 @@
1
- // src/deepagents-harness.ts
2
- import { posix } from "path";
3
- import {
4
- commonTool,
5
- HarnessCapabilityUnsupportedError,
6
- harnessV1DiagnosticFromBridgeFrame,
7
- harnessStateDirectoryPath,
8
- harnessSessionDataDirectoryPath
9
- } from "@ai-sdk/harness";
10
- import {
11
- applyCredentialForwarding,
12
- createBridgeToken,
13
- createSandboxCredentialEnvironment,
14
- markBridgeStarting,
15
- createBridgeErrorHandler,
16
- createBridgeStartupError,
17
- drainBridgeProcessStream,
18
- forwardBridgeProcessStream,
19
- getRestrictedSandboxSession,
20
- resolveSandboxHomeDir,
21
- SandboxChannel,
22
- shellQuote,
23
- warnCredentialBrokeringUnavailable,
24
- waitForBridgeReady,
25
- withBridgeToken,
26
- writeSkills
27
- } from "@ai-sdk/harness/utils";
28
- import {
29
- tool
30
- } from "@ai-sdk/provider-utils";
1
+ import { posix } from "node:path";
2
+ import { HarnessCapabilityUnsupportedError, commonTool, harnessSessionDataDirectoryPath, harnessStateDirectoryPath, harnessV1BridgeInboundCommandSchemas, harnessV1BridgeOutboundMessageSchema, harnessV1BridgeStartBaseSchema, harnessV1DiagnosticFromBridgeFrame } from "@ai-sdk/harness";
3
+ import { SandboxChannel, applyCredentialForwarding, createBridgeErrorHandler, createBridgeStartupError, createBridgeToken, createCredentialRequestTransformation, createReadBridgeAsset, drainBridgeProcessStream, forwardBridgeProcessStream, getAiGatewayAuthFromEnv, getRestrictedSandboxSession, isHarnessAuthenticationEnvironment, markBridgeStarting, resolveSandboxCredentialEnvironment, resolveSandboxHomeDir, shellQuote, waitForBridgeReady, warnCredentialBrokeringUnavailable, withBridgeToken, writeSkills } from "@ai-sdk/harness/utils";
4
+ import { tool } from "@ai-sdk/provider-utils";
31
5
  import { WebSocket } from "ws";
32
- import { z as z2 } from "zod/v4";
33
-
34
- // src/deepagents-bootstrap.ts
35
- import { createReadBridgeAsset } from "@ai-sdk/harness/utils";
36
- var readBridgeAsset = createReadBridgeAsset({
37
- "package.json": new URL("./bridge/package.json", import.meta.url),
38
- "pnpm-lock.yaml": new URL("./bridge/pnpm-lock.yaml", import.meta.url),
39
- "index.mjs": new URL("./bridge/index.mjs", import.meta.url)
6
+ import { z } from "zod/v4";
7
+ //#region src/deepagents-bootstrap.ts
8
+ const readBridgeAsset = createReadBridgeAsset({
9
+ "package.json": new URL("./bridge/package.json", import.meta.url),
10
+ "pnpm-lock.yaml": new URL("./bridge/pnpm-lock.yaml", import.meta.url),
11
+ "index.mjs": new URL("./bridge/index.mjs", import.meta.url)
40
12
  });
41
- var DEEPAGENTS_BOOTSTRAP_DIR = ".harness-bootstrap/deepagents";
42
- var RIPGREP_VERSION = "14.1.1";
43
- var RIPGREP_SHA256_X64 = "4cf9f2741e6c465ffdb7c26f38056a59e2a2544b51f7cc128ef28337eeae4d8e";
44
- var RIPGREP_SHA256_ARM = "c827481c4ff4ea10c9dc7a4022c8de5db34a5737cb74484d62eb94a95841ab2f";
45
- var cachedBootstrap;
13
+ const DEEPAGENTS_BOOTSTRAP_DIR = ".harness-bootstrap/deepagents";
14
+ const RIPGREP_VERSION = "14.1.1";
15
+ const RIPGREP_SHA256_X64 = "4cf9f2741e6c465ffdb7c26f38056a59e2a2544b51f7cc128ef28337eeae4d8e";
16
+ const RIPGREP_SHA256_ARM = "c827481c4ff4ea10c9dc7a4022c8de5db34a5737cb74484d62eb94a95841ab2f";
17
+ let cachedBootstrap;
46
18
  async function getDeepAgentsBootstrap() {
47
- if (cachedBootstrap != null) return cachedBootstrap;
48
- const [bridge, pkg, lock] = await Promise.all([
49
- readBridgeAsset("index.mjs"),
50
- readBridgeAsset("package.json"),
51
- readBridgeAsset("pnpm-lock.yaml")
52
- ]);
53
- cachedBootstrap = {
54
- harnessId: "deepagents",
55
- bootstrapDir: DEEPAGENTS_BOOTSTRAP_DIR,
56
- files: [
57
- { path: `${DEEPAGENTS_BOOTSTRAP_DIR}/bridge.mjs`, content: bridge },
58
- { path: `${DEEPAGENTS_BOOTSTRAP_DIR}/package.json`, content: pkg },
59
- { path: `${DEEPAGENTS_BOOTSTRAP_DIR}/pnpm-lock.yaml`, content: lock }
60
- ],
61
- commands: [
62
- { command: installRipgrepCommand() },
63
- {
64
- command: "pnpm install --frozen-lockfile --store-dir .pnpm-store"
65
- }
66
- ]
67
- };
68
- return cachedBootstrap;
19
+ if (cachedBootstrap != null) return cachedBootstrap;
20
+ const [bridge, pkg, lock] = await Promise.all([
21
+ readBridgeAsset("index.mjs"),
22
+ readBridgeAsset("package.json"),
23
+ readBridgeAsset("pnpm-lock.yaml")
24
+ ]);
25
+ cachedBootstrap = {
26
+ harnessId: "deepagents",
27
+ bootstrapDir: DEEPAGENTS_BOOTSTRAP_DIR,
28
+ files: [
29
+ {
30
+ path: `${DEEPAGENTS_BOOTSTRAP_DIR}/bridge.mjs`,
31
+ content: bridge
32
+ },
33
+ {
34
+ path: `${DEEPAGENTS_BOOTSTRAP_DIR}/package.json`,
35
+ content: pkg
36
+ },
37
+ {
38
+ path: `${DEEPAGENTS_BOOTSTRAP_DIR}/pnpm-lock.yaml`,
39
+ content: lock
40
+ }
41
+ ],
42
+ commands: [{ command: installRipgrepCommand() }, { command: "pnpm install --frozen-lockfile --store-dir .pnpm-store" }]
43
+ };
44
+ return cachedBootstrap;
69
45
  }
70
46
  function installRipgrepCommand() {
71
- const v = RIPGREP_VERSION;
72
- return [
73
- "command -v rg >/dev/null 2>&1 || {",
74
- 'case "$(uname -m)" in',
75
- `aarch64) a=aarch64-unknown-linux-gnu; sha=${RIPGREP_SHA256_ARM} ;;`,
76
- `*) a=x86_64-unknown-linux-musl; sha=${RIPGREP_SHA256_X64} ;;`,
77
- "esac;",
78
- `f=/tmp/ripgrep-${v}.tar.gz;`,
79
- `curl -fsSL "https://github.com/BurntSushi/ripgrep/releases/download/${v}/ripgrep-${v}-$a.tar.gz" -o "$f"`,
80
- '&& echo "$sha $f" | sha256sum -c -',
81
- '&& tar xzf "$f" -C /tmp',
82
- `&& mv "/tmp/ripgrep-${v}-$a/rg" /usr/local/bin/rg && chmod +x /usr/local/bin/rg;`,
83
- "}"
84
- ].join(" ");
47
+ const v = RIPGREP_VERSION;
48
+ return [
49
+ "command -v rg >/dev/null 2>&1 || {",
50
+ "case \"$(uname -m)\" in",
51
+ `aarch64) a=aarch64-unknown-linux-gnu; sha=${RIPGREP_SHA256_ARM} ;;`,
52
+ `*) a=x86_64-unknown-linux-musl; sha=${RIPGREP_SHA256_X64} ;;`,
53
+ "esac;",
54
+ `f=/tmp/ripgrep-${v}.tar.gz;`,
55
+ `curl -fsSL "https://github.com/BurntSushi/ripgrep/releases/download/${v}/ripgrep-${v}-$a.tar.gz" -o "$f"`,
56
+ "&& echo \"$sha $f\" | sha256sum -c -",
57
+ "&& tar xzf \"$f\" -C /tmp",
58
+ `&& mv "/tmp/ripgrep-${v}-$a/rg" /usr/local/bin/rg && chmod +x /usr/local/bin/rg;`,
59
+ "}"
60
+ ].join(" ");
85
61
  }
86
-
87
- // src/deepagents-auth.ts
88
- import {
89
- createCredentialRequestTransformation,
90
- getAiGatewayAuthFromEnv,
91
- isHarnessAuthenticationEnvironment
92
- } from "@ai-sdk/harness/utils";
93
- var DEEPAGENTS_CREDENTIAL_ENVIRONMENT_VARIABLES = [
94
- "AI_GATEWAY_API_KEY",
95
- "ANTHROPIC_API_KEY",
96
- "ANTHROPIC_AUTH_TOKEN"
62
+ //#endregion
63
+ //#region src/deepagents-auth.ts
64
+ const DEEPAGENTS_CREDENTIAL_ENVIRONMENT_VARIABLES = [
65
+ "AI_GATEWAY_API_KEY",
66
+ "ANTHROPIC_API_KEY",
67
+ "ANTHROPIC_AUTH_TOKEN"
97
68
  ];
98
- function createDeepAgentsRequestTransformations({
99
- env: environment,
100
- sandboxEnv: sandboxEnvironment,
101
- auth: authenticationMode
102
- }) {
103
- const matchUrl = authenticationMode === "ai-gateway" ? environment.ANTHROPIC_BASE_URL : environment.ANTHROPIC_BASE_URL ?? "https://api.anthropic.com";
104
- const transformations = [];
105
- if (environment.ANTHROPIC_API_KEY != null && sandboxEnvironment.ANTHROPIC_API_KEY != null) {
106
- transformations.push(
107
- createCredentialRequestTransformation({
108
- matchUrl,
109
- matchHeaders: {
110
- "x-api-key": sandboxEnvironment.ANTHROPIC_API_KEY
111
- },
112
- transformHeaders: {
113
- "x-api-key": environment.ANTHROPIC_API_KEY
114
- }
115
- })
116
- );
117
- }
118
- if (environment.ANTHROPIC_AUTH_TOKEN != null && sandboxEnvironment.ANTHROPIC_AUTH_TOKEN != null) {
119
- transformations.push(
120
- createCredentialRequestTransformation({
121
- matchUrl,
122
- matchHeaders: {
123
- Authorization: `Bearer ${sandboxEnvironment.ANTHROPIC_AUTH_TOKEN}`
124
- },
125
- transformHeaders: {
126
- Authorization: `Bearer ${environment.ANTHROPIC_AUTH_TOKEN}`
127
- }
128
- })
129
- );
130
- }
131
- return transformations;
69
+ function createDeepAgentsRequestTransformations({ env: environment, sandboxEnv: sandboxEnvironment, auth: authenticationMode }) {
70
+ const matchUrl = authenticationMode === "ai-gateway" ? environment.ANTHROPIC_BASE_URL : environment.ANTHROPIC_BASE_URL ?? "https://api.anthropic.com";
71
+ const transformations = [];
72
+ if (environment.ANTHROPIC_API_KEY != null && sandboxEnvironment.ANTHROPIC_API_KEY != null) transformations.push(createCredentialRequestTransformation({
73
+ matchUrl,
74
+ matchHeaders: { "x-api-key": sandboxEnvironment.ANTHROPIC_API_KEY },
75
+ transformHeaders: { "x-api-key": environment.ANTHROPIC_API_KEY }
76
+ }));
77
+ if (environment.ANTHROPIC_AUTH_TOKEN != null && sandboxEnvironment.ANTHROPIC_AUTH_TOKEN != null) transformations.push(createCredentialRequestTransformation({
78
+ matchUrl,
79
+ matchHeaders: { Authorization: `Bearer ${sandboxEnvironment.ANTHROPIC_AUTH_TOKEN}` },
80
+ transformHeaders: { Authorization: `Bearer ${environment.ANTHROPIC_AUTH_TOKEN}` }
81
+ }));
82
+ return transformations;
132
83
  }
133
- function resolveDeepAgentsEnv({
134
- auth,
135
- processEnv = process.env
136
- }) {
137
- const suppliedEnvironment = isHarnessAuthenticationEnvironment(auth);
138
- const authenticationEnvironment = suppliedEnvironment ? auth : processEnv;
139
- if (auth === "anthropic") {
140
- return pickAnthropic({ processEnv: authenticationEnvironment });
141
- }
142
- const gatewayAuthFromEnv = getAiGatewayAuthFromEnv({
143
- env: authenticationEnvironment
144
- });
145
- if (auth === "ai-gateway" || gatewayAuthFromEnv.apiKey) {
146
- return pickGateway({ gatewayAuthFromEnv });
147
- }
148
- return pickAnthropic({ processEnv: authenticationEnvironment });
84
+ function resolveDeepAgentsEnv({ auth, processEnv = process.env }) {
85
+ const authenticationEnvironment = isHarnessAuthenticationEnvironment(auth) ? auth : processEnv;
86
+ if (auth === "anthropic") return pickAnthropic({ processEnv: authenticationEnvironment });
87
+ const gatewayAuthFromEnv = getAiGatewayAuthFromEnv({ env: authenticationEnvironment });
88
+ if (auth === "ai-gateway" || gatewayAuthFromEnv.apiKey) return pickGateway({ gatewayAuthFromEnv });
89
+ return pickAnthropic({ processEnv: authenticationEnvironment });
149
90
  }
150
- function resolveDeepAgentsAuthenticationMode({
151
- auth,
152
- processEnv = process.env
153
- }) {
154
- if (isHarnessAuthenticationEnvironment(auth)) {
155
- return getAiGatewayAuthFromEnv({ env: auth }).apiKey ? "ai-gateway" : "anthropic";
156
- }
157
- if (auth === "anthropic") {
158
- return "anthropic";
159
- }
160
- if (auth === "ai-gateway") {
161
- return "ai-gateway";
162
- }
163
- return getAiGatewayAuthFromEnv({ env: processEnv }).apiKey ? "ai-gateway" : "anthropic";
91
+ function resolveDeepAgentsAuthenticationMode({ auth, processEnv = process.env }) {
92
+ if (isHarnessAuthenticationEnvironment(auth)) return getAiGatewayAuthFromEnv({ env: auth }).apiKey ? "ai-gateway" : "anthropic";
93
+ if (auth === "anthropic") return "anthropic";
94
+ if (auth === "ai-gateway") return "ai-gateway";
95
+ return getAiGatewayAuthFromEnv({ env: processEnv }).apiKey ? "ai-gateway" : "anthropic";
164
96
  }
165
- function pickAnthropic({
166
- processEnv
167
- }) {
168
- const env = {};
169
- const apiKey = processEnv.ANTHROPIC_API_KEY;
170
- if (apiKey) env.ANTHROPIC_API_KEY = apiKey;
171
- const authToken = processEnv.ANTHROPIC_AUTH_TOKEN;
172
- if (authToken) env.ANTHROPIC_AUTH_TOKEN = authToken;
173
- const baseUrl = processEnv.ANTHROPIC_BASE_URL;
174
- if (baseUrl) env.ANTHROPIC_BASE_URL = baseUrl;
175
- return env;
97
+ function pickAnthropic({ processEnv }) {
98
+ const env = {};
99
+ const apiKey = processEnv.ANTHROPIC_API_KEY;
100
+ if (apiKey) env.ANTHROPIC_API_KEY = apiKey;
101
+ const authToken = processEnv.ANTHROPIC_AUTH_TOKEN;
102
+ if (authToken) env.ANTHROPIC_AUTH_TOKEN = authToken;
103
+ const baseUrl = processEnv.ANTHROPIC_BASE_URL;
104
+ if (baseUrl) env.ANTHROPIC_BASE_URL = baseUrl;
105
+ return env;
176
106
  }
177
- function pickGateway({
178
- gatewayAuthFromEnv
179
- }) {
180
- const apiKey = gatewayAuthFromEnv.apiKey;
181
- const baseUrl = gatewayAuthFromEnv.baseUrl.replace(/\/+$/, "");
182
- const env = {};
183
- if (apiKey) {
184
- env.AI_GATEWAY_API_KEY = apiKey;
185
- env.ANTHROPIC_API_KEY = apiKey;
186
- }
187
- env.ANTHROPIC_BASE_URL = baseUrl;
188
- return env;
107
+ function pickGateway({ gatewayAuthFromEnv }) {
108
+ const apiKey = gatewayAuthFromEnv.apiKey;
109
+ const baseUrl = gatewayAuthFromEnv.baseUrl.replace(/\/+$/, "");
110
+ const env = {};
111
+ if (apiKey) {
112
+ env.AI_GATEWAY_API_KEY = apiKey;
113
+ env.ANTHROPIC_API_KEY = apiKey;
114
+ }
115
+ env.ANTHROPIC_BASE_URL = baseUrl;
116
+ return env;
189
117
  }
190
-
191
- // src/deepagents-bridge-protocol.ts
192
- import {
193
- harnessV1BridgeInboundCommandSchemas,
194
- harnessV1BridgeOutboundMessageSchema,
195
- harnessV1BridgeReadySchema,
196
- harnessV1BridgeStartBaseSchema
197
- } from "@ai-sdk/harness";
198
- import { z } from "zod/v4";
199
- var outboundMessageSchema = harnessV1BridgeOutboundMessageSchema;
200
- var thinkingSchema = z.discriminatedUnion("type", [
201
- z.object({
202
- type: z.literal("adaptive"),
203
- display: z.enum(["summarized", "omitted"]).optional()
204
- }),
205
- z.object({
206
- type: z.literal("enabled"),
207
- budget_tokens: z.number(),
208
- display: z.enum(["summarized", "omitted"]).optional()
209
- }),
210
- z.object({ type: z.literal("disabled") })
118
+ //#endregion
119
+ //#region src/deepagents-bridge-protocol.ts
120
+ const outboundMessageSchema = harnessV1BridgeOutboundMessageSchema;
121
+ const thinkingSchema = z.discriminatedUnion("type", [
122
+ z.object({
123
+ type: z.literal("adaptive"),
124
+ display: z.enum(["summarized", "omitted"]).optional()
125
+ }),
126
+ z.object({
127
+ type: z.literal("enabled"),
128
+ budget_tokens: z.number(),
129
+ display: z.enum(["summarized", "omitted"]).optional()
130
+ }),
131
+ z.object({ type: z.literal("disabled") })
211
132
  ]);
212
- var startMessageSchema = harnessV1BridgeStartBaseSchema.extend({
213
- mcpServers: z.record(z.string(), z.unknown()).optional(),
214
- /*
215
- * Appended to Deep Agents's native system prompt when the bridge constructs
216
- * the session's agent.
217
- */
218
- instructions: z.string().optional(),
219
- thinking: thinkingSchema.optional(),
220
- effort: z.enum(["low", "medium", "high", "xhigh", "max"]).optional(),
221
- // In-backend skills source dirs ($HOME and <workDir>), passed to createDeepAgent({ skills }).
222
- skillsPaths: z.array(z.string()).optional(),
223
- skillsChanged: z.boolean().optional(),
224
- // Max LangGraph super-steps per turn (streamEvents recursionLimit).
225
- recursionLimit: z.number().optional(),
226
- headers: z.record(z.string(), z.string()).optional()
133
+ const startMessageSchema = harnessV1BridgeStartBaseSchema.extend({
134
+ mcpServers: z.record(z.string(), z.unknown()).optional(),
135
+ instructions: z.string().optional(),
136
+ thinking: thinkingSchema.optional(),
137
+ effort: z.enum([
138
+ "low",
139
+ "medium",
140
+ "high",
141
+ "xhigh",
142
+ "max"
143
+ ]).optional(),
144
+ skillsPaths: z.array(z.string()).optional(),
145
+ skillsChanged: z.boolean().optional(),
146
+ recursionLimit: z.number().optional(),
147
+ headers: z.record(z.string(), z.string()).optional()
227
148
  });
228
- var inboundMessageSchema = z.discriminatedUnion("type", [
229
- startMessageSchema,
230
- ...harnessV1BridgeInboundCommandSchemas
231
- ]);
232
-
233
- // src/version.ts
234
- var VERSION = true ? "1.0.132" : "0.0.0-test";
235
-
236
- // src/deepagents-harness.ts
237
- var DEEPAGENTS_CLIENT_APP = `ai-sdk-harness-deepagents/${VERSION}`;
238
- var SKILLS_SOURCE_PATH = "/.agents/skills";
239
- var DEEPAGENTS_BUILTIN_TOOLS = {
240
- read: commonTool("read", {
241
- nativeName: "read_file",
242
- toolUseKind: "readonly",
243
- description: "Read file contents",
244
- inputSchema: z2.object({ file_path: z2.string() })
245
- }),
246
- write: commonTool("write", {
247
- nativeName: "write_file",
248
- toolUseKind: "edit",
249
- description: "Create a file",
250
- inputSchema: z2.object({ file_path: z2.string(), content: z2.string() })
251
- }),
252
- edit: commonTool("edit", {
253
- nativeName: "edit_file",
254
- toolUseKind: "edit",
255
- description: "Perform exact string replacements in a file",
256
- inputSchema: z2.object({
257
- file_path: z2.string(),
258
- old_string: z2.string(),
259
- new_string: z2.string()
260
- })
261
- }),
262
- bash: commonTool("bash", {
263
- nativeName: "execute",
264
- toolUseKind: "bash",
265
- description: "Run a shell command",
266
- inputSchema: z2.object({ command: z2.string() })
267
- }),
268
- grep: commonTool("grep", {
269
- nativeName: "grep",
270
- toolUseKind: "readonly",
271
- description: "Search file contents",
272
- inputSchema: z2.object({ pattern: z2.string() })
273
- }),
274
- glob: commonTool("glob", {
275
- nativeName: "glob",
276
- toolUseKind: "readonly",
277
- description: "Find files matching a glob pattern",
278
- inputSchema: z2.object({ pattern: z2.string() })
279
- }),
280
- // No common-name equivalent — keyed by native name.
281
- ls: tool({
282
- description: "List files in a directory",
283
- inputSchema: z2.object({ path: z2.string().optional() })
284
- }),
285
- task: tool({
286
- description: "Spawn a subagent to handle a delegated task",
287
- inputSchema: z2.object({
288
- description: z2.string().optional(),
289
- subagent_type: z2.string().optional()
290
- })
291
- }),
292
- write_todos: tool({
293
- description: "Manage a structured todo list",
294
- inputSchema: z2.object({ todos: z2.array(z2.unknown()).optional() })
295
- })
149
+ z.discriminatedUnion("type", [startMessageSchema, ...harnessV1BridgeInboundCommandSchemas]);
150
+ //#endregion
151
+ //#region src/version.ts
152
+ const VERSION = "1.0.134";
153
+ //#endregion
154
+ //#region src/deepagents-harness.ts
155
+ /**
156
+ * Value to use in User-Agent and `x-client-app` headers.
157
+ */
158
+ const DEEPAGENTS_CLIENT_APP = `ai-sdk-harness-deepagents/${VERSION}`;
159
+ const SKILLS_SOURCE_PATH = "/.agents/skills";
160
+ const DEEPAGENTS_BUILTIN_TOOLS = {
161
+ read: commonTool("read", {
162
+ nativeName: "read_file",
163
+ toolUseKind: "readonly",
164
+ description: "Read file contents",
165
+ inputSchema: z.object({ file_path: z.string() })
166
+ }),
167
+ write: commonTool("write", {
168
+ nativeName: "write_file",
169
+ toolUseKind: "edit",
170
+ description: "Create a file",
171
+ inputSchema: z.object({
172
+ file_path: z.string(),
173
+ content: z.string()
174
+ })
175
+ }),
176
+ edit: commonTool("edit", {
177
+ nativeName: "edit_file",
178
+ toolUseKind: "edit",
179
+ description: "Perform exact string replacements in a file",
180
+ inputSchema: z.object({
181
+ file_path: z.string(),
182
+ old_string: z.string(),
183
+ new_string: z.string()
184
+ })
185
+ }),
186
+ bash: commonTool("bash", {
187
+ nativeName: "execute",
188
+ toolUseKind: "bash",
189
+ description: "Run a shell command",
190
+ inputSchema: z.object({ command: z.string() })
191
+ }),
192
+ grep: commonTool("grep", {
193
+ nativeName: "grep",
194
+ toolUseKind: "readonly",
195
+ description: "Search file contents",
196
+ inputSchema: z.object({ pattern: z.string() })
197
+ }),
198
+ glob: commonTool("glob", {
199
+ nativeName: "glob",
200
+ toolUseKind: "readonly",
201
+ description: "Find files matching a glob pattern",
202
+ inputSchema: z.object({ pattern: z.string() })
203
+ }),
204
+ ls: tool({
205
+ description: "List files in a directory",
206
+ inputSchema: z.object({ path: z.string().optional() })
207
+ }),
208
+ task: tool({
209
+ description: "Spawn a subagent to handle a delegated task",
210
+ inputSchema: z.object({
211
+ description: z.string().optional(),
212
+ subagent_type: z.string().optional()
213
+ })
214
+ }),
215
+ write_todos: tool({
216
+ description: "Manage a structured todo list",
217
+ inputSchema: z.object({ todos: z.array(z.unknown()).optional() })
218
+ })
296
219
  };
297
- var deepAgentsBridgeCoordsSchema = z2.object({
298
- port: z2.number(),
299
- token: z2.string(),
300
- lastSeenEventId: z2.number(),
301
- sandboxId: z2.string().optional()
220
+ const deepAgentsBridgeCoordsSchema = z.object({
221
+ port: z.number(),
222
+ token: z.string(),
223
+ lastSeenEventId: z.number(),
224
+ sandboxId: z.string().optional()
302
225
  });
303
- var deepAgentsResumeStateSchema = z2.object({
304
- bridge: deepAgentsBridgeCoordsSchema.optional(),
305
- sandboxCredentialEnvironment: z2.record(z2.string(), z2.string()).optional()
226
+ const deepAgentsResumeStateSchema = z.object({
227
+ bridge: deepAgentsBridgeCoordsSchema.optional(),
228
+ sandboxCredentialEnvironment: z.record(z.string(), z.string()).optional()
306
229
  });
307
230
  function createDeepAgents(settings = {}) {
308
- return {
309
- specificationVersion: "harness-v1",
310
- harnessId: "deepagents",
311
- builtinTools: DEEPAGENTS_BUILTIN_TOOLS,
312
- // Built-in tool approvals are gated in-bridge via DeepAgents' interruptOn (HITL) middleware.
313
- supportsBuiltinToolApprovals: true,
314
- lifecycleStateSchema: deepAgentsResumeStateSchema,
315
- getBootstrap: getDeepAgentsBootstrap,
316
- doStart: async (startOpts) => {
317
- const permissionMode = startOpts.permissionMode;
318
- const sandboxSession = startOpts.sandboxSession;
319
- const toolSafeSandboxSession = getRestrictedSandboxSession(sandboxSession);
320
- const sandboxId = "id" in sandboxSession ? sandboxSession.id : void 0;
321
- validateBasicSandboxSettings({
322
- sandboxSession,
323
- port: settings.port,
324
- portEndpoint: settings.portEndpoint
325
- });
326
- if (settings.mintBridgeToken != null && sandboxId == null) {
327
- throw new HarnessCapabilityUnsupportedError({
328
- harnessId: "deepagents",
329
- message: "The deepagents harness cannot use `mintBridgeToken` with a sandbox session that does not expose an id."
330
- });
331
- }
332
- const lifecycleState = startOpts.continueFrom ?? startOpts.resumeFrom;
333
- const isResume = lifecycleState != null;
334
- const isContinue = startOpts.continueFrom != null;
335
- const resumeData = isResume && typeof lifecycleState?.data === "object" ? lifecycleState.data : void 0;
336
- const coords = resumeData?.bridge;
337
- const authenticationMode = resolveDeepAgentsAuthenticationMode({
338
- auth: settings.auth
339
- });
340
- const resolvedAuthEnvironment = resolveDeepAgentsEnv({
341
- auth: settings.auth
342
- });
343
- let sandboxAuthEnvironment = resolvedAuthEnvironment;
344
- let sandboxCredentialEnvironment;
345
- let credentialsBrokered = false;
346
- if ("addRequestTransformations" in sandboxSession && sandboxSession.addRequestTransformations != null) {
347
- sandboxCredentialEnvironment = resumeData?.sandboxCredentialEnvironment ?? await createSandboxCredentialEnvironment({
348
- environment: resolvedAuthEnvironment,
349
- credentialEnvironmentVariables: DEEPAGENTS_CREDENTIAL_ENVIRONMENT_VARIABLES,
350
- credentialForwarding: settings.credentialForwarding
351
- });
352
- sandboxAuthEnvironment = {
353
- ...resolvedAuthEnvironment,
354
- ...sandboxCredentialEnvironment
355
- };
356
- const requestTransformations = createDeepAgentsRequestTransformations({
357
- env: resolvedAuthEnvironment,
358
- sandboxEnv: sandboxAuthEnvironment,
359
- auth: authenticationMode
360
- });
361
- if (requestTransformations.length > 0) {
362
- await sandboxSession.addRequestTransformations(
363
- requestTransformations
364
- );
365
- }
366
- credentialsBrokered = true;
367
- }
368
- const homeDir = await resolveSandboxHomeDir({
369
- sandbox: toolSafeSandboxSession,
370
- abortSignal: startOpts.abortSignal
371
- });
372
- const stateDir = harnessStateDirectoryPath({ sandboxHomeDir: homeDir });
373
- const bootstrapDir = posix.resolve(stateDir, DEEPAGENTS_BOOTSTRAP_DIR);
374
- const workDir = startOpts.sessionWorkDir;
375
- const homeSkillsRoot = `${homeDir}${SKILLS_SOURCE_PATH}`;
376
- const skillsPaths = [`${workDir}${SKILLS_SOURCE_PATH}`, homeSkillsRoot];
377
- const sessionDataDir = harnessSessionDataDirectoryPath({
378
- stateDirectory: stateDir,
379
- sessionId: startOpts.sessionId
380
- });
381
- const bridgeStateDir = `${sessionDataDir}/bridge`;
382
- const timeoutMs = settings.startupTimeoutMs ?? 12e4;
383
- const report = startOpts.observability?.report;
384
- const onDiagnostic = report ? (frame) => report(
385
- harnessV1DiagnosticFromBridgeFrame(frame, {
386
- sessionId: startOpts.sessionId,
387
- timestamp: Date.now()
388
- })
389
- ) : void 0;
390
- const onBridgeError = createBridgeErrorHandler({
391
- harnessId: "deepagents",
392
- sessionId: startOpts.sessionId
393
- });
394
- if (coords) {
395
- try {
396
- const endpoint2 = await resolveBridgeEndpoint({
397
- sandboxSession,
398
- override: settings.portEndpoint,
399
- port: coords.port
400
- });
401
- const attachEndpoint = withBridgeToken({
402
- endpoint: endpoint2,
403
- token: coords.token
404
- });
405
- const attachChannel = new SandboxChannel({
406
- connect: ({ abortSignal }) => openWebSocket({ ...attachEndpoint, abortSignal }),
407
- outboundSchema: outboundMessageSchema,
408
- initialLastSeenEventId: coords.lastSeenEventId,
409
- onDiagnostic,
410
- onBridgeError,
411
- reconnect: settings.reconnect
412
- });
413
- await attachChannel.open(isContinue ? { resume: true } : void 0);
414
- return createSession({
415
- sessionId: startOpts.sessionId,
416
- channel: attachChannel,
417
- proc: void 0,
418
- thinking: settings.thinking,
419
- effort: settings.effort,
420
- bridgePort: coords.port,
421
- bridgeToken: coords.token,
422
- sandboxId,
423
- sandboxCredentialEnvironment,
424
- isResume: true,
425
- sandbox: toolSafeSandboxSession,
426
- homeDir,
427
- skillsPaths,
428
- permissionMode,
429
- builtinToolFiltering: startOpts.builtinToolFiltering,
430
- recursionLimit: settings.recursionLimit,
431
- mcpServers: settings.mcpServers,
432
- headers: startOpts.headers
433
- });
434
- } catch {
435
- }
436
- }
437
- const port = resolveBridgePort({
438
- sandboxSession,
439
- override: settings.port
440
- });
441
- const token = settings.mintBridgeToken == null ? createBridgeToken() : settings.mintBridgeToken(sandboxId);
442
- const forwardedAuthEnvironment = credentialsBrokered ? sandboxAuthEnvironment : await applyCredentialForwarding({
443
- environment: sandboxAuthEnvironment,
444
- credentialEnvironmentVariables: DEEPAGENTS_CREDENTIAL_ENVIRONMENT_VARIABLES,
445
- credentialForwarding: settings.credentialForwarding
446
- });
447
- if (!credentialsBrokered) {
448
- warnCredentialBrokeringUnavailable({
449
- environment: resolvedAuthEnvironment,
450
- forwardedEnvironment: forwardedAuthEnvironment,
451
- credentialEnvironmentVariables: DEEPAGENTS_CREDENTIAL_ENVIRONMENT_VARIABLES
452
- });
453
- }
454
- const env = {
455
- ...forwardedAuthEnvironment,
456
- AI_SDK_HARNESS_CLIENT_APP: DEEPAGENTS_CLIENT_APP,
457
- BRIDGE_CHANNEL_TOKEN: token,
458
- BRIDGE_WS_PORT: String(port)
459
- };
460
- await toolSafeSandboxSession.run({
461
- command: `mkdir -p ${shellQuote(workDir)} ${shellQuote(bridgeStateDir)}`,
462
- abortSignal: startOpts.abortSignal
463
- });
464
- await markBridgeStarting({
465
- sandbox: toolSafeSandboxSession,
466
- bridgeStateDir,
467
- bridgeType: "deepagents",
468
- abortSignal: startOpts.abortSignal
469
- });
470
- const proc = await toolSafeSandboxSession.spawn({
471
- command: `node ${shellQuote(`${bootstrapDir}/bridge.mjs`)} --workdir ${shellQuote(workDir)} --bridge-state-dir ${shellQuote(bridgeStateDir)} --bootstrap-dir ${shellQuote(bootstrapDir)}${isResume ? " --resume true" : ""}`,
472
- env,
473
- abortSignal: startOpts.abortSignal
474
- });
475
- const stderrTail = [];
476
- const bridgeStderrDone = forwardBridgeProcessStream({
477
- stream: proc.stderr,
478
- streamName: "stderr",
479
- source: "deepagents",
480
- collectTail: stderrTail
481
- });
482
- const { port: boundPort } = await waitForBridgeReady({
483
- proc,
484
- sandbox: toolSafeSandboxSession,
485
- bridgeStateDir,
486
- bridgeType: "deepagents",
487
- timeoutMs,
488
- abortSignal: startOpts.abortSignal,
489
- createTimeoutError: ({ proc: proc2, stdoutTail }) => createBridgeStartupError({
490
- message: "deepagents bridge did not become ready in time.",
491
- proc: proc2,
492
- stdoutTail,
493
- stderrTail,
494
- stderrDone: bridgeStderrDone
495
- }),
496
- createExitError: ({ proc: proc2, stdoutTail }) => createBridgeStartupError({
497
- message: "deepagents bridge exited before becoming ready.",
498
- proc: proc2,
499
- stdoutTail,
500
- stderrTail,
501
- stderrDone: bridgeStderrDone
502
- })
503
- });
504
- void drainBridgeProcessStream(proc.stdout);
505
- const endpoint = await resolveBridgeEndpoint({
506
- sandboxSession,
507
- override: settings.portEndpoint,
508
- port: boundPort
509
- });
510
- const bridgeEndpoint = withBridgeToken({ endpoint, token });
511
- const channel = new SandboxChannel({
512
- connect: ({ abortSignal }) => openWebSocket({ ...bridgeEndpoint, abortSignal }),
513
- outboundSchema: outboundMessageSchema,
514
- onDiagnostic,
515
- onBridgeError,
516
- reconnect: settings.reconnect
517
- });
518
- await channel.open();
519
- return createSession({
520
- sessionId: startOpts.sessionId,
521
- channel,
522
- proc,
523
- thinking: settings.thinking,
524
- effort: settings.effort,
525
- bridgePort: boundPort,
526
- bridgeToken: token,
527
- sandboxId,
528
- sandboxCredentialEnvironment,
529
- isResume,
530
- sandbox: toolSafeSandboxSession,
531
- homeDir,
532
- skillsPaths,
533
- permissionMode,
534
- builtinToolFiltering: startOpts.builtinToolFiltering,
535
- recursionLimit: settings.recursionLimit,
536
- mcpServers: settings.mcpServers,
537
- headers: startOpts.headers
538
- });
539
- }
540
- };
231
+ return {
232
+ specificationVersion: "harness-v1",
233
+ harnessId: "deepagents",
234
+ builtinTools: DEEPAGENTS_BUILTIN_TOOLS,
235
+ supportsBuiltinToolApprovals: true,
236
+ lifecycleStateSchema: deepAgentsResumeStateSchema,
237
+ getBootstrap: getDeepAgentsBootstrap,
238
+ doStart: async (startOpts) => {
239
+ const permissionMode = startOpts.permissionMode;
240
+ const sandboxSession = startOpts.sandboxSession;
241
+ const toolSafeSandboxSession = getRestrictedSandboxSession(sandboxSession);
242
+ const sandboxId = "id" in sandboxSession ? sandboxSession.id : void 0;
243
+ validateBasicSandboxSettings({
244
+ sandboxSession,
245
+ port: settings.port,
246
+ portEndpoint: settings.portEndpoint
247
+ });
248
+ if (settings.mintBridgeToken != null && sandboxId == null) throw new HarnessCapabilityUnsupportedError({
249
+ harnessId: "deepagents",
250
+ message: "The deepagents harness cannot use `mintBridgeToken` with a sandbox session that does not expose an id."
251
+ });
252
+ const lifecycleState = startOpts.continueFrom ?? startOpts.resumeFrom;
253
+ const isResume = lifecycleState != null;
254
+ const isContinue = startOpts.continueFrom != null;
255
+ const resumeData = isResume && typeof lifecycleState?.data === "object" ? lifecycleState.data : void 0;
256
+ const coords = resumeData?.bridge;
257
+ const authenticationMode = resolveDeepAgentsAuthenticationMode({ auth: settings.auth });
258
+ const resolvedAuthEnvironment = resolveDeepAgentsEnv({ auth: settings.auth });
259
+ let sandboxAuthEnvironment = resolvedAuthEnvironment;
260
+ let sandboxCredentialEnvironment;
261
+ let credentialsBrokered = false;
262
+ if ("addRequestTransformations" in sandboxSession && sandboxSession.addRequestTransformations != null) {
263
+ sandboxCredentialEnvironment = await resolveSandboxCredentialEnvironment({
264
+ environment: resolvedAuthEnvironment,
265
+ credentialEnvironmentVariables: DEEPAGENTS_CREDENTIAL_ENVIRONMENT_VARIABLES,
266
+ credentialForwarding: settings.credentialForwarding,
267
+ previousSandboxCredentialEnvironment: resumeData?.sandboxCredentialEnvironment
268
+ });
269
+ sandboxAuthEnvironment = {
270
+ ...resolvedAuthEnvironment,
271
+ ...sandboxCredentialEnvironment
272
+ };
273
+ const requestTransformations = createDeepAgentsRequestTransformations({
274
+ env: resolvedAuthEnvironment,
275
+ sandboxEnv: sandboxAuthEnvironment,
276
+ auth: authenticationMode
277
+ });
278
+ if (requestTransformations.length > 0) await sandboxSession.addRequestTransformations(requestTransformations);
279
+ credentialsBrokered = true;
280
+ }
281
+ const homeDir = await resolveSandboxHomeDir({
282
+ sandbox: toolSafeSandboxSession,
283
+ abortSignal: startOpts.abortSignal
284
+ });
285
+ const stateDir = harnessStateDirectoryPath({ sandboxHomeDir: homeDir });
286
+ const bootstrapDir = posix.resolve(stateDir, DEEPAGENTS_BOOTSTRAP_DIR);
287
+ const workDir = startOpts.sessionWorkDir;
288
+ const homeSkillsRoot = `${homeDir}${SKILLS_SOURCE_PATH}`;
289
+ const skillsPaths = [`${workDir}${SKILLS_SOURCE_PATH}`, homeSkillsRoot];
290
+ const bridgeStateDir = `${harnessSessionDataDirectoryPath({
291
+ stateDirectory: stateDir,
292
+ sessionId: startOpts.sessionId
293
+ })}/bridge`;
294
+ const timeoutMs = settings.startupTimeoutMs ?? 12e4;
295
+ const report = startOpts.observability?.report;
296
+ const onDiagnostic = report ? (frame) => report(harnessV1DiagnosticFromBridgeFrame(frame, {
297
+ sessionId: startOpts.sessionId,
298
+ timestamp: Date.now()
299
+ })) : void 0;
300
+ const onBridgeError = createBridgeErrorHandler({
301
+ harnessId: "deepagents",
302
+ sessionId: startOpts.sessionId
303
+ });
304
+ if (coords) try {
305
+ const endpoint = await resolveBridgeEndpoint({
306
+ sandboxSession,
307
+ override: settings.portEndpoint,
308
+ port: coords.port
309
+ });
310
+ const attachEndpoint = withBridgeToken({
311
+ endpoint,
312
+ token: coords.token
313
+ });
314
+ const attachChannel = new SandboxChannel({
315
+ connect: ({ abortSignal }) => openWebSocket({
316
+ ...attachEndpoint,
317
+ abortSignal
318
+ }),
319
+ outboundSchema: outboundMessageSchema,
320
+ initialLastSeenEventId: coords.lastSeenEventId,
321
+ onDiagnostic,
322
+ onBridgeError,
323
+ reconnect: settings.reconnect
324
+ });
325
+ await attachChannel.open(isContinue ? { resume: true } : void 0);
326
+ return createSession({
327
+ sessionId: startOpts.sessionId,
328
+ channel: attachChannel,
329
+ proc: void 0,
330
+ thinking: settings.thinking,
331
+ effort: settings.effort,
332
+ bridgePort: coords.port,
333
+ bridgeToken: coords.token,
334
+ sandboxId,
335
+ sandboxCredentialEnvironment,
336
+ isResume: true,
337
+ sandbox: toolSafeSandboxSession,
338
+ homeDir,
339
+ skillsPaths,
340
+ permissionMode,
341
+ builtinToolFiltering: startOpts.builtinToolFiltering,
342
+ recursionLimit: settings.recursionLimit,
343
+ mcpServers: settings.mcpServers,
344
+ headers: startOpts.headers
345
+ });
346
+ } catch {}
347
+ const port = resolveBridgePort({
348
+ sandboxSession,
349
+ override: settings.port
350
+ });
351
+ const token = settings.mintBridgeToken == null ? createBridgeToken() : settings.mintBridgeToken(sandboxId);
352
+ const forwardedAuthEnvironment = credentialsBrokered ? sandboxAuthEnvironment : await applyCredentialForwarding({
353
+ environment: sandboxAuthEnvironment,
354
+ credentialEnvironmentVariables: DEEPAGENTS_CREDENTIAL_ENVIRONMENT_VARIABLES,
355
+ credentialForwarding: settings.credentialForwarding
356
+ });
357
+ if (!credentialsBrokered) warnCredentialBrokeringUnavailable({
358
+ environment: resolvedAuthEnvironment,
359
+ forwardedEnvironment: forwardedAuthEnvironment,
360
+ credentialEnvironmentVariables: DEEPAGENTS_CREDENTIAL_ENVIRONMENT_VARIABLES
361
+ });
362
+ const env = {
363
+ ...forwardedAuthEnvironment,
364
+ AI_SDK_HARNESS_CLIENT_APP: DEEPAGENTS_CLIENT_APP,
365
+ BRIDGE_CHANNEL_TOKEN: token,
366
+ BRIDGE_WS_PORT: String(port)
367
+ };
368
+ await toolSafeSandboxSession.run({
369
+ command: `mkdir -p ${shellQuote(workDir)} ${shellQuote(bridgeStateDir)}`,
370
+ abortSignal: startOpts.abortSignal
371
+ });
372
+ await markBridgeStarting({
373
+ sandbox: toolSafeSandboxSession,
374
+ bridgeStateDir,
375
+ bridgeType: "deepagents",
376
+ abortSignal: startOpts.abortSignal
377
+ });
378
+ const proc = await toolSafeSandboxSession.spawn({
379
+ command: `node ${shellQuote(`${bootstrapDir}/bridge.mjs`)} --workdir ${shellQuote(workDir)} --bridge-state-dir ${shellQuote(bridgeStateDir)} --bootstrap-dir ${shellQuote(bootstrapDir)}${isResume ? " --resume true" : ""}`,
380
+ env,
381
+ abortSignal: startOpts.abortSignal
382
+ });
383
+ const stderrTail = [];
384
+ const bridgeStderrDone = forwardBridgeProcessStream({
385
+ stream: proc.stderr,
386
+ streamName: "stderr",
387
+ source: "deepagents",
388
+ collectTail: stderrTail
389
+ });
390
+ const { port: boundPort } = await waitForBridgeReady({
391
+ proc,
392
+ sandbox: toolSafeSandboxSession,
393
+ bridgeStateDir,
394
+ bridgeType: "deepagents",
395
+ timeoutMs,
396
+ abortSignal: startOpts.abortSignal,
397
+ createTimeoutError: ({ proc, stdoutTail }) => createBridgeStartupError({
398
+ message: "deepagents bridge did not become ready in time.",
399
+ proc,
400
+ stdoutTail,
401
+ stderrTail,
402
+ stderrDone: bridgeStderrDone
403
+ }),
404
+ createExitError: ({ proc, stdoutTail }) => createBridgeStartupError({
405
+ message: "deepagents bridge exited before becoming ready.",
406
+ proc,
407
+ stdoutTail,
408
+ stderrTail,
409
+ stderrDone: bridgeStderrDone
410
+ })
411
+ });
412
+ drainBridgeProcessStream(proc.stdout);
413
+ const endpoint = await resolveBridgeEndpoint({
414
+ sandboxSession,
415
+ override: settings.portEndpoint,
416
+ port: boundPort
417
+ });
418
+ const bridgeEndpoint = withBridgeToken({
419
+ endpoint,
420
+ token
421
+ });
422
+ const channel = new SandboxChannel({
423
+ connect: ({ abortSignal }) => openWebSocket({
424
+ ...bridgeEndpoint,
425
+ abortSignal
426
+ }),
427
+ outboundSchema: outboundMessageSchema,
428
+ onDiagnostic,
429
+ onBridgeError,
430
+ reconnect: settings.reconnect
431
+ });
432
+ await channel.open();
433
+ return createSession({
434
+ sessionId: startOpts.sessionId,
435
+ channel,
436
+ proc,
437
+ thinking: settings.thinking,
438
+ effort: settings.effort,
439
+ bridgePort: boundPort,
440
+ bridgeToken: token,
441
+ sandboxId,
442
+ sandboxCredentialEnvironment,
443
+ isResume,
444
+ sandbox: toolSafeSandboxSession,
445
+ homeDir,
446
+ skillsPaths,
447
+ permissionMode,
448
+ builtinToolFiltering: startOpts.builtinToolFiltering,
449
+ recursionLimit: settings.recursionLimit,
450
+ mcpServers: settings.mcpServers,
451
+ headers: startOpts.headers
452
+ });
453
+ }
454
+ };
541
455
  }
542
- function resolveBridgePort({
543
- sandboxSession,
544
- override
545
- }) {
546
- if (override !== void 0) return override;
547
- if ("ports" in sandboxSession && sandboxSession.ports.length > 0) {
548
- return sandboxSession.ports[0];
549
- }
550
- throw new HarnessCapabilityUnsupportedError({
551
- harnessId: "deepagents",
552
- message: "The deepagents harness needs a TCP port exposed by the sandbox. Create the sandbox with `ports: [<port>]` or pass `createDeepAgents({ port })`."
553
- });
456
+ function resolveBridgePort({ sandboxSession, override }) {
457
+ if (override !== void 0) return override;
458
+ if ("ports" in sandboxSession && sandboxSession.ports.length > 0) return sandboxSession.ports[0];
459
+ throw new HarnessCapabilityUnsupportedError({
460
+ harnessId: "deepagents",
461
+ message: "The deepagents harness needs a TCP port exposed by the sandbox. Create the sandbox with `ports: [<port>]` or pass `createDeepAgents({ port })`."
462
+ });
554
463
  }
555
- function validateBasicSandboxSettings({
556
- sandboxSession,
557
- port,
558
- portEndpoint
559
- }) {
560
- if ("getPortEndpoint" in sandboxSession) return;
561
- if (port == null) {
562
- throw new HarnessCapabilityUnsupportedError({
563
- harnessId: "deepagents",
564
- message: "The deepagents harness requires an explicit `port` when using a basic sandbox session."
565
- });
566
- }
567
- if (portEndpoint == null) {
568
- throw new HarnessCapabilityUnsupportedError({
569
- harnessId: "deepagents",
570
- message: "The deepagents harness requires an explicit `portEndpoint` when using a basic sandbox session."
571
- });
572
- }
464
+ function validateBasicSandboxSettings({ sandboxSession, port, portEndpoint }) {
465
+ if ("getPortEndpoint" in sandboxSession) return;
466
+ if (port == null) throw new HarnessCapabilityUnsupportedError({
467
+ harnessId: "deepagents",
468
+ message: "The deepagents harness requires an explicit `port` when using a basic sandbox session."
469
+ });
470
+ if (portEndpoint == null) throw new HarnessCapabilityUnsupportedError({
471
+ harnessId: "deepagents",
472
+ message: "The deepagents harness requires an explicit `portEndpoint` when using a basic sandbox session."
473
+ });
573
474
  }
574
- async function resolveBridgeEndpoint({
575
- sandboxSession,
576
- override,
577
- port
578
- }) {
579
- if (override != null) return override;
580
- if ("getPortEndpoint" in sandboxSession) {
581
- return sandboxSession.getPortEndpoint({ port, protocol: "ws" });
582
- }
583
- throw new HarnessCapabilityUnsupportedError({
584
- harnessId: "deepagents",
585
- message: "The deepagents harness requires an explicit `portEndpoint` when using a basic sandbox session."
586
- });
475
+ async function resolveBridgeEndpoint({ sandboxSession, override, port }) {
476
+ if (override != null) return override;
477
+ if ("getPortEndpoint" in sandboxSession) return sandboxSession.getPortEndpoint({
478
+ port,
479
+ protocol: "ws"
480
+ });
481
+ throw new HarnessCapabilityUnsupportedError({
482
+ harnessId: "deepagents",
483
+ message: "The deepagents harness requires an explicit `portEndpoint` when using a basic sandbox session."
484
+ });
587
485
  }
588
- function openWebSocket({
589
- url,
590
- headers,
591
- abortSignal
592
- }) {
593
- return new Promise((resolve, reject) => {
594
- if (abortSignal.aborted) {
595
- reject(abortSignal.reason ?? new Error("WebSocket connection aborted"));
596
- return;
597
- }
598
- const ws = new WebSocket(url, {
599
- headers: headers == null ? void 0 : { ...headers }
600
- });
601
- let settled = false;
602
- const cleanup = () => {
603
- abortSignal.removeEventListener("abort", onAbort);
604
- ws.off("open", onOpen);
605
- ws.off("error", onError);
606
- };
607
- const rejectWithCleanup = (error) => {
608
- if (settled) return;
609
- settled = true;
610
- cleanup();
611
- ws.once("error", () => {
612
- });
613
- try {
614
- ws.terminate();
615
- } catch {
616
- try {
617
- ws.close();
618
- } catch {
619
- }
620
- }
621
- reject(error);
622
- };
623
- const onOpen = () => {
624
- if (settled) return;
625
- settled = true;
626
- cleanup();
627
- resolve(ws);
628
- };
629
- const onError = (err) => {
630
- rejectWithCleanup(err);
631
- };
632
- const onAbort = () => rejectWithCleanup(
633
- abortSignal.reason ?? new Error("WebSocket connection aborted")
634
- );
635
- ws.once("open", onOpen);
636
- ws.once("error", onError);
637
- abortSignal.addEventListener("abort", onAbort, { once: true });
638
- });
486
+ function openWebSocket({ url, headers, abortSignal }) {
487
+ return new Promise((resolve, reject) => {
488
+ if (abortSignal.aborted) {
489
+ reject(abortSignal.reason ?? /* @__PURE__ */ new Error("WebSocket connection aborted"));
490
+ return;
491
+ }
492
+ const ws = new WebSocket(url, { headers: headers == null ? void 0 : { ...headers } });
493
+ let settled = false;
494
+ const cleanup = () => {
495
+ abortSignal.removeEventListener("abort", onAbort);
496
+ ws.off("open", onOpen);
497
+ ws.off("error", onError);
498
+ };
499
+ const rejectWithCleanup = (error) => {
500
+ if (settled) return;
501
+ settled = true;
502
+ cleanup();
503
+ ws.once("error", () => {});
504
+ try {
505
+ ws.terminate();
506
+ } catch {
507
+ try {
508
+ ws.close();
509
+ } catch {}
510
+ }
511
+ reject(error);
512
+ };
513
+ const onOpen = () => {
514
+ if (settled) return;
515
+ settled = true;
516
+ cleanup();
517
+ resolve(ws);
518
+ };
519
+ const onError = (err) => {
520
+ rejectWithCleanup(err);
521
+ };
522
+ const onAbort = () => rejectWithCleanup(abortSignal.reason ?? /* @__PURE__ */ new Error("WebSocket connection aborted"));
523
+ ws.once("open", onOpen);
524
+ ws.once("error", onError);
525
+ abortSignal.addEventListener("abort", onAbort, { once: true });
526
+ });
639
527
  }
640
- function createSession({
641
- sessionId,
642
- channel,
643
- proc,
644
- thinking,
645
- effort,
646
- bridgePort,
647
- bridgeToken,
648
- sandboxId,
649
- sandboxCredentialEnvironment,
650
- isResume,
651
- sandbox,
652
- homeDir,
653
- skillsPaths,
654
- permissionMode,
655
- builtinToolFiltering,
656
- recursionLimit,
657
- mcpServers,
658
- headers
659
- }) {
660
- let stopped = false;
661
- const wireTurn = (turnOpts) => {
662
- let pendingResolve;
663
- let pendingReject;
664
- const done = new Promise((resolve, reject) => {
665
- pendingResolve = resolve;
666
- pendingReject = reject;
667
- });
668
- const unsubs = [];
669
- const forward = (event) => {
670
- try {
671
- turnOpts.emit(event);
672
- } catch {
673
- }
674
- };
675
- const eventTypes = [
676
- "stream-start",
677
- "text-start",
678
- "text-delta",
679
- "text-end",
680
- "reasoning-start",
681
- "reasoning-delta",
682
- "reasoning-end",
683
- "tool-call",
684
- "tool-approval-request",
685
- "tool-result",
686
- "file-change",
687
- "finish-step",
688
- "raw"
689
- ];
690
- let isSettled = false;
691
- const settleSuccess = () => {
692
- if (isSettled) return;
693
- isSettled = true;
694
- for (const u of unsubs) u();
695
- pendingResolve();
696
- };
697
- const settleError = (err) => {
698
- if (isSettled) return;
699
- isSettled = true;
700
- for (const u of unsubs) u();
701
- pendingReject(err);
702
- };
703
- for (const type of eventTypes) {
704
- unsubs.push(channel.on(type, (msg) => forward(msg)));
705
- }
706
- unsubs.push(
707
- channel.on("finish", (msg) => {
708
- forward(msg);
709
- settleSuccess();
710
- })
711
- );
712
- unsubs.push(
713
- channel.on("error", (msg) => {
714
- forward(msg);
715
- settleError(msg.error);
716
- })
717
- );
718
- const onClose = (_code, reason) => {
719
- if (isSettled) return;
720
- if (reason === "suspended") {
721
- settleSuccess();
722
- return;
723
- }
724
- settleError(
725
- new Error("deepagents bridge closed before the turn finished.")
726
- );
727
- };
728
- channel.onClose(onClose);
729
- const onAbort = () => {
730
- if (isSettled) return;
731
- try {
732
- channel.send({ type: "abort" });
733
- } catch {
734
- }
735
- settleError(
736
- turnOpts.abortSignal?.reason ?? new DOMException("Aborted", "AbortError")
737
- );
738
- };
739
- if (turnOpts.abortSignal) {
740
- if (turnOpts.abortSignal.aborted) {
741
- onAbort();
742
- } else {
743
- turnOpts.abortSignal.addEventListener("abort", onAbort, { once: true });
744
- }
745
- }
746
- return {
747
- submitToolResult: async (input) => {
748
- channel.send({
749
- type: "tool-result",
750
- toolCallId: input.toolCallId,
751
- output: input.output,
752
- isError: input.isError
753
- });
754
- },
755
- submitToolApproval: async (input) => {
756
- channel.send({
757
- type: "tool-approval-response",
758
- approvalId: input.approvalId,
759
- approved: input.approved,
760
- ...input.reason != null ? { reason: input.reason } : {}
761
- });
762
- },
763
- done
764
- };
765
- };
766
- const unsupported = (capability) => {
767
- throw new HarnessCapabilityUnsupportedError({
768
- harnessId: "deepagents",
769
- message: `Harness 'deepagents' does not support ${capability} yet.`
770
- });
771
- };
772
- return {
773
- sessionId,
774
- isResume,
775
- doPromptTurn: async (promptOpts) => {
776
- if (promptOpts.responseFormat?.type === "json" && promptOpts.responseFormat.schema == null) {
777
- throw new HarnessCapabilityUnsupportedError({
778
- message: "Harness 'deepagents' requires a JSON schema for structured output.",
779
- harnessId: "deepagents"
780
- });
781
- }
782
- const skillWriteResult = await writeSkills({
783
- sandbox,
784
- homePath: homeDir,
785
- skillsDir: ".agents/skills",
786
- skills: promptOpts.skills,
787
- abortSignal: promptOpts.abortSignal,
788
- skillNamePattern: /^[a-z0-9]([a-z0-9-]{0,62}[a-z0-9])?$/,
789
- invalidSkillNameMessage: ({ name }) => `Invalid deepagents skill name '${name}': must be lowercase alphanumeric with hyphens, 1-64 chars.`,
790
- filePathMode: "strip-leading-slashes",
791
- invalidSkillFilePathMessage: ({ skillName, filePath }) => `Invalid skill file path for '${skillName}': ${filePath}`
792
- });
793
- const control = wireTurn({
794
- emit: promptOpts.emit,
795
- abortSignal: promptOpts.abortSignal
796
- });
797
- channel.send({
798
- type: "start",
799
- prompt: extractUserText(promptOpts.prompt),
800
- ...promptOpts.instructions ? { instructions: promptOpts.instructions } : {},
801
- tools: (promptOpts.tools ?? []).map((t) => ({
802
- name: t.name,
803
- description: t.description,
804
- inputSchema: t.inputSchema
805
- })),
806
- ...promptOpts.responseFormat == null ? {} : { responseFormat: promptOpts.responseFormat },
807
- ...promptOpts.model ? { model: promptOpts.model } : {},
808
- ...thinking ? { thinking } : {},
809
- ...effort ? { effort } : {},
810
- ...skillsPaths?.length ? { skillsPaths } : {},
811
- skillsChanged: skillWriteResult.changed,
812
- ...permissionMode ? { permissionMode } : {},
813
- ...builtinToolFiltering ? { builtinToolFiltering } : {},
814
- ...recursionLimit != null ? { recursionLimit } : {},
815
- ...mcpServers == null ? {} : { mcpServers },
816
- ...headers == null ? {} : { headers }
817
- });
818
- return control;
819
- },
820
- doContinueTurn: async (continueOpts) => {
821
- if (continueOpts.responseFormat?.type === "json" && continueOpts.responseFormat.schema == null) {
822
- throw new HarnessCapabilityUnsupportedError({
823
- message: "Harness 'deepagents' requires a JSON schema for structured output.",
824
- harnessId: "deepagents"
825
- });
826
- }
827
- return wireTurn({
828
- emit: continueOpts.emit,
829
- abortSignal: continueOpts.abortSignal
830
- });
831
- },
832
- doSuspendTurn: async () => {
833
- if (stopped) {
834
- throw new Error(
835
- `deepagents session ${sessionId} is stopped; cannot suspend.`
836
- );
837
- }
838
- stopped = true;
839
- const lastSeenEventId = await channel.suspend();
840
- const payload = {
841
- type: "continue-turn",
842
- harnessId: "deepagents",
843
- specificationVersion: "harness-v1",
844
- data: {
845
- ...sandboxCredentialEnvironment == null ? {} : { sandboxCredentialEnvironment },
846
- bridge: {
847
- port: bridgePort,
848
- token: bridgeToken,
849
- lastSeenEventId,
850
- ...sandboxId == null ? {} : { sandboxId }
851
- }
852
- }
853
- };
854
- return payload;
855
- },
856
- doDetach: async () => {
857
- if (stopped) {
858
- throw new Error(
859
- `deepagents session ${sessionId} is already stopped; cannot detach.`
860
- );
861
- }
862
- stopped = true;
863
- const lastSeenEventId = await channel.suspend();
864
- const payload = {
865
- type: "resume-session",
866
- harnessId: "deepagents",
867
- specificationVersion: "harness-v1",
868
- data: {
869
- ...sandboxCredentialEnvironment == null ? {} : { sandboxCredentialEnvironment },
870
- bridge: {
871
- port: bridgePort,
872
- token: bridgeToken,
873
- lastSeenEventId,
874
- ...sandboxId == null ? {} : { sandboxId }
875
- }
876
- }
877
- };
878
- return payload;
879
- },
880
- doCompact: async () => unsupported("manual compaction"),
881
- doStop: async () => {
882
- if (stopped) {
883
- throw new Error(
884
- `deepagents session ${sessionId} is already stopped; cannot stop.`
885
- );
886
- }
887
- stopped = true;
888
- await teardown({ channel, proc, operation: "stop" });
889
- const payload = {
890
- type: "resume-session",
891
- harnessId: "deepagents",
892
- specificationVersion: "harness-v1",
893
- data: sandboxCredentialEnvironment == null ? {} : { sandboxCredentialEnvironment }
894
- };
895
- return payload;
896
- },
897
- doDestroy: async () => {
898
- if (stopped) return;
899
- stopped = true;
900
- await teardown({ channel, proc, operation: "destroy" });
901
- }
902
- };
528
+ function createSession({ sessionId, channel, proc, thinking, effort, bridgePort, bridgeToken, sandboxId, sandboxCredentialEnvironment, isResume, sandbox, homeDir, skillsPaths, permissionMode, builtinToolFiltering, recursionLimit, mcpServers, headers }) {
529
+ let stopped = false;
530
+ const wireTurn = (turnOpts) => {
531
+ let pendingResolve;
532
+ let pendingReject;
533
+ const done = new Promise((resolve, reject) => {
534
+ pendingResolve = resolve;
535
+ pendingReject = reject;
536
+ });
537
+ const unsubs = [];
538
+ const forward = (event) => {
539
+ try {
540
+ turnOpts.emit(event);
541
+ } catch {}
542
+ };
543
+ const eventTypes = [
544
+ "stream-start",
545
+ "text-start",
546
+ "text-delta",
547
+ "text-end",
548
+ "reasoning-start",
549
+ "reasoning-delta",
550
+ "reasoning-end",
551
+ "tool-call",
552
+ "tool-approval-request",
553
+ "tool-result",
554
+ "file-change",
555
+ "finish-step",
556
+ "raw"
557
+ ];
558
+ let isSettled = false;
559
+ const settleSuccess = () => {
560
+ if (isSettled) return;
561
+ isSettled = true;
562
+ for (const u of unsubs) u();
563
+ pendingResolve();
564
+ };
565
+ const settleError = (err) => {
566
+ if (isSettled) return;
567
+ isSettled = true;
568
+ for (const u of unsubs) u();
569
+ pendingReject(err);
570
+ };
571
+ for (const type of eventTypes) unsubs.push(channel.on(type, (msg) => forward(msg)));
572
+ unsubs.push(channel.on("finish", (msg) => {
573
+ forward(msg);
574
+ settleSuccess();
575
+ }));
576
+ unsubs.push(channel.on("error", (msg) => {
577
+ forward(msg);
578
+ settleError(msg.error);
579
+ }));
580
+ const onClose = (_code, reason) => {
581
+ if (isSettled) return;
582
+ if (reason === "suspended") {
583
+ settleSuccess();
584
+ return;
585
+ }
586
+ settleError(/* @__PURE__ */ new Error("deepagents bridge closed before the turn finished."));
587
+ };
588
+ channel.onClose(onClose);
589
+ const onAbort = () => {
590
+ if (isSettled) return;
591
+ try {
592
+ channel.send({ type: "abort" });
593
+ } catch {}
594
+ settleError(turnOpts.abortSignal?.reason ?? new DOMException("Aborted", "AbortError"));
595
+ };
596
+ if (turnOpts.abortSignal) {
597
+ if (turnOpts.abortSignal.aborted) onAbort();
598
+ else turnOpts.abortSignal.addEventListener("abort", onAbort, { once: true });
599
+ }
600
+ return {
601
+ submitToolResult: async (input) => {
602
+ channel.send({
603
+ type: "tool-result",
604
+ toolCallId: input.toolCallId,
605
+ output: input.output,
606
+ isError: input.isError
607
+ });
608
+ },
609
+ submitToolApproval: async (input) => {
610
+ channel.send({
611
+ type: "tool-approval-response",
612
+ approvalId: input.approvalId,
613
+ approved: input.approved,
614
+ ...input.reason != null ? { reason: input.reason } : {}
615
+ });
616
+ },
617
+ done
618
+ };
619
+ };
620
+ const unsupported = (capability) => {
621
+ throw new HarnessCapabilityUnsupportedError({
622
+ harnessId: "deepagents",
623
+ message: `Harness 'deepagents' does not support ${capability} yet.`
624
+ });
625
+ };
626
+ return {
627
+ sessionId,
628
+ isResume,
629
+ doPromptTurn: async (promptOpts) => {
630
+ if (promptOpts.responseFormat?.type === "json" && promptOpts.responseFormat.schema == null) throw new HarnessCapabilityUnsupportedError({
631
+ message: "Harness 'deepagents' requires a JSON schema for structured output.",
632
+ harnessId: "deepagents"
633
+ });
634
+ const skillWriteResult = await writeSkills({
635
+ sandbox,
636
+ homePath: homeDir,
637
+ skillsDir: ".agents/skills",
638
+ skills: promptOpts.skills,
639
+ abortSignal: promptOpts.abortSignal,
640
+ skillNamePattern: /^[a-z0-9]([a-z0-9-]{0,62}[a-z0-9])?$/,
641
+ invalidSkillNameMessage: ({ name }) => `Invalid deepagents skill name '${name}': must be lowercase alphanumeric with hyphens, 1-64 chars.`,
642
+ filePathMode: "strip-leading-slashes",
643
+ invalidSkillFilePathMessage: ({ skillName, filePath }) => `Invalid skill file path for '${skillName}': ${filePath}`
644
+ });
645
+ const control = wireTurn({
646
+ emit: promptOpts.emit,
647
+ abortSignal: promptOpts.abortSignal
648
+ });
649
+ channel.send({
650
+ type: "start",
651
+ prompt: extractUserText(promptOpts.prompt),
652
+ ...promptOpts.instructions ? { instructions: promptOpts.instructions } : {},
653
+ tools: (promptOpts.tools ?? []).map((t) => ({
654
+ name: t.name,
655
+ description: t.description,
656
+ inputSchema: t.inputSchema
657
+ })),
658
+ ...promptOpts.responseFormat == null ? {} : { responseFormat: promptOpts.responseFormat },
659
+ ...promptOpts.model ? { model: promptOpts.model } : {},
660
+ ...thinking ? { thinking } : {},
661
+ ...effort ? { effort } : {},
662
+ ...skillsPaths?.length ? { skillsPaths } : {},
663
+ skillsChanged: skillWriteResult.changed,
664
+ ...permissionMode ? { permissionMode } : {},
665
+ ...builtinToolFiltering ? { builtinToolFiltering } : {},
666
+ ...recursionLimit != null ? { recursionLimit } : {},
667
+ ...mcpServers == null ? {} : { mcpServers },
668
+ ...headers == null ? {} : { headers }
669
+ });
670
+ return control;
671
+ },
672
+ doContinueTurn: async (continueOpts) => {
673
+ if (continueOpts.responseFormat?.type === "json" && continueOpts.responseFormat.schema == null) throw new HarnessCapabilityUnsupportedError({
674
+ message: "Harness 'deepagents' requires a JSON schema for structured output.",
675
+ harnessId: "deepagents"
676
+ });
677
+ return wireTurn({
678
+ emit: continueOpts.emit,
679
+ abortSignal: continueOpts.abortSignal
680
+ });
681
+ },
682
+ doSuspendTurn: async () => {
683
+ if (stopped) throw new Error(`deepagents session ${sessionId} is stopped; cannot suspend.`);
684
+ stopped = true;
685
+ const lastSeenEventId = await channel.suspend();
686
+ return {
687
+ type: "continue-turn",
688
+ harnessId: "deepagents",
689
+ specificationVersion: "harness-v1",
690
+ data: {
691
+ ...sandboxCredentialEnvironment == null ? {} : { sandboxCredentialEnvironment },
692
+ bridge: {
693
+ port: bridgePort,
694
+ token: bridgeToken,
695
+ lastSeenEventId,
696
+ ...sandboxId == null ? {} : { sandboxId }
697
+ }
698
+ }
699
+ };
700
+ },
701
+ doDetach: async () => {
702
+ if (stopped) throw new Error(`deepagents session ${sessionId} is already stopped; cannot detach.`);
703
+ stopped = true;
704
+ const lastSeenEventId = await channel.suspend();
705
+ return {
706
+ type: "resume-session",
707
+ harnessId: "deepagents",
708
+ specificationVersion: "harness-v1",
709
+ data: {
710
+ ...sandboxCredentialEnvironment == null ? {} : { sandboxCredentialEnvironment },
711
+ bridge: {
712
+ port: bridgePort,
713
+ token: bridgeToken,
714
+ lastSeenEventId,
715
+ ...sandboxId == null ? {} : { sandboxId }
716
+ }
717
+ }
718
+ };
719
+ },
720
+ doCompact: async () => unsupported("manual compaction"),
721
+ doStop: async () => {
722
+ if (stopped) throw new Error(`deepagents session ${sessionId} is already stopped; cannot stop.`);
723
+ stopped = true;
724
+ await teardown({
725
+ channel,
726
+ proc,
727
+ operation: "stop"
728
+ });
729
+ return {
730
+ type: "resume-session",
731
+ harnessId: "deepagents",
732
+ specificationVersion: "harness-v1",
733
+ data: sandboxCredentialEnvironment == null ? {} : { sandboxCredentialEnvironment }
734
+ };
735
+ },
736
+ doDestroy: async () => {
737
+ if (stopped) return;
738
+ stopped = true;
739
+ await teardown({
740
+ channel,
741
+ proc,
742
+ operation: "destroy"
743
+ });
744
+ }
745
+ };
903
746
  }
904
- async function teardown({
905
- channel,
906
- proc,
907
- operation
908
- }) {
909
- channel.beginClose();
910
- try {
911
- if (!channel.isClosed()) {
912
- channel.send({ type: operation });
913
- }
914
- } catch {
915
- }
916
- let stopTimer;
917
- try {
918
- if (proc) {
919
- await Promise.race([
920
- proc.wait(),
921
- new Promise((resolve) => {
922
- stopTimer = setTimeout(resolve, 5e3);
923
- stopTimer.unref?.();
924
- })
925
- ]);
926
- }
927
- } finally {
928
- if (stopTimer) clearTimeout(stopTimer);
929
- try {
930
- await proc?.kill();
931
- } catch {
932
- }
933
- channel.close();
934
- }
747
+ async function teardown({ channel, proc, operation }) {
748
+ channel.beginClose();
749
+ try {
750
+ if (!channel.isClosed()) channel.send({ type: operation });
751
+ } catch {}
752
+ let stopTimer;
753
+ try {
754
+ if (proc) await Promise.race([proc.wait(), new Promise((resolve) => {
755
+ stopTimer = setTimeout(resolve, 5e3);
756
+ stopTimer.unref?.();
757
+ })]);
758
+ } finally {
759
+ if (stopTimer) clearTimeout(stopTimer);
760
+ try {
761
+ await proc?.kill();
762
+ } catch {}
763
+ channel.close();
764
+ }
935
765
  }
936
766
  function extractUserText(prompt) {
937
- if (typeof prompt === "string") return prompt;
938
- const { content } = prompt;
939
- if (typeof content === "string") return content;
940
- const parts = [];
941
- for (const part of content) {
942
- if (part.type !== "text") {
943
- throw new HarnessCapabilityUnsupportedError({
944
- harnessId: "deepagents",
945
- message: `The deepagents harness does not yet support user message parts of type '${part.type}'. Pass a string or a user message whose content contains only text parts.`
946
- });
947
- }
948
- parts.push(part.text);
949
- }
950
- return parts.join("\n\n");
767
+ if (typeof prompt === "string") return prompt;
768
+ const { content } = prompt;
769
+ if (typeof content === "string") return content;
770
+ const parts = [];
771
+ for (const part of content) {
772
+ if (part.type !== "text") throw new HarnessCapabilityUnsupportedError({
773
+ harnessId: "deepagents",
774
+ message: `The deepagents harness does not yet support user message parts of type '${part.type}'. Pass a string or a user message whose content contains only text parts.`
775
+ });
776
+ parts.push(part.text);
777
+ }
778
+ return parts.join("\n\n");
951
779
  }
780
+ //#endregion
781
+ //#region src/index.ts
782
+ /** Default `deepagents` harness instance; equivalent to `createDeepAgents()`. */
783
+ const deepAgents = createDeepAgents();
784
+ //#endregion
785
+ export { VERSION, createDeepAgents, deepAgents };
952
786
 
953
- // src/index.ts
954
- var deepAgents = createDeepAgents();
955
- export {
956
- VERSION,
957
- createDeepAgents,
958
- deepAgents
959
- };
960
787
  //# sourceMappingURL=index.js.map