@agentuity/server 0.0.105 → 0.0.106

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 (105) hide show
  1. package/dist/api/api.d.ts +11 -6
  2. package/dist/api/api.d.ts.map +1 -1
  3. package/dist/api/api.js +21 -13
  4. package/dist/api/api.js.map +1 -1
  5. package/dist/api/index.d.ts +1 -0
  6. package/dist/api/index.d.ts.map +1 -1
  7. package/dist/api/index.js +1 -0
  8. package/dist/api/index.js.map +1 -1
  9. package/dist/api/project/deploy.d.ts +0 -6
  10. package/dist/api/project/deploy.d.ts.map +1 -1
  11. package/dist/api/project/deploy.js +0 -2
  12. package/dist/api/project/deploy.js.map +1 -1
  13. package/dist/api/project/get.d.ts +2 -1
  14. package/dist/api/project/get.d.ts.map +1 -1
  15. package/dist/api/project/get.js +10 -2
  16. package/dist/api/project/get.js.map +1 -1
  17. package/dist/api/region/create.d.ts +2 -0
  18. package/dist/api/region/create.d.ts.map +1 -1
  19. package/dist/api/region/create.js +1 -0
  20. package/dist/api/region/create.js.map +1 -1
  21. package/dist/api/region/delete.d.ts +12 -2
  22. package/dist/api/region/delete.d.ts.map +1 -1
  23. package/dist/api/region/delete.js +6 -1
  24. package/dist/api/region/delete.js.map +1 -1
  25. package/dist/api/region/resources.d.ts +4 -0
  26. package/dist/api/region/resources.d.ts.map +1 -1
  27. package/dist/api/region/resources.js +2 -0
  28. package/dist/api/region/resources.js.map +1 -1
  29. package/dist/api/sandbox/client.d.ts +125 -0
  30. package/dist/api/sandbox/client.d.ts.map +1 -0
  31. package/dist/api/sandbox/client.js +202 -0
  32. package/dist/api/sandbox/client.js.map +1 -0
  33. package/dist/api/sandbox/create.d.ts +24 -0
  34. package/dist/api/sandbox/create.d.ts.map +1 -0
  35. package/dist/api/sandbox/create.js +133 -0
  36. package/dist/api/sandbox/create.js.map +1 -0
  37. package/dist/api/sandbox/destroy.d.ts +14 -0
  38. package/dist/api/sandbox/destroy.d.ts.map +1 -0
  39. package/dist/api/sandbox/destroy.js +25 -0
  40. package/dist/api/sandbox/destroy.js.map +1 -0
  41. package/dist/api/sandbox/execute.d.ts +18 -0
  42. package/dist/api/sandbox/execute.d.ts.map +1 -0
  43. package/dist/api/sandbox/execute.js +77 -0
  44. package/dist/api/sandbox/execute.js.map +1 -0
  45. package/dist/api/sandbox/execution.d.ts +46 -0
  46. package/dist/api/sandbox/execution.d.ts.map +1 -0
  47. package/dist/api/sandbox/execution.js +101 -0
  48. package/dist/api/sandbox/execution.js.map +1 -0
  49. package/dist/api/sandbox/files.d.ts +41 -0
  50. package/dist/api/sandbox/files.d.ts.map +1 -0
  51. package/dist/api/sandbox/files.js +91 -0
  52. package/dist/api/sandbox/files.js.map +1 -0
  53. package/dist/api/sandbox/get.d.ts +16 -0
  54. package/dist/api/sandbox/get.d.ts.map +1 -0
  55. package/dist/api/sandbox/get.js +57 -0
  56. package/dist/api/sandbox/get.js.map +1 -0
  57. package/dist/api/sandbox/index.d.ts +22 -0
  58. package/dist/api/sandbox/index.d.ts.map +1 -0
  59. package/dist/api/sandbox/index.js +12 -0
  60. package/dist/api/sandbox/index.js.map +1 -0
  61. package/dist/api/sandbox/list.d.ts +15 -0
  62. package/dist/api/sandbox/list.d.ts.map +1 -0
  63. package/dist/api/sandbox/list.js +75 -0
  64. package/dist/api/sandbox/list.js.map +1 -0
  65. package/dist/api/sandbox/run.d.ts +28 -0
  66. package/dist/api/sandbox/run.d.ts.map +1 -0
  67. package/dist/api/sandbox/run.js +269 -0
  68. package/dist/api/sandbox/run.js.map +1 -0
  69. package/dist/api/sandbox/snapshot.d.ts +89 -0
  70. package/dist/api/sandbox/snapshot.d.ts.map +1 -0
  71. package/dist/api/sandbox/snapshot.js +140 -0
  72. package/dist/api/sandbox/snapshot.js.map +1 -0
  73. package/dist/api/sandbox/util.d.ts +37 -0
  74. package/dist/api/sandbox/util.d.ts.map +1 -0
  75. package/dist/api/sandbox/util.js +45 -0
  76. package/dist/api/sandbox/util.js.map +1 -0
  77. package/dist/config.d.ts +1 -0
  78. package/dist/config.d.ts.map +1 -1
  79. package/dist/config.js +1 -0
  80. package/dist/config.js.map +1 -1
  81. package/dist/runtime-bootstrap.d.ts.map +1 -1
  82. package/dist/runtime-bootstrap.js +3 -0
  83. package/dist/runtime-bootstrap.js.map +1 -1
  84. package/package.json +4 -4
  85. package/src/api/api.ts +33 -13
  86. package/src/api/index.ts +1 -0
  87. package/src/api/project/deploy.ts +0 -2
  88. package/src/api/project/get.ts +10 -2
  89. package/src/api/region/create.ts +1 -0
  90. package/src/api/region/delete.ts +9 -2
  91. package/src/api/region/resources.ts +2 -0
  92. package/src/api/sandbox/client.ts +349 -0
  93. package/src/api/sandbox/create.ts +166 -0
  94. package/src/api/sandbox/destroy.ts +41 -0
  95. package/src/api/sandbox/execute.ts +102 -0
  96. package/src/api/sandbox/execution.ts +154 -0
  97. package/src/api/sandbox/files.ts +138 -0
  98. package/src/api/sandbox/get.ts +74 -0
  99. package/src/api/sandbox/index.ts +35 -0
  100. package/src/api/sandbox/list.ts +94 -0
  101. package/src/api/sandbox/run.ts +360 -0
  102. package/src/api/sandbox/snapshot.ts +247 -0
  103. package/src/api/sandbox/util.ts +55 -0
  104. package/src/config.ts +2 -0
  105. package/src/runtime-bootstrap.ts +3 -0
