@ai-sdk/harness-deepagents 1.0.10 → 1.0.12

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
@@ -9,8 +9,11 @@ import {
9
9
  } from "@ai-sdk/harness";
10
10
  import {
11
11
  markBridgeStarting,
12
+ resolveSandboxHomeDir,
12
13
  SandboxChannel,
13
- waitForBridgeReady
14
+ shellQuote,
15
+ waitForBridgeReady,
16
+ writeSkills as writeHarnessSkills
14
17
  } from "@ai-sdk/harness/utils";
15
18
  import { tool } from "@ai-sdk/provider-utils";
16
19
  import { WebSocket } from "ws";
@@ -254,6 +257,7 @@ function createDeepAgents(settings = {}) {
254
257
  isResume: true,
255
258
  attached: true,
256
259
  permissionMode,
260
+ builtinToolFiltering: startOpts.builtinToolFiltering,
257
261
  recursionLimit: settings.recursionLimit
258
262
  });
259
263
  } catch {
@@ -330,6 +334,7 @@ function createDeepAgents(settings = {}) {
330
334
  attached: false,
331
335
  skillsPaths,
332
336
  permissionMode,
337
+ builtinToolFiltering: startOpts.builtinToolFiltering,
333
338
  recursionLimit: settings.recursionLimit
334
339
  });
335
340
  }
@@ -360,68 +365,22 @@ async function readBridgeAsset(name) {
360
365
  }
361
366
  throw lastErr ?? new Error(`bridge asset not found: ${name}`);
362
367
  }
