@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/CHANGELOG.md +18 -0
- package/dist/bridge/index.mjs +122 -12
- package/dist/bridge/index.mjs.map +1 -1
- package/dist/index.js +18 -57
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/bridge/approvals.ts +33 -2
- package/src/bridge/index.ts +18 -1
- package/src/bridge/tool-filtering.ts +129 -0
- package/src/deepagents-harness.ts +24 -64
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
type HarnessV1,
|
|
9
9
|
type HarnessV1Bootstrap,
|
|
10
10
|
type HarnessV1BuiltinTool,
|
|
11
|
+
type HarnessV1BuiltinToolFiltering,
|
|
11
12
|
type HarnessV1ContinueTurnState,
|
|
12
13
|
type HarnessV1NetworkSandboxSession,
|
|
13
14
|
type HarnessV1PermissionMode,
|
|
@@ -20,8 +21,11 @@ import {
|
|
|
20
21
|
} from '@ai-sdk/harness';
|
|
21
22
|
import {
|
|
22
23
|
markBridgeStarting,
|
|
24
|
+
resolveSandboxHomeDir,
|
|
23
25
|
SandboxChannel,
|
|
26
|
+
shellQuote,
|
|
24
27
|
waitForBridgeReady,
|
|
28
|
+
writeSkills as writeHarnessSkills,
|
|
25
29
|
} from '@ai-sdk/harness/utils';
|
|
26
30
|
import { tool, type Experimental_SandboxProcess } from '@ai-sdk/provider-utils';
|
|
27
31
|
import { WebSocket } from 'ws';
|
|
@@ -247,6 +251,7 @@ export function createDeepAgents(
|
|
|
247
251
|
isResume: true,
|
|
248
252
|
attached: true,
|
|
249
253
|
permissionMode,
|
|
254
|
+
builtinToolFiltering: startOpts.builtinToolFiltering,
|
|
250
255
|
recursionLimit: settings.recursionLimit,
|
|
251
256
|
});
|
|
252
257
|
} catch {
|
|
@@ -340,6 +345,7 @@ export function createDeepAgents(
|
|
|
340
345
|
attached: false,
|
|
341
346
|
skillsPaths,
|
|
342
347
|
permissionMode,
|
|
348
|
+
builtinToolFiltering: startOpts.builtinToolFiltering,
|
|
343
349
|
recursionLimit: settings.recursionLimit,
|
|
344
350
|
});
|
|
345
351
|
},
|
|
@@ -378,27 +384,6 @@ async function readBridgeAsset(name: string): Promise<string> {
|
|
|
378
384
|
throw lastErr ?? new Error(`bridge asset not found: ${name}`);
|
|
379
385
|
}
|
|
380
386
|
|
|
381
|
-
// Resolve the sandbox $HOME so skills can be written outside the work dir.
|
|
382
|
-
async function resolveSandboxHomeDir({
|
|
383
|
-
sandbox,
|
|
384
|
-
abortSignal,
|
|
385
|
-
}: {
|
|
386
|
-
sandbox: ReturnType<HarnessV1NetworkSandboxSession['restricted']>;
|
|
387
|
-
abortSignal?: AbortSignal;
|
|
388
|
-
}): Promise<string> {
|
|
389
|
-
const result = await sandbox.run({
|
|
390
|
-
command: 'printf "%s" "$HOME"',
|
|
391
|
-
abortSignal,
|
|
392
|
-
});
|
|
393
|
-
const homeDir = result.stdout.trim();
|
|
394
|
-
if (result.exitCode !== 0 || !homeDir.startsWith('/')) {
|
|
395
|
-
throw new Error(
|
|
396
|
-
`Unable to resolve sandbox HOME directory: ${result.stderr || result.stdout}`,
|
|
397
|
-
);
|
|
398
|
-
}
|
|
399
|
-
return homeDir;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
387
|
// 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.
|
|
403
388
|
async function writeSkills({
|
|
404
389
|
sandbox,
|
|
@@ -411,50 +396,22 @@ async function writeSkills({
|
|
|
411
396
|
skills: ReadonlyArray<HarnessV1Skill>;
|
|
412
397
|
abortSignal?: AbortSignal;
|
|
413
398
|
}): Promise<void> {
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
})
|
|
424
|
-
|
|
425
|
-
await sandbox.writeTextFile({
|
|
426
|
-
path: `${skillDir}/${safeSkillFilePath(name, file.path)}`,
|
|
427
|
-
content: file.content,
|
|
428
|
-
abortSignal,
|
|
429
|
-
});
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
function safeSkillName(name: string): string {
|
|
435
|
-
if (!/^[a-z0-9]([a-z0-9-]{0,62}[a-z0-9])?$/.test(name)) {
|
|
436
|
-
throw new Error(
|
|
399
|
+
/*
|
|
400
|
+
* DeepAgents requires each `SKILL.md` frontmatter name to match the parent
|
|
401
|
+
* directory name, so keep the stricter lowercase skill-name policy here.
|
|
402
|
+
*/
|
|
403
|
+
await writeHarnessSkills({
|
|
404
|
+
sandbox,
|
|
405
|
+
rootDir: root,
|
|
406
|
+
skills,
|
|
407
|
+
abortSignal,
|
|
408
|
+
skillNamePattern: /^[a-z0-9]([a-z0-9-]{0,62}[a-z0-9])?$/,
|
|
409
|
+
invalidSkillNameMessage: ({ name }) =>
|
|
437
410
|
`Invalid deepagents skill name '${name}': must be lowercase alphanumeric with hyphens, 1-64 chars.`,
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
function safeSkillFilePath(skillName: string, filePath: string): string {
|
|
444
|
-
const normalized = filePath.replace(/^\/+/, '');
|
|
445
|
-
if (
|
|
446
|
-
normalized === '' ||
|
|
447
|
-
normalized.startsWith('../') ||
|
|
448
|
-
normalized.includes('/../') ||
|
|
449
|
-
normalized.endsWith('/..')
|
|
450
|
-
) {
|
|
451
|
-
throw new Error(`Invalid skill file path for '${skillName}': ${filePath}`);
|
|
452
|
-
}
|
|
453
|
-
return normalized;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
function shellQuote(value: string): string {
|
|
457
|
-
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
411
|
+
filePathMode: 'strip-leading-slashes',
|
|
412
|
+
invalidSkillFilePathMessage: ({ skillName, filePath }) =>
|
|
413
|
+
`Invalid skill file path for '${skillName}': ${filePath}`,
|
|
414
|
+
});
|
|
458
415
|
}
|
|
459
416
|
|
|
460
417
|
function openWebSocket(url: string): Promise<WebSocket> {
|
|
@@ -506,6 +463,7 @@ function createSession({
|
|
|
506
463
|
attached,
|
|
507
464
|
skillsPaths,
|
|
508
465
|
permissionMode,
|
|
466
|
+
builtinToolFiltering,
|
|
509
467
|
recursionLimit,
|
|
510
468
|
}: {
|
|
511
469
|
sessionId: string;
|
|
@@ -523,6 +481,7 @@ function createSession({
|
|
|
523
481
|
attached: boolean;
|
|
524
482
|
skillsPaths?: string[];
|
|
525
483
|
permissionMode?: HarnessV1PermissionMode;
|
|
484
|
+
builtinToolFiltering?: HarnessV1BuiltinToolFiltering;
|
|
526
485
|
recursionLimit?: number;
|
|
527
486
|
}): HarnessV1Session {
|
|
528
487
|
let stopped = false;
|
|
@@ -679,6 +638,7 @@ function createSession({
|
|
|
679
638
|
...(model ? { model } : {}),
|
|
680
639
|
...(skillsPaths?.length ? { skillsPaths } : {}),
|
|
681
640
|
...(permissionMode ? { permissionMode } : {}),
|
|
641
|
+
...(builtinToolFiltering ? { builtinToolFiltering } : {}),
|
|
682
642
|
...(recursionLimit != null ? { recursionLimit } : {}),
|
|
683
643
|
});
|
|
684
644
|
|