@agentuity/cli 0.0.69 → 0.0.70

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 (153) hide show
  1. package/AGENTS.md +1 -1
  2. package/README.md +1 -1
  3. package/dist/cmd/ai/capabilities/show.d.ts.map +1 -1
  4. package/dist/cmd/ai/capabilities/show.js +0 -13
  5. package/dist/cmd/ai/capabilities/show.js.map +1 -1
  6. package/dist/cmd/ai/prompt/agent.js +1 -1
  7. package/dist/cmd/ai/prompt/api.js +1 -1
  8. package/dist/cmd/build/ast.d.ts +1 -2
  9. package/dist/cmd/build/ast.d.ts.map +1 -1
  10. package/dist/cmd/build/ast.js +261 -260
  11. package/dist/cmd/build/ast.js.map +1 -1
  12. package/dist/cmd/build/bundler.d.ts +2 -1
  13. package/dist/cmd/build/bundler.d.ts.map +1 -1
  14. package/dist/cmd/build/bundler.js +11 -2
  15. package/dist/cmd/build/bundler.js.map +1 -1
  16. package/dist/cmd/build/index.js +1 -1
  17. package/dist/cmd/build/index.js.map +1 -1
  18. package/dist/cmd/build/plugin.d.ts.map +1 -1
  19. package/dist/cmd/build/plugin.js +152 -414
  20. package/dist/cmd/build/plugin.js.map +1 -1
  21. package/dist/cmd/build/route-registry.d.ts +36 -0
  22. package/dist/cmd/build/route-registry.d.ts.map +1 -0
  23. package/dist/cmd/build/route-registry.js +151 -0
  24. package/dist/cmd/build/route-registry.js.map +1 -0
  25. package/dist/cmd/cloud/deploy.d.ts.map +1 -1
  26. package/dist/cmd/cloud/deploy.js +1 -0
  27. package/dist/cmd/cloud/deploy.js.map +1 -1
  28. package/dist/cmd/cloud/index.d.ts.map +1 -1
  29. package/dist/cmd/cloud/index.js +0 -2
  30. package/dist/cmd/cloud/index.js.map +1 -1
  31. package/dist/cmd/dev/index.js +3 -3
  32. package/dist/cmd/dev/index.js.map +1 -1
  33. package/dist/cmd/dev/sync.d.ts.map +1 -1
  34. package/dist/cmd/dev/sync.js +0 -15
  35. package/dist/cmd/dev/sync.js.map +1 -1
  36. package/dist/cmd/dev/templates.d.ts.map +1 -1
  37. package/dist/cmd/dev/templates.js +11 -35
  38. package/dist/cmd/dev/templates.js.map +1 -1
  39. package/dist/cmd/profile/create.d.ts.map +1 -1
  40. package/dist/cmd/profile/create.js +0 -1
  41. package/dist/cmd/profile/create.js.map +1 -1
  42. package/dist/cmd/project/template-flow.d.ts.map +1 -1
  43. package/dist/cmd/project/template-flow.js +64 -53
  44. package/dist/cmd/project/template-flow.js.map +1 -1
  45. package/dist/config.d.ts.map +1 -1
  46. package/dist/config.js +0 -3
  47. package/dist/config.js.map +1 -1
  48. package/dist/tui/box.d.ts +19 -0
  49. package/dist/tui/box.d.ts.map +1 -0
  50. package/dist/tui/box.js +160 -0
  51. package/dist/tui/box.js.map +1 -0
  52. package/dist/tui/colors.d.ts +20 -0
  53. package/dist/tui/colors.d.ts.map +1 -0
  54. package/dist/tui/colors.js +52 -0
  55. package/dist/tui/colors.js.map +1 -0
  56. package/dist/tui/group.d.ts +25 -0
  57. package/dist/tui/group.d.ts.map +1 -0
  58. package/dist/tui/group.js +32 -0
  59. package/dist/tui/group.js.map +1 -0
  60. package/dist/tui/prompt.d.ts +65 -0
  61. package/dist/tui/prompt.d.ts.map +1 -0
  62. package/dist/tui/prompt.js +377 -0
  63. package/dist/tui/prompt.js.map +1 -0
  64. package/dist/tui/symbols.d.ts +32 -0
  65. package/dist/tui/symbols.d.ts.map +1 -0
  66. package/dist/tui/symbols.js +52 -0
  67. package/dist/tui/symbols.js.map +1 -0
  68. package/dist/tui.d.ts +6 -0
  69. package/dist/tui.d.ts.map +1 -1
  70. package/dist/tui.js +6 -0
  71. package/dist/tui.js.map +1 -1
  72. package/dist/types.d.ts +0 -24
  73. package/dist/types.d.ts.map +1 -1
  74. package/dist/types.js +0 -1
  75. package/dist/types.js.map +1 -1
  76. package/package.json +3 -3
  77. package/src/cmd/ai/capabilities/show.ts +0 -13
  78. package/src/cmd/ai/prompt/agent.ts +1 -1
  79. package/src/cmd/ai/prompt/api.ts +1 -1
  80. package/src/cmd/build/ast.ts +364 -334
  81. package/src/cmd/build/bundler.ts +16 -1
  82. package/src/cmd/build/index.ts +1 -1
  83. package/src/cmd/build/plugin.ts +171 -493
  84. package/src/cmd/build/route-registry.ts +198 -0
  85. package/src/cmd/cloud/deploy.ts +1 -0
  86. package/src/cmd/cloud/index.ts +0 -2
  87. package/src/cmd/dev/index.ts +3 -3
  88. package/src/cmd/dev/sync.ts +0 -28
  89. package/src/cmd/dev/templates.ts +11 -35
  90. package/src/cmd/profile/create.ts +0 -1
  91. package/src/cmd/project/template-flow.ts +77 -57
  92. package/src/config.ts +0 -3
  93. package/src/tui/box.ts +202 -0
  94. package/src/tui/colors.ts +55 -0
  95. package/src/tui/group.ts +56 -0
  96. package/src/tui/prompt.ts +506 -0
  97. package/src/tui/symbols.ts +64 -0
  98. package/src/tui.ts +14 -0
  99. package/src/types.ts +0 -1
  100. package/dist/cmd/cloud/objectstore/delete-bucket.d.ts +0 -3
  101. package/dist/cmd/cloud/objectstore/delete-bucket.d.ts.map +0 -1
  102. package/dist/cmd/cloud/objectstore/delete-bucket.js +0 -72
  103. package/dist/cmd/cloud/objectstore/delete-bucket.js.map +0 -1
  104. package/dist/cmd/cloud/objectstore/delete.d.ts +0 -3
  105. package/dist/cmd/cloud/objectstore/delete.d.ts.map +0 -1
  106. package/dist/cmd/cloud/objectstore/delete.js +0 -65
  107. package/dist/cmd/cloud/objectstore/delete.js.map +0 -1
  108. package/dist/cmd/cloud/objectstore/get.d.ts +0 -3
  109. package/dist/cmd/cloud/objectstore/get.d.ts.map +0 -1
  110. package/dist/cmd/cloud/objectstore/get.js +0 -75
  111. package/dist/cmd/cloud/objectstore/get.js.map +0 -1
  112. package/dist/cmd/cloud/objectstore/index.d.ts +0 -3
  113. package/dist/cmd/cloud/objectstore/index.d.ts.map +0 -1
  114. package/dist/cmd/cloud/objectstore/index.js +0 -36
  115. package/dist/cmd/cloud/objectstore/index.js.map +0 -1
  116. package/dist/cmd/cloud/objectstore/list-buckets.d.ts +0 -3
  117. package/dist/cmd/cloud/objectstore/list-buckets.d.ts.map +0 -1
  118. package/dist/cmd/cloud/objectstore/list-buckets.js +0 -46
  119. package/dist/cmd/cloud/objectstore/list-buckets.js.map +0 -1
  120. package/dist/cmd/cloud/objectstore/list-keys.d.ts +0 -3
  121. package/dist/cmd/cloud/objectstore/list-keys.d.ts.map +0 -1
  122. package/dist/cmd/cloud/objectstore/list-keys.js +0 -58
  123. package/dist/cmd/cloud/objectstore/list-keys.js.map +0 -1
  124. package/dist/cmd/cloud/objectstore/put.d.ts +0 -3
  125. package/dist/cmd/cloud/objectstore/put.d.ts.map +0 -1
  126. package/dist/cmd/cloud/objectstore/put.js +0 -66
  127. package/dist/cmd/cloud/objectstore/put.js.map +0 -1
  128. package/dist/cmd/cloud/objectstore/repl.d.ts +0 -3
  129. package/dist/cmd/cloud/objectstore/repl.d.ts.map +0 -1
  130. package/dist/cmd/cloud/objectstore/repl.js +0 -224
  131. package/dist/cmd/cloud/objectstore/repl.js.map +0 -1
  132. package/dist/cmd/cloud/objectstore/url.d.ts +0 -3
  133. package/dist/cmd/cloud/objectstore/url.d.ts.map +0 -1
  134. package/dist/cmd/cloud/objectstore/url.js +0 -64
  135. package/dist/cmd/cloud/objectstore/url.js.map +0 -1
  136. package/dist/cmd/cloud/objectstore/util.d.ts +0 -11
  137. package/dist/cmd/cloud/objectstore/util.d.ts.map +0 -1
  138. package/dist/cmd/cloud/objectstore/util.js +0 -18
  139. package/dist/cmd/cloud/objectstore/util.js.map +0 -1
  140. package/src/cmd/build/ast.test.ts +0 -418
  141. package/src/cmd/build/fix-duplicate-exports.test.ts +0 -387
  142. package/src/cmd/cloud/objectstore/delete-bucket.ts +0 -77
  143. package/src/cmd/cloud/objectstore/delete.ts +0 -67
  144. package/src/cmd/cloud/objectstore/get.ts +0 -77
  145. package/src/cmd/cloud/objectstore/index.ts +0 -36
  146. package/src/cmd/cloud/objectstore/list-buckets.ts +0 -51
  147. package/src/cmd/cloud/objectstore/list-keys.ts +0 -63
  148. package/src/cmd/cloud/objectstore/put.ts +0 -74
  149. package/src/cmd/cloud/objectstore/repl.ts +0 -239
  150. package/src/cmd/cloud/objectstore/url.ts +0 -67
  151. package/src/cmd/cloud/objectstore/util.ts +0 -29
  152. package/src/crypto/box.test.ts +0 -431
  153. package/src/env-util.test.ts +0 -194
