@ai-sdk/harness-deepagents 1.0.133 → 1.0.135
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 +19 -0
- package/dist/bridge/index.mjs +1343 -2393
- package/dist/bridge/index.mjs.map +1 -1
- package/dist/index.d.ts +131 -129
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +758 -932
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/src/bridge/index.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -1,961 +1,787 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
HarnessCapabilityUnsupportedError,
|
|
6
|
-
harnessV1DiagnosticFromBridgeFrame,
|
|
7
|
-
harnessStateDirectoryPath,
|
|
8
|
-
harnessSessionDataDirectoryPath
|
|
9
|
-
} from "@ai-sdk/harness";
|
|
10
|
-
import {
|
|
11
|
-
applyCredentialForwarding,
|
|
12
|
-
createBridgeToken,
|
|
13
|
-
resolveSandboxCredentialEnvironment,
|
|
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
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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
|
-
|
|
135
|
-
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
|
|
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
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
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
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
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
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
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
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
149
|
+
z.discriminatedUnion("type", [startMessageSchema, ...harnessV1BridgeInboundCommandSchemas]);
|
|
150
|
+
//#endregion
|
|
151
|
+
//#region src/version.ts
|
|
152
|
+
const VERSION = "1.0.135";
|
|
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
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
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
|
-
|
|
304
|
-
|
|
305
|
-
|
|
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
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
homeDir,
|
|
533
|
-
skillsPaths,
|
|
534
|
-
permissionMode,
|
|
535
|
-
builtinToolFiltering: startOpts.builtinToolFiltering,
|
|
536
|
-
recursionLimit: settings.recursionLimit,
|
|
537
|
-
mcpServers: settings.mcpServers,
|
|
538
|
-
headers: startOpts.headers
|
|
539
|
-
});
|
|
540
|
-
}
|
|
541
|
-
};
|
|
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
|
+
};
|
|
542
455
|
}
|
|
543
|
-
function resolveBridgePort({
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
}
|
|
551
|
-
throw new HarnessCapabilityUnsupportedError({
|
|
552
|
-
harnessId: "deepagents",
|
|
553
|
-
message: "The deepagents harness needs a TCP port exposed by the sandbox. Create the sandbox with `ports: [<port>]` or pass `createDeepAgents({ port })`."
|
|
554
|
-
});
|
|
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
|
+
});
|
|
555
463
|
}
|
|
556
|
-
function validateBasicSandboxSettings({
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
});
|
|
567
|
-
}
|
|
568
|
-
if (portEndpoint == null) {
|
|
569
|
-
throw new HarnessCapabilityUnsupportedError({
|
|
570
|
-
harnessId: "deepagents",
|
|
571
|
-
message: "The deepagents harness requires an explicit `portEndpoint` when using a basic sandbox session."
|
|
572
|
-
});
|
|
573
|
-
}
|
|
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
|
+
});
|
|
574
474
|
}
|
|
575
|
-
async function resolveBridgeEndpoint({
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
harnessId: "deepagents",
|
|
586
|
-
message: "The deepagents harness requires an explicit `portEndpoint` when using a basic sandbox session."
|
|
587
|
-
});
|
|
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
|
+
});
|
|
588
485
|
}
|
|
589
|
-
function openWebSocket({
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
const onError = (err) => {
|
|
631
|
-
rejectWithCleanup(err);
|
|
632
|
-
};
|
|
633
|
-
const onAbort = () => rejectWithCleanup(
|
|
634
|
-
abortSignal.reason ?? new Error("WebSocket connection aborted")
|
|
635
|
-
);
|
|
636
|
-
ws.once("open", onOpen);
|
|
637
|
-
ws.once("error", onError);
|
|
638
|
-
abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
639
|
-
});
|
|
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
|
+
});
|
|
640
527
|
}
|
|
641
|
-
function createSession({
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
throw new Error(
|
|
860
|
-
`deepagents session ${sessionId} is already stopped; cannot detach.`
|
|
861
|
-
);
|
|
862
|
-
}
|
|
863
|
-
stopped = true;
|
|
864
|
-
const lastSeenEventId = await channel.suspend();
|
|
865
|
-
const payload = {
|
|
866
|
-
type: "resume-session",
|
|
867
|
-
harnessId: "deepagents",
|
|
868
|
-
specificationVersion: "harness-v1",
|
|
869
|
-
data: {
|
|
870
|
-
...sandboxCredentialEnvironment == null ? {} : { sandboxCredentialEnvironment },
|
|
871
|
-
bridge: {
|
|
872
|
-
port: bridgePort,
|
|
873
|
-
token: bridgeToken,
|
|
874
|
-
lastSeenEventId,
|
|
875
|
-
...sandboxId == null ? {} : { sandboxId }
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
};
|
|
879
|
-
return payload;
|
|
880
|
-
},
|
|
881
|
-
doCompact: async () => unsupported("manual compaction"),
|
|
882
|
-
doStop: async () => {
|
|
883
|
-
if (stopped) {
|
|
884
|
-
throw new Error(
|
|
885
|
-
`deepagents session ${sessionId} is already stopped; cannot stop.`
|
|
886
|
-
);
|
|
887
|
-
}
|
|
888
|
-
stopped = true;
|
|
889
|
-
await teardown({ channel, proc, operation: "stop" });
|
|
890
|
-
const payload = {
|
|
891
|
-
type: "resume-session",
|
|
892
|
-
harnessId: "deepagents",
|
|
893
|
-
specificationVersion: "harness-v1",
|
|
894
|
-
data: sandboxCredentialEnvironment == null ? {} : { sandboxCredentialEnvironment }
|
|
895
|
-
};
|
|
896
|
-
return payload;
|
|
897
|
-
},
|
|
898
|
-
doDestroy: async () => {
|
|
899
|
-
if (stopped) return;
|
|
900
|
-
stopped = true;
|
|
901
|
-
await teardown({ channel, proc, operation: "destroy" });
|
|
902
|
-
}
|
|
903
|
-
};
|
|
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
|
+
};
|
|
904
746
|
}
|
|
905
|
-
async function teardown({
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
stopTimer = setTimeout(resolve, 5e3);
|
|
924
|
-
stopTimer.unref?.();
|
|
925
|
-
})
|
|
926
|
-
]);
|
|
927
|
-
}
|
|
928
|
-
} finally {
|
|
929
|
-
if (stopTimer) clearTimeout(stopTimer);
|
|
930
|
-
try {
|
|
931
|
-
await proc?.kill();
|
|
932
|
-
} catch {
|
|
933
|
-
}
|
|
934
|
-
channel.close();
|
|
935
|
-
}
|
|
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
|
+
}
|
|
936
765
|
}
|
|
937
766
|
function extractUserText(prompt) {
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
}
|
|
951
|
-
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");
|
|
952
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 };
|
|
953
786
|
|
|
954
|
-
// src/index.ts
|
|
955
|
-
var deepAgents = createDeepAgents();
|
|
956
|
-
export {
|
|
957
|
-
VERSION,
|
|
958
|
-
createDeepAgents,
|
|
959
|
-
deepAgents
|
|
960
|
-
};
|
|
961
787
|
//# sourceMappingURL=index.js.map
|