@chanl/cli 2.0.3 → 3.0.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.
Files changed (67) hide show
  1. package/dist/__tests__/agents.test.js +574 -0
  2. package/dist/__tests__/agents.test.js.map +1 -0
  3. package/dist/__tests__/auth.test.d.ts +2 -0
  4. package/dist/__tests__/auth.test.js +87 -0
  5. package/dist/__tests__/auth.test.js.map +1 -0
  6. package/dist/__tests__/calls.test.d.ts +2 -0
  7. package/dist/__tests__/calls.test.js +115 -0
  8. package/dist/__tests__/calls.test.js.map +1 -0
  9. package/dist/__tests__/chat.test.d.ts +2 -0
  10. package/dist/__tests__/chat.test.js +357 -0
  11. package/dist/__tests__/chat.test.js.map +1 -0
  12. package/dist/__tests__/cli-base.test.d.ts +2 -0
  13. package/dist/__tests__/cli-base.test.js +87 -0
  14. package/dist/__tests__/cli-base.test.js.map +1 -0
  15. package/dist/__tests__/cli-missing.test.d.ts +2 -0
  16. package/dist/__tests__/cli-missing.test.js +546 -0
  17. package/dist/__tests__/cli-missing.test.js.map +1 -0
  18. package/dist/__tests__/helpers.d.ts +234 -0
  19. package/dist/__tests__/helpers.js +314 -0
  20. package/dist/__tests__/helpers.js.map +1 -0
  21. package/dist/__tests__/mcp.test.d.ts +2 -0
  22. package/dist/__tests__/mcp.test.js +470 -0
  23. package/dist/__tests__/mcp.test.js.map +1 -0
  24. package/dist/__tests__/prompts.test.d.ts +2 -0
  25. package/dist/__tests__/prompts.test.js +227 -0
  26. package/dist/__tests__/prompts.test.js.map +1 -0
  27. package/dist/__tests__/scenarios.test.d.ts +2 -0
  28. package/dist/__tests__/scenarios.test.js +270 -0
  29. package/dist/__tests__/scenarios.test.js.map +1 -0
  30. package/dist/__tests__/tools.test.d.ts +2 -0
  31. package/dist/__tests__/tools.test.js +331 -0
  32. package/dist/__tests__/tools.test.js.map +1 -0
  33. package/dist/__tests__/toolsets.test.d.ts +2 -0
  34. package/dist/__tests__/toolsets.test.js +196 -0
  35. package/dist/__tests__/toolsets.test.js.map +1 -0
  36. package/dist/__tests__/workspaces.test.d.ts +2 -0
  37. package/dist/__tests__/workspaces.test.js +155 -0
  38. package/dist/__tests__/workspaces.test.js.map +1 -0
  39. package/dist/commands/agents.js +103 -13
  40. package/dist/commands/agents.js.map +1 -1
  41. package/dist/commands/chat.js +2 -2
  42. package/dist/commands/chat.js.map +1 -1
  43. package/dist/commands/config.js +24 -2
  44. package/dist/commands/config.js.map +1 -1
  45. package/dist/commands/mcp.js +1 -1
  46. package/dist/commands/mcp.js.map +1 -1
  47. package/dist/commands/memory.js +137 -4
  48. package/dist/commands/memory.js.map +1 -1
  49. package/dist/commands/personas.js +3 -3
  50. package/dist/commands/personas.js.map +1 -1
  51. package/dist/commands/prompts.js +148 -1
  52. package/dist/commands/prompts.js.map +1 -1
  53. package/dist/commands/scenarios.js +2 -2
  54. package/dist/commands/scenarios.js.map +1 -1
  55. package/dist/commands/scorecards.js +3 -3
  56. package/dist/commands/scorecards.js.map +1 -1
  57. package/dist/commands/tools.js +5 -5
  58. package/dist/commands/tools.js.map +1 -1
  59. package/dist/utils/config-store.d.ts +8 -0
  60. package/dist/utils/config-store.js +18 -1
  61. package/dist/utils/config-store.js.map +1 -1
  62. package/dist/utils/sdk-factory.js +15 -3
  63. package/dist/utils/sdk-factory.js.map +1 -1
  64. package/package.json +4 -4
  65. package/dist/__tests__/cli.test.js +0 -2313
  66. package/dist/__tests__/cli.test.js.map +0 -1
  67. /package/dist/__tests__/{cli.test.d.ts → agents.test.d.ts} +0 -0
