@agentuity/cli 0.0.64 → 0.0.66

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 (216) hide show
  1. package/dist/api.d.ts +1 -0
  2. package/dist/api.d.ts.map +1 -1
  3. package/dist/api.js +12 -2
  4. package/dist/api.js.map +1 -1
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/cli.js +5 -1
  7. package/dist/cli.js.map +1 -1
  8. package/dist/cmd/auth/signup.js +1 -1
  9. package/dist/cmd/auth/signup.js.map +1 -1
  10. package/dist/cmd/build/ast.d.ts.map +1 -1
  11. package/dist/cmd/build/ast.js +70 -4
  12. package/dist/cmd/build/ast.js.map +1 -1
  13. package/dist/cmd/build/ast.test.js +186 -1
  14. package/dist/cmd/build/ast.test.js.map +1 -1
  15. package/dist/cmd/build/bundler.d.ts +2 -24
  16. package/dist/cmd/build/bundler.d.ts.map +1 -1
  17. package/dist/cmd/build/bundler.js +24 -41
  18. package/dist/cmd/build/bundler.js.map +1 -1
  19. package/dist/cmd/build/index.d.ts.map +1 -1
  20. package/dist/cmd/build/index.js +14 -24
  21. package/dist/cmd/build/index.js.map +1 -1
  22. package/dist/cmd/build/plugin.d.ts.map +1 -1
  23. package/dist/cmd/build/plugin.js +13 -10
  24. package/dist/cmd/build/plugin.js.map +1 -1
  25. package/dist/cmd/build/workbench-templates.d.ts +1 -1
  26. package/dist/cmd/build/workbench-templates.d.ts.map +1 -1
  27. package/dist/cmd/build/workbench-templates.js +6 -19
  28. package/dist/cmd/build/workbench-templates.js.map +1 -1
  29. package/dist/cmd/cloud/apikey/create.d.ts.map +1 -1
  30. package/dist/cmd/cloud/apikey/create.js +7 -16
  31. package/dist/cmd/cloud/apikey/create.js.map +1 -1
  32. package/dist/cmd/cloud/db/create.d.ts.map +1 -1
  33. package/dist/cmd/cloud/db/create.js +4 -3
  34. package/dist/cmd/cloud/db/create.js.map +1 -1
  35. package/dist/cmd/cloud/db/delete.js +1 -1
  36. package/dist/cmd/cloud/db/delete.js.map +1 -1
  37. package/dist/cmd/cloud/db/get.d.ts.map +1 -1
  38. package/dist/cmd/cloud/db/get.js +73 -4
  39. package/dist/cmd/cloud/db/get.js.map +1 -1
  40. package/dist/cmd/cloud/db/index.d.ts.map +1 -1
  41. package/dist/cmd/cloud/db/index.js +9 -1
  42. package/dist/cmd/cloud/db/index.js.map +1 -1
  43. package/dist/cmd/cloud/db/list.js +1 -1
  44. package/dist/cmd/cloud/db/list.js.map +1 -1
  45. package/dist/cmd/cloud/db/logs.d.ts +2 -0
  46. package/dist/cmd/cloud/db/logs.d.ts.map +1 -0
  47. package/dist/cmd/cloud/db/logs.js +150 -0
  48. package/dist/cmd/cloud/db/logs.js.map +1 -0
  49. package/dist/cmd/cloud/db/sql.d.ts.map +1 -1
  50. package/dist/cmd/cloud/db/sql.js +17 -52
  51. package/dist/cmd/cloud/db/sql.js.map +1 -1
  52. package/dist/cmd/cloud/deploy.d.ts.map +1 -1
  53. package/dist/cmd/cloud/deploy.js +3 -2
  54. package/dist/cmd/cloud/deploy.js.map +1 -1
  55. package/dist/cmd/cloud/deployment/list.d.ts.map +1 -1
  56. package/dist/cmd/cloud/deployment/list.js +1 -1
  57. package/dist/cmd/cloud/deployment/list.js.map +1 -1
  58. package/dist/cmd/cloud/deployment/logs.d.ts.map +1 -1
  59. package/dist/cmd/cloud/deployment/logs.js +1 -1
  60. package/dist/cmd/cloud/deployment/logs.js.map +1 -1
  61. package/dist/cmd/cloud/deployment/remove.js +1 -1
  62. package/dist/cmd/cloud/deployment/remove.js.map +1 -1
  63. package/dist/cmd/cloud/deployment/rollback.js +1 -1
  64. package/dist/cmd/cloud/deployment/rollback.js.map +1 -1
  65. package/dist/cmd/cloud/deployment/show.js +1 -1
  66. package/dist/cmd/cloud/deployment/show.js.map +1 -1
  67. package/dist/cmd/cloud/deployment/undeploy.js +1 -1
  68. package/dist/cmd/cloud/deployment/undeploy.js.map +1 -1
  69. package/dist/cmd/cloud/keyvalue/util.d.ts +3 -0
  70. package/dist/cmd/cloud/keyvalue/util.d.ts.map +1 -1
  71. package/dist/cmd/cloud/keyvalue/util.js +4 -3
  72. package/dist/cmd/cloud/keyvalue/util.js.map +1 -1
  73. package/dist/cmd/cloud/objectstore/util.d.ts +3 -0
  74. package/dist/cmd/cloud/objectstore/util.d.ts.map +1 -1
  75. package/dist/cmd/cloud/objectstore/util.js +3 -3
  76. package/dist/cmd/cloud/objectstore/util.js.map +1 -1
  77. package/dist/cmd/cloud/session/get.d.ts.map +1 -1
  78. package/dist/cmd/cloud/session/get.js +4 -4
  79. package/dist/cmd/cloud/session/get.js.map +1 -1
  80. package/dist/cmd/cloud/session/list.d.ts.map +1 -1
  81. package/dist/cmd/cloud/session/list.js +4 -4
  82. package/dist/cmd/cloud/session/list.js.map +1 -1
  83. package/dist/cmd/cloud/session/logs.d.ts.map +1 -1
  84. package/dist/cmd/cloud/session/logs.js +1 -1
  85. package/dist/cmd/cloud/session/logs.js.map +1 -1
  86. package/dist/cmd/cloud/storage/create.js +1 -1
  87. package/dist/cmd/cloud/storage/create.js.map +1 -1
  88. package/dist/cmd/cloud/storage/delete.js +1 -1
  89. package/dist/cmd/cloud/storage/delete.js.map +1 -1
  90. package/dist/cmd/cloud/storage/download.js +1 -1
  91. package/dist/cmd/cloud/storage/download.js.map +1 -1
  92. package/dist/cmd/cloud/storage/get.js +1 -1
  93. package/dist/cmd/cloud/storage/get.js.map +1 -1
  94. package/dist/cmd/cloud/storage/list.js +1 -1
  95. package/dist/cmd/cloud/storage/list.js.map +1 -1
  96. package/dist/cmd/cloud/storage/upload.js +1 -1
  97. package/dist/cmd/cloud/storage/upload.js.map +1 -1
  98. package/dist/cmd/cloud/stream/util.d.ts +3 -0
  99. package/dist/cmd/cloud/stream/util.d.ts.map +1 -1
  100. package/dist/cmd/cloud/stream/util.js +4 -3
  101. package/dist/cmd/cloud/stream/util.js.map +1 -1
  102. package/dist/cmd/cloud/thread/delete.d.ts.map +1 -1
  103. package/dist/cmd/cloud/thread/delete.js +4 -4
  104. package/dist/cmd/cloud/thread/delete.js.map +1 -1
  105. package/dist/cmd/cloud/thread/get.d.ts.map +1 -1
  106. package/dist/cmd/cloud/thread/get.js +4 -4
  107. package/dist/cmd/cloud/thread/get.js.map +1 -1
  108. package/dist/cmd/cloud/thread/list.d.ts.map +1 -1
  109. package/dist/cmd/cloud/thread/list.js +4 -4
  110. package/dist/cmd/cloud/thread/list.js.map +1 -1
  111. package/dist/cmd/cloud/vector/util.d.ts +3 -0
  112. package/dist/cmd/cloud/vector/util.d.ts.map +1 -1
  113. package/dist/cmd/cloud/vector/util.js +4 -3
  114. package/dist/cmd/cloud/vector/util.js.map +1 -1
  115. package/dist/cmd/dev/index.d.ts.map +1 -1
  116. package/dist/cmd/dev/index.js +48 -21
  117. package/dist/cmd/dev/index.js.map +1 -1
  118. package/dist/cmd/profile/current.d.ts +3 -0
  119. package/dist/cmd/profile/current.d.ts.map +1 -0
  120. package/dist/cmd/profile/current.js +27 -0
  121. package/dist/cmd/profile/current.js.map +1 -0
  122. package/dist/cmd/profile/index.d.ts.map +1 -1
  123. package/dist/cmd/profile/index.js +9 -1
  124. package/dist/cmd/profile/index.js.map +1 -1
  125. package/dist/cmd/profile/show.d.ts.map +1 -1
  126. package/dist/cmd/profile/show.js +0 -1
  127. package/dist/cmd/profile/show.js.map +1 -1
  128. package/dist/cmd/project/download.d.ts.map +1 -1
  129. package/dist/cmd/project/download.js +15 -16
  130. package/dist/cmd/project/download.js.map +1 -1
  131. package/dist/cmd/project/template-flow.d.ts.map +1 -1
  132. package/dist/cmd/project/template-flow.js +5 -4
  133. package/dist/cmd/project/template-flow.js.map +1 -1
  134. package/dist/cmd/project/templates.d.ts +2 -1
  135. package/dist/cmd/project/templates.d.ts.map +1 -1
  136. package/dist/cmd/project/templates.js +4 -9
  137. package/dist/cmd/project/templates.js.map +1 -1
  138. package/dist/command-prefix.d.ts.map +1 -1
  139. package/dist/command-prefix.js +2 -1
  140. package/dist/command-prefix.js.map +1 -1
  141. package/dist/config.d.ts +2 -2
  142. package/dist/config.d.ts.map +1 -1
  143. package/dist/config.js +127 -24
  144. package/dist/config.js.map +1 -1
  145. package/dist/download.js +1 -1
  146. package/dist/download.js.map +1 -1
  147. package/dist/env-util.d.ts.map +1 -1
  148. package/dist/env-util.js +3 -0
  149. package/dist/env-util.js.map +1 -1
  150. package/dist/schemas/deploy.d.ts +24 -0
  151. package/dist/schemas/deploy.d.ts.map +1 -0
  152. package/dist/schemas/deploy.js +26 -0
  153. package/dist/schemas/deploy.js.map +1 -0
  154. package/dist/types.d.ts +12 -12
  155. package/dist/types.d.ts.map +1 -1
  156. package/dist/types.js +11 -35
  157. package/dist/types.js.map +1 -1
  158. package/dist/utils/workbench-notify.d.ts +29 -0
  159. package/dist/utils/workbench-notify.d.ts.map +1 -0
  160. package/dist/utils/workbench-notify.js +56 -0
  161. package/dist/utils/workbench-notify.js.map +1 -0
  162. package/package.json +3 -3
  163. package/src/api.ts +13 -2
  164. package/src/cli.ts +6 -1
  165. package/src/cmd/auth/signup.ts +1 -1
  166. package/src/cmd/build/ast.test.ts +246 -1
  167. package/src/cmd/build/ast.ts +88 -4
  168. package/src/cmd/build/bundler.ts +27 -44
  169. package/src/cmd/build/index.ts +15 -24
  170. package/src/cmd/build/plugin.ts +13 -10
  171. package/src/cmd/build/workbench-templates.ts +6 -21
  172. package/src/cmd/cloud/apikey/create.ts +7 -15
  173. package/src/cmd/cloud/db/create.ts +4 -3
  174. package/src/cmd/cloud/db/delete.ts +1 -1
  175. package/src/cmd/cloud/db/get.ts +86 -6
  176. package/src/cmd/cloud/db/index.ts +9 -1
  177. package/src/cmd/cloud/db/list.ts +1 -1
  178. package/src/cmd/cloud/db/logs.ts +163 -0
  179. package/src/cmd/cloud/db/sql.ts +17 -67
  180. package/src/cmd/cloud/deploy.ts +3 -2
  181. package/src/cmd/cloud/deployment/list.ts +1 -4
  182. package/src/cmd/cloud/deployment/logs.ts +1 -4
  183. package/src/cmd/cloud/deployment/remove.ts +1 -1
  184. package/src/cmd/cloud/deployment/rollback.ts +1 -1
  185. package/src/cmd/cloud/deployment/show.ts +1 -1
  186. package/src/cmd/cloud/deployment/undeploy.ts +1 -1
  187. package/src/cmd/cloud/keyvalue/util.ts +5 -3
  188. package/src/cmd/cloud/objectstore/util.ts +4 -3
  189. package/src/cmd/cloud/session/get.ts +4 -7
  190. package/src/cmd/cloud/session/list.ts +4 -7
  191. package/src/cmd/cloud/session/logs.ts +1 -4
  192. package/src/cmd/cloud/storage/create.ts +1 -1
  193. package/src/cmd/cloud/storage/delete.ts +1 -1
  194. package/src/cmd/cloud/storage/download.ts +1 -1
  195. package/src/cmd/cloud/storage/get.ts +1 -1
  196. package/src/cmd/cloud/storage/list.ts +1 -1
  197. package/src/cmd/cloud/storage/upload.ts +1 -1
  198. package/src/cmd/cloud/stream/util.ts +7 -3
  199. package/src/cmd/cloud/thread/delete.ts +4 -7
  200. package/src/cmd/cloud/thread/get.ts +4 -7
  201. package/src/cmd/cloud/thread/list.ts +4 -7
  202. package/src/cmd/cloud/vector/util.ts +5 -3
  203. package/src/cmd/dev/index.ts +54 -21
  204. package/src/cmd/profile/current.ts +31 -0
  205. package/src/cmd/profile/index.ts +9 -1
  206. package/src/cmd/profile/show.ts +0 -1
  207. package/src/cmd/project/download.ts +15 -16
  208. package/src/cmd/project/template-flow.ts +6 -4
  209. package/src/cmd/project/templates.ts +9 -11
  210. package/src/command-prefix.ts +4 -1
  211. package/src/config.ts +150 -24
  212. package/src/download.ts +1 -1
  213. package/src/env-util.ts +3 -0
  214. package/src/schemas/deploy.ts +28 -0
  215. package/src/types.ts +11 -35
  216. package/src/utils/workbench-notify.ts +67 -0
