@agentuity/cli 1.0.44 → 1.0.46
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/bin/cli.ts +189 -143
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +45 -2
- package/dist/cli.js.map +1 -1
- package/dist/cmd/cloud/sandbox/cp.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/cp.js +69 -13
- package/dist/cmd/cloud/sandbox/cp.js.map +1 -1
- package/dist/cmd/cloud/sandbox/events.d.ts +3 -0
- package/dist/cmd/cloud/sandbox/events.d.ts.map +1 -0
- package/dist/cmd/cloud/sandbox/events.js +92 -0
- package/dist/cmd/cloud/sandbox/events.js.map +1 -0
- package/dist/cmd/cloud/sandbox/exec.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/exec.js +22 -0
- package/dist/cmd/cloud/sandbox/exec.js.map +1 -1
- package/dist/cmd/cloud/sandbox/execution/get.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/execution/get.js +5 -0
- package/dist/cmd/cloud/sandbox/execution/get.js.map +1 -1
- package/dist/cmd/cloud/sandbox/execution/list.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/execution/list.js +12 -7
- package/dist/cmd/cloud/sandbox/execution/list.js.map +1 -1
- package/dist/cmd/cloud/sandbox/get.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/get.js +1 -0
- package/dist/cmd/cloud/sandbox/get.js.map +1 -1
- package/dist/cmd/cloud/sandbox/index.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/index.js +2 -0
- package/dist/cmd/cloud/sandbox/index.js.map +1 -1
- package/dist/cmd/cloud/sandbox/util.js +1 -1
- package/dist/cmd/cloud/sandbox/util.js.map +1 -1
- package/package.json +6 -6
- package/src/cli.ts +56 -2
- package/src/cmd/cloud/sandbox/cp.ts +89 -14
- package/src/cmd/cloud/sandbox/events.ts +108 -0
- package/src/cmd/cloud/sandbox/exec.ts +27 -0
- package/src/cmd/cloud/sandbox/execution/get.ts +5 -0
- package/src/cmd/cloud/sandbox/execution/list.ts +13 -14
- package/src/cmd/cloud/sandbox/get.ts +1 -0
- package/src/cmd/cloud/sandbox/index.ts +2 -0
- package/src/cmd/cloud/sandbox/util.ts +1 -1
|
@@ -45,32 +45,41 @@ const SandboxCpResponseSchema = z.object({
|
|
|
45
45
|
directoriesCreated: z
|
|
46
46
|
.array(z.string())
|
|
47
47
|
.optional()
|
|
48
|
-
.describe(
|
|
48
|
+
.describe(
|
|
49
|
+
'Parent directories that were auto-created on the destination (not present in --strict mode or when all directories already exist)'
|
|
50
|
+
),
|
|
49
51
|
});
|
|
50
52
|
|
|
51
53
|
export const cpSubcommand = createCommand({
|
|
52
54
|
name: 'cp',
|
|
53
55
|
aliases: ['copy'],
|
|
54
|
-
description:
|
|
56
|
+
description:
|
|
57
|
+
'Copy files or directories to or from a sandbox. Parent directories are automatically created if they do not exist (similar to mkdir -p).',
|
|
55
58
|
tags: ['slow', 'requires-auth'],
|
|
56
59
|
requires: { auth: true, apiClient: true },
|
|
57
60
|
examples: [
|
|
58
61
|
{
|
|
59
|
-
command: getCommand('cloud sandbox cp ./local-file.txt
|
|
62
|
+
command: getCommand('cloud sandbox cp ./local-file.txt sbx_abc123:/path/to/file.txt'),
|
|
60
63
|
description: 'Copy a local file to a sandbox',
|
|
61
64
|
},
|
|
62
65
|
{
|
|
63
|
-
command: getCommand('cloud sandbox cp
|
|
66
|
+
command: getCommand('cloud sandbox cp sbx_abc123:/path/to/file.txt ./local-file.txt'),
|
|
64
67
|
description: 'Copy a file from a sandbox to local',
|
|
65
68
|
},
|
|
66
69
|
{
|
|
67
|
-
command: getCommand('cloud sandbox cp --recursive ./local-dir
|
|
70
|
+
command: getCommand('cloud sandbox cp --recursive ./local-dir sbx_abc123:/path/to/dir'),
|
|
68
71
|
description: 'Copy a local directory to a sandbox recursively',
|
|
69
72
|
},
|
|
70
73
|
{
|
|
71
|
-
command: getCommand('cloud sandbox cp -r
|
|
74
|
+
command: getCommand('cloud sandbox cp -r sbx_abc123:/path/to/dir ./local-dir'),
|
|
72
75
|
description: 'Copy a directory from a sandbox to local recursively',
|
|
73
76
|
},
|
|
77
|
+
{
|
|
78
|
+
command: getCommand(
|
|
79
|
+
'cloud sandbox cp --strict ./local-file.txt sbx_abc123:/path/to/file.txt'
|
|
80
|
+
),
|
|
81
|
+
description: 'Copy a file, failing if the target directory does not exist',
|
|
82
|
+
},
|
|
74
83
|
],
|
|
75
84
|
schema: {
|
|
76
85
|
args: z.object({
|
|
@@ -82,6 +91,13 @@ export const cpSubcommand = createCommand({
|
|
|
82
91
|
options: z.object({
|
|
83
92
|
timeout: z.string().optional().describe('Operation timeout (e.g., "5m", "1h")'),
|
|
84
93
|
recursive: z.boolean().default(false).optional().describe('Copy directories recursively'),
|
|
94
|
+
strict: z
|
|
95
|
+
.boolean()
|
|
96
|
+
.default(false)
|
|
97
|
+
.optional()
|
|
98
|
+
.describe(
|
|
99
|
+
'Fail if the target parent directory does not exist instead of auto-creating it'
|
|
100
|
+
),
|
|
85
101
|
}),
|
|
86
102
|
aliases: {
|
|
87
103
|
recursive: ['r'],
|
|
@@ -103,7 +119,7 @@ export const cpSubcommand = createCommand({
|
|
|
103
119
|
|
|
104
120
|
if (!source.sandboxId && !destination.sandboxId) {
|
|
105
121
|
logger.fatal(
|
|
106
|
-
'At least one path must include a sandbox ID (e.g.,
|
|
122
|
+
'At least one path must include a sandbox ID (e.g., sbx_abc123:/path/to/file)'
|
|
107
123
|
);
|
|
108
124
|
}
|
|
109
125
|
|
|
@@ -115,6 +131,7 @@ export const cpSubcommand = createCommand({
|
|
|
115
131
|
|
|
116
132
|
const client = createSandboxClient(logger, auth, region);
|
|
117
133
|
const recursive = opts.recursive ?? false;
|
|
134
|
+
const strict = opts.strict ?? false;
|
|
118
135
|
|
|
119
136
|
if (source.sandboxId) {
|
|
120
137
|
return await downloadFromSandbox(
|
|
@@ -138,7 +155,8 @@ export const cpSubcommand = createCommand({
|
|
|
138
155
|
destination.path,
|
|
139
156
|
opts.timeout,
|
|
140
157
|
recursive,
|
|
141
|
-
options.json ?? false
|
|
158
|
+
options.json ?? false,
|
|
159
|
+
strict
|
|
142
160
|
);
|
|
143
161
|
}
|
|
144
162
|
},
|
|
@@ -193,7 +211,8 @@ async function uploadToSandbox(
|
|
|
193
211
|
remotePath: string,
|
|
194
212
|
timeout: string | undefined,
|
|
195
213
|
recursive: boolean,
|
|
196
|
-
jsonOutput: boolean
|
|
214
|
+
jsonOutput: boolean,
|
|
215
|
+
strict: boolean
|
|
197
216
|
): Promise<z.infer<typeof SandboxCpResponseSchema>> {
|
|
198
217
|
const resolvedPath = resolve(localPath);
|
|
199
218
|
|
|
@@ -218,7 +237,8 @@ async function uploadToSandbox(
|
|
|
218
237
|
resolvedPath,
|
|
219
238
|
remotePath,
|
|
220
239
|
timeout,
|
|
221
|
-
jsonOutput
|
|
240
|
+
jsonOutput,
|
|
241
|
+
strict
|
|
222
242
|
);
|
|
223
243
|
}
|
|
224
244
|
|
|
@@ -231,20 +251,22 @@ async function uploadToSandbox(
|
|
|
231
251
|
localPath,
|
|
232
252
|
remotePath,
|
|
233
253
|
timeout,
|
|
234
|
-
jsonOutput
|
|
254
|
+
jsonOutput,
|
|
255
|
+
strict
|
|
235
256
|
);
|
|
236
257
|
}
|
|
237
258
|
|
|
238
259
|
async function uploadSingleFile(
|
|
239
260
|
client: APIClient,
|
|
240
|
-
|
|
261
|
+
logger: Logger,
|
|
241
262
|
orgId: string,
|
|
242
263
|
sandboxId: string,
|
|
243
264
|
resolvedPath: string,
|
|
244
265
|
displayPath: string,
|
|
245
266
|
remotePath: string,
|
|
246
267
|
_timeout: string | undefined,
|
|
247
|
-
jsonOutput: boolean
|
|
268
|
+
jsonOutput: boolean,
|
|
269
|
+
strict: boolean
|
|
248
270
|
): Promise<z.infer<typeof SandboxCpResponseSchema>> {
|
|
249
271
|
const buffer = readFileSync(resolvedPath);
|
|
250
272
|
|
|
@@ -254,6 +276,32 @@ async function uploadSingleFile(
|
|
|
254
276
|
targetPath = baseDir ? baseDir + basename(resolvedPath) : basename(resolvedPath);
|
|
255
277
|
}
|
|
256
278
|
|
|
279
|
+
if (strict) {
|
|
280
|
+
const parentDir = dirname(targetPath);
|
|
281
|
+
const knownDirs = new Set(['/', '/home', '/home/agentuity']);
|
|
282
|
+
if (!knownDirs.has(parentDir)) {
|
|
283
|
+
const checkExecution = await sandboxExecute(client, {
|
|
284
|
+
sandboxId,
|
|
285
|
+
options: {
|
|
286
|
+
command: ['test', '-d', parentDir],
|
|
287
|
+
},
|
|
288
|
+
orgId,
|
|
289
|
+
});
|
|
290
|
+
await waitForExecution(client, orgId, checkExecution.executionId, logger);
|
|
291
|
+
const execInfo = await executionGet(client, {
|
|
292
|
+
executionId: checkExecution.executionId,
|
|
293
|
+
orgId,
|
|
294
|
+
});
|
|
295
|
+
if (execInfo.exitCode !== 0) {
|
|
296
|
+
logger.fatal(
|
|
297
|
+
`Target directory does not exist: ${parentDir}\n` +
|
|
298
|
+
`Use without --strict to auto-create parent directories, or create it first with:\n` +
|
|
299
|
+
` ${getCommand(`cloud sandbox mkdir ${sandboxId} ${parentDir} -p`)}`
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
257
305
|
const files: FileToWrite[] = [{ path: targetPath, content: buffer }];
|
|
258
306
|
|
|
259
307
|
await sandboxWriteFiles(client, { sandboxId, files, orgId });
|
|
@@ -280,7 +328,8 @@ async function uploadDirectory(
|
|
|
280
328
|
localDir: string,
|
|
281
329
|
remotePath: string,
|
|
282
330
|
_timeout: string | undefined,
|
|
283
|
-
jsonOutput: boolean
|
|
331
|
+
jsonOutput: boolean,
|
|
332
|
+
strict: boolean
|
|
284
333
|
): Promise<z.infer<typeof SandboxCpResponseSchema>> {
|
|
285
334
|
const allFiles = getAllFiles(localDir);
|
|
286
335
|
|
|
@@ -295,6 +344,32 @@ async function uploadDirectory(
|
|
|
295
344
|
? effectiveRemotePath.slice(0, -1)
|
|
296
345
|
: effectiveRemotePath;
|
|
297
346
|
|
|
347
|
+
if (strict) {
|
|
348
|
+
const parentDir = dirname(baseRemotePath);
|
|
349
|
+
const knownDirs = new Set(['/', '/home', '/home/agentuity']);
|
|
350
|
+
if (!knownDirs.has(parentDir)) {
|
|
351
|
+
const checkExecution = await sandboxExecute(client, {
|
|
352
|
+
sandboxId,
|
|
353
|
+
options: {
|
|
354
|
+
command: ['test', '-d', parentDir],
|
|
355
|
+
},
|
|
356
|
+
orgId,
|
|
357
|
+
});
|
|
358
|
+
await waitForExecution(client, orgId, checkExecution.executionId, logger);
|
|
359
|
+
const execInfo = await executionGet(client, {
|
|
360
|
+
executionId: checkExecution.executionId,
|
|
361
|
+
orgId,
|
|
362
|
+
});
|
|
363
|
+
if (execInfo.exitCode !== 0) {
|
|
364
|
+
logger.fatal(
|
|
365
|
+
`Target directory does not exist: ${parentDir}\n` +
|
|
366
|
+
`Use without --strict to auto-create parent directories, or create it first with:\n` +
|
|
367
|
+
` ${getCommand(`cloud sandbox mkdir ${sandboxId} ${parentDir} -p`)}`
|
|
368
|
+
);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
298
373
|
for (const filePath of allFiles) {
|
|
299
374
|
const relativePath = toForwardSlash(relative(localDir, filePath));
|
|
300
375
|
const targetPath = `${baseRemotePath}/${relativePath}`;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { sandboxEventList } from '@agentuity/server';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { getCommand } from '../../../command-prefix';
|
|
4
|
+
import * as tui from '../../../tui';
|
|
5
|
+
import { createCommand } from '../../../types';
|
|
6
|
+
import { createSandboxClient, getSandboxRegion } from './util';
|
|
7
|
+
|
|
8
|
+
const SandboxEventInfoSchema = z.object({
|
|
9
|
+
eventId: z.string().describe('Event ID'),
|
|
10
|
+
sandboxId: z.string().describe('Sandbox ID'),
|
|
11
|
+
type: z.string().describe('Event type'),
|
|
12
|
+
event: z.record(z.string(), z.unknown()).describe('Event data'),
|
|
13
|
+
createdAt: z.string().describe('Creation timestamp'),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const SandboxEventListResponseSchema = z.object({
|
|
17
|
+
events: z.array(SandboxEventInfoSchema).describe('List of events'),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export const eventsSubcommand = createCommand({
|
|
21
|
+
name: 'events',
|
|
22
|
+
aliases: ['event'],
|
|
23
|
+
description: 'List events for a sandbox',
|
|
24
|
+
tags: ['read-only', 'fast', 'requires-auth'],
|
|
25
|
+
requires: { auth: true, org: true },
|
|
26
|
+
idempotent: true,
|
|
27
|
+
examples: [
|
|
28
|
+
{
|
|
29
|
+
command: getCommand('cloud sandbox events sbx_abc123'),
|
|
30
|
+
description: 'List events for a sandbox (oldest first)',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
command: getCommand('cloud sandbox events sbx_abc123 --reverse'),
|
|
34
|
+
description: 'List events newest first',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
command: getCommand('cloud sandbox events sbx_abc123 --limit 10'),
|
|
38
|
+
description: 'List events with a limit',
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
schema: {
|
|
42
|
+
args: z.object({
|
|
43
|
+
sandboxId: z.string().describe('Sandbox ID'),
|
|
44
|
+
}),
|
|
45
|
+
options: z.object({
|
|
46
|
+
limit: z.number().optional().describe('Maximum number of results (default: 50, max: 100)'),
|
|
47
|
+
reverse: z.boolean().optional().describe('Reverse sort order (newest first)'),
|
|
48
|
+
orgId: z.string().optional().describe('filter by organization id'),
|
|
49
|
+
}),
|
|
50
|
+
response: SandboxEventListResponseSchema,
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
async handler(ctx) {
|
|
54
|
+
const { args, opts, options, auth, logger, orgId: ctxOrgId, config } = ctx;
|
|
55
|
+
const effectiveOrgId = opts?.orgId || ctxOrgId;
|
|
56
|
+
const region = await getSandboxRegion(
|
|
57
|
+
logger,
|
|
58
|
+
auth,
|
|
59
|
+
config?.name,
|
|
60
|
+
args.sandboxId,
|
|
61
|
+
effectiveOrgId,
|
|
62
|
+
config
|
|
63
|
+
);
|
|
64
|
+
const client = createSandboxClient(logger, auth, region);
|
|
65
|
+
|
|
66
|
+
const result = await sandboxEventList(client, {
|
|
67
|
+
sandboxId: args.sandboxId,
|
|
68
|
+
orgId: effectiveOrgId,
|
|
69
|
+
limit: opts.limit,
|
|
70
|
+
direction: opts.reverse ? 'desc' : undefined,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
if (!options.json) {
|
|
74
|
+
if (result.events.length === 0) {
|
|
75
|
+
tui.info('No events found');
|
|
76
|
+
} else {
|
|
77
|
+
const tableData = result.events.map((evt) => {
|
|
78
|
+
return {
|
|
79
|
+
ID: evt.eventId,
|
|
80
|
+
Type: evt.type,
|
|
81
|
+
Created: evt.createdAt,
|
|
82
|
+
};
|
|
83
|
+
});
|
|
84
|
+
tui.table(tableData, [
|
|
85
|
+
{ name: 'ID', alignment: 'left' },
|
|
86
|
+
{ name: 'Type', alignment: 'left' },
|
|
87
|
+
{ name: 'Created', alignment: 'left' },
|
|
88
|
+
]);
|
|
89
|
+
|
|
90
|
+
tui.info(
|
|
91
|
+
`Total: ${result.events.length} ${tui.plural(result.events.length, 'event', 'events')}`
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
events: result.events.map((e) => ({
|
|
98
|
+
eventId: e.eventId,
|
|
99
|
+
sandboxId: e.sandboxId,
|
|
100
|
+
type: e.type,
|
|
101
|
+
event: e.event,
|
|
102
|
+
createdAt: e.createdAt,
|
|
103
|
+
})),
|
|
104
|
+
};
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
export default eventsSubcommand;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { Writable } from 'node:stream';
|
|
3
|
+
import { ErrorCode } from '../../../errors';
|
|
3
4
|
import { createCommand } from '../../../types';
|
|
4
5
|
import * as tui from '../../../tui';
|
|
5
6
|
import { createSandboxClient } from './util';
|
|
@@ -24,6 +25,14 @@ const SandboxExecResponseSchema = z.object({
|
|
|
24
25
|
.optional()
|
|
25
26
|
.describe('Standard error output (only when separate streams are available)'),
|
|
26
27
|
output: z.string().optional().describe('Combined stdout/stderr output'),
|
|
28
|
+
outputTruncated: z
|
|
29
|
+
.boolean()
|
|
30
|
+
.optional()
|
|
31
|
+
.describe('Whether the captured output was truncated due to size limits'),
|
|
32
|
+
autoResumed: z
|
|
33
|
+
.boolean()
|
|
34
|
+
.optional()
|
|
35
|
+
.describe('True if the sandbox was automatically resumed from a suspended state'),
|
|
27
36
|
});
|
|
28
37
|
|
|
29
38
|
export const execSubcommand = createCommand({
|
|
@@ -62,6 +71,18 @@ export const execSubcommand = createCommand({
|
|
|
62
71
|
async handler(ctx) {
|
|
63
72
|
const { args, opts, options, auth, logger, apiClient } = ctx;
|
|
64
73
|
|
|
74
|
+
// Validate timeout format if provided (fail fast before any network calls)
|
|
75
|
+
if (opts.timeout) {
|
|
76
|
+
// Go's time.ParseDuration accepts "0" or one-or-more number+unit tokens.
|
|
77
|
+
// Valid units: ns, us, µs (U+00B5), μs (U+03BC), ms, s, m, h
|
|
78
|
+
if (!/^(?:0|(\d+(\.\d+)?(ns|us|[µμ]s|ms|s|m|h))+)$/.test(opts.timeout)) {
|
|
79
|
+
tui.fatal(
|
|
80
|
+
`Invalid timeout format '${opts.timeout}': expected duration like '5s', '1m', '1h', '300ms'`,
|
|
81
|
+
ErrorCode.INVALID_ARGUMENT
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
65
86
|
// Resolve sandbox to get region and orgId using CLI API
|
|
66
87
|
const sandboxInfo = await sandboxResolve(apiClient, args.sandboxId);
|
|
67
88
|
const { region, orgId } = sandboxInfo;
|
|
@@ -87,6 +108,10 @@ export const execSubcommand = createCommand({
|
|
|
87
108
|
orgId,
|
|
88
109
|
});
|
|
89
110
|
|
|
111
|
+
if (execution.autoResumed && !options.json) {
|
|
112
|
+
tui.warning('Sandbox was automatically resumed from suspended state');
|
|
113
|
+
}
|
|
114
|
+
|
|
90
115
|
const stdoutStreamUrl = execution.stdoutStreamUrl;
|
|
91
116
|
const stderrStreamUrl = execution.stderrStreamUrl;
|
|
92
117
|
const streamAbortController = new AbortController();
|
|
@@ -213,6 +238,8 @@ export const execSubcommand = createCommand({
|
|
|
213
238
|
stdout: options.json ? stdoutOutput : undefined,
|
|
214
239
|
stderr: options.json ? stderrOutput : undefined,
|
|
215
240
|
output: options.json ? output : undefined,
|
|
241
|
+
outputTruncated: finalExecution.outputTruncated ?? undefined,
|
|
242
|
+
autoResumed: execution.autoResumed ?? undefined,
|
|
216
243
|
};
|
|
217
244
|
} finally {
|
|
218
245
|
process.off('SIGINT', handleSignal);
|
|
@@ -17,6 +17,10 @@ const ExecutionGetResponseSchema = z.object({
|
|
|
17
17
|
error: z.string().optional().describe('Error message if failed'),
|
|
18
18
|
stdoutStreamUrl: z.string().optional().describe('URL to stream stdout'),
|
|
19
19
|
stderrStreamUrl: z.string().optional().describe('URL to stream stderr'),
|
|
20
|
+
outputTruncated: z
|
|
21
|
+
.boolean()
|
|
22
|
+
.optional()
|
|
23
|
+
.describe('Whether the captured output was truncated due to size limits'),
|
|
20
24
|
});
|
|
21
25
|
|
|
22
26
|
export const getSubcommand = createCommand({
|
|
@@ -108,6 +112,7 @@ export const getSubcommand = createCommand({
|
|
|
108
112
|
error: result.error,
|
|
109
113
|
stdoutStreamUrl: result.stdoutStreamUrl,
|
|
110
114
|
stderrStreamUrl: result.stderrStreamUrl,
|
|
115
|
+
outputTruncated: result.outputTruncated,
|
|
111
116
|
};
|
|
112
117
|
},
|
|
113
118
|
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { executionList } from '@agentuity/server';
|
|
1
|
+
import { executionList, sandboxResolve } from '@agentuity/server';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { getCommand } from '../../../../command-prefix';
|
|
4
4
|
import * as tui from '../../../../tui';
|
|
5
5
|
import { createCommand } from '../../../../types';
|
|
6
|
-
import { createSandboxClient
|
|
6
|
+
import { createSandboxClient } from '../util';
|
|
7
7
|
|
|
8
8
|
const ExecutionInfoSchema = z.object({
|
|
9
9
|
executionId: z.string().describe('Execution ID'),
|
|
@@ -25,7 +25,7 @@ export const listSubcommand = createCommand({
|
|
|
25
25
|
aliases: ['ls'],
|
|
26
26
|
description: 'List executions for a sandbox',
|
|
27
27
|
tags: ['read-only', 'fast', 'requires-auth'],
|
|
28
|
-
requires: { auth: true,
|
|
28
|
+
requires: { auth: true, apiClient: true },
|
|
29
29
|
idempotent: true,
|
|
30
30
|
examples: [
|
|
31
31
|
{
|
|
@@ -43,22 +43,21 @@ export const listSubcommand = createCommand({
|
|
|
43
43
|
}),
|
|
44
44
|
options: z.object({
|
|
45
45
|
limit: z.number().optional().describe('Maximum number of results (default: 50, max: 100)'),
|
|
46
|
-
orgId: z
|
|
46
|
+
orgId: z
|
|
47
|
+
.string()
|
|
48
|
+
.optional()
|
|
49
|
+
.describe('Override organization ID (default: resolved from sandbox)'),
|
|
47
50
|
}),
|
|
48
51
|
response: ExecutionListResponseSchema,
|
|
49
52
|
},
|
|
50
53
|
|
|
51
54
|
async handler(ctx) {
|
|
52
|
-
const { args, opts, options, auth, logger,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
args.sandboxId,
|
|
59
|
-
effectiveOrgId,
|
|
60
|
-
config
|
|
61
|
-
);
|
|
55
|
+
const { args, opts, options, auth, logger, apiClient } = ctx;
|
|
56
|
+
|
|
57
|
+
// Resolve sandbox to get region and orgId (like exec.ts does)
|
|
58
|
+
const sandboxInfo = await sandboxResolve(apiClient, args.sandboxId);
|
|
59
|
+
const { region, orgId: resolvedOrgId } = sandboxInfo;
|
|
60
|
+
const effectiveOrgId = opts?.orgId || resolvedOrgId;
|
|
62
61
|
const client = createSandboxClient(logger, auth, region);
|
|
63
62
|
|
|
64
63
|
const result = await executionList(client, {
|
|
@@ -20,6 +20,7 @@ import { pauseSubcommand } from './pause';
|
|
|
20
20
|
import { resumeSubcommand } from './resume';
|
|
21
21
|
import { checkpointCommand } from './checkpoint';
|
|
22
22
|
import { statsSubcommand } from './stats';
|
|
23
|
+
import { eventsSubcommand } from './events';
|
|
23
24
|
import { getCommand } from '../../../command-prefix';
|
|
24
25
|
|
|
25
26
|
export const command = createCommand({
|
|
@@ -63,6 +64,7 @@ export const command = createCommand({
|
|
|
63
64
|
resumeSubcommand,
|
|
64
65
|
checkpointCommand,
|
|
65
66
|
statsSubcommand,
|
|
67
|
+
eventsSubcommand,
|
|
66
68
|
],
|
|
67
69
|
requires: { auth: true, org: true },
|
|
68
70
|
});
|
|
@@ -41,7 +41,7 @@ export async function getSandboxRegion(
|
|
|
41
41
|
config
|
|
42
42
|
);
|
|
43
43
|
|
|
44
|
-
const sandbox = await sandboxGet(globalClient, { sandboxId, orgId });
|
|
44
|
+
const sandbox = await sandboxGet(globalClient, { sandboxId, orgId, includeDeleted: true });
|
|
45
45
|
if (!sandbox.region) {
|
|
46
46
|
tui.fatal(`Sandbox '${sandboxId}' has no region information`, ErrorCode.RESOURCE_NOT_FOUND);
|
|
47
47
|
}
|