@agentuity/server 0.0.110 → 0.0.112
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.
- package/dist/api/api.d.ts +5 -0
- package/dist/api/api.d.ts.map +1 -1
- package/dist/api/api.js +23 -4
- package/dist/api/api.js.map +1 -1
- package/dist/api/project/deploy.d.ts +37 -1
- package/dist/api/project/deploy.d.ts.map +1 -1
- package/dist/api/project/deploy.js +49 -1
- package/dist/api/project/deploy.js.map +1 -1
- package/dist/api/sandbox/create.d.ts.map +1 -1
- package/dist/api/sandbox/create.js +7 -0
- package/dist/api/sandbox/create.js.map +1 -1
- package/dist/api/sandbox/files.d.ts +120 -0
- package/dist/api/sandbox/files.d.ts.map +1 -1
- package/dist/api/sandbox/files.js +287 -0
- package/dist/api/sandbox/files.js.map +1 -1
- package/dist/api/sandbox/get.d.ts.map +1 -1
- package/dist/api/sandbox/get.js +14 -0
- package/dist/api/sandbox/get.js.map +1 -1
- package/dist/api/sandbox/index.d.ts +2 -2
- package/dist/api/sandbox/index.d.ts.map +1 -1
- package/dist/api/sandbox/index.js +1 -1
- package/dist/api/sandbox/index.js.map +1 -1
- package/dist/api/sandbox/snapshot.d.ts +0 -1
- package/dist/api/sandbox/snapshot.d.ts.map +1 -1
- package/dist/api/sandbox/snapshot.js +6 -8
- package/dist/api/sandbox/snapshot.js.map +1 -1
- package/dist/config.d.ts +7 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +17 -4
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +3 -1
- package/dist/schema.js.map +1 -1
- package/package.json +5 -5
- package/src/api/api.ts +40 -4
- package/src/api/project/deploy.ts +97 -1
- package/src/api/sandbox/create.ts +7 -0
- package/src/api/sandbox/files.ts +450 -0
- package/src/api/sandbox/get.ts +15 -0
- package/src/api/sandbox/index.ts +27 -2
- package/src/api/sandbox/snapshot.ts +6 -10
- package/src/config.ts +21 -4
- package/src/index.ts +1 -1
- package/src/schema.ts +3 -1
package/dist/schema.js
CHANGED
|
@@ -12,7 +12,9 @@ export const toJSONSchema = (schema) => {
|
|
|
12
12
|
return agentuityToJSONSchema(schema);
|
|
13
13
|
}
|
|
14
14
|
// Check if it's a Zod schema
|
|
15
|
-
|
|
15
|
+
// Zod 3 uses _def.typeName (e.g., "ZodObject")
|
|
16
|
+
// Zod 4 uses _def.type (e.g., "object")
|
|
17
|
+
if (schema?._def?.typeName || schema?._def?.type) {
|
|
16
18
|
try {
|
|
17
19
|
return z.toJSONSchema(schema);
|
|
18
20
|
}
|
package/dist/schema.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,IAAI,qBAAqB,EAAmB,MAAM,mBAAmB,CAAC;AAE3F;;;;GAIG;AACH,8DAA8D;AAC9D,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,MAAW,EAAc,EAAE;IACvD,gEAAgE;IAChE,IAAI,MAAM,EAAE,CAAC,WAAW,CAAC,EAAE,MAAM,KAAK,WAAW,EAAE,CAAC;QACnD,OAAO,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IACD,6BAA6B;IAC7B,IAAI,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,IAAI,qBAAqB,EAAmB,MAAM,mBAAmB,CAAC;AAE3F;;;;GAIG;AACH,8DAA8D;AAC9D,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,MAAW,EAAc,EAAE;IACvD,gEAAgE;IAChE,IAAI,MAAM,EAAE,CAAC,WAAW,CAAC,EAAE,MAAM,KAAK,WAAW,EAAE,CAAC;QACnD,OAAO,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IACD,6BAA6B;IAC7B,+CAA+C;IAC/C,wCAAwC;IACxC,IAAI,MAAM,EAAE,IAAI,EAAE,QAAQ,IAAI,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAClD,IAAI,CAAC;YACJ,OAAO,CAAC,CAAC,YAAY,CAAC,MAAM,CAAe,CAAC;QAC7C,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,EAAE,CAAC;QACX,CAAC;IACF,CAAC;IACD,sBAAsB;IACtB,OAAO,EAAE,CAAC;AACX,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentuity/server",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.112",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"author": "Agentuity employees and contributors",
|
|
6
6
|
"type": "module",
|
|
@@ -25,12 +25,12 @@
|
|
|
25
25
|
"prepublishOnly": "bun run clean && bun run build"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@agentuity/core": "0.0.
|
|
29
|
-
"@agentuity/schema": "0.0.
|
|
30
|
-
"zod": "^4.
|
|
28
|
+
"@agentuity/core": "0.0.112",
|
|
29
|
+
"@agentuity/schema": "0.0.112",
|
|
30
|
+
"zod": "^4.3.5"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@agentuity/test-utils": "0.0.
|
|
33
|
+
"@agentuity/test-utils": "0.0.112",
|
|
34
34
|
"@types/bun": "latest",
|
|
35
35
|
"@types/node": "^22.0.0",
|
|
36
36
|
"bun-types": "latest",
|
package/src/api/api.ts
CHANGED
|
@@ -186,6 +186,19 @@ export class APIClient {
|
|
|
186
186
|
return this.#makeRequest('GET', endpoint, undefined, signal);
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
+
/**
|
|
190
|
+
* Raw POST request that returns the Response object directly.
|
|
191
|
+
* Useful for binary uploads where you need to pass raw body data.
|
|
192
|
+
*/
|
|
193
|
+
async rawPost(
|
|
194
|
+
endpoint: string,
|
|
195
|
+
body: Uint8Array | ArrayBuffer | ReadableStream<Uint8Array> | string,
|
|
196
|
+
contentType: string,
|
|
197
|
+
signal?: AbortSignal
|
|
198
|
+
): Promise<Response> {
|
|
199
|
+
return this.#makeRequest('POST', endpoint, body, signal, contentType);
|
|
200
|
+
}
|
|
201
|
+
|
|
189
202
|
/**
|
|
190
203
|
* Generic request method (prefer HTTP verb methods: get, post, put, delete, patch)
|
|
191
204
|
*/
|
|
@@ -249,7 +262,8 @@ export class APIClient {
|
|
|
249
262
|
method: string,
|
|
250
263
|
endpoint: string,
|
|
251
264
|
body?: unknown,
|
|
252
|
-
signal?: AbortSignal
|
|
265
|
+
signal?: AbortSignal,
|
|
266
|
+
contentType?: string
|
|
253
267
|
): Promise<Response> {
|
|
254
268
|
this.#logger.trace('sending %s to %s%s', method, this.#baseUrl, endpoint);
|
|
255
269
|
|
|
@@ -260,10 +274,14 @@ export class APIClient {
|
|
|
260
274
|
try {
|
|
261
275
|
const url = `${this.#baseUrl}${endpoint}`;
|
|
262
276
|
const headers: Record<string, string> = {
|
|
263
|
-
'Content-Type': 'application/json',
|
|
264
|
-
Accept: 'application/json',
|
|
277
|
+
'Content-Type': contentType ?? 'application/json',
|
|
265
278
|
};
|
|
266
279
|
|
|
280
|
+
// Only set Accept header for JSON requests (not binary uploads)
|
|
281
|
+
if (!contentType || contentType === 'application/json') {
|
|
282
|
+
headers['Accept'] = 'application/json';
|
|
283
|
+
}
|
|
284
|
+
|
|
267
285
|
if (this.#config?.userAgent) {
|
|
268
286
|
headers['User-Agent'] = this.#config.userAgent;
|
|
269
287
|
}
|
|
@@ -281,10 +299,28 @@ export class APIClient {
|
|
|
281
299
|
let response: Response;
|
|
282
300
|
|
|
283
301
|
try {
|
|
302
|
+
let requestBody:
|
|
303
|
+
| Uint8Array
|
|
304
|
+
| ArrayBuffer
|
|
305
|
+
| ReadableStream<Uint8Array>
|
|
306
|
+
| string
|
|
307
|
+
| undefined;
|
|
308
|
+
if (body !== undefined) {
|
|
309
|
+
if (contentType && contentType !== 'application/json') {
|
|
310
|
+
requestBody = body as
|
|
311
|
+
| Uint8Array
|
|
312
|
+
| ArrayBuffer
|
|
313
|
+
| ReadableStream<Uint8Array>
|
|
314
|
+
| string;
|
|
315
|
+
} else {
|
|
316
|
+
requestBody = JSON.stringify(body);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
284
320
|
response = await fetch(url, {
|
|
285
321
|
method,
|
|
286
322
|
headers,
|
|
287
|
-
body:
|
|
323
|
+
body: requestBody,
|
|
288
324
|
signal,
|
|
289
325
|
});
|
|
290
326
|
} catch (ex) {
|
|
@@ -33,7 +33,7 @@ const BaseFileFields = {
|
|
|
33
33
|
const EvalSchema = z.object({
|
|
34
34
|
...BaseFileFields,
|
|
35
35
|
id: z.string().describe('the unique calculated id for the eval'),
|
|
36
|
-
|
|
36
|
+
identifier: z.string().describe('the unique id for eval for the project across deployments'),
|
|
37
37
|
name: z.string().describe('the name of the eval'),
|
|
38
38
|
description: z.string().optional().describe('the eval description'),
|
|
39
39
|
agentIdentifier: z.string().describe('the identifier of the agent'),
|
|
@@ -164,6 +164,10 @@ const CreateProjectDeployment = z.object({
|
|
|
164
164
|
id: z.string().describe('the unique id for the deployment'),
|
|
165
165
|
orgId: z.string().describe('the organization id'),
|
|
166
166
|
publicKey: z.string().describe('the public key to use for encrypting the deployment'),
|
|
167
|
+
buildLogsStreamURL: z
|
|
168
|
+
.string()
|
|
169
|
+
.optional()
|
|
170
|
+
.describe('the URL for streaming build logs (PUT to write, GET to read)'),
|
|
167
171
|
});
|
|
168
172
|
|
|
169
173
|
const CreateProjectDeploymentSchema = APIResponseSchema(CreateProjectDeployment);
|
|
@@ -314,3 +318,95 @@ export async function projectDeploymentStatus(
|
|
|
314
318
|
}
|
|
315
319
|
throw new ProjectResponseError({ message: resp.message });
|
|
316
320
|
}
|
|
321
|
+
|
|
322
|
+
export interface ClientDiagnosticsError {
|
|
323
|
+
type: 'file' | 'general';
|
|
324
|
+
scope: 'typescript' | 'ast' | 'build' | 'bundler' | 'validation' | 'deploy';
|
|
325
|
+
path?: string;
|
|
326
|
+
line?: number;
|
|
327
|
+
column?: number;
|
|
328
|
+
message: string;
|
|
329
|
+
code?: string;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
export interface ClientDiagnosticsTiming {
|
|
333
|
+
name: string;
|
|
334
|
+
startedAt: string;
|
|
335
|
+
completedAt: string;
|
|
336
|
+
durationMs: number;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
export interface ClientDiagnostics {
|
|
340
|
+
success: boolean;
|
|
341
|
+
errors: ClientDiagnosticsError[];
|
|
342
|
+
warnings: ClientDiagnosticsError[];
|
|
343
|
+
diagnostics: ClientDiagnosticsTiming[];
|
|
344
|
+
error?: string;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export interface DeploymentFailPayload {
|
|
348
|
+
error?: string;
|
|
349
|
+
diagnostics?: ClientDiagnostics;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const ClientDiagnosticsErrorSchema = z.object({
|
|
353
|
+
type: z.enum(['file', 'general']),
|
|
354
|
+
scope: z.enum(['typescript', 'ast', 'build', 'bundler', 'validation', 'deploy']),
|
|
355
|
+
path: z.string().optional(),
|
|
356
|
+
line: z.number().optional(),
|
|
357
|
+
column: z.number().optional(),
|
|
358
|
+
message: z.string(),
|
|
359
|
+
code: z.string().optional(),
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
const ClientDiagnosticsTimingSchema = z.object({
|
|
363
|
+
name: z.string(),
|
|
364
|
+
startedAt: z.string(),
|
|
365
|
+
completedAt: z.string(),
|
|
366
|
+
durationMs: z.number(),
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
const ClientDiagnosticsSchema = z.object({
|
|
370
|
+
success: z.boolean(),
|
|
371
|
+
errors: z.array(ClientDiagnosticsErrorSchema),
|
|
372
|
+
warnings: z.array(ClientDiagnosticsErrorSchema),
|
|
373
|
+
diagnostics: z.array(ClientDiagnosticsTimingSchema),
|
|
374
|
+
error: z.string().optional(),
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
const DeploymentFailPayloadSchema = z.object({
|
|
378
|
+
error: z.string().optional(),
|
|
379
|
+
diagnostics: ClientDiagnosticsSchema.optional(),
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
const DeploymentFailResponseObject = z.object({
|
|
383
|
+
state: z.literal('failed'),
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
const DeploymentFailResponseSchema = APIResponseSchema(DeploymentFailResponseObject);
|
|
387
|
+
type DeploymentFailResponse = z.infer<typeof DeploymentFailResponseSchema>;
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Report a deployment failure from the client
|
|
391
|
+
*
|
|
392
|
+
* @param client
|
|
393
|
+
* @param deploymentId
|
|
394
|
+
* @param payload - Error message and/or structured diagnostics
|
|
395
|
+
* @returns
|
|
396
|
+
*/
|
|
397
|
+
export async function projectDeploymentFail(
|
|
398
|
+
client: APIClient,
|
|
399
|
+
deploymentId: string,
|
|
400
|
+
payload: DeploymentFailPayload
|
|
401
|
+
): Promise<void> {
|
|
402
|
+
const resp = await client.request<DeploymentFailResponse, DeploymentFailPayload>(
|
|
403
|
+
'POST',
|
|
404
|
+
`/cli/deploy/1/fail/${deploymentId}`,
|
|
405
|
+
DeploymentFailResponseSchema,
|
|
406
|
+
payload,
|
|
407
|
+
DeploymentFailPayloadSchema
|
|
408
|
+
);
|
|
409
|
+
if (!resp.success) {
|
|
410
|
+
throw new ProjectResponseError({ message: resp.message });
|
|
411
|
+
}
|
|
412
|
+
}
|
|
@@ -65,6 +65,10 @@ const SandboxCreateRequestSchema = z
|
|
|
65
65
|
.array(z.string())
|
|
66
66
|
.optional()
|
|
67
67
|
.describe('Apt packages to install when creating the sandbox'),
|
|
68
|
+
metadata: z
|
|
69
|
+
.record(z.string(), z.unknown())
|
|
70
|
+
.optional()
|
|
71
|
+
.describe('Optional user-defined metadata to associate with the sandbox'),
|
|
68
72
|
})
|
|
69
73
|
.describe('Request body for creating a new sandbox');
|
|
70
74
|
|
|
@@ -143,6 +147,9 @@ export async function sandboxCreate(
|
|
|
143
147
|
if (options.dependencies && options.dependencies.length > 0) {
|
|
144
148
|
body.dependencies = options.dependencies;
|
|
145
149
|
}
|
|
150
|
+
if (options.metadata) {
|
|
151
|
+
body.metadata = options.metadata;
|
|
152
|
+
}
|
|
146
153
|
|
|
147
154
|
const queryParams = new URLSearchParams();
|
|
148
155
|
if (orgId) {
|
package/src/api/sandbox/files.ts
CHANGED
|
@@ -136,3 +136,453 @@ export async function sandboxReadFile(
|
|
|
136
136
|
|
|
137
137
|
return response.body;
|
|
138
138
|
}
|
|
139
|
+
|
|
140
|
+
const MkDirRequestSchema = z
|
|
141
|
+
.object({
|
|
142
|
+
path: z.string().describe('Path to the directory to create'),
|
|
143
|
+
recursive: z.boolean().optional().describe('Create parent directories if needed'),
|
|
144
|
+
})
|
|
145
|
+
.describe('Request body for creating a directory');
|
|
146
|
+
|
|
147
|
+
const MkDirResponseSchema = z.discriminatedUnion('success', [
|
|
148
|
+
z.object({
|
|
149
|
+
success: z.literal<false>(false),
|
|
150
|
+
message: z.string().describe('the error message'),
|
|
151
|
+
}),
|
|
152
|
+
z.object({
|
|
153
|
+
success: z.literal<true>(true),
|
|
154
|
+
}),
|
|
155
|
+
]);
|
|
156
|
+
|
|
157
|
+
export interface MkDirParams {
|
|
158
|
+
sandboxId: string;
|
|
159
|
+
path: string;
|
|
160
|
+
recursive?: boolean;
|
|
161
|
+
orgId?: string;
|
|
162
|
+
signal?: AbortSignal;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Creates a directory in a sandbox workspace.
|
|
167
|
+
*
|
|
168
|
+
* @param client - The API client to use for the request
|
|
169
|
+
* @param params - Parameters including sandbox ID, path, and recursive flag
|
|
170
|
+
* @throws {SandboxResponseError} If the mkdir request fails
|
|
171
|
+
*/
|
|
172
|
+
export async function sandboxMkDir(client: APIClient, params: MkDirParams): Promise<void> {
|
|
173
|
+
const { sandboxId, path, recursive, orgId, signal } = params;
|
|
174
|
+
|
|
175
|
+
const body: z.infer<typeof MkDirRequestSchema> = {
|
|
176
|
+
path,
|
|
177
|
+
recursive: recursive ?? false,
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const queryParams = new URLSearchParams();
|
|
181
|
+
if (orgId) {
|
|
182
|
+
queryParams.set('orgId', orgId);
|
|
183
|
+
}
|
|
184
|
+
const queryString = queryParams.toString();
|
|
185
|
+
const url = `/fs/${API_VERSION}/mkdir/${sandboxId}${queryString ? `?${queryString}` : ''}`;
|
|
186
|
+
|
|
187
|
+
const resp = await client.post<z.infer<typeof MkDirResponseSchema>>(
|
|
188
|
+
url,
|
|
189
|
+
body,
|
|
190
|
+
MkDirResponseSchema,
|
|
191
|
+
MkDirRequestSchema,
|
|
192
|
+
signal
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
if (!resp.success) {
|
|
196
|
+
throw new SandboxResponseError({ message: resp.message, sandboxId });
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const RmDirRequestSchema = z
|
|
201
|
+
.object({
|
|
202
|
+
path: z.string().describe('Path to the directory to remove'),
|
|
203
|
+
recursive: z.boolean().optional().describe('Remove directory and all contents'),
|
|
204
|
+
})
|
|
205
|
+
.describe('Request body for removing a directory');
|
|
206
|
+
|
|
207
|
+
const RmDirResponseSchema = z.discriminatedUnion('success', [
|
|
208
|
+
z.object({
|
|
209
|
+
success: z.literal<false>(false),
|
|
210
|
+
message: z.string().describe('the error message'),
|
|
211
|
+
}),
|
|
212
|
+
z.object({
|
|
213
|
+
success: z.literal<true>(true),
|
|
214
|
+
}),
|
|
215
|
+
]);
|
|
216
|
+
|
|
217
|
+
export interface RmDirParams {
|
|
218
|
+
sandboxId: string;
|
|
219
|
+
path: string;
|
|
220
|
+
recursive?: boolean;
|
|
221
|
+
orgId?: string;
|
|
222
|
+
signal?: AbortSignal;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Removes a directory from a sandbox workspace.
|
|
227
|
+
*
|
|
228
|
+
* @param client - The API client to use for the request
|
|
229
|
+
* @param params - Parameters including sandbox ID, path, and recursive flag
|
|
230
|
+
* @throws {SandboxResponseError} If the rmdir request fails
|
|
231
|
+
*/
|
|
232
|
+
export async function sandboxRmDir(client: APIClient, params: RmDirParams): Promise<void> {
|
|
233
|
+
const { sandboxId, path, recursive, orgId, signal } = params;
|
|
234
|
+
|
|
235
|
+
const body: z.infer<typeof RmDirRequestSchema> = {
|
|
236
|
+
path,
|
|
237
|
+
recursive: recursive ?? false,
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
const queryParams = new URLSearchParams();
|
|
241
|
+
if (orgId) {
|
|
242
|
+
queryParams.set('orgId', orgId);
|
|
243
|
+
}
|
|
244
|
+
const queryString = queryParams.toString();
|
|
245
|
+
const url = `/fs/${API_VERSION}/rmdir/${sandboxId}${queryString ? `?${queryString}` : ''}`;
|
|
246
|
+
|
|
247
|
+
const resp = await client.post<z.infer<typeof RmDirResponseSchema>>(
|
|
248
|
+
url,
|
|
249
|
+
body,
|
|
250
|
+
RmDirResponseSchema,
|
|
251
|
+
RmDirRequestSchema,
|
|
252
|
+
signal
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
if (!resp.success) {
|
|
256
|
+
throw new SandboxResponseError({ message: resp.message, sandboxId });
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const RmFileRequestSchema = z
|
|
261
|
+
.object({
|
|
262
|
+
path: z.string().describe('Path to the file to remove'),
|
|
263
|
+
})
|
|
264
|
+
.describe('Request body for removing a file');
|
|
265
|
+
|
|
266
|
+
const RmFileResponseSchema = z.discriminatedUnion('success', [
|
|
267
|
+
z.object({
|
|
268
|
+
success: z.literal<false>(false),
|
|
269
|
+
message: z.string().describe('the error message'),
|
|
270
|
+
}),
|
|
271
|
+
z.object({
|
|
272
|
+
success: z.literal<true>(true),
|
|
273
|
+
}),
|
|
274
|
+
]);
|
|
275
|
+
|
|
276
|
+
export interface RmFileParams {
|
|
277
|
+
sandboxId: string;
|
|
278
|
+
path: string;
|
|
279
|
+
orgId?: string;
|
|
280
|
+
signal?: AbortSignal;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Removes a file from a sandbox workspace.
|
|
285
|
+
*
|
|
286
|
+
* @param client - The API client to use for the request
|
|
287
|
+
* @param params - Parameters including sandbox ID and path
|
|
288
|
+
* @throws {SandboxResponseError} If the rm request fails
|
|
289
|
+
*/
|
|
290
|
+
export async function sandboxRmFile(client: APIClient, params: RmFileParams): Promise<void> {
|
|
291
|
+
const { sandboxId, path, orgId, signal } = params;
|
|
292
|
+
|
|
293
|
+
const body: z.infer<typeof RmFileRequestSchema> = {
|
|
294
|
+
path,
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
const queryParams = new URLSearchParams();
|
|
298
|
+
if (orgId) {
|
|
299
|
+
queryParams.set('orgId', orgId);
|
|
300
|
+
}
|
|
301
|
+
const queryString = queryParams.toString();
|
|
302
|
+
const url = `/fs/${API_VERSION}/rm/${sandboxId}${queryString ? `?${queryString}` : ''}`;
|
|
303
|
+
|
|
304
|
+
const resp = await client.post<z.infer<typeof RmFileResponseSchema>>(
|
|
305
|
+
url,
|
|
306
|
+
body,
|
|
307
|
+
RmFileResponseSchema,
|
|
308
|
+
RmFileRequestSchema,
|
|
309
|
+
signal
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
if (!resp.success) {
|
|
313
|
+
throw new SandboxResponseError({ message: resp.message, sandboxId });
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const FileInfoSchema = z.object({
|
|
318
|
+
path: z.string().describe('File path relative to the listed directory'),
|
|
319
|
+
size: z.number().describe('File size in bytes'),
|
|
320
|
+
isDir: z.boolean().describe('Whether the entry is a directory'),
|
|
321
|
+
mode: z.string().describe('Unix permissions as octal string (e.g., "0644")'),
|
|
322
|
+
modTime: z.string().describe('Modification time in RFC3339 format'),
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
const ListFilesDataSchema = z.object({
|
|
326
|
+
files: z.array(FileInfoSchema).describe('Array of file information'),
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
const ListFilesResponseSchema = z.discriminatedUnion('success', [
|
|
330
|
+
z.object({
|
|
331
|
+
success: z.literal<false>(false),
|
|
332
|
+
message: z.string().describe('the error message'),
|
|
333
|
+
}),
|
|
334
|
+
z.object({
|
|
335
|
+
success: z.literal<true>(true),
|
|
336
|
+
data: ListFilesDataSchema,
|
|
337
|
+
}),
|
|
338
|
+
]);
|
|
339
|
+
|
|
340
|
+
export interface FileInfo {
|
|
341
|
+
path: string;
|
|
342
|
+
size: number;
|
|
343
|
+
isDir: boolean;
|
|
344
|
+
mode: string;
|
|
345
|
+
modTime: string;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
export interface ListFilesParams {
|
|
349
|
+
sandboxId: string;
|
|
350
|
+
path?: string;
|
|
351
|
+
orgId?: string;
|
|
352
|
+
signal?: AbortSignal;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
export interface ListFilesResult {
|
|
356
|
+
files: FileInfo[];
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Lists files in a sandbox workspace directory.
|
|
361
|
+
*
|
|
362
|
+
* @param client - The API client to use for the request
|
|
363
|
+
* @param params - Parameters including sandbox ID and optional path
|
|
364
|
+
* @returns The list of files and directories
|
|
365
|
+
* @throws {SandboxResponseError} If the list request fails
|
|
366
|
+
*/
|
|
367
|
+
export async function sandboxListFiles(
|
|
368
|
+
client: APIClient,
|
|
369
|
+
params: ListFilesParams
|
|
370
|
+
): Promise<ListFilesResult> {
|
|
371
|
+
const { sandboxId, path, orgId, signal } = params;
|
|
372
|
+
|
|
373
|
+
const queryParams = new URLSearchParams();
|
|
374
|
+
if (path) {
|
|
375
|
+
queryParams.set('path', path);
|
|
376
|
+
}
|
|
377
|
+
if (orgId) {
|
|
378
|
+
queryParams.set('orgId', orgId);
|
|
379
|
+
}
|
|
380
|
+
const queryString = queryParams.toString();
|
|
381
|
+
const url = `/fs/${API_VERSION}/list/${sandboxId}${queryString ? `?${queryString}` : ''}`;
|
|
382
|
+
|
|
383
|
+
const resp = await client.get<z.infer<typeof ListFilesResponseSchema>>(
|
|
384
|
+
url,
|
|
385
|
+
ListFilesResponseSchema,
|
|
386
|
+
signal
|
|
387
|
+
);
|
|
388
|
+
|
|
389
|
+
if (resp.success) {
|
|
390
|
+
return {
|
|
391
|
+
files: resp.data.files,
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
throw new SandboxResponseError({ message: resp.message, sandboxId });
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
export type ArchiveFormat = 'zip' | 'tar.gz';
|
|
399
|
+
|
|
400
|
+
export interface DownloadArchiveParams {
|
|
401
|
+
sandboxId: string;
|
|
402
|
+
path?: string;
|
|
403
|
+
format?: ArchiveFormat;
|
|
404
|
+
orgId?: string;
|
|
405
|
+
signal?: AbortSignal;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Downloads files from a sandbox as a compressed archive.
|
|
410
|
+
*
|
|
411
|
+
* @param client - The API client to use for the request
|
|
412
|
+
* @param params - Parameters including sandbox ID, path, and format
|
|
413
|
+
* @returns A ReadableStream of the archive contents
|
|
414
|
+
* @throws {SandboxResponseError} If the download request fails
|
|
415
|
+
*/
|
|
416
|
+
export async function sandboxDownloadArchive(
|
|
417
|
+
client: APIClient,
|
|
418
|
+
params: DownloadArchiveParams
|
|
419
|
+
): Promise<ReadableStream<Uint8Array>> {
|
|
420
|
+
const { sandboxId, path, format, orgId, signal } = params;
|
|
421
|
+
|
|
422
|
+
const queryParams = new URLSearchParams();
|
|
423
|
+
if (path) {
|
|
424
|
+
queryParams.set('path', path);
|
|
425
|
+
}
|
|
426
|
+
if (format) {
|
|
427
|
+
queryParams.set('format', format);
|
|
428
|
+
}
|
|
429
|
+
if (orgId) {
|
|
430
|
+
queryParams.set('orgId', orgId);
|
|
431
|
+
}
|
|
432
|
+
const queryString = queryParams.toString();
|
|
433
|
+
const url = `/fs/${API_VERSION}/download/${sandboxId}${queryString ? `?${queryString}` : ''}`;
|
|
434
|
+
|
|
435
|
+
const response = await client.rawGet(url, signal);
|
|
436
|
+
|
|
437
|
+
if (!response.ok) {
|
|
438
|
+
const text = await response.text().catch(() => 'Unknown error');
|
|
439
|
+
throw new SandboxResponseError({
|
|
440
|
+
message: `Failed to download archive: ${response.status} ${text}`,
|
|
441
|
+
sandboxId,
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if (!response.body) {
|
|
446
|
+
throw new SandboxResponseError({
|
|
447
|
+
message: 'No response body',
|
|
448
|
+
sandboxId,
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
return response.body;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
export interface UploadArchiveParams {
|
|
456
|
+
sandboxId: string;
|
|
457
|
+
archive: Uint8Array | ArrayBuffer | ReadableStream<Uint8Array>;
|
|
458
|
+
path?: string;
|
|
459
|
+
format?: ArchiveFormat | '';
|
|
460
|
+
orgId?: string;
|
|
461
|
+
signal?: AbortSignal;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
const UploadArchiveResponseSchema = z.discriminatedUnion('success', [
|
|
465
|
+
z.object({
|
|
466
|
+
success: z.literal<false>(false),
|
|
467
|
+
message: z.string().describe('the error message'),
|
|
468
|
+
}),
|
|
469
|
+
z.object({
|
|
470
|
+
success: z.literal<true>(true),
|
|
471
|
+
}),
|
|
472
|
+
]);
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* Uploads a compressed archive to a sandbox and extracts it.
|
|
476
|
+
*
|
|
477
|
+
* @param client - The API client to use for the request
|
|
478
|
+
* @param params - Parameters including sandbox ID, archive data, path, and optional format
|
|
479
|
+
* @throws {SandboxResponseError} If the upload request fails
|
|
480
|
+
*/
|
|
481
|
+
export async function sandboxUploadArchive(
|
|
482
|
+
client: APIClient,
|
|
483
|
+
params: UploadArchiveParams
|
|
484
|
+
): Promise<void> {
|
|
485
|
+
const { sandboxId, archive, path, format, orgId, signal } = params;
|
|
486
|
+
|
|
487
|
+
const queryParams = new URLSearchParams();
|
|
488
|
+
if (path) {
|
|
489
|
+
queryParams.set('path', path);
|
|
490
|
+
}
|
|
491
|
+
if (format) {
|
|
492
|
+
queryParams.set('format', format);
|
|
493
|
+
}
|
|
494
|
+
if (orgId) {
|
|
495
|
+
queryParams.set('orgId', orgId);
|
|
496
|
+
}
|
|
497
|
+
const queryString = queryParams.toString();
|
|
498
|
+
const url = `/fs/${API_VERSION}/upload/${sandboxId}${queryString ? `?${queryString}` : ''}`;
|
|
499
|
+
|
|
500
|
+
const response = await client.rawPost(url, archive, 'application/octet-stream', signal);
|
|
501
|
+
|
|
502
|
+
if (!response.ok) {
|
|
503
|
+
const text = await response.text().catch(() => 'Unknown error');
|
|
504
|
+
throw new SandboxResponseError({
|
|
505
|
+
message: `Failed to upload archive: ${response.status} ${text}`,
|
|
506
|
+
sandboxId,
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
const body = await response.json();
|
|
511
|
+
const result = UploadArchiveResponseSchema.parse(body);
|
|
512
|
+
|
|
513
|
+
if (!result.success) {
|
|
514
|
+
throw new SandboxResponseError({ message: result.message, sandboxId });
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
const SetEnvRequestSchema = z.object({
|
|
519
|
+
env: z
|
|
520
|
+
.record(z.string(), z.string().nullable())
|
|
521
|
+
.describe('Environment variables to set (null to delete)'),
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
const SetEnvDataSchema = z.object({
|
|
525
|
+
env: z.record(z.string(), z.string()).describe('Current environment variables after update'),
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
const SetEnvResponseSchema = z.discriminatedUnion('success', [
|
|
529
|
+
z.object({
|
|
530
|
+
success: z.literal<false>(false),
|
|
531
|
+
message: z.string().describe('the error message'),
|
|
532
|
+
}),
|
|
533
|
+
z.object({
|
|
534
|
+
success: z.literal<true>(true),
|
|
535
|
+
data: SetEnvDataSchema,
|
|
536
|
+
}),
|
|
537
|
+
]);
|
|
538
|
+
|
|
539
|
+
export interface SetEnvParams {
|
|
540
|
+
sandboxId: string;
|
|
541
|
+
env: Record<string, string | null>;
|
|
542
|
+
orgId?: string;
|
|
543
|
+
signal?: AbortSignal;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
export interface SetEnvResult {
|
|
547
|
+
env: Record<string, string>;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* Sets environment variables on a sandbox. Pass null to delete a variable.
|
|
552
|
+
*
|
|
553
|
+
* @param client - The API client to use for the request
|
|
554
|
+
* @param params - Parameters including sandbox ID and env key/value pairs
|
|
555
|
+
* @returns The current environment variables after the update
|
|
556
|
+
* @throws {SandboxResponseError} If the request fails
|
|
557
|
+
*/
|
|
558
|
+
export async function sandboxSetEnv(
|
|
559
|
+
client: APIClient,
|
|
560
|
+
params: SetEnvParams
|
|
561
|
+
): Promise<SetEnvResult> {
|
|
562
|
+
const { sandboxId, env, orgId, signal } = params;
|
|
563
|
+
|
|
564
|
+
const body: z.infer<typeof SetEnvRequestSchema> = { env };
|
|
565
|
+
|
|
566
|
+
const queryParams = new URLSearchParams();
|
|
567
|
+
if (orgId) {
|
|
568
|
+
queryParams.set('orgId', orgId);
|
|
569
|
+
}
|
|
570
|
+
const queryString = queryParams.toString();
|
|
571
|
+
const url = `/sandbox/env/${API_VERSION}/${sandboxId}${queryString ? `?${queryString}` : ''}`;
|
|
572
|
+
|
|
573
|
+
const resp = await client.patch<z.infer<typeof SetEnvResponseSchema>>(
|
|
574
|
+
url,
|
|
575
|
+
body,
|
|
576
|
+
SetEnvResponseSchema,
|
|
577
|
+
SetEnvRequestSchema,
|
|
578
|
+
signal
|
|
579
|
+
);
|
|
580
|
+
|
|
581
|
+
if (resp.success) {
|
|
582
|
+
return {
|
|
583
|
+
env: resp.data.env,
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
throw new SandboxResponseError({ message: resp.message, sandboxId });
|
|
588
|
+
}
|