@agentuity/cli 0.0.59 → 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 (125) 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/cloud/db/create.d.ts +2 -0
  8. package/dist/cmd/cloud/db/create.d.ts.map +1 -0
  9. package/dist/cmd/cloud/db/create.js +68 -0
  10. package/dist/cmd/cloud/db/create.js.map +1 -0
  11. package/dist/cmd/cloud/db/delete.d.ts.map +1 -0
  12. package/dist/cmd/cloud/db/delete.js +106 -0
  13. package/dist/cmd/cloud/db/delete.js.map +1 -0
  14. package/dist/cmd/cloud/db/get.d.ts +2 -0
  15. package/dist/cmd/cloud/db/get.d.ts.map +1 -0
  16. package/dist/cmd/cloud/db/get.js +66 -0
  17. package/dist/cmd/cloud/db/get.js.map +1 -0
  18. package/dist/cmd/cloud/db/index.d.ts +2 -0
  19. package/dist/cmd/cloud/db/index.d.ts.map +1 -0
  20. package/dist/cmd/cloud/db/index.js +14 -0
  21. package/dist/cmd/cloud/db/index.js.map +1 -0
  22. package/dist/cmd/cloud/db/list.d.ts.map +1 -0
  23. package/dist/cmd/cloud/db/list.js +75 -0
  24. package/dist/cmd/cloud/db/list.js.map +1 -0
  25. package/dist/cmd/cloud/db/sql.d.ts +2 -0
  26. package/dist/cmd/cloud/db/sql.d.ts.map +1 -0
  27. package/dist/cmd/cloud/db/sql.js +102 -0
  28. package/dist/cmd/cloud/db/sql.js.map +1 -0
  29. package/dist/cmd/cloud/env/get.d.ts.map +1 -1
  30. package/dist/cmd/cloud/env/get.js +2 -3
  31. package/dist/cmd/cloud/env/get.js.map +1 -1
  32. package/dist/cmd/cloud/env/list.d.ts.map +1 -1
  33. package/dist/cmd/cloud/env/list.js +1 -2
  34. package/dist/cmd/cloud/env/list.js.map +1 -1
  35. package/dist/cmd/cloud/index.d.ts.map +1 -1
  36. package/dist/cmd/cloud/index.js +4 -2
  37. package/dist/cmd/cloud/index.js.map +1 -1
  38. package/dist/cmd/cloud/secret/get.d.ts.map +1 -1
  39. package/dist/cmd/cloud/secret/get.js +2 -3
  40. package/dist/cmd/cloud/secret/get.js.map +1 -1
  41. package/dist/cmd/cloud/secret/list.d.ts.map +1 -1
  42. package/dist/cmd/cloud/secret/list.js +1 -2
  43. package/dist/cmd/cloud/secret/list.js.map +1 -1
  44. package/dist/cmd/cloud/storage/create.d.ts +2 -0
  45. package/dist/cmd/cloud/storage/create.d.ts.map +1 -0
  46. package/dist/cmd/cloud/storage/create.js +61 -0
  47. package/dist/cmd/cloud/storage/create.js.map +1 -0
  48. package/dist/cmd/cloud/storage/delete.d.ts +2 -0
  49. package/dist/cmd/cloud/storage/delete.d.ts.map +1 -0
  50. package/dist/cmd/cloud/storage/delete.js +167 -0
  51. package/dist/cmd/cloud/storage/delete.js.map +1 -0
  52. package/dist/cmd/cloud/storage/download.d.ts +2 -0
  53. package/dist/cmd/cloud/storage/download.d.ts.map +1 -0
  54. package/dist/cmd/cloud/storage/download.js +131 -0
  55. package/dist/cmd/cloud/storage/download.js.map +1 -0
  56. package/dist/cmd/cloud/storage/get.d.ts +2 -0
  57. package/dist/cmd/cloud/storage/get.d.ts.map +1 -0
  58. package/dist/cmd/cloud/storage/get.js +86 -0
  59. package/dist/cmd/cloud/storage/get.js.map +1 -0
  60. package/dist/cmd/cloud/storage/index.d.ts +2 -0
  61. package/dist/cmd/cloud/storage/index.d.ts.map +1 -0
  62. package/dist/cmd/cloud/storage/index.js +22 -0
  63. package/dist/cmd/cloud/storage/index.js.map +1 -0
  64. package/dist/cmd/cloud/storage/list.d.ts +2 -0
  65. package/dist/cmd/cloud/storage/list.d.ts.map +1 -0
  66. package/dist/cmd/cloud/storage/list.js +170 -0
  67. package/dist/cmd/cloud/storage/list.js.map +1 -0
  68. package/dist/cmd/cloud/storage/upload.d.ts +2 -0
  69. package/dist/cmd/cloud/storage/upload.d.ts.map +1 -0
  70. package/dist/cmd/cloud/storage/upload.js +133 -0
  71. package/dist/cmd/cloud/storage/upload.js.map +1 -0
  72. package/dist/cmd/cloud/storage/utils.d.ts +18 -0
  73. package/dist/cmd/cloud/storage/utils.d.ts.map +1 -0
  74. package/dist/cmd/cloud/storage/utils.js +21 -0
  75. package/dist/cmd/cloud/storage/utils.js.map +1 -0
  76. package/dist/tui.d.ts +2 -1
  77. package/dist/tui.d.ts.map +1 -1
  78. package/dist/tui.js +3 -0
  79. package/dist/tui.js.map +1 -1
  80. package/dist/version.js +1 -1
  81. package/dist/version.js.map +1 -1
  82. package/package.json +3 -3
  83. package/src/cli.ts +15 -1
  84. package/src/cmd/ai/capabilities/show.ts +11 -4
  85. package/src/cmd/cloud/db/create.ts +72 -0
  86. package/src/cmd/cloud/db/delete.ts +118 -0
  87. package/src/cmd/cloud/db/get.ts +75 -0
  88. package/src/cmd/cloud/db/index.ts +14 -0
  89. package/src/cmd/cloud/db/list.ts +83 -0
  90. package/src/cmd/cloud/db/sql.ts +125 -0
  91. package/src/cmd/cloud/env/get.ts +2 -3
  92. package/src/cmd/cloud/env/list.ts +1 -2
  93. package/src/cmd/cloud/index.ts +5 -2
  94. package/src/cmd/cloud/secret/get.ts +2 -3
  95. package/src/cmd/cloud/secret/list.ts +1 -2
  96. package/src/cmd/cloud/storage/create.ts +65 -0
  97. package/src/cmd/cloud/storage/delete.ts +195 -0
  98. package/src/cmd/cloud/storage/download.ts +154 -0
  99. package/src/cmd/cloud/storage/get.ts +97 -0
  100. package/src/cmd/cloud/storage/index.ts +22 -0
  101. package/src/cmd/cloud/storage/list.ts +197 -0
  102. package/src/cmd/cloud/storage/upload.ts +150 -0
  103. package/src/cmd/cloud/storage/utils.ts +26 -0
  104. package/src/tui.ts +4 -0
  105. package/src/version.ts +1 -1
  106. package/dist/cmd/cloud/resource/add.d.ts +0 -2
  107. package/dist/cmd/cloud/resource/add.d.ts.map +0 -1
  108. package/dist/cmd/cloud/resource/add.js +0 -70
  109. package/dist/cmd/cloud/resource/add.js.map +0 -1
  110. package/dist/cmd/cloud/resource/delete.d.ts.map +0 -1
  111. package/dist/cmd/cloud/resource/delete.js +0 -126
  112. package/dist/cmd/cloud/resource/delete.js.map +0 -1
  113. package/dist/cmd/cloud/resource/index.d.ts +0 -2
  114. package/dist/cmd/cloud/resource/index.d.ts.map +0 -1
  115. package/dist/cmd/cloud/resource/index.js +0 -12
  116. package/dist/cmd/cloud/resource/index.js.map +0 -1
  117. package/dist/cmd/cloud/resource/list.d.ts.map +0 -1
  118. package/dist/cmd/cloud/resource/list.js +0 -100
  119. package/dist/cmd/cloud/resource/list.js.map +0 -1
  120. package/src/cmd/cloud/resource/add.ts +0 -75
  121. package/src/cmd/cloud/resource/delete.ts +0 -141
  122. package/src/cmd/cloud/resource/index.ts +0 -12
  123. package/src/cmd/cloud/resource/list.ts +0 -105
  124. /package/dist/cmd/cloud/{resource → db}/delete.d.ts +0 -0
  125. /package/dist/cmd/cloud/{resource → db}/list.d.ts +0 -0
