@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/job.ts ADDED
@@ -0,0 +1,161 @@
1
+ import { type APIClient, APIResponseSchema } from '@agentuity/api';
2
+ import { CreateJobOptionsSchema, JobSchema, type Job } from './types.ts';
3
+ import { throwSandboxError } from './util.ts';
4
+ import { z } from 'zod';
5
+
6
+ export const CreateJobRequestSchema = CreateJobOptionsSchema;
7
+
8
+ export const CreateJobDataSchema = JobSchema;
9
+
10
+ export const CreateJobResponseSchema = APIResponseSchema(CreateJobDataSchema);
11
+
12
+ export const JobCreateParamsSchema = z.object({
13
+ sandboxId: z.string().describe('Sandbox ID where the job should run'),
14
+ options: CreateJobOptionsSchema.describe('Job creation options'),
15
+ orgId: z.string().optional().describe('Optional org id for CLI auth context'),
16
+ signal: z.custom<AbortSignal>().optional().describe('Optional abort signal for cancellation'),
17
+ });
18
+ export type JobCreateParams = z.infer<typeof JobCreateParamsSchema>;
19
+
20
+ export async function jobCreate(client: APIClient, params: JobCreateParams): Promise<Job> {
21
+ const { sandboxId, options, orgId, signal } = params;
22
+ const body: z.infer<typeof CreateJobRequestSchema> = {
23
+ command: options.command,
24
+ };
25
+ if (options.streams) {
26
+ body.streams = options.streams;
27
+ }
28
+
29
+ const queryParams = new URLSearchParams();
30
+ if (orgId) {
31
+ queryParams.set('orgId', orgId);
32
+ }
33
+ const queryString = queryParams.toString();
34
+ const url = `/sandbox/sandboxes/${sandboxId}/jobs${queryString ? `?${queryString}` : ''}`;
35
+
36
+ const resp = await client.post<z.infer<typeof CreateJobResponseSchema>>(
37
+ url,
38
+ body,
39
+ CreateJobResponseSchema,
40
+ CreateJobRequestSchema,
41
+ signal
42
+ );
43
+
44
+ if (resp.success) {
45
+ return resp.data;
46
+ }
47
+
48
+ throwSandboxError(resp, { sandboxId });
49
+ }
50
+
51
+ export const JobGetDataSchema = JobSchema;
52
+
53
+ export const JobGetResponseSchema = APIResponseSchema(JobGetDataSchema);
54
+
55
+ export const JobGetParamsSchema = z.object({
56
+ sandboxId: z.string().describe('Sandbox ID'),
57
+ jobId: z.string().describe('Job ID'),
58
+ orgId: z.string().optional().describe('Organization ID'),
59
+ signal: z.custom<AbortSignal>().optional().describe('Abort signal for cancellation'),
60
+ });
61
+ export type JobGetParams = z.infer<typeof JobGetParamsSchema>;
62
+
63
+ export async function jobGet(client: APIClient, params: JobGetParams): Promise<Job> {
64
+ const { sandboxId, jobId, orgId, signal } = params;
65
+ const queryParams = new URLSearchParams();
66
+ if (orgId) {
67
+ queryParams.set('orgId', orgId);
68
+ }
69
+ const queryString = queryParams.toString();
70
+ const url = `/sandbox/sandboxes/${sandboxId}/jobs/${jobId}${queryString ? `?${queryString}` : ''}`;
71
+
72
+ const resp = await client.get<z.infer<typeof JobGetResponseSchema>>(
73
+ url,
74
+ JobGetResponseSchema,
75
+ signal
76
+ );
77
+
78
+ if (resp.success) {
79
+ return resp.data;
80
+ }
81
+
82
+ throwSandboxError(resp, { sandboxId, jobId: params.jobId });
83
+ }
84
+
85
+ export const JobListDataSchema = z.object({
86
+ jobs: z.array(JobSchema).describe('List of jobs'),
87
+ });
88
+ export type JobListResponse = z.infer<typeof JobListDataSchema>;
89
+
90
+ export const JobListResponseSchema = APIResponseSchema(JobListDataSchema);
91
+
92
+ export const JobListParamsSchema = z.object({
93
+ sandboxId: z.string().describe('Sandbox ID'),
94
+ orgId: z.string().optional().describe('Organization ID'),
95
+ limit: z.number().optional().describe('Maximum number of results'),
96
+ signal: z.custom<AbortSignal>().optional().describe('Abort signal for cancellation'),
97
+ });
98
+ export type JobListParams = z.infer<typeof JobListParamsSchema>;
99
+
100
+ export async function jobList(client: APIClient, params: JobListParams): Promise<JobListResponse> {
101
+ const { sandboxId, orgId, limit, signal } = params;
102
+ const queryParams = new URLSearchParams();
103
+ if (orgId) {
104
+ queryParams.set('orgId', orgId);
105
+ }
106
+ if (limit !== undefined) {
107
+ queryParams.set('limit', String(limit));
108
+ }
109
+ const queryString = queryParams.toString();
110
+ const url = `/sandbox/sandboxes/${sandboxId}/jobs${queryString ? `?${queryString}` : ''}`;
111
+
112
+ const resp = await client.get<z.infer<typeof JobListResponseSchema>>(
113
+ url,
114
+ JobListResponseSchema,
115
+ signal
116
+ );
117
+
118
+ if (resp.success) {
119
+ return resp.data;
120
+ }
121
+
122
+ throwSandboxError(resp, { sandboxId });
123
+ }
124
+
125
+ export const JobStopDataSchema = JobSchema;
126
+
127
+ export const JobStopResponseSchema = APIResponseSchema(JobStopDataSchema);
128
+
129
+ export const JobStopParamsSchema = z.object({
130
+ sandboxId: z.string().describe('Sandbox ID'),
131
+ jobId: z.string().describe('Job ID'),
132
+ force: z.boolean().optional().describe('Force termination (SIGKILL)'),
133
+ orgId: z.string().optional().describe('Organization ID'),
134
+ signal: z.custom<AbortSignal>().optional().describe('Abort signal for cancellation'),
135
+ });
136
+ export type JobStopParams = z.infer<typeof JobStopParamsSchema>;
137
+
138
+ export async function jobStop(client: APIClient, params: JobStopParams): Promise<Job> {
139
+ const { sandboxId, jobId, force, orgId, signal } = params;
140
+ const queryParams = new URLSearchParams();
141
+ if (orgId) {
142
+ queryParams.set('orgId', orgId);
143
+ }
144
+ if (force) {
145
+ queryParams.set('force', 'true');
146
+ }
147
+ const queryString = queryParams.toString();
148
+ const url = `/sandbox/sandboxes/${sandboxId}/jobs/${jobId}${queryString ? `?${queryString}` : ''}`;
149
+
150
+ const resp = await client.delete<z.infer<typeof JobStopResponseSchema>>(
151
+ url,
152
+ JobStopResponseSchema,
153
+ signal
154
+ );
155
+
156
+ if (resp.success) {
157
+ return resp.data;
158
+ }
159
+
160
+ throwSandboxError(resp, { sandboxId, jobId: params.jobId });
161
+ }
package/src/list.ts ADDED
@@ -0,0 +1,239 @@
1
+ import type {
2
+ ListSandboxesResponse,
3
+ SandboxRuntimeInfo,
4
+ SandboxSnapshotInfo,
5
+ SandboxStatus,
6
+ } from './types.ts';
7
+ import { ListSandboxesParamsSchema } from './types.ts';
8
+ import { z } from 'zod';
9
+ import { type APIClient, APIResponseSchema } from '@agentuity/api';
10
+ import { throwSandboxError } from './util.ts';
11
+
12
+ export const SandboxOrgInfoSchema = z
13
+ .object({
14
+ id: z.string().describe('Organization ID'),
15
+ name: z.string().describe('Organization name'),
16
+ })
17
+ .describe('Organization associated with the sandbox');
18
+
19
+ export const SandboxRuntimeInfoSchema = z
20
+ .object({
21
+ id: z.string().describe('Runtime ID'),
22
+ name: z.string().describe('Runtime name (e.g., "bun:1")'),
23
+ iconUrl: z.string().optional().describe('URL for runtime icon'),
24
+ brandColor: z.string().optional().describe('Brand color for the runtime (hex color code)'),
25
+ tags: z.array(z.string()).optional().describe('Optional tags for categorization'),
26
+ })
27
+ .describe('Runtime information');
28
+
29
+ export const SandboxSnapshotUserInfoSchema = z
30
+ .object({
31
+ id: z.string().describe('User ID'),
32
+ firstName: z.string().optional().describe("User's first name"),
33
+ lastName: z.string().optional().describe("User's last name"),
34
+ })
35
+ .describe('Snapshot user information');
36
+
37
+ export const SandboxSnapshotOrgInfoSchema = z
38
+ .object({
39
+ id: z.string().describe('Organization ID'),
40
+ name: z.string().describe('Organization name'),
41
+ slug: z.string().optional().describe('Organization slug'),
42
+ })
43
+ .describe('Snapshot organization information');
44
+
45
+ export const SandboxSnapshotInfoSchema = z
46
+ .union([
47
+ z
48
+ .object({
49
+ id: z.string().describe('Snapshot ID'),
50
+ name: z.string().optional().describe('Snapshot name'),
51
+ tag: z.string().optional().describe('Snapshot tag'),
52
+ fullName: z.string().optional().describe('Full name with org slug (@slug/name:tag)'),
53
+ public: z.literal(true).describe('Public snapshot'),
54
+ org: SandboxSnapshotOrgInfoSchema.describe(
55
+ 'Organization that owns the public snapshot'
56
+ ),
57
+ })
58
+ .describe('Public snapshot'),
59
+ z
60
+ .object({
61
+ id: z.string().describe('Snapshot ID'),
62
+ name: z.string().optional().describe('Snapshot name'),
63
+ tag: z.string().optional().describe('Snapshot tag'),
64
+ fullName: z.string().optional().describe('Full name with org slug (@slug/name:tag)'),
65
+ public: z.literal(false).describe('Private snapshot'),
66
+ user: SandboxSnapshotUserInfoSchema.describe('User who created the private snapshot'),
67
+ })
68
+ .describe('Private snapshot'),
69
+ ])
70
+ .describe('Snapshot information (discriminated union)');
71
+
72
+ export const SandboxInfoSchema = z
73
+ .object({
74
+ sandboxId: z.string().describe('Unique identifier for the sandbox'),
75
+ identifier: z.string().optional().describe('Short identifier for DNS hostname'),
76
+ name: z.string().optional().describe('Sandbox name'),
77
+ description: z.string().optional().describe('Sandbox description'),
78
+ status: z
79
+ .enum([
80
+ 'creating',
81
+ 'idle',
82
+ 'running',
83
+ 'paused',
84
+ 'stopping',
85
+ 'suspended',
86
+ 'terminated',
87
+ 'failed',
88
+ 'deleted',
89
+ ])
90
+ .describe('Current status of the sandbox'),
91
+ mode: z.string().optional().describe('Sandbox mode (interactive or oneshot)'),
92
+ createdAt: z.string().describe('ISO timestamp when the sandbox was created'),
93
+ region: z.string().optional().describe('Region where the sandbox is running'),
94
+ runtime: SandboxRuntimeInfoSchema.optional().describe('Runtime information'),
95
+ snapshot: SandboxSnapshotInfoSchema.optional().describe('Snapshot information'),
96
+ executions: z.number().describe('Total number of executions in this sandbox'),
97
+ stdoutStreamUrl: z.string().optional().describe('URL for streaming stdout output'),
98
+ stderrStreamUrl: z.string().optional().describe('URL for streaming stderr output'),
99
+ auditStreamId: z.string().optional().describe('ID of the audit event stream'),
100
+ auditStreamUrl: z.string().optional().describe('URL for streaming audit events'),
101
+ networkEnabled: z.boolean().optional().describe('Whether network access is enabled'),
102
+ networkPort: z.number().optional().describe('Network port exposed from the sandbox'),
103
+ url: z
104
+ .string()
105
+ .optional()
106
+ .describe('Public URL for the sandbox (only set if networkPort is configured)'),
107
+ org: SandboxOrgInfoSchema.describe('Organization associated with the sandbox'),
108
+ timeout: z
109
+ .object({
110
+ idle: z.string().optional().describe('Idle timeout duration (e.g., "5m", "1h").'),
111
+ execution: z
112
+ .string()
113
+ .optional()
114
+ .describe('Execution timeout duration (e.g., "30m", "2h").'),
115
+ paused: z
116
+ .string()
117
+ .optional()
118
+ .describe('Paused timeout duration (e.g., "24h", "0s" for infinite).'),
119
+ })
120
+ .optional()
121
+ .describe('Timeout configuration for the sandbox.'),
122
+ command: z
123
+ .object({
124
+ exec: z.array(z.string()).describe('Command and arguments to execute.'),
125
+ mode: z
126
+ .enum(['oneshot', 'interactive'])
127
+ .optional()
128
+ .describe('Execution mode for the command.'),
129
+ })
130
+ .optional()
131
+ .describe('Command configuration for the sandbox.'),
132
+ })
133
+ .describe('Summary information about a sandbox');
134
+
135
+ export const ListSandboxesDataSchema = z
136
+ .object({
137
+ sandboxes: z.array(SandboxInfoSchema).describe('List of sandbox entries'),
138
+ total: z.number().describe('Total number of sandboxes matching the query'),
139
+ })
140
+ .describe('Paginated list of sandboxes');
141
+
142
+ export const ListSandboxesResponseSchema = APIResponseSchema(ListSandboxesDataSchema);
143
+
144
+ export const SandboxListParamsSchema = ListSandboxesParamsSchema.extend({
145
+ orgId: z.string().optional().describe('Optional org id for CLI auth context'),
146
+ deletedOnly: z.boolean().optional().describe('Whether to return only deleted sandboxes'),
147
+ });
148
+
149
+ export type SandboxListParams = z.infer<typeof SandboxListParamsSchema>;
150
+
151
+ /**
152
+ * Lists sandboxes with optional filtering and pagination.
153
+ *
154
+ * @param client - The API client to use for the request
155
+ * @param params - Optional parameters for filtering by project, status, and pagination
156
+ * @returns Paginated list of sandboxes with total count
157
+ * @throws {SandboxResponseError} If the request fails
158
+ */
159
+ export async function sandboxList(
160
+ client: APIClient,
161
+ params?: SandboxListParams
162
+ ): Promise<ListSandboxesResponse> {
163
+ const queryParams = new URLSearchParams();
164
+
165
+ if (params?.orgId) {
166
+ queryParams.set('orgId', params.orgId);
167
+ }
168
+ if (params?.name) {
169
+ queryParams.set('name', params.name);
170
+ }
171
+ if (params?.mode) {
172
+ queryParams.set('mode', params.mode);
173
+ }
174
+ if (params?.projectId) {
175
+ queryParams.set('projectId', params.projectId);
176
+ }
177
+ if (params?.snapshotId) {
178
+ queryParams.set('snapshotId', params.snapshotId);
179
+ }
180
+ if (params?.status) {
181
+ queryParams.set('status', params.status);
182
+ }
183
+ if (params?.live !== undefined) {
184
+ queryParams.set('live', params.live.toString());
185
+ }
186
+ if (params?.limit !== undefined) {
187
+ queryParams.set('limit', params.limit.toString());
188
+ }
189
+ if (params?.offset !== undefined) {
190
+ queryParams.set('offset', params.offset.toString());
191
+ }
192
+ if (params?.sort) {
193
+ queryParams.set('sort', params.sort);
194
+ }
195
+ if (params?.direction) {
196
+ queryParams.set('direction', params.direction);
197
+ }
198
+ if (params?.deletedOnly) {
199
+ queryParams.set('deletedOnly', 'true');
200
+ }
201
+
202
+ const queryString = queryParams.toString();
203
+ const url = `/sandbox${queryString ? `?${queryString}` : ''}`;
204
+
205
+ const resp = await client.get<z.infer<typeof ListSandboxesResponseSchema>>(
206
+ url,
207
+ ListSandboxesResponseSchema
208
+ );
209
+
210
+ if (resp.success) {
211
+ return {
212
+ sandboxes: resp.data.sandboxes.map((s) => ({
213
+ sandboxId: s.sandboxId,
214
+ identifier: s.identifier,
215
+ name: s.name,
216
+ description: s.description,
217
+ status: s.status as SandboxStatus,
218
+ mode: s.mode,
219
+ createdAt: s.createdAt,
220
+ region: s.region,
221
+ runtime: s.runtime as SandboxRuntimeInfo | undefined,
222
+ snapshot: s.snapshot as SandboxSnapshotInfo | undefined,
223
+ executions: s.executions,
224
+ stdoutStreamUrl: s.stdoutStreamUrl,
225
+ stderrStreamUrl: s.stderrStreamUrl,
226
+ auditStreamId: s.auditStreamId,
227
+ auditStreamUrl: s.auditStreamUrl,
228
+ networkEnabled: s.networkEnabled,
229
+ networkPort: s.networkPort,
230
+ url: s.url,
231
+ org: s.org,
232
+ timeout: s.timeout,
233
+ })),
234
+ total: resp.data.total,
235
+ };
236
+ }
237
+
238
+ throwSandboxError(resp, {});
239
+ }
package/src/pause.ts ADDED
@@ -0,0 +1,75 @@
1
+ import { z } from 'zod';
2
+ import { type APIClient } from '@agentuity/api';
3
+ import { throwSandboxError } from './util.ts';
4
+
5
+ export const PauseResponseSchema = z.discriminatedUnion('success', [
6
+ z.object({
7
+ success: z.literal<false>(false),
8
+ message: z.string(),
9
+ code: z.string().optional(),
10
+ }),
11
+ z.object({
12
+ success: z.literal<true>(true),
13
+ sandboxId: z.string(),
14
+ status: z.string(),
15
+ checkpointId: z.string().optional(),
16
+ terminatesAt: z.string().optional(),
17
+ }),
18
+ ]);
19
+
20
+ export const SandboxPauseParamsSchema = z.object({
21
+ sandboxId: z.string().describe('Sandbox ID to pause'),
22
+ orgId: z.string().optional().describe('Optional org id for CLI auth context'),
23
+ });
24
+
25
+ export type SandboxPauseParams = z.infer<typeof SandboxPauseParamsSchema>;
26
+
27
+ /** Result returned from pausing a sandbox */
28
+ export interface SandboxPauseResult {
29
+ /** The sandbox ID that was paused */
30
+ sandboxId: string;
31
+ /** New status (typically "suspended") */
32
+ status: string;
33
+ /** Checkpoint ID created during pause */
34
+ checkpointId?: string;
35
+ /** ISO 8601 timestamp when sandbox will auto-terminate if not resumed (omitted if no paused timeout) */
36
+ terminatesAt?: string;
37
+ }
38
+
39
+ /**
40
+ * Pauses a running sandbox, creating a checkpoint of its current state.
41
+ *
42
+ * @param client - The API client to use for the request
43
+ * @param params - Parameters including the sandbox ID to pause
44
+ * @returns Pause result including terminatesAt if a paused timeout is configured
45
+ * @throws {SandboxResponseError} If the sandbox is not found or pause fails
46
+ */
47
+ export async function sandboxPause(
48
+ client: APIClient,
49
+ params: SandboxPauseParams
50
+ ): Promise<SandboxPauseResult> {
51
+ const { sandboxId, orgId } = params;
52
+ const queryParams = new URLSearchParams();
53
+ if (orgId) {
54
+ queryParams.set('orgId', orgId);
55
+ }
56
+ const queryString = queryParams.toString();
57
+ const url = `/sandbox/${encodeURIComponent(sandboxId)}/pause${queryString ? `?${queryString}` : ''}`;
58
+
59
+ const resp = await client.post<z.infer<typeof PauseResponseSchema>>(
60
+ url,
61
+ undefined,
62
+ PauseResponseSchema
63
+ );
64
+
65
+ if (resp.success) {
66
+ return {
67
+ sandboxId: resp.sandboxId,
68
+ status: resp.status,
69
+ checkpointId: resp.checkpointId,
70
+ terminatesAt: resp.terminatesAt,
71
+ };
72
+ }
73
+
74
+ throwSandboxError(resp, { sandboxId });
75
+ }
package/src/resolve.ts ADDED
@@ -0,0 +1,96 @@
1
+ import { StructuredError } from '@agentuity/core';
2
+ import { z } from 'zod';
3
+ import { type APIClient, APIResponseSchemaOptionalData } from '@agentuity/api';
4
+
5
+ /**
6
+ * Data schema for sandbox resolve endpoint
7
+ */
8
+ export const SandboxResolveDataSchema = z
9
+ .object({
10
+ id: z.string().describe('Unique identifier for the sandbox.'),
11
+ name: z.string().nullable().describe('Sandbox name, or null if unnamed.'),
12
+ region: z.string().describe('Cloud region where the sandbox is running.'),
13
+ status: z.string().describe('Current status of the sandbox.'),
14
+ orgId: z.string().describe('Organization ID that owns the sandbox.'),
15
+ projectId: z
16
+ .string()
17
+ .nullable()
18
+ .describe('Project ID the sandbox belongs to, or null if unassigned.'),
19
+ })
20
+ .describe('Resolved sandbox information from cross-organization lookup.');
21
+
22
+ /**
23
+ * Response schema for sandbox resolve endpoint using standardized discriminated union
24
+ */
25
+ export const SandboxResolveResponseSchema = APIResponseSchemaOptionalData(SandboxResolveDataSchema);
26
+
27
+ /**
28
+ * Resolved sandbox info returned from the CLI API
29
+ */
30
+ export type ResolvedSandboxInfo = z.infer<typeof SandboxResolveDataSchema>;
31
+
32
+ /**
33
+ * Error thrown when sandbox resolution fails.
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * try {
38
+ * await sandboxResolve(client, 'sbx_123');
39
+ * } catch (error) {
40
+ * if (error._tag === 'SandboxResolveError') {
41
+ * console.error(`Sandbox not found: ${error.sandboxId}`);
42
+ * }
43
+ * }
44
+ * ```
45
+ */
46
+ export const SandboxResolveError = StructuredError('SandboxResolveError')<{
47
+ sandboxId?: string;
48
+ statusCode?: number;
49
+ }>();
50
+
51
+ /**
52
+ * Resolve a sandbox by ID across all organizations the user has access to.
53
+ * Uses the CLI API endpoint which searches across all user's orgs.
54
+ *
55
+ * @param client - API client configured for CLI endpoints
56
+ * @param sandboxId - The sandbox ID to resolve
57
+ * @returns Resolved sandbox info including region and orgId
58
+ * @throws {SandboxResolveError} If sandbox not found or request fails
59
+ */
60
+ export async function sandboxResolve(
61
+ client: APIClient,
62
+ sandboxId: string
63
+ ): Promise<ResolvedSandboxInfo> {
64
+ const response = await client.get<z.infer<typeof SandboxResolveResponseSchema>>(
65
+ `/cli/sandbox/${sandboxId}`,
66
+ SandboxResolveResponseSchema
67
+ );
68
+
69
+ if (!response.success) {
70
+ // Extract status code from error code if present (e.g., "NOT_FOUND" -> 404)
71
+ // Fall back to 404 if no code is provided
72
+ const statusCode = response.code === 'NOT_FOUND' ? 404 : response.code ? 400 : 404;
73
+ throw new SandboxResolveError({
74
+ message: response.message || 'Sandbox not found',
75
+ sandboxId,
76
+ statusCode,
77
+ });
78
+ }
79
+
80
+ if (!response.data) {
81
+ throw new SandboxResolveError({
82
+ message: 'Sandbox not found',
83
+ sandboxId,
84
+ statusCode: 404,
85
+ });
86
+ }
87
+
88
+ return {
89
+ id: response.data.id,
90
+ name: response.data.name,
91
+ region: response.data.region,
92
+ status: response.data.status,
93
+ orgId: response.data.orgId,
94
+ projectId: response.data.projectId,
95
+ };
96
+ }
package/src/resume.ts ADDED
@@ -0,0 +1,41 @@
1
+ import { z } from 'zod';
2
+ import { type APIClient, APIResponseSchemaNoData } from '@agentuity/api';
3
+ import { throwSandboxError } from './util.ts';
4
+
5
+ export const ResumeResponseSchema = APIResponseSchemaNoData();
6
+
7
+ export const SandboxResumeParamsSchema = z.object({
8
+ sandboxId: z.string().describe('Sandbox ID to resume'),
9
+ orgId: z.string().optional().describe('Optional org id for CLI auth context'),
10
+ });
11
+
12
+ export type SandboxResumeParams = z.infer<typeof SandboxResumeParamsSchema>;
13
+
14
+ /**
15
+ * Resumes a paused sandbox from its checkpoint.
16
+ *
17
+ * @param client - The API client to use for the request
18
+ * @param params - Parameters including the sandbox ID to resume
19
+ * @throws {SandboxResponseError} If the sandbox is not found or resume fails
20
+ */
21
+ export async function sandboxResume(client: APIClient, params: SandboxResumeParams): Promise<void> {
22
+ const { sandboxId, orgId } = params;
23
+ const queryParams = new URLSearchParams();
24
+ if (orgId) {
25
+ queryParams.set('orgId', orgId);
26
+ }
27
+ const queryString = queryParams.toString();
28
+ const url = `/sandbox/${encodeURIComponent(sandboxId)}/resume${queryString ? `?${queryString}` : ''}`;
29
+
30
+ const resp = await client.post<z.infer<typeof ResumeResponseSchema>>(
31
+ url,
32
+ undefined,
33
+ ResumeResponseSchema
34
+ );
35
+
36
+ if (resp.success) {
37
+ return;
38
+ }
39
+
40
+ throwSandboxError(resp, { sandboxId });
41
+ }