zeitlich 0.2.15 → 0.2.16
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 +50 -0
- package/dist/adapters/sandbox/daytona/index.cjs +52 -23
- package/dist/adapters/sandbox/daytona/index.cjs.map +1 -1
- package/dist/adapters/sandbox/daytona/index.d.cts +10 -2
- package/dist/adapters/sandbox/daytona/index.d.ts +10 -2
- package/dist/adapters/sandbox/daytona/index.js +52 -23
- package/dist/adapters/sandbox/daytona/index.js.map +1 -1
- package/dist/adapters/sandbox/inmemory/index.cjs +21 -16
- package/dist/adapters/sandbox/inmemory/index.cjs.map +1 -1
- package/dist/adapters/sandbox/inmemory/index.d.cts +1 -1
- package/dist/adapters/sandbox/inmemory/index.d.ts +1 -1
- package/dist/adapters/sandbox/inmemory/index.js +21 -16
- package/dist/adapters/sandbox/inmemory/index.js.map +1 -1
- package/dist/adapters/sandbox/virtual/index.cjs +38 -38
- package/dist/adapters/sandbox/virtual/index.cjs.map +1 -1
- package/dist/adapters/sandbox/virtual/index.d.cts +6 -6
- package/dist/adapters/sandbox/virtual/index.d.ts +6 -6
- package/dist/adapters/sandbox/virtual/index.js +37 -37
- package/dist/adapters/sandbox/virtual/index.js.map +1 -1
- package/dist/adapters/thread/google-genai/index.d.cts +2 -2
- package/dist/adapters/thread/google-genai/index.d.ts +2 -2
- package/dist/adapters/thread/langchain/index.d.cts +2 -2
- package/dist/adapters/thread/langchain/index.d.ts +2 -2
- package/dist/index.cjs +2 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +2 -3
- package/dist/index.js.map +1 -1
- package/dist/{types-CDubRtad.d.cts → types-BMRzfELQ.d.cts} +2 -0
- package/dist/{types-CDubRtad.d.ts → types-BMRzfELQ.d.ts} +2 -0
- package/dist/{types-CwwgQ_9H.d.ts → types-BSOte_8s.d.ts} +6 -2
- package/dist/{types-BVP87m_W.d.cts → types-DCi2qXjN.d.cts} +6 -2
- package/dist/{types-Dje1TdH6.d.cts → types-Drli9aCK.d.cts} +1 -1
- package/dist/{types-BWvIYK28.d.ts → types-XPtivmSJ.d.ts} +1 -1
- package/dist/workflow.cjs +2 -3
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +6 -6
- package/dist/workflow.d.ts +6 -6
- package/dist/workflow.js +2 -3
- package/dist/workflow.js.map +1 -1
- package/package.json +1 -1
- package/src/adapters/sandbox/daytona/filesystem.ts +43 -19
- package/src/adapters/sandbox/daytona/index.ts +16 -3
- package/src/adapters/sandbox/daytona/types.ts +4 -0
- package/src/adapters/sandbox/inmemory/index.ts +22 -16
- package/src/adapters/sandbox/virtual/filesystem.ts +29 -31
- package/src/adapters/sandbox/virtual/index.ts +5 -3
- package/src/adapters/sandbox/virtual/provider.ts +5 -2
- package/src/adapters/sandbox/virtual/types.ts +3 -0
- package/src/adapters/sandbox/virtual/with-virtual-sandbox.ts +4 -3
- package/src/lib/sandbox/tree.integration.test.ts +153 -0
- package/src/lib/sandbox/types.ts +2 -0
- package/src/lib/session/session-edge-cases.integration.test.ts +962 -0
- package/src/lib/session/session.integration.test.ts +852 -0
- package/src/lib/session/session.ts +5 -4
- package/src/lib/skills/skills.integration.test.ts +308 -0
- package/src/lib/state/manager.integration.test.ts +342 -0
- package/src/lib/subagent/subagent.integration.test.ts +467 -0
- package/src/lib/thread/id.test.ts +50 -0
- package/src/lib/tool-router/auto-append-sandbox.integration.test.ts +344 -0
- package/src/lib/tool-router/router-edge-cases.integration.test.ts +623 -0
- package/src/lib/tool-router/router.integration.test.ts +699 -0
- package/src/lib/types.test.ts +29 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ApplicationFailure } from '@temporalio/common';
|
|
2
|
+
import { posix } from 'path';
|
|
2
3
|
import { uuid4 } from '@temporalio/workflow';
|
|
3
4
|
import { Context } from '@temporalio/activity';
|
|
4
5
|
|
|
@@ -12,23 +13,18 @@ var SandboxNotSupportedError = class extends ApplicationFailure {
|
|
|
12
13
|
);
|
|
13
14
|
}
|
|
14
15
|
};
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
function normalisePath(p) {
|
|
18
|
-
if (!p.startsWith("/")) p = "/" + p;
|
|
19
|
-
p = p.replace(/\/+/g, "/");
|
|
20
|
-
if (p.length > 1 && p.endsWith("/")) p = p.slice(0, -1);
|
|
21
|
-
return p;
|
|
16
|
+
function normalisePath(p, workspaceBase = "/") {
|
|
17
|
+
return posix.resolve(workspaceBase, p);
|
|
22
18
|
}
|
|
23
19
|
function parentDir(p) {
|
|
24
20
|
const idx = p.lastIndexOf("/");
|
|
25
21
|
return idx <= 0 ? "/" : p.slice(0, idx);
|
|
26
22
|
}
|
|
27
|
-
function inferDirectories(entries) {
|
|
23
|
+
function inferDirectories(entries, workspaceBase) {
|
|
28
24
|
const dirs = /* @__PURE__ */ new Set();
|
|
29
25
|
dirs.add("/");
|
|
30
26
|
for (const entry of entries) {
|
|
31
|
-
let dir = parentDir(normalisePath(entry.path));
|
|
27
|
+
let dir = parentDir(normalisePath(entry.path, workspaceBase));
|
|
32
28
|
while (dir !== "/" && !dirs.has(dir)) {
|
|
33
29
|
dirs.add(dir);
|
|
34
30
|
dir = parentDir(dir);
|
|
@@ -38,14 +34,16 @@ function inferDirectories(entries) {
|
|
|
38
34
|
return dirs;
|
|
39
35
|
}
|
|
40
36
|
var VirtualSandboxFileSystem = class {
|
|
41
|
-
constructor(tree, resolver, ctx) {
|
|
37
|
+
constructor(tree, resolver, ctx, workspaceBase = "/") {
|
|
42
38
|
this.resolver = resolver;
|
|
43
39
|
this.ctx = ctx;
|
|
40
|
+
this.workspaceBase = normalisePath(workspaceBase);
|
|
44
41
|
this.entries = new Map(
|
|
45
|
-
tree.map((e) => [normalisePath(e.path), e])
|
|
42
|
+
tree.map((e) => [normalisePath(e.path, this.workspaceBase), e])
|
|
46
43
|
);
|
|
47
|
-
this.directories = inferDirectories(tree);
|
|
44
|
+
this.directories = inferDirectories(tree, this.workspaceBase);
|
|
48
45
|
}
|
|
46
|
+
workspaceBase;
|
|
49
47
|
entries;
|
|
50
48
|
directories;
|
|
51
49
|
mutations = [];
|
|
@@ -55,18 +53,18 @@ var VirtualSandboxFileSystem = class {
|
|
|
55
53
|
}
|
|
56
54
|
/** Look up a file entry by virtual path. */
|
|
57
55
|
getEntry(path) {
|
|
58
|
-
return this.entries.get(normalisePath(path));
|
|
56
|
+
return this.entries.get(normalisePath(path, this.workspaceBase));
|
|
59
57
|
}
|
|
60
58
|
// --------------------------------------------------------------------------
|
|
61
59
|
// Read operations — delegate to resolver lazily
|
|
62
60
|
// --------------------------------------------------------------------------
|
|
63
61
|
async readFile(path) {
|
|
64
|
-
const entry = this.entries.get(normalisePath(path));
|
|
62
|
+
const entry = this.entries.get(normalisePath(path, this.workspaceBase));
|
|
65
63
|
if (!entry) throw new Error(`ENOENT: no such file: ${path}`);
|
|
66
64
|
return this.resolver.readFile(entry.id, this.ctx);
|
|
67
65
|
}
|
|
68
66
|
async readFileBuffer(path) {
|
|
69
|
-
const entry = this.entries.get(normalisePath(path));
|
|
67
|
+
const entry = this.entries.get(normalisePath(path, this.workspaceBase));
|
|
70
68
|
if (!entry) throw new Error(`ENOENT: no such file: ${path}`);
|
|
71
69
|
return this.resolver.readFileBuffer(entry.id, this.ctx);
|
|
72
70
|
}
|
|
@@ -74,11 +72,11 @@ var VirtualSandboxFileSystem = class {
|
|
|
74
72
|
// Metadata operations — pure, resolved from the tree
|
|
75
73
|
// --------------------------------------------------------------------------
|
|
76
74
|
async exists(path) {
|
|
77
|
-
const norm = normalisePath(path);
|
|
75
|
+
const norm = normalisePath(path, this.workspaceBase);
|
|
78
76
|
return this.entries.has(norm) || this.directories.has(norm);
|
|
79
77
|
}
|
|
80
78
|
async stat(path) {
|
|
81
|
-
const norm = normalisePath(path);
|
|
79
|
+
const norm = normalisePath(path, this.workspaceBase);
|
|
82
80
|
const entry = this.entries.get(norm);
|
|
83
81
|
if (entry) {
|
|
84
82
|
return {
|
|
@@ -101,7 +99,7 @@ var VirtualSandboxFileSystem = class {
|
|
|
101
99
|
throw new Error(`ENOENT: no such file or directory: ${path}`);
|
|
102
100
|
}
|
|
103
101
|
async readdir(path) {
|
|
104
|
-
const norm = normalisePath(path);
|
|
102
|
+
const norm = normalisePath(path, this.workspaceBase);
|
|
105
103
|
if (!this.directories.has(norm)) {
|
|
106
104
|
throw new Error(`ENOENT: no such directory: ${path}`);
|
|
107
105
|
}
|
|
@@ -125,7 +123,7 @@ var VirtualSandboxFileSystem = class {
|
|
|
125
123
|
}
|
|
126
124
|
async readdirWithFileTypes(path) {
|
|
127
125
|
const names = await this.readdir(path);
|
|
128
|
-
const norm = normalisePath(path);
|
|
126
|
+
const norm = normalisePath(path, this.workspaceBase);
|
|
129
127
|
const prefix = norm === "/" ? "/" : norm + "/";
|
|
130
128
|
return names.map((name) => {
|
|
131
129
|
const full = prefix + name;
|
|
@@ -138,7 +136,7 @@ var VirtualSandboxFileSystem = class {
|
|
|
138
136
|
// Write operations — delegate to resolver, record mutations
|
|
139
137
|
// --------------------------------------------------------------------------
|
|
140
138
|
async writeFile(path, content) {
|
|
141
|
-
const norm = normalisePath(path);
|
|
139
|
+
const norm = normalisePath(path, this.workspaceBase);
|
|
142
140
|
const existing = this.entries.get(norm);
|
|
143
141
|
if (existing) {
|
|
144
142
|
await this.resolver.writeFile(existing.id, content, this.ctx);
|
|
@@ -159,7 +157,7 @@ var VirtualSandboxFileSystem = class {
|
|
|
159
157
|
}
|
|
160
158
|
}
|
|
161
159
|
async appendFile(path, content) {
|
|
162
|
-
const norm = normalisePath(path);
|
|
160
|
+
const norm = normalisePath(path, this.workspaceBase);
|
|
163
161
|
const existing = this.entries.get(norm);
|
|
164
162
|
if (!existing) {
|
|
165
163
|
return this.writeFile(path, content);
|
|
@@ -177,7 +175,7 @@ var VirtualSandboxFileSystem = class {
|
|
|
177
175
|
this.mutations.push({ type: "update", path: norm, entry: updated });
|
|
178
176
|
}
|
|
179
177
|
async mkdir(_path, _options) {
|
|
180
|
-
const norm = normalisePath(_path);
|
|
178
|
+
const norm = normalisePath(_path, this.workspaceBase);
|
|
181
179
|
if (this.directories.has(norm)) return;
|
|
182
180
|
if (_options?.recursive) {
|
|
183
181
|
this.addParentDirectories(norm + "/placeholder");
|
|
@@ -191,7 +189,7 @@ var VirtualSandboxFileSystem = class {
|
|
|
191
189
|
}
|
|
192
190
|
}
|
|
193
191
|
async rm(path, options) {
|
|
194
|
-
const norm = normalisePath(path);
|
|
192
|
+
const norm = normalisePath(path, this.workspaceBase);
|
|
195
193
|
const entry = this.entries.get(norm);
|
|
196
194
|
if (entry) {
|
|
197
195
|
await this.resolver.deleteFile(entry.id, this.ctx);
|
|
@@ -222,8 +220,8 @@ var VirtualSandboxFileSystem = class {
|
|
|
222
220
|
}
|
|
223
221
|
}
|
|
224
222
|
async cp(src, dest, _options) {
|
|
225
|
-
const normSrc = normalisePath(src);
|
|
226
|
-
const normDest = normalisePath(dest);
|
|
223
|
+
const normSrc = normalisePath(src, this.workspaceBase);
|
|
224
|
+
const normDest = normalisePath(dest, this.workspaceBase);
|
|
227
225
|
const entry = this.entries.get(normSrc);
|
|
228
226
|
if (entry) {
|
|
229
227
|
const content = await this.resolver.readFile(entry.id, this.ctx);
|
|
@@ -256,15 +254,13 @@ var VirtualSandboxFileSystem = class {
|
|
|
256
254
|
throw new SandboxNotSupportedError("readlink");
|
|
257
255
|
}
|
|
258
256
|
resolvePath(base, path) {
|
|
259
|
-
|
|
260
|
-
const combined = base.endsWith("/") ? base + path : base + "/" + path;
|
|
261
|
-
return normalisePath(combined);
|
|
257
|
+
return posix.resolve(normalisePath(base, this.workspaceBase), path);
|
|
262
258
|
}
|
|
263
259
|
// --------------------------------------------------------------------------
|
|
264
260
|
// Helpers
|
|
265
261
|
// --------------------------------------------------------------------------
|
|
266
262
|
addParentDirectories(filePath) {
|
|
267
|
-
let dir = parentDir(normalisePath(filePath));
|
|
263
|
+
let dir = parentDir(normalisePath(filePath, this.workspaceBase));
|
|
268
264
|
while (!this.directories.has(dir)) {
|
|
269
265
|
this.directories.add(dir);
|
|
270
266
|
dir = parentDir(dir);
|
|
@@ -302,18 +298,21 @@ var VirtualSandboxProvider = class {
|
|
|
302
298
|
const fileTree = await this.resolver.resolveEntries(
|
|
303
299
|
options.resolverContext
|
|
304
300
|
);
|
|
301
|
+
const workspaceBase = options.workspaceBase ?? "/";
|
|
305
302
|
const sandbox = createVirtualSandbox(
|
|
306
303
|
sandboxId,
|
|
307
304
|
fileTree,
|
|
308
305
|
this.resolver,
|
|
309
|
-
options.resolverContext
|
|
306
|
+
options.resolverContext,
|
|
307
|
+
workspaceBase
|
|
310
308
|
);
|
|
311
309
|
return {
|
|
312
310
|
sandbox,
|
|
313
311
|
stateUpdate: {
|
|
314
312
|
sandboxId,
|
|
315
313
|
fileTree,
|
|
316
|
-
resolverContext: options.resolverContext
|
|
314
|
+
resolverContext: options.resolverContext,
|
|
315
|
+
workspaceBase
|
|
317
316
|
}
|
|
318
317
|
};
|
|
319
318
|
}
|
|
@@ -348,7 +347,7 @@ async function queryParentWorkflowState(client) {
|
|
|
348
347
|
function withVirtualSandbox(client, provider, handler) {
|
|
349
348
|
return async (args, context) => {
|
|
350
349
|
const state = await queryParentWorkflowState(client);
|
|
351
|
-
const { sandboxId, fileTree, resolverContext } = state;
|
|
350
|
+
const { sandboxId, fileTree, resolverContext, workspaceBase } = state;
|
|
352
351
|
if (!fileTree || !sandboxId) {
|
|
353
352
|
return {
|
|
354
353
|
toolResponse: `Error: No fileTree/sandboxId in agent state. The ${context.toolName} tool requires a virtual sandbox.`,
|
|
@@ -359,7 +358,8 @@ function withVirtualSandbox(client, provider, handler) {
|
|
|
359
358
|
sandboxId,
|
|
360
359
|
fileTree,
|
|
361
360
|
provider.resolver,
|
|
362
|
-
resolverContext
|
|
361
|
+
resolverContext,
|
|
362
|
+
workspaceBase ?? "/"
|
|
363
363
|
);
|
|
364
364
|
const response = await handler(args, { ...context, sandbox });
|
|
365
365
|
const mutations = sandbox.fs.getMutations();
|
|
@@ -375,9 +375,9 @@ function withVirtualSandbox(client, provider, handler) {
|
|
|
375
375
|
|
|
376
376
|
// src/adapters/sandbox/virtual/index.ts
|
|
377
377
|
var VirtualSandboxImpl = class {
|
|
378
|
-
constructor(id, tree, resolver, ctx) {
|
|
378
|
+
constructor(id, tree, resolver, ctx, workspaceBase = "/") {
|
|
379
379
|
this.id = id;
|
|
380
|
-
this.fs = new VirtualSandboxFileSystem(tree, resolver, ctx);
|
|
380
|
+
this.fs = new VirtualSandboxFileSystem(tree, resolver, ctx, workspaceBase);
|
|
381
381
|
}
|
|
382
382
|
capabilities = {
|
|
383
383
|
filesystem: true,
|
|
@@ -391,8 +391,8 @@ var VirtualSandboxImpl = class {
|
|
|
391
391
|
async destroy() {
|
|
392
392
|
}
|
|
393
393
|
};
|
|
394
|
-
function createVirtualSandbox(id, tree, resolver, ctx) {
|
|
395
|
-
return new VirtualSandboxImpl(id, tree, resolver, ctx);
|
|
394
|
+
function createVirtualSandbox(id, tree, resolver, ctx, workspaceBase = "/") {
|
|
395
|
+
return new VirtualSandboxImpl(id, tree, resolver, ctx, workspaceBase);
|
|
396
396
|
}
|
|
397
397
|
|
|
398
398
|
export { VirtualSandboxFileSystem, VirtualSandboxProvider, createVirtualSandbox, withVirtualSandbox };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/sandbox/types.ts","../../../../src/adapters/sandbox/virtual/filesystem.ts","../../../../src/lib/thread/id.ts","../../../../src/adapters/sandbox/virtual/provider.ts","../../../../src/lib/activity.ts","../../../../src/adapters/sandbox/virtual/with-virtual-sandbox.ts","../../../../src/adapters/sandbox/virtual/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["// ============================================================================\n// Sandbox Filesystem\n// ============================================================================\n\nexport interface DirentEntry {\n name: string;\n isFile: boolean;\n isDirectory: boolean;\n isSymbolicLink: boolean;\n}\n\nexport interface FileStat {\n isFile: boolean;\n isDirectory: boolean;\n isSymbolicLink: boolean;\n size: number;\n mtime: Date;\n}\n\n/**\n * Provider-agnostic filesystem interface.\n *\n * Implementations that don't support a method should throw\n * {@link SandboxNotSupportedError}.\n */\nexport interface SandboxFileSystem {\n readFile(path: string): Promise<string>;\n readFileBuffer(path: string): Promise<Uint8Array>;\n writeFile(path: string, content: string | Uint8Array): Promise<void>;\n appendFile(path: string, content: string | Uint8Array): Promise<void>;\n exists(path: string): Promise<boolean>;\n stat(path: string): Promise<FileStat>;\n mkdir(path: string, options?: { recursive?: boolean }): Promise<void>;\n readdir(path: string): Promise<string[]>;\n readdirWithFileTypes(path: string): Promise<DirentEntry[]>;\n rm(path: string, options?: { recursive?: boolean; force?: boolean }): Promise<void>;\n cp(src: string, dest: string, options?: { recursive?: boolean }): Promise<void>;\n mv(src: string, dest: string): Promise<void>;\n readlink(path: string): Promise<string>;\n resolvePath(base: string, path: string): string;\n}\n\n// ============================================================================\n// Execution\n// ============================================================================\n\nexport interface ExecOptions {\n timeout?: number;\n cwd?: string;\n env?: Record<string, string>;\n}\n\nexport interface ExecResult {\n exitCode: number;\n stdout: string;\n stderr: string;\n}\n\n// ============================================================================\n// Capabilities\n// ============================================================================\n\nexport interface SandboxCapabilities {\n /** Sandbox supports filesystem operations */\n filesystem: boolean;\n /** Sandbox supports shell/command execution */\n execution: boolean;\n /** Sandbox state can be persisted and restored */\n persistence: boolean;\n}\n\n// ============================================================================\n// Sandbox\n// ============================================================================\n\nexport interface Sandbox {\n readonly id: string;\n readonly capabilities: SandboxCapabilities;\n readonly fs: SandboxFileSystem;\n\n exec(command: string, options?: ExecOptions): Promise<ExecResult>;\n destroy(): Promise<void>;\n}\n\n// ============================================================================\n// Snapshots\n// ============================================================================\n\nexport interface SandboxSnapshot {\n sandboxId: string;\n providerId: string;\n /** Provider-specific serialised state */\n data: unknown;\n createdAt: string;\n}\n\n// ============================================================================\n// Provider\n// ============================================================================\n\nexport interface SandboxCreateOptions {\n /** Preferred sandbox ID (provider may ignore) */\n id?: string;\n /** Seed the filesystem with these files */\n initialFiles?: Record<string, string | Uint8Array>;\n /** Environment variables available inside the sandbox */\n env?: Record<string, string>;\n}\n\nexport interface SandboxCreateResult {\n sandbox: Sandbox;\n /** Optional state to merge into the workflow's `AgentState` via the session. */\n stateUpdate?: Record<string, unknown>;\n}\n\nexport interface SandboxProvider<\n TOptions extends SandboxCreateOptions = SandboxCreateOptions,\n TSandbox extends Sandbox = Sandbox,\n> {\n readonly id: string;\n readonly capabilities: SandboxCapabilities;\n\n create(options?: TOptions): Promise<SandboxCreateResult>;\n get(sandboxId: string): Promise<TSandbox>;\n destroy(sandboxId: string): Promise<void>;\n snapshot(sandboxId: string): Promise<SandboxSnapshot>;\n restore(snapshot: SandboxSnapshot): Promise<Sandbox>;\n}\n\n// ============================================================================\n// SandboxOps — workflow-side activity interface (like ThreadOps)\n// ============================================================================\n\nexport interface SandboxOps<\n TOptions extends SandboxCreateOptions = SandboxCreateOptions,\n> {\n createSandbox(\n options?: TOptions,\n ): Promise<{ sandboxId: string; stateUpdate?: Record<string, unknown> }>;\n destroySandbox(sandboxId: string): Promise<void>;\n snapshotSandbox(sandboxId: string): Promise<SandboxSnapshot>;\n}\n\n// ============================================================================\n// Errors\n// ============================================================================\n\nimport { ApplicationFailure } from \"@temporalio/common\";\n\nexport class SandboxNotSupportedError extends ApplicationFailure {\n constructor(operation: string) {\n super(\n `Sandbox does not support: ${operation}`,\n \"SandboxNotSupportedError\",\n true,\n );\n }\n}\n\nexport class SandboxNotFoundError extends ApplicationFailure {\n constructor(sandboxId: string) {\n super(`Sandbox not found: ${sandboxId}`, \"SandboxNotFoundError\", true);\n }\n}\n","import type {\n SandboxFileSystem,\n DirentEntry,\n FileStat,\n} from \"../../../lib/sandbox/types\";\nimport { SandboxNotSupportedError } from \"../../../lib/sandbox/types\";\nimport type {\n FileEntry,\n FileEntryMetadata,\n FileResolver,\n TreeMutation,\n} from \"./types\";\n\n/**\n * Normalise a virtual path to a canonical form: absolute, no trailing slash\n * (except root), no double slashes.\n */\nfunction normalisePath(p: string): string {\n if (!p.startsWith(\"/\")) p = \"/\" + p;\n p = p.replace(/\\/+/g, \"/\");\n if (p.length > 1 && p.endsWith(\"/\")) p = p.slice(0, -1);\n return p;\n}\n\n/** Return the parent directory of a normalised path (\"/a/b\" → \"/a\"). */\nfunction parentDir(p: string): string {\n const idx = p.lastIndexOf(\"/\");\n return idx <= 0 ? \"/\" : p.slice(0, idx);\n}\n\n/**\n * Collect the set of implicit directory paths from a flat file list.\n * E.g. \"/a/b/c.ts\" contributes \"/a/b\", \"/a\", \"/\".\n */\nfunction inferDirectories(entries: { path: string }[]): Set<string> {\n const dirs = new Set<string>();\n dirs.add(\"/\");\n for (const entry of entries) {\n let dir = parentDir(normalisePath(entry.path));\n while (dir !== \"/\" && !dirs.has(dir)) {\n dirs.add(dir);\n dir = parentDir(dir);\n }\n dirs.add(\"/\");\n }\n return dirs;\n}\n\n/**\n * Ephemeral {@link SandboxFileSystem} backed by a {@link FileResolver}.\n *\n * Created fresh for each tool invocation from the current workflow file tree.\n * Directory structure is inferred from file paths. All mutations are tracked\n * and can be retrieved via {@link getMutations} after the handler completes.\n */\nexport class VirtualSandboxFileSystem<\n TCtx = unknown,\n TMeta = FileEntryMetadata,\n> implements SandboxFileSystem\n{\n private entries: Map<string, FileEntry<TMeta>>;\n private directories: Set<string>;\n private mutations: TreeMutation<TMeta>[] = [];\n\n constructor(\n tree: FileEntry<TMeta>[],\n private resolver: FileResolver<TCtx, TMeta>,\n private ctx: TCtx,\n ) {\n this.entries = new Map(\n tree.map((e) => [normalisePath(e.path), e]),\n );\n this.directories = inferDirectories(tree);\n }\n\n /** Return all mutations accumulated during this invocation. */\n getMutations(): TreeMutation<TMeta>[] {\n return this.mutations;\n }\n\n /** Look up a file entry by virtual path. */\n getEntry(path: string): FileEntry<TMeta> | undefined {\n return this.entries.get(normalisePath(path));\n }\n\n // --------------------------------------------------------------------------\n // Read operations — delegate to resolver lazily\n // --------------------------------------------------------------------------\n\n async readFile(path: string): Promise<string> {\n const entry = this.entries.get(normalisePath(path));\n if (!entry) throw new Error(`ENOENT: no such file: ${path}`);\n return this.resolver.readFile(entry.id, this.ctx);\n }\n\n async readFileBuffer(path: string): Promise<Uint8Array> {\n const entry = this.entries.get(normalisePath(path));\n if (!entry) throw new Error(`ENOENT: no such file: ${path}`);\n return this.resolver.readFileBuffer(entry.id, this.ctx);\n }\n\n // --------------------------------------------------------------------------\n // Metadata operations — pure, resolved from the tree\n // --------------------------------------------------------------------------\n\n async exists(path: string): Promise<boolean> {\n const norm = normalisePath(path);\n return this.entries.has(norm) || this.directories.has(norm);\n }\n\n async stat(path: string): Promise<FileStat> {\n const norm = normalisePath(path);\n const entry = this.entries.get(norm);\n if (entry) {\n return {\n isFile: true,\n isDirectory: false,\n isSymbolicLink: false,\n size: entry.size,\n mtime: new Date(entry.mtime),\n };\n }\n if (this.directories.has(norm)) {\n return {\n isFile: false,\n isDirectory: true,\n isSymbolicLink: false,\n size: 0,\n mtime: new Date(),\n };\n }\n throw new Error(`ENOENT: no such file or directory: ${path}`);\n }\n\n async readdir(path: string): Promise<string[]> {\n const norm = normalisePath(path);\n if (!this.directories.has(norm)) {\n throw new Error(`ENOENT: no such directory: ${path}`);\n }\n const prefix = norm === \"/\" ? \"/\" : norm + \"/\";\n const names = new Set<string>();\n\n for (const p of this.entries.keys()) {\n if (p.startsWith(prefix)) {\n const rest = p.slice(prefix.length);\n const seg = rest.split(\"/\")[0];\n if (seg) names.add(seg);\n }\n }\n for (const d of this.directories) {\n if (d.startsWith(prefix) && d !== norm) {\n const rest = d.slice(prefix.length);\n const seg = rest.split(\"/\")[0];\n if (seg) names.add(seg);\n }\n }\n return [...names].sort();\n }\n\n async readdirWithFileTypes(path: string): Promise<DirentEntry[]> {\n const names = await this.readdir(path);\n const norm = normalisePath(path);\n const prefix = norm === \"/\" ? \"/\" : norm + \"/\";\n\n return names.map((name) => {\n const full = prefix + name;\n const isFile = this.entries.has(full);\n const isDirectory = this.directories.has(full);\n return { name, isFile, isDirectory, isSymbolicLink: false };\n });\n }\n\n // --------------------------------------------------------------------------\n // Write operations — delegate to resolver, record mutations\n // --------------------------------------------------------------------------\n\n async writeFile(path: string, content: string | Uint8Array): Promise<void> {\n const norm = normalisePath(path);\n const existing = this.entries.get(norm);\n\n if (existing) {\n await this.resolver.writeFile(existing.id, content, this.ctx);\n const size =\n typeof content === \"string\"\n ? new TextEncoder().encode(content).byteLength\n : content.byteLength;\n const updated: FileEntry<TMeta> = {\n ...existing,\n size,\n mtime: new Date().toISOString(),\n };\n this.entries.set(norm, updated);\n this.mutations.push({ type: \"update\", path: norm, entry: updated });\n } else {\n const entry = await this.resolver.createFile(norm, content, this.ctx);\n const normalised = { ...entry, path: norm };\n this.entries.set(norm, normalised);\n this.addParentDirectories(norm);\n this.mutations.push({ type: \"add\", entry: normalised });\n }\n }\n\n async appendFile(path: string, content: string | Uint8Array): Promise<void> {\n const norm = normalisePath(path);\n const existing = this.entries.get(norm);\n\n if (!existing) {\n return this.writeFile(path, content);\n }\n\n const current = await this.resolver.readFile(existing.id, this.ctx);\n const appended =\n typeof content === \"string\"\n ? current + content\n : current + new TextDecoder().decode(content);\n await this.resolver.writeFile(existing.id, appended, this.ctx);\n\n const size = new TextEncoder().encode(appended).byteLength;\n const updated: FileEntry<TMeta> = {\n ...existing,\n size,\n mtime: new Date().toISOString(),\n };\n this.entries.set(norm, updated);\n this.mutations.push({ type: \"update\", path: norm, entry: updated });\n }\n\n async mkdir(_path: string, _options?: { recursive?: boolean }): Promise<void> {\n const norm = normalisePath(_path);\n if (this.directories.has(norm)) return;\n\n if (_options?.recursive) {\n this.addParentDirectories(norm + \"/placeholder\");\n this.directories.add(norm);\n } else {\n const parent = parentDir(norm);\n if (!this.directories.has(parent)) {\n throw new Error(`ENOENT: no such directory: ${parent}`);\n }\n this.directories.add(norm);\n }\n }\n\n async rm(\n path: string,\n options?: { recursive?: boolean; force?: boolean },\n ): Promise<void> {\n const norm = normalisePath(path);\n const entry = this.entries.get(norm);\n\n if (entry) {\n await this.resolver.deleteFile(entry.id, this.ctx);\n this.entries.delete(norm);\n this.mutations.push({ type: \"remove\", path: norm });\n return;\n }\n\n if (this.directories.has(norm)) {\n if (!options?.recursive) {\n throw new Error(`EISDIR: is a directory (use recursive): ${path}`);\n }\n const prefix = norm === \"/\" ? \"/\" : norm + \"/\";\n for (const [p, e] of this.entries) {\n if (p.startsWith(prefix)) {\n await this.resolver.deleteFile(e.id, this.ctx);\n this.entries.delete(p);\n this.mutations.push({ type: \"remove\", path: p });\n }\n }\n for (const d of this.directories) {\n if (d.startsWith(prefix)) this.directories.delete(d);\n }\n this.directories.delete(norm);\n return;\n }\n\n if (!options?.force) {\n throw new Error(`ENOENT: no such file or directory: ${path}`);\n }\n }\n\n async cp(\n src: string,\n dest: string,\n _options?: { recursive?: boolean },\n ): Promise<void> {\n const normSrc = normalisePath(src);\n const normDest = normalisePath(dest);\n\n const entry = this.entries.get(normSrc);\n if (entry) {\n const content = await this.resolver.readFile(entry.id, this.ctx);\n await this.writeFile(normDest, content);\n return;\n }\n\n if (!this.directories.has(normSrc)) {\n throw new Error(`ENOENT: no such file or directory: ${src}`);\n }\n if (!_options?.recursive) {\n throw new Error(`EISDIR: is a directory (use recursive): ${src}`);\n }\n\n const prefix = normSrc === \"/\" ? \"/\" : normSrc + \"/\";\n for (const [p, e] of this.entries) {\n if (p.startsWith(prefix)) {\n const relative = p.slice(normSrc.length);\n const content = await this.resolver.readFile(e.id, this.ctx);\n await this.writeFile(normDest + relative, content);\n }\n }\n }\n\n async mv(src: string, dest: string): Promise<void> {\n await this.cp(src, dest, { recursive: true });\n await this.rm(src, { recursive: true });\n }\n\n // --------------------------------------------------------------------------\n // Unsupported\n // --------------------------------------------------------------------------\n\n async readlink(_path: string): Promise<string> {\n throw new SandboxNotSupportedError(\"readlink\");\n }\n\n resolvePath(base: string, path: string): string {\n if (path.startsWith(\"/\")) return normalisePath(path);\n const combined =\n base.endsWith(\"/\") ? base + path : base + \"/\" + path;\n return normalisePath(combined);\n }\n\n // --------------------------------------------------------------------------\n // Helpers\n // --------------------------------------------------------------------------\n\n private addParentDirectories(filePath: string): void {\n let dir = parentDir(normalisePath(filePath));\n while (!this.directories.has(dir)) {\n this.directories.add(dir);\n dir = parentDir(dir);\n }\n }\n}\n","import { uuid4 } from \"@temporalio/workflow\";\n\nconst BASE62 =\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n\n/**\n * Generate a compact, workflow-deterministic identifier.\n *\n * Uses Temporal's `uuid4()` internally (seeded by the workflow's RNG),\n * then re-encodes the hex bytes into a base-62 alphabet for a shorter,\n * more token-efficient identifier (~3 tokens vs ~10 for a full UUID).\n *\n * Suitable for thread IDs, child workflow IDs, or any workflow-scoped identifier.\n *\n * @param length - Number of base-62 characters (default 12, ~71 bits of entropy)\n */\nexport function getShortId(length = 12): string {\n const hex = uuid4().replace(/-/g, \"\");\n let result = \"\";\n for (let i = 0; i < length; i++) {\n const byte = parseInt(hex.slice(i * 2, i * 2 + 2), 16);\n result += BASE62[byte % BASE62.length];\n }\n return result;\n}\n","import type {\n SandboxCapabilities,\n SandboxCreateResult,\n SandboxProvider,\n} from \"../../../lib/sandbox/types\";\nimport { SandboxNotSupportedError } from \"../../../lib/sandbox/types\";\nimport { getShortId } from \"../../../lib/thread/id\";\nimport { createVirtualSandbox } from \"./index\";\nimport type {\n FileEntryMetadata,\n FileResolver,\n VirtualSandboxCreateOptions,\n} from \"./types\";\n\n/**\n * Stateless {@link SandboxProvider} backed by a {@link FileResolver}.\n *\n * The provider holds **no internal state**. All sandbox state (sandboxId,\n * fileTree, resolverContext) is returned as a `stateUpdate` from\n * {@link create} and merged into the workflow's `AgentState` by the session.\n * {@link withVirtualSandbox} reads this state back on every tool invocation.\n *\n * @example\n * ```typescript\n * const provider = new VirtualSandboxProvider(resolver);\n * const manager = new SandboxManager(provider);\n *\n * export const activities = {\n * ...manager.createActivities(),\n * readFile: withVirtualSandbox(client, provider, readHandler),\n * };\n * ```\n */\nexport class VirtualSandboxProvider<\n TCtx = unknown,\n TMeta = FileEntryMetadata,\n> implements SandboxProvider<VirtualSandboxCreateOptions<TCtx>> {\n readonly id = \"virtual\";\n readonly capabilities: SandboxCapabilities = {\n filesystem: true,\n execution: false,\n persistence: true,\n };\n\n readonly resolver: FileResolver<TCtx, TMeta>;\n\n constructor(resolver: FileResolver<TCtx, TMeta>) {\n this.resolver = resolver;\n }\n\n async create(\n options?: VirtualSandboxCreateOptions<TCtx>\n ): Promise<SandboxCreateResult> {\n if (!options || !(\"resolverContext\" in options)) {\n throw new Error(\"VirtualSandboxProvider.create requires resolverContext\");\n }\n\n const sandboxId = options.id ?? getShortId();\n const fileTree = await this.resolver.resolveEntries(\n options.resolverContext\n );\n\n const sandbox = createVirtualSandbox(\n sandboxId,\n fileTree,\n this.resolver,\n options.resolverContext\n );\n\n return {\n sandbox,\n stateUpdate: {\n sandboxId,\n fileTree,\n resolverContext: options.resolverContext,\n },\n };\n }\n\n async get(): Promise<never> {\n throw new SandboxNotSupportedError(\n \"get (virtual sandbox state lives in workflow AgentState)\"\n );\n }\n\n async destroy(): Promise<void> {\n // No-op — no internal state to clean up\n }\n\n async snapshot(): Promise<never> {\n throw new SandboxNotSupportedError(\n \"snapshot (virtual sandbox state lives in workflow AgentState)\"\n );\n }\n\n async restore(): Promise<never> {\n throw new SandboxNotSupportedError(\n \"restore (virtual sandbox state lives in workflow AgentState)\"\n );\n }\n}\n","import { Context } from \"@temporalio/activity\";\nimport type { WorkflowClient } from \"@temporalio/client\";\nimport type { BaseAgentState, RunAgentConfig } from \"./types\";\nimport type {\n ActivityToolHandler,\n RouterContext,\n ToolHandlerResponse,\n} from \"./tool-router/types\";\n\n/**\n * Query the parent workflow's state from within an activity.\n * Resolves the workflow handle from the current activity context.\n */\nexport async function queryParentWorkflowState<T>(\n client: WorkflowClient\n): Promise<T> {\n const { workflowExecution } = Context.current().info;\n const handle = client.getHandle(\n workflowExecution.workflowId,\n workflowExecution.runId\n );\n return handle.query<T>(\"getAgentState\");\n}\n\n/**\n * Wraps a handler into a `RunAgentActivity` by auto-fetching the parent\n * workflow's agent state before each invocation.\n *\n * @example\n * ```typescript\n * import { createRunAgentActivity } from 'zeitlich';\n * import { createLangChainModelInvoker } from 'zeitlich/adapters/thread/langchain';\n *\n * const invoker = createLangChainModelInvoker({ redis, model });\n * return { runAgent: createRunAgentActivity(client, invoker) };\n * ```\n */\nexport function createRunAgentActivity<R, S extends BaseAgentState = BaseAgentState>(\n client: WorkflowClient,\n handler: (config: RunAgentConfig & { state: S }) => Promise<R>,\n): (config: RunAgentConfig) => Promise<R> {\n return async (config: RunAgentConfig) => {\n const state = await queryParentWorkflowState<S>(client);\n return handler({ ...config, state });\n };\n}\n\n/**\n * Context injected into tool handlers created via {@link withParentWorkflowState}.\n */\nexport interface AgentStateContext<S extends BaseAgentState = BaseAgentState> extends RouterContext {\n state: S;\n}\n\n/**\n * Wraps a tool handler into an `ActivityToolHandler` by auto-fetching the\n * parent workflow's agent state before each invocation.\n *\n * @typeParam S - Custom agent state type (defaults to `BaseAgentState`)\n *\n * @example\n * ```typescript\n * import { withParentWorkflowState, type AgentStateContext } from 'zeitlich';\n *\n * // With custom state:\n * interface MyState extends BaseAgentState { customField: string }\n * const myHandler = withParentWorkflowState<MyArgs, MyResult, MyState>(\n * client,\n * async (args, ctx) => {\n * console.log(ctx.state.customField);\n * return { toolResponse: 'done', data: null };\n * },\n * );\n * ```\n */\nexport function withParentWorkflowState<TArgs, TResult, S extends BaseAgentState = BaseAgentState>(\n client: WorkflowClient,\n handler: (\n args: TArgs,\n context: AgentStateContext<S>,\n ) => Promise<ToolHandlerResponse<TResult>>,\n): ActivityToolHandler<TArgs, TResult> {\n return async (args, context) => {\n const state = await queryParentWorkflowState<S>(client);\n return handler(args, { ...context, state });\n };\n}\n","import type { WorkflowClient } from \"@temporalio/client\";\nimport { queryParentWorkflowState } from \"../../../lib/activity\";\nimport type { ActivityToolHandler } from \"../../../lib/tool-router/types\";\nimport type {\n FileEntryMetadata,\n TreeMutation,\n VirtualSandboxContext,\n VirtualSandboxState,\n} from \"./types\";\nimport type { VirtualSandboxProvider } from \"./provider\";\nimport { createVirtualSandbox } from \"./index\";\n\n/**\n * Wraps a tool handler that needs a virtual sandbox, automatically querying\n * the parent workflow for the current file tree and resolver context.\n *\n * On each invocation the wrapper:\n * 1. Queries the workflow's `AgentState` for `fileTree` and `resolverContext`\n * 2. Creates an ephemeral {@link VirtualSandbox} from tree + provider's resolver\n * 3. Runs the inner handler\n * 4. Returns the handler's result together with any {@link TreeMutation}s\n *\n * The consumer applies mutations back to workflow state via a post-tool hook.\n *\n * @param client - Temporal `WorkflowClient` for querying the parent workflow\n * @param agentName - Agent name (used to derive the state query name)\n * @param provider - {@link VirtualSandboxProvider} (wraps the resolver)\n * @param handler - Inner handler expecting a {@link VirtualSandboxContext}\n *\n * @example\n * ```typescript\n * import { withVirtualSandbox, type VirtualSandboxContext } from 'zeitlich';\n *\n * const readHandler: ActivityToolHandler<FileReadArgs, ReadResult, VirtualSandboxContext> =\n * async (args, { sandbox }) => {\n * const content = await sandbox.fs.readFile(args.path);\n * return { toolResponse: content, data: { path: args.path, content } };\n * };\n *\n * // At activity registration:\n * const provider = new VirtualSandboxProvider(resolver);\n * const handler = withVirtualSandbox(client, \"myAgent\", provider, readHandler);\n * ```\n */\nexport function withVirtualSandbox<\n TArgs,\n TResult,\n TCtx,\n TMeta = FileEntryMetadata,\n>(\n client: WorkflowClient,\n provider: VirtualSandboxProvider<TCtx, TMeta>,\n handler: ActivityToolHandler<\n TArgs,\n TResult,\n VirtualSandboxContext<TCtx, TMeta>\n >\n): ActivityToolHandler<\n TArgs,\n (TResult & { treeMutations: TreeMutation<TMeta>[] }) | null\n> {\n return async (args, context) => {\n const state =\n await queryParentWorkflowState<VirtualSandboxState<TCtx, TMeta>>(client);\n\n const { sandboxId, fileTree, resolverContext } = state;\n if (!fileTree || !sandboxId) {\n return {\n toolResponse: `Error: No fileTree/sandboxId in agent state. The ${context.toolName} tool requires a virtual sandbox.`,\n data: null,\n };\n }\n\n const sandbox = createVirtualSandbox(\n sandboxId,\n fileTree,\n provider.resolver,\n resolverContext\n );\n const response = await handler(args, { ...context, sandbox });\n const mutations = sandbox.fs.getMutations();\n\n return {\n toolResponse: response.toolResponse,\n data: {\n ...(response.data ?? {}),\n treeMutations: mutations,\n } as TResult & { treeMutations: TreeMutation<TMeta>[] },\n };\n };\n}\n","import type {\n Sandbox,\n SandboxCapabilities,\n ExecOptions,\n ExecResult,\n} from \"../../../lib/sandbox/types\";\nimport { SandboxNotSupportedError } from \"../../../lib/sandbox/types\";\nimport { VirtualSandboxFileSystem } from \"./filesystem\";\nimport type {\n FileEntry,\n FileEntryMetadata,\n FileResolver,\n VirtualSandbox,\n} from \"./types\";\n\n// ============================================================================\n// VirtualSandbox\n// ============================================================================\n\nclass VirtualSandboxImpl<\n TCtx = unknown,\n TMeta = FileEntryMetadata,\n> implements Sandbox\n{\n readonly capabilities: SandboxCapabilities = {\n filesystem: true,\n execution: false,\n persistence: true,\n };\n\n readonly fs: VirtualSandboxFileSystem<TCtx, TMeta>;\n\n constructor(\n readonly id: string,\n tree: FileEntry<TMeta>[],\n resolver: FileResolver<TCtx, TMeta>,\n ctx: TCtx\n ) {\n this.fs = new VirtualSandboxFileSystem(tree, resolver, ctx);\n }\n\n async exec(_command: string, _options?: ExecOptions): Promise<ExecResult> {\n throw new SandboxNotSupportedError(\"exec\");\n }\n\n async destroy(): Promise<void> {\n // Ephemeral — nothing to clean up\n }\n}\n\n// ============================================================================\n// Factory\n// ============================================================================\n\n/**\n * Create an ephemeral {@link Sandbox} from a file tree and resolver.\n *\n * Used internally by {@link withVirtualSandbox} and\n * {@link VirtualSandboxProvider}; consumers can also call this directly\n * if they need a sandbox outside the wrapper pattern.\n */\nexport function createVirtualSandbox<\n TCtx,\n TMeta = FileEntryMetadata,\n>(\n id: string,\n tree: FileEntry<TMeta>[],\n resolver: FileResolver<TCtx, TMeta>,\n ctx: TCtx,\n): VirtualSandbox<TCtx, TMeta> {\n return new VirtualSandboxImpl(id, tree, resolver, ctx);\n}\n\n// Re-exports for convenience\nexport { VirtualSandboxFileSystem } from \"./filesystem\";\nexport { VirtualSandboxProvider } from \"./provider\";\nexport { withVirtualSandbox } from \"./with-virtual-sandbox\";\nexport type {\n FileEntry,\n FileEntryMetadata,\n FileResolver,\n VirtualFileTree,\n VirtualSandboxCreateOptions,\n VirtualSandboxState,\n VirtualSandboxContext,\n VirtualSandbox,\n TreeMutation,\n} from \"./types\";\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/sandbox/types.ts","../../../../src/adapters/sandbox/virtual/filesystem.ts","../../../../src/lib/thread/id.ts","../../../../src/adapters/sandbox/virtual/provider.ts","../../../../src/lib/activity.ts","../../../../src/adapters/sandbox/virtual/with-virtual-sandbox.ts","../../../../src/adapters/sandbox/virtual/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["// ============================================================================\n// Sandbox Filesystem\n// ============================================================================\n\nexport interface DirentEntry {\n name: string;\n isFile: boolean;\n isDirectory: boolean;\n isSymbolicLink: boolean;\n}\n\nexport interface FileStat {\n isFile: boolean;\n isDirectory: boolean;\n isSymbolicLink: boolean;\n size: number;\n mtime: Date;\n}\n\n/**\n * Provider-agnostic filesystem interface.\n *\n * Implementations that don't support a method should throw\n * {@link SandboxNotSupportedError}.\n */\nexport interface SandboxFileSystem {\n /** Base directory used when resolving relative paths. */\n readonly workspaceBase: string;\n readFile(path: string): Promise<string>;\n readFileBuffer(path: string): Promise<Uint8Array>;\n writeFile(path: string, content: string | Uint8Array): Promise<void>;\n appendFile(path: string, content: string | Uint8Array): Promise<void>;\n exists(path: string): Promise<boolean>;\n stat(path: string): Promise<FileStat>;\n mkdir(path: string, options?: { recursive?: boolean }): Promise<void>;\n readdir(path: string): Promise<string[]>;\n readdirWithFileTypes(path: string): Promise<DirentEntry[]>;\n rm(path: string, options?: { recursive?: boolean; force?: boolean }): Promise<void>;\n cp(src: string, dest: string, options?: { recursive?: boolean }): Promise<void>;\n mv(src: string, dest: string): Promise<void>;\n readlink(path: string): Promise<string>;\n resolvePath(base: string, path: string): string;\n}\n\n// ============================================================================\n// Execution\n// ============================================================================\n\nexport interface ExecOptions {\n timeout?: number;\n cwd?: string;\n env?: Record<string, string>;\n}\n\nexport interface ExecResult {\n exitCode: number;\n stdout: string;\n stderr: string;\n}\n\n// ============================================================================\n// Capabilities\n// ============================================================================\n\nexport interface SandboxCapabilities {\n /** Sandbox supports filesystem operations */\n filesystem: boolean;\n /** Sandbox supports shell/command execution */\n execution: boolean;\n /** Sandbox state can be persisted and restored */\n persistence: boolean;\n}\n\n// ============================================================================\n// Sandbox\n// ============================================================================\n\nexport interface Sandbox {\n readonly id: string;\n readonly capabilities: SandboxCapabilities;\n readonly fs: SandboxFileSystem;\n\n exec(command: string, options?: ExecOptions): Promise<ExecResult>;\n destroy(): Promise<void>;\n}\n\n// ============================================================================\n// Snapshots\n// ============================================================================\n\nexport interface SandboxSnapshot {\n sandboxId: string;\n providerId: string;\n /** Provider-specific serialised state */\n data: unknown;\n createdAt: string;\n}\n\n// ============================================================================\n// Provider\n// ============================================================================\n\nexport interface SandboxCreateOptions {\n /** Preferred sandbox ID (provider may ignore) */\n id?: string;\n /** Seed the filesystem with these files */\n initialFiles?: Record<string, string | Uint8Array>;\n /** Environment variables available inside the sandbox */\n env?: Record<string, string>;\n}\n\nexport interface SandboxCreateResult {\n sandbox: Sandbox;\n /** Optional state to merge into the workflow's `AgentState` via the session. */\n stateUpdate?: Record<string, unknown>;\n}\n\nexport interface SandboxProvider<\n TOptions extends SandboxCreateOptions = SandboxCreateOptions,\n TSandbox extends Sandbox = Sandbox,\n> {\n readonly id: string;\n readonly capabilities: SandboxCapabilities;\n\n create(options?: TOptions): Promise<SandboxCreateResult>;\n get(sandboxId: string): Promise<TSandbox>;\n destroy(sandboxId: string): Promise<void>;\n snapshot(sandboxId: string): Promise<SandboxSnapshot>;\n restore(snapshot: SandboxSnapshot): Promise<Sandbox>;\n}\n\n// ============================================================================\n// SandboxOps — workflow-side activity interface (like ThreadOps)\n// ============================================================================\n\nexport interface SandboxOps<\n TOptions extends SandboxCreateOptions = SandboxCreateOptions,\n> {\n createSandbox(\n options?: TOptions,\n ): Promise<{ sandboxId: string; stateUpdate?: Record<string, unknown> }>;\n destroySandbox(sandboxId: string): Promise<void>;\n snapshotSandbox(sandboxId: string): Promise<SandboxSnapshot>;\n}\n\n// ============================================================================\n// Errors\n// ============================================================================\n\nimport { ApplicationFailure } from \"@temporalio/common\";\n\nexport class SandboxNotSupportedError extends ApplicationFailure {\n constructor(operation: string) {\n super(\n `Sandbox does not support: ${operation}`,\n \"SandboxNotSupportedError\",\n true,\n );\n }\n}\n\nexport class SandboxNotFoundError extends ApplicationFailure {\n constructor(sandboxId: string) {\n super(`Sandbox not found: ${sandboxId}`, \"SandboxNotFoundError\", true);\n }\n}\n","import type {\n SandboxFileSystem,\n DirentEntry,\n FileStat,\n} from \"../../../lib/sandbox/types\";\nimport { SandboxNotSupportedError } from \"../../../lib/sandbox/types\";\nimport { posix } from \"node:path\";\nimport type {\n FileEntry,\n FileEntryMetadata,\n FileResolver,\n TreeMutation,\n} from \"./types\";\n\n/** Normalize a path against the provided workspace base. */\nfunction normalisePath(p: string, workspaceBase = \"/\"): string {\n return posix.resolve(workspaceBase, p);\n}\n\n/** Return the parent directory of a normalised path (\"/a/b\" → \"/a\"). */\nfunction parentDir(p: string): string {\n const idx = p.lastIndexOf(\"/\");\n return idx <= 0 ? \"/\" : p.slice(0, idx);\n}\n\n/**\n * Collect the set of implicit directory paths from a flat file list.\n * E.g. \"/a/b/c.ts\" contributes \"/a/b\", \"/a\", \"/\".\n */\nfunction inferDirectories(\n entries: { path: string }[],\n workspaceBase: string,\n): Set<string> {\n const dirs = new Set<string>();\n dirs.add(\"/\");\n for (const entry of entries) {\n let dir = parentDir(normalisePath(entry.path, workspaceBase));\n while (dir !== \"/\" && !dirs.has(dir)) {\n dirs.add(dir);\n dir = parentDir(dir);\n }\n dirs.add(\"/\");\n }\n return dirs;\n}\n\n/**\n * Ephemeral {@link SandboxFileSystem} backed by a {@link FileResolver}.\n *\n * Created fresh for each tool invocation from the current workflow file tree.\n * Directory structure is inferred from file paths. All mutations are tracked\n * and can be retrieved via {@link getMutations} after the handler completes.\n */\nexport class VirtualSandboxFileSystem<\n TCtx = unknown,\n TMeta = FileEntryMetadata,\n> implements SandboxFileSystem\n{\n readonly workspaceBase: string;\n private entries: Map<string, FileEntry<TMeta>>;\n private directories: Set<string>;\n private mutations: TreeMutation<TMeta>[] = [];\n\n constructor(\n tree: FileEntry<TMeta>[],\n private resolver: FileResolver<TCtx, TMeta>,\n private ctx: TCtx,\n workspaceBase = \"/\",\n ) {\n this.workspaceBase = normalisePath(workspaceBase);\n this.entries = new Map(\n tree.map((e) => [normalisePath(e.path, this.workspaceBase), e]),\n );\n this.directories = inferDirectories(tree, this.workspaceBase);\n }\n\n /** Return all mutations accumulated during this invocation. */\n getMutations(): TreeMutation<TMeta>[] {\n return this.mutations;\n }\n\n /** Look up a file entry by virtual path. */\n getEntry(path: string): FileEntry<TMeta> | undefined {\n return this.entries.get(normalisePath(path, this.workspaceBase));\n }\n\n // --------------------------------------------------------------------------\n // Read operations — delegate to resolver lazily\n // --------------------------------------------------------------------------\n\n async readFile(path: string): Promise<string> {\n const entry = this.entries.get(normalisePath(path, this.workspaceBase));\n if (!entry) throw new Error(`ENOENT: no such file: ${path}`);\n return this.resolver.readFile(entry.id, this.ctx);\n }\n\n async readFileBuffer(path: string): Promise<Uint8Array> {\n const entry = this.entries.get(normalisePath(path, this.workspaceBase));\n if (!entry) throw new Error(`ENOENT: no such file: ${path}`);\n return this.resolver.readFileBuffer(entry.id, this.ctx);\n }\n\n // --------------------------------------------------------------------------\n // Metadata operations — pure, resolved from the tree\n // --------------------------------------------------------------------------\n\n async exists(path: string): Promise<boolean> {\n const norm = normalisePath(path, this.workspaceBase);\n return this.entries.has(norm) || this.directories.has(norm);\n }\n\n async stat(path: string): Promise<FileStat> {\n const norm = normalisePath(path, this.workspaceBase);\n const entry = this.entries.get(norm);\n if (entry) {\n return {\n isFile: true,\n isDirectory: false,\n isSymbolicLink: false,\n size: entry.size,\n mtime: new Date(entry.mtime),\n };\n }\n if (this.directories.has(norm)) {\n return {\n isFile: false,\n isDirectory: true,\n isSymbolicLink: false,\n size: 0,\n mtime: new Date(),\n };\n }\n throw new Error(`ENOENT: no such file or directory: ${path}`);\n }\n\n async readdir(path: string): Promise<string[]> {\n const norm = normalisePath(path, this.workspaceBase);\n if (!this.directories.has(norm)) {\n throw new Error(`ENOENT: no such directory: ${path}`);\n }\n const prefix = norm === \"/\" ? \"/\" : norm + \"/\";\n const names = new Set<string>();\n\n for (const p of this.entries.keys()) {\n if (p.startsWith(prefix)) {\n const rest = p.slice(prefix.length);\n const seg = rest.split(\"/\")[0];\n if (seg) names.add(seg);\n }\n }\n for (const d of this.directories) {\n if (d.startsWith(prefix) && d !== norm) {\n const rest = d.slice(prefix.length);\n const seg = rest.split(\"/\")[0];\n if (seg) names.add(seg);\n }\n }\n return [...names].sort();\n }\n\n async readdirWithFileTypes(path: string): Promise<DirentEntry[]> {\n const names = await this.readdir(path);\n const norm = normalisePath(path, this.workspaceBase);\n const prefix = norm === \"/\" ? \"/\" : norm + \"/\";\n\n return names.map((name) => {\n const full = prefix + name;\n const isFile = this.entries.has(full);\n const isDirectory = this.directories.has(full);\n return { name, isFile, isDirectory, isSymbolicLink: false };\n });\n }\n\n // --------------------------------------------------------------------------\n // Write operations — delegate to resolver, record mutations\n // --------------------------------------------------------------------------\n\n async writeFile(path: string, content: string | Uint8Array): Promise<void> {\n const norm = normalisePath(path, this.workspaceBase);\n const existing = this.entries.get(norm);\n\n if (existing) {\n await this.resolver.writeFile(existing.id, content, this.ctx);\n const size =\n typeof content === \"string\"\n ? new TextEncoder().encode(content).byteLength\n : content.byteLength;\n const updated: FileEntry<TMeta> = {\n ...existing,\n size,\n mtime: new Date().toISOString(),\n };\n this.entries.set(norm, updated);\n this.mutations.push({ type: \"update\", path: norm, entry: updated });\n } else {\n const entry = await this.resolver.createFile(norm, content, this.ctx);\n const normalised = { ...entry, path: norm };\n this.entries.set(norm, normalised);\n this.addParentDirectories(norm);\n this.mutations.push({ type: \"add\", entry: normalised });\n }\n }\n\n async appendFile(path: string, content: string | Uint8Array): Promise<void> {\n const norm = normalisePath(path, this.workspaceBase);\n const existing = this.entries.get(norm);\n\n if (!existing) {\n return this.writeFile(path, content);\n }\n\n const current = await this.resolver.readFile(existing.id, this.ctx);\n const appended =\n typeof content === \"string\"\n ? current + content\n : current + new TextDecoder().decode(content);\n await this.resolver.writeFile(existing.id, appended, this.ctx);\n\n const size = new TextEncoder().encode(appended).byteLength;\n const updated: FileEntry<TMeta> = {\n ...existing,\n size,\n mtime: new Date().toISOString(),\n };\n this.entries.set(norm, updated);\n this.mutations.push({ type: \"update\", path: norm, entry: updated });\n }\n\n async mkdir(_path: string, _options?: { recursive?: boolean }): Promise<void> {\n const norm = normalisePath(_path, this.workspaceBase);\n if (this.directories.has(norm)) return;\n\n if (_options?.recursive) {\n this.addParentDirectories(norm + \"/placeholder\");\n this.directories.add(norm);\n } else {\n const parent = parentDir(norm);\n if (!this.directories.has(parent)) {\n throw new Error(`ENOENT: no such directory: ${parent}`);\n }\n this.directories.add(norm);\n }\n }\n\n async rm(\n path: string,\n options?: { recursive?: boolean; force?: boolean },\n ): Promise<void> {\n const norm = normalisePath(path, this.workspaceBase);\n const entry = this.entries.get(norm);\n\n if (entry) {\n await this.resolver.deleteFile(entry.id, this.ctx);\n this.entries.delete(norm);\n this.mutations.push({ type: \"remove\", path: norm });\n return;\n }\n\n if (this.directories.has(norm)) {\n if (!options?.recursive) {\n throw new Error(`EISDIR: is a directory (use recursive): ${path}`);\n }\n const prefix = norm === \"/\" ? \"/\" : norm + \"/\";\n for (const [p, e] of this.entries) {\n if (p.startsWith(prefix)) {\n await this.resolver.deleteFile(e.id, this.ctx);\n this.entries.delete(p);\n this.mutations.push({ type: \"remove\", path: p });\n }\n }\n for (const d of this.directories) {\n if (d.startsWith(prefix)) this.directories.delete(d);\n }\n this.directories.delete(norm);\n return;\n }\n\n if (!options?.force) {\n throw new Error(`ENOENT: no such file or directory: ${path}`);\n }\n }\n\n async cp(\n src: string,\n dest: string,\n _options?: { recursive?: boolean },\n ): Promise<void> {\n const normSrc = normalisePath(src, this.workspaceBase);\n const normDest = normalisePath(dest, this.workspaceBase);\n\n const entry = this.entries.get(normSrc);\n if (entry) {\n const content = await this.resolver.readFile(entry.id, this.ctx);\n await this.writeFile(normDest, content);\n return;\n }\n\n if (!this.directories.has(normSrc)) {\n throw new Error(`ENOENT: no such file or directory: ${src}`);\n }\n if (!_options?.recursive) {\n throw new Error(`EISDIR: is a directory (use recursive): ${src}`);\n }\n\n const prefix = normSrc === \"/\" ? \"/\" : normSrc + \"/\";\n for (const [p, e] of this.entries) {\n if (p.startsWith(prefix)) {\n const relative = p.slice(normSrc.length);\n const content = await this.resolver.readFile(e.id, this.ctx);\n await this.writeFile(normDest + relative, content);\n }\n }\n }\n\n async mv(src: string, dest: string): Promise<void> {\n await this.cp(src, dest, { recursive: true });\n await this.rm(src, { recursive: true });\n }\n\n // --------------------------------------------------------------------------\n // Unsupported\n // --------------------------------------------------------------------------\n\n async readlink(_path: string): Promise<string> {\n throw new SandboxNotSupportedError(\"readlink\");\n }\n\n resolvePath(base: string, path: string): string {\n return posix.resolve(normalisePath(base, this.workspaceBase), path);\n }\n\n // --------------------------------------------------------------------------\n // Helpers\n // --------------------------------------------------------------------------\n\n private addParentDirectories(filePath: string): void {\n let dir = parentDir(normalisePath(filePath, this.workspaceBase));\n while (!this.directories.has(dir)) {\n this.directories.add(dir);\n dir = parentDir(dir);\n }\n }\n}\n","import { uuid4 } from \"@temporalio/workflow\";\n\nconst BASE62 =\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n\n/**\n * Generate a compact, workflow-deterministic identifier.\n *\n * Uses Temporal's `uuid4()` internally (seeded by the workflow's RNG),\n * then re-encodes the hex bytes into a base-62 alphabet for a shorter,\n * more token-efficient identifier (~3 tokens vs ~10 for a full UUID).\n *\n * Suitable for thread IDs, child workflow IDs, or any workflow-scoped identifier.\n *\n * @param length - Number of base-62 characters (default 12, ~71 bits of entropy)\n */\nexport function getShortId(length = 12): string {\n const hex = uuid4().replace(/-/g, \"\");\n let result = \"\";\n for (let i = 0; i < length; i++) {\n const byte = parseInt(hex.slice(i * 2, i * 2 + 2), 16);\n result += BASE62[byte % BASE62.length];\n }\n return result;\n}\n","import type {\n SandboxCapabilities,\n SandboxCreateResult,\n SandboxProvider,\n} from \"../../../lib/sandbox/types\";\nimport { SandboxNotSupportedError } from \"../../../lib/sandbox/types\";\nimport { getShortId } from \"../../../lib/thread/id\";\nimport { createVirtualSandbox } from \"./index\";\nimport type {\n FileEntryMetadata,\n FileResolver,\n VirtualSandboxCreateOptions,\n} from \"./types\";\n\n/**\n * Stateless {@link SandboxProvider} backed by a {@link FileResolver}.\n *\n * The provider holds **no internal state**. All sandbox state (sandboxId,\n * fileTree, resolverContext, workspaceBase) is returned as a `stateUpdate` from\n * {@link create} and merged into the workflow's `AgentState` by the session.\n * {@link withVirtualSandbox} reads this state back on every tool invocation.\n *\n * @example\n * ```typescript\n * const provider = new VirtualSandboxProvider(resolver);\n * const manager = new SandboxManager(provider);\n *\n * export const activities = {\n * ...manager.createActivities(),\n * readFile: withVirtualSandbox(client, provider, readHandler),\n * };\n * ```\n */\nexport class VirtualSandboxProvider<\n TCtx = unknown,\n TMeta = FileEntryMetadata,\n> implements SandboxProvider<VirtualSandboxCreateOptions<TCtx>> {\n readonly id = \"virtual\";\n readonly capabilities: SandboxCapabilities = {\n filesystem: true,\n execution: false,\n persistence: true,\n };\n\n readonly resolver: FileResolver<TCtx, TMeta>;\n\n constructor(resolver: FileResolver<TCtx, TMeta>) {\n this.resolver = resolver;\n }\n\n async create(\n options?: VirtualSandboxCreateOptions<TCtx>\n ): Promise<SandboxCreateResult> {\n if (!options || !(\"resolverContext\" in options)) {\n throw new Error(\"VirtualSandboxProvider.create requires resolverContext\");\n }\n\n const sandboxId = options.id ?? getShortId();\n const fileTree = await this.resolver.resolveEntries(\n options.resolverContext\n );\n const workspaceBase = options.workspaceBase ?? \"/\";\n\n const sandbox = createVirtualSandbox(\n sandboxId,\n fileTree,\n this.resolver,\n options.resolverContext,\n workspaceBase,\n );\n\n return {\n sandbox,\n stateUpdate: {\n sandboxId,\n fileTree,\n resolverContext: options.resolverContext,\n workspaceBase,\n },\n };\n }\n\n async get(): Promise<never> {\n throw new SandboxNotSupportedError(\n \"get (virtual sandbox state lives in workflow AgentState)\"\n );\n }\n\n async destroy(): Promise<void> {\n // No-op — no internal state to clean up\n }\n\n async snapshot(): Promise<never> {\n throw new SandboxNotSupportedError(\n \"snapshot (virtual sandbox state lives in workflow AgentState)\"\n );\n }\n\n async restore(): Promise<never> {\n throw new SandboxNotSupportedError(\n \"restore (virtual sandbox state lives in workflow AgentState)\"\n );\n }\n}\n","import { Context } from \"@temporalio/activity\";\nimport type { WorkflowClient } from \"@temporalio/client\";\nimport type { BaseAgentState, RunAgentConfig } from \"./types\";\nimport type {\n ActivityToolHandler,\n RouterContext,\n ToolHandlerResponse,\n} from \"./tool-router/types\";\n\n/**\n * Query the parent workflow's state from within an activity.\n * Resolves the workflow handle from the current activity context.\n */\nexport async function queryParentWorkflowState<T>(\n client: WorkflowClient\n): Promise<T> {\n const { workflowExecution } = Context.current().info;\n const handle = client.getHandle(\n workflowExecution.workflowId,\n workflowExecution.runId\n );\n return handle.query<T>(\"getAgentState\");\n}\n\n/**\n * Wraps a handler into a `RunAgentActivity` by auto-fetching the parent\n * workflow's agent state before each invocation.\n *\n * @example\n * ```typescript\n * import { createRunAgentActivity } from 'zeitlich';\n * import { createLangChainModelInvoker } from 'zeitlich/adapters/thread/langchain';\n *\n * const invoker = createLangChainModelInvoker({ redis, model });\n * return { runAgent: createRunAgentActivity(client, invoker) };\n * ```\n */\nexport function createRunAgentActivity<R, S extends BaseAgentState = BaseAgentState>(\n client: WorkflowClient,\n handler: (config: RunAgentConfig & { state: S }) => Promise<R>,\n): (config: RunAgentConfig) => Promise<R> {\n return async (config: RunAgentConfig) => {\n const state = await queryParentWorkflowState<S>(client);\n return handler({ ...config, state });\n };\n}\n\n/**\n * Context injected into tool handlers created via {@link withParentWorkflowState}.\n */\nexport interface AgentStateContext<S extends BaseAgentState = BaseAgentState> extends RouterContext {\n state: S;\n}\n\n/**\n * Wraps a tool handler into an `ActivityToolHandler` by auto-fetching the\n * parent workflow's agent state before each invocation.\n *\n * @typeParam S - Custom agent state type (defaults to `BaseAgentState`)\n *\n * @example\n * ```typescript\n * import { withParentWorkflowState, type AgentStateContext } from 'zeitlich';\n *\n * // With custom state:\n * interface MyState extends BaseAgentState { customField: string }\n * const myHandler = withParentWorkflowState<MyArgs, MyResult, MyState>(\n * client,\n * async (args, ctx) => {\n * console.log(ctx.state.customField);\n * return { toolResponse: 'done', data: null };\n * },\n * );\n * ```\n */\nexport function withParentWorkflowState<TArgs, TResult, S extends BaseAgentState = BaseAgentState>(\n client: WorkflowClient,\n handler: (\n args: TArgs,\n context: AgentStateContext<S>,\n ) => Promise<ToolHandlerResponse<TResult>>,\n): ActivityToolHandler<TArgs, TResult> {\n return async (args, context) => {\n const state = await queryParentWorkflowState<S>(client);\n return handler(args, { ...context, state });\n };\n}\n","import type { WorkflowClient } from \"@temporalio/client\";\nimport { queryParentWorkflowState } from \"../../../lib/activity\";\nimport type { ActivityToolHandler } from \"../../../lib/tool-router/types\";\nimport type {\n FileEntryMetadata,\n TreeMutation,\n VirtualSandboxContext,\n VirtualSandboxState,\n} from \"./types\";\nimport type { VirtualSandboxProvider } from \"./provider\";\nimport { createVirtualSandbox } from \"./index\";\n\n/**\n * Wraps a tool handler that needs a virtual sandbox, automatically querying\n * the parent workflow for the current file tree and resolver context.\n *\n * On each invocation the wrapper:\n * 1. Queries the workflow's `AgentState` for `fileTree`, `resolverContext`, and `workspaceBase`\n * 2. Creates an ephemeral {@link VirtualSandbox} from tree + provider's resolver\n * 3. Runs the inner handler\n * 4. Returns the handler's result together with any {@link TreeMutation}s\n *\n * The consumer applies mutations back to workflow state via a post-tool hook.\n *\n * @param client - Temporal `WorkflowClient` for querying the parent workflow\n * @param agentName - Agent name (used to derive the state query name)\n * @param provider - {@link VirtualSandboxProvider} (wraps the resolver)\n * @param handler - Inner handler expecting a {@link VirtualSandboxContext}\n *\n * @example\n * ```typescript\n * import { withVirtualSandbox, type VirtualSandboxContext } from 'zeitlich';\n *\n * const readHandler: ActivityToolHandler<FileReadArgs, ReadResult, VirtualSandboxContext> =\n * async (args, { sandbox }) => {\n * const content = await sandbox.fs.readFile(args.path);\n * return { toolResponse: content, data: { path: args.path, content } };\n * };\n *\n * // At activity registration:\n * const provider = new VirtualSandboxProvider(resolver);\n * const handler = withVirtualSandbox(client, \"myAgent\", provider, readHandler);\n * ```\n */\nexport function withVirtualSandbox<\n TArgs,\n TResult,\n TCtx,\n TMeta = FileEntryMetadata,\n>(\n client: WorkflowClient,\n provider: VirtualSandboxProvider<TCtx, TMeta>,\n handler: ActivityToolHandler<\n TArgs,\n TResult,\n VirtualSandboxContext<TCtx, TMeta>\n >\n): ActivityToolHandler<\n TArgs,\n (TResult & { treeMutations: TreeMutation<TMeta>[] }) | null\n> {\n return async (args, context) => {\n const state =\n await queryParentWorkflowState<VirtualSandboxState<TCtx, TMeta>>(client);\n\n const { sandboxId, fileTree, resolverContext, workspaceBase } = state;\n if (!fileTree || !sandboxId) {\n return {\n toolResponse: `Error: No fileTree/sandboxId in agent state. The ${context.toolName} tool requires a virtual sandbox.`,\n data: null,\n };\n }\n\n const sandbox = createVirtualSandbox(\n sandboxId,\n fileTree,\n provider.resolver,\n resolverContext,\n workspaceBase ?? \"/\",\n );\n const response = await handler(args, { ...context, sandbox });\n const mutations = sandbox.fs.getMutations();\n\n return {\n toolResponse: response.toolResponse,\n data: {\n ...(response.data ?? {}),\n treeMutations: mutations,\n } as TResult & { treeMutations: TreeMutation<TMeta>[] },\n };\n };\n}\n","import type {\n Sandbox,\n SandboxCapabilities,\n ExecOptions,\n ExecResult,\n} from \"../../../lib/sandbox/types\";\nimport { SandboxNotSupportedError } from \"../../../lib/sandbox/types\";\nimport { VirtualSandboxFileSystem } from \"./filesystem\";\nimport type {\n FileEntry,\n FileEntryMetadata,\n FileResolver,\n VirtualSandbox,\n} from \"./types\";\n\n// ============================================================================\n// VirtualSandbox\n// ============================================================================\n\nclass VirtualSandboxImpl<\n TCtx = unknown,\n TMeta = FileEntryMetadata,\n> implements Sandbox\n{\n readonly capabilities: SandboxCapabilities = {\n filesystem: true,\n execution: false,\n persistence: true,\n };\n\n readonly fs: VirtualSandboxFileSystem<TCtx, TMeta>;\n\n constructor(\n readonly id: string,\n tree: FileEntry<TMeta>[],\n resolver: FileResolver<TCtx, TMeta>,\n ctx: TCtx,\n workspaceBase = \"/\",\n ) {\n this.fs = new VirtualSandboxFileSystem(tree, resolver, ctx, workspaceBase);\n }\n\n async exec(_command: string, _options?: ExecOptions): Promise<ExecResult> {\n throw new SandboxNotSupportedError(\"exec\");\n }\n\n async destroy(): Promise<void> {\n // Ephemeral — nothing to clean up\n }\n}\n\n// ============================================================================\n// Factory\n// ============================================================================\n\n/**\n * Create an ephemeral {@link Sandbox} from a file tree and resolver.\n *\n * Used internally by {@link withVirtualSandbox} and\n * {@link VirtualSandboxProvider}; consumers can also call this directly\n * if they need a sandbox outside the wrapper pattern.\n */\nexport function createVirtualSandbox<\n TCtx,\n TMeta = FileEntryMetadata,\n>(\n id: string,\n tree: FileEntry<TMeta>[],\n resolver: FileResolver<TCtx, TMeta>,\n ctx: TCtx,\n workspaceBase = \"/\",\n): VirtualSandbox<TCtx, TMeta> {\n return new VirtualSandboxImpl(id, tree, resolver, ctx, workspaceBase);\n}\n\n// Re-exports for convenience\nexport { VirtualSandboxFileSystem } from \"./filesystem\";\nexport { VirtualSandboxProvider } from \"./provider\";\nexport { withVirtualSandbox } from \"./with-virtual-sandbox\";\nexport type {\n FileEntry,\n FileEntryMetadata,\n FileResolver,\n VirtualFileTree,\n VirtualSandboxCreateOptions,\n VirtualSandboxState,\n VirtualSandboxContext,\n VirtualSandbox,\n TreeMutation,\n} from \"./types\";\n"]}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import Redis from 'ioredis';
|
|
2
2
|
import { Content, GoogleGenAI, Part } from '@google/genai';
|
|
3
|
-
import { T as ThreadOps, M as ModelInvoker, a as ModelInvokerConfig, A as AgentResponse } from '../../../types-
|
|
3
|
+
import { T as ThreadOps, M as ModelInvoker, a as ModelInvokerConfig, A as AgentResponse } from '../../../types-Drli9aCK.cjs';
|
|
4
4
|
import { B as BaseThreadManager } from '../../../types-35POpVfa.cjs';
|
|
5
5
|
import { M as MessageContent, T as ToolMessageContent } from '../../../types-BMXzv7TN.cjs';
|
|
6
6
|
import '@temporalio/common';
|
|
7
7
|
import 'zod';
|
|
8
|
-
import '../../../types-
|
|
8
|
+
import '../../../types-BMRzfELQ.cjs';
|
|
9
9
|
import '@temporalio/workflow';
|
|
10
10
|
import '@temporalio/common/lib/interfaces';
|
|
11
11
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import Redis from 'ioredis';
|
|
2
2
|
import { Content, GoogleGenAI, Part } from '@google/genai';
|
|
3
|
-
import { T as ThreadOps, M as ModelInvoker, a as ModelInvokerConfig, A as AgentResponse } from '../../../types-
|
|
3
|
+
import { T as ThreadOps, M as ModelInvoker, a as ModelInvokerConfig, A as AgentResponse } from '../../../types-XPtivmSJ.js';
|
|
4
4
|
import { B as BaseThreadManager } from '../../../types-35POpVfa.js';
|
|
5
5
|
import { M as MessageContent, T as ToolMessageContent } from '../../../types-BMXzv7TN.js';
|
|
6
6
|
import '@temporalio/common';
|
|
7
7
|
import 'zod';
|
|
8
|
-
import '../../../types-
|
|
8
|
+
import '../../../types-BMRzfELQ.js';
|
|
9
9
|
import '@temporalio/workflow';
|
|
10
10
|
import '@temporalio/common/lib/interfaces';
|
|
11
11
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import Redis from 'ioredis';
|
|
2
|
-
import { T as ThreadOps, M as ModelInvoker, a as ModelInvokerConfig, A as AgentResponse } from '../../../types-
|
|
2
|
+
import { T as ThreadOps, M as ModelInvoker, a as ModelInvokerConfig, A as AgentResponse } from '../../../types-Drli9aCK.cjs';
|
|
3
3
|
import { StoredMessage, MessageContent, $InferMessageContent, MessageStructure } from '@langchain/core/messages';
|
|
4
4
|
import { BaseChatModel } from '@langchain/core/language_models/chat_models';
|
|
5
5
|
import { B as BaseThreadManager } from '../../../types-35POpVfa.cjs';
|
|
6
6
|
import '@temporalio/common';
|
|
7
7
|
import '../../../types-BMXzv7TN.cjs';
|
|
8
8
|
import 'zod';
|
|
9
|
-
import '../../../types-
|
|
9
|
+
import '../../../types-BMRzfELQ.cjs';
|
|
10
10
|
import '@temporalio/workflow';
|
|
11
11
|
import '@temporalio/common/lib/interfaces';
|
|
12
12
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import Redis from 'ioredis';
|
|
2
|
-
import { T as ThreadOps, M as ModelInvoker, a as ModelInvokerConfig, A as AgentResponse } from '../../../types-
|
|
2
|
+
import { T as ThreadOps, M as ModelInvoker, a as ModelInvokerConfig, A as AgentResponse } from '../../../types-XPtivmSJ.js';
|
|
3
3
|
import { StoredMessage, MessageContent, $InferMessageContent, MessageStructure } from '@langchain/core/messages';
|
|
4
4
|
import { BaseChatModel } from '@langchain/core/language_models/chat_models';
|
|
5
5
|
import { B as BaseThreadManager } from '../../../types-35POpVfa.js';
|
|
6
6
|
import '@temporalio/common';
|
|
7
7
|
import '../../../types-BMXzv7TN.js';
|
|
8
8
|
import 'zod';
|
|
9
|
-
import '../../../types-
|
|
9
|
+
import '../../../types-BMRzfELQ.js';
|
|
10
10
|
import '@temporalio/workflow';
|
|
11
11
|
import '@temporalio/common/lib/interfaces';
|
|
12
12
|
|
package/dist/index.cjs
CHANGED
|
@@ -561,9 +561,7 @@ var createSession = async ({
|
|
|
561
561
|
const result = await sandboxOps.createSandbox({ id: threadId });
|
|
562
562
|
sandboxId = result.sandboxId;
|
|
563
563
|
if (result.stateUpdate) {
|
|
564
|
-
stateManager.mergeUpdate(
|
|
565
|
-
result.stateUpdate
|
|
566
|
-
);
|
|
564
|
+
stateManager.mergeUpdate(result.stateUpdate);
|
|
567
565
|
}
|
|
568
566
|
}
|
|
569
567
|
if (hooks.onSessionStart) {
|
|
@@ -648,6 +646,7 @@ var createSession = async ({
|
|
|
648
646
|
);
|
|
649
647
|
if (!conditionMet) {
|
|
650
648
|
stateManager.cancel();
|
|
649
|
+
exitReason = "cancelled";
|
|
651
650
|
await workflow.condition(() => false, "2s");
|
|
652
651
|
break;
|
|
653
652
|
}
|