@agentuity/cli 0.0.101 → 0.0.102

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 (210) hide show
  1. package/AGENTS.md +19 -188
  2. package/bin/cli.ts +13 -6
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +41 -12
  5. package/dist/cli.js.map +1 -1
  6. package/dist/cmd/ai/index.d.ts.map +1 -1
  7. package/dist/cmd/ai/index.js +6 -1
  8. package/dist/cmd/ai/index.js.map +1 -1
  9. package/dist/cmd/ai/prompt/agent.d.ts +7 -0
  10. package/dist/cmd/ai/prompt/agent.d.ts.map +1 -1
  11. package/dist/cmd/ai/prompt/agent.js +12 -323
  12. package/dist/cmd/ai/prompt/agent.js.map +1 -1
  13. package/dist/cmd/ai/prompt/api.d.ts +7 -0
  14. package/dist/cmd/ai/prompt/api.d.ts.map +1 -1
  15. package/dist/cmd/ai/prompt/api.js +12 -260
  16. package/dist/cmd/ai/prompt/api.js.map +1 -1
  17. package/dist/cmd/ai/prompt/version.d.ts +35 -0
  18. package/dist/cmd/ai/prompt/version.d.ts.map +1 -0
  19. package/dist/cmd/ai/prompt/version.js +55 -0
  20. package/dist/cmd/ai/prompt/version.js.map +1 -0
  21. package/dist/cmd/ai/prompt/web.d.ts +7 -0
  22. package/dist/cmd/ai/prompt/web.d.ts.map +1 -1
  23. package/dist/cmd/ai/prompt/web.js +12 -283
  24. package/dist/cmd/ai/prompt/web.js.map +1 -1
  25. package/dist/cmd/ai/skills/generate.d.ts +3 -0
  26. package/dist/cmd/ai/skills/generate.d.ts.map +1 -0
  27. package/dist/cmd/ai/skills/generate.js +65 -0
  28. package/dist/cmd/ai/skills/generate.js.map +1 -0
  29. package/dist/cmd/ai/skills/generator.d.ts +4 -0
  30. package/dist/cmd/ai/skills/generator.d.ts.map +1 -0
  31. package/dist/cmd/ai/skills/generator.js +402 -0
  32. package/dist/cmd/ai/skills/generator.js.map +1 -0
  33. package/dist/cmd/ai/skills/index.d.ts +4 -0
  34. package/dist/cmd/ai/skills/index.d.ts.map +1 -0
  35. package/dist/cmd/ai/skills/index.js +21 -0
  36. package/dist/cmd/ai/skills/index.js.map +1 -0
  37. package/dist/cmd/auth/signup.d.ts.map +1 -1
  38. package/dist/cmd/auth/signup.js +1 -0
  39. package/dist/cmd/auth/signup.js.map +1 -1
  40. package/dist/cmd/build/entry-generator.d.ts.map +1 -1
  41. package/dist/cmd/build/entry-generator.js +40 -5
  42. package/dist/cmd/build/entry-generator.js.map +1 -1
  43. package/dist/cmd/build/vite/bun-dev-server.d.ts +7 -1
  44. package/dist/cmd/build/vite/bun-dev-server.d.ts.map +1 -1
  45. package/dist/cmd/build/vite/bun-dev-server.js +52 -26
  46. package/dist/cmd/build/vite/bun-dev-server.js.map +1 -1
  47. package/dist/cmd/build/vite/metadata-generator.d.ts.map +1 -1
  48. package/dist/cmd/build/vite/metadata-generator.js +58 -7
  49. package/dist/cmd/build/vite/metadata-generator.js.map +1 -1
  50. package/dist/cmd/build/vite/prompt-generator.d.ts +23 -0
  51. package/dist/cmd/build/vite/prompt-generator.d.ts.map +1 -0
  52. package/dist/cmd/build/vite/prompt-generator.js +123 -0
  53. package/dist/cmd/build/vite/prompt-generator.js.map +1 -0
  54. package/dist/cmd/build/vite/registry-generator.d.ts.map +1 -1
  55. package/dist/cmd/build/vite/registry-generator.js +28 -11
  56. package/dist/cmd/build/vite/registry-generator.js.map +1 -1
  57. package/dist/cmd/build/vite/server-bundler.d.ts +4 -0
  58. package/dist/cmd/build/vite/server-bundler.d.ts.map +1 -1
  59. package/dist/cmd/build/vite/server-bundler.js +45 -16
  60. package/dist/cmd/build/vite/server-bundler.js.map +1 -1
  61. package/dist/cmd/build/vite/vite-asset-server-config.d.ts.map +1 -1
  62. package/dist/cmd/build/vite/vite-asset-server-config.js +4 -0
  63. package/dist/cmd/build/vite/vite-asset-server-config.js.map +1 -1
  64. package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
  65. package/dist/cmd/build/vite/vite-builder.js +99 -87
  66. package/dist/cmd/build/vite/vite-builder.js.map +1 -1
  67. package/dist/cmd/cloud/deploy.d.ts.map +1 -1
  68. package/dist/cmd/cloud/deploy.js +78 -27
  69. package/dist/cmd/cloud/deploy.js.map +1 -1
  70. package/dist/cmd/cloud/keyvalue/create-namespace.d.ts.map +1 -1
  71. package/dist/cmd/cloud/keyvalue/create-namespace.js +3 -1
  72. package/dist/cmd/cloud/keyvalue/create-namespace.js.map +1 -1
  73. package/dist/cmd/cloud/keyvalue/delete-namespace.d.ts.map +1 -1
  74. package/dist/cmd/cloud/keyvalue/delete-namespace.js +3 -1
  75. package/dist/cmd/cloud/keyvalue/delete-namespace.js.map +1 -1
  76. package/dist/cmd/cloud/keyvalue/delete.d.ts.map +1 -1
  77. package/dist/cmd/cloud/keyvalue/delete.js +3 -1
  78. package/dist/cmd/cloud/keyvalue/delete.js.map +1 -1
  79. package/dist/cmd/cloud/keyvalue/set.d.ts.map +1 -1
  80. package/dist/cmd/cloud/keyvalue/set.js +4 -2
  81. package/dist/cmd/cloud/keyvalue/set.js.map +1 -1
  82. package/dist/cmd/cloud/stream/get.d.ts.map +1 -1
  83. package/dist/cmd/cloud/stream/get.js +2 -13
  84. package/dist/cmd/cloud/stream/get.js.map +1 -1
  85. package/dist/cmd/cloud/vector/delete-namespace.d.ts +3 -0
  86. package/dist/cmd/cloud/vector/delete-namespace.d.ts.map +1 -0
  87. package/dist/cmd/cloud/vector/delete-namespace.js +77 -0
  88. package/dist/cmd/cloud/vector/delete-namespace.js.map +1 -0
  89. package/dist/cmd/cloud/vector/index.d.ts.map +1 -1
  90. package/dist/cmd/cloud/vector/index.js +21 -4
  91. package/dist/cmd/cloud/vector/index.js.map +1 -1
  92. package/dist/cmd/cloud/vector/list-namespaces.d.ts +3 -0
  93. package/dist/cmd/cloud/vector/list-namespaces.d.ts.map +1 -0
  94. package/dist/cmd/cloud/vector/list-namespaces.js +42 -0
  95. package/dist/cmd/cloud/vector/list-namespaces.js.map +1 -0
  96. package/dist/cmd/cloud/vector/stats.d.ts +3 -0
  97. package/dist/cmd/cloud/vector/stats.d.ts.map +1 -0
  98. package/dist/cmd/cloud/vector/stats.js +142 -0
  99. package/dist/cmd/cloud/vector/stats.js.map +1 -0
  100. package/dist/cmd/cloud/vector/upsert.d.ts +3 -0
  101. package/dist/cmd/cloud/vector/upsert.d.ts.map +1 -0
  102. package/dist/cmd/cloud/vector/upsert.js +192 -0
  103. package/dist/cmd/cloud/vector/upsert.js.map +1 -0
  104. package/dist/cmd/dev/file-watcher.d.ts.map +1 -1
  105. package/dist/cmd/dev/file-watcher.js +90 -31
  106. package/dist/cmd/dev/file-watcher.js.map +1 -1
  107. package/dist/cmd/dev/index.d.ts.map +1 -1
  108. package/dist/cmd/dev/index.js +213 -57
  109. package/dist/cmd/dev/index.js.map +1 -1
  110. package/dist/cmd/dev/skills.d.ts +10 -0
  111. package/dist/cmd/dev/skills.d.ts.map +1 -0
  112. package/dist/cmd/dev/skills.js +57 -0
  113. package/dist/cmd/dev/skills.js.map +1 -0
  114. package/dist/cmd/dev/sync.js +7 -7
  115. package/dist/cmd/dev/sync.js.map +1 -1
  116. package/dist/cmd/index.d.ts.map +1 -1
  117. package/dist/cmd/index.js +1 -0
  118. package/dist/cmd/index.js.map +1 -1
  119. package/dist/cmd/project/create.d.ts.map +1 -1
  120. package/dist/cmd/project/create.js +3 -0
  121. package/dist/cmd/project/create.js.map +1 -1
  122. package/dist/cmd/project/template-flow.d.ts +1 -0
  123. package/dist/cmd/project/template-flow.d.ts.map +1 -1
  124. package/dist/cmd/project/template-flow.js +30 -5
  125. package/dist/cmd/project/template-flow.js.map +1 -1
  126. package/dist/cmd/setup/index.d.ts.map +1 -1
  127. package/dist/cmd/setup/index.js +1 -0
  128. package/dist/cmd/setup/index.js.map +1 -1
  129. package/dist/cmd/upgrade/index.d.ts +15 -0
  130. package/dist/cmd/upgrade/index.d.ts.map +1 -1
  131. package/dist/cmd/upgrade/index.js +59 -4
  132. package/dist/cmd/upgrade/index.js.map +1 -1
  133. package/dist/domain.d.ts +45 -0
  134. package/dist/domain.d.ts.map +1 -0
  135. package/dist/domain.js +200 -0
  136. package/dist/domain.js.map +1 -0
  137. package/dist/schema-generator.d.ts +2 -0
  138. package/dist/schema-generator.d.ts.map +1 -1
  139. package/dist/schema-generator.js +18 -0
  140. package/dist/schema-generator.js.map +1 -1
  141. package/dist/steps.d.ts +1 -1
  142. package/dist/steps.d.ts.map +1 -1
  143. package/dist/steps.js +16 -5
  144. package/dist/steps.js.map +1 -1
  145. package/dist/tui/prompt.d.ts +1 -2
  146. package/dist/tui/prompt.d.ts.map +1 -1
  147. package/dist/tui/prompt.js +8 -4
  148. package/dist/tui/prompt.js.map +1 -1
  149. package/dist/tui.d.ts +16 -0
  150. package/dist/tui.d.ts.map +1 -1
  151. package/dist/tui.js +23 -2
  152. package/dist/tui.js.map +1 -1
  153. package/dist/types.d.ts +9 -2
  154. package/dist/types.d.ts.map +1 -1
  155. package/dist/types.js +3 -3
  156. package/dist/types.js.map +1 -1
  157. package/package.json +4 -4
  158. package/src/cli.ts +47 -12
  159. package/src/cmd/ai/index.ts +6 -1
  160. package/src/cmd/ai/prompt/agent.md +306 -0
  161. package/src/cmd/ai/prompt/agent.ts +12 -322
  162. package/src/cmd/ai/prompt/api.md +360 -0
  163. package/src/cmd/ai/prompt/api.ts +13 -260
  164. package/src/cmd/ai/prompt/version.ts +61 -0
  165. package/src/cmd/ai/prompt/web.md +509 -0
  166. package/src/cmd/ai/prompt/web.ts +12 -282
  167. package/src/cmd/ai/skills/generate.ts +75 -0
  168. package/src/cmd/ai/skills/generator.ts +519 -0
  169. package/src/cmd/ai/skills/index.ts +23 -0
  170. package/src/cmd/auth/signup.ts +1 -0
  171. package/src/cmd/build/entry-generator.ts +43 -7
  172. package/src/cmd/build/vite/bun-dev-server.ts +57 -27
  173. package/src/cmd/build/vite/metadata-generator.ts +73 -7
  174. package/src/cmd/build/vite/prompt-generator.ts +169 -0
  175. package/src/cmd/build/vite/registry-generator.ts +33 -10
  176. package/src/cmd/build/vite/server-bundler.ts +53 -22
  177. package/src/cmd/build/vite/vite-asset-server-config.ts +5 -0
  178. package/src/cmd/build/vite/vite-builder.ts +107 -87
  179. package/src/cmd/cloud/deploy.ts +99 -31
  180. package/src/cmd/cloud/keyvalue/create-namespace.ts +3 -1
  181. package/src/cmd/cloud/keyvalue/delete-namespace.ts +3 -1
  182. package/src/cmd/cloud/keyvalue/delete.ts +3 -1
  183. package/src/cmd/cloud/keyvalue/set.ts +4 -2
  184. package/src/cmd/cloud/stream/get.ts +2 -9
  185. package/src/cmd/cloud/vector/delete-namespace.ts +89 -0
  186. package/src/cmd/cloud/vector/index.ts +21 -4
  187. package/src/cmd/cloud/vector/list-namespaces.ts +46 -0
  188. package/src/cmd/cloud/vector/stats.ts +160 -0
  189. package/src/cmd/cloud/vector/upsert.ts +216 -0
  190. package/src/cmd/dev/file-watcher.ts +101 -32
  191. package/src/cmd/dev/index.ts +304 -111
  192. package/src/cmd/dev/skills.ts +82 -0
  193. package/src/cmd/dev/sync.ts +7 -7
  194. package/src/cmd/index.ts +1 -0
  195. package/src/cmd/project/create.ts +3 -0
  196. package/src/cmd/project/template-flow.ts +37 -5
  197. package/src/cmd/setup/index.ts +1 -0
  198. package/src/cmd/upgrade/index.ts +68 -4
  199. package/src/domain.ts +273 -0
  200. package/src/schema-generator.ts +23 -0
  201. package/src/steps.ts +16 -5
  202. package/src/tui/prompt.ts +11 -5
  203. package/src/tui.ts +21 -2
  204. package/src/types/md.d.ts +8 -0
  205. package/src/types.ts +12 -3
  206. package/dist/cmd/cloud/domain.d.ts +0 -17
  207. package/dist/cmd/cloud/domain.d.ts.map +0 -1
  208. package/dist/cmd/cloud/domain.js +0 -79
  209. package/dist/cmd/cloud/domain.js.map +0 -1
  210. package/src/cmd/cloud/domain.ts +0 -100