@@ -0,0 +1,198 @@
1
+ import { writeFileSync, mkdirSync, existsSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+
4
+ /**
5
+ * Route information extracted from route files
6
+ */
7
+ export interface RouteInfo {
8
+ /** HTTP method (GET, POST, etc.) */
9
+ method: string;
10
+ /** Route path */
11
+ path: string;
12
+ /** Relative file path */
13
+ filename: string;
14
+ /** Variable name of the route handler */
15
+ handlerVariable?: string;
16
+ /** Whether this route uses validator */
17
+ hasValidator: boolean;
18
+ /** Route type: 'api' | 'websocket' | 'sse' | 'stream' */
19
+ routeType?: string;
20
+ /** Agent variable name if using agent.validator() */
21
+ agentVariable?: string;
22
+ /** Agent import path (e.g., '@agent/hello', '../shared/agents') */
23
+ agentImportPath?: string;
24
+ /** Input schema variable name if using validator({ input }) */
25
+ inputSchemaVariable?: string;
26
+ /** Output schema variable name if using validator({ output }) */
27
+ outputSchemaVariable?: string;
28
+ }
29
+
30
+ /**
31
+ * Generate RouteRegistry type definitions from discovered routes.
32
+ *
33
+ * Creates a module augmentation for @agentuity/react that provides
34
+ * strongly-typed route keys with input/output schema information.
35
+ *
36
+ * @param srcDir - Source directory path
37
+ * @param routes - Array of route information
38
+ */
39
+ export function generateRouteRegistry(srcDir: string, routes: RouteInfo[]): void {
40
+ // Filter routes by type and validator presence
41
+ const apiRoutes = routes.filter((r) => r.hasValidator && r.routeType === 'api');
42
+ const websocketRoutes = routes.filter((r) => r.hasValidator && r.routeType === 'websocket');
43
+ const sseRoutes = routes.filter((r) => r.hasValidator && r.routeType === 'sse');
44
+
45
+ if (apiRoutes.length === 0 && websocketRoutes.length === 0 && sseRoutes.length === 0) {
46
+ // No typed routes, skip generation
47
+ return;
48
+ }
49
+
50
+ // Generate imports for agents and schemas
51
+ const imports: string[] = [];
52
+ const agentImports = new Map<string, string>(); // Maps agent variable to unique import name
53
+ const schemaImports = new Set<string>(); // Track which schema variables we've seen
54
+
55
+ // Combine all typed routes for import collection
56
+ const allTypedRoutes = [...apiRoutes, ...websocketRoutes, ...sseRoutes];
57
+
58
+ // First pass: collect all unique agents and schema variables
59
+ allTypedRoutes.forEach((route) => {
60
+ // If this route uses an agent, import it directly
61
+ if (route.agentVariable && route.agentImportPath && !agentImports.has(route.agentVariable)) {
62
+ // Resolve the import path (could be @agent/hello, ../shared, etc.)
63
+ let resolvedPath = route.agentImportPath;
64
+
65
+ // If it's a path alias like @agent/hello, convert to relative path
66
+ if (resolvedPath.startsWith('@agent/')) {
67
+ resolvedPath = `../src/agent/${resolvedPath.substring('@agent/'.length)}`;
68
+ } else if (resolvedPath.startsWith('@api/')) {
69
+ resolvedPath = `../src/web/${resolvedPath.substring('@api/'.length)}`;
70
+ } else if (resolvedPath.startsWith('./') || resolvedPath.startsWith('../')) {
71
+ // Relative path - need to resolve relative to route file location
72
+ const routeDir = route.filename.substring(0, route.filename.lastIndexOf('/'));
73
+ resolvedPath = `../${routeDir}/${resolvedPath}`;
74
+ }
75
+
76
+ // Generate unique import name: agent_hello, agent_user, etc.
77
+ const uniqueImportName = `agent_${route.agentVariable}`;
78
+ imports.push(`import type ${uniqueImportName} from '${resolvedPath}';`);
79
+ agentImports.set(route.agentVariable, uniqueImportName);
80
+ }
81
+
82
+ // Track schema variables for potential import from route file
83
+ if (route.inputSchemaVariable) {
84
+ schemaImports.add(route.inputSchemaVariable);
85
+ }
86
+ if (route.outputSchemaVariable) {
87
+ schemaImports.add(route.outputSchemaVariable);
88
+ }
89
+ });
90
+
91
+ // Import schema variables from route files
92
+ const routeFileImports = new Map<string, Set<string>>(); // Maps route file to schema variables
93
+ allTypedRoutes.forEach((route) => {
94
+ if (route.inputSchemaVariable || route.outputSchemaVariable) {
95
+ const filename = route.filename.replace(/\\/g, '/');
96
+ const importPath = `../${filename.replace(/\.ts$/, '')}`;
97
+
98
+ if (!routeFileImports.has(importPath)) {
99
+ routeFileImports.set(importPath, new Set());
100
+ }
101
+
102
+ if (route.inputSchemaVariable) {
103
+ routeFileImports.get(importPath)!.add(route.inputSchemaVariable);
104
+ }
105
+ if (route.outputSchemaVariable) {
106
+ routeFileImports.get(importPath)!.add(route.outputSchemaVariable);
107
+ }
108
+ }
109
+ });
110
+
111
+ // Generate imports for schema variables
112
+ routeFileImports.forEach((schemas, importPath) => {
113
+ const schemaList = Array.from(schemas).join(', ');
114
+ imports.push(`import type { ${schemaList} } from '${importPath}';`);
115
+ });
116
+
117
+ const importsStr = imports.join('\n');
118
+
119
+ // Helper function to generate route entry
120
+ const generateRouteEntry = (route: RouteInfo): string => {
121
+ const routeKey = route.path; // Use path only for websocket/sse, or METHOD path for API
122
+
123
+ // If we have an agent variable, we can infer types from it
124
+ if (route.agentVariable) {
125
+ const importName = agentImports.get(route.agentVariable)!;
126
+ return ` '${routeKey}': {
127
+ inputSchema: typeof ${importName} extends { inputSchema?: infer I } ? I : never;
128
+ outputSchema: typeof ${importName} extends { outputSchema?: infer O } ? O : never;
129
+ };`;
130
+ }
131
+
132
+ // If we have standalone validator with schema variables
133
+ if (route.inputSchemaVariable || route.outputSchemaVariable) {
134
+ const inputType = route.inputSchemaVariable
135
+ ? `typeof ${route.inputSchemaVariable}`
136
+ : 'never';
137
+ const outputType = route.outputSchemaVariable
138
+ ? `typeof ${route.outputSchemaVariable}`
139
+ : 'never';
140
+ return ` '${routeKey}': {
141
+ inputSchema: ${inputType};
142
+ outputSchema: ${outputType};
143
+ };`;
144
+ }
145
+
146
+ // Fall back to any if we can't determine the schema source
147
+ return ` '${routeKey}': {
148
+ // Unable to extract schema types - validator might use inline schemas
149
+ inputSchema: any;
150
+ outputSchema: any;
151
+ };`;
152
+ };
153
+
154
+ // Generate RouteRegistry interface (API routes use METHOD path format)
155
+ const apiRouteEntries = apiRoutes
156
+ .map((route) => {
157
+ const routeKey = `${route.method.toUpperCase()} ${route.path}`;
158
+ return generateRouteEntry({ ...route, path: routeKey });
159
+ })
160
+ .join('\n');
161
+
162
+ // Generate WebSocketRouteRegistry (path only, no method)
163
+ const websocketRouteEntries = websocketRoutes.map(generateRouteEntry).join('\n');
164
+
165
+ // Generate SSERouteRegistry (path only, no method)
166
+ const sseRouteEntries = sseRoutes.map(generateRouteEntry).join('\n');
167
+
168
+ const generatedContent = `// Auto-generated by Agentuity - do not edit manually
169
+ ${importsStr}
170
+
171
+ // Augment @agentuity/react types with project-specific routes
172
+ declare module '@agentuity/react' {
173
+ export interface RouteRegistry {
174
+ ${apiRouteEntries}
175
+ }
176
+
177
+ export interface WebSocketRouteRegistry {
178
+ ${websocketRouteEntries}
179
+ }
180
+
181
+ export interface SSERouteRegistry {
182
+ ${sseRouteEntries}
183
+ }
184
+ }
185
+ `;
186
+
187
+ // Get the project root (parent of srcDir)
188
+ const projectRoot = join(srcDir, '..');
189
+ const agentuityDir = join(projectRoot, '.agentuity');
190
+ const registryPath = join(agentuityDir, 'routes.generated.ts');
191
+
192
+ // Ensure .agentuity directory exists
193
+ if (!existsSync(agentuityDir)) {
194
+ mkdirSync(agentuityDir, { recursive: true });
195
+ }
196
+
197
+ writeFileSync(registryPath, generatedContent, 'utf-8');
198
+ }
@@ -186,6 +186,7 @@ export const deploySubcommand = createSubcommand({
186
186
  provider: opts?.provider,
187
187
  trigger: opts?.trigger,
188
188
  tag: opts?.tag,
189
+ region: project.region,
189
190
  });
190
191
  build = await loadBuildMetadata(join(projectDir, '.agentuity'));
191
192
  instructions = await projectDeploymentUpdate(
@@ -9,7 +9,6 @@ import { scpSubcommand } from './scp';
9
9
  import { deploymentCommand } from './deployment';
10
10
  import keyvalueCommand from './keyvalue';
11
11
  import { agentCommand } from './agent';
12
- import objectstoreCommand from './objectstore';
13
12
  import envCommand from './env';
14
13
  import secretCommand from './secret';
15
14
  import apikeyCommand from './apikey';
@@ -29,7 +28,6 @@ export const command = createCommand({
29
28
  apikeyCommand,
30
29
  keyvalueCommand,
31
30
  agentCommand,
32
- objectstoreCommand,
33
31
  streamCommand,
34
32
  vectorCommand,
35
33
  envCommand,
@@ -121,7 +121,7 @@ export const command = createCommand({
121
121
  config = _config;
122
122
  devmode = endpoint;
123
123
  gravityURL = getGravityDevModeURL(project.region, config);
124
- logger.error('gravity url: %s', gravityURL);
124
+ logger.trace('gravity url: %s', gravityURL);
125
125
  }
126
126
 
127
127
  logger.debug(
@@ -201,7 +201,6 @@ export const command = createCommand({
201
201
  env.AGENTUITY_TRANSPORT_URL = serviceUrls.catalyst;
202
202
  env.AGENTUITY_CATALYST_URL = serviceUrls.catalyst;
203
203
  env.AGENTUITY_VECTOR_URL = serviceUrls.vector;
204
- env.AGENTUITY_OBJECTSTORE_URL = serviceUrls.objectstore;
205
204
  env.AGENTUITY_KEYVALUE_URL = serviceUrls.keyvalue;
206
205
  env.AGENTUITY_STREAM_URL = serviceUrls.stream;
207
206
  env.AGENTUITY_CLOUD_ORG_ID = project.orgId;
@@ -499,6 +498,7 @@ export const command = createCommand({
499
498
  projectId: project?.projectId,
500
499
  deploymentId,
501
500
  port: opts.port,
501
+ region: project?.region ?? 'local',
502
502
  });
503
503
  building = false;
504
504
  buildCompletedAt = Date.now();
@@ -1005,7 +1005,7 @@ export const command = createCommand({
1005
1005
  if (changedFile?.startsWith('src/agent/')) {
1006
1006
  logger.debug('agent directory created: %s', changedFile);
1007
1007
  createAgentTemplates(absPath);
1008
- } else if (changedFile?.startsWith('src/web/')) {
1008
+ } else if (changedFile?.startsWith('src/api/')) {
1009
1009
  logger.debug('api directory created: %s', changedFile);
1010
1010
  createAPITemplates(absPath);
1011
1011
  }
@@ -5,28 +5,16 @@ import type { APIClient } from '../../api';
5
5
  interface AgentSyncPayload {
6
6
  id: string;
7
7
  name: string;
8
- identifier: string;
9
8
  agentId: string;
10
9
  description?: string;
11
10
  version: string;
12
11
  filename: string;
13
12
  projectId: string;
14
- subagents?: Array<{
15
- id: string;
16
- name: string;
17
- identifier: string;
18
- agentId: string;
19
- description?: string;
20
- version: string;
21
- filename: string;
22
- projectId: string;
23
- }>;
24
13
  }
25
14
 
26
15
  interface EvalSyncPayload {
27
16
  id: string;
28
17
  name: string;
29
- identifier: string;
30
18
  evalId: string;
31
19
  description?: string;
32
20
  version: string;
@@ -64,30 +52,14 @@ function getAgentsToSync(
64
52
  agent.name
65
53
  );
66
54
 
67
- // Add projectId to subagents if they exist
68
- const subagents = agent.subagents?.map((subagent) => {
69
- return {
70
- id: subagent.id,
71
- name: subagent.name,
72
- identifier: subagent.identifier,
73
- agentId: subagent.agentId,
74
- description: subagent.description,
75
- version: subagent.version,
76
- filename: subagent.filename,
77
- projectId,
78
- };
79
- });
80
-
81
55
  agentsToCreate.push({
82
56
  id: agent.id,
83
57
  name: agent.name,
84
- identifier: agent.identifier,
85
58
  agentId: agent.agentId,
86
59
  description: agent.description,
87
60
  version: agent.version,
88
61
  filename: agent.filename,
89
62
  projectId,
90
- ...(subagents && { subagents }),
91
63
  });
92
64
  }
93
65
  }
@@ -1,16 +1,13 @@
1
1
  /* eslint-disable no-control-regex */
2
2
  import { writeFileSync } from 'node:fs';
3
3
  import { basename, join } from 'node:path';
4
- import { toCamelCase } from '../../utils/string';
4
+ import { toPascalCase } from '../../utils/string';
5
5
 
6
6
  const newAgentTemplate = (name: string) => `import { createAgent } from '@agentuity/runtime';
7
7
  import { s } from '@agentuity/schema';
8
8
 
9
- const agent = createAgent({
10
- metadata: {
11
- name: '${name}',
12
- description: 'Add your agent description here',
13
- },
9
+ export const ${name} = createAgent('${name}', {
10
+ description: 'Add your agent description here',
14
11
  schema: {
15
12
  input: s.string(),
16
13
  output: s.string(),
@@ -20,47 +17,25 @@ const agent = createAgent({
20
17
  return input;
21
18
  },
22
19
  });
20
+ `;
23
21
 
24
- export default agent;
22
+ const newAgentIndexTemplate = (name: string) => `export { ${name} } from './agent';
25
23
  `;
26
24
 
27
- const newAgentRouteTemplate = (name: string) => {
28
- const camelName = toCamelCase(name);
25
+ const newRouteTemplate = () => {
29
26
  return `import { createRouter } from '@agentuity/runtime';
30
- import agent from './agent';
31
27
 
32
28
  const router = createRouter();
33
29
 
34
30
  router.get('/', async (c) => {
35
- // TODO: add your code here
36
- const output = await c.agent.${camelName}.run('hello world');
31
+ // TODO: add your code here - for now we just echo back what you sent
37
32
  return c.text(output);
38
33
  });
39
34
 
40
- router.post('/', agent.validator(), async (c) => {
41
- const data = c.req.valid('json');
42
- const output = await c.agent.${camelName}.run(data);
43
- return c.json(output);
44
- });
45
-
46
35
  export default router;
47
-
48
36
  `;
49
37
  };
50
38
 
51
- const newAPIRouteTemplate = (_name: string) => `import { createRouter } from '@agentuity/runtime';
52
-
53
- const router = createRouter();
54
-
55
- router.get('/', async (c) => {
56
- // TODO: add your code here
57
- return c.text('Hello');
58
- });
59
-
60
- export default router;
61
-
62
- `;
63
-
64
39
  const invalidDirRegex = /[<>:"/\\|?*]/;
65
40
 
66
41
  // biome-ignore lint/suspicious/noControlCharactersInRegex: checking for invalid control characters in directory names
@@ -82,8 +57,9 @@ export function createAgentTemplates(dir: string) {
82
57
  if (!isValidDirectoryName(name)) {
83
58
  return;
84
59
  }
85
- writeFileSync(join(dir, 'agent.ts'), newAgentTemplate(name));
86
- writeFileSync(join(dir, 'route.ts'), newAgentRouteTemplate(name));
60
+ const agentName = toPascalCase(name);
61
+ writeFileSync(join(dir, 'agent.ts'), newAgentTemplate(agentName));
62
+ writeFileSync(join(dir, 'index.ts'), newAgentIndexTemplate(agentName));
87
63
  }
88
64
 
89
65
  export function createAPITemplates(dir: string) {
@@ -91,5 +67,5 @@ export function createAPITemplates(dir: string) {
91
67
  if (!isValidDirectoryName(name)) {
92
68
  return;
93
69
  }
94
- writeFileSync(join(dir, 'route.ts'), newAPIRouteTemplate(name));
70
+ writeFileSync(join(dir, 'index.ts'), newRouteTemplate());
95
71
  }
@@ -79,7 +79,6 @@ export const createCommand = createSubcommand({
79
79
  transport_url: 'https://catalyst.agentuity.io',
80
80
  stream_url: 'https://streams.agentuity.io',
81
81
  kv_url: 'https://catalyst.agentuity.io',
82
- object_url: 'https://catalyst.agentuity.io',
83
82
  vector_url: 'https://catalyst.agentuity.io',
84
83
  catalyst_url: 'https://catalyst.agentuity.io',
85
84
  ion_url: 'https://ion.agentuity.io',
@@ -3,7 +3,6 @@ import { z } from 'zod';
3
3
  import { existsSync, readdirSync, rmSync, statSync } from 'node:fs';
4
4
  import { cwd } from 'node:process';
5
5
  import { homedir } from 'node:os';
6
- import enquirer from 'enquirer';
7
6
  import {
8
7
  projectCreate,
9
8
  projectExists,
@@ -16,6 +15,7 @@ import {
16
15
  } from '@agentuity/server';
17
16
  import type { Logger } from '@agentuity/core';
18
17
  import * as tui from '../../tui';
18
+ import { createPrompt, note } from '../../tui';
19
19
  import { playSound } from '../../sound';
20
20
  import { fetchTemplates, type TemplateInfo } from './templates';
21
21
  import { downloadTemplate, setupProject } from './download';
@@ -95,10 +95,15 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
95
95
  catalystClient = new ServerAPIClient(catalystUrl, logger, auth.apiKey);
96
96
  }
97
97
 
98
+ // Create prompt flow
99
+ const prompt = createPrompt();
100
+
101
+ if (!skipPrompts) {
102
+ prompt.intro('Create Agentuity Project');
103
+ }
104
+
98
105
  if (!projectName && !skipPrompts) {
99
- const response = await enquirer.prompt<{ name: string }>({
100
- type: 'input',
101
- name: 'name',
106
+ projectName = await prompt.text({
102
107
  message: 'What is the name of your project?',
103
108
  initial: 'My First Agent',
104
109
  validate: async (value: string) => {
@@ -117,7 +122,6 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
117
122
  return true;
118
123
  },
119
124
  });
120
- projectName = response.name;
121
125
  }
122
126
  projectName = projectName || 'My First Agent';
123
127
 
@@ -140,14 +144,13 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
140
144
  // In TTY mode, ask if they want to overwrite
141
145
  if (process.stdin.isTTY && !skipPrompts) {
142
146
  tui.warning(`Directory ${dest} already exists and is not empty.`, true);
143
- const response = await enquirer.prompt<{ overwrite: boolean }>({
144
- type: 'confirm',
145
- name: 'overwrite',
147
+ console.log(tui.tuiColors.secondary('│'));
148
+ const overwrite = await prompt.confirm({
146
149
  message: 'Delete and overwrite the directory?',
147
150
  initial: false,
148
151
  });
149
152
 
150
- if (!response.overwrite) {
153
+ if (!overwrite) {
151
154
  tui.info('Operation cancelled');
152
155
  process.exit(0);
153
156
  }
@@ -160,6 +163,7 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
160
163
  }
161
164
  rmSync(dest, { recursive: true, force: true });
162
165
  tui.success(`Deleted ${dest}`);
166
+ console.log(tui.tuiColors.secondary('│'));
163
167
  } else {
164
168
  logger.fatal(
165
169
  `Directory ${dest} already exists and is not empty.`,
@@ -180,16 +184,15 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
180
184
  } else if (skipPrompts) {
181
185
  selectedTemplate = templates[0];
182
186
  } else {
183
- const response = await enquirer.prompt<{ template: string }>({
184
- type: 'select',
185
- name: 'template',
187
+ const templateId = await prompt.select({
186
188
  message: 'Select a template:',
187
- choices: templates.map((t) => ({
188
- name: t.id,
189
- message: `${t.name.padEnd(15, ' ')} ${tui.muted(t.description)}`,
189
+ options: templates.map((t) => ({
190
+ value: t.id,
191
+ label: t.name,
192
+ hint: t.description,
190
193
  })),
191
194
  });
192
- const found = templates.find((t) => t.id === response.template);
195
+ const found = templates.find((t) => t.id === templateId);
193
196
  if (!found) {
194
197
  logger.fatal('Template selection failed', ErrorCode.USER_CANCELLED);
195
198
  return;
@@ -197,8 +200,6 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
197
200
  selectedTemplate = found;
198
201
  }
199
202
 
200
- tui.info(`✨ Using template: ${tui.bold(selectedTemplate.name)}`);
201
-
202
203
  // Download template
203
204
  await downloadTemplate({
204
205
  dest,
@@ -218,6 +219,17 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
218
219
  logger,
219
220
  });
220
221
 
222
+ // Re-display template selection after spinners clear it
223
+ if (!skipPrompts) {
224
+ const { symbols, tuiColors } = tui;
225
+ console.log(`${tuiColors.completed(symbols.completed)} Select a template:`);
226
+ console.log(`${tuiColors.secondary(symbols.bar)} ${tuiColors.muted(selectedTemplate.name)}`);
227
+ // Only add bar if we're going to show resource prompts
228
+ if (auth && apiClient && catalystClient && orgId && region) {
229
+ console.log(tuiColors.secondary(symbols.bar));
230
+ }
231
+ }
232
+
221
233
  const resourceConfig: ResourcesTypes = Resources.parse({});
222
234
 
223
235
  if (auth && apiClient && catalystClient && orgId && region) {
@@ -232,37 +244,31 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
232
244
 
233
245
  logger.debug(`Resources for org ${orgId} in region ${region}:`, resources);
234
246
 
235
- const choices = await enquirer.prompt<{
236
- db_action: string;
237
- s3_action: string;
238
- }>([
239
- {
240
- type: 'select',
241
- name: 'db_action',
242
- message: 'Create SQL Database?',
243
- choices: [
244
- { name: 'Create New', message: 'Create a new (free)' },
245
- { name: 'Skip', message: 'Skip or Setup later' },
246
- ...resources.db.map((db) => ({
247
- name: db.name,
248
- message: `Use database: ${db.name}`,
249
- })),
250
- ],
251
- },
252
- {
253
- type: 'select',
254
- name: 's3_action',
255
- message: 'Create Storage Bucket?',
256
- choices: [
257
- { name: 'Create New', message: 'Create a new (free)' },
258
- { name: 'Skip', message: 'Skip or Setup later' },
259
- ...resources.s3.map((db) => ({
260
- name: db.bucket_name,
261
- message: `Use bucket: ${db.bucket_name}`,
262
- })),
263
- ],
264
- },
265
- ]);
247
+ const db_action = await prompt.select({
248
+ message: 'Create SQL Database?',
249
+ options: [
250
+ { value: 'Create New', label: 'Create a new (free)' },
251
+ { value: 'Skip', label: 'Skip or Setup later' },
252
+ ...resources.db.map((db) => ({
253
+ value: db.name,
254
+ label: `Use database: ${tui.tuiColors.primary(db.name)}`,
255
+ })),
256
+ ],
257
+ });
258
+
259
+ const s3_action = await prompt.select({
260
+ message: 'Create Storage Bucket?',
261
+ options: [
262
+ { value: 'Create New', label: 'Create a new (free)' },
263
+ { value: 'Skip', label: 'Skip or Setup later' },
264
+ ...resources.s3.map((bucket) => ({
265
+ value: bucket.bucket_name,
266
+ label: `Use bucket: ${tui.tuiColors.primary(bucket.bucket_name)}`,
267
+ })),
268
+ ],
269
+ });
270
+
271
+ const choices = { db_action, s3_action };
266
272
  switch (choices.s3_action) {
267
273
  case 'Create New': {
268
274
  const created = await tui.spinner({
@@ -364,16 +370,30 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
364
370
  }
365
371
 
366
372
  // Show completion message
367
- tui.success('✨ Project created successfully!\n');
368
- tui.info('Next steps:');
369
- if (dirName !== '.') {
370
- const dirDisplay = cwd() === targetDir ? basename(dirName) : dest;
371
- tui.newline();
372
- console.log(` 1. ${tui.bold(`cd ${dirDisplay}`)}`);
373
- console.log(` 2. ${tui.bold('bun run dev')}`);
373
+ if (!skipPrompts) {
374
+ tui.success(' Project created successfully!\n');
375
+
376
+ // Show next steps in a box with primary color for commands
377
+ if (dirName !== '.') {
378
+ // Use relative path if dest is under cwd, otherwise show full path
379
+ const currentDir = cwd();
380
+ const dirDisplay = dest.startsWith(currentDir) ? basename(dest) : dest;
381
+ note(
382
+ `${tui.tuiColors.primary(`cd ${dirDisplay}`)}\n${tui.tuiColors.primary('bun run dev')}`,
383
+ 'Next steps'
384
+ );
385
+ } else {
386
+ note(tui.tuiColors.primary('bun run dev'), 'Next steps');
387
+ }
388
+
389
+ prompt.outro(
390
+ `${tui.tuiColors.muted('🛟 Need help?')} ${tui.link('https://discord.gg/agentuity')}`,
391
+ `${tui.tuiColors.muted('⭐️ Follow us:')} ${tui.link('https://github.com/agentuity/sdk')}`
392
+ );
374
393
  } else {
375
- console.log(` ${tui.bold('bun run dev')}`);
394
+ tui.success(' Project created successfully!');
376
395
  }
396
+
377
397
  playSound();
378
398
  }
379
399
 
package/src/config.ts CHANGED
@@ -170,9 +170,6 @@ export async function loadConfig(customPath?: string): Promise<Config | null> {
170
170
  if (process.env.AGENTUITY_KEYVALUE_URL) {
171
171
  overrides.kv_url = process.env.AGENTUITY_KEYVALUE_URL;
172
172
  }
173
- if (process.env.AGENTUITY_OBJECTSTORE_URL) {
174
- overrides.object_url = process.env.AGENTUITY_OBJECTSTORE_URL;
175
- }
176
173
  if (process.env.AGENTUITY_VECTOR_URL) {
177
174
  overrides.vector_url = process.env.AGENTUITY_VECTOR_URL;
178
175
  }