@agentuity/cli 0.0.58 → 0.0.60
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/cli.d.ts.map +1 -1
- package/dist/cli.js +14 -1
- package/dist/cli.js.map +1 -1
- package/dist/cmd/ai/capabilities/show.d.ts.map +1 -1
- package/dist/cmd/ai/capabilities/show.js +11 -4
- package/dist/cmd/ai/capabilities/show.js.map +1 -1
- package/dist/cmd/build/bundler.d.ts +1 -1
- package/dist/cmd/cloud/agent/get.d.ts +2 -0
- package/dist/cmd/cloud/agent/get.d.ts.map +1 -0
- package/dist/cmd/cloud/agent/get.js +97 -0
- package/dist/cmd/cloud/agent/get.js.map +1 -0
- package/dist/cmd/cloud/agent/index.d.ts +2 -0
- package/dist/cmd/cloud/agent/index.d.ts.map +1 -0
- package/dist/cmd/cloud/agent/index.js +11 -0
- package/dist/cmd/cloud/agent/index.js.map +1 -0
- package/dist/cmd/cloud/agent/list.d.ts.map +1 -0
- package/dist/cmd/cloud/agent/list.js +101 -0
- package/dist/cmd/cloud/agent/list.js.map +1 -0
- package/dist/cmd/cloud/agent/schema.d.ts +4 -0
- package/dist/cmd/cloud/agent/schema.d.ts.map +1 -0
- package/dist/cmd/cloud/agent/schema.js +22 -0
- package/dist/cmd/cloud/agent/schema.js.map +1 -0
- package/dist/cmd/cloud/apikey/create.d.ts +2 -0
- package/dist/cmd/cloud/apikey/create.d.ts.map +1 -0
- package/dist/cmd/cloud/apikey/create.js +100 -0
- package/dist/cmd/cloud/apikey/create.js.map +1 -0
- package/dist/cmd/cloud/apikey/delete.d.ts.map +1 -0
- package/dist/cmd/cloud/apikey/delete.js +55 -0
- package/dist/cmd/cloud/apikey/delete.js.map +1 -0
- package/dist/cmd/cloud/apikey/get.d.ts +2 -0
- package/dist/cmd/cloud/apikey/get.d.ts.map +1 -0
- package/dist/cmd/cloud/apikey/get.js +57 -0
- package/dist/cmd/cloud/apikey/get.js.map +1 -0
- package/dist/cmd/cloud/apikey/index.d.ts.map +1 -0
- package/dist/cmd/cloud/apikey/index.js +13 -0
- package/dist/cmd/cloud/apikey/index.js.map +1 -0
- package/dist/cmd/cloud/apikey/list.d.ts +2 -0
- package/dist/cmd/cloud/apikey/list.d.ts.map +1 -0
- package/dist/cmd/cloud/apikey/list.js +53 -0
- package/dist/cmd/cloud/apikey/list.js.map +1 -0
- package/dist/cmd/cloud/db/create.d.ts +2 -0
- package/dist/cmd/cloud/db/create.d.ts.map +1 -0
- package/dist/cmd/cloud/db/create.js +68 -0
- package/dist/cmd/cloud/db/create.js.map +1 -0
- package/dist/cmd/cloud/db/delete.d.ts +2 -0
- package/dist/cmd/cloud/db/delete.d.ts.map +1 -0
- package/dist/cmd/cloud/db/delete.js +106 -0
- package/dist/cmd/cloud/db/delete.js.map +1 -0
- package/dist/cmd/cloud/db/get.d.ts +2 -0
- package/dist/cmd/cloud/db/get.d.ts.map +1 -0
- package/dist/cmd/cloud/db/get.js +66 -0
- package/dist/cmd/cloud/db/get.js.map +1 -0
- package/dist/cmd/cloud/db/index.d.ts +2 -0
- package/dist/cmd/cloud/db/index.d.ts.map +1 -0
- package/dist/cmd/cloud/db/index.js +14 -0
- package/dist/cmd/cloud/db/index.js.map +1 -0
- package/dist/cmd/cloud/db/list.d.ts +2 -0
- package/dist/cmd/cloud/db/list.d.ts.map +1 -0
- package/dist/cmd/cloud/db/list.js +75 -0
- package/dist/cmd/cloud/db/list.js.map +1 -0
- package/dist/cmd/cloud/db/sql.d.ts +2 -0
- package/dist/cmd/cloud/db/sql.d.ts.map +1 -0
- package/dist/cmd/cloud/db/sql.js +102 -0
- package/dist/cmd/cloud/db/sql.js.map +1 -0
- package/dist/cmd/cloud/deployment/index.d.ts.map +1 -1
- package/dist/cmd/cloud/deployment/index.js +2 -0
- package/dist/cmd/cloud/deployment/index.js.map +1 -1
- package/dist/cmd/cloud/deployment/logs.d.ts +2 -0
- package/dist/cmd/cloud/deployment/logs.d.ts.map +1 -0
- package/dist/cmd/cloud/deployment/logs.js +70 -0
- package/dist/cmd/cloud/deployment/logs.js.map +1 -0
- package/dist/cmd/cloud/env/get.d.ts.map +1 -1
- package/dist/cmd/cloud/env/get.js +2 -3
- package/dist/cmd/cloud/env/get.js.map +1 -1
- package/dist/cmd/cloud/env/list.d.ts.map +1 -1
- package/dist/cmd/cloud/env/list.js +1 -2
- package/dist/cmd/cloud/env/list.js.map +1 -1
- package/dist/cmd/cloud/index.d.ts.map +1 -1
- package/dist/cmd/cloud/index.js +12 -4
- package/dist/cmd/cloud/index.js.map +1 -1
- package/dist/cmd/cloud/secret/get.d.ts.map +1 -1
- package/dist/cmd/cloud/secret/get.js +2 -3
- package/dist/cmd/cloud/secret/get.js.map +1 -1
- package/dist/cmd/cloud/secret/list.d.ts.map +1 -1
- package/dist/cmd/cloud/secret/list.js +1 -2
- package/dist/cmd/cloud/secret/list.js.map +1 -1
- package/dist/cmd/cloud/session/logs.d.ts.map +1 -1
- package/dist/cmd/cloud/session/logs.js +12 -9
- package/dist/cmd/cloud/session/logs.js.map +1 -1
- package/dist/cmd/cloud/storage/create.d.ts +2 -0
- package/dist/cmd/cloud/storage/create.d.ts.map +1 -0
- package/dist/cmd/cloud/storage/create.js +61 -0
- package/dist/cmd/cloud/storage/create.js.map +1 -0
- package/dist/cmd/cloud/storage/delete.d.ts +2 -0
- package/dist/cmd/cloud/storage/delete.d.ts.map +1 -0
- package/dist/cmd/cloud/storage/delete.js +167 -0
- package/dist/cmd/cloud/storage/delete.js.map +1 -0
- package/dist/cmd/cloud/storage/download.d.ts +2 -0
- package/dist/cmd/cloud/storage/download.d.ts.map +1 -0
- package/dist/cmd/cloud/storage/download.js +131 -0
- package/dist/cmd/cloud/storage/download.js.map +1 -0
- package/dist/cmd/cloud/storage/get.d.ts +2 -0
- package/dist/cmd/cloud/storage/get.d.ts.map +1 -0
- package/dist/cmd/cloud/storage/get.js +86 -0
- package/dist/cmd/cloud/storage/get.js.map +1 -0
- package/dist/cmd/cloud/storage/index.d.ts +2 -0
- package/dist/cmd/cloud/storage/index.d.ts.map +1 -0
- package/dist/cmd/cloud/storage/index.js +22 -0
- package/dist/cmd/cloud/storage/index.js.map +1 -0
- package/dist/cmd/cloud/storage/list.d.ts +2 -0
- package/dist/cmd/cloud/storage/list.d.ts.map +1 -0
- package/dist/cmd/cloud/storage/list.js +170 -0
- package/dist/cmd/cloud/storage/list.js.map +1 -0
- package/dist/cmd/cloud/storage/upload.d.ts +2 -0
- package/dist/cmd/cloud/storage/upload.d.ts.map +1 -0
- package/dist/cmd/cloud/storage/upload.js +133 -0
- package/dist/cmd/cloud/storage/upload.js.map +1 -0
- package/dist/cmd/cloud/storage/utils.d.ts +18 -0
- package/dist/cmd/cloud/storage/utils.d.ts.map +1 -0
- package/dist/cmd/cloud/storage/utils.js +21 -0
- package/dist/cmd/cloud/storage/utils.js.map +1 -0
- package/dist/cmd/cloud/stream/delete.d.ts +3 -0
- package/dist/cmd/cloud/stream/delete.d.ts.map +1 -0
- package/dist/cmd/cloud/stream/delete.js +42 -0
- package/dist/cmd/cloud/stream/delete.js.map +1 -0
- package/dist/cmd/cloud/stream/get.d.ts +3 -0
- package/dist/cmd/cloud/stream/get.d.ts.map +1 -0
- package/dist/cmd/cloud/stream/get.js +110 -0
- package/dist/cmd/cloud/stream/get.js.map +1 -0
- package/dist/cmd/cloud/stream/index.d.ts +3 -0
- package/dist/cmd/cloud/stream/index.d.ts.map +1 -0
- package/dist/cmd/cloud/stream/index.js +13 -0
- package/dist/cmd/cloud/stream/index.js.map +1 -0
- package/dist/cmd/cloud/stream/list.d.ts +3 -0
- package/dist/cmd/cloud/stream/list.d.ts.map +1 -0
- package/dist/cmd/cloud/stream/list.js +131 -0
- package/dist/cmd/cloud/stream/list.js.map +1 -0
- package/dist/cmd/cloud/stream/util.d.ts +8 -0
- package/dist/cmd/cloud/stream/util.d.ts.map +1 -0
- package/dist/cmd/cloud/stream/util.js +19 -0
- package/dist/cmd/cloud/stream/util.js.map +1 -0
- package/dist/cmd/cloud/vector/delete.d.ts +3 -0
- package/dist/cmd/cloud/vector/delete.d.ts.map +1 -0
- package/dist/cmd/cloud/vector/delete.js +90 -0
- package/dist/cmd/cloud/vector/delete.js.map +1 -0
- package/dist/cmd/cloud/vector/get.d.ts +3 -0
- package/dist/cmd/cloud/vector/get.d.ts.map +1 -0
- package/dist/cmd/cloud/vector/get.js +80 -0
- package/dist/cmd/cloud/vector/get.js.map +1 -0
- package/dist/cmd/cloud/vector/index.d.ts +3 -0
- package/dist/cmd/cloud/vector/index.d.ts.map +1 -0
- package/dist/cmd/cloud/vector/index.js +14 -0
- package/dist/cmd/cloud/vector/index.js.map +1 -0
- package/dist/cmd/cloud/vector/search.d.ts +3 -0
- package/dist/cmd/cloud/vector/search.d.ts.map +1 -0
- package/dist/cmd/cloud/vector/search.js +136 -0
- package/dist/cmd/cloud/vector/search.js.map +1 -0
- package/dist/cmd/cloud/vector/util.d.ts +8 -0
- package/dist/cmd/cloud/vector/util.d.ts.map +1 -0
- package/dist/cmd/cloud/vector/util.js +18 -0
- package/dist/cmd/cloud/vector/util.js.map +1 -0
- package/dist/cmd/dev/agents.d.ts.map +1 -1
- package/dist/cmd/dev/agents.js +3 -2
- package/dist/cmd/dev/agents.js.map +1 -1
- package/dist/cmd/dev/index.js +3 -3
- package/dist/cmd/dev/index.js.map +1 -1
- package/dist/cmd/index.d.ts.map +1 -1
- package/dist/cmd/index.js +38 -42
- package/dist/cmd/index.js.map +1 -1
- package/dist/schema-parser.d.ts.map +1 -1
- package/dist/schema-parser.js +3 -1
- package/dist/schema-parser.js.map +1 -1
- package/dist/tui.d.ts +12 -2
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +61 -31
- package/dist/tui.js.map +1 -1
- package/dist/utils/date.d.ts +14 -0
- package/dist/utils/date.d.ts.map +1 -0
- package/dist/utils/date.js +51 -0
- package/dist/utils/date.js.map +1 -0
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +6 -6
- package/src/cli.ts +15 -1
- package/src/cmd/ai/capabilities/show.ts +11 -4
- package/src/cmd/cloud/agent/get.ts +105 -0
- package/src/cmd/cloud/agent/index.ts +11 -0
- package/src/cmd/cloud/agent/list.ts +107 -0
- package/src/cmd/cloud/agent/schema.ts +25 -0
- package/src/cmd/cloud/apikey/create.ts +114 -0
- package/src/cmd/cloud/apikey/delete.ts +66 -0
- package/src/cmd/cloud/apikey/get.ts +62 -0
- package/src/cmd/cloud/apikey/index.ts +13 -0
- package/src/cmd/cloud/apikey/list.ts +58 -0
- package/src/cmd/cloud/db/create.ts +72 -0
- package/src/cmd/cloud/db/delete.ts +118 -0
- package/src/cmd/cloud/db/get.ts +75 -0
- package/src/cmd/cloud/db/index.ts +14 -0
- package/src/cmd/cloud/db/list.ts +83 -0
- package/src/cmd/cloud/db/sql.ts +125 -0
- package/src/cmd/cloud/deployment/index.ts +2 -0
- package/src/cmd/cloud/deployment/logs.ts +75 -0
- package/src/cmd/cloud/env/get.ts +2 -3
- package/src/cmd/cloud/env/list.ts +1 -2
- package/src/cmd/cloud/index.ts +13 -4
- package/src/cmd/cloud/secret/get.ts +2 -3
- package/src/cmd/cloud/secret/list.ts +1 -2
- package/src/cmd/cloud/session/logs.ts +12 -11
- package/src/cmd/cloud/storage/create.ts +65 -0
- package/src/cmd/cloud/storage/delete.ts +195 -0
- package/src/cmd/cloud/storage/download.ts +154 -0
- package/src/cmd/cloud/storage/get.ts +97 -0
- package/src/cmd/cloud/storage/index.ts +22 -0
- package/src/cmd/cloud/storage/list.ts +197 -0
- package/src/cmd/cloud/storage/upload.ts +150 -0
- package/src/cmd/cloud/storage/utils.ts +26 -0
- package/src/cmd/cloud/stream/delete.ts +49 -0
- package/src/cmd/cloud/stream/get.ts +118 -0
- package/src/cmd/cloud/stream/index.ts +14 -0
- package/src/cmd/cloud/stream/list.ts +146 -0
- package/src/cmd/cloud/stream/util.ts +32 -0
- package/src/cmd/cloud/vector/delete.ts +105 -0
- package/src/cmd/cloud/vector/get.ts +94 -0
- package/src/cmd/cloud/vector/index.ts +15 -0
- package/src/cmd/cloud/vector/search.ts +156 -0
- package/src/cmd/cloud/vector/util.ts +28 -0
- package/src/cmd/dev/agents.ts +4 -3
- package/src/cmd/dev/index.ts +3 -3
- package/src/cmd/index.ts +38 -42
- package/src/schema-parser.ts +3 -1
- package/src/tui.ts +73 -36
- package/src/utils/date.ts +57 -0
- package/src/version.ts +1 -1
- package/dist/cmd/cloud/agents/index.d.ts.map +0 -1
- package/dist/cmd/cloud/agents/index.js +0 -133
- package/dist/cmd/cloud/agents/index.js.map +0 -1
- package/dist/cmd/cloud/resource/add.d.ts +0 -2
- package/dist/cmd/cloud/resource/add.d.ts.map +0 -1
- package/dist/cmd/cloud/resource/add.js +0 -70
- package/dist/cmd/cloud/resource/add.js.map +0 -1
- package/dist/cmd/cloud/resource/delete.d.ts.map +0 -1
- package/dist/cmd/cloud/resource/delete.js +0 -126
- package/dist/cmd/cloud/resource/delete.js.map +0 -1
- package/dist/cmd/cloud/resource/index.d.ts +0 -2
- package/dist/cmd/cloud/resource/index.d.ts.map +0 -1
- package/dist/cmd/cloud/resource/index.js +0 -12
- package/dist/cmd/cloud/resource/index.js.map +0 -1
- package/dist/cmd/cloud/resource/list.d.ts.map +0 -1
- package/dist/cmd/cloud/resource/list.js +0 -100
- package/dist/cmd/cloud/resource/list.js.map +0 -1
- package/src/cmd/cloud/agents/index.ts +0 -148
- package/src/cmd/cloud/resource/add.ts +0 -75
- package/src/cmd/cloud/resource/delete.ts +0 -141
- package/src/cmd/cloud/resource/index.ts +0 -12
- package/src/cmd/cloud/resource/list.ts +0 -105
- /package/dist/cmd/cloud/{resource → agent}/list.d.ts +0 -0
- /package/dist/cmd/cloud/{resource → apikey}/delete.d.ts +0 -0
- /package/dist/cmd/cloud/{agents → apikey}/index.d.ts +0 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { listResources } from '@agentuity/server';
|
|
3
|
+
import { createSubcommand } from '../../../types';
|
|
4
|
+
import * as tui from '../../../tui';
|
|
5
|
+
import { getCatalystAPIClient } from '../../../config';
|
|
6
|
+
import { getCommand } from '../../../command-prefix';
|
|
7
|
+
import { ErrorCode } from '../../../errors';
|
|
8
|
+
import { createS3Client } from './utils';
|
|
9
|
+
|
|
10
|
+
export const downloadSubcommand = createSubcommand({
|
|
11
|
+
name: 'download',
|
|
12
|
+
description: 'Download a file from storage bucket',
|
|
13
|
+
tags: ['read-only', 'requires-auth'],
|
|
14
|
+
requires: { auth: true, org: true, region: true },
|
|
15
|
+
idempotent: true,
|
|
16
|
+
examples: [
|
|
17
|
+
`${getCommand('cloud storage download')} my-bucket file.txt`,
|
|
18
|
+
`${getCommand('cloud storage download')} my-bucket file.txt output.txt`,
|
|
19
|
+
`${getCommand('cloud storage download')} my-bucket file.txt - > output.txt`,
|
|
20
|
+
`${getCommand('cloud storage download')} my-bucket file.txt --metadata`,
|
|
21
|
+
],
|
|
22
|
+
schema: {
|
|
23
|
+
args: z.object({
|
|
24
|
+
name: z.string().describe('Bucket name'),
|
|
25
|
+
filename: z.string().describe('File path to download'),
|
|
26
|
+
output: z.string().optional().describe('Output file path or "-" for STDOUT'),
|
|
27
|
+
}),
|
|
28
|
+
options: z.object({
|
|
29
|
+
metadata: z.boolean().optional().describe('Download metadata only (not file contents)'),
|
|
30
|
+
}),
|
|
31
|
+
response: z.object({
|
|
32
|
+
success: z.boolean().describe('Whether download succeeded'),
|
|
33
|
+
bucket: z.string().describe('Bucket name'),
|
|
34
|
+
filename: z.string().describe('Downloaded filename'),
|
|
35
|
+
size: z.number().optional().describe('File size in bytes'),
|
|
36
|
+
contentType: z.string().optional().describe('Content type'),
|
|
37
|
+
lastModified: z.string().optional().describe('Last modified timestamp'),
|
|
38
|
+
}),
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
async handler(ctx) {
|
|
42
|
+
const { logger, args, opts, options, orgId, region, config, auth } = ctx;
|
|
43
|
+
|
|
44
|
+
const catalystClient = getCatalystAPIClient(config, logger, auth);
|
|
45
|
+
|
|
46
|
+
// Fetch bucket credentials
|
|
47
|
+
const resources = await tui.spinner({
|
|
48
|
+
message: `Fetching credentials for ${args.name}`,
|
|
49
|
+
clearOnSuccess: true,
|
|
50
|
+
callback: async () => {
|
|
51
|
+
return listResources(catalystClient, orgId, region);
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const bucket = resources.s3.find((s3) => s3.bucket_name === args.name);
|
|
56
|
+
|
|
57
|
+
if (!bucket) {
|
|
58
|
+
tui.fatal(`Storage bucket '${args.name}' not found`, ErrorCode.RESOURCE_NOT_FOUND);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (!bucket.access_key || !bucket.secret_key || !bucket.endpoint) {
|
|
62
|
+
tui.fatal(
|
|
63
|
+
`Storage bucket '${args.name}' is missing credentials`,
|
|
64
|
+
ErrorCode.CONFIG_INVALID
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Initialize S3 client
|
|
69
|
+
const s3Client = createS3Client({
|
|
70
|
+
endpoint: bucket.endpoint,
|
|
71
|
+
access_key: bucket.access_key,
|
|
72
|
+
secret_key: bucket.secret_key,
|
|
73
|
+
region: bucket.region,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
if (opts.metadata) {
|
|
77
|
+
// Download metadata only
|
|
78
|
+
const metadata = await tui.spinner({
|
|
79
|
+
message: `Fetching metadata for ${args.filename}`,
|
|
80
|
+
clearOnSuccess: true,
|
|
81
|
+
callback: async () => {
|
|
82
|
+
return s3Client.stat(args.filename);
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
if (!options.json) {
|
|
87
|
+
console.log(tui.bold('File: ') + args.filename);
|
|
88
|
+
console.log(tui.bold('Bucket: ') + args.name);
|
|
89
|
+
if (metadata.size) {
|
|
90
|
+
console.log(tui.bold('Size: ') + metadata.size + ' bytes');
|
|
91
|
+
}
|
|
92
|
+
if (metadata.type) {
|
|
93
|
+
console.log(tui.bold('Content Type: ') + metadata.type);
|
|
94
|
+
}
|
|
95
|
+
if (metadata.lastModified) {
|
|
96
|
+
console.log(tui.bold('Last Modified: ') + metadata.lastModified);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
success: true,
|
|
102
|
+
bucket: args.name,
|
|
103
|
+
filename: args.filename,
|
|
104
|
+
size: metadata.size,
|
|
105
|
+
contentType: metadata.type,
|
|
106
|
+
lastModified: metadata.lastModified?.toISOString(),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Download file content
|
|
111
|
+
const s3File = s3Client.file(args.filename);
|
|
112
|
+
|
|
113
|
+
const fileContent = await tui.spinner({
|
|
114
|
+
message: `Downloading ${args.filename} from ${args.name}`,
|
|
115
|
+
clearOnSuccess: true,
|
|
116
|
+
callback: async () => {
|
|
117
|
+
return Buffer.from(await s3File.arrayBuffer());
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// Write to output or STDOUT
|
|
122
|
+
const outputPath = args.output || '-';
|
|
123
|
+
|
|
124
|
+
if (outputPath === '-') {
|
|
125
|
+
// Write to STDOUT
|
|
126
|
+
// When outputting to STDOUT in JSON mode, we can't mix file content with JSON
|
|
127
|
+
if (options.json) {
|
|
128
|
+
tui.fatal(
|
|
129
|
+
'Cannot use --json with STDOUT output. Use --metadata to get JSON metadata, or specify an output file.',
|
|
130
|
+
ErrorCode.INVALID_ARGUMENT
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
process.stdout.write(fileContent);
|
|
135
|
+
} else {
|
|
136
|
+
// Write to file
|
|
137
|
+
await Bun.write(outputPath, fileContent);
|
|
138
|
+
if (!options.json) {
|
|
139
|
+
tui.success(
|
|
140
|
+
`Downloaded ${tui.bold(args.filename)} to ${tui.bold(outputPath)} (${fileContent.length} bytes)`
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
success: true,
|
|
147
|
+
bucket: args.name,
|
|
148
|
+
filename: args.filename,
|
|
149
|
+
size: fileContent.length,
|
|
150
|
+
contentType: s3File.type,
|
|
151
|
+
lastModified: undefined,
|
|
152
|
+
};
|
|
153
|
+
},
|
|
154
|
+
});
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { listResources } from '@agentuity/server';
|
|
3
|
+
import { createSubcommand } from '../../../types';
|
|
4
|
+
import * as tui from '../../../tui';
|
|
5
|
+
import { getCatalystAPIClient } from '../../../config';
|
|
6
|
+
import { getCommand } from '../../../command-prefix';
|
|
7
|
+
import { ErrorCode } from '../../../errors';
|
|
8
|
+
|
|
9
|
+
const StorageGetResponseSchema = z.object({
|
|
10
|
+
bucket_name: z.string().describe('Storage bucket name'),
|
|
11
|
+
access_key: z.string().optional().describe('S3 access key'),
|
|
12
|
+
secret_key: z.string().optional().describe('S3 secret key'),
|
|
13
|
+
region: z.string().optional().describe('S3 region'),
|
|
14
|
+
endpoint: z.string().optional().describe('S3 endpoint URL'),
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export const getSubcommand = createSubcommand({
|
|
18
|
+
name: 'get',
|
|
19
|
+
aliases: ['show'],
|
|
20
|
+
description: 'Show details about a specific storage bucket',
|
|
21
|
+
tags: ['read-only', 'fast', 'requires-auth'],
|
|
22
|
+
requires: { auth: true, org: true, region: true },
|
|
23
|
+
idempotent: true,
|
|
24
|
+
examples: [
|
|
25
|
+
`${getCommand('cloud storage get')} my-bucket`,
|
|
26
|
+
`${getCommand('cloud storage show')} my-bucket`,
|
|
27
|
+
`${getCommand('cloud storage get')} my-bucket --show-credentials`,
|
|
28
|
+
],
|
|
29
|
+
schema: {
|
|
30
|
+
args: z.object({
|
|
31
|
+
name: z.string().describe('Bucket name'),
|
|
32
|
+
}),
|
|
33
|
+
options: z.object({
|
|
34
|
+
showCredentials: z
|
|
35
|
+
.boolean()
|
|
36
|
+
.optional()
|
|
37
|
+
.describe(
|
|
38
|
+
'Show credentials in plain text (default: masked in terminal, unmasked in JSON)'
|
|
39
|
+
),
|
|
40
|
+
}),
|
|
41
|
+
response: StorageGetResponseSchema,
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
async handler(ctx) {
|
|
45
|
+
const { logger, args, opts, options, orgId, region, config, auth } = ctx;
|
|
46
|
+
|
|
47
|
+
const catalystClient = getCatalystAPIClient(config, logger, auth);
|
|
48
|
+
|
|
49
|
+
const resources = await tui.spinner({
|
|
50
|
+
message: `Fetching storage bucket ${args.name}`,
|
|
51
|
+
clearOnSuccess: true,
|
|
52
|
+
callback: async () => {
|
|
53
|
+
return listResources(catalystClient, orgId, region);
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const bucket = resources.s3.find((s3) => s3.bucket_name === args.name);
|
|
58
|
+
|
|
59
|
+
if (!bucket) {
|
|
60
|
+
tui.fatal(`Storage bucket '${args.name}' not found`, ErrorCode.RESOURCE_NOT_FOUND);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Mask credentials in terminal output by default, unless --show-credentials is passed
|
|
64
|
+
const shouldShowCredentials = opts.showCredentials === true;
|
|
65
|
+
const shouldMask = !options.json && !shouldShowCredentials;
|
|
66
|
+
|
|
67
|
+
if (!options.json) {
|
|
68
|
+
console.log(tui.bold('Bucket Name: ') + bucket.bucket_name);
|
|
69
|
+
if (bucket.access_key) {
|
|
70
|
+
const displayAccessKey = shouldMask
|
|
71
|
+
? tui.maskSecret(bucket.access_key)
|
|
72
|
+
: bucket.access_key;
|
|
73
|
+
console.log(tui.bold('Access Key: ') + displayAccessKey);
|
|
74
|
+
}
|
|
75
|
+
if (bucket.secret_key) {
|
|
76
|
+
const displaySecretKey = shouldMask
|
|
77
|
+
? tui.maskSecret(bucket.secret_key)
|
|
78
|
+
: bucket.secret_key;
|
|
79
|
+
console.log(tui.bold('Secret Key: ') + displaySecretKey);
|
|
80
|
+
}
|
|
81
|
+
if (bucket.region) {
|
|
82
|
+
console.log(tui.bold('Region: ') + bucket.region);
|
|
83
|
+
}
|
|
84
|
+
if (bucket.endpoint) {
|
|
85
|
+
console.log(tui.bold('Endpoint: ') + bucket.endpoint);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
bucket_name: bucket.bucket_name,
|
|
91
|
+
access_key: bucket.access_key ?? undefined,
|
|
92
|
+
secret_key: bucket.secret_key ?? undefined,
|
|
93
|
+
region: bucket.region ?? undefined,
|
|
94
|
+
endpoint: bucket.endpoint ?? undefined,
|
|
95
|
+
};
|
|
96
|
+
},
|
|
97
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createCommand } from '../../../types';
|
|
2
|
+
import { createSubcommand } from './create';
|
|
3
|
+
import { listSubcommand } from './list';
|
|
4
|
+
import { deleteSubcommand } from './delete';
|
|
5
|
+
import { getSubcommand } from './get';
|
|
6
|
+
import { uploadSubcommand } from './upload';
|
|
7
|
+
import { downloadSubcommand } from './download';
|
|
8
|
+
|
|
9
|
+
export const storageCommand = createCommand({
|
|
10
|
+
name: 'storage',
|
|
11
|
+
aliases: ['s3'],
|
|
12
|
+
description: 'Manage storage resources',
|
|
13
|
+
tags: ['slow', 'requires-auth', 'requires-deployment'],
|
|
14
|
+
subcommands: [
|
|
15
|
+
createSubcommand,
|
|
16
|
+
listSubcommand,
|
|
17
|
+
getSubcommand,
|
|
18
|
+
uploadSubcommand,
|
|
19
|
+
downloadSubcommand,
|
|
20
|
+
deleteSubcommand,
|
|
21
|
+
],
|
|
22
|
+
});
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { listResources } from '@agentuity/server';
|
|
3
|
+
import { createSubcommand } from '../../../types';
|
|
4
|
+
import * as tui from '../../../tui';
|
|
5
|
+
import { getCatalystAPIClient } from '../../../config';
|
|
6
|
+
import { getCommand } from '../../../command-prefix';
|
|
7
|
+
import { ErrorCode } from '../../../errors';
|
|
8
|
+
import { createS3Client } from './utils';
|
|
9
|
+
|
|
10
|
+
const StorageListResponseSchema = z.object({
|
|
11
|
+
buckets: z
|
|
12
|
+
.array(
|
|
13
|
+
z.object({
|
|
14
|
+
bucket_name: z.string().describe('Storage bucket name'),
|
|
15
|
+
access_key: z.string().optional().describe('S3 access key'),
|
|
16
|
+
secret_key: z.string().optional().describe('S3 secret key'),
|
|
17
|
+
region: z.string().optional().describe('S3 region'),
|
|
18
|
+
endpoint: z.string().optional().describe('S3 endpoint URL'),
|
|
19
|
+
})
|
|
20
|
+
)
|
|
21
|
+
.optional()
|
|
22
|
+
.describe('List of storage resources'),
|
|
23
|
+
files: z
|
|
24
|
+
.array(
|
|
25
|
+
z.object({
|
|
26
|
+
key: z.string().describe('File key/path'),
|
|
27
|
+
size: z.number().describe('File size in bytes'),
|
|
28
|
+
lastModified: z.string().describe('Last modified timestamp'),
|
|
29
|
+
})
|
|
30
|
+
)
|
|
31
|
+
.optional()
|
|
32
|
+
.describe('List of files in bucket'),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
export const listSubcommand = createSubcommand({
|
|
36
|
+
name: 'list',
|
|
37
|
+
aliases: ['ls'],
|
|
38
|
+
description: 'List storage resources or files in a bucket',
|
|
39
|
+
tags: ['read-only', 'fast', 'requires-auth'],
|
|
40
|
+
requires: { auth: true, org: true, region: true },
|
|
41
|
+
idempotent: true,
|
|
42
|
+
examples: [
|
|
43
|
+
getCommand('cloud storage list'),
|
|
44
|
+
getCommand('cloud storage list my-bucket'),
|
|
45
|
+
getCommand('cloud storage list my-bucket path/prefix'),
|
|
46
|
+
getCommand('--json cloud storage list'),
|
|
47
|
+
getCommand('cloud storage ls'),
|
|
48
|
+
getCommand('cloud storage list --show-credentials'),
|
|
49
|
+
],
|
|
50
|
+
schema: {
|
|
51
|
+
args: z.object({
|
|
52
|
+
name: z.string().optional().describe('Bucket name to list files from'),
|
|
53
|
+
prefix: z.string().optional().describe('Path prefix to filter files'),
|
|
54
|
+
}),
|
|
55
|
+
options: z.object({
|
|
56
|
+
showCredentials: z
|
|
57
|
+
.boolean()
|
|
58
|
+
.optional()
|
|
59
|
+
.describe(
|
|
60
|
+
'Show credentials in plain text (default: masked in terminal, unmasked in JSON)'
|
|
61
|
+
),
|
|
62
|
+
}),
|
|
63
|
+
response: StorageListResponseSchema,
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
async handler(ctx) {
|
|
67
|
+
const { logger, args, opts, options, orgId, region, config, auth } = ctx;
|
|
68
|
+
|
|
69
|
+
const catalystClient = getCatalystAPIClient(config, logger, auth);
|
|
70
|
+
|
|
71
|
+
const resources = await tui.spinner({
|
|
72
|
+
message: `Fetching storage for ${orgId} in ${region}`,
|
|
73
|
+
clearOnSuccess: true,
|
|
74
|
+
callback: async () => {
|
|
75
|
+
return listResources(catalystClient, orgId, region);
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// If bucket name is provided, list files in the bucket
|
|
80
|
+
if (args.name) {
|
|
81
|
+
const bucket = resources.s3.find((s3) => s3.bucket_name === args.name);
|
|
82
|
+
|
|
83
|
+
if (!bucket) {
|
|
84
|
+
tui.fatal(`Storage bucket '${args.name}' not found`, ErrorCode.RESOURCE_NOT_FOUND);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (!bucket.access_key || !bucket.secret_key || !bucket.endpoint) {
|
|
88
|
+
tui.fatal(
|
|
89
|
+
`Storage bucket '${args.name}' is missing credentials`,
|
|
90
|
+
ErrorCode.CONFIG_INVALID
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const s3Client = createS3Client({
|
|
95
|
+
endpoint: bucket.endpoint,
|
|
96
|
+
access_key: bucket.access_key,
|
|
97
|
+
secret_key: bucket.secret_key,
|
|
98
|
+
region: bucket.region,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
const result = await tui.spinner({
|
|
102
|
+
message: `Listing files in ${args.name}${args.prefix ? ` with prefix ${args.prefix}` : ''}`,
|
|
103
|
+
clearOnSuccess: true,
|
|
104
|
+
callback: async () => {
|
|
105
|
+
return s3Client.list(
|
|
106
|
+
args.prefix
|
|
107
|
+
? {
|
|
108
|
+
prefix: args.prefix,
|
|
109
|
+
}
|
|
110
|
+
: null
|
|
111
|
+
);
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const objects = result.contents || [];
|
|
116
|
+
|
|
117
|
+
if (!options.json) {
|
|
118
|
+
if (objects.length === 0) {
|
|
119
|
+
tui.info('No files found');
|
|
120
|
+
} else {
|
|
121
|
+
tui.info(
|
|
122
|
+
tui.bold(`Files in ${args.name}${args.prefix ? ` (prefix: ${args.prefix})` : ''}`)
|
|
123
|
+
);
|
|
124
|
+
tui.newline();
|
|
125
|
+
for (const obj of objects) {
|
|
126
|
+
console.log(
|
|
127
|
+
`${obj.key} ${tui.muted(`(${obj.size} bytes, ${obj.lastModified})`)}`
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
files: objects.map((obj) => {
|
|
135
|
+
const lastModified = obj.lastModified;
|
|
136
|
+
let lastModifiedStr = '';
|
|
137
|
+
if (typeof lastModified === 'string') {
|
|
138
|
+
lastModifiedStr = lastModified;
|
|
139
|
+
} else if (
|
|
140
|
+
lastModified &&
|
|
141
|
+
typeof lastModified === 'object' &&
|
|
142
|
+
'toISOString' in lastModified
|
|
143
|
+
) {
|
|
144
|
+
lastModifiedStr = (lastModified as Date).toISOString();
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
key: obj.key,
|
|
148
|
+
size: obj.size ?? 0,
|
|
149
|
+
lastModified: lastModifiedStr,
|
|
150
|
+
};
|
|
151
|
+
}),
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Otherwise, list buckets
|
|
156
|
+
// Mask credentials in terminal output by default, unless --show-credentials is passed
|
|
157
|
+
const shouldShowCredentials = opts.showCredentials === true;
|
|
158
|
+
const shouldMask = !options.json && !shouldShowCredentials;
|
|
159
|
+
|
|
160
|
+
if (!options.json) {
|
|
161
|
+
if (resources.s3.length === 0) {
|
|
162
|
+
tui.info('No storage buckets found');
|
|
163
|
+
} else {
|
|
164
|
+
tui.info(tui.bold('Storage'));
|
|
165
|
+
tui.newline();
|
|
166
|
+
for (const s3 of resources.s3) {
|
|
167
|
+
console.log(tui.bold(s3.bucket_name));
|
|
168
|
+
if (s3.access_key) {
|
|
169
|
+
const displayAccessKey = shouldMask
|
|
170
|
+
? tui.maskSecret(s3.access_key)
|
|
171
|
+
: s3.access_key;
|
|
172
|
+
console.log(` Access Key: ${tui.muted(displayAccessKey)}`);
|
|
173
|
+
}
|
|
174
|
+
if (s3.secret_key) {
|
|
175
|
+
const displaySecretKey = shouldMask
|
|
176
|
+
? tui.maskSecret(s3.secret_key)
|
|
177
|
+
: s3.secret_key;
|
|
178
|
+
console.log(` Secret Key: ${tui.muted(displaySecretKey)}`);
|
|
179
|
+
}
|
|
180
|
+
if (s3.region) console.log(` Region: ${tui.muted(s3.region)}`);
|
|
181
|
+
if (s3.endpoint) console.log(` Endpoint: ${tui.muted(s3.endpoint)}`);
|
|
182
|
+
tui.newline();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return {
|
|
188
|
+
buckets: resources.s3.map((s3) => ({
|
|
189
|
+
bucket_name: s3.bucket_name,
|
|
190
|
+
access_key: s3.access_key ?? undefined,
|
|
191
|
+
secret_key: s3.secret_key ?? undefined,
|
|
192
|
+
region: s3.region ?? undefined,
|
|
193
|
+
endpoint: s3.endpoint ?? undefined,
|
|
194
|
+
})),
|
|
195
|
+
};
|
|
196
|
+
},
|
|
197
|
+
});
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { basename } from 'path';
|
|
3
|
+
import { listResources } from '@agentuity/server';
|
|
4
|
+
import { createSubcommand } from '../../../types';
|
|
5
|
+
import * as tui from '../../../tui';
|
|
6
|
+
import { getCatalystAPIClient } from '../../../config';
|
|
7
|
+
import { getCommand } from '../../../command-prefix';
|
|
8
|
+
import { ErrorCode } from '../../../errors';
|
|
9
|
+
import { createS3Client } from './utils';
|
|
10
|
+
|
|
11
|
+
export const uploadSubcommand = createSubcommand({
|
|
12
|
+
name: 'upload',
|
|
13
|
+
aliases: ['put'],
|
|
14
|
+
description: 'Upload a file to storage bucket',
|
|
15
|
+
tags: ['write', 'requires-auth'],
|
|
16
|
+
requires: { auth: true, org: true, region: true },
|
|
17
|
+
idempotent: false,
|
|
18
|
+
examples: [
|
|
19
|
+
`${getCommand('cloud storage upload')} my-bucket file.txt`,
|
|
20
|
+
`${getCommand('cloud storage put')} my-bucket file.txt --content-type text/plain`,
|
|
21
|
+
`cat file.txt | ${getCommand('cloud storage upload')} my-bucket -`,
|
|
22
|
+
],
|
|
23
|
+
schema: {
|
|
24
|
+
args: z.object({
|
|
25
|
+
name: z.string().describe('Bucket name'),
|
|
26
|
+
filename: z.string().describe('File path to upload or "-" for STDIN'),
|
|
27
|
+
}),
|
|
28
|
+
options: z.object({
|
|
29
|
+
contentType: z
|
|
30
|
+
.string()
|
|
31
|
+
.optional()
|
|
32
|
+
.describe('Content type (auto-detected if not provided)'),
|
|
33
|
+
}),
|
|
34
|
+
response: z.object({
|
|
35
|
+
success: z.boolean().describe('Whether upload succeeded'),
|
|
36
|
+
bucket: z.string().describe('Bucket name'),
|
|
37
|
+
filename: z.string().describe('Uploaded filename'),
|
|
38
|
+
size: z.number().describe('File size in bytes'),
|
|
39
|
+
}),
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
async handler(ctx) {
|
|
43
|
+
const { logger, args, opts, options, orgId, region, config, auth } = ctx;
|
|
44
|
+
|
|
45
|
+
const catalystClient = getCatalystAPIClient(config, logger, auth);
|
|
46
|
+
|
|
47
|
+
// Fetch bucket credentials
|
|
48
|
+
const resources = await tui.spinner({
|
|
49
|
+
message: `Fetching credentials for ${args.name}`,
|
|
50
|
+
clearOnSuccess: true,
|
|
51
|
+
callback: async () => {
|
|
52
|
+
return listResources(catalystClient, orgId, region);
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const bucket = resources.s3.find((s3) => s3.bucket_name === args.name);
|
|
57
|
+
|
|
58
|
+
if (!bucket) {
|
|
59
|
+
tui.fatal(`Storage bucket '${args.name}' not found`, ErrorCode.RESOURCE_NOT_FOUND);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (!bucket.access_key || !bucket.secret_key || !bucket.endpoint) {
|
|
63
|
+
tui.fatal(
|
|
64
|
+
`Storage bucket '${args.name}' is missing credentials`,
|
|
65
|
+
ErrorCode.CONFIG_INVALID
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Read file content
|
|
70
|
+
let fileContent: Buffer;
|
|
71
|
+
let actualFilename: string;
|
|
72
|
+
|
|
73
|
+
if (args.filename === '-') {
|
|
74
|
+
// Read from STDIN
|
|
75
|
+
const chunks: Buffer[] = [];
|
|
76
|
+
for await (const chunk of Bun.stdin.stream()) {
|
|
77
|
+
chunks.push(Buffer.from(chunk));
|
|
78
|
+
}
|
|
79
|
+
fileContent = Buffer.concat(chunks);
|
|
80
|
+
actualFilename = 'stdin';
|
|
81
|
+
} else {
|
|
82
|
+
// Read from file
|
|
83
|
+
const file = Bun.file(args.filename);
|
|
84
|
+
if (!(await file.exists())) {
|
|
85
|
+
tui.fatal(`File not found: ${args.filename}`, ErrorCode.FILE_NOT_FOUND);
|
|
86
|
+
}
|
|
87
|
+
fileContent = Buffer.from(await file.arrayBuffer());
|
|
88
|
+
actualFilename = basename(args.filename);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Auto-detect content type
|
|
92
|
+
let contentType = opts.contentType;
|
|
93
|
+
if (!contentType && args.filename !== '-') {
|
|
94
|
+
const filename = basename(args.filename);
|
|
95
|
+
const dotIndex = filename.lastIndexOf('.');
|
|
96
|
+
const ext = dotIndex > 0 ? filename.substring(dotIndex + 1).toLowerCase() : undefined;
|
|
97
|
+
const mimeTypes: Record<string, string> = {
|
|
98
|
+
txt: 'text/plain',
|
|
99
|
+
html: 'text/html',
|
|
100
|
+
css: 'text/css',
|
|
101
|
+
yaml: 'application/x-yaml',
|
|
102
|
+
yml: 'application/x-yaml',
|
|
103
|
+
js: 'application/javascript',
|
|
104
|
+
json: 'application/json',
|
|
105
|
+
xml: 'application/xml',
|
|
106
|
+
pdf: 'application/pdf',
|
|
107
|
+
zip: 'application/zip',
|
|
108
|
+
jpg: 'image/jpeg',
|
|
109
|
+
jpeg: 'image/jpeg',
|
|
110
|
+
png: 'image/png',
|
|
111
|
+
gif: 'image/gif',
|
|
112
|
+
svg: 'image/svg+xml',
|
|
113
|
+
mp4: 'video/mp4',
|
|
114
|
+
mp3: 'audio/mpeg',
|
|
115
|
+
};
|
|
116
|
+
contentType = ext ? mimeTypes[ext] : 'application/octet-stream';
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Upload using Bun.s3
|
|
120
|
+
const s3Client = createS3Client({
|
|
121
|
+
endpoint: bucket.endpoint,
|
|
122
|
+
access_key: bucket.access_key,
|
|
123
|
+
secret_key: bucket.secret_key,
|
|
124
|
+
region: bucket.region,
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
await tui.spinner({
|
|
128
|
+
message: `Uploading ${actualFilename} to ${args.name}`,
|
|
129
|
+
clearOnSuccess: true,
|
|
130
|
+
callback: async () => {
|
|
131
|
+
await s3Client.write(actualFilename, fileContent, {
|
|
132
|
+
type: contentType,
|
|
133
|
+
});
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
if (!options.json) {
|
|
138
|
+
tui.success(
|
|
139
|
+
`Uploaded ${tui.bold(actualFilename)} to ${tui.bold(args.name)} (${fileContent.length} bytes)`
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return {
|
|
144
|
+
success: true,
|
|
145
|
+
bucket: args.name,
|
|
146
|
+
filename: actualFilename,
|
|
147
|
+
size: fileContent.length,
|
|
148
|
+
};
|
|
149
|
+
},
|
|
150
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { S3Client } from 'bun';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Creates an S3Client configured for Agentuity storage buckets
|
|
5
|
+
*
|
|
6
|
+
* Agentuity provides bucket-specific endpoints in virtual-hosted-style format.
|
|
7
|
+
* The endpoint is already bucket-specific (e.g., bucket-name.agentuity.run),
|
|
8
|
+
* so we use virtualHostedStyle: true WITHOUT passing a bucket parameter.
|
|
9
|
+
*
|
|
10
|
+
* @param bucket - Bucket configuration with endpoint, credentials, and region
|
|
11
|
+
* @returns Configured S3Client instance
|
|
12
|
+
*/
|
|
13
|
+
export function createS3Client(bucket: {
|
|
14
|
+
endpoint: string;
|
|
15
|
+
access_key: string;
|
|
16
|
+
secret_key: string;
|
|
17
|
+
region?: string | null;
|
|
18
|
+
}): S3Client {
|
|
19
|
+
return new S3Client({
|
|
20
|
+
endpoint: bucket.endpoint.startsWith('http') ? bucket.endpoint : `https://${bucket.endpoint}`,
|
|
21
|
+
accessKeyId: bucket.access_key,
|
|
22
|
+
secretAccessKey: bucket.secret_key,
|
|
23
|
+
region: bucket.region || 'auto',
|
|
24
|
+
virtualHostedStyle: true,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createCommand } from '../../../types';
|
|
3
|
+
import * as tui from '../../../tui';
|
|
4
|
+
import { createStorageAdapter } from './util';
|
|
5
|
+
import { getCommand } from '../../../command-prefix';
|
|
6
|
+
|
|
7
|
+
const DeleteStreamResponseSchema = z.object({
|
|
8
|
+
id: z.string().describe('Stream ID'),
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export const deleteSubcommand = createCommand({
|
|
12
|
+
name: 'delete',
|
|
13
|
+
aliases: ['del', 'rm'],
|
|
14
|
+
description: 'Delete a stream by ID (soft delete)',
|
|
15
|
+
tags: ['destructive', 'deletes-resource', 'slow', 'requires-auth'],
|
|
16
|
+
idempotent: true,
|
|
17
|
+
requires: { auth: true, project: true },
|
|
18
|
+
examples: [
|
|
19
|
+
`${getCommand('stream delete stream-id-123')} - Delete a stream`,
|
|
20
|
+
`${getCommand('stream rm stream-id-456')} - Delete stream (using alias)`,
|
|
21
|
+
`${getCommand('stream del stream-id-789')} - Delete stream (using alias)`,
|
|
22
|
+
],
|
|
23
|
+
schema: {
|
|
24
|
+
args: z.object({
|
|
25
|
+
id: z.string().min(1).describe('the stream ID to delete'),
|
|
26
|
+
}),
|
|
27
|
+
response: DeleteStreamResponseSchema,
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
async handler(ctx) {
|
|
31
|
+
const { args, options } = ctx;
|
|
32
|
+
const started = Date.now();
|
|
33
|
+
const storage = await createStorageAdapter(ctx);
|
|
34
|
+
|
|
35
|
+
await storage.delete(args.id);
|
|
36
|
+
|
|
37
|
+
const durationMs = Date.now() - started;
|
|
38
|
+
|
|
39
|
+
if (!options.json) {
|
|
40
|
+
tui.success(`deleted stream ${args.id} in ${durationMs.toFixed(1)}ms`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
id: args.id,
|
|
45
|
+
};
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
export default deleteSubcommand;
|