@@ -0,0 +1,360 @@
1
+ # APIs Folder Guide
2
+
3
+ This folder contains REST API routes for your Agentuity application. Each API is organized in its own subdirectory.
4
+
5
+ ## Generated Types
6
+
7
+ The `src/generated/` folder contains auto-generated TypeScript files:
8
+
9
+ - `routes.ts` - Route registry with strongly-typed route definitions and schema types
10
+ - `registry.ts` - Agent registry (for calling agents from routes)
11
+ - `app.ts` - Application entry point (regenerated on every build)
12
+
13
+ **Important:** Never edit files in `src/generated/` - they are overwritten on every build.
14
+
15
+ Import generated types in your routes:
16
+
17
+ ```typescript
18
+ import type { POST_Api_UsersInput, POST_Api_UsersOutput } from '../generated/routes';
19
+ ```
20
+
21
+ ## Directory Structure
22
+
23
+ Each API folder must contain:
24
+
25
+ - **route.ts** (required) - HTTP route definitions using Hono router
26
+
27
+ Example structure:
28
+
29
+ ```
30
+ src/api/
31
+ ├── index.ts (optional, mounted at /api)
32
+ ├── status/
33
+ │ └── route.ts (mounted at /api/status)
34
+ ├── users/
35
+ │ └── route.ts (mounted at /api/users)
36
+ ├── agent-call/
37
+ └── route.ts (mounted at /api/agent-call)
38
+ ```
39
+
40
+ ## Creating an API
41
+
42
+ ### Basic API (route.ts)
43
+
44
+ ```typescript
45
+ import { createRouter } from '@agentuity/runtime';
46
+
47
+ const router = createRouter();
48
+
49
+ // GET /api/status
50
+ router.get('/', (c) => {
51
+ return c.json({
52
+ status: 'ok',
53
+ timestamp: new Date().toISOString(),
54
+ version: '1.0.0',
55
+ });
56
+ });
57
+
58
+ // POST /api/status
59
+ router.post('/', async (c) => {
60
+ const body = await c.req.json();
61
+ return c.json({ received: body });
62
+ });
63
+
64
+ export default router;
65
+ ```
66
+
67
+ ### API with Request Validation
68
+
69
+ ```typescript
70
+ import { createRouter } from '@agentuity/runtime';
71
+ import { s } from '@agentuity/schema';
72
+ import { validator } from 'hono/validator';
73
+
74
+ const router = createRouter();
75
+
76
+ const createUserSchema = s.object({
77
+ name: s.string(),
78
+ email: s.string(),
79
+ age: s.number(),
80
+ });
81
+
82
+ router.post(
83
+ '/',
84
+ validator('json', (value, c) => {
85
+ const result = createUserSchema['~standard'].validate(value);
86
+ if (result.issues) {
87
+ return c.json({ error: 'Validation failed', issues: result.issues }, 400);
88
+ }
89
+ return result.value;
90
+ }),
91
+ async (c) => {
92
+ const data = c.req.valid('json');
93
+ // data is fully typed: { name: string, email: string, age: number }
94
+ return c.json({
95
+ success: true,
96
+ user: data,
97
+ });
98
+ }
99
+ );
100
+
101
+ export default router;
102
+ ```
103
+
104
+ ### API Calling Agents
105
+
106
+ APIs can call agents directly by importing them:
107
+
108
+ ```typescript
109
+ import { createRouter } from '@agentuity/runtime';
110
+ import helloAgent from '@agent/hello';
111
+
112
+ const router = createRouter();
113
+
114
+ router.get('/', async (c) => {
115
+ // Call an agent directly
116
+ const result = await helloAgent.run({ name: 'API Caller', age: 42 });
117
+
118
+ return c.json({
119
+ success: true,
120
+ agentResult: result,
121
+ });
122
+ });
123
+
124
+ router.post('/with-input', async (c) => {
125
+ const body = await c.req.json();
126
+ const { name, age } = body;
127
+
128
+ // Call agent with dynamic input
129
+ const result = await helloAgent.run({ name, age });
130
+
131
+ return c.json({
132
+ success: true,
133
+ agentResult: result,
134
+ });
135
+ });
136
+
137
+ export default router;
138
+ ```
139
+
140
+ ### API with Agent Validation
141
+
142
+ Use `agent.validator()` for automatic input validation from agent schemas:
143
+
144
+ ```typescript
145
+ import { createRouter } from '@agentuity/runtime';
146
+ import myAgent from '@agent/my-agent';
147
+
148
+ const router = createRouter();
149
+
150
+ // POST with automatic validation using agent's input schema
151
+ router.post('/', myAgent.validator(), async (c) => {
152
+ const data = c.req.valid('json'); // Fully typed from agent schema!
153
+ const result = await myAgent.run(data);
154
+ return c.json({ success: true, result });
155
+ });
156
+
157
+ export default router;
158
+ ```
159
+
160
+ ### API with Logging
161
+
162
+ ```typescript
163
+ import { createRouter } from '@agentuity/runtime';
164
+
165
+ const router = createRouter();
166
+
167
+ router.get('/log-test', (c) => {
168
+ c.var.logger.info('Info message');
169
+ c.var.logger.error('Error message');
170
+ c.var.logger.warn('Warning message');
171
+ c.var.logger.debug('Debug message');
172
+ c.var.logger.trace('Trace message');
173
+
174
+ return c.text('Check logs');
175
+ });
176
+
177
+ export default router;
178
+ ```
179
+
180
+ ## Route Context (c)
181
+
182
+ The route handler receives a Hono context object with:
183
+
184
+ - **c.req** - Request object (c.req.json(), c.req.param(), c.req.query(), etc.)
185
+ - **c.json()** - Return JSON response
186
+ - **c.text()** - Return text response
187
+ - **c.html()** - Return HTML response
188
+ - **c.redirect()** - Redirect to URL
189
+ - **c.var.logger** - Structured logger (info, warn, error, debug, trace)
190
+ - **c.var.kv** - Key-value storage
191
+ - **c.var.vector** - Vector storage
192
+ - **c.var.stream** - Stream management
193
+ - **Import agents directly** - Import and call agents directly (recommended)
194
+
195
+ ## HTTP Methods
196
+
197
+ ```typescript
198
+ const router = createRouter();
199
+
200
+ router.get('/path', (c) => {
201
+ /* ... */
202
+ });
203
+ router.post('/path', (c) => {
204
+ /* ... */
205
+ });
206
+ router.put('/path', (c) => {
207
+ /* ... */
208
+ });
209
+ router.patch('/path', (c) => {
210
+ /* ... */
211
+ });
212
+ router.delete('/path', (c) => {
213
+ /* ... */
214
+ });
215
+ router.options('/path', (c) => {
216
+ /* ... */
217
+ });
218
+ ```
219
+
220
+ ## Path Parameters
221
+
222
+ ```typescript
223
+ // GET /api/users/:id
224
+ router.get('/:id', (c) => {
225
+ const id = c.req.param('id');
226
+ return c.json({ userId: id });
227
+ });
228
+
229
+ // GET /api/posts/:postId/comments/:commentId
230
+ router.get('/:postId/comments/:commentId', (c) => {
231
+ const postId = c.req.param('postId');
232
+ const commentId = c.req.param('commentId');
233
+ return c.json({ postId, commentId });
234
+ });
235
+ ```
236
+
237
+ ## Query Parameters
238
+
239
+ ```typescript
240
+ // GET /api/search?q=hello&limit=10
241
+ router.get('/search', (c) => {
242
+ const query = c.req.query('q');
243
+ const limit = c.req.query('limit') || '20';
244
+ return c.json({ query, limit: parseInt(limit) });
245
+ });
246
+ ```
247
+
248
+ ## Request Body
249
+
250
+ ```typescript
251
+ // JSON body
252
+ router.post('/', async (c) => {
253
+ const body = await c.req.json();
254
+ return c.json({ received: body });
255
+ });
256
+
257
+ // Form data
258
+ router.post('/upload', async (c) => {
259
+ const formData = await c.req.formData();
260
+ const file = formData.get('file');
261
+ return c.json({ fileName: file?.name });
262
+ });
263
+ ```
264
+
265
+ ## Error Handling
266
+
267
+ ```typescript
268
+ import myAgent from '@agent/my-agent';
269
+
270
+ router.get('/', async (c) => {
271
+ try {
272
+ const result = await myAgent.run({ data: 'test' });
273
+ return c.json({ success: true, result });
274
+ } catch (error) {
275
+ c.var.logger.error('Agent call failed:', error);
276
+ return c.json(
277
+ {
278
+ success: false,
279
+ error: error instanceof Error ? error.message : String(error),
280
+ },
281
+ 500
282
+ );
283
+ }
284
+ });
285
+ ```
286
+
287
+ ## Response Types
288
+
289
+ ```typescript
290
+ // JSON response
291
+ return c.json({ data: 'value' });
292
+
293
+ // Text response
294
+ return c.text('Hello World');
295
+
296
+ // HTML response
297
+ return c.html('<h1>Hello</h1>');
298
+
299
+ // Custom status code
300
+ return c.json({ error: 'Not found' }, 404);
301
+
302
+ // Redirect
303
+ return c.redirect('/new-path');
304
+
305
+ // Headers
306
+ return c.json({ data: 'value' }, 200, {
307
+ 'X-Custom-Header': 'value',
308
+ });
309
+ ```
310
+
311
+ ## Streaming Routes
312
+
313
+ ```typescript
314
+ import { createRouter } from '@agentuity/runtime';
315
+
316
+ const router = createRouter();
317
+
318
+ // Stream response
319
+ router.stream('/events', (c) => {
320
+ return new ReadableStream({
321
+ start(controller) {
322
+ controller.enqueue('event 1\n');
323
+ controller.enqueue('event 2\n');
324
+ controller.close();
325
+ },
326
+ });
327
+ });
328
+
329
+ // Server-Sent Events
330
+ router.sse('/notifications', (c) => {
331
+ return (stream) => {
332
+ stream.writeSSE({ data: 'Hello', event: 'message' });
333
+ stream.writeSSE({ data: 'World', event: 'message' });
334
+ };
335
+ });
336
+
337
+ // WebSocket
338
+ router.websocket('/ws', (c) => {
339
+ return (ws) => {
340
+ ws.onOpen(() => {
341
+ ws.send('Connected!');
342
+ });
343
+ ws.onMessage((event) => {
344
+ ws.send(`Echo: ${event.data}`);
345
+ });
346
+ };
347
+ });
348
+
349
+ export default router;
350
+ ```
351
+
352
+ ## Rules
353
+
354
+ - Each API folder name becomes the route name (e.g., `status/` → `/api/status`)
355
+ - **route.ts** must export default the router instance
356
+ - Use c.var.logger for logging, not console.log
357
+ - Import agents directly to call them (e.g., `import agent from '@agent/name'`)
358
+ - Validation should use @agentuity/schema or agent.validator() for type safety
359
+ - Return appropriate HTTP status codes
360
+ - APIs run at `/api/{folderName}` by default
@@ -1,6 +1,8 @@
1
1
  import { createSubcommand } from '../../../types';
