@agentuity/cli 0.0.64 → 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.
Files changed (154) hide show
  1. package/dist/cmd/build/ast.d.ts.map +1 -1
  2. package/dist/cmd/build/ast.js +70 -4
  3. package/dist/cmd/build/ast.js.map +1 -1
  4. package/dist/cmd/build/ast.test.js +186 -1
  5. package/dist/cmd/build/ast.test.js.map +1 -1
  6. package/dist/cmd/build/bundler.d.ts +2 -24
  7. package/dist/cmd/build/bundler.d.ts.map +1 -1
  8. package/dist/cmd/build/bundler.js +24 -41
  9. package/dist/cmd/build/bundler.js.map +1 -1
  10. package/dist/cmd/build/index.js +22 -23
  11. package/dist/cmd/build/index.js.map +1 -1
  12. package/dist/cmd/build/plugin.d.ts.map +1 -1
  13. package/dist/cmd/build/plugin.js +5 -4
  14. package/dist/cmd/build/plugin.js.map +1 -1
  15. package/dist/cmd/build/workbench-templates.d.ts +1 -1
  16. package/dist/cmd/build/workbench-templates.d.ts.map +1 -1
  17. package/dist/cmd/build/workbench-templates.js +6 -19
  18. package/dist/cmd/build/workbench-templates.js.map +1 -1
  19. package/dist/cmd/cloud/apikey/create.d.ts.map +1 -1
  20. package/dist/cmd/cloud/apikey/create.js +7 -16
  21. package/dist/cmd/cloud/apikey/create.js.map +1 -1
  22. package/dist/cmd/cloud/db/create.d.ts.map +1 -1
  23. package/dist/cmd/cloud/db/create.js +3 -2
  24. package/dist/cmd/cloud/db/create.js.map +1 -1
  25. package/dist/cmd/cloud/db/get.d.ts.map +1 -1
  26. package/dist/cmd/cloud/db/get.js +72 -3
  27. package/dist/cmd/cloud/db/get.js.map +1 -1
  28. package/dist/cmd/cloud/db/index.d.ts.map +1 -1
  29. package/dist/cmd/cloud/db/index.js +9 -1
  30. package/dist/cmd/cloud/db/index.js.map +1 -1
  31. package/dist/cmd/cloud/db/logs.d.ts +2 -0
  32. package/dist/cmd/cloud/db/logs.d.ts.map +1 -0
  33. package/dist/cmd/cloud/db/logs.js +150 -0
  34. package/dist/cmd/cloud/db/logs.js.map +1 -0
  35. package/dist/cmd/cloud/db/sql.d.ts.map +1 -1
  36. package/dist/cmd/cloud/db/sql.js +16 -51
  37. package/dist/cmd/cloud/db/sql.js.map +1 -1
  38. package/dist/cmd/cloud/deploy.d.ts.map +1 -1
  39. package/dist/cmd/cloud/deploy.js +3 -2
  40. package/dist/cmd/cloud/deploy.js.map +1 -1
  41. package/dist/cmd/cloud/deployment/list.d.ts.map +1 -1
  42. package/dist/cmd/cloud/deployment/list.js +1 -1
  43. package/dist/cmd/cloud/deployment/list.js.map +1 -1
  44. package/dist/cmd/cloud/deployment/logs.d.ts.map +1 -1
  45. package/dist/cmd/cloud/deployment/logs.js +1 -1
  46. package/dist/cmd/cloud/deployment/logs.js.map +1 -1
  47. package/dist/cmd/cloud/deployment/remove.js +1 -1
  48. package/dist/cmd/cloud/deployment/remove.js.map +1 -1
  49. package/dist/cmd/cloud/deployment/rollback.js +1 -1
  50. package/dist/cmd/cloud/deployment/rollback.js.map +1 -1
  51. package/dist/cmd/cloud/deployment/show.js +1 -1
  52. package/dist/cmd/cloud/deployment/show.js.map +1 -1
  53. package/dist/cmd/cloud/deployment/undeploy.js +1 -1
  54. package/dist/cmd/cloud/deployment/undeploy.js.map +1 -1
  55. package/dist/cmd/cloud/keyvalue/util.js +1 -1
  56. package/dist/cmd/cloud/keyvalue/util.js.map +1 -1
  57. package/dist/cmd/cloud/objectstore/util.js +1 -1
  58. package/dist/cmd/cloud/objectstore/util.js.map +1 -1
  59. package/dist/cmd/cloud/session/get.d.ts.map +1 -1
  60. package/dist/cmd/cloud/session/get.js +1 -1
  61. package/dist/cmd/cloud/session/get.js.map +1 -1
  62. package/dist/cmd/cloud/session/list.d.ts.map +1 -1
  63. package/dist/cmd/cloud/session/list.js +1 -1
  64. package/dist/cmd/cloud/session/list.js.map +1 -1
  65. package/dist/cmd/cloud/session/logs.d.ts.map +1 -1
  66. package/dist/cmd/cloud/session/logs.js +1 -1
  67. package/dist/cmd/cloud/session/logs.js.map +1 -1
  68. package/dist/cmd/cloud/stream/util.d.ts.map +1 -1
  69. package/dist/cmd/cloud/stream/util.js +2 -1
  70. package/dist/cmd/cloud/stream/util.js.map +1 -1
  71. package/dist/cmd/cloud/thread/delete.d.ts.map +1 -1
  72. package/dist/cmd/cloud/thread/delete.js +1 -1
  73. package/dist/cmd/cloud/thread/delete.js.map +1 -1
  74. package/dist/cmd/cloud/thread/get.d.ts.map +1 -1
  75. package/dist/cmd/cloud/thread/get.js +1 -1
  76. package/dist/cmd/cloud/thread/get.js.map +1 -1
  77. package/dist/cmd/cloud/thread/list.d.ts.map +1 -1
  78. package/dist/cmd/cloud/thread/list.js +1 -1
  79. package/dist/cmd/cloud/thread/list.js.map +1 -1
  80. package/dist/cmd/cloud/vector/util.js +1 -1
  81. package/dist/cmd/cloud/vector/util.js.map +1 -1
  82. package/dist/cmd/dev/index.d.ts.map +1 -1
  83. package/dist/cmd/dev/index.js +34 -1
  84. package/dist/cmd/dev/index.js.map +1 -1
  85. package/dist/cmd/profile/current.d.ts +3 -0
  86. package/dist/cmd/profile/current.d.ts.map +1 -0
  87. package/dist/cmd/profile/current.js +27 -0
  88. package/dist/cmd/profile/current.js.map +1 -0
  89. package/dist/cmd/profile/index.d.ts.map +1 -1
  90. package/dist/cmd/profile/index.js +9 -1
  91. package/dist/cmd/profile/index.js.map +1 -1
  92. package/dist/cmd/profile/show.d.ts.map +1 -1
  93. package/dist/cmd/profile/show.js +0 -1
  94. package/dist/cmd/profile/show.js.map +1 -1
  95. package/dist/command-prefix.d.ts.map +1 -1
  96. package/dist/command-prefix.js +2 -1
  97. package/dist/command-prefix.js.map +1 -1
  98. package/dist/config.d.ts +1 -1
  99. package/dist/config.d.ts.map +1 -1
  100. package/dist/config.js +18 -5
  101. package/dist/config.js.map +1 -1
  102. package/dist/download.js +1 -1
  103. package/dist/download.js.map +1 -1
  104. package/dist/env-util.d.ts.map +1 -1
  105. package/dist/env-util.js +3 -0
  106. package/dist/env-util.js.map +1 -1
  107. package/dist/schemas/deploy.d.ts +24 -0
  108. package/dist/schemas/deploy.d.ts.map +1 -0
  109. package/dist/schemas/deploy.js +26 -0
  110. package/dist/schemas/deploy.js.map +1 -0
  111. package/dist/utils/workbench-notify.d.ts +29 -0
  112. package/dist/utils/workbench-notify.d.ts.map +1 -0
  113. package/dist/utils/workbench-notify.js +56 -0
  114. package/dist/utils/workbench-notify.js.map +1 -0
  115. package/package.json +3 -3
  116. package/src/cmd/build/ast.test.ts +246 -1
  117. package/src/cmd/build/ast.ts +88 -4
  118. package/src/cmd/build/bundler.ts +27 -44
  119. package/src/cmd/build/index.ts +23 -23
  120. package/src/cmd/build/plugin.ts +5 -4
  121. package/src/cmd/build/workbench-templates.ts +6 -21
  122. package/src/cmd/cloud/apikey/create.ts +7 -15
  123. package/src/cmd/cloud/db/create.ts +3 -2
  124. package/src/cmd/cloud/db/get.ts +85 -5
  125. package/src/cmd/cloud/db/index.ts +9 -1
  126. package/src/cmd/cloud/db/logs.ts +163 -0
  127. package/src/cmd/cloud/db/sql.ts +16 -66
  128. package/src/cmd/cloud/deploy.ts +3 -2
  129. package/src/cmd/cloud/deployment/list.ts +1 -4
  130. package/src/cmd/cloud/deployment/logs.ts +1 -4
  131. package/src/cmd/cloud/deployment/remove.ts +1 -1
  132. package/src/cmd/cloud/deployment/rollback.ts +1 -1
  133. package/src/cmd/cloud/deployment/show.ts +1 -1
  134. package/src/cmd/cloud/deployment/undeploy.ts +1 -1
  135. package/src/cmd/cloud/keyvalue/util.ts +1 -1
  136. package/src/cmd/cloud/objectstore/util.ts +1 -1
  137. package/src/cmd/cloud/session/get.ts +1 -4
  138. package/src/cmd/cloud/session/list.ts +1 -4
  139. package/src/cmd/cloud/session/logs.ts +1 -4
  140. package/src/cmd/cloud/stream/util.ts +4 -1
  141. package/src/cmd/cloud/thread/delete.ts +1 -4
  142. package/src/cmd/cloud/thread/get.ts +1 -4
  143. package/src/cmd/cloud/thread/list.ts +1 -4
  144. package/src/cmd/cloud/vector/util.ts +1 -1
  145. package/src/cmd/dev/index.ts +40 -1
  146. package/src/cmd/profile/current.ts +31 -0
  147. package/src/cmd/profile/index.ts +9 -1
  148. package/src/cmd/profile/show.ts +0 -1
  149. package/src/command-prefix.ts +4 -1
  150. package/src/config.ts +20 -5
  151. package/src/download.ts +1 -1
  152. package/src/env-util.ts +3 -0
  153. package/src/schemas/deploy.ts +28 -0
  154. package/src/utils/workbench-notify.ts +67 -0
