@ai-sdk/harness-deepagents 1.0.70 → 1.0.72

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.d.ts CHANGED
@@ -2,7 +2,12 @@ import * as _ai_sdk_provider_utils from '@ai-sdk/provider-utils';
2
2
  import * as _ai_sdk_harness from '@ai-sdk/harness';
3
3
  import { HarnessV1, HarnessV1BuiltinTool } from '@ai-sdk/harness';
4
4
 
5
- type DeepAgentsAuthOptions = {
5
+ type DeepAgentsResolvedAuthenticationMode = 'anthropic' | 'ai-gateway';
6
+ type DeepAgentsAuthenticationMode = DeepAgentsResolvedAuthenticationMode | 'auto';
7
+ /**
8
+ * @deprecated Passing an object to auth options is deprecated. Use a `DeepAgentsAuthenticationMode` string value ("auto" | "anthropic" | "ai-gateway") instead, and pass credentials via environment variables.
9
+ */
10
+ type LegacyDeepAgentsAuthOptions = {
6
11
  readonly anthropic?: {
7
12
  readonly apiKey?: string;
8
13
  readonly authToken?: string;
@@ -13,6 +18,7 @@ type DeepAgentsAuthOptions = {
13
18
  readonly baseUrl?: string;
14
19
  };
15
20
  };
21
+ type DeepAgentsAuthOptions = DeepAgentsAuthenticationMode | LegacyDeepAgentsAuthOptions;
16
22
 
17
23
  type DeepAgentsThinkingConfig = {
18
24
  readonly type: 'adaptive';
@@ -130,4 +136,4 @@ declare const deepAgents: _ai_sdk_harness.HarnessV1<{
130
136
  }, any, any>;
131
137
  }>;
132
138
 
133
- export { type DeepAgentsAuthOptions, type DeepAgentsHarnessSettings, type DeepAgentsThinkingConfig, VERSION, createDeepAgents, deepAgents };
139
+ export { type DeepAgentsAuthOptions, type DeepAgentsAuthenticationMode, type DeepAgentsHarnessSettings, type DeepAgentsThinkingConfig, VERSION, createDeepAgents, deepAgents };
package/dist/index.js CHANGED
@@ -1,8 +1,6 @@
1
1
  // src/deepagents-harness.ts
2
2
  import { randomBytes } from "crypto";
3
- import { readFile } from "fs/promises";
4
3
  import { posix } from "path";
5
- import { fileURLToPath } from "url";
6
4
  import {
7
5
  commonTool,
8
6
  HarnessCapabilityUnsupportedError,
@@ -14,9 +12,11 @@ import {
14
12
  createBridgeStartupError,
15
13
  drainBridgeProcessStream,
16
14
  forwardBridgeProcessStream,
15
+ maskSandboxCredentials,
17
16
  resolveSandboxHomeDir,
18
17
  SandboxChannel,
19
18
  shellQuote,
19
+ warnCredentialBrokeringUnavailable,
20
20
  waitForBridgeReady,
21
21
  writeSkills as writeHarnessSkills
22
22
  } from "@ai-sdk/harness/utils";
@@ -24,24 +24,148 @@ import { tool } from "@ai-sdk/provider-utils";
24
24
  import { WebSocket } from "ws";
25
25
  import { z as z2 } from "zod/v4";
26
26
 
27
+ // src/deepagents-bootstrap.ts
28
+ import { readFile } from "fs/promises";
29
+ import { fileURLToPath } from "url";
30
+ var DEEPAGENTS_BOOTSTRAP_DIR = ".harness-bootstrap/deepagents";
31
+ var RIPGREP_VERSION = "14.1.1";
32
+ var RIPGREP_SHA256_X64 = "4cf9f2741e6c465ffdb7c26f38056a59e2a2544b51f7cc128ef28337eeae4d8e";
33
+ var RIPGREP_SHA256_ARM = "c827481c4ff4ea10c9dc7a4022c8de5db34a5737cb74484d62eb94a95841ab2f";
34
+ var cachedBootstrap;
35
+ async function getDeepAgentsBootstrap() {
36
+ if (cachedBootstrap != null) return cachedBootstrap;
37
+ const [bridge, pkg, lock] = await Promise.all([
38
+ readBridgeAsset("index.mjs"),
39
+ readBridgeAsset("package.json"),
40
+ readBridgeAsset("pnpm-lock.yaml")
41
+ ]);
42
+ cachedBootstrap = {
43
+ harnessId: "deepagents",
44
+ bootstrapDir: DEEPAGENTS_BOOTSTRAP_DIR,
45
+ files: [
46
+ { path: `${DEEPAGENTS_BOOTSTRAP_DIR}/bridge.mjs`, content: bridge },
47
+ { path: `${DEEPAGENTS_BOOTSTRAP_DIR}/package.json`, content: pkg },
48
+ { path: `${DEEPAGENTS_BOOTSTRAP_DIR}/pnpm-lock.yaml`, content: lock }
49
+ ],
50
+ commands: [
51
+ { command: installRipgrepCommand() },
52
+ {
53
+ command: "pnpm install --frozen-lockfile --store-dir .pnpm-store"
54
+ }
55
+ ]
56
+ };
57
+ return cachedBootstrap;
58
+ }
59
+ function installRipgrepCommand() {
60
+ const v = RIPGREP_VERSION;
61
+ return [
62
+ "command -v rg >/dev/null 2>&1 || {",
63
+ 'case "$(uname -m)" in',
64
+ `aarch64) a=aarch64-unknown-linux-gnu; sha=${RIPGREP_SHA256_ARM} ;;`,
65
+ `*) a=x86_64-unknown-linux-musl; sha=${RIPGREP_SHA256_X64} ;;`,
66
+ "esac;",
67
+ `f=/tmp/ripgrep-${v}.tar.gz;`,
68
+ `curl -fsSL "https://github.com/BurntSushi/ripgrep/releases/download/${v}/ripgrep-${v}-$a.tar.gz" -o "$f"`,
69
+ '&& echo "$sha $f" | sha256sum -c -',
70
+ '&& tar xzf "$f" -C /tmp',
71
+ `&& mv "/tmp/ripgrep-${v}-$a/rg" /usr/local/bin/rg && chmod +x /usr/local/bin/rg;`,
72
+ "}"
73
+ ].join(" ");
74
+ }
75
+ async function readBridgeAsset(name) {
76
+ const candidates = [
77
+ new URL(`./bridge/${name}`, import.meta.url),
78
+ new URL(`../bridge/${name}`, import.meta.url)
79
+ ];
80
+ let lastErr;
81
+ for (const url of candidates) {
82
+ try {
83
+ return await readFile(fileURLToPath(url), "utf8");
84
+ } catch (err) {
85
+ const code = err.code;
86
+ if (code !== "ENOENT") throw err;
87
+ lastErr = err;
88
+ }
89
+ }
90
+ throw lastErr ?? new Error(`bridge asset not found: ${name}`);
91
+ }
92
+
27
93
  // src/deepagents-auth.ts
28
- import { getAiGatewayAuthFromEnv } from "@ai-sdk/harness/utils";
94
+ import {
95
+ createCredentialRequestTransformation,
96
+ getAiGatewayAuthFromEnv
97
+ } from "@ai-sdk/harness/utils";
98
+ var DEEPAGENTS_CREDENTIAL_ENVIRONMENT_VARIABLES = [
99
+ "AI_GATEWAY_API_KEY",
100
+ "ANTHROPIC_API_KEY",
101
+ "ANTHROPIC_AUTH_TOKEN"
102
+ ];
103
+ function createDeepAgentsRequestTransformations(env, auth) {
104
+ const headers = {};
105
+ if (env.ANTHROPIC_API_KEY) {
106
+ headers["x-api-key"] = env.ANTHROPIC_API_KEY;
107
+ }
108
+ if (env.ANTHROPIC_AUTH_TOKEN) {
109
+ headers.Authorization = `Bearer ${env.ANTHROPIC_AUTH_TOKEN}`;
110
+ }
111
+ return Object.keys(headers).length === 0 ? [] : [
112
+ createCredentialRequestTransformation({
113
+ baseUrl: auth === "ai-gateway" ? env.ANTHROPIC_BASE_URL : env.ANTHROPIC_BASE_URL ?? "https://api.anthropic.com",
114
+ headers
115
+ })
116
+ ];
117
+ }
29
118
  function resolveDeepAgentsEnv({
30
119
  auth,
31
120
  processEnv = process.env
32
121
  }) {
33
- if (auth?.anthropic) {
34
- return pickAnthropic({ explicit: auth.anthropic, processEnv });
122
+ const normalizedAuth = normalizeDeepAgentsAuthToLegacyAuth(auth);
123
+ if (normalizedAuth?.anthropic) {
124
+ return pickAnthropic({ explicit: normalizedAuth.anthropic, processEnv });
35
125
  }
36
126
  const gatewayAuthFromEnv = getAiGatewayAuthFromEnv({ env: processEnv });
37
- if (auth?.gateway) {
38
- return pickGateway({ explicit: auth.gateway, gatewayAuthFromEnv });
127
+ if (normalizedAuth?.gateway) {
128
+ return pickGateway({
129
+ explicit: normalizedAuth.gateway,
130
+ gatewayAuthFromEnv
131
+ });
39
132
  }
40
133
  if (gatewayAuthFromEnv.apiKey) {
41
134
  return pickGateway({ explicit: {}, gatewayAuthFromEnv });
42
135
  }
43
136
  return pickAnthropic({ processEnv });
44
137
  }
138
+ function resolveDeepAgentsAuthenticationMode({
139
+ auth,
140
+ processEnv = process.env
141
+ }) {
142
+ if (auth === "anthropic" || typeof auth !== "string" && auth?.anthropic) {
143
+ return "anthropic";
144
+ }
145
+ if (auth === "ai-gateway" || typeof auth !== "string" && auth?.gateway) {
146
+ return "ai-gateway";
147
+ }
148
+ return getAiGatewayAuthFromEnv({ env: processEnv }).apiKey ? "ai-gateway" : "anthropic";
149
+ }
150
+ function normalizeDeepAgentsAuthToLegacyAuth(auth) {
151
+ if (auth == null || auth === "auto") {
152
+ return void 0;
153
+ }
154
+ if (typeof auth === "string") {
155
+ switch (auth) {
156
+ case "anthropic":
157
+ return { anthropic: {} };
158
+ case "ai-gateway":
159
+ return { gateway: {} };
160
+ default:
161
+ return void 0;
162
+ }
163
+ }
164
+ console.warn(
165
+ '[deepagents] Passing an object to auth options is deprecated. Use a string mode ("auto" | "anthropic" | "ai-gateway") instead, and pass credentials via environment variables.'
166
+ );
167
+ return auth;
168
+ }
45
169
  function pickAnthropic({
46
170
  explicit,
47
171
  processEnv
@@ -114,30 +238,10 @@ var inboundMessageSchema = z.discriminatedUnion("type", [
114
238
  ]);
115
239
 
116
240
  // src/version.ts
117
- var VERSION = true ? "1.0.70" : "0.0.0-test";
241
+ var VERSION = true ? "1.0.72" : "0.0.0-test";
118
242
 
119
243
  // src/deepagents-harness.ts
120
- var BOOTSTRAP_DIR = ".harness-bootstrap/deepagents";
121
244
  var DEEPAGENTS_CLIENT_APP = `ai-sdk/harness-deepagents/${VERSION}`;
122
- var RIPGREP_VERSION = "14.1.1";
123
- var RIPGREP_SHA256_X64 = "4cf9f2741e6c465ffdb7c26f38056a59e2a2544b51f7cc128ef28337eeae4d8e";
124
- var RIPGREP_SHA256_ARM = "c827481c4ff4ea10c9dc7a4022c8de5db34a5737cb74484d62eb94a95841ab2f";
125
- function installRipgrepCommand() {
126
- const v = RIPGREP_VERSION;
127
- return [
128
- "command -v rg >/dev/null 2>&1 || {",
129
- 'case "$(uname -m)" in',
130
- `aarch64) a=aarch64-unknown-linux-gnu; sha=${RIPGREP_SHA256_ARM} ;;`,
131
- `*) a=x86_64-unknown-linux-musl; sha=${RIPGREP_SHA256_X64} ;;`,
132
- "esac;",
133
- `f=/tmp/ripgrep-${v}.tar.gz;`,
134
- `curl -fsSL "https://github.com/BurntSushi/ripgrep/releases/download/${v}/ripgrep-${v}-$a.tar.gz" -o "$f"`,
135
- '&& echo "$sha $f" | sha256sum -c -',
136
- '&& tar xzf "$f" -C /tmp',
137
- `&& mv "/tmp/ripgrep-${v}-$a/rg" /usr/local/bin/rg && chmod +x /usr/local/bin/rg;`,
138
- "}"
139
- ].join(" ");
140
- }
141
245
  var SKILLS_SOURCE_PATH = "/.agents/skills";
142
246
  var DEEPAGENTS_BUILTIN_TOOLS = {
143
247
  read: commonTool("read", {
@@ -207,7 +311,6 @@ var deepAgentsResumeStateSchema = z2.object({
207
311
  bridge: deepAgentsBridgeCoordsSchema.optional()
208
312
  });
209
313
  function createDeepAgents(settings = {}) {
210
- let cachedBootstrap;
211
314
  return {
212
315
  specificationVersion: "harness-v1",
213
316
  harnessId: "deepagents",
@@ -215,38 +318,39 @@ function createDeepAgents(settings = {}) {
215
318
  // Built-in tool approvals are gated in-bridge via DeepAgents' interruptOn (HITL) middleware.
216
319
  supportsBuiltinToolApprovals: true,
217
320
  lifecycleStateSchema: deepAgentsResumeStateSchema,
218
- getBootstrap: async () => {
219
- if (cachedBootstrap != null) return cachedBootstrap;
220
- const [bridge, pkg, lock] = await Promise.all([
221
- readBridgeAsset("index.mjs"),
222
- readBridgeAsset("package.json"),
223
- readBridgeAsset("pnpm-lock.yaml")
224
- ]);
225
- cachedBootstrap = {
226
- harnessId: "deepagents",
227
- bootstrapDir: BOOTSTRAP_DIR,
228
- files: [
229
- { path: `${BOOTSTRAP_DIR}/bridge.mjs`, content: bridge },
230
- { path: `${BOOTSTRAP_DIR}/package.json`, content: pkg },
231
- { path: `${BOOTSTRAP_DIR}/pnpm-lock.yaml`, content: lock }
232
- ],
233
- commands: [
234
- { command: installRipgrepCommand() },
235
- {
236
- command: "pnpm install --frozen-lockfile --store-dir .pnpm-store"
237
- }
238
- ]
239
- };
240
- return cachedBootstrap;
241
- },
321
+ getBootstrap: getDeepAgentsBootstrap,
242
322
  doStart: async (startOpts) => {
243
323
  const permissionMode = startOpts.permissionMode;
244
324
  const sandboxSession = startOpts.sandboxSession;
325
+ const authenticationMode = resolveDeepAgentsAuthenticationMode({
326
+ auth: settings.auth
327
+ });
328
+ const resolvedAuthEnvironment = resolveDeepAgentsEnv({
329
+ auth: settings.auth
330
+ });
331
+ let sandboxAuthEnvironment = resolvedAuthEnvironment;
332
+ if (sandboxSession.addRequestTransformations != null) {
333
+ const requestTransformations = createDeepAgentsRequestTransformations(
334
+ resolvedAuthEnvironment,
335
+ authenticationMode
336
+ );
337
+ if (requestTransformations.length > 0) {
338
+ await sandboxSession.addRequestTransformations(
339
+ requestTransformations
340
+ );
341
+ }
342
+ sandboxAuthEnvironment = maskSandboxCredentials({
343
+ environment: resolvedAuthEnvironment,
344
+ credentialEnvironmentVariables: DEEPAGENTS_CREDENTIAL_ENVIRONMENT_VARIABLES
345
+ });
346
+ } else {
347
+ warnCredentialBrokeringUnavailable();
348
+ }
245
349
  const session = sandboxSession.restricted();
246
350
  const sandboxId = sandboxSession.id;
247
351
  const bootstrapDir = posix.resolve(
248
352
  sandboxSession.defaultWorkingDirectory,
249
- BOOTSTRAP_DIR
353
+ DEEPAGENTS_BOOTSTRAP_DIR
250
354
  );
251
355
  const lifecycleState = startOpts.continueFrom ?? startOpts.resumeFrom;
252
356
  const isResume = lifecycleState != null;
@@ -269,12 +373,16 @@ function createDeepAgents(settings = {}) {
269
373
  });
270
374
  if (coords) {
271
375
  try {
272
- const attachUrl = await sandboxSession.getPortUrl({
376
+ const endpoint2 = await sandboxSession.getPortEndpoint({
273
377
  port: coords.port,
274
378
  protocol: "ws"
275
- }) + `?agent_bridge_token=${encodeURIComponent(coords.token)}`;
379
+ });
380
+ const attachEndpoint = withBridgeToken({
381
+ endpoint: endpoint2,
382
+ token: coords.token
383
+ });
276
384
  const attachChannel = new SandboxChannel({
277
- connect: () => openWebSocket(attachUrl),
385
+ connect: () => openWebSocket(attachEndpoint),
278
386
  outboundSchema: outboundMessageSchema,
279
387
  initialLastSeenEventId: coords.lastSeenEventId,
280
388
  onDiagnostic,
@@ -319,7 +427,7 @@ function createDeepAgents(settings = {}) {
319
427
  skillsPaths.push(homeSkillsRoot);
320
428
  }
321
429
  const env = {
322
- ...resolveDeepAgentsEnv({ auth: settings.auth }),
430
+ ...sandboxAuthEnvironment,
323
431
  AI_SDK_HARNESS_CLIENT_APP: DEEPAGENTS_CLIENT_APP,
324
432
  BRIDGE_CHANNEL_TOKEN: token,
325
433
  BRIDGE_WS_PORT: String(port)
@@ -369,12 +477,13 @@ function createDeepAgents(settings = {}) {
369
477
  })
370
478
  });
371
479
  void drainBridgeProcessStream(proc.stdout);
372
- const wsUrl = await sandboxSession.getPortUrl({
480
+ const endpoint = await sandboxSession.getPortEndpoint({
373
481
  port: boundPort,
374
482
  protocol: "ws"
375
- }) + `?agent_bridge_token=${encodeURIComponent(token)}`;
483
+ });
484
+ const bridgeEndpoint = withBridgeToken({ endpoint, token });
376
485
  const channel = new SandboxChannel({
377
- connect: () => openWebSocket(wsUrl),
486
+ connect: () => openWebSocket(bridgeEndpoint),
378
487
  outboundSchema: outboundMessageSchema,
379
488
  onDiagnostic,
380
489
  onBridgeError
@@ -410,23 +519,6 @@ function resolveBridgePort(sandboxSession, override) {
410
519
  message: "The deepagents harness needs a TCP port exposed by the sandbox. Create the sandbox with `ports: [<port>]` or pass `createDeepAgents({ port })`."
411
520
  });
412
521
  }
413
- async function readBridgeAsset(name) {
414
- const candidates = [
415
- new URL(`./bridge/${name}`, import.meta.url),
416
- new URL(`../bridge/${name}`, import.meta.url)
417
- ];
418
- let lastErr;
419
- for (const url of candidates) {
420
- try {
421
- return await readFile(fileURLToPath(url), "utf8");
422
- } catch (err) {
423
- const code = err.code;
424
- if (code !== "ENOENT") throw err;
425
- lastErr = err;
426
- }
427
- }
428
- throw lastErr ?? new Error(`bridge asset not found: ${name}`);
429
- }
430
522
  async function writeSkills({
431
523
  sandbox,
432
524
  root,
@@ -444,9 +536,14 @@ async function writeSkills({
444
536
  invalidSkillFilePathMessage: ({ skillName, filePath }) => `Invalid skill file path for '${skillName}': ${filePath}`
445
537
  });
446
538
  }
447
- function openWebSocket(url) {
539
+ function openWebSocket({
540
+ url,
541
+ headers
542
+ }) {
448
543
  return new Promise((resolve, reject) => {
449
- const ws = new WebSocket(url);
544
+ const ws = new WebSocket(url, {
545
+ headers: headers == null ? void 0 : { ...headers }
546
+ });
450
547
  const onOpen = () => {
451
548
  ws.off("error", onError);
452
549
  resolve(ws);
@@ -459,6 +556,14 @@ function openWebSocket(url) {
459
556
  ws.once("error", onError);
460
557
  });
461
558
  }
559
+ function withBridgeToken({
560
+ endpoint,
561
+ token
562
+ }) {
563
+ const bridgeUrl = new URL(endpoint.url);
564
+ bridgeUrl.searchParams.set("agent_bridge_token", token);
565
+ return { ...endpoint, url: bridgeUrl.toString() };
566
+ }
462
567
  function createSession({
463
568
  sessionId,
464
569
  channel,