@loopstack/sandbox-filesystem 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +234 -0
  2. package/dist/index.d.ts +8 -0
  3. package/dist/index.js +25 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/sandbox-filesystem.module.d.ts +2 -0
  6. package/dist/sandbox-filesystem.module.js +46 -0
  7. package/dist/sandbox-filesystem.module.js.map +1 -0
  8. package/dist/tools/sandbox-create-directory.tool.d.ts +19 -0
  9. package/dist/tools/sandbox-create-directory.tool.js +77 -0
  10. package/dist/tools/sandbox-create-directory.tool.js.map +1 -0
  11. package/dist/tools/sandbox-delete.tool.d.ts +20 -0
  12. package/dist/tools/sandbox-delete.tool.js +77 -0
  13. package/dist/tools/sandbox-delete.tool.js.map +1 -0
  14. package/dist/tools/sandbox-exists.tool.d.ts +20 -0
  15. package/dist/tools/sandbox-exists.tool.js +89 -0
  16. package/dist/tools/sandbox-exists.tool.js.map +1 -0
  17. package/dist/tools/sandbox-file-info.tool.d.ts +27 -0
  18. package/dist/tools/sandbox-file-info.tool.js +96 -0
  19. package/dist/tools/sandbox-file-info.tool.js.map +1 -0
  20. package/dist/tools/sandbox-list-directory.tool.d.ts +26 -0
  21. package/dist/tools/sandbox-list-directory.tool.js +102 -0
  22. package/dist/tools/sandbox-list-directory.tool.js.map +1 -0
  23. package/dist/tools/sandbox-read-file.tool.d.ts +22 -0
  24. package/dist/tools/sandbox-read-file.tool.js +71 -0
  25. package/dist/tools/sandbox-read-file.tool.js.map +1 -0
  26. package/dist/tools/sandbox-write-file.tool.d.ts +24 -0
  27. package/dist/tools/sandbox-write-file.tool.js +96 -0
  28. package/dist/tools/sandbox-write-file.tool.js.map +1 -0
  29. package/package.json +51 -0
  30. package/src/index.ts +8 -0
  31. package/src/sandbox-filesystem.module.ts +48 -0
  32. package/src/tools/sandbox-create-directory.tool.ts +93 -0
  33. package/src/tools/sandbox-delete.tool.ts +87 -0
  34. package/src/tools/sandbox-exists.tool.ts +102 -0
  35. package/src/tools/sandbox-file-info.tool.ts +119 -0
  36. package/src/tools/sandbox-list-directory.tool.ts +131 -0
  37. package/src/tools/sandbox-read-file.tool.ts +82 -0
  38. package/src/tools/sandbox-write-file.tool.ts +121 -0
