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:
Ajax Davis 2025-12-04 23:34:37 +10:00
parent 8b000cf0ca
commit 38c85bd904
28 changed files with 1426 additions and 2 deletions

View file

@ -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,
});
`;
}

View file

@ -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);
}

View 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}
`;
}

View file

@ -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}
`;
}