feat: add @tpmjs/create-basic-tools CLI generator
- Interactive CLI generator for scaffolding TPMJS tool packages - Generates packages with minimum 2 tools (ideally 2-3) - Zod 4 schemas - uses Zod directly (not jsonSchema wrapper) - One file per tool in src/tools/<toolName>.ts - TPMJS validated against official schemas from @tpmjs/types - Complete package generation ready to publish to npm - Works both standalone and in monorepo packages/ folders 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
8b000cf0ca
commit
38c85bd904
28 changed files with 1426 additions and 2 deletions
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* Generates tsconfig.json content
|
||||
*/
|
||||
export function generateTsConfig(): string {
|
||||
const config = {
|
||||
compilerOptions: {
|
||||
target: 'ES2022',
|
||||
module: 'ESNext',
|
||||
moduleResolution: 'bundler',
|
||||
lib: ['ES2022'],
|
||||
outDir: './dist',
|
||||
rootDir: './src',
|
||||
declaration: true,
|
||||
declarationMap: true,
|
||||
sourceMap: true,
|
||||
strict: true,
|
||||
esModuleInterop: true,
|
||||
skipLibCheck: true,
|
||||
forceConsistentCasingInFileNames: true,
|
||||
resolveJsonModule: true,
|
||||
allowSyntheticDefaultImports: true,
|
||||
},
|
||||
include: ['src/**/*'],
|
||||
exclude: ['node_modules', 'dist'],
|
||||
};
|
||||
|
||||
return JSON.stringify(config, null, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates tsup.config.ts content
|
||||
*/
|
||||
export function generateTsupConfig(): string {
|
||||
return `import { defineConfig } from 'tsup';
|
||||
|
||||
export default defineConfig({
|
||||
entry: ['src/index.ts'],
|
||||
format: ['esm'],
|
||||
dts: true,
|
||||
clean: true,
|
||||
treeshake: true,
|
||||
splitting: false,
|
||||
});
|
||||
`;
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
import type { GeneratorConfig } from '../types.js';
|
||||
|
||||
/**
|
||||
* Generates the package.json content for a TPMJS tool package
|
||||
*/
|
||||
export function generatePackageJson(config: GeneratorConfig): string {
|
||||
const { packageInfo, tools } = config;
|
||||
|
||||
const pkg = {
|
||||
name: packageInfo.name,
|
||||
version: '0.0.1',
|
||||
description: packageInfo.description,
|
||||
type: 'module',
|
||||
main: 'dist/index.js',
|
||||
types: 'dist/index.d.ts',
|
||||
scripts: {
|
||||
build: 'tsup',
|
||||
dev: 'tsup --watch',
|
||||
'type-check': 'tsc --noEmit',
|
||||
},
|
||||
keywords: ['tpmjs-tool', 'ai-sdk', packageInfo.category],
|
||||
author: packageInfo.author || '',
|
||||
license: packageInfo.license,
|
||||
tpmjs: {
|
||||
category: packageInfo.category,
|
||||
tools: tools.map((tool) => ({
|
||||
exportName: tool.exportName,
|
||||
description: tool.description,
|
||||
...(tool.parameters && { parameters: tool.parameters }),
|
||||
...(tool.returns && { returns: tool.returns }),
|
||||
...(tool.aiAgent && { aiAgent: tool.aiAgent }),
|
||||
})),
|
||||
...(tools.some((t) => t.env) && {
|
||||
env: tools.flatMap((t) => t.env || []),
|
||||
}),
|
||||
...(tools.some((t) => t.frameworks) && {
|
||||
frameworks: Array.from(new Set(tools.flatMap((t) => t.frameworks || []))),
|
||||
}),
|
||||
},
|
||||
dependencies: {
|
||||
ai: '^6.0.0',
|
||||
zod: '^4.1.13',
|
||||
},
|
||||
devDependencies: {
|
||||
tsup: '^8.3.5',
|
||||
typescript: '^5.9.3',
|
||||
},
|
||||
files: ['dist', 'README.md'],
|
||||
};
|
||||
|
||||
return JSON.stringify(pkg, null, 2);
|
||||
}
|
||||
77
packages/tools/create-basic-tools/src/generators/readme.ts
Normal file
77
packages/tools/create-basic-tools/src/generators/readme.ts
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
import type { GeneratorConfig } from '../types.js';
|
||||
|
||||
/**
|
||||
* Generates README.md content for the tool package
|
||||
*/
|
||||
export function generateReadme(config: GeneratorConfig): string {
|
||||
const { packageInfo, tools } = config;
|
||||
|
||||
const toolsList = tools.map((tool) => `- **${tool.exportName}**: ${tool.description}`).join('\n');
|
||||
|
||||
const usageExample = tools[0];
|
||||
if (!usageExample) {
|
||||
throw new Error('At least one tool is required');
|
||||
}
|
||||
|
||||
return `# ${packageInfo.name}
|
||||
|
||||
${packageInfo.description}
|
||||
|
||||
## Installation
|
||||
|
||||
\`\`\`bash
|
||||
pnpm add ${packageInfo.name}
|
||||
\`\`\`
|
||||
|
||||
## Tools
|
||||
|
||||
This package provides ${tools.length} tool${tools.length > 1 ? 's' : ''} for the AI SDK:
|
||||
|
||||
${toolsList}
|
||||
|
||||
## Usage
|
||||
|
||||
\`\`\`typescript
|
||||
import { ${usageExample.exportName} } from '${packageInfo.name}';
|
||||
import { generateText } from 'ai';
|
||||
import { openai } from '@ai-sdk/openai';
|
||||
|
||||
const result = await generateText({
|
||||
model: openai('gpt-4'),
|
||||
prompt: 'Process this text for me',
|
||||
tools: {
|
||||
${usageExample.exportName},
|
||||
},
|
||||
});
|
||||
|
||||
console.log(result.text);
|
||||
\`\`\`
|
||||
|
||||
## Development
|
||||
|
||||
\`\`\`bash
|
||||
# Install dependencies
|
||||
pnpm install
|
||||
|
||||
# Build the package
|
||||
pnpm build
|
||||
|
||||
# Type-check
|
||||
pnpm type-check
|
||||
|
||||
# Watch mode
|
||||
pnpm dev
|
||||
\`\`\`
|
||||
|
||||
## Publishing
|
||||
|
||||
1. Update the version in \`package.json\`
|
||||
2. Build the package: \`pnpm build\`
|
||||
3. Publish to npm: \`pnpm publish --access public\`
|
||||
4. Your tools will appear on [tpmjs.com](https://tpmjs.com) within 2-15 minutes
|
||||
|
||||
## License
|
||||
|
||||
${packageInfo.license}
|
||||
`;
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
import type { ToolDefinition } from '../types.js';
|
||||
|
||||
/**
|
||||
* Generates a single tool file with Zod schema
|
||||
*/
|
||||
export function generateToolFile(tool: ToolDefinition): string {
|
||||
const { exportName, description } = tool;
|
||||
|
||||
// Generate schema name (capitalize first letter + "Schema")
|
||||
const schemaName = `${exportName.charAt(0).toUpperCase()}${exportName.slice(1)}Schema`;
|
||||
|
||||
// Generate simple Zod schema (can be enhanced in advanced mode)
|
||||
const schemaContent = generateSimpleSchema();
|
||||
|
||||
return `import { tool } from 'ai';
|
||||
import { z } from 'zod';
|
||||
|
||||
const ${schemaName} = z.object({
|
||||
${schemaContent}
|
||||
});
|
||||
|
||||
export const ${exportName} = tool({
|
||||
description: '${description}',
|
||||
inputSchema: ${schemaName},
|
||||
async execute(input: z.infer<typeof ${schemaName}>) {
|
||||
// TODO: Implement the tool logic here
|
||||
console.log('${exportName} called with:', input);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Tool executed successfully. Replace this with your implementation.',
|
||||
input,
|
||||
};
|
||||
},
|
||||
});
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a simple Zod schema with example fields
|
||||
*/
|
||||
function generateSimpleSchema(): string {
|
||||
return ` text: z.string().min(1, 'Text cannot be empty').describe('The input text to process.'),
|
||||
options: z.object({
|
||||
language: z.string().default('en').describe('Language code (e.g., en, es, fr).'),
|
||||
maxLength: z.number().int().positive().default(100).describe('Maximum length of output.'),
|
||||
}).default({ language: 'en', maxLength: 100 }).describe('Optional configuration.'),`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the main index.ts file that re-exports all tools
|
||||
*/
|
||||
export function generateIndexFile(tools: ToolDefinition[]): string {
|
||||
const exports = tools
|
||||
.map((tool) => `export { ${tool.exportName} } from './tools/${tool.exportName}.js';`)
|
||||
.join('\n');
|
||||
|
||||
return `/**
|
||||
* TPMJS Tool Package
|
||||
* Auto-generated by @tpmjs/create-basic-tools
|
||||
*/
|
||||
|
||||
${exports}
|
||||
`;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue