@chanl-ai/cli 2.0.1
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/bin/chanl.js +10 -0
- package/dist/__tests__/cli.test.d.ts +2 -0
- package/dist/__tests__/cli.test.js +2313 -0
- package/dist/__tests__/cli.test.js.map +1 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.js +72 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/agents.d.ts +8 -0
- package/dist/commands/agents.js +671 -0
- package/dist/commands/agents.js.map +1 -0
- package/dist/commands/auth.d.ts +16 -0
- package/dist/commands/auth.js +294 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/call.d.ts +8 -0
- package/dist/commands/call.js +166 -0
- package/dist/commands/call.js.map +1 -0
- package/dist/commands/calls.d.ts +8 -0
- package/dist/commands/calls.js +719 -0
- package/dist/commands/calls.js.map +1 -0
- package/dist/commands/chat.d.ts +8 -0
- package/dist/commands/chat.js +203 -0
- package/dist/commands/chat.js.map +1 -0
- package/dist/commands/config.d.ts +8 -0
- package/dist/commands/config.js +231 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/health.d.ts +8 -0
- package/dist/commands/health.js +55 -0
- package/dist/commands/health.js.map +1 -0
- package/dist/commands/index.d.ts +18 -0
- package/dist/commands/index.js +39 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/knowledge.d.ts +8 -0
- package/dist/commands/knowledge.js +539 -0
- package/dist/commands/knowledge.js.map +1 -0
- package/dist/commands/mcp.d.ts +8 -0
- package/dist/commands/mcp.js +589 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/memory.d.ts +8 -0
- package/dist/commands/memory.js +408 -0
- package/dist/commands/memory.js.map +1 -0
- package/dist/commands/personas.d.ts +8 -0
- package/dist/commands/personas.js +356 -0
- package/dist/commands/personas.js.map +1 -0
- package/dist/commands/prompts.d.ts +8 -0
- package/dist/commands/prompts.js +295 -0
- package/dist/commands/prompts.js.map +1 -0
- package/dist/commands/scenarios.d.ts +8 -0
- package/dist/commands/scenarios.js +591 -0
- package/dist/commands/scenarios.js.map +1 -0
- package/dist/commands/scorecards.d.ts +8 -0
- package/dist/commands/scorecards.js +570 -0
- package/dist/commands/scorecards.js.map +1 -0
- package/dist/commands/tools.d.ts +8 -0
- package/dist/commands/tools.js +632 -0
- package/dist/commands/tools.js.map +1 -0
- package/dist/commands/toolsets.d.ts +8 -0
- package/dist/commands/toolsets.js +464 -0
- package/dist/commands/toolsets.js.map +1 -0
- package/dist/commands/workspaces.d.ts +8 -0
- package/dist/commands/workspaces.js +170 -0
- package/dist/commands/workspaces.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/config-store.d.ts +117 -0
- package/dist/utils/config-store.js +191 -0
- package/dist/utils/config-store.js.map +1 -0
- package/dist/utils/interactive.d.ts +41 -0
- package/dist/utils/interactive.js +83 -0
- package/dist/utils/interactive.js.map +1 -0
- package/dist/utils/output.d.ts +100 -0
- package/dist/utils/output.js +221 -0
- package/dist/utils/output.js.map +1 -0
- package/dist/utils/sdk-factory.d.ts +15 -0
- package/dist/utils/sdk-factory.js +34 -0
- package/dist/utils/sdk-factory.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/commands/tools.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { readFile } from 'fs/promises';\nimport { confirm } from '@inquirer/prompts';\nimport ora from 'ora';\nimport chalk from 'chalk';\nimport type { Tool, ToolExecution, ToolType, CreateToolInput, UpdateToolInput, ExecuteResult } from '@chanl-ai/sdk';\nimport { createSdk } from '../utils/sdk-factory.js';\nimport {\n printSuccess,\n printError,\n printInfo,\n printLabel,\n printBlank,\n printSimpleTable,\n isJsonOutput,\n printJson,\n formatDate,\n} from '../utils/output.js';\n\n// Sample tool templates for --template flag\nconst TOOL_TEMPLATES = {\n http: {\n name: 'my-api-tool',\n description: 'Calls an external API endpoint',\n type: 'http',\n inputSchema: {\n type: 'object',\n properties: {\n query: { type: 'string', description: 'Search query' },\n },\n required: ['query'],\n },\n configuration: {\n http: {\n method: 'POST',\n url: 'https://api.example.com/search',\n headers: { 'Content-Type': 'application/json' },\n bodyTemplate: '{\"q\": \"{{query}}\"}',\n },\n },\n isEnabled: true,\n tags: ['api', 'search'],\n },\n javascript: {\n name: 'my-js-tool',\n description: 'Executes JavaScript code',\n type: 'javascript',\n inputSchema: {\n type: 'object',\n properties: {\n a: { type: 'number', description: 'First number' },\n b: { type: 'number', description: 'Second number' },\n },\n required: ['a', 'b'],\n },\n configuration: {\n javascript: {\n code: 'return { result: args.a + args.b };',\n },\n },\n isEnabled: true,\n },\n};\n\n/**\n * Create the tools command group\n */\nexport function createToolsCommand(): Command {\n const tools = new Command('tools').description('Manage MCP tools');\n\n // tools list\n tools\n .command('list')\n .description('List all tools in the workspace')\n .option('-t, --type <type>', 'Filter by type: http, javascript, code')\n .option('-e, --enabled', 'Show only enabled tools')\n .option('-d, --disabled', 'Show only disabled tools')\n .option('--tag <tag>', 'Filter by tag (e.g., --tag api)')\n .option('--no-system', 'Exclude system tools (kb_search, chanl_reason, etc.)')\n .option('-l, --limit <number>', 'Items per page (default: 20)', '20')\n .option('-p, --page <number>', 'Page number (default: 1)', '1')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl tools list # List all tools\n $ chanl tools list --enabled # Only enabled tools\n $ chanl tools list --type http # Only HTTP tools\n $ chanl tools list --tag api # Filter by tag\n $ chanl tools list --no-system # Exclude system tools\n $ chanl tools list --json # Output as JSON`\n )\n .action(handleToolsList);\n\n // tools get <id>\n tools\n .command('get <id>')\n .description('Get detailed info about a tool')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl tools get 507f1f77bcf86cd799439011\n $ chanl tools get 507f1f77bcf86cd799439011 --json`\n )\n .action(handleToolsGet);\n\n // tools create\n tools\n .command('create')\n .description('Create a new tool from JSON file')\n .option('-f, --file <path>', 'Path to JSON file with tool definition')\n .option('--template [type]', 'Output a sample JSON template (http or javascript)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl tools create --template http > my-tool.json # Generate template\n $ chanl tools create -f my-tool.json # Create from file\n\nRequired JSON fields:\n name Tool name (used in MCP)\n description What the tool does\n type \"http\" | \"javascript\" | \"code\"\n inputSchema JSON Schema for input parameters\n configuration Tool-specific config (http.url, http.method, etc.)\n\nOptional fields:\n isEnabled Enable immediately (default: true)\n tags Array of category tags\n\nRun 'chanl tools create --template' to see full structure.`\n )\n .action(handleToolsCreate);\n\n // tools update <id>\n tools\n .command('update <id>')\n .description('Update a tool from JSON file')\n .requiredOption('-f, --file <path>', 'Path to JSON file with updates')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl tools update 507f1f77bcf86cd799439011 -f updates.json\n\nThe JSON file only needs fields you want to change:\n {\"description\": \"Updated description\", \"isEnabled\": false}`\n )\n .action(handleToolsUpdate);\n\n // tools delete <id>\n tools\n .command('delete <id>')\n .description('Delete a tool permanently')\n .option('-y, --yes', 'Skip confirmation prompt')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl tools delete 507f1f77bcf86cd799439011 # With confirmation\n $ chanl tools delete 507f1f77bcf86cd799439011 -y # Skip confirmation`\n )\n .action(handleToolsDelete);\n\n // tools execute <id>\n tools\n .command('execute <id>')\n .description('Execute a tool and get results')\n .requiredOption('-i, --input <json>', 'Input arguments as JSON string')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl tools execute 507f1f77bcf86cd799439011 -i '{\"query\": \"hello\"}'\n $ chanl tools execute my-tool-id -i '{\"location\": \"London\"}' --json`\n )\n .action(handleToolsExecute);\n\n // tools test <id>\n tools\n .command('test <id>')\n .description('Test a tool execution (dry run)')\n .requiredOption('-i, --input <json>', 'Input arguments as JSON string')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl tools test 507f1f77bcf86cd799439011 -i '{\"message\": \"test\"}'`\n )\n .action(handleToolsTest);\n\n // tools executions <id>\n tools\n .command('executions <id>')\n .description('Get execution history for a tool')\n .option('-l, --limit <number>', 'Items per page (default: 10)', '10')\n .option('-p, --page <number>', 'Page number (default: 1)', '1')\n .option('--status <status>', 'Filter: pending, running, completed, failed')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl tools executions 507f1f77bcf86cd799439011\n $ chanl tools executions my-tool-id --status failed --limit 5`\n )\n .action(handleToolsExecutions);\n\n // tools enable <id>\n tools\n .command('enable <id>')\n .description('Enable a tool (makes it available in MCP)')\n .action(handleToolsEnable);\n\n // tools disable <id>\n tools\n .command('disable <id>')\n .description('Disable a tool (hides from MCP)')\n .action(handleToolsDisable);\n\n // tools categories\n tools\n .command('categories')\n .description('Show tool categories (tags) with counts')\n .addHelpText(\n 'after',\n `\nShows all tags used across tools with:\n - Total tools in each category\n - Number of enabled tools`\n )\n .action(handleToolsCategories);\n\n return tools;\n}\n\n/**\n * Handle tools list command\n */\nasync function handleToolsList(options: {\n type?: string;\n enabled?: boolean;\n disabled?: boolean;\n tag?: string;\n system?: boolean; // --no-system sets this to false\n limit: string;\n page: string;\n}): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching tools...').start();\n\n try {\n // Determine enabled filter\n let isEnabled: boolean | undefined;\n if (options.enabled) isEnabled = true;\n else if (options.disabled) isEnabled = false;\n\n const response = await sdk.tools.list({\n type: options.type as ToolType | undefined,\n isEnabled,\n tag: options.tag,\n includeSystem: options.system, // --no-system sets this to false\n limit: parseInt(options.limit, 10),\n page: parseInt(options.page, 10),\n });\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch tools', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { tools, total, pagination } = response.data;\n\n if (isJsonOutput()) {\n printJson({ tools, total, pagination });\n return;\n }\n\n if (tools.length === 0) {\n printInfo('No tools found');\n return;\n }\n\n printBlank();\n printSimpleTable(\n ['Name', 'Type', 'Enabled', 'Tags', 'Last Called'],\n tools.map((tool) => [\n tool.name,\n tool.type,\n tool.isEnabled ? chalk.green('✓') : chalk.red('✗'),\n tool.tags.length > 0 ? tool.tags.join(', ') : '-',\n tool.stats.lastCalledAt ? formatDate(tool.stats.lastCalledAt) : 'Never',\n ])\n );\n\n printBlank();\n printInfo(`Total: ${total} tools (Page ${pagination.page} of ${pagination.totalPages})`);\n } catch (error) {\n spinner.fail('Failed to fetch tools');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle tools get command\n */\nasync function handleToolsGet(id: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching tool...').start();\n\n try {\n const response = await sdk.tools.get(id);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch tool', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { tool } = response.data;\n\n if (isJsonOutput()) {\n printJson(tool);\n return;\n }\n\n printBlank();\n printToolDetails(tool);\n } catch (error) {\n spinner.fail('Failed to fetch tool');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle tools create command\n */\nasync function handleToolsCreate(options: { file?: string; template?: boolean | string }): Promise<void> {\n // Handle --template flag: output sample JSON and exit\n if (options.template !== undefined) {\n const templateType = typeof options.template === 'string' ? options.template : 'http';\n const template = TOOL_TEMPLATES[templateType as keyof typeof TOOL_TEMPLATES];\n\n if (!template) {\n printError('Unknown template type', `Available: http, javascript`);\n process.exitCode = 1;\n return;\n }\n\n // Output raw JSON (for piping to file)\n console.log(JSON.stringify(template, null, 2));\n return;\n }\n\n // Require --file if not using --template\n if (!options.file) {\n printError('Missing required option', \"Use '-f, --file <path>' or '--template' for sample JSON\");\n printInfo(\"Run 'chanl tools create --help' for usage\");\n process.exitCode = 1;\n return;\n }\n\n const sdk = createSdk();\n if (!sdk) return;\n\n // Read and parse JSON file\n let input: Record<string, unknown>;\n try {\n const content = await readFile(options.file, 'utf-8');\n input = JSON.parse(content);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Failed to read file', message);\n process.exitCode = 1;\n return;\n }\n\n const spinner = ora('Creating tool...').start();\n\n try {\n const response = await sdk.tools.create(input as unknown as CreateToolInput);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to create tool', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { tool } = response.data;\n\n if (isJsonOutput()) {\n printJson({ success: true, tool });\n return;\n }\n\n printSuccess(`Created tool: ${tool.name} (${tool.id})`);\n } catch (error) {\n spinner.fail('Failed to create tool');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle tools update command\n */\nasync function handleToolsUpdate(id: string, options: { file: string }): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n // Read and parse JSON file\n let input: Record<string, unknown>;\n try {\n const content = await readFile(options.file, 'utf-8');\n input = JSON.parse(content);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Failed to read file', message);\n process.exitCode = 1;\n return;\n }\n\n const spinner = ora('Updating tool...').start();\n\n try {\n const response = await sdk.tools.update(id, input as unknown as UpdateToolInput);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to update tool', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { tool } = response.data;\n\n if (isJsonOutput()) {\n printJson({ success: true, tool });\n return;\n }\n\n printSuccess(`Updated tool: ${tool.name} (${tool.id})`);\n } catch (error) {\n spinner.fail('Failed to update tool');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle tools delete command\n */\nasync function handleToolsDelete(id: string, options: { yes?: boolean }): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n // Confirm deletion unless --yes flag is provided\n if (!options.yes) {\n try {\n const confirmed = await confirm({\n message: `Are you sure you want to delete tool '${id}'?`,\n default: false,\n });\n\n if (!confirmed) {\n printInfo('Deletion cancelled');\n return;\n }\n } catch {\n // User cancelled (Ctrl+C)\n printBlank();\n printInfo('Deletion cancelled');\n return;\n }\n }\n\n const spinner = ora('Deleting tool...').start();\n\n try {\n const response = await sdk.tools.delete(id);\n\n spinner.stop();\n\n if (!response.success) {\n printError('Failed to delete tool', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson({ success: true, deleted: true, id });\n return;\n }\n\n printSuccess(`Deleted tool: ${id}`);\n } catch (error) {\n spinner.fail('Failed to delete tool');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle tools execute command\n */\nasync function handleToolsExecute(id: string, options: { input: string }): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n // Parse input JSON\n let args: Record<string, unknown>;\n try {\n args = JSON.parse(options.input);\n } catch {\n printError('Invalid JSON input', `Could not parse: ${options.input}`);\n process.exitCode = 1;\n return;\n }\n\n const spinner = ora('Executing tool...').start();\n\n try {\n const response = await sdk.tools.execute(id, args);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Execution failed', response.message);\n process.exitCode = 1;\n return;\n }\n\n const execution = response.data;\n\n if (isJsonOutput()) {\n printJson(execution);\n return;\n }\n\n printExecutionResult(execution);\n } catch (error) {\n spinner.fail('Execution failed');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle tools test command\n */\nasync function handleToolsTest(id: string, options: { input: string }): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n // Parse input JSON\n let args: Record<string, unknown>;\n try {\n args = JSON.parse(options.input);\n } catch {\n printError('Invalid JSON input', `Could not parse: ${options.input}`);\n process.exitCode = 1;\n return;\n }\n\n const spinner = ora('Testing tool...').start();\n\n try {\n const response = await sdk.tools.test(id, args);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Test failed', response.message);\n process.exitCode = 1;\n return;\n }\n\n const execution = response.data;\n\n if (isJsonOutput()) {\n printJson(execution);\n return;\n }\n\n printInfo('Test execution:');\n printExecutionResult(execution);\n } catch (error) {\n spinner.fail('Test failed');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle tools executions command\n */\nasync function handleToolsExecutions(\n id: string,\n options: {\n limit: string;\n page: string;\n status?: string;\n }\n): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching executions...').start();\n\n try {\n const response = await sdk.tools.getExecutions(id, {\n limit: parseInt(options.limit, 10),\n page: parseInt(options.page, 10),\n status: options.status as ToolExecution['status'] | undefined,\n });\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch executions', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { data: executions, total, pagination } = response.data;\n\n if (isJsonOutput()) {\n printJson({ executions, total, pagination });\n return;\n }\n\n if (executions.length === 0) {\n printInfo('No executions found');\n return;\n }\n\n printBlank();\n printSimpleTable(\n ['Execution ID', 'Status', 'Duration', 'Source', 'Created'],\n executions.map((exec) => [\n exec.id.substring(0, 12) + '...',\n formatStatus(exec.status),\n exec.executionTimeMs ? `${exec.executionTimeMs}ms` : '-',\n exec.source,\n formatDate(exec.createdAt),\n ])\n );\n\n printBlank();\n printInfo(`Total: ${total} executions (Page ${pagination.page} of ${pagination.totalPages})`);\n } catch (error) {\n spinner.fail('Failed to fetch executions');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle tools enable command\n */\nasync function handleToolsEnable(id: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Enabling tool...').start();\n\n try {\n const response = await sdk.tools.enable(id);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to enable tool', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { tool } = response.data;\n\n if (isJsonOutput()) {\n printJson({ success: true, tool });\n return;\n }\n\n printSuccess(`Enabled tool: ${tool.name} (${tool.id})`);\n } catch (error) {\n spinner.fail('Failed to enable tool');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle tools disable command\n */\nasync function handleToolsDisable(id: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Disabling tool...').start();\n\n try {\n const response = await sdk.tools.disable(id);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to disable tool', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { tool } = response.data;\n\n if (isJsonOutput()) {\n printJson({ success: true, tool });\n return;\n }\n\n printSuccess(`Disabled tool: ${tool.name} (${tool.id})`);\n } catch (error) {\n spinner.fail('Failed to disable tool');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle tools categories command\n */\nasync function handleToolsCategories(): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching categories...').start();\n\n try {\n const response = await sdk.tools.getCategories();\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch categories', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { categories, uncategorized } = response.data;\n\n if (isJsonOutput()) {\n printJson({ categories, uncategorized });\n return;\n }\n\n if (categories.length === 0 && uncategorized.count === 0) {\n printInfo('No categories found');\n return;\n }\n\n printBlank();\n printSimpleTable(\n ['Category', 'Total', 'Enabled'],\n [\n ...categories.map((cat) => [\n cat.tag,\n cat.count.toString(),\n `${cat.enabled} (${Math.round((cat.enabled / cat.count) * 100)}%)`,\n ]),\n [\n chalk.gray('(uncategorized)'),\n uncategorized.count.toString(),\n uncategorized.count > 0\n ? `${uncategorized.enabled} (${Math.round((uncategorized.enabled / uncategorized.count) * 100)}%)`\n : '0 (0%)',\n ],\n ]\n );\n\n const totalCount = categories.reduce((sum, c) => sum + c.count, 0) + uncategorized.count;\n const totalEnabled = categories.reduce((sum, c) => sum + c.enabled, 0) + uncategorized.enabled;\n\n printBlank();\n printInfo(`Total: ${totalCount} tools, ${totalEnabled} enabled`);\n } catch (error) {\n spinner.fail('Failed to fetch categories');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Print tool details in formatted output\n */\nfunction printToolDetails(tool: Tool): void {\n printLabel('Name', tool.name);\n printLabel('ID', tool.id);\n printLabel('Type', tool.type);\n printLabel('Enabled', tool.isEnabled ? chalk.green('Yes') : chalk.red('No'));\n printLabel('Description', tool.description);\n\n if (tool.tags.length > 0) {\n printLabel('Tags', tool.tags.join(', '));\n }\n\n printBlank();\n printInfo('Input Schema:');\n console.log(chalk.gray(JSON.stringify(tool.inputSchema, null, 2)));\n\n printBlank();\n printInfo('Configuration:');\n console.log(chalk.gray(JSON.stringify(tool.configuration, null, 2)));\n\n printBlank();\n printInfo('Statistics:');\n printLabel(' Total Calls', tool.stats.totalCalls.toString());\n printLabel(' Successful', tool.stats.successfulCalls.toString());\n printLabel(' Failed', tool.stats.failedCalls.toString());\n printLabel(' Avg Latency', `${tool.stats.averageLatencyMs}ms`);\n if (tool.stats.lastCalledAt) {\n printLabel(' Last Called', formatDate(tool.stats.lastCalledAt));\n }\n\n printBlank();\n printLabel('Created', formatDate(tool.createdAt));\n printLabel('Updated', formatDate(tool.updatedAt));\n printBlank();\n}\n\n/**\n * Print execution result (real-time execute/test response)\n */\nfunction printExecutionResult(result: ExecuteResult): void {\n printBlank();\n\n // Status based on success boolean\n const statusText = result.success\n ? chalk.green('✓ Success')\n : chalk.red('✗ Failed');\n printLabel('Status', statusText);\n\n // Duration\n if (result.latencyMs) {\n printLabel('Duration', `${result.latencyMs}ms`);\n }\n\n // Execution ID for reference\n if (result.executionId) {\n printLabel('Execution ID', result.executionId);\n }\n\n // Error message if failed\n if (!result.success && result.error) {\n printBlank();\n printError('Error', result.error);\n }\n\n // Output data\n if (result.data) {\n printBlank();\n printInfo('Output:');\n console.log(chalk.gray(JSON.stringify(result.data, null, 2)));\n }\n\n printBlank();\n}\n\n/**\n * Format execution status with color (for history display)\n */\nfunction formatStatus(status: ToolExecution['status']): string {\n switch (status) {\n case 'completed':\n return chalk.green('✓ completed');\n case 'failed':\n return chalk.red('✗ failed');\n case 'running':\n return chalk.blue('⋯ running');\n case 'pending':\n return chalk.gray('○ pending');\n case 'corrected':\n return chalk.yellow('⚡ corrected');\n default:\n return status;\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { readFile } from "fs/promises";
|
|
3
|
+
import { confirm } from "@inquirer/prompts";
|
|
4
|
+
import ora from "ora";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import { createSdk } from "../utils/sdk-factory.js";
|
|
7
|
+
import {
|
|
8
|
+
printSuccess,
|
|
9
|
+
printError,
|
|
10
|
+
printInfo,
|
|
11
|
+
printLabel,
|
|
12
|
+
printBlank,
|
|
13
|
+
printSimpleTable,
|
|
14
|
+
isJsonOutput,
|
|
15
|
+
printJson,
|
|
16
|
+
formatDate
|
|
17
|
+
} from "../utils/output.js";
|
|
18
|
+
const TOOLSET_TEMPLATE = {
|
|
19
|
+
name: "my-toolset",
|
|
20
|
+
description: "A curated collection of tools for a specific use case",
|
|
21
|
+
tools: ["tool-id-1", "tool-id-2"],
|
|
22
|
+
toolOverrides: {
|
|
23
|
+
"tool-id-1": {
|
|
24
|
+
name: "custom_name",
|
|
25
|
+
description: "Override description for this tool"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
isEnabled: true,
|
|
29
|
+
tags: ["production", "customer-facing"]
|
|
30
|
+
};
|
|
31
|
+
function createToolsetsCommand() {
|
|
32
|
+
const toolsets = new Command("toolsets").description("Manage MCP toolsets (collections of tools)").addHelpText(
|
|
33
|
+
"after",
|
|
34
|
+
`
|
|
35
|
+
What are Toolsets?
|
|
36
|
+
Toolsets group multiple tools together and allow you to customize how they
|
|
37
|
+
appear to AI agents. Use toolsets to:
|
|
38
|
+
- Create curated tool collections for specific use cases
|
|
39
|
+
- Override tool names/descriptions per context
|
|
40
|
+
- Enable/disable entire groups of tools at once
|
|
41
|
+
|
|
42
|
+
Examples:
|
|
43
|
+
$ chanl toolsets list # List all toolsets
|
|
44
|
+
$ chanl toolsets create -f toolset.json # Create new toolset
|
|
45
|
+
$ chanl toolsets add-tools <id> -t id1,id2 # Add tools to toolset`
|
|
46
|
+
);
|
|
47
|
+
toolsets.command("list").description("List all toolsets in the workspace").option("-e, --enabled", "Show only enabled toolsets").option("-d, --disabled", "Show only disabled toolsets").option("--tag <tag>", "Filter by tag").option("-s, --search <search>", "Search by name or description").option("-l, --limit <number>", "Items per page (default: 20)", "20").option("-p, --page <number>", "Page number (default: 1)", "1").addHelpText(
|
|
48
|
+
"after",
|
|
49
|
+
`
|
|
50
|
+
Examples:
|
|
51
|
+
$ chanl toolsets list # List all
|
|
52
|
+
$ chanl toolsets list --enabled # Only enabled
|
|
53
|
+
$ chanl toolsets list --search "api" # Search by name`
|
|
54
|
+
).action(handleToolsetsList);
|
|
55
|
+
toolsets.command("get <id>").description("Get detailed info about a toolset").addHelpText(
|
|
56
|
+
"after",
|
|
57
|
+
`
|
|
58
|
+
Example:
|
|
59
|
+
$ chanl toolsets get 507f1f77bcf86cd799439011`
|
|
60
|
+
).action(handleToolsetsGet);
|
|
61
|
+
toolsets.command("create").description("Create a new toolset from JSON file").option("-f, --file <path>", "Path to JSON file with toolset definition").option("--template", "Output a sample JSON template").addHelpText(
|
|
62
|
+
"after",
|
|
63
|
+
`
|
|
64
|
+
Examples:
|
|
65
|
+
$ chanl toolsets create --template > my-toolset.json # Generate template
|
|
66
|
+
$ chanl toolsets create -f my-toolset.json # Create from file
|
|
67
|
+
|
|
68
|
+
Required JSON fields:
|
|
69
|
+
name Toolset name
|
|
70
|
+
description What this toolset is for
|
|
71
|
+
tools Array of tool IDs to include
|
|
72
|
+
|
|
73
|
+
Optional fields:
|
|
74
|
+
toolOverrides Override name/description per tool
|
|
75
|
+
isEnabled Enable immediately (default: true)
|
|
76
|
+
tags Array of category tags`
|
|
77
|
+
).action(handleToolsetsCreate);
|
|
78
|
+
toolsets.command("update <id>").description("Update a toolset from JSON file").requiredOption("-f, --file <path>", "Path to JSON file with updates").addHelpText(
|
|
79
|
+
"after",
|
|
80
|
+
`
|
|
81
|
+
Example:
|
|
82
|
+
$ chanl toolsets update 507f1f77bcf86cd799439011 -f updates.json`
|
|
83
|
+
).action(handleToolsetsUpdate);
|
|
84
|
+
toolsets.command("delete <id>").description("Delete a toolset permanently").option("-y, --yes", "Skip confirmation prompt").addHelpText(
|
|
85
|
+
"after",
|
|
86
|
+
`
|
|
87
|
+
Examples:
|
|
88
|
+
$ chanl toolsets delete 507f1f77bcf86cd799439011 # With confirmation
|
|
89
|
+
$ chanl toolsets delete 507f1f77bcf86cd799439011 -y # Skip confirmation`
|
|
90
|
+
).action(handleToolsetsDelete);
|
|
91
|
+
toolsets.command("enable <id>").description("Enable a toolset (makes its tools available)").action(handleToolsetsEnable);
|
|
92
|
+
toolsets.command("disable <id>").description("Disable a toolset (hides its tools)").action(handleToolsetsDisable);
|
|
93
|
+
toolsets.command("add-tools <id>").description("Add tools to an existing toolset").requiredOption("-t, --tools <ids>", "Comma-separated tool IDs").addHelpText(
|
|
94
|
+
"after",
|
|
95
|
+
`
|
|
96
|
+
Example:
|
|
97
|
+
$ chanl toolsets add-tools 507f1f77bcf86cd799439011 -t tool1,tool2,tool3`
|
|
98
|
+
).action(handleToolsetsAddTools);
|
|
99
|
+
toolsets.command("remove-tools <id>").description("Remove tools from a toolset").requiredOption("-t, --tools <ids>", "Comma-separated tool IDs").addHelpText(
|
|
100
|
+
"after",
|
|
101
|
+
`
|
|
102
|
+
Example:
|
|
103
|
+
$ chanl toolsets remove-tools 507f1f77bcf86cd799439011 -t tool1,tool2`
|
|
104
|
+
).action(handleToolsetsRemoveTools);
|
|
105
|
+
return toolsets;
|
|
106
|
+
}
|
|
107
|
+
async function handleToolsetsList(options) {
|
|
108
|
+
const sdk = createSdk();
|
|
109
|
+
if (!sdk) return;
|
|
110
|
+
const spinner = ora("Fetching toolsets...").start();
|
|
111
|
+
try {
|
|
112
|
+
let enabled;
|
|
113
|
+
if (options.enabled) enabled = true;
|
|
114
|
+
else if (options.disabled) enabled = false;
|
|
115
|
+
const response = await sdk.toolsets.list({
|
|
116
|
+
enabled,
|
|
117
|
+
tag: options.tag,
|
|
118
|
+
search: options.search,
|
|
119
|
+
limit: parseInt(options.limit, 10),
|
|
120
|
+
page: parseInt(options.page, 10)
|
|
121
|
+
});
|
|
122
|
+
spinner.stop();
|
|
123
|
+
if (!response.success || !response.data) {
|
|
124
|
+
printError("Failed to fetch toolsets", response.message);
|
|
125
|
+
process.exitCode = 1;
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const toolsets = response.data.data;
|
|
129
|
+
const total = response.data.total;
|
|
130
|
+
const pagination = response.data.pagination || {
|
|
131
|
+
page: parseInt(options.page, 10),
|
|
132
|
+
limit: parseInt(options.limit, 10),
|
|
133
|
+
totalPages: Math.ceil(total / parseInt(options.limit, 10)),
|
|
134
|
+
hasNext: false,
|
|
135
|
+
hasPrev: false
|
|
136
|
+
};
|
|
137
|
+
if (isJsonOutput()) {
|
|
138
|
+
printJson({ toolsets, total, pagination });
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (toolsets.length === 0) {
|
|
142
|
+
printInfo("No toolsets found");
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
printBlank();
|
|
146
|
+
printSimpleTable(
|
|
147
|
+
["Name", "Tool Count", "Enabled", "Tags", "Version"],
|
|
148
|
+
toolsets.map((toolset) => [
|
|
149
|
+
toolset.name,
|
|
150
|
+
toolset.toolCount.toString(),
|
|
151
|
+
toolset.enabled ? chalk.green("Yes") : chalk.red("No"),
|
|
152
|
+
toolset.tags && toolset.tags.length > 0 ? toolset.tags.join(", ") : "-",
|
|
153
|
+
toolset.version
|
|
154
|
+
])
|
|
155
|
+
);
|
|
156
|
+
printBlank();
|
|
157
|
+
printInfo(`Total: ${total} toolsets (Page ${pagination.page} of ${pagination.totalPages})`);
|
|
158
|
+
} catch (error) {
|
|
159
|
+
spinner.fail("Failed to fetch toolsets");
|
|
160
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
161
|
+
printError("Error", message);
|
|
162
|
+
process.exitCode = 1;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
async function handleToolsetsGet(id) {
|
|
166
|
+
const sdk = createSdk();
|
|
167
|
+
if (!sdk) return;
|
|
168
|
+
const spinner = ora("Fetching toolset...").start();
|
|
169
|
+
try {
|
|
170
|
+
const response = await sdk.toolsets.get(id);
|
|
171
|
+
spinner.stop();
|
|
172
|
+
if (!response.success || !response.data) {
|
|
173
|
+
printError("Failed to fetch toolset", response.message);
|
|
174
|
+
process.exitCode = 1;
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const toolset = response.data;
|
|
178
|
+
if (isJsonOutput()) {
|
|
179
|
+
printJson(toolset);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
printBlank();
|
|
183
|
+
printToolsetDetails(toolset);
|
|
184
|
+
} catch (error) {
|
|
185
|
+
spinner.fail("Failed to fetch toolset");
|
|
186
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
187
|
+
printError("Error", message);
|
|
188
|
+
process.exitCode = 1;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
async function handleToolsetsCreate(options) {
|
|
192
|
+
if (options.template) {
|
|
193
|
+
console.log(JSON.stringify(TOOLSET_TEMPLATE, null, 2));
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (!options.file) {
|
|
197
|
+
printError("Missing required option", "Use '-f, --file <path>' or '--template' for sample JSON");
|
|
198
|
+
printInfo("Run 'chanl toolsets create --help' for usage");
|
|
199
|
+
process.exitCode = 1;
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const sdk = createSdk();
|
|
203
|
+
if (!sdk) return;
|
|
204
|
+
let input;
|
|
205
|
+
try {
|
|
206
|
+
const content = await readFile(options.file, "utf-8");
|
|
207
|
+
input = JSON.parse(content);
|
|
208
|
+
} catch (error) {
|
|
209
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
210
|
+
printError("Failed to read file", message);
|
|
211
|
+
process.exitCode = 1;
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
const spinner = ora("Creating toolset...").start();
|
|
215
|
+
try {
|
|
216
|
+
const response = await sdk.toolsets.create(input);
|
|
217
|
+
spinner.stop();
|
|
218
|
+
if (!response.success || !response.data) {
|
|
219
|
+
printError("Failed to create toolset", response.message);
|
|
220
|
+
process.exitCode = 1;
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
const toolset = response.data;
|
|
224
|
+
if (isJsonOutput()) {
|
|
225
|
+
printJson({ success: true, toolset });
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
printSuccess(`Created toolset: ${toolset.name} (${toolset.id})`);
|
|
229
|
+
} catch (error) {
|
|
230
|
+
spinner.fail("Failed to create toolset");
|
|
231
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
232
|
+
printError("Error", message);
|
|
233
|
+
process.exitCode = 1;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
async function handleToolsetsUpdate(id, options) {
|
|
237
|
+
const sdk = createSdk();
|
|
238
|
+
if (!sdk) return;
|
|
239
|
+
let input;
|
|
240
|
+
try {
|
|
241
|
+
const content = await readFile(options.file, "utf-8");
|
|
242
|
+
input = JSON.parse(content);
|
|
243
|
+
} catch (error) {
|
|
244
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
245
|
+
printError("Failed to read file", message);
|
|
246
|
+
process.exitCode = 1;
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
const spinner = ora("Updating toolset...").start();
|
|
250
|
+
try {
|
|
251
|
+
const response = await sdk.toolsets.update(id, input);
|
|
252
|
+
spinner.stop();
|
|
253
|
+
if (!response.success || !response.data) {
|
|
254
|
+
printError("Failed to update toolset", response.message);
|
|
255
|
+
process.exitCode = 1;
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
const toolset = response.data;
|
|
259
|
+
if (isJsonOutput()) {
|
|
260
|
+
printJson({ success: true, toolset });
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
printSuccess(`Updated toolset: ${toolset.name} (${toolset.id})`);
|
|
264
|
+
} catch (error) {
|
|
265
|
+
spinner.fail("Failed to update toolset");
|
|
266
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
267
|
+
printError("Error", message);
|
|
268
|
+
process.exitCode = 1;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
async function handleToolsetsDelete(id, options) {
|
|
272
|
+
const sdk = createSdk();
|
|
273
|
+
if (!sdk) return;
|
|
274
|
+
if (!options.yes) {
|
|
275
|
+
try {
|
|
276
|
+
const confirmed = await confirm({
|
|
277
|
+
message: `Are you sure you want to delete toolset '${id}'?`,
|
|
278
|
+
default: false
|
|
279
|
+
});
|
|
280
|
+
if (!confirmed) {
|
|
281
|
+
printInfo("Deletion cancelled");
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
} catch {
|
|
285
|
+
printBlank();
|
|
286
|
+
printInfo("Deletion cancelled");
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
const spinner = ora("Deleting toolset...").start();
|
|
291
|
+
try {
|
|
292
|
+
const response = await sdk.toolsets.delete(id);
|
|
293
|
+
spinner.stop();
|
|
294
|
+
if (!response.success) {
|
|
295
|
+
printError("Failed to delete toolset", response.message);
|
|
296
|
+
process.exitCode = 1;
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
if (isJsonOutput()) {
|
|
300
|
+
printJson({ success: true, deleted: true, id });
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
printSuccess(`Deleted toolset: ${id}`);
|
|
304
|
+
} catch (error) {
|
|
305
|
+
spinner.fail("Failed to delete toolset");
|
|
306
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
307
|
+
printError("Error", message);
|
|
308
|
+
process.exitCode = 1;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
async function handleToolsetsEnable(id) {
|
|
312
|
+
const sdk = createSdk();
|
|
313
|
+
if (!sdk) return;
|
|
314
|
+
const spinner = ora("Enabling toolset...").start();
|
|
315
|
+
try {
|
|
316
|
+
const response = await sdk.toolsets.enable(id);
|
|
317
|
+
spinner.stop();
|
|
318
|
+
if (!response.success || !response.data) {
|
|
319
|
+
printError("Failed to enable toolset", response.message);
|
|
320
|
+
process.exitCode = 1;
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
const toolset = response.data;
|
|
324
|
+
if (isJsonOutput()) {
|
|
325
|
+
printJson({ success: true, toolset });
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
printSuccess(`Enabled toolset: ${toolset.name} (${toolset.id})`);
|
|
329
|
+
} catch (error) {
|
|
330
|
+
spinner.fail("Failed to enable toolset");
|
|
331
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
332
|
+
printError("Error", message);
|
|
333
|
+
process.exitCode = 1;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
async function handleToolsetsDisable(id) {
|
|
337
|
+
const sdk = createSdk();
|
|
338
|
+
if (!sdk) return;
|
|
339
|
+
const spinner = ora("Disabling toolset...").start();
|
|
340
|
+
try {
|
|
341
|
+
const response = await sdk.toolsets.disable(id);
|
|
342
|
+
spinner.stop();
|
|
343
|
+
if (!response.success || !response.data) {
|
|
344
|
+
printError("Failed to disable toolset", response.message);
|
|
345
|
+
process.exitCode = 1;
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
const toolset = response.data;
|
|
349
|
+
if (isJsonOutput()) {
|
|
350
|
+
printJson({ success: true, toolset });
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
printSuccess(`Disabled toolset: ${toolset.name} (${toolset.id})`);
|
|
354
|
+
} catch (error) {
|
|
355
|
+
spinner.fail("Failed to disable toolset");
|
|
356
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
357
|
+
printError("Error", message);
|
|
358
|
+
process.exitCode = 1;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
async function handleToolsetsAddTools(id, options) {
|
|
362
|
+
const sdk = createSdk();
|
|
363
|
+
if (!sdk) return;
|
|
364
|
+
const toolIds = options.tools.split(",").map((t) => t.trim()).filter(Boolean);
|
|
365
|
+
if (toolIds.length === 0) {
|
|
366
|
+
printError("No tool IDs provided", "Provide tool IDs with --tools flag");
|
|
367
|
+
process.exitCode = 1;
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
const spinner = ora("Adding tools to toolset...").start();
|
|
371
|
+
try {
|
|
372
|
+
const response = await sdk.toolsets.manageTools(id, { add: toolIds });
|
|
373
|
+
spinner.stop();
|
|
374
|
+
if (!response.success || !response.data) {
|
|
375
|
+
printError("Failed to add tools", response.message);
|
|
376
|
+
process.exitCode = 1;
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
const toolset = response.data;
|
|
380
|
+
if (isJsonOutput()) {
|
|
381
|
+
printJson({ success: true, toolset });
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
printSuccess(`Added ${toolIds.length} tool(s) to toolset: ${toolset.name}`);
|
|
385
|
+
printInfo(`Toolset now has ${toolset.toolCount} tool(s)`);
|
|
386
|
+
} catch (error) {
|
|
387
|
+
spinner.fail("Failed to add tools");
|
|
388
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
389
|
+
printError("Error", message);
|
|
390
|
+
process.exitCode = 1;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
async function handleToolsetsRemoveTools(id, options) {
|
|
394
|
+
const sdk = createSdk();
|
|
395
|
+
if (!sdk) return;
|
|
396
|
+
const toolIds = options.tools.split(",").map((t) => t.trim()).filter(Boolean);
|
|
397
|
+
if (toolIds.length === 0) {
|
|
398
|
+
printError("No tool IDs provided", "Provide tool IDs with --tools flag");
|
|
399
|
+
process.exitCode = 1;
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
const spinner = ora("Removing tools from toolset...").start();
|
|
403
|
+
try {
|
|
404
|
+
const response = await sdk.toolsets.manageTools(id, { remove: toolIds });
|
|
405
|
+
spinner.stop();
|
|
406
|
+
if (!response.success || !response.data) {
|
|
407
|
+
printError("Failed to remove tools", response.message);
|
|
408
|
+
process.exitCode = 1;
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
const toolset = response.data;
|
|
412
|
+
if (isJsonOutput()) {
|
|
413
|
+
printJson({ success: true, toolset });
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
printSuccess(`Removed ${toolIds.length} tool(s) from toolset: ${toolset.name}`);
|
|
417
|
+
printInfo(`Toolset now has ${toolset.toolCount} tool(s)`);
|
|
418
|
+
} catch (error) {
|
|
419
|
+
spinner.fail("Failed to remove tools");
|
|
420
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
421
|
+
printError("Error", message);
|
|
422
|
+
process.exitCode = 1;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
function printToolsetDetails(toolset) {
|
|
426
|
+
printLabel("Name", toolset.name);
|
|
427
|
+
printLabel("ID", toolset.id);
|
|
428
|
+
printLabel("Description", toolset.description);
|
|
429
|
+
printLabel("Version", toolset.version);
|
|
430
|
+
printLabel("Enabled", toolset.enabled ? chalk.green("Yes") : chalk.red("No"));
|
|
431
|
+
printLabel("Public", toolset.isPublic ? chalk.green("Yes") : chalk.red("No"));
|
|
432
|
+
if (toolset.registryId) {
|
|
433
|
+
printLabel("Registry ID", toolset.registryId);
|
|
434
|
+
}
|
|
435
|
+
if (toolset.tags && toolset.tags.length > 0) {
|
|
436
|
+
printLabel("Tags", toolset.tags.join(", "));
|
|
437
|
+
}
|
|
438
|
+
printBlank();
|
|
439
|
+
printInfo(`Tools (${toolset.toolCount}):`);
|
|
440
|
+
if (toolset.tools.length > 0) {
|
|
441
|
+
for (const toolId of toolset.tools) {
|
|
442
|
+
console.log(chalk.gray(` - ${toolId}`));
|
|
443
|
+
}
|
|
444
|
+
} else {
|
|
445
|
+
console.log(chalk.gray(" No tools in this toolset"));
|
|
446
|
+
}
|
|
447
|
+
if (toolset.toolOverrides && Object.keys(toolset.toolOverrides).length > 0) {
|
|
448
|
+
printBlank();
|
|
449
|
+
printInfo("Tool Overrides:");
|
|
450
|
+
for (const [toolId, override] of Object.entries(toolset.toolOverrides)) {
|
|
451
|
+
console.log(chalk.gray(` ${toolId}:`));
|
|
452
|
+
if (override.name) console.log(chalk.gray(` name: ${override.name}`));
|
|
453
|
+
if (override.description) console.log(chalk.gray(` description: ${override.description}`));
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
printBlank();
|
|
457
|
+
printLabel("Created", formatDate(toolset.createdAt));
|
|
458
|
+
printLabel("Updated", formatDate(toolset.updatedAt));
|
|
459
|
+
printBlank();
|
|
460
|
+
}
|
|
461
|
+
export {
|
|
462
|
+
createToolsetsCommand
|
|
463
|
+
};
|
|
464
|
+
//# sourceMappingURL=toolsets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/commands/toolsets.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { readFile } from 'fs/promises';\nimport { confirm } from '@inquirer/prompts';\nimport ora from 'ora';\nimport chalk from 'chalk';\nimport type { Toolset, CreateToolsetInput, UpdateToolsetInput } from '@chanl-ai/sdk';\nimport { createSdk } from '../utils/sdk-factory.js';\nimport {\n printSuccess,\n printError,\n printInfo,\n printLabel,\n printBlank,\n printSimpleTable,\n isJsonOutput,\n printJson,\n formatDate,\n} from '../utils/output.js';\n\n// Sample toolset template\nconst TOOLSET_TEMPLATE = {\n name: 'my-toolset',\n description: 'A curated collection of tools for a specific use case',\n tools: ['tool-id-1', 'tool-id-2'],\n toolOverrides: {\n 'tool-id-1': {\n name: 'custom_name',\n description: 'Override description for this tool',\n },\n },\n isEnabled: true,\n tags: ['production', 'customer-facing'],\n};\n\n/**\n * Create the toolsets command group\n */\nexport function createToolsetsCommand(): Command {\n const toolsets = new Command('toolsets')\n .description('Manage MCP toolsets (collections of tools)')\n .addHelpText(\n 'after',\n `\nWhat are Toolsets?\n Toolsets group multiple tools together and allow you to customize how they\n appear to AI agents. Use toolsets to:\n - Create curated tool collections for specific use cases\n - Override tool names/descriptions per context\n - Enable/disable entire groups of tools at once\n\nExamples:\n $ chanl toolsets list # List all toolsets\n $ chanl toolsets create -f toolset.json # Create new toolset\n $ chanl toolsets add-tools <id> -t id1,id2 # Add tools to toolset`\n );\n\n // toolsets list\n toolsets\n .command('list')\n .description('List all toolsets in the workspace')\n .option('-e, --enabled', 'Show only enabled toolsets')\n .option('-d, --disabled', 'Show only disabled toolsets')\n .option('--tag <tag>', 'Filter by tag')\n .option('-s, --search <search>', 'Search by name or description')\n .option('-l, --limit <number>', 'Items per page (default: 20)', '20')\n .option('-p, --page <number>', 'Page number (default: 1)', '1')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl toolsets list # List all\n $ chanl toolsets list --enabled # Only enabled\n $ chanl toolsets list --search \"api\" # Search by name`\n )\n .action(handleToolsetsList);\n\n // toolsets get <id>\n toolsets\n .command('get <id>')\n .description('Get detailed info about a toolset')\n .addHelpText(\n 'after',\n `\nExample:\n $ chanl toolsets get 507f1f77bcf86cd799439011`\n )\n .action(handleToolsetsGet);\n\n // toolsets create\n toolsets\n .command('create')\n .description('Create a new toolset from JSON file')\n .option('-f, --file <path>', 'Path to JSON file with toolset definition')\n .option('--template', 'Output a sample JSON template')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl toolsets create --template > my-toolset.json # Generate template\n $ chanl toolsets create -f my-toolset.json # Create from file\n\nRequired JSON fields:\n name Toolset name\n description What this toolset is for\n tools Array of tool IDs to include\n\nOptional fields:\n toolOverrides Override name/description per tool\n isEnabled Enable immediately (default: true)\n tags Array of category tags`\n )\n .action(handleToolsetsCreate);\n\n // toolsets update <id>\n toolsets\n .command('update <id>')\n .description('Update a toolset from JSON file')\n .requiredOption('-f, --file <path>', 'Path to JSON file with updates')\n .addHelpText(\n 'after',\n `\nExample:\n $ chanl toolsets update 507f1f77bcf86cd799439011 -f updates.json`\n )\n .action(handleToolsetsUpdate);\n\n // toolsets delete <id>\n toolsets\n .command('delete <id>')\n .description('Delete a toolset permanently')\n .option('-y, --yes', 'Skip confirmation prompt')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl toolsets delete 507f1f77bcf86cd799439011 # With confirmation\n $ chanl toolsets delete 507f1f77bcf86cd799439011 -y # Skip confirmation`\n )\n .action(handleToolsetsDelete);\n\n // toolsets enable <id>\n toolsets\n .command('enable <id>')\n .description('Enable a toolset (makes its tools available)')\n .action(handleToolsetsEnable);\n\n // toolsets disable <id>\n toolsets\n .command('disable <id>')\n .description('Disable a toolset (hides its tools)')\n .action(handleToolsetsDisable);\n\n // toolsets add-tools <id>\n toolsets\n .command('add-tools <id>')\n .description('Add tools to an existing toolset')\n .requiredOption('-t, --tools <ids>', 'Comma-separated tool IDs')\n .addHelpText(\n 'after',\n `\nExample:\n $ chanl toolsets add-tools 507f1f77bcf86cd799439011 -t tool1,tool2,tool3`\n )\n .action(handleToolsetsAddTools);\n\n // toolsets remove-tools <id>\n toolsets\n .command('remove-tools <id>')\n .description('Remove tools from a toolset')\n .requiredOption('-t, --tools <ids>', 'Comma-separated tool IDs')\n .addHelpText(\n 'after',\n `\nExample:\n $ chanl toolsets remove-tools 507f1f77bcf86cd799439011 -t tool1,tool2`\n )\n .action(handleToolsetsRemoveTools);\n\n return toolsets;\n}\n\n/**\n * Handle toolsets list command\n */\nasync function handleToolsetsList(options: {\n enabled?: boolean;\n disabled?: boolean;\n tag?: string;\n search?: string;\n limit: string;\n page: string;\n}): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching toolsets...').start();\n\n try {\n // Determine enabled filter\n let enabled: boolean | undefined;\n if (options.enabled) enabled = true;\n else if (options.disabled) enabled = false;\n\n const response = await sdk.toolsets.list({\n enabled,\n tag: options.tag,\n search: options.search,\n limit: parseInt(options.limit, 10),\n page: parseInt(options.page, 10),\n });\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch toolsets', response.message);\n process.exitCode = 1;\n return;\n }\n\n const toolsets = response.data.data;\n const total = response.data.total;\n const pagination = response.data.pagination || {\n page: parseInt(options.page, 10),\n limit: parseInt(options.limit, 10),\n totalPages: Math.ceil(total / parseInt(options.limit, 10)),\n hasNext: false,\n hasPrev: false,\n };\n\n if (isJsonOutput()) {\n printJson({ toolsets, total, pagination });\n return;\n }\n\n if (toolsets.length === 0) {\n printInfo('No toolsets found');\n return;\n }\n\n printBlank();\n printSimpleTable(\n ['Name', 'Tool Count', 'Enabled', 'Tags', 'Version'],\n toolsets.map((toolset) => [\n toolset.name,\n toolset.toolCount.toString(),\n toolset.enabled ? chalk.green('Yes') : chalk.red('No'),\n toolset.tags && toolset.tags.length > 0 ? toolset.tags.join(', ') : '-',\n toolset.version,\n ])\n );\n\n printBlank();\n printInfo(`Total: ${total} toolsets (Page ${pagination.page} of ${pagination.totalPages})`);\n } catch (error) {\n spinner.fail('Failed to fetch toolsets');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle toolsets get command\n */\nasync function handleToolsetsGet(id: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching toolset...').start();\n\n try {\n const response = await sdk.toolsets.get(id);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch toolset', response.message);\n process.exitCode = 1;\n return;\n }\n\n // API returns toolset directly in data (not nested as { toolset: ... })\n const toolset = response.data;\n\n if (isJsonOutput()) {\n printJson(toolset);\n return;\n }\n\n printBlank();\n printToolsetDetails(toolset);\n } catch (error) {\n spinner.fail('Failed to fetch toolset');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle toolsets create command\n */\nasync function handleToolsetsCreate(options: { file?: string; template?: boolean }): Promise<void> {\n // Handle --template flag: output sample JSON and exit\n if (options.template) {\n console.log(JSON.stringify(TOOLSET_TEMPLATE, null, 2));\n return;\n }\n\n // Require --file if not using --template\n if (!options.file) {\n printError('Missing required option', \"Use '-f, --file <path>' or '--template' for sample JSON\");\n printInfo(\"Run 'chanl toolsets create --help' for usage\");\n process.exitCode = 1;\n return;\n }\n\n const sdk = createSdk();\n if (!sdk) return;\n\n // Read and parse JSON file\n let input: Record<string, unknown>;\n try {\n const content = await readFile(options.file, 'utf-8');\n input = JSON.parse(content);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Failed to read file', message);\n process.exitCode = 1;\n return;\n }\n\n const spinner = ora('Creating toolset...').start();\n\n try {\n const response = await sdk.toolsets.create(input as unknown as CreateToolsetInput);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to create toolset', response.message);\n process.exitCode = 1;\n return;\n }\n\n const toolset = response.data;\n\n if (isJsonOutput()) {\n printJson({ success: true, toolset });\n return;\n }\n\n printSuccess(`Created toolset: ${toolset.name} (${toolset.id})`);\n } catch (error) {\n spinner.fail('Failed to create toolset');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle toolsets update command\n */\nasync function handleToolsetsUpdate(id: string, options: { file: string }): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n // Read and parse JSON file\n let input: Record<string, unknown>;\n try {\n const content = await readFile(options.file, 'utf-8');\n input = JSON.parse(content);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Failed to read file', message);\n process.exitCode = 1;\n return;\n }\n\n const spinner = ora('Updating toolset...').start();\n\n try {\n const response = await sdk.toolsets.update(id, input as unknown as UpdateToolsetInput);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to update toolset', response.message);\n process.exitCode = 1;\n return;\n }\n\n const toolset = response.data;\n\n if (isJsonOutput()) {\n printJson({ success: true, toolset });\n return;\n }\n\n printSuccess(`Updated toolset: ${toolset.name} (${toolset.id})`);\n } catch (error) {\n spinner.fail('Failed to update toolset');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle toolsets delete command\n */\nasync function handleToolsetsDelete(id: string, options: { yes?: boolean }): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n // Confirm deletion unless --yes flag is provided\n if (!options.yes) {\n try {\n const confirmed = await confirm({\n message: `Are you sure you want to delete toolset '${id}'?`,\n default: false,\n });\n\n if (!confirmed) {\n printInfo('Deletion cancelled');\n return;\n }\n } catch {\n // User cancelled (Ctrl+C)\n printBlank();\n printInfo('Deletion cancelled');\n return;\n }\n }\n\n const spinner = ora('Deleting toolset...').start();\n\n try {\n const response = await sdk.toolsets.delete(id);\n\n spinner.stop();\n\n if (!response.success) {\n printError('Failed to delete toolset', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson({ success: true, deleted: true, id });\n return;\n }\n\n printSuccess(`Deleted toolset: ${id}`);\n } catch (error) {\n spinner.fail('Failed to delete toolset');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle toolsets enable command\n */\nasync function handleToolsetsEnable(id: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Enabling toolset...').start();\n\n try {\n const response = await sdk.toolsets.enable(id);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to enable toolset', response.message);\n process.exitCode = 1;\n return;\n }\n\n const toolset = response.data;\n\n if (isJsonOutput()) {\n printJson({ success: true, toolset });\n return;\n }\n\n printSuccess(`Enabled toolset: ${toolset.name} (${toolset.id})`);\n } catch (error) {\n spinner.fail('Failed to enable toolset');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle toolsets disable command\n */\nasync function handleToolsetsDisable(id: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Disabling toolset...').start();\n\n try {\n const response = await sdk.toolsets.disable(id);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to disable toolset', response.message);\n process.exitCode = 1;\n return;\n }\n\n const toolset = response.data;\n\n if (isJsonOutput()) {\n printJson({ success: true, toolset });\n return;\n }\n\n printSuccess(`Disabled toolset: ${toolset.name} (${toolset.id})`);\n } catch (error) {\n spinner.fail('Failed to disable toolset');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle toolsets add-tools command\n */\nasync function handleToolsetsAddTools(id: string, options: { tools: string }): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const toolIds = options.tools.split(',').map((t) => t.trim()).filter(Boolean);\n\n if (toolIds.length === 0) {\n printError('No tool IDs provided', 'Provide tool IDs with --tools flag');\n process.exitCode = 1;\n return;\n }\n\n const spinner = ora('Adding tools to toolset...').start();\n\n try {\n const response = await sdk.toolsets.manageTools(id, { add: toolIds });\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to add tools', response.message);\n process.exitCode = 1;\n return;\n }\n\n const toolset = response.data;\n\n if (isJsonOutput()) {\n printJson({ success: true, toolset });\n return;\n }\n\n printSuccess(`Added ${toolIds.length} tool(s) to toolset: ${toolset.name}`);\n printInfo(`Toolset now has ${toolset.toolCount} tool(s)`);\n } catch (error) {\n spinner.fail('Failed to add tools');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle toolsets remove-tools command\n */\nasync function handleToolsetsRemoveTools(id: string, options: { tools: string }): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const toolIds = options.tools.split(',').map((t) => t.trim()).filter(Boolean);\n\n if (toolIds.length === 0) {\n printError('No tool IDs provided', 'Provide tool IDs with --tools flag');\n process.exitCode = 1;\n return;\n }\n\n const spinner = ora('Removing tools from toolset...').start();\n\n try {\n const response = await sdk.toolsets.manageTools(id, { remove: toolIds });\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to remove tools', response.message);\n process.exitCode = 1;\n return;\n }\n\n const toolset = response.data;\n\n if (isJsonOutput()) {\n printJson({ success: true, toolset });\n return;\n }\n\n printSuccess(`Removed ${toolIds.length} tool(s) from toolset: ${toolset.name}`);\n printInfo(`Toolset now has ${toolset.toolCount} tool(s)`);\n } catch (error) {\n spinner.fail('Failed to remove tools');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Print toolset details in formatted output\n */\nfunction printToolsetDetails(toolset: Toolset): void {\n printLabel('Name', toolset.name);\n printLabel('ID', toolset.id);\n printLabel('Description', toolset.description);\n printLabel('Version', toolset.version);\n printLabel('Enabled', toolset.enabled ? chalk.green('Yes') : chalk.red('No'));\n printLabel('Public', toolset.isPublic ? chalk.green('Yes') : chalk.red('No'));\n\n if (toolset.registryId) {\n printLabel('Registry ID', toolset.registryId);\n }\n\n if (toolset.tags && toolset.tags.length > 0) {\n printLabel('Tags', toolset.tags.join(', '));\n }\n\n printBlank();\n printInfo(`Tools (${toolset.toolCount}):`);\n if (toolset.tools.length > 0) {\n for (const toolId of toolset.tools) {\n console.log(chalk.gray(` - ${toolId}`));\n }\n } else {\n console.log(chalk.gray(' No tools in this toolset'));\n }\n\n if (toolset.toolOverrides && Object.keys(toolset.toolOverrides).length > 0) {\n printBlank();\n printInfo('Tool Overrides:');\n for (const [toolId, override] of Object.entries(toolset.toolOverrides)) {\n console.log(chalk.gray(` ${toolId}:`));\n if (override.name) console.log(chalk.gray(` name: ${override.name}`));\n if (override.description) console.log(chalk.gray(` description: ${override.description}`));\n }\n }\n\n printBlank();\n printLabel('Created', formatDate(toolset.createdAt));\n printLabel('Updated', formatDate(toolset.updatedAt));\n printBlank();\n}\n"],"mappings":"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","names":[]}
|