@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.
Files changed (258) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +14 -1
  3. package/dist/cli.js.map +1 -1
  4. package/dist/cmd/ai/capabilities/show.d.ts.map +1 -1
  5. package/dist/cmd/ai/capabilities/show.js +11 -4
  6. package/dist/cmd/ai/capabilities/show.js.map +1 -1
  7. package/dist/cmd/build/bundler.d.ts +1 -1
  8. package/dist/cmd/cloud/agent/get.d.ts +2 -0
  9. package/dist/cmd/cloud/agent/get.d.ts.map +1 -0
  10. package/dist/cmd/cloud/agent/get.js +97 -0
  11. package/dist/cmd/cloud/agent/get.js.map +1 -0
  12. package/dist/cmd/cloud/agent/index.d.ts +2 -0
  13. package/dist/cmd/cloud/agent/index.d.ts.map +1 -0
  14. package/dist/cmd/cloud/agent/index.js +11 -0
  15. package/dist/cmd/cloud/agent/index.js.map +1 -0
  16. package/dist/cmd/cloud/agent/list.d.ts.map +1 -0
  17. package/dist/cmd/cloud/agent/list.js +101 -0
  18. package/dist/cmd/cloud/agent/list.js.map +1 -0
  19. package/dist/cmd/cloud/agent/schema.d.ts +4 -0
  20. package/dist/cmd/cloud/agent/schema.d.ts.map +1 -0
  21. package/dist/cmd/cloud/agent/schema.js +22 -0
  22. package/dist/cmd/cloud/agent/schema.js.map +1 -0
  23. package/dist/cmd/cloud/apikey/create.d.ts +2 -0
  24. package/dist/cmd/cloud/apikey/create.d.ts.map +1 -0
  25. package/dist/cmd/cloud/apikey/create.js +100 -0
  26. package/dist/cmd/cloud/apikey/create.js.map +1 -0
  27. package/dist/cmd/cloud/apikey/delete.d.ts.map +1 -0
  28. package/dist/cmd/cloud/apikey/delete.js +55 -0
  29. package/dist/cmd/cloud/apikey/delete.js.map +1 -0
  30. package/dist/cmd/cloud/apikey/get.d.ts +2 -0
  31. package/dist/cmd/cloud/apikey/get.d.ts.map +1 -0
  32. package/dist/cmd/cloud/apikey/get.js +57 -0
  33. package/dist/cmd/cloud/apikey/get.js.map +1 -0
  34. package/dist/cmd/cloud/apikey/index.d.ts.map +1 -0
  35. package/dist/cmd/cloud/apikey/index.js +13 -0
  36. package/dist/cmd/cloud/apikey/index.js.map +1 -0
  37. package/dist/cmd/cloud/apikey/list.d.ts +2 -0
  38. package/dist/cmd/cloud/apikey/list.d.ts.map +1 -0
  39. package/dist/cmd/cloud/apikey/list.js +53 -0
  40. package/dist/cmd/cloud/apikey/list.js.map +1 -0
  41. package/dist/cmd/cloud/db/create.d.ts +2 -0
  42. package/dist/cmd/cloud/db/create.d.ts.map +1 -0
  43. package/dist/cmd/cloud/db/create.js +68 -0
  44. package/dist/cmd/cloud/db/create.js.map +1 -0
  45. package/dist/cmd/cloud/db/delete.d.ts +2 -0
  46. package/dist/cmd/cloud/db/delete.d.ts.map +1 -0
  47. package/dist/cmd/cloud/db/delete.js +106 -0
  48. package/dist/cmd/cloud/db/delete.js.map +1 -0
  49. package/dist/cmd/cloud/db/get.d.ts +2 -0
  50. package/dist/cmd/cloud/db/get.d.ts.map +1 -0
  51. package/dist/cmd/cloud/db/get.js +66 -0
  52. package/dist/cmd/cloud/db/get.js.map +1 -0
  53. package/dist/cmd/cloud/db/index.d.ts +2 -0
  54. package/dist/cmd/cloud/db/index.d.ts.map +1 -0
  55. package/dist/cmd/cloud/db/index.js +14 -0
  56. package/dist/cmd/cloud/db/index.js.map +1 -0
  57. package/dist/cmd/cloud/db/list.d.ts +2 -0
  58. package/dist/cmd/cloud/db/list.d.ts.map +1 -0
  59. package/dist/cmd/cloud/db/list.js +75 -0
  60. package/dist/cmd/cloud/db/list.js.map +1 -0
  61. package/dist/cmd/cloud/db/sql.d.ts +2 -0
  62. package/dist/cmd/cloud/db/sql.d.ts.map +1 -0
  63. package/dist/cmd/cloud/db/sql.js +102 -0
  64. package/dist/cmd/cloud/db/sql.js.map +1 -0
  65. package/dist/cmd/cloud/deployment/index.d.ts.map +1 -1
  66. package/dist/cmd/cloud/deployment/index.js +2 -0
  67. package/dist/cmd/cloud/deployment/index.js.map +1 -1
  68. package/dist/cmd/cloud/deployment/logs.d.ts +2 -0
  69. package/dist/cmd/cloud/deployment/logs.d.ts.map +1 -0
  70. package/dist/cmd/cloud/deployment/logs.js +70 -0
  71. package/dist/cmd/cloud/deployment/logs.js.map +1 -0
  72. package/dist/cmd/cloud/env/get.d.ts.map +1 -1
  73. package/dist/cmd/cloud/env/get.js +2 -3
  74. package/dist/cmd/cloud/env/get.js.map +1 -1
  75. package/dist/cmd/cloud/env/list.d.ts.map +1 -1
  76. package/dist/cmd/cloud/env/list.js +1 -2
  77. package/dist/cmd/cloud/env/list.js.map +1 -1
  78. package/dist/cmd/cloud/index.d.ts.map +1 -1
  79. package/dist/cmd/cloud/index.js +12 -4
  80. package/dist/cmd/cloud/index.js.map +1 -1
  81. package/dist/cmd/cloud/secret/get.d.ts.map +1 -1
  82. package/dist/cmd/cloud/secret/get.js +2 -3
  83. package/dist/cmd/cloud/secret/get.js.map +1 -1
  84. package/dist/cmd/cloud/secret/list.d.ts.map +1 -1
  85. package/dist/cmd/cloud/secret/list.js +1 -2
  86. package/dist/cmd/cloud/secret/list.js.map +1 -1
  87. package/dist/cmd/cloud/session/logs.d.ts.map +1 -1
  88. package/dist/cmd/cloud/session/logs.js +12 -9
  89. package/dist/cmd/cloud/session/logs.js.map +1 -1
  90. package/dist/cmd/cloud/storage/create.d.ts +2 -0
  91. package/dist/cmd/cloud/storage/create.d.ts.map +1 -0
  92. package/dist/cmd/cloud/storage/create.js +61 -0
  93. package/dist/cmd/cloud/storage/create.js.map +1 -0
  94. package/dist/cmd/cloud/storage/delete.d.ts +2 -0
  95. package/dist/cmd/cloud/storage/delete.d.ts.map +1 -0
  96. package/dist/cmd/cloud/storage/delete.js +167 -0
  97. package/dist/cmd/cloud/storage/delete.js.map +1 -0
  98. package/dist/cmd/cloud/storage/download.d.ts +2 -0
  99. package/dist/cmd/cloud/storage/download.d.ts.map +1 -0
  100. package/dist/cmd/cloud/storage/download.js +131 -0
  101. package/dist/cmd/cloud/storage/download.js.map +1 -0
  102. package/dist/cmd/cloud/storage/get.d.ts +2 -0
  103. package/dist/cmd/cloud/storage/get.d.ts.map +1 -0
  104. package/dist/cmd/cloud/storage/get.js +86 -0
  105. package/dist/cmd/cloud/storage/get.js.map +1 -0
  106. package/dist/cmd/cloud/storage/index.d.ts +2 -0
  107. package/dist/cmd/cloud/storage/index.d.ts.map +1 -0
  108. package/dist/cmd/cloud/storage/index.js +22 -0
  109. package/dist/cmd/cloud/storage/index.js.map +1 -0
  110. package/dist/cmd/cloud/storage/list.d.ts +2 -0
  111. package/dist/cmd/cloud/storage/list.d.ts.map +1 -0
  112. package/dist/cmd/cloud/storage/list.js +170 -0
  113. package/dist/cmd/cloud/storage/list.js.map +1 -0
  114. package/dist/cmd/cloud/storage/upload.d.ts +2 -0
  115. package/dist/cmd/cloud/storage/upload.d.ts.map +1 -0
  116. package/dist/cmd/cloud/storage/upload.js +133 -0
  117. package/dist/cmd/cloud/storage/upload.js.map +1 -0
  118. package/dist/cmd/cloud/storage/utils.d.ts +18 -0
  119. package/dist/cmd/cloud/storage/utils.d.ts.map +1 -0
  120. package/dist/cmd/cloud/storage/utils.js +21 -0
  121. package/dist/cmd/cloud/storage/utils.js.map +1 -0
  122. package/dist/cmd/cloud/stream/delete.d.ts +3 -0
  123. package/dist/cmd/cloud/stream/delete.d.ts.map +1 -0
  124. package/dist/cmd/cloud/stream/delete.js +42 -0
  125. package/dist/cmd/cloud/stream/delete.js.map +1 -0
  126. package/dist/cmd/cloud/stream/get.d.ts +3 -0
  127. package/dist/cmd/cloud/stream/get.d.ts.map +1 -0
  128. package/dist/cmd/cloud/stream/get.js +110 -0
  129. package/dist/cmd/cloud/stream/get.js.map +1 -0
  130. package/dist/cmd/cloud/stream/index.d.ts +3 -0
  131. package/dist/cmd/cloud/stream/index.d.ts.map +1 -0
  132. package/dist/cmd/cloud/stream/index.js +13 -0
  133. package/dist/cmd/cloud/stream/index.js.map +1 -0
  134. package/dist/cmd/cloud/stream/list.d.ts +3 -0
  135. package/dist/cmd/cloud/stream/list.d.ts.map +1 -0
  136. package/dist/cmd/cloud/stream/list.js +131 -0
  137. package/dist/cmd/cloud/stream/list.js.map +1 -0
  138. package/dist/cmd/cloud/stream/util.d.ts +8 -0
  139. package/dist/cmd/cloud/stream/util.d.ts.map +1 -0
  140. package/dist/cmd/cloud/stream/util.js +19 -0
  141. package/dist/cmd/cloud/stream/util.js.map +1 -0
  142. package/dist/cmd/cloud/vector/delete.d.ts +3 -0
  143. package/dist/cmd/cloud/vector/delete.d.ts.map +1 -0
  144. package/dist/cmd/cloud/vector/delete.js +90 -0
  145. package/dist/cmd/cloud/vector/delete.js.map +1 -0
  146. package/dist/cmd/cloud/vector/get.d.ts +3 -0
  147. package/dist/cmd/cloud/vector/get.d.ts.map +1 -0
  148. package/dist/cmd/cloud/vector/get.js +80 -0
  149. package/dist/cmd/cloud/vector/get.js.map +1 -0
  150. package/dist/cmd/cloud/vector/index.d.ts +3 -0
  151. package/dist/cmd/cloud/vector/index.d.ts.map +1 -0
  152. package/dist/cmd/cloud/vector/index.js +14 -0
  153. package/dist/cmd/cloud/vector/index.js.map +1 -0
  154. package/dist/cmd/cloud/vector/search.d.ts +3 -0
  155. package/dist/cmd/cloud/vector/search.d.ts.map +1 -0
  156. package/dist/cmd/cloud/vector/search.js +136 -0
  157. package/dist/cmd/cloud/vector/search.js.map +1 -0
  158. package/dist/cmd/cloud/vector/util.d.ts +8 -0
  159. package/dist/cmd/cloud/vector/util.d.ts.map +1 -0
  160. package/dist/cmd/cloud/vector/util.js +18 -0
  161. package/dist/cmd/cloud/vector/util.js.map +1 -0
  162. package/dist/cmd/dev/agents.d.ts.map +1 -1
  163. package/dist/cmd/dev/agents.js +3 -2
  164. package/dist/cmd/dev/agents.js.map +1 -1
  165. package/dist/cmd/dev/index.js +3 -3
  166. package/dist/cmd/dev/index.js.map +1 -1
  167. package/dist/cmd/index.d.ts.map +1 -1
  168. package/dist/cmd/index.js +38 -42
  169. package/dist/cmd/index.js.map +1 -1
  170. package/dist/schema-parser.d.ts.map +1 -1
  171. package/dist/schema-parser.js +3 -1
  172. package/dist/schema-parser.js.map +1 -1
  173. package/dist/tui.d.ts +12 -2
  174. package/dist/tui.d.ts.map +1 -1
  175. package/dist/tui.js +61 -31
  176. package/dist/tui.js.map +1 -1
  177. package/dist/utils/date.d.ts +14 -0
  178. package/dist/utils/date.d.ts.map +1 -0
  179. package/dist/utils/date.js +51 -0
  180. package/dist/utils/date.js.map +1 -0
  181. package/dist/version.js +1 -1
  182. package/dist/version.js.map +1 -1
  183. package/package.json +6 -6
  184. package/src/cli.ts +15 -1
  185. package/src/cmd/ai/capabilities/show.ts +11 -4
  186. package/src/cmd/cloud/agent/get.ts +105 -0
  187. package/src/cmd/cloud/agent/index.ts +11 -0
  188. package/src/cmd/cloud/agent/list.ts +107 -0
  189. package/src/cmd/cloud/agent/schema.ts +25 -0
  190. package/src/cmd/cloud/apikey/create.ts +114 -0
  191. package/src/cmd/cloud/apikey/delete.ts +66 -0
  192. package/src/cmd/cloud/apikey/get.ts +62 -0
  193. package/src/cmd/cloud/apikey/index.ts +13 -0
  194. package/src/cmd/cloud/apikey/list.ts +58 -0
  195. package/src/cmd/cloud/db/create.ts +72 -0
  196. package/src/cmd/cloud/db/delete.ts +118 -0
  197. package/src/cmd/cloud/db/get.ts +75 -0
  198. package/src/cmd/cloud/db/index.ts +14 -0
  199. package/src/cmd/cloud/db/list.ts +83 -0
  200. package/src/cmd/cloud/db/sql.ts +125 -0
  201. package/src/cmd/cloud/deployment/index.ts +2 -0
  202. package/src/cmd/cloud/deployment/logs.ts +75 -0
  203. package/src/cmd/cloud/env/get.ts +2 -3
  204. package/src/cmd/cloud/env/list.ts +1 -2
  205. package/src/cmd/cloud/index.ts +13 -4
  206. package/src/cmd/cloud/secret/get.ts +2 -3
  207. package/src/cmd/cloud/secret/list.ts +1 -2
  208. package/src/cmd/cloud/session/logs.ts +12 -11
  209. package/src/cmd/cloud/storage/create.ts +65 -0
  210. package/src/cmd/cloud/storage/delete.ts +195 -0
  211. package/src/cmd/cloud/storage/download.ts +154 -0
  212. package/src/cmd/cloud/storage/get.ts +97 -0
  213. package/src/cmd/cloud/storage/index.ts +22 -0
  214. package/src/cmd/cloud/storage/list.ts +197 -0
  215. package/src/cmd/cloud/storage/upload.ts +150 -0
  216. package/src/cmd/cloud/storage/utils.ts +26 -0
  217. package/src/cmd/cloud/stream/delete.ts +49 -0
  218. package/src/cmd/cloud/stream/get.ts +118 -0
  219. package/src/cmd/cloud/stream/index.ts +14 -0
  220. package/src/cmd/cloud/stream/list.ts +146 -0
  221. package/src/cmd/cloud/stream/util.ts +32 -0
  222. package/src/cmd/cloud/vector/delete.ts +105 -0
  223. package/src/cmd/cloud/vector/get.ts +94 -0
  224. package/src/cmd/cloud/vector/index.ts +15 -0
  225. package/src/cmd/cloud/vector/search.ts +156 -0
  226. package/src/cmd/cloud/vector/util.ts +28 -0
  227. package/src/cmd/dev/agents.ts +4 -3
  228. package/src/cmd/dev/index.ts +3 -3
  229. package/src/cmd/index.ts +38 -42
  230. package/src/schema-parser.ts +3 -1
  231. package/src/tui.ts +73 -36
  232. package/src/utils/date.ts +57 -0
  233. package/src/version.ts +1 -1
  234. package/dist/cmd/cloud/agents/index.d.ts.map +0 -1
  235. package/dist/cmd/cloud/agents/index.js +0 -133
  236. package/dist/cmd/cloud/agents/index.js.map +0 -1
  237. package/dist/cmd/cloud/resource/add.d.ts +0 -2
  238. package/dist/cmd/cloud/resource/add.d.ts.map +0 -1
  239. package/dist/cmd/cloud/resource/add.js +0 -70
  240. package/dist/cmd/cloud/resource/add.js.map +0 -1
  241. package/dist/cmd/cloud/resource/delete.d.ts.map +0 -1
  242. package/dist/cmd/cloud/resource/delete.js +0 -126
  243. package/dist/cmd/cloud/resource/delete.js.map +0 -1
  244. package/dist/cmd/cloud/resource/index.d.ts +0 -2
  245. package/dist/cmd/cloud/resource/index.d.ts.map +0 -1
  246. package/dist/cmd/cloud/resource/index.js +0 -12
  247. package/dist/cmd/cloud/resource/index.js.map +0 -1
  248. package/dist/cmd/cloud/resource/list.d.ts.map +0 -1
  249. package/dist/cmd/cloud/resource/list.js +0 -100
  250. package/dist/cmd/cloud/resource/list.js.map +0 -1
  251. package/src/cmd/cloud/agents/index.ts +0 -148
  252. package/src/cmd/cloud/resource/add.ts +0 -75
  253. package/src/cmd/cloud/resource/delete.ts +0 -141
  254. package/src/cmd/cloud/resource/index.ts +0 -12
  255. package/src/cmd/cloud/resource/list.ts +0 -105
  256. /package/dist/cmd/cloud/{resource → agent}/list.d.ts +0 -0
  257. /package/dist/cmd/cloud/{resource → apikey}/delete.d.ts +0 -0
  258. /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;