@vertesia/tools-sdk 1.0.0-dev.20260305.083323Z → 1.0.0-dev.20260331.091034Z
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/lib/cjs/ActivityCollection.js +93 -0
- package/lib/cjs/ActivityCollection.js.map +1 -0
- package/lib/cjs/auth.js +3 -3
- package/lib/cjs/auth.js.map +1 -1
- package/lib/cjs/index.js +1 -0
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/server/activities.js +103 -0
- package/lib/cjs/server/activities.js.map +1 -0
- package/lib/cjs/server/app-package.js +14 -1
- package/lib/cjs/server/app-package.js.map +1 -1
- package/lib/cjs/server/interactions.js +21 -9
- package/lib/cjs/server/interactions.js.map +1 -1
- package/lib/cjs/server/site.js +7 -1
- package/lib/cjs/server/site.js.map +1 -1
- package/lib/cjs/server/skills.js +10 -0
- package/lib/cjs/server/skills.js.map +1 -1
- package/lib/cjs/server.js +4 -1
- package/lib/cjs/server.js.map +1 -1
- package/lib/cjs/site/templates.js +138 -3
- package/lib/cjs/site/templates.js.map +1 -1
- package/lib/esm/ActivityCollection.js +89 -0
- package/lib/esm/ActivityCollection.js.map +1 -0
- package/lib/esm/auth.js +3 -3
- package/lib/esm/auth.js.map +1 -1
- package/lib/esm/index.js +1 -0
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/server/activities.js +100 -0
- package/lib/esm/server/activities.js.map +1 -0
- package/lib/esm/server/app-package.js +14 -1
- package/lib/esm/server/app-package.js.map +1 -1
- package/lib/esm/server/interactions.js +21 -9
- package/lib/esm/server/interactions.js.map +1 -1
- package/lib/esm/server/site.js +8 -2
- package/lib/esm/server/site.js.map +1 -1
- package/lib/esm/server/skills.js +10 -0
- package/lib/esm/server/skills.js.map +1 -1
- package/lib/esm/server.js +4 -1
- package/lib/esm/server.js.map +1 -1
- package/lib/esm/site/templates.js +136 -3
- package/lib/esm/site/templates.js.map +1 -1
- package/lib/types/ActivityCollection.d.ts +55 -0
- package/lib/types/ActivityCollection.d.ts.map +1 -0
- package/lib/types/index.d.ts +1 -0
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/server/activities.d.ts +4 -0
- package/lib/types/server/activities.d.ts.map +1 -0
- package/lib/types/server/app-package.d.ts.map +1 -1
- package/lib/types/server/interactions.d.ts.map +1 -1
- package/lib/types/server/site.d.ts.map +1 -1
- package/lib/types/server/types.d.ts +5 -0
- package/lib/types/server/types.d.ts.map +1 -1
- package/lib/types/server.d.ts.map +1 -1
- package/lib/types/site/templates.d.ts +10 -0
- package/lib/types/site/templates.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/ActivityCollection.test.ts +161 -0
- package/src/ActivityCollection.ts +136 -0
- package/src/auth.ts +3 -3
- package/src/index.ts +1 -0
- package/src/server/activities.test.ts +165 -0
- package/src/server/activities.ts +114 -0
- package/src/server/app-package.ts +15 -2
- package/src/server/interactions.ts +22 -11
- package/src/server/site.ts +9 -0
- package/src/server/skills.ts +10 -0
- package/src/server/types.ts +5 -0
- package/src/server.ts +4 -0
- package/src/site/templates.ts +143 -2
|
@@ -50,16 +50,22 @@ export function createInteractionsRoute(app: Hono, basePath: string, config: Too
|
|
|
50
50
|
const name = c.req.param('name');
|
|
51
51
|
|
|
52
52
|
const parts = name.split(':');
|
|
53
|
-
if (parts.length
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
53
|
+
if (parts.length === 2) {
|
|
54
|
+
// Explicit collection:interaction format
|
|
55
|
+
const collName = parts[0];
|
|
56
|
+
const interName = parts[1];
|
|
57
|
+
const inter = interactions.find(t => t.name === collName)?.getInteractionByName(interName);
|
|
58
|
+
if (inter) {
|
|
59
|
+
return c.json({ ...inter, id: collName + ":" + interName });
|
|
60
|
+
}
|
|
61
|
+
} else {
|
|
62
|
+
// Search all collections for the interaction by name
|
|
63
|
+
for (const coll of interactions) {
|
|
64
|
+
const inter = coll.getInteractionByName(name);
|
|
65
|
+
if (inter) {
|
|
66
|
+
return c.json({ ...inter, id: coll.name + ":" + name });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
63
69
|
}
|
|
64
70
|
|
|
65
71
|
throw new HTTPException(404, {
|
|
@@ -89,6 +95,11 @@ function createInteractionEndpoints(coll: InteractionCollection): Hono {
|
|
|
89
95
|
endpoint.get('/:name', async (c: Context) => {
|
|
90
96
|
await authorize(c);
|
|
91
97
|
const name = c.req.param('name');
|
|
98
|
+
if (!name) {
|
|
99
|
+
throw new HTTPException(400, {
|
|
100
|
+
message: 'Interaction name is required'
|
|
101
|
+
});
|
|
102
|
+
}
|
|
92
103
|
const inter = coll.getInteractionByName(name);
|
|
93
104
|
if (!inter) {
|
|
94
105
|
throw new HTTPException(404, {
|
|
@@ -102,4 +113,4 @@ function createInteractionEndpoints(coll: InteractionCollection): Hono {
|
|
|
102
113
|
});
|
|
103
114
|
|
|
104
115
|
return endpoint;
|
|
105
|
-
}
|
|
116
|
+
}
|
package/src/server/site.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
2
|
import {
|
|
3
|
+
activityCollectionPage,
|
|
3
4
|
contentTypeCollectionPage,
|
|
4
5
|
indexPage,
|
|
5
6
|
interactionCollectionPage,
|
|
@@ -13,6 +14,7 @@ import { ToolServerConfig } from "./types.js";
|
|
|
13
14
|
export function createSiteRoute(app: Hono, basePath: string, config: ToolServerConfig) {
|
|
14
15
|
const {
|
|
15
16
|
tools = [],
|
|
17
|
+
activities = [],
|
|
16
18
|
interactions = [],
|
|
17
19
|
types = [],
|
|
18
20
|
skills = [],
|
|
@@ -31,6 +33,13 @@ export function createSiteRoute(app: Hono, basePath: string, config: ToolServerC
|
|
|
31
33
|
});
|
|
32
34
|
}
|
|
33
35
|
|
|
36
|
+
// Activity collection pages
|
|
37
|
+
for (const coll of activities) {
|
|
38
|
+
app.get(`${basePath}/activities/${coll.name}`, (c) => {
|
|
39
|
+
return c.html(activityCollectionPage(coll));
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
34
43
|
// Skill collection pages
|
|
35
44
|
for (const coll of skills) {
|
|
36
45
|
app.get(`${basePath}/skills/${coll.name}`, (c) => {
|
package/src/server/skills.ts
CHANGED
|
@@ -95,6 +95,11 @@ function createSkillEndpoints(coll: SkillCollection): Hono {
|
|
|
95
95
|
// Returns all scripts bundled with the skill
|
|
96
96
|
endpoint.get('/:name/scripts', (c: Context) => {
|
|
97
97
|
const name = c.req.param('name');
|
|
98
|
+
if (!name) {
|
|
99
|
+
throw new HTTPException(400, {
|
|
100
|
+
message: 'Skill name is required'
|
|
101
|
+
});
|
|
102
|
+
}
|
|
98
103
|
const skillName = name.startsWith('learn_') ? name.slice(6) : name;
|
|
99
104
|
const skill = coll.getSkill(skillName);
|
|
100
105
|
if (!skill) {
|
|
@@ -113,6 +118,11 @@ function createSkillEndpoints(coll: SkillCollection): Hono {
|
|
|
113
118
|
// Get a specific skill by name
|
|
114
119
|
endpoint.get('/:name', (c: Context) => {
|
|
115
120
|
const name = c.req.param('name');
|
|
121
|
+
if (!name) {
|
|
122
|
+
throw new HTTPException(400, {
|
|
123
|
+
message: 'Skill name is required'
|
|
124
|
+
});
|
|
125
|
+
}
|
|
116
126
|
// Handle both "learn_name" and "name" formats
|
|
117
127
|
const skillName = name.startsWith('learn_') ? name.slice(6) : name;
|
|
118
128
|
const skill = coll.getSkill(skillName);
|
package/src/server/types.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Context } from "hono";
|
|
2
|
+
import { ActivityCollection } from "../ActivityCollection.js";
|
|
2
3
|
import { InteractionCollection } from "../InteractionCollection.js";
|
|
3
4
|
import { SkillCollection } from "../SkillCollection.js";
|
|
4
5
|
import { RenderingTemplateCollection } from "../RenderingTemplateCollection.js";
|
|
@@ -49,6 +50,10 @@ export interface ToolServerConfig {
|
|
|
49
50
|
* Tool collections to expose
|
|
50
51
|
*/
|
|
51
52
|
tools?: ToolCollection[];
|
|
53
|
+
/**
|
|
54
|
+
* Activity collections to expose for DSL workflows
|
|
55
|
+
*/
|
|
56
|
+
activities?: ActivityCollection[];
|
|
52
57
|
/**
|
|
53
58
|
* Interaction collections to expose
|
|
54
59
|
*/
|
package/src/server.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { Context, Hono } from "hono";
|
|
|
2
2
|
import { cors } from "hono/cors";
|
|
3
3
|
import { HTTPException } from "hono/http-exception";
|
|
4
4
|
import { z } from "zod";
|
|
5
|
+
import { createActivitiesRoute } from "./server/activities.js";
|
|
5
6
|
import { createInteractionsRoute } from "./server/interactions.js";
|
|
6
7
|
import { createMcpRoute } from "./server/mcp.js";
|
|
7
8
|
import { createSiteRoute } from "./server/site.js";
|
|
@@ -48,6 +49,7 @@ export function createToolServer(config: ToolServerConfig): Hono {
|
|
|
48
49
|
interactions = [],
|
|
49
50
|
skills = [],
|
|
50
51
|
templates = [],
|
|
52
|
+
activities = [],
|
|
51
53
|
mcpProviders = [],
|
|
52
54
|
disableHtml = false,
|
|
53
55
|
} = config;
|
|
@@ -98,6 +100,7 @@ export function createToolServer(config: ToolServerConfig): Hono {
|
|
|
98
100
|
tools: allToolEndpoints,
|
|
99
101
|
interactions: interactions.map(col => `${prefix}/interactions/${col.name}`),
|
|
100
102
|
templates: templates.map(col => `${prefix}/templates/${col.name}`),
|
|
103
|
+
activities: activities.map(col => `${prefix}/activities/${col.name}`),
|
|
101
104
|
mcp: mcpProviders.map(p => `${prefix}/mcp/${p.name}`),
|
|
102
105
|
}
|
|
103
106
|
});
|
|
@@ -108,6 +111,7 @@ export function createToolServer(config: ToolServerConfig): Hono {
|
|
|
108
111
|
createToolsRoute(app, `${prefix}/tools`, config);
|
|
109
112
|
createSkillsRoute(app, `${prefix}/skills`, config);
|
|
110
113
|
createWidgetsRoute(app, `${prefix}/widgets`, config);
|
|
114
|
+
createActivitiesRoute(app, `${prefix}/activities`, config);
|
|
111
115
|
createInteractionsRoute(app, `${prefix}/interactions`, config);
|
|
112
116
|
createTemplatesRoute(app, `${prefix}/templates`, config);
|
|
113
117
|
createContentTypesRoute(app, `${prefix}/types`, config);
|
package/src/site/templates.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { RemoteActivityDefinition } from "@vertesia/common";
|
|
2
|
+
import type { ActivityCollection } from "../ActivityCollection.js";
|
|
1
3
|
import type { InteractionCollection } from "../InteractionCollection.js";
|
|
2
4
|
import { ToolServerConfig } from "../server/types.js";
|
|
3
5
|
import type { SkillCollection } from "../SkillCollection.js";
|
|
@@ -35,6 +37,11 @@ const templateIcon = /*html*/`
|
|
|
35
37
|
<polyline points="10 9 9 9 8 9"/>
|
|
36
38
|
</svg>`;
|
|
37
39
|
|
|
40
|
+
const activityIcon = /*html*/`
|
|
41
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
42
|
+
<polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/>
|
|
43
|
+
</svg>`;
|
|
44
|
+
|
|
38
45
|
/**
|
|
39
46
|
* Extended styles for detail pages
|
|
40
47
|
*/
|
|
@@ -822,6 +829,7 @@ export function indexPage(
|
|
|
822
829
|
const {
|
|
823
830
|
title = 'Tools Server',
|
|
824
831
|
tools = [],
|
|
832
|
+
activities = [],
|
|
825
833
|
interactions = [],
|
|
826
834
|
skills = [],
|
|
827
835
|
templates = [],
|
|
@@ -851,10 +859,11 @@ export function indexPage(
|
|
|
851
859
|
<p class="hero-eyebrow">Tools Server</p>
|
|
852
860
|
<h1 class="hero-title">${title}</h1>
|
|
853
861
|
<p class="hero-tagline">
|
|
854
|
-
Discover the tools, skills, interactions, and content types exposed by this server.
|
|
862
|
+
Discover the tools, activities, skills, interactions, and content types exposed by this server.
|
|
855
863
|
</p>
|
|
856
864
|
<div class="hero-summary">
|
|
857
865
|
${tools.length ? /*html*/`<span><dot></dot> ${tools.length} tool collection${tools.length !== 1 ? 's' : ''}</span>` : ''}
|
|
866
|
+
${activities.length ? /*html*/`<span><dot></dot> ${activities.length} activity collection${activities.length !== 1 ? 's' : ''}</span>` : ''}
|
|
858
867
|
${skills.length ? /*html*/`<span><dot></dot> ${skills.length} skill collection${skills.length !== 1 ? 's' : ''}</span>` : ''}
|
|
859
868
|
${interactions.length ? /*html*/`<span><dot></dot> ${interactions.length} interaction collection${interactions.length !== 1 ? 's' : ''}</span>` : ''}
|
|
860
869
|
${types.length ? /*html*/`<span><dot></dot> ${types.length} content type collection${types.length !== 1 ? 's' : ''}</span>` : ''}
|
|
@@ -886,7 +895,7 @@ export function indexPage(
|
|
|
886
895
|
type="search"
|
|
887
896
|
id="collection-search"
|
|
888
897
|
class="search-input"
|
|
889
|
-
placeholder="Search tools, skills, interactions, types, templates..."
|
|
898
|
+
placeholder="Search tools, activities, skills, interactions, types, templates..."
|
|
890
899
|
aria-label="Search collections"
|
|
891
900
|
autocomplete="off"
|
|
892
901
|
/>
|
|
@@ -910,6 +919,22 @@ export function indexPage(
|
|
|
910
919
|
</section>
|
|
911
920
|
` : ''}
|
|
912
921
|
|
|
922
|
+
${activities.length > 0 ? /*html*/`
|
|
923
|
+
<section data-section="activities">
|
|
924
|
+
<hr>
|
|
925
|
+
<div class="section-header">
|
|
926
|
+
<h2>Activity Collections</h2>
|
|
927
|
+
<p class="section-subtitle">Remote activities for DSL workflows, invoked via HTTP.</p>
|
|
928
|
+
</div>
|
|
929
|
+
<div class="card-grid">
|
|
930
|
+
${activities.map((a: ActivityCollection) => {
|
|
931
|
+
const count = a.getActivityDefinitions().length;
|
|
932
|
+
return collectionCard(a, 'activities', `${count} activit${count !== 1 ? 'ies' : 'y'}`);
|
|
933
|
+
}).join('')}
|
|
934
|
+
</div>
|
|
935
|
+
</section>
|
|
936
|
+
` : ''}
|
|
937
|
+
|
|
913
938
|
${skills.length > 0 ? /*html*/`
|
|
914
939
|
<section data-section="skills">
|
|
915
940
|
<hr>
|
|
@@ -1227,3 +1252,119 @@ export function contentTypeCollectionPage(collection: ContentTypesCollection): s
|
|
|
1227
1252
|
</body>
|
|
1228
1253
|
</html>`;
|
|
1229
1254
|
}
|
|
1255
|
+
|
|
1256
|
+
/**
|
|
1257
|
+
* Render a detailed activity card
|
|
1258
|
+
*/
|
|
1259
|
+
export function activityDetailCard(activity: RemoteActivityDefinition, collectionName: string): string {
|
|
1260
|
+
const schema = activity.input_schema;
|
|
1261
|
+
const properties = schema?.properties as Record<string, unknown> | undefined;
|
|
1262
|
+
const required = (schema as Record<string, unknown>)?.required as string[] | undefined;
|
|
1263
|
+
|
|
1264
|
+
return /*html*/`
|
|
1265
|
+
<div class="detail-card">
|
|
1266
|
+
<div class="detail-header">
|
|
1267
|
+
<div>
|
|
1268
|
+
<h3 class="detail-title">${activity.name}</h3>
|
|
1269
|
+
<p class="detail-desc">${activity.description || 'No description'}</p>
|
|
1270
|
+
</div>
|
|
1271
|
+
<div class="detail-badges">
|
|
1272
|
+
<span class="badge" style="background: #ec4899; color: white;">Activity</span>
|
|
1273
|
+
</div>
|
|
1274
|
+
</div>
|
|
1275
|
+
<div class="detail-body">
|
|
1276
|
+
<div class="detail-section">
|
|
1277
|
+
<h4 class="detail-section-title">Endpoint</h4>
|
|
1278
|
+
<div class="endpoint-box">
|
|
1279
|
+
<code>POST ${activity.url || `/api/activities/${collectionName}`}</code>
|
|
1280
|
+
<button class="copy-btn" onclick="navigator.clipboard.writeText('${activity.url || `/api/activities/${collectionName}`}')" title="Copy">
|
|
1281
|
+
${copyIcon}
|
|
1282
|
+
</button>
|
|
1283
|
+
</div>
|
|
1284
|
+
</div>
|
|
1285
|
+
|
|
1286
|
+
${schema ? /*html*/`
|
|
1287
|
+
<div class="detail-section">
|
|
1288
|
+
<h4 class="detail-section-title">Input Schema</h4>
|
|
1289
|
+
${properties ? /*html*/`
|
|
1290
|
+
<div class="info-grid" style="margin-bottom: 1rem;">
|
|
1291
|
+
${Object.entries(properties).map(([key, value]) => {
|
|
1292
|
+
const prop = value as Record<string, unknown>;
|
|
1293
|
+
const isRequired = required?.includes(key);
|
|
1294
|
+
return /*html*/`
|
|
1295
|
+
<div class="info-item">
|
|
1296
|
+
<div class="info-label">${key}${isRequired ? ' *' : ''}</div>
|
|
1297
|
+
<div class="info-value">
|
|
1298
|
+
<code>${prop.type || 'any'}</code>
|
|
1299
|
+
${prop.description ? `<br><span style="color: #6b7280; font-size: 0.85rem;">${prop.description}</span>` : ''}
|
|
1300
|
+
</div>
|
|
1301
|
+
</div>`;
|
|
1302
|
+
}).join('')}
|
|
1303
|
+
</div>
|
|
1304
|
+
` : ''}
|
|
1305
|
+
<details>
|
|
1306
|
+
<summary style="cursor: pointer; color: #6b7280; font-size: 0.85rem;">View full schema</summary>
|
|
1307
|
+
<div class="schema-block" style="margin-top: 0.75rem;">${highlightJson(schema)}</div>
|
|
1308
|
+
</details>
|
|
1309
|
+
</div>
|
|
1310
|
+
` : /*html*/`
|
|
1311
|
+
<div class="detail-section">
|
|
1312
|
+
<div class="empty-state">No input schema defined</div>
|
|
1313
|
+
</div>
|
|
1314
|
+
`}
|
|
1315
|
+
|
|
1316
|
+
${activity.output_schema ? /*html*/`
|
|
1317
|
+
<div class="detail-section">
|
|
1318
|
+
<h4 class="detail-section-title">Output Schema</h4>
|
|
1319
|
+
<details>
|
|
1320
|
+
<summary style="cursor: pointer; color: #6b7280; font-size: 0.85rem;">View output schema</summary>
|
|
1321
|
+
<div class="schema-block" style="margin-top: 0.75rem;">${highlightJson(activity.output_schema)}</div>
|
|
1322
|
+
</details>
|
|
1323
|
+
</div>
|
|
1324
|
+
` : ''}
|
|
1325
|
+
</div>
|
|
1326
|
+
</div>`;
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
/**
|
|
1330
|
+
* Render an activity collection detail page
|
|
1331
|
+
*/
|
|
1332
|
+
export function activityCollectionPage(collection: ActivityCollection): string {
|
|
1333
|
+
const activitiesArray = collection.getActivityDefinitions();
|
|
1334
|
+
return /*html*/`
|
|
1335
|
+
<!DOCTYPE html>
|
|
1336
|
+
<html lang="en">
|
|
1337
|
+
<head>
|
|
1338
|
+
<meta charset="UTF-8">
|
|
1339
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1340
|
+
<title>${collection.title || collection.name} - Activities</title>
|
|
1341
|
+
<style>${detailStyles}</style>
|
|
1342
|
+
</head>
|
|
1343
|
+
<body>
|
|
1344
|
+
<nav class="nav">
|
|
1345
|
+
<a href="/">${backArrow} Back to all collections</a>
|
|
1346
|
+
</nav>
|
|
1347
|
+
|
|
1348
|
+
<div class="header">
|
|
1349
|
+
<div class="header-icon">${collection.icon || activityIcon}</div>
|
|
1350
|
+
<div>
|
|
1351
|
+
<h1>${collection.title || collection.name}</h1>
|
|
1352
|
+
<p style="color: #6b7280; margin: 0.25rem 0 0 0;">${collection.description || ''}</p>
|
|
1353
|
+
<div class="endpoint-box">
|
|
1354
|
+
<code>/api/activities/${collection.name}</code>
|
|
1355
|
+
<button class="copy-btn" onclick="navigator.clipboard.writeText(window.location.origin + '/api/activities/${collection.name}')" title="Copy endpoint URL">
|
|
1356
|
+
${copyIcon}
|
|
1357
|
+
</button>
|
|
1358
|
+
</div>
|
|
1359
|
+
</div>
|
|
1360
|
+
</div>
|
|
1361
|
+
|
|
1362
|
+
<h2>${activitiesArray.length} Activit${activitiesArray.length !== 1 ? 'ies' : 'y'}</h2>
|
|
1363
|
+
|
|
1364
|
+
${activitiesArray.length > 0 ?
|
|
1365
|
+
activitiesArray.map(activity => activityDetailCard(activity, collection.name)).join('') :
|
|
1366
|
+
'<div class="empty-state">No activities in this collection</div>'
|
|
1367
|
+
}
|
|
1368
|
+
</body>
|
|
1369
|
+
</html>`;
|
|
1370
|
+
}
|