@agentuity/cli 0.0.104 → 0.0.106

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 (214) hide show
  1. package/bin/cli.ts +6 -3
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +93 -21
  4. package/dist/cli.js.map +1 -1
  5. package/dist/cmd/ai/prompt/version.d.ts +1 -0
  6. package/dist/cmd/ai/prompt/version.d.ts.map +1 -1
  7. package/dist/cmd/ai/prompt/version.js +3 -2
  8. package/dist/cmd/ai/prompt/version.js.map +1 -1
  9. package/dist/cmd/build/ast.d.ts.map +1 -1
  10. package/dist/cmd/build/ast.js +179 -37
  11. package/dist/cmd/build/ast.js.map +1 -1
  12. package/dist/cmd/build/entry-generator.d.ts.map +1 -1
  13. package/dist/cmd/build/entry-generator.js +24 -14
  14. package/dist/cmd/build/entry-generator.js.map +1 -1
  15. package/dist/cmd/build/vite/registry-generator.d.ts.map +1 -1
  16. package/dist/cmd/build/vite/registry-generator.js +8 -9
  17. package/dist/cmd/build/vite/registry-generator.js.map +1 -1
  18. package/dist/cmd/build/vite/vite-asset-server.d.ts.map +1 -1
  19. package/dist/cmd/build/vite/vite-asset-server.js.map +1 -1
  20. package/dist/cmd/cloud/db/create.d.ts.map +1 -1
  21. package/dist/cmd/cloud/db/create.js +11 -2
  22. package/dist/cmd/cloud/db/create.js.map +1 -1
  23. package/dist/cmd/cloud/db/delete.d.ts.map +1 -1
  24. package/dist/cmd/cloud/db/delete.js +13 -2
  25. package/dist/cmd/cloud/db/delete.js.map +1 -1
  26. package/dist/cmd/cloud/deploy.js +3 -3
  27. package/dist/cmd/cloud/deploy.js.map +1 -1
  28. package/dist/cmd/cloud/env/delete.js +1 -1
  29. package/dist/cmd/cloud/env/delete.js.map +1 -1
  30. package/dist/cmd/cloud/env/import.js +4 -4
  31. package/dist/cmd/cloud/env/import.js.map +1 -1
  32. package/dist/cmd/cloud/env/pull.d.ts.map +1 -1
  33. package/dist/cmd/cloud/env/pull.js +7 -9
  34. package/dist/cmd/cloud/env/pull.js.map +1 -1
  35. package/dist/cmd/cloud/env/push.js +2 -2
  36. package/dist/cmd/cloud/env/push.js.map +1 -1
  37. package/dist/cmd/cloud/env/set.js +3 -3
  38. package/dist/cmd/cloud/env/set.js.map +1 -1
  39. package/dist/cmd/cloud/index.d.ts.map +1 -1
  40. package/dist/cmd/cloud/index.js +2 -0
  41. package/dist/cmd/cloud/index.js.map +1 -1
  42. package/dist/cmd/cloud/sandbox/cp.d.ts +3 -0
  43. package/dist/cmd/cloud/sandbox/cp.d.ts.map +1 -0
  44. package/dist/cmd/cloud/sandbox/cp.js +334 -0
  45. package/dist/cmd/cloud/sandbox/cp.js.map +1 -0
  46. package/dist/cmd/cloud/sandbox/create.d.ts +3 -0
  47. package/dist/cmd/cloud/sandbox/create.d.ts.map +1 -0
  48. package/dist/cmd/cloud/sandbox/create.js +105 -0
  49. package/dist/cmd/cloud/sandbox/create.js.map +1 -0
  50. package/dist/cmd/cloud/sandbox/delete.d.ts +3 -0
  51. package/dist/cmd/cloud/sandbox/delete.d.ts.map +1 -0
  52. package/dist/cmd/cloud/sandbox/delete.js +72 -0
  53. package/dist/cmd/cloud/sandbox/delete.js.map +1 -0
  54. package/dist/cmd/cloud/sandbox/exec.d.ts +3 -0
  55. package/dist/cmd/cloud/sandbox/exec.d.ts.map +1 -0
  56. package/dist/cmd/cloud/sandbox/exec.js +211 -0
  57. package/dist/cmd/cloud/sandbox/exec.js.map +1 -0
  58. package/dist/cmd/cloud/sandbox/execution/get.d.ts +3 -0
  59. package/dist/cmd/cloud/sandbox/execution/get.d.ts.map +1 -0
  60. package/dist/cmd/cloud/sandbox/execution/get.js +96 -0
  61. package/dist/cmd/cloud/sandbox/execution/get.js.map +1 -0
  62. package/dist/cmd/cloud/sandbox/execution/index.d.ts +3 -0
  63. package/dist/cmd/cloud/sandbox/execution/index.d.ts.map +1 -0
  64. package/dist/cmd/cloud/sandbox/execution/index.js +24 -0
  65. package/dist/cmd/cloud/sandbox/execution/index.js.map +1 -0
  66. package/dist/cmd/cloud/sandbox/execution/list.d.ts +3 -0
  67. package/dist/cmd/cloud/sandbox/execution/list.d.ts.map +1 -0
  68. package/dist/cmd/cloud/sandbox/execution/list.js +100 -0
  69. package/dist/cmd/cloud/sandbox/execution/list.js.map +1 -0
  70. package/dist/cmd/cloud/sandbox/get.d.ts +3 -0
  71. package/dist/cmd/cloud/sandbox/get.d.ts.map +1 -0
  72. package/dist/cmd/cloud/sandbox/get.js +95 -0
  73. package/dist/cmd/cloud/sandbox/get.js.map +1 -0
  74. package/dist/cmd/cloud/sandbox/index.d.ts +3 -0
  75. package/dist/cmd/cloud/sandbox/index.d.ts.map +1 -0
  76. package/dist/cmd/cloud/sandbox/index.js +45 -0
  77. package/dist/cmd/cloud/sandbox/index.js.map +1 -0
  78. package/dist/cmd/cloud/sandbox/list.d.ts +3 -0
  79. package/dist/cmd/cloud/sandbox/list.d.ts.map +1 -0
  80. package/dist/cmd/cloud/sandbox/list.js +120 -0
  81. package/dist/cmd/cloud/sandbox/list.js.map +1 -0
  82. package/dist/cmd/cloud/sandbox/run.d.ts +3 -0
  83. package/dist/cmd/cloud/sandbox/run.d.ts.map +1 -0
  84. package/dist/cmd/cloud/sandbox/run.js +152 -0
  85. package/dist/cmd/cloud/sandbox/run.js.map +1 -0
  86. package/dist/cmd/cloud/sandbox/snapshot/create.d.ts +3 -0
  87. package/dist/cmd/cloud/sandbox/snapshot/create.d.ts.map +1 -0
  88. package/dist/cmd/cloud/sandbox/snapshot/create.js +65 -0
  89. package/dist/cmd/cloud/sandbox/snapshot/create.js.map +1 -0
  90. package/dist/cmd/cloud/sandbox/snapshot/delete.d.ts +3 -0
  91. package/dist/cmd/cloud/sandbox/snapshot/delete.d.ts.map +1 -0
  92. package/dist/cmd/cloud/sandbox/snapshot/delete.js +66 -0
  93. package/dist/cmd/cloud/sandbox/snapshot/delete.js.map +1 -0
  94. package/dist/cmd/cloud/sandbox/snapshot/get.d.ts +3 -0
  95. package/dist/cmd/cloud/sandbox/snapshot/get.d.ts.map +1 -0
  96. package/dist/cmd/cloud/sandbox/snapshot/get.js +154 -0
  97. package/dist/cmd/cloud/sandbox/snapshot/get.js.map +1 -0
  98. package/dist/cmd/cloud/sandbox/snapshot/index.d.ts +3 -0
  99. package/dist/cmd/cloud/sandbox/snapshot/index.d.ts.map +1 -0
  100. package/dist/cmd/cloud/sandbox/snapshot/index.js +27 -0
  101. package/dist/cmd/cloud/sandbox/snapshot/index.js.map +1 -0
  102. package/dist/cmd/cloud/sandbox/snapshot/list.d.ts +3 -0
  103. package/dist/cmd/cloud/sandbox/snapshot/list.d.ts.map +1 -0
  104. package/dist/cmd/cloud/sandbox/snapshot/list.js +83 -0
  105. package/dist/cmd/cloud/sandbox/snapshot/list.js.map +1 -0
  106. package/dist/cmd/cloud/sandbox/snapshot/tag.d.ts +3 -0
  107. package/dist/cmd/cloud/sandbox/snapshot/tag.d.ts.map +1 -0
  108. package/dist/cmd/cloud/sandbox/snapshot/tag.js +63 -0
  109. package/dist/cmd/cloud/sandbox/snapshot/tag.js.map +1 -0
  110. package/dist/cmd/cloud/sandbox/util.d.ts +15 -0
  111. package/dist/cmd/cloud/sandbox/util.d.ts.map +1 -0
  112. package/dist/cmd/cloud/sandbox/util.js +50 -0
  113. package/dist/cmd/cloud/sandbox/util.js.map +1 -0
  114. package/dist/cmd/cloud/secret/delete.d.ts.map +1 -1
  115. package/dist/cmd/cloud/secret/delete.js +3 -3
  116. package/dist/cmd/cloud/secret/delete.js.map +1 -1
  117. package/dist/cmd/cloud/secret/import.js +6 -6
  118. package/dist/cmd/cloud/secret/import.js.map +1 -1
  119. package/dist/cmd/cloud/secret/index.d.ts.map +1 -1
  120. package/dist/cmd/cloud/secret/index.js +1 -0
  121. package/dist/cmd/cloud/secret/index.js.map +1 -1
  122. package/dist/cmd/cloud/secret/pull.d.ts.map +1 -1
  123. package/dist/cmd/cloud/secret/pull.js +7 -9
  124. package/dist/cmd/cloud/secret/pull.js.map +1 -1
  125. package/dist/cmd/cloud/secret/push.js +3 -3
  126. package/dist/cmd/cloud/secret/push.js.map +1 -1
  127. package/dist/cmd/cloud/secret/set.d.ts.map +1 -1
  128. package/dist/cmd/cloud/secret/set.js +3 -3
  129. package/dist/cmd/cloud/secret/set.js.map +1 -1
  130. package/dist/cmd/cloud/storage/create.d.ts.map +1 -1
  131. package/dist/cmd/cloud/storage/create.js +13 -2
  132. package/dist/cmd/cloud/storage/create.js.map +1 -1
  133. package/dist/cmd/cloud/storage/delete.d.ts.map +1 -1
  134. package/dist/cmd/cloud/storage/delete.js +13 -2
  135. package/dist/cmd/cloud/storage/delete.js.map +1 -1
  136. package/dist/cmd/cloud/stream/list.d.ts.map +1 -1
  137. package/dist/cmd/cloud/stream/list.js +2 -13
  138. package/dist/cmd/cloud/stream/list.js.map +1 -1
  139. package/dist/cmd/dev/index.d.ts.map +1 -1
  140. package/dist/cmd/dev/index.js +14 -1
  141. package/dist/cmd/dev/index.js.map +1 -1
  142. package/dist/cmd/profile/create.d.ts.map +1 -1
  143. package/dist/cmd/profile/create.js +1 -0
  144. package/dist/cmd/profile/create.js.map +1 -1
  145. package/dist/cmd/project/template-flow.d.ts.map +1 -1
  146. package/dist/cmd/project/template-flow.js +27 -10
  147. package/dist/cmd/project/template-flow.js.map +1 -1
  148. package/dist/config.d.ts +0 -2
  149. package/dist/config.d.ts.map +1 -1
  150. package/dist/config.js +3 -0
  151. package/dist/config.js.map +1 -1
  152. package/dist/env-util.d.ts +16 -8
  153. package/dist/env-util.d.ts.map +1 -1
  154. package/dist/env-util.js +46 -18
  155. package/dist/env-util.js.map +1 -1
  156. package/dist/tui.d.ts +20 -3
  157. package/dist/tui.d.ts.map +1 -1
  158. package/dist/tui.js +82 -23
  159. package/dist/tui.js.map +1 -1
  160. package/dist/types.d.ts +18 -4
  161. package/dist/types.d.ts.map +1 -1
  162. package/dist/types.js +1 -0
  163. package/dist/types.js.map +1 -1
  164. package/package.json +4 -4
  165. package/src/cli.ts +99 -21
  166. package/src/cmd/ai/prompt/api.md +26 -21
  167. package/src/cmd/ai/prompt/version.ts +3 -2
  168. package/src/cmd/build/ast.ts +214 -37
  169. package/src/cmd/build/entry-generator.ts +24 -14
  170. package/src/cmd/build/vite/registry-generator.ts +8 -11
  171. package/src/cmd/build/vite/vite-asset-server.ts +3 -1
  172. package/src/cmd/cloud/db/create.ts +13 -2
  173. package/src/cmd/cloud/db/delete.ts +15 -2
  174. package/src/cmd/cloud/deploy.ts +3 -3
  175. package/src/cmd/cloud/env/delete.ts +1 -1
  176. package/src/cmd/cloud/env/import.ts +4 -4
  177. package/src/cmd/cloud/env/pull.ts +7 -16
  178. package/src/cmd/cloud/env/push.ts +2 -2
  179. package/src/cmd/cloud/env/set.ts +3 -3
  180. package/src/cmd/cloud/index.ts +2 -0
  181. package/src/cmd/cloud/sandbox/cp.ts +531 -0
  182. package/src/cmd/cloud/sandbox/create.ts +114 -0
  183. package/src/cmd/cloud/sandbox/delete.ts +80 -0
  184. package/src/cmd/cloud/sandbox/exec.ts +254 -0
  185. package/src/cmd/cloud/sandbox/execution/get.ts +106 -0
  186. package/src/cmd/cloud/sandbox/execution/index.ts +25 -0
  187. package/src/cmd/cloud/sandbox/execution/list.ts +111 -0
  188. package/src/cmd/cloud/sandbox/get.ts +104 -0
  189. package/src/cmd/cloud/sandbox/index.ts +46 -0
  190. package/src/cmd/cloud/sandbox/list.ts +129 -0
  191. package/src/cmd/cloud/sandbox/run.ts +170 -0
  192. package/src/cmd/cloud/sandbox/snapshot/create.ts +71 -0
  193. package/src/cmd/cloud/sandbox/snapshot/delete.ts +74 -0
  194. package/src/cmd/cloud/sandbox/snapshot/get.ts +188 -0
  195. package/src/cmd/cloud/sandbox/snapshot/index.ts +28 -0
  196. package/src/cmd/cloud/sandbox/snapshot/list.ts +90 -0
  197. package/src/cmd/cloud/sandbox/snapshot/tag.ts +70 -0
  198. package/src/cmd/cloud/sandbox/util.ts +59 -0
  199. package/src/cmd/cloud/secret/delete.ts +8 -3
  200. package/src/cmd/cloud/secret/import.ts +6 -6
  201. package/src/cmd/cloud/secret/index.ts +1 -0
  202. package/src/cmd/cloud/secret/pull.ts +7 -16
  203. package/src/cmd/cloud/secret/push.ts +3 -3
  204. package/src/cmd/cloud/secret/set.ts +8 -3
  205. package/src/cmd/cloud/storage/create.ts +15 -2
  206. package/src/cmd/cloud/storage/delete.ts +15 -2
  207. package/src/cmd/cloud/stream/list.ts +2 -9
  208. package/src/cmd/dev/index.ts +18 -1
  209. package/src/cmd/profile/create.ts +1 -0
  210. package/src/cmd/project/template-flow.ts +29 -13
  211. package/src/config.ts +3 -0
  212. package/src/env-util.ts +52 -21
  213. package/src/tui.ts +131 -39
  214. package/src/types.ts +18 -16
