@vertesia/tools-sdk 0.81.1 → 1.0.0-dev.20260203.130115Z
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/package.json +9 -8
- package/src/ContentTypesCollection.ts +51 -0
- package/src/InteractionCollection.ts +1 -94
- package/src/SkillCollection.ts +88 -15
- package/src/ToolCollection.ts +65 -17
- package/src/ToolRegistry.ts +101 -9
- package/src/auth.ts +37 -6
- package/src/index.ts +7 -3
- package/src/server/app-package.ts +102 -0
- package/src/server/conyent-types.ts +71 -0
- package/src/server/interactions.ts +100 -0
- package/src/server/mcp.ts +51 -0
- package/src/server/site.ts +53 -0
- package/src/server/skills.ts +133 -0
- package/src/server/tools.ts +128 -0
- package/src/server/types.ts +87 -0
- package/src/server/widgets.ts +38 -0
- package/src/server.ts +80 -359
- package/src/site/styles.ts +71 -0
- package/src/site/templates.ts +215 -119
- package/src/types.ts +22 -18
- package/src/utils.ts +20 -0
- package/lib/cjs/InteractionCollection.js +0 -164
- package/lib/cjs/InteractionCollection.js.map +0 -1
- package/lib/cjs/SkillCollection.js +0 -318
- package/lib/cjs/SkillCollection.js.map +0 -1
- package/lib/cjs/ToolCollection.js +0 -192
- package/lib/cjs/ToolCollection.js.map +0 -1
- package/lib/cjs/ToolRegistry.js +0 -44
- package/lib/cjs/ToolRegistry.js.map +0 -1
- package/lib/cjs/auth.js +0 -89
- package/lib/cjs/auth.js.map +0 -1
- package/lib/cjs/build/validate.js +0 -7
- package/lib/cjs/build/validate.js.map +0 -1
- package/lib/cjs/copy-assets.js +0 -84
- package/lib/cjs/copy-assets.js.map +0 -1
- package/lib/cjs/index.js +0 -30
- package/lib/cjs/index.js.map +0 -1
- package/lib/cjs/package.json +0 -3
- package/lib/cjs/server.js +0 -327
- package/lib/cjs/server.js.map +0 -1
- package/lib/cjs/site/styles.js +0 -621
- package/lib/cjs/site/styles.js.map +0 -1
- package/lib/cjs/site/templates.js +0 -932
- package/lib/cjs/site/templates.js.map +0 -1
- package/lib/cjs/types.js +0 -3
- package/lib/cjs/types.js.map +0 -1
- package/lib/cjs/utils.js +0 -7
- package/lib/cjs/utils.js.map +0 -1
- package/lib/esm/InteractionCollection.js +0 -125
- package/lib/esm/InteractionCollection.js.map +0 -1
- package/lib/esm/SkillCollection.js +0 -311
- package/lib/esm/SkillCollection.js.map +0 -1
- package/lib/esm/ToolCollection.js +0 -154
- package/lib/esm/ToolCollection.js.map +0 -1
- package/lib/esm/ToolRegistry.js +0 -39
- package/lib/esm/ToolRegistry.js.map +0 -1
- package/lib/esm/auth.js +0 -82
- package/lib/esm/auth.js.map +0 -1
- package/lib/esm/build/validate.js +0 -4
- package/lib/esm/build/validate.js.map +0 -1
- package/lib/esm/copy-assets.js +0 -81
- package/lib/esm/copy-assets.js.map +0 -1
- package/lib/esm/index.js +0 -10
- package/lib/esm/index.js.map +0 -1
- package/lib/esm/server.js +0 -323
- package/lib/esm/server.js.map +0 -1
- package/lib/esm/site/styles.js +0 -618
- package/lib/esm/site/styles.js.map +0 -1
- package/lib/esm/site/templates.js +0 -920
- package/lib/esm/site/templates.js.map +0 -1
- package/lib/esm/types.js +0 -2
- package/lib/esm/types.js.map +0 -1
- package/lib/esm/utils.js +0 -4
- package/lib/esm/utils.js.map +0 -1
- package/lib/types/InteractionCollection.d.ts +0 -48
- package/lib/types/InteractionCollection.d.ts.map +0 -1
- package/lib/types/SkillCollection.d.ts +0 -111
- package/lib/types/SkillCollection.d.ts.map +0 -1
- package/lib/types/ToolCollection.d.ts +0 -61
- package/lib/types/ToolCollection.d.ts.map +0 -1
- package/lib/types/ToolRegistry.d.ts +0 -15
- package/lib/types/ToolRegistry.d.ts.map +0 -1
- package/lib/types/auth.d.ts +0 -20
- package/lib/types/auth.d.ts.map +0 -1
- package/lib/types/build/validate.d.ts +0 -2
- package/lib/types/build/validate.d.ts.map +0 -1
- package/lib/types/copy-assets.d.ts +0 -14
- package/lib/types/copy-assets.d.ts.map +0 -1
- package/lib/types/index.d.ts +0 -10
- package/lib/types/index.d.ts.map +0 -1
- package/lib/types/server.d.ts +0 -72
- package/lib/types/server.d.ts.map +0 -1
- package/lib/types/site/styles.d.ts +0 -5
- package/lib/types/site/styles.d.ts.map +0 -1
- package/lib/types/site/templates.d.ts +0 -54
- package/lib/types/site/templates.d.ts.map +0 -1
- package/lib/types/types.d.ts +0 -262
- package/lib/types/types.d.ts.map +0 -1
- package/lib/types/utils.d.ts +0 -2
- package/lib/types/utils.d.ts.map +0 -1
package/src/server.ts
CHANGED
|
@@ -1,69 +1,29 @@
|
|
|
1
|
-
import { CatalogInteractionRef } from "@vertesia/common";
|
|
2
1
|
import { Context, Hono } from "hono";
|
|
3
2
|
import { cors } from "hono/cors";
|
|
4
3
|
import { HTTPException } from "hono/http-exception";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
} from "./
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { createInteractionsRoute } from "./server/interactions.js";
|
|
6
|
+
import { createMcpRoute } from "./server/mcp.js";
|
|
7
|
+
import { createSiteRoute } from "./server/site.js";
|
|
8
|
+
import { createSkillsRoute } from "./server/skills.js";
|
|
9
|
+
import { createToolsRoute } from "./server/tools.js";
|
|
10
|
+
import { ToolContext, ToolServerConfig } from "./server/types.js";
|
|
11
|
+
import { ToolExecutionPayload } from "./types.js";
|
|
12
|
+
import { createWidgetsRoute } from "./server/widgets.js";
|
|
13
|
+
import { createPackageRoute } from "./server/app-package.js";
|
|
14
|
+
import { createContentTypesRoute } from "./server/conyent-types.js";
|
|
15
|
+
|
|
16
|
+
// Schema for tool execution payload
|
|
17
|
+
const ToolExecutionPayloadSchema = z.object({
|
|
18
|
+
tool_use: z.object({
|
|
19
|
+
id: z.string(),
|
|
20
|
+
tool_name: z.string(),
|
|
21
|
+
tool_input: z.record(z.string(), z.any()).default({}),
|
|
22
|
+
}),
|
|
23
|
+
metadata: z.record(z.string(), z.any()).optional(),
|
|
24
|
+
});
|
|
20
25
|
|
|
21
|
-
/**
|
|
22
|
-
* MCP Provider interface for server configuration
|
|
23
|
-
*/
|
|
24
|
-
export interface MCPProviderConfig {
|
|
25
|
-
name: string;
|
|
26
|
-
description?: string;
|
|
27
|
-
createMCPConnection: (session: any, config: Record<string, any>) => Promise<{
|
|
28
|
-
name: string;
|
|
29
|
-
url: string;
|
|
30
|
-
token: string;
|
|
31
|
-
}>;
|
|
32
|
-
}
|
|
33
26
|
|
|
34
|
-
/**
|
|
35
|
-
* Server configuration options
|
|
36
|
-
*/
|
|
37
|
-
export interface ToolServerConfig {
|
|
38
|
-
/**
|
|
39
|
-
* Server title for HTML pages (default: 'Tools Server')
|
|
40
|
-
*/
|
|
41
|
-
title?: string;
|
|
42
|
-
/**
|
|
43
|
-
* API prefix (default: '/api')
|
|
44
|
-
*/
|
|
45
|
-
prefix?: string;
|
|
46
|
-
/**
|
|
47
|
-
* Tool collections to expose
|
|
48
|
-
*/
|
|
49
|
-
tools?: ToolCollection[];
|
|
50
|
-
/**
|
|
51
|
-
* Interaction collections to expose
|
|
52
|
-
*/
|
|
53
|
-
interactions?: InteractionCollection[];
|
|
54
|
-
/**
|
|
55
|
-
* Skill collections to expose
|
|
56
|
-
*/
|
|
57
|
-
skills?: SkillCollection[];
|
|
58
|
-
/**
|
|
59
|
-
* MCP providers to expose
|
|
60
|
-
*/
|
|
61
|
-
mcpProviders?: MCPProviderConfig[];
|
|
62
|
-
/**
|
|
63
|
-
* Disable HTML pages (default: false)
|
|
64
|
-
*/
|
|
65
|
-
disableHtml?: boolean;
|
|
66
|
-
}
|
|
67
27
|
|
|
68
28
|
/**
|
|
69
29
|
* Create a Hono server for tools, interactions, and skills.
|
|
@@ -82,13 +42,12 @@ export interface ToolServerConfig {
|
|
|
82
42
|
*/
|
|
83
43
|
export function createToolServer(config: ToolServerConfig): Hono {
|
|
84
44
|
const {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
disableHtml = false,
|
|
45
|
+
prefix = '/api',
|
|
46
|
+
tools = [],
|
|
47
|
+
interactions = [],
|
|
48
|
+
skills = [],
|
|
49
|
+
mcpProviders = [],
|
|
50
|
+
disableHtml = false,
|
|
92
51
|
} = config;
|
|
93
52
|
|
|
94
53
|
const app = new Hono();
|
|
@@ -96,33 +55,31 @@ export function createToolServer(config: ToolServerConfig): Hono {
|
|
|
96
55
|
// Add CORS middleware globally
|
|
97
56
|
app.use('*', cors({ origin: '*', allowMethods: ['GET', 'POST', 'OPTIONS'] }));
|
|
98
57
|
|
|
99
|
-
//
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
});
|
|
58
|
+
// Middleware to parse and validate body, store on context for reuse
|
|
59
|
+
app.use('*', async (c, next) => {
|
|
60
|
+
const ctx = c as unknown as ToolContext;
|
|
61
|
+
if (c.req.method === 'POST') {
|
|
62
|
+
try {
|
|
63
|
+
const text = await c.req.text();
|
|
64
|
+
const body = JSON.parse(text);
|
|
65
|
+
const result = ToolExecutionPayloadSchema.safeParse(body);
|
|
66
|
+
if (result.success) {
|
|
67
|
+
ctx.payload = result.data as ToolExecutionPayload<any>;
|
|
68
|
+
ctx.toolUseId = result.data.tool_use.id;
|
|
69
|
+
ctx.toolName = result.data.tool_use.tool_name;
|
|
70
|
+
}
|
|
71
|
+
// If validation fails, still store raw body for error reporting
|
|
72
|
+
// but don't set payload - handlers will return validation error
|
|
73
|
+
} catch {
|
|
74
|
+
// Ignore parsing errors - body might not be JSON
|
|
75
|
+
}
|
|
118
76
|
}
|
|
77
|
+
await next();
|
|
78
|
+
});
|
|
119
79
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
return c.html(interactionCollectionPage(coll));
|
|
124
|
-
});
|
|
125
|
-
}
|
|
80
|
+
// HTML pages (unless disabled)
|
|
81
|
+
if (!disableHtml) {
|
|
82
|
+
createSiteRoute(app, '', config);
|
|
126
83
|
}
|
|
127
84
|
|
|
128
85
|
// Add base API route
|
|
@@ -143,292 +100,56 @@ export function createToolServer(config: ToolServerConfig): Hono {
|
|
|
143
100
|
});
|
|
144
101
|
});
|
|
145
102
|
|
|
146
|
-
// ================== Aggregate Endpoints ==================
|
|
147
|
-
// These must be registered BEFORE collection-specific routes
|
|
148
|
-
|
|
149
|
-
// GET /api/skills - Returns all skills from all collections
|
|
150
|
-
app.get(`${prefix}/skills`, (c) => {
|
|
151
|
-
const url = new URL(c.req.url);
|
|
152
|
-
const allSkills: ToolDefinition[] = [];
|
|
153
|
-
|
|
154
|
-
for (const coll of skills) {
|
|
155
|
-
allSkills.push(...coll.getToolDefinitions());
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
return c.json({
|
|
159
|
-
src: `${url.origin}${url.pathname}`,
|
|
160
|
-
title: 'All Skills',
|
|
161
|
-
description: 'All available skills across all collections',
|
|
162
|
-
tools: allSkills,
|
|
163
|
-
collections: skills.map(s => ({
|
|
164
|
-
name: s.name,
|
|
165
|
-
title: s.title,
|
|
166
|
-
description: s.description,
|
|
167
|
-
})),
|
|
168
|
-
} satisfies ToolCollectionDefinition & { collections: any[] });
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
// GET /api/tools - Returns all tools from all collections
|
|
172
|
-
app.get(`${prefix}/tools`, (c) => {
|
|
173
|
-
const url = new URL(c.req.url);
|
|
174
|
-
const allTools: ToolDefinition[] = [];
|
|
175
|
-
|
|
176
|
-
for (const coll of tools) {
|
|
177
|
-
allTools.push(...coll.getToolDefinitions());
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return c.json({
|
|
181
|
-
src: `${url.origin}${url.pathname}`,
|
|
182
|
-
title: 'All Tools',
|
|
183
|
-
description: 'All available tools across all collections',
|
|
184
|
-
tools: allTools,
|
|
185
|
-
collections: tools.map(t => ({
|
|
186
|
-
name: t.name,
|
|
187
|
-
title: t.title,
|
|
188
|
-
description: t.description,
|
|
189
|
-
})),
|
|
190
|
-
} satisfies ToolCollectionDefinition & { collections: any[] });
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
// GET /api/interactions - Returns all interactions from all collections
|
|
194
|
-
app.get(`${prefix}/interactions`, (c) => {
|
|
195
|
-
const allInteractions: CatalogInteractionRef[] = [];
|
|
196
|
-
|
|
197
|
-
for (const coll of interactions) {
|
|
198
|
-
for (const inter of coll.interactions) {
|
|
199
|
-
allInteractions.push({
|
|
200
|
-
type: "app",
|
|
201
|
-
id: inter.name,
|
|
202
|
-
name: inter.name,
|
|
203
|
-
title: inter.title || inter.name,
|
|
204
|
-
description: inter.description,
|
|
205
|
-
tags: inter.tags || [],
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
return c.json({
|
|
211
|
-
title: 'All Interactions',
|
|
212
|
-
description: 'All available interactions across all collections',
|
|
213
|
-
interactions: allInteractions,
|
|
214
|
-
collections: interactions.map(i => ({
|
|
215
|
-
name: i.name,
|
|
216
|
-
title: i.title,
|
|
217
|
-
description: i.description,
|
|
218
|
-
})),
|
|
219
|
-
});
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
// Create tool collection endpoints
|
|
223
|
-
for (const coll of tools) {
|
|
224
|
-
app.route(`${prefix}/tools/${coll.name}`, createToolEndpoints(coll));
|
|
225
|
-
// Also expose at root for backwards compatibility
|
|
226
|
-
app.route(`${prefix}/${coll.name}`, createToolEndpoints(coll));
|
|
227
|
-
}
|
|
228
103
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
}
|
|
104
|
+
createPackageRoute(app, `${prefix}/package`, config);
|
|
105
|
+
createToolsRoute(app, `${prefix}/tools`, config);
|
|
106
|
+
createSkillsRoute(app, `${prefix}/skills`, config);
|
|
107
|
+
createWidgetsRoute(app, `${prefix}/widgets`, config);
|
|
108
|
+
createInteractionsRoute(app, `${prefix}/interactions`, config);
|
|
109
|
+
createContentTypesRoute(app, `${prefix}/types`, config);
|
|
110
|
+
createMcpRoute(app, `${prefix}/mcp`, config);
|
|
233
111
|
|
|
234
|
-
// Create skill collection endpoints (exposed as tools)
|
|
235
|
-
for (const coll of skills) {
|
|
236
|
-
app.route(`${prefix}/skills/${coll.name}`, createSkillEndpoints(coll));
|
|
237
|
-
}
|
|
238
112
|
|
|
239
|
-
//
|
|
240
|
-
if (mcpProviders.length > 0) {
|
|
241
|
-
app.route(`${prefix}/mcp`, createMCPEndpoints(mcpProviders));
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// Global error handler
|
|
113
|
+
// Global error handler - returns ToolExecutionResponseError format
|
|
245
114
|
app.onError((err, c) => {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
console.error('Uncaught Error:', err);
|
|
250
|
-
return c.json({ error: 'Internal Server Error' }, 500);
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
return app;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
// ================== Tool Endpoints ==================
|
|
257
|
-
|
|
258
|
-
function createToolEndpoints(coll: ToolCollection): Hono {
|
|
259
|
-
const endpoint = new Hono();
|
|
260
|
-
|
|
261
|
-
endpoint.post('/', (c: Context) => {
|
|
262
|
-
return coll.execute(c);
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
endpoint.get('/', (c) => {
|
|
266
|
-
const importSourceUrl = c.req.query('import') != null;
|
|
267
|
-
const url = new URL(c.req.url);
|
|
268
|
-
return c.json({
|
|
269
|
-
src: importSourceUrl
|
|
270
|
-
? `${url.origin}/libs/vertesia-tools-${coll.name}.js`
|
|
271
|
-
: `${url.origin}${url.pathname}`,
|
|
272
|
-
title: coll.title || coll.name,
|
|
273
|
-
description: coll.description || '',
|
|
274
|
-
tools: coll.getToolDefinitions()
|
|
275
|
-
} satisfies ToolCollectionDefinition);
|
|
276
|
-
});
|
|
115
|
+
const ctx = c as unknown as ToolContext;
|
|
116
|
+
const status = err instanceof HTTPException ? err.status : 500;
|
|
117
|
+
const errorMessage = err instanceof HTTPException ? err.message : 'Internal Server Error';
|
|
277
118
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
// ================== Interaction Endpoints ==================
|
|
282
|
-
|
|
283
|
-
function createInteractionEndpoints(coll: InteractionCollection): Hono {
|
|
284
|
-
const endpoint = new Hono();
|
|
285
|
-
|
|
286
|
-
endpoint.get('/', (c: Context) => {
|
|
287
|
-
return c.json(coll.interactions.map(inter => ({
|
|
288
|
-
type: "app",
|
|
289
|
-
id: inter.name,
|
|
290
|
-
name: inter.name,
|
|
291
|
-
title: inter.title || inter.name,
|
|
292
|
-
description: inter.description,
|
|
293
|
-
tags: inter.tags || [],
|
|
294
|
-
} satisfies CatalogInteractionRef)));
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
endpoint.get('/:name', async (c: Context) => {
|
|
298
|
-
await authorize(c);
|
|
299
|
-
const name = c.req.param('name');
|
|
300
|
-
const inter = coll.getInteractionByName(name);
|
|
301
|
-
if (!inter) {
|
|
302
|
-
throw new HTTPException(404, {
|
|
303
|
-
message: "No interaction found with name: " + name
|
|
304
|
-
});
|
|
119
|
+
if (!(err instanceof HTTPException)) {
|
|
120
|
+
console.error('Uncaught Error:', err);
|
|
305
121
|
}
|
|
306
|
-
return c.json(inter);
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
return endpoint;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
// ================== Skill Endpoints ==================
|
|
313
|
-
|
|
314
|
-
function createSkillEndpoints(coll: SkillCollection): Hono {
|
|
315
|
-
const endpoint = new Hono();
|
|
316
122
|
|
|
317
|
-
// List skills as tool definitions (tool collection format)
|
|
318
|
-
// This allows skills to be used exactly like tools
|
|
319
|
-
endpoint.get('/', (c: Context) => {
|
|
320
|
-
const url = new URL(c.req.url);
|
|
321
123
|
return c.json({
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
}
|
|
124
|
+
tool_use_id: ctx.toolUseId || 'unknown',
|
|
125
|
+
status,
|
|
126
|
+
error: errorMessage,
|
|
127
|
+
data: ctx.toolName ? { tool_name: ctx.toolName } : undefined,
|
|
128
|
+
}, status);
|
|
327
129
|
});
|
|
328
130
|
|
|
329
|
-
//
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
const name = c.req.param('name');
|
|
333
|
-
const skillName = name.startsWith('skill_') ? name.slice(6) : name;
|
|
334
|
-
const skill = coll.getSkill(skillName);
|
|
335
|
-
if (!skill) {
|
|
336
|
-
throw new HTTPException(404, {
|
|
337
|
-
message: `Skill not found: ${skillName}`
|
|
338
|
-
});
|
|
339
|
-
}
|
|
131
|
+
// Not found handler - returns ToolExecutionResponseError format
|
|
132
|
+
app.notFound((c) => {
|
|
133
|
+
const ctx = c as unknown as ToolContext;
|
|
340
134
|
return c.json({
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
// Get a specific script file
|
|
347
|
-
endpoint.get('/:name/scripts/:filename', (c: Context) => {
|
|
348
|
-
const name = c.req.param('name');
|
|
349
|
-
const filename = c.req.param('filename');
|
|
350
|
-
const skillName = name.startsWith('skill_') ? name.slice(6) : name;
|
|
351
|
-
const skill = coll.getSkill(skillName);
|
|
352
|
-
if (!skill) {
|
|
353
|
-
throw new HTTPException(404, {
|
|
354
|
-
message: `Skill not found: ${skillName}`
|
|
355
|
-
});
|
|
356
|
-
}
|
|
357
|
-
const script = skill.scripts?.find(s => s.name === filename);
|
|
358
|
-
if (!script) {
|
|
359
|
-
throw new HTTPException(404, {
|
|
360
|
-
message: `Script not found: ${filename}`
|
|
361
|
-
});
|
|
362
|
-
}
|
|
363
|
-
// Return as plain text with appropriate content type
|
|
364
|
-
const contentType = filename.endsWith('.py') ? 'text/x-python'
|
|
365
|
-
: filename.endsWith('.sh') ? 'text/x-shellscript'
|
|
366
|
-
: filename.endsWith('.js') ? 'text/javascript'
|
|
367
|
-
: 'text/plain';
|
|
368
|
-
return c.text(script.content, 200, { 'Content-Type': contentType });
|
|
369
|
-
});
|
|
370
|
-
|
|
371
|
-
// Get a specific skill by name
|
|
372
|
-
endpoint.get('/:name', (c: Context) => {
|
|
373
|
-
const name = c.req.param('name');
|
|
374
|
-
// Handle both "skill_name" and "name" formats
|
|
375
|
-
const skillName = name.startsWith('skill_') ? name.slice(6) : name;
|
|
376
|
-
const skill = coll.getSkill(skillName);
|
|
377
|
-
if (!skill) {
|
|
378
|
-
throw new HTTPException(404, {
|
|
379
|
-
message: `Skill not found: ${skillName}`
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
|
-
return c.json(skill satisfies SkillDefinition);
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
// Execute skill (standard tool execution format)
|
|
386
|
-
endpoint.post('/', (c: Context) => {
|
|
387
|
-
return coll.execute(c);
|
|
135
|
+
tool_use_id: ctx.toolUseId || 'unknown',
|
|
136
|
+
status: 404,
|
|
137
|
+
error: `Not found: ${c.req.method} ${c.req.path}`,
|
|
138
|
+
data: ctx.toolName ? { tool_name: ctx.toolName } : undefined,
|
|
139
|
+
}, 404);
|
|
388
140
|
});
|
|
389
141
|
|
|
390
|
-
return
|
|
142
|
+
return app;
|
|
391
143
|
}
|
|
392
144
|
|
|
393
|
-
// ================== MCP Endpoints ==================
|
|
394
|
-
|
|
395
|
-
function createMCPEndpoints(providers: MCPProviderConfig[]): Hono {
|
|
396
|
-
const endpoint = new Hono();
|
|
397
|
-
|
|
398
|
-
for (const p of providers) {
|
|
399
|
-
endpoint.post(`/${p.name}`, async (c: Context) => {
|
|
400
|
-
const session = await authorize(c);
|
|
401
|
-
const config = await readJsonBody(c);
|
|
402
|
-
const info = await p.createMCPConnection(session, config);
|
|
403
|
-
return c.json(info);
|
|
404
|
-
});
|
|
405
|
-
|
|
406
|
-
endpoint.get(`/${p.name}`, (c: Context) => c.json({
|
|
407
|
-
name: p.name,
|
|
408
|
-
description: p.description,
|
|
409
|
-
}));
|
|
410
|
-
}
|
|
411
145
|
|
|
412
|
-
return endpoint;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
async function readJsonBody(ctx: Context): Promise<Record<string, any>> {
|
|
416
|
-
try {
|
|
417
|
-
const text = await ctx.req.text();
|
|
418
|
-
const jsonContent = text?.trim() || '';
|
|
419
|
-
if (!jsonContent) return {};
|
|
420
|
-
return JSON.parse(jsonContent) as Record<string, any>;
|
|
421
|
-
} catch (err: any) {
|
|
422
|
-
throw new HTTPException(400, {
|
|
423
|
-
message: "Failed to parse JSON body: " + err.message
|
|
424
|
-
});
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
146
|
|
|
428
147
|
// ================== Server Utilities ==================
|
|
429
148
|
|
|
430
149
|
/**
|
|
431
|
-
* Simple development server with static
|
|
150
|
+
* Simple development server with static fimesale handling
|
|
151
|
+
*
|
|
152
|
+
* @deprecated Use tools server template
|
|
432
153
|
*/
|
|
433
154
|
export function createDevServer(config: ToolServerConfig & {
|
|
434
155
|
staticHandler?: (c: Context, next: () => Promise<void>) => Promise<Response | void>;
|
package/src/site/styles.ts
CHANGED
|
@@ -396,6 +396,43 @@ hr {
|
|
|
396
396
|
font-family: ui-monospace, monospace;
|
|
397
397
|
}
|
|
398
398
|
|
|
399
|
+
.endpoint-box {
|
|
400
|
+
display: flex;
|
|
401
|
+
align-items: center;
|
|
402
|
+
gap: 0.75rem;
|
|
403
|
+
background: #f3f4f6;
|
|
404
|
+
padding: 0.75rem 1rem;
|
|
405
|
+
border-radius: 8px;
|
|
406
|
+
margin-top: 0.5rem;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
.endpoint-box code {
|
|
410
|
+
flex: 1;
|
|
411
|
+
font-family: ui-monospace, monospace;
|
|
412
|
+
font-size: 0.875rem;
|
|
413
|
+
color: #1f2937;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
.copy-btn {
|
|
417
|
+
background: #e5e7eb;
|
|
418
|
+
border: none;
|
|
419
|
+
padding: 0.5rem;
|
|
420
|
+
border-radius: 6px;
|
|
421
|
+
cursor: pointer;
|
|
422
|
+
color: #6b7280;
|
|
423
|
+
transition: all 0.15s;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
.copy-btn:hover {
|
|
427
|
+
background: #d1d5db;
|
|
428
|
+
color: #374151;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
.copy-btn svg {
|
|
432
|
+
width: 16px;
|
|
433
|
+
height: 16px;
|
|
434
|
+
}
|
|
435
|
+
|
|
399
436
|
.badge {
|
|
400
437
|
display: inline-block;
|
|
401
438
|
font-size: 0.75rem;
|
|
@@ -583,6 +620,24 @@ hr {
|
|
|
583
620
|
background: rgba(15, 23, 42, 0.95);
|
|
584
621
|
}
|
|
585
622
|
|
|
623
|
+
.endpoint-box {
|
|
624
|
+
background: rgba(31, 41, 55, 0.95);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
.endpoint-box code {
|
|
628
|
+
color: #e5e7eb;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
.copy-btn {
|
|
632
|
+
background: rgba(55, 65, 81, 0.95);
|
|
633
|
+
color: #e5e7eb;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
.copy-btn:hover {
|
|
637
|
+
background: rgba(75, 85, 99, 0.98);
|
|
638
|
+
color: #f9fafb;
|
|
639
|
+
}
|
|
640
|
+
|
|
586
641
|
.badge {
|
|
587
642
|
background: rgba(15, 23, 42, 0.96);
|
|
588
643
|
color: #e5e7eb;
|
|
@@ -613,5 +668,21 @@ hr {
|
|
|
613
668
|
.logo-dark {
|
|
614
669
|
display: block;
|
|
615
670
|
}
|
|
671
|
+
|
|
672
|
+
.plugin-link-primary:hover {
|
|
673
|
+
background: #2563eb !important;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
.plugin-link-secondary:hover {
|
|
677
|
+
background: #059669 !important;
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
.plugin-link-primary:hover {
|
|
682
|
+
background: #2563eb;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
.plugin-link-secondary:hover {
|
|
686
|
+
background: #059669;
|
|
616
687
|
}
|
|
617
688
|
`;
|