@@ -50,30 +50,30 @@ export const command = createCommand({
50
50
 
51
51
  const env: Map<string, string> = new Map();
52
52
 
53
- if (opts.dev) {
54
- if (config?.overrides?.transport_url) {
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,
@@ -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 metadata route if workbench is actually configured
729
+ // Only create the workbench routes if workbench is actually configured
730
730
  if (workbenchConfig) {
731
731
  inserts.push(`await (async() => {
732
- const { createWorkbenchMetadataRoute, getRouter } = await import('@agentuity/runtime');
733
- const router = getRouter()!;
734
- router.get('/_agentuity/workbench/metadata.json', createWorkbenchMetadataRoute());
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 { WorkbenchConfig } from '@agentuity/core';
1
+ import { encodeWorkbenchConfig, type WorkbenchConfig } from '@agentuity/core';
2
2
 
3
3
  export function generateWorkbenchMainTsx(config: WorkbenchConfig): string {
4
- const configString = JSON.stringify(config);
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 { AgentuityProvider } from '@agentuity/react';
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
- // Create workbench instance with config from bundler
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
- root.render(<App />);
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
- let result: Awaited<ReturnType<typeof apikeyCreate>>;
86
- try {
87
- result = await tui.spinner('Creating API key', () => {
88
- return apikeyCreate(apiClient, {
89
- name: opts.name,
90
- expiresAt: expiresAt,
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
- } catch (error) {
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 (optional)'),
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 "${opts.name}" already exists. Use another name or don't specify --name for a unique name to be generated automatically.`,
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
  }
@@ -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.object({
10
- name: z.string().describe('Database name'),
11
- url: z.string().optional().describe('Database connection URL'),
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: [createSubcommand, listSubcommand, getSubcommand, deleteSubcommand, sqlSubcommand],
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
+ });
@@ -1,23 +1,14 @@
1
1
  import { z } from 'zod';
2
- import { SQL } from 'bun';
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
- executionTime: z.number().optional().describe('Query execution time in ms'),
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 resources: ResourceList = await tui.spinner({
59
- message: `Fetching database ${args.name}`,
49
+ const result = await tui.spinner({
50
+ message: `Executing query on ${args.name}`,
60
51
  clearOnSuccess: true,
61
52
  callback: async () => {
62
- return listResources(catalystClient, orgId, region);
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 (rows.length === 0) {
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 ${rows.length} row${rows.length !== 1 ? 's' : ''} (${executionTime?.toFixed(2)}ms):`
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: rows.length,
131
- executionTime,
79
+ rows: result.rows,
80
+ rowCount: result.rowCount,
81
+ truncated: result.truncated,
132
82
  };
133
83
  },
134
84
  });
@@ -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
- return stepError(ex instanceof Error ? ex.message : String(ex));
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 instanceof Error ? ex.message : String(ex)}`);
72
+ tui.fatal(`Failed to remove deployment: ${ex}`);
73
73
  }
74
74
  },
75
75
  });
@@ -86,7 +86,7 @@ export const rollbackSubcommand = createSubcommand({
86
86
  targetDeploymentId,
87
87
  };
88
88
  } catch (ex) {
89
- tui.fatal(`Failed to rollback: ${ex instanceof Error ? ex.message : String(ex)}`);
89
+ tui.fatal(`Failed to rollback: ${ex}`);
90
90
  }
91
91
  },
92
92
  });
@@ -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 instanceof Error ? ex.message : String(ex)}`);
158
+ tui.fatal(`Failed to show deployment: ${ex}`);
159
159
  }
160
160
  },
161
161
  });