@@ -0,0 +1,118 @@
1
+ import { z } from 'zod';
2
+ import { listResources, deleteResources } from '@agentuity/server';
3
+ import enquirer from 'enquirer';
4
+ import { createSubcommand } from '../../../types';
5
+ import * as tui from '../../../tui';
6
+ import { getCatalystAPIClient } from '../../../config';
7
+ import { getCommand } from '../../../command-prefix';
8
+ import { isDryRunMode, outputDryRun } from '../../../explain';
9
+
10
+ export const deleteSubcommand = createSubcommand({
11
+ name: 'delete',
12
+ aliases: ['rm', 'del'],
13
+ description: 'Delete a database resource',
14
+ tags: ['destructive', 'deletes-resource', 'slow', 'requires-auth', 'requires-deployment'],
15
+ idempotent: false,
16
+ requires: { auth: true, org: true, region: true },
17
+ examples: [
18
+ getCommand('cloud db delete my-database'),
19
+ getCommand('cloud db rm my-database'),
20
+ getCommand('cloud db delete'),
21
+ getCommand('--dry-run cloud db delete my-database'),
22
+ ],
23
+ schema: {
24
+ args: z.object({
25
+ name: z.string().optional().describe('Database name to delete'),
26
+ }),
27
+ options: z.object({
28
+ confirm: z.boolean().optional().describe('Skip confirmation prompts'),
29
+ }),
30
+ response: z.object({
31
+ success: z.boolean().describe('Whether deletion succeeded'),
32
+ name: z.string().describe('Deleted database name'),
33
+ }),
34
+ },
35
+
36
+ async handler(ctx) {
37
+ const { logger, args, opts, config, orgId, region, auth, options } = ctx;
38
+
39
+ const catalystClient = getCatalystAPIClient(config, logger, auth);
40
+
41
+ let dbName = args.name;
42
+
43
+ if (!dbName) {
44
+ const resources = await tui.spinner({
45
+ message: `Fetching databases for ${orgId} in ${region}`,
46
+ clearOnSuccess: true,
47
+ callback: async () => {
48
+ return listResources(catalystClient, orgId, region!);
49
+ },
50
+ });
51
+
52
+ if (resources.db.length === 0) {
53
+ tui.info('No databases found to delete');
54
+ return { success: false, name: '' };
55
+ }
56
+
57
+ const response = await enquirer.prompt<{ db: string }>({
58
+ type: 'select',
59
+ name: 'db',
60
+ message: 'Select database to delete:',
61
+ choices: resources.db.map((db) => ({
62
+ name: db.name,
63
+ message: db.name,
64
+ })),
65
+ });
66
+
67
+ dbName = response.db;
68
+ }
69
+
70
+ // Handle dry-run mode
71
+ if (isDryRunMode(options)) {
72
+ outputDryRun(`Would delete database: ${dbName}`, options);
73
+ if (!options.json) {
74
+ tui.newline();
75
+ tui.info('[DRY RUN] Database deletion skipped');
76
+ }
77
+ return {
78
+ success: false,
79
+ name: dbName,
80
+ };
81
+ }
82
+
83
+ if (!opts.confirm) {
84
+ tui.warning(`You are about to delete database: ${tui.bold(dbName)}`);
85
+
86
+ const confirm = await enquirer.prompt<{ confirm: boolean }>({
87
+ type: 'confirm',
88
+ name: 'confirm',
89
+ message: 'Are you sure you want to delete this database?',
90
+ initial: false,
91
+ });
92
+
93
+ if (!confirm.confirm) {
94
+ tui.info('Deletion cancelled');
95
+ return { success: false, name: dbName };
96
+ }
97
+ }
98
+
99
+ const deleted = await tui.spinner({
100
+ message: `Deleting database ${dbName}`,
101
+ clearOnSuccess: true,
102
+ callback: async () => {
103
+ return deleteResources(catalystClient, orgId, region!, [{ type: 'db', name: dbName }]);
104
+ },
105
+ });
106
+
107
+ if (deleted.length > 0) {
108
+ tui.success(`Deleted database: ${tui.bold(deleted[0])}`);
109
+ return {
110
+ success: true,
111
+ name: deleted[0],
112
+ };
113
+ } else {
114
+ tui.error('Failed to delete database');
115
+ return { success: false, name: dbName };
116
+ }
117
+ },
118
+ });
@@ -0,0 +1,75 @@
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 DBGetResponseSchema = z.object({
10
+ name: z.string().describe('Database name'),
11
+ url: z.string().optional().describe('Database connection URL'),
12
+ });
13
+
14
+ export const getSubcommand = createSubcommand({
15
+ name: 'get',
16
+ aliases: ['show'],
17
+ description: 'Show details about a specific database',
18
+ tags: ['read-only', 'fast', 'requires-auth'],
19
+ requires: { auth: true, org: true, region: true },
20
+ idempotent: true,
21
+ examples: [
22
+ `${getCommand('cloud db get')} my-database`,
23
+ `${getCommand('cloud db show')} my-database`,
24
+ `${getCommand('cloud db get')} my-database --show-credentials`,
25
+ ],
26
+ schema: {
27
+ args: z.object({
28
+ name: z.string().describe('Database name'),
29
+ }),
30
+ options: z.object({
31
+ showCredentials: z
32
+ .boolean()
33
+ .optional()
34
+ .describe('Show credentials in plain text (default: masked in terminal, unmasked in JSON)'),
35
+ }),
36
+ response: DBGetResponseSchema,
37
+ },
38
+
39
+ async handler(ctx) {
40
+ const { logger, args, opts, options, orgId, region, config, auth } = ctx;
41
+
42
+ const catalystClient = getCatalystAPIClient(config, logger, auth);
43
+
44
+ const resources = await tui.spinner({
45
+ message: `Fetching database ${args.name}`,
46
+ clearOnSuccess: true,
47
+ callback: async () => {
48
+ return listResources(catalystClient, orgId, region);
49
+ },
50
+ });
51
+
52
+ const db = resources.db.find((d) => d.name === args.name);
53
+
54
+ if (!db) {
55
+ tui.fatal(`Database '${args.name}' not found`, ErrorCode.RESOURCE_NOT_FOUND);
56
+ }
57
+
58
+ // Mask credentials in terminal output by default, unless --show-credentials is passed
59
+ const shouldShowCredentials = opts.showCredentials === true;
60
+ const shouldMask = !options.json && !shouldShowCredentials;
61
+
62
+ if (!options.json) {
63
+ console.log(tui.bold('Name: ') + db.name);
64
+ if (db.url) {
65
+ const displayUrl = shouldMask ? tui.maskSecret(db.url) : db.url;
66
+ console.log(tui.bold('URL: ') + displayUrl);
67
+ }
68
+ }
69
+
70
+ return {
71
+ name: db.name,
72
+ url: db.url ?? undefined,
73
+ };
74
+ },
75
+ });
@@ -0,0 +1,14 @@
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 { sqlSubcommand } from './sql';
7
+
8
+ export const dbCommand = createCommand({
9
+ name: 'db',
10
+ aliases: ['database'],
11
+ description: 'Manage database resources',
12
+ tags: ['slow', 'requires-auth', 'requires-deployment'],
13
+ subcommands: [createSubcommand, listSubcommand, getSubcommand, deleteSubcommand, sqlSubcommand],
14
+ });
@@ -0,0 +1,83 @@
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
+
8
+ const DBListResponseSchema = z.object({
9
+ databases: z
10
+ .array(
11
+ z.object({
12
+ name: z.string().describe('Database name'),
13
+ url: z.string().optional().describe('Database connection URL'),
14
+ })
15
+ )
16
+ .describe('List of database resources'),
17
+ });
18
+
19
+ export const listSubcommand = createSubcommand({
20
+ name: 'list',
21
+ aliases: ['ls'],
22
+ description: 'List database resources',
23
+ tags: ['read-only', 'fast', 'requires-auth'],
24
+ requires: { auth: true, org: true, region: true },
25
+ idempotent: true,
26
+ examples: [
27
+ getCommand('cloud db list'),
28
+ getCommand('--json cloud db list'),
29
+ getCommand('cloud db ls'),
30
+ getCommand('cloud db list --show-credentials'),
31
+ ],
32
+ schema: {
33
+ options: z.object({
34
+ showCredentials: z
35
+ .boolean()
36
+ .optional()
37
+ .describe('Show credentials in plain text (default: masked in terminal, unmasked in JSON)'),
38
+ }),
39
+ response: DBListResponseSchema,
40
+ },
41
+
42
+ async handler(ctx) {
43
+ const { logger, opts, options, orgId, region, config, auth } = ctx;
44
+
45
+ const catalystClient = getCatalystAPIClient(config, logger, auth);
46
+
47
+ const resources = await tui.spinner({
48
+ message: `Fetching databases for ${orgId} in ${region}`,
49
+ clearOnSuccess: true,
50
+ callback: async () => {
51
+ return listResources(catalystClient, orgId, region);
52
+ },
53
+ });
54
+
55
+ // Mask credentials in terminal output by default, unless --show-credentials is passed
56
+ const shouldShowCredentials = opts.showCredentials === true;
57
+ const shouldMask = !options.json && !shouldShowCredentials;
58
+
59
+ if (!options.json) {
60
+ if (resources.db.length === 0) {
61
+ tui.info('No databases found');
62
+ } else {
63
+ tui.info(tui.bold('Databases'));
64
+ tui.newline();
65
+ for (const db of resources.db) {
66
+ console.log(tui.bold(db.name));
67
+ if (db.url) {
68
+ const displayUrl = shouldMask ? tui.maskSecret(db.url) : db.url;
69
+ console.log(` URL: ${tui.muted(displayUrl)}`);
70
+ }
71
+ tui.newline();
72
+ }
73
+ }
74
+ }
75
+
76
+ return {
77
+ databases: resources.db.map((db) => ({
78
+ name: db.name,
79
+ url: db.url ?? undefined,
80
+ })),
81
+ };
82
+ },
83
+ });
@@ -0,0 +1,125 @@
1
+ import { z } from 'zod';
2
+ import { SQL } from 'bun';
3
+ import { listResources, type ResourceList } 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
+
10
+ interface DatabaseResource {
11
+ name: string;
12
+ username?: string | null;
13
+ password?: string | null;
14
+ url?: string | null;
15
+ }
16
+
17
+ const DBSQLResponseSchema = z.object({
18
+ rows: z.array(z.record(z.string(), z.unknown())).describe('Query results'),
19
+ rowCount: z.number().describe('Number of rows returned'),
20
+ executionTime: z.number().optional().describe('Query execution time in ms'),
21
+ });
22
+
23
+ export const sqlSubcommand = createSubcommand({
24
+ name: 'sql',
25
+ aliases: ['exec', 'query'],
26
+ description: 'Execute SQL query on a database',
27
+ tags: ['slow', 'requires-auth'],
28
+ requires: { auth: true, org: true, region: true },
29
+ idempotent: false,
30
+ examples: [
31
+ `${getCommand('cloud db sql')} my-database "SELECT * FROM users LIMIT 10"`,
32
+ `${getCommand('cloud db exec')} my-database "SELECT COUNT(*) FROM orders" --json`,
33
+ `${getCommand('cloud db query')} my-database "SELECT * FROM products WHERE price > 100"`,
34
+ ],
35
+ schema: {
36
+ args: z.object({
37
+ name: z.string().describe('Database name'),
38
+ query: z.string().describe('SQL query to execute'),
39
+ }),
40
+ options: z.object({}),
41
+ response: DBSQLResponseSchema,
42
+ },
43
+
44
+ async handler(ctx) {
45
+ const { logger, args, options, orgId, region, config, auth } = ctx;
46
+
47
+ const catalystClient = getCatalystAPIClient(config, logger, auth);
48
+
49
+ const resources: ResourceList = await tui.spinner({
50
+ message: `Fetching database ${args.name}`,
51
+ clearOnSuccess: true,
52
+ callback: async () => {
53
+ return listResources(catalystClient, orgId, region);
54
+ },
55
+ });
56
+
57
+ const db: DatabaseResource | undefined = resources.db.find(
58
+ (d: DatabaseResource) => d.name === args.name
59
+ );
60
+
61
+ if (!db) {
62
+ tui.fatal(`Database '${args.name}' not found`, ErrorCode.RESOURCE_NOT_FOUND);
63
+ }
64
+
65
+ if (!db.url) {
66
+ tui.fatal(`Database '${args.name}' has no connection URL`, ErrorCode.RUNTIME_ERROR);
67
+ }
68
+
69
+ let database: SQL | undefined;
70
+ let rows: Record<string, unknown>[];
71
+ let executionTime: number | undefined;
72
+
73
+ try {
74
+ // Add sslmode=require if not already present in URL
75
+ let connectionUrl = db.url;
76
+ if (!connectionUrl.includes('sslmode=') && !connectionUrl.includes('ssl=')) {
77
+ const separator = connectionUrl.includes('?') ? '&' : '?';
78
+ connectionUrl = `${connectionUrl}${separator}sslmode=require`;
79
+ }
80
+
81
+ database = new SQL(connectionUrl);
82
+
83
+ const startTime = performance.now();
84
+ const result = await tui.spinner({
85
+ message: `Executing query on ${args.name}`,
86
+ clearOnSuccess: true,
87
+ callback: async () => {
88
+ return database!.unsafe(args.query);
89
+ },
90
+ });
91
+ executionTime = performance.now() - startTime;
92
+
93
+ rows = result;
94
+ } catch (error) {
95
+ const message = error instanceof Error ? error.message : String(error);
96
+ tui.fatal(`Query execution failed: ${message}`, ErrorCode.RUNTIME_ERROR);
97
+ } finally {
98
+ if (database) {
99
+ await database.close();
100
+ }
101
+ }
102
+
103
+ if (!options.json) {
104
+ if (rows.length === 0) {
105
+ tui.info('No rows returned');
106
+ } else {
107
+ if (process.stdout.isTTY) {
108
+ tui.newline();
109
+ tui.success(
110
+ `Query returned ${rows.length} row${rows.length !== 1 ? 's' : ''} (${executionTime?.toFixed(2)}ms):`
111
+ );
112
+ tui.newline();
113
+ }
114
+
115
+ tui.table(rows);
116
+ }
117
+ }
118
+
119
+ return {
120
+ rows,
121
+ rowCount: rows.length,
122
+ executionTime,
123
+ };
124
+ },
125
+ });
@@ -2,7 +2,6 @@ import { z } from 'zod';
2
2
  import { createSubcommand } from '../../../types';
