@loopstack/sandbox-filesystem 0.5.0 → 0.5.1

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.
Files changed (2) hide show
  1. package/README.md +90 -133
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -30,11 +30,11 @@ See [SETUP.md](./SETUP.md) for installation and setup instructions.
30
30
 
31
31
  ## Usage
32
32
 
33
- Inject the tools in your workflow class using the @InjectTool() decorator:
33
+ Inject the tools in your workflow class using the `@InjectTool()` decorator:
34
34
 
35
35
  ```typescript
36
36
  import { z } from 'zod';
37
- import { InjectTool, Input, State, Workflow } from '@loopstack/common';
37
+ import { BaseWorkflow, Final, Initial, InjectTool, ToolResult, Transition, Workflow } from '@loopstack/common';
38
38
  import {
39
39
  SandboxCreateDirectory,
40
40
  SandboxDelete,
@@ -48,24 +48,11 @@ import { SandboxDestroy, SandboxInit } from '@loopstack/sandbox-tool';
48
48
 
49
49
  @Workflow({
50
50
  uiConfig: __dirname + '/my.ui.yaml',
51
+ schema: z.object({
52
+ outputDir: z.string().default(process.cwd() + '/out'),
53
+ }),
51
54
  })
52
- export class MyWorkflow {
53
- @Input({
54
- schema: z.object({
55
- outputDir: z.string().default(process.cwd() + '/out'),
56
- }),
57
- })
58
- args: { outputDir: string };
59
-
60
- @State({
61
- schema: z.object({
62
- containerId: z.string().optional(),
63
- fileContent: z.string().optional(),
64
- fileList: z.array(z.any()).optional(),
65
- }),
66
- })
67
- state: { containerId: string; fileContent: string; fileList: any[] };
68
-
55
+ export class MyWorkflow extends BaseWorkflow<{ outputDir: string }> {
69
56
  // Sandbox lifecycle tools (from @loopstack/sandbox-tool)
70
57
  @InjectTool() sandboxInit: SandboxInit;
71
58
  @InjectTool() sandboxDestroy: SandboxDestroy;
@@ -78,119 +65,89 @@ export class MyWorkflow {
78
65
  @InjectTool() sandboxDelete: SandboxDelete;
79
66
  @InjectTool() sandboxExists: SandboxExists;
80
67
  @InjectTool() sandboxFileInfo: SandboxFileInfo;
81
- }
82
- ```
83
68
 