363
- async function resolveSandboxHomeDir({
364
- sandbox,
365
- abortSignal
366
- }) {
367
- const result = await sandbox.run({
368
- command: 'printf "%s" "$HOME"',
369
- abortSignal
370
- });
371
- const homeDir = result.stdout.trim();
372
- if (result.exitCode !== 0 || !homeDir.startsWith("/")) {
373
- throw new Error(
374
- `Unable to resolve sandbox HOME directory: ${result.stderr || result.stdout}`
375
- );
376
- }
377
- return homeDir;
378
- }
379
368
  async function writeSkills({
380
369
  sandbox,
381
370
  root,
382
371
  skills,
383
372
  abortSignal
384
373
  }) {
385
- for (const skill of skills) {
386
- const name = safeSkillName(skill.name);
387
- const skillDir = `${root}/${name}`;
388
- const content = `---
389
- name: ${name}
390
- description: ${skill.description}
391
- ---
392
-
393
- ${skill.content}`;
394
- await sandbox.writeTextFile({
395
- path: `${skillDir}/SKILL.md`,
396
- content,
397
- abortSignal
398
- });
399
- for (const file of skill.files ?? []) {
400
- await sandbox.writeTextFile({
401
- path: `${skillDir}/${safeSkillFilePath(name, file.path)}`,
402
- content: file.content,
403
- abortSignal
404
- });
405
- }
406
- }
407
- }
408
- function safeSkillName(name) {
409
- if (!/^[a-z0-9]([a-z0-9-]{0,62}[a-z0-9])?$/.test(name)) {
410
- throw new Error(
411
- `Invalid deepagents skill name '${name}': must be lowercase alphanumeric with hyphens, 1-64 chars.`
412
- );
413
- }
414
- return name;
415
- }
416
- function safeSkillFilePath(skillName, filePath) {
417
- const normalized = filePath.replace(/^\/+/, "");
418
- if (normalized === "" || normalized.startsWith("../") || normalized.includes("/../") || normalized.endsWith("/..")) {
419
- throw new Error(`Invalid skill file path for '${skillName}': ${filePath}`);
420
- }
421
- return normalized;
422
- }
423
- function shellQuote(value) {
424
- return `'${value.replace(/'/g, `'\\''`)}'`;
374
+ await writeHarnessSkills({
375
+ sandbox,
376
+ rootDir: root,
377
+ skills,
378
+ abortSignal,
379
+ skillNamePattern: /^[a-z0-9]([a-z0-9-]{0,62}[a-z0-9])?$/,
380
+ invalidSkillNameMessage: ({ name }) => `Invalid deepagents skill name '${name}': must be lowercase alphanumeric with hyphens, 1-64 chars.`,
381
+ filePathMode: "strip-leading-slashes",
382
+ invalidSkillFilePathMessage: ({ skillName, filePath }) => `Invalid skill file path for '${skillName}': ${filePath}`
383
+ });
425
384
  }
426
385
  function openWebSocket(url) {
427
386
  return new Promise((resolve, reject) => {
@@ -466,6 +425,7 @@ function createSession({
466
425
  attached,
467
426
  skillsPaths,
468
427
  permissionMode,
428
+ builtinToolFiltering,
469
429
  recursionLimit
470
430
  }) {
471
431
  let stopped = false;
@@ -607,6 +567,7 @@ function createSession({
607
567
  ...model ? { model } : {},
608
568
  ...skillsPaths?.length ? { skillsPaths } : {},
609
569
  ...permissionMode ? { permissionMode } : {},
570
+ ...builtinToolFiltering ? { builtinToolFiltering } : {},
610
571
  ...recursionLimit != null ? { recursionLimit } : {}
611
572
  });
612
573
  return control;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/deepagents-harness.ts","../src/deepagents-auth.ts","../src/deepagents-bridge-protocol.ts","../src/index.ts"],"sourcesContent":["import { randomBytes } from 'node:crypto';\nimport { readFile } from 'node:fs/promises';\nimport { fileURLToPath } from 'node:url';\nimport {\n commonTool,\n HarnessCapabilityUnsupportedError,\n harnessV1DiagnosticFromBridgeFrame,\n type HarnessV1,\n type HarnessV1Bootstrap,\n type HarnessV1BuiltinTool,\n type HarnessV1ContinueTurnState,\n type HarnessV1NetworkSandboxSession,\n type HarnessV1PermissionMode,\n type HarnessV1Prompt,\n type HarnessV1PromptControl,\n type HarnessV1ResumeSessionState,\n type HarnessV1Session,\n type HarnessV1Skill,\n type HarnessV1StreamPart,\n} from '@ai-sdk/harness';\nimport {\n markBridgeStarting,\n SandboxChannel,\n waitForBridgeReady,\n} from '@ai-sdk/harness/utils';\nimport { tool, type Experimental_SandboxProcess } from '@ai-sdk/provider-utils';\nimport { WebSocket } from 'ws';\nimport { z } from 'zod/v4';\nimport {\n resolveDeepAgentsEnv,\n type DeepAgentsAuthOptions,\n} from './deepagents-auth';\nimport {\n outboundMessageSchema,\n type InboundMessage,\n type OutboundMessage,\n} from './deepagents-bridge-protocol';\n\ntype DeepAgentsChannel = SandboxChannel<OutboundMessage, InboundMessage>;\n\n// Pure derived state in /tmp; reinstalled per sandbox, persistence is the provider snapshot.\nconst BOOTSTRAP_DIR = '/tmp/harness/deepagents';\n\n// Pinned ripgrep release + per-arch tarball checksums (verified before install).\nconst RIPGREP_VERSION = '14.1.1';\nconst RIPGREP_SHA256_X64 =\n '4cf9f2741e6c465ffdb7c26f38056a59e2a2544b51f7cc128ef28337eeae4d8e';\nconst RIPGREP_SHA256_ARM =\n 'c827481c4ff4ea10c9dc7a4022c8de5db34a5737cb74484d62eb94a95841ab2f';\n\n// Idempotent, checksum-verified install of a static ripgrep binary into a PATH dir.\n// DeepAgents' grep shells out to `rg`; without it, its fallback reads the whole workdir (incl. node_modules) into memory and OOMs. Skipped if `rg` already exists.\nfunction installRipgrepCommand(): string {\n const v = RIPGREP_VERSION;\n return [\n 'command -v rg >/dev/null 2>&1 || {',\n 'case \"$(uname -m)\" in',\n `aarch64) a=aarch64-unknown-linux-gnu; sha=${RIPGREP_SHA256_ARM} ;;`,\n `*) a=x86_64-unknown-linux-musl; sha=${RIPGREP_SHA256_X64} ;;`,\n 'esac;',\n `f=/tmp/ripgrep-${v}.tar.gz;`,\n `curl -fsSL \"https://github.com/BurntSushi/ripgrep/releases/download/${v}/ripgrep-${v}-$a.tar.gz\" -o \"$f\"`,\n '&& echo \"$sha $f\" | sha256sum -c -',\n '&& tar xzf \"$f\" -C /tmp',\n `&& mv \"/tmp/ripgrep-${v}-$a/rg\" /usr/local/bin/rg && chmod +x /usr/local/bin/rg;`,\n '}',\n ].join(' ');\n}\n\n// Skills source subpath, written under $HOME (out of the work dir so it can't clash with code cloned into the work dir) and also discovered from <workDir> for repo-provided skills.\nconst SKILLS_SOURCE_PATH = '/.agents/skills';\n\nexport type DeepAgentsHarnessSettings = {\n readonly auth?: DeepAgentsAuthOptions;\n /** Model id for the DeepAgents runtime, e.g. `claude-sonnet-4` (converted to `provider:model`). */\n readonly model?: string;\n /** Bridge port override; defaults to the sandbox's first declared port. */\n readonly port?: number;\n /** Maximum milliseconds to wait for the bridge to advertise its port. Defaults to 120000. */\n readonly startupTimeoutMs?: number;\n /** Max LangGraph super-steps per turn before it errors. Defaults to 100; raise for long multi-step tasks. */\n readonly recursionLimit?: number;\n};\n\n// Every model-callable DeepAgents built-in, keyed by what the bridge emits (commonName ?? nativeName); all must be listed or AI SDK throws AI_NoSuchToolError.\nconst DEEPAGENTS_BUILTIN_TOOLS = {\n read: commonTool('read', {\n nativeName: 'read_file',\n toolUseKind: 'readonly',\n description: 'Read file contents',\n inputSchema: z.object({ file_path: z.string() }),\n }),\n write: commonTool('write', {\n nativeName: 'write_file',\n toolUseKind: 'edit',\n description: 'Create a file',\n inputSchema: z.object({ file_path: z.string(), content: z.string() }),\n }),\n edit: commonTool('edit', {\n nativeName: 'edit_file',\n toolUseKind: 'edit',\n description: 'Perform exact string replacements in a file',\n inputSchema: z.object({\n file_path: z.string(),\n old_string: z.string(),\n new_string: z.string(),\n }),\n }),\n bash: commonTool('bash', {\n nativeName: 'execute',\n toolUseKind: 'bash',\n description: 'Run a shell command',\n inputSchema: z.object({ command: z.string() }),\n }),\n grep: commonTool('grep', {\n nativeName: 'grep',\n toolUseKind: 'readonly',\n description: 'Search file contents',\n inputSchema: z.object({ pattern: z.string() }),\n }),\n glob: commonTool('glob', {\n nativeName: 'glob',\n toolUseKind: 'readonly',\n description: 'Find files matching a glob pattern',\n inputSchema: z.object({ pattern: z.string() }),\n }),\n // No common-name equivalent — keyed by native name.\n ls: tool({\n description: 'List files in a directory',\n inputSchema: z.object({ path: z.string().optional() }),\n }),\n task: tool({\n description: 'Spawn a subagent to handle a delegated task',\n inputSchema: z.object({\n description: z.string().optional(),\n subagent_type: z.string().optional(),\n }),\n }),\n write_todos: tool({\n description: 'Manage a structured todo list',\n inputSchema: z.object({ todos: z.array(z.unknown()).optional() }),\n }),\n} as const satisfies Record<string, HarnessV1BuiltinTool<any, any>>;\n\n// Live bridge coordinates returned by doDetach/doSuspendTurn so a later process can reattach.\nconst deepAgentsBridgeCoordsSchema = z.object({\n port: z.number(),\n token: z.string(),\n lastSeenEventId: z.number(),\n sandboxId: z.string().optional(),\n});\nconst deepAgentsResumeStateSchema = z.object({\n bridge: deepAgentsBridgeCoordsSchema.optional(),\n});\ntype DeepAgentsBridgeCoords = z.infer<typeof deepAgentsBridgeCoordsSchema>;\n\nexport function createDeepAgents(\n settings: DeepAgentsHarnessSettings = {},\n): HarnessV1<typeof DEEPAGENTS_BUILTIN_TOOLS> {\n let cachedBootstrap: HarnessV1Bootstrap | undefined;\n\n return {\n specificationVersion: 'harness-v1',\n harnessId: 'deepagents',\n builtinTools: DEEPAGENTS_BUILTIN_TOOLS,\n // Built-in tool approvals are gated in-bridge via DeepAgents' interruptOn (HITL) middleware.\n supportsBuiltinToolApprovals: true,\n lifecycleStateSchema: deepAgentsResumeStateSchema,\n getBootstrap: async () => {\n if (cachedBootstrap != null) return cachedBootstrap;\n const [bridge, pkg, lock] = await Promise.all([\n readBridgeAsset('index.mjs'),\n readBridgeAsset('package.json'),\n readBridgeAsset('pnpm-lock.yaml'),\n ]);\n cachedBootstrap = {\n harnessId: 'deepagents',\n bootstrapDir: BOOTSTRAP_DIR,\n files: [\n { path: `${BOOTSTRAP_DIR}/bridge.mjs`, content: bridge },\n { path: `${BOOTSTRAP_DIR}/package.json`, content: pkg },\n { path: `${BOOTSTRAP_DIR}/pnpm-lock.yaml`, content: lock },\n ],\n commands: [\n { command: `mkdir -p ${BOOTSTRAP_DIR}` },\n { command: installRipgrepCommand() },\n {\n command: `pnpm --dir ${BOOTSTRAP_DIR} install --frozen-lockfile --store-dir ${BOOTSTRAP_DIR}/.pnpm-store`,\n },\n ],\n };\n return cachedBootstrap;\n },\n doStart: async startOpts => {\n const permissionMode = startOpts.permissionMode;\n const sandboxSession = startOpts.sandboxSession;\n const session = sandboxSession.restricted();\n const sandboxId = sandboxSession.id;\n\n const lifecycleState = startOpts.continueFrom ?? startOpts.resumeFrom;\n const isResume = lifecycleState != null;\n const isContinue = startOpts.continueFrom != null;\n const coords =\n isResume && typeof lifecycleState?.data === 'object'\n ? (lifecycleState.data as { bridge?: DeepAgentsBridgeCoords }).bridge\n : undefined;\n\n const workDir = startOpts.sessionWorkDir;\n const sessionDataDir = `${sandboxSession.defaultWorkingDirectory}/.agent-runs/${startOpts.sessionId}`;\n const bridgeStateDir = `${sessionDataDir}/bridge`;\n const timeoutMs = settings.startupTimeoutMs ?? 120_000;\n\n const report = startOpts.observability?.report;\n const onDiagnostic = report\n ? (frame: Parameters<typeof harnessV1DiagnosticFromBridgeFrame>[0]) =>\n report(\n harnessV1DiagnosticFromBridgeFrame(frame, {\n sessionId: startOpts.sessionId,\n timestamp: Date.now(),\n }),\n )\n : undefined;\n\n // Attach to the still-running bridge (continueFrom replays past the cursor); on failure fall through to a fresh spawn.\n if (coords) {\n try {\n const attachUrl =\n (await sandboxSession.getPortUrl({\n port: coords.port,\n protocol: 'ws',\n })) + `?agent_bridge_token=${encodeURIComponent(coords.token)}`;\n const attachChannel: DeepAgentsChannel = new SandboxChannel({\n connect: () => openWebSocket(attachUrl),\n outboundSchema: outboundMessageSchema,\n initialLastSeenEventId: coords.lastSeenEventId,\n onDiagnostic,\n });\n await attachChannel.open(isContinue ? { resume: true } : undefined);\n return createSession({\n sessionId: startOpts.sessionId,\n channel: attachChannel,\n proc: undefined,\n model: settings.model,\n bridgePort: coords.port,\n bridgeToken: coords.token,\n sandboxId,\n isResume: true,\n attached: true,\n permissionMode,\n recursionLimit: settings.recursionLimit,\n });\n } catch {\n // Bridge no longer reachable — recover by respawning below.\n }\n }\n\n const port = resolveBridgePort(sandboxSession, settings.port);\n const token = randomBytes(32).toString('hex');\n\n // Always discover repo-provided skills under <workDir>/.agents/skills (e.g. a cloned repo); a missing dir is tolerated by deepagents.\n // Absolute paths: LocalShellBackend (non-virtual) treats a leading-slash path as a real fs path.\n const skillsPaths = [`${workDir}${SKILLS_SOURCE_PATH}`];\n // Host-provided skills go to $HOME (out of the work dir) and take priority (listed last → wins on name collision).\n if ((startOpts.skills?.length ?? 0) > 0) {\n const homeDir = await resolveSandboxHomeDir({\n sandbox: session,\n abortSignal: startOpts.abortSignal,\n });\n const homeSkillsRoot = `${homeDir}${SKILLS_SOURCE_PATH}`;\n await writeSkills({\n sandbox: session,\n root: homeSkillsRoot,\n skills: startOpts.skills ?? [],\n abortSignal: startOpts.abortSignal,\n });\n skillsPaths.push(homeSkillsRoot);\n }\n\n const env = {\n ...resolveDeepAgentsEnv({ auth: settings.auth }),\n BRIDGE_CHANNEL_TOKEN: token,\n BRIDGE_WS_PORT: String(port),\n };\n\n await session.run({\n command: `mkdir -p ${shellQuote(workDir)} ${shellQuote(bridgeStateDir)}`,\n abortSignal: startOpts.abortSignal,\n });\n\n await markBridgeStarting({\n sandbox: session,\n bridgeStateDir,\n bridgeType: 'deepagents',\n abortSignal: startOpts.abortSignal,\n });\n\n const proc = await session.spawn({\n command: `node ${BOOTSTRAP_DIR}/bridge.mjs --workdir ${shellQuote(workDir)} --bridge-state-dir ${shellQuote(bridgeStateDir)} --bootstrap-dir ${shellQuote(BOOTSTRAP_DIR)}`,\n env,\n abortSignal: startOpts.abortSignal,\n });\n\n const { port: boundPort } = await waitForBridgeReady({\n proc,\n sandbox: session,\n bridgeStateDir,\n bridgeType: 'deepagents',\n timeoutMs,\n abortSignal: startOpts.abortSignal,\n createTimeoutError: () =>\n new Error('deepagents bridge did not become ready in time.'),\n createExitError: () =>\n new Error('deepagents bridge exited before becoming ready.'),\n });\n void forwardBridgeStderr(proc.stderr);\n\n const wsUrl =\n (await sandboxSession.getPortUrl({\n port: boundPort,\n protocol: 'ws',\n })) + `?agent_bridge_token=${encodeURIComponent(token)}`;\n\n const channel: DeepAgentsChannel = new SandboxChannel({\n connect: () => openWebSocket(wsUrl),\n outboundSchema: outboundMessageSchema,\n onDiagnostic,\n });\n await channel.open();\n\n return createSession({\n sessionId: startOpts.sessionId,\n channel,\n proc,\n model: settings.model,\n bridgePort: boundPort,\n bridgeToken: token,\n sandboxId,\n isResume,\n // Freshly spawned bridge — it must receive the instructions on the first prompt.\n attached: false,\n skillsPaths,\n permissionMode,\n recursionLimit: settings.recursionLimit,\n });\n },\n };\n}\n\nfunction resolveBridgePort(\n sandboxSession: HarnessV1NetworkSandboxSession,\n override: number | undefined,\n): number {\n if (override !== undefined) return override;\n if (sandboxSession.ports.length > 0) return sandboxSession.ports[0];\n throw new HarnessCapabilityUnsupportedError({\n harnessId: 'deepagents',\n message:\n 'The deepagents harness needs a TCP port exposed by the sandbox. ' +\n 'Create the sandbox with `ports: [<port>]` or pass `createDeepAgents({ port })`.',\n });\n}\n\nasync function readBridgeAsset(name: string): Promise<string> {\n const candidates = [\n new URL(`./bridge/${name}`, import.meta.url),\n new URL(`../bridge/${name}`, import.meta.url),\n ];\n let lastErr: unknown;\n for (const url of candidates) {\n try {\n return await readFile(fileURLToPath(url), 'utf8');\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code !== 'ENOENT') throw err;\n lastErr = err;\n }\n }\n throw lastErr ?? new Error(`bridge asset not found: ${name}`);\n}\n\n// Resolve the sandbox $HOME so skills can be written outside the work dir.\nasync function resolveSandboxHomeDir({\n sandbox,\n abortSignal,\n}: {\n sandbox: ReturnType<HarnessV1NetworkSandboxSession['restricted']>;\n abortSignal?: AbortSignal;\n}): Promise<string> {\n const result = await sandbox.run({\n command: 'printf \"%s\" \"$HOME\"',\n abortSignal,\n });\n const homeDir = result.stdout.trim();\n if (result.exitCode !== 0 || !homeDir.startsWith('/')) {\n throw new Error(\n `Unable to resolve sandbox HOME directory: ${result.stderr || result.stdout}`,\n );\n }\n return homeDir;\n}\n\n// Materialize each skill as a native deepagents `<name>/SKILL.md` folder (+ attached files) under the given root, so skills load on demand and file references resolve.\nasync function writeSkills({\n sandbox,\n root,\n skills,\n abortSignal,\n}: {\n sandbox: ReturnType<HarnessV1NetworkSandboxSession['restricted']>;\n root: string;\n skills: ReadonlyArray<HarnessV1Skill>;\n abortSignal?: AbortSignal;\n}): Promise<void> {\n for (const skill of skills) {\n const name = safeSkillName(skill.name);\n const skillDir = `${root}/${name}`;\n // SKILL.md `name` must match the parent directory name (deepagents requirement).\n const content = `---\\nname: ${name}\\ndescription: ${skill.description}\\n---\\n\\n${skill.content}`;\n await sandbox.writeTextFile({\n path: `${skillDir}/SKILL.md`,\n content,\n abortSignal,\n });\n for (const file of skill.files ?? []) {\n await sandbox.writeTextFile({\n path: `${skillDir}/${safeSkillFilePath(name, file.path)}`,\n content: file.content,\n abortSignal,\n });\n }\n }\n}\n\nfunction safeSkillName(name: string): string {\n if (!/^[a-z0-9]([a-z0-9-]{0,62}[a-z0-9])?$/.test(name)) {\n throw new Error(\n `Invalid deepagents skill name '${name}': must be lowercase alphanumeric with hyphens, 1-64 chars.`,\n );\n }\n return name;\n}\n\nfunction safeSkillFilePath(skillName: string, filePath: string): string {\n const normalized = filePath.replace(/^\\/+/, '');\n if (\n normalized === '' ||\n normalized.startsWith('../') ||\n normalized.includes('/../') ||\n normalized.endsWith('/..')\n ) {\n throw new Error(`Invalid skill file path for '${skillName}': ${filePath}`);\n }\n return normalized;\n}\n\nfunction shellQuote(value: string): string {\n return `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n\nfunction openWebSocket(url: string): Promise<WebSocket> {\n return new Promise((resolve, reject) => {\n const ws = new WebSocket(url);\n const onOpen = () => {\n ws.off('error', onError);\n resolve(ws);\n };\n const onError = (err: Error) => {\n ws.off('open', onOpen);\n reject(err);\n };\n ws.once('open', onOpen);\n ws.once('error', onError);\n });\n}\n\nasync function forwardBridgeStderr(\n stream: ReadableStream<Uint8Array>,\n): Promise<void> {\n try {\n const reader = stream.pipeThrough(new TextDecoderStream()).getReader();\n while (true) {\n const { value, done } = await reader.read();\n if (done) return;\n if (value) {\n const trimmed = value.endsWith('\\n') ? value.slice(0, -1) : value;\n if (trimmed.length > 0) {\n // eslint-disable-next-line no-console\n console.log(`[bridge stderr] ${trimmed}`);\n }\n }\n }\n } catch {\n // Reader errors are non-fatal — best-effort diagnostic only.\n }\n}\n\nfunction createSession({\n sessionId,\n channel,\n proc,\n model,\n bridgePort,\n bridgeToken,\n sandboxId,\n isResume,\n attached,\n skillsPaths,\n permissionMode,\n recursionLimit,\n}: {\n sessionId: string;\n channel: DeepAgentsChannel;\n // Undefined on attach — the live bridge was spawned by another process.\n proc: Experimental_SandboxProcess | undefined;\n model: string | undefined;\n bridgePort: number;\n bridgeToken: string;\n sandboxId: string;\n isResume: boolean;\n // True only when attaching to a live bridge that already built the agent with\n // its instructions. A fresh spawn (incl. a respawn on attach failure or a\n // stop-resume) starts a new bridge that must receive the instructions again.\n attached: boolean;\n skillsPaths?: string[];\n permissionMode?: HarnessV1PermissionMode;\n recursionLimit?: number;\n}): HarnessV1Session {\n let stopped = false;\n let instructionsApplied = attached;\n\n const wireTurn = (turnOpts: {\n emit: (event: HarnessV1StreamPart) => void;\n abortSignal?: AbortSignal;\n }): HarnessV1PromptControl => {\n let pendingResolve: (() => void) | undefined;\n let pendingReject: ((err: unknown) => void) | undefined;\n const done = new Promise<void>((resolve, reject) => {\n pendingResolve = resolve;\n pendingReject = reject;\n });\n\n const unsubs: Array<() => void> = [];\n const forward = (event: HarnessV1StreamPart) => {\n try {\n turnOpts.emit(event);\n } catch {}\n };\n\n const eventTypes = [\n 'stream-start',\n 'text-start',\n 'text-delta',\n 'text-end',\n 'reasoning-start',\n 'reasoning-delta',\n 'reasoning-end',\n 'tool-call',\n 'tool-approval-request',\n 'tool-result',\n 'file-change',\n 'finish-step',\n 'raw',\n ] as const;\n let isSettled = false;\n const settleSuccess = () => {\n if (isSettled) return;\n isSettled = true;\n for (const u of unsubs) u();\n pendingResolve!();\n };\n const settleError = (err: unknown) => {\n if (isSettled) return;\n isSettled = true;\n for (const u of unsubs) u();\n pendingReject!(err);\n };\n\n for (const type of eventTypes) {\n unsubs.push(channel.on(type, msg => forward(msg)));\n }\n unsubs.push(\n channel.on('finish', msg => {\n forward(msg);\n settleSuccess();\n }),\n );\n unsubs.push(\n channel.on('error', msg => {\n forward(msg);\n settleError(msg.error);\n }),\n );\n\n // A `'suspended'` close is a graceful slice-boundary freeze (suspend/detach keep the bridge alive for continuation); end the turn cleanly. Any other close is an unexpected bridge failure.\n const onClose = (_code: number, reason: string) => {\n if (isSettled) return;\n if (reason === 'suspended') {\n settleSuccess();\n return;\n }\n settleError(\n new Error('deepagents bridge closed before the turn finished.'),\n );\n };\n channel.onClose(onClose);\n\n const onAbort = () => {\n if (isSettled) return;\n try {\n channel.send({ type: 'abort' });\n } catch {}\n settleError(\n turnOpts.abortSignal?.reason ??\n new DOMException('Aborted', 'AbortError'),\n );\n };\n if (turnOpts.abortSignal) {\n if (turnOpts.abortSignal.aborted) {\n onAbort();\n } else {\n turnOpts.abortSignal.addEventListener('abort', onAbort, { once: true });\n }\n }\n\n return {\n submitToolResult: async input => {\n channel.send({\n type: 'tool-result',\n toolCallId: input.toolCallId,\n output: input.output,\n isError: input.isError,\n });\n },\n submitUserMessage: async text => {\n channel.send({ type: 'user-message', text });\n },\n submitToolApproval: async input => {\n channel.send({\n type: 'tool-approval-response',\n approvalId: input.approvalId,\n approved: input.approved,\n ...(input.reason != null ? { reason: input.reason } : {}),\n });\n },\n done,\n };\n };\n\n const unsupported = (capability: string): never => {\n throw new HarnessCapabilityUnsupportedError({\n harnessId: 'deepagents',\n message: `Harness 'deepagents' does not support ${capability} yet.`,\n });\n };\n\n return {\n sessionId,\n isResume,\n modelId: model,\n doPromptTurn: async promptOpts => {\n const control = wireTurn({\n emit: promptOpts.emit,\n abortSignal: promptOpts.abortSignal,\n });\n\n const applyInstructions =\n !instructionsApplied && !!promptOpts.instructions;\n instructionsApplied = true;\n\n channel.send({\n type: 'start',\n prompt: extractUserText(promptOpts.prompt),\n ...(applyInstructions ? { instructions: promptOpts.instructions } : {}),\n tools: (promptOpts.tools ?? []).map(t => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema,\n })),\n ...(model ? { model } : {}),\n ...(skillsPaths?.length ? { skillsPaths } : {}),\n ...(permissionMode ? { permissionMode } : {}),\n ...(recursionLimit != null ? { recursionLimit } : {}),\n });\n\n return control;\n },\n doContinueTurn: async continueOpts => {\n // Attach/replay: doStart opened with `{ resume: true }` so the bridge replays past the cursor; no `start` is sent (that would clear the replay log).\n return wireTurn({\n emit: continueOpts.emit,\n abortSignal: continueOpts.abortSignal,\n });\n },\n doSuspendTurn: async () => {\n if (stopped) {\n throw new Error(\n `deepagents session ${sessionId} is stopped; cannot suspend.`,\n );\n }\n stopped = true;\n // Freeze the active turn at the cursor, leaving the bridge running so the next slice replays the tail.\n const lastSeenEventId = await channel.suspend();\n const payload: HarnessV1ContinueTurnState = {\n type: 'continue-turn',\n harnessId: 'deepagents',\n specificationVersion: 'harness-v1',\n data: {\n bridge: {\n port: bridgePort,\n token: bridgeToken,\n lastSeenEventId,\n sandboxId,\n },\n },\n };\n return payload;\n },\n doDetach: async () => {\n if (stopped) {\n throw new Error(\n `deepagents session ${sessionId} is already stopped; cannot detach.`,\n );\n }\n stopped = true;\n // Park between turns: close the host socket but leave the bridge running for a later reattach via these coords.\n const lastSeenEventId = await channel.suspend();\n const payload: HarnessV1ResumeSessionState = {\n type: 'resume-session',\n harnessId: 'deepagents',\n specificationVersion: 'harness-v1',\n data: {\n bridge: {\n port: bridgePort,\n token: bridgeToken,\n lastSeenEventId,\n sandboxId,\n },\n },\n };\n return payload;\n },\n doCompact: async () => unsupported('manual compaction'),\n doStop: async () => {\n if (stopped) {\n throw new Error(\n `deepagents session ${sessionId} is already stopped; cannot stop.`,\n );\n }\n stopped = true;\n await teardown(channel, proc);\n // In-memory conversation is lost on teardown; the sandbox snapshot preserves the workspace files, not the conversation.\n const payload: HarnessV1ResumeSessionState = {\n type: 'resume-session',\n harnessId: 'deepagents',\n specificationVersion: 'harness-v1',\n data: {},\n };\n return payload;\n },\n doDestroy: async () => {\n if (stopped) return;\n stopped = true;\n await teardown(channel, proc);\n },\n };\n}\n\nasync function teardown(\n channel: DeepAgentsChannel,\n proc: Experimental_SandboxProcess | undefined,\n): Promise<void> {\n channel.beginClose();\n try {\n if (!channel.isClosed()) {\n channel.send({ type: 'shutdown' });\n }\n } catch {}\n let stopTimer: ReturnType<typeof setTimeout> | undefined;\n try {\n if (proc) {\n await Promise.race([\n proc.wait(),\n new Promise<void>(resolve => {\n stopTimer = setTimeout(resolve, 5000);\n stopTimer.unref?.();\n }),\n ]);\n }\n } finally {\n if (stopTimer) clearTimeout(stopTimer);\n try {\n await proc?.kill();\n } catch {}\n channel.close();\n }\n}\n\n// Reduce the prompt to plain user text; non-text parts are unsupported.\nfunction extractUserText(prompt: HarnessV1Prompt): string {\n if (typeof prompt === 'string') return prompt;\n const { content } = prompt;\n if (typeof content === 'string') return content;\n const parts: string[] = [];\n for (const part of content) {\n if (part.type !== 'text') {\n throw new HarnessCapabilityUnsupportedError({\n harnessId: 'deepagents',\n 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.`,\n });\n }\n parts.push(part.text);\n }\n return parts.join('\\n\\n');\n}\n","import { getAiGatewayAuthFromEnv } from '@ai-sdk/harness/utils';\n\nexport type DeepAgentsAuthOptions = {\n readonly anthropic?: {\n readonly apiKey?: string;\n readonly authToken?: string;\n readonly baseUrl?: string;\n };\n readonly gateway?: {\n readonly apiKey?: string;\n readonly baseUrl?: string;\n };\n};\n\n// DeepAgents always drives the Anthropic client. Non-Anthropic models reach it\n// through AI Gateway's Anthropic-compatible endpoint, which translates to any\n// model (Gemini, OpenAI, etc.), tool calls included.\nexport function resolveDeepAgentsEnv({\n auth,\n processEnv = process.env,\n}: {\n auth?: DeepAgentsAuthOptions;\n processEnv?: Record<string, string | undefined>;\n}): Record<string, string> {\n if (auth?.anthropic) {\n return pickAnthropic({ explicit: auth.anthropic, processEnv });\n }\n\n const gatewayAuthFromEnv = getAiGatewayAuthFromEnv({ env: processEnv });\n if (auth?.gateway) {\n return pickGateway({ explicit: auth.gateway, gatewayAuthFromEnv });\n }\n if (gatewayAuthFromEnv.apiKey) {\n return pickGateway({ explicit: {}, gatewayAuthFromEnv });\n }\n\n return pickAnthropic({ processEnv });\n}\n\nfunction pickAnthropic({\n explicit,\n processEnv,\n}: {\n explicit?: NonNullable<DeepAgentsAuthOptions['anthropic']>;\n processEnv: Record<string, string | undefined>;\n}): Record<string, string> {\n const env: Record<string, string> = {};\n const apiKey = explicit?.apiKey ?? processEnv.ANTHROPIC_API_KEY;\n if (apiKey) env.ANTHROPIC_API_KEY = apiKey;\n const authToken = explicit?.authToken ?? processEnv.ANTHROPIC_AUTH_TOKEN;\n if (authToken) env.ANTHROPIC_AUTH_TOKEN = authToken;\n const baseUrl = explicit?.baseUrl ?? processEnv.ANTHROPIC_BASE_URL;\n if (baseUrl) env.ANTHROPIC_BASE_URL = baseUrl;\n return env;\n}\n\nfunction pickGateway({\n explicit,\n gatewayAuthFromEnv,\n}: {\n explicit: NonNullable<DeepAgentsAuthOptions['gateway']>;\n gatewayAuthFromEnv: ReturnType<typeof getAiGatewayAuthFromEnv>;\n}): Record<string, string> {\n const apiKey = explicit.apiKey ?? gatewayAuthFromEnv.apiKey;\n // The Anthropic SDK appends `/v1/messages`, so the gateway base stays at its root.\n const baseUrl = (explicit.baseUrl ?? gatewayAuthFromEnv.baseUrl).replace(\n /\\/+$/,\n '',\n );\n const env: Record<string, string> = {};\n if (apiKey) {\n env.AI_GATEWAY_API_KEY = apiKey;\n env.ANTHROPIC_API_KEY = apiKey;\n }\n env.ANTHROPIC_BASE_URL = baseUrl;\n return env;\n}\n","import {\n harnessV1BridgeInboundCommandSchemas,\n harnessV1BridgeOutboundMessageSchema,\n harnessV1BridgeReadySchema,\n harnessV1BridgeStartBaseSchema,\n} from '@ai-sdk/harness';\nimport { z } from 'zod/v4';\n\n// Deep Agents bridge wire protocol; only the `start` payload is adapter-specific.\nexport const outboundMessageSchema = harnessV1BridgeOutboundMessageSchema;\nexport type OutboundMessage = z.infer<typeof outboundMessageSchema>;\n\nexport const startMessageSchema = harnessV1BridgeStartBaseSchema.extend({\n // Prepended to the first user message (createDeepAgent takes no instructions param).\n instructions: z.string().optional(),\n // In-backend skills source dirs ($HOME and <workDir>), passed to createDeepAgent({ skills }).\n skillsPaths: z.array(z.string()).optional(),\n // Max LangGraph super-steps per turn (streamEvents recursionLimit).\n recursionLimit: z.number().optional(),\n});\n\nexport type StartMessage = z.infer<typeof startMessageSchema>;\n\nexport const inboundMessageSchema = z.discriminatedUnion('type', [\n startMessageSchema,\n ...harnessV1BridgeInboundCommandSchemas,\n]);\nexport type InboundMessage = z.infer<typeof inboundMessageSchema>;\n\nexport const bridgeReadySchema = harnessV1BridgeReadySchema;\nexport type BridgeReady = z.infer<typeof bridgeReadySchema>;\n","import { createDeepAgents } from './deepagents-harness';\n\n/** Default `deepagents` harness instance; equivalent to `createDeepAgents()`. */\nexport const deepAgents = createDeepAgents();\n\nexport { createDeepAgents } from './deepagents-harness';\nexport type { DeepAgentsHarnessSettings } from './deepagents-harness';\nexport type { DeepAgentsAuthOptions } from './deepagents-auth';\n"],"mappings":"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","names":["z","z"]}
