@ai-sdk/harness 1.0.2 → 1.0.4
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 +12 -0
- package/README.md +12 -0
- package/agent/index.ts +9 -1
- package/dist/agent/index.d.ts +19 -5
- package/dist/agent/index.js +106 -1
- package/dist/agent/index.js.map +1 -1
- package/dist/index.js +234 -15587
- package/dist/index.js.map +1 -1
- package/dist/utils/index.js +186 -11487
- package/dist/utils/index.js.map +1 -1
- package/package.json +3 -2
- package/src/agent/prepare-sandbox-for-harness.ts +148 -0
- package/src/agent/prewarm.ts +7 -4
- package/src/v1/harness-v1-builtin-tool.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @ai-sdk/harness
|
|
2
2
|
|
|
3
|
+
## 1.0.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- c493634: fix(harness): fix harness Zod usage to be v3/v4 compatible
|
|
8
|
+
|
|
9
|
+
## 1.0.3
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 51d10a0: feat(harness): add `prepareSandboxForHarness` utility to prepare a caller-owned sandbox for one or more harnesses
|
|
14
|
+
|
|
3
15
|
## 1.0.2
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -91,6 +91,18 @@ Use `session.detach()` to park a bridge-backed session for later attach, `sessio
|
|
|
91
91
|
- Use `sandboxConfig.onBootstrap` for expensive sandbox setup that should be baked into a reusable snapshot, such as installing tools or cloning a large repository. Provide `sandboxConfig.bootstrapHash` with it and change that value whenever the bootstrap output should invalidate the cached snapshot.
|
|
92
92
|
- Use `sandboxConfig.workDir` to set a stable working directory for the agent, relative to the sandbox's default working directory; otherwise regular sessions use the existing `<harnessId>-<sessionId>` directory. In that case, the `onBootstrap` callback receives the sandbox's default working directory.
|
|
93
93
|
|
|
94
|
+
Use `prepareHarnessSandboxTemplate()` to create or refresh the sandbox provider's
|
|
95
|
+
own reusable template for one harness before serving traffic. This is the
|
|
96
|
+
replacement for `prewarmHarness()`, which remains as a deprecated alias.
|
|
97
|
+
|
|
98
|
+
Use `prepareSandboxForHarness()` when you own an existing sandbox and want to
|
|
99
|
+
prepare it before creating your own snapshot. It applies the selected harness
|
|
100
|
+
bootstrap recipes and `sandboxConfig.onBootstrap`, returns the computed
|
|
101
|
+
preparation identity and per-harness recipe identities, and leaves snapshotting
|
|
102
|
+
or stopping the sandbox to your code. Later, create a sandbox from that snapshot
|
|
103
|
+
and pass the native sandbox object to `createVercelSandbox({ sandbox })` for the
|
|
104
|
+
`HarnessAgent`.
|
|
105
|
+
|
|
94
106
|
### Available harnesses
|
|
95
107
|
|
|
96
108
|
See the [harness adapters documentation](https://ai-sdk.dev/v7/docs/ai-sdk-harnesses/harness-adapters).
|
package/agent/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { HarnessAgent } from '../src/agent/harness-agent';
|
|
2
2
|
export type {
|
|
3
|
+
HarnessAgentSandboxConfig,
|
|
3
4
|
HarnessAgentSettings,
|
|
4
5
|
HarnessAgentToolApprovalConfiguration,
|
|
5
6
|
} from '../src/agent/harness-agent-settings';
|
|
@@ -29,7 +30,14 @@ export {
|
|
|
29
30
|
collectHarnessAgentToolApprovalContinuations,
|
|
30
31
|
type HarnessAgentToolApprovalContinuation,
|
|
31
32
|
} from '../src/agent/harness-agent-tool-approval-continuation';
|
|
32
|
-
export {
|
|
33
|
+
export {
|
|
34
|
+
prepareHarnessSandboxTemplate,
|
|
35
|
+
prewarmHarness,
|
|
36
|
+
} from '../src/agent/prewarm';
|
|
37
|
+
export {
|
|
38
|
+
prepareSandboxForHarness,
|
|
39
|
+
type PrepareSandboxForHarnessResult,
|
|
40
|
+
} from '../src/agent/prepare-sandbox-for-harness';
|
|
33
41
|
export type {
|
|
34
42
|
HarnessDebugConfig,
|
|
35
43
|
HarnessDebugLevel,
|
package/dist/agent/index.d.ts
CHANGED
|
@@ -1456,25 +1456,39 @@ declare class HarnessAgent<THarness extends HarnessAgentAdapter<any> = HarnessAg
|
|
|
1456
1456
|
|
|
1457
1457
|
type SandboxBootstrapSettings = Omit<HarnessAgentSandboxConfig, 'onSession'>;
|
|
1458
1458
|
/**
|
|
1459
|
-
*
|
|
1460
|
-
*
|
|
1459
|
+
* Prepare a harness's sandbox template without running an agent. Idempotent: if
|
|
1460
|
+
* the template already exists (snapshot present, or marker on a non-snapshot
|
|
1461
1461
|
* provider), this resolves quickly.
|
|
1462
1462
|
*
|
|
1463
1463
|
* Use from a CI/deploy script to amortize the first-session cost so production
|
|
1464
1464
|
* sessions always resume from snapshot. For adapters without a bootstrap
|
|
1465
1465
|
* recipe (no `getBootstrap`) this is a no-op.
|
|
1466
1466
|
*
|
|
1467
|
-
* The temporary network sandbox session created during
|
|
1467
|
+
* The temporary network sandbox session created during preparation is stopped
|
|
1468
1468
|
* before the function resolves; the snapshot/template state persists in the
|
|
1469
1469
|
* provider's native storage (for Vercel: as the `currentSnapshotId` of the
|
|
1470
1470
|
* named template sandbox).
|
|
1471
1471
|
*/
|
|
1472
|
-
declare function
|
|
1472
|
+
declare function prepareHarnessSandboxTemplate(options: {
|
|
1473
1473
|
readonly harness: HarnessAgentAdapter;
|
|
1474
1474
|
readonly sandboxProvider: HarnessV1SandboxProvider;
|
|
1475
1475
|
readonly sandboxConfig?: SandboxBootstrapSettings;
|
|
1476
1476
|
readonly abortSignal?: AbortSignal;
|
|
1477
1477
|
}): Promise<void>;
|
|
1478
|
+
/** @deprecated Use `prepareHarnessSandboxTemplate` instead. */
|
|
1479
|
+
declare const prewarmHarness: typeof prepareHarnessSandboxTemplate;
|
|
1480
|
+
|
|
1481
|
+
type PrepareSandboxForHarnessResult = {
|
|
1482
|
+
readonly identity?: string;
|
|
1483
|
+
readonly recipeIdentities: Record<string, string>;
|
|
1484
|
+
readonly skippedHarnessIds: ReadonlyArray<string>;
|
|
1485
|
+
};
|
|
1486
|
+
declare function prepareSandboxForHarness(options: {
|
|
1487
|
+
readonly session: Experimental_SandboxSession;
|
|
1488
|
+
readonly harnesses: ReadonlyArray<HarnessAgentAdapter>;
|
|
1489
|
+
readonly sandboxConfig?: HarnessAgentSandboxConfig;
|
|
1490
|
+
readonly abortSignal?: AbortSignal;
|
|
1491
|
+
}): Promise<PrepareSandboxForHarnessResult>;
|
|
1478
1492
|
|
|
1479
1493
|
declare const symbol$1: unique symbol;
|
|
1480
1494
|
/**
|
|
@@ -1551,4 +1565,4 @@ interface TraceTreeReporterOptions {
|
|
|
1551
1565
|
}
|
|
1552
1566
|
declare function createTraceTreeReporter(options?: TraceTreeReporterOptions): Telemetry;
|
|
1553
1567
|
|
|
1554
|
-
export { type FileReporter, type FileReporterOptions, HarnessAgent, type HarnessAgentAdapter, type HarnessAgentAdapterSession, type HarnessAgentBuiltinTool, type HarnessAgentBuiltinToolName, type HarnessAgentBuiltinToolUseKind, type HarnessAgentBuiltinTools, type HarnessAgentContinueTurnOptions, type HarnessAgentContinueTurnState, type HarnessAgentLifecycleState, type HarnessAgentPendingToolApproval, type HarnessAgentPermissionMode, type HarnessAgentPrompt, type HarnessAgentPromptControl, type HarnessAgentPromptTurnOptions, type HarnessAgentResumeSessionState, HarnessAgentSession, type HarnessAgentSettings, type HarnessAgentSkill, type HarnessAgentStartOptions, type HarnessAgentStreamPart, type HarnessAgentToolApprovalConfiguration, type HarnessAgentToolApprovalContinuation, type HarnessAgentToolSpec, HarnessCapabilityUnsupportedError, type HarnessDebugConfig, type HarnessDebugLevel, type HarnessDiagnostic, type HarnessDiagnosticConsumer, HarnessError, type TraceTreeReporterOptions, collectHarnessAgentToolApprovalContinuations, createFileReporter, createTraceTreeReporter, prewarmHarness };
|
|
1568
|
+
export { type FileReporter, type FileReporterOptions, HarnessAgent, type HarnessAgentAdapter, type HarnessAgentAdapterSession, type HarnessAgentBuiltinTool, type HarnessAgentBuiltinToolName, type HarnessAgentBuiltinToolUseKind, type HarnessAgentBuiltinTools, type HarnessAgentContinueTurnOptions, type HarnessAgentContinueTurnState, type HarnessAgentLifecycleState, type HarnessAgentPendingToolApproval, type HarnessAgentPermissionMode, type HarnessAgentPrompt, type HarnessAgentPromptControl, type HarnessAgentPromptTurnOptions, type HarnessAgentResumeSessionState, type HarnessAgentSandboxConfig, HarnessAgentSession, type HarnessAgentSettings, type HarnessAgentSkill, type HarnessAgentStartOptions, type HarnessAgentStreamPart, type HarnessAgentToolApprovalConfiguration, type HarnessAgentToolApprovalContinuation, type HarnessAgentToolSpec, HarnessCapabilityUnsupportedError, type HarnessDebugConfig, type HarnessDebugLevel, type HarnessDiagnostic, type HarnessDiagnosticConsumer, HarnessError, type PrepareSandboxForHarnessResult, type TraceTreeReporterOptions, collectHarnessAgentToolApprovalContinuations, createFileReporter, createTraceTreeReporter, prepareHarnessSandboxTemplate, prepareSandboxForHarness, prewarmHarness };
|
package/dist/agent/index.js
CHANGED
|
@@ -2916,7 +2916,7 @@ async function cleanupAfterStartFailure(input) {
|
|
|
2916
2916
|
}
|
|
2917
2917
|
|
|
2918
2918
|
// src/agent/prewarm.ts
|
|
2919
|
-
async function
|
|
2919
|
+
async function prepareHarnessSandboxTemplate(options) {
|
|
2920
2920
|
var _a3, _b3, _c;
|
|
2921
2921
|
const sandboxConfig = (_a3 = options.sandboxConfig) != null ? _a3 : {};
|
|
2922
2922
|
validateSandboxBootstrapSettings(sandboxConfig);
|
|
@@ -2951,6 +2951,109 @@ async function prewarmHarness(options) {
|
|
|
2951
2951
|
});
|
|
2952
2952
|
}
|
|
2953
2953
|
}
|
|
2954
|
+
var prewarmHarness = prepareHarnessSandboxTemplate;
|
|
2955
|
+
|
|
2956
|
+
// src/agent/prepare-sandbox-for-harness.ts
|
|
2957
|
+
var PREPARED_SANDBOX_IDENTITY_VERSION = 1;
|
|
2958
|
+
async function prepareSandboxForHarness(options) {
|
|
2959
|
+
var _a3, _b3;
|
|
2960
|
+
const sandboxConfig = (_a3 = options.sandboxConfig) != null ? _a3 : {};
|
|
2961
|
+
validateSandboxBootstrapSettings(sandboxConfig);
|
|
2962
|
+
if (options.harnesses.length === 0) {
|
|
2963
|
+
throw new Error(
|
|
2964
|
+
"prepareSandboxForHarness: at least one harness must be provided."
|
|
2965
|
+
);
|
|
2966
|
+
}
|
|
2967
|
+
const harnesses = [...options.harnesses].sort(
|
|
2968
|
+
(a, b) => a.harnessId.localeCompare(b.harnessId)
|
|
2969
|
+
);
|
|
2970
|
+
assertUniqueHarnessIds(harnesses);
|
|
2971
|
+
const workDir = sandboxConfig.workDir == null ? void 0 : normalizeSandboxWorkDir(sandboxConfig.workDir);
|
|
2972
|
+
const recipeIdentities = {};
|
|
2973
|
+
const skippedHarnessIds = [];
|
|
2974
|
+
for (const harness of harnesses) {
|
|
2975
|
+
const recipe = await ((_b3 = harness.getBootstrap) == null ? void 0 : _b3.call(harness, {
|
|
2976
|
+
abortSignal: options.abortSignal
|
|
2977
|
+
}));
|
|
2978
|
+
if (recipe == null) {
|
|
2979
|
+
skippedHarnessIds.push(harness.harnessId);
|
|
2980
|
+
continue;
|
|
2981
|
+
}
|
|
2982
|
+
const recipeIdentity = await hashHarnessBootstrap(recipe);
|
|
2983
|
+
recipeIdentities[harness.harnessId] = recipeIdentity;
|
|
2984
|
+
await applyBootstrapRecipe(options.session, recipe, recipeIdentity, {
|
|
2985
|
+
abortSignal: options.abortSignal
|
|
2986
|
+
});
|
|
2987
|
+
}
|
|
2988
|
+
if (sandboxConfig.onBootstrap != null) {
|
|
2989
|
+
await runSandboxBootstrap({
|
|
2990
|
+
session: options.session,
|
|
2991
|
+
workDir,
|
|
2992
|
+
onBootstrap: sandboxConfig.onBootstrap,
|
|
2993
|
+
abortSignal: options.abortSignal
|
|
2994
|
+
});
|
|
2995
|
+
}
|
|
2996
|
+
const identity = await resolvePreparedSandboxIdentity({
|
|
2997
|
+
recipeIdentities,
|
|
2998
|
+
bootstrapHash: sandboxConfig.bootstrapHash,
|
|
2999
|
+
workDir
|
|
3000
|
+
});
|
|
3001
|
+
return {
|
|
3002
|
+
...identity != null ? { identity } : {},
|
|
3003
|
+
recipeIdentities,
|
|
3004
|
+
skippedHarnessIds
|
|
3005
|
+
};
|
|
3006
|
+
}
|
|
3007
|
+
function assertUniqueHarnessIds(harnesses) {
|
|
3008
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3009
|
+
for (const harness of harnesses) {
|
|
3010
|
+
if (seen.has(harness.harnessId)) {
|
|
3011
|
+
throw new Error(
|
|
3012
|
+
`prepareSandboxForHarness: duplicate harness id "${harness.harnessId}".`
|
|
3013
|
+
);
|
|
3014
|
+
}
|
|
3015
|
+
seen.add(harness.harnessId);
|
|
3016
|
+
}
|
|
3017
|
+
}
|
|
3018
|
+
async function resolvePreparedSandboxIdentity({
|
|
3019
|
+
recipeIdentities,
|
|
3020
|
+
bootstrapHash,
|
|
3021
|
+
workDir
|
|
3022
|
+
}) {
|
|
3023
|
+
const entries = Object.entries(recipeIdentities).sort(
|
|
3024
|
+
([a], [b]) => a.localeCompare(b)
|
|
3025
|
+
);
|
|
3026
|
+
if (entries.length === 0 && bootstrapHash == null) {
|
|
3027
|
+
return void 0;
|
|
3028
|
+
}
|
|
3029
|
+
const encoder = new TextEncoder();
|
|
3030
|
+
const chunks = [];
|
|
3031
|
+
const pushString = (value) => {
|
|
3032
|
+
chunks.push(encoder.encode(value));
|
|
3033
|
+
chunks.push(encoder.encode("\0"));
|
|
3034
|
+
};
|
|
3035
|
+
pushString(String(PREPARED_SANDBOX_IDENTITY_VERSION));
|
|
3036
|
+
pushString(workDir != null ? workDir : "");
|
|
3037
|
+
pushString(bootstrapHash != null ? bootstrapHash : "");
|
|
3038
|
+
for (const [harnessId, identity] of entries) {
|
|
3039
|
+
pushString(harnessId);
|
|
3040
|
+
pushString(identity);
|
|
3041
|
+
}
|
|
3042
|
+
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
3043
|
+
const buffer = new Uint8Array(totalLength);
|
|
3044
|
+
let offset = 0;
|
|
3045
|
+
for (const chunk of chunks) {
|
|
3046
|
+
buffer.set(chunk, offset);
|
|
3047
|
+
offset += chunk.length;
|
|
3048
|
+
}
|
|
3049
|
+
const digest = await crypto.subtle.digest("SHA-256", buffer);
|
|
3050
|
+
const bytes = new Uint8Array(digest);
|
|
3051
|
+
let hex = "";
|
|
3052
|
+
for (let i = 0; i < 8; i++) {
|
|
3053
|
+
hex += bytes[i].toString(16).padStart(2, "0");
|
|
3054
|
+
}
|
|
3055
|
+
return hex;
|
|
3056
|
+
}
|
|
2954
3057
|
|
|
2955
3058
|
// src/agent/observability/file-reporter.ts
|
|
2956
3059
|
import { appendFileSync, mkdirSync } from "fs";
|
|
@@ -3180,6 +3283,8 @@ export {
|
|
|
3180
3283
|
collectHarnessAgentToolApprovalContinuations,
|
|
3181
3284
|
createFileReporter,
|
|
3182
3285
|
createTraceTreeReporter,
|
|
3286
|
+
prepareHarnessSandboxTemplate,
|
|
3287
|
+
prepareSandboxForHarness,
|
|
3183
3288
|
prewarmHarness
|
|
3184
3289
|
};
|
|
3185
3290
|
//# sourceMappingURL=index.js.map
|