tool-server-template 0.80.0
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/.env.example +14 -0
- package/LICENSE +13 -0
- package/README.md +611 -0
- package/TESTING.md +480 -0
- package/api/index.js +31 -0
- package/lib/build-site.d.ts +2 -0
- package/lib/build-site.d.ts.map +1 -0
- package/lib/build-site.js +42 -0
- package/lib/build-site.js.map +1 -0
- package/lib/copy-assets.d.ts +8 -0
- package/lib/copy-assets.d.ts.map +1 -0
- package/lib/copy-assets.js +62 -0
- package/lib/copy-assets.js.map +1 -0
- package/lib/interactions/index.d.ts +2 -0
- package/lib/interactions/index.d.ts.map +1 -0
- package/lib/interactions/index.js +10 -0
- package/lib/interactions/index.js.map +1 -0
- package/lib/interactions/summarize/icon.svg.d.ts +3 -0
- package/lib/interactions/summarize/icon.svg.d.ts.map +1 -0
- package/lib/interactions/summarize/icon.svg.js +10 -0
- package/lib/interactions/summarize/icon.svg.js.map +1 -0
- package/lib/interactions/summarize/index.d.ts +3 -0
- package/lib/interactions/summarize/index.d.ts.map +1 -0
- package/lib/interactions/summarize/index.js +14 -0
- package/lib/interactions/summarize/index.js.map +1 -0
- package/lib/interactions/summarize/text_summarizer/index.d.ts +53 -0
- package/lib/interactions/summarize/text_summarizer/index.d.ts.map +1 -0
- package/lib/interactions/summarize/text_summarizer/index.js +56 -0
- package/lib/interactions/summarize/text_summarizer/index.js.map +1 -0
- package/lib/interactions/summarize/text_summarizer/prompt.jst +31 -0
- package/lib/interactions/summarize/text_summarizer/prompt.jst.js +4 -0
- package/lib/interactions/summarize/text_summarizer/prompt.jst.js.map +1 -0
- package/lib/server-node.d.ts +2 -0
- package/lib/server-node.d.ts.map +1 -0
- package/lib/server-node.js +14 -0
- package/lib/server-node.js.map +1 -0
- package/lib/server.d.ts +3 -0
- package/lib/server.d.ts.map +1 -0
- package/lib/server.js +17 -0
- package/lib/server.js.map +1 -0
- package/lib/skills/code-review/SKILL.md +59 -0
- package/lib/skills/index.d.ts +4 -0
- package/lib/skills/index.d.ts.map +1 -0
- package/lib/skills/index.js +14 -0
- package/lib/skills/index.js.map +1 -0
- package/lib/tools/calculator/calculator.d.ts +23 -0
- package/lib/tools/calculator/calculator.d.ts.map +1 -0
- package/lib/tools/calculator/calculator.js +42 -0
- package/lib/tools/calculator/calculator.js.map +1 -0
- package/lib/tools/calculator/icon.svg.d.ts +3 -0
- package/lib/tools/calculator/icon.svg.d.ts.map +1 -0
- package/lib/tools/calculator/icon.svg.js +10 -0
- package/lib/tools/calculator/icon.svg.js.map +1 -0
- package/lib/tools/calculator/index.d.ts +3 -0
- package/lib/tools/calculator/index.d.ts.map +1 -0
- package/lib/tools/calculator/index.js +14 -0
- package/lib/tools/calculator/index.js.map +1 -0
- package/lib/tools/calculator/manifest.d.ts +16 -0
- package/lib/tools/calculator/manifest.d.ts.map +1 -0
- package/lib/tools/calculator/manifest.js +17 -0
- package/lib/tools/calculator/manifest.js.map +1 -0
- package/lib/tools/index.d.ts +2 -0
- package/lib/tools/index.d.ts.map +1 -0
- package/lib/tools/index.js +8 -0
- package/lib/tools/index.js.map +1 -0
- package/package.json +51 -0
- package/public/.gitkeep +1 -0
- package/rollup.config.bundle.js +60 -0
- package/rollup.config.js +99 -0
- package/src/build-site.ts +77 -0
- package/src/copy-assets.ts +104 -0
- package/src/interactions/index.ts +7 -0
- package/src/interactions/summarize/icon.svg.ts +7 -0
- package/src/interactions/summarize/index.ts +11 -0
- package/src/interactions/summarize/text_summarizer/index.ts +53 -0
- package/src/interactions/summarize/text_summarizer/prompt.jst +31 -0
- package/src/raw-imports.d.ts +4 -0
- package/src/server-node.ts +24 -0
- package/src/server.ts +22 -0
- package/src/skills/code-review/SKILL.md +59 -0
- package/src/skills/index.ts +12 -0
- package/src/tools/calculator/calculator.ts +60 -0
- package/src/tools/calculator/icon.svg.ts +7 -0
- package/src/tools/calculator/index.ts +11 -0
- package/src/tools/calculator/manifest.ts +16 -0
- package/src/tools/index.ts +5 -0
- package/template.config.json +27 -0
- package/tsconfig.json +25 -0
- package/vercel.json +29 -0
package/TESTING.md
ADDED
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
# Testing Guide
|
|
2
|
+
|
|
3
|
+
This guide shows you how to test your tool server locally before deploying.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
Install dependencies:
|
|
8
|
+
```bash
|
|
9
|
+
pnpm install
|
|
10
|
+
# or
|
|
11
|
+
npm install
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Note: The `dev` command automatically builds on first run, so you can skip the manual build step unless you specifically need production builds.
|
|
15
|
+
|
|
16
|
+
## Testing Methods
|
|
17
|
+
|
|
18
|
+
The template uses **Node.js HTTP server** for both development and production - ensuring you test the exact same code that runs in production (Cloud Run, Railway, etc.).
|
|
19
|
+
|
|
20
|
+
### Development Mode (with auto-rebuild)
|
|
21
|
+
|
|
22
|
+
This mode watches for file changes and automatically rebuilds and restarts the server:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pnpm dev
|
|
26
|
+
# or
|
|
27
|
+
npm run dev
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**What happens:**
|
|
31
|
+
- Terminal 1: Rollup watch mode rebuilds TypeScript on file changes
|
|
32
|
+
- Terminal 2: Node.js --watch restarts server when lib/ changes
|
|
33
|
+
- Both run via `concurrently` in a single command
|
|
34
|
+
|
|
35
|
+
**Server runs on:** http://localhost:3000 (default)
|
|
36
|
+
|
|
37
|
+
**Test the API:**
|
|
38
|
+
```bash
|
|
39
|
+
# List all tools/skills/interactions
|
|
40
|
+
curl http://localhost:3000/api
|
|
41
|
+
|
|
42
|
+
# Execute calculator tool
|
|
43
|
+
curl -X POST http://localhost:3000/api \
|
|
44
|
+
-H "Content-Type: application/json" \
|
|
45
|
+
-d '{
|
|
46
|
+
"tool_name": "calculator",
|
|
47
|
+
"tool_input": {"expression": "10 * 5 + 2^3"},
|
|
48
|
+
"context": {"serverUrl": "http://localhost:3000"}
|
|
49
|
+
}'
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Browse the UI:**
|
|
53
|
+
- Main page: http://localhost:3000/
|
|
54
|
+
- Calculator tool: http://localhost:3000/tools/calculator
|
|
55
|
+
- Code review skill: http://localhost:3000/skills/code-review
|
|
56
|
+
- Summarize interaction: http://localhost:3000/interactions/summarize
|
|
57
|
+
|
|
58
|
+
**Custom port:**
|
|
59
|
+
```bash
|
|
60
|
+
PORT=8080 pnpm dev
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Production Mode
|
|
64
|
+
|
|
65
|
+
This is identical to how it runs in Cloud Run, Railway, etc.
|
|
66
|
+
|
|
67
|
+
**Step 1: Build**
|
|
68
|
+
```bash
|
|
69
|
+
pnpm build
|
|
70
|
+
# or
|
|
71
|
+
npm run build
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Step 2: Start the server**
|
|
75
|
+
```bash
|
|
76
|
+
pnpm start
|
|
77
|
+
# or
|
|
78
|
+
npm start
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Server will start on **http://localhost:3000** (default)
|
|
82
|
+
|
|
83
|
+
### Manual Control (Advanced)
|
|
84
|
+
|
|
85
|
+
If you want separate control of build and server processes:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Terminal 1: Rollup watch mode
|
|
89
|
+
pnpm run build:watch
|
|
90
|
+
|
|
91
|
+
# Terminal 2: Node with auto-restart
|
|
92
|
+
pnpm run start:watch
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Testing Individual Resources
|
|
96
|
+
|
|
97
|
+
### 1. Testing the Calculator Tool
|
|
98
|
+
|
|
99
|
+
Replace `{{VERTESIA_JWT}}` with a valid Vertesia JWT token in all examples below.
|
|
100
|
+
|
|
101
|
+
**Basic calculation:**
|
|
102
|
+
```bash
|
|
103
|
+
curl -H "Authorization: Bearer {{VERTESIA_JWT}}" \
|
|
104
|
+
-H "Content-Type: application/json" \
|
|
105
|
+
-X POST "http://localhost:3000/api/tools/calculator" \
|
|
106
|
+
-d '{
|
|
107
|
+
"tool_use": {
|
|
108
|
+
"id": "run1",
|
|
109
|
+
"tool_name": "calculator",
|
|
110
|
+
"tool_input": {"expression": "2 + 2"}
|
|
111
|
+
}
|
|
112
|
+
}'
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Expected response:
|
|
116
|
+
```json
|
|
117
|
+
{
|
|
118
|
+
"is_error": false,
|
|
119
|
+
"content": "Result: 2 + 2 = 4"
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**Complex expression:**
|
|
124
|
+
```bash
|
|
125
|
+
curl -H "Authorization: Bearer {{VERTESIA_JWT}}" \
|
|
126
|
+
-H "Content-Type: application/json" \
|
|
127
|
+
-X POST "http://localhost:3000/api/tools/calculator" \
|
|
128
|
+
-d '{
|
|
129
|
+
"tool_use": {
|
|
130
|
+
"id": "run2",
|
|
131
|
+
"tool_name": "calculator",
|
|
132
|
+
"tool_input": {"expression": "(10 + 5) * 2 - 3^2"}
|
|
133
|
+
}
|
|
134
|
+
}'
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**Error handling:**
|
|
138
|
+
```bash
|
|
139
|
+
curl -H "Authorization: Bearer {{VERTESIA_JWT}}" \
|
|
140
|
+
-H "Content-Type: application/json" \
|
|
141
|
+
-X POST "http://localhost:3000/api/tools/calculator" \
|
|
142
|
+
-d '{
|
|
143
|
+
"tool_use": {
|
|
144
|
+
"id": "run3",
|
|
145
|
+
"tool_name": "calculator",
|
|
146
|
+
"tool_input": {"expression": "invalid"}
|
|
147
|
+
}
|
|
148
|
+
}'
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Expected response:
|
|
152
|
+
```json
|
|
153
|
+
{
|
|
154
|
+
"is_error": true,
|
|
155
|
+
"content": "Calculation error: Failed to evaluate expression: ..."
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### 2. Testing Skills
|
|
160
|
+
|
|
161
|
+
Skills are prompt templates, so you can't "execute" them via the API. Instead, retrieve their details:
|
|
162
|
+
|
|
163
|
+
**Get skill details:**
|
|
164
|
+
```bash
|
|
165
|
+
curl -H "Authorization: Bearer {{VERTESIA_JWT}}" \
|
|
166
|
+
"http://localhost:3000/api/skills/code-review/skill_code-review"
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**List all skills:**
|
|
170
|
+
```bash
|
|
171
|
+
curl -H "Authorization: Bearer {{VERTESIA_JWT}}" \
|
|
172
|
+
"http://localhost:3000/api" | jq '.skills'
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**View skill in browser:**
|
|
176
|
+
- http://localhost:3000/skills/code-review
|
|
177
|
+
|
|
178
|
+
### 3. Testing Interactions
|
|
179
|
+
|
|
180
|
+
Interactions define workflows with templated prompts.
|
|
181
|
+
|
|
182
|
+
**Get interaction details:**
|
|
183
|
+
```bash
|
|
184
|
+
curl -H "Authorization: Bearer {{VERTESIA_JWT}}" \
|
|
185
|
+
"http://localhost:3000/api/interactions/summarize/text_summarizer"
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**List all interactions:**
|
|
189
|
+
```bash
|
|
190
|
+
curl -H "Authorization: Bearer {{VERTESIA_JWT}}" \
|
|
191
|
+
"http://localhost:3000/api" | jq '.interactions'
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Browse interaction page:**
|
|
195
|
+
- http://localhost:3000/interactions/summarize
|
|
196
|
+
|
|
197
|
+
## Testing Vercel Deployment Locally
|
|
198
|
+
|
|
199
|
+
If you want to test the Vercel deployment setup locally:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
# Install Vercel CLI
|
|
203
|
+
npm i -g vercel
|
|
204
|
+
|
|
205
|
+
# Run Vercel dev server
|
|
206
|
+
pnpm start:vercel
|
|
207
|
+
# or
|
|
208
|
+
vercel dev
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
This simulates the Vercel serverless function environment.
|
|
212
|
+
|
|
213
|
+
## Common Test Scenarios
|
|
214
|
+
|
|
215
|
+
### Test 1: Server Health Check
|
|
216
|
+
```bash
|
|
217
|
+
# Should return 200 with list of tools/skills/interactions
|
|
218
|
+
curl -i http://localhost:3000/api
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Test 2: Invalid Tool Name
|
|
222
|
+
```bash
|
|
223
|
+
curl -H "Authorization: Bearer {{VERTESIA_JWT}}" \
|
|
224
|
+
-H "Content-Type: application/json" \
|
|
225
|
+
-X POST "http://localhost:3000/api/tools/nonexistent" \
|
|
226
|
+
-d '{
|
|
227
|
+
"tool_use": {
|
|
228
|
+
"id": "test1",
|
|
229
|
+
"tool_name": "nonexistent",
|
|
230
|
+
"tool_input": {}
|
|
231
|
+
}
|
|
232
|
+
}'
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Should return an error response.
|
|
236
|
+
|
|
237
|
+
### Test 3: Missing Required Parameters
|
|
238
|
+
```bash
|
|
239
|
+
curl -H "Authorization: Bearer {{VERTESIA_JWT}}" \
|
|
240
|
+
-H "Content-Type: application/json" \
|
|
241
|
+
-X POST "http://localhost:3000/api/tools/calculator" \
|
|
242
|
+
-d '{
|
|
243
|
+
"tool_use": {
|
|
244
|
+
"id": "test2",
|
|
245
|
+
"tool_name": "calculator",
|
|
246
|
+
"tool_input": {}
|
|
247
|
+
}
|
|
248
|
+
}'
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Should return validation error about missing `expression`.
|
|
252
|
+
|
|
253
|
+
### Test 4: HTML Pages Generated
|
|
254
|
+
```bash
|
|
255
|
+
# Check main index page exists
|
|
256
|
+
curl -s http://localhost:3000/ | grep -q "Tool Server Template"
|
|
257
|
+
echo $? # Should output 0 (success)
|
|
258
|
+
|
|
259
|
+
# Check calculator tool page
|
|
260
|
+
curl -s http://localhost:3000/tools/calculator | grep -q "Calculator Tools"
|
|
261
|
+
echo $? # Should output 0
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### Test 5: Browser Bundles Created
|
|
265
|
+
```bash
|
|
266
|
+
# Check that browser bundle exists
|
|
267
|
+
ls -lh dist/libs/tool-server-calculator.js
|
|
268
|
+
|
|
269
|
+
# Should show the bundled file with size
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Debugging Tips
|
|
273
|
+
|
|
274
|
+
### Enable Detailed Logging
|
|
275
|
+
|
|
276
|
+
Add to your `.env` file:
|
|
277
|
+
```bash
|
|
278
|
+
DEBUG=*
|
|
279
|
+
NODE_ENV=development
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Check Build Output
|
|
283
|
+
|
|
284
|
+
After building, verify structure:
|
|
285
|
+
```bash
|
|
286
|
+
tree lib/ -L 3
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Expected structure:
|
|
290
|
+
```
|
|
291
|
+
lib/
|
|
292
|
+
├── server.js
|
|
293
|
+
├── server-node.js
|
|
294
|
+
├── build-site.js
|
|
295
|
+
├── index.html
|
|
296
|
+
├── tools/
|
|
297
|
+
│ └── calculator/
|
|
298
|
+
│ ├── index.html
|
|
299
|
+
│ ├── index.js
|
|
300
|
+
│ └── ...
|
|
301
|
+
├── skills/
|
|
302
|
+
│ └── code-review/
|
|
303
|
+
│ ├── index.html
|
|
304
|
+
│ └── SKILL.md
|
|
305
|
+
├── interactions/
|
|
306
|
+
│ └── summarize/
|
|
307
|
+
│ └── ...
|
|
308
|
+
└── libs/
|
|
309
|
+
└── tool-server-calculator.js
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Check TypeScript Compilation
|
|
313
|
+
|
|
314
|
+
Verify no TypeScript errors:
|
|
315
|
+
```bash
|
|
316
|
+
pnpm exec tsc --noEmit
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Watch Rollup Build Process
|
|
320
|
+
|
|
321
|
+
See what Rollup is doing:
|
|
322
|
+
```bash
|
|
323
|
+
pnpm run build:watch
|
|
324
|
+
# Watch the console for build errors
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Test with Different Ports
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
# Test port binding
|
|
331
|
+
PORT=8080 pnpm start
|
|
332
|
+
PORT=9000 pnpm start
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Debug Raw Imports
|
|
336
|
+
|
|
337
|
+
If `?raw` imports aren't working, check:
|
|
338
|
+
```bash
|
|
339
|
+
# Verify the rawPlugin is in rollup.config.js
|
|
340
|
+
grep -A 10 "rawPlugin" rollup.config.js
|
|
341
|
+
|
|
342
|
+
# Check the imported file exists
|
|
343
|
+
ls -la src/interactions/*/prompts/*.jst
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
## Performance Testing
|
|
347
|
+
|
|
348
|
+
### Simple Load Test with Apache Bench
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
# Install apache bench (usually pre-installed on Mac/Linux)
|
|
352
|
+
# On Mac: already available
|
|
353
|
+
# On Ubuntu: apt-get install apache2-utils
|
|
354
|
+
|
|
355
|
+
# Test GET /api endpoint
|
|
356
|
+
ab -n 1000 -c 10 http://localhost:3000/api
|
|
357
|
+
|
|
358
|
+
# Test POST /api endpoint (save request to file first)
|
|
359
|
+
cat > post_data.json <<EOF
|
|
360
|
+
{
|
|
361
|
+
"tool_name": "calculator",
|
|
362
|
+
"tool_input": {"expression": "2 + 2"},
|
|
363
|
+
"context": {"serverUrl": "http://localhost:3000"}
|
|
364
|
+
}
|
|
365
|
+
EOF
|
|
366
|
+
|
|
367
|
+
ab -n 1000 -c 10 -p post_data.json -T application/json http://localhost:3000/api
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
## Environment Variables
|
|
371
|
+
|
|
372
|
+
Create a `.env` file for local testing:
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
# Copy example
|
|
376
|
+
cp .env.example .env
|
|
377
|
+
|
|
378
|
+
# Edit with your values
|
|
379
|
+
PORT=3000
|
|
380
|
+
NODE_ENV=development
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
## Next Steps
|
|
384
|
+
|
|
385
|
+
Once local testing passes:
|
|
386
|
+
|
|
387
|
+
1. **Deploy to Vercel:**
|
|
388
|
+
```bash
|
|
389
|
+
vercel
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
2. **Deploy to Cloud Run:**
|
|
393
|
+
```bash
|
|
394
|
+
# Build Docker image (you'll need to create a Dockerfile)
|
|
395
|
+
gcloud run deploy tool-server \
|
|
396
|
+
--source . \
|
|
397
|
+
--platform managed \
|
|
398
|
+
--region us-central1
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
3. **Deploy to Railway/Fly.io/Render:**
|
|
402
|
+
- They can auto-detect the Node.js server from `package.json`
|
|
403
|
+
- Use `npm start` as the start command
|
|
404
|
+
|
|
405
|
+
## Troubleshooting
|
|
406
|
+
|
|
407
|
+
### Problem: `@vertesia/tools-sdk` not found
|
|
408
|
+
|
|
409
|
+
**Solution:** Make sure you're in a pnpm workspace with the SDK, or update `package.json` to point to the correct SDK location.
|
|
410
|
+
|
|
411
|
+
### Problem: HTML pages not showing
|
|
412
|
+
|
|
413
|
+
**Solution:** Run `pnpm build` first. HTML pages are generated during the build process.
|
|
414
|
+
|
|
415
|
+
### Problem: Port already in use
|
|
416
|
+
|
|
417
|
+
**Solution:** Use a different port:
|
|
418
|
+
```bash
|
|
419
|
+
PORT=8080 pnpm start
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
### Problem: Tool execution returns 404
|
|
423
|
+
|
|
424
|
+
**Solution:** Check that the tool is properly registered in `src/tools/index.ts` and rebuild:
|
|
425
|
+
```bash
|
|
426
|
+
pnpm build
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### Problem: Changes not reflected in dev mode
|
|
430
|
+
|
|
431
|
+
**Solution:**
|
|
432
|
+
- Make sure `pnpm dev` is running (it should auto-rebuild)
|
|
433
|
+
- Check the console for Rollup build errors
|
|
434
|
+
- If it's still not working, restart `pnpm dev`
|
|
435
|
+
|
|
436
|
+
### Problem: "Cannot find module" errors
|
|
437
|
+
|
|
438
|
+
**Solution:** Make sure you're using `.js` extensions in imports:
|
|
439
|
+
```typescript
|
|
440
|
+
// ✅ Correct
|
|
441
|
+
import { MyTool } from './my-tool.js';
|
|
442
|
+
|
|
443
|
+
// ❌ Wrong
|
|
444
|
+
import { MyTool } from './my-tool';
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
## Summary
|
|
448
|
+
|
|
449
|
+
**Quick Start for Testing:**
|
|
450
|
+
|
|
451
|
+
```bash
|
|
452
|
+
# 1. Install dependencies
|
|
453
|
+
pnpm install
|
|
454
|
+
|
|
455
|
+
# 2. Start development server (builds automatically + auto-rebuild + restart)
|
|
456
|
+
pnpm dev
|
|
457
|
+
|
|
458
|
+
# 3. In another terminal, test the API
|
|
459
|
+
curl http://localhost:3000/api
|
|
460
|
+
|
|
461
|
+
# 4. Test calculator tool
|
|
462
|
+
curl -H "Authorization: Bearer {{VERTESIA_JWT}}" \
|
|
463
|
+
-H "Content-Type: application/json" \
|
|
464
|
+
-X POST "http://localhost:3000/api/tools/calculator" \
|
|
465
|
+
-d '{"tool_use":{"id":"test","tool_name":"calculator","tool_input":{"expression":"2+2"}}}'
|
|
466
|
+
|
|
467
|
+
# 5. Open browser
|
|
468
|
+
open http://localhost:3000
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
**Understanding the Build Process:**
|
|
472
|
+
|
|
473
|
+
The template uses **Rollup** for everything:
|
|
474
|
+
- **TypeScript compilation** (src → dist) with `@rollup/plugin-typescript`
|
|
475
|
+
- **Raw imports** (`?raw`) via custom rawPlugin
|
|
476
|
+
- **Browser bundles** (lib/tools → dist/libs) with minification
|
|
477
|
+
|
|
478
|
+
All in one `rollup.config.js` file!
|
|
479
|
+
|
|
480
|
+
You're all set! 🚀
|
package/api/index.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vercel Serverless Function Adapter
|
|
3
|
+
*
|
|
4
|
+
* This adapter allows the Hono server to run as a Vercel serverless function.
|
|
5
|
+
* All HTTP methods are forwarded to the Hono app's fetch handler.
|
|
6
|
+
*/
|
|
7
|
+
import app from '../lib/server.js';
|
|
8
|
+
|
|
9
|
+
export async function GET(request) {
|
|
10
|
+
return await app.fetch(request);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export async function POST(request) {
|
|
14
|
+
return await app.fetch(request);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export async function PUT(request) {
|
|
18
|
+
return await app.fetch(request);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export async function PATCH(request) {
|
|
22
|
+
return await app.fetch(request);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function DELETE(request) {
|
|
26
|
+
return await app.fetch(request);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function OPTIONS(request) {
|
|
30
|
+
return await app.fetch(request);
|
|
31
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-site.d.ts","sourceRoot":"","sources":["../src/build-site.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { indexPage, toolCollectionPage, skillCollectionPage, interactionCollectionPage } from '@vertesia/tools-sdk';
|
|
2
|
+
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { loadInteractions } from './interactions/index.js';
|
|
4
|
+
import { skills } from './skills/index.js';
|
|
5
|
+
import { tools } from './tools/index.js';
|
|
6
|
+
|
|
7
|
+
async function build(outDir) {
|
|
8
|
+
console.log(`Building static site to ${outDir}...`);
|
|
9
|
+
mkdirSync(outDir, { recursive: true });
|
|
10
|
+
const interactions = await loadInteractions();
|
|
11
|
+
console.log('Creating index page...');
|
|
12
|
+
writeFileSync(`${outDir}/index.html`, indexPage(tools, skills, interactions, 'Tool Server Template'));
|
|
13
|
+
console.log(`Creating ${tools.length} tool collection pages...`);
|
|
14
|
+
for (const coll of tools) {
|
|
15
|
+
const dir = `${outDir}/tools/${coll.name}`;
|
|
16
|
+
mkdirSync(dir, { recursive: true });
|
|
17
|
+
writeFileSync(`${dir}/index.html`, toolCollectionPage(coll));
|
|
18
|
+
}
|
|
19
|
+
console.log(`Creating ${skills.length} skill collection pages...`);
|
|
20
|
+
for (const coll of skills) {
|
|
21
|
+
const dir = `${outDir}/skills/${coll.name}`;
|
|
22
|
+
mkdirSync(dir, { recursive: true });
|
|
23
|
+
writeFileSync(`${dir}/index.html`, skillCollectionPage(coll));
|
|
24
|
+
}
|
|
25
|
+
console.log(`Creating ${interactions.length} interaction collection pages...`);
|
|
26
|
+
for (const coll of interactions) {
|
|
27
|
+
const dir = `${outDir}/interactions/${coll.name}`;
|
|
28
|
+
mkdirSync(dir, { recursive: true });
|
|
29
|
+
writeFileSync(`${dir}/index.html`, interactionCollectionPage(coll));
|
|
30
|
+
}
|
|
31
|
+
console.log('✓ Static site build complete!');
|
|
32
|
+
}
|
|
33
|
+
const outDir = process.argv[2] || './dist';
|
|
34
|
+
build(outDir)
|
|
35
|
+
.then(() => {
|
|
36
|
+
process.exit(0);
|
|
37
|
+
})
|
|
38
|
+
.catch(error => {
|
|
39
|
+
console.error('Build failed:', error);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
});
|
|
42
|
+
//# sourceMappingURL=build-site.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-site.js","sources":["../src/build-site.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AAeA,eAAe,KAAK,CAAC,MAAc,EAAA;AAC/B,IAAA,OAAO,CAAC,GAAG,CAAC,2BAA2B,MAAM,CAAA,GAAA,CAAK,CAAC;IAGnD,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AAGtC,IAAA,MAAM,YAAY,GAAG,MAAM,gBAAgB,EAAE;AAG7C,IAAA,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC;AACrC,IAAA,aAAa,CACT,CAAA,EAAG,MAAM,CAAA,WAAA,CAAa,EACtB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,sBAAsB,CAAC,CACjE;IAGD,OAAO,CAAC,GAAG,CAAC,CAAA,SAAA,EAAY,KAAK,CAAC,MAAM,CAAA,yBAAA,CAA2B,CAAC;AAChE,IAAA,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;QACtB,MAAM,GAAG,GAAG,CAAA,EAAG,MAAM,UAAU,IAAI,CAAC,IAAI,CAAA,CAAE;QAC1C,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QACnC,aAAa,CACT,CAAA,EAAG,GAAG,CAAA,WAAA,CAAa,EACnB,kBAAkB,CAAC,IAAI,CAAC,CAC3B;IACL;IAGA,OAAO,CAAC,GAAG,CAAC,CAAA,SAAA,EAAY,MAAM,CAAC,MAAM,CAAA,0BAAA,CAA4B,CAAC;AAClE,IAAA,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE;QACvB,MAAM,GAAG,GAAG,CAAA,EAAG,MAAM,WAAW,IAAI,CAAC,IAAI,CAAA,CAAE;QAC3C,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QACnC,aAAa,CACT,CAAA,EAAG,GAAG,CAAA,WAAA,CAAa,EACnB,mBAAmB,CAAC,IAAI,CAAC,CAC5B;IACL;IAGA,OAAO,CAAC,GAAG,CAAC,CAAA,SAAA,EAAY,YAAY,CAAC,MAAM,CAAA,gCAAA,CAAkC,CAAC;AAC9E,IAAA,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE;QAC7B,MAAM,GAAG,GAAG,CAAA,EAAG,MAAM,iBAAiB,IAAI,CAAC,IAAI,CAAA,CAAE;QACjD,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QACnC,aAAa,CACT,CAAA,EAAG,GAAG,CAAA,WAAA,CAAa,EACnB,yBAAyB,CAAC,IAAI,CAAC,CAClC;IACL;AAEA,IAAA,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC;AAChD;AAGA,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,QAAQ;AAC1C,KAAK,CAAC,MAAM;KACP,IAAI,CAAC,MAAK;AACP,IAAA,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AACnB,CAAC;KACA,KAAK,CAAC,KAAK,IAAG;AACX,IAAA,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,CAAC;AACrC,IAAA,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AACnB,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy-assets.d.ts","sourceRoot":"","sources":["../src/copy-assets.ts"],"names":[],"mappings":";AAuCA,MAAM,WAAW,iBAAiB;IAE9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAKD,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,iBAAsB,GAAG,IAAI,CA2CvE"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync, readdirSync, statSync, mkdirSync, copyFileSync } from 'fs';
|
|
3
|
+
import { join, dirname } from 'path';
|
|
4
|
+
|
|
5
|
+
function copyFilesRecursive(src, dest, fileFilter) {
|
|
6
|
+
if (!existsSync(src))
|
|
7
|
+
return;
|
|
8
|
+
const entries = readdirSync(src);
|
|
9
|
+
for (const entry of entries) {
|
|
10
|
+
const srcPath = join(src, entry);
|
|
11
|
+
const destPath = join(dest, entry);
|
|
12
|
+
const stat = statSync(srcPath);
|
|
13
|
+
if (stat.isDirectory()) {
|
|
14
|
+
copyFilesRecursive(srcPath, destPath, fileFilter);
|
|
15
|
+
}
|
|
16
|
+
else if (fileFilter(entry)) {
|
|
17
|
+
mkdirSync(dirname(destPath), { recursive: true });
|
|
18
|
+
copyFileSync(srcPath, destPath);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function copyRuntimeAssets(options = {}) {
|
|
23
|
+
const { srcDir = './src', distDir = './dist', verbose = true } = options;
|
|
24
|
+
if (verbose) {
|
|
25
|
+
console.log('Copying runtime assets to dist...');
|
|
26
|
+
}
|
|
27
|
+
const skillsSrc = join(srcDir, 'skills');
|
|
28
|
+
const skillsDest = join(distDir, 'skills');
|
|
29
|
+
if (existsSync(skillsSrc)) {
|
|
30
|
+
copyFilesRecursive(skillsSrc, skillsDest, (filename) => {
|
|
31
|
+
return filename === 'SKILL.md' ||
|
|
32
|
+
filename === 'SKILL.jst' ||
|
|
33
|
+
filename.endsWith('.py');
|
|
34
|
+
});
|
|
35
|
+
if (verbose) {
|
|
36
|
+
console.log(' ✓ Skills assets (SKILL.md, SKILL.jst, *.py)');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const interactionsSrc = join(srcDir, 'interactions');
|
|
40
|
+
const interactionsDest = join(distDir, 'interactions');
|
|
41
|
+
if (existsSync(interactionsSrc)) {
|
|
42
|
+
copyFilesRecursive(interactionsSrc, interactionsDest, (filename) => {
|
|
43
|
+
return filename === 'prompt.jst' ||
|
|
44
|
+
filename === 'prompt.md';
|
|
45
|
+
});
|
|
46
|
+
if (verbose) {
|
|
47
|
+
console.log(' ✓ Interaction assets (prompt.jst, prompt.md)');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (verbose) {
|
|
51
|
+
console.log('Runtime assets copied successfully!');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (typeof process !== 'undefined' && process.argv[1]?.includes('copy-assets')) {
|
|
55
|
+
const args = process.argv.slice(2);
|
|
56
|
+
const srcDir = args[0] || './src';
|
|
57
|
+
const distDir = args[1] || './dist';
|
|
58
|
+
copyRuntimeAssets({ srcDir, distDir });
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export { copyRuntimeAssets };
|
|
62
|
+
//# sourceMappingURL=copy-assets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy-assets.js","sources":["../src/copy-assets.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAkBA,SAAS,kBAAkB,CAAC,GAAW,EAAE,IAAY,EAAE,UAAyC,EAAA;AAC5F,IAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE;AAEtB,IAAA,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC;AAEhC,IAAA,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC;QAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC;AAClC,QAAA,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC;AAE9B,QAAA,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE;AAEpB,YAAA,kBAAkB,CAAC,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC;QACrD;AAAO,aAAA,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE;AAE1B,YAAA,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AACjD,YAAA,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC;QACnC;IACJ;AACJ;AAcM,SAAU,iBAAiB,CAAC,OAAA,GAA6B,EAAE,EAAA;AAC7D,IAAA,MAAM,EACF,MAAM,GAAG,OAAO,EAChB,OAAO,GAAG,QAAQ,EAClB,OAAO,GAAG,IAAI,EACjB,GAAG,OAAO;IAEX,IAAI,OAAO,EAAE;AACT,QAAA,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC;IACpD;IAGA,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC;IACxC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC;AAE1C,IAAA,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE;QACvB,kBAAkB,CAAC,SAAS,EAAE,UAAU,EAAE,CAAC,QAAQ,KAAI;YACnD,OAAO,QAAQ,KAAK,UAAU;AACvB,gBAAA,QAAQ,KAAK,WAAW;AACxB,gBAAA,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC;AACnC,QAAA,CAAC,CAAC;QACF,IAAI,OAAO,EAAE;AACT,YAAA,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC;QAChE;IACJ;IAGA,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC;IACpD,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC;AAEtD,IAAA,IAAI,UAAU,CAAC,eAAe,CAAC,EAAE;QAC7B,kBAAkB,CAAC,eAAe,EAAE,gBAAgB,EAAE,CAAC,QAAQ,KAAI;YAC/D,OAAO,QAAQ,KAAK,YAAY;gBACzB,QAAQ,KAAK,WAAW;AACnC,QAAA,CAAC,CAAC;QACF,IAAI,OAAO,EAAE;AACT,YAAA,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC;QACjE;IACJ;IAEA,IAAI,OAAO,EAAE;AACT,QAAA,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC;IACtD;AACJ;AAGA,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAC,EAAE;IAC5E,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAClC,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO;IACjC,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,QAAQ;AAEnC,IAAA,iBAAiB,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC1C;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/interactions/index.ts"],"names":[],"mappings":"AAEA,wBAAsB,gBAAgB,mEAIrC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/interactions/index.ts"],"sourcesContent":[null],"names":[],"mappings":";;AAEO,eAAe,gBAAgB,GAAA;IAClC,OAAO;QACH;KACH;AACL;;;;"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
declare const _default: "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\"/>\n <polyline points=\"14 2 14 8 20 8\"/>\n <line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\"/>\n <line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\"/>\n <polyline points=\"10 9 9 9 8 9\"/>\n</svg>";
|
|
2
|
+
export default _default;
|
|
3
|
+
//# sourceMappingURL=icon.svg.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icon.svg.d.ts","sourceRoot":"","sources":["../../../src/interactions/summarize/icon.svg.ts"],"names":[],"mappings":";AAAA,wBAMQ"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
var icon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
2
|
+
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
|
|
3
|
+
<polyline points="14 2 14 8 20 8"/>
|
|
4
|
+
<line x1="16" y1="13" x2="8" y2="13"/>
|
|
5
|
+
<line x1="16" y1="17" x2="8" y2="17"/>
|
|
6
|
+
<polyline points="10 9 9 9 8 9"/>
|
|
7
|
+
</svg>`;
|
|
8
|
+
|
|
9
|
+
export { icon as default };
|
|
10
|
+
//# sourceMappingURL=icon.svg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icon.svg.js","sources":["../../../src/interactions/summarize/icon.svg.ts"],"sourcesContent":[null],"names":[],"mappings":"AAAA,WAAe,CAAA;;;;;;OAMR;;;;"}
|