@agentuity/sandbox 3.0.12 → 3.1.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 (122) hide show
  1. package/AGENTS.md +3 -3
  2. package/dist/api-reference.d.ts +1221 -0
  3. package/dist/api-reference.d.ts.map +1 -0
  4. package/dist/api-reference.js +1046 -0
  5. package/dist/api-reference.js.map +1 -0
  6. package/dist/base64.d.ts +2 -0
  7. package/dist/base64.d.ts.map +1 -0
  8. package/dist/base64.js +14 -0
  9. package/dist/base64.js.map +1 -0
  10. package/dist/client.d.ts +431 -0
  11. package/dist/client.d.ts.map +1 -0
  12. package/dist/client.js +632 -0
  13. package/dist/client.js.map +1 -0
  14. package/dist/create.d.ts +203 -0
  15. package/dist/create.d.ts.map +1 -0
  16. package/dist/create.js +235 -0
  17. package/dist/create.js.map +1 -0
  18. package/dist/destroy.d.ts +23 -0
  19. package/dist/destroy.d.ts.map +1 -0
  20. package/dist/destroy.js +30 -0
  21. package/dist/destroy.js.map +1 -0
  22. package/dist/disk-checkpoint.d.ts +108 -0
  23. package/dist/disk-checkpoint.d.ts.map +1 -0
  24. package/dist/disk-checkpoint.js +124 -0
  25. package/dist/disk-checkpoint.js.map +1 -0
  26. package/dist/events.d.ts +56 -0
  27. package/dist/events.d.ts.map +1 -0
  28. package/dist/events.js +54 -0
  29. package/dist/events.js.map +1 -0
  30. package/dist/execute.d.ts +99 -0
  31. package/dist/execute.d.ts.map +1 -0
  32. package/dist/execute.js +138 -0
  33. package/dist/execute.js.map +1 -0
  34. package/dist/execution.d.ts +150 -0
  35. package/dist/execution.d.ts.map +1 -0
  36. package/dist/execution.js +120 -0
  37. package/dist/execution.js.map +1 -0
  38. package/dist/files.d.ts +283 -0
  39. package/dist/files.d.ts.map +1 -0
  40. package/dist/files.js +471 -0
  41. package/dist/files.js.map +1 -0
  42. package/dist/get.d.ts +288 -0
  43. package/dist/get.d.ts.map +1 -0
  44. package/dist/get.js +256 -0
  45. package/dist/get.js.map +1 -0
  46. package/dist/getStatus.d.ts +23 -0
  47. package/dist/getStatus.d.ts.map +1 -0
  48. package/dist/getStatus.js +53 -0
  49. package/dist/getStatus.js.map +1 -0
  50. package/dist/index.d.ts +42 -1
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +22 -1
  53. package/dist/index.js.map +1 -1
  54. package/dist/job.d.ts +227 -0
  55. package/dist/job.d.ts.map +1 -0
  56. package/dist/job.js +109 -0
  57. package/dist/job.js.map +1 -0
  58. package/dist/list.d.ts +330 -0
  59. package/dist/list.d.ts.map +1 -0
  60. package/dist/list.js +209 -0
  61. package/dist/list.js.map +1 -0
  62. package/dist/pause.d.ts +39 -0
  63. package/dist/pause.d.ts.map +1 -0
  64. package/dist/pause.js +48 -0
  65. package/dist/pause.js.map +1 -0
  66. package/dist/resolve.d.ts +75 -0
  67. package/dist/resolve.d.ts.map +1 -0
  68. package/dist/resolve.js +76 -0
  69. package/dist/resolve.js.map +1 -0
  70. package/dist/resume.d.ts +23 -0
  71. package/dist/resume.d.ts.map +1 -0
  72. package/dist/resume.js +30 -0
  73. package/dist/resume.js.map +1 -0
  74. package/dist/run.d.ts +73 -0
  75. package/dist/run.d.ts.map +1 -0
  76. package/dist/run.js +568 -0
  77. package/dist/run.js.map +1 -0
  78. package/dist/runtime.d.ts +94 -0
  79. package/dist/runtime.d.ts.map +1 -0
  80. package/dist/runtime.js +82 -0
  81. package/dist/runtime.js.map +1 -0
  82. package/dist/snapshot-build.d.ts +48 -0
  83. package/dist/snapshot-build.d.ts.map +1 -0
  84. package/dist/snapshot-build.js +72 -0
  85. package/dist/snapshot-build.js.map +1 -0
  86. package/dist/snapshot.d.ts +596 -0
  87. package/dist/snapshot.d.ts.map +1 -0
  88. package/dist/snapshot.js +612 -0
  89. package/dist/snapshot.js.map +1 -0
  90. package/dist/types.d.ts +1010 -0
  91. package/dist/types.d.ts.map +1 -0
  92. package/dist/types.js +853 -0
  93. package/dist/types.js.map +1 -0
  94. package/dist/util.d.ts +296 -0
  95. package/dist/util.d.ts.map +1 -0
  96. package/dist/util.js +234 -0
  97. package/dist/util.js.map +1 -0
  98. package/package.json +7 -2
  99. package/src/api-reference.ts +1094 -0
  100. package/src/base64.ts +14 -0
  101. package/src/client.ts +998 -0
  102. package/src/create.ts +273 -0
  103. package/src/destroy.ts +43 -0
  104. package/src/disk-checkpoint.ts +184 -0
  105. package/src/events.ts +72 -0
  106. package/src/execute.ts +167 -0
  107. package/src/execution.ts +152 -0
  108. package/src/files.ts +637 -0
  109. package/src/get.ts +291 -0
  110. package/src/getStatus.ts +72 -0
  111. package/src/index.ts +252 -18
  112. package/src/job.ts +161 -0
  113. package/src/list.ts +239 -0
  114. package/src/pause.ts +75 -0
  115. package/src/resolve.ts +96 -0
  116. package/src/resume.ts +41 -0
  117. package/src/run.ts +783 -0
  118. package/src/runtime.ts +106 -0
  119. package/src/snapshot-build.ts +94 -0
  120. package/src/snapshot.ts +791 -0
  121. package/src/types.ts +1033 -0
  122. package/src/util.ts +280 -0