@@ -1 +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/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":[]}
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/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":[]}
@@ -6,6 +6,12 @@ interface ChanlCliConfig {
6
6
  jwtToken?: string;
7
7
  refreshToken?: string;
8
8
  baseUrl: string;
9
+ /** Alias for baseUrl (e.g. local eval server URL). */
10
+ server?: string;
11
+ /** `local` rewrites `/api/v1` paths for OSS-style servers. */
12
+ deployment?: 'local' | 'cloud';
13
+ /** Override API prefix; use empty string for flat `/scenarios` routes. */
14
+ apiPrefix?: string;
9
15
  workspaceId?: string;
10
16
  appUrl?: string;
11
17
  defaultFormat: 'table' | 'json';
@@ -69,6 +75,8 @@ declare class ConfigStore {
69
75
  * Priority: CHANL_BASE_URL env var > config file > default
70
76
  */
71
77
  getBaseUrl(): string;
78
+ getDeployment(): 'local' | 'cloud' | undefined;
79
+ getApiPrefix(): string | undefined;
72
80
  /**
73
81
  * Get the app URL for browser-based flows (e.g., CLI auth)
74
82
  * Priority: CHANL_APP_URL env var > config file > derived from baseUrl
@@ -29,6 +29,9 @@ class ConfigStore {
29
29
  jwtToken: { type: "string" },
30
30
  refreshToken: { type: "string" },
31
31
  baseUrl: { type: "string", default: DEFAULT_CONFIG.baseUrl },
32
+ server: { type: "string" },
33
+ deployment: { type: "string" },
34
+ apiPrefix: { type: "string" },
32
35
  workspaceId: { type: "string" },
33
36
  appUrl: { type: "string" },
34
37
  defaultFormat: {
@@ -106,7 +109,21 @@ class ConfigStore {
106
109
  * Priority: CHANL_BASE_URL env var > config file > default
107
110
  */
108
111
  getBaseUrl() {
109
- return process.env["CHANL_BASE_URL"] || this.get("baseUrl");
112
+ return process.env["CHANL_BASE_URL"] || this.get("server") || this.get("baseUrl");
113
+ }
114
+ getDeployment() {
115
+ const d = process.env["CHANL_DEPLOYMENT"] || this.get("deployment");
116
+ if (d === "local" || d === "cloud") return d;
117
+ const base = this.getBaseUrl();
118
+ if (base.includes("localhost:18005") || base.includes("127.0.0.1:18005")) {
119
+ return "local";
120
+ }
121
+ return void 0;
122
+ }
123
+ getApiPrefix() {
124
+ const fromEnv = process.env["CHANL_API_PREFIX"];
125
+ if (fromEnv !== void 0) return fromEnv;
126
+ return this.get("apiPrefix");
110
127
  }
111
128
  /**
112
129
  * Get the app URL for browser-based flows (e.g., CLI auth)
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/config-store.ts"],"sourcesContent":["import Conf from 'conf';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { existsSync, mkdirSync } from 'node:fs';\n\n/**\n * CLI configuration schema\n */\nexport interface ChanlCliConfig {\n apiKey?: string;\n jwtToken?: string;\n refreshToken?: string;\n baseUrl: string;\n workspaceId?: string;\n appUrl?: string;\n defaultFormat: 'table' | 'json';\n}\n\n/**\n * Default configuration values\n */\nconst DEFAULT_CONFIG: ChanlCliConfig = {\n baseUrl: 'https://platform.chanl.ai',\n defaultFormat: 'table',\n};\n\n/**\n * Get the Chanl config directory path\n * Uses ~/.chanl/ for storing configuration\n */\nexport function getConfigDir(): string {\n return join(homedir(), '.chanl');\n}\n\n/**\n * Ensure the config directory exists\n */\nfunction ensureConfigDir(): void {\n const configDir = getConfigDir();\n if (!existsSync(configDir)) {\n mkdirSync(configDir, { recursive: true });\n }\n}\n\n/**\n * Config store using Conf library\n * Stores configuration in ~/.chanl/config.json\n */\nclass ConfigStore {\n private store: Conf<ChanlCliConfig>;\n\n constructor() {\n ensureConfigDir();\n this.store = new Conf<ChanlCliConfig>({\n projectName: 'chanl',\n cwd: getConfigDir(),\n configName: 'config',\n defaults: DEFAULT_CONFIG,\n schema: {\n apiKey: { type: 'string' },\n jwtToken: { type: 'string' },\n refreshToken: { type: 'string' },\n baseUrl: { type: 'string', default: DEFAULT_CONFIG.baseUrl },\n workspaceId: { type: 'string' },\n appUrl: { type: 'string' },\n defaultFormat: {\n type: 'string',\n enum: ['table', 'json'],\n default: 'table',\n },\n },\n });\n }\n\n /**\n * Get a configuration value\n * Supports dot notation for nested values\n */\n get<K extends keyof ChanlCliConfig>(key: K): ChanlCliConfig[K] {\n return this.store.get(key);\n }\n\n /**\n * Set a configuration value\n */\n set<K extends keyof ChanlCliConfig>(key: K, value: ChanlCliConfig[K]): void {\n this.store.set(key, value);\n }\n\n /**\n * Delete a configuration value\n */\n delete(key: keyof ChanlCliConfig): void {\n this.store.delete(key);\n }\n\n /**\n * Get all configuration values\n */\n getAll(): ChanlCliConfig {\n return this.store.store;\n }\n\n /**\n * Check if a key exists in the configuration\n */\n has(key: keyof ChanlCliConfig): boolean {\n return this.store.has(key);\n }\n\n /**\n * Clear all configuration\n */\n clear(): void {\n this.store.clear();\n }\n\n /**\n * Get the path to the config file\n */\n getPath(): string {\n return this.store.path;\n }\n\n /**\n * Get API key with environment variable fallback\n * Priority: CHANL_API_KEY env var > config file\n */\n getApiKey(): string | undefined {\n return process.env['CHANL_API_KEY'] || this.get('apiKey');\n }\n\n /**\n * Get JWT token from config\n */\n getJwtToken(): string | undefined {\n return this.get('jwtToken');\n }\n\n /**\n * Get refresh token from config\n */\n getRefreshToken(): string | undefined {\n return this.get('refreshToken');\n }\n\n /**\n * Get base URL with environment variable fallback\n * Priority: CHANL_BASE_URL env var > config file > default\n */\n getBaseUrl(): string {\n return process.env['CHANL_BASE_URL'] || this.get('baseUrl');\n }\n\n /**\n * Get the app URL for browser-based flows (e.g., CLI auth)\n * Priority: CHANL_APP_URL env var > config file > derived from baseUrl\n */\n getAppUrl(): string {\n if (process.env['CHANL_APP_URL']) return process.env['CHANL_APP_URL'];\n const stored = this.get('appUrl');\n if (stored) return stored;\n\n // Derive from baseUrl — localhost auto-maps to local frontend\n const baseUrl = this.getBaseUrl();\n if (baseUrl.includes('localhost')) return 'http://localhost:3001';\n return 'https://app.chanl.ai';\n }\n\n /**\n * Get workspace ID with environment variable fallback\n * Priority: CHANL_WORKSPACE_ID env var > config file\n */\n getWorkspaceId(): string | undefined {\n return process.env['CHANL_WORKSPACE_ID'] || this.get('workspaceId');\n }\n\n /**\n * Check if user is authenticated (has API key or JWT token)\n */\n isAuthenticated(): boolean {\n return !!(this.getApiKey() || this.getJwtToken());\n }\n\n /**\n * Get the auth method in use\n */\n getAuthMethod(): 'api-key' | 'jwt' | null {\n if (this.getApiKey()) return 'api-key';\n if (this.getJwtToken()) return 'jwt';\n return null;\n }\n\n /**\n * Set API key in config\n */\n setApiKey(apiKey: string): void {\n this.set('apiKey', apiKey);\n }\n\n /**\n * Set JWT tokens in config (from browser login)\n */\n setJwtAuth(jwtToken: string, refreshToken: string): void {\n this.set('jwtToken', jwtToken);\n this.set('refreshToken', refreshToken);\n // Clear API key if switching to JWT auth\n this.delete('apiKey');\n }\n\n /**\n * Remove all auth credentials from config (logout)\n */\n clearAuth(): void {\n this.delete('apiKey');\n this.delete('jwtToken');\n this.delete('refreshToken');\n }\n\n /**\n * Remove API key from config (logout)\n */\n removeApiKey(): void {\n this.delete('apiKey');\n }\n\n /**\n * Set workspace ID in config\n */\n setWorkspaceId(workspaceId: string): void {\n this.set('workspaceId', workspaceId);\n }\n\n /**\n * Set base URL in config\n */\n setBaseUrl(baseUrl: string): void {\n this.set('baseUrl', baseUrl);\n }\n}\n\n// Export singleton instance\nexport const configStore = new ConfigStore();\n\n// Export class for testing purposes\nexport { ConfigStore };\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/utils/config-store.ts"],"sourcesContent":["import Conf from 'conf';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { existsSync, mkdirSync } from 'node:fs';\n\n/**\n * CLI configuration schema\n */\nexport interface ChanlCliConfig {\n apiKey?: string;\n jwtToken?: string;\n refreshToken?: string;\n baseUrl: string;\n /** Alias for baseUrl (e.g. local eval server URL). */\n server?: string;\n /** `local` rewrites `/api/v1` paths for OSS-style servers. */\n deployment?: 'local' | 'cloud';\n /** Override API prefix; use empty string for flat `/scenarios` routes. */\n apiPrefix?: string;\n workspaceId?: string;\n appUrl?: string;\n defaultFormat: 'table' | 'json';\n}\n\n/**\n * Default configuration values\n */\nconst DEFAULT_CONFIG: ChanlCliConfig = {\n baseUrl: 'https://platform.chanl.ai',\n defaultFormat: 'table',\n};\n\n/**\n * Get the Chanl config directory path\n * Uses ~/.chanl/ for storing configuration\n */\nexport function getConfigDir(): string {\n return join(homedir(), '.chanl');\n}\n\n/**\n * Ensure the config directory exists\n */\nfunction ensureConfigDir(): void {\n const configDir = getConfigDir();\n if (!existsSync(configDir)) {\n mkdirSync(configDir, { recursive: true });\n }\n}\n\n/**\n * Config store using Conf library\n * Stores configuration in ~/.chanl/config.json\n */\nclass ConfigStore {\n private store: Conf<ChanlCliConfig>;\n\n constructor() {\n ensureConfigDir();\n this.store = new Conf<ChanlCliConfig>({\n projectName: 'chanl',\n cwd: getConfigDir(),\n configName: 'config',\n defaults: DEFAULT_CONFIG,\n schema: {\n apiKey: { type: 'string' },\n jwtToken: { type: 'string' },\n refreshToken: { type: 'string' },\n baseUrl: { type: 'string', default: DEFAULT_CONFIG.baseUrl },\n server: { type: 'string' },\n deployment: { type: 'string' },\n apiPrefix: { type: 'string' },\n workspaceId: { type: 'string' },\n appUrl: { type: 'string' },\n defaultFormat: {\n type: 'string',\n enum: ['table', 'json'],\n default: 'table',\n },\n },\n });\n }\n\n /**\n * Get a configuration value\n * Supports dot notation for nested values\n */\n get<K extends keyof ChanlCliConfig>(key: K): ChanlCliConfig[K] {\n return this.store.get(key);\n }\n\n /**\n * Set a configuration value\n */\n set<K extends keyof ChanlCliConfig>(key: K, value: ChanlCliConfig[K]): void {\n this.store.set(key, value);\n }\n\n /**\n * Delete a configuration value\n */\n delete(key: keyof ChanlCliConfig): void {\n this.store.delete(key);\n }\n\n /**\n * Get all configuration values\n */\n getAll(): ChanlCliConfig {\n return this.store.store;\n }\n\n /**\n * Check if a key exists in the configuration\n */\n has(key: keyof ChanlCliConfig): boolean {\n return this.store.has(key);\n }\n\n /**\n * Clear all configuration\n */\n clear(): void {\n this.store.clear();\n }\n\n /**\n * Get the path to the config file\n */\n getPath(): string {\n return this.store.path;\n }\n\n /**\n * Get API key with environment variable fallback\n * Priority: CHANL_API_KEY env var > config file\n */\n getApiKey(): string | undefined {\n return process.env['CHANL_API_KEY'] || this.get('apiKey');\n }\n\n /**\n * Get JWT token from config\n */\n getJwtToken(): string | undefined {\n return this.get('jwtToken');\n }\n\n /**\n * Get refresh token from config\n */\n getRefreshToken(): string | undefined {\n return this.get('refreshToken');\n }\n\n /**\n * Get base URL with environment variable fallback\n * Priority: CHANL_BASE_URL env var > config file > default\n */\n getBaseUrl(): string {\n return (\n process.env['CHANL_BASE_URL'] ||\n this.get('server') ||\n this.get('baseUrl')\n );\n }\n\n getDeployment(): 'local' | 'cloud' | undefined {\n const d = process.env['CHANL_DEPLOYMENT'] || this.get('deployment');\n if (d === 'local' || d === 'cloud') return d;\n const base = this.getBaseUrl();\n if (\n base.includes('localhost:18005') ||\n base.includes('127.0.0.1:18005')\n ) {\n return 'local';\n }\n return undefined;\n }\n\n getApiPrefix(): string | undefined {\n const fromEnv = process.env['CHANL_API_PREFIX'];\n if (fromEnv !== undefined) return fromEnv;\n return this.get('apiPrefix') as string | undefined;\n }\n\n /**\n * Get the app URL for browser-based flows (e.g., CLI auth)\n * Priority: CHANL_APP_URL env var > config file > derived from baseUrl\n */\n getAppUrl(): string {\n if (process.env['CHANL_APP_URL']) return process.env['CHANL_APP_URL'];\n const stored = this.get('appUrl');\n if (stored) return stored;\n\n // Derive from baseUrl — localhost auto-maps to local frontend\n const baseUrl = this.getBaseUrl();\n if (baseUrl.includes('localhost')) return 'http://localhost:3001';\n return 'https://app.chanl.ai';\n }\n\n /**\n * Get workspace ID with environment variable fallback\n * Priority: CHANL_WORKSPACE_ID env var > config file\n */\n getWorkspaceId(): string | undefined {\n return process.env['CHANL_WORKSPACE_ID'] || this.get('workspaceId');\n }\n\n /**\n * Check if user is authenticated (has API key or JWT token)\n */\n isAuthenticated(): boolean {\n return !!(this.getApiKey() || this.getJwtToken());\n }\n\n /**\n * Get the auth method in use\n */\n getAuthMethod(): 'api-key' | 'jwt' | null {\n if (this.getApiKey()) return 'api-key';\n if (this.getJwtToken()) return 'jwt';\n return null;\n }\n\n /**\n * Set API key in config\n */\n setApiKey(apiKey: string): void {\n this.set('apiKey', apiKey);\n }\n\n /**\n * Set JWT tokens in config (from browser login)\n */\n setJwtAuth(jwtToken: string, refreshToken: string): void {\n this.set('jwtToken', jwtToken);\n this.set('refreshToken', refreshToken);\n // Clear API key if switching to JWT auth\n this.delete('apiKey');\n }\n\n /**\n * Remove all auth credentials from config (logout)\n */\n clearAuth(): void {\n this.delete('apiKey');\n this.delete('jwtToken');\n this.delete('refreshToken');\n }\n\n /**\n * Remove API key from config (logout)\n */\n removeApiKey(): void {\n this.delete('apiKey');\n }\n\n /**\n * Set workspace ID in config\n */\n setWorkspaceId(workspaceId: string): void {\n this.set('workspaceId', workspaceId);\n }\n\n /**\n * Set base URL in config\n */\n setBaseUrl(baseUrl: string): void {\n this.set('baseUrl', baseUrl);\n }\n}\n\n// Export singleton instance\nexport const configStore = new ConfigStore();\n\n// Export class for testing purposes\nexport { ConfigStore };\n"],"mappings":"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","names":[]}
@@ -10,13 +10,25 @@ function createSdk() {
10
10
  process.exitCode = 1;
11
11
  return null;
12
12
  }
13
+ const deployment = configStore.getDeployment();
14
+ const apiPrefix = configStore.getApiPrefix();
13
15
  if (apiKey) {
14
16
  if (apiKey.startsWith("eyJ")) {
15
- return new ChanlSDK({ jwtToken: apiKey, baseUrl });
17
+ return new ChanlSDK({
18
+ jwtToken: apiKey,
19
+ baseUrl,
20
+ deployment,
21
+ apiPrefix
22
+ });
16
23
  }
17
- return new ChanlSDK({ apiKey, baseUrl });
24
+ return new ChanlSDK({ apiKey, baseUrl, deployment, apiPrefix });
18
25
  }
19
- return new ChanlSDK({ jwtToken, baseUrl });
26
+ return new ChanlSDK({
27
+ jwtToken,
28
+ baseUrl,
29
+ deployment,
30
+ apiPrefix
31
+ });
20
32
  }
21
33
  function getWorkspaceId() {
22
34
  const workspaceId = configStore.getWorkspaceId();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/sdk-factory.ts"],"sourcesContent":["import { ChanlSDK } from '@chanl/sdk';\nimport { configStore } from './config-store.js';\nimport { printError } from './output.js';\n\n/**\n * Create an authenticated SDK instance from stored config.\n * Supports both API key and JWT token auth.\n * Returns null with error message if not authenticated.\n */\nexport function createSdk(): ChanlSDK | null {\n const apiKey = configStore.getApiKey();\n const jwtToken = configStore.getJwtToken();\n const baseUrl = configStore.getBaseUrl();\n\n if (!apiKey && !jwtToken) {\n printError('Not authenticated', \"Run 'chanl login' to authenticate\");\n process.exitCode = 1;\n return null;\n }\n\n if (apiKey) {\n // API key might be a JWT (legacy compat)\n if (apiKey.startsWith('eyJ')) {\n return new ChanlSDK({ jwtToken: apiKey, baseUrl });\n }\n return new ChanlSDK({ apiKey, baseUrl });\n }\n\n return new ChanlSDK({ jwtToken: jwtToken!, baseUrl });\n}\n\n/**\n * Get workspace ID from config, with error message if not set.\n * Returns null with error message if no workspace selected.\n */\nexport function getWorkspaceId(): string | null {\n const workspaceId = configStore.getWorkspaceId();\n\n if (!workspaceId) {\n printError('No workspace selected', \"Run 'chanl config set workspaceId <id>' to select a workspace\");\n process.exitCode = 1;\n return null;\n }\n\n return workspaceId;\n}\n"],"mappings":"AAAA,SAAS,gBAAgB;AACzB,SAAS,mBAAmB;AAC5B,SAAS,kBAAkB;AAOpB,SAAS,YAA6B;AAC3C,QAAM,SAAS,YAAY,UAAU;AACrC,QAAM,WAAW,YAAY,YAAY;AACzC,QAAM,UAAU,YAAY,WAAW;AAEvC,MAAI,CAAC,UAAU,CAAC,UAAU;AACxB,eAAW,qBAAqB,mCAAmC;AACnE,YAAQ,WAAW;AACnB,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ;AAEV,QAAI,OAAO,WAAW,KAAK,GAAG;AAC5B,aAAO,IAAI,SAAS,EAAE,UAAU,QAAQ,QAAQ,CAAC;AAAA,IACnD;AACA,WAAO,IAAI,SAAS,EAAE,QAAQ,QAAQ,CAAC;AAAA,EACzC;AAEA,SAAO,IAAI,SAAS,EAAE,UAAqB,QAAQ,CAAC;AACtD;AAMO,SAAS,iBAAgC;AAC9C,QAAM,cAAc,YAAY,eAAe;AAE/C,MAAI,CAAC,aAAa;AAChB,eAAW,yBAAyB,+DAA+D;AACnG,YAAQ,WAAW;AACnB,WAAO;AAAA,EACT;AAEA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../src/utils/sdk-factory.ts"],"sourcesContent":["import { ChanlSDK } from '@chanl/sdk';\nimport { configStore } from './config-store.js';\nimport { printError } from './output.js';\n\n/**\n * Create an authenticated SDK instance from stored config.\n * Supports both API key and JWT token auth.\n * Returns null with error message if not authenticated.\n */\nexport function createSdk(): ChanlSDK | null {\n const apiKey = configStore.getApiKey();\n const jwtToken = configStore.getJwtToken();\n const baseUrl = configStore.getBaseUrl();\n\n if (!apiKey && !jwtToken) {\n printError('Not authenticated', \"Run 'chanl login' to authenticate\");\n process.exitCode = 1;\n return null;\n }\n\n const deployment = configStore.getDeployment();\n const apiPrefix = configStore.getApiPrefix();\n\n if (apiKey) {\n // API key might be a JWT (legacy compat)\n if (apiKey.startsWith('eyJ')) {\n return new ChanlSDK({\n jwtToken: apiKey,\n baseUrl,\n deployment,\n apiPrefix,\n });\n }\n return new ChanlSDK({ apiKey, baseUrl, deployment, apiPrefix });\n }\n\n return new ChanlSDK({\n jwtToken: jwtToken!,\n baseUrl,\n deployment,\n apiPrefix,\n });\n}\n\n/**\n * Get workspace ID from config, with error message if not set.\n * Returns null with error message if no workspace selected.\n */\nexport function getWorkspaceId(): string | null {\n const workspaceId = configStore.getWorkspaceId();\n\n if (!workspaceId) {\n printError('No workspace selected', \"Run 'chanl config set workspaceId <id>' to select a workspace\");\n process.exitCode = 1;\n return null;\n }\n\n return workspaceId;\n}\n"],"mappings":"AAAA,SAAS,gBAAgB;AACzB,SAAS,mBAAmB;AAC5B,SAAS,kBAAkB;AAOpB,SAAS,YAA6B;AAC3C,QAAM,SAAS,YAAY,UAAU;AACrC,QAAM,WAAW,YAAY,YAAY;AACzC,QAAM,UAAU,YAAY,WAAW;AAEvC,MAAI,CAAC,UAAU,CAAC,UAAU;AACxB,eAAW,qBAAqB,mCAAmC;AACnE,YAAQ,WAAW;AACnB,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,YAAY,cAAc;AAC7C,QAAM,YAAY,YAAY,aAAa;AAE3C,MAAI,QAAQ;AAEV,QAAI,OAAO,WAAW,KAAK,GAAG;AAC5B,aAAO,IAAI,SAAS;AAAA,QAClB,UAAU;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AACA,WAAO,IAAI,SAAS,EAAE,QAAQ,SAAS,YAAY,UAAU,CAAC;AAAA,EAChE;AAEA,SAAO,IAAI,SAAS;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAMO,SAAS,iBAAgC;AAC9C,QAAM,cAAc,YAAY,eAAe;AAE/C,MAAI,CAAC,aAAa;AAChB,eAAW,yBAAyB,+DAA+D;AACnG,YAAQ,WAAW;AACnB,WAAO;AAAA,EACT;AAEA,SAAO;AACT;","names":[]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@chanl/cli",
3
- "version": "2.0.3",
4
- "description": "Command-line interface for Chanl Analytics",
3
+ "version": "3.0.0",
4
+ "description": "Command-line interface for the Chanl AI platform",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "bin": {
@@ -21,11 +21,11 @@
21
21
  "keywords": [
22
22
  "chanl",
23
23
  "cli",
24
- "analytics",
24
+ "ai-agents",
25
25
  "api",
26
26
  "command-line"
27
27
  ],
28
- "author": "Chanl Analytics",
28
+ "author": "Chanl AI",
29
29
  "license": "MIT",
30
30
  "dependencies": {
31
31
  "@chanl/sdk": "*",