@ai-sdk/harness 1.0.123 → 1.0.126

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.
@@ -25,8 +25,8 @@ type SandboxBootstrapSettings = Omit<HarnessAgentSandboxConfig, 'onSession'>;
25
25
  *
26
26
  * The temporary network sandbox session created during preparation is stopped
27
27
  * before the function resolves; the snapshot/template state persists in the
28
- * provider's native storage (for Vercel: as the `currentSnapshotId` of the
29
- * named template sandbox).
28
+ * provider's native storage.
29
+ * @deprecated Use `createHarnessSandboxTemplate` and pass its template to a sandbox session creator instead.
30
30
  */
31
31
  export async function prepareHarnessSandboxTemplate(options: {
32
32
  readonly harness: HarnessAgentAdapter;
@@ -34,6 +34,9 @@ export async function prepareHarnessSandboxTemplate(options: {
34
34
  readonly sandboxConfig?: SandboxBootstrapSettings;
35
35
  readonly abortSignal?: AbortSignal;
36
36
  }): Promise<void> {
37
+ console.warn(
38
+ 'prepareHarnessSandboxTemplate (prewarmHarness) is deprecated. Use createHarnessSandboxTemplate and a sandbox session creator instead.',
39
+ );
37
40
  const sandboxConfig = options.sandboxConfig ?? {};
38
41
  validateSandboxBootstrapSettings(sandboxConfig);
39
42
 
@@ -13,9 +13,9 @@ import {
13
13
  runSandboxBootstrap,
14
14
  validateSandboxBootstrapSettings,
15
15
  } from './internal/sandbox-bootstrap';
16
+ import { resolvePreparedSandboxIdentity } from './internal/prepared-sandbox-identity';
16
17
 
17
- const PREPARED_SANDBOX_IDENTITY_VERSION = 1;
18
-
18
+ /** @deprecated Use `createHarnessSandboxTemplate` and `template.prepare` instead. */
19
19
  export type PrepareSandboxForHarnessResult = {
20
20
  readonly identity?: string;
21
21
  readonly recipeIdentities: Record<string, string>;
@@ -41,6 +41,7 @@ export type PrepareSandboxForHarnessResult = {
41
41
  *
42
42
  * Repeated harness IDs are prepared once. When multiple adapters use the same
43
43
  * ID, the last adapter in `harnesses` is used.
44
+ * @deprecated Use `createHarnessSandboxTemplate` and `template.prepare` instead.
44
45
  */
45
46
  export async function prepareSandboxForHarness(options: {
46
47
  readonly session: SandboxSession;
@@ -48,6 +49,9 @@ export async function prepareSandboxForHarness(options: {
48
49
  readonly sandboxConfig?: HarnessAgentSandboxConfig;
49
50
  readonly abortSignal?: AbortSignal;
50
51
  }): Promise<PrepareSandboxForHarnessResult> {
52
+ console.warn(
53
+ 'prepareSandboxForHarness is deprecated. Use createHarnessSandboxTemplate and template.prepare instead.',
54
+ );
51
55
  const sandboxConfig = options.sandboxConfig ?? {};
52
56
  validateSandboxBootstrapSettings(sandboxConfig);
53
57
 
@@ -107,6 +111,7 @@ export async function prepareSandboxForHarness(options: {
107
111
  session: options.session,
108
112
  workDir,
109
113
  onBootstrap: sandboxConfig.onBootstrap,
114
+ bootstrapHash: sandboxConfig.bootstrapHash,
110
115
  defaultWorkingDirectory,
111
116
  abortSignal: options.abortSignal,
112
117
  });
@@ -124,52 +129,3 @@ export async function prepareSandboxForHarness(options: {
124
129
  skippedHarnessIds,
125
130
  };
126
131
  }
127
-
128
- async function resolvePreparedSandboxIdentity({
129
- recipeIdentities,
130
- bootstrapHash,
131
- workDir,
132
- }: {
133
- readonly recipeIdentities: Record<string, string>;
134
- readonly bootstrapHash?: string;
135
- readonly workDir?: string;
136
- }): Promise<string | undefined> {
137
- const entries = Object.entries(recipeIdentities).sort(([a], [b]) =>
138
- a.localeCompare(b),
139
- );
140
- if (entries.length === 0 && bootstrapHash == null) {
141
- return undefined;
142
- }
143
-
144
- const encoder = new TextEncoder();
145
- const chunks: Uint8Array[] = [];
146
- const pushString = (value: string) => {
147
- chunks.push(encoder.encode(value));
148
- chunks.push(encoder.encode('\0'));
149
- };
150
-
151
- pushString(String(PREPARED_SANDBOX_IDENTITY_VERSION));
152
- pushString(workDir ?? '');
153
- pushString(bootstrapHash ?? '');
154
-
155
- for (const [harnessId, identity] of entries) {
156
- pushString(harnessId);
157
- pushString(identity);
158
- }
159
-
160
- const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
161
- const buffer = new Uint8Array(totalLength);
162
- let offset = 0;
163
- for (const chunk of chunks) {
164
- buffer.set(chunk, offset);
165
- offset += chunk.length;
166
- }
167
-
168
- const digest = await crypto.subtle.digest('SHA-256', buffer);
169
- const bytes = new Uint8Array(digest);
170
- let hex = '';
171
- for (let i = 0; i < 8; i++) {
172
- hex += bytes[i].toString(16).padStart(2, '0');
173
- }
174
- return hex;
175
- }
@@ -34,8 +34,8 @@ export function harnessStateDirectoryPath({
34
34
  }
35
35
 
36
36
  /**
37
- * Network sandbox session returned by `HarnessV1SandboxProvider.createSession()`. The
38
- * harness keeps this for the lifetime of a session. It is itself a
37
+ * Network sandbox session returned by sandbox adapter creation and resume
38
+ * functions. The harness keeps this for the lifetime of a session. It is itself a
39
39
  * {@link SandboxSession} (file I/O, exec, spawn) and adds the infra surface on
40
40
  * top: port resolution, lifecycle, and network-policy mutation.
41
41
  *
@@ -46,22 +46,15 @@ export function harnessStateDirectoryPath({
46
46
  */
47
47
  export interface HarnessV1NetworkSandboxSession extends SandboxSession {
48
48
  /**
49
- * Stable identifier for the underlying sandbox resource. Used by the
50
- * harness session manager as the durable lookup key for cross-process
51
- * resume — the framework persists this on lifecycle state so a future
52
- * process can call `HarnessV1SandboxProvider.resume?({ sessionId })` and
53
- * reach the same resource. Providers populate it from their native
54
- * identifier (Vercel: the sandbox name; just-bash: a UUID minted at
55
- * create time).
49
+ * Identifier for the sandbox session. Persist this separately from the
50
+ * harness session ID and resume state when reattaching across processes.
56
51
  */
57
52
  readonly id: string;
58
53
 
59
54
  /**
60
55
  * The sandbox's default working directory — the absolute path that
61
56
  * `run`/`spawn` resolve relative commands against when no `workingDirectory`
62
- * is given. Read from the live sandbox (it is provider-specific and
63
- * configurable at create time: Vercel defaults to `/vercel/sandbox`,
64
- * just-bash to `/home/user`), never hardcoded.
57
+ * is given. Read from the live sandbox, never hardcoded.
65
58
  *
66
59
  * The framework composes each session's working directory underneath this
67
60
  * path (`<defaultWorkingDirectory>/<harnessId>-<sessionId>`) so adapters do
@@ -105,7 +98,7 @@ export interface HarnessV1NetworkSandboxSession extends SandboxSession {
105
98
 
106
99
  /**
107
100
  * Update the sandbox's outbound network policy. Optional — implementations
108
- * without a local enforcement primitive (e.g. just-bash) omit this. Callers
101
+ * without a local enforcement primitive omit this. Callers
109
102
  * use optional-call (`sandboxSession.setNetworkPolicy?.(policy)`); a
110
103
  * missing implementation is a no-op.
111
104
  */
@@ -139,7 +132,7 @@ export interface HarnessV1NetworkSandboxSession extends SandboxSession {
139
132
  /**
140
133
  * Replace the set of ports exposed by the sandbox. Full-replacement
141
134
  * semantics: ports omitted from the array are deregistered. Optional —
142
- * implementations that cannot expose ports (e.g. just-bash) omit this.
135
+ * implementations that cannot expose ports omit this.
143
136
  */
144
137
  readonly setPorts?: (
145
138
  ports: ReadonlyArray<number>,
@@ -7,6 +7,7 @@ import type { HarnessV1NetworkSandboxSession } from './harness-v1-network-sandbo
7
7
  * `LanguageModelV4` providers, no I/O performed at construction. The actual
8
8
  * sandbox is created (or wrapped) when `HarnessAgent` calls `createSession()`.
9
9
  */
10
+ /** @deprecated Supply a sandbox session to `HarnessAgent.createSession()` instead. */
10
11
  export interface HarnessV1SandboxProvider {
11
12
  readonly specificationVersion: 'harness-sandbox-v1';
12
13
  readonly providerId: string;
@@ -54,8 +55,8 @@ export interface HarnessV1SandboxProvider {
54
55
 
55
56
  /**
56
57
  * Reattach to an existing sandbox previously created with the same
57
- * `sessionId`. Optional — providers that cannot rehydrate by id (e.g.
58
- * just-bash) omit this; the harness throws
58
+ * `sessionId`. Optional — providers that cannot rehydrate by id omit
59
+ * this; the harness throws
59
60
  * `HarnessCapabilityUnsupportedError` when resume is attempted against
60
61
  * them.
61
62
  *
@@ -0,0 +1,14 @@
1
+ import type { HarnessV1SandboxTemplate } from './harness-v1-sandbox-template';
2
+
3
+ export type HarnessV1SandboxSessionCreateOptions<
4
+ TProviderOptions extends object,
5
+ > = TProviderOptions & {
6
+ /**
7
+ * Manually assign the ID of a newly created sandbox session. Creation never
8
+ * looks up or resumes an existing session. An existing sandbox resource with
9
+ * the same ID is a creation conflict.
10
+ */
11
+ readonly sandboxId?: string;
12
+ readonly template?: HarnessV1SandboxTemplate;
13
+ readonly abortSignal?: AbortSignal;
14
+ };
@@ -0,0 +1,10 @@
1
+ export type HarnessV1SandboxSessionResumeOptions<
2
+ TProviderOptions extends object,
3
+ > = TProviderOptions & {
4
+ /**
5
+ * ID of the existing sandbox session to reattach. Resume never creates a
6
+ * sandbox when the ID cannot be found.
7
+ */
8
+ readonly sandboxId: string;
9
+ readonly abortSignal?: AbortSignal;
10
+ };
@@ -0,0 +1,9 @@
1
+ import type { Experimental_SandboxSession } from '@ai-sdk/provider-utils';
2
+
3
+ export type HarnessV1SandboxTemplate = {
4
+ readonly identity: string;
5
+ readonly prepare: (options: {
6
+ readonly session: Experimental_SandboxSession;
7
+ readonly abortSignal?: AbortSignal;
8
+ }) => Promise<void>;
9
+ };
package/src/v1/index.ts CHANGED
@@ -48,6 +48,9 @@ export type {
48
48
  HarnessV1ResponseFormat,
49
49
  } from './harness-v1-response-format';
50
50
  export type { HarnessV1SandboxProvider } from './harness-v1-sandbox-provider';
51
+ export type { HarnessV1SandboxTemplate } from './harness-v1-sandbox-template';
52
+ export type { HarnessV1SandboxSessionCreateOptions } from './harness-v1-sandbox-session-create-options';
53
+ export type { HarnessV1SandboxSessionResumeOptions } from './harness-v1-sandbox-session-resume-options';
51
54
  export type {
52
55
  HarnessV1ContinueTurnState,
53
56
  HarnessV1LifecycleState,