@@ -0,0 +1,166 @@
1
+ import { z } from 'zod';
2
+ import { APIClient, APIResponseSchema } from '../api';
3
+ import { SandboxResponseError, API_VERSION } from './util';
4
+ import type { SandboxCreateOptions, SandboxStatus } from '@agentuity/core';
5
+
6
+ const SandboxCreateRequestSchema = z
7
+ .object({
8
+ resources: z
9
+ .object({
10
+ memory: z.string().optional().describe('Memory limit (e.g., "512Mi", "1Gi")'),
11
+ cpu: z.string().optional().describe('CPU limit (e.g., "0.5", "1")'),
12
+ disk: z.string().optional().describe('Disk size limit (e.g., "1Gi", "10Gi")'),
13
+ })
14
+ .optional()
15
+ .describe('Resource constraints for the sandbox'),
16
+ env: z
17
+ .record(z.string(), z.string())
18
+ .optional()
19
+ .describe('Environment variables to set in the sandbox'),
20
+ network: z
21
+ .object({
22
+ enabled: z.boolean().optional().describe('Whether network access is enabled'),
23
+ })
24
+ .optional()
25
+ .describe('Network configuration for the sandbox'),
26
+ stream: z
27
+ .object({
28
+ stdout: z.string().optional().describe('Stream ID for stdout output'),
29
+ stderr: z.string().optional().describe('Stream ID for stderr output'),
30
+ stdin: z.string().optional().describe('Stream ID for stdin input'),
31
+ timestamps: z.boolean().optional().describe('Whether to include timestamps in output'),
32
+ })
33
+ .optional()
34
+ .describe('Stream configuration for I/O redirection'),
35
+ timeout: z
36
+ .object({
37
+ idle: z.string().optional().describe('Idle timeout duration (e.g., "5m", "1h")'),
38
+ execution: z.string().optional().describe('Maximum execution time (e.g., "30m", "2h")'),
39
+ })
40
+ .optional()
41
+ .describe('Timeout settings for the sandbox'),
42
+ command: z
43
+ .object({
44
+ exec: z.array(z.string()).describe('Command and arguments to execute'),
45
+ files: z
46
+ .array(
47
+ z.object({
48
+ path: z
49
+ .string()
50
+ .describe('Path to the file relative to the sandbox workspace'),
51
+ content: z.string().describe('Base64-encoded file content'),
52
+ })
53
+ )
54
+ .optional()
55
+ .describe('Files to write before execution'),
56
+ mode: z
57
+ .enum(['oneshot', 'interactive'])
58
+ .optional()
59
+ .describe('Execution mode: oneshot runs once, interactive keeps running'),
60
+ })
61
+ .optional()
62
+ .describe('Initial command to run in the sandbox'),
63
+ snapshot: z.string().optional().describe('Snapshot ID to restore the sandbox from'),
64
+ dependencies: z
65
+ .array(z.string())
66
+ .optional()
67
+ .describe('Apt packages to install when creating the sandbox'),
68
+ })
69
+ .describe('Request body for creating a new sandbox');
70
+
71
+ const SandboxCreateDataSchema = z
72
+ .object({
73
+ sandboxId: z.string().describe('Unique identifier for the created sandbox'),
74
+ status: z
75
+ .enum(['creating', 'idle', 'running', 'terminated', 'failed'])
76
+ .describe('Current status of the sandbox'),
77
+ stdoutStreamId: z.string().optional().describe('Stream ID for reading stdout'),
78
+ stdoutStreamUrl: z.string().optional().describe('URL for streaming stdout output'),
79
+ stderrStreamId: z.string().optional().describe('Stream ID for reading stderr'),
80
+ stderrStreamUrl: z.string().optional().describe('URL for streaming stderr output'),
81
+ })
82
+ .describe('Response data from sandbox creation');
83
+
84
+ const SandboxCreateResponseSchema = APIResponseSchema(SandboxCreateDataSchema);
85
+
86
+ export interface SandboxCreateResponse {
87
+ sandboxId: string;
88
+ status: SandboxStatus;
89
+ stdoutStreamId?: string;
90
+ stdoutStreamUrl?: string;
91
+ stderrStreamId?: string;
92
+ stderrStreamUrl?: string;
93
+ }
94
+
95
+ export interface SandboxCreateParams {
96
+ options?: SandboxCreateOptions;
97
+ orgId?: string;
98
+ }
99
+
100
+ /**
101
+ * Creates a new sandbox instance.
102
+ *
103
+ * @param client - The API client to use for the request
104
+ * @param params - Parameters for creating the sandbox
105
+ * @returns The created sandbox response including sandbox ID and stream URLs
106
+ * @throws {SandboxResponseError} If the sandbox creation fails
107
+ */
108
+ export async function sandboxCreate(
109
+ client: APIClient,
110
+ params: SandboxCreateParams = {}
111
+ ): Promise<SandboxCreateResponse> {
112
+ const { options = {}, orgId } = params;
113
+ const body: z.infer<typeof SandboxCreateRequestSchema> = {};
114
+
115
+ if (options.resources) {
116
+ body.resources = options.resources;
117
+ }
118
+ if (options.env) {
119
+ body.env = options.env;
120
+ }
121
+ if (options.network) {
122
+ body.network = options.network;
123
+ }
124
+ if (options.stream) {
125
+ body.stream = options.stream;
126
+ }
127
+ if (options.timeout) {
128
+ body.timeout = options.timeout;
129
+ }
130
+ if (options.command) {
131
+ body.command = {
132
+ exec: options.command.exec,
133
+ mode: options.command.mode,
134
+ files: options.command.files?.map((f) => ({
135
+ path: f.path,
136
+ content: f.content.toString('base64'),
137
+ })),
138
+ };
139
+ }
140
+ if (options.snapshot) {
141
+ body.snapshot = options.snapshot;
142
+ }
143
+ if (options.dependencies && options.dependencies.length > 0) {
144
+ body.dependencies = options.dependencies;
145
+ }
146
+
147
+ const queryParams = new URLSearchParams();
148
+ if (orgId) {
149
+ queryParams.set('orgId', orgId);
150
+ }
151
+ const queryString = queryParams.toString();
152
+ const url = `/sandbox/${API_VERSION}${queryString ? `?${queryString}` : ''}`;
153
+
154
+ const resp = await client.post<z.infer<typeof SandboxCreateResponseSchema>>(
155
+ url,
156
+ body,
157
+ SandboxCreateResponseSchema,
158
+ SandboxCreateRequestSchema
159
+ );
160
+
161
+ if (resp.success) {
162
+ return resp.data;
163
+ }
164
+
165
+ throw new SandboxResponseError({ message: resp.message });
166
+ }
@@ -0,0 +1,41 @@
1
+ import { z } from 'zod';
2
+ import { APIClient, APIResponseSchemaNoData } from '../api';
3
+ import { SandboxResponseError, API_VERSION } from './util';
4
+
5
+ const DestroyResponseSchema = APIResponseSchemaNoData();
6
+
7
+ export interface SandboxDestroyParams {
8
+ sandboxId: string;
9
+ orgId?: string;
10
+ }
11
+
12
+ /**
13
+ * Destroys a sandbox and releases all associated resources.
14
+ *
15
+ * @param client - The API client to use for the request
16
+ * @param params - Parameters including the sandbox ID to destroy
17
+ * @throws {SandboxResponseError} If the sandbox is not found or destruction fails
18
+ */
19
+ export async function sandboxDestroy(
20
+ client: APIClient,
21
+ params: SandboxDestroyParams
22
+ ): Promise<void> {
23
+ const { sandboxId, orgId } = params;
24
+ const queryParams = new URLSearchParams();
25
+ if (orgId) {
26
+ queryParams.set('orgId', orgId);
27
+ }
28
+ const queryString = queryParams.toString();
29
+ const url = `/sandbox/${API_VERSION}/${sandboxId}${queryString ? `?${queryString}` : ''}`;
30
+
31
+ const resp = await client.delete<z.infer<typeof DestroyResponseSchema>>(
32
+ url,
33
+ DestroyResponseSchema
34
+ );
35
+
36
+ if (resp.success) {
37
+ return;
38
+ }
39
+
40
+ throw new SandboxResponseError({ message: resp.message, sandboxId });
41
+ }
@@ -0,0 +1,102 @@
1
+ import { z } from 'zod';
2
+ import { APIClient, APIResponseSchema } from '../api';
3
+ import { SandboxResponseError, API_VERSION } from './util';
4
+ import { FileToWriteSchema } from './files';
5
+ import type { ExecuteOptions, Execution, ExecutionStatus } from '@agentuity/core';
6
+
7
+ const ExecuteRequestSchema = z
8
+ .object({
9
+ command: z.array(z.string()).describe('Command and arguments to execute'),
10
+ files: z.array(FileToWriteSchema).optional().describe('Files to write before execution'),
11
+ timeout: z.string().optional().describe('Execution timeout (e.g., "30s", "5m")'),
12
+ stream: z
13
+ .object({
14
+ stdout: z.string().optional().describe('Stream ID for stdout output'),
15
+ stderr: z.string().optional().describe('Stream ID for stderr output'),
16
+ timestamps: z.boolean().optional().describe('Whether to include timestamps in output'),
17
+ })
18
+ .optional()
19
+ .describe('Stream configuration for output redirection'),
20
+ })
21
+ .describe('Request body for executing a command in a sandbox');
22
+
23
+ const ExecuteDataSchema = z
24
+ .object({
25
+ executionId: z.string().describe('Unique identifier for the execution'),
26
+ status: z
27
+ .enum(['queued', 'running', 'completed', 'failed', 'timeout', 'cancelled'])
28
+ .describe('Current status of the execution'),
29
+ exitCode: z.number().optional().describe('Exit code of the executed command'),
30
+ durationMs: z.number().optional().describe('Execution duration in milliseconds'),
31
+ stdoutStreamUrl: z.string().optional().describe('URL for streaming stdout output'),
32
+ stderrStreamUrl: z.string().optional().describe('URL for streaming stderr output'),
33
+ })
34
+ .describe('Response data from command execution');
35
+
36
+ const ExecuteResponseSchema = APIResponseSchema(ExecuteDataSchema);
37
+
38
+ export interface SandboxExecuteParams {
39
+ sandboxId: string;
40
+ options: ExecuteOptions;
41
+ orgId?: string;
42
+ signal?: AbortSignal;
43
+ }
44
+
45
+ /**
46
+ * Executes a command in an existing sandbox.
47
+ *
48
+ * @param client - The API client to use for the request
49
+ * @param params - Parameters including sandbox ID and execution options
50
+ * @returns The execution result including status and stream URLs
51
+ * @throws {SandboxResponseError} If the execution request fails
52
+ */
53
+ export async function sandboxExecute(
54
+ client: APIClient,
55
+ params: SandboxExecuteParams
56
+ ): Promise<Execution> {
57
+ const { sandboxId, options, orgId, signal } = params;
58
+ const body: z.infer<typeof ExecuteRequestSchema> = {
59
+ command: options.command,
60
+ };
61
+
62
+ if (options.files) {
63
+ body.files = options.files.map((f) => ({
64
+ path: f.path,
65
+ content: f.content.toString('base64'),
66
+ }));
67
+ }
68
+ if (options.timeout) {
69
+ body.timeout = options.timeout;
70
+ }
71
+ if (options.stream) {
72
+ body.stream = options.stream;
73
+ }
74
+
75
+ const queryParams = new URLSearchParams();
76
+ if (orgId) {
77
+ queryParams.set('orgId', orgId);
78
+ }
79
+ const queryString = queryParams.toString();
80
+ const url = `/sandbox/${API_VERSION}/${sandboxId}/execute${queryString ? `?${queryString}` : ''}`;
81
+
82
+ const resp = await client.post<z.infer<typeof ExecuteResponseSchema>>(
83
+ url,
84
+ body,
85
+ ExecuteResponseSchema,
86
+ ExecuteRequestSchema,
87
+ signal ?? options.signal
88
+ );
89
+
90
+ if (resp.success) {
91
+ return {
92
+ executionId: resp.data.executionId,
93
+ status: resp.data.status as ExecutionStatus,
94
+ exitCode: resp.data.exitCode,
95
+ durationMs: resp.data.durationMs,
96
+ stdoutStreamUrl: resp.data.stdoutStreamUrl,
97
+ stderrStreamUrl: resp.data.stderrStreamUrl,
98
+ };
99
+ }
100
+
101
+ throw new SandboxResponseError({ message: resp.message, sandboxId });
102
+ }
@@ -0,0 +1,154 @@
1
+ import { z } from 'zod';
2
+ import { APIClient, APIResponseSchema } from '../api';
3
+ import { SandboxResponseError, API_VERSION } from './util';
4
+ import type { ExecutionStatus } from '@agentuity/core';
5
+
6
+ const ExecutionInfoSchema = z
7
+ .object({
8
+ executionId: z.string().describe('Unique identifier for the execution'),
9
+ sandboxId: z.string().describe('ID of the sandbox where the execution ran'),
10
+ status: z
11
+ .enum(['queued', 'running', 'completed', 'failed', 'timeout', 'cancelled'])
12
+ .describe('Current status of the execution'),
13
+ command: z.array(z.string()).optional().describe('Command that was executed'),
14
+ exitCode: z.number().optional().describe('Exit code of the executed command'),
15
+ durationMs: z.number().optional().describe('Execution duration in milliseconds'),
16
+ startedAt: z.string().optional().describe('ISO timestamp when execution started'),
17
+ completedAt: z.string().optional().describe('ISO timestamp when execution completed'),
18
+ error: z.string().optional().describe('Error message if execution failed'),
19
+ stdoutStreamUrl: z.string().optional().describe('URL to stream stdout output'),
20
+ stderrStreamUrl: z.string().optional().describe('URL to stream stderr output'),
21
+ })
22
+ .describe('Detailed information about a command execution');
23
+
24
+ const ExecutionGetResponseSchema = APIResponseSchema(ExecutionInfoSchema);
25
+
26
+ const ExecutionListDataSchema = z
27
+ .object({
28
+ executions: z.array(ExecutionInfoSchema).describe('List of executions'),
29
+ })
30
+ .describe('List of executions for a sandbox');
31
+
32
+ const ExecutionListResponseSchema = APIResponseSchema(ExecutionListDataSchema);
33
+
34
+ export interface ExecutionInfo {
35
+ executionId: string;
36
+ sandboxId: string;
37
+ status: ExecutionStatus;
38
+ command?: string[];
39
+ exitCode?: number;
40
+ durationMs?: number;
41
+ startedAt?: string;
42
+ completedAt?: string;
43
+ error?: string;
44
+ stdoutStreamUrl?: string;
45
+ stderrStreamUrl?: string;
46
+ }
47
+
48
+ export interface ExecutionGetParams {
49
+ executionId: string;
50
+ orgId?: string;
51
+ }
52
+
53
+ /**
54
+ * Retrieves detailed information about a specific execution.
55
+ *
56
+ * @param client - The API client to use for the request
57
+ * @param params - Parameters including the execution ID
58
+ * @returns Detailed execution information including status, timing, and errors
59
+ * @throws {SandboxResponseError} If the execution is not found or request fails
60
+ */
61
+ export async function executionGet(
62
+ client: APIClient,
63
+ params: ExecutionGetParams
64
+ ): Promise<ExecutionInfo> {
65
+ const { executionId, orgId } = params;
66
+ const queryParams = new URLSearchParams();
67
+ if (orgId) {
68
+ queryParams.set('orgId', orgId);
69
+ }
70
+ const queryString = queryParams.toString();
71
+ const url = `/sandbox/${API_VERSION}/execution/${executionId}${queryString ? `?${queryString}` : ''}`;
72
+
73
+ const resp = await client.get<z.infer<typeof ExecutionGetResponseSchema>>(
74
+ url,
75
+ ExecutionGetResponseSchema
76
+ );
77
+
78
+ if (resp.success) {
79
+ return {
80
+ executionId: resp.data.executionId,
81
+ sandboxId: resp.data.sandboxId,
82
+ status: resp.data.status as ExecutionStatus,
83
+ command: resp.data.command,
84
+ exitCode: resp.data.exitCode,
85
+ durationMs: resp.data.durationMs,
86
+ startedAt: resp.data.startedAt,
87
+ completedAt: resp.data.completedAt,
88
+ error: resp.data.error,
89
+ stdoutStreamUrl: resp.data.stdoutStreamUrl,
90
+ stderrStreamUrl: resp.data.stderrStreamUrl,
91
+ };
92
+ }
93
+
94
+ throw new SandboxResponseError({ message: resp.message, executionId });
95
+ }
96
+
97
+ export interface ExecutionListParams {
98
+ sandboxId: string;
99
+ orgId?: string;
100
+ limit?: number;
101
+ }
102
+
103
+ export interface ExecutionListResponse {
104
+ executions: ExecutionInfo[];
105
+ }
106
+
107
+ /**
108
+ * Lists all executions for a specific sandbox.
109
+ *
110
+ * @param client - The API client to use for the request
111
+ * @param params - Parameters including the sandbox ID and optional limit
112
+ * @returns List of execution information for the sandbox
113
+ * @throws {SandboxResponseError} If the sandbox is not found or request fails
114
+ */
115
+ export async function executionList(
116
+ client: APIClient,
117
+ params: ExecutionListParams
118
+ ): Promise<ExecutionListResponse> {
119
+ const { sandboxId, orgId, limit } = params;
120
+ const queryParams = new URLSearchParams();
121
+ if (orgId) {
122
+ queryParams.set('orgId', orgId);
123
+ }
124
+ if (limit !== undefined) {
125
+ queryParams.set('limit', String(limit));
126
+ }
127
+ const queryString = queryParams.toString();
128
+ const url = `/sandbox/${API_VERSION}/sandboxes/${sandboxId}/executions${queryString ? `?${queryString}` : ''}`;
129
+
130
+ const resp = await client.get<z.infer<typeof ExecutionListResponseSchema>>(
131
+ url,
132
+ ExecutionListResponseSchema
133
+ );
134
+
135
+ if (resp.success) {
136
+ return {
137
+ executions: resp.data.executions.map((exec) => ({
138
+ executionId: exec.executionId,
139
+ sandboxId: exec.sandboxId,
140
+ status: exec.status as ExecutionStatus,
141
+ command: exec.command,
142
+ exitCode: exec.exitCode,
143
+ durationMs: exec.durationMs,
144
+ startedAt: exec.startedAt,
145
+ completedAt: exec.completedAt,
146
+ error: exec.error,
147
+ stdoutStreamUrl: exec.stdoutStreamUrl,
148
+ stderrStreamUrl: exec.stderrStreamUrl,
149
+ })),
150
+ };
151
+ }
152
+
153
+ throw new SandboxResponseError({ message: resp.message, sandboxId });
154
+ }
@@ -0,0 +1,138 @@
1
+ import { z } from 'zod';
2
+ import { APIClient } from '../api';
3
+ import { SandboxResponseError, API_VERSION } from './util';
4
+ import type { FileToWrite } from '@agentuity/core';
5
+
6
+ export const FileToWriteSchema = z.object({
7
+ path: z.string().describe('Path to the file relative to the sandbox workspace'),
8
+ content: z.string().describe('Base64-encoded file content'),
9
+ });
10
+
11
+ const WriteFilesRequestSchema = z
12
+ .object({
13
+ files: z.array(FileToWriteSchema).describe('Array of files to write'),
14
+ })
15
+ .describe('Request body for writing files to a sandbox');
16
+
17
+ const WriteFilesDataSchema = z
18
+ .object({
19
+ filesWritten: z.number().describe('Number of files successfully written'),
20
+ })
21
+ .describe('Response data from writing files');
22
+
23
+ const WriteFilesResponseSchema = z.discriminatedUnion('success', [
24
+ z.object({
25
+ success: z.literal<false>(false),
26
+ message: z.string().describe('the error message'),
27
+ }),
28
+ z.object({
29
+ success: z.literal<true>(true),
30
+ data: WriteFilesDataSchema.optional(),
31
+ filesWritten: z.number().optional(),
32
+ }),
33
+ ]);
34
+
35
+ export interface WriteFilesParams {
36
+ sandboxId: string;
37
+ files: FileToWrite[];
38
+ orgId?: string;
39
+ signal?: AbortSignal;
40
+ }
41
+
42
+ export interface WriteFilesResult {
43
+ filesWritten: number;
44
+ }
45
+
46
+ /**
47
+ * Writes files to a sandbox workspace.
48
+ *
49
+ * @param client - The API client to use for the request
50
+ * @param params - Parameters including sandbox ID and files to write
51
+ * @returns The result including number of files written
52
+ * @throws {SandboxResponseError} If the write request fails
53
+ */
54
+ export async function sandboxWriteFiles(
55
+ client: APIClient,
56
+ params: WriteFilesParams
57
+ ): Promise<WriteFilesResult> {
58
+ const { sandboxId, files, orgId, signal } = params;
59
+
60
+ const body: z.infer<typeof WriteFilesRequestSchema> = {
61
+ files: files.map((f) => ({
62
+ path: f.path,
63
+ content: f.content.toString('base64'),
64
+ })),
65
+ };
66
+
67
+ const queryParams = new URLSearchParams();
68
+ if (orgId) {
69
+ queryParams.set('orgId', orgId);
70
+ }
71
+ const queryString = queryParams.toString();
72
+ const url = `/fs/${API_VERSION}/${sandboxId}${queryString ? `?${queryString}` : ''}`;
73
+
74
+ const resp = await client.post<z.infer<typeof WriteFilesResponseSchema>>(
75
+ url,
76
+ body,
77
+ WriteFilesResponseSchema,
78
+ WriteFilesRequestSchema,
79
+ signal
80
+ );
81
+
82
+ if (resp.success) {
83
+ return {
84
+ filesWritten: resp.data?.filesWritten ?? resp.filesWritten ?? 0,
85
+ };
86
+ }
87
+
88
+ throw new SandboxResponseError({ message: resp.message, sandboxId });
89
+ }
90
+
91
+ export interface ReadFileParams {
92
+ sandboxId: string;
93
+ path: string;
94
+ orgId?: string;
95
+ signal?: AbortSignal;
96
+ }
97
+
98
+ /**
99
+ * Reads a file from a sandbox workspace.
100
+ *
101
+ * @param client - The API client to use for the request
102
+ * @param params - Parameters including sandbox ID and file path
103
+ * @returns A ReadableStream of the file contents
104
+ * @throws {SandboxResponseError} If the read request fails
105
+ */
106
+ export async function sandboxReadFile(
107
+ client: APIClient,
108
+ params: ReadFileParams
109
+ ): Promise<ReadableStream<Uint8Array>> {
110
+ const { sandboxId, path, orgId, signal } = params;
111
+
112
+ const queryParams = new URLSearchParams();
113
+ queryParams.set('path', path);
114
+ if (orgId) {
115
+ queryParams.set('orgId', orgId);
116
+ }
117
+ const queryString = queryParams.toString();
118
+ const url = `/fs/${API_VERSION}/${sandboxId}?${queryString}`;
119
+
120
+ const response = await client.rawGet(url, signal);
121
+
122
+ if (!response.ok) {
123
+ const text = await response.text().catch(() => 'Unknown error');
124
+ throw new SandboxResponseError({
125
+ message: `Failed to read file: ${response.status} ${text}`,
126
+ sandboxId,
127
+ });
128
+ }
129
+
130
+ if (!response.body) {
131
+ throw new SandboxResponseError({
132
+ message: 'No response body',
133
+ sandboxId,
134
+ });
135
+ }
136
+
137
+ return response.body;
138
+ }
@@ -0,0 +1,74 @@
1
+ import { z } from 'zod';
2
+ import { APIClient, APIResponseSchema } from '../api';
3
+ import { SandboxResponseError, API_VERSION } from './util';
4
+ import type { SandboxInfo, SandboxStatus } from '@agentuity/core';
5
+
6
+ const SandboxInfoDataSchema = z
7
+ .object({
8
+ sandboxId: z.string().describe('Unique identifier for the sandbox'),
9
+ status: z
10
+ .enum(['creating', 'idle', 'running', 'terminated', 'failed'])
11
+ .describe('Current status of the sandbox'),
12
+ createdAt: z.string().describe('ISO timestamp when the sandbox was created'),
13
+ region: z.string().optional().describe('Region where the sandbox is running'),
14
+ snapshotId: z.string().optional().describe('Snapshot ID this sandbox was created from'),
15
+ snapshotTag: z.string().optional().describe('Snapshot tag this sandbox was created from'),
16
+ executions: z.number().describe('Total number of executions in this sandbox'),
17
+ stdoutStreamUrl: z.string().optional().describe('URL for streaming stdout output'),
18
+ stderrStreamUrl: z.string().optional().describe('URL for streaming stderr output'),
19
+ dependencies: z
20
+ .array(z.string())
21
+ .optional()
22
+ .describe('Apt packages installed in the sandbox'),
23
+ })
24
+ .describe('Detailed information about a sandbox');
25
+
26
+ const SandboxGetResponseSchema = APIResponseSchema(SandboxInfoDataSchema);
27
+
28
+ export interface SandboxGetParams {
29
+ sandboxId: string;
30
+ orgId?: string;
31
+ }
32
+
33
+ /**
34
+ * Retrieves information about a specific sandbox.
35
+ *
36
+ * @param client - The API client to use for the request
37
+ * @param params - Parameters including the sandbox ID
38
+ * @returns Sandbox information including status, creation time, and execution count
39
+ * @throws {SandboxResponseError} If the sandbox is not found or request fails
40
+ */
41
+ export async function sandboxGet(
42
+ client: APIClient,
43
+ params: SandboxGetParams
44
+ ): Promise<SandboxInfo> {
45
+ const { sandboxId, orgId } = params;
46
+ const queryParams = new URLSearchParams();
47
+ if (orgId) {
48
+ queryParams.set('orgId', orgId);
49
+ }
50
+ const queryString = queryParams.toString();
51
+ const url = `/sandbox/${API_VERSION}/${sandboxId}${queryString ? `?${queryString}` : ''}`;
52
+
53
+ const resp = await client.get<z.infer<typeof SandboxGetResponseSchema>>(
54
+ url,
55
+ SandboxGetResponseSchema
56
+ );
57
+
58
+ if (resp.success) {
59
+ return {
60
+ sandboxId: resp.data.sandboxId,
61
+ status: resp.data.status as SandboxStatus,
62
+ createdAt: resp.data.createdAt,
63
+ region: resp.data.region,
64
+ snapshotId: resp.data.snapshotId,
65
+ snapshotTag: resp.data.snapshotTag,
66
+ executions: resp.data.executions,
67
+ stdoutStreamUrl: resp.data.stdoutStreamUrl,
68
+ stderrStreamUrl: resp.data.stderrStreamUrl,
69
+ dependencies: resp.data.dependencies,
70
+ };
71
+ }
72
+
73
+ throw new SandboxResponseError({ message: resp.message, sandboxId });
74
+ }