zeitlich 0.2.15 → 0.2.17
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 +125 -64
- 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 +83 -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 +80 -38
- 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.cjs +2 -2
- package/dist/adapters/thread/langchain/index.cjs.map +1 -1
- package/dist/adapters/thread/langchain/index.d.cts +2 -2
- package/dist/adapters/thread/langchain/index.d.ts +2 -2
- package/dist/adapters/thread/langchain/index.js +2 -2
- package/dist/adapters/thread/langchain/index.js.map +1 -1
- package/dist/index.cjs +102 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +98 -11
- package/dist/index.js.map +1 -1
- package/dist/{types-CwwgQ_9H.d.ts → queries-BlC1I3DK.d.ts} +48 -3
- package/dist/{types-BVP87m_W.d.cts → queries-DlJ3jE48.d.cts} +48 -3
- 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-Dje1TdH6.d.cts → types-Bh-BbfCp.d.cts} +31 -12
- package/dist/{types-BWvIYK28.d.ts → types-NkiAxU4t.d.ts} +31 -12
- package/dist/workflow.cjs +102 -10
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +114 -40
- package/dist/workflow.d.ts +114 -40
- package/dist/workflow.js +98 -11
- 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 +7 -3
- package/src/adapters/sandbox/virtual/provider.ts +5 -2
- package/src/adapters/sandbox/virtual/queries.ts +97 -0
- package/src/adapters/sandbox/virtual/types.ts +3 -0
- package/src/adapters/sandbox/virtual/with-virtual-sandbox.ts +4 -3
- package/src/adapters/thread/langchain/activities.ts +7 -5
- 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 +853 -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/define.ts +34 -47
- package/src/lib/subagent/handler.ts +9 -6
- package/src/lib/subagent/index.ts +4 -1
- package/src/lib/subagent/subagent.integration.test.ts +573 -0
- package/src/lib/subagent/types.ts +40 -10
- package/src/lib/subagent/workflow.ts +114 -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
- package/src/lib/workflow.test.ts +131 -0
- package/src/lib/workflow.ts +45 -0
- package/src/workflow.ts +12 -2
package/README.md
CHANGED
|
@@ -97,7 +97,8 @@ import {
|
|
|
97
97
|
askUserQuestionTool,
|
|
98
98
|
bashTool,
|
|
99
99
|
defineTool,
|
|
100
|
-
|
|
100
|
+
defineSubagentWorkflow,
|
|
101
|
+
defineSubagent,
|
|
101
102
|
type ModelInvoker,
|
|
102
103
|
} from "zeitlich/workflow";
|
|
103
104
|
|
|
@@ -371,58 +372,68 @@ const session = await createSession({
|
|
|
371
372
|
|
|
372
373
|
### Subagents
|
|
373
374
|
|
|
374
|
-
Spawn child agents as Temporal child workflows.
|
|
375
|
+
Spawn child agents as Temporal child workflows. Use `defineSubagentWorkflow` to define the workflow with its metadata once, then `defineSubagent` to register it in the parent:
|
|
375
376
|
|
|
376
377
|
```typescript
|
|
377
|
-
|
|
378
|
+
// researcher.workflow.ts
|
|
379
|
+
import { proxyActivities } from "@temporalio/workflow";
|
|
378
380
|
import {
|
|
379
381
|
createAgentStateManager,
|
|
380
382
|
createSession,
|
|
381
|
-
|
|
383
|
+
defineSubagentWorkflow,
|
|
382
384
|
} from "zeitlich/workflow";
|
|
383
|
-
import { agentConfig } from "./config";
|
|
384
385
|
import type { createResearcherActivities } from "./activities";
|
|
385
386
|
|
|
386
387
|
const { runResearcherActivity } = proxyActivities<
|
|
387
388
|
ReturnType<typeof createResearcherActivities>
|
|
388
389
|
>({ startToCloseTimeout: "30m", heartbeatTimeout: "5m" });
|
|
389
390
|
|
|
390
|
-
//
|
|
391
|
-
export const
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
391
|
+
// Define the workflow — name, description (and optional resultSchema) live here
|
|
392
|
+
export const researcherWorkflow = defineSubagentWorkflow(
|
|
393
|
+
{
|
|
394
|
+
name: "Researcher",
|
|
395
|
+
description: "Researches topics and gathers information",
|
|
396
|
+
},
|
|
397
|
+
async (prompt, sessionInput) => {
|
|
398
|
+
const stateManager = createAgentStateManager({
|
|
399
|
+
initialState: { systemPrompt: "You are a researcher." },
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
const session = await createSession({
|
|
403
|
+
...sessionInput, // spreads agentName, threadId, continueThread, sandboxId
|
|
404
|
+
runAgent: runResearcherActivity,
|
|
405
|
+
buildContextMessage: () => [{ type: "text", text: prompt }],
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
const { finalMessage, threadId } = await session.runSession({ stateManager });
|
|
409
|
+
return {
|
|
410
|
+
toolResponse: finalMessage ? extractText(finalMessage) : "No response",
|
|
411
|
+
data: null,
|
|
412
|
+
threadId,
|
|
413
|
+
};
|
|
414
|
+
},
|
|
415
|
+
);
|
|
416
|
+
```
|
|
400
417
|
|
|
401
|
-
|
|
402
|
-
...agentConfig,
|
|
403
|
-
threadId: runId,
|
|
404
|
-
runAgent: runResearcherActivity,
|
|
405
|
-
buildContextMessage: () => [{ type: "text", text: prompt }],
|
|
406
|
-
});
|
|
418
|
+
In the parent workflow, register it with `defineSubagent` and pass it to `createSession`:
|
|
407
419
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
};
|
|
413
|
-
};
|
|
420
|
+
```typescript
|
|
421
|
+
// parent.workflow.ts
|
|
422
|
+
import { defineSubagent } from "zeitlich/workflow";
|
|
423
|
+
import { researcherWorkflow } from "./researcher.workflow";
|
|
414
424
|
|
|
415
|
-
//
|
|
416
|
-
export const researcherSubagent =
|
|
417
|
-
agentName: agentConfig.agentName,
|
|
418
|
-
description: agentConfig.description,
|
|
419
|
-
workflow: researcherSubagentWorkflow,
|
|
420
|
-
};
|
|
421
|
-
```
|
|
425
|
+
// Metadata (name, description) comes from the workflow definition
|
|
426
|
+
export const researcherSubagent = defineSubagent(researcherWorkflow);
|
|
422
427
|
|
|
423
|
-
|
|
428
|
+
// Optionally override parent-specific config
|
|
429
|
+
export const researcherSubagent = defineSubagent(researcherWorkflow, {
|
|
430
|
+
allowThreadContinuation: true,
|
|
431
|
+
sandbox: "own",
|
|
432
|
+
hooks: {
|
|
433
|
+
onPostExecution: ({ result }) => console.log("researcher done", result),
|
|
434
|
+
},
|
|
435
|
+
});
|
|
424
436
|
|
|
425
|
-
```typescript
|
|
426
437
|
const session = await createSession({
|
|
427
438
|
// ... other config
|
|
428
439
|
subagents: [researcherSubagent, codeReviewerSubagent],
|
|
@@ -461,34 +472,32 @@ When `continueThread` is true the session **forks** the provided thread — it c
|
|
|
461
472
|
Subagents can opt in to thread continuation via `allowThreadContinuation`. When enabled, the parent agent can pass a `threadId` to resume a previous subagent conversation:
|
|
462
473
|
|
|
463
474
|
```typescript
|
|
464
|
-
import {
|
|
475
|
+
import { defineSubagentWorkflow, defineSubagent } from "zeitlich/workflow";
|
|
465
476
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
}
|
|
477
|
+
export const researcherWorkflow = defineSubagentWorkflow(
|
|
478
|
+
{
|
|
479
|
+
name: "Researcher",
|
|
480
|
+
description: "Researches topics and gathers information",
|
|
481
|
+
},
|
|
482
|
+
async (prompt, sessionInput) => {
|
|
483
|
+
const session = await createSession({
|
|
484
|
+
...sessionInput, // threadId/continueThread are provided by parent when resuming
|
|
485
|
+
// ... other config
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
const { threadId, finalMessage } = await session.runSession({ stateManager });
|
|
489
|
+
return {
|
|
490
|
+
toolResponse: finalMessage ? extractText(finalMessage) : "No response",
|
|
491
|
+
data: null,
|
|
492
|
+
threadId,
|
|
493
|
+
};
|
|
494
|
+
},
|
|
495
|
+
);
|
|
484
496
|
|
|
485
|
-
//
|
|
486
|
-
export const researcherSubagent = {
|
|
487
|
-
agentName: "Researcher",
|
|
488
|
-
description: "Researches topics and gathers information",
|
|
489
|
-
workflow: researcherWorkflow,
|
|
497
|
+
// Enable thread continuation in the parent registration
|
|
498
|
+
export const researcherSubagent = defineSubagent(researcherWorkflow, {
|
|
490
499
|
allowThreadContinuation: true,
|
|
491
|
-
};
|
|
500
|
+
});
|
|
492
501
|
```
|
|
493
502
|
|
|
494
503
|
The subagent returns its `threadId` in the response, which the handler surfaces to the parent LLM as `[Thread ID: ...]`. The parent can then pass that ID back in a subsequent `Subagent` tool call to continue the conversation.
|
|
@@ -545,6 +554,56 @@ export const createActivities = ({ redis, client }) => ({
|
|
|
545
554
|
});
|
|
546
555
|
```
|
|
547
556
|
|
|
557
|
+
#### Sandbox Path Semantics (Virtual + Daytona)
|
|
558
|
+
|
|
559
|
+
Filesystem adapters now apply the same path rules:
|
|
560
|
+
|
|
561
|
+
- Absolute paths are used as-is (canonicalized).
|
|
562
|
+
- Relative paths are resolved from `/`.
|
|
563
|
+
- Paths are normalized (duplicate slashes removed, `.`/`..` collapsed).
|
|
564
|
+
|
|
565
|
+
This means `readFile("a/b.txt")` is treated as `/a/b.txt` across adapters.
|
|
566
|
+
|
|
567
|
+
Each `fs` instance also exposes `workspaceBase`, which is the base used for relative paths.
|
|
568
|
+
|
|
569
|
+
**Virtual sandbox example (path-only calls):**
|
|
570
|
+
|
|
571
|
+
```typescript
|
|
572
|
+
import { createVirtualSandbox, VirtualSandboxProvider } from "zeitlich";
|
|
573
|
+
|
|
574
|
+
const provider = new VirtualSandboxProvider(resolver);
|
|
575
|
+
const { sandbox } = await provider.create({
|
|
576
|
+
resolverContext: { projectId: "p1" },
|
|
577
|
+
workspaceBase: "/repo",
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
const fs = sandbox.fs;
|
|
581
|
+
console.log(fs.workspaceBase); // "/repo"
|
|
582
|
+
|
|
583
|
+
await fs.writeFile("src/index.ts", 'export const ok = true;\n');
|
|
584
|
+
const content = await fs.readFile("src/index.ts"); // reads /repo/src/index.ts
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
**Daytona sandbox example (base `/home/daytona`):**
|
|
588
|
+
|
|
589
|
+
```typescript
|
|
590
|
+
import { DaytonaSandboxProvider } from "zeitlich";
|
|
591
|
+
|
|
592
|
+
const provider = new DaytonaSandboxProvider();
|
|
593
|
+
const { sandbox } = await provider.create({
|
|
594
|
+
workspaceBase: "/home/daytona",
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
const fs = sandbox.fs;
|
|
598
|
+
console.log(fs.workspaceBase); // "/home/daytona"
|
|
599
|
+
|
|
600
|
+
await fs.mkdir("project", { recursive: true });
|
|
601
|
+
await fs.writeFile("project/README.md", "# Hello from Daytona\n");
|
|
602
|
+
const content = await fs.readFile("project/README.md");
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
For Daytona, use `workspaceBase: "/home/daytona"` (or your own working dir) so relative paths stay in the expected workspace.
|
|
606
|
+
|
|
548
607
|
### Built-in Tools
|
|
549
608
|
|
|
550
609
|
Zeitlich provides ready-to-use tool definitions and handlers for common agent operations.
|
|
@@ -612,11 +671,12 @@ Safe for use in Temporal workflow files:
|
|
|
612
671
|
| `createAgentStateManager` | Creates a state manager for workflow state with query/update handlers |
|
|
613
672
|
| `createToolRouter` | Creates a tool router (used internally by session, or for advanced use) |
|
|
614
673
|
| `defineTool` | Identity function for type-safe tool definition with handler and hooks |
|
|
615
|
-
| `
|
|
674
|
+
| `defineSubagentWorkflow` | Defines a subagent workflow with embedded name, description, and optional resultSchema |
|
|
675
|
+
| `defineSubagent` | Creates a `SubagentConfig` from a `SubagentDefinition` with optional parent-specific overrides |
|
|
616
676
|
| `getShortId` | Generate a compact, workflow-deterministic identifier (base-62, 12 chars) |
|
|
617
677
|
| Tool definitions | `askUserQuestionTool`, `globTool`, `grepTool`, `readFileTool`, `writeFileTool`, `editTool`, `bashTool` |
|
|
618
678
|
| Task tools | `taskCreateTool`, `taskGetTool`, `taskListTool`, `taskUpdateTool` for workflow task management |
|
|
619
|
-
| Types | `
|
|
679
|
+
| Types | `SubagentDefinition`, `SubagentConfig`, `ToolDefinition`, `ToolWithHandler`, `RouterContext`, `SessionConfig`, etc. |
|
|
620
680
|
|
|
621
681
|
### Activity Entry Point (`zeitlich`)
|
|
622
682
|
|
|
@@ -656,7 +716,8 @@ LangChain-specific implementations:
|
|
|
656
716
|
| `RouterContext` | Base context every tool handler receives (`threadId`, `toolCallId`, `toolName`, `sandboxId?`) |
|
|
657
717
|
| `Hooks` | Combined session lifecycle + tool execution hooks |
|
|
658
718
|
| `ToolRouterHooks` | Narrowed hook interface for tool execution only (pre/post/failure) |
|
|
659
|
-
| `
|
|
719
|
+
| `SubagentDefinition` | Callable subagent workflow with embedded metadata (from `defineSubagentWorkflow`) |
|
|
720
|
+
| `SubagentConfig` | Resolved subagent configuration consumed by `createSession` |
|
|
660
721
|
| `AgentState` | Generic agent state type |
|
|
661
722
|
|
|
662
723
|
## Architecture
|
|
@@ -20,42 +20,53 @@ var SandboxNotFoundError = class extends common.ApplicationFailure {
|
|
|
20
20
|
}
|
|
21
21
|
};
|
|
22
22
|
var DaytonaSandboxFileSystem = class {
|
|
23
|
-
constructor(sandbox) {
|
|
23
|
+
constructor(sandbox, workspaceBase = "/home/daytona") {
|
|
24
24
|
this.sandbox = sandbox;
|
|
25
|
+
this.workspaceBase = path.posix.resolve("/", workspaceBase);
|
|
26
|
+
}
|
|
27
|
+
workspaceBase;
|
|
28
|
+
normalisePath(path$1) {
|
|
29
|
+
return path.posix.resolve(this.workspaceBase, path$1);
|
|
25
30
|
}
|
|
26
31
|
async readFile(path) {
|
|
27
|
-
const
|
|
32
|
+
const norm = this.normalisePath(path);
|
|
33
|
+
const buf = await this.sandbox.fs.downloadFile(norm);
|
|
28
34
|
return buf.toString("utf-8");
|
|
29
35
|
}
|
|
30
36
|
async readFileBuffer(path) {
|
|
31
|
-
const
|
|
37
|
+
const norm = this.normalisePath(path);
|
|
38
|
+
const buf = await this.sandbox.fs.downloadFile(norm);
|
|
32
39
|
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
33
40
|
}
|
|
34
41
|
async writeFile(path, content) {
|
|
42
|
+
const norm = this.normalisePath(path);
|
|
35
43
|
const buf = typeof content === "string" ? Buffer.from(content, "utf-8") : Buffer.from(content);
|
|
36
|
-
await this.sandbox.fs.uploadFile(buf,
|
|
44
|
+
await this.sandbox.fs.uploadFile(buf, norm);
|
|
37
45
|
}
|
|
38
46
|
async appendFile(path, content) {
|
|
47
|
+
const norm = this.normalisePath(path);
|
|
39
48
|
let existing;
|
|
40
49
|
try {
|
|
41
|
-
existing = await this.sandbox.fs.downloadFile(
|
|
50
|
+
existing = await this.sandbox.fs.downloadFile(norm);
|
|
42
51
|
} catch {
|
|
43
|
-
return this.writeFile(
|
|
52
|
+
return this.writeFile(norm, content);
|
|
44
53
|
}
|
|
45
54
|
const addition = typeof content === "string" ? Buffer.from(content, "utf-8") : content;
|
|
46
55
|
const merged = Buffer.concat([existing, Buffer.from(addition)]);
|
|
47
|
-
await this.sandbox.fs.uploadFile(merged,
|
|
56
|
+
await this.sandbox.fs.uploadFile(merged, norm);
|
|
48
57
|
}
|
|
49
58
|
async exists(path) {
|
|
59
|
+
const norm = this.normalisePath(path);
|
|
50
60
|
try {
|
|
51
|
-
await this.sandbox.fs.getFileDetails(
|
|
61
|
+
await this.sandbox.fs.getFileDetails(norm);
|
|
52
62
|
return true;
|
|
53
63
|
} catch {
|
|
54
64
|
return false;
|
|
55
65
|
}
|
|
56
66
|
}
|
|
57
67
|
async stat(path) {
|
|
58
|
-
const
|
|
68
|
+
const norm = this.normalisePath(path);
|
|
69
|
+
const info = await this.sandbox.fs.getFileDetails(norm);
|
|
59
70
|
return {
|
|
60
71
|
isFile: !info.isDir,
|
|
61
72
|
isDirectory: info.isDir,
|
|
@@ -65,14 +76,17 @@ var DaytonaSandboxFileSystem = class {
|
|
|
65
76
|
};
|
|
66
77
|
}
|
|
67
78
|
async mkdir(path, _options) {
|
|
68
|
-
|
|
79
|
+
const norm = this.normalisePath(path);
|
|
80
|
+
await this.sandbox.fs.createFolder(norm, "755");
|
|
69
81
|
}
|
|
70
82
|
async readdir(path) {
|
|
71
|
-
const
|
|
83
|
+
const norm = this.normalisePath(path);
|
|
84
|
+
const entries = await this.sandbox.fs.listFiles(norm);
|
|
72
85
|
return entries.map((e) => e.name);
|
|
73
86
|
}
|
|
74
87
|
async readdirWithFileTypes(path) {
|
|
75
|
-
const
|
|
88
|
+
const norm = this.normalisePath(path);
|
|
89
|
+
const entries = await this.sandbox.fs.listFiles(norm);
|
|
76
90
|
return entries.map((e) => ({
|
|
77
91
|
name: e.name,
|
|
78
92
|
isFile: !e.isDir,
|
|
@@ -81,41 +95,45 @@ var DaytonaSandboxFileSystem = class {
|
|
|
81
95
|
}));
|
|
82
96
|
}
|
|
83
97
|
async rm(path, options) {
|
|
98
|
+
const norm = this.normalisePath(path);
|
|
84
99
|
try {
|
|
85
|
-
await this.sandbox.fs.deleteFile(
|
|
100
|
+
await this.sandbox.fs.deleteFile(norm, options?.recursive);
|
|
86
101
|
} catch (err) {
|
|
87
102
|
if (!options?.force) throw err;
|
|
88
103
|
}
|
|
89
104
|
}
|
|
90
105
|
async cp(src, dest, options) {
|
|
91
|
-
const
|
|
106
|
+
const normSrc = this.normalisePath(src);
|
|
107
|
+
const normDest = this.normalisePath(dest);
|
|
108
|
+
const info = await this.sandbox.fs.getFileDetails(normSrc);
|
|
92
109
|
if (info.isDir) {
|
|
93
110
|
if (!options?.recursive) {
|
|
94
111
|
throw new Error(`EISDIR: is a directory (use recursive): ${src}`);
|
|
95
112
|
}
|
|
96
|
-
await this.sandbox.process.executeCommand(`cp -r "${
|
|
113
|
+
await this.sandbox.process.executeCommand(`cp -r "${normSrc}" "${normDest}"`);
|
|
97
114
|
} else {
|
|
98
|
-
await this.sandbox.process.executeCommand(`cp "${
|
|
115
|
+
await this.sandbox.process.executeCommand(`cp "${normSrc}" "${normDest}"`);
|
|
99
116
|
}
|
|
100
117
|
}
|
|
101
118
|
async mv(src, dest) {
|
|
102
|
-
|
|
119
|
+
const normSrc = this.normalisePath(src);
|
|
120
|
+
const normDest = this.normalisePath(dest);
|
|
121
|
+
await this.sandbox.fs.moveFiles(normSrc, normDest);
|
|
103
122
|
}
|
|
104
123
|
async readlink(_path) {
|
|
105
124
|
throw new SandboxNotSupportedError("readlink");
|
|
106
125
|
}
|
|
107
126
|
resolvePath(base, path$1) {
|
|
108
|
-
|
|
109
|
-
return path.posix.resolve(base, path$1);
|
|
127
|
+
return path.posix.resolve(this.normalisePath(base), path$1);
|
|
110
128
|
}
|
|
111
129
|
};
|
|
112
130
|
|
|
113
131
|
// src/adapters/sandbox/daytona/index.ts
|
|
114
132
|
var DaytonaSandboxImpl = class {
|
|
115
|
-
constructor(id, sdkSandbox) {
|
|
133
|
+
constructor(id, sdkSandbox, workspaceBase = "/home/daytona") {
|
|
116
134
|
this.id = id;
|
|
117
135
|
this.sdkSandbox = sdkSandbox;
|
|
118
|
-
this.fs = new DaytonaSandboxFileSystem(sdkSandbox);
|
|
136
|
+
this.fs = new DaytonaSandboxFileSystem(sdkSandbox, workspaceBase);
|
|
119
137
|
}
|
|
120
138
|
capabilities = {
|
|
121
139
|
filesystem: true,
|
|
@@ -148,8 +166,11 @@ var DaytonaSandboxProvider = class {
|
|
|
148
166
|
persistence: false
|
|
149
167
|
};
|
|
150
168
|
client;
|
|
169
|
+
defaultWorkspaceBase;
|
|
170
|
+
workspaceBaseById = /* @__PURE__ */ new Map();
|
|
151
171
|
constructor(config) {
|
|
152
172
|
this.client = new sdk.Daytona(config);
|
|
173
|
+
this.defaultWorkspaceBase = config?.workspaceBase ?? "/home/daytona";
|
|
153
174
|
}
|
|
154
175
|
async create(options) {
|
|
155
176
|
const sdkSandbox = await this.client.create(
|
|
@@ -164,7 +185,13 @@ var DaytonaSandboxProvider = class {
|
|
|
164
185
|
},
|
|
165
186
|
{ timeout: options?.timeout ?? 60 }
|
|
166
187
|
);
|
|
167
|
-
const
|
|
188
|
+
const workspaceBase = options?.workspaceBase ?? this.defaultWorkspaceBase;
|
|
189
|
+
this.workspaceBaseById.set(sdkSandbox.id, workspaceBase);
|
|
190
|
+
const sandbox = new DaytonaSandboxImpl(
|
|
191
|
+
sdkSandbox.id,
|
|
192
|
+
sdkSandbox,
|
|
193
|
+
workspaceBase
|
|
194
|
+
);
|
|
168
195
|
if (options?.initialFiles) {
|
|
169
196
|
for (const [path, content] of Object.entries(options.initialFiles)) {
|
|
170
197
|
await sandbox.fs.writeFile(path, content);
|
|
@@ -175,7 +202,8 @@ var DaytonaSandboxProvider = class {
|
|
|
175
202
|
async get(sandboxId) {
|
|
176
203
|
try {
|
|
177
204
|
const sdkSandbox = await this.client.get(sandboxId);
|
|
178
|
-
|
|
205
|
+
const workspaceBase = this.workspaceBaseById.get(sandboxId) ?? this.defaultWorkspaceBase;
|
|
206
|
+
return new DaytonaSandboxImpl(sdkSandbox.id, sdkSandbox, workspaceBase);
|
|
179
207
|
} catch {
|
|
180
208
|
throw new SandboxNotFoundError(sandboxId);
|
|
181
209
|
}
|
|
@@ -184,6 +212,7 @@ var DaytonaSandboxProvider = class {
|
|
|
184
212
|
try {
|
|
185
213
|
const sdkSandbox = await this.client.get(sandboxId);
|
|
186
214
|
await this.client.delete(sdkSandbox);
|
|
215
|
+
this.workspaceBaseById.delete(sandboxId);
|
|
187
216
|
} catch {
|
|
188
217
|
}
|
|
189
218
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/sandbox/types.ts","../../../../src/adapters/sandbox/daytona/filesystem.ts","../../../../src/adapters/sandbox/daytona/index.ts"],"names":["ApplicationFailure","path","posix","Daytona"],"mappings":"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","file":"index.cjs","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 { Sandbox as DaytonaSdkSandbox } from \"@daytonaio/sdk\";\nimport type {\n SandboxFileSystem,\n DirentEntry,\n FileStat,\n} from \"../../../lib/sandbox/types\";\nimport { SandboxNotSupportedError } from \"../../../lib/sandbox/types\";\nimport { posix } from \"node:path\";\n\n/**\n * {@link SandboxFileSystem} backed by a Daytona SDK sandbox.\n *\n * Maps zeitlich's filesystem interface to Daytona's `sandbox.fs` and\n * `sandbox.process` APIs. Operations that have no direct Daytona equivalent\n * (e.g. `appendFile`, `cp`) are composed from primitives.\n */\nexport class DaytonaSandboxFileSystem implements SandboxFileSystem {\n constructor(private sandbox: DaytonaSdkSandbox) {}\n\n async readFile(path: string): Promise<string> {\n const buf = await this.sandbox.fs.downloadFile(path);\n return buf.toString(\"utf-8\");\n }\n\n async readFileBuffer(path: string): Promise<Uint8Array> {\n const buf = await this.sandbox.fs.downloadFile(path);\n return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);\n }\n\n async writeFile(path: string, content: string | Uint8Array): Promise<void> {\n const buf =\n typeof content === \"string\"\n ? Buffer.from(content, \"utf-8\")\n : Buffer.from(content);\n await this.sandbox.fs.uploadFile(buf, path);\n }\n\n async appendFile(\n path: string,\n content: string | Uint8Array,\n ): Promise<void> {\n let existing: Buffer;\n try {\n existing = await this.sandbox.fs.downloadFile(path);\n } catch {\n return this.writeFile(path, content);\n }\n\n const addition =\n typeof content === \"string\" ? Buffer.from(content, \"utf-8\") : content;\n const merged = Buffer.concat([existing, Buffer.from(addition)]);\n await this.sandbox.fs.uploadFile(merged, path);\n }\n\n async exists(path: string): Promise<boolean> {\n try {\n await this.sandbox.fs.getFileDetails(path);\n return true;\n } catch {\n return false;\n }\n }\n\n async stat(path: string): Promise<FileStat> {\n const info = await this.sandbox.fs.getFileDetails(path);\n return {\n isFile: !info.isDir,\n isDirectory: info.isDir,\n isSymbolicLink: false,\n size: info.size,\n mtime: new Date(info.modTime),\n };\n }\n\n async mkdir(\n path: string,\n _options?: { recursive?: boolean },\n ): Promise<void> {\n await this.sandbox.fs.createFolder(path, \"755\");\n }\n\n async readdir(path: string): Promise<string[]> {\n const entries = await this.sandbox.fs.listFiles(path);\n return entries.map((e) => e.name);\n }\n\n async readdirWithFileTypes(path: string): Promise<DirentEntry[]> {\n const entries = await this.sandbox.fs.listFiles(path);\n return entries.map((e) => ({\n name: e.name,\n isFile: !e.isDir,\n isDirectory: e.isDir,\n isSymbolicLink: false,\n }));\n }\n\n async rm(\n path: string,\n options?: { recursive?: boolean; force?: boolean },\n ): Promise<void> {\n try {\n await this.sandbox.fs.deleteFile(path, options?.recursive);\n } catch (err) {\n if (!options?.force) throw err;\n }\n }\n\n async cp(\n src: string,\n dest: string,\n options?: { recursive?: boolean },\n ): Promise<void> {\n const info = await this.sandbox.fs.getFileDetails(src);\n if (info.isDir) {\n if (!options?.recursive) {\n throw new Error(`EISDIR: is a directory (use recursive): ${src}`);\n }\n await this.sandbox.process.executeCommand(`cp -r \"${src}\" \"${dest}\"`);\n } else {\n await this.sandbox.process.executeCommand(`cp \"${src}\" \"${dest}\"`);\n }\n }\n\n async mv(src: string, dest: string): Promise<void> {\n await this.sandbox.fs.moveFiles(src, dest);\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 (posix.isAbsolute(path)) return posix.normalize(path);\n return posix.resolve(base, path);\n }\n}\n","import {\n Daytona,\n type Sandbox as DaytonaSdkSandbox,\n} from \"@daytonaio/sdk\";\nimport type {\n Sandbox,\n SandboxCapabilities,\n SandboxCreateResult,\n SandboxProvider,\n SandboxSnapshot,\n ExecOptions,\n ExecResult,\n} from \"../../../lib/sandbox/types\";\nimport {\n SandboxNotFoundError,\n SandboxNotSupportedError,\n} from \"../../../lib/sandbox/types\";\nimport { DaytonaSandboxFileSystem } from \"./filesystem\";\nimport type {\n DaytonaSandbox,\n DaytonaSandboxConfig,\n DaytonaSandboxCreateOptions,\n} from \"./types\";\n\n// ============================================================================\n// DaytonaSandbox\n// ============================================================================\n\nclass DaytonaSandboxImpl implements Sandbox {\n readonly capabilities: SandboxCapabilities = {\n filesystem: true,\n execution: true,\n persistence: false,\n };\n\n readonly fs: DaytonaSandboxFileSystem;\n\n constructor(\n readonly id: string,\n private sdkSandbox: DaytonaSdkSandbox,\n ) {\n this.fs = new DaytonaSandboxFileSystem(sdkSandbox);\n }\n\n async exec(command: string, options?: ExecOptions): Promise<ExecResult> {\n const response = await this.sdkSandbox.process.executeCommand(\n command,\n options?.cwd,\n options?.env,\n options?.timeout,\n );\n\n return {\n exitCode: response.exitCode ?? 0,\n stdout: response.result ?? \"\",\n stderr: \"\",\n };\n }\n\n async destroy(): Promise<void> {\n await this.sdkSandbox.delete(60);\n }\n}\n\n// ============================================================================\n// DaytonaSandboxProvider\n// ============================================================================\n\nexport class DaytonaSandboxProvider\n implements SandboxProvider<DaytonaSandboxCreateOptions, DaytonaSandbox>\n{\n readonly id = \"daytona\";\n readonly capabilities: SandboxCapabilities = {\n filesystem: true,\n execution: true,\n persistence: false,\n };\n\n private client: Daytona;\n\n constructor(config?: DaytonaSandboxConfig) {\n this.client = new Daytona(config);\n }\n\n async create(\n options?: DaytonaSandboxCreateOptions,\n ): Promise<SandboxCreateResult> {\n const sdkSandbox = await this.client.create(\n {\n language: options?.language,\n snapshot: options?.snapshot,\n envVars: options?.env,\n labels: options?.labels,\n autoStopInterval: options?.autoStopInterval,\n autoArchiveInterval: options?.autoArchiveInterval,\n autoDeleteInterval: options?.autoDeleteInterval,\n },\n { timeout: options?.timeout ?? 60 },\n );\n\n const sandbox = new DaytonaSandboxImpl(sdkSandbox.id, sdkSandbox);\n\n if (options?.initialFiles) {\n for (const [path, content] of Object.entries(options.initialFiles)) {\n await sandbox.fs.writeFile(path, content);\n }\n }\n\n return { sandbox };\n }\n\n async get(sandboxId: string): Promise<DaytonaSandbox> {\n try {\n const sdkSandbox = await this.client.get(sandboxId);\n return new DaytonaSandboxImpl(sdkSandbox.id, sdkSandbox);\n } catch {\n throw new SandboxNotFoundError(sandboxId);\n }\n }\n\n async destroy(sandboxId: string): Promise<void> {\n try {\n const sdkSandbox = await this.client.get(sandboxId);\n await this.client.delete(sdkSandbox);\n } catch {\n // Already gone\n }\n }\n\n async snapshot(_sandboxId: string): Promise<SandboxSnapshot> {\n throw new SandboxNotSupportedError(\n \"snapshot (use Daytona's native snapshot API directly)\",\n );\n }\n\n async restore(_snapshot: SandboxSnapshot): Promise<never> {\n throw new SandboxNotSupportedError(\n \"restore (use Daytona's native snapshot API directly)\",\n );\n }\n}\n\n// Re-exports\nexport { DaytonaSandboxFileSystem } from \"./filesystem\";\nexport type {\n DaytonaSandbox,\n DaytonaSandboxConfig,\n DaytonaSandboxCreateOptions,\n} from \"./types\";\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/sandbox/types.ts","../../../../src/adapters/sandbox/daytona/filesystem.ts","../../../../src/adapters/sandbox/daytona/index.ts"],"names":["ApplicationFailure","posix","path","Daytona"],"mappings":"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","file":"index.cjs","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 { Sandbox as DaytonaSdkSandbox } from \"@daytonaio/sdk\";\nimport type {\n SandboxFileSystem,\n DirentEntry,\n FileStat,\n} from \"../../../lib/sandbox/types\";\nimport { SandboxNotSupportedError } from \"../../../lib/sandbox/types\";\nimport { posix } from \"node:path\";\n\n/**\n * {@link SandboxFileSystem} backed by a Daytona SDK sandbox.\n *\n * Maps zeitlich's filesystem interface to Daytona's `sandbox.fs` and\n * `sandbox.process` APIs. Operations that have no direct Daytona equivalent\n * (e.g. `appendFile`, `cp`) are composed from primitives.\n */\nexport class DaytonaSandboxFileSystem implements SandboxFileSystem {\n readonly workspaceBase: string;\n\n constructor(\n private sandbox: DaytonaSdkSandbox,\n workspaceBase = \"/home/daytona\",\n ) {\n this.workspaceBase = posix.resolve(\"/\", workspaceBase);\n }\n\n private normalisePath(path: string): string {\n return posix.resolve(this.workspaceBase, path);\n }\n\n async readFile(path: string): Promise<string> {\n const norm = this.normalisePath(path);\n const buf = await this.sandbox.fs.downloadFile(norm);\n return buf.toString(\"utf-8\");\n }\n\n async readFileBuffer(path: string): Promise<Uint8Array> {\n const norm = this.normalisePath(path);\n const buf = await this.sandbox.fs.downloadFile(norm);\n return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);\n }\n\n async writeFile(path: string, content: string | Uint8Array): Promise<void> {\n const norm = this.normalisePath(path);\n const buf =\n typeof content === \"string\"\n ? Buffer.from(content, \"utf-8\")\n : Buffer.from(content);\n await this.sandbox.fs.uploadFile(buf, norm);\n }\n\n async appendFile(\n path: string,\n content: string | Uint8Array,\n ): Promise<void> {\n const norm = this.normalisePath(path);\n let existing: Buffer;\n try {\n existing = await this.sandbox.fs.downloadFile(norm);\n } catch {\n return this.writeFile(norm, content);\n }\n\n const addition =\n typeof content === \"string\" ? Buffer.from(content, \"utf-8\") : content;\n const merged = Buffer.concat([existing, Buffer.from(addition)]);\n await this.sandbox.fs.uploadFile(merged, norm);\n }\n\n async exists(path: string): Promise<boolean> {\n const norm = this.normalisePath(path);\n try {\n await this.sandbox.fs.getFileDetails(norm);\n return true;\n } catch {\n return false;\n }\n }\n\n async stat(path: string): Promise<FileStat> {\n const norm = this.normalisePath(path);\n const info = await this.sandbox.fs.getFileDetails(norm);\n return {\n isFile: !info.isDir,\n isDirectory: info.isDir,\n isSymbolicLink: false,\n size: info.size,\n mtime: new Date(info.modTime),\n };\n }\n\n async mkdir(\n path: string,\n _options?: { recursive?: boolean },\n ): Promise<void> {\n const norm = this.normalisePath(path);\n await this.sandbox.fs.createFolder(norm, \"755\");\n }\n\n async readdir(path: string): Promise<string[]> {\n const norm = this.normalisePath(path);\n const entries = await this.sandbox.fs.listFiles(norm);\n return entries.map((e) => e.name);\n }\n\n async readdirWithFileTypes(path: string): Promise<DirentEntry[]> {\n const norm = this.normalisePath(path);\n const entries = await this.sandbox.fs.listFiles(norm);\n return entries.map((e) => ({\n name: e.name,\n isFile: !e.isDir,\n isDirectory: e.isDir,\n isSymbolicLink: false,\n }));\n }\n\n async rm(\n path: string,\n options?: { recursive?: boolean; force?: boolean },\n ): Promise<void> {\n const norm = this.normalisePath(path);\n try {\n await this.sandbox.fs.deleteFile(norm, options?.recursive);\n } catch (err) {\n if (!options?.force) throw err;\n }\n }\n\n async cp(\n src: string,\n dest: string,\n options?: { recursive?: boolean },\n ): Promise<void> {\n const normSrc = this.normalisePath(src);\n const normDest = this.normalisePath(dest);\n const info = await this.sandbox.fs.getFileDetails(normSrc);\n if (info.isDir) {\n if (!options?.recursive) {\n throw new Error(`EISDIR: is a directory (use recursive): ${src}`);\n }\n await this.sandbox.process.executeCommand(`cp -r \"${normSrc}\" \"${normDest}\"`);\n } else {\n await this.sandbox.process.executeCommand(`cp \"${normSrc}\" \"${normDest}\"`);\n }\n }\n\n async mv(src: string, dest: string): Promise<void> {\n const normSrc = this.normalisePath(src);\n const normDest = this.normalisePath(dest);\n await this.sandbox.fs.moveFiles(normSrc, normDest);\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(this.normalisePath(base), path);\n }\n}\n","import {\n Daytona,\n type Sandbox as DaytonaSdkSandbox,\n} from \"@daytonaio/sdk\";\nimport type {\n Sandbox,\n SandboxCapabilities,\n SandboxCreateResult,\n SandboxProvider,\n SandboxSnapshot,\n ExecOptions,\n ExecResult,\n} from \"../../../lib/sandbox/types\";\nimport {\n SandboxNotFoundError,\n SandboxNotSupportedError,\n} from \"../../../lib/sandbox/types\";\nimport { DaytonaSandboxFileSystem } from \"./filesystem\";\nimport type {\n DaytonaSandbox,\n DaytonaSandboxConfig,\n DaytonaSandboxCreateOptions,\n} from \"./types\";\n\n// ============================================================================\n// DaytonaSandbox\n// ============================================================================\n\nclass DaytonaSandboxImpl implements Sandbox {\n readonly capabilities: SandboxCapabilities = {\n filesystem: true,\n execution: true,\n persistence: false,\n };\n\n readonly fs: DaytonaSandboxFileSystem;\n\n constructor(\n readonly id: string,\n private sdkSandbox: DaytonaSdkSandbox,\n workspaceBase = \"/home/daytona\",\n ) {\n this.fs = new DaytonaSandboxFileSystem(sdkSandbox, workspaceBase);\n }\n\n async exec(command: string, options?: ExecOptions): Promise<ExecResult> {\n const response = await this.sdkSandbox.process.executeCommand(\n command,\n options?.cwd,\n options?.env,\n options?.timeout,\n );\n\n return {\n exitCode: response.exitCode ?? 0,\n stdout: response.result ?? \"\",\n stderr: \"\",\n };\n }\n\n async destroy(): Promise<void> {\n await this.sdkSandbox.delete(60);\n }\n}\n\n// ============================================================================\n// DaytonaSandboxProvider\n// ============================================================================\n\nexport class DaytonaSandboxProvider\n implements SandboxProvider<DaytonaSandboxCreateOptions, DaytonaSandbox>\n{\n readonly id = \"daytona\";\n readonly capabilities: SandboxCapabilities = {\n filesystem: true,\n execution: true,\n persistence: false,\n };\n\n private client: Daytona;\n private readonly defaultWorkspaceBase: string;\n private workspaceBaseById = new Map<string, string>();\n\n constructor(config?: DaytonaSandboxConfig) {\n this.client = new Daytona(config);\n this.defaultWorkspaceBase = config?.workspaceBase ?? \"/home/daytona\";\n }\n\n async create(\n options?: DaytonaSandboxCreateOptions,\n ): Promise<SandboxCreateResult> {\n const sdkSandbox = await this.client.create(\n {\n language: options?.language,\n snapshot: options?.snapshot,\n envVars: options?.env,\n labels: options?.labels,\n autoStopInterval: options?.autoStopInterval,\n autoArchiveInterval: options?.autoArchiveInterval,\n autoDeleteInterval: options?.autoDeleteInterval,\n },\n { timeout: options?.timeout ?? 60 },\n );\n\n const workspaceBase = options?.workspaceBase ?? this.defaultWorkspaceBase;\n this.workspaceBaseById.set(sdkSandbox.id, workspaceBase);\n const sandbox = new DaytonaSandboxImpl(\n sdkSandbox.id,\n sdkSandbox,\n workspaceBase,\n );\n\n if (options?.initialFiles) {\n for (const [path, content] of Object.entries(options.initialFiles)) {\n await sandbox.fs.writeFile(path, content);\n }\n }\n\n return { sandbox };\n }\n\n async get(sandboxId: string): Promise<DaytonaSandbox> {\n try {\n const sdkSandbox = await this.client.get(sandboxId);\n const workspaceBase =\n this.workspaceBaseById.get(sandboxId) ?? this.defaultWorkspaceBase;\n return new DaytonaSandboxImpl(sdkSandbox.id, sdkSandbox, workspaceBase);\n } catch {\n throw new SandboxNotFoundError(sandboxId);\n }\n }\n\n async destroy(sandboxId: string): Promise<void> {\n try {\n const sdkSandbox = await this.client.get(sandboxId);\n await this.client.delete(sdkSandbox);\n this.workspaceBaseById.delete(sandboxId);\n } catch {\n // Already gone\n }\n }\n\n async snapshot(_sandboxId: string): Promise<SandboxSnapshot> {\n throw new SandboxNotSupportedError(\n \"snapshot (use Daytona's native snapshot API directly)\",\n );\n }\n\n async restore(_snapshot: SandboxSnapshot): Promise<never> {\n throw new SandboxNotSupportedError(\n \"restore (use Daytona's native snapshot API directly)\",\n );\n }\n}\n\n// Re-exports\nexport { DaytonaSandboxFileSystem } from \"./filesystem\";\nexport type {\n DaytonaSandbox,\n DaytonaSandboxConfig,\n DaytonaSandboxCreateOptions,\n} from \"./types\";\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as SandboxFileSystem, F as FileStat, D as DirentEntry, S as Sandbox$1, d as SandboxCreateOptions, b as SandboxProvider, c as SandboxCapabilities, e as SandboxCreateResult, f as SandboxSnapshot } from '../../../types-
|
|
1
|
+
import { a as SandboxFileSystem, F as FileStat, D as DirentEntry, S as Sandbox$1, d as SandboxCreateOptions, b as SandboxProvider, c as SandboxCapabilities, e as SandboxCreateResult, f as SandboxSnapshot } from '../../../types-BMRzfELQ.cjs';
|
|
2
2
|
import { Sandbox } from '@daytonaio/sdk';
|
|
3
3
|
import '@temporalio/common';
|
|
4
4
|
|
|
@@ -11,7 +11,9 @@ import '@temporalio/common';
|
|
|
11
11
|
*/
|
|
12
12
|
declare class DaytonaSandboxFileSystem implements SandboxFileSystem {
|
|
13
13
|
private sandbox;
|
|
14
|
-
|
|
14
|
+
readonly workspaceBase: string;
|
|
15
|
+
constructor(sandbox: Sandbox, workspaceBase?: string);
|
|
16
|
+
private normalisePath;
|
|
15
17
|
readFile(path: string): Promise<string>;
|
|
16
18
|
readFileBuffer(path: string): Promise<Uint8Array>;
|
|
17
19
|
writeFile(path: string, content: string | Uint8Array): Promise<void>;
|
|
@@ -45,6 +47,8 @@ interface DaytonaSandboxConfig {
|
|
|
45
47
|
apiKey?: string;
|
|
46
48
|
apiUrl?: string;
|
|
47
49
|
target?: string;
|
|
50
|
+
/** Default base path for resolving relative filesystem paths. */
|
|
51
|
+
workspaceBase?: string;
|
|
48
52
|
}
|
|
49
53
|
interface DaytonaSandboxCreateOptions extends SandboxCreateOptions {
|
|
50
54
|
/** Programming language runtime. Defaults to "python". */
|
|
@@ -69,12 +73,16 @@ interface DaytonaSandboxCreateOptions extends SandboxCreateOptions {
|
|
|
69
73
|
labels?: Record<string, string>;
|
|
70
74
|
/** Timeout in seconds for sandbox creation. Default 60. */
|
|
71
75
|
timeout?: number;
|
|
76
|
+
/** Base path for resolving relative filesystem paths in this sandbox. */
|
|
77
|
+
workspaceBase?: string;
|
|
72
78
|
}
|
|
73
79
|
|
|
74
80
|
declare class DaytonaSandboxProvider implements SandboxProvider<DaytonaSandboxCreateOptions, DaytonaSandbox> {
|
|
75
81
|
readonly id = "daytona";
|
|
76
82
|
readonly capabilities: SandboxCapabilities;
|
|
77
83
|
private client;
|
|
84
|
+
private readonly defaultWorkspaceBase;
|
|
85
|
+
private workspaceBaseById;
|
|
78
86
|
constructor(config?: DaytonaSandboxConfig);
|
|
79
87
|
create(options?: DaytonaSandboxCreateOptions): Promise<SandboxCreateResult>;
|
|
80
88
|
get(sandboxId: string): Promise<DaytonaSandbox>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as SandboxFileSystem, F as FileStat, D as DirentEntry, S as Sandbox$1, d as SandboxCreateOptions, b as SandboxProvider, c as SandboxCapabilities, e as SandboxCreateResult, f as SandboxSnapshot } from '../../../types-
|
|
1
|
+
import { a as SandboxFileSystem, F as FileStat, D as DirentEntry, S as Sandbox$1, d as SandboxCreateOptions, b as SandboxProvider, c as SandboxCapabilities, e as SandboxCreateResult, f as SandboxSnapshot } from '../../../types-BMRzfELQ.js';
|
|
2
2
|
import { Sandbox } from '@daytonaio/sdk';
|
|
3
3
|
import '@temporalio/common';
|
|
4
4
|
|
|
@@ -11,7 +11,9 @@ import '@temporalio/common';
|
|
|
11
11
|
*/
|
|
12
12
|
declare class DaytonaSandboxFileSystem implements SandboxFileSystem {
|
|
13
13
|
private sandbox;
|
|
14
|
-
|
|
14
|
+
readonly workspaceBase: string;
|
|
15
|
+
constructor(sandbox: Sandbox, workspaceBase?: string);
|
|
16
|
+
private normalisePath;
|
|
15
17
|
readFile(path: string): Promise<string>;
|
|
16
18
|
readFileBuffer(path: string): Promise<Uint8Array>;
|
|
17
19
|
writeFile(path: string, content: string | Uint8Array): Promise<void>;
|
|
@@ -45,6 +47,8 @@ interface DaytonaSandboxConfig {
|
|
|
45
47
|
apiKey?: string;
|
|
46
48
|
apiUrl?: string;
|
|
47
49
|
target?: string;
|
|
50
|
+
/** Default base path for resolving relative filesystem paths. */
|
|
51
|
+
workspaceBase?: string;
|
|
48
52
|
}
|
|
49
53
|
interface DaytonaSandboxCreateOptions extends SandboxCreateOptions {
|
|
50
54
|
/** Programming language runtime. Defaults to "python". */
|
|
@@ -69,12 +73,16 @@ interface DaytonaSandboxCreateOptions extends SandboxCreateOptions {
|
|
|
69
73
|
labels?: Record<string, string>;
|
|
70
74
|
/** Timeout in seconds for sandbox creation. Default 60. */
|
|
71
75
|
timeout?: number;
|
|
76
|
+
/** Base path for resolving relative filesystem paths in this sandbox. */
|
|
77
|
+
workspaceBase?: string;
|
|
72
78
|
}
|
|
73
79
|
|
|
74
80
|
declare class DaytonaSandboxProvider implements SandboxProvider<DaytonaSandboxCreateOptions, DaytonaSandbox> {
|
|
75
81
|
readonly id = "daytona";
|
|
76
82
|
readonly capabilities: SandboxCapabilities;
|
|
77
83
|
private client;
|
|
84
|
+
private readonly defaultWorkspaceBase;
|
|
85
|
+
private workspaceBaseById;
|
|
78
86
|
constructor(config?: DaytonaSandboxConfig);
|
|
79
87
|
create(options?: DaytonaSandboxCreateOptions): Promise<SandboxCreateResult>;
|
|
80
88
|
get(sandboxId: string): Promise<DaytonaSandbox>;
|