@@ -1,5 +1,4 @@
1
1
  import { $ } from 'bun';
2
- import { z } from 'zod';
3
2
  import { join, relative, resolve, dirname, basename } from 'node:path';
4
3
  import { cpSync, existsSync, mkdirSync, rmSync } from 'node:fs';
5
4
  import gitParseUrl from 'git-url-parse';
@@ -12,34 +11,11 @@ import { createLogger } from '@agentuity/server';
12
11
  import type { LogLevel } from '../../types';
13
12
  import { generateWorkbenchMainTsx, generateWorkbenchIndexHtml } from './workbench-templates';
14
13
  import { analyzeWorkbench } from './ast';
15
- import { encodeWorkbenchConfig, StructuredError } from '@agentuity/core';
16
-
17
- export const DeployOptionsSchema = z.object({
18
- tag: z
19
- .array(z.string())
20
- .default(['latest'])
21
- .optional()
22
- .describe('One or more tags to add to the deployment'),
23
- logsUrl: z.url().optional().describe('The url to the CI build logs'),
24
- trigger: z
25
- .enum(['cli', 'workflow', 'webhook'])
26
- .default('cli')
27
- .optional()
28
- .describe('The trigger that caused the build'),
29
- commitUrl: z.url().optional().describe('The url to the CI commit'),
30
- message: z.string().optional().describe('The message to associate with this deployment'),
31
- provider: z.string().optional().describe('The CI provider name (attempts to autodetect)'),
32
- event: z
33
- .enum(['pull_request', 'push', 'manual', 'workflow'])
34
- .default('manual')
35
- .optional()
36
- .describe('The event that triggered the deployment'),
37
- pullRequestNumber: z.number().optional().describe('the pull request number'),
38
- pullRequestCommentId: z.string().optional().describe('the pull request comment id'),
39
- pullRequestURL: z.url().optional().describe('the pull request url'),
40
- });
41
-
42
- type DeployOptions = z.infer<typeof DeployOptionsSchema>;
14
+ import { StructuredError } from '@agentuity/core';
15
+ import { DeployOptionsSchema, type DeployOptions } from '../../schemas/deploy';
16
+
17
+ // Re-export for backward compatibility
18
+ export { DeployOptionsSchema };
43
19
 