2
2
  import type { CommandContext } from '../../../types';
3
3
  import { getCommand } from '../../../command-prefix';
4
+ import { appendHashComment } from './version';
5
+ import apiPromptContent from './api.md' with { type: 'text' };
4
6
 
5
7
  export const apiSubcommand = createSubcommand({
6
8
  name: 'api',
@@ -14,265 +16,16 @@ export const apiSubcommand = createSubcommand({
14
16
  },
15
17
  });
16
18
 
17
- export function generateLLMPrompt(): string {
18
- return `# APIs Folder Guide
19
-
20
- This folder contains REST API routes for your Agentuity application. Each API is organized in its own subdirectory.
21
-
22
- ## Directory Structure
23
-
24
- Each API folder must contain:
25
- - **route.ts** (required) - HTTP route definitions using Hono router
26
-
27
- Example structure:
28
- \`\`\`
29
- src/api/
30
- ├── index.ts (optional, mounted at /api)
31
- ├── status/
32
- │ └── route.ts (mounted at /api/status)
33
- ├── users/
34
- │ └── route.ts (mounted at /api/users)
35
- ├── agent-call/
36
- └── route.ts (mounted at /api/agent-call)
37
- \`\`\`
38
-
39
- ## Creating an API
40
-
41
- ### Basic API (route.ts)
42
-
43
- \`\`\`typescript
44
- import { createRouter } from '@agentuity/runtime';
45
-
46
- const router = createRouter();
47
-
48
- // GET /api/status
49
- router.get('/', (c) => {
50
- return c.json({
51
- status: 'ok',
52
- timestamp: new Date().toISOString(),
53
- version: '1.0.0',
54
- });
55
- });
56
-
57
- // POST /api/status
58
- router.post('/', async (c) => {
59
- const body = await c.req.json();
60
- return c.json({ received: body });
61
- });
62
-
63
- export default router;
64
- \`\`\`
65
-
66
- ### API with Request Validation
67
-
68
- \`\`\`typescript
69
- import { createRouter } from '@agentuity/runtime';
70
- import { s } from '@agentuity/schema';
71
-
72
- const router = createRouter();
73
-
74
- const createUserSchema = s.object({
75
- name: s.string(),
76
- email: s.string(),
77
- age: s.number(),
78
- });
79
-
80
- const validator = createRouter.validator({
81
- input: createUserSchema,
82
- });
83
-
84
- router.post('/', validator, async (c) => {
85
- const data = c.req.valid('json');
86
- // data is fully typed: { name: string, email: string, age: number }
87
- return c.json({
88
- success: true,
89
- user: data
90
- });
91
- });
92
-
93
- export default router;
94
- \`\`\`
95
-
96
- ### API Calling Agents
97
-
98
- APIs can call agents directly:
99
-
100
- \`\`\`typescript
101
- import { createRouter } from '@agentuity/runtime';
102
-
103
- const router = createRouter();
104
-
105
- router.get('/', async (c) => {
106
- // Call an agent from the agents/ folder
107
- const result = await c.agent.hello.run({ name: 'API Caller', age: 42 });
108
-
109
- return c.json({
110
- success: true,
111
- agentResult: result,
112
- });
113
- });
114
-
115
- router.post('/with-input', async (c) => {
116
- const body = await c.req.json();
117
- const { name, age } = body;
118
-
119
- // Call agent with dynamic input
120
- const result = await c.agent.simple.run({ name, age });
121
-
122
- return c.json({
123
- success: true,
124
- agentResult: result,
125
- });
126
- });
127
-
128
- export default router;
129
- \`\`\`
130
-
131
- ### API with Logging
132
-
133
- \`\`\`typescript
134
- import { createRouter } from '@agentuity/runtime';
135
-
136
- const router = createRouter();
137
-
138
- router.get('/log-test', (c) => {
139
- c.var.logger.info('Info message');
140
- c.var.logger.error('Error message');
141
- c.var.logger.warn('Warning message');
142
- c.var.logger.debug('Debug message');
143
- c.var.logger.trace('Trace message');
144
-
145
- return c.text('Check logs');
146
- });
147
-
148
- export default router;
149
- \`\`\`
150
-
151
- ## Route Context (c)
152
-
153
- The route handler receives a Hono context object with:
154
-
155
- - **c.req** - Request object (c.req.json(), c.req.param(), c.req.query(), etc.)
156
- - **c.json()** - Return JSON response
157
- - **c.text()** - Return text response
158
- - **c.html()** - Return HTML response
159
- - **c.redirect()** - Redirect to URL
160
- - **c.var.logger** - Structured logger (info, warn, error, debug, trace)
161
- - **Import agents directly** - Import and call agents directly instead of using c.var.agent
162
- - **c.var.kv** - Key-value storage
163
- - **c.var.vector** - Vector storage
164
- - **c.var.stream** - Stream management
165
-
166
- ## HTTP Methods
167
-
168
- \`\`\`typescript
169
- const router = createRouter();
170
-
171
- router.get('/path', (c) => { /* ... */ });
172
- router.post('/path', (c) => { /* ... */ });
173
- router.put('/path', (c) => { /* ... */ });
174
- router.patch('/path', (c) => { /* ... */ });
175
- router.delete('/path', (c) => { /* ... */ });
176
- router.options('/path', (c) => { /* ... */ });
177
- \`\`\`
178
-
179
- ## Path Parameters
180
-
181
- \`\`\`typescript
182
- // GET /api/users/:id
183
- router.get('/:id', (c) => {
184
- const id = c.req.param('id');
185
- return c.json({ userId: id });
186
- });
187
-
188
- // GET /api/posts/:postId/comments/:commentId
189
- router.get('/:postId/comments/:commentId', (c) => {
190
- const postId = c.req.param('postId');
191
- const commentId = c.req.param('commentId');
192
- return c.json({ postId, commentId });
193
- });
194
- \`\`\`
195
-
196
- ## Query Parameters
197
-
198
- \`\`\`typescript
199
- // GET /api/search?q=hello&limit=10
200
- router.get('/search', (c) => {
201
- const query = c.req.query('q');
202
- const limit = c.req.query('limit') || '20';
203
- return c.json({ query, limit: parseInt(limit) });
204
- });
205
- \`\`\`
206
-
207
- ## Request Body
208
-
209
- \`\`\`typescript
210
- // JSON body
211
- router.post('/', async (c) => {
212
- const body = await c.req.json();
213
- return c.json({ received: body });
214
- });
215
-
216
- // Form data
217
- router.post('/upload', async (c) => {
218
- const formData = await c.req.formData();
219
- const file = formData.get('file');
220
- return c.json({ fileName: file?.name });
221
- });
222
- \`\`\`
223
-
224
- ## Error Handling
225
-
226
- \`\`\`typescript
227
- router.get('/', async (c) => {
228
- try {
229
- const result = await c.agent.myAgent.run({ data: 'test' });
230
- return c.json({ success: true, result });
231
- } catch (error) {
232
- c.var.logger.error('Agent call failed:', error);
233
- return c.json(
234
- {
235
- success: false,
236
- error: error instanceof Error ? error.message : String(error),
237
- },
238
- 500
239
- );
240
- }
241
- });
242
- \`\`\`
243
-
244
- ## Response Types
245
-
246
- \`\`\`typescript
247
- // JSON response
248
- return c.json({ data: 'value' });
249
-
250
- // Text response
251
- return c.text('Hello World');
252
-
253
- // HTML response
254
- return c.html('<h1>Hello</h1>');
255
-
256
- // Custom status code
257
- return c.json({ error: 'Not found' }, 404);
258
-
259
- // Redirect
260
- return c.redirect('/new-path');
261
-
262
- // Headers
263
- return c.json({ data: 'value' }, 200, {
264
- 'X-Custom-Header': 'value',
265
- });
266
- \`\`\`
267
-
268
- ## Rules
19
+ /**
20
+ * Get the raw prompt content without hash.
21
+ */
22
+ export function getPromptContent(): string {
23
+ return apiPromptContent;
24
+ }
269
25
 
270
- - Each API folder name becomes the route name (e.g., \`status/\` → \`/api/status\`)
271
- - **route.ts** must export default the router instance
272
- - Use c.var.logger for logging, not console.log
273
- - All agents are accessible via c.agent.{agentName}
274
- - Validation should use @agentuity/schema or any Standard Schema compatible library
275
- - Return appropriate HTTP status codes
276
- - APIs run at \`/api/{folderName}\` by default
277
- `;
26
+ /**
27
+ * Generate the API prompt with hash comment.
28
+ */
29
+ export function generateLLMPrompt(): string {
30
+ return appendHashComment(apiPromptContent);
278
31
  }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Prompt file versioning utilities.
3
+ *
4
+ * Hash format at end of file: <!-- prompt_hash: [hash] -->
5
+ *
6
+ * - hash: SHA256 of file content (excluding the hash line)
7
+ *
8
+ * This allows detecting if the source template has changed.
9
+ */
10
+
11
+ const HASH_REGEX = /\n?<!-- prompt_hash: ([a-f0-9]+) -->$/;
12
+
13
+ /**
14
+ * Compute SHA256 hash of content using Bun's built-in hasher.
15
+ */
16
+ export function computeHash(content: string): string {
17
+ const hasher = new Bun.CryptoHasher('sha256');
18
+ hasher.update(content);
19
+ return hasher.digest().toHex();
20
+ }
21
+
22
+ /**
23
+ * Strip the hash comment from content.
24
+ */
25
+ export function stripHashComment(content: string): string {
26
+ return content.replace(HASH_REGEX, '');
27
+ }
28
+
29
+ /**
30
+ * Extract hash from file content.
31
+ * Returns null if no hash comment found.
32
+ */
33
+ export function extractHash(content: string): string | null {
34
+ const match = content.match(HASH_REGEX);
35
+ return match ? match[1] : null;
36
+ }
37
+
38
+ /**
39
+ * Generate content with hash comment appended.
40
+ */
41
+ export function appendHashComment(content: string): string {
42
+ const hash = computeHash(content);
43
+ return `${content}\n<!-- prompt_hash: ${hash} -->`;
44
+ }
45
+
46
+ /**
47
+ * Check if a file needs to be updated based on hash comparison.
48
+ *
49
+ * @param fileContent - Current file content (with hash comment)
50
+ * @param sourceContent - Source template content (without hash comment)
51
+ * @returns true if file needs to be updated (hashes differ)
52
+ */
53
+ export function needsUpdate(fileContent: string, sourceContent: string): boolean {
54
+ const fileHash = extractHash(fileContent);
55
+ if (!fileHash) {
56
+ return true;
57
+ }
58
+
59
+ const sourceHash = computeHash(sourceContent);
60
+ return fileHash !== sourceHash;
61
+ }