diff --git a/packages/tools/create-basic-tools/README.md b/packages/tools/create-basic-tools/README.md index b172518..daf0064 100644 --- a/packages/tools/create-basic-tools/README.md +++ b/packages/tools/create-basic-tools/README.md @@ -1,15 +1,15 @@ # @tpmjs/create-basic-tools -CLI generator for scaffolding production-ready TPMJS tool packages with 2-3 tools by default. +CLI generator for scaffolding production-ready TPMJS tool packages. Just enter your package name and you're done! ## Features -- 🎯 **Multi-tool packages**: Generates packages with minimum 2 tools (ideally 2-3) +- ⚡ **Super fast**: Just asks for your package name, generates everything else +- 🎯 **2 example tools**: Start with working examples you can customize - 🔧 **Zod 4 schemas**: Uses Zod directly (not jsonSchema wrapper) - ⚡ **AI SDK v6**: Full compatibility with the latest AI SDK - 📦 **One file per tool**: Clean `src/tools/.ts` structure - ✅ **TPMJS validated**: Auto-validates against official TPMJS schemas -- 🎨 **Beautiful CLI**: Interactive prompts with @clack/prompts - 📝 **Complete setup**: Generates package.json, tsconfig, tsup config, README, and more - 🚀 **Publish ready**: Generated packages are ready to publish to npm immediately @@ -21,14 +21,13 @@ CLI generator for scaffolding production-ready TPMJS tool packages with 2-3 tool pnpmx @tpmjs/create-basic-tools ``` -This will guide you through an interactive wizard that asks: +The CLI asks for just your package name and uses sensible defaults for everything else: -1. **Package info**: name, description, author, license -2. **Tool definitions**: At least 2 tools (export name + description) -3. **Category**: Choose from 12 TPMJS categories -4. **Mode**: Simple (basic Zod schemas) or Advanced (full control) -5. **Output path**: Where to create the package -6. **Confirmation**: Review and confirm +- **Description**: Auto-generated from package name +- **Tools**: 2 example tools you can customize +- **Category**: `ai-ml` (generic) +- **License**: MIT +- **Output**: Derived from package name ### Example Session @@ -40,54 +39,34 @@ $ pnpmx @tpmjs/create-basic-tools ◇ Package name │ @myorg/content-tools │ -◇ Package description -│ AI SDK tools for content processing +◆ Generating package... │ -◇ Tool #1 export name -│ summarizeText -│ -◇ Tool #1 description -│ Summarize a block of text into a concise overview. -│ -◇ Tool #2 export name -│ extractKeywords -│ -◇ Tool #2 description -│ Extract important keywords from text. -│ -◇ Add tool #3? (already have 2) -│ Yes -│ -◇ Tool #3 export name -│ classifySentiment -│ -◇ Tool #3 description -│ Classify the sentiment of text as positive, negative, or neutral. -│ -◇ Category -│ text-analysis -│ -◇ Mode -│ Simple Mode - Basic Zod schemas -│ -◇ Where should we create the package? -│ ./content-tools -│ -◇ Ready to generate? -│ Yes -│ -└ Success! Created @myorg/content-tools at ./content-tools +└ ✓ Success! Created @myorg/content-tools at ./content-tools + + Files created: + src/tools/exampleTool.ts + src/tools/anotherTool.ts + src/index.ts + package.json + + Next steps: + cd ./content-tools + pnpm install + pnpm build + pnpm type-check + pnpm publish ``` +That's it! The generator creates 2 example tools you can rename and customize for your use case. + ## Generated Package Structure ``` content-tools/ ├── src/ │ ├── tools/ # One file per tool -│ │ ├── summarizeText.ts -│ │ ├── extractKeywords.ts -│ │ └── classifySentiment.ts +│ │ ├── exampleTool.ts +│ │ └── anotherTool.ts │ └── index.ts # Re-exports all tools ├── dist/ # Build output (after pnpm build) │ ├── index.js @@ -101,6 +80,8 @@ content-tools/ └── LICENSE ``` +Simply rename `exampleTool.ts` and `anotherTool.ts` to match your use case, then customize the implementation. + ## Generated Tool File Example Each tool file follows this Zod-first pattern: @@ -109,7 +90,7 @@ Each tool file follows this Zod-first pattern: import { tool } from 'ai'; import { z } from 'zod'; -const SummarizeTextSchema = z.object({ +const ExampleToolSchema = z.object({ 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).'), @@ -117,12 +98,12 @@ const SummarizeTextSchema = z.object({ }).default({ language: 'en', maxLength: 100 }).describe('Optional configuration.'), }); -export const summarizeText = tool({ - description: 'Summarize a block of text into a concise overview.', - inputSchema: SummarizeTextSchema, - async execute(input: z.infer) { +export const exampleTool = tool({ + description: 'An example tool - customize this for your use case', + inputSchema: ExampleToolSchema, + async execute(input: z.infer) { // TODO: Implement the tool logic here - console.log('summarizeText called with:', input); + console.log('exampleTool called with:', input); return { success: true, diff --git a/packages/tools/create-basic-tools/package.json b/packages/tools/create-basic-tools/package.json index 9f66b83..cd6f237 100644 --- a/packages/tools/create-basic-tools/package.json +++ b/packages/tools/create-basic-tools/package.json @@ -1,6 +1,6 @@ { "name": "@tpmjs/create-basic-tools", - "version": "1.0.2", + "version": "1.0.3", "description": "CLI generator for scaffolding production-ready TPMJS tool packages", "type": "module", "bin": { diff --git a/packages/tools/create-basic-tools/src/cli.ts b/packages/tools/create-basic-tools/src/cli.ts index 27bca3b..19b98e2 100644 --- a/packages/tools/create-basic-tools/src/cli.ts +++ b/packages/tools/create-basic-tools/src/cli.ts @@ -4,9 +4,6 @@ import { generateTsConfig, generateTsupConfig } from './generators/config-files. import { generatePackageJson } from './generators/package-json.js'; import { generateReadme } from './generators/readme.js'; import { generateIndexFile, generateToolFile } from './generators/source-code.js'; -import { promptCategoryAndMode, promptConfirmation, promptOutputPath } from './prompts/advanced.js'; -import { promptBasicInfo } from './prompts/basic.js'; -import { promptTools } from './prompts/tools.js'; import type { GenerationResult, GeneratorConfig } from './types.js'; import { copyTemplate, @@ -23,41 +20,25 @@ import * as logger from './utils/logger.js'; export async function runInteractiveCLI(): Promise { clack.intro(logger.bold('create-tpmjs-tool')); - // Step 1: Get basic package info - const packageInfo = await promptBasicInfo(); - if (!packageInfo) { + // Only ask for package name + const name = await clack.text({ + message: 'Package name', + placeholder: '@yourname/my-tools', + validate: (value) => { + if (!value) return 'Package name is required'; + if (!value.includes('/')) return 'Package name should be scoped (e.g., @yourname/my-tools)'; + }, + }); + + if (clack.isCancel(name)) { clack.cancel('Operation cancelled'); process.exit(0); } - // Step 2: Get tool definitions (minimum 2) - const tools = await promptTools(); - if (!tools || tools.length < 2) { - clack.cancel('Operation cancelled'); - process.exit(0); - } - - // Step 3: Get category and mode - const categoryAndMode = await promptCategoryAndMode(); - - if (!categoryAndMode) { - clack.cancel('Operation cancelled'); - process.exit(0); - } - - packageInfo.category = categoryAndMode.category; - - // Step 4: Get output path - const packageNameWithoutScope = packageInfo.name.split('/').pop() || packageInfo.name; + // Use defaults for everything else + const packageNameWithoutScope = (name as string).split('/').pop() || (name as string); const defaultPath = `./${packageNameWithoutScope}`; - - const outputPath = await promptOutputPath(defaultPath); - if (!outputPath) { - clack.cancel('Operation cancelled'); - process.exit(0); - } - - const absoluteOutputPath = getAbsolutePath(outputPath); + const absoluteOutputPath = getAbsolutePath(defaultPath); // Check if directory exists if (await pathExists(absoluteOutputPath)) { @@ -66,22 +47,34 @@ export async function runInteractiveCLI(): Promise { process.exit(1); } - // Step 5: Confirm generation - const confirmed = await promptConfirmation(packageInfo.name, tools.length, outputPath); - if (!confirmed) { - clack.cancel('Operation cancelled'); - process.exit(0); - } - - // Step 6: Generate the package + // Generate with sensible defaults const spinner = clack.spinner(); spinner.start('Generating package...'); + const packageInfo = { + name: name as string, + description: `AI SDK tools for ${packageNameWithoutScope}`, + author: '', + license: 'MIT', + category: 'ai-ml', + }; + + const tools = [ + { + exportName: 'exampleTool', + description: 'An example tool - customize this for your use case', + }, + { + exportName: 'anotherTool', + description: 'Another example tool - add your implementation here', + }, + ]; + const config: GeneratorConfig = { packageInfo, tools, outputPath: absoluteOutputPath, - mode: categoryAndMode.mode, + mode: 'simple', }; try { @@ -90,13 +83,13 @@ export async function runInteractiveCLI(): Promise { spinner.stop('Package generated successfully!'); clack.outro(` -${logger.green('✓')} Success! Created ${logger.bold(packageInfo.name)} at ${logger.cyan(outputPath)} +${logger.green('✓')} Success! Created ${logger.bold(packageInfo.name)} at ${logger.cyan(defaultPath)} Files created: ${result.filesCreated.map((f) => ` ${f}`).join('\n')} Next steps: - ${logger.cyan(`cd ${outputPath}`)} + ${logger.cyan(`cd ${defaultPath}`)} ${logger.cyan('pnpm install')} ${logger.cyan('pnpm build')} ${logger.cyan('pnpm type-check')}