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
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rollup Configuration for building tools as es bundles for import() usage
|
|
3
|
+
*
|
|
4
|
+
* Not used for now.
|
|
5
|
+
*
|
|
6
|
+
* Creates browser-ready bundles for each tool collection in lib/tools
|
|
7
|
+
* Input: lib/tools/{TOOL_DIR}/index.js (already compiled from TypeScript)
|
|
8
|
+
* Output: dist/libs/tool-server-{name}.js (browser bundles)
|
|
9
|
+
*/
|
|
10
|
+
import { nodeResolve } from '@rollup/plugin-node-resolve';
|
|
11
|
+
import commonjs from '@rollup/plugin-commonjs';
|
|
12
|
+
import json from '@rollup/plugin-json';
|
|
13
|
+
import { terser } from 'rollup-plugin-terser';
|
|
14
|
+
import fs from 'fs';
|
|
15
|
+
import path from 'path';
|
|
16
|
+
|
|
17
|
+
const libToolCollectionsDir = './lib/tools';
|
|
18
|
+
const outputDir = './dist/libs';
|
|
19
|
+
|
|
20
|
+
// Ensure output directory exists
|
|
21
|
+
if (!fs.existsSync(outputDir)) {
|
|
22
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Get all directories in lib/tools with an index.js
|
|
26
|
+
const entries = fs.existsSync(libToolCollectionsDir)
|
|
27
|
+
? fs.readdirSync(libToolCollectionsDir).filter((name) => {
|
|
28
|
+
const dir = path.join(libToolCollectionsDir, name);
|
|
29
|
+
return (
|
|
30
|
+
fs.statSync(dir).isDirectory() &&
|
|
31
|
+
fs.existsSync(path.join(dir, 'index.js'))
|
|
32
|
+
);
|
|
33
|
+
})
|
|
34
|
+
: [];
|
|
35
|
+
|
|
36
|
+
// Create a bundle configuration for each tool collection
|
|
37
|
+
const browserBundles = entries.map((name) => ({
|
|
38
|
+
input: path.join(libToolCollectionsDir, name, 'index.js'),
|
|
39
|
+
output: {
|
|
40
|
+
file: path.join(outputDir, `tool-server-${name}.js`),
|
|
41
|
+
format: 'es',
|
|
42
|
+
sourcemap: true,
|
|
43
|
+
inlineDynamicImports: true
|
|
44
|
+
},
|
|
45
|
+
plugins: [
|
|
46
|
+
nodeResolve({
|
|
47
|
+
browser: true,
|
|
48
|
+
preferBuiltins: false
|
|
49
|
+
}),
|
|
50
|
+
json(),
|
|
51
|
+
commonjs(),
|
|
52
|
+
terser({
|
|
53
|
+
compress: {
|
|
54
|
+
drop_console: false
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
]
|
|
58
|
+
}));
|
|
59
|
+
|
|
60
|
+
export default browserBundles;
|
package/rollup.config.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rollup Configuration for Server Build
|
|
3
|
+
*
|
|
4
|
+
* This configuration handles:
|
|
5
|
+
* 1. TypeScript compilation (src → lib) with preserveModules
|
|
6
|
+
* 2. Raw file imports (?raw) for template files
|
|
7
|
+
*
|
|
8
|
+
* Browser bundles are in rollup.config.browser.js
|
|
9
|
+
*/
|
|
10
|
+
import json from '@rollup/plugin-json';
|
|
11
|
+
import typescript from '@rollup/plugin-typescript';
|
|
12
|
+
import fs from 'fs';
|
|
13
|
+
import path from 'path';
|
|
14
|
+
|
|
15
|
+
// ============================================================================
|
|
16
|
+
// Raw Plugin - Supports ?raw imports for template files
|
|
17
|
+
// ============================================================================
|
|
18
|
+
function rawPlugin() {
|
|
19
|
+
return {
|
|
20
|
+
name: 'raw-loader',
|
|
21
|
+
resolveId(id, importer) {
|
|
22
|
+
if (id.endsWith('?raw')) {
|
|
23
|
+
const cleanId = id.slice(0, -4); // Remove '?raw'
|
|
24
|
+
if (cleanId.startsWith('.') && importer) {
|
|
25
|
+
// Resolve relative path
|
|
26
|
+
const resolved = path.resolve(path.dirname(importer), cleanId);
|
|
27
|
+
return resolved + '?raw';
|
|
28
|
+
}
|
|
29
|
+
return id;
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
load(id) {
|
|
33
|
+
if (id.endsWith('?raw')) {
|
|
34
|
+
const filePath = id.slice(0, -4); // Remove '?raw'
|
|
35
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
36
|
+
return `export default ${JSON.stringify(content)}`;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ============================================================================
|
|
43
|
+
// Exit Plugin - Forces process exit after build completes
|
|
44
|
+
// This prevents TypeScript plugin from keeping the process alive
|
|
45
|
+
// ============================================================================
|
|
46
|
+
function exitPlugin() {
|
|
47
|
+
return {
|
|
48
|
+
name: 'force-exit',
|
|
49
|
+
closeBundle() {
|
|
50
|
+
console.log('Tool server build Done');
|
|
51
|
+
// Force exit after bundle completes to prevent hanging
|
|
52
|
+
setImmediate(() => process.exit(0));
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ============================================================================
|
|
58
|
+
// Server Build Configuration (TypeScript → JavaScript)
|
|
59
|
+
// ============================================================================
|
|
60
|
+
const serverBuild = {
|
|
61
|
+
input: {
|
|
62
|
+
server: './src/server.ts',
|
|
63
|
+
'server-node': './src/server-node.ts',
|
|
64
|
+
'build-site': './src/build-site.ts',
|
|
65
|
+
'copy-assets': './src/copy-assets.ts'
|
|
66
|
+
},
|
|
67
|
+
output: {
|
|
68
|
+
dir: 'lib',
|
|
69
|
+
format: 'es',
|
|
70
|
+
sourcemap: true,
|
|
71
|
+
preserveModules: true,
|
|
72
|
+
preserveModulesRoot: 'src',
|
|
73
|
+
entryFileNames: '[name].js'
|
|
74
|
+
},
|
|
75
|
+
external: (id) => {
|
|
76
|
+
// Keep relative imports as part of the bundle
|
|
77
|
+
if (id.startsWith('.') || id.startsWith('/')) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
// Externalize all node modules and absolute imports
|
|
81
|
+
return true;
|
|
82
|
+
},
|
|
83
|
+
plugins: [
|
|
84
|
+
rawPlugin(),
|
|
85
|
+
typescript({
|
|
86
|
+
tsconfig: './tsconfig.json',
|
|
87
|
+
declaration: true,
|
|
88
|
+
declarationDir: 'lib',
|
|
89
|
+
sourceMap: true
|
|
90
|
+
}),
|
|
91
|
+
json(),
|
|
92
|
+
exitPlugin()
|
|
93
|
+
]
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// ============================================================================
|
|
97
|
+
// Export server build configuration only
|
|
98
|
+
// ============================================================================
|
|
99
|
+
export default serverBuild;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {
|
|
2
|
+
indexPage,
|
|
3
|
+
interactionCollectionPage,
|
|
4
|
+
skillCollectionPage,
|
|
5
|
+
toolCollectionPage
|
|
6
|
+
} from "@vertesia/tools-sdk";
|
|
7
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
8
|
+
import { loadInteractions } from "./interactions/index.js";
|
|
9
|
+
import { skills } from "./skills/index.js";
|
|
10
|
+
import { tools } from "./tools/index.js";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Generates static HTML pages for all tool collections, skills, and interactions
|
|
14
|
+
* This runs during the build process to create browsable documentation
|
|
15
|
+
*/
|
|
16
|
+
async function build(outDir: string) {
|
|
17
|
+
console.log(`Building static site to ${outDir}...`);
|
|
18
|
+
|
|
19
|
+
// Ensure output directory exists
|
|
20
|
+
mkdirSync(outDir, { recursive: true });
|
|
21
|
+
|
|
22
|
+
// Load interactions
|
|
23
|
+
const interactions = await loadInteractions();
|
|
24
|
+
|
|
25
|
+
// Create main index page
|
|
26
|
+
console.log('Creating index page...');
|
|
27
|
+
writeFileSync(
|
|
28
|
+
`${outDir}/index.html`,
|
|
29
|
+
indexPage(tools, skills, interactions, 'Tool Server Template')
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
// Create pages for each tool collection
|
|
33
|
+
console.log(`Creating ${tools.length} tool collection pages...`);
|
|
34
|
+
for (const coll of tools) {
|
|
35
|
+
const dir = `${outDir}/tools/${coll.name}`;
|
|
36
|
+
mkdirSync(dir, { recursive: true });
|
|
37
|
+
writeFileSync(
|
|
38
|
+
`${dir}/index.html`,
|
|
39
|
+
toolCollectionPage(coll)
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Create pages for each skill collection
|
|
44
|
+
console.log(`Creating ${skills.length} skill collection pages...`);
|
|
45
|
+
for (const coll of skills) {
|
|
46
|
+
const dir = `${outDir}/skills/${coll.name}`;
|
|
47
|
+
mkdirSync(dir, { recursive: true });
|
|
48
|
+
writeFileSync(
|
|
49
|
+
`${dir}/index.html`,
|
|
50
|
+
skillCollectionPage(coll)
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Create pages for each interaction collection
|
|
55
|
+
console.log(`Creating ${interactions.length} interaction collection pages...`);
|
|
56
|
+
for (const coll of interactions) {
|
|
57
|
+
const dir = `${outDir}/interactions/${coll.name}`;
|
|
58
|
+
mkdirSync(dir, { recursive: true });
|
|
59
|
+
writeFileSync(
|
|
60
|
+
`${dir}/index.html`,
|
|
61
|
+
interactionCollectionPage(coll)
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
console.log('✓ Static site build complete!');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Run the build
|
|
69
|
+
const outDir = process.argv[2] || './dist';
|
|
70
|
+
build(outDir)
|
|
71
|
+
.then(() => {
|
|
72
|
+
process.exit(0);
|
|
73
|
+
})
|
|
74
|
+
.catch(error => {
|
|
75
|
+
console.error('Build failed:', error);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
});
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Copy runtime assets (skill files, prompt files, scripts) to dist folder
|
|
4
|
+
* These files are read from disk at runtime and need to be deployed with the app
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* npx tools-sdk-copy-assets [srcDir] [distDir]
|
|
8
|
+
*
|
|
9
|
+
* Or import and call directly:
|
|
10
|
+
* import { copyRuntimeAssets } from '@vertesia/tools-sdk';
|
|
11
|
+
* copyRuntimeAssets('./src', './dist');
|
|
12
|
+
*/
|
|
13
|
+
import { existsSync, readdirSync, statSync, mkdirSync, copyFileSync } from "fs";
|
|
14
|
+
import { dirname, join } from "path";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Recursively copy files matching a filter
|
|
18
|
+
*/
|
|
19
|
+
function copyFilesRecursive(src: string, dest: string, fileFilter: (filename: string) => boolean): void {
|
|
20
|
+
if (!existsSync(src)) return;
|
|
21
|
+
|
|
22
|
+
const entries = readdirSync(src);
|
|
23
|
+
|
|
24
|
+
for (const entry of entries) {
|
|
25
|
+
const srcPath = join(src, entry);
|
|
26
|
+
const destPath = join(dest, entry);
|
|
27
|
+
const stat = statSync(srcPath);
|
|
28
|
+
|
|
29
|
+
if (stat.isDirectory()) {
|
|
30
|
+
// Recurse into directories
|
|
31
|
+
copyFilesRecursive(srcPath, destPath, fileFilter);
|
|
32
|
+
} else if (fileFilter(entry)) {
|
|
33
|
+
// Copy matching files
|
|
34
|
+
mkdirSync(dirname(destPath), { recursive: true });
|
|
35
|
+
copyFileSync(srcPath, destPath);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface CopyAssetsOptions {
|
|
41
|
+
/** Source directory (default: './src') */
|
|
42
|
+
srcDir?: string;
|
|
43
|
+
/** Destination directory (default: './dist') */
|
|
44
|
+
distDir?: string;
|
|
45
|
+
/** Whether to log progress (default: true) */
|
|
46
|
+
verbose?: boolean;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Copy runtime assets (skills, interactions) from src to dist
|
|
51
|
+
*/
|
|
52
|
+
export function copyRuntimeAssets(options: CopyAssetsOptions = {}): void {
|
|
53
|
+
const {
|
|
54
|
+
srcDir = './src',
|
|
55
|
+
distDir = './dist',
|
|
56
|
+
verbose = true
|
|
57
|
+
} = options;
|
|
58
|
+
|
|
59
|
+
if (verbose) {
|
|
60
|
+
console.log('Copying runtime assets to dist...');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Copy skill files (SKILL.md, SKILL.jst, *.py)
|
|
64
|
+
const skillsSrc = join(srcDir, 'skills');
|
|
65
|
+
const skillsDest = join(distDir, 'skills');
|
|
66
|
+
|
|
67
|
+
if (existsSync(skillsSrc)) {
|
|
68
|
+
copyFilesRecursive(skillsSrc, skillsDest, (filename) => {
|
|
69
|
+
return filename === 'SKILL.md' ||
|
|
70
|
+
filename === 'SKILL.jst' ||
|
|
71
|
+
filename.endsWith('.py');
|
|
72
|
+
});
|
|
73
|
+
if (verbose) {
|
|
74
|
+
console.log(' ✓ Skills assets (SKILL.md, SKILL.jst, *.py)');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Copy interaction prompt files (prompt.jst, prompt.md)
|
|
79
|
+
const interactionsSrc = join(srcDir, 'interactions');
|
|
80
|
+
const interactionsDest = join(distDir, 'interactions');
|
|
81
|
+
|
|
82
|
+
if (existsSync(interactionsSrc)) {
|
|
83
|
+
copyFilesRecursive(interactionsSrc, interactionsDest, (filename) => {
|
|
84
|
+
return filename === 'prompt.jst' ||
|
|
85
|
+
filename === 'prompt.md';
|
|
86
|
+
});
|
|
87
|
+
if (verbose) {
|
|
88
|
+
console.log(' ✓ Interaction assets (prompt.jst, prompt.md)');
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (verbose) {
|
|
93
|
+
console.log('Runtime assets copied successfully!');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// CLI entry point
|
|
98
|
+
if (typeof process !== 'undefined' && process.argv[1]?.includes('copy-assets')) {
|
|
99
|
+
const args = process.argv.slice(2);
|
|
100
|
+
const srcDir = args[0] || './src';
|
|
101
|
+
const distDir = args[1] || './dist';
|
|
102
|
+
|
|
103
|
+
copyRuntimeAssets({ srcDir, distDir });
|
|
104
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export 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">
|
|
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>`;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { InteractionCollection } from "@vertesia/tools-sdk";
|
|
2
|
+
import textSummarizer from "./text_summarizer/index.js";
|
|
3
|
+
import icon from "./icon.svg.js";
|
|
4
|
+
|
|
5
|
+
export const SummarizeInteractions = new InteractionCollection({
|
|
6
|
+
name: "summarize",
|
|
7
|
+
title: "Summarization Interactions",
|
|
8
|
+
description: "A collection of interactions for summarizing and condensing text",
|
|
9
|
+
icon,
|
|
10
|
+
interactions: [textSummarizer]
|
|
11
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { PromptRole } from "@llumiverse/common";
|
|
2
|
+
import { InteractionSpec, TemplateType } from "@vertesia/common";
|
|
3
|
+
import PROMPT_CONTENT from "./prompt.jst?raw";
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
name: "text_summarizer",
|
|
7
|
+
title: "Text Summarizer",
|
|
8
|
+
description: "Summarizes text according to specified parameters like style, length, and format.",
|
|
9
|
+
result_schema: {
|
|
10
|
+
type: "object",
|
|
11
|
+
properties: {
|
|
12
|
+
summary: {
|
|
13
|
+
type: "string",
|
|
14
|
+
description: "The generated summary"
|
|
15
|
+
},
|
|
16
|
+
word_count: {
|
|
17
|
+
type: "number",
|
|
18
|
+
description: "Number of words in the summary"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
required: ["summary"]
|
|
22
|
+
},
|
|
23
|
+
prompts: [{
|
|
24
|
+
role: PromptRole.user,
|
|
25
|
+
content: PROMPT_CONTENT,
|
|
26
|
+
content_type: TemplateType.jst,
|
|
27
|
+
schema: {
|
|
28
|
+
type: "object",
|
|
29
|
+
properties: {
|
|
30
|
+
text: {
|
|
31
|
+
type: "string",
|
|
32
|
+
description: "The text to summarize"
|
|
33
|
+
},
|
|
34
|
+
style: {
|
|
35
|
+
type: "string",
|
|
36
|
+
enum: ["concise", "detailed", "bullet-points", "executive"],
|
|
37
|
+
description: "The summary style"
|
|
38
|
+
},
|
|
39
|
+
maxLength: {
|
|
40
|
+
type: "number",
|
|
41
|
+
description: "Maximum length in words (optional)"
|
|
42
|
+
},
|
|
43
|
+
format: {
|
|
44
|
+
type: "string",
|
|
45
|
+
enum: ["paragraph", "bullet-points", "structured"],
|
|
46
|
+
description: "Output format (optional)"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
required: ["text"]
|
|
50
|
+
}
|
|
51
|
+
}],
|
|
52
|
+
tags: ["text", "summarization", "nlp", "content"]
|
|
53
|
+
} satisfies InteractionSpec;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
return `
|
|
2
|
+
# Text Summarization Request
|
|
3
|
+
|
|
4
|
+
Please summarize the following text according to the specifications below.
|
|
5
|
+
|
|
6
|
+
## Text to Summarize
|
|
7
|
+
${text}
|
|
8
|
+
|
|
9
|
+
## Summarization Parameters
|
|
10
|
+
- **Style**: ${style || 'concise'}
|
|
11
|
+
- **Max Length**: ${maxLength ? maxLength + ' words' : 'flexible'}
|
|
12
|
+
${format ? `- **Output Format**: ${format}` : ''}
|
|
13
|
+
|
|
14
|
+
## Instructions
|
|
15
|
+
|
|
16
|
+
1. Read and understand the full text
|
|
17
|
+
2. Identify the main points and key information
|
|
18
|
+
3. Create a summary that:
|
|
19
|
+
- Captures the essential meaning
|
|
20
|
+
- Maintains accuracy
|
|
21
|
+
- Uses clear, simple language
|
|
22
|
+
- Follows the ${style} style
|
|
23
|
+
${maxLength ? `- Stays within ${maxLength} words` : ''}
|
|
24
|
+
${format ? `- Is formatted as ${format}` : ''}
|
|
25
|
+
|
|
26
|
+
4. If the text contains multiple topics, organize your summary accordingly
|
|
27
|
+
|
|
28
|
+
## Output
|
|
29
|
+
|
|
30
|
+
Provide your summary below:
|
|
31
|
+
`;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node.js HTTP Server Entry Point
|
|
3
|
+
*
|
|
4
|
+
* This file starts a standalone Node.js HTTP server using @hono/node-server.
|
|
5
|
+
* Use this for:
|
|
6
|
+
* - Local development and testing
|
|
7
|
+
* - Deploying to Cloud Run, Railway, Fly.io, etc.
|
|
8
|
+
* - Running in Docker containers
|
|
9
|
+
*/
|
|
10
|
+
import { serve } from '@hono/node-server';
|
|
11
|
+
import server from './server.js';
|
|
12
|
+
|
|
13
|
+
const port = parseInt(process.env.PORT || '3000', 10);
|
|
14
|
+
|
|
15
|
+
console.log(`Starting Tool Server on port ${port}...`);
|
|
16
|
+
console.log(`API endpoint: http://localhost:${port}/api`);
|
|
17
|
+
console.log(`Web UI: http://localhost:${port}/`);
|
|
18
|
+
|
|
19
|
+
serve({
|
|
20
|
+
fetch: server.fetch,
|
|
21
|
+
port
|
|
22
|
+
}, (info) => {
|
|
23
|
+
console.log(`✓ Server is running at http://localhost:${info.port}`);
|
|
24
|
+
});
|
package/src/server.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createToolServer } from "@vertesia/tools-sdk";
|
|
2
|
+
import { loadInteractions } from "./interactions/index.js";
|
|
3
|
+
import { skills } from "./skills/index.js";
|
|
4
|
+
import { tools } from "./tools/index.js";
|
|
5
|
+
|
|
6
|
+
const CONFIG__SERVER_TITLE = "Tool Server Template";
|
|
7
|
+
|
|
8
|
+
// Load interactions asynchronously
|
|
9
|
+
const interactions = await loadInteractions();
|
|
10
|
+
|
|
11
|
+
// Create server using tools-sdk
|
|
12
|
+
const server = createToolServer({
|
|
13
|
+
title: CONFIG__SERVER_TITLE,
|
|
14
|
+
prefix: '/api',
|
|
15
|
+
tools,
|
|
16
|
+
interactions,
|
|
17
|
+
skills,
|
|
18
|
+
// Uncomment and configure MCP providers if needed
|
|
19
|
+
// mcpProviders: []
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export default server;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-review
|
|
3
|
+
title: Code Review Assistant
|
|
4
|
+
keywords: code, review, quality, best-practices, refactoring
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Code Review Assistant
|
|
8
|
+
|
|
9
|
+
You are a code review assistant. Your role is to analyze code and provide constructive feedback focusing on:
|
|
10
|
+
|
|
11
|
+
## Review Areas
|
|
12
|
+
|
|
13
|
+
1. **Code Quality**
|
|
14
|
+
- Readability and maintainability
|
|
15
|
+
- Naming conventions
|
|
16
|
+
- Code organization and structure
|
|
17
|
+
- DRY (Don't Repeat Yourself) principle
|
|
18
|
+
|
|
19
|
+
2. **Best Practices**
|
|
20
|
+
- Language-specific idioms and patterns
|
|
21
|
+
- Error handling
|
|
22
|
+
- Edge cases
|
|
23
|
+
- Security considerations
|
|
24
|
+
|
|
25
|
+
3. **Performance**
|
|
26
|
+
- Algorithmic efficiency
|
|
27
|
+
- Resource usage
|
|
28
|
+
- Potential bottlenecks
|
|
29
|
+
|
|
30
|
+
4. **Testing**
|
|
31
|
+
- Test coverage
|
|
32
|
+
- Test quality and clarity
|
|
33
|
+
- Missing test cases
|
|
34
|
+
|
|
35
|
+
## Review Format
|
|
36
|
+
|
|
37
|
+
Structure your review as follows:
|
|
38
|
+
|
|
39
|
+
### Strengths
|
|
40
|
+
List what the code does well.
|
|
41
|
+
|
|
42
|
+
### Issues
|
|
43
|
+
For each issue found:
|
|
44
|
+
- **Severity**: Critical | Major | Minor
|
|
45
|
+
- **Location**: File and line number
|
|
46
|
+
- **Description**: What the issue is
|
|
47
|
+
- **Recommendation**: How to fix it
|
|
48
|
+
- **Example**: Show improved code if applicable
|
|
49
|
+
|
|
50
|
+
### Summary
|
|
51
|
+
Provide an overall assessment and priority recommendations.
|
|
52
|
+
|
|
53
|
+
## Guidelines
|
|
54
|
+
|
|
55
|
+
- Be constructive and respectful
|
|
56
|
+
- Explain the "why" behind suggestions
|
|
57
|
+
- Provide specific, actionable feedback
|
|
58
|
+
- Consider the context and requirements
|
|
59
|
+
- Balance perfection with pragmatism
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { SkillCollection, loadSkillsFromDirectory } from "@vertesia/tools-sdk";
|
|
2
|
+
|
|
3
|
+
export const CodeReviewSkills = new SkillCollection({
|
|
4
|
+
name: "code-review",
|
|
5
|
+
title: "Code Review Skills",
|
|
6
|
+
description: "Skills for reviewing and analyzing code quality",
|
|
7
|
+
skills: loadSkillsFromDirectory(new URL("./code-review", import.meta.url).pathname)
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export const skills = [
|
|
11
|
+
CodeReviewSkills
|
|
12
|
+
];
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Tool, ToolExecutionContext, ToolExecutionPayload } from "@vertesia/tools-sdk";
|
|
2
|
+
import manifest from "./manifest.js";
|
|
3
|
+
import { ToolResultContent } from "@vertesia/common";
|
|
4
|
+
|
|
5
|
+
interface CalculatorParams {
|
|
6
|
+
expression: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Safely evaluates a mathematical expression
|
|
11
|
+
* Supports: +, -, *, /, ^, parentheses, and decimal numbers
|
|
12
|
+
*/
|
|
13
|
+
function evaluateExpression(expr: string): number {
|
|
14
|
+
// Remove whitespace
|
|
15
|
+
expr = expr.replace(/\s+/g, '');
|
|
16
|
+
|
|
17
|
+
// Replace ^ with ** for exponentiation
|
|
18
|
+
expr = expr.replace(/\^/g, '**');
|
|
19
|
+
|
|
20
|
+
// Validate expression - only allow numbers, operators, parentheses, and decimal points
|
|
21
|
+
if (!/^[0-9+\-*/.()^]+$/.test(expr)) {
|
|
22
|
+
throw new Error('Invalid expression. Only numbers and operators (+, -, *, /, ^) are allowed.');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Use Function constructor for safe evaluation (better than eval)
|
|
26
|
+
try {
|
|
27
|
+
const result = new Function(`'use strict'; return (${expr})`)();
|
|
28
|
+
if (typeof result !== 'number' || !isFinite(result)) {
|
|
29
|
+
throw new Error('Result is not a valid number');
|
|
30
|
+
}
|
|
31
|
+
return result;
|
|
32
|
+
} catch (error) {
|
|
33
|
+
throw new Error(`Failed to evaluate expression: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function calculate(
|
|
38
|
+
payload: ToolExecutionPayload<CalculatorParams>,
|
|
39
|
+
_context: ToolExecutionContext
|
|
40
|
+
): Promise<ToolResultContent> {
|
|
41
|
+
try {
|
|
42
|
+
const { expression } = payload.tool_use.tool_input!;
|
|
43
|
+
const result = evaluateExpression(expression);
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
is_error: false,
|
|
47
|
+
content: `Result: ${expression} = ${result}`
|
|
48
|
+
} satisfies ToolResultContent;
|
|
49
|
+
} catch (error) {
|
|
50
|
+
return {
|
|
51
|
+
is_error: true,
|
|
52
|
+
content: `Calculation error: ${error instanceof Error ? error.message : 'Unknown error'}`
|
|
53
|
+
} satisfies ToolResultContent;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export const CalculatorTool = {
|
|
58
|
+
...manifest,
|
|
59
|
+
run: calculate
|
|
60
|
+
} satisfies Tool<CalculatorParams>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export 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">
|
|
2
|
+
<rect x="4" y="2" width="16" height="20" rx="2"/>
|
|
3
|
+
<line x1="8" y1="6" x2="16" y2="6"/>
|
|
4
|
+
<line x1="8" y1="10" x2="16" y2="10"/>
|
|
5
|
+
<line x1="8" y1="14" x2="16" y2="14"/>
|
|
6
|
+
<line x1="8" y1="18" x2="16" y2="18"/>
|
|
7
|
+
</svg>`;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ToolCollection } from "@vertesia/tools-sdk";
|
|
2
|
+
import { CalculatorTool } from "./calculator.js";
|
|
3
|
+
import icon from "./icon.svg.js";
|
|
4
|
+
|
|
5
|
+
export const CalculatorTools = new ToolCollection({
|
|
6
|
+
name: "calculator",
|
|
7
|
+
title: "Calculator Tools",
|
|
8
|
+
description: "A collection of tools for performing mathematical calculations",
|
|
9
|
+
icon,
|
|
10
|
+
tools: [CalculatorTool]
|
|
11
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ToolDefinition } from "@vertesia/tools-sdk";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
name: "calculator",
|
|
5
|
+
description: "Performs basic mathematical calculations. Supports addition (+), subtraction (-), multiplication (*), division (/), and exponentiation (^).",
|
|
6
|
+
input_schema: {
|
|
7
|
+
type: "object",
|
|
8
|
+
properties: {
|
|
9
|
+
expression: {
|
|
10
|
+
type: "string",
|
|
11
|
+
description: "A mathematical expression to evaluate (e.g., '2 + 2', '10 * 5 - 3', '2^8')"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
required: ["expression"]
|
|
15
|
+
}
|
|
16
|
+
} satisfies ToolDefinition;
|