package/README.md ADDED
@@ -0,0 +1,234 @@
1
+ # @loopstack/sandbox-filesystem
2
+
3
+ > A module for the [Loopstack AI](https://loopstack.ai) automation framework.
4
+
5
+ This module provides secure, controlled filesystem operations within Docker sandbox environments for Loopstack workflows.
6
+
7
+ ## Overview
8
+
9
+ The Sandbox Filesystem module enables workflows to perform file and directory operations in isolated Docker containers. It provides a comprehensive set of tools for reading, writing, listing, and managing files within sandbox environments, ensuring secure execution of filesystem operations.
10
+
11
+ By using this module, you'll be able to:
12
+
13
+ - Create, read, update, and delete files within sandbox containers
14
+ - List directory contents with recursive options
15
+ - Create directories with automatic parent directory creation
16
+ - Get detailed file and directory metadata
17
+ - Check for file/directory existence
18
+ - Handle both text and binary file content using UTF-8 or base64 encoding
19
+ - Perform all operations within the security boundary of Docker containers
20
+
21
+ This module is essential for workflows that need to manipulate files in isolated environments, such as code execution sandboxes, build environments, or secure file processing pipelines.
22
+
23
+ **Note:** This module requires `@loopstack/sandbox-tool` as a dependency. The Docker sandbox containers must be initialized using `SandboxInit` and destroyed using `SandboxDestroy` from the `@loopstack/sandbox-tool` module. The filesystem tools operate on containers that have been created by the sandbox-tool.
24
+
25
+ ## Installation
26
+
27
+ You can add this module using the `loopstack` cli or via `npm`.
28
+
29
+ ### a) Add Sources via `loopstack add`
30
+
31
+ ```bash
32
+ loopstack add @loopstack/sandbox-filesystem
33
+ ```
34
+
35
+ This command copies the source files into your `src` directory.
36
+
37
+ - It is a great way to explore the code to learn new concepts or add own customizations
38
+ - It will set up the module for you, so you do not need to manually update your application
39
+
40
+ ### b) Install via `npm install`(recommended)
41
+
42
+ ```bash
43
+ npm install --save @loopstack/sandbox-filesystem
44
+ ```
45
+
46
+ Use npm install if you want to use and maintain the module as node dependency.
47
+
48
+ - Use this, if you do not need to make changes to the code or want to review the source code.
49
+
50
+ ## Setup
51
+
52
+ ### 1. Manual setup (optional)
53
+
54
+ > This step is automatically done for you when using the `loopstack add` command.
55
+
56
+ - Add `SandboxFilesystemModule` to the imports of `default.module.ts` or any other custom module.
57
+
58
+ See here for more information about working with [Modules](https://loopstack.ai/docs/building-with-loopstack/creating-a-module) and [Workspaces](https://loopstack.ai/docs/building-with-loopstack/creating-workspaces)
59
+
60
+ ### 2. Use in Your Workflow
61
+
62
+ Inject the tools in your workflow class using the @Tool() decorator:
63
+
64
+ ```typescript
65
+ import { Injectable } from '@nestjs/common';
66
+ import { z } from 'zod';
67
+ import { BlockConfig, Tool, WithArguments, WithState } from '@loopstack/common';
68
+ import { WorkflowBase } from '@loopstack/core';
69
+ import {
70
+ SandboxCreateDirectory,
71
+ SandboxDelete,
72
+ SandboxExists,
73
+ SandboxFileInfo,
74
+ SandboxListDirectory,
75
+ SandboxReadFile,
76
+ SandboxWriteFile,
77
+ } from '@loopstack/sandbox-filesystem';
78
+ import { SandboxDestroy, SandboxInit } from '@loopstack/sandbox-tool';
79
+
80
+ @Injectable()
81
+ @BlockConfig({
82
+ configFile: __dirname + '/my.workflow.yaml',
83
+ })
84
+ @WithArguments(
85
+ z.object({
86
+ outputDir: z.string().default(process.cwd() + '/out'),
87
+ }),
88
+ )
89
+ @WithState(
90
+ z.object({
91
+ containerId: z.string().optional(),
92
+ fileContent: z.string().optional(),
93
+ fileList: z.array(z.any()).optional(),
94
+ }),
95
+ )
96
+ export class MyWorkflow extends WorkflowBase {
97
+ // Sandbox lifecycle tools (from @loopstack/sandbox-tool)
98
+ @Tool() sandboxInit: SandboxInit;
99
+ @Tool() sandboxDestroy: SandboxDestroy;
100
+
101
+ // Filesystem tools (from @loopstack/sandbox-filesystem)
102
+ @Tool() sandboxWriteFile: SandboxWriteFile;
103
+ @Tool() sandboxReadFile: SandboxReadFile;
104
+ @Tool() sandboxListDirectory: SandboxListDirectory;
105
+ @Tool() sandboxCreateDirectory: SandboxCreateDirectory;
106
+ @Tool() sandboxDelete: SandboxDelete;
107
+ @Tool() sandboxExists: SandboxExists;
108
+ @Tool() sandboxFileInfo: SandboxFileInfo;
109
+ }
110
+ ```
111
+
112
+ And use them in your YAML workflow configuration:
113
+
114
+ ```yaml
115
+ # src/my.workflow.yaml
116
+ transitions:
117
+ # Initialize the sandbox container (required before filesystem operations)
118
+ - id: init_sandbox
119
+ from: start
120
+ to: sandbox_ready
121
+ call:
122
+ - tool: sandboxInit
123
+ args:
124
+ containerId: my-sandbox
125
+ imageName: node:18
126
+ containerName: my-filesystem-sandbox
127
+ projectOutPath: ${ args.outputDir }
128
+ rootPath: workspace
129
+ assign:
130
+ containerId: ${ result.data.containerId }
131
+
132
+ # Create a directory
133
+ - id: create_dir
134
+ from: sandbox_ready
135
+ to: dir_created
136
+ call:
137
+ - tool: sandboxCreateDirectory
138
+ args:
139
+ containerId: ${ containerId }
140
+ path: /workspace
141
+ recursive: true
142
+
143
+ # Write a file
144
+ - id: write_file
145
+ from: dir_created
146
+ to: file_written
147
+ call:
148
+ - tool: sandboxWriteFile
149
+ args:
150
+ containerId: ${ containerId }
151
+ path: /workspace/result.txt
152
+ content: 'Hello from sandbox!'
153
+ encoding: utf8
154
+ createParentDirs: true
155
+
156
+ # Read the file
157
+ - id: read_file
158
+ from: file_written
159
+ to: file_read
160
+ call:
161
+ - tool: sandboxReadFile
162
+ args:
163
+ containerId: ${ containerId }
164
+ path: /workspace/result.txt
165
+ encoding: utf8
166
+ assign:
167
+ fileContent: ${ result.data.content }
168
+
169
+ # List directory contents
170
+ - id: list_dir
171
+ from: file_read
172
+ to: dir_listed
173
+ call:
174
+ - tool: sandboxListDirectory
175
+ args:
176
+ containerId: ${ containerId }
177
+ path: /workspace
178
+ recursive: false
179
+ assign:
180
+ fileList: ${ result.data.entries }
181
+
182
+ # Check file existence
183
+ - id: check_exists
184
+ from: dir_listed
185
+ to: existence_checked
186
+ call:
187
+ - tool: sandboxExists
188
+ args:
189
+ containerId: ${ containerId }
190
+ path: /workspace/result.txt
191
+
192
+ # Get file info
193
+ - id: get_info
194
+ from: existence_checked
195
+ to: info_retrieved
196
+ call:
197
+ - tool: sandboxFileInfo
198
+ args:
199
+ containerId: ${ containerId }
200
+ path: /workspace/result.txt
201
+
202
+ # Delete the file
203
+ - id: delete_file
204
+ from: info_retrieved
205
+ to: file_deleted
206
+ call:
207
+ - tool: sandboxDelete
208
+ args:
209
+ containerId: ${ containerId }
210
+ path: /workspace/result.txt
211
+ force: true
212
+
213
+ # Destroy the sandbox container (cleanup)
214
+ - id: destroy_sandbox
215
+ from: file_deleted
216
+ to: end
217
+ call:
218
+ - tool: sandboxDestroy
219
+ args:
220
+ containerId: ${ containerId }
221
+ removeContainer: true
222
+ ```
223
+
224
+ ## About
225
+
226
+ Author: Tobias Blättermann, Jakob Klippel
227
+
228
+ License: Apache-2.0
229
+
230
+ ### Additional Resources:
231
+
232
+ - [Loopstack Documentation](https://loopstack.ai)
233
+ - [Getting Started with Loopstack](https://loopstack.ai)
234
+ - For more examples how to use this tool look for `@loopstack/sandbox-filesystem` in the [Loopstack Registry](https://loopstack.ai/registry)
@@ -0,0 +1,8 @@
1
+ export * from './sandbox-filesystem.module';
2
+ export * from './tools/sandbox-read-file.tool';
3
+ export * from './tools/sandbox-write-file.tool';
4
+ export * from './tools/sandbox-list-directory.tool';
5
+ export * from './tools/sandbox-create-directory.tool';
6
+ export * from './tools/sandbox-delete.tool';
7
+ export * from './tools/sandbox-exists.tool';
8
+ export * from './tools/sandbox-file-info.tool';
package/dist/index.js ADDED
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./sandbox-filesystem.module"), exports);
18
+ __exportStar(require("./tools/sandbox-read-file.tool"), exports);
19
+ __exportStar(require("./tools/sandbox-write-file.tool"), exports);
20
+ __exportStar(require("./tools/sandbox-list-directory.tool"), exports);
21
+ __exportStar(require("./tools/sandbox-create-directory.tool"), exports);
22
+ __exportStar(require("./tools/sandbox-delete.tool"), exports);
23
+ __exportStar(require("./tools/sandbox-exists.tool"), exports);
24
+ __exportStar(require("./tools/sandbox-file-info.tool"), exports);
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8DAA4C;AAC5C,iEAA+C;AAC/C,kEAAgD;AAChD,sEAAoD;AACpD,wEAAsD;AACtD,8DAA4C;AAC5C,8DAA4C;AAC5C,iEAA+C"}
@@ -0,0 +1,2 @@
1
+ export declare class SandboxFilesystemModule {
2
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.SandboxFilesystemModule = void 0;
10
+ const common_1 = require("@nestjs/common");
11
+ const core_1 = require("@loopstack/core");
12
+ const sandbox_tool_1 = require("@loopstack/sandbox-tool");
13
+ const sandbox_create_directory_tool_1 = require("./tools/sandbox-create-directory.tool");
14
+ const sandbox_delete_tool_1 = require("./tools/sandbox-delete.tool");
15
+ const sandbox_exists_tool_1 = require("./tools/sandbox-exists.tool");
16
+ const sandbox_file_info_tool_1 = require("./tools/sandbox-file-info.tool");
17
+ const sandbox_list_directory_tool_1 = require("./tools/sandbox-list-directory.tool");
18
+ const sandbox_read_file_tool_1 = require("./tools/sandbox-read-file.tool");
19
+ const sandbox_write_file_tool_1 = require("./tools/sandbox-write-file.tool");
20
+ let SandboxFilesystemModule = class SandboxFilesystemModule {
21
+ };
22
+ exports.SandboxFilesystemModule = SandboxFilesystemModule;
23
+ exports.SandboxFilesystemModule = SandboxFilesystemModule = __decorate([
24
+ (0, common_1.Module)({
25
+ imports: [core_1.LoopCoreModule, sandbox_tool_1.SandboxToolModule],
26
+ providers: [
27
+ sandbox_read_file_tool_1.SandboxReadFile,
28
+ sandbox_write_file_tool_1.SandboxWriteFile,
29
+ sandbox_list_directory_tool_1.SandboxListDirectory,
30
+ sandbox_create_directory_tool_1.SandboxCreateDirectory,
31
+ sandbox_delete_tool_1.SandboxDelete,
32
+ sandbox_exists_tool_1.SandboxExists,
33
+ sandbox_file_info_tool_1.SandboxFileInfo,
34
+ ],
35
+ exports: [
36
+ sandbox_read_file_tool_1.SandboxReadFile,
37
+ sandbox_write_file_tool_1.SandboxWriteFile,
38
+ sandbox_list_directory_tool_1.SandboxListDirectory,
39
+ sandbox_create_directory_tool_1.SandboxCreateDirectory,
40
+ sandbox_delete_tool_1.SandboxDelete,
41
+ sandbox_exists_tool_1.SandboxExists,
42
+ sandbox_file_info_tool_1.SandboxFileInfo,
43
+ ],
44
+ })
45
+ ], SandboxFilesystemModule);
46
+ //# sourceMappingURL=sandbox-filesystem.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox-filesystem.module.js","sourceRoot":"","sources":["../src/sandbox-filesystem.module.ts"],"names":[],"mappings":";;;;;;;;;AAeA,2CAAwC;AACxC,0CAAiD;AACjD,0DAA4D;AAC5D,yFAA+E;AAC/E,qEAA4D;AAC5D,qEAA4D;AAC5D,2EAAiE;AACjE,qFAA2E;AAC3E,2EAAiE;AACjE,6EAAmE;AAuB5D,IAAM,uBAAuB,GAA7B,MAAM,uBAAuB;CAAG,CAAA;AAA1B,0DAAuB;kCAAvB,uBAAuB;IArBnC,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,qBAAc,EAAE,gCAAiB,CAAC;QAC5C,SAAS,EAAE;YACT,wCAAe;YACf,0CAAgB;YAChB,kDAAoB;YACpB,sDAAsB;YACtB,mCAAa;YACb,mCAAa;YACb,wCAAe;SAChB;QACD,OAAO,EAAE;YACP,wCAAe;YACf,0CAAgB;YAChB,kDAAoB;YACpB,sDAAsB;YACtB,mCAAa;YACb,mCAAa;YACb,wCAAe;SAChB;KACF,CAAC;GACW,uBAAuB,CAAG"}
@@ -0,0 +1,19 @@
1
+ import { z } from 'zod';
2
+ import { ToolResult } from '@loopstack/common';
3
+ import { ToolBase, WorkflowExecution } from '@loopstack/core';
4
+ declare const propertiesSchema: z.ZodObject<{
5
+ containerId: z.ZodString;
6
+ path: z.ZodString;
7
+ recursive: z.ZodDefault<z.ZodBoolean>;
8
+ }, z.core.$strict>;
9
+ type SandboxCreateDirectoryArgs = z.infer<typeof propertiesSchema>;
10
+ interface SandboxCreateDirectoryResult {
11
+ path: string;
12
+ created: boolean;
13
+ }
14
+ export declare class SandboxCreateDirectory extends ToolBase<SandboxCreateDirectoryArgs> {
15
+ private readonly logger;
16
+ private sandboxCommand;
17
+ execute(args: SandboxCreateDirectoryArgs, _ctx: WorkflowExecution): Promise<ToolResult<SandboxCreateDirectoryResult>>;
18
+ }
19
+ export {};
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var SandboxCreateDirectory_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.SandboxCreateDirectory = void 0;
14
+ const common_1 = require("@nestjs/common");
15
+ const zod_1 = require("zod");
16
+ const common_2 = require("@loopstack/common");
17
+ const core_1 = require("@loopstack/core");
18
+ const sandbox_tool_1 = require("@loopstack/sandbox-tool");
19
+ const propertiesSchema = zod_1.z
20
+ .object({
21
+ containerId: zod_1.z.string().describe('The ID of the container to create the directory in'),
22
+ path: zod_1.z.string().describe('The path of the directory to create'),
23
+ recursive: zod_1.z.boolean().default(true).describe("Whether to create parent directories if they don't exist"),
24
+ })
25
+ .strict();
26
+ let SandboxCreateDirectory = SandboxCreateDirectory_1 = class SandboxCreateDirectory extends core_1.ToolBase {
27
+ logger = new common_1.Logger(SandboxCreateDirectory_1.name);
28
+ sandboxCommand;
29
+ async execute(args, _ctx) {
30
+ const { containerId, path: dirPath, recursive } = args;
31
+ this.logger.debug(`Creating directory ${dirPath} in container ${containerId} (recursive: ${recursive})`);
32
+ const mkdirArgs = recursive ? ['-p', dirPath] : [dirPath];
33
+ const result = await this.sandboxCommand.execute({
34
+ containerId,
35
+ executable: 'mkdir',
36
+ args: mkdirArgs,
37
+ workingDirectory: '/',
38
+ timeout: 10000,
39
+ });
40
+ if (!result.data) {
41
+ this.logger.error(`Failed to create directory ${dirPath}: No result data`);
42
+ throw new Error(`Failed to create directory ${dirPath}: No result data`);
43
+ }
44
+ const alreadyExists = result.data.exitCode !== 0 && result.data.stderr.includes('File exists');
45
+ if (result.data.exitCode !== 0 && !alreadyExists) {
46
+ this.logger.error(`Failed to create directory ${dirPath}: ${result.data.stderr || 'Unknown error'}`);
47
+ throw new Error(`Failed to create directory ${dirPath}: ${result.data.stderr || 'Unknown error'}`);
48
+ }
49
+ if (alreadyExists) {
50
+ this.logger.debug(`Directory ${dirPath} already exists`);
51
+ }
52
+ else {
53
+ this.logger.log(`Successfully created directory ${dirPath} in container ${containerId}`);
54
+ }
55
+ return {
56
+ data: {
57
+ path: dirPath,
58
+ created: result.data.exitCode === 0,
59
+ },
60
+ };
61
+ }
62
+ };
63
+ exports.SandboxCreateDirectory = SandboxCreateDirectory;
64
+ __decorate([
65
+ (0, common_2.Tool)(),
66
+ __metadata("design:type", sandbox_tool_1.SandboxCommand)
67
+ ], SandboxCreateDirectory.prototype, "sandboxCommand", void 0);
68
+ exports.SandboxCreateDirectory = SandboxCreateDirectory = SandboxCreateDirectory_1 = __decorate([
69
+ (0, common_1.Injectable)(),
70
+ (0, common_2.BlockConfig)({
71
+ config: {
72
+ description: 'Create a directory in a sandbox container',
73
+ },
74
+ }),
75
+ (0, common_2.WithArguments)(propertiesSchema)
76
+ ], SandboxCreateDirectory);
77
+ //# sourceMappingURL=sandbox-create-directory.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox-create-directory.tool.js","sourceRoot":"","sources":["../../src/tools/sandbox-create-directory.tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { z } from 'zod';
2
+ import { ToolResult } from '@loopstack/common';
3
+ import { ToolBase, WorkflowExecution } from '@loopstack/core';
4
+ declare const propertiesSchema: z.ZodObject<{
5
+ containerId: z.ZodString;
6
+ path: z.ZodString;
7
+ recursive: z.ZodDefault<z.ZodBoolean>;
8
+ force: z.ZodDefault<z.ZodBoolean>;
9
+ }, z.core.$strict>;
10
+ type SandboxDeleteArgs = z.infer<typeof propertiesSchema>;
11
+ interface SandboxDeleteResult {
12
+ path: string;
13
+ deleted: boolean;
14
+ }
15
+ export declare class SandboxDelete extends ToolBase<SandboxDeleteArgs> {
16
+ private readonly logger;
17
+ private sandboxCommand;
18
+ execute(args: SandboxDeleteArgs, _ctx: WorkflowExecution): Promise<ToolResult<SandboxDeleteResult>>;
19
+ }
20
+ export {};
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var SandboxDelete_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.SandboxDelete = void 0;
14
+ const common_1 = require("@nestjs/common");
15
+ const zod_1 = require("zod");
16
+ const common_2 = require("@loopstack/common");
17
+ const core_1 = require("@loopstack/core");
18
+ const sandbox_tool_1 = require("@loopstack/sandbox-tool");
19
+ const propertiesSchema = zod_1.z
20
+ .object({
21
+ containerId: zod_1.z.string().describe('The ID of the container to delete the file/directory from'),
22
+ path: zod_1.z.string().describe('The path to the file or directory to delete'),
23
+ recursive: zod_1.z.boolean().default(false).describe('Whether to recursively delete directories and their contents'),
24
+ force: zod_1.z.boolean().default(false).describe('Whether to force deletion without prompting for confirmation'),
25
+ })
26
+ .strict();
27
+ let SandboxDelete = SandboxDelete_1 = class SandboxDelete extends core_1.ToolBase {
28
+ logger = new common_1.Logger(SandboxDelete_1.name);
29
+ sandboxCommand;
30
+ async execute(args, _ctx) {
31
+ const { containerId, path: targetPath, recursive, force } = args;
32
+ this.logger.debug(`Deleting ${targetPath} in container ${containerId} (recursive: ${recursive}, force: ${force})`);
33
+ const rmArgs = [];
34
+ if (recursive)
35
+ rmArgs.push('-r');
36
+ if (force)
37
+ rmArgs.push('-f');
38
+ rmArgs.push(targetPath);
39
+ const result = await this.sandboxCommand.execute({
40
+ containerId,
41
+ executable: 'rm',
42
+ args: rmArgs,
43
+ workingDirectory: '/',
44
+ timeout: 30000,
45
+ });
46
+ if (!result.data) {
47
+ this.logger.error(`Failed to delete ${targetPath}: No result data`);
48
+ throw new Error(`Failed to delete ${targetPath}: No result data`);
49
+ }
50
+ if (result.data.exitCode !== 0) {
51
+ this.logger.error(`Failed to delete ${targetPath}: ${result.data.stderr || 'Unknown error'}`);
52
+ throw new Error(`Failed to delete ${targetPath}: ${result.data.stderr || 'Unknown error'}`);
53
+ }
54
+ this.logger.log(`Successfully deleted ${targetPath} in container ${containerId}`);
55
+ return {
56
+ data: {
57
+ path: targetPath,
58
+ deleted: true,
59
+ },
60
+ };
61
+ }
62
+ };
63
+ exports.SandboxDelete = SandboxDelete;
64
+ __decorate([
65
+ (0, common_2.Tool)(),
66
+ __metadata("design:type", sandbox_tool_1.SandboxCommand)
67
+ ], SandboxDelete.prototype, "sandboxCommand", void 0);
68
+ exports.SandboxDelete = SandboxDelete = SandboxDelete_1 = __decorate([
69
+ (0, common_1.Injectable)(),
70
+ (0, common_2.BlockConfig)({
71
+ config: {
72
+ description: 'Delete a file or directory in a sandbox container',
73
+ },
74
+ }),
75
+ (0, common_2.WithArguments)(propertiesSchema)
76
+ ], SandboxDelete);
77
+ //# sourceMappingURL=sandbox-delete.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox-delete.tool.js","sourceRoot":"","sources":["../../src/tools/sandbox-delete.tool.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAeA,2CAAoD;AACpD,6BAAwB;AACxB,8CAAiF;AACjF,0CAA8D;AAC9D,0DAAyD;AAEzD,MAAM,gBAAgB,GAAG,OAAC;KACvB,MAAM,CAAC;IACN,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2DAA2D,CAAC;IAC7F,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;IACxE,SAAS,EAAE,OAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,8DAA8D,CAAC;IAC9G,KAAK,EAAE,OAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,8DAA8D,CAAC;CAC3G,CAAC;KACD,MAAM,EAAE,CAAC;AAgBL,IAAM,aAAa,qBAAnB,MAAM,aAAc,SAAQ,eAA2B;IAC3C,MAAM,GAAG,IAAI,eAAM,CAAC,eAAa,CAAC,IAAI,CAAC,CAAC;IAEzC,cAAc,CAAiB;IAE/C,KAAK,CAAC,OAAO,CAAC,IAAuB,EAAE,IAAuB;QAC5D,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;QAEjE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,UAAU,iBAAiB,WAAW,gBAAgB,SAAS,YAAY,KAAK,GAAG,CAAC,CAAC;QAEnH,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,IAAI,SAAS;YAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,KAAK;YAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAExB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC;YAC/C,WAAW;YACX,UAAU,EAAE,IAAI;YAChB,IAAI,EAAE,MAAM;YACZ,gBAAgB,EAAE,GAAG;YACrB,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,UAAU,kBAAkB,CAAC,CAAC;YACpE,MAAM,IAAI,KAAK,CAAC,oBAAoB,UAAU,kBAAkB,CAAC,CAAC;QACpE,CAAC;QAED,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,UAAU,KAAK,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,eAAe,EAAE,CAAC,CAAC;YAC9F,MAAM,IAAI,KAAK,CAAC,oBAAoB,UAAU,KAAK,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,eAAe,EAAE,CAAC,CAAC;QAC9F,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,wBAAwB,UAAU,iBAAiB,WAAW,EAAE,CAAC,CAAC;QAElF,OAAO;YACL,IAAI,EAAE;gBACJ,IAAI,EAAE,UAAU;gBAChB,OAAO,EAAE,IAAI;aACd;SACF,CAAC;IACJ,CAAC;CACF,CAAA;AA1CY,sCAAa;AAGR;IAAf,IAAA,aAAI,GAAE;8BAAyB,6BAAc;qDAAC;wBAHpC,aAAa;IAPzB,IAAA,mBAAU,GAAE;IACZ,IAAA,oBAAW,EAAC;QACX,MAAM,EAAE;YACN,WAAW,EAAE,mDAAmD;SACjE;KACF,CAAC;IACD,IAAA,sBAAa,EAAC,gBAAgB,CAAC;GACnB,aAAa,CA0CzB"}
@@ -0,0 +1,20 @@
1
+ import { z } from 'zod';
2
+ import { ToolResult } from '@loopstack/common';
3
+ import { ToolBase, WorkflowExecution } from '@loopstack/core';
4
+ declare const propertiesSchema: z.ZodObject<{
5
+ containerId: z.ZodString;
6
+ path: z.ZodString;
7
+ }, z.core.$strict>;
8
+ type SandboxExistsArgs = z.infer<typeof propertiesSchema>;
9
+ interface SandboxExistsResult {
10
+ path: string;
11
+ exists: boolean;
12
+ type: 'file' | 'directory' | 'symlink' | 'other' | null;
13
+ }
14
+ export declare class SandboxExists extends ToolBase<SandboxExistsArgs> {
15
+ private readonly logger;
16
+ private sandboxCommand;
17
+ execute(args: SandboxExistsArgs, _ctx: WorkflowExecution): Promise<ToolResult<SandboxExistsResult>>;
18
+ private parseFileType;
19
+ }
20
+ export {};
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var SandboxExists_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.SandboxExists = void 0;
14
+ const common_1 = require("@nestjs/common");
15
+ const zod_1 = require("zod");
16
+ const common_2 = require("@loopstack/common");
17
+ const core_1 = require("@loopstack/core");
18
+ const sandbox_tool_1 = require("@loopstack/sandbox-tool");
19
+ const propertiesSchema = zod_1.z
20
+ .object({
21
+ containerId: zod_1.z.string().describe('The ID of the container to check for file existence'),
22
+ path: zod_1.z.string().describe('The path to check for existence'),
23
+ })
24
+ .strict();
25
+ let SandboxExists = SandboxExists_1 = class SandboxExists extends core_1.ToolBase {
26
+ logger = new common_1.Logger(SandboxExists_1.name);
27
+ sandboxCommand;
28
+ async execute(args, _ctx) {
29
+ const { containerId, path: targetPath } = args;
30
+ this.logger.debug(`Checking existence of ${targetPath} in container ${containerId}`);
31
+ const result = await this.sandboxCommand.execute({
32
+ containerId,
33
+ executable: 'sh',
34
+ args: [
35
+ '-c',
36
+ `if [ -e '${targetPath.replace(/'/g, "'\\''")}' ]; then stat -c '%F' '${targetPath.replace(/'/g, "'\\''")}'; else echo 'NOT_FOUND'; fi`,
37
+ ],
38
+ workingDirectory: '/',
39
+ timeout: 10000,
40
+ });
41
+ if (!result.data) {
42
+ this.logger.error(`Failed to check existence of ${targetPath}: No result data`);
43
+ throw new Error(`Failed to check existence of ${targetPath}: No result data`);
44
+ }
45
+ if (result.data.exitCode !== 0) {
46
+ this.logger.error(`Failed to check existence of ${targetPath}: ${result.data.stderr || 'Unknown error'}`);
47
+ throw new Error(`Failed to check existence of ${targetPath}: ${result.data.stderr || 'Unknown error'}`);
48
+ }
49
+ const output = result.data.stdout.trim();
50
+ const exists = output !== 'NOT_FOUND';
51
+ let type = null;
52
+ if (exists) {
53
+ type = this.parseFileType(output);
54
+ }
55
+ this.logger.debug(`Path ${targetPath} exists: ${exists}${exists ? `, type: ${type}` : ''}`);
56
+ return {
57
+ data: {
58
+ path: targetPath,
59
+ exists,
60
+ type,
61
+ },
62
+ };
63
+ }
64
+ parseFileType(statOutput) {
65
+ const lower = statOutput.toLowerCase();
66
+ if (lower.includes('regular'))
67
+ return 'file';
68
+ if (lower.includes('directory'))
69
+ return 'directory';
70
+ if (lower.includes('symbolic link'))
71
+ return 'symlink';
72
+ return 'other';
73
+ }
74
+ };
75
+ exports.SandboxExists = SandboxExists;
76
+ __decorate([
77
+ (0, common_2.Tool)(),
78
+ __metadata("design:type", sandbox_tool_1.SandboxCommand)
79
+ ], SandboxExists.prototype, "sandboxCommand", void 0);
80
+ exports.SandboxExists = SandboxExists = SandboxExists_1 = __decorate([
81
+ (0, common_1.Injectable)(),
82
+ (0, common_2.BlockConfig)({
83
+ config: {
84
+ description: 'Check if a file or directory exists in a sandbox container',
85
+ },
86
+ }),
87
+ (0, common_2.WithArguments)(propertiesSchema)
88
+ ], SandboxExists);
89
+ //# sourceMappingURL=sandbox-exists.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox-exists.tool.js","sourceRoot":"","sources":["../../src/tools/sandbox-exists.tool.ts"],"names":[],"mappings":"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"}