@@ -0,0 +1,90 @@
1
+ import { z } from 'zod';
2
+ import { createCommand } from '../../../../types';
3
+ import * as tui from '../../../../tui';
4
+ import { createSandboxClient } from '../util';
5
+ import { getCommand } from '../../../../command-prefix';
6
+ import { snapshotList } from '@agentuity/server';
7
+
8
+ const SnapshotInfoSchema = z.object({
9
+ snapshotId: z.string(),
10
+ sandboxId: z.string(),
11
+ tag: z.string().nullable().optional(),
12
+ sizeBytes: z.number(),
13
+ fileCount: z.number(),
14
+ parentSnapshotId: z.string().nullable().optional(),
15
+ createdAt: z.string(),
16
+ });
17
+
18
+ const SnapshotListResponseSchema = z.object({
19
+ snapshots: z.array(SnapshotInfoSchema).describe('List of snapshots'),
20
+ total: z.number().describe('Total number of snapshots'),
21
+ });
22
+
23
+ export const listSubcommand = createCommand({
24
+ name: 'list',
25
+ aliases: ['ls'],
26
+ description: 'List snapshots',
27
+ tags: ['slow', 'requires-auth'],
28
+ requires: { auth: true, region: true, org: true },
29
+ examples: [
30
+ {
31
+ command: getCommand('cloud sandbox snapshot list'),
32
+ description: 'List all snapshots',
33
+ },
34
+ {
35
+ command: getCommand('cloud sandbox snapshot list --sandbox sbx_abc123'),
36
+ description: 'List snapshots for a specific sandbox',
37
+ },
38
+ ],
39
+ schema: {
40
+ options: z.object({
41
+ sandbox: z.string().optional().describe('Filter by sandbox ID'),
42
+ limit: z.number().optional().describe('Maximum number of results'),
43
+ offset: z.number().optional().describe('Offset for pagination'),
44
+ }),
45
+ response: SnapshotListResponseSchema,
46
+ },
47
+
48
+ async handler(ctx) {
49
+ const { opts, options, auth, region, logger, orgId } = ctx;
50
+ const client = createSandboxClient(logger, auth, region);
51
+
52
+ const result = await snapshotList(client, {
53
+ sandboxId: opts.sandbox,
54
+ limit: opts.limit,
55
+ offset: opts.offset,
56
+ orgId,
57
+ });
58
+
59
+ if (!options.json) {
60
+ if (result.snapshots.length === 0) {
61
+ tui.info('No snapshots found');
62
+ } else {
63
+ const tableData = result.snapshots.map((snap) => {
64
+ return {
65
+ ID: snap.snapshotId,
66
+ Tag: snap.tag ?? '-',
67
+ Sandbox: snap.sandboxId,
68
+ Size: tui.formatBytes(snap.sizeBytes),
69
+ Files: snap.fileCount,
70
+ 'Created At': snap.createdAt,
71
+ };
72
+ });
73
+ tui.table(tableData, [
74
+ { name: 'ID', alignment: 'left' },
75
+ { name: 'Tag', alignment: 'left' },
76
+ { name: 'Sandbox', alignment: 'left' },
77
+ { name: 'Size', alignment: 'right' },
78
+ { name: 'Files', alignment: 'right' },
79
+ { name: 'Created At', alignment: 'left' },
80
+ ]);
81
+
82
+ tui.info(`Total: ${result.total} ${tui.plural(result.total, 'snapshot', 'snapshots')}`);
83
+ }
84
+ }
85
+
86
+ return result;
87
+ },
88
+ });
89
+
90
+ export default listSubcommand;
@@ -0,0 +1,70 @@
1
+ import { z } from 'zod';
2
+ import { createCommand } from '../../../../types';
3
+ import * as tui from '../../../../tui';
4
+ import { createSandboxClient } from '../util';
5
+ import { getCommand } from '../../../../command-prefix';
6
+ import { snapshotTag } from '@agentuity/server';
7
+
8
+ const SnapshotTagResponseSchema = z.object({
9
+ snapshotId: z.string().describe('Snapshot ID'),
10
+ tag: z.string().nullable().optional().describe('New tag'),
11
+ });
12
+
13
+ export const tagSubcommand = createCommand({
14
+ name: 'tag',
15
+ description: 'Add or update a tag on a snapshot',
16
+ tags: ['slow', 'requires-auth'],
17
+ requires: { auth: true, region: true, org: true },
18
+ examples: [
19
+ {
20
+ command: getCommand('cloud sandbox snapshot tag snp_abc123 latest'),
21
+ description: 'Tag a snapshot as "latest"',
22
+ },
23
+ {
24
+ command: getCommand('cloud sandbox snapshot tag snp_abc123 --clear'),
25
+ description: 'Remove a tag from a snapshot',
26
+ },
27
+ ],
28
+ schema: {
29
+ args: z.object({
30
+ snapshotId: z.string().describe('Snapshot ID to tag'),
31
+ tag: z.string().optional().describe('Tag name to apply'),
32
+ }),
33
+ options: z.object({
34
+ clear: z.boolean().optional().describe('Remove the tag from the snapshot'),
35
+ }),
36
+ response: SnapshotTagResponseSchema,
37
+ },
38
+
39
+ async handler(ctx) {
40
+ const { args, opts, options, auth, region, logger, orgId } = ctx;
41
+ const client = createSandboxClient(logger, auth, region);
42
+
43
+ if (!args.tag && !opts.clear) {
44
+ throw new Error('Either provide a tag name or use --clear to remove the tag');
45
+ }
46
+
47
+ const tag = opts.clear ? null : (args.tag ?? null);
48
+
49
+ const snapshot = await snapshotTag(client, {
50
+ snapshotId: args.snapshotId,
51
+ tag,
52
+ orgId,
53
+ });
54
+
55
+ if (!options.json) {
56
+ if (tag) {
57
+ tui.success(`tagged snapshot ${tui.bold(snapshot.snapshotId)} as ${tui.bold(tag)}`);
58
+ } else {
59
+ tui.success(`removed tag from snapshot ${tui.bold(snapshot.snapshotId)}`);
60
+ }
61
+ }
62
+
63
+ return {
64
+ snapshotId: snapshot.snapshotId,
65
+ tag: snapshot.tag,
66
+ };
67
+ },
68
+ });
69
+
70
+ export default tagSubcommand;
@@ -0,0 +1,59 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import type { Logger, FileToWrite } from '@agentuity/core';
4
+ import { APIClient, getServiceUrls } from '@agentuity/server';
5
+ import type { AuthData } from '../../../types';
6
+
7
+ export function createSandboxClient(logger: Logger, auth: AuthData, region: string): APIClient {
8
+ const urls = getServiceUrls(region);
9
+ return new APIClient(urls.catalyst, logger, auth.apiKey);
10
+ }
11
+
12
+ /**
13
+ * Parse --file arguments and read file contents.
14
+ *
15
+ * Formats:
16
+ * - <sandbox-path>:<local-path> - explicit mapping (e.g., script.js:./local/script.js)
17
+ * - <filename> - shorthand, uses same name for both (e.g., script.js -> script.js:./script.js)
18
+ *
19
+ * @returns Array of FileToWrite objects
20
+ */
21
+ export function parseFileArgs(fileArgs: string[] | undefined): FileToWrite[] {
22
+ if (!fileArgs || fileArgs.length === 0) {
23
+ return [];
24
+ }
25
+
26
+ const files: FileToWrite[] = [];
27
+
28
+ for (const arg of fileArgs) {
29
+ let sandboxPath: string;
30
+ let localPath: string;
31
+
32
+ const colonIndex = arg.indexOf(':');
33
+ if (colonIndex === -1) {
34
+ // Shorthand: just filename, use same name for sandbox and look in current dir
35
+ sandboxPath = arg;
36
+ localPath = `./${arg}`;
37
+ } else {
38
+ sandboxPath = arg.slice(0, colonIndex);
39
+ localPath = arg.slice(colonIndex + 1);
40
+
41
+ if (!sandboxPath) {
42
+ throw new Error(`Invalid --file format: "${arg}". Sandbox path cannot be empty`);
43
+ }
44
+ if (!localPath) {
45
+ throw new Error(`Invalid --file format: "${arg}". Local path cannot be empty`);
46
+ }
47
+ }
48
+
49
+ const resolvedPath = resolve(localPath);
50
+ if (!existsSync(resolvedPath)) {
51
+ throw new Error(`File not found: ${localPath} (resolved to ${resolvedPath})`);
52
+ }
53
+
54
+ const content = readFileSync(resolvedPath);
55
+ files.push({ path: sandboxPath, content });
56
+ }
57
+
58
+ return files;
59
+ }
@@ -2,7 +2,12 @@ import { z } from 'zod';
2
2
  import { createSubcommand } from '../../../types';
