@agentuity/cli 0.1.15 → 0.1.16

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 (114) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +15 -1
  3. package/dist/cli.js.map +1 -1
  4. package/dist/cmd/ai/opencode/install.js +1 -1
  5. package/dist/cmd/ai/opencode/install.js.map +1 -1
  6. package/dist/cmd/cloud/env/delete.d.ts.map +1 -1
  7. package/dist/cmd/cloud/env/delete.js +87 -34
  8. package/dist/cmd/cloud/env/delete.js.map +1 -1
  9. package/dist/cmd/cloud/env/get.d.ts.map +1 -1
  10. package/dist/cmd/cloud/env/get.js +50 -16
  11. package/dist/cmd/cloud/env/get.js.map +1 -1
  12. package/dist/cmd/cloud/env/import.d.ts.map +1 -1
  13. package/dist/cmd/cloud/env/import.js +76 -32
  14. package/dist/cmd/cloud/env/import.js.map +1 -1
  15. package/dist/cmd/cloud/env/index.d.ts.map +1 -1
  16. package/dist/cmd/cloud/env/index.js +6 -2
  17. package/dist/cmd/cloud/env/index.js.map +1 -1
  18. package/dist/cmd/cloud/env/list.d.ts.map +1 -1
  19. package/dist/cmd/cloud/env/list.js +94 -23
  20. package/dist/cmd/cloud/env/list.js.map +1 -1
  21. package/dist/cmd/cloud/env/org-util.d.ts +16 -0
  22. package/dist/cmd/cloud/env/org-util.d.ts.map +1 -0
  23. package/dist/cmd/cloud/env/org-util.js +28 -0
  24. package/dist/cmd/cloud/env/org-util.js.map +1 -0
  25. package/dist/cmd/cloud/env/pull.d.ts.map +1 -1
  26. package/dist/cmd/cloud/env/pull.js +61 -29
  27. package/dist/cmd/cloud/env/pull.js.map +1 -1
  28. package/dist/cmd/cloud/env/push.d.ts.map +1 -1
  29. package/dist/cmd/cloud/env/push.js +69 -23
  30. package/dist/cmd/cloud/env/push.js.map +1 -1
  31. package/dist/cmd/cloud/env/set.d.ts.map +1 -1
  32. package/dist/cmd/cloud/env/set.js +69 -26
  33. package/dist/cmd/cloud/env/set.js.map +1 -1
  34. package/dist/cmd/cloud/keyvalue/create-namespace.js +1 -1
  35. package/dist/cmd/cloud/keyvalue/create-namespace.js.map +1 -1
  36. package/dist/cmd/cloud/keyvalue/delete-namespace.js +2 -2
  37. package/dist/cmd/cloud/keyvalue/delete-namespace.js.map +1 -1
  38. package/dist/cmd/cloud/keyvalue/delete.js +1 -1
  39. package/dist/cmd/cloud/keyvalue/delete.js.map +1 -1
  40. package/dist/cmd/cloud/keyvalue/get.js +1 -1
  41. package/dist/cmd/cloud/keyvalue/get.js.map +1 -1
  42. package/dist/cmd/cloud/keyvalue/index.js +1 -1
  43. package/dist/cmd/cloud/keyvalue/index.js.map +1 -1
  44. package/dist/cmd/cloud/keyvalue/keys.js +1 -1
  45. package/dist/cmd/cloud/keyvalue/keys.js.map +1 -1
  46. package/dist/cmd/cloud/keyvalue/list-namespaces.js +1 -1
  47. package/dist/cmd/cloud/keyvalue/list-namespaces.js.map +1 -1
  48. package/dist/cmd/cloud/keyvalue/repl.d.ts.map +1 -1
  49. package/dist/cmd/cloud/keyvalue/repl.js +8 -5
  50. package/dist/cmd/cloud/keyvalue/repl.js.map +1 -1
  51. package/dist/cmd/cloud/keyvalue/search.js +1 -1
  52. package/dist/cmd/cloud/keyvalue/search.js.map +1 -1
  53. package/dist/cmd/cloud/keyvalue/set.js +1 -1
  54. package/dist/cmd/cloud/keyvalue/set.js.map +1 -1
  55. package/dist/cmd/cloud/keyvalue/stats.js +1 -1
  56. package/dist/cmd/cloud/keyvalue/stats.js.map +1 -1
  57. package/dist/cmd/cloud/keyvalue/util.d.ts +4 -4
  58. package/dist/cmd/cloud/keyvalue/util.d.ts.map +1 -1
  59. package/dist/cmd/cloud/keyvalue/util.js +4 -9
  60. package/dist/cmd/cloud/keyvalue/util.js.map +1 -1
  61. package/dist/cmd/project/create.d.ts.map +1 -1
  62. package/dist/cmd/project/create.js +12 -0
  63. package/dist/cmd/project/create.js.map +1 -1
  64. package/dist/cmd/project/template-flow.d.ts +3 -0
  65. package/dist/cmd/project/template-flow.d.ts.map +1 -1
  66. package/dist/cmd/project/template-flow.js +157 -68
  67. package/dist/cmd/project/template-flow.js.map +1 -1
  68. package/dist/cmd/setup/index.d.ts.map +1 -1
  69. package/dist/cmd/setup/index.js +2 -1
  70. package/dist/cmd/setup/index.js.map +1 -1
  71. package/dist/onboarding/agentPrompt.d.ts +8 -0
  72. package/dist/onboarding/agentPrompt.d.ts.map +1 -0
  73. package/dist/onboarding/agentPrompt.js +263 -0
  74. package/dist/onboarding/agentPrompt.js.map +1 -0
  75. package/dist/schema-generator.d.ts +1 -1
  76. package/dist/schema-generator.d.ts.map +1 -1
  77. package/dist/schema-parser.d.ts +1 -1
  78. package/dist/schema-parser.d.ts.map +1 -1
  79. package/dist/schema-parser.js +36 -1
  80. package/dist/schema-parser.js.map +1 -1
  81. package/dist/tui.d.ts.map +1 -1
  82. package/dist/tui.js +17 -7
  83. package/dist/tui.js.map +1 -1
  84. package/package.json +6 -6
  85. package/src/cli.ts +14 -1
  86. package/src/cmd/ai/opencode/install.ts +1 -1
  87. package/src/cmd/cloud/env/delete.ts +100 -41
  88. package/src/cmd/cloud/env/get.ts +53 -16
  89. package/src/cmd/cloud/env/import.ts +86 -37
  90. package/src/cmd/cloud/env/index.ts +6 -2
  91. package/src/cmd/cloud/env/list.ts +102 -27
  92. package/src/cmd/cloud/env/org-util.ts +37 -0
  93. package/src/cmd/cloud/env/pull.ts +67 -31
  94. package/src/cmd/cloud/env/push.ts +81 -28
  95. package/src/cmd/cloud/env/set.ts +82 -33
  96. package/src/cmd/cloud/keyvalue/create-namespace.ts +1 -1
  97. package/src/cmd/cloud/keyvalue/delete-namespace.ts +2 -2
  98. package/src/cmd/cloud/keyvalue/delete.ts +1 -1
  99. package/src/cmd/cloud/keyvalue/get.ts +1 -1
  100. package/src/cmd/cloud/keyvalue/index.ts +1 -1
  101. package/src/cmd/cloud/keyvalue/keys.ts +1 -1
  102. package/src/cmd/cloud/keyvalue/list-namespaces.ts +1 -1
  103. package/src/cmd/cloud/keyvalue/repl.ts +8 -5
  104. package/src/cmd/cloud/keyvalue/search.ts +1 -1
  105. package/src/cmd/cloud/keyvalue/set.ts +1 -1
  106. package/src/cmd/cloud/keyvalue/stats.ts +1 -1
  107. package/src/cmd/cloud/keyvalue/util.ts +8 -17
  108. package/src/cmd/project/create.ts +12 -0
  109. package/src/cmd/project/template-flow.ts +183 -69
  110. package/src/cmd/setup/index.ts +2 -1
  111. package/src/onboarding/agentPrompt.ts +263 -0
  112. package/src/schema-generator.ts +1 -1
  113. package/src/schema-parser.ts +42 -3
  114. package/src/tui.ts +19 -9