1
+ {"version":3,"sources":["../src/deepagents-harness.ts","../src/deepagents-auth.ts","../src/deepagents-bridge-protocol.ts","../src/index.ts"],"sourcesContent":["import { randomBytes } from 'node:crypto';\nimport { readFile } from 'node:fs/promises';\nimport { fileURLToPath } from 'node:url';\nimport {\n commonTool,\n HarnessCapabilityUnsupportedError,\n harnessV1DiagnosticFromBridgeFrame,\n type HarnessV1,\n type HarnessV1Bootstrap,\n type HarnessV1BuiltinTool,\n type HarnessV1BuiltinToolFiltering,\n type HarnessV1ContinueTurnState,\n type HarnessV1NetworkSandboxSession,\n type HarnessV1PermissionMode,\n type HarnessV1Prompt,\n type HarnessV1PromptControl,\n type HarnessV1ResumeSessionState,\n type HarnessV1Session,\n type HarnessV1Skill,\n type HarnessV1StreamPart,\n} from '@ai-sdk/harness';\nimport {\n markBridgeStarting,\n resolveSandboxHomeDir,\n SandboxChannel,\n shellQuote,\n waitForBridgeReady,\n writeSkills as writeHarnessSkills,\n} from '@ai-sdk/harness/utils';\nimport { tool, type Experimental_SandboxProcess } from '@ai-sdk/provider-utils';\nimport { WebSocket } from 'ws';\nimport { z } from 'zod/v4';\nimport {\n resolveDeepAgentsEnv,\n type DeepAgentsAuthOptions,\n} from './deepagents-auth';\nimport {\n outboundMessageSchema,\n type InboundMessage,\n type OutboundMessage,\n} from './deepagents-bridge-protocol';\n\ntype DeepAgentsChannel = SandboxChannel<OutboundMessage, InboundMessage>;\n\n// Pure derived state in /tmp; reinstalled per sandbox, persistence is the provider snapshot.\nconst BOOTSTRAP_DIR = '/tmp/harness/deepagents';\n\n// Pinned ripgrep release + per-arch tarball checksums (verified before install).\nconst RIPGREP_VERSION = '14.1.1';\nconst RIPGREP_SHA256_X64 =\n '4cf9f2741e6c465ffdb7c26f38056a59e2a2544b51f7cc128ef28337eeae4d8e';\nconst RIPGREP_SHA256_ARM =\n 'c827481c4ff4ea10c9dc7a4022c8de5db34a5737cb74484d62eb94a95841ab2f';\n\n// Idempotent, checksum-verified install of a static ripgrep binary into a PATH dir.\n// DeepAgents' grep shells out to `rg`; without it, its fallback reads the whole workdir (incl. node_modules) into memory and OOMs. Skipped if `rg` already exists.\nfunction installRipgrepCommand(): string {\n const v = RIPGREP_VERSION;\n return [\n 'command -v rg >/dev/null 2>&1 || {',\n 'case \"$(uname -m)\" in',\n `aarch64) a=aarch64-unknown-linux-gnu; sha=${RIPGREP_SHA256_ARM} ;;`,\n `*) a=x86_64-unknown-linux-musl; sha=${RIPGREP_SHA256_X64} ;;`,\n 'esac;',\n `f=/tmp/ripgrep-${v}.tar.gz;`,\n `curl -fsSL \"https://github.com/BurntSushi/ripgrep/releases/download/${v}/ripgrep-${v}-$a.tar.gz\" -o \"$f\"`,\n '&& echo \"$sha $f\" | sha256sum -c -',\n '&& tar xzf \"$f\" -C /tmp',\n `&& mv \"/tmp/ripgrep-${v}-$a/rg\" /usr/local/bin/rg && chmod +x /usr/local/bin/rg;`,\n '}',\n ].join(' ');\n}\n\n// Skills source subpath, written under $HOME (out of the work dir so it can't clash with code cloned into the work dir) and also discovered from <workDir> for repo-provided skills.\nconst SKILLS_SOURCE_PATH = '/.agents/skills';\n\nexport type DeepAgentsHarnessSettings = {\n readonly auth?: DeepAgentsAuthOptions;\n /** Model id for the DeepAgents runtime, e.g. `claude-sonnet-4` (converted to `provider:model`). */\n readonly model?: string;\n /** Bridge port override; defaults to the sandbox's first declared port. */\n readonly port?: number;\n /** Maximum milliseconds to wait for the bridge to advertise its port. Defaults to 120000. */\n readonly startupTimeoutMs?: number;\n /** Max LangGraph super-steps per turn before it errors. Defaults to 100; raise for long multi-step tasks. */\n readonly recursionLimit?: number;\n};\n\n// Every model-callable DeepAgents built-in, keyed by what the bridge emits (commonName ?? nativeName); all must be listed or AI SDK throws AI_NoSuchToolError.\nconst DEEPAGENTS_BUILTIN_TOOLS = {\n read: commonTool('read', {\n nativeName: 'read_file',\n toolUseKind: 'readonly',\n description: 'Read file contents',\n inputSchema: z.object({ file_path: z.string() }),\n }),\n write: commonTool('write', {\n nativeName: 'write_file',\n toolUseKind: 'edit',\n description: 'Create a file',\n inputSchema: z.object({ file_path: z.string(), content: z.string() }),\n }),\n edit: commonTool('edit', {\n nativeName: 'edit_file',\n toolUseKind: 'edit',\n description: 'Perform exact string replacements in a file',\n inputSchema: z.object({\n file_path: z.string(),\n old_string: z.string(),\n new_string: z.string(),\n }),\n }),\n bash: commonTool('bash', {\n nativeName: 'execute',\n toolUseKind: 'bash',\n description: 'Run a shell command',\n inputSchema: z.object({ command: z.string() }),\n }),\n grep: commonTool('grep', {\n nativeName: 'grep',\n toolUseKind: 'readonly',\n description: 'Search file contents',\n inputSchema: z.object({ pattern: z.string() }),\n }),\n glob: commonTool('glob', {\n nativeName: 'glob',\n toolUseKind: 'readonly',\n description: 'Find files matching a glob pattern',\n inputSchema: z.object({ pattern: z.string() }),\n }),\n // No common-name equivalent — keyed by native name.\n ls: tool({\n description: 'List files in a directory',\n inputSchema: z.object({ path: z.string().optional() }),\n }),\n task: tool({\n description: 'Spawn a subagent to handle a delegated task',\n inputSchema: z.object({\n description: z.string().optional(),\n subagent_type: z.string().optional(),\n }),\n }),\n write_todos: tool({\n description: 'Manage a structured todo list',\n inputSchema: z.object({ todos: z.array(z.unknown()).optional() }),\n }),\n} as const satisfies Record<string, HarnessV1BuiltinTool<any, any>>;\n\n// Live bridge coordinates returned by doDetach/doSuspendTurn so a later process can reattach.\nconst deepAgentsBridgeCoordsSchema = z.object({\n port: z.number(),\n token: z.string(),\n lastSeenEventId: z.number(),\n sandboxId: z.string().optional(),\n});\nconst deepAgentsResumeStateSchema = z.object({\n bridge: deepAgentsBridgeCoordsSchema.optional(),\n});\ntype DeepAgentsBridgeCoords = z.infer<typeof deepAgentsBridgeCoordsSchema>;\n\nexport function createDeepAgents(\n settings: DeepAgentsHarnessSettings = {},\n): HarnessV1<typeof DEEPAGENTS_BUILTIN_TOOLS> {\n let cachedBootstrap: HarnessV1Bootstrap | undefined;\n\n return {\n specificationVersion: 'harness-v1',\n harnessId: 'deepagents',\n builtinTools: DEEPAGENTS_BUILTIN_TOOLS,\n // Built-in tool approvals are gated in-bridge via DeepAgents' interruptOn (HITL) middleware.\n supportsBuiltinToolApprovals: true,\n lifecycleStateSchema: deepAgentsResumeStateSchema,\n getBootstrap: async () => {\n if (cachedBootstrap != null) return cachedBootstrap;\n const [bridge, pkg, lock] = await Promise.all([\n readBridgeAsset('index.mjs'),\n readBridgeAsset('package.json'),\n readBridgeAsset('pnpm-lock.yaml'),\n ]);\n cachedBootstrap = {\n harnessId: 'deepagents',\n bootstrapDir: BOOTSTRAP_DIR,\n files: [\n { path: `${BOOTSTRAP_DIR}/bridge.mjs`, content: bridge },\n { path: `${BOOTSTRAP_DIR}/package.json`, content: pkg },\n { path: `${BOOTSTRAP_DIR}/pnpm-lock.yaml`, content: lock },\n ],\n commands: [\n { command: `mkdir -p ${BOOTSTRAP_DIR}` },\n { command: installRipgrepCommand() },\n {\n command: `pnpm --dir ${BOOTSTRAP_DIR} install --frozen-lockfile --store-dir ${BOOTSTRAP_DIR}/.pnpm-store`,\n },\n ],\n };\n return cachedBootstrap;\n },\n doStart: async startOpts => {\n const permissionMode = startOpts.permissionMode;\n const sandboxSession = startOpts.sandboxSession;\n const session = sandboxSession.restricted();\n const sandboxId = sandboxSession.id;\n\n const lifecycleState = startOpts.continueFrom ?? startOpts.resumeFrom;\n const isResume = lifecycleState != null;\n const isContinue = startOpts.continueFrom != null;\n const coords =\n isResume && typeof lifecycleState?.data === 'object'\n ? (lifecycleState.data as { bridge?: DeepAgentsBridgeCoords }).bridge\n : undefined;\n\n const workDir = startOpts.sessionWorkDir;\n const sessionDataDir = `${sandboxSession.defaultWorkingDirectory}/.agent-runs/${startOpts.sessionId}`;\n const bridgeStateDir = `${sessionDataDir}/bridge`;\n const timeoutMs = settings.startupTimeoutMs ?? 120_000;\n\n const report = startOpts.observability?.report;\n const onDiagnostic = report\n ? (frame: Parameters<typeof harnessV1DiagnosticFromBridgeFrame>[0]) =>\n report(\n harnessV1DiagnosticFromBridgeFrame(frame, {\n sessionId: startOpts.sessionId,\n timestamp: Date.now(),\n }),\n )\n : undefined;\n\n // Attach to the still-running bridge (continueFrom replays past the cursor); on failure fall through to a fresh spawn.\n if (coords) {\n try {\n const attachUrl =\n (await sandboxSession.getPortUrl({\n port: coords.port,\n protocol: 'ws',\n })) + `?agent_bridge_token=${encodeURIComponent(coords.token)}`;\n const attachChannel: DeepAgentsChannel = new SandboxChannel({\n connect: () => openWebSocket(attachUrl),\n outboundSchema: outboundMessageSchema,\n initialLastSeenEventId: coords.lastSeenEventId,\n onDiagnostic,\n });\n await attachChannel.open(isContinue ? { resume: true } : undefined);\n return createSession({\n sessionId: startOpts.sessionId,\n channel: attachChannel,\n proc: undefined,\n model: settings.model,\n bridgePort: coords.port,\n bridgeToken: coords.token,\n sandboxId,\n isResume: true,\n attached: true,\n permissionMode,\n builtinToolFiltering: startOpts.builtinToolFiltering,\n recursionLimit: settings.recursionLimit,\n });\n } catch {\n // Bridge no longer reachable — recover by respawning below.\n }\n }\n\n const port = resolveBridgePort(sandboxSession, settings.port);\n const token = randomBytes(32).toString('hex');\n\n // Always discover repo-provided skills under <workDir>/.agents/skills (e.g. a cloned repo); a missing dir is tolerated by deepagents.\n // Absolute paths: LocalShellBackend (non-virtual) treats a leading-slash path as a real fs path.\n const skillsPaths = [`${workDir}${SKILLS_SOURCE_PATH}`];\n // Host-provided skills go to $HOME (out of the work dir) and take priority (listed last → wins on name collision).\n if ((startOpts.skills?.length ?? 0) > 0) {\n const homeDir = await resolveSandboxHomeDir({\n sandbox: session,\n abortSignal: startOpts.abortSignal,\n });\n const homeSkillsRoot = `${homeDir}${SKILLS_SOURCE_PATH}`;\n await writeSkills({\n sandbox: session,\n root: homeSkillsRoot,\n skills: startOpts.skills ?? [],\n abortSignal: startOpts.abortSignal,\n });\n skillsPaths.push(homeSkillsRoot);\n }\n\n const env = {\n ...resolveDeepAgentsEnv({ auth: settings.auth }),\n BRIDGE_CHANNEL_TOKEN: token,\n BRIDGE_WS_PORT: String(port),\n };\n\n await session.run({\n command: `mkdir -p ${shellQuote(workDir)} ${shellQuote(bridgeStateDir)}`,\n abortSignal: startOpts.abortSignal,\n });\n\n await markBridgeStarting({\n sandbox: session,\n bridgeStateDir,\n bridgeType: 'deepagents',\n abortSignal: startOpts.abortSignal,\n });\n\n const proc = await session.spawn({\n command: `node ${BOOTSTRAP_DIR}/bridge.mjs --workdir ${shellQuote(workDir)} --bridge-state-dir ${shellQuote(bridgeStateDir)} --bootstrap-dir ${shellQuote(BOOTSTRAP_DIR)}`,\n env,\n abortSignal: startOpts.abortSignal,\n });\n\n const { port: boundPort } = await waitForBridgeReady({\n proc,\n sandbox: session,\n bridgeStateDir,\n bridgeType: 'deepagents',\n timeoutMs,\n abortSignal: startOpts.abortSignal,\n createTimeoutError: () =>\n new Error('deepagents bridge did not become ready in time.'),\n createExitError: () =>\n new Error('deepagents bridge exited before becoming ready.'),\n });\n void forwardBridgeStderr(proc.stderr);\n\n const wsUrl =\n (await sandboxSession.getPortUrl({\n port: boundPort,\n protocol: 'ws',\n })) + `?agent_bridge_token=${encodeURIComponent(token)}`;\n\n const channel: DeepAgentsChannel = new SandboxChannel({\n connect: () => openWebSocket(wsUrl),\n outboundSchema: outboundMessageSchema,\n onDiagnostic,\n });\n await channel.open();\n\n return createSession({\n sessionId: startOpts.sessionId,\n channel,\n proc,\n model: settings.model,\n bridgePort: boundPort,\n bridgeToken: token,\n sandboxId,\n isResume,\n // Freshly spawned bridge — it must receive the instructions on the first prompt.\n attached: false,\n skillsPaths,\n permissionMode,\n builtinToolFiltering: startOpts.builtinToolFiltering,\n recursionLimit: settings.recursionLimit,\n });\n },\n };\n}\n\nfunction resolveBridgePort(\n sandboxSession: HarnessV1NetworkSandboxSession,\n override: number | undefined,\n): number {\n if (override !== undefined) return override;\n if (sandboxSession.ports.length > 0) return sandboxSession.ports[0];\n throw new HarnessCapabilityUnsupportedError({\n harnessId: 'deepagents',\n message:\n 'The deepagents harness needs a TCP port exposed by the sandbox. ' +\n 'Create the sandbox with `ports: [<port>]` or pass `createDeepAgents({ port })`.',\n });\n}\n\nasync function readBridgeAsset(name: string): Promise<string> {\n const candidates = [\n new URL(`./bridge/${name}`, import.meta.url),\n new URL(`../bridge/${name}`, import.meta.url),\n ];\n let lastErr: unknown;\n for (const url of candidates) {\n try {\n return await readFile(fileURLToPath(url), 'utf8');\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code !== 'ENOENT') throw err;\n lastErr = err;\n }\n }\n throw lastErr ?? new Error(`bridge asset not found: ${name}`);\n}\n\n// Materialize each skill as a native deepagents `<name>/SKILL.md` folder (+ attached files) under the given root, so skills load on demand and file references resolve.\nasync function writeSkills({\n sandbox,\n root,\n skills,\n abortSignal,\n}: {\n sandbox: ReturnType<HarnessV1NetworkSandboxSession['restricted']>;\n root: string;\n skills: ReadonlyArray<HarnessV1Skill>;\n abortSignal?: AbortSignal;\n}): Promise<void> {\n /*\n * DeepAgents requires each `SKILL.md` frontmatter name to match the parent\n * directory name, so keep the stricter lowercase skill-name policy here.\n */\n await writeHarnessSkills({\n sandbox,\n rootDir: root,\n skills,\n abortSignal,\n skillNamePattern: /^[a-z0-9]([a-z0-9-]{0,62}[a-z0-9])?$/,\n invalidSkillNameMessage: ({ name }) =>\n `Invalid deepagents skill name '${name}': must be lowercase alphanumeric with hyphens, 1-64 chars.`,\n filePathMode: 'strip-leading-slashes',\n invalidSkillFilePathMessage: ({ skillName, filePath }) =>\n `Invalid skill file path for '${skillName}': ${filePath}`,\n });\n}\n\nfunction openWebSocket(url: string): Promise<WebSocket> {\n return new Promise((resolve, reject) => {\n const ws = new WebSocket(url);\n const onOpen = () => {\n ws.off('error', onError);\n resolve(ws);\n };\n const onError = (err: Error) => {\n ws.off('open', onOpen);\n reject(err);\n };\n ws.once('open', onOpen);\n ws.once('error', onError);\n });\n}\n\nasync function forwardBridgeStderr(\n stream: ReadableStream<Uint8Array>,\n): Promise<void> {\n try {\n const reader = stream.pipeThrough(new TextDecoderStream()).getReader();\n while (true) {\n const { value, done } = await reader.read();\n if (done) return;\n if (value) {\n const trimmed = value.endsWith('\\n') ? value.slice(0, -1) : value;\n if (trimmed.length > 0) {\n // eslint-disable-next-line no-console\n console.log(`[bridge stderr] ${trimmed}`);\n }\n }\n }\n } catch {\n // Reader errors are non-fatal — best-effort diagnostic only.\n }\n}\n\nfunction createSession({\n sessionId,\n channel,\n proc,\n model,\n bridgePort,\n bridgeToken,\n sandboxId,\n isResume,\n attached,\n skillsPaths,\n permissionMode,\n builtinToolFiltering,\n recursionLimit,\n}: {\n sessionId: string;\n channel: DeepAgentsChannel;\n // Undefined on attach — the live bridge was spawned by another process.\n proc: Experimental_SandboxProcess | undefined;\n model: string | undefined;\n bridgePort: number;\n bridgeToken: string;\n sandboxId: string;\n isResume: boolean;\n // True only when attaching to a live bridge that already built the agent with\n // its instructions. A fresh spawn (incl. a respawn on attach failure or a\n // stop-resume) starts a new bridge that must receive the instructions again.\n attached: boolean;\n skillsPaths?: string[];\n permissionMode?: HarnessV1PermissionMode;\n builtinToolFiltering?: HarnessV1BuiltinToolFiltering;\n recursionLimit?: number;\n}): HarnessV1Session {\n let stopped = false;\n let instructionsApplied = attached;\n\n const wireTurn = (turnOpts: {\n emit: (event: HarnessV1StreamPart) => void;\n abortSignal?: AbortSignal;\n }): HarnessV1PromptControl => {\n let pendingResolve: (() => void) | undefined;\n let pendingReject: ((err: unknown) => void) | undefined;\n const done = new Promise<void>((resolve, reject) => {\n pendingResolve = resolve;\n pendingReject = reject;\n });\n\n const unsubs: Array<() => void> = [];\n const forward = (event: HarnessV1StreamPart) => {\n try {\n turnOpts.emit(event);\n } catch {}\n };\n\n const eventTypes = [\n 'stream-start',\n 'text-start',\n 'text-delta',\n 'text-end',\n 'reasoning-start',\n 'reasoning-delta',\n 'reasoning-end',\n 'tool-call',\n 'tool-approval-request',\n 'tool-result',\n 'file-change',\n 'finish-step',\n 'raw',\n ] as const;\n let isSettled = false;\n const settleSuccess = () => {\n if (isSettled) return;\n isSettled = true;\n for (const u of unsubs) u();\n pendingResolve!();\n };\n const settleError = (err: unknown) => {\n if (isSettled) return;\n isSettled = true;\n for (const u of unsubs) u();\n pendingReject!(err);\n };\n\n for (const type of eventTypes) {\n unsubs.push(channel.on(type, msg => forward(msg)));\n }\n unsubs.push(\n channel.on('finish', msg => {\n forward(msg);\n settleSuccess();\n }),\n );\n unsubs.push(\n channel.on('error', msg => {\n forward(msg);\n settleError(msg.error);\n }),\n );\n\n // A `'suspended'` close is a graceful slice-boundary freeze (suspend/detach keep the bridge alive for continuation); end the turn cleanly. Any other close is an unexpected bridge failure.\n const onClose = (_code: number, reason: string) => {\n if (isSettled) return;\n if (reason === 'suspended') {\n settleSuccess();\n return;\n }\n settleError(\n new Error('deepagents bridge closed before the turn finished.'),\n );\n };\n channel.onClose(onClose);\n\n const onAbort = () => {\n if (isSettled) return;\n try {\n channel.send({ type: 'abort' });\n } catch {}\n settleError(\n turnOpts.abortSignal?.reason ??\n new DOMException('Aborted', 'AbortError'),\n );\n };\n if (turnOpts.abortSignal) {\n if (turnOpts.abortSignal.aborted) {\n onAbort();\n } else {\n turnOpts.abortSignal.addEventListener('abort', onAbort, { once: true });\n }\n }\n\n return {\n submitToolResult: async input => {\n channel.send({\n type: 'tool-result',\n toolCallId: input.toolCallId,\n output: input.output,\n isError: input.isError,\n });\n },\n submitUserMessage: async text => {\n channel.send({ type: 'user-message', text });\n },\n submitToolApproval: async input => {\n channel.send({\n type: 'tool-approval-response',\n approvalId: input.approvalId,\n approved: input.approved,\n ...(input.reason != null ? { reason: input.reason } : {}),\n });\n },\n done,\n };\n };\n\n const unsupported = (capability: string): never => {\n throw new HarnessCapabilityUnsupportedError({\n harnessId: 'deepagents',\n message: `Harness 'deepagents' does not support ${capability} yet.`,\n });\n };\n\n return {\n sessionId,\n isResume,\n modelId: model,\n doPromptTurn: async promptOpts => {\n const control = wireTurn({\n emit: promptOpts.emit,\n abortSignal: promptOpts.abortSignal,\n });\n\n const applyInstructions =\n !instructionsApplied && !!promptOpts.instructions;\n instructionsApplied = true;\n\n channel.send({\n type: 'start',\n prompt: extractUserText(promptOpts.prompt),\n ...(applyInstructions ? { instructions: promptOpts.instructions } : {}),\n tools: (promptOpts.tools ?? []).map(t => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema,\n })),\n ...(model ? { model } : {}),\n ...(skillsPaths?.length ? { skillsPaths } : {}),\n ...(permissionMode ? { permissionMode } : {}),\n ...(builtinToolFiltering ? { builtinToolFiltering } : {}),\n ...(recursionLimit != null ? { recursionLimit } : {}),\n });\n\n return control;\n },\n doContinueTurn: async continueOpts => {\n // Attach/replay: doStart opened with `{ resume: true }` so the bridge replays past the cursor; no `start` is sent (that would clear the replay log).\n return wireTurn({\n emit: continueOpts.emit,\n abortSignal: continueOpts.abortSignal,\n });\n },\n doSuspendTurn: async () => {\n if (stopped) {\n throw new Error(\n `deepagents session ${sessionId} is stopped; cannot suspend.`,\n );\n }\n stopped = true;\n // Freeze the active turn at the cursor, leaving the bridge running so the next slice replays the tail.\n const lastSeenEventId = await channel.suspend();\n const payload: HarnessV1ContinueTurnState = {\n type: 'continue-turn',\n harnessId: 'deepagents',\n specificationVersion: 'harness-v1',\n data: {\n bridge: {\n port: bridgePort,\n token: bridgeToken,\n lastSeenEventId,\n sandboxId,\n },\n },\n };\n return payload;\n },\n doDetach: async () => {\n if (stopped) {\n throw new Error(\n `deepagents session ${sessionId} is already stopped; cannot detach.`,\n );\n }\n stopped = true;\n // Park between turns: close the host socket but leave the bridge running for a later reattach via these coords.\n const lastSeenEventId = await channel.suspend();\n const payload: HarnessV1ResumeSessionState = {\n type: 'resume-session',\n harnessId: 'deepagents',\n specificationVersion: 'harness-v1',\n data: {\n bridge: {\n port: bridgePort,\n token: bridgeToken,\n lastSeenEventId,\n sandboxId,\n },\n },\n };\n return payload;\n },\n doCompact: async () => unsupported('manual compaction'),\n doStop: async () => {\n if (stopped) {\n throw new Error(\n `deepagents session ${sessionId} is already stopped; cannot stop.`,\n );\n }\n stopped = true;\n await teardown(channel, proc);\n // In-memory conversation is lost on teardown; the sandbox snapshot preserves the workspace files, not the conversation.\n const payload: HarnessV1ResumeSessionState = {\n type: 'resume-session',\n harnessId: 'deepagents',\n specificationVersion: 'harness-v1',\n data: {},\n };\n return payload;\n },\n doDestroy: async () => {\n if (stopped) return;\n stopped = true;\n await teardown(channel, proc);\n },\n };\n}\n\nasync function teardown(\n channel: DeepAgentsChannel,\n proc: Experimental_SandboxProcess | undefined,\n): Promise<void> {\n channel.beginClose();\n try {\n if (!channel.isClosed()) {\n channel.send({ type: 'shutdown' });\n }\n } catch {}\n let stopTimer: ReturnType<typeof setTimeout> | undefined;\n try {\n if (proc) {\n await Promise.race([\n proc.wait(),\n new Promise<void>(resolve => {\n stopTimer = setTimeout(resolve, 5000);\n stopTimer.unref?.();\n }),\n ]);\n }\n } finally {\n if (stopTimer) clearTimeout(stopTimer);\n try {\n await proc?.kill();\n } catch {}\n channel.close();\n }\n}\n\n// Reduce the prompt to plain user text; non-text parts are unsupported.\nfunction extractUserText(prompt: HarnessV1Prompt): string {\n if (typeof prompt === 'string') return prompt;\n const { content } = prompt;\n if (typeof content === 'string') return content;\n const parts: string[] = [];\n for (const part of content) {\n if (part.type !== 'text') {\n throw new HarnessCapabilityUnsupportedError({\n harnessId: 'deepagents',\n 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.`,\n });\n }\n parts.push(part.text);\n }\n return parts.join('\\n\\n');\n}\n","import { getAiGatewayAuthFromEnv } from '@ai-sdk/harness/utils';\n\nexport type DeepAgentsAuthOptions = {\n readonly anthropic?: {\n readonly apiKey?: string;\n readonly authToken?: string;\n readonly baseUrl?: string;\n };\n readonly gateway?: {\n readonly apiKey?: string;\n readonly baseUrl?: string;\n };\n};\n\n// DeepAgents always drives the Anthropic client. Non-Anthropic models reach it\n// through AI Gateway's Anthropic-compatible endpoint, which translates to any\n// model (Gemini, OpenAI, etc.), tool calls included.\nexport function resolveDeepAgentsEnv({\n auth,\n processEnv = process.env,\n}: {\n auth?: DeepAgentsAuthOptions;\n processEnv?: Record<string, string | undefined>;\n}): Record<string, string> {\n if (auth?.anthropic) {\n return pickAnthropic({ explicit: auth.anthropic, processEnv });\n }\n\n const gatewayAuthFromEnv = getAiGatewayAuthFromEnv({ env: processEnv });\n if (auth?.gateway) {\n return pickGateway({ explicit: auth.gateway, gatewayAuthFromEnv });\n }\n if (gatewayAuthFromEnv.apiKey) {\n return pickGateway({ explicit: {}, gatewayAuthFromEnv });\n }\n\n return pickAnthropic({ processEnv });\n}\n\nfunction pickAnthropic({\n explicit,\n processEnv,\n}: {\n explicit?: NonNullable<DeepAgentsAuthOptions['anthropic']>;\n processEnv: Record<string, string | undefined>;\n}): Record<string, string> {\n const env: Record<string, string> = {};\n const apiKey = explicit?.apiKey ?? processEnv.ANTHROPIC_API_KEY;\n if (apiKey) env.ANTHROPIC_API_KEY = apiKey;\n const authToken = explicit?.authToken ?? processEnv.ANTHROPIC_AUTH_TOKEN;\n if (authToken) env.ANTHROPIC_AUTH_TOKEN = authToken;\n const baseUrl = explicit?.baseUrl ?? processEnv.ANTHROPIC_BASE_URL;\n if (baseUrl) env.ANTHROPIC_BASE_URL = baseUrl;\n return env;\n}\n\nfunction pickGateway({\n explicit,\n gatewayAuthFromEnv,\n}: {\n explicit: NonNullable<DeepAgentsAuthOptions['gateway']>;\n gatewayAuthFromEnv: ReturnType<typeof getAiGatewayAuthFromEnv>;\n}): Record<string, string> {\n const apiKey = explicit.apiKey ?? gatewayAuthFromEnv.apiKey;\n // The Anthropic SDK appends `/v1/messages`, so the gateway base stays at its root.\n const baseUrl = (explicit.baseUrl ?? gatewayAuthFromEnv.baseUrl).replace(\n /\\/+$/,\n '',\n );\n const env: Record<string, string> = {};\n if (apiKey) {\n env.AI_GATEWAY_API_KEY = apiKey;\n env.ANTHROPIC_API_KEY = apiKey;\n }\n env.ANTHROPIC_BASE_URL = baseUrl;\n return env;\n}\n","import {\n harnessV1BridgeInboundCommandSchemas,\n harnessV1BridgeOutboundMessageSchema,\n harnessV1BridgeReadySchema,\n harnessV1BridgeStartBaseSchema,\n} from '@ai-sdk/harness';\nimport { z } from 'zod/v4';\n\n// Deep Agents bridge wire protocol; only the `start` payload is adapter-specific.\nexport const outboundMessageSchema = harnessV1BridgeOutboundMessageSchema;\nexport type OutboundMessage = z.infer<typeof outboundMessageSchema>;\n\nexport const startMessageSchema = harnessV1BridgeStartBaseSchema.extend({\n // Prepended to the first user message (createDeepAgent takes no instructions param).\n instructions: z.string().optional(),\n // In-backend skills source dirs ($HOME and <workDir>), passed to createDeepAgent({ skills }).\n skillsPaths: z.array(z.string()).optional(),\n // Max LangGraph super-steps per turn (streamEvents recursionLimit).\n recursionLimit: z.number().optional(),\n});\n\nexport type StartMessage = z.infer<typeof startMessageSchema>;\n\nexport const inboundMessageSchema = z.discriminatedUnion('type', [\n startMessageSchema,\n ...harnessV1BridgeInboundCommandSchemas,\n]);\nexport type InboundMessage = z.infer<typeof inboundMessageSchema>;\n\nexport const bridgeReadySchema = harnessV1BridgeReadySchema;\nexport type BridgeReady = z.infer<typeof bridgeReadySchema>;\n","import { createDeepAgents } from './deepagents-harness';\n\n/** Default `deepagents` harness instance; equivalent to `createDeepAgents()`. */\nexport const deepAgents = createDeepAgents();\n\nexport { createDeepAgents } from './deepagents-harness';\nexport type { DeepAgentsHarnessSettings } from './deepagents-harness';\nexport type { DeepAgentsAuthOptions } from './deepagents-auth';\n"],"mappings":"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","names":["z","z"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/harness-deepagents",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -27,8 +27,8 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "ws": "8.21.0",
30
- "@ai-sdk/harness": "1.0.11",
31
- "@ai-sdk/provider-utils": "5.0.2"
30
+ "@ai-sdk/harness": "1.0.13",
31
+ "@ai-sdk/provider-utils": "5.0.3"
32
32
  },
33
33
  "peerDependencies": {
34
34
  "zod": "^3.25.76 || ^4.1.8"
@@ -13,8 +13,32 @@ export const NATIVE_TOOL_KIND: Readonly<
13
13
  grep: 'readonly',
14
14
  glob: 'readonly',
15
15
  ls: 'readonly',
16
+ task: 'edit',
17
+ write_todos: 'edit',
16
18
  };
17
19
 
20
+ const NATIVE_TO_COMMON: Readonly<Record<string, string>> = {
21
+ read_file: 'read',
22
+ write_file: 'write',
23
+ edit_file: 'edit',
24
+ execute: 'bash',
25
+ };
26
+
27
+ export function toCommonName(nativeName: string): string {
28
+ return NATIVE_TO_COMMON[nativeName] ?? nativeName;
29
+ }
30
+
31
+ export function isBuiltinToolIncluded(input: {
32
+ nativeName: string;
33
+ toolFiltering: StartMessage['builtinToolFiltering'];
34
+ }): boolean {
35
+ if (input.toolFiltering == null) return true;
36
+ const toolName = toCommonName(input.nativeName);
37
+ return input.toolFiltering.mode === 'allow'
38
+ ? input.toolFiltering.toolNames.includes(toolName)
39
+ : !input.toolFiltering.toolNames.includes(toolName);
40
+ }
41
+
18
42
  export function builtinToolRequiresApproval(
19
43
  kind: 'readonly' | 'edit' | 'bash',
20
44
  permissionMode: PermissionMode,
@@ -27,16 +51,23 @@ export function builtinToolRequiresApproval(
27
51
  // Per-tool HITL config for createDeepAgent; only built-ins are gated (host tools approve at the agent layer).
28
52
  export function buildInterruptOn(
29
53
  permissionMode: PermissionMode | undefined,
54
+ builtinToolFiltering: StartMessage['builtinToolFiltering'],
30
55
  ):
31
56
  | Record<string, { allowedDecisions: Array<'approve' | 'reject'> }>
32
57
  | undefined {
33
- if (!permissionMode || permissionMode === 'allow-all') return undefined;
34
58
  const config: Record<
35
59
  string,
36
60
  { allowedDecisions: Array<'approve' | 'reject'> }
37
61
  > = {};
38
62
  for (const [nativeName, kind] of Object.entries(NATIVE_TOOL_KIND)) {
39
- if (builtinToolRequiresApproval(kind, permissionMode)) {
63
+ if (
64
+ permissionMode != null &&
65
+ isBuiltinToolIncluded({
66
+ nativeName,
67
+ toolFiltering: builtinToolFiltering,
68
+ }) &&
69
+ builtinToolRequiresApproval(kind, permissionMode)
70
+ ) {
40
71
  config[nativeName] = { allowedDecisions: ['approve', 'reject'] };
41
72
  }
42
73
  }
@@ -15,6 +15,7 @@ import type { StartMessage } from '../deepagents-bridge-protocol';
15
15
  import { buildInterruptOn, collectActionRequests } from './approvals';
16
16
  import { jsonSchemaToZodObject } from './json-schema-to-zod';
17
17
  import { createLocalShellBackend } from './local-shell-backend';
18
+ import { createBuiltinToolFilteringMiddleware } from './tool-filtering';
18
19
 
19
20
  // Native Deep Agents tool name -> harness-v1 common name (renames only; grep/glob/ls/task/write_todos forward unchanged).
20
21
  const NATIVE_TO_COMMON: Readonly<Record<string, string>> = {
@@ -118,9 +119,22 @@ async function runTurn(start: StartMessage, turn: BridgeTurn): Promise<void> {
118
119
  const emit = (event: Record<string, unknown>) =>
119
120
  turn.emit(event as BridgeEvent);
120
121
 
121
- const interruptOn = buildInterruptOn(start.permissionMode);
122
+ const interruptOn = buildInterruptOn(
123
+ start.permissionMode,
124
+ start.builtinToolFiltering,
125
+ );
122
126
  if (!agent) {
123
127
  const model = buildModel(start.model);
128
+ const builtinToolFilteringMiddleware = createBuiltinToolFilteringMiddleware(
129
+ {
130
+ builtinToolFiltering: start.builtinToolFiltering,
131
+ emit: event => {
132
+ const turn = currentTurn;
133
+ if (!turn) throw new Error('no active turn');
134
+ turn.emit(event as BridgeEvent);
135
+ },
136
+ },
137
+ );
124
138
  agent = createDeepAgent({
125
139
  // Defer to Deep Agents's own default when the host configured no model.
126
140
  ...(model ? { model } : {}),
@@ -129,6 +143,9 @@ async function runTurn(start: StartMessage, turn: BridgeTurn): Promise<void> {
129
143
  systemPrompt: start.instructions || undefined,
130
144
  // Native skills loaded from the source dirs ($HOME-materialized + <workDir> for repo-provided skills).
131
145
  ...(start.skillsPaths?.length ? { skills: start.skillsPaths } : {}),
146
+ ...(builtinToolFilteringMiddleware
147
+ ? { middleware: [builtinToolFilteringMiddleware] }
148
+ : {}),
132
149
  // Gate built-in tools behind HITL approval when the permission mode requires it.
133
150
  ...(interruptOn ? { interruptOn } : {}),
134
151
  // Real instance (LangGraph rejects `true` for root graphs); gives multi-turn memory.
@@ -0,0 +1,129 @@
1
+ import {
2
+ AIMessage,
3
+ ToolMessage,
4
+ type ToolCall,
5
+ } from '@langchain/core/messages';
6
+ import type { createDeepAgent } from 'deepagents';
7
+ import type { StartMessage } from '../deepagents-bridge-protocol';
8
+ import {
9
+ isBuiltinToolIncluded,
10
+ NATIVE_TOOL_KIND,
11
+ toCommonName,
12
+ } from './approvals';
13
+
14
+ type DeepAgentsMiddleware = NonNullable<
15
+ NonNullable<Parameters<typeof createDeepAgent>[0]>['middleware']
16
+ >[number];
17
+
18
+ type DeepAgentsState = {
19
+ messages: unknown[];
20
+ };
21
+
22
+ type DeepAgentsMiddlewareUpdate = {
23
+ messages: unknown[];
24
+ jumpTo?: 'model';
25
+ };
26
+
27
+ const MIDDLEWARE_BRAND = Symbol.for('AgentMiddleware');
28
+
29
+ function getBuiltinToolFilteringDenialReason(input: {
30
+ toolName: string;
31
+ }): string {
32
+ return `Tool '${input.toolName}' is inactive due to the HarnessAgent tool filtering policy.`;
33
+ }
34
+
35
+ function stringifyToolInput(input: unknown): string {
36
+ return JSON.stringify(input ?? {});
37
+ }
38
+
39
+ function isNativeBuiltinToolCall(input: { toolCall: ToolCall }): boolean {
40
+ return Object.keys(NATIVE_TOOL_KIND).includes(input.toolCall.name);
41
+ }
42
+
43
+ function isInactiveBuiltinToolCall(input: {
44
+ toolCall: ToolCall;
45
+ builtinToolFiltering: StartMessage['builtinToolFiltering'];
46
+ }): boolean {
47
+ return (
48
+ isNativeBuiltinToolCall({ toolCall: input.toolCall }) &&
49
+ !isBuiltinToolIncluded({
50
+ nativeName: input.toolCall.name,
51
+ toolFiltering: input.builtinToolFiltering,
52
+ })
53
+ );
54
+ }
55
+
56
+ export function createBuiltinToolFilteringMiddleware(input: {
57
+ builtinToolFiltering: StartMessage['builtinToolFiltering'];
58
+ emit: (event: Record<string, unknown>) => void;
59
+ }): DeepAgentsMiddleware | undefined {
60
+ if (input.builtinToolFiltering == null) return undefined;
61
+
62
+ return {
63
+ [MIDDLEWARE_BRAND]: true,
64
+ name: 'HarnessBuiltinToolFilteringMiddleware',
65
+ afterModel: {
66
+ canJumpTo: ['model'],
67
+ hook: (
68
+ state: DeepAgentsState,
69
+ ): DeepAgentsMiddlewareUpdate | undefined => {
70
+ const lastMessage = [...state.messages]
71
+ .reverse()
72
+ .find(message => AIMessage.isInstance(message));
73
+
74
+ if (!lastMessage?.tool_calls?.length) return undefined;
75
+
76
+ let hasActiveToolCalls = false;
77
+ const deniedToolMessages: ToolMessage[] = [];
78
+
79
+ for (const toolCall of lastMessage.tool_calls) {
80
+ if (
81
+ !isInactiveBuiltinToolCall({
82
+ toolCall,
83
+ builtinToolFiltering: input.builtinToolFiltering,
84
+ })
85
+ ) {
86
+ hasActiveToolCalls = true;
87
+ continue;
88
+ }
89
+
90
+ const nativeName = toolCall.name;
91
+ toolCall.id ??= `${nativeName}-filtered-${deniedToolMessages.length}`;
92
+ const toolName = toCommonName(nativeName);
93
+ const reason = getBuiltinToolFilteringDenialReason({ toolName });
94
+
95
+ input.emit({
96
+ type: 'tool-call',
97
+ toolCallId: toolCall.id,
98
+ toolName,
99
+ input: stringifyToolInput(toolCall.args),
100
+ providerExecuted: true,
101
+ nativeName,
102
+ });
103
+ input.emit({
104
+ type: 'tool-result',
105
+ toolCallId: toolCall.id,
106
+ toolName,
107
+ result: reason,
108
+ });
109
+
110
+ deniedToolMessages.push(
111
+ new ToolMessage({
112
+ content: reason,
113
+ name: nativeName,
114
+ tool_call_id: toolCall.id,
115
+ status: 'error',
116
+ }),
117
+ );
118
+ }
119
+
120
+ if (deniedToolMessages.length === 0) return undefined;
121
+
122
+ return {
123
+ messages: [lastMessage, ...deniedToolMessages],
124
+ ...(hasActiveToolCalls ? {} : { jumpTo: 'model' }),
125
+ };
126
+ },
127
+ },
128
+ } as DeepAgentsMiddleware;
129
+ }