@tanstack/ai-sandbox 0.3.3 → 0.4.0
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/README.md +26 -0
- package/dist/esm/checkpoint-store.d.ts +147 -0
- package/dist/esm/checkpoint-store.js +267 -0
- package/dist/esm/checkpoint-store.js.map +1 -0
- package/dist/esm/contracts.d.ts +19 -0
- package/dist/esm/index.d.ts +11 -1
- package/dist/esm/index.js +12 -7
- package/dist/esm/memory-snapshot-types.d.ts +129 -0
- package/dist/esm/memory-snapshots.d.ts +6 -0
- package/dist/esm/memory-snapshots.js +490 -0
- package/dist/esm/memory-snapshots.js.map +1 -0
- package/dist/esm/middleware.d.ts +33 -1
- package/dist/esm/middleware.js +339 -94
- package/dist/esm/middleware.js.map +1 -1
- package/dist/esm/ngrok.d.ts +1 -1
- package/dist/esm/sandbox.d.ts +16 -0
- package/dist/esm/sandbox.js +62 -9
- package/dist/esm/sandbox.js.map +1 -1
- package/dist/esm/snapshot-operations.d.ts +65 -0
- package/dist/esm/snapshot-operations.js +317 -0
- package/dist/esm/snapshot-operations.js.map +1 -0
- package/dist/esm/snapshot-tools.d.ts +185 -0
- package/dist/esm/snapshot-tools.js +160 -0
- package/dist/esm/snapshot-tools.js.map +1 -0
- package/dist/esm/snapshots.d.ts +51 -0
- package/dist/esm/snapshots.js +350 -0
- package/dist/esm/snapshots.js.map +1 -0
- package/dist/esm/testkit/checkpoint-conformance.d.ts +2 -0
- package/dist/esm/testkit/checkpoint-conformance.js +453 -0
- package/dist/esm/testkit/checkpoint-conformance.js.map +1 -0
- package/dist/esm/testkit/checkpoint-fork-conformance.d.ts +18 -0
- package/dist/esm/testkit/checkpoint-fork-conformance.js +191 -0
- package/dist/esm/testkit/checkpoint-fork-conformance.js.map +1 -0
- package/dist/esm/testkit/conformance.d.ts +4 -0
- package/dist/esm/testkit/conformance.js +3 -1
- package/dist/esm/testkit/conformance.js.map +1 -1
- package/package.json +8 -3
- package/skills/ai-sandbox/SKILL.md +96 -8
- package/src/checkpoint-store.ts +652 -0
- package/src/contracts.ts +12 -0
- package/src/index.ts +56 -0
- package/src/memory-snapshot-types.ts +167 -0
- package/src/memory-snapshots.ts +936 -0
- package/src/middleware.ts +610 -160
- package/src/sandbox.ts +107 -6
- package/src/snapshot-operations.ts +540 -0
- package/src/snapshot-tools.ts +208 -0
- package/src/snapshots.ts +711 -0
- package/src/testkit/checkpoint-conformance.ts +472 -0
- package/src/testkit/checkpoint-fork-conformance.ts +299 -0
- package/src/testkit/conformance.ts +7 -0
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import { SandboxSnapshotError, captureSandboxArtifacts, captureSandboxFiles, resolveSandboxSnapshotPolicy } from "./snapshots.js";
|
|
2
|
+
import { resolveAllSecrets } from "./secrets.js";
|
|
3
|
+
import { computeSandboxKey, computeWorkspaceHash } from "./key.js";
|
|
4
|
+
import { stageEnsureExistingSandbox } from "./sandbox.js";
|
|
5
|
+
//#region src/snapshot-operations.ts
|
|
6
|
+
async function withWriterLease(acquire, renew, operation) {
|
|
7
|
+
const writer = await acquire();
|
|
8
|
+
const release = writer.release.bind(writer);
|
|
9
|
+
const renewWriter = renew ? writer.renew.bind(writer) : void 0;
|
|
10
|
+
const renewAfterMs = renew ? writer.renewAfterMs : void 0;
|
|
11
|
+
let renewalTimer;
|
|
12
|
+
let renewalTask;
|
|
13
|
+
let renewalFailure;
|
|
14
|
+
let stopped = false;
|
|
15
|
+
const scheduleRenewal = () => {
|
|
16
|
+
if (renewWriter === void 0 || renewAfterMs === void 0) return;
|
|
17
|
+
renewalTimer = setTimeout(() => {
|
|
18
|
+
renewalTimer = void 0;
|
|
19
|
+
renewalTask = (async () => {
|
|
20
|
+
try {
|
|
21
|
+
await renewWriter();
|
|
22
|
+
} catch (error) {
|
|
23
|
+
renewalFailure = { error };
|
|
24
|
+
} finally {
|
|
25
|
+
renewalTask = void 0;
|
|
26
|
+
}
|
|
27
|
+
if (!stopped && renewalFailure === void 0) scheduleRenewal();
|
|
28
|
+
})();
|
|
29
|
+
}, renewAfterMs);
|
|
30
|
+
};
|
|
31
|
+
if (renew) scheduleRenewal();
|
|
32
|
+
const throwIfLost = async () => {
|
|
33
|
+
await renewalTask;
|
|
34
|
+
if (renewalFailure !== void 0) throw renewalFailure.error;
|
|
35
|
+
};
|
|
36
|
+
let outcome;
|
|
37
|
+
let operationFailure;
|
|
38
|
+
try {
|
|
39
|
+
outcome = { value: await operation(writer, throwIfLost) };
|
|
40
|
+
} catch (error) {
|
|
41
|
+
operationFailure = { error };
|
|
42
|
+
}
|
|
43
|
+
stopped = true;
|
|
44
|
+
if (renewalTimer !== void 0) clearTimeout(renewalTimer);
|
|
45
|
+
await renewalTask;
|
|
46
|
+
let releaseFailure;
|
|
47
|
+
try {
|
|
48
|
+
await release();
|
|
49
|
+
} catch (error) {
|
|
50
|
+
releaseFailure = { error };
|
|
51
|
+
}
|
|
52
|
+
if (renewalFailure !== void 0) throw renewalFailure.error;
|
|
53
|
+
if (operationFailure !== void 0) throw operationFailure.error;
|
|
54
|
+
if (releaseFailure !== void 0) throw releaseFailure.error;
|
|
55
|
+
if (outcome === void 0) throw new Error("Writer operation had no outcome");
|
|
56
|
+
return outcome.value;
|
|
57
|
+
}
|
|
58
|
+
function stageWorkspace(workspace) {
|
|
59
|
+
if (workspace === void 0) return void 0;
|
|
60
|
+
const source = workspace.source;
|
|
61
|
+
const packageManager = workspace.packageManager;
|
|
62
|
+
const setup = workspace.setup;
|
|
63
|
+
const scripts = workspace.scripts;
|
|
64
|
+
const skills = workspace.skills;
|
|
65
|
+
const instructions = workspace.instructions;
|
|
66
|
+
const plugins = workspace.plugins;
|
|
67
|
+
const secrets = workspace.secrets;
|
|
68
|
+
const root = workspace.root;
|
|
69
|
+
return {
|
|
70
|
+
source,
|
|
71
|
+
...Object.hasOwn(workspace, "packageManager") ? { packageManager } : {},
|
|
72
|
+
...Object.hasOwn(workspace, "setup") ? { setup } : {},
|
|
73
|
+
...Object.hasOwn(workspace, "scripts") ? { scripts } : {},
|
|
74
|
+
...Object.hasOwn(workspace, "skills") ? { skills } : {},
|
|
75
|
+
...Object.hasOwn(workspace, "instructions") ? { instructions } : {},
|
|
76
|
+
...Object.hasOwn(workspace, "plugins") ? { plugins } : {},
|
|
77
|
+
...Object.hasOwn(workspace, "secrets") ? { secrets } : {},
|
|
78
|
+
...Object.hasOwn(workspace, "root") ? { root } : {}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function effectivePolicy(supplied, workspaceHash) {
|
|
82
|
+
return resolveSandboxSnapshotPolicy(supplied, workspaceHash);
|
|
83
|
+
}
|
|
84
|
+
function stageInstanceStore(store) {
|
|
85
|
+
return {
|
|
86
|
+
get: store.get.bind(store),
|
|
87
|
+
upsert: store.upsert.bind(store),
|
|
88
|
+
delete: store.delete.bind(store)
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function stageLockStore(locks) {
|
|
92
|
+
if (locks === void 0) return void 0;
|
|
93
|
+
return { withLock: locks.withLock.bind(locks) };
|
|
94
|
+
}
|
|
95
|
+
function requireSnapshotPersistence(persistence) {
|
|
96
|
+
const stores = persistence.stores;
|
|
97
|
+
if (!stores?.messages || !stores.artifacts || !stores.blobs) throw new SandboxSnapshotError("SANDBOX_SNAPSHOT_MISSING_PERSISTENCE_STORES", "Sandbox snapshots require persistence stores.messages, stores.artifacts, and stores.blobs");
|
|
98
|
+
return persistence;
|
|
99
|
+
}
|
|
100
|
+
function createSandboxSnapshots(input) {
|
|
101
|
+
const persistence = requireSnapshotPersistence(input.persistence);
|
|
102
|
+
const checkpoints = input.checkpoints;
|
|
103
|
+
const policy = input.policy;
|
|
104
|
+
const boundSandbox = input.sandbox;
|
|
105
|
+
const boundInstances = input.instances;
|
|
106
|
+
const boundTenant = input.tenant;
|
|
107
|
+
const boundLocks = input.locks;
|
|
108
|
+
return {
|
|
109
|
+
persistence,
|
|
110
|
+
checkpoints,
|
|
111
|
+
...policy === void 0 ? {} : { policy },
|
|
112
|
+
async save(saveInput) {
|
|
113
|
+
const sandbox = saveInput.sandbox ?? boundSandbox;
|
|
114
|
+
const instances = saveInput.instances ?? boundInstances;
|
|
115
|
+
if (sandbox === void 0) throw new SandboxSnapshotError("SANDBOX_SNAPSHOT_MISSING_SANDBOX", "Named snapshots require a sandbox at create time or on save");
|
|
116
|
+
if (instances === void 0) throw new SandboxSnapshotError("SANDBOX_SNAPSHOT_MISSING_INSTANCES", "Named snapshots require instances at create time or on save");
|
|
117
|
+
return saveNamedSandboxSnapshot({
|
|
118
|
+
definition: sandbox,
|
|
119
|
+
threadId: saveInput.threadId,
|
|
120
|
+
runId: saveInput.runId,
|
|
121
|
+
instances,
|
|
122
|
+
persistence,
|
|
123
|
+
checkpoints,
|
|
124
|
+
policy,
|
|
125
|
+
label: saveInput.label,
|
|
126
|
+
tenant: saveInput.tenant ?? boundTenant,
|
|
127
|
+
locks: saveInput.locks ?? boundLocks,
|
|
128
|
+
signal: saveInput.signal,
|
|
129
|
+
adapterName: saveInput.adapterName
|
|
130
|
+
});
|
|
131
|
+
},
|
|
132
|
+
fork(forkInput) {
|
|
133
|
+
return forkFromSandboxSnapshot({
|
|
134
|
+
threadId: forkInput.threadId,
|
|
135
|
+
checkpointId: forkInput.checkpointId,
|
|
136
|
+
destinationThreadId: forkInput.destinationThreadId,
|
|
137
|
+
checkpoints,
|
|
138
|
+
destinationCheckpointId: forkInput.destinationCheckpointId,
|
|
139
|
+
createdAt: forkInput.createdAt
|
|
140
|
+
});
|
|
141
|
+
},
|
|
142
|
+
readArtifact(readInput) {
|
|
143
|
+
return resolveSnapshotArtifact({
|
|
144
|
+
threadId: readInput.threadId,
|
|
145
|
+
checkpointId: readInput.checkpointId,
|
|
146
|
+
artifactId: readInput.artifactId,
|
|
147
|
+
persistence,
|
|
148
|
+
checkpoints
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
async function saveNamedSandboxSnapshot(input) {
|
|
154
|
+
const definition = input.definition;
|
|
155
|
+
const threadId = input.threadId;
|
|
156
|
+
const runId = input.runId;
|
|
157
|
+
const instances = stageInstanceStore(input.instances);
|
|
158
|
+
const label = input.label;
|
|
159
|
+
const suppliedTenant = input.tenant;
|
|
160
|
+
const tenantUserId = suppliedTenant?.userId;
|
|
161
|
+
const tenantOrgId = suppliedTenant?.orgId;
|
|
162
|
+
const tenant = suppliedTenant ? {
|
|
163
|
+
...tenantUserId === void 0 ? {} : { userId: tenantUserId },
|
|
164
|
+
...tenantOrgId === void 0 ? {} : { orgId: tenantOrgId }
|
|
165
|
+
} : void 0;
|
|
166
|
+
const locks = stageLockStore(input.locks);
|
|
167
|
+
const signal = input.signal;
|
|
168
|
+
const adapterName = input.adapterName;
|
|
169
|
+
const lifecycle = definition.lifecycle;
|
|
170
|
+
const reuse = lifecycle?.reuse;
|
|
171
|
+
const snapshotMaxAge = lifecycle?.snapshotMaxAge;
|
|
172
|
+
const workspace = stageWorkspace(definition.workspace);
|
|
173
|
+
const sandboxId = definition.id;
|
|
174
|
+
const provider = definition.provider;
|
|
175
|
+
const providerName = provider.name;
|
|
176
|
+
const resume = provider.resume.bind(provider);
|
|
177
|
+
const ensureExisting = stageEnsureExistingSandbox(definition);
|
|
178
|
+
const stores = input.persistence.stores;
|
|
179
|
+
const messages = stores.messages;
|
|
180
|
+
const loadThread = messages.loadThread.bind(messages);
|
|
181
|
+
const artifactStore = stores.artifacts;
|
|
182
|
+
const listForThread = artifactStore.listForThread.bind(artifactStore);
|
|
183
|
+
const suppliedBlobs = stores.blobs;
|
|
184
|
+
const blobs = {
|
|
185
|
+
get: suppliedBlobs.get.bind(suppliedBlobs),
|
|
186
|
+
head: suppliedBlobs.head.bind(suppliedBlobs),
|
|
187
|
+
put: suppliedBlobs.put.bind(suppliedBlobs)
|
|
188
|
+
};
|
|
189
|
+
const checkpoints = input.checkpoints;
|
|
190
|
+
const acquireWriter = checkpoints.acquireWriter.bind(checkpoints);
|
|
191
|
+
const getHead = checkpoints.getHead.bind(checkpoints);
|
|
192
|
+
const append = checkpoints.append.bind(checkpoints);
|
|
193
|
+
const policy = effectivePolicy(input.policy, workspace === void 0 ? void 0 : computeWorkspaceHash(workspace));
|
|
194
|
+
const workspaceSecrets = workspace?.secrets;
|
|
195
|
+
const secrets = workspaceSecrets ? resolveAllSecrets(workspaceSecrets) : {};
|
|
196
|
+
const workspaceRoot = workspace?.root;
|
|
197
|
+
const key = computeSandboxKey({
|
|
198
|
+
threadId,
|
|
199
|
+
sandboxId,
|
|
200
|
+
providerName,
|
|
201
|
+
workspace,
|
|
202
|
+
tenant
|
|
203
|
+
});
|
|
204
|
+
return withWriterLease(() => acquireWriter(threadId), true, async (writer, throwIfLost) => {
|
|
205
|
+
if (reuse === "none") throw new SandboxSnapshotError("SANDBOX_SNAPSHOT_REUSE_NONE", "Named snapshots require a reusable sandbox lifecycle");
|
|
206
|
+
const handle = await ensureExisting({
|
|
207
|
+
threadId,
|
|
208
|
+
runId,
|
|
209
|
+
store: instances,
|
|
210
|
+
locks,
|
|
211
|
+
tenant,
|
|
212
|
+
signal,
|
|
213
|
+
adapterName
|
|
214
|
+
}, {
|
|
215
|
+
key,
|
|
216
|
+
workspace,
|
|
217
|
+
resolvedSecrets: workspaceSecrets ? secrets : void 0,
|
|
218
|
+
snapshotMaxAge,
|
|
219
|
+
resume
|
|
220
|
+
});
|
|
221
|
+
if (!handle) throw new SandboxSnapshotError("SANDBOX_SNAPSHOT_MISSING_REUSABLE_SANDBOX", "Named snapshots require an existing resumable sandbox");
|
|
222
|
+
const conversation = await loadThread(threadId);
|
|
223
|
+
const files = await captureSandboxFiles(handle, {
|
|
224
|
+
blobs,
|
|
225
|
+
workspaceRoot
|
|
226
|
+
}, policy, secrets);
|
|
227
|
+
const artifacts = await captureSandboxArtifacts({
|
|
228
|
+
blobs,
|
|
229
|
+
artifacts: { listForThread }
|
|
230
|
+
}, threadId, secrets);
|
|
231
|
+
const parentCheckpointId = await getHead(threadId);
|
|
232
|
+
await throwIfLost();
|
|
233
|
+
const checkpoint = {
|
|
234
|
+
id: crypto.randomUUID(),
|
|
235
|
+
threadId,
|
|
236
|
+
parentCheckpointId,
|
|
237
|
+
createdAt: Date.now(),
|
|
238
|
+
reason: "named",
|
|
239
|
+
label,
|
|
240
|
+
sourceRunId: runId,
|
|
241
|
+
files: files.files,
|
|
242
|
+
conversation,
|
|
243
|
+
artifacts
|
|
244
|
+
};
|
|
245
|
+
await append({
|
|
246
|
+
checkpoint,
|
|
247
|
+
expectedHeadId: parentCheckpointId,
|
|
248
|
+
writer
|
|
249
|
+
});
|
|
250
|
+
await throwIfLost();
|
|
251
|
+
return checkpoint;
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
async function forkFromSandboxSnapshot(input) {
|
|
255
|
+
const sourceThreadId = input.threadId;
|
|
256
|
+
const sourceCheckpointId = input.checkpointId;
|
|
257
|
+
const destinationThreadId = input.destinationThreadId;
|
|
258
|
+
const suppliedDestinationCheckpointId = input.destinationCheckpointId;
|
|
259
|
+
const suppliedCreatedAt = input.createdAt;
|
|
260
|
+
const destinationCheckpointId = suppliedDestinationCheckpointId ?? crypto.randomUUID();
|
|
261
|
+
const createdAt = suppliedCreatedAt ?? Date.now();
|
|
262
|
+
const checkpoints = input.checkpoints;
|
|
263
|
+
const acquireWriter = checkpoints.acquireWriter.bind(checkpoints);
|
|
264
|
+
const forkFromCheckpoint = checkpoints.forkFromCheckpoint?.bind(checkpoints);
|
|
265
|
+
return withWriterLease(() => acquireWriter(destinationThreadId), false, async (writer) => {
|
|
266
|
+
if (forkFromCheckpoint === void 0) throw new SandboxSnapshotError("SANDBOX_SNAPSHOT_FORK_UNAVAILABLE", "The checkpoint store does not support atomic forks");
|
|
267
|
+
return (await forkFromCheckpoint({
|
|
268
|
+
sourceThreadId,
|
|
269
|
+
sourceCheckpointId,
|
|
270
|
+
destinationThreadId,
|
|
271
|
+
destinationCheckpointId,
|
|
272
|
+
createdAt,
|
|
273
|
+
writer
|
|
274
|
+
})).checkpoint;
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
async function sha256(bytes) {
|
|
278
|
+
const digest = await crypto.subtle.digest("SHA-256", new Uint8Array(bytes));
|
|
279
|
+
return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
280
|
+
}
|
|
281
|
+
async function resolveSnapshotArtifact(input) {
|
|
282
|
+
const threadId = input.threadId;
|
|
283
|
+
const checkpointId = input.checkpointId;
|
|
284
|
+
const artifactId = input.artifactId;
|
|
285
|
+
const checkpoints = input.checkpoints;
|
|
286
|
+
const getCheckpoint = checkpoints.get.bind(checkpoints);
|
|
287
|
+
const blobs = input.persistence.stores.blobs;
|
|
288
|
+
const getBlob = blobs.get.bind(blobs);
|
|
289
|
+
const checkpoint = await getCheckpoint(checkpointId);
|
|
290
|
+
if (!checkpoint) throw new SandboxSnapshotError("SANDBOX_SNAPSHOT_MISSING_CHECKPOINT_ARTIFACT", "Snapshot checkpoint does not exist");
|
|
291
|
+
const checkpointThreadId = checkpoint.threadId;
|
|
292
|
+
const checkpointArtifacts = checkpoint.artifacts;
|
|
293
|
+
if (checkpointThreadId !== threadId) throw new SandboxSnapshotError("SANDBOX_SNAPSHOT_FOREIGN_CHECKPOINT_ARTIFACT", "Snapshot checkpoint belongs to another thread");
|
|
294
|
+
const foundArtifact = checkpointArtifacts.find((value) => value.artifactId === artifactId);
|
|
295
|
+
if (!foundArtifact) throw new SandboxSnapshotError("SANDBOX_SNAPSHOT_MISSING_CHECKPOINT_ARTIFACT", "Snapshot artifact does not exist");
|
|
296
|
+
const artifact = {
|
|
297
|
+
artifactId: foundArtifact.artifactId,
|
|
298
|
+
name: foundArtifact.name,
|
|
299
|
+
mimeType: foundArtifact.mimeType,
|
|
300
|
+
size: foundArtifact.size,
|
|
301
|
+
blobKey: foundArtifact.blobKey,
|
|
302
|
+
createdAt: foundArtifact.createdAt
|
|
303
|
+
};
|
|
304
|
+
const blob = await getBlob(artifact.blobKey);
|
|
305
|
+
if (!blob) throw new SandboxSnapshotError("SANDBOX_SNAPSHOT_INVALID_ARTIFACT_BYTES", "Snapshot artifact blob does not exist");
|
|
306
|
+
const arrayBuffer = blob.arrayBuffer.bind(blob);
|
|
307
|
+
const bytes = new Uint8Array(await arrayBuffer());
|
|
308
|
+
if (bytes.byteLength !== artifact.size || artifact.blobKey !== `sandbox-artifacts/sha256/${await sha256(bytes)}`) throw new SandboxSnapshotError("SANDBOX_SNAPSHOT_INVALID_ARTIFACT_BYTES", "Snapshot artifact bytes do not match metadata");
|
|
309
|
+
return {
|
|
310
|
+
artifact: { ...artifact },
|
|
311
|
+
bytes: bytes.slice()
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
//#endregion
|
|
315
|
+
export { createSandboxSnapshots };
|
|
316
|
+
|
|
317
|
+
//# sourceMappingURL=snapshot-operations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot-operations.js","names":[],"sources":["../../src/snapshot-operations.ts"],"sourcesContent":["import {\n captureSandboxArtifacts,\n captureSandboxFiles,\n resolveSandboxSnapshotPolicy,\n SandboxSnapshotError,\n} from './snapshots'\nimport { resolveAllSecrets } from './secrets'\nimport { computeSandboxKey, computeWorkspaceHash } from './key'\nimport { stageEnsureExistingSandbox } from './sandbox'\nimport type { ModelMessage } from '@tanstack/ai'\nimport type { LockStore } from '@tanstack/ai/locks'\nimport type {\n SandboxCheckpoint,\n SandboxCheckpointStore,\n SandboxCheckpointWriterLease,\n} from './checkpoint-store'\nimport type { SandboxInstanceStore } from './instance-store'\nimport type { SandboxDefinition } from './sandbox'\nimport type { SandboxSnapshotBundle, SandboxSnapshotPolicy } from './snapshots'\nimport type { WorkspaceDefinition } from './workspace'\n\nexport interface SnapshotPersistence {\n stores: {\n messages: {\n loadThread: (threadId: string) => Promise<ReadonlyArray<ModelMessage>>\n }\n artifacts: NonNullable<SandboxSnapshotBundle['artifacts']>\n blobs: SandboxSnapshotBundle['blobs']\n }\n}\n\nexport interface CreateSandboxSnapshotsInput<\n TPersistence extends SnapshotPersistence = SnapshotPersistence,\n TCheckpoints extends SandboxCheckpointStore = SandboxCheckpointStore,\n> {\n persistence: TPersistence\n checkpoints: TCheckpoints\n policy?: SandboxSnapshotPolicy\n sandbox?: SandboxDefinition\n instances?: SandboxInstanceStore\n tenant?: { userId?: string; orgId?: string }\n locks?: LockStore\n}\n\nexport interface SaveSandboxSnapshotInput {\n threadId: string\n runId: string\n label: string\n sandbox?: SandboxDefinition\n instances?: SandboxInstanceStore\n tenant?: { userId?: string; orgId?: string }\n locks?: LockStore\n signal?: AbortSignal\n adapterName?: string\n}\n\nexport interface ForkSandboxSnapshotInput {\n threadId: string\n checkpointId: string\n destinationThreadId: string\n destinationCheckpointId?: string\n createdAt?: number\n}\n\nexport interface ReadSandboxSnapshotArtifactInput {\n threadId: string\n checkpointId: string\n artifactId: string\n}\n\nexport interface SandboxSnapshots<\n TPersistence extends SnapshotPersistence = SnapshotPersistence,\n TCheckpoints extends SandboxCheckpointStore = SandboxCheckpointStore,\n> {\n persistence: TPersistence\n checkpoints: TCheckpoints\n policy?: SandboxSnapshotPolicy\n save: (input: SaveSandboxSnapshotInput) => Promise<SandboxCheckpoint>\n fork: (input: ForkSandboxSnapshotInput) => Promise<SandboxCheckpoint>\n readArtifact: (input: ReadSandboxSnapshotArtifactInput) => Promise<{\n artifact: SandboxCheckpoint['artifacts'][number]\n bytes: Uint8Array\n }>\n}\n\ntype Failure = { error: unknown }\n\nasync function withWriterLease<T>(\n acquire: () => Promise<SandboxCheckpointWriterLease>,\n renew: boolean,\n operation: (\n writer: SandboxCheckpointWriterLease,\n throwIfLost: () => Promise<void>,\n ) => Promise<T>,\n): Promise<T> {\n const writer = await acquire()\n const release = writer.release.bind(writer)\n const renewWriter = renew ? writer.renew.bind(writer) : undefined\n const renewAfterMs = renew ? writer.renewAfterMs : undefined\n let renewalTimer: ReturnType<typeof setTimeout> | undefined\n let renewalTask: Promise<void> | undefined\n let renewalFailure: Failure | undefined\n let stopped = false\n\n const scheduleRenewal = (): void => {\n if (renewWriter === undefined || renewAfterMs === undefined) return\n renewalTimer = setTimeout(() => {\n renewalTimer = undefined\n renewalTask = (async () => {\n try {\n await renewWriter()\n } catch (error) {\n renewalFailure = { error }\n } finally {\n renewalTask = undefined\n }\n if (!stopped && renewalFailure === undefined) scheduleRenewal()\n })()\n }, renewAfterMs)\n }\n if (renew) scheduleRenewal()\n\n const throwIfLost = async (): Promise<void> => {\n await renewalTask\n if (renewalFailure !== undefined) throw renewalFailure.error\n }\n\n let outcome: { value: T } | undefined\n let operationFailure: Failure | undefined\n try {\n outcome = { value: await operation(writer, throwIfLost) }\n } catch (error) {\n operationFailure = { error }\n }\n\n stopped = true\n if (renewalTimer !== undefined) clearTimeout(renewalTimer)\n await renewalTask\n let releaseFailure: Failure | undefined\n try {\n await release()\n } catch (error) {\n releaseFailure = { error }\n }\n\n if (renewalFailure !== undefined) throw renewalFailure.error\n if (operationFailure !== undefined) throw operationFailure.error\n if (releaseFailure !== undefined) throw releaseFailure.error\n if (outcome === undefined) throw new Error('Writer operation had no outcome')\n return outcome.value\n}\n\nfunction stageWorkspace(\n workspace: WorkspaceDefinition | undefined,\n): WorkspaceDefinition | undefined {\n if (workspace === undefined) return undefined\n const source = workspace.source\n const packageManager = workspace.packageManager\n const setup = workspace.setup\n const scripts = workspace.scripts\n const skills = workspace.skills\n const instructions = workspace.instructions\n const plugins = workspace.plugins\n const secrets = workspace.secrets\n const root = workspace.root\n return {\n source,\n ...(Object.hasOwn(workspace, 'packageManager') ? { packageManager } : {}),\n ...(Object.hasOwn(workspace, 'setup') ? { setup } : {}),\n ...(Object.hasOwn(workspace, 'scripts') ? { scripts } : {}),\n ...(Object.hasOwn(workspace, 'skills') ? { skills } : {}),\n ...(Object.hasOwn(workspace, 'instructions') ? { instructions } : {}),\n ...(Object.hasOwn(workspace, 'plugins') ? { plugins } : {}),\n ...(Object.hasOwn(workspace, 'secrets') ? { secrets } : {}),\n ...(Object.hasOwn(workspace, 'root') ? { root } : {}),\n }\n}\n\nfunction effectivePolicy(\n supplied: SandboxSnapshotPolicy | undefined,\n workspaceHash: string | undefined,\n): SandboxSnapshotPolicy {\n return resolveSandboxSnapshotPolicy(supplied, workspaceHash)\n}\n\nfunction stageInstanceStore(store: SandboxInstanceStore): SandboxInstanceStore {\n const get = store.get.bind(store)\n const upsert = store.upsert.bind(store)\n const deleteRecord = store.delete.bind(store)\n return { get, upsert, delete: deleteRecord }\n}\n\nfunction stageLockStore(locks: LockStore | undefined): LockStore | undefined {\n if (locks === undefined) return undefined\n const withLock = locks.withLock.bind(locks)\n return { withLock }\n}\n\nfunction requireSnapshotPersistence<TPersistence extends SnapshotPersistence>(\n persistence: TPersistence,\n): TPersistence {\n const stores = persistence.stores\n if (!stores?.messages || !stores.artifacts || !stores.blobs) {\n throw new SandboxSnapshotError(\n 'SANDBOX_SNAPSHOT_MISSING_PERSISTENCE_STORES',\n 'Sandbox snapshots require persistence stores.messages, stores.artifacts, and stores.blobs',\n )\n }\n return persistence\n}\n\nexport function createSandboxSnapshots<\n TPersistence extends SnapshotPersistence,\n TCheckpoints extends SandboxCheckpointStore,\n>(\n input: CreateSandboxSnapshotsInput<TPersistence, TCheckpoints>,\n): SandboxSnapshots<TPersistence, TCheckpoints> {\n const persistence = requireSnapshotPersistence(input.persistence)\n const checkpoints = input.checkpoints\n const policy = input.policy\n const boundSandbox = input.sandbox\n const boundInstances = input.instances\n const boundTenant = input.tenant\n const boundLocks = input.locks\n\n return {\n persistence,\n checkpoints,\n ...(policy === undefined ? {} : { policy }),\n async save(saveInput) {\n const sandbox = saveInput.sandbox ?? boundSandbox\n const instances = saveInput.instances ?? boundInstances\n if (sandbox === undefined)\n throw new SandboxSnapshotError(\n 'SANDBOX_SNAPSHOT_MISSING_SANDBOX',\n 'Named snapshots require a sandbox at create time or on save',\n )\n if (instances === undefined)\n throw new SandboxSnapshotError(\n 'SANDBOX_SNAPSHOT_MISSING_INSTANCES',\n 'Named snapshots require instances at create time or on save',\n )\n return saveNamedSandboxSnapshot({\n definition: sandbox,\n threadId: saveInput.threadId,\n runId: saveInput.runId,\n instances,\n persistence,\n checkpoints,\n policy,\n label: saveInput.label,\n tenant: saveInput.tenant ?? boundTenant,\n locks: saveInput.locks ?? boundLocks,\n signal: saveInput.signal,\n adapterName: saveInput.adapterName,\n })\n },\n fork(forkInput) {\n return forkFromSandboxSnapshot({\n threadId: forkInput.threadId,\n checkpointId: forkInput.checkpointId,\n destinationThreadId: forkInput.destinationThreadId,\n checkpoints,\n destinationCheckpointId: forkInput.destinationCheckpointId,\n createdAt: forkInput.createdAt,\n })\n },\n readArtifact(readInput) {\n return resolveSnapshotArtifact({\n threadId: readInput.threadId,\n checkpointId: readInput.checkpointId,\n artifactId: readInput.artifactId,\n persistence,\n checkpoints,\n })\n },\n }\n}\n\nasync function saveNamedSandboxSnapshot(input: {\n definition: SandboxDefinition\n threadId: string\n runId: string\n instances: SandboxInstanceStore\n persistence: SnapshotPersistence\n checkpoints: SandboxCheckpointStore\n policy?: SandboxSnapshotPolicy\n label: string\n tenant?: { userId?: string; orgId?: string }\n locks?: LockStore\n signal?: AbortSignal\n adapterName?: string\n}): Promise<SandboxCheckpoint> {\n const definition = input.definition\n const threadId = input.threadId\n const runId = input.runId\n const instances = stageInstanceStore(input.instances)\n const label = input.label\n const suppliedTenant = input.tenant\n const tenantUserId = suppliedTenant?.userId\n const tenantOrgId = suppliedTenant?.orgId\n const tenant = suppliedTenant\n ? {\n ...(tenantUserId === undefined ? {} : { userId: tenantUserId }),\n ...(tenantOrgId === undefined ? {} : { orgId: tenantOrgId }),\n }\n : undefined\n const locks = stageLockStore(input.locks)\n const signal = input.signal\n const adapterName = input.adapterName\n const lifecycle = definition.lifecycle\n const reuse = lifecycle?.reuse\n const snapshotMaxAge = lifecycle?.snapshotMaxAge\n const workspace = stageWorkspace(definition.workspace)\n const sandboxId = definition.id\n const provider = definition.provider\n const providerName = provider.name\n const resume = provider.resume.bind(provider)\n const ensureExisting = stageEnsureExistingSandbox(definition)\n const persistence = input.persistence\n const stores = persistence.stores\n const messages = stores.messages\n const loadThread = messages.loadThread.bind(messages)\n const artifactStore = stores.artifacts\n const listForThread = artifactStore.listForThread.bind(artifactStore)\n const suppliedBlobs = stores.blobs\n const getBlob = suppliedBlobs.get.bind(suppliedBlobs)\n const headBlob = suppliedBlobs.head.bind(suppliedBlobs)\n const putBlob = suppliedBlobs.put.bind(suppliedBlobs)\n const blobs: SandboxSnapshotBundle['blobs'] = {\n get: getBlob,\n head: headBlob,\n put: putBlob,\n }\n const checkpoints = input.checkpoints\n const acquireWriter = checkpoints.acquireWriter.bind(checkpoints)\n const getHead = checkpoints.getHead.bind(checkpoints)\n const append = checkpoints.append.bind(checkpoints)\n const policy = effectivePolicy(\n input.policy,\n workspace === undefined ? undefined : computeWorkspaceHash(workspace),\n )\n const workspaceSecrets = workspace?.secrets\n const secrets = workspaceSecrets ? resolveAllSecrets(workspaceSecrets) : {}\n const workspaceRoot = workspace?.root\n const key = computeSandboxKey({\n threadId,\n sandboxId,\n providerName,\n workspace,\n tenant,\n })\n\n return withWriterLease(\n () => acquireWriter(threadId),\n true,\n async (writer, throwIfLost) => {\n if (reuse === 'none')\n throw new SandboxSnapshotError(\n 'SANDBOX_SNAPSHOT_REUSE_NONE',\n 'Named snapshots require a reusable sandbox lifecycle',\n )\n const handle = await ensureExisting(\n {\n threadId,\n runId,\n store: instances,\n locks,\n tenant,\n signal,\n adapterName,\n },\n {\n key,\n workspace,\n resolvedSecrets: workspaceSecrets ? secrets : undefined,\n snapshotMaxAge,\n resume,\n },\n )\n if (!handle)\n throw new SandboxSnapshotError(\n 'SANDBOX_SNAPSHOT_MISSING_REUSABLE_SANDBOX',\n 'Named snapshots require an existing resumable sandbox',\n )\n const conversation = await loadThread(threadId)\n const files = await captureSandboxFiles(\n handle,\n { blobs, workspaceRoot },\n policy,\n secrets,\n )\n const artifacts = await captureSandboxArtifacts(\n {\n blobs,\n artifacts: { listForThread },\n },\n threadId,\n secrets,\n )\n const parentCheckpointId = await getHead(threadId)\n await throwIfLost()\n const checkpoint: SandboxCheckpoint = {\n id: crypto.randomUUID(),\n threadId,\n parentCheckpointId,\n createdAt: Date.now(),\n reason: 'named',\n label,\n sourceRunId: runId,\n files: files.files,\n conversation,\n artifacts,\n }\n await append({\n checkpoint,\n expectedHeadId: parentCheckpointId,\n writer,\n })\n await throwIfLost()\n return checkpoint\n },\n )\n}\n\nasync function forkFromSandboxSnapshot(input: {\n threadId: string\n checkpointId: string\n destinationThreadId: string\n checkpoints: SandboxCheckpointStore\n destinationCheckpointId?: string\n createdAt?: number\n}): Promise<SandboxCheckpoint> {\n const sourceThreadId = input.threadId\n const sourceCheckpointId = input.checkpointId\n const destinationThreadId = input.destinationThreadId\n const suppliedDestinationCheckpointId = input.destinationCheckpointId\n const suppliedCreatedAt = input.createdAt\n const destinationCheckpointId =\n suppliedDestinationCheckpointId ?? crypto.randomUUID()\n const createdAt = suppliedCreatedAt ?? Date.now()\n const checkpoints = input.checkpoints\n const acquireWriter = checkpoints.acquireWriter.bind(checkpoints)\n const forkFromCheckpoint = checkpoints.forkFromCheckpoint?.bind(checkpoints)\n\n return withWriterLease(\n () => acquireWriter(destinationThreadId),\n false,\n async (writer) => {\n if (forkFromCheckpoint === undefined)\n throw new SandboxSnapshotError(\n 'SANDBOX_SNAPSHOT_FORK_UNAVAILABLE',\n 'The checkpoint store does not support atomic forks',\n )\n const result = await forkFromCheckpoint({\n sourceThreadId,\n sourceCheckpointId,\n destinationThreadId,\n destinationCheckpointId,\n createdAt,\n writer,\n })\n return result.checkpoint\n },\n )\n}\n\nasync function sha256(bytes: Uint8Array): Promise<string> {\n const digest = await crypto.subtle.digest('SHA-256', new Uint8Array(bytes))\n return Array.from(new Uint8Array(digest), (byte) =>\n byte.toString(16).padStart(2, '0'),\n ).join('')\n}\n\nasync function resolveSnapshotArtifact(input: {\n threadId: string\n checkpointId: string\n artifactId: string\n persistence: SnapshotPersistence\n checkpoints: SandboxCheckpointStore\n}): Promise<{\n artifact: SandboxCheckpoint['artifacts'][number]\n bytes: Uint8Array\n}> {\n const threadId = input.threadId\n const checkpointId = input.checkpointId\n const artifactId = input.artifactId\n const checkpoints = input.checkpoints\n const getCheckpoint = checkpoints.get.bind(checkpoints)\n const persistence = input.persistence\n const stores = persistence.stores\n const blobs = stores.blobs\n const getBlob = blobs.get.bind(blobs)\n const checkpoint = await getCheckpoint(checkpointId)\n if (!checkpoint)\n throw new SandboxSnapshotError(\n 'SANDBOX_SNAPSHOT_MISSING_CHECKPOINT_ARTIFACT',\n 'Snapshot checkpoint does not exist',\n )\n const checkpointThreadId = checkpoint.threadId\n const checkpointArtifacts = checkpoint.artifacts\n if (checkpointThreadId !== threadId)\n throw new SandboxSnapshotError(\n 'SANDBOX_SNAPSHOT_FOREIGN_CHECKPOINT_ARTIFACT',\n 'Snapshot checkpoint belongs to another thread',\n )\n const foundArtifact = checkpointArtifacts.find(\n (value) => value.artifactId === artifactId,\n )\n if (!foundArtifact)\n throw new SandboxSnapshotError(\n 'SANDBOX_SNAPSHOT_MISSING_CHECKPOINT_ARTIFACT',\n 'Snapshot artifact does not exist',\n )\n const artifact = {\n artifactId: foundArtifact.artifactId,\n name: foundArtifact.name,\n mimeType: foundArtifact.mimeType,\n size: foundArtifact.size,\n blobKey: foundArtifact.blobKey,\n createdAt: foundArtifact.createdAt,\n }\n const blob = await getBlob(artifact.blobKey)\n if (!blob)\n throw new SandboxSnapshotError(\n 'SANDBOX_SNAPSHOT_INVALID_ARTIFACT_BYTES',\n 'Snapshot artifact blob does not exist',\n )\n const arrayBuffer = blob.arrayBuffer.bind(blob)\n const bytes = new Uint8Array(await arrayBuffer())\n if (\n bytes.byteLength !== artifact.size ||\n artifact.blobKey !== `sandbox-artifacts/sha256/${await sha256(bytes)}`\n )\n throw new SandboxSnapshotError(\n 'SANDBOX_SNAPSHOT_INVALID_ARTIFACT_BYTES',\n 'Snapshot artifact bytes do not match metadata',\n )\n return { artifact: { ...artifact }, bytes: bytes.slice() }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { SandboxSnapshots } from './snapshot-operations.js';
|
|
2
|
+
export interface CreateSnapshotToolsOptions {
|
|
3
|
+
threadId: string;
|
|
4
|
+
runId: string;
|
|
5
|
+
createThreadId: () => string;
|
|
6
|
+
tenant?: {
|
|
7
|
+
userId?: string;
|
|
8
|
+
orgId?: string;
|
|
9
|
+
};
|
|
10
|
+
onForked?: (input: {
|
|
11
|
+
destinationThreadId: string;
|
|
12
|
+
checkpointId: string;
|
|
13
|
+
}) => void | Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
export declare function createSnapshotTools(snapshots: SandboxSnapshots, options: CreateSnapshotToolsOptions): readonly [import('@tanstack/ai').ServerTool<{
|
|
16
|
+
type: string;
|
|
17
|
+
properties: {
|
|
18
|
+
label: {
|
|
19
|
+
type: string;
|
|
20
|
+
description: string;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
required: string[];
|
|
24
|
+
additionalProperties: false;
|
|
25
|
+
}, {
|
|
26
|
+
type: string;
|
|
27
|
+
properties: {
|
|
28
|
+
checkpointId: {
|
|
29
|
+
type: string;
|
|
30
|
+
};
|
|
31
|
+
label: {
|
|
32
|
+
type: string;
|
|
33
|
+
};
|
|
34
|
+
threadId: {
|
|
35
|
+
type: string;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
required: string[];
|
|
39
|
+
additionalProperties: false;
|
|
40
|
+
}, "save_sandbox_snapshot", unknown, false, undefined> & {
|
|
41
|
+
inputSchema: {
|
|
42
|
+
type: string;
|
|
43
|
+
properties: {
|
|
44
|
+
label: {
|
|
45
|
+
type: string;
|
|
46
|
+
description: string;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
required: string[];
|
|
50
|
+
additionalProperties: false;
|
|
51
|
+
};
|
|
52
|
+
outputSchema: {
|
|
53
|
+
type: string;
|
|
54
|
+
properties: {
|
|
55
|
+
checkpointId: {
|
|
56
|
+
type: string;
|
|
57
|
+
};
|
|
58
|
+
label: {
|
|
59
|
+
type: string;
|
|
60
|
+
};
|
|
61
|
+
threadId: {
|
|
62
|
+
type: string;
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
required: string[];
|
|
66
|
+
additionalProperties: false;
|
|
67
|
+
};
|
|
68
|
+
approvalSchema: undefined;
|
|
69
|
+
}, import('@tanstack/ai').ServerTool<{
|
|
70
|
+
type: string;
|
|
71
|
+
properties: {
|
|
72
|
+
checkpointId: {
|
|
73
|
+
type: string;
|
|
74
|
+
description: string;
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
additionalProperties: false;
|
|
78
|
+
}, {
|
|
79
|
+
type: string;
|
|
80
|
+
properties: {
|
|
81
|
+
checkpointId: {
|
|
82
|
+
type: string;
|
|
83
|
+
};
|
|
84
|
+
destinationThreadId: {
|
|
85
|
+
type: string;
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
required: string[];
|
|
89
|
+
additionalProperties: false;
|
|
90
|
+
}, "fork_sandbox_snapshot", unknown, false, undefined> & {
|
|
91
|
+
inputSchema: {
|
|
92
|
+
type: string;
|
|
93
|
+
properties: {
|
|
94
|
+
checkpointId: {
|
|
95
|
+
type: string;
|
|
96
|
+
description: string;
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
additionalProperties: false;
|
|
100
|
+
};
|
|
101
|
+
outputSchema: {
|
|
102
|
+
type: string;
|
|
103
|
+
properties: {
|
|
104
|
+
checkpointId: {
|
|
105
|
+
type: string;
|
|
106
|
+
};
|
|
107
|
+
destinationThreadId: {
|
|
108
|
+
type: string;
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
required: string[];
|
|
112
|
+
additionalProperties: false;
|
|
113
|
+
};
|
|
114
|
+
approvalSchema: undefined;
|
|
115
|
+
}, import('@tanstack/ai').ServerTool<{
|
|
116
|
+
type: string;
|
|
117
|
+
properties: {
|
|
118
|
+
checkpointId: {
|
|
119
|
+
type: string;
|
|
120
|
+
};
|
|
121
|
+
artifactId: {
|
|
122
|
+
type: string;
|
|
123
|
+
};
|
|
124
|
+
};
|
|
125
|
+
required: string[];
|
|
126
|
+
additionalProperties: false;
|
|
127
|
+
}, {
|
|
128
|
+
type: string;
|
|
129
|
+
properties: {
|
|
130
|
+
artifactId: {
|
|
131
|
+
type: string;
|
|
132
|
+
};
|
|
133
|
+
name: {
|
|
134
|
+
type: string;
|
|
135
|
+
};
|
|
136
|
+
mimeType: {
|
|
137
|
+
type: string;
|
|
138
|
+
};
|
|
139
|
+
size: {
|
|
140
|
+
type: string;
|
|
141
|
+
};
|
|
142
|
+
createdAt: {
|
|
143
|
+
type: string;
|
|
144
|
+
};
|
|
145
|
+
};
|
|
146
|
+
required: string[];
|
|
147
|
+
additionalProperties: false;
|
|
148
|
+
}, "read_sandbox_snapshot_artifact", unknown, false, undefined> & {
|
|
149
|
+
inputSchema: {
|
|
150
|
+
type: string;
|
|
151
|
+
properties: {
|
|
152
|
+
checkpointId: {
|
|
153
|
+
type: string;
|
|
154
|
+
};
|
|
155
|
+
artifactId: {
|
|
156
|
+
type: string;
|
|
157
|
+
};
|
|
158
|
+
};
|
|
159
|
+
required: string[];
|
|
160
|
+
additionalProperties: false;
|
|
161
|
+
};
|
|
162
|
+
outputSchema: {
|
|
163
|
+
type: string;
|
|
164
|
+
properties: {
|
|
165
|
+
artifactId: {
|
|
166
|
+
type: string;
|
|
167
|
+
};
|
|
168
|
+
name: {
|
|
169
|
+
type: string;
|
|
170
|
+
};
|
|
171
|
+
mimeType: {
|
|
172
|
+
type: string;
|
|
173
|
+
};
|
|
174
|
+
size: {
|
|
175
|
+
type: string;
|
|
176
|
+
};
|
|
177
|
+
createdAt: {
|
|
178
|
+
type: string;
|
|
179
|
+
};
|
|
180
|
+
};
|
|
181
|
+
required: string[];
|
|
182
|
+
additionalProperties: false;
|
|
183
|
+
};
|
|
184
|
+
approvalSchema: undefined;
|
|
185
|
+
}];
|