3
3
  import * as tui from '../../../tui';
4
4
  import { projectEnvDelete } from '@agentuity/server';
5
- import { findEnvFile, readEnvFile, writeEnvFile, filterAgentuitySdkKeys } from '../../../env-util';
5
+ import {
6
+ findExistingEnvFile,
7
+ readEnvFile,
8
+ writeEnvFile,
9
+ filterAgentuitySdkKeys,
10
+ } from '../../../env-util';
6
11
  import { getCommand } from '../../../command-prefix';
7
12
 
8
13
  const SecretDeleteResponseSchema = z.object({
@@ -40,8 +45,8 @@ export const deleteSubcommand = createSubcommand({
40
45
  });
41
46
  });
42
47
 
43
- // Update local .env.production file
44
- const envFilePath = await findEnvFile(projectDir);
48
+ // Update local .env file
49
+ const envFilePath = await findExistingEnvFile(projectDir);
45
50
  const currentEnv = await readEnvFile(envFilePath);
46
51
  delete currentEnv[args.key];
47
52
 
@@ -3,7 +3,7 @@ import { createSubcommand } from '../../../types';
3
3
  import * as tui from '../../../tui';
4
4
  import { projectEnvUpdate } from '@agentuity/server';
5
5
  import {
6
- findEnvFile,
6
+ findExistingEnvFile,
7
7
  readEnvFile,
8
8
  writeEnvFile,
9
9
  filterAgentuitySdkKeys,
@@ -21,7 +21,7 @@ const SecretImportResponseSchema = z.object({
21
21
 
22
22
  export const importSubcommand = createSubcommand({
23
23
  name: 'import',
24
- description: 'Import secrets from a file to cloud and local .env.production',
24
+ description: 'Import secrets from a file to cloud and local .env',
25
25
  tags: [
26
26
  'mutating',
27
27
  'creates-resource',
@@ -33,8 +33,8 @@ export const importSubcommand = createSubcommand({
33
33
  examples: [
34
34
  { command: getCommand('secret import .env.local'), description: 'Run .env.local command' },
35
35
  {
36
- command: getCommand('secret import .env.production.backup'),
37
- description: 'Run .env.production.backup command',
36
+ command: getCommand('secret import .env.backup'),
37
+ description: 'Run .env.backup command',
38
38
  },
39
39
  ],
40
40
  idempotent: false,
@@ -85,8 +85,8 @@ export const importSubcommand = createSubcommand({
85
85
  });
86
86
  });
87
87
 
88
- // Merge with local .env.production file
89
- const localEnvPath = await findEnvFile(projectDir);
88
+ // Merge with local .env file
89
+ const localEnvPath = await findExistingEnvFile(projectDir);
90
90
  const localEnv = await readEnvFile(localEnvPath);
91
91
  const mergedEnv = mergeEnvVars(localEnv, filteredSecrets);
92
92
 
@@ -10,6 +10,7 @@ import { getCommand } from '../../../command-prefix';
10
10
 
11
11
  export const command = createCommand({
12
12
  name: 'secret',
13
+ aliases: ['secrets'],
13
14
  description: 'Manage secrets for your project',
14
15
  tags: ['fast', 'requires-auth', 'requires-project'],
15
16
  examples: [
@@ -3,13 +3,7 @@ import { join } from 'node:path';
3
3
  import { createSubcommand } from '../../../types';
4
4
  import * as tui from '../../../tui';
5
5
  import { projectGet } from '@agentuity/server';
6
- import {
7
- findEnvFile,
8
- findExistingEnvFile,
9
- readEnvFile,
10
- writeEnvFile,
11
- mergeEnvVars,
12
- } from '../../../env-util';
6
+ import { findExistingEnvFile, readEnvFile, writeEnvFile, mergeEnvVars } from '../../../env-util';
13
7
  import { getCommand } from '../../../command-prefix';
14
8
 
15
9
  const SecretPullResponseSchema = z.object({
@@ -21,7 +15,7 @@ const SecretPullResponseSchema = z.object({
21
15
 
22
16
  export const pullSubcommand = createSubcommand({
23
17
  name: 'pull',
24
- description: 'Pull secrets from cloud to local .env.production file',
18
+ description: 'Pull secrets from cloud to local .env file',
25
19
  tags: ['slow', 'requires-auth', 'requires-project'],
26
20
  idempotent: true,
27
21
  examples: [
@@ -45,14 +39,11 @@ export const pullSubcommand = createSubcommand({
45
39
  return projectGet(apiClient, { id: project.projectId, mask: false });
46
40
  });
47
41
 
48
- const cloudSecrets = projectData.secrets || {};
42
+ const cloudSecrets = { ...projectData.env, ...projectData.secrets }; // secret pull with actually do both secrets and env since thats likely what the user would want
49
43
 
50
- // Read current local env from existing file (.env.production or .env)
51
- const existingEnvPath = await findExistingEnvFile(projectDir);
52
- const localEnv = await readEnvFile(existingEnvPath);
53
-
54
- // Target file is always .env.production
55
- const targetEnvPath = await findEnvFile(projectDir);
44
+ // Target file is always .env
45
+ const targetEnvPath = await findExistingEnvFile(projectDir);
46
+ const localEnv = await readEnvFile(targetEnvPath);
56
47
 
57
48
  // Merge: cloud values override local if force=true, otherwise keep local
58
49
  let mergedEnv: Record<string, string>;
@@ -64,7 +55,7 @@ export const pullSubcommand = createSubcommand({
64
55
  mergedEnv = mergeEnvVars(cloudSecrets, localEnv);
65
56
  }
66
57
 
67
- // Write to .env.production (skip AGENTUITY_ keys)
58
+ // Write to .env (skip AGENTUITY_ keys)
68
59
  await writeEnvFile(targetEnvPath, mergedEnv, {
69
60
  skipKeys: Object.keys(mergedEnv).filter((k) => k.startsWith('AGENTUITY_')),
70
61
  });
@@ -2,7 +2,7 @@ import { z } from 'zod';
2
2
  import { createSubcommand } from '../../../types';
3
3
  import * as tui from '../../../tui';
4
4
  import { projectEnvUpdate } from '@agentuity/server';
5
- import { findEnvFile, readEnvFile, filterAgentuitySdkKeys } from '../../../env-util';
5
+ import { findExistingEnvFile, readEnvFile, filterAgentuitySdkKeys } from '../../../env-util';
6
6
  import { getCommand } from '../../../command-prefix';
7
7
 
8
8
  const SecretPushResponseSchema = z.object({
@@ -13,7 +13,7 @@ const SecretPushResponseSchema = z.object({
13
13
 
14
14
  export const pushSubcommand = createSubcommand({
15
15
  name: 'push',
16
- description: 'Push secrets from local .env.production file to cloud',
16
+ description: 'Push secrets from local .env file to cloud',
17
17
  tags: [
18
18
  'mutating',
19
19
  'updates-resource',
@@ -34,7 +34,7 @@ export const pushSubcommand = createSubcommand({
34
34
  const { apiClient, project, projectDir } = ctx;
35
35
 
36
36
  // Read local env file
37
- const envFilePath = await findEnvFile(projectDir);
37
+ const envFilePath = await findExistingEnvFile(projectDir);
38
38
  const localEnv = await readEnvFile(envFilePath);
39
39
 
40
40
  // Filter out AGENTUITY_ prefixed keys (don't push SDK keys)
@@ -2,7 +2,12 @@ import { z } from 'zod';
2
2
  import { createSubcommand } from '../../../types';
3
3
  import * as tui from '../../../tui';
4
4
  import { projectEnvUpdate } from '@agentuity/server';
5
- import { findEnvFile, readEnvFile, writeEnvFile, filterAgentuitySdkKeys } from '../../../env-util';
5
+ import {
6
+ findExistingEnvFile,
7
+ readEnvFile,
8
+ writeEnvFile,
9
+ filterAgentuitySdkKeys,
10
+ } from '../../../env-util';
6
11
  import { getCommand } from '../../../command-prefix';
7
12
 
8
13
  const SecretSetResponseSchema = z.object({
@@ -51,8 +56,8 @@ export const setSubcommand = createSubcommand({
51
56
  });
52
57
  });
53
58
 
54
- // Update local .env.production file
55
- const envFilePath = await findEnvFile(projectDir);
59
+ // Update local .env file
60
+ const envFilePath = await findExistingEnvFile(projectDir);
56
61
  const currentEnv = await readEnvFile(envFilePath);
57
62
  currentEnv[args.key] = args.value;
58
63
 
@@ -5,6 +5,7 @@ import * as tui from '../../../tui';
5
5
  import { getCatalystAPIClient } from '../../../config';
6
6
  import { getCommand } from '../../../command-prefix';
7
7
  import { isDryRunMode, outputDryRun } from '../../../explain';
8
+ import { addResourceEnvVars } from '../../../env-util';
8
9
 
9
10
  export const createSubcommand = defineSubcommand({
10
11
  name: 'create',
@@ -62,10 +63,22 @@ export const createSubcommand = defineSubcommand({
62
63
  });
63
64
 
64
65
  if (created.length > 0) {
65
- tui.success(`Created storage: ${tui.bold(created[0].name)}`);
66
+ const resource = created[0];
67
+
68
+ // Write environment variables to .env if running inside a project
69
+ if (ctx.projectDir && resource.env && Object.keys(resource.env).length > 0) {
70
+ await addResourceEnvVars(ctx.projectDir, resource.env);
71
+ if (!options.json) {
72
+ tui.info('Environment variables written to .env');
73
+ }
74
+ }
75
+
76
+ if (!options.json) {
77
+ tui.success(`Created storage: ${tui.bold(resource.name)}`);
78
+ }
66
79
  return {
67
80
  success: true,
68
- name: created[0].name,
81
+ name: resource.name,
69
82
  };
70
83
  } else {
71
84
  tui.fatal('Failed to create storage');
@@ -8,6 +8,7 @@ import { getCommand } from '../../../command-prefix';
8
8
  import { isDryRunMode, outputDryRun } from '../../../explain';
9
9
  import { ErrorCode } from '../../../errors';
10
10
  import { createS3Client } from './utils';
11
+ import { removeResourceEnvVars } from '../../../env-util';
11
12
 
12
13
  export const deleteSubcommand = createSubcommand({
13
14
  name: 'delete',
@@ -194,10 +195,22 @@ export const deleteSubcommand = createSubcommand({
194
195
  });
195
196
 
196
197
  if (deleted.length > 0) {
197
- tui.success(`Deleted storage bucket: ${tui.bold(deleted[0])}`);
198
+ const resource = deleted[0];
199
+
200
+ // Remove env vars from .env if running inside a project
201
+ if (ctx.projectDir && resource.env_keys.length > 0) {
202
+ await removeResourceEnvVars(ctx.projectDir, resource.env_keys);
203
+ if (!options.json) {
204
+ tui.info(`Removed ${resource.env_keys.join(', ')} from .env`);
205
+ }
206
+ }
207
+
208
+ if (!options.json) {
209
+ tui.success(`Deleted storage bucket: ${tui.bold(resource.name)}`);
210
+ }
198
211
  return {
199
212
  success: true,
200
- name: deleted[0],
213
+ name: resource.name,
201
214
  };
202
215
  } else {
203
216
  tui.error('Failed to delete storage bucket');
@@ -3,13 +3,6 @@ import { createCommand } from '../../../types';
3
3
  import * as tui from '../../../tui';
4
4
  import { createStorageAdapter } from './util';
5
5
  import { getCommand } from '../../../command-prefix';
6
- function formatBytes(bytes: number): string {
7
- if (bytes === 0) return '0 B';
8
- if (bytes < 1024) return `${bytes} B`;
9
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`;
10
- if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
11
- return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
12
- }
13
6
 
14
7
  const StreamInfoSchema = z.object({
15
8
  id: z.string().describe('Stream ID'),
@@ -124,7 +117,7 @@ export const listSubcommand = createCommand({
124
117
  return {
125
118
  Name: stream.name,
126
119
  ID: stream.id,
127
- Size: formatBytes(sizeBytes),
120
+ Size: tui.formatBytes(sizeBytes),
128
121
  Metadata:
129
122
  metadataStr.length > 40 ? metadataStr.substring(0, 37) + '...' : metadataStr,
130
123
  URL: tui.link(stream.url),
@@ -139,7 +132,7 @@ export const listSubcommand = createCommand({
139
132
  { name: 'URL', alignment: 'left' },
140
133
  ]);
141
134
 
142
- tui.info(`Total: ${result.total} stream(s)`);
135
+ tui.info(`Total: ${result.total} ${tui.plural(result.total, 'stream', 'streams')}`);
143
136
  }
144
137
 
145
138
  return {
@@ -12,7 +12,7 @@ import { APIClient, getAPIBaseURL, getAppBaseURL, getGravityDevModeURL } from '.
12
12
  import { download } from './download';
13
13
  import { createDevmodeSyncService } from './sync';
14
14
  import { getDevmodeDeploymentId } from '../build/ast';
15
- import { getDefaultConfigDir, saveConfig } from '../../config';
15
+ import { getDefaultConfigDir, saveConfig, loadProjectSDKKey } from '../../config';
16
16
  import type { Config } from '../../types';
17
17
  import { createFileWatcher } from './file-watcher';
18
18
  import { regenerateSkillsAsync } from './skills';
@@ -709,6 +709,22 @@ export const command = createCommand({
709
709
  // These must be set so the bundled patches can route LLM calls through AI Gateway
710
710
  const serviceUrls = getServiceUrls(project?.region);
711
711
 
712
+ // Load SDK key from project .env files for AI Gateway routing
713
+ // This must be set so the bundled AI SDK patches can inject the API key
714
+ if (!process.env.AGENTUITY_SDK_KEY) {
715
+ const sdkKey = await loadProjectSDKKey(logger, rootDir);
716
+ if (sdkKey) {
717
+ process.env.AGENTUITY_SDK_KEY = sdkKey;
718
+ } else if (project) {
719
+ tui.warn(
720
+ 'AGENTUITY_SDK_KEY not found in .env file. Numerous features will be unavailable.'
721
+ );
722
+ tui.bullet(
723
+ `Run "${getCommand('cloud env pull')}" to sync your SDK key, or add AGENTUITY_SDK_KEY to your .env file.`
724
+ );
725
+ }
726
+ }
727
+
712
728
  process.env.AGENTUITY_SDK_DEV_MODE = 'true';
713
729
  process.env.AGENTUITY_ENV = 'development';
714
730
  process.env.NODE_ENV = 'development';
@@ -723,6 +739,7 @@ export const command = createCommand({
723
739
  process.env.AGENTUITY_CATALYST_URL = serviceUrls.catalyst;
724
740
  process.env.AGENTUITY_VECTOR_URL = serviceUrls.vector;
725
741
  process.env.AGENTUITY_KEYVALUE_URL = serviceUrls.keyvalue;
742
+ process.env.AGENTUITY_SANDBOX_URL = serviceUrls.sandbox;
726
743
  process.env.AGENTUITY_STREAM_URL = serviceUrls.stream;
727
744
  process.env.AGENTUITY_CLOUD_ORG_ID = project.orgId;
728
745
  process.env.AGENTUITY_CLOUD_PROJECT_ID = project.projectId;
@@ -79,6 +79,7 @@ export const createCommand = createSubcommand({
79
79
  app_url: 'https://app.agentuity.io',
80
80
  transport_url: 'https://catalyst.agentuity.io',
81
81
  stream_url: 'https://streams.agentuity.io',
82
+ sandbox_url: 'https://catalyst.agentuity.io',
82
83
  kv_url: 'https://catalyst.agentuity.io',
83
84
  vector_url: 'https://catalyst.agentuity.io',
84
85
  catalyst_url: 'https://catalyst.agentuity.io',
@@ -1,5 +1,4 @@
1
1
  import { basename, resolve } from 'node:path';
2
- import { z } from 'zod';
3
2
  import { existsSync, readdirSync, rmSync, statSync } from 'node:fs';
4
3
  import { cwd } from 'node:process';
5
4
  import { homedir } from 'node:os';
@@ -10,7 +9,6 @@ import {
10
9
  projectEnvUpdate,
11
10
  getServiceUrls,
12
11
  APIClient as ServerAPIClient,
13
- Resources,
14
12
  createResources,
15
13
  } from '@agentuity/server';
16
14
  import type { Logger } from '@agentuity/core';
@@ -24,15 +22,15 @@ import { ErrorCode } from '../../errors';
24
22
  import type { APIClient } from '../../api';
25
23
  import { createProjectConfig } from '../../config';
26
24
  import {
27
- findEnvFile,
25
+ findExistingEnvFile,
28
26
  readEnvFile,
29
27
  filterAgentuitySdkKeys,
30
28
  splitEnvAndSecrets,
29
+ addResourceEnvVars,
30
+ type EnvVars,
31
31
  } from '../../env-util';
32
32
  import { promptForDNS } from '../../domain';
33
33
 
34
- type ResourcesTypes = z.infer<typeof Resources>;
35
-
36
34
  interface CreateFlowOptions {
37
35
  projectName?: string;
38
36
  dir?: string;
@@ -252,8 +250,8 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
252
250
  }
253
251
  }
254
252
 
255
- const resourceConfig: ResourcesTypes = Resources.parse({});
256
253
  let _domains = domains;
254
+ const resourceEnvVars: EnvVars = {};
257
255
 
258
256
  if (auth && apiClient && catalystClient && orgId && region && !skipPrompts) {
259
257
  // Fetch resources for selected org and region using Catalyst API
@@ -317,14 +315,21 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
317
315
  return createResources(catalystClient, orgId, region!, [{ type: 's3' }]);
318
316
  },
319
317
  });
320
- resourceConfig.storage = created[0].name;
318
+ // Collect env vars from newly created resource
319
+ if (created[0]?.env) {
320
+ Object.assign(resourceEnvVars, created[0].env);
321
+ }
321
322
  break;
322
323
  }
323
324
  case 'Skip': {
324
325
  break;
325
326
  }
326
327
  default: {
327
- resourceConfig.storage = choices.s3_action;
328
+ // User selected an existing bucket - get env vars from the resources list
329
+ const selectedBucket = resources.s3.find((b) => b.bucket_name === choices.s3_action);
330
+ if (selectedBucket?.env) {
331
+ Object.assign(resourceEnvVars, selectedBucket.env);
332
+ }
328
333
  break;
329
334
  }
330
335
  }
@@ -337,14 +342,21 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
337
342
  return createResources(catalystClient, orgId, region!, [{ type: 'db' }]);
338
343
  },
339
344
  });
340
- resourceConfig.db = created[0].name;
345
+ // Collect env vars from newly created resource
346
+ if (created[0]?.env) {
347
+ Object.assign(resourceEnvVars, created[0].env);
348
+ }
341
349
  break;
342
350
  }
343
351
  case 'Skip': {
344
352
  break;
345
353
  }
346
354
  default: {
347
- resourceConfig.db = choices.db_action;
355
+ // User selected an existing database - get env vars from the resources list
356
+ const selectedDb = resources.db.find((d) => d.name === choices.db_action);
357
+ if (selectedDb?.env) {
358
+ Object.assign(resourceEnvVars, selectedDb.env);
359
+ }
348
360
  break;
349
361
  }
350
362
  }
@@ -384,7 +396,6 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
384
396
  orgId,
385
397
  sdkKey: project.sdkKey,
386
398
  deployment: {
387
- resources: resourceConfig,
388
399
  domains: _domains,
389
400
  },
390
401
  region: cloudRegion,
@@ -392,14 +403,19 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
392
403
  },
393
404
  });
394
405
 
395
- // After registration, push any existing env/secrets from .env.production
406
+ // Write resource environment variables to .env
407
+ if (Object.keys(resourceEnvVars).length > 0) {
408
+ await addResourceEnvVars(dest, resourceEnvVars);
409
+ }
410
+
411
+ // After registration, push any existing env/secrets from .env
396
412
  if (projectId) {
397
413
  await tui.spinner({
398
414
  message: 'Syncing environment variables',
399
415
  clearOnSuccess: true,
400
416
  callback: async () => {
401
417
  try {
402
- const envFilePath = await findEnvFile(dest);
418
+ const envFilePath = await findExistingEnvFile(dest);
403
419
  const localEnv = await readEnvFile(envFilePath);
404
420
  const filteredEnv = filterAgentuitySdkKeys(localEnv);
405
421
 
package/src/config.ts CHANGED
@@ -181,6 +181,9 @@ export async function loadConfig(customPath?: string, skipCache = false): Promis
181
181
  if (process.env.AGENTUITY_KEYVALUE_URL) {
182
182
  overrides.kv_url = process.env.AGENTUITY_KEYVALUE_URL;
183
183
  }
184
+ if (process.env.AGENTUITY_SANDBOX_URL) {
185
+ overrides.sandbox_url = process.env.AGENTUITY_SANDBOX_URL;
186
+ }
184
187
  if (process.env.AGENTUITY_VECTOR_URL) {
185
188
  overrides.vector_url = process.env.AGENTUITY_VECTOR_URL;
186
189
  }