3
3
  import * as tui from '../../../tui';
4
4
  import { projectGet } from '@agentuity/server';
5
- import { maskSecret } from '../../../env-util';
6
5
  import { getCommand } from '../../../command-prefix';
7
6
  import { ErrorCode } from '../../../errors';
8
7
 
@@ -50,13 +49,13 @@ export const getSubcommand = createSubcommand({
50
49
  // Display the value, masked if requested
51
50
  if (process.stdout.isTTY) {
52
51
  if (opts?.mask) {
53
- tui.success(`${args.key}=${maskSecret(value)}`);
52
+ tui.success(`${args.key}=${tui.maskSecret(value)}`);
54
53
  } else {
55
54
  tui.success(`${args.key}=${value}`);
56
55
  }
57
56
  } else {
58
57
  if (opts?.mask) {
59
- console.log(`${args.key}=${maskSecret(value)}`);
58
+ console.log(`${args.key}=${tui.maskSecret(value)}`);
60
59
  } else {
61
60
  console.log(`${args.key}=${value}`);
62
61
  }
@@ -2,7 +2,6 @@ import { z } from 'zod';
2
2
  import { createSubcommand } from '../../../types';
3
3
  import * as tui from '../../../tui';
4
4
  import { projectGet } from '@agentuity/server';
5
- import { maskSecret } from '../../../env-util';
6
5
  import { getCommand } from '../../../command-prefix';
7
6
 
8
7
  const EnvListResponseSchema = z.record(
@@ -55,7 +54,7 @@ export const listSubcommand = createSubcommand({
55
54
  const shouldMask = opts?.mask === true;
56
55
  for (const key of sortedKeys) {
57
56
  const value = env[key];
58
- const displayValue = shouldMask ? maskSecret(value) : value;
57
+ const displayValue = shouldMask ? tui.maskSecret(value) : value;
59
58
  if (process.stdout.isTTY) {
60
59
  console.log(`${tui.bold(key)}=${displayValue}`);
61
60
  } else {
@@ -1,6 +1,7 @@
1
1
  import { createCommand } from '../../types';
2
2
  import { deploySubcommand } from './deploy';
3
- import { resourceSubcommand } from './resource';
3
+ import { dbCommand } from './db';
4
+ import { storageCommand } from './storage';
4
5
  import { sessionCommand } from './session';
5
6
  import { sshSubcommand } from './ssh';
6
7
  import { scpSubcommand } from './scp';
@@ -14,6 +15,7 @@ import apikeyCommand from './apikey';
14
15
  import streamCommand from './stream';
15
16
  import vectorCommand from './vector';
16
17
 
18
+
17
19
  export const command = createCommand({
18
20
  name: 'cloud',
19
21
  description: 'Cloud related commands',
@@ -28,7 +30,8 @@ export const command = createCommand({
28
30
  envCommand,
29
31
  secretCommand,
30
32
  deploySubcommand,
31
- resourceSubcommand,
33
+ dbCommand,
34
+ storageCommand,
32
35
  sessionCommand,
33
36
  sshSubcommand,
34
37
  scpSubcommand,
@@ -2,7 +2,6 @@ import { z } from 'zod';
2
2
  import { createSubcommand } from '../../../types';
3
3
  import * as tui from '../../../tui';
4
4
  import { projectGet } from '@agentuity/server';
5
- import { maskSecret } from '../../../env-util';
6
5
  import { getCommand } from '../../../command-prefix';
7
6
  import { ErrorCode } from '../../../errors';
8
7
 
@@ -53,14 +52,14 @@ export const getSubcommand = createSubcommand({
53
52
  if (process.stdout.isTTY) {
54
53
  // Display the value, masked by default
55
54
  if (opts?.mask) {
56
- tui.success(`${args.key}=${maskSecret(value)}`);
55
+ tui.success(`${args.key}=${tui.maskSecret(value)}`);
57
56
  } else {
58
57
  tui.success(`${args.key}=${value}`);
59
58
  }
60
59
  } else {
61
60
  // Display the value, masked by default
62
61
  if (opts?.mask) {
63
- console.log(`${args.key}=${maskSecret(value)}`);
62
+ console.log(`${args.key}=${tui.maskSecret(value)}`);
64
63
  } else {
65
64
  console.log(`${args.key}=${value}`);
66
65
  }
@@ -2,7 +2,6 @@ import { z } from 'zod';
2
2
  import { createSubcommand } from '../../../types';
3
3
  import * as tui from '../../../tui';
4
4
  import { projectGet } from '@agentuity/server';
5
- import { maskSecret } from '../../../env-util';
6
5
  import { getCommand } from '../../../command-prefix';
7
6
 
8
7
  const SecretListResponseSchema = z.record(z.string(), z.string().describe('Secret value'));
@@ -52,7 +51,7 @@ export const listSubcommand = createSubcommand({
52
51
  const shouldMask = opts?.mask !== false;
53
52
  for (const key of sortedKeys) {
54
53
  const value = secrets[key];
55
- const displayValue = shouldMask ? maskSecret(value) : value;
54
+ const displayValue = shouldMask ? tui.maskSecret(value) : value;
56
55
  if (process.stdout.isTTY) {
57
56
  console.log(`${tui.bold(key)}=${displayValue}`);
58
57
  } else {
@@ -0,0 +1,65 @@
1
+ import { z } from 'zod';
2
+ import { createResources } from '@agentuity/server';
3
+ import { createSubcommand as defineSubcommand } from '../../../types';
4
+ import * as tui from '../../../tui';
5
+ import { getCatalystAPIClient } from '../../../config';
6
+ import { getCommand } from '../../../command-prefix';
7
+ import { isDryRunMode, outputDryRun } from '../../../explain';
8
+
9
+ export const createSubcommand = defineSubcommand({
10
+ name: 'create',
11
+ aliases: ['new'],
12
+ description: 'Create a new storage resource',
13
+ tags: ['mutating', 'creates-resource', 'slow', 'requires-auth', 'requires-deployment'],
14
+ idempotent: false,
15
+ requires: { auth: true, org: true, region: true },
16
+ examples: [
17
+ getCommand('cloud storage create'),
18
+ getCommand('cloud storage new'),
19
+ getCommand('--dry-run cloud storage create'),
20
+ ],
21
+ schema: {
22
+ response: z.object({
23
+ success: z.boolean().describe('Whether creation succeeded'),
24
+ name: z.string().describe('Created storage bucket name'),
25
+ }),
26
+ },
27
+
28
+ async handler(ctx) {
29
+ const { logger, orgId, region, config, auth, options } = ctx;
30
+
31
+ // Handle dry-run mode
32
+ if (isDryRunMode(options)) {
33
+ const message = `Would create storage bucket in region: ${region}`;
34
+ outputDryRun(message, options);
35
+ if (!options.json) {
36
+ tui.newline();
37
+ tui.info('[DRY RUN] Storage creation skipped');
38
+ }
39
+ return {
40
+ success: false,
41
+ name: 'dry-run-bucket',
42
+ };
43
+ }
44
+
45
+ const catalystClient = getCatalystAPIClient(config, logger, auth);
46
+
47
+ const created = await tui.spinner({
48
+ message: `Creating storage in ${region}`,
49
+ clearOnSuccess: true,
50
+ callback: async () => {
51
+ return createResources(catalystClient, orgId, region!, [{ type: 's3' }]);
52
+ },
53
+ });
54
+
55
+ if (created.length > 0) {
56
+ tui.success(`Created storage: ${tui.bold(created[0].name)}`);
57
+ return {
58
+ success: true,
59
+ name: created[0].name,
60
+ };
61
+ } else {
62
+ tui.fatal('Failed to create storage');
63
+ }
64
+ },
65
+ });