@agentuity/cli 0.0.63 → 0.0.65
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/cmd/build/ast.d.ts.map +1 -1
- package/dist/cmd/build/ast.js +70 -4
- package/dist/cmd/build/ast.js.map +1 -1
- package/dist/cmd/build/ast.test.js +186 -1
- package/dist/cmd/build/ast.test.js.map +1 -1
- package/dist/cmd/build/bundler.d.ts +2 -24
- package/dist/cmd/build/bundler.d.ts.map +1 -1
- package/dist/cmd/build/bundler.js +24 -41
- package/dist/cmd/build/bundler.js.map +1 -1
- package/dist/cmd/build/index.js +22 -23
- package/dist/cmd/build/index.js.map +1 -1
- package/dist/cmd/build/plugin.d.ts.map +1 -1
- package/dist/cmd/build/plugin.js +5 -4
- package/dist/cmd/build/plugin.js.map +1 -1
- package/dist/cmd/build/workbench-templates.d.ts +1 -1
- package/dist/cmd/build/workbench-templates.d.ts.map +1 -1
- package/dist/cmd/build/workbench-templates.js +6 -19
- package/dist/cmd/build/workbench-templates.js.map +1 -1
- package/dist/cmd/cloud/apikey/create.d.ts.map +1 -1
- package/dist/cmd/cloud/apikey/create.js +7 -16
- package/dist/cmd/cloud/apikey/create.js.map +1 -1
- package/dist/cmd/cloud/db/create.d.ts.map +1 -1
- package/dist/cmd/cloud/db/create.js +3 -2
- package/dist/cmd/cloud/db/create.js.map +1 -1
- package/dist/cmd/cloud/db/get.d.ts.map +1 -1
- package/dist/cmd/cloud/db/get.js +72 -3
- package/dist/cmd/cloud/db/get.js.map +1 -1
- package/dist/cmd/cloud/db/index.d.ts.map +1 -1
- package/dist/cmd/cloud/db/index.js +9 -1
- package/dist/cmd/cloud/db/index.js.map +1 -1
- package/dist/cmd/cloud/db/logs.d.ts +2 -0
- package/dist/cmd/cloud/db/logs.d.ts.map +1 -0
- package/dist/cmd/cloud/db/logs.js +150 -0
- package/dist/cmd/cloud/db/logs.js.map +1 -0
- package/dist/cmd/cloud/db/sql.d.ts.map +1 -1
- package/dist/cmd/cloud/db/sql.js +16 -51
- package/dist/cmd/cloud/db/sql.js.map +1 -1
- package/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.js +3 -2
- package/dist/cmd/cloud/deploy.js.map +1 -1
- package/dist/cmd/cloud/deployment/list.d.ts.map +1 -1
- package/dist/cmd/cloud/deployment/list.js +1 -1
- package/dist/cmd/cloud/deployment/list.js.map +1 -1
- package/dist/cmd/cloud/deployment/logs.d.ts.map +1 -1
- package/dist/cmd/cloud/deployment/logs.js +1 -1
- package/dist/cmd/cloud/deployment/logs.js.map +1 -1
- package/dist/cmd/cloud/deployment/remove.js +1 -1
- package/dist/cmd/cloud/deployment/remove.js.map +1 -1
- package/dist/cmd/cloud/deployment/rollback.js +1 -1
- package/dist/cmd/cloud/deployment/rollback.js.map +1 -1
- package/dist/cmd/cloud/deployment/show.js +1 -1
- package/dist/cmd/cloud/deployment/show.js.map +1 -1
- package/dist/cmd/cloud/deployment/undeploy.js +1 -1
- package/dist/cmd/cloud/deployment/undeploy.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/util.js +1 -1
- package/dist/cmd/cloud/keyvalue/util.js.map +1 -1
- package/dist/cmd/cloud/objectstore/util.js +1 -1
- package/dist/cmd/cloud/objectstore/util.js.map +1 -1
- package/dist/cmd/cloud/session/get.d.ts.map +1 -1
- package/dist/cmd/cloud/session/get.js +1 -1
- package/dist/cmd/cloud/session/get.js.map +1 -1
- package/dist/cmd/cloud/session/list.d.ts.map +1 -1
- package/dist/cmd/cloud/session/list.js +1 -1
- package/dist/cmd/cloud/session/list.js.map +1 -1
- package/dist/cmd/cloud/session/logs.d.ts.map +1 -1
- package/dist/cmd/cloud/session/logs.js +1 -1
- package/dist/cmd/cloud/session/logs.js.map +1 -1
- package/dist/cmd/cloud/stream/util.d.ts.map +1 -1
- package/dist/cmd/cloud/stream/util.js +2 -1
- package/dist/cmd/cloud/stream/util.js.map +1 -1
- package/dist/cmd/cloud/thread/delete.d.ts.map +1 -1
- package/dist/cmd/cloud/thread/delete.js +1 -1
- package/dist/cmd/cloud/thread/delete.js.map +1 -1
- package/dist/cmd/cloud/thread/get.d.ts.map +1 -1
- package/dist/cmd/cloud/thread/get.js +1 -1
- package/dist/cmd/cloud/thread/get.js.map +1 -1
- package/dist/cmd/cloud/thread/list.d.ts.map +1 -1
- package/dist/cmd/cloud/thread/list.js +1 -1
- package/dist/cmd/cloud/thread/list.js.map +1 -1
- package/dist/cmd/cloud/vector/util.js +1 -1
- package/dist/cmd/cloud/vector/util.js.map +1 -1
- package/dist/cmd/dev/index.d.ts.map +1 -1
- package/dist/cmd/dev/index.js +34 -1
- package/dist/cmd/dev/index.js.map +1 -1
- package/dist/cmd/profile/current.d.ts +3 -0
- package/dist/cmd/profile/current.d.ts.map +1 -0
- package/dist/cmd/profile/current.js +27 -0
- package/dist/cmd/profile/current.js.map +1 -0
- package/dist/cmd/profile/index.d.ts.map +1 -1
- package/dist/cmd/profile/index.js +9 -1
- package/dist/cmd/profile/index.js.map +1 -1
- package/dist/cmd/profile/show.d.ts.map +1 -1
- package/dist/cmd/profile/show.js +0 -1
- package/dist/cmd/profile/show.js.map +1 -1
- package/dist/command-prefix.d.ts.map +1 -1
- package/dist/command-prefix.js +2 -1
- package/dist/command-prefix.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +18 -5
- package/dist/config.js.map +1 -1
- package/dist/download.js +1 -1
- package/dist/download.js.map +1 -1
- package/dist/env-util.d.ts.map +1 -1
- package/dist/env-util.js +3 -0
- package/dist/env-util.js.map +1 -1
- package/dist/schemas/deploy.d.ts +24 -0
- package/dist/schemas/deploy.d.ts.map +1 -0
- package/dist/schemas/deploy.js +26 -0
- package/dist/schemas/deploy.js.map +1 -0
- package/dist/utils/workbench-notify.d.ts +29 -0
- package/dist/utils/workbench-notify.d.ts.map +1 -0
- package/dist/utils/workbench-notify.js +56 -0
- package/dist/utils/workbench-notify.js.map +1 -0
- package/package.json +3 -3
- package/src/cmd/build/ast.test.ts +246 -1
- package/src/cmd/build/ast.ts +88 -4
- package/src/cmd/build/bundler.ts +27 -44
- package/src/cmd/build/index.ts +23 -23
- package/src/cmd/build/plugin.ts +5 -4
- package/src/cmd/build/workbench-templates.ts +6 -21
- package/src/cmd/cloud/apikey/create.ts +7 -15
- package/src/cmd/cloud/db/create.ts +3 -2
- package/src/cmd/cloud/db/get.ts +85 -5
- package/src/cmd/cloud/db/index.ts +9 -1
- package/src/cmd/cloud/db/logs.ts +163 -0
- package/src/cmd/cloud/db/sql.ts +16 -66
- package/src/cmd/cloud/deploy.ts +3 -2
- package/src/cmd/cloud/deployment/list.ts +1 -4
- package/src/cmd/cloud/deployment/logs.ts +1 -4
- package/src/cmd/cloud/deployment/remove.ts +1 -1
- package/src/cmd/cloud/deployment/rollback.ts +1 -1
- package/src/cmd/cloud/deployment/show.ts +1 -1
- package/src/cmd/cloud/deployment/undeploy.ts +1 -1
- package/src/cmd/cloud/keyvalue/util.ts +1 -1
- package/src/cmd/cloud/objectstore/util.ts +1 -1
- package/src/cmd/cloud/session/get.ts +1 -4
- package/src/cmd/cloud/session/list.ts +1 -4
- package/src/cmd/cloud/session/logs.ts +1 -4
- package/src/cmd/cloud/stream/util.ts +4 -1
- package/src/cmd/cloud/thread/delete.ts +1 -4
- package/src/cmd/cloud/thread/get.ts +1 -4
- package/src/cmd/cloud/thread/list.ts +1 -4
- package/src/cmd/cloud/vector/util.ts +1 -1
- package/src/cmd/dev/index.ts +40 -1
- package/src/cmd/profile/current.ts +31 -0
- package/src/cmd/profile/index.ts +9 -1
- package/src/cmd/profile/show.ts +0 -1
- package/src/command-prefix.ts +4 -1
- package/src/config.ts +20 -5
- package/src/download.ts +1 -1
- package/src/env-util.ts +3 -0
- package/src/schemas/deploy.ts +28 -0
- package/src/utils/workbench-notify.ts +67 -0
package/src/cmd/build/index.ts
CHANGED
|
@@ -50,30 +50,30 @@ export const command = createCommand({
|
|
|
50
50
|
|
|
51
51
|
const env: Map<string, string> = new Map();
|
|
52
52
|
|
|
53
|
-
if (
|
|
54
|
-
|
|
55
|
-
env.set('AGENTUITY_TRANSPORT_URL', config.overrides.transport_url);
|
|
56
|
-
}
|
|
57
|
-
if (config?.overrides?.catalyst_url) {
|
|
58
|
-
env.set('AGENTUITY_CATALYST_URL', config.overrides.catalyst_url);
|
|
59
|
-
}
|
|
60
|
-
if (config?.overrides?.vector_url) {
|
|
61
|
-
env.set('AGENTUITY_VECTOR_URL', config.overrides.vector_url);
|
|
62
|
-
}
|
|
63
|
-
if (config?.overrides?.object_url) {
|
|
64
|
-
env.set('AGENTUITY_OBJECTSTORE_URL', config.overrides.object_url);
|
|
65
|
-
}
|
|
66
|
-
if (config?.overrides?.kv_url) {
|
|
67
|
-
env.set('AGENTUITY_KEYVALUE_URL', config.overrides.kv_url);
|
|
68
|
-
}
|
|
69
|
-
if (config?.overrides?.stream_url) {
|
|
70
|
-
env.set('AGENTUITY_STREAM_URL', config.overrides.stream_url);
|
|
71
|
-
}
|
|
72
|
-
if (project) {
|
|
73
|
-
env.set('AGENTUITY_CLOUD_ORG_ID', project.orgId);
|
|
74
|
-
env.set('AGENTUITY_CLOUD_PROJECT_ID', project.projectId);
|
|
75
|
-
}
|
|
53
|
+
if (config?.overrides?.transport_url) {
|
|
54
|
+
env.set('AGENTUITY_TRANSPORT_URL', config.overrides.transport_url);
|
|
76
55
|
}
|
|
56
|
+
if (config?.overrides?.catalyst_url) {
|
|
57
|
+
env.set('AGENTUITY_CATALYST_URL', config.overrides.catalyst_url);
|
|
58
|
+
}
|
|
59
|
+
if (config?.overrides?.vector_url) {
|
|
60
|
+
env.set('AGENTUITY_VECTOR_URL', config.overrides.vector_url);
|
|
61
|
+
}
|
|
62
|
+
if (config?.overrides?.object_url) {
|
|
63
|
+
env.set('AGENTUITY_OBJECTSTORE_URL', config.overrides.object_url);
|
|
64
|
+
}
|
|
65
|
+
if (config?.overrides?.kv_url) {
|
|
66
|
+
env.set('AGENTUITY_KEYVALUE_URL', config.overrides.kv_url);
|
|
67
|
+
}
|
|
68
|
+
if (config?.overrides?.stream_url) {
|
|
69
|
+
env.set('AGENTUITY_STREAM_URL', config.overrides.stream_url);
|
|
70
|
+
}
|
|
71
|
+
if (project) {
|
|
72
|
+
env.set('AGENTUITY_CLOUD_ORG_ID', project.orgId);
|
|
73
|
+
env.set('AGENTUITY_CLOUD_PROJECT_ID', project.projectId);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
ctx.logger.trace('setting env to %s', env);
|
|
77
77
|
|
|
78
78
|
await bundle({
|
|
79
79
|
rootDir: absoluteProjectDir,
|
package/src/cmd/build/plugin.ts
CHANGED
|
@@ -726,12 +726,13 @@ const AgentuityBundler: BunPlugin = {
|
|
|
726
726
|
// Generate lifecycle types if setup() is present in app.ts
|
|
727
727
|
await setupLifecycleTypes(rootDir, outDir, srcDir, logger);
|
|
728
728
|
|
|
729
|
-
// Only create the workbench
|
|
729
|
+
// Only create the workbench routes if workbench is actually configured
|
|
730
730
|
if (workbenchConfig) {
|
|
731
731
|
inserts.push(`await (async() => {
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
732
|
+
const { createWorkbenchRouter, getRouter } = await import('@agentuity/runtime');
|
|
733
|
+
const router = getRouter()!;
|
|
734
|
+
const workbenchRouter = createWorkbenchRouter();
|
|
735
|
+
router.route('/', workbenchRouter);
|
|
735
736
|
})();`);
|
|
736
737
|
}
|
|
737
738
|
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { encodeWorkbenchConfig, type WorkbenchConfig } from '@agentuity/core';
|
|
2
2
|
|
|
3
3
|
export function generateWorkbenchMainTsx(config: WorkbenchConfig): string {
|
|
4
|
-
const
|
|
5
|
-
|
|
4
|
+
const encodedConfig = encodeWorkbenchConfig(config);
|
|
6
5
|
return `// Generated workbench entry point
|
|
7
6
|
import React from 'react';
|
|
8
7
|
import { createRoot } from 'react-dom/client';
|
|
9
|
-
import {
|
|
10
|
-
import { createWorkbench, Workbench } from '@agentuity/workbench';
|
|
8
|
+
import { App } from '@agentuity/workbench';
|
|
11
9
|
import '@agentuity/workbench/styles';
|
|
12
10
|
|
|
13
11
|
// Root element
|
|
@@ -16,23 +14,10 @@ if (!rootElement) {
|
|
|
16
14
|
throw new Error('Root element not found');
|
|
17
15
|
}
|
|
18
16
|
|
|
19
|
-
//
|
|
20
|
-
const workbenchConfig = ${configString};
|
|
21
|
-
const workbench = createWorkbench(workbenchConfig);
|
|
22
|
-
|
|
23
|
-
function App() {
|
|
24
|
-
return (
|
|
25
|
-
<AgentuityProvider baseUrl={window.location.origin}>
|
|
26
|
-
<div className="min-h-screen bg-background text-foreground">
|
|
27
|
-
<Workbench workbench={workbench} />
|
|
28
|
-
</div>
|
|
29
|
-
</AgentuityProvider>
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Render the app
|
|
17
|
+
// Render the app (App has its own provider and config)
|
|
34
18
|
const root = createRoot(rootElement);
|
|
35
|
-
|
|
19
|
+
console.log('encodedConfig', '${encodedConfig}');
|
|
20
|
+
root.render(<App configBase64="${encodedConfig}" />);
|
|
36
21
|
`;
|
|
37
22
|
}
|
|
38
23
|
|
|
@@ -82,22 +82,14 @@ export const createSubcommand = createSubcommandHelper({
|
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
projectId: projectId,
|
|
92
|
-
orgId: orgId,
|
|
93
|
-
});
|
|
85
|
+
const result = await tui.spinner('Creating API key', () => {
|
|
86
|
+
return apikeyCreate(apiClient, {
|
|
87
|
+
name: opts.name,
|
|
88
|
+
expiresAt: expiresAt,
|
|
89
|
+
projectId: projectId,
|
|
90
|
+
orgId: orgId,
|
|
94
91
|
});
|
|
95
|
-
}
|
|
96
|
-
if (error instanceof Error) {
|
|
97
|
-
tui.fatal(error.message);
|
|
98
|
-
}
|
|
99
|
-
throw error;
|
|
100
|
-
}
|
|
92
|
+
});
|
|
101
93
|
|
|
102
94
|
if (!options.json) {
|
|
103
95
|
tui.newline();
|
|
@@ -22,7 +22,7 @@ export const createSubcommand = defineSubcommand({
|
|
|
22
22
|
],
|
|
23
23
|
schema: {
|
|
24
24
|
options: z.object({
|
|
25
|
-
name: z.string().optional().describe('Custom database name
|
|
25
|
+
name: z.string().optional().describe('Custom database name'),
|
|
26
26
|
}),
|
|
27
27
|
response: z.object({
|
|
28
28
|
success: z.boolean().describe('Whether creation succeeded'),
|
|
@@ -75,8 +75,9 @@ export const createSubcommand = defineSubcommand({
|
|
|
75
75
|
} catch (ex) {
|
|
76
76
|
if (ex instanceof APIError) {
|
|
77
77
|
if (ex.status === 409) {
|
|
78
|
+
const dbName = opts.name || 'auto-generated';
|
|
78
79
|
tui.fatal(
|
|
79
|
-
`database with the name "${
|
|
80
|
+
`database with the name "${dbName}" already exists. Use another name or don't specify --name for a unique name to be generated automatically.`,
|
|
80
81
|
ErrorCode.INVALID_ARGUMENT
|
|
81
82
|
);
|
|
82
83
|
}
|
package/src/cmd/cloud/db/get.ts
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { listResources } from '@agentuity/server';
|
|
2
|
+
import { listResources, dbTables, generateCreateTableSQL } from '@agentuity/server';
|
|
3
3
|
import { createSubcommand } from '../../../types';
|
|
4
4
|
import * as tui from '../../../tui';
|
|
5
5
|
import { getCatalystAPIClient } from '../../../config';
|
|
6
6
|
import { getCommand } from '../../../command-prefix';
|
|
7
7
|
import { ErrorCode } from '../../../errors';
|
|
8
8
|
|
|
9
|
-
const DBGetResponseSchema = z
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
const DBGetResponseSchema = z
|
|
10
|
+
.object({
|
|
11
|
+
name: z.string().describe('Database name'),
|
|
12
|
+
url: z.string().optional().describe('Database connection URL'),
|
|
13
|
+
})
|
|
14
|
+
.or(
|
|
15
|
+
z.object({
|
|
16
|
+
tables: z.union([z.array(z.string()), z.array(z.any())]).describe('Table information'),
|
|
17
|
+
})
|
|
18
|
+
);
|
|
13
19
|
|
|
14
20
|
export const getSubcommand = createSubcommand({
|
|
15
21
|
name: 'get',
|
|
@@ -28,6 +34,18 @@ export const getSubcommand = createSubcommand({
|
|
|
28
34
|
command: `${getCommand('cloud db get')} my-database --show-credentials`,
|
|
29
35
|
description: 'Get database with credentials',
|
|
30
36
|
},
|
|
37
|
+
{
|
|
38
|
+
command: `${getCommand('cloud db get')} my-database --show-tables`,
|
|
39
|
+
description: 'Get table schemas from the database',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
command: `${getCommand('cloud db get')} my-database --show-tables --sql`,
|
|
43
|
+
description: 'Get table schemas as SQL CREATE statements',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
command: `${getCommand('cloud db get')} my-database --show-tables --json`,
|
|
47
|
+
description: 'Get table schemas as JSON',
|
|
48
|
+
},
|
|
31
49
|
],
|
|
32
50
|
schema: {
|
|
33
51
|
args: z.object({
|
|
@@ -40,6 +58,8 @@ export const getSubcommand = createSubcommand({
|
|
|
40
58
|
.describe(
|
|
41
59
|
'Show credentials in plain text (default: masked in terminal, unmasked in JSON)'
|
|
42
60
|
),
|
|
61
|
+
showTables: z.boolean().optional().describe('Fetch table schemas from the database'),
|
|
62
|
+
sql: z.boolean().optional().describe('Output table schemas as SQL CREATE statements'),
|
|
43
63
|
}),
|
|
44
64
|
response: DBGetResponseSchema,
|
|
45
65
|
},
|
|
@@ -63,6 +83,66 @@ export const getSubcommand = createSubcommand({
|
|
|
63
83
|
tui.fatal(`Database '${args.name}' not found`, ErrorCode.RESOURCE_NOT_FOUND);
|
|
64
84
|
}
|
|
65
85
|
|
|
86
|
+
// If --tables flag is provided, fetch table schemas
|
|
87
|
+
if (opts.showTables) {
|
|
88
|
+
const tables = await tui.spinner({
|
|
89
|
+
message: `Fetching table schemas for ${args.name}`,
|
|
90
|
+
clearOnSuccess: true,
|
|
91
|
+
callback: async () => {
|
|
92
|
+
return dbTables(catalystClient, {
|
|
93
|
+
database: args.name,
|
|
94
|
+
orgId,
|
|
95
|
+
region,
|
|
96
|
+
});
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
if (!tables || tables.length === 0) {
|
|
101
|
+
if (!options.json) {
|
|
102
|
+
tui.info(`No tables found in database '${args.name}'`);
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
name: args.name,
|
|
106
|
+
url: db.url ?? undefined,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// --sql option: output CREATE TABLE statements
|
|
111
|
+
if (opts.sql) {
|
|
112
|
+
if (options.json) {
|
|
113
|
+
return { tables: tables.map(generateCreateTableSQL) };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
for (const table of tables) {
|
|
117
|
+
console.log(generateCreateTableSQL(table));
|
|
118
|
+
console.log('');
|
|
119
|
+
}
|
|
120
|
+
return { tables: tables.map((t) => t.table_name) };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// --json option: return raw table schemas
|
|
124
|
+
if (options.json) {
|
|
125
|
+
return { tables };
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Default: display as tables using tui.table
|
|
129
|
+
for (const table of tables) {
|
|
130
|
+
console.log(tui.bold(`\nTable: ${table.table_name}`));
|
|
131
|
+
|
|
132
|
+
const tableData = table.columns.map((col) => ({
|
|
133
|
+
Column: col.name,
|
|
134
|
+
Type: col.data_type,
|
|
135
|
+
Nullable: col.is_nullable ? 'YES' : 'NO',
|
|
136
|
+
Default: col.default_value || '',
|
|
137
|
+
'Primary Key': col.is_primary_key ? 'YES' : '',
|
|
138
|
+
}));
|
|
139
|
+
|
|
140
|
+
tui.table(tableData);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return { tables: tables.map((t) => t.table_name) };
|
|
144
|
+
}
|
|
145
|
+
|
|
66
146
|
// Mask credentials in terminal output by default, unless --show-credentials is passed
|
|
67
147
|
const shouldShowCredentials = opts.showCredentials === true;
|
|
68
148
|
const shouldMask = !options.json && !shouldShowCredentials;
|
|
@@ -3,6 +3,7 @@ import { createSubcommand } from './create';
|
|
|
3
3
|
import { listSubcommand } from './list';
|
|
4
4
|
import { deleteSubcommand } from './delete';
|
|
5
5
|
import { getSubcommand } from './get';
|
|
6
|
+
import { logsSubcommand } from './logs';
|
|
6
7
|
import { sqlSubcommand } from './sql';
|
|
7
8
|
import { getCommand } from '../../../command-prefix';
|
|
8
9
|
|
|
@@ -15,5 +16,12 @@ export const dbCommand = createCommand({
|
|
|
15
16
|
{ command: getCommand('cloud db list'), description: 'List all databases' },
|
|
16
17
|
{ command: getCommand('cloud db sql "SELECT * FROM users"'), description: 'Run SQL query' },
|
|
17
18
|
],
|
|
18
|
-
subcommands: [
|
|
19
|
+
subcommands: [
|
|
20
|
+
createSubcommand,
|
|
21
|
+
listSubcommand,
|
|
22
|
+
getSubcommand,
|
|
23
|
+
deleteSubcommand,
|
|
24
|
+
logsSubcommand,
|
|
25
|
+
sqlSubcommand,
|
|
26
|
+
],
|
|
19
27
|
});
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createSubcommand } from '../../../types';
|
|
3
|
+
import * as tui from '../../../tui';
|
|
4
|
+
import { dbLogs, DbQueryLogSchema } from '@agentuity/server';
|
|
5
|
+
import { getCatalystAPIClient } from '../../../config';
|
|
6
|
+
import { getCommand } from '../../../command-prefix';
|
|
7
|
+
import { ErrorCode } from '../../../errors';
|
|
8
|
+
|
|
9
|
+
const DbLogsResponseSchema = z.array(DbQueryLogSchema);
|
|
10
|
+
|
|
11
|
+
export const logsSubcommand = createSubcommand({
|
|
12
|
+
name: 'logs',
|
|
13
|
+
aliases: ['log'],
|
|
14
|
+
description: 'Get query logs for a specific database',
|
|
15
|
+
tags: ['read-only', 'slow', 'requires-auth'],
|
|
16
|
+
examples: [
|
|
17
|
+
{
|
|
18
|
+
command: getCommand('cloud db logs my-database'),
|
|
19
|
+
description: 'View query logs for database',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
command: getCommand('cloud db logs my-database --limit=50'),
|
|
23
|
+
description: 'Limit to 50 log entries',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
command: getCommand('cloud db logs my-database --has-error'),
|
|
27
|
+
description: 'Show only queries with errors',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
command: getCommand('cloud db logs my-database --username=user123'),
|
|
31
|
+
description: 'Filter by username',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
command: getCommand('cloud db logs my-database --command=SELECT'),
|
|
35
|
+
description: 'Filter by SQL command type',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
command: getCommand('cloud db logs my-database --session-id=sess_abc123'),
|
|
39
|
+
description: 'Filter by session ID',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
command: getCommand('cloud db logs my-database --show-session-id'),
|
|
43
|
+
description: 'Show session ID column',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
command: getCommand('cloud db logs my-database --show-username'),
|
|
47
|
+
description: 'Show username column',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
command: getCommand('cloud db logs my-database --pretty'),
|
|
51
|
+
description: 'Show full formatted SQL on separate lines',
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
requires: { auth: true, org: true, region: true },
|
|
55
|
+
idempotent: true,
|
|
56
|
+
schema: {
|
|
57
|
+
args: z.object({
|
|
58
|
+
database: z.string().describe('Database name'),
|
|
59
|
+
}),
|
|
60
|
+
options: z.object({
|
|
61
|
+
startDate: z.string().optional().describe('Start date for filtering logs'),
|
|
62
|
+
endDate: z.string().optional().describe('End date for filtering logs'),
|
|
63
|
+
username: z.string().optional().describe('Filter by username'),
|
|
64
|
+
command: z.string().optional().describe('Filter by SQL command type'),
|
|
65
|
+
hasError: z.boolean().optional().describe('Show only queries with errors'),
|
|
66
|
+
sessionId: z.string().optional().describe('Filter by session ID (trace ID)'),
|
|
67
|
+
showSessionId: z.boolean().default(false).describe('Show session ID column in output'),
|
|
68
|
+
showUsername: z.boolean().default(false).describe('Show username column in output'),
|
|
69
|
+
pretty: z.boolean().default(false).describe('Show full formatted SQL on separate line'),
|
|
70
|
+
limit: z.coerce
|
|
71
|
+
.number()
|
|
72
|
+
.int()
|
|
73
|
+
.min(1)
|
|
74
|
+
.default(100)
|
|
75
|
+
.describe('Maximum number of logs to return'),
|
|
76
|
+
timestamps: z.boolean().default(true).describe('Show timestamps in output'),
|
|
77
|
+
}),
|
|
78
|
+
response: DbLogsResponseSchema,
|
|
79
|
+
},
|
|
80
|
+
async handler(ctx) {
|
|
81
|
+
const { args, options, orgId, region, config, logger, auth } = ctx;
|
|
82
|
+
const showTimestamps = ctx.opts.timestamps ?? true;
|
|
83
|
+
const showSessionId = ctx.opts.showSessionId ?? false;
|
|
84
|
+
const showUsername = ctx.opts.showUsername ?? false;
|
|
85
|
+
const prettySQL = ctx.opts.pretty ?? false;
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
const catalystClient = getCatalystAPIClient(config, logger, auth);
|
|
89
|
+
|
|
90
|
+
const logs = await dbLogs(catalystClient, {
|
|
91
|
+
database: args.database,
|
|
92
|
+
orgId,
|
|
93
|
+
region,
|
|
94
|
+
startDate: ctx.opts.startDate,
|
|
95
|
+
endDate: ctx.opts.endDate,
|
|
96
|
+
username: ctx.opts.username,
|
|
97
|
+
command: ctx.opts.command,
|
|
98
|
+
hasError: ctx.opts.hasError,
|
|
99
|
+
sessionId: ctx.opts.sessionId,
|
|
100
|
+
limit: ctx.opts.limit,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
if (!options.json) {
|
|
104
|
+
if (logs.length === 0) {
|
|
105
|
+
tui.info('No logs found for this database.');
|
|
106
|
+
} else {
|
|
107
|
+
for (const log of logs) {
|
|
108
|
+
// Format timestamp with explicit locale for consistency
|
|
109
|
+
const timestamp = showTimestamps
|
|
110
|
+
? `${tui.muted(new Date(log.timestamp).toLocaleString('en-US', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' }).padEnd(22))} `
|
|
111
|
+
: '';
|
|
112
|
+
|
|
113
|
+
// Format command with cyan color (using info color) and consistent width
|
|
114
|
+
const commandText = log.command.padEnd(8);
|
|
115
|
+
const command = tui.colorInfo(commandText);
|
|
116
|
+
|
|
117
|
+
// Format duration with consistent width
|
|
118
|
+
const duration = `${log.duration.toFixed(2)}ms`.padStart(9);
|
|
119
|
+
|
|
120
|
+
// Format username if requested
|
|
121
|
+
const username = showUsername
|
|
122
|
+
? `${tui.muted(`[${log.username}]`.padEnd(14))} `
|
|
123
|
+
: '';
|
|
124
|
+
|
|
125
|
+
// Format session ID if requested (already has sess_ prefix from API)
|
|
126
|
+
const sessionId = showSessionId
|
|
127
|
+
? `${tui.muted((log.sessionId || '').padEnd(38))} `
|
|
128
|
+
: '';
|
|
129
|
+
|
|
130
|
+
if (prettySQL) {
|
|
131
|
+
// Pretty mode: show metadata on first line, full SQL on next line
|
|
132
|
+
console.log(
|
|
133
|
+
`${timestamp}${command} ${tui.muted(duration)} ${username}${sessionId}`
|
|
134
|
+
);
|
|
135
|
+
// Show full formatted SQL indented on next line with clear color
|
|
136
|
+
console.log(` ${log.sql}`);
|
|
137
|
+
} else {
|
|
138
|
+
// Normal mode: truncate SQL and show inline
|
|
139
|
+
const sqlClean = log.sql
|
|
140
|
+
.replace(/[\n\r\t]+/g, ' ')
|
|
141
|
+
.replace(/\s+/g, ' ')
|
|
142
|
+
.trim();
|
|
143
|
+
const sql =
|
|
144
|
+
sqlClean.length > 100 ? `${sqlClean.substring(0, 97)}...` : sqlClean;
|
|
145
|
+
console.log(
|
|
146
|
+
`${timestamp}${command} ${tui.muted(duration)} ${username}${sessionId}${sql}`
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Show error on separate line underneath if present
|
|
151
|
+
if (log.error) {
|
|
152
|
+
console.log(tui.colorError(` ↳ ERROR: ${log.error}`));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return logs;
|
|
159
|
+
} catch (ex) {
|
|
160
|
+
tui.fatal(`Failed to get database logs: ${ex}`, ErrorCode.API_ERROR);
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
});
|
package/src/cmd/cloud/db/sql.ts
CHANGED
|
@@ -1,23 +1,14 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import {
|
|
3
|
-
import { listResources, type ResourceList } from '@agentuity/server';
|
|
2
|
+
import { dbQuery } from '@agentuity/server';
|
|
4
3
|
import { createSubcommand } from '../../../types';
|
|
5
4
|
import * as tui from '../../../tui';
|
|
6
5
|
import { getCatalystAPIClient } from '../../../config';
|
|
7
6
|
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
7
|
|
|
17
8
|
const DBSQLResponseSchema = z.object({
|
|
18
9
|
rows: z.array(z.record(z.string(), z.unknown())).describe('Query results'),
|
|
19
10
|
rowCount: z.number().describe('Number of rows returned'),
|
|
20
|
-
|
|
11
|
+
truncated: z.boolean().describe('Whether results were truncated'),
|
|
21
12
|
});
|
|
22
13
|
|
|
23
14
|
export const sqlSubcommand = createSubcommand({
|
|
@@ -55,80 +46,39 @@ export const sqlSubcommand = createSubcommand({
|
|
|
55
46
|
|
|
56
47
|
const catalystClient = getCatalystAPIClient(config, logger, auth);
|
|
57
48
|
|
|
58
|
-
const
|
|
59
|
-
message: `
|
|
49
|
+
const result = await tui.spinner({
|
|
50
|
+
message: `Executing query on ${args.name}`,
|
|
60
51
|
clearOnSuccess: true,
|
|
61
52
|
callback: async () => {
|
|
62
|
-
return
|
|
53
|
+
return dbQuery(catalystClient, {
|
|
54
|
+
database: args.name,
|
|
55
|
+
query: args.query,
|
|
56
|
+
orgId,
|
|
57
|
+
region,
|
|
58
|
+
});
|
|
63
59
|
},
|
|
64
60
|
});
|
|
65
61
|
|
|
66
|
-
const db: DatabaseResource | undefined = resources.db.find(
|
|
67
|
-
(d: DatabaseResource) => d.name === args.name
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
if (!db) {
|
|
71
|
-
tui.fatal(`Database '${args.name}' not found`, ErrorCode.RESOURCE_NOT_FOUND);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (!db.url) {
|
|
75
|
-
tui.fatal(`Database '${args.name}' has no connection URL`, ErrorCode.RUNTIME_ERROR);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
let database: SQL | undefined;
|
|
79
|
-
let rows: Record<string, unknown>[];
|
|
80
|
-
let executionTime: number | undefined;
|
|
81
|
-
|
|
82
|
-
try {
|
|
83
|
-
// Add sslmode=require if not already present in URL
|
|
84
|
-
let connectionUrl = db.url;
|
|
85
|
-
if (!connectionUrl.includes('sslmode=') && !connectionUrl.includes('ssl=')) {
|
|
86
|
-
const separator = connectionUrl.includes('?') ? '&' : '?';
|
|
87
|
-
connectionUrl = `${connectionUrl}${separator}sslmode=require`;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
database = new SQL(connectionUrl);
|
|
91
|
-
|
|
92
|
-
const startTime = performance.now();
|
|
93
|
-
const result = await tui.spinner({
|
|
94
|
-
message: `Executing query on ${args.name}`,
|
|
95
|
-
clearOnSuccess: true,
|
|
96
|
-
callback: async () => {
|
|
97
|
-
return database!.unsafe(args.query);
|
|
98
|
-
},
|
|
99
|
-
});
|
|
100
|
-
executionTime = performance.now() - startTime;
|
|
101
|
-
|
|
102
|
-
rows = result;
|
|
103
|
-
} catch (error) {
|
|
104
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
105
|
-
tui.fatal(`Query execution failed: ${message}`, ErrorCode.RUNTIME_ERROR);
|
|
106
|
-
} finally {
|
|
107
|
-
if (database) {
|
|
108
|
-
await database.close();
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
62
|
if (!options.json) {
|
|
113
|
-
if (
|
|
63
|
+
if (result.rowCount === 0) {
|
|
114
64
|
tui.info('No rows returned');
|
|
115
65
|
} else {
|
|
116
66
|
if (process.stdout.isTTY) {
|
|
117
67
|
tui.newline();
|
|
118
68
|
tui.success(
|
|
119
|
-
`Query returned ${
|
|
69
|
+
`Query returned ${result.rowCount} row${result.rowCount !== 1 ? 's' : ''}${result.truncated ? ' (truncated to 1000 rows)' : ''}:`
|
|
120
70
|
);
|
|
121
71
|
tui.newline();
|
|
122
72
|
}
|
|
123
73
|
|
|
124
|
-
tui.table(rows);
|
|
74
|
+
tui.table(result.rows);
|
|
125
75
|
}
|
|
126
76
|
}
|
|
127
77
|
|
|
128
78
|
return {
|
|
129
|
-
rows,
|
|
130
|
-
rowCount:
|
|
131
|
-
|
|
79
|
+
rows: result.rows,
|
|
80
|
+
rowCount: result.rowCount,
|
|
81
|
+
truncated: result.truncated,
|
|
132
82
|
};
|
|
133
83
|
},
|
|
134
84
|
});
|
package/src/cmd/cloud/deploy.ts
CHANGED
|
@@ -27,9 +27,9 @@ import {
|
|
|
27
27
|
} from '../../env-util';
|
|
28
28
|
import { zipDir } from '../../utils/zip';
|
|
29
29
|
import { encryptFIPSKEMDEMStream } from '../../crypto/box';
|
|
30
|
-
import { DeployOptionsSchema } from '../build/bundler';
|
|
31
30
|
import { getCommand } from '../../command-prefix';
|
|
32
31
|
import { checkCustomDomainForDNS } from './domain';
|
|
32
|
+
import { DeployOptionsSchema } from '../../schemas/deploy';
|
|
33
33
|
|
|
34
34
|
const DeployResponseSchema = z.object({
|
|
35
35
|
success: z.boolean().describe('Whether deployment succeeded'),
|
|
@@ -162,7 +162,8 @@ export const deploySubcommand = createSubcommand({
|
|
|
162
162
|
);
|
|
163
163
|
return stepSuccess();
|
|
164
164
|
} catch (ex) {
|
|
165
|
-
|
|
165
|
+
const _ex = ex as { message?: string };
|
|
166
|
+
return stepError(_ex.message ?? String(_ex), ex as Error);
|
|
166
167
|
}
|
|
167
168
|
},
|
|
168
169
|
},
|
|
@@ -103,10 +103,7 @@ export const listSubcommand = createSubcommand({
|
|
|
103
103
|
|
|
104
104
|
return result;
|
|
105
105
|
} catch (ex) {
|
|
106
|
-
tui.fatal(
|
|
107
|
-
`Failed to list deployments: ${ex instanceof Error ? ex.message : String(ex)}`,
|
|
108
|
-
ErrorCode.API_ERROR
|
|
109
|
-
);
|
|
106
|
+
tui.fatal(`Failed to list deployments: ${ex}`, ErrorCode.API_ERROR);
|
|
110
107
|
}
|
|
111
108
|
},
|
|
112
109
|
});
|
|
@@ -78,10 +78,7 @@ export const logsSubcommand = createSubcommand({
|
|
|
78
78
|
|
|
79
79
|
return logs;
|
|
80
80
|
} catch (ex) {
|
|
81
|
-
tui.fatal(
|
|
82
|
-
`Failed to fetch deployment logs: ${ex instanceof Error ? ex.message : String(ex)}`,
|
|
83
|
-
ErrorCode.API_ERROR
|
|
84
|
-
);
|
|
81
|
+
tui.fatal(`Failed to fetch deployment logs: ${ex}`, ErrorCode.API_ERROR);
|
|
85
82
|
}
|
|
86
83
|
},
|
|
87
84
|
});
|
|
@@ -69,7 +69,7 @@ export const removeSubcommand = createSubcommand({
|
|
|
69
69
|
deploymentId: args.deployment_id,
|
|
70
70
|
};
|
|
71
71
|
} catch (ex) {
|
|
72
|
-
tui.fatal(`Failed to remove deployment: ${ex
|
|
72
|
+
tui.fatal(`Failed to remove deployment: ${ex}`);
|
|
73
73
|
}
|
|
74
74
|
},
|
|
75
75
|
});
|
|
@@ -155,7 +155,7 @@ export const showSubcommand = createSubcommand({
|
|
|
155
155
|
metadata: deployment.metadata ?? undefined,
|
|
156
156
|
};
|
|
157
157
|
} catch (ex) {
|
|
158
|
-
tui.fatal(`Failed to show deployment: ${ex
|
|
158
|
+
tui.fatal(`Failed to show deployment: ${ex}`);
|
|
159
159
|
}
|
|
160
160
|
},
|
|
161
161
|
});
|