@castari/cli 0.3.0 → 0.3.2

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.
@@ -0,0 +1,369 @@
1
+ import { Command } from 'commander';
2
+ import ora from 'ora';
3
+ import Table from 'cli-table3';
4
+ import chalk from 'chalk';
5
+ import { createWriteStream } from 'node:fs';
6
+ import { stat, readFile } from 'node:fs/promises';
7
+ import { basename } from 'node:path';
8
+ import { createHash } from 'node:crypto';
9
+ import { CastariClient } from '@castari/sdk';
10
+ import { info, hint, blank, keyValue, formatNumber } from '../utils/output.js';
11
+ import { handleError } from '../utils/errors.js';
12
+ // Threshold for using presigned upload (10MB)
13
+ const PRESIGNED_UPLOAD_THRESHOLD = 10 * 1024 * 1024;
14
+ /**
15
+ * Format file size in human-readable format
16
+ */
17
+ function formatSize(bytes) {
18
+ if (bytes === 0)
19
+ return '0 B';
20
+ const units = ['B', 'KB', 'MB', 'GB', 'TB'];
21
+ const i = Math.floor(Math.log(bytes) / Math.log(1024));
22
+ return `${(bytes / Math.pow(1024, i)).toFixed(i === 0 ? 0 : 1)} ${units[i]}`;
23
+ }
24
+ /**
25
+ * Format date for file listing
26
+ */
27
+ function formatFileDate(dateStr) {
28
+ const date = new Date(dateStr);
29
+ return date.toLocaleDateString('en-US', {
30
+ year: 'numeric',
31
+ month: 'short',
32
+ day: 'numeric',
33
+ hour: '2-digit',
34
+ minute: '2-digit',
35
+ });
36
+ }
37
+ /**
38
+ * Format scope with color
39
+ */
40
+ function formatScope(scope) {
41
+ switch (scope) {
42
+ case 'user':
43
+ return chalk.blue(scope);
44
+ case 'agent':
45
+ return chalk.green(scope);
46
+ case 'session':
47
+ return chalk.yellow(scope);
48
+ default:
49
+ return scope;
50
+ }
51
+ }
52
+ /**
53
+ * Format upload status with color
54
+ */
55
+ function formatUploadStatus(status) {
56
+ switch (status) {
57
+ case 'confirmed':
58
+ return chalk.green(status);
59
+ case 'pending':
60
+ return chalk.yellow(status);
61
+ default:
62
+ return status;
63
+ }
64
+ }
65
+ /**
66
+ * Calculate SHA256 hash of a buffer
67
+ */
68
+ function sha256(buffer) {
69
+ return createHash('sha256').update(buffer).digest('hex');
70
+ }
71
+ /**
72
+ * cast files list
73
+ */
74
+ const listCommand = new Command('list')
75
+ .description('List files in managed storage')
76
+ .option('--limit <n>', 'Maximum number of files to return', '50')
77
+ .option('--offset <n>', 'Number of files to skip', '0')
78
+ .option('--scope <scope>', 'Filter by scope (user, agent, session)')
79
+ .option('--tags <tags>', 'Filter by tags (comma-separated)')
80
+ .option('--search <query>', 'Search in filename and description')
81
+ .action(async (options) => {
82
+ const spinner = ora('Listing files...').start();
83
+ try {
84
+ const client = new CastariClient();
85
+ await client.ensureAuthenticated();
86
+ const result = await client.files.list({
87
+ limit: parseInt(options.limit, 10),
88
+ offset: parseInt(options.offset, 10),
89
+ scope: options.scope,
90
+ tags: options.tags,
91
+ search: options.search,
92
+ });
93
+ spinner.stop();
94
+ if (result.files.length === 0) {
95
+ info('No files found');
96
+ hint("Upload a file with: cast files upload <path>");
97
+ return;
98
+ }
99
+ const table = new Table({
100
+ head: [
101
+ chalk.white('File ID'),
102
+ chalk.white('Filename'),
103
+ chalk.white('Size'),
104
+ chalk.white('Scope'),
105
+ chalk.white('Created'),
106
+ ],
107
+ style: {
108
+ head: [],
109
+ border: [],
110
+ },
111
+ colWidths: [24, 30, 12, 10, 20],
112
+ });
113
+ for (const file of result.files) {
114
+ table.push([
115
+ file.file_id,
116
+ file.filename.length > 28
117
+ ? file.filename.substring(0, 25) + '...'
118
+ : file.filename,
119
+ formatSize(file.size_bytes),
120
+ formatScope(file.scope),
121
+ formatFileDate(file.created_at),
122
+ ]);
123
+ }
124
+ console.log(table.toString());
125
+ blank();
126
+ info(`Showing ${result.files.length} of ${formatNumber(result.meta.total)} file${result.meta.total === 1 ? '' : 's'}`);
127
+ if (result.meta.has_more) {
128
+ hint(`Use --offset ${result.meta.offset + result.meta.limit} to see more`);
129
+ }
130
+ }
131
+ catch (err) {
132
+ spinner.fail('Failed to list files');
133
+ handleError(err);
134
+ }
135
+ });
136
+ /**
137
+ * cast files upload <path>
138
+ */
139
+ const uploadCommand = new Command('upload')
140
+ .description('Upload a file to managed storage')
141
+ .argument('<path>', 'Local file path')
142
+ .option('--description <desc>', 'File description')
143
+ .option('--tags <tags>', 'Comma-separated tags')
144
+ .action(async (localPath, options) => {
145
+ try {
146
+ const client = new CastariClient();
147
+ await client.ensureAuthenticated();
148
+ // Check if file exists and get size
149
+ let fileStats;
150
+ try {
151
+ fileStats = await stat(localPath);
152
+ }
153
+ catch {
154
+ handleError(new Error(`File not found: ${localPath}`));
155
+ }
156
+ if (!fileStats.isFile()) {
157
+ handleError(new Error(`Not a file: ${localPath}`));
158
+ }
159
+ const filename = basename(localPath);
160
+ const fileSize = fileStats.size;
161
+ const tags = options.tags?.split(',').map((t) => t.trim()) || [];
162
+ const spinner = ora(`Uploading ${filename} (${formatSize(fileSize)})...`).start();
163
+ let result;
164
+ if (fileSize > PRESIGNED_UPLOAD_THRESHOLD) {
165
+ // Use presigned upload for large files
166
+ spinner.text = `Getting upload URL for ${filename}...`;
167
+ const presigned = await client.files.getUploadUrl(filename, fileSize, {
168
+ description: options.description,
169
+ tags,
170
+ });
171
+ spinner.text = `Uploading ${filename} (${formatSize(fileSize)})...`;
172
+ // Read file and calculate hash
173
+ const fileBuffer = await readFile(localPath);
174
+ const hash = sha256(fileBuffer);
175
+ // Upload to presigned URL
176
+ const uploadResponse = await fetch(presigned.upload_url, {
177
+ method: presigned.upload_method,
178
+ body: fileBuffer,
179
+ headers: presigned.upload_headers,
180
+ });
181
+ if (!uploadResponse.ok) {
182
+ throw new Error(`Upload failed: ${uploadResponse.statusText}`);
183
+ }
184
+ // Confirm upload
185
+ spinner.text = 'Confirming upload...';
186
+ const confirmed = await client.files.confirmUpload(presigned.file_id, hash);
187
+ result = {
188
+ file_id: confirmed.file_id,
189
+ filename: confirmed.filename,
190
+ size_bytes: confirmed.size_bytes,
191
+ };
192
+ }
193
+ else {
194
+ // Use direct multipart upload for small files
195
+ const fileBuffer = await readFile(localPath);
196
+ const blob = new Blob([fileBuffer]);
197
+ const uploadResult = await client.files.upload(blob, filename, {
198
+ description: options.description,
199
+ tags,
200
+ });
201
+ result = {
202
+ file_id: uploadResult.file_id,
203
+ filename: uploadResult.filename,
204
+ size_bytes: uploadResult.size_bytes,
205
+ };
206
+ }
207
+ spinner.succeed(`Uploaded ${result.filename}`);
208
+ blank();
209
+ keyValue('File ID', result.file_id);
210
+ keyValue('Size', formatSize(result.size_bytes));
211
+ blank();
212
+ hint(`Attach to agent: cast agents files add <agent-slug> ${result.file_id}`);
213
+ }
214
+ catch (err) {
215
+ handleError(err);
216
+ }
217
+ });
218
+ /**
219
+ * cast files get <file_id>
220
+ */
221
+ const getCommand = new Command('get')
222
+ .description('Get file details')
223
+ .argument('<file_id>', 'File ID')
224
+ .action(async (fileId) => {
225
+ const spinner = ora('Fetching file...').start();
226
+ try {
227
+ const client = new CastariClient();
228
+ await client.ensureAuthenticated();
229
+ const file = await client.files.get(fileId);
230
+ spinner.stop();
231
+ blank();
232
+ keyValue('File ID', file.file_id);
233
+ keyValue('Filename', file.filename);
234
+ keyValue('Size', formatSize(file.size_bytes));
235
+ keyValue('Content Type', file.content_type ?? 'unknown');
236
+ keyValue('Scope', formatScope(file.scope));
237
+ if (file.scope_id) {
238
+ keyValue('Scope ID', file.scope_id);
239
+ }
240
+ keyValue('Status', formatUploadStatus(file.upload_status));
241
+ if (file.description) {
242
+ keyValue('Description', file.description);
243
+ }
244
+ if (file.tags.length > 0) {
245
+ keyValue('Tags', file.tags.join(', '));
246
+ }
247
+ keyValue('SHA256', file.sha256_hash);
248
+ keyValue('Created', formatFileDate(file.created_at));
249
+ keyValue('Updated', formatFileDate(file.updated_at));
250
+ blank();
251
+ }
252
+ catch (err) {
253
+ spinner.fail('Failed to get file');
254
+ handleError(err);
255
+ }
256
+ });
257
+ /**
258
+ * cast files delete <file_id>
259
+ */
260
+ const deleteCommand = new Command('delete')
261
+ .description('Delete a file')
262
+ .argument('<file_id>', 'File ID')
263
+ .option('-f, --force', 'Skip confirmation')
264
+ .action(async (fileId, options) => {
265
+ try {
266
+ const client = new CastariClient();
267
+ await client.ensureAuthenticated();
268
+ // Confirm deletion unless --force is used
269
+ if (!options.force) {
270
+ const readline = await import('node:readline');
271
+ const rl = readline.createInterface({
272
+ input: process.stdin,
273
+ output: process.stdout,
274
+ });
275
+ const answer = await new Promise((resolve) => {
276
+ rl.question(chalk.yellow(`Are you sure you want to delete file '${fileId}'? [y/N] `), resolve);
277
+ });
278
+ rl.close();
279
+ if (answer.toLowerCase() !== 'y' && answer.toLowerCase() !== 'yes') {
280
+ info('Deletion cancelled');
281
+ return;
282
+ }
283
+ }
284
+ const spinner = ora('Deleting file...').start();
285
+ await client.files.delete(fileId);
286
+ spinner.succeed(`File '${fileId}' deleted`);
287
+ }
288
+ catch (err) {
289
+ handleError(err);
290
+ }
291
+ });
292
+ /**
293
+ * cast files download <file_id>
294
+ */
295
+ const downloadCommand = new Command('download')
296
+ .description('Download a file')
297
+ .argument('<file_id>', 'File ID')
298
+ .option('--output <path>', 'Output file path (default: original filename)')
299
+ .action(async (fileId, options) => {
300
+ try {
301
+ const client = new CastariClient();
302
+ await client.ensureAuthenticated();
303
+ // First get file metadata to know the filename
304
+ const spinner = ora('Fetching file info...').start();
305
+ const file = await client.files.get(fileId);
306
+ const outputPath = options.output || file.filename;
307
+ spinner.text = `Downloading ${file.filename}...`;
308
+ // Download file content via SDK (uses configured base URL and auth)
309
+ const response = await client.files.download(fileId);
310
+ // Write to file
311
+ const arrayBuffer = await response.arrayBuffer();
312
+ const buffer = Buffer.from(arrayBuffer);
313
+ await new Promise((resolve, reject) => {
314
+ const writeStream = createWriteStream(outputPath);
315
+ writeStream.write(buffer);
316
+ writeStream.end();
317
+ writeStream.on('finish', resolve);
318
+ writeStream.on('error', reject);
319
+ });
320
+ spinner.succeed(`Downloaded to ${outputPath}`);
321
+ info(`Size: ${formatSize(buffer.length)}`);
322
+ }
323
+ catch (err) {
324
+ handleError(err);
325
+ }
326
+ });
327
+ /**
328
+ * cast files usage
329
+ */
330
+ const usageCommand = new Command('usage')
331
+ .description('Show storage usage')
332
+ .action(async () => {
333
+ const spinner = ora('Fetching storage usage...').start();
334
+ try {
335
+ const client = new CastariClient();
336
+ await client.ensureAuthenticated();
337
+ const usage = await client.files.getUsage();
338
+ spinner.stop();
339
+ blank();
340
+ keyValue('Total Files', formatNumber(usage.total_files));
341
+ keyValue('Total Size', formatSize(usage.total_bytes));
342
+ keyValue('Quota Used', `${usage.usage_percent.toFixed(1)}%`);
343
+ keyValue('Quota Limit', `${usage.limit_mb} MB`);
344
+ blank();
345
+ // Show progress bar
346
+ const barWidth = 40;
347
+ const filled = Math.round((usage.usage_percent / 100) * barWidth);
348
+ const empty = barWidth - filled;
349
+ const bar = chalk.green('█'.repeat(filled)) + chalk.gray('░'.repeat(empty));
350
+ console.log(` ${bar} ${usage.usage_percent.toFixed(1)}%`);
351
+ blank();
352
+ }
353
+ catch (err) {
354
+ spinner.fail('Failed to get storage usage');
355
+ handleError(err);
356
+ }
357
+ });
358
+ /**
359
+ * cast files
360
+ */
361
+ export const filesCommand = new Command('files')
362
+ .description('Manage files in Castari storage')
363
+ .addCommand(listCommand)
364
+ .addCommand(uploadCommand)
365
+ .addCommand(getCommand)
366
+ .addCommand(deleteCommand)
367
+ .addCommand(downloadCommand)
368
+ .addCommand(usageCommand);
369
+ //# sourceMappingURL=files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/commands/files.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * cast mounts
4
+ */
5
+ export declare const mountsCommand: Command;
6
+ //# sourceMappingURL=mounts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mounts.d.ts","sourceRoot":"","sources":["../../src/commands/mounts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsSpC;;GAEG;AACH,eAAO,MAAM,aAAa,SAKE,CAAC"}
@@ -0,0 +1,252 @@
1
+ import { Command } from 'commander';
2
+ import ora from 'ora';
3
+ import Table from 'cli-table3';
4
+ import chalk from 'chalk';
5
+ import prompts from 'prompts';
6
+ import { CastariClient } from '@castari/sdk';
7
+ import { info, hint, blank, keyValue } from '../utils/output.js';
8
+ import { handleError } from '../utils/errors.js';
9
+ /**
10
+ * Format enabled status with color
11
+ */
12
+ function formatEnabled(enabled) {
13
+ return enabled ? chalk.green('Enabled') : chalk.gray('Disabled');
14
+ }
15
+ /**
16
+ * Format permission rules
17
+ */
18
+ function formatPermissions(rules) {
19
+ if (rules.length === 0) {
20
+ return chalk.gray('rw (default)');
21
+ }
22
+ return rules.map((r) => `${r.path}:${r.mode}`).join(', ');
23
+ }
24
+ /**
25
+ * cast mounts list <agent-slug>
26
+ */
27
+ const listCommand = new Command('list')
28
+ .description('List mounts for an agent')
29
+ .argument('<agent-slug>', 'Agent slug')
30
+ .action(async (agentSlug) => {
31
+ const spinner = ora('Fetching mounts...').start();
32
+ try {
33
+ const client = new CastariClient();
34
+ await client.ensureAuthenticated();
35
+ const mounts = await client.mounts.getMounts(agentSlug);
36
+ spinner.stop();
37
+ if (mounts.length === 0) {
38
+ info(`No mounts configured for agent '${agentSlug}'`);
39
+ hint(`Add one with: cast mounts add ${agentSlug}`);
40
+ return;
41
+ }
42
+ const table = new Table({
43
+ head: [
44
+ chalk.white('ID'),
45
+ chalk.white('Bucket'),
46
+ chalk.white('Mount Path'),
47
+ chalk.white('Prefix'),
48
+ chalk.white('Status'),
49
+ ],
50
+ style: {
51
+ head: [],
52
+ border: [],
53
+ },
54
+ });
55
+ for (const mount of mounts) {
56
+ table.push([
57
+ mount.id.substring(0, 8),
58
+ mount.bucket.slug,
59
+ mount.mount_path,
60
+ mount.source_prefix || chalk.gray('-'),
61
+ formatEnabled(mount.enabled),
62
+ ]);
63
+ }
64
+ console.log(table.toString());
65
+ }
66
+ catch (err) {
67
+ spinner.fail('Failed to list mounts');
68
+ handleError(err);
69
+ }
70
+ });
71
+ /**
72
+ * cast mounts add <agent-slug>
73
+ */
74
+ const addCommand = new Command('add')
75
+ .description('Add a mount to an agent')
76
+ .argument('<agent-slug>', 'Agent slug')
77
+ .option('--bucket <bucket-slug>', 'Bucket to mount')
78
+ .option('--path <mount-path>', 'Mount path (e.g., /data)')
79
+ .option('--prefix <source-prefix>', 'Source prefix in bucket')
80
+ .option('--read-only', 'Make the mount read-only')
81
+ .action(async (agentSlug, options) => {
82
+ try {
83
+ const client = new CastariClient();
84
+ await client.ensureAuthenticated();
85
+ let bucketSlug = options.bucket;
86
+ let mountPath = options.path;
87
+ let sourcePrefix = options.prefix;
88
+ // Interactive mode if bucket or path not provided
89
+ if (!bucketSlug || !mountPath) {
90
+ // Fetch available buckets for selection
91
+ const buckets = await client.storage.getBuckets();
92
+ if (buckets.length === 0) {
93
+ info('No buckets available');
94
+ hint("Create one with: cast buckets create <name>");
95
+ return;
96
+ }
97
+ const responses = await prompts([
98
+ {
99
+ type: bucketSlug ? null : 'select',
100
+ name: 'bucket',
101
+ message: 'Select bucket to mount',
102
+ choices: buckets.map((b) => ({
103
+ title: `${b.name} (${b.slug})`,
104
+ value: b.slug,
105
+ })),
106
+ },
107
+ {
108
+ type: mountPath ? null : 'text',
109
+ name: 'path',
110
+ message: 'Mount path (e.g., /data)',
111
+ initial: '/data',
112
+ validate: (value) => value.startsWith('/') ? true : 'Mount path must start with /',
113
+ },
114
+ {
115
+ type: sourcePrefix !== undefined ? null : 'text',
116
+ name: 'prefix',
117
+ message: 'Source prefix in bucket (optional)',
118
+ initial: '',
119
+ },
120
+ ]);
121
+ if ((!responses.bucket && !bucketSlug) || (!responses.path && !mountPath)) {
122
+ info('Mount creation cancelled');
123
+ return;
124
+ }
125
+ bucketSlug = bucketSlug || responses.bucket;
126
+ mountPath = mountPath || responses.path;
127
+ sourcePrefix = sourcePrefix !== undefined ? sourcePrefix : responses.prefix;
128
+ }
129
+ const spinner = ora('Adding mount...').start();
130
+ const mount = await client.mounts.addMount(agentSlug, {
131
+ bucketSlug: bucketSlug,
132
+ mountPath: mountPath,
133
+ sourcePrefix: sourcePrefix || undefined,
134
+ permissionRules: options.readOnly ? [{ path: '/', mode: 'ro' }] : undefined,
135
+ });
136
+ spinner.succeed(`Mount added to agent '${agentSlug}'`);
137
+ blank();
138
+ keyValue('Mount ID', mount.id.substring(0, 8));
139
+ keyValue('Bucket', mount.bucket.slug);
140
+ keyValue('Mount Path', mount.mount_path);
141
+ keyValue('Source Prefix', mount.source_prefix || '-');
142
+ keyValue('Permissions', formatPermissions(mount.permission_rules));
143
+ blank();
144
+ hint('Redeploy the agent to apply changes');
145
+ }
146
+ catch (err) {
147
+ handleError(err);
148
+ }
149
+ });
150
+ /**
151
+ * cast mounts remove <agent-slug> <mount-id>
152
+ */
153
+ const removeCommand = new Command('remove')
154
+ .description('Remove a mount from an agent')
155
+ .argument('<agent-slug>', 'Agent slug')
156
+ .argument('<mount-id>', 'Mount ID (or prefix)')
157
+ .option('-f, --force', 'Skip confirmation')
158
+ .action(async (agentSlug, mountId, options) => {
159
+ try {
160
+ const client = new CastariClient();
161
+ await client.ensureAuthenticated();
162
+ // Find the full mount ID if a prefix was provided
163
+ const mounts = await client.mounts.getMounts(agentSlug);
164
+ const mount = mounts.find((m) => m.id.startsWith(mountId));
165
+ if (!mount) {
166
+ handleError(new Error(`Mount '${mountId}' not found for agent '${agentSlug}'`));
167
+ }
168
+ // Confirm deletion unless --force is used
169
+ if (!options.force) {
170
+ const response = await prompts({
171
+ type: 'confirm',
172
+ name: 'confirm',
173
+ message: `Remove mount at '${mount.mount_path}' from agent '${agentSlug}'?`,
174
+ initial: false,
175
+ });
176
+ if (!response.confirm) {
177
+ info('Removal cancelled');
178
+ return;
179
+ }
180
+ }
181
+ const spinner = ora('Removing mount...').start();
182
+ await client.mounts.removeMount(agentSlug, mount.id);
183
+ spinner.succeed(`Mount removed from agent '${agentSlug}'`);
184
+ hint('Redeploy the agent to apply changes');
185
+ }
186
+ catch (err) {
187
+ handleError(err);
188
+ }
189
+ });
190
+ /**
191
+ * cast mounts update <agent-slug> <mount-id>
192
+ */
193
+ const updateCommand = new Command('update')
194
+ .description('Update a mount configuration')
195
+ .argument('<agent-slug>', 'Agent slug')
196
+ .argument('<mount-id>', 'Mount ID (or prefix)')
197
+ .option('--path <mount-path>', 'New mount path')
198
+ .option('--prefix <source-prefix>', 'New source prefix')
199
+ .option('--enable', 'Enable the mount')
200
+ .option('--disable', 'Disable the mount')
201
+ .action(async (agentSlug, mountId, options) => {
202
+ try {
203
+ const client = new CastariClient();
204
+ await client.ensureAuthenticated();
205
+ // Find the full mount ID if a prefix was provided
206
+ const mounts = await client.mounts.getMounts(agentSlug);
207
+ const mount = mounts.find((m) => m.id.startsWith(mountId));
208
+ if (!mount) {
209
+ handleError(new Error(`Mount '${mountId}' not found for agent '${agentSlug}'`));
210
+ }
211
+ // Determine enabled state
212
+ let enabled;
213
+ if (options.enable) {
214
+ enabled = true;
215
+ }
216
+ else if (options.disable) {
217
+ enabled = false;
218
+ }
219
+ // Check if any updates were specified
220
+ if (!options.path && options.prefix === undefined && enabled === undefined) {
221
+ info('No updates specified');
222
+ hint('Use --path, --prefix, --enable, or --disable to update the mount');
223
+ return;
224
+ }
225
+ const spinner = ora('Updating mount...').start();
226
+ const updated = await client.mounts.updateMount(agentSlug, mount.id, {
227
+ mountPath: options.path,
228
+ sourcePrefix: options.prefix,
229
+ enabled,
230
+ });
231
+ spinner.succeed(`Mount updated`);
232
+ blank();
233
+ keyValue('Mount Path', updated.mount_path);
234
+ keyValue('Source Prefix', updated.source_prefix || '-');
235
+ keyValue('Status', formatEnabled(updated.enabled));
236
+ blank();
237
+ hint('Redeploy the agent to apply changes');
238
+ }
239
+ catch (err) {
240
+ handleError(err);
241
+ }
242
+ });
243
+ /**
244
+ * cast mounts
245
+ */
246
+ export const mountsCommand = new Command('mounts')
247
+ .description('Manage agent storage mounts')
248
+ .addCommand(listCommand)
249
+ .addCommand(addCommand)
250
+ .addCommand(removeCommand)
251
+ .addCommand(updateCommand);
252
+ //# sourceMappingURL=mounts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mounts.js","sourceRoot":"","sources":["../../src/commands/mounts.ts"],"names":[],"mappings":"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"}