package/src/execute.ts ADDED
@@ -0,0 +1,167 @@
1
+ import type { ExecuteOptions, Execution, ExecutionStatus } from './types.ts';
2
+ import { z } from 'zod';
3
+ import type { APIClient } from '@agentuity/api';
4
+ import { SandboxBusyError, SandboxNotFoundError, throwSandboxError } from './util.ts';
5
+ import { base64Encode } from './base64.ts';
6
+
7
+ export const ExecuteRequestSchema = z
8
+ .object({
9
+ command: z.array(z.string()).describe('Command and arguments to execute'),
10
+ files: z
11
+ .array(
12
+ z.object({
13
+ path: z.string().describe('File path relative to workspace'),
14
+ content: z.string().describe('Base64-encoded file content'),
15
+ })
16
+ )
17
+ .optional()
18
+ .describe('Files to write before execution'),
19
+ timeout: z.string().optional().describe('Execution timeout (e.g., "30s", "5m")'),
20
+ stream: z
21
+ .object({
22
+ stdout: z.string().optional().describe('Stream ID for stdout output'),
23
+ stderr: z.string().optional().describe('Stream ID for stderr output'),
24
+ timestamps: z.boolean().optional().describe('Whether to include timestamps in output'),
25
+ })
26
+ .optional()
27
+ .describe('Stream configuration for output redirection'),
28
+ })
29
+ .describe('Request body for executing a command in a sandbox');
30
+
31
+ export const ExecuteDataSchema = z
32
+ .object({
33
+ executionId: z.string().describe('Unique identifier for the execution'),
34
+ status: z
35
+ .enum(['queued', 'running', 'completed', 'failed', 'timeout', 'cancelled'])
36
+ .describe('Current status of the execution'),
37
+ exitCode: z.number().optional().describe('Exit code of the executed command'),
38
+ durationMs: z.number().optional().describe('Execution duration in milliseconds'),
39
+ stdoutStreamUrl: z.string().optional().describe('URL for streaming stdout output'),
40
+ stderrStreamUrl: z.string().optional().describe('URL for streaming stderr output'),
41
+ outputTruncated: z
42
+ .boolean()
43
+ .optional()
44
+ .describe('Whether the captured output was truncated due to size limits'),
45
+ })
46
+ .describe('Response data from command execution');
47
+
48
+ export const ExecuteResponseSchema = z.discriminatedUnion('success', [
49
+ z.object({
50
+ success: z.literal(false),
51
+ message: z.string(),
52
+ code: z.string().optional(),
53
+ }),
54
+ z.object({
55
+ success: z.literal(true),
56
+ data: ExecuteDataSchema,
57
+ /** True if the sandbox was automatically resumed from a suspended state */
58
+ autoResumed: z.boolean().optional(),
59
+ }),
60
+ ]);
61
+
62
+ export const SandboxExecuteParamsSchema = z.object({
63
+ sandboxId: z.string().describe('Sandbox ID where command should execute'),
64
+ options: z.custom<ExecuteOptions>().describe('Command execution options'),
65
+ orgId: z.string().optional().describe('Optional org id for CLI auth context'),
66
+ signal: z.custom<AbortSignal>().optional().describe('Optional abort signal for cancellation'),
67
+ });
68
+
69
+ export type SandboxExecuteParams = z.infer<typeof SandboxExecuteParamsSchema>;
70
+
71
+ /**
72
+ * Executes a command in an existing sandbox.
73
+ *
74
+ * @param client - The API client to use for the request
75
+ * @param params - Parameters including sandbox ID and execution options
76
+ * @returns The execution result including status and stream URLs
77
+ * @throws {SandboxResponseError} If the execution request fails
78
+ */
79
+ export async function sandboxExecute(
80
+ client: APIClient,
81
+ params: SandboxExecuteParams
82
+ ): Promise<Execution> {
83
+ const { sandboxId, options, orgId, signal } = params;
84
+ const body: z.infer<typeof ExecuteRequestSchema> = {
85
+ command: options.command,
86
+ };
87
+
88
+ if (options.files && options.files.length > 0) {
89
+ body.files = options.files.map((f) => ({
90
+ path: f.path,
91
+ content: base64Encode(f.content),
92
+ }));
93
+ }
94
+ if (options.timeout) {
95
+ body.timeout = options.timeout;
96
+ }
97
+ if (options.stream) {
98
+ body.stream = options.stream;
99
+ }
100
+
101
+ const queryParams = new URLSearchParams();
102
+ if (orgId) {
103
+ queryParams.set('orgId', orgId);
104
+ }
105
+ const queryString = queryParams.toString();
106
+ const url = `/sandbox/${sandboxId}/execute${queryString ? `?${queryString}` : ''}`;
107
+
108
+ let resp: z.infer<typeof ExecuteResponseSchema>;
109
+ try {
110
+ resp = await client.post<z.infer<typeof ExecuteResponseSchema>>(
111
+ url,
112
+ body,
113
+ ExecuteResponseSchema,
114
+ ExecuteRequestSchema,
115
+ signal ?? options.signal
116
+ );
117
+ } catch (error: unknown) {
118
+ if (
119
+ error &&
120
+ typeof error === 'object' &&
121
+ '_tag' in error &&
122
+ (error as { _tag: string })._tag === 'APIErrorResponse' &&
123
+ 'status' in error
124
+ ) {
125
+ const status = (error as { status: number }).status;
126
+
127
+ // Detect 404 Not Found — sandbox may not exist or may still be initializing.
128
+ // The server normally handles the creating→idle wait transparently, but this
129
+ // provides a clear typed error if a 404 reaches the SDK for any reason.
130
+ if (status === 404) {
131
+ throw new SandboxNotFoundError({
132
+ message:
133
+ 'Sandbox not found. If you just created this sandbox, it may still be initializing. The server should handle this automatically — if this persists, the sandbox may have been destroyed.',
134
+ sandboxId,
135
+ });
136
+ }
137
+
138
+ // Detect 409 Conflict (sandbox busy) and throw a specific error.
139
+ // The sandbox API client is configured with maxRetries: 0 to fail fast
140
+ // when sandbox is busy (retrying wouldn't help - sandbox is still busy).
141
+ // Convert APIErrorResponse with status 409 to SandboxBusyError for clarity.
142
+ if (status === 409) {
143
+ throw new SandboxBusyError({
144
+ message:
145
+ 'Sandbox is currently busy executing another command. Please wait for the current execution to complete before submitting a new one.',
146
+ sandboxId,
147
+ });
148
+ }
149
+ }
150
+ throw error;
151
+ }
152
+
153
+ if (resp.success) {
154
+ return {
155
+ executionId: resp.data.executionId,
156
+ status: resp.data.status as ExecutionStatus,
157
+ exitCode: resp.data.exitCode,
158
+ durationMs: resp.data.durationMs,
159
+ stdoutStreamUrl: resp.data.stdoutStreamUrl,
160
+ stderrStreamUrl: resp.data.stderrStreamUrl,
161
+ outputTruncated: resp.data.outputTruncated,
162
+ autoResumed: resp.autoResumed,
163
+ };
164
+ }
165
+
166
+ throwSandboxError(resp, { sandboxId });
167
+ }
@@ -0,0 +1,152 @@
1
+ import { ExecutionStatusSchema } from './types.ts';
2
+ import { z } from 'zod';
3
+ import { type APIClient, APIResponseSchema } from '@agentuity/api';
4
+ import { throwSandboxError } from './util.ts';
5
+
6
+ export 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
+ type: z
11
+ .string()
12
+ .optional()
13
+ .describe('Type of execution (e.g., exec, write_files, read_file)'),
14
+ status: ExecutionStatusSchema.describe('Current status of the execution'),
15
+ command: z.array(z.string()).optional().describe('Command that was executed'),
16
+ exitCode: z.number().optional().describe('Exit code of the executed command'),
17
+ durationMs: z.number().optional().describe('Execution duration in milliseconds'),
18
+ startedAt: z.string().optional().describe('ISO timestamp when execution started'),
19
+ completedAt: z.string().optional().describe('ISO timestamp when execution completed'),
20
+ error: z.string().optional().describe('Error message if execution failed'),
21
+ stdoutStreamUrl: z.string().optional().describe('URL to stream stdout output'),
22
+ stderrStreamUrl: z.string().optional().describe('URL to stream stderr output'),
23
+ outputTruncated: z
24
+ .boolean()
25
+ .optional()
26
+ .describe('Whether the captured output was truncated due to size limits'),
27
+ })
28
+ .describe('Detailed information about a command execution');
29
+
30
+ export const ExecutionGetResponseSchema = APIResponseSchema(ExecutionInfoSchema);
31
+
32
+ export const ExecutionListDataSchema = z
33
+ .object({
34
+ executions: z.array(ExecutionInfoSchema).describe('List of executions'),
35
+ })
36
+ .describe('List of executions for a sandbox');
37
+
38
+ export const ExecutionListResponseSchema = APIResponseSchema(ExecutionListDataSchema);
39
+
40
+ export type ExecutionInfo = z.infer<typeof ExecutionInfoSchema>;
41
+
42
+ export const ExecutionGetParamsSchema = z.object({
43
+ executionId: z.string().describe('execution id'),
44
+ orgId: z.string().optional().describe('organization id'),
45
+ /** Optional wait duration for long-polling. */
46
+ wait: z.string().optional().describe('wait duration for long-polling'),
47
+ /** Optional AbortSignal to cancel the in-flight request. */
48
+ signal: z.custom<AbortSignal>().optional().describe('abort signal for cancellation'),
49
+ });
50
+ export type ExecutionGetParams = z.infer<typeof ExecutionGetParamsSchema>;
51
+
52
+ /**
53
+ * Retrieves detailed information about a specific execution.
54
+ *
55
+ * @param client - The API client to use for the request
56
+ * @param params - Parameters including the execution ID and optional wait duration
57
+ * @returns Detailed execution information including status, timing, and errors
58
+ * @throws {SandboxResponseError} If the execution is not found or request fails
59
+ *
60
+ * @example
61
+ * // Immediate return (current behavior)
62
+ * const info = await executionGet(client, { executionId: 'exec_123' });
63
+ *
64
+ * @example
65
+ * // Long-poll: wait up to 60 seconds for completion
66
+ * const info = await executionGet(client, { executionId: 'exec_123', wait: '60s' });
67
+ */
68
+ export async function executionGet(
69
+ client: APIClient,
70
+ params: ExecutionGetParams
71
+ ): Promise<ExecutionInfo> {
72
+ const { executionId, orgId, wait, signal } = params;
73
+ const queryParams = new URLSearchParams();
74
+ if (orgId) {
75
+ queryParams.set('orgId', orgId);
76
+ }
77
+ if (wait) {
78
+ queryParams.set('wait', wait);
79
+ }
80
+ const queryString = queryParams.toString();
81
+ const url = `/sandbox/execution/${executionId}${queryString ? `?${queryString}` : ''}`;
82
+
83
+ const resp = await client.get<z.infer<typeof ExecutionGetResponseSchema>>(
84
+ url,
85
+ ExecutionGetResponseSchema,
86
+ signal
87
+ );
88
+
89
+ if (resp.success) {
90
+ return {
91
+ executionId: resp.data.executionId,
92
+ sandboxId: resp.data.sandboxId,
93
+ type: resp.data.type,
94
+ status: resp.data.status,
95
+ command: resp.data.command,
96
+ exitCode: resp.data.exitCode,
97
+ durationMs: resp.data.durationMs,
98
+ startedAt: resp.data.startedAt,
99
+ completedAt: resp.data.completedAt,
100
+ error: resp.data.error,
101
+ stdoutStreamUrl: resp.data.stdoutStreamUrl,
102
+ stderrStreamUrl: resp.data.stderrStreamUrl,
103
+ outputTruncated: resp.data.outputTruncated,
104
+ };
105
+ }
106
+
107
+ throwSandboxError(resp, { executionId });
108
+ }
109
+
110
+ export const ExecutionListParamsSchema = z.object({
111
+ sandboxId: z.string().describe('sandbox id'),
112
+ orgId: z.string().optional().describe('organization id'),
113
+ limit: z.number().optional().describe('limit'),
114
+ });
115
+ export type ExecutionListParams = z.infer<typeof ExecutionListParamsSchema>;
116
+
117
+ export type ExecutionListResponse = z.infer<typeof ExecutionListDataSchema>;
118
+
119
+ /**
120
+ * Lists all executions for a specific sandbox.
121
+ *
122
+ * @param client - The API client to use for the request
123
+ * @param params - Parameters including the sandbox ID and optional limit
124
+ * @returns List of execution information for the sandbox
125
+ * @throws {SandboxResponseError} If the sandbox is not found or request fails
126
+ */
127
+ export async function executionList(
128
+ client: APIClient,
129
+ params: ExecutionListParams
130
+ ): Promise<ExecutionListResponse> {
131
+ const { sandboxId, orgId, limit } = params;
132
+ const queryParams = new URLSearchParams();
133
+ if (orgId) {
134
+ queryParams.set('orgId', orgId);
135
+ }
136
+ if (limit !== undefined) {
137
+ queryParams.set('limit', String(limit));
138
+ }
139
+ const queryString = queryParams.toString();
140
+ const url = `/sandbox/sandboxes/${sandboxId}/executions${queryString ? `?${queryString}` : ''}`;
141
+
142
+ const resp = await client.get<z.infer<typeof ExecutionListResponseSchema>>(
143
+ url,
144
+ ExecutionListResponseSchema
145
+ );
146
+
147
+ if (resp.success) {
148
+ return resp.data;
149
+ }
150
+
151
+ throwSandboxError(resp, { sandboxId });
152
+ }