84
- And use them in your YAML workflow configuration:
85
-
86
- ```yaml
87
- # src/my.ui.yaml
88
- transitions:
89
- # Initialize the sandbox container (required before filesystem operations)
90
- - id: init_sandbox
91
- from: start
92
- to: sandbox_ready
93
- call:
94
- - tool: sandboxInit
95
- args:
96
- containerId: my-sandbox
97
- imageName: node:18
98
- containerName: my-filesystem-sandbox
99
- projectOutPath: ${{ args.outputDir }}
100
- rootPath: workspace
101
- assign:
102
- containerId: ${{ result.data.containerId }}
103
-
104
- # Create a directory
105
- - id: create_dir
106
- from: sandbox_ready
107
- to: dir_created
108
- call:
109
- - tool: sandboxCreateDirectory
110
- args:
111
- containerId: ${{ state.containerId }}
112
- path: /workspace
113
- recursive: true
114
-
115
- # Write a file
116
- - id: write_file
117
- from: dir_created
118
- to: file_written
119
- call:
120
- - tool: sandboxWriteFile
121
- args:
122
- containerId: ${{ state.containerId }}
123
- path: /workspace/result.txt
124
- content: 'Hello from sandbox!'
125
- encoding: utf8
126
- createParentDirs: true
127
-
128
- # Read the file
129
- - id: read_file
130
- from: file_written
131
- to: file_read
132
- call:
133
- - tool: sandboxReadFile
134
- args:
135
- containerId: ${{ state.containerId }}
136
- path: /workspace/result.txt
137
- encoding: utf8
138
- assign:
139
- fileContent: ${{ result.data.content }}
140
-
141
- # List directory contents
142
- - id: list_dir
143
- from: file_read
144
- to: dir_listed
145
- call:
146
- - tool: sandboxListDirectory
147
- args:
148
- containerId: ${{ state.containerId }}
149
- path: /workspace
150
- recursive: false
151
- assign:
152
- fileList: ${{ result.data.entries }}
153
-
154
- # Check file existence
155
- - id: check_exists
156
- from: dir_listed
157
- to: existence_checked
158
- call:
159
- - tool: sandboxExists
160
- args:
161
- containerId: ${{ state.containerId }}
162
- path: /workspace/result.txt
163
-
164
- # Get file info
165
- - id: get_info
166
- from: existence_checked
167
- to: info_retrieved
168
- call:
169
- - tool: sandboxFileInfo
170
- args:
171
- containerId: ${{ state.containerId }}
172
- path: /workspace/result.txt
173
-
174
- # Delete the file
175
- - id: delete_file
176
- from: info_retrieved
177
- to: file_deleted
178
- call:
179
- - tool: sandboxDelete
180
- args:
181
- containerId: ${{ state.containerId }}
182
- path: /workspace/result.txt
183
- force: true
184
-
185
- # Destroy the sandbox container (cleanup)
186
- - id: destroy_sandbox
187
- from: file_deleted
188
- to: end
189
- call:
190
- - tool: sandboxDestroy
191
- args:
192
- containerId: ${{ state.containerId }}
193
- removeContainer: true
69
+ containerId?: string;
70
+ fileContent?: string;
71
+
72
+ // Initialize the sandbox container (required before filesystem operations)
73
+ @Initial({ to: 'sandbox_ready' })
74
+ async initSandbox(args: { outputDir: string }) {
75
+ const result = await this.sandboxInit.call({
76
+ containerId: 'my-sandbox',
77
+ imageName: 'node:18',
78
+ containerName: 'my-filesystem-sandbox',
79
+ projectOutPath: args.outputDir,
80
+ rootPath: 'workspace',
81
+ });
82
+
83
+ this.containerId = result.data!.containerId;
84
+ }
85
+
86
+ // Create a directory and write a file
87
+ @Transition({ from: 'sandbox_ready', to: 'file_written' })
88
+ async writeFile() {
89
+ await this.sandboxCreateDirectory.call({
90
+ containerId: this.containerId!,
91
+ path: '/workspace/output',
92
+ recursive: true,
93
+ });
94
+
95
+ await this.sandboxWriteFile.call({
96
+ containerId: this.containerId!,
97
+ path: '/workspace/output/result.txt',
98
+ content: 'Hello from sandbox!',
99
+ encoding: 'utf8',
100
+ createParentDirs: true,
101
+ });
102
+ }
103
+
104
+ // Read the file back
105
+ @Transition({ from: 'file_written', to: 'file_read' })
106
+ async readFile() {
107
+ const result = await this.sandboxReadFile.call({
108
+ containerId: this.containerId!,
109
+ path: '/workspace/output/result.txt',
110
+ encoding: 'utf8',
111
+ });
112
+
113
+ this.fileContent = result.data!.content;
114
+ }
115
+
116
+ // List directory, check existence, get info
117
+ @Transition({ from: 'file_read', to: 'inspected' })
118
+ async inspectFiles() {
119
+ await this.sandboxListDirectory.call({
120
+ containerId: this.containerId!,
121
+ path: '/workspace/output',
122
+ recursive: false,
123
+ });
124
+
125
+ await this.sandboxExists.call({
126
+ containerId: this.containerId!,
127
+ path: '/workspace/output/result.txt',
128
+ });
129
+
130
+ await this.sandboxFileInfo.call({
131
+ containerId: this.containerId!,
132
+ path: '/workspace/output/result.txt',
133
+ });
134
+ }
135
+
136
+ // Clean up and destroy the sandbox
137
+ @Final({ from: 'inspected' })
138
+ async cleanup() {
139
+ await this.sandboxDelete.call({
140
+ containerId: this.containerId!,
141
+ path: '/workspace/output/result.txt',
142
+ force: true,
143
+ });
144
+
145
+ await this.sandboxDestroy.call({
146
+ containerId: this.containerId!,
147
+ removeContainer: true,
148
+ });
149
+ }
150
+ }
194
151
  ```
195
152
 
196
153
  ## About
@@ -201,6 +158,6 @@ License: Apache-2.0
201
158
 
202
159
  ### Additional Resources:
203
160
 
204
- - [Loopstack Documentation](https://loopstack.ai)
205
- - [Getting Started with Loopstack](https://loopstack.ai)
161
+ - [Loopstack Documentation](https://loopstack.ai/docs)
162
+ - [Getting Started with Loopstack](https://loopstack.ai/docs/getting-started)
206
163
  - For more examples how to use this tool look for `@loopstack/sandbox-filesystem` in the [Loopstack Registry](https://loopstack.ai/registry)
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "filesystem",
8
8
  "sandbox"
9
9
  ],
10
- "version": "0.5.0",
10
+ "version": "0.5.1",
11
11
  "license": "Apache-2.0",
12
12
  "author": {
13
13
  "name": "Tobias Blättermann, Jakob Klippel"
@@ -28,7 +28,7 @@
28
28
  },
29
29
  "dependencies": {
30
30
  "@loopstack/common": "^0.25.0",
31
- "@loopstack/sandbox-tool": "^0.5.0",
31
+ "@loopstack/sandbox-tool": "^0.5.1",
32
32
  "@nestjs/common": "^11.1.14",
33
33
  "zod": "^4.3.6"
34
34
  },