@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.
- 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/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.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.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/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 +4 -2
- 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/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/tui.d.ts +2 -1
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +3 -0
- package/dist/tui.js.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +3 -3
- package/src/cli.ts +15 -1
- package/src/cmd/ai/capabilities/show.ts +11 -4
- 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/env/get.ts +2 -3
- package/src/cmd/cloud/env/list.ts +1 -2
- package/src/cmd/cloud/index.ts +5 -2
- package/src/cmd/cloud/secret/get.ts +2 -3
- package/src/cmd/cloud/secret/list.ts +1 -2
- 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/tui.ts +4 -0
- package/src/version.ts +1 -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/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 → db}/delete.d.ts +0 -0
- /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
|
+
});
|
package/src/cmd/cloud/env/get.ts
CHANGED
|
@@ -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 {
|
package/src/cmd/cloud/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createCommand } from '../../types';
|
|
2
2
|
import { deploySubcommand } from './deploy';
|
|
3
|
-
import {
|
|
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
|
-
|
|
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
|
+
});
|