@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.
- package/AGENTS.md +19 -188
- package/bin/cli.ts +13 -6
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +41 -12
- package/dist/cli.js.map +1 -1
- package/dist/cmd/ai/index.d.ts.map +1 -1
- package/dist/cmd/ai/index.js +6 -1
- package/dist/cmd/ai/index.js.map +1 -1
- package/dist/cmd/ai/prompt/agent.d.ts +7 -0
- package/dist/cmd/ai/prompt/agent.d.ts.map +1 -1
- package/dist/cmd/ai/prompt/agent.js +12 -323
- package/dist/cmd/ai/prompt/agent.js.map +1 -1
- package/dist/cmd/ai/prompt/api.d.ts +7 -0
- package/dist/cmd/ai/prompt/api.d.ts.map +1 -1
- package/dist/cmd/ai/prompt/api.js +12 -260
- package/dist/cmd/ai/prompt/api.js.map +1 -1
- package/dist/cmd/ai/prompt/version.d.ts +35 -0
- package/dist/cmd/ai/prompt/version.d.ts.map +1 -0
- package/dist/cmd/ai/prompt/version.js +55 -0
- package/dist/cmd/ai/prompt/version.js.map +1 -0
- package/dist/cmd/ai/prompt/web.d.ts +7 -0
- package/dist/cmd/ai/prompt/web.d.ts.map +1 -1
- package/dist/cmd/ai/prompt/web.js +12 -283
- package/dist/cmd/ai/prompt/web.js.map +1 -1
- package/dist/cmd/ai/skills/generate.d.ts +3 -0
- package/dist/cmd/ai/skills/generate.d.ts.map +1 -0
- package/dist/cmd/ai/skills/generate.js +65 -0
- package/dist/cmd/ai/skills/generate.js.map +1 -0
- package/dist/cmd/ai/skills/generator.d.ts +4 -0
- package/dist/cmd/ai/skills/generator.d.ts.map +1 -0
- package/dist/cmd/ai/skills/generator.js +402 -0
- package/dist/cmd/ai/skills/generator.js.map +1 -0
- package/dist/cmd/ai/skills/index.d.ts +4 -0
- package/dist/cmd/ai/skills/index.d.ts.map +1 -0
- package/dist/cmd/ai/skills/index.js +21 -0
- package/dist/cmd/ai/skills/index.js.map +1 -0
- package/dist/cmd/auth/signup.d.ts.map +1 -1
- package/dist/cmd/auth/signup.js +1 -0
- package/dist/cmd/auth/signup.js.map +1 -1
- package/dist/cmd/build/entry-generator.d.ts.map +1 -1
- package/dist/cmd/build/entry-generator.js +40 -5
- package/dist/cmd/build/entry-generator.js.map +1 -1
- package/dist/cmd/build/vite/bun-dev-server.d.ts +7 -1
- package/dist/cmd/build/vite/bun-dev-server.d.ts.map +1 -1
- package/dist/cmd/build/vite/bun-dev-server.js +52 -26
- package/dist/cmd/build/vite/bun-dev-server.js.map +1 -1
- package/dist/cmd/build/vite/metadata-generator.d.ts.map +1 -1
- package/dist/cmd/build/vite/metadata-generator.js +58 -7
- package/dist/cmd/build/vite/metadata-generator.js.map +1 -1
- package/dist/cmd/build/vite/prompt-generator.d.ts +23 -0
- package/dist/cmd/build/vite/prompt-generator.d.ts.map +1 -0
- package/dist/cmd/build/vite/prompt-generator.js +123 -0
- package/dist/cmd/build/vite/prompt-generator.js.map +1 -0
- package/dist/cmd/build/vite/registry-generator.d.ts.map +1 -1
- package/dist/cmd/build/vite/registry-generator.js +28 -11
- package/dist/cmd/build/vite/registry-generator.js.map +1 -1
- package/dist/cmd/build/vite/server-bundler.d.ts +4 -0
- package/dist/cmd/build/vite/server-bundler.d.ts.map +1 -1
- package/dist/cmd/build/vite/server-bundler.js +45 -16
- package/dist/cmd/build/vite/server-bundler.js.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server-config.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server-config.js +4 -0
- package/dist/cmd/build/vite/vite-asset-server-config.js.map +1 -1
- package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-builder.js +99 -87
- package/dist/cmd/build/vite/vite-builder.js.map +1 -1
- package/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.js +78 -27
- package/dist/cmd/cloud/deploy.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/create-namespace.d.ts.map +1 -1
- package/dist/cmd/cloud/keyvalue/create-namespace.js +3 -1
- package/dist/cmd/cloud/keyvalue/create-namespace.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/delete-namespace.d.ts.map +1 -1
- package/dist/cmd/cloud/keyvalue/delete-namespace.js +3 -1
- package/dist/cmd/cloud/keyvalue/delete-namespace.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/delete.d.ts.map +1 -1
- package/dist/cmd/cloud/keyvalue/delete.js +3 -1
- package/dist/cmd/cloud/keyvalue/delete.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/set.d.ts.map +1 -1
- package/dist/cmd/cloud/keyvalue/set.js +4 -2
- package/dist/cmd/cloud/keyvalue/set.js.map +1 -1
- package/dist/cmd/cloud/stream/get.d.ts.map +1 -1
- package/dist/cmd/cloud/stream/get.js +2 -13
- package/dist/cmd/cloud/stream/get.js.map +1 -1
- package/dist/cmd/cloud/vector/delete-namespace.d.ts +3 -0
- package/dist/cmd/cloud/vector/delete-namespace.d.ts.map +1 -0
- package/dist/cmd/cloud/vector/delete-namespace.js +77 -0
- package/dist/cmd/cloud/vector/delete-namespace.js.map +1 -0
- package/dist/cmd/cloud/vector/index.d.ts.map +1 -1
- package/dist/cmd/cloud/vector/index.js +21 -4
- package/dist/cmd/cloud/vector/index.js.map +1 -1
- package/dist/cmd/cloud/vector/list-namespaces.d.ts +3 -0
- package/dist/cmd/cloud/vector/list-namespaces.d.ts.map +1 -0
- package/dist/cmd/cloud/vector/list-namespaces.js +42 -0
- package/dist/cmd/cloud/vector/list-namespaces.js.map +1 -0
- package/dist/cmd/cloud/vector/stats.d.ts +3 -0
- package/dist/cmd/cloud/vector/stats.d.ts.map +1 -0
- package/dist/cmd/cloud/vector/stats.js +142 -0
- package/dist/cmd/cloud/vector/stats.js.map +1 -0
- package/dist/cmd/cloud/vector/upsert.d.ts +3 -0
- package/dist/cmd/cloud/vector/upsert.d.ts.map +1 -0
- package/dist/cmd/cloud/vector/upsert.js +192 -0
- package/dist/cmd/cloud/vector/upsert.js.map +1 -0
- package/dist/cmd/dev/file-watcher.d.ts.map +1 -1
- package/dist/cmd/dev/file-watcher.js +90 -31
- package/dist/cmd/dev/file-watcher.js.map +1 -1
- package/dist/cmd/dev/index.d.ts.map +1 -1
- package/dist/cmd/dev/index.js +213 -57
- package/dist/cmd/dev/index.js.map +1 -1
- package/dist/cmd/dev/skills.d.ts +10 -0
- package/dist/cmd/dev/skills.d.ts.map +1 -0
- package/dist/cmd/dev/skills.js +57 -0
- package/dist/cmd/dev/skills.js.map +1 -0
- package/dist/cmd/dev/sync.js +7 -7
- package/dist/cmd/dev/sync.js.map +1 -1
- package/dist/cmd/index.d.ts.map +1 -1
- package/dist/cmd/index.js +1 -0
- package/dist/cmd/index.js.map +1 -1
- package/dist/cmd/project/create.d.ts.map +1 -1
- package/dist/cmd/project/create.js +3 -0
- package/dist/cmd/project/create.js.map +1 -1
- package/dist/cmd/project/template-flow.d.ts +1 -0
- package/dist/cmd/project/template-flow.d.ts.map +1 -1
- package/dist/cmd/project/template-flow.js +30 -5
- package/dist/cmd/project/template-flow.js.map +1 -1
- package/dist/cmd/setup/index.d.ts.map +1 -1
- package/dist/cmd/setup/index.js +1 -0
- package/dist/cmd/setup/index.js.map +1 -1
- package/dist/cmd/upgrade/index.d.ts +15 -0
- package/dist/cmd/upgrade/index.d.ts.map +1 -1
- package/dist/cmd/upgrade/index.js +59 -4
- package/dist/cmd/upgrade/index.js.map +1 -1
- package/dist/domain.d.ts +45 -0
- package/dist/domain.d.ts.map +1 -0
- package/dist/domain.js +200 -0
- package/dist/domain.js.map +1 -0
- package/dist/schema-generator.d.ts +2 -0
- package/dist/schema-generator.d.ts.map +1 -1
- package/dist/schema-generator.js +18 -0
- package/dist/schema-generator.js.map +1 -1
- package/dist/steps.d.ts +1 -1
- package/dist/steps.d.ts.map +1 -1
- package/dist/steps.js +16 -5
- package/dist/steps.js.map +1 -1
- package/dist/tui/prompt.d.ts +1 -2
- package/dist/tui/prompt.d.ts.map +1 -1
- package/dist/tui/prompt.js +8 -4
- package/dist/tui/prompt.js.map +1 -1
- package/dist/tui.d.ts +16 -0
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +23 -2
- package/dist/tui.js.map +1 -1
- package/dist/types.d.ts +9 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +3 -3
- package/dist/types.js.map +1 -1
- package/package.json +4 -4
- package/src/cli.ts +47 -12
- package/src/cmd/ai/index.ts +6 -1
- package/src/cmd/ai/prompt/agent.md +306 -0
- package/src/cmd/ai/prompt/agent.ts +12 -322
- package/src/cmd/ai/prompt/api.md +360 -0
- package/src/cmd/ai/prompt/api.ts +13 -260
- package/src/cmd/ai/prompt/version.ts +61 -0
- package/src/cmd/ai/prompt/web.md +509 -0
- package/src/cmd/ai/prompt/web.ts +12 -282
- package/src/cmd/ai/skills/generate.ts +75 -0
- package/src/cmd/ai/skills/generator.ts +519 -0
- package/src/cmd/ai/skills/index.ts +23 -0
- package/src/cmd/auth/signup.ts +1 -0
- package/src/cmd/build/entry-generator.ts +43 -7
- package/src/cmd/build/vite/bun-dev-server.ts +57 -27
- package/src/cmd/build/vite/metadata-generator.ts +73 -7
- package/src/cmd/build/vite/prompt-generator.ts +169 -0
- package/src/cmd/build/vite/registry-generator.ts +33 -10
- package/src/cmd/build/vite/server-bundler.ts +53 -22
- package/src/cmd/build/vite/vite-asset-server-config.ts +5 -0
- package/src/cmd/build/vite/vite-builder.ts +107 -87
- package/src/cmd/cloud/deploy.ts +99 -31
- package/src/cmd/cloud/keyvalue/create-namespace.ts +3 -1
- package/src/cmd/cloud/keyvalue/delete-namespace.ts +3 -1
- package/src/cmd/cloud/keyvalue/delete.ts +3 -1
- package/src/cmd/cloud/keyvalue/set.ts +4 -2
- package/src/cmd/cloud/stream/get.ts +2 -9
- package/src/cmd/cloud/vector/delete-namespace.ts +89 -0
- package/src/cmd/cloud/vector/index.ts +21 -4
- package/src/cmd/cloud/vector/list-namespaces.ts +46 -0
- package/src/cmd/cloud/vector/stats.ts +160 -0
- package/src/cmd/cloud/vector/upsert.ts +216 -0
- package/src/cmd/dev/file-watcher.ts +101 -32
- package/src/cmd/dev/index.ts +304 -111
- package/src/cmd/dev/skills.ts +82 -0
- package/src/cmd/dev/sync.ts +7 -7
- package/src/cmd/index.ts +1 -0
- package/src/cmd/project/create.ts +3 -0
- package/src/cmd/project/template-flow.ts +37 -5
- package/src/cmd/setup/index.ts +1 -0
- package/src/cmd/upgrade/index.ts +68 -4
- package/src/domain.ts +273 -0
- package/src/schema-generator.ts +23 -0
- package/src/steps.ts +16 -5
- package/src/tui/prompt.ts +11 -5
- package/src/tui.ts +21 -2
- package/src/types/md.d.ts +8 -0
- package/src/types.ts +12 -3
- package/dist/cmd/cloud/domain.d.ts +0 -17
- package/dist/cmd/cloud/domain.d.ts.map +0 -1
- package/dist/cmd/cloud/domain.js +0 -79
- package/dist/cmd/cloud/domain.js.map +0 -1
- 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
|
package/src/cmd/ai/prompt/api.ts
CHANGED
|
@@ -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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
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
|
+
}
|