44
20
  export interface BundleOptions extends DeployOptions {
45
21
  rootDir: string;
@@ -138,6 +114,15 @@ export async function bundle({
138
114
  mkdirSync(join(outDir, 'chunk'), { recursive: true });
139
115
  mkdirSync(join(outDir, 'asset'), { recursive: true });
140
116
 
117
+ // Pre-create all nested source directories in output
118
+ // This is needed because Bun.build with naming.entry preserves structure
119
+ // but doesn't create nested directories automatically
120
+ for (const entrypoint of appEntrypoints) {
121
+ const relPath = relative(rootDir, dirname(entrypoint));
122
+ const outputSubdir = join(outDir, relPath);
123
+ mkdirSync(outputSubdir, { recursive: true });
124
+ }
125
+
141
126
  const pkgFile = Bun.file(join(rootDir, 'package.json'));
142
127
  const pkgContents = JSON.parse(await pkgFile.text());
143
128
  const isProd = !dev;
@@ -270,10 +255,15 @@ export async function bundle({
270
255
  );
271
256
 
272
257
  if (webEntrypoints.length) {
258
+ const webOutDir = join(outDir, 'web');
259
+ mkdirSync(webOutDir, { recursive: true });
260
+ mkdirSync(join(webOutDir, 'chunk'), { recursive: true });
261
+ mkdirSync(join(webOutDir, 'asset'), { recursive: true });
262
+
273
263
  const config: Bun.BuildConfig = {
274
264
  entrypoints: webEntrypoints,
275
265
  root: webDir,
276
- outdir: join(outDir, 'web'),
266
+ outdir: webOutDir,
277
267
  define,
278
268
  sourcemap: dev ? 'inline' : 'linked',
279
269
  env: 'AGENTUITY_PUBLIC_*',
@@ -330,15 +320,9 @@ export async function bundle({
330
320
  const analysis = analyzeWorkbench(appContent);
331
321
 
332
322
  if (analysis.hasWorkbench) {
333
- // Encode workbench config for environment variable
334
- const config = analysis.config || { route: '/workbench', headers: {} };
335
- // Add port to config (defaults to 3500 if not provided)
336
- const configWithPort = { ...config, port: port || 3500 };
337
- const encodedConfig = encodeWorkbenchConfig(configWithPort);
338
- const workbenchDefine = {
339
- ...define,
340
- AGENTUITY_WORKBENCH_CONFIG_INLINE: JSON.stringify(encodedConfig),
341
- };
323
+ // Create workbench config with proper defaults
324
+ const defaultConfig = { route: '/workbench', headers: {}, port: port || 3500 };
325
+ const config = { ...defaultConfig, ...analysis.config };
342
326
  const logger = createLogger((process.env.AGENTUITY_LOG_LEVEL as LogLevel) || 'info');
343
327
  try {
344
328
  // Generate workbench files on the fly instead of using files from package
@@ -356,14 +340,13 @@ export async function bundle({
356
340
  const workbenchBuildConfig: Bun.BuildConfig = {
357
341
  entrypoints: [workbenchIndexFile],
358
342
  outdir: join(outDir, 'workbench'),
359
- define: workbenchDefine,
360
343
  sourcemap: dev ? 'inline' : 'linked',
361
- plugins: [AgentuityBundler],
344
+ plugins: [AgentuityBundler], // i dont think we need this plugin here
362
345
  target: 'browser',
363
346
  format: 'esm',
364
347
  banner: `// Generated file. DO NOT EDIT`,
365
- minify: true,
366
- splitting: true,
348
+ minify: !dev, // Disable minification in dev to avoid module resolution issues
349
+ splitting: !dev, // Disable code splitting in dev to avoid relative import resolution issues
367
350
  packages: 'bundle',
368
351
  naming: {
369
352
  entry: '[dir]/[name].[ext]',
@@ -390,7 +373,7 @@ export async function bundle({
390
373
  }
391
374
  // Clean up temp directory even on failure
392
375
  rmSync(tempWorkbenchDir, { recursive: true, force: true });
393
- process.exit(1);
376
+ logger.fatal('Workbench bundling failed');
394
377
  }
395
378
  } catch (error) {
396
379
  logger.error('Failed to bundle workbench:', error);
@@ -1,5 +1,6 @@
1
1
  import { z } from 'zod';
2
2
  import { resolve, join } from 'node:path';
3
+ import { getServiceUrls } from '@agentuity/server';
3
4
  import { createCommand } from '../../types';
4
5
  import { bundle } from './bundler';
5
6
  import * as tui from '../../tui';
@@ -40,7 +41,7 @@ export const command = createCommand({
40
41
  },
41
42
 
42
43
  async handler(ctx) {
43
- const { opts, projectDir, project, config } = ctx;
44
+ const { opts, projectDir, project } = ctx;
44
45
 
45
46
  const absoluteProjectDir = resolve(projectDir);
46
47
  const outDir = opts.outdir ? resolve(opts.outdir) : join(absoluteProjectDir, '.agentuity');
@@ -50,31 +51,21 @@ export const command = createCommand({
50
51
 
51
52
  const env: Map<string, string> = new Map();
52
53
 
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
- }
54
+ if (project) {
55
+ const serviceUrls = getServiceUrls(project.region);
56
+ env.set('AGENTUITY_TRANSPORT_URL', serviceUrls.catalyst);
57
+ env.set('AGENTUITY_CATALYST_URL', serviceUrls.catalyst);
58
+ env.set('AGENTUITY_VECTOR_URL', serviceUrls.vector);
59
+ env.set('AGENTUITY_OBJECTSTORE_URL', serviceUrls.objectstore);
60
+ env.set('AGENTUITY_KEYVALUE_URL', serviceUrls.keyvalue);
61
+ env.set('AGENTUITY_STREAM_URL', serviceUrls.stream);
62
+ env.set('AGENTUITY_CLOUD_ORG_ID', project.orgId);
63
+ env.set('AGENTUITY_CLOUD_PROJECT_ID', project.projectId);
64
+ env.set('AGENTUITY_REGION', project.region);
76
65
  }
77
66
 
67
+ ctx.logger.trace('setting env to %s', env);
68
+
78
69
  await bundle({
79
70
  rootDir: absoluteProjectDir,
80
71
  dev: opts.dev || false,
@@ -636,15 +636,17 @@ const AgentuityBundler: BunPlugin = {
636
636
  const workbenchConfig = await setupWorkbench(srcDir);
637
637
 
638
638
  if (existsSync(indexFile)) {
639
- inserts.push(`await (async () => {
640
- const { serveStatic } = require('hono/bun');
641
- const { getRouter, registerDevModeRoutes } = await import('@agentuity/runtime');
639
+ inserts.push(`import { serveStatic } from 'hono/bun';
640
+ import { getRouter, registerDevModeRoutes } from '@agentuity/runtime';
641
+ import { readFileSync, existsSync } from 'node:fs';
642
+
643
+ (() => {
642
644
  const router = getRouter()!;
643
645
 
644
646
  // Setup workbench routes if workbench was bundled
645
647
  const workbenchIndexPath = import.meta.dir + '/workbench/index.html';
646
- if (await Bun.file(workbenchIndexPath).exists()) {
647
- let workbenchIndex = await Bun.file(workbenchIndexPath).text();
648
+ if (existsSync(workbenchIndexPath)) {
649
+ let workbenchIndex = readFileSync(workbenchIndexPath, 'utf-8');
648
650
 
649
651
  // Always serve assets at /workbench/* regardless of HTML route
650
652
  const workbenchStatic = serveStatic({ root: import.meta.dir + '/workbench' });
@@ -662,7 +664,7 @@ const AgentuityBundler: BunPlugin = {
662
664
  router.get(route, (c) => c.html(workbenchIndex));
663
665
  }
664
666
 
665
- let index = await Bun.file(import.meta.dir + '/web/index.html').text();
667
+ let index = readFileSync(import.meta.dir + '/web/index.html', 'utf-8');
666
668
  if (${isDevMode}) {
667
669
  const end = index.lastIndexOf('</html>');
668
670
  const html = registerDevModeRoutes(router);
@@ -726,12 +728,13 @@ const AgentuityBundler: BunPlugin = {
726
728
  // Generate lifecycle types if setup() is present in app.ts
727
729
  await setupLifecycleTypes(rootDir, outDir, srcDir, logger);
728
730
 
729
- // Only create the workbench metadata route if workbench is actually configured
731
+ // Only create the workbench routes if workbench is actually configured
730
732
  if (workbenchConfig) {
731
733
  inserts.push(`await (async() => {
732
- const { createWorkbenchMetadataRoute, getRouter } = await import('@agentuity/runtime');
733
- const router = getRouter()!;
734
- router.get('/_agentuity/workbench/metadata.json', createWorkbenchMetadataRoute());
734
+ const { createWorkbenchRouter, getRouter } = await import('@agentuity/runtime');
735
+ const router = getRouter()!;
736
+ const workbenchRouter = createWorkbenchRouter();
737
+ router.route('/', workbenchRouter);
735
738
  })();`);
736
739
  }
737
740
 
@@ -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'),
@@ -49,7 +49,7 @@ export const createSubcommand = defineSubcommand({
49
49
  };
50
50
  }
51
51
 
52
- const catalystClient = getCatalystAPIClient(config, logger, auth);
52
+ const catalystClient = getCatalystAPIClient(config, logger, auth, region);
53
53
 
54
54
  try {
55
55
  const created = await tui.spinner({
@@ -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
  }
@@ -37,7 +37,7 @@ export const deleteSubcommand = createSubcommand({
37
37
  async handler(ctx) {
38
38
  const { logger, args, opts, config, orgId, region, auth, options } = ctx;
39
39
 
40
- const catalystClient = getCatalystAPIClient(config, logger, auth);
40
+ const catalystClient = getCatalystAPIClient(config, logger, auth, region);
41
41
 
42
42
  let dbName = args.name;
43
43
 
@@ -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
  },
@@ -47,7 +67,7 @@ export const getSubcommand = createSubcommand({
47
67
  async handler(ctx) {
48
68
  const { logger, args, opts, options, orgId, region, config, auth } = ctx;
49
69
 
50
- const catalystClient = getCatalystAPIClient(config, logger, auth);
70
+ const catalystClient = getCatalystAPIClient(config, logger, auth, region);
51
71
 
52
72
  const resources = await tui.spinner({
53
73
  message: `Fetching database ${args.name}`,
@@ -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
  });
@@ -48,7 +48,7 @@ export const listSubcommand = createSubcommand({
48
48
  async handler(ctx) {
49
49
  const { logger, opts, options, orgId, region, config, auth } = ctx;
50
50
 
51
- const catalystClient = getCatalystAPIClient(config, logger, auth);
51
+ const catalystClient = getCatalystAPIClient(config, logger, auth, region);
52
52
 
53
53
  const resources = await tui.spinner({
54
54
  message: `Fetching databases for ${orgId} in ${region}`,
@@ -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, region);
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
+ });