@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
@@ -2,6 +2,7 @@
2
2
  import { z } from 'zod';
3
3
  import { resolve, join } from 'node:path';
4
4
  import { bundle } from '../build/bundler';
5
+ import { getServiceUrls } from '@agentuity/server';
5
6
  import { getBuildMetadata } from '../build/plugin';
6
7
  import { existsSync, type FSWatcher, watch, statSync, readdirSync } from 'node:fs';
7
8
  import {
@@ -15,12 +16,13 @@ import { type Config, createCommand } from '../../types';
15
16
  import * as tui from '../../tui';
16
17
  import { createAgentTemplates, createAPITemplates } from './templates';
17
18
  import { generateEndpoint, type DevmodeResponse } from './api';
18
- import { APIClient, getAPIBaseURL } from '../../api';
19
+ import { APIClient, getAPIBaseURL, getGravityDevModeURL } from '../../api';
19
20
  import { download } from './download';
20
21
  import { createDevmodeSyncService } from './sync';
21
22
  import { getDevmodeDeploymentId } from '../build/ast';
22
23
  import { BuildMetadata } from '@agentuity/server';
23
24
  import { getCommand } from '../../command-prefix';
25
+ import { notifyWorkbenchClients } from '../../utils/workbench-notify';
24
26
 
25
27
  const shouldDisableInteractive = (interactive?: boolean) => {
26
28
  if (!interactive) {
@@ -55,6 +57,12 @@ export const command = createCommand({
55
57
  .max(65535)
56
58
  .default(3500)
57
59
  .describe('The TCP port to start the dev start'),
60
+ watch: z
61
+ .array(z.string())
62
+ .optional()
63
+ .describe(
64
+ 'Additional paths to watch for changes (e.g., --watch ../packages/workbench/dist)'
65
+ ),
58
66
  }),
59
67
  },
60
68
  optional: { auth: 'Continue without an account (local only)', project: true },
@@ -94,6 +102,7 @@ export const command = createCommand({
94
102
 
95
103
  let devmode: DevmodeResponse | undefined;
96
104
  let gravityBin: string | undefined;
105
+ let gravityURL: string | undefined;
97
106
 
98
107
  if (auth && project && opts.public) {
99
108
  // Generate devmode endpoint only when using --public
@@ -111,6 +120,8 @@ export const command = createCommand({
111
120
  await saveConfig(_config);
112
121
  config = _config;
113
122
  devmode = endpoint;
123
+ gravityURL = getGravityDevModeURL(project.region, config);
124
+ logger.error('gravity url: %s', gravityURL);
114
125
  }
115
126
 
116
127
  logger.debug(
@@ -176,33 +187,23 @@ export const command = createCommand({
176
187
  env.AGENTUITY_SDK_DEV_MODE = 'true';
177
188
  env.AGENTUITY_ENV = 'development';
178
189
  env.NODE_ENV = 'development';
190
+ env.AGENTUITY_REGION = project?.region;
179
191
  env.PORT = Number(opts.port).toFixed();
180
192
  env.AGENTUITY_PORT = env.PORT;
193
+ const serviceUrls = getServiceUrls(project?.region);
181
194
  if (options.logLevel !== undefined) env.AGENTUITY_LOG_LEVEL = options.logLevel;
182
195
  // Pass through AGENTUITY_SDK_LOG_LEVEL for internal SDK logger
183
196
  if (process.env.AGENTUITY_SDK_LOG_LEVEL) {
184
197
  env.AGENTUITY_SDK_LOG_LEVEL = process.env.AGENTUITY_SDK_LOG_LEVEL;
185
198
  }
186
199
  env.AGENTUITY_FORCE_LOCAL_SERVICES = opts.local === true ? 'true' : 'false';
187
- if (config?.overrides?.transport_url) {
188
- env.AGENTUITY_TRANSPORT_URL = config.overrides.transport_url;
189
- }
190
- if (config?.overrides?.catalyst_url) {
191
- env.AGENTUITY_CATALYST_URL = config.overrides.catalyst_url;
192
- }
193
- if (config?.overrides?.vector_url) {
194
- env.AGENTUITY_VECTOR_URL = config.overrides.vector_url;
195
- }
196
- if (config?.overrides?.object_url) {
197
- env.AGENTUITY_OBJECTSTORE_URL = config.overrides.object_url;
198
- }
199
- if (config?.overrides?.kv_url) {
200
- env.AGENTUITY_KEYVALUE_URL = config.overrides.kv_url;
201
- }
202
- if (config?.overrides?.stream_url) {
203
- env.AGENTUITY_STREAM_URL = config.overrides.stream_url;
204
- }
205
200
  if (project) {
201
+ env.AGENTUITY_TRANSPORT_URL = serviceUrls.catalyst;
202
+ env.AGENTUITY_CATALYST_URL = serviceUrls.catalyst;
203
+ env.AGENTUITY_VECTOR_URL = serviceUrls.vector;
204
+ env.AGENTUITY_OBJECTSTORE_URL = serviceUrls.objectstore;
205
+ env.AGENTUITY_KEYVALUE_URL = serviceUrls.keyvalue;
206
+ env.AGENTUITY_STREAM_URL = serviceUrls.stream;
206
207
  env.AGENTUITY_CLOUD_ORG_ID = project.orgId;
207
208
  env.AGENTUITY_CLOUD_PROJECT_ID = project.projectId;
208
209
  }
@@ -230,6 +231,19 @@ export const command = createCommand({
230
231
 
231
232
  // Watch directories instead of files to survive atomic replacements (sed -i, cp)
232
233
  const watches = [rootDir];
234
+
235
+ // Add additional watch paths from options
236
+ if (opts.watch) {
237
+ for (const watchPath of opts.watch) {
238
+ const resolvedPath = resolve(rootDir, watchPath);
239
+ if (existsSync(resolvedPath)) {
240
+ watches.push(resolvedPath);
241
+ logger.debug('Added additional watch path: %s', resolvedPath);
242
+ } else {
243
+ logger.warn('Watch path does not exist: %s', resolvedPath);
244
+ }
245
+ }
246
+ }
233
247
  const watchers: FSWatcher[] = [];
234
248
  let failures = 0;
235
249
  let running = false;
@@ -249,7 +263,7 @@ export const command = createCommand({
249
263
  let gravityClient: Bun.Subprocess | undefined;
250
264
  let initialStartupComplete = false;
251
265
 
252
- const sdkKey = await loadProjectSDKKey(rootDir);
266
+ const sdkKey = await loadProjectSDKKey(logger, rootDir);
253
267
  if (!sdkKey) {
254
268
  tui.warning(`Couldn't find the AGENTUITY_SDK_KEY in ${rootDir} .env file`);
255
269
  }
@@ -275,7 +289,7 @@ export const command = createCommand({
275
289
  '--port',
276
290
  env.PORT!,
277
291
  '--url',
278
- config?.overrides?.gravity_url ?? 'grpc://devmode.agentuity.com',
292
+ gravityURL!,
279
293
  '--log-level',
280
294
  process.env.AGENTUITY_GRAVITY_LOG_LEVEL ?? 'error',
281
295
  ],
@@ -450,6 +464,16 @@ export const command = createCommand({
450
464
  checkRestartThrottle();
451
465
  tui.info('Restarting on file change');
452
466
  showedRestartMessage = true;
467
+
468
+ // Notify workbench clients before killing the server
469
+ await notifyWorkbenchClients({
470
+ port: opts.port,
471
+ message: 'restarting',
472
+ });
473
+
474
+ // Small delay to ensure the restart message is processed before killing server
475
+ await new Promise((resolve) => setTimeout(resolve, 200));
476
+
453
477
  await kill();
454
478
  logger.trace('Server killed, continuing with restart');
455
479
  // Continue with restart after kill completes
@@ -624,6 +648,15 @@ export const command = createCommand({
624
648
  logger.trace('Initial startup complete, file watcher restarts now enabled');
625
649
  }
626
650
 
651
+ // Notify workbench clients that the server is alive and ready
652
+ // Use setTimeout to ensure server is fully ready before notifying
653
+ setTimeout(async () => {
654
+ await notifyWorkbenchClients({
655
+ port: opts.port,
656
+ message: 'alive',
657
+ });
658
+ }, 500);
659
+
627
660
  logger.trace('Attaching exit handler to dev server process...');
628
661
  // Attach non-blocking exit handler
629
662
  exitPromise
@@ -0,0 +1,31 @@
1
+ import { z } from 'zod';
2
+ import { createSubcommand } from '../../types';
3
+ import { getCommand } from '../../command-prefix';
4
+
5
+ export const currentCommand = createSubcommand({
6
+ name: 'current',
7
+ description: 'Show the name of the currently active profile',
8
+ tags: ['read-only', 'fast'],
9
+ idempotent: true,
10
+ aliases: [],
11
+ examples: [
12
+ { command: getCommand('profile current'), description: 'Show current profile' },
13
+ { command: getCommand('profile current --json'), description: 'Show output in JSON format' },
14
+ ],
15
+ schema: {
16
+ response: z.string().describe('The name of the current profile'),
17
+ },
18
+
19
+ async handler(ctx) {
20
+ const { options } = ctx;
21
+ const profileName = ctx.config?.name || 'production';
22
+
23
+ if (!options.json) {
24
+ console.log(profileName);
25
+ }
26
+
27
+ return profileName;
28
+ },
29
+ });
30
+
31
+ export default currentCommand;
@@ -4,6 +4,7 @@ import { useCommand } from './use';
4
4
  import { listCommand } from './list';
5
5
  import { showCommand } from './show';
6
6
  import { deleteCommand } from './delete';
7
+ import { currentCommand } from './current';
7
8
  import { getCommand } from '../../command-prefix';
8
9
 
9
10
  export const command = createCommand({
@@ -18,5 +19,12 @@ export const command = createCommand({
18
19
  description: 'Switch to production profile',
19
20
  },
20
21
  ],
21
- subcommands: [createProfileCmd, useCommand, listCommand, showCommand, deleteCommand],
22
+ subcommands: [
23
+ createProfileCmd,
24
+ useCommand,
25
+ listCommand,
26
+ showCommand,
27
+ deleteCommand,
28
+ currentCommand,
29
+ ],
22
30
  });
@@ -12,7 +12,6 @@ export const showCommand = createSubcommand({
12
12
  name: 'show',
13
13
  description: 'Show the configuration of a profile',
14
14
  tags: ['read-only', 'fast'],
15
- aliases: ['current'],
16
15
  examples: [
17
16
  { command: getCommand('profile show'), description: 'Show details' },
18
17
  { command: getCommand('profile show production'), description: 'Show details' },
@@ -22,7 +22,6 @@ import { generateLLMPrompt as generateWebPrompt } from '../ai/prompt/web';
22
22
  import { generateLLMPrompt as generateAPIPrompt } from '../ai/prompt/api';
23
23
  import type { TemplateInfo } from './templates';
24
24
 
25
- const GITHUB_REPO = 'agentuity/sdk';
26
25
  const GITHUB_BRANCH = 'main';
27
26
 
28
27
  interface DownloadOptions {
@@ -91,14 +90,14 @@ export async function downloadTemplate(options: DownloadOptions): Promise<void>
91
90
  // Download from GitHub
92
91
  const branch = templateBranch || GITHUB_BRANCH;
93
92
  const templatePath = `templates/${template.directory}`;
94
- const url = `https://codeload.github.com/${GITHUB_REPO}/tar.gz/${branch}`;
93
+ const url = `https://agentuity.sh/template/sdk/${branch}/tar.gz`;
95
94
  const tempDir = mkdtempSync(join(tmpdir(), 'agentuity-'));
96
95
  const tarballPath = join(tempDir, 'download.tar.gz');
97
96
 
98
- logger.debug('[download] URL:', url);
99
- logger.debug('[download] Branch:', branch);
100
- logger.debug('[download] Template path:', templatePath);
101
- logger.debug('[download] Temp dir:', tempDir);
97
+ logger.debug('[download] URL: %s', url);
98
+ logger.debug('[download] Branch: %s', branch);
99
+ logger.debug('[download] Template path: %s', templatePath);
100
+ logger.debug('[download] Temp dir: %s', tempDir);
102
101
 
103
102
  try {
104
103
  // Step 1: Download tarball to temp file
@@ -120,8 +119,8 @@ export async function downloadTemplate(options: DownloadOptions): Promise<void>
120
119
  const buffer = Buffer.concat(chunks);
121
120
  await Bun.write(tarballPath, buffer);
122
121
 
123
- logger.debug('[download] Downloaded bytes:', buffer.length);
124
- logger.debug('[download] Tarball path:', tarballPath);
122
+ logger.debug('[download] Downloaded bytes: %dbytes', buffer.length);
123
+ logger.debug('[download] Tarball path: %s', tarballPath);
125
124
  }
126
125
  );
127
126
 
@@ -132,8 +131,8 @@ export async function downloadTemplate(options: DownloadOptions): Promise<void>
132
131
  mkdirSync(extractDir, { recursive: true });
133
132
 
134
133
  const prefix = `sdk-${branch}/${templatePath}/`;
135
- logger.debug('[extract] Extract dir:', extractDir);
136
- logger.debug('[extract] Filter prefix:', prefix);
134
+ logger.debug('[extract] Extract dir: %s', extractDir);
135
+ logger.debug('[extract] Filter prefix: %s', prefix);
137
136
 
138
137
  // Track extraction stats for debugging
139
138
  let ignoredCount = 0;
@@ -152,8 +151,8 @@ export async function downloadTemplate(options: DownloadOptions): Promise<void>
152
151
  // This is a file/dir we want to extract - strip the prefix
153
152
  header.name = header.name.substring(prefix.length);
154
153
  mappedEntries.add(header.name); // Track that we mapped this
155
- logger.debug('[extract] MAP:', originalName, '->', header.name);
156
- logger.debug('[extract] EXTRACT:', originalName);
154
+ logger.debug('[extract] MAP: %s -> %s', originalName, header.name);
155
+ logger.debug('[extract] EXTRACT: %s', originalName);
157
156
  extractedCount++;
158
157
  }
159
158
  return header;
@@ -172,7 +171,7 @@ export async function downloadTemplate(options: DownloadOptions): Promise<void>
172
171
  }
173
172
 
174
173
  // Otherwise, ignore it
175
- logger.debug('[extract] IGNORE:', header.name);
174
+ logger.debug('[extract] IGNORE: %s', header.name);
176
175
  ignoredCount++;
177
176
  return true;
178
177
  },
@@ -183,14 +182,14 @@ export async function downloadTemplate(options: DownloadOptions): Promise<void>
183
182
  await finished(extractor);
184
183
 
185
184
  logger.debug('[extract] Extraction complete');
186
- logger.debug('[extract] Ignored entries:', ignoredCount);
187
- logger.debug('[extract] Extracted entries:', extractedCount);
185
+ logger.debug('[extract] Ignored entries: %d', ignoredCount);
186
+ logger.debug('[extract] Extracted entries: %d', extractedCount);
188
187
 
189
188
  // Step 3: Copy extracted files to destination
190
189
  await cleanup(extractDir, dest);
191
190
  } finally {
192
191
  // Clean up temp directory
193
- logger.debug('[cleanup] Removing temp dir:', tempDir);
192
+ logger.debug('[cleanup] Removing temp dir: %s', tempDir);
194
193
  rmSync(tempDir, { recursive: true, force: true });
195
194
  }
196
195
  }
@@ -74,7 +74,7 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
74
74
  message: 'Fetching templates',
75
75
  clearOnSuccess: true,
76
76
  callback: async () => {
77
- return fetchTemplates(templateDir, templateBranch);
77
+ return fetchTemplates(logger, templateDir, templateBranch);
78
78
  },
79
79
  });
80
80
 
@@ -90,7 +90,7 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
90
90
  let catalystClient: ServerAPIClient | undefined;
91
91
 
92
92
  if (auth) {
93
- const serviceUrls = getServiceUrls();
93
+ const serviceUrls = getServiceUrls(region!);
94
94
  const catalystUrl = config?.overrides?.catalyst_url ?? serviceUrls.catalyst;
95
95
  catalystClient = new ServerAPIClient(catalystUrl, logger, auth.apiKey);
96
96
  }
@@ -308,6 +308,8 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
308
308
  if (auth && apiClient && orgId) {
309
309
  let projectId: string | undefined;
310
310
 
311
+ const cloudRegion = region ?? process.env.AGENTUITY_REGION ?? 'usc';
312
+
311
313
  await tui.spinner({
312
314
  message: 'Registering your project',
313
315
  clearOnSuccess: true,
@@ -315,7 +317,7 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
315
317
  const project = await projectCreate(apiClient, {
316
318
  name: projectName,
317
319
  orgId,
318
- cloudRegion: region ?? 'usc',
320
+ cloudRegion,
319
321
  });
320
322
  projectId = project.id;
321
323
  return createProjectConfig(dest, {
@@ -325,7 +327,7 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
325
327
  deployment: {
326
328
  resources: resourceConfig,
327
329
  },
328
- region: region ?? 'usc',
330
+ region: cloudRegion,
329
331
  });
330
332
  },
331
333
  });
@@ -1,8 +1,6 @@
1
- import { StructuredError } from '@agentuity/core';
1
+ import { StructuredError, Logger } from '@agentuity/core';
2
2
 
3
- const GITHUB_REPO = 'agentuity/sdk';
4
3
  const GITHUB_BRANCH = 'main';
5
- const TEMPLATES_JSON_PATH = 'templates/templates.json';
6
4
 
7
5
  export interface TemplateInfo {
8
6
  id: string;
@@ -18,7 +16,11 @@ interface TemplatesManifest {
18
16
  const TemplateMissingConfigurationError = StructuredError('TemplateMissingConfigurationError');
19
17
  const TemplateDownloadError = StructuredError('TemplateDownloadError')<{ status: number }>();
20
18
 
21
- export async function fetchTemplates(localDir?: string, branch?: string): Promise<TemplateInfo[]> {
19
+ export async function fetchTemplates(
20
+ logger: Logger,
21
+ localDir?: string,
22
+ branch?: string
23
+ ): Promise<TemplateInfo[]> {
22
24
  // Load from local directory if provided
23
25
  if (localDir) {
24
26
  const { join } = await import('node:path');
@@ -38,15 +40,11 @@ export async function fetchTemplates(localDir?: string, branch?: string): Promis
38
40
 
39
41
  // Fetch from GitHub
40
42
  const branchToUse = branch || GITHUB_BRANCH;
41
- const url = `https://raw.githubusercontent.com/${GITHUB_REPO}/${branchToUse}/${TEMPLATES_JSON_PATH}`;
43
+ const url = `https://agentuity.sh/template/sdk/${branchToUse}`;
42
44
 
43
- const headers: Record<string, string> = {};
44
- if (process.env.GITHUB_TOKEN) {
45
- headers['Authorization'] = `token ${process.env.GITHUB_TOKEN}`;
46
- }
47
-
48
- const response = await fetch(url, { headers });
45
+ const response = await fetch(url);
49
46
  if (!response.ok) {
47
+ logger.trace('error fetching template from %s. %s', url, await response.text());
50
48
  throw new TemplateDownloadError({
51
49
  status: response.status,
52
50
  message: `Failed to fetch templates: ${response.statusText}`,
@@ -17,10 +17,13 @@ export function getCommandPrefix(): string {
17
17
  const scriptPath = process.argv[1] || '';
18
18
  const normalized = path.normalize(scriptPath);
19
19
 
20
+ const isCompiledBinary =
21
+ process.argv[0] === 'bun' && scriptPath.startsWith('/$bunfs/root/agentuity-');
22
+
20
23
  // If we have AGENTUITY_CLI_VERSION set we are running from compiled binary OR
21
24
  // If the script is in node_modules/.bin or a global bin directory, it's likely global
22
25
  const isGlobal =
23
- process.env.AGENTUITY_CLI_VERSION ||
26
+ isCompiledBinary ||
24
27
  (normalized.includes(`${path.sep}bin${path.sep}`) &&
25
28
  !normalized.includes(`${path.sep}node_modules${path.sep}`) &&
26
29
  !normalized.includes(path.join('packages', 'cli', 'bin')));
package/src/config.ts CHANGED
@@ -233,7 +233,11 @@ export async function saveConfig(config: Config, customPath?: string): Promise<v
233
233
  const configPath = customPath || (await getProfile());
234
234
  await ensureConfigDir();
235
235
 
236
- const content = formatYAML(config);
236
+ // Strip auth from config before saving (never store auth in config file)
237
+ const configToSave = { ...config };
238
+ delete configToSave.auth;
239
+
240
+ const content = formatYAML(configToSave);
237
241
  await writeFile(configPath, content + '\n', { mode: 0o600 });
238
242
  // Ensure existing files get correct permissions on upgrade
239
243
  await chmod(configPath, 0o600);
@@ -252,26 +256,61 @@ async function getOrInitConfig(): Promise<Config> {
252
256
 
253
257
  export async function saveAuth(auth: AuthData): Promise<void> {
254
258
  const config = await getOrInitConfig();
255
- config.auth = {
259
+ const profileName = config.name || defaultProfileName;
260
+
261
+ const authData = {
256
262
  api_key: auth.apiKey,
257
263
  user_id: auth.userId,
258
264
  expires: auth.expires.getTime(),
259
265
  };
260
- config.preferences = config.preferences || {};
261
- (config.preferences as Record<string, unknown>).orgId = '';
262
- await saveConfig(config);
266
+
267
+ // Try to store in Bun secrets API
268
+ try {
269
+ await Bun.secrets.set({
270
+ service: `agentuity.cli.${profileName}`,
271
+ name: 'auth',
272
+ value: JSON.stringify(authData),
273
+ });
274
+
275
+ // Successfully stored in secrets, ensure auth is removed from config file
276
+ if (config.auth) {
277
+ delete config.auth;
278
+ await saveConfig(config);
279
+ }
280
+ } catch {
281
+ // Bun.secrets API not available or failed, fallback to config file
282
+ config.auth = authData;
283
+ config.preferences = config.preferences || {};
284
+ (config.preferences as Record<string, unknown>).orgId = '';
285
+
286
+ // Save with auth in config as fallback (saveConfig will try to strip it but we're setting it here)
287
+ const configPath = await getProfile();
288
+ await ensureConfigDir();
289
+ const content = formatYAML(config);
290
+ await writeFile(configPath, content + '\n', { mode: 0o600 });
291
+ await chmod(configPath, 0o600);
292
+ cachedConfig = config;
293
+ }
263
294
  }
264
295
 
265
296
  export async function clearAuth(): Promise<void> {
266
297
  const config = await getOrInitConfig();
267
- config.auth = {
268
- api_key: '',
269
- user_id: '',
270
- expires: Date.now(),
271
- };
272
- config.preferences = config.preferences || {};
273
- (config.preferences as Record<string, unknown>).orgId = '';
274
- await saveConfig(config);
298
+ const profileName = config.name || defaultProfileName;
299
+
300
+ // Try to delete from Bun secrets API
301
+ try {
302
+ await Bun.secrets.delete({ service: `agentuity.cli.${profileName}`, name: 'auth' });
303
+ } catch {
304
+ // Bun.secrets API not available or failed
305
+ }
306
+
307
+ // Clear auth from config file (for backwards compatibility)
308
+ if (config.auth) {
309
+ delete config.auth;
310
+ config.preferences = config.preferences || {};
311
+ (config.preferences as Record<string, unknown>).orgId = '';
312
+ await saveConfig(config);
313
+ }
275
314
  }
276
315
 
277
316
  export async function saveProjectDir(projectDir: string): Promise<void> {
@@ -289,8 +328,59 @@ export async function saveOrgId(orgId: string): Promise<void> {
289
328
  await saveConfig(config);
290
329
  }
291
330
 
331
+ async function migrateAuthToSecrets(
332
+ config: Config,
333
+ profileName: string,
334
+ auth: { api_key: string; user_id: string; expires: number }
335
+ ): Promise<boolean> {
336
+ try {
337
+ const authData = {
338
+ api_key: auth.api_key,
339
+ user_id: auth.user_id,
340
+ expires: auth.expires,
341
+ };
342
+
343
+ await Bun.secrets.set({
344
+ service: `agentuity.cli.${profileName}`,
345
+ name: 'auth',
346
+ value: JSON.stringify(authData),
347
+ });
348
+
349
+ // Successfully migrated, remove from config file
350
+ delete config.auth;
351
+ await saveConfig(config);
352
+
353
+ return true;
354
+ } catch {
355
+ // Migration failed, leave in config file
356
+ return false;
357
+ }
358
+ }
359
+
292
360
  export async function getAuth(): Promise<AuthData | null> {
293
- // allow automated login from environment variables if present
361
+ const config = await loadConfig();
362
+ const profileName = config?.name || defaultProfileName;
363
+
364
+ // Priority 1: Try Bun secrets API first (most secure)
365
+ try {
366
+ const authJson = await Bun.secrets.get({
367
+ service: `agentuity.cli.${profileName}`,
368
+ name: 'auth',
369
+ });
370
+
371
+ if (authJson) {
372
+ const auth = JSON.parse(authJson) as { api_key: string; user_id: string; expires: number };
373
+ return {
374
+ apiKey: auth.api_key,
375
+ userId: auth.user_id,
376
+ expires: new Date(auth.expires),
377
+ };
378
+ }
379
+ } catch {
380
+ // Bun.secrets API not available or failed, fallback to other methods
381
+ }
382
+
383
+ // Priority 2: Allow automated login from environment variables
294
384
  if (process.env.AGENTUITY_CLI_API_KEY && process.env.AGENTUITY_USER_ID) {
295
385
  return {
296
386
  apiKey: process.env.AGENTUITY_CLI_API_KEY,
@@ -299,7 +389,7 @@ export async function getAuth(): Promise<AuthData | null> {
299
389
  };
300
390
  }
301
391
 
302
- const config = await loadConfig();
392
+ // Priority 3: Fallback to config file (backwards compatibility + migration)
303
393
  if (!config) return null;
304
394
  const auth = config.auth as { api_key?: string; user_id?: string; expires?: number } | undefined;
305
395
 
@@ -307,10 +397,23 @@ export async function getAuth(): Promise<AuthData | null> {
307
397
  return null;
308
398
  }
309
399
 
400
+ // Check if token is unexpired
401
+ const expiresDate = new Date(auth.expires || 0);
402
+ const isExpired = expiresDate.getTime() <= Date.now();
403
+
404
+ // If unexpired, attempt to migrate to Bun.secrets
405
+ if (!isExpired) {
406
+ await migrateAuthToSecrets(config, profileName, {
407
+ api_key: auth.api_key,
408
+ user_id: auth.user_id,
409
+ expires: auth.expires || 0,
410
+ });
411
+ }
412
+
310
413
  return {
311
414
  apiKey: auth.api_key,
312
415
  userId: auth.user_id,
313
- expires: new Date(auth.expires || 0),
416
+ expires: expiresDate,
314
417
  };
315
418
  }
316
419
 
@@ -631,37 +734,60 @@ export async function loadBuildMetadata(dir: string): Promise<BuildMetadata> {
631
734
  return result.data;
632
735
  }
633
736
 
634
- export async function loadProjectSDKKey(projectDir: string): Promise<string | undefined> {
737
+ export async function loadProjectSDKKey(
738
+ logger: Logger,
739
+ projectDir: string
740
+ ): Promise<string | undefined> {
741
+ const c = await getOrInitConfig();
635
742
  const files: string[] =
636
- process.env.NODE_ENV === 'production'
743
+ process.env.NODE_ENV === 'production' || c?.name !== 'local'
637
744
  ? ['.env', '.env.production']
638
- : ['.env.development', '.env.local', '.env'];
639
- const c = await getOrInitConfig();
745
+ : ['.env.development', '.env'];
640
746
  if (c) {
641
747
  files.unshift(`.env.${c.name}`);
642
748
  }
749
+ logger.trace(`[SDK_KEY] Searching for AGENTUITY_SDK_KEY in files: ${files.join(', ')}`);
750
+ logger.trace(`[SDK_KEY] Project directory: ${projectDir}`);
751
+ logger.trace(`[SDK_KEY] NODE_ENV: ${process.env.NODE_ENV}`);
643
752
  for (const filename of files) {
644
753
  const fn = join(projectDir, filename);
754
+ logger.trace(`[SDK_KEY] Checking file: ${fn}`);
645
755
  if (existsSync(fn)) {
756
+ logger.trace(`[SDK_KEY] File exists: ${fn}`);
646
757
  const buf = await Bun.file(fn).text();
647
758
  const tok = buf.split(/\n/);
648
759
  for (const t of tok) {
649
760
  if (t.charAt(0) !== '#' && t.startsWith('AGENTUITY_SDK_KEY=')) {
650
761
  const i = t.indexOf('=');
651
- return t.substring(i + 1).trim();
762
+ const key = t.substring(i + 1).trim();
763
+ logger.trace(`[SDK_KEY] Found AGENTUITY_SDK_KEY in: ${fn}`);
764
+ logger.trace(`[SDK_KEY] Key value: ${key.substring(0, 10)}...`);
765
+ return key;
652
766
  }
653
767
  }
768
+ logger.trace(`[SDK_KEY] No AGENTUITY_SDK_KEY found in: ${fn}`);
769
+ } else {
770
+ logger.trace(`[SDK_KEY] File does not exist: ${fn}`);
654
771
  }
655
772
  }
773
+ logger.trace(`[SDK_KEY] AGENTUITY_SDK_KEY not found in any file`);
656
774
  }
657
775
 
658
- export function getCatalystAPIClient(config: Config | null, logger: Logger, auth: AuthData) {
659
- const serviceUrls = getServiceUrls();
660
- const catalystUrl = config?.overrides?.catalyst_url ?? serviceUrls.catalyst;
776
+ export function getCatalystAPIClient(
777
+ config: Config | null,
778
+ logger: Logger,
779
+ auth: AuthData,
780
+ region: string
781
+ ) {
782
+ const serviceUrls = getServiceUrls(region);
783
+ const catalystUrl = serviceUrls.catalyst;
661
784
  return new ServerAPIClient(catalystUrl, logger, auth.apiKey);
662
785
  }
663
786
 
664
787
  export function getIONHost(config: Config | null) {
788
+ if (config?.name === 'local') {
789
+ return 'ion.agentuity.io';
790
+ }
665
791
  const url = new URL(config?.overrides?.ion_url ?? 'https://ion.agentuity.cloud');
666
792
  return url.hostname;
667
793
  }
package/src/download.ts CHANGED
@@ -30,7 +30,7 @@ export async function downloadWithProgress(
30
30
  url,
31
31
  status: response.status,
32
32
  sessionId: response.headers.get('x-session-id'),
33
- error: `Download failed: ${response.statusText}`,
33
+ message: `Download failed: ${response.statusText}`,
34
34
  });
35
35
  }
36
36