@@ -1,7 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { createSubcommand } from '../../../types';
3
3
  import * as tui from '../../../tui';
4
- import { projectEnvUpdate } from '@agentuity/server';
4
+ import { projectEnvUpdate, orgEnvUpdate } from '@agentuity/server';
5
5
  import {
6
6
  findExistingEnvFile,
7
7
  readEnvFile,
@@ -10,6 +10,7 @@ import {
10
10
  validateNoPublicSecrets,
11
11
  } from '../../../env-util';
12
12
  import { getCommand } from '../../../command-prefix';
13
+ import { resolveOrgId, isOrgScope } from './org-util';
13
14
 
14
15
  const EnvPushResponseSchema = z.object({
15
16
  success: z.boolean().describe('Whether push succeeded'),
@@ -17,6 +18,7 @@ const EnvPushResponseSchema = z.object({
17
18
  envCount: z.number().describe('Number of env vars pushed'),
18
19
  secretCount: z.number().describe('Number of secrets pushed'),
19
20
  source: z.string().describe('Source file path'),
21
+ scope: z.enum(['project', 'org']).describe('The scope where variables were pushed'),
20
22
  });
21
23
 
22
24
  export const pushSubcommand = createSubcommand({
@@ -28,18 +30,33 @@ export const pushSubcommand = createSubcommand({
28
30
  'slow',
29
31
  'api-intensive',
30
32
  'requires-auth',
31
- 'requires-project',
32
33
  ],
33
34
  idempotent: true,
34
- examples: [{ command: getCommand('env push'), description: 'Push all variables to cloud' }],
35
- requires: { auth: true, project: true, apiClient: true },
35
+ examples: [
36
+ { command: getCommand('env push'), description: 'Push all variables to cloud (project)' },
37
+ { command: getCommand('env push --org'), description: 'Push all variables to organization' },
38
+ ],
39
+ requires: { auth: true, apiClient: true },
40
+ optional: { project: true },
36
41
  prerequisites: ['env set'],
37
42
  schema: {
43
+ options: z.object({
44
+ org: z
45
+ .union([z.boolean(), z.string()])
46
+ .optional()
47
+ .describe('push to organization level (use --org for default org)'),
48
+ }),
38
49
  response: EnvPushResponseSchema,
39
50
  },
40
51
 
41
52
  async handler(ctx) {
42
- const { apiClient, project, projectDir } = ctx;
53
+ const { apiClient, project, projectDir, config, opts } = ctx;
54
+ const useOrgScope = isOrgScope(opts?.org);
55
+
56
+ // Always require projectDir since push reads from local .env file
57
+ if (!projectDir) {
58
+ tui.fatal('Project directory required. Run from a project directory.');
59
+ }
43
60
 
44
61
  // Read local env file
45
62
  const envFilePath = await findExistingEnvFile(projectDir);
@@ -56,6 +73,7 @@ export const pushSubcommand = createSubcommand({
56
73
  envCount: 0,
57
74
  secretCount: 0,
58
75
  source: envFilePath,
76
+ scope: useOrgScope ? 'org' as const : 'project' as const,
59
77
  };
60
78
  }
61
79
 
@@ -74,29 +92,64 @@ export const pushSubcommand = createSubcommand({
74
92
  }
75
93
  }
76
94
 
77
- // Push to cloud
78
- await tui.spinner('Pushing variables to cloud', () => {
79
- return projectEnvUpdate(apiClient, {
80
- id: project.projectId,
81
- env,
82
- secrets,
95
+ if (useOrgScope) {
96
+ // Organization scope
97
+ const orgId = await resolveOrgId(apiClient, config, opts!.org!);
98
+
99
+ await tui.spinner('Pushing variables to organization', () => {
100
+ return orgEnvUpdate(apiClient, {
101
+ id: orgId,
102
+ env,
103
+ secrets,
104
+ });
105
+ });
106
+
107
+ const envCount = Object.keys(env).length;
108
+ const secretCount = Object.keys(secrets).length;
109
+ const totalCount = envCount + secretCount;
110
+
111
+ tui.success(
112
+ `Pushed ${totalCount} variable${totalCount !== 1 ? 's' : ''} to organization (${envCount} env, ${secretCount} secret${secretCount !== 1 ? 's' : ''})`
113
+ );
114
+
115
+ return {
116
+ success: true,
117
+ pushed: totalCount,
118
+ envCount,
119
+ secretCount,
120
+ source: envFilePath,
121
+ scope: 'org' as const,
122
+ };
123
+ } else {
124
+ // Project scope (existing behavior)
125
+ if (!project) {
126
+ tui.fatal('Project context required. Run from a project directory or use --org for organization scope.');
127
+ }
128
+
129
+ await tui.spinner('Pushing variables to cloud', () => {
130
+ return projectEnvUpdate(apiClient, {
131
+ id: project.projectId,
132
+ env,
133
+ secrets,
134
+ });
83
135
  });
84
- });
85
-
86
- const envCount = Object.keys(env).length;
87
- const secretCount = Object.keys(secrets).length;
88
- const totalCount = envCount + secretCount;
89
-
90
- tui.success(
91
- `Pushed ${totalCount} variable${totalCount !== 1 ? 's' : ''} to cloud (${envCount} env, ${secretCount} secret${secretCount !== 1 ? 's' : ''})`
92
- );
93
-
94
- return {
95
- success: true,
96
- pushed: totalCount,
97
- envCount,
98
- secretCount,
99
- source: envFilePath,
100
- };
136
+
137
+ const envCount = Object.keys(env).length;
138
+ const secretCount = Object.keys(secrets).length;
139
+ const totalCount = envCount + secretCount;
140
+
141
+ tui.success(
142
+ `Pushed ${totalCount} variable${totalCount !== 1 ? 's' : ''} to cloud (${envCount} env, ${secretCount} secret${secretCount !== 1 ? 's' : ''})`
143
+ );
144
+
145
+ return {
146
+ success: true,
147
+ pushed: totalCount,
148
+ envCount,
149
+ secretCount,
150
+ source: envFilePath,
151
+ scope: 'project' as const,
152
+ };
153
+ }
101
154
  },
102
155
  });
@@ -1,7 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { createSubcommand } from '../../../types';
3
3
  import * as tui from '../../../tui';
4
- import { projectEnvUpdate } from '@agentuity/server';
4
+ import { projectEnvUpdate, orgEnvUpdate } from '@agentuity/server';
5
5
  import {
6
6
  findExistingEnvFile,
7
7
  readEnvFile,
@@ -13,20 +13,23 @@ import {
13
13
  PUBLIC_VAR_PREFIXES,
14
14
  } from '../../../env-util';
15
15
  import { getCommand } from '../../../command-prefix';
16
+ import { resolveOrgId, isOrgScope } from './org-util';
16
17
 
17
18
  const EnvSetResponseSchema = z.object({
18
19
  success: z.boolean().describe('Whether the operation succeeded'),
19
20
  key: z.string().describe('Environment variable key'),
20
- path: z.string().describe('Local file path where env var was saved'),
21
+ path: z.string().optional().describe('Local file path where env var was saved (project scope only)'),
21
22
  secret: z.boolean().describe('Whether the value was stored as a secret'),
23
+ scope: z.enum(['project', 'org']).describe('The scope where the variable was set'),
22
24
  });
23
25
 
24
26
  export const setSubcommand = createSubcommand({
25
27
  name: 'set',
26
28
  description: 'Set an environment variable or secret',
27
- tags: ['mutating', 'updates-resource', 'slow', 'requires-auth', 'requires-project'],
29
+ tags: ['mutating', 'updates-resource', 'slow', 'requires-auth'],
28
30
  idempotent: true,
29
- requires: { auth: true, project: true, apiClient: true },
31
+ requires: { auth: true, apiClient: true },
32
+ optional: { project: true },
30
33
  examples: [
31
34
  {
32
35
  command: getCommand('env set NODE_ENV production'),
@@ -37,6 +40,10 @@ export const setSubcommand = createSubcommand({
37
40
  command: getCommand('env set API_KEY "sk_..." --secret'),
38
41
  description: 'Set a secret value',
39
42
  },
43
+ {
44
+ command: getCommand('env set OPENAI_API_KEY "sk_..." --secret --org'),
45
+ description: 'Set an organization-wide secret',
46
+ },
40
47
  ],
41
48
  schema: {
42
49
  args: z.object({
@@ -48,12 +55,23 @@ export const setSubcommand = createSubcommand({
48
55
  .boolean()
49
56
  .default(false)
50
57
  .describe('store as a secret (encrypted and masked in UI)'),
58
+ org: z
59
+ .union([z.boolean(), z.string()])
60
+ .optional()
61
+ .describe('set at organization level (use --org for default org, or --org <orgId> for specific org)'),
51
62
  }),
52
63
  response: EnvSetResponseSchema,
53
64
  },
54
65
 
55
66
  async handler(ctx) {
56
- const { args, opts, apiClient, project, projectDir } = ctx;
67
+ const { args, opts, apiClient, project, projectDir, config } = ctx;
68
+ const useOrgScope = isOrgScope(opts?.org);
69
+
70
+ // Require project context if not using org scope
71
+ if (!useOrgScope && !project) {
72
+ tui.fatal('Project context required. Run from a project directory or use --org for organization scope.');
73
+ }
74
+
57
75
  let isSecret = opts?.secret ?? false;
58
76
  const isPublic = isPublicVarKey(args.key);
59
77
 
@@ -81,34 +99,65 @@ export const setSubcommand = createSubcommand({
81
99
  }
82
100
  }
83
101
 
84
- // Set in cloud
85
- const updatePayload = isSecret
86
- ? { id: project.projectId, secrets: { [args.key]: args.value } }
87
- : { id: project.projectId, env: { [args.key]: args.value } };
88
-
89
102
  const label = isSecret ? 'secret' : 'environment variable';
90
- await tui.spinner(`Setting ${label} in cloud`, () => {
91
- return projectEnvUpdate(apiClient, updatePayload);
92
- });
93
-
94
- // Update local .env file
95
- const envFilePath = await findExistingEnvFile(projectDir);
96
- const currentEnv = await readEnvFile(envFilePath);
97
- currentEnv[args.key] = args.value;
98
-
99
- // Filter out AGENTUITY_ keys before writing
100
- const filteredEnv = filterAgentuitySdkKeys(currentEnv);
101
- await writeEnvFile(envFilePath, filteredEnv);
102
-
103
- tui.success(
104
- `${isSecret ? 'Secret' : 'Environment variable'} '${args.key}' set successfully (cloud + ${envFilePath})`
105
- );
106
-
107
- return {
108
- success: true,
109
- key: args.key,
110
- path: envFilePath,
111
- secret: isSecret,
112
- };
103
+
104
+ if (useOrgScope) {
105
+ // Organization scope
106
+ const orgId = await resolveOrgId(apiClient, config, opts!.org!);
107
+
108
+ const updatePayload = isSecret
109
+ ? { id: orgId, secrets: { [args.key]: args.value } }
110
+ : { id: orgId, env: { [args.key]: args.value } };
111
+
112
+ await tui.spinner(`Setting organization ${label} in cloud`, () => {
113
+ return orgEnvUpdate(apiClient, updatePayload);
114
+ });
115
+
116
+ tui.success(
117
+ `Organization ${isSecret ? 'secret' : 'environment variable'} '${args.key}' set successfully (affects all projects in org)`
118
+ );
119
+
120
+ return {
121
+ success: true,
122
+ key: args.key,
123
+ secret: isSecret,
124
+ scope: 'org' as const,
125
+ };
126
+ } else {
127
+ // Project scope (existing behavior)
128
+ const updatePayload = isSecret
129
+ ? { id: project!.projectId, secrets: { [args.key]: args.value } }
130
+ : { id: project!.projectId, env: { [args.key]: args.value } };
131
+
132
+ await tui.spinner(`Setting ${label} in cloud`, () => {
133
+ return projectEnvUpdate(apiClient, updatePayload);
134
+ });
135
+
136
+ // Update local .env file only if we have a project directory
137
+ // (not when using --project-id without being in a project folder)
138
+ let envFilePath: string | undefined;
139
+ if (projectDir) {
140
+ envFilePath = await findExistingEnvFile(projectDir);
141
+ const currentEnv = await readEnvFile(envFilePath);
142
+ currentEnv[args.key] = args.value;
143
+
144
+ // Filter out AGENTUITY_ keys before writing
145
+ const filteredEnv = filterAgentuitySdkKeys(currentEnv);
146
+ await writeEnvFile(envFilePath, filteredEnv);
147
+ }
148
+
149
+ const successMsg = envFilePath
150
+ ? `${isSecret ? 'Secret' : 'Environment variable'} '${args.key}' set successfully (cloud + ${envFilePath})`
151
+ : `${isSecret ? 'Secret' : 'Environment variable'} '${args.key}' set successfully (cloud only)`;
152
+ tui.success(successMsg);
153
+
154
+ return {
155
+ success: true,
156
+ key: args.key,
157
+ path: envFilePath,
158
+ secret: isSecret,
159
+ scope: 'project' as const,
160
+ };
161
+ }
113
162
  },
114
163
  });
@@ -9,7 +9,7 @@ export const createNamespaceSubcommand = createCommand({
9
9
  description: 'Create a new keyvalue namespace',
10
10
  tags: ['mutating', 'creates-resource', 'slow', 'requires-auth'],
11
11
  idempotent: false,
12
- requires: { auth: true, project: true },
12
+ requires: { auth: true },
13
13
  examples: [
14
14
  {
15
15
  command: getCommand('kv create-namespace production'),
@@ -8,9 +8,9 @@ export const deleteNamespaceSubcommand = createCommand({
8
8
  name: 'delete-namespace',
9
9
  aliases: ['rm-namespace'],
10
10
  description: 'Delete a keyvalue namespace and all its keys',
11
- tags: ['destructive', 'deletes-resource', 'slow', 'requires-auth', 'requires-project'],
11
+ tags: ['destructive', 'deletes-resource', 'slow', 'requires-auth'],
12
12
  idempotent: true,
13
- requires: { auth: true, project: true },
13
+ requires: { auth: true },
14
14
  examples: [
15
15
  {
16
16
  command: getCommand('kv delete-namespace staging'),
@@ -16,7 +16,7 @@ export const deleteSubcommand = createCommand({
16
16
  description: 'Delete a key from the keyvalue storage',
17
17
  tags: ['destructive', 'deletes-resource', 'slow', 'requires-auth'],
18
18
  idempotent: true,
19
- requires: { auth: true, project: true },
19
+ requires: { auth: true },
20
20
  examples: [
21
21
  { command: getCommand('kv delete production user:123'), description: 'Delete user data' },
22
22
  { command: getCommand('kv delete cache session:abc'), description: 'Delete cached session' },
@@ -14,7 +14,7 @@ export const getSubcommand = createCommand({
14
14
  name: 'get',
15
15
  description: 'Get a value from the keyvalue storage',
16
16
  tags: ['read-only', 'fast', 'requires-auth'],
17
- requires: { auth: true, project: true },
17
+ requires: { auth: true },
18
18
  examples: [
19
19
  { command: getCommand('kv get production user:123'), description: 'Get user data' },
20
20
  { command: getCommand('kv get cache session:abc'), description: 'Get cached session' },
@@ -35,6 +35,6 @@ export const command = createCommand({
35
35
  createNamespaceSubcommand,
36
36
  deleteNamespaceSubcommand,
37
37
  ],
38
- requires: { auth: true, project: true },
38
+ requires: { auth: true },
39
39
  });
40
40
  export default command;
@@ -13,7 +13,7 @@ export const keysSubcommand = createCommand({
13
13
  aliases: ['ls', 'list'],
14
14
  description: 'List all keys in a keyvalue namespace',
15
15
  tags: ['read-only', 'slow', 'requires-auth'],
16
- requires: { auth: true, project: true },
16
+ requires: { auth: true },
17
17
  idempotent: true,
18
18
  examples: [
19
19
  { command: getCommand('kv keys production'), description: 'List all keys in production' },
@@ -10,7 +10,7 @@ export const listNamespacesSubcommand = createCommand({
10
10
  aliases: ['namespaces', 'ns'],
11
11
  description: 'List all keyvalue namespaces',
12
12
  tags: ['read-only', 'fast', 'requires-auth'],
13
- requires: { auth: true, project: true },
13
+ requires: { auth: true },
14
14
  examples: [
15
15
  { command: getCommand('kv list-namespaces'), description: 'List all namespaces' },
16
16
  { command: getCommand('kv namespaces'), description: 'List namespaces (using alias)' },
@@ -11,16 +11,19 @@ export const replSubcommand = createCommand({
11
11
  description: 'Start an interactive repl for working with keyvalue database',
12
12
  tags: ['slow', 'requires-auth'],
13
13
  idempotent: false,
14
- requires: { auth: true, project: true },
14
+ requires: { auth: true },
15
+ optional: { project: true },
15
16
  examples: [{ command: getCommand('kv repl'), description: 'Start interactive KV session' }],
16
17
 
17
18
  async handler(ctx) {
18
19
  showBanner(undefined, true);
19
- tui.info('Managing keyvalue store for project');
20
- tui.newline();
21
- console.log(tui.bold('Org:'.padEnd(10, ' ')), ' ', tui.muted(ctx.project.orgId));
22
- console.log(tui.bold('Project:'.padEnd(10, ' ')), ' ', tui.muted(ctx.project.projectId));
20
+ tui.info('Managing keyvalue store');
23
21
  tui.newline();
22
+ if (ctx.project) {
23
+ console.log(tui.bold('Org:'.padEnd(10, ' ')), ' ', tui.muted(ctx.project.orgId));
24
+ console.log(tui.bold('Project:'.padEnd(10, ' ')), ' ', tui.muted(ctx.project.projectId));
25
+ tui.newline();
26
+ }
24
27
 
25
28
  const storage = await createStorageAdapter(ctx);
26
29
 
@@ -20,7 +20,7 @@ export const searchSubcommand = createCommand({
20
20
  name: 'search',
21
21
  description: 'Search for keys matching a keyword in a keyvalue namespace',
22
22
  tags: ['read-only', 'slow', 'requires-auth'],
23
- requires: { auth: true, project: true },
23
+ requires: { auth: true },
24
24
  idempotent: true,
25
25
  examples: [
26
26
  {
@@ -19,7 +19,7 @@ export const setSubcommand = createCommand({
19
19
  description: 'Set a key and value in the keyvalue storage',
20
20
  tags: ['mutating', 'updates-resource', 'slow', 'requires-auth'],
21
21
  idempotent: true,
22
- requires: { auth: true, project: true },
22
+ requires: { auth: true },
23
23
  examples: [
24
24
  {
25
25
  command: getCommand(
@@ -26,7 +26,7 @@ export const statsSubcommand = createCommand({
26
26
  name: 'stats',
27
27
  description: 'Get statistics for keyvalue storage',
28
28
  tags: ['read-only', 'fast', 'requires-auth'],
29
- requires: { auth: true, project: true },
29
+ requires: { auth: true },
30
30
  idempotent: true,
31
31
  examples: [
32
32
  { command: getCommand('kv stats'), description: 'Show stats for all namespaces' },
@@ -1,34 +1,25 @@
1
- import { KeyValueStorageService, Logger } from '@agentuity/core';
1
+ import { KeyValueStorageService, type Logger } from '@agentuity/core';
2
2
  import { createServerFetchAdapter, getServiceUrls } from '@agentuity/server';
3
- import { loadProjectSDKKey } from '../../../config';
4
- import { ErrorCode } from '../../../errors';
5
- import type { Config } from '../../../types';
6
- import * as tui from '../../../tui';
3
+ import { getDefaultRegion } from '../../../config';
4
+ import type { AuthData, Config } from '../../../types';
7
5
 
8
6
  export async function createStorageAdapter(ctx: {
9
7
  logger: Logger;
10
- projectDir: string;
11
8
  config: Config | null;
12
- project: { region: string };
9
+ auth: AuthData;
10
+ project?: { region: string };
13
11
  }) {
14
- const sdkKey = await loadProjectSDKKey(ctx.logger, ctx.projectDir);
15
- if (!sdkKey) {
16
- tui.fatal(
17
- `Couldn't find the AGENTUITY_SDK_KEY in ${ctx.projectDir} .env file`,
18
- ErrorCode.CONFIG_NOT_FOUND
19
- );
20
- }
21
-
22
12
  const adapter = createServerFetchAdapter(
23
13
  {
24
14
  headers: {
25
- Authorization: `Bearer ${sdkKey}`,
15
+ Authorization: `Bearer ${ctx.auth.apiKey}`,
26
16
  },
27
17
  },
28
18
  ctx.logger
29
19
  );
30
20
 
31
- const urls = getServiceUrls(ctx.project.region);
21
+ const region = ctx.project?.region || (await getDefaultRegion(ctx.config?.name, ctx.config));
22
+ const urls = getServiceUrls(region);
32
23
  const baseUrl = urls.catalyst;
33
24
  return new KeyValueStorageService(baseUrl, adapter);
34
25
  }
@@ -69,6 +69,15 @@ export const createProjectSubcommand = createSubcommand({
69
69
  .default(true)
70
70
  .optional()
71
71
  .describe('Register the project, if authenticated (use --no-register to skip)'),
72
+ database: z
73
+ .string()
74
+ .optional()
75
+ .describe('Database action: "skip", "new", or existing database name'),
76
+ storage: z
77
+ .string()
78
+ .optional()
79
+ .describe('Storage action: "skip", "new", or existing bucket name'),
80
+ enableAuth: z.boolean().optional().describe('Enable Agentuity Auth'),
72
81
  }),
73
82
  response: ProjectCreateResponseSchema,
74
83
  },
@@ -101,6 +110,9 @@ export const createProjectSubcommand = createSubcommand({
101
110
  apiClient,
102
111
  orgId: opts.register === true ? orgId : undefined,
103
112
  region,
113
+ database: opts.database,
114
+ storage: opts.storage,
115
+ enableAuth: opts.enableAuth,
104
116
  });
105
117
 
106
118
  // Exit with error code if setup failed and not in JSON mode