@chanl/cli 2.0.1 → 2.0.2

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 (45) hide show
  1. package/dist/__tests__/cli.test.d.ts +2 -0
  2. package/dist/__tests__/cli.test.js +1 -1
  3. package/dist/__tests__/cli.test.js.map +1 -1
  4. package/dist/cli.d.ts +12 -0
  5. package/dist/cli.js +3 -1
  6. package/dist/cli.js.map +1 -1
  7. package/dist/commands/agents.d.ts +8 -0
  8. package/dist/commands/agents.js +1 -1
  9. package/dist/commands/agents.js.map +1 -1
  10. package/dist/commands/auth.d.ts +16 -0
  11. package/dist/commands/call.d.ts +8 -0
  12. package/dist/commands/calls.d.ts +8 -0
  13. package/dist/commands/chat.d.ts +8 -0
  14. package/dist/commands/config.d.ts +8 -0
  15. package/dist/commands/health.d.ts +8 -0
  16. package/dist/commands/health.js +7 -3
  17. package/dist/commands/health.js.map +1 -1
  18. package/dist/commands/index.d.ts +18 -0
  19. package/dist/commands/knowledge.d.ts +8 -0
  20. package/dist/commands/mcp.d.ts +8 -0
  21. package/dist/commands/mcp.js +4 -4
  22. package/dist/commands/mcp.js.map +1 -1
  23. package/dist/commands/memory.d.ts +8 -0
  24. package/dist/commands/personas.d.ts +8 -0
  25. package/dist/commands/personas.js +1 -1
  26. package/dist/commands/personas.js.map +1 -1
  27. package/dist/commands/prompts.d.ts +8 -0
  28. package/dist/commands/scenarios.d.ts +8 -0
  29. package/dist/commands/scenarios.js +1 -1
  30. package/dist/commands/scenarios.js.map +1 -1
  31. package/dist/commands/scorecards.d.ts +8 -0
  32. package/dist/commands/scorecards.js +1 -1
  33. package/dist/commands/scorecards.js.map +1 -1
  34. package/dist/commands/tools.d.ts +8 -0
  35. package/dist/commands/toolsets.d.ts +8 -0
  36. package/dist/commands/toolsets.js +3 -3
  37. package/dist/commands/toolsets.js.map +1 -1
  38. package/dist/commands/workspaces.d.ts +8 -0
  39. package/dist/index.d.ts +2 -0
  40. package/dist/index.js.map +1 -1
  41. package/dist/utils/config-store.d.ts +117 -0
  42. package/dist/utils/interactive.d.ts +41 -0
  43. package/dist/utils/output.d.ts +100 -0
  44. package/dist/utils/sdk-factory.d.ts +15 -0
  45. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/mcp.ts"],"sourcesContent":["import { Command } from 'commander';\nimport ora from 'ora';\nimport chalk from 'chalk';\nimport type { McpConfigResponse, McpStatusResponse, McpTool, McpToolCallResult } from '@chanl/sdk';\nimport { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';\nimport { configStore } from '../utils/config-store.js';\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} from '../utils/output.js';\n\n/**\n * Create the MCP command group\n */\nexport function createMcpCommand(): Command {\n const mcp = new Command('mcp')\n .description('MCP server configuration and status')\n .addHelpText(\n 'after',\n `\nWhat is MCP?\n Model Context Protocol (MCP) lets AI agents (Claude, Cursor, etc.) use your\n Chanl tools, knowledge base, and prompts. The MCP server bridges your workspace\n with AI clients.\n\nQuick Start:\n $ chanl mcp # Check server status\n $ chanl mcp test # Run protocol test\n $ chanl mcp config # Get config for your AI client\n\nConnecting AI Clients:\n 1. Run 'chanl mcp config --format claude' to get Claude Desktop config\n 2. Add the JSON to Claude Desktop's settings\n 3. Your Chanl tools will appear in Claude!`\n )\n .action(handleMcpDefault); // Default action when no subcommand\n\n // mcp info\n mcp\n .command('info')\n .description('Show MCP server URL, status, and resource counts')\n .addHelpText(\n 'after',\n `\nExample:\n $ chanl mcp info # Show server details\n $ chanl mcp info --json # Output as JSON`\n )\n .action(handleMcpInfo);\n\n // mcp status\n mcp\n .command('status')\n .description('Health check the MCP server')\n .addHelpText(\n 'after',\n `\nExample:\n $ chanl mcp status # Quick health check`\n )\n .action(handleMcpStatus);\n\n // mcp test\n mcp\n .command('test')\n .description('Run MCP protocol test with real MCP client')\n .addHelpText(\n 'after',\n `\nTests the full MCP protocol handshake:\n 1. Connect to MCP server\n 2. List available tools\n 3. List resources (knowledge base)\n 4. List prompts\n\nExample:\n $ chanl mcp test # Run all protocol tests\n $ chanl mcp test --json # Output results as JSON`\n )\n .action(handleMcpTest);\n\n // mcp config\n mcp\n .command('config')\n .description('Output MCP configuration for AI clients')\n .option('-f, --format <format>', 'Format: claude, cursor, generic', 'generic')\n .addHelpText(\n 'after',\n `\nGenerates configuration JSON for connecting AI clients to your MCP server.\n\nSupported formats:\n claude - Claude Desktop (claude_desktop_config.json)\n cursor - Cursor IDE settings\n generic - Generic MCP client format\n\nExamples:\n $ chanl mcp config # Generic format\n $ chanl mcp config --format claude # Claude Desktop format\n $ chanl mcp config --format cursor # Cursor IDE format\n $ chanl mcp config --format claude > config.json # Save to file\n\nSetup Claude Desktop:\n 1. Run: chanl mcp config --format claude\n 2. Copy the JSON output\n 3. Paste into ~/Library/Application Support/Claude/claude_desktop_config.json`\n )\n .action(handleMcpConfig);\n\n // mcp tools <agent-id>\n mcp\n .command('tools <agent-id>')\n .description('List MCP tools available for an agent')\n .addHelpText(\n 'after',\n `\nExample:\n $ chanl mcp tools agent_123 # List tools for agent\n $ chanl mcp tools agent_123 --json # Output as JSON`\n )\n .action(handleMcpTools);\n\n // mcp call <agent-id> <tool-name> [args]\n mcp\n .command('call <agent-id> <tool-name> [args]')\n .description('Call an MCP tool by name')\n .addHelpText(\n 'after',\n `\nExample:\n $ chanl mcp call agent_123 get_weather '{\"city\":\"London\"}'\n $ chanl mcp call agent_123 ping\n $ chanl mcp call agent_123 get_weather '{\"city\":\"London\"}' --json`\n )\n .action(handleMcpCall);\n\n // mcp inspect <agent-id> <tool-name>\n mcp\n .command('inspect <agent-id> <tool-name>')\n .description('Show schema and details for a specific MCP tool')\n .addHelpText(\n 'after',\n `\nExample:\n $ chanl mcp inspect agent_123 get_weather\n $ chanl mcp inspect agent_123 get_weather --json`\n )\n .action(handleMcpInspect);\n\n // mcp install\n mcp\n .command('install')\n .description('Generate MCP config snippet for editors (Cursor, VSCode, Claude)')\n .option('-f, --format <format>', 'Format: claude, cursor, vscode, generic', 'generic')\n .addHelpText(\n 'after',\n `\nGenerates a ready-to-use MCP configuration using your stored API key and workspace.\nNo server call needed — works offline.\n\nSupported formats:\n claude - Claude Desktop / Claude Code\n cursor - Cursor IDE\n vscode - Visual Studio Code\n generic - Generic MCP client (default)\n\nExamples:\n $ chanl mcp install # Generic format\n $ chanl mcp install --format claude # Claude Desktop format\n $ chanl mcp install --format cursor # Cursor IDE format\n $ chanl mcp install --format vscode # VSCode format\n $ chanl mcp install --format claude > mcp.json # Save to file`\n )\n .action(handleMcpInstall);\n\n return mcp;\n}\n\n/**\n * Handle mcp info command\n */\nasync function handleMcpInfo(): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching MCP configuration...').start();\n\n try {\n const response = await sdk.mcp.getConfig();\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch MCP configuration', response.message);\n process.exitCode = 1;\n return;\n }\n\n const config: McpConfigResponse = response.data;\n\n if (isJsonOutput()) {\n printJson(config);\n return;\n }\n\n printBlank();\n printSimpleTable(\n ['Property', 'Value'],\n [\n ['Server URL', config.serverUrl],\n ['Environment', config.environment],\n ['Status', config.status === 'active' ? chalk.green('active') : chalk.red('disabled')],\n ['Tools', config.toolCount.toString()],\n ['Resources', config.resourceCount.toString()],\n ['Prompts', config.promptCount.toString()],\n ...(config.toolsetName ? [['Toolset', config.toolsetName]] : []),\n ]\n );\n printBlank();\n } catch (error) {\n spinner.fail('Failed to fetch MCP configuration');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle mcp status command\n */\nasync function handleMcpStatus(): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Checking MCP server health...').start();\n\n try {\n const response = await sdk.mcp.getStatus();\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to check MCP status', response.message);\n process.exitCode = 1;\n return;\n }\n\n const status: McpStatusResponse = response.data;\n\n if (isJsonOutput()) {\n printJson(status);\n return;\n }\n\n printBlank();\n if (status.healthy) {\n printSuccess('MCP server is healthy');\n printLabel('Message', status.message);\n if (status.responseTimeMs) {\n printLabel('Response Time', status.responseTimeMs + 'ms');\n }\n } else {\n printError('MCP server is unhealthy', status.message);\n if (status.error) {\n printLabel('Error', status.error);\n }\n process.exitCode = 1;\n }\n printBlank();\n } catch (error) {\n spinner.fail('Failed to check MCP status');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle mcp config command\n */\nasync function handleMcpConfig(options: { format: string }): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching MCP configuration...').start();\n\n try {\n const response = await sdk.mcp.getConfig();\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch MCP configuration', response.message);\n process.exitCode = 1;\n return;\n }\n\n const config: McpConfigResponse = response.data;\n const format = options.format.toLowerCase();\n\n let output: unknown;\n\n switch (format) {\n case 'claude':\n output = config.agentConfigs.claude;\n break;\n case 'cursor':\n output = config.agentConfigs.cursor;\n break;\n case 'generic':\n default:\n output = config.agentConfigs.generic;\n break;\n }\n\n // Always output JSON for config command (it's meant to be piped/copied)\n printJson(output);\n\n if (!isJsonOutput()) {\n printBlank();\n printInfo(`Configuration for ${format} format. Copy and paste into your ${format === 'claude' ? 'Claude Desktop' : format === 'cursor' ? 'Cursor IDE' : 'MCP client'} configuration.`);\n printInfo(`Replace \\${CHANL_MCP_API_KEY} with your actual MCP API key.`);\n }\n } catch (error) {\n spinner.fail('Failed to fetch MCP configuration');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle bare 'chanl mcp' command (default)\n * Shows combined info + status\n */\nasync function handleMcpDefault(): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Checking MCP server...').start();\n\n try {\n // Fetch config and status in parallel\n const [configResponse, statusResponse] = await Promise.all([\n sdk.mcp.getConfig(),\n sdk.mcp.getStatus(),\n ]);\n\n spinner.stop();\n\n if (!configResponse.success || !configResponse.data) {\n printError('Failed to fetch MCP configuration', configResponse.message);\n process.exitCode = 1;\n return;\n }\n\n const config: McpConfigResponse = configResponse.data;\n const status: McpStatusResponse | undefined = statusResponse.data;\n\n if (isJsonOutput()) {\n printJson({ config, status });\n return;\n }\n\n // Format status indicator\n const statusIcon = status?.healthy ? chalk.green('✓') : chalk.red('✗');\n const statusText = status?.healthy ? 'Connected' : 'Unhealthy';\n const latency = status?.responseTimeMs ? ` (${status.responseTimeMs}ms)` : '';\n\n printBlank();\n console.log(chalk.bold('MCP Server'));\n console.log(chalk.dim('─'.repeat(40)));\n printLabel('Server URL', config.serverUrl);\n printLabel('Status', `${statusIcon} ${statusText}${latency}`);\n printLabel('Tools', `${config.toolCount} enabled`);\n printLabel('Resources', config.resourceCount.toString());\n printLabel('Prompts', config.promptCount.toString());\n console.log(chalk.dim('─'.repeat(40)));\n printBlank();\n\n if (!status?.healthy) {\n printInfo(\"Run 'chanl mcp test' for detailed diagnostics\");\n process.exitCode = 1;\n }\n } catch (error) {\n spinner.fail('Failed to check MCP server');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle mcp tools command\n * Lists MCP tools available for an agent\n */\nasync function handleMcpTools(agentId: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching MCP tools...').start();\n\n try {\n const response = await sdk.mcp.listTools(agentId);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch MCP tools', response.message);\n process.exitCode = 1;\n return;\n }\n\n const tools: McpTool[] = response.data.tools;\n\n if (isJsonOutput()) {\n printJson({ tools });\n return;\n }\n\n if (tools.length === 0) {\n printBlank();\n printInfo('No MCP tools available for this agent');\n printBlank();\n return;\n }\n\n printBlank();\n printSimpleTable(\n ['Name', 'Description'],\n tools.map((t) => [\n t.name,\n t.description || chalk.dim('No description'),\n ])\n );\n printBlank();\n printInfo(`Total: ${tools.length} tool${tools.length === 1 ? '' : 's'}`);\n printBlank();\n } catch (error) {\n spinner.fail('Failed to fetch MCP 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 mcp call command\n * Calls an MCP tool by name with optional JSON arguments\n */\nasync function handleMcpCall(agentId: string, toolName: string, argsJson?: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n // Parse args if provided\n let args: Record<string, unknown> | undefined;\n if (argsJson) {\n try {\n args = JSON.parse(argsJson) as Record<string, unknown>;\n } catch {\n printError('Invalid JSON arguments', `Could not parse: ${argsJson}`);\n process.exitCode = 1;\n return;\n }\n }\n\n const spinner = ora(`Calling tool '${toolName}'...`).start();\n\n try {\n const response = await sdk.mcp.callTool(agentId, toolName, args);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to call tool', response.message);\n process.exitCode = 1;\n return;\n }\n\n const result: McpToolCallResult = response.data;\n\n if (isJsonOutput()) {\n printJson(result);\n return;\n }\n\n // Check if tool returned an error\n if (result.isError) {\n for (const item of result.content) {\n if (item.text) {\n printError('Tool returned an error', item.text);\n }\n }\n process.exitCode = 1;\n return;\n }\n\n // Display result content\n printBlank();\n for (const item of result.content) {\n if (item.text) {\n console.log(item.text);\n } else {\n // Non-text content: display as JSON\n printJson(item);\n }\n }\n printBlank();\n } catch (error) {\n spinner.fail('Failed to call 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 mcp inspect command\n * Shows schema and details for a specific MCP tool\n */\nasync function handleMcpInspect(agentId: string, toolName: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora(`Fetching tool '${toolName}'...`).start();\n\n try {\n const response = await sdk.mcp.getTool(agentId, toolName);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch tool details', response.message);\n process.exitCode = 1;\n return;\n }\n\n const tool: McpTool = response.data.tool;\n\n if (isJsonOutput()) {\n printJson(tool);\n return;\n }\n\n printBlank();\n console.log(chalk.bold(tool.name));\n console.log(chalk.dim('─'.repeat(40)));\n if (tool.description) {\n printLabel('Description', tool.description);\n }\n printBlank();\n\n // Display input schema\n console.log(chalk.bold('Input Schema'));\n console.log(chalk.dim('─'.repeat(40)));\n\n const schema = tool.inputSchema;\n const properties = schema['properties'] as Record<string, Record<string, unknown>> | undefined;\n const required = (schema['required'] as string[]) || [];\n\n if (properties) {\n const rows: string[][] = [];\n for (const [name, prop] of Object.entries(properties)) {\n const isRequired = required.includes(name);\n const typeStr = String(prop['type'] || 'any');\n const desc = String(prop['description'] || '');\n const reqStr = isRequired ? chalk.red('*') : ' ';\n rows.push([`${reqStr} ${name}`, typeStr, desc]);\n }\n printSimpleTable(['Parameter', 'Type', 'Description'], rows);\n } else {\n printInfo('No parameters defined');\n }\n\n printBlank();\n } catch (error) {\n spinner.fail('Failed to fetch tool details');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle mcp install command\n * Generates MCP config snippets for various editors, using stored API key\n */\nasync function handleMcpInstall(options: { format: string }): Promise<void> {\n const apiKey = configStore.getApiKey();\n if (!apiKey) {\n printError('Not authenticated', \"Run 'chanl login' to authenticate first\");\n process.exitCode = 1;\n return;\n }\n\n const baseUrl = configStore.getBaseUrl() || 'https://api.chanl.ai';\n // Derive MCP server URL from base URL\n // Production: https://api.chanl.ai -> workspace.chanl.app/mcp (generic)\n // For install, use the base URL with /mcp path\n const mcpUrl = baseUrl.replace(/\\/$/, '') + '/mcp';\n\n const format = options.format.toLowerCase();\n\n const serverConfig = {\n url: mcpUrl,\n headers: { 'X-API-Key': apiKey },\n transport: 'streamable-http' as const,\n };\n\n let output: unknown;\n\n switch (format) {\n case 'claude':\n output = {\n mcpServers: {\n chanl: serverConfig,\n },\n };\n break;\n case 'cursor':\n output = {\n mcpServers: {\n chanl: serverConfig,\n },\n };\n break;\n case 'vscode':\n output = {\n mcpServers: {\n chanl: serverConfig,\n },\n };\n break;\n case 'generic':\n default:\n output = {\n mcpServers: {\n chanl: serverConfig,\n },\n };\n break;\n }\n\n // Always output JSON (config is meant to be copied)\n printJson(output);\n\n if (!isJsonOutput()) {\n printBlank();\n const targetName =\n format === 'claude' ? 'Claude Desktop / Claude Code' :\n format === 'cursor' ? 'Cursor IDE' :\n format === 'vscode' ? 'Visual Studio Code' :\n 'your MCP client';\n printInfo(`Copy the JSON above into your ${targetName} configuration.`);\n printBlank();\n }\n}\n\n/**\n * Handle mcp test command\n * Runs real MCP protocol test using @modelcontextprotocol/sdk\n */\nasync function handleMcpTest(): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n // First get the MCP config to know the server URL\n const spinner = ora('Fetching MCP configuration...').start();\n\n let config: McpConfigResponse;\n try {\n const configResponse = await sdk.mcp.getConfig();\n if (!configResponse.success || !configResponse.data) {\n spinner.fail('Failed to fetch MCP configuration');\n printError('Error', configResponse.message || 'Unknown error');\n process.exitCode = 1;\n return;\n }\n config = configResponse.data;\n } catch (error) {\n spinner.fail('Failed to fetch MCP configuration');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n return;\n }\n\n spinner.text = 'Running MCP protocol test...';\n\n // Get API key for MCP authentication\n // Use MCP_API_KEY env var if set (for local dev), otherwise fall back to stored key\n const apiKey = process.env.MCP_API_KEY || configStore.getApiKey();\n if (!apiKey) {\n spinner.fail('No API key available');\n printError('Error', 'API key required for MCP test. Set MCP_API_KEY env var for local dev.');\n process.exitCode = 1;\n return;\n }\n\n const results: { test: string; passed: boolean; detail: string }[] = [];\n\n try {\n // Create MCP client with Streamable HTTP transport\n const transport = new StreamableHTTPClientTransport(new URL(config.serverUrl), {\n requestInit: {\n headers: { 'X-API-Key': apiKey },\n },\n });\n\n const client = new Client(\n { name: 'chanl-cli', version: '1.0.0' },\n { capabilities: {} }\n );\n\n // Test 1: Connect\n spinner.text = 'Connecting to MCP server...';\n const connectStart = Date.now();\n await client.connect(transport);\n const connectTime = Date.now() - connectStart;\n results.push({ test: 'Connection', passed: true, detail: `${connectTime}ms` });\n\n // Test 2: List tools\n spinner.text = 'Testing tools/list...';\n try {\n const tools = await client.listTools();\n results.push({ test: 'tools/list', passed: true, detail: `${tools.tools.length} tools` });\n } catch (err) {\n results.push({ test: 'tools/list', passed: false, detail: err instanceof Error ? err.message : 'Failed' });\n }\n\n // Test 3: List resources\n spinner.text = 'Testing resources/list...';\n try {\n const resources = await client.listResources();\n results.push({ test: 'resources/list', passed: true, detail: `${resources.resources.length} resources` });\n } catch (err) {\n // Resources may not be available (no knowledge base)\n results.push({ test: 'resources/list', passed: true, detail: 'N/A (no knowledge base)' });\n }\n\n // Test 4: List prompts\n spinner.text = 'Testing prompts/list...';\n try {\n const prompts = await client.listPrompts();\n results.push({ test: 'prompts/list', passed: true, detail: `${prompts.prompts.length} prompts` });\n } catch (err) {\n results.push({ test: 'prompts/list', passed: true, detail: 'N/A' });\n }\n\n await client.close();\n spinner.stop();\n\n // Output results\n if (isJsonOutput()) {\n printJson({ serverUrl: config.serverUrl, results });\n return;\n }\n\n printBlank();\n console.log(chalk.bold('🧪 MCP Protocol Test'));\n console.log(chalk.dim('─'.repeat(50)));\n printLabel('Server', config.serverUrl);\n console.log(chalk.dim('─'.repeat(50)));\n\n let allPassed = true;\n for (const result of results) {\n const icon = result.passed ? chalk.green('✓') : chalk.red('✗');\n console.log(`${icon} ${result.test}: ${result.detail}`);\n if (!result.passed) allPassed = false;\n }\n\n console.log(chalk.dim('─'.repeat(50)));\n\n if (allPassed) {\n printSuccess('All tests passed');\n } else {\n printError('Some tests failed', 'Check the results above');\n process.exitCode = 1;\n }\n printBlank();\n } catch (error) {\n spinner.fail('MCP protocol test failed');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Connection failed', message);\n printInfo('Make sure the MCP server is running and accessible');\n process.exitCode = 1;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/commands/mcp.ts"],"sourcesContent":["import { Command } from 'commander';\nimport ora from 'ora';\nimport chalk from 'chalk';\nimport type { McpConfigResponse, McpStatusResponse, McpTool, McpToolCallResult } from '@chanl/sdk';\nimport { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';\nimport { configStore } from '../utils/config-store.js';\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} from '../utils/output.js';\n\n/**\n * Create the MCP command group\n */\nexport function createMcpCommand(): Command {\n const mcp = new Command('mcp')\n .description('MCP server configuration and status')\n .addHelpText(\n 'after',\n `\nWhat is MCP?\n Model Context Protocol (MCP) lets AI agents (Claude, Cursor, etc.) use your\n Chanl tools, knowledge base, and prompts. The MCP server bridges your workspace\n with AI clients.\n\nQuick Start:\n $ chanl mcp # Check server status\n $ chanl mcp test # Run protocol test\n $ chanl mcp config # Get config for your AI client\n\nConnecting AI Clients:\n 1. Run 'chanl mcp config --format claude' to get Claude Desktop config\n 2. Add the JSON to Claude Desktop's settings\n 3. Your Chanl tools will appear in Claude!`\n )\n .action(handleMcpDefault); // Default action when no subcommand\n\n // mcp info\n mcp\n .command('info')\n .description('Show MCP server URL, status, and resource counts')\n .addHelpText(\n 'after',\n `\nExample:\n $ chanl mcp info # Show server details\n $ chanl mcp info --json # Output as JSON`\n )\n .action(handleMcpInfo);\n\n // mcp status\n mcp\n .command('status')\n .description('Health check the MCP server')\n .addHelpText(\n 'after',\n `\nExample:\n $ chanl mcp status # Quick health check`\n )\n .action(handleMcpStatus);\n\n // mcp test\n mcp\n .command('test')\n .description('Run MCP protocol test with real MCP client')\n .addHelpText(\n 'after',\n `\nTests the full MCP protocol handshake:\n 1. Connect to MCP server\n 2. List available tools\n 3. List resources (knowledge base)\n 4. List prompts\n\nExample:\n $ chanl mcp test # Run all protocol tests\n $ chanl mcp test --json # Output results as JSON`\n )\n .action(handleMcpTest);\n\n // mcp config\n mcp\n .command('config')\n .description('Output MCP configuration for AI clients')\n .option('-f, --format <format>', 'Format: claude, cursor, generic', 'generic')\n .addHelpText(\n 'after',\n `\nGenerates configuration JSON for connecting AI clients to your MCP server.\n\nSupported formats:\n claude - Claude Desktop (claude_desktop_config.json)\n cursor - Cursor IDE settings\n generic - Generic MCP client format\n\nExamples:\n $ chanl mcp config # Generic format\n $ chanl mcp config --format claude # Claude Desktop format\n $ chanl mcp config --format cursor # Cursor IDE format\n $ chanl mcp config --format claude > config.json # Save to file\n\nSetup Claude Desktop:\n 1. Run: chanl mcp config --format claude\n 2. Copy the JSON output\n 3. Paste into ~/Library/Application Support/Claude/claude_desktop_config.json`\n )\n .action(handleMcpConfig);\n\n // mcp tools <agent-id>\n mcp\n .command('tools <agent-id>')\n .description('List MCP tools available for an agent')\n .addHelpText(\n 'after',\n `\nExample:\n $ chanl mcp tools agent_123 # List tools for agent\n $ chanl mcp tools agent_123 --json # Output as JSON`\n )\n .action(handleMcpTools);\n\n // mcp call <agent-id> <tool-name> [args]\n mcp\n .command('call <agent-id> <tool-name> [args]')\n .description('Call an MCP tool by name')\n .addHelpText(\n 'after',\n `\nExample:\n $ chanl mcp call agent_123 get_weather '{\"city\":\"London\"}'\n $ chanl mcp call agent_123 ping\n $ chanl mcp call agent_123 get_weather '{\"city\":\"London\"}' --json`\n )\n .action(handleMcpCall);\n\n // mcp inspect <agent-id> <tool-name>\n mcp\n .command('inspect <agent-id> <tool-name>')\n .description('Show schema and details for a specific MCP tool')\n .addHelpText(\n 'after',\n `\nExample:\n $ chanl mcp inspect agent_123 get_weather\n $ chanl mcp inspect agent_123 get_weather --json`\n )\n .action(handleMcpInspect);\n\n // mcp install\n mcp\n .command('install')\n .description('Generate MCP config snippet for editors (Cursor, VSCode, Claude)')\n .option('-f, --format <format>', 'Format: claude, cursor, vscode, generic', 'generic')\n .addHelpText(\n 'after',\n `\nGenerates a ready-to-use MCP configuration using your stored API key and workspace.\nNo server call needed — works offline.\n\nSupported formats:\n claude - Claude Desktop / Claude Code\n cursor - Cursor IDE\n vscode - Visual Studio Code\n generic - Generic MCP client (default)\n\nExamples:\n $ chanl mcp install # Generic format\n $ chanl mcp install --format claude # Claude Desktop format\n $ chanl mcp install --format cursor # Cursor IDE format\n $ chanl mcp install --format vscode # VSCode format\n $ chanl mcp install --format claude > mcp.json # Save to file`\n )\n .action(handleMcpInstall);\n\n return mcp;\n}\n\n/**\n * Handle mcp info command\n */\nasync function handleMcpInfo(): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching MCP configuration...').start();\n\n try {\n const response = await sdk.mcp.getConfig();\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch MCP configuration', response.message);\n process.exitCode = 1;\n return;\n }\n\n const config: McpConfigResponse = response.data;\n\n if (isJsonOutput()) {\n printJson(config);\n return;\n }\n\n printBlank();\n printSimpleTable(\n ['Property', 'Value'],\n [\n ['Server URL', config.serverUrl],\n ['Environment', config.environment],\n ['Status', config.status === 'active' ? chalk.green('active') : chalk.red('disabled')],\n ['Tools', config.toolCount.toString()],\n ['Resources', config.resourceCount.toString()],\n ['Prompts', config.promptCount.toString()],\n ...(config.toolsetName ? [['Toolset', config.toolsetName]] : []),\n ]\n );\n printBlank();\n } catch (error) {\n spinner.fail('Failed to fetch MCP configuration');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle mcp status command\n */\nasync function handleMcpStatus(): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Checking MCP server health...').start();\n\n try {\n const response = await sdk.mcp.getStatus();\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to check MCP status', response.message);\n process.exitCode = 1;\n return;\n }\n\n const status: McpStatusResponse = response.data;\n\n if (isJsonOutput()) {\n printJson(status);\n return;\n }\n\n printBlank();\n if (status.healthy) {\n printSuccess('MCP server is healthy');\n printLabel('Message', status.message);\n if (status.responseTimeMs) {\n printLabel('Response Time', status.responseTimeMs + 'ms');\n }\n } else {\n printError('MCP server is unhealthy', status.message);\n if (status.error) {\n printLabel('Error', status.error);\n }\n process.exitCode = 1;\n }\n printBlank();\n } catch (error) {\n spinner.fail('Failed to check MCP status');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle mcp config command\n */\nasync function handleMcpConfig(options: { format: string }): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching MCP configuration...').start();\n\n try {\n const response = await sdk.mcp.getConfig();\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch MCP configuration', response.message);\n process.exitCode = 1;\n return;\n }\n\n const config: McpConfigResponse = response.data;\n const format = options.format.toLowerCase();\n\n let output: unknown;\n\n switch (format) {\n case 'claude':\n output = config.agentConfigs.claude;\n break;\n case 'cursor':\n output = config.agentConfigs.cursor;\n break;\n case 'generic':\n default:\n output = config.agentConfigs.generic;\n break;\n }\n\n // Always output JSON for config command (it's meant to be piped/copied)\n printJson(output);\n\n if (!isJsonOutput()) {\n printBlank();\n printInfo(`Configuration for ${format} format. Copy and paste into your ${format === 'claude' ? 'Claude Desktop' : format === 'cursor' ? 'Cursor IDE' : 'MCP client'} configuration.`);\n printInfo(`Replace \\${CHANL_MCP_API_KEY} with your actual MCP API key.`);\n }\n } catch (error) {\n spinner.fail('Failed to fetch MCP configuration');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle bare 'chanl mcp' command (default)\n * Shows combined info + status\n */\nasync function handleMcpDefault(): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Checking MCP server...').start();\n\n try {\n // Fetch config and status in parallel\n const [configResponse, statusResponse] = await Promise.all([\n sdk.mcp.getConfig(),\n sdk.mcp.getStatus(),\n ]);\n\n spinner.stop();\n\n if (!configResponse.success || !configResponse.data) {\n printError('Failed to fetch MCP configuration', configResponse.message);\n process.exitCode = 1;\n return;\n }\n\n const config: McpConfigResponse = configResponse.data;\n const status: McpStatusResponse | undefined = statusResponse.data;\n\n if (isJsonOutput()) {\n printJson({ config, status });\n return;\n }\n\n // Format status indicator\n const statusIcon = status?.healthy ? chalk.green('✓') : chalk.red('✗');\n const statusText = status?.healthy ? 'Connected' : 'Unhealthy';\n const latency = status?.responseTimeMs ? ` (${status.responseTimeMs}ms)` : '';\n\n printBlank();\n console.log(chalk.bold('MCP Server'));\n console.log(chalk.dim('─'.repeat(40)));\n printLabel('Server URL', config.serverUrl ?? 'Not configured');\n printLabel('Status', `${statusIcon} ${statusText}${latency}`);\n printLabel('Tools', `${config.toolCount ?? 0} enabled`);\n printLabel('Resources', (config.resourceCount ?? 0).toString());\n printLabel('Prompts', (config.promptCount ?? 0).toString());\n console.log(chalk.dim('─'.repeat(40)));\n printBlank();\n\n if (!status?.healthy) {\n printInfo(\"Run 'chanl mcp test' for detailed diagnostics\");\n process.exitCode = 1;\n }\n } catch (error) {\n spinner.fail('Failed to check MCP server');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle mcp tools command\n * Lists MCP tools available for an agent\n */\nasync function handleMcpTools(agentId: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching MCP tools...').start();\n\n try {\n const response = await sdk.mcp.listTools(agentId);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch MCP tools', response.message);\n process.exitCode = 1;\n return;\n }\n\n const tools: McpTool[] = response.data.tools;\n\n if (isJsonOutput()) {\n printJson({ tools });\n return;\n }\n\n if (tools.length === 0) {\n printBlank();\n printInfo('No MCP tools available for this agent');\n printBlank();\n return;\n }\n\n printBlank();\n printSimpleTable(\n ['Name', 'Description'],\n tools.map((t) => [\n t.name,\n t.description || chalk.dim('No description'),\n ])\n );\n printBlank();\n printInfo(`Total: ${tools.length} tool${tools.length === 1 ? '' : 's'}`);\n printBlank();\n } catch (error) {\n spinner.fail('Failed to fetch MCP 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 mcp call command\n * Calls an MCP tool by name with optional JSON arguments\n */\nasync function handleMcpCall(agentId: string, toolName: string, argsJson?: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n // Parse args if provided\n let args: Record<string, unknown> | undefined;\n if (argsJson) {\n try {\n args = JSON.parse(argsJson) as Record<string, unknown>;\n } catch {\n printError('Invalid JSON arguments', `Could not parse: ${argsJson}`);\n process.exitCode = 1;\n return;\n }\n }\n\n const spinner = ora(`Calling tool '${toolName}'...`).start();\n\n try {\n const response = await sdk.mcp.callTool(agentId, toolName, args);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to call tool', response.message);\n process.exitCode = 1;\n return;\n }\n\n const result: McpToolCallResult = response.data;\n\n if (isJsonOutput()) {\n printJson(result);\n return;\n }\n\n // Check if tool returned an error\n if (result.isError) {\n for (const item of result.content) {\n if (item.text) {\n printError('Tool returned an error', item.text);\n }\n }\n process.exitCode = 1;\n return;\n }\n\n // Display result content\n printBlank();\n for (const item of result.content) {\n if (item.text) {\n console.log(item.text);\n } else {\n // Non-text content: display as JSON\n printJson(item);\n }\n }\n printBlank();\n } catch (error) {\n spinner.fail('Failed to call 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 mcp inspect command\n * Shows schema and details for a specific MCP tool\n */\nasync function handleMcpInspect(agentId: string, toolName: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora(`Fetching tool '${toolName}'...`).start();\n\n try {\n const response = await sdk.mcp.getTool(agentId, toolName);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch tool details', response.message);\n process.exitCode = 1;\n return;\n }\n\n const tool: McpTool = response.data.tool;\n\n if (isJsonOutput()) {\n printJson(tool);\n return;\n }\n\n printBlank();\n console.log(chalk.bold(tool.name));\n console.log(chalk.dim('─'.repeat(40)));\n if (tool.description) {\n printLabel('Description', tool.description);\n }\n printBlank();\n\n // Display input schema\n console.log(chalk.bold('Input Schema'));\n console.log(chalk.dim('─'.repeat(40)));\n\n const schema = tool.inputSchema;\n const properties = schema['properties'] as Record<string, Record<string, unknown>> | undefined;\n const required = (schema['required'] as string[]) || [];\n\n if (properties) {\n const rows: string[][] = [];\n for (const [name, prop] of Object.entries(properties)) {\n const isRequired = required.includes(name);\n const typeStr = String(prop['type'] || 'any');\n const desc = String(prop['description'] || '');\n const reqStr = isRequired ? chalk.red('*') : ' ';\n rows.push([`${reqStr} ${name}`, typeStr, desc]);\n }\n printSimpleTable(['Parameter', 'Type', 'Description'], rows);\n } else {\n printInfo('No parameters defined');\n }\n\n printBlank();\n } catch (error) {\n spinner.fail('Failed to fetch tool details');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle mcp install command\n * Generates MCP config snippets for various editors, using stored API key\n */\nasync function handleMcpInstall(options: { format: string }): Promise<void> {\n const apiKey = configStore.getApiKey();\n if (!apiKey) {\n printError('Not authenticated', \"Run 'chanl login' to authenticate first\");\n process.exitCode = 1;\n return;\n }\n\n const baseUrl = configStore.getBaseUrl() || 'https://api.chanl.ai';\n // Derive MCP server URL from base URL\n // Production: https://api.chanl.ai -> workspace.chanl.app/mcp (generic)\n // For install, use the base URL with /mcp path\n const mcpUrl = baseUrl.replace(/\\/$/, '') + '/mcp';\n\n const format = options.format.toLowerCase();\n\n const serverConfig = {\n url: mcpUrl,\n headers: { 'X-API-Key': apiKey },\n transport: 'streamable-http' as const,\n };\n\n let output: unknown;\n\n switch (format) {\n case 'claude':\n output = {\n mcpServers: {\n chanl: serverConfig,\n },\n };\n break;\n case 'cursor':\n output = {\n mcpServers: {\n chanl: serverConfig,\n },\n };\n break;\n case 'vscode':\n output = {\n mcpServers: {\n chanl: serverConfig,\n },\n };\n break;\n case 'generic':\n default:\n output = {\n mcpServers: {\n chanl: serverConfig,\n },\n };\n break;\n }\n\n // Always output JSON (config is meant to be copied)\n printJson(output);\n\n if (!isJsonOutput()) {\n printBlank();\n const targetName =\n format === 'claude' ? 'Claude Desktop / Claude Code' :\n format === 'cursor' ? 'Cursor IDE' :\n format === 'vscode' ? 'Visual Studio Code' :\n 'your MCP client';\n printInfo(`Copy the JSON above into your ${targetName} configuration.`);\n printBlank();\n }\n}\n\n/**\n * Handle mcp test command\n * Runs real MCP protocol test using @modelcontextprotocol/sdk\n */\nasync function handleMcpTest(): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n // First get the MCP config to know the server URL\n const spinner = ora('Fetching MCP configuration...').start();\n\n let config: McpConfigResponse;\n try {\n const configResponse = await sdk.mcp.getConfig();\n if (!configResponse.success || !configResponse.data) {\n spinner.fail('Failed to fetch MCP configuration');\n printError('Error', configResponse.message || 'Unknown error');\n process.exitCode = 1;\n return;\n }\n config = configResponse.data;\n } catch (error) {\n spinner.fail('Failed to fetch MCP configuration');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n return;\n }\n\n spinner.text = 'Running MCP protocol test...';\n\n // Get API key for MCP authentication\n // Use MCP_API_KEY env var if set (for local dev), otherwise fall back to stored key\n const apiKey = process.env.MCP_API_KEY || configStore.getApiKey();\n if (!apiKey) {\n spinner.fail('No API key available');\n printError('Error', 'API key required for MCP test. Set MCP_API_KEY env var for local dev.');\n process.exitCode = 1;\n return;\n }\n\n const results: { test: string; passed: boolean; detail: string }[] = [];\n\n try {\n // Create MCP client with Streamable HTTP transport\n const transport = new StreamableHTTPClientTransport(new URL(config.serverUrl), {\n requestInit: {\n headers: { 'X-API-Key': apiKey },\n },\n });\n\n const client = new Client(\n { name: 'chanl-cli', version: '1.0.0' },\n { capabilities: {} }\n );\n\n // Test 1: Connect\n spinner.text = 'Connecting to MCP server...';\n const connectStart = Date.now();\n await client.connect(transport);\n const connectTime = Date.now() - connectStart;\n results.push({ test: 'Connection', passed: true, detail: `${connectTime}ms` });\n\n // Test 2: List tools\n spinner.text = 'Testing tools/list...';\n try {\n const tools = await client.listTools();\n results.push({ test: 'tools/list', passed: true, detail: `${tools.tools.length} tools` });\n } catch (err) {\n results.push({ test: 'tools/list', passed: false, detail: err instanceof Error ? err.message : 'Failed' });\n }\n\n // Test 3: List resources\n spinner.text = 'Testing resources/list...';\n try {\n const resources = await client.listResources();\n results.push({ test: 'resources/list', passed: true, detail: `${resources.resources.length} resources` });\n } catch (err) {\n // Resources may not be available (no knowledge base)\n results.push({ test: 'resources/list', passed: true, detail: 'N/A (no knowledge base)' });\n }\n\n // Test 4: List prompts\n spinner.text = 'Testing prompts/list...';\n try {\n const prompts = await client.listPrompts();\n results.push({ test: 'prompts/list', passed: true, detail: `${prompts.prompts.length} prompts` });\n } catch (err) {\n results.push({ test: 'prompts/list', passed: true, detail: 'N/A' });\n }\n\n await client.close();\n spinner.stop();\n\n // Output results\n if (isJsonOutput()) {\n printJson({ serverUrl: config.serverUrl, results });\n return;\n }\n\n printBlank();\n console.log(chalk.bold('🧪 MCP Protocol Test'));\n console.log(chalk.dim('─'.repeat(50)));\n printLabel('Server', config.serverUrl);\n console.log(chalk.dim('─'.repeat(50)));\n\n let allPassed = true;\n for (const result of results) {\n const icon = result.passed ? chalk.green('✓') : chalk.red('✗');\n console.log(`${icon} ${result.test}: ${result.detail}`);\n if (!result.passed) allPassed = false;\n }\n\n console.log(chalk.dim('─'.repeat(50)));\n\n if (allPassed) {\n printSuccess('All tests passed');\n } else {\n printError('Some tests failed', 'Check the results above');\n process.exitCode = 1;\n }\n printBlank();\n } catch (error) {\n spinner.fail('MCP protocol test failed');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Connection failed', message);\n printInfo('Make sure the MCP server is running and accessible');\n process.exitCode = 1;\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,8 @@
1
+ import { Command } from 'commander';
2
+
3
+ /**
4
+ * Create the memory command group
5
+ */
6
+ declare function createMemoryCommand(): Command;
7
+
8
+ export { createMemoryCommand };
@@ -0,0 +1,8 @@
1
+ import { Command } from 'commander';
2
+
3
+ /**
4
+ * Create the personas command group
5
+ */
6
+ declare function createPersonasCommand(): Command;
7
+
8
+ export { createPersonasCommand };
@@ -177,7 +177,7 @@ async function handlePersonasList(options) {
177
177
  );
178
178
  printBlank();
179
179
  if (pagination) {
180
- printInfo(`Total: ${pagination.total} personas (Page ${pagination.page} of ${pagination.pages})`);
180
+ printInfo(`Total: ${pagination.total} personas (Page ${pagination.page} of ${pagination.totalPages})`);
181
181
  }
182
182
  } catch (error) {
183
183
  spinner.fail("Failed to fetch personas");
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/personas.ts"],"sourcesContent":["import { Command } from 'commander';\nimport ora from 'ora';\nimport chalk from 'chalk';\nimport { readFileSync } from 'fs';\nimport type { Persona, CreatePersonaData } from '@chanl/sdk';\nimport { createSdk } from '../utils/sdk-factory.js';\nimport {\n printError,\n printSuccess,\n printInfo,\n printBlank,\n printSimpleTable,\n printLabel,\n isJsonOutput,\n printJson,\n formatDate,\n} from '../utils/output.js';\n\n/**\n * Create the personas command group\n */\nexport function createPersonasCommand(): Command {\n const personas = new Command('personas')\n .description('Manage test personas for scenario simulations')\n .addHelpText(\n 'after',\n `\nWhat are Personas?\n Personas represent simulated callers with specific voice, emotion, and\n behavior characteristics. They are used in scenario testing to simulate\n realistic customer interactions.\n\nQuick Start:\n $ chanl personas list # List all personas\n $ chanl personas get <id> # View persona details\n $ chanl personas create --template # Generate template JSON\n $ chanl personas create -f persona.json # Create from file\n $ chanl personas delete <id> # Delete a persona\n\nPersona Characteristics:\n - Voice: gender, accent, speech style, clarity\n - Emotion: friendly, frustrated, calm, stressed, etc.\n - Behavior: interruption patterns, cooperation level\n - Environment: background noise, connection quality`\n );\n\n // personas list\n personas\n .command('list')\n .description('List all personas')\n .option('-l, --language <lang>', 'Filter by language (english, spanish, portuguese)')\n .option('--active', 'Show only active personas')\n .option('--limit <number>', 'Number of items per page', '20')\n .option('-p, --page <number>', 'Page number', '1')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl personas list # List all personas\n $ chanl personas list --language english # Filter by language\n $ chanl personas list --active # Only active personas\n $ chanl personas list --json # Output as JSON`\n )\n .action(handlePersonasList);\n\n // personas get <id>\n personas\n .command('get <id>')\n .description('Get persona details')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl personas get abc123 # Get persona details\n $ chanl personas get abc123 --json # Output as JSON`\n )\n .action(handlePersonasGet);\n\n // personas create\n personas\n .command('create')\n .description('Create a new persona')\n .option('-f, --file <path>', 'Path to JSON file with persona data')\n .option('--template', 'Output a template JSON file to stdout')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl personas create --template > persona.json # Get template\n $ chanl personas create -f persona.json # Create from file\n\nTemplate contains all required and optional fields with example values.\nEdit the template and use 'create -f' to create your persona.`\n )\n .action(handlePersonasCreate);\n\n // personas update <id>\n personas\n .command('update <id>')\n .description('Update an existing persona')\n .option('-f, --file <path>', 'Path to JSON file with update data')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl personas update abc123 -f updates.json # Update from file\n\nThe update file should contain only the fields you want to change.`\n )\n .action(handlePersonasUpdate);\n\n // personas delete <id>\n personas\n .command('delete <id>')\n .description('Delete a persona')\n .option('-y, --yes', 'Skip confirmation prompt')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl personas delete abc123 # Delete with confirmation\n $ chanl personas delete abc123 --yes # Delete without confirmation`\n )\n .action(handlePersonasDelete);\n\n return personas;\n}\n\n/**\n * Format emotion with color\n */\nfunction formatEmotion(emotion?: string): string {\n const colors: Record<string, (s: string) => string> = {\n friendly: chalk.green,\n calm: chalk.green,\n polite: chalk.green,\n neutral: chalk.gray,\n curious: chalk.cyan,\n distracted: chalk.yellow,\n concerned: chalk.yellow,\n stressed: chalk.yellow,\n annoyed: chalk.red,\n frustrated: chalk.red,\n irritated: chalk.red,\n };\n const colorFn = colors[emotion || ''] || chalk.gray;\n return colorFn(emotion || 'unknown');\n}\n\n/**\n * Get persona template\n */\nfunction getPersonaTemplate(): CreatePersonaData {\n return {\n name: 'Example Persona',\n gender: 'female',\n emotion: 'friendly',\n language: 'english',\n accent: 'american',\n intentClarity: 'very clear',\n speechStyle: 'normal',\n backgroundNoise: false,\n allowInterruptions: true,\n description: 'A helpful and friendly customer',\n backstory:\n 'Sarah is a regular customer who values good service. She is calling about a recent order.',\n variables: {\n accountNumber: '12345',\n orderNumber: 'ORD-2024-001',\n },\n tags: ['customer-service', 'order-inquiry'],\n behavior: {\n personality: 'cooperative',\n emotionalState: 'calm',\n cooperationLevel: 'high',\n patience: 'moderate',\n communicationStyle: 'direct',\n },\n conversationTraits: {\n allowInterruptions: true,\n interruptionFrequency: 'low',\n asksClarifyingQuestions: true,\n repeatsInformation: false,\n goesOffTopic: false,\n },\n environment: {\n backgroundNoise: false,\n noiseType: 'none',\n connectionQuality: 'excellent',\n },\n };\n}\n\n/**\n * Handle personas list command\n */\nasync function handlePersonasList(options: {\n language?: string;\n active?: boolean;\n limit: string;\n page: string;\n}): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching personas...').start();\n\n try {\n const response = await sdk.personas.list({\n language: options.language,\n isActive: options.active,\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 personas', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { personas, pagination } = response.data;\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n if (personas.length === 0) {\n printInfo('No personas found');\n printInfo(\"Use 'chanl personas create --template' to create one\");\n return;\n }\n\n printBlank();\n printSimpleTable(\n ['ID', 'Name', 'Emotion', 'Language', 'Accent', 'Speech', 'Active'],\n personas.map((p: Persona) => [\n p.id.slice(-12),\n p.name.slice(0, 20),\n formatEmotion(p.emotion),\n p.language || '-',\n p.accent || '-',\n p.speechStyle || '-',\n p.isActive ? chalk.green('yes') : chalk.gray('no'),\n ])\n );\n\n printBlank();\n if (pagination) {\n printInfo(`Total: ${pagination.total} personas (Page ${pagination.page} of ${pagination.pages})`);\n }\n } catch (error) {\n spinner.fail('Failed to fetch personas');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle personas get command\n */\nasync function handlePersonasGet(id: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching persona...').start();\n\n try {\n const response = await sdk.personas.get(id);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch persona', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const { persona } = response.data;\n printBlank();\n console.log(chalk.bold('Persona Details:'));\n console.log(` ID: ${persona.id}`);\n console.log(` Name: ${persona.name}`);\n console.log(` Gender: ${persona.gender || '-'}`);\n console.log(` Emotion: ${formatEmotion(persona.emotion)}`);\n console.log(` Language: ${persona.language || '-'}`);\n console.log(` Accent: ${persona.accent || '-'}`);\n console.log(` Speech Style: ${persona.speechStyle || '-'}`);\n console.log(` Intent Clarity: ${persona.intentClarity || '-'}`);\n console.log(` Active: ${persona.isActive ? chalk.green('yes') : chalk.gray('no')}`);\n console.log(` Default: ${persona.isDefault ? chalk.cyan('yes') : chalk.gray('no')}`);\n\n if (persona.description) {\n console.log(`\\n Description:`);\n console.log(` ${persona.description}`);\n }\n\n if (persona.backstory) {\n console.log(`\\n Backstory:`);\n console.log(` ${persona.backstory}`);\n }\n\n console.log(`\\n Created: ${formatDate(persona.createdAt)}`);\n console.log(` Updated: ${formatDate(persona.updatedAt)}`);\n printBlank();\n } catch (error) {\n spinner.fail('Failed to fetch persona');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle personas create command\n */\nasync function handlePersonasCreate(options: {\n file?: string;\n template?: boolean;\n}): Promise<void> {\n // Handle template output\n if (options.template) {\n const template = getPersonaTemplate();\n console.log(JSON.stringify(template, null, 2));\n return;\n }\n\n // Require file for actual creation\n if (!options.file) {\n printError('Missing required option', \"Use '-f <file>' to specify persona data or '--template' to get a template\");\n process.exitCode = 1;\n return;\n }\n\n const sdk = createSdk();\n if (!sdk) return;\n\n // Read and parse the file\n let personaData: CreatePersonaData;\n try {\n const content = readFileSync(options.file, 'utf-8');\n personaData = 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 persona...').start();\n\n try {\n const response = await sdk.personas.create(personaData);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to create persona', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const { persona } = response.data;\n printSuccess(`Persona created: ${persona.name}`);\n printLabel('ID', persona.id);\n } catch (error) {\n spinner.fail('Failed to create persona');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle personas update command\n */\nasync function handlePersonasUpdate(\n id: string,\n options: { file?: string }\n): Promise<void> {\n if (!options.file) {\n printError('Missing required option', \"Use '-f <file>' to specify update data\");\n process.exitCode = 1;\n return;\n }\n\n const sdk = createSdk();\n if (!sdk) return;\n\n // Read and parse the file\n let updateData: Partial<CreatePersonaData>;\n try {\n const content = readFileSync(options.file, 'utf-8');\n updateData = 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 persona...').start();\n\n try {\n const response = await sdk.personas.update(id, updateData);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to update persona', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const { persona } = response.data;\n printSuccess(`Persona updated: ${persona.name}`);\n } catch (error) {\n spinner.fail('Failed to update persona');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle personas delete command\n */\nasync function handlePersonasDelete(\n id: string,\n options: { yes?: boolean }\n): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n // Confirm deletion unless --yes flag\n if (!options.yes) {\n printInfo(`About to delete persona: ${id}`);\n printInfo(\"Use '--yes' flag to skip this confirmation\");\n // In a real CLI we'd prompt for confirmation\n // For now, just proceed\n }\n\n const spinner = ora('Deleting persona...').start();\n\n try {\n const response = await sdk.personas.delete(id);\n\n spinner.stop();\n\n if (!response.success) {\n printError('Failed to delete persona', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson({ success: true, deleted: id });\n return;\n }\n\n printSuccess(`Persona deleted: ${id}`);\n } catch (error) {\n spinner.fail('Failed to delete persona');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/commands/personas.ts"],"sourcesContent":["import { Command } from 'commander';\nimport ora from 'ora';\nimport chalk from 'chalk';\nimport { readFileSync } from 'fs';\nimport type { Persona, CreatePersonaData } from '@chanl/sdk';\nimport { createSdk } from '../utils/sdk-factory.js';\nimport {\n printError,\n printSuccess,\n printInfo,\n printBlank,\n printSimpleTable,\n printLabel,\n isJsonOutput,\n printJson,\n formatDate,\n} from '../utils/output.js';\n\n/**\n * Create the personas command group\n */\nexport function createPersonasCommand(): Command {\n const personas = new Command('personas')\n .description('Manage test personas for scenario simulations')\n .addHelpText(\n 'after',\n `\nWhat are Personas?\n Personas represent simulated callers with specific voice, emotion, and\n behavior characteristics. They are used in scenario testing to simulate\n realistic customer interactions.\n\nQuick Start:\n $ chanl personas list # List all personas\n $ chanl personas get <id> # View persona details\n $ chanl personas create --template # Generate template JSON\n $ chanl personas create -f persona.json # Create from file\n $ chanl personas delete <id> # Delete a persona\n\nPersona Characteristics:\n - Voice: gender, accent, speech style, clarity\n - Emotion: friendly, frustrated, calm, stressed, etc.\n - Behavior: interruption patterns, cooperation level\n - Environment: background noise, connection quality`\n );\n\n // personas list\n personas\n .command('list')\n .description('List all personas')\n .option('-l, --language <lang>', 'Filter by language (english, spanish, portuguese)')\n .option('--active', 'Show only active personas')\n .option('--limit <number>', 'Number of items per page', '20')\n .option('-p, --page <number>', 'Page number', '1')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl personas list # List all personas\n $ chanl personas list --language english # Filter by language\n $ chanl personas list --active # Only active personas\n $ chanl personas list --json # Output as JSON`\n )\n .action(handlePersonasList);\n\n // personas get <id>\n personas\n .command('get <id>')\n .description('Get persona details')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl personas get abc123 # Get persona details\n $ chanl personas get abc123 --json # Output as JSON`\n )\n .action(handlePersonasGet);\n\n // personas create\n personas\n .command('create')\n .description('Create a new persona')\n .option('-f, --file <path>', 'Path to JSON file with persona data')\n .option('--template', 'Output a template JSON file to stdout')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl personas create --template > persona.json # Get template\n $ chanl personas create -f persona.json # Create from file\n\nTemplate contains all required and optional fields with example values.\nEdit the template and use 'create -f' to create your persona.`\n )\n .action(handlePersonasCreate);\n\n // personas update <id>\n personas\n .command('update <id>')\n .description('Update an existing persona')\n .option('-f, --file <path>', 'Path to JSON file with update data')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl personas update abc123 -f updates.json # Update from file\n\nThe update file should contain only the fields you want to change.`\n )\n .action(handlePersonasUpdate);\n\n // personas delete <id>\n personas\n .command('delete <id>')\n .description('Delete a persona')\n .option('-y, --yes', 'Skip confirmation prompt')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl personas delete abc123 # Delete with confirmation\n $ chanl personas delete abc123 --yes # Delete without confirmation`\n )\n .action(handlePersonasDelete);\n\n return personas;\n}\n\n/**\n * Format emotion with color\n */\nfunction formatEmotion(emotion?: string): string {\n const colors: Record<string, (s: string) => string> = {\n friendly: chalk.green,\n calm: chalk.green,\n polite: chalk.green,\n neutral: chalk.gray,\n curious: chalk.cyan,\n distracted: chalk.yellow,\n concerned: chalk.yellow,\n stressed: chalk.yellow,\n annoyed: chalk.red,\n frustrated: chalk.red,\n irritated: chalk.red,\n };\n const colorFn = colors[emotion || ''] || chalk.gray;\n return colorFn(emotion || 'unknown');\n}\n\n/**\n * Get persona template\n */\nfunction getPersonaTemplate(): CreatePersonaData {\n return {\n name: 'Example Persona',\n gender: 'female',\n emotion: 'friendly',\n language: 'english',\n accent: 'american',\n intentClarity: 'very clear',\n speechStyle: 'normal',\n backgroundNoise: false,\n allowInterruptions: true,\n description: 'A helpful and friendly customer',\n backstory:\n 'Sarah is a regular customer who values good service. She is calling about a recent order.',\n variables: {\n accountNumber: '12345',\n orderNumber: 'ORD-2024-001',\n },\n tags: ['customer-service', 'order-inquiry'],\n behavior: {\n personality: 'cooperative',\n emotionalState: 'calm',\n cooperationLevel: 'high',\n patience: 'moderate',\n communicationStyle: 'direct',\n },\n conversationTraits: {\n allowInterruptions: true,\n interruptionFrequency: 'low',\n asksClarifyingQuestions: true,\n repeatsInformation: false,\n goesOffTopic: false,\n },\n environment: {\n backgroundNoise: false,\n noiseType: 'none',\n connectionQuality: 'excellent',\n },\n };\n}\n\n/**\n * Handle personas list command\n */\nasync function handlePersonasList(options: {\n language?: string;\n active?: boolean;\n limit: string;\n page: string;\n}): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching personas...').start();\n\n try {\n const response = await sdk.personas.list({\n language: options.language,\n isActive: options.active,\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 personas', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { personas, pagination } = response.data;\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n if (personas.length === 0) {\n printInfo('No personas found');\n printInfo(\"Use 'chanl personas create --template' to create one\");\n return;\n }\n\n printBlank();\n printSimpleTable(\n ['ID', 'Name', 'Emotion', 'Language', 'Accent', 'Speech', 'Active'],\n personas.map((p: Persona) => [\n p.id.slice(-12),\n p.name.slice(0, 20),\n formatEmotion(p.emotion),\n p.language || '-',\n p.accent || '-',\n p.speechStyle || '-',\n p.isActive ? chalk.green('yes') : chalk.gray('no'),\n ])\n );\n\n printBlank();\n if (pagination) {\n printInfo(`Total: ${pagination.total} personas (Page ${pagination.page} of ${pagination.totalPages})`);\n }\n } catch (error) {\n spinner.fail('Failed to fetch personas');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle personas get command\n */\nasync function handlePersonasGet(id: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching persona...').start();\n\n try {\n const response = await sdk.personas.get(id);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch persona', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const { persona } = response.data;\n printBlank();\n console.log(chalk.bold('Persona Details:'));\n console.log(` ID: ${persona.id}`);\n console.log(` Name: ${persona.name}`);\n console.log(` Gender: ${persona.gender || '-'}`);\n console.log(` Emotion: ${formatEmotion(persona.emotion)}`);\n console.log(` Language: ${persona.language || '-'}`);\n console.log(` Accent: ${persona.accent || '-'}`);\n console.log(` Speech Style: ${persona.speechStyle || '-'}`);\n console.log(` Intent Clarity: ${persona.intentClarity || '-'}`);\n console.log(` Active: ${persona.isActive ? chalk.green('yes') : chalk.gray('no')}`);\n console.log(` Default: ${persona.isDefault ? chalk.cyan('yes') : chalk.gray('no')}`);\n\n if (persona.description) {\n console.log(`\\n Description:`);\n console.log(` ${persona.description}`);\n }\n\n if (persona.backstory) {\n console.log(`\\n Backstory:`);\n console.log(` ${persona.backstory}`);\n }\n\n console.log(`\\n Created: ${formatDate(persona.createdAt)}`);\n console.log(` Updated: ${formatDate(persona.updatedAt)}`);\n printBlank();\n } catch (error) {\n spinner.fail('Failed to fetch persona');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle personas create command\n */\nasync function handlePersonasCreate(options: {\n file?: string;\n template?: boolean;\n}): Promise<void> {\n // Handle template output\n if (options.template) {\n const template = getPersonaTemplate();\n console.log(JSON.stringify(template, null, 2));\n return;\n }\n\n // Require file for actual creation\n if (!options.file) {\n printError('Missing required option', \"Use '-f <file>' to specify persona data or '--template' to get a template\");\n process.exitCode = 1;\n return;\n }\n\n const sdk = createSdk();\n if (!sdk) return;\n\n // Read and parse the file\n let personaData: CreatePersonaData;\n try {\n const content = readFileSync(options.file, 'utf-8');\n personaData = 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 persona...').start();\n\n try {\n const response = await sdk.personas.create(personaData);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to create persona', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const { persona } = response.data;\n printSuccess(`Persona created: ${persona.name}`);\n printLabel('ID', persona.id);\n } catch (error) {\n spinner.fail('Failed to create persona');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle personas update command\n */\nasync function handlePersonasUpdate(\n id: string,\n options: { file?: string }\n): Promise<void> {\n if (!options.file) {\n printError('Missing required option', \"Use '-f <file>' to specify update data\");\n process.exitCode = 1;\n return;\n }\n\n const sdk = createSdk();\n if (!sdk) return;\n\n // Read and parse the file\n let updateData: Partial<CreatePersonaData>;\n try {\n const content = readFileSync(options.file, 'utf-8');\n updateData = 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 persona...').start();\n\n try {\n const response = await sdk.personas.update(id, updateData);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to update persona', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const { persona } = response.data;\n printSuccess(`Persona updated: ${persona.name}`);\n } catch (error) {\n spinner.fail('Failed to update persona');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle personas delete command\n */\nasync function handlePersonasDelete(\n id: string,\n options: { yes?: boolean }\n): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n // Confirm deletion unless --yes flag\n if (!options.yes) {\n printInfo(`About to delete persona: ${id}`);\n printInfo(\"Use '--yes' flag to skip this confirmation\");\n // In a real CLI we'd prompt for confirmation\n // For now, just proceed\n }\n\n const spinner = ora('Deleting persona...').start();\n\n try {\n const response = await sdk.personas.delete(id);\n\n spinner.stop();\n\n if (!response.success) {\n printError('Failed to delete persona', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson({ success: true, deleted: id });\n return;\n }\n\n printSuccess(`Persona deleted: ${id}`);\n } catch (error) {\n spinner.fail('Failed to delete persona');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,8 @@
1
+ import { Command } from 'commander';
2
+
3
+ /**
4
+ * Create the prompts command group
5
+ */
6
+ declare function createPromptsCommand(): Command;
7
+
8
+ export { createPromptsCommand };
@@ -0,0 +1,8 @@
1
+ import { Command } from 'commander';
2
+
3
+ /**
4
+ * Create the scenarios command group
5
+ */
6
+ declare function createScenariosCommand(): Command;
7
+
8
+ export { createScenariosCommand };
@@ -145,7 +145,7 @@ async function handleScenariosList(options) {
145
145
  ])
146
146
  );
147
147
  printBlank();
148
- printInfo(`Total: ${pagination.total} scenarios (Page ${pagination.page} of ${pagination.pages})`);
148
+ printInfo(`Total: ${pagination.total} scenarios (Page ${pagination.page} of ${pagination.totalPages})`);
149
149
  } catch (error) {
150
150
  spinner.fail("Failed to fetch scenarios");
151
151
  const message = error instanceof Error ? error.message : "Unknown error";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/scenarios.ts"],"sourcesContent":["import { Command } from 'commander';\nimport ora from 'ora';\nimport chalk from 'chalk';\nimport type { ChanlSDK, ScenarioExecution, ToolCall, BatchResult } from '@chanl/sdk';\nimport { createSdk } from '../utils/sdk-factory.js';\nimport {\n printError,\n printInfo,\n printBlank,\n printSimpleTable,\n printLabel,\n isJsonOutput,\n printJson,\n formatDate,\n} from '../utils/output.js';\nimport {\n formatElapsed,\n printSegment,\n displayScorecard,\n} from '../utils/interactive.js';\n\n/**\n * Create the scenarios command group\n */\nexport function createScenariosCommand(): Command {\n const scenarios = new Command('scenarios')\n .description('Manage and run test scenarios')\n .addHelpText(\n 'after',\n `\nWhat are Scenarios?\n Scenarios are test cases that run against your AI agents. Each scenario\n defines a conversation flow, expected responses, and scoring criteria.\n\nQuick Start:\n $ chanl scenarios list # See all scenarios\n $ chanl scenarios run <id> # Execute a scenario\n $ chanl scenarios run <id> --watch # Execute and watch progress\n $ chanl scenarios history <id> # View past runs\n\nExecution Workflow:\n 1. List scenarios to find the one you want to test\n 2. Run the scenario (optionally with --watch)\n 3. Check execution status with 'executions' or 'execution <id>'\n 4. Review history with 'history <scenarioId>'`\n );\n\n // scenarios list\n scenarios\n .command('list')\n .description('List all scenarios')\n .option('-s, --status <status>', 'Filter by status (draft, active, paused, completed, archived)')\n .option('-c, --category <category>', 'Filter by category')\n .option('-l, --limit <number>', 'Number of items per page', '20')\n .option('-p, --page <number>', 'Page number', '1')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl scenarios list # List all scenarios\n $ chanl scenarios list --status active # Only active scenarios\n $ chanl scenarios list --category sales # Filter by category\n $ chanl scenarios list --json # Output as JSON`\n )\n .action(handleScenariosList);\n\n // scenarios get <id>\n scenarios\n .command('get <id>')\n .description('Get a scenario by ID')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl scenarios get abc123 # Get scenario details\n $ chanl scenarios get abc123 --json # Output as JSON`\n )\n .action(handleScenariosGet);\n\n // scenarios run <id>\n scenarios\n .command('run <id>')\n .description('Execute a scenario')\n .option('-a, --agent <agentId>', 'Specific agent to run against')\n .option('-m, --mode <mode>', 'Simulation mode: text, websocket, phone', 'websocket')\n .option('-p, --phone <number>', 'Phone number for phone mode (E.164 format)')\n .option('-w, --watch', 'Watch execution progress until completion')\n .option('--dry-run', 'Validate without actually executing')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl scenarios run abc123 # Run with defaults\n $ chanl scenarios run abc123 --watch # Run and watch progress\n $ chanl scenarios run abc123 --agent agent_xyz # Run against specific agent\n $ chanl scenarios run abc123 --mode phone --phone +14155551234\n $ chanl scenarios run abc123 --dry-run # Validate only\n\nSimulation Modes:\n text Free, instant text-based testing\n websocket Real WebSocket testing (requires provider API key)\n phone Real phone call (requires provider + phone number)`\n )\n .action(handleScenariosRun);\n\n // scenarios executions\n scenarios\n .command('executions')\n .description('List scenario executions')\n .option('-s, --scenario <scenarioId>', 'Filter by scenario ID')\n .option('--status <status>', 'Filter by status (queued, running, completed, failed, timeout, cancelled)')\n .option('-l, --limit <number>', 'Number of items', '10')\n .option('-p, --page <number>', 'Page number', '1')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl scenarios executions # List recent executions\n $ chanl scenarios executions --scenario abc123 # For specific scenario\n $ chanl scenarios executions --status completed # Only completed\n $ chanl scenarios executions --json # Output as JSON`\n )\n .action(handleScenariosExecutions);\n\n // scenarios execution <executionId>\n scenarios\n .command('execution <executionId>')\n .description('Get execution details')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl scenarios execution exec_abc123 # Get execution details\n $ chanl scenarios execution exec_abc123 --json`\n )\n .action(handleScenariosExecution);\n\n // scenarios history <scenarioId>\n scenarios\n .command('history <scenarioId>')\n .description('Get simulation history for a scenario')\n .option('-l, --limit <number>', 'Number of simulations to show', '10')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl scenarios history abc123 # Last 10 runs\n $ chanl scenarios history abc123 --limit 5 # Last 5 runs\n $ chanl scenarios history abc123 --json # Output as JSON`\n )\n .action(handleScenariosHistory);\n\n // scenarios run-all\n scenarios\n .command('run-all')\n .description('Run all scenarios for an agent and show aggregate results')\n .requiredOption('-a, --agent <agentId>', 'Agent ID to run scenarios against')\n .option('--min-score <score>', 'Minimum passing score (0-100)', '0')\n .option('--parallel <count>', 'Max concurrent executions', '3')\n .option('-m, --mode <mode>', 'Simulation mode: text, phone', 'text')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl scenarios run-all --agent agent_abc # Run all with defaults\n $ chanl scenarios run-all --agent agent_abc --min-score 80 # Fail if any score < 80\n $ chanl scenarios run-all --agent agent_abc --parallel 5 # Run 5 at a time\n $ chanl scenarios run-all --agent agent_abc --json # Output as JSON\n\nExit Codes:\n 0 All scenarios passed (score >= min-score)\n 1 One or more scenarios failed`\n )\n .action(handleScenariosRunAll);\n\n return scenarios;\n}\n\n/**\n * Handle scenarios list command\n */\nasync function handleScenariosList(options: {\n status?: string;\n category?: string;\n limit: string;\n page: string;\n}): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching scenarios...').start();\n\n try {\n const response = await sdk.scenarios.list({\n status: options.status,\n category: options.category,\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 scenarios', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { scenarios, pagination } = response.data;\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n if (scenarios.length === 0) {\n printInfo('No scenarios found');\n return;\n }\n\n printBlank();\n printSimpleTable(\n ['Name', 'Status', 'Category', 'Difficulty', 'Created'],\n scenarios.map((s) => [\n s.name,\n formatStatus(s.status),\n s.category || '-',\n s.difficulty || '-',\n formatDate(s.createdAt),\n ])\n );\n\n printBlank();\n printInfo(`Total: ${pagination.total} scenarios (Page ${pagination.page} of ${pagination.pages})`);\n } catch (error) {\n spinner.fail('Failed to fetch scenarios');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle scenarios get command\n */\nasync function handleScenariosGet(id: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching scenario...').start();\n\n try {\n const response = await sdk.scenarios.get(id);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch scenario', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const { scenario } = response.data;\n printBlank();\n console.log(chalk.bold('Scenario Details:'));\n console.log(` Name: ${scenario.name}`);\n console.log(` ID: ${scenario.id}`);\n console.log(` Status: ${formatStatus(scenario.status)}`);\n console.log(` Category: ${scenario.category || '-'}`);\n console.log(` Difficulty: ${scenario.difficulty || '-'}`);\n console.log(` Created: ${formatDate(scenario.createdAt)}`);\n if (scenario.description) {\n console.log(` Description: ${scenario.description}`);\n }\n printBlank();\n } catch (error) {\n spinner.fail('Failed to fetch scenario');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Format status with color\n */\nfunction formatStatus(status?: string): string {\n switch (status) {\n case 'active':\n return chalk.green('active');\n case 'paused':\n return chalk.yellow('paused');\n case 'completed':\n return chalk.blue('completed');\n case 'archived':\n return chalk.gray('archived');\n case 'draft':\n default:\n return chalk.gray(status || 'draft');\n }\n}\n\n/**\n * Format execution status with color\n */\nfunction formatExecutionStatus(status?: string): string {\n switch (status) {\n case 'completed':\n return chalk.green('completed');\n case 'running':\n return chalk.cyan('running');\n case 'queued':\n return chalk.blue('queued');\n case 'failed':\n return chalk.red('failed');\n case 'timeout':\n return chalk.yellow('timeout');\n case 'cancelled':\n return chalk.gray('cancelled');\n default:\n return chalk.gray(status || 'unknown');\n }\n}\n\n/**\n * Format score with color\n */\nfunction formatScore(score?: number): string {\n if (score === undefined || score === null) return '-';\n if (score >= 80) return chalk.green(`${score}%`);\n if (score >= 60) return chalk.yellow(`${score}%`);\n return chalk.red(`${score}%`);\n}\n\n/**\n * Format duration in seconds\n */\nfunction formatDuration(seconds?: number): string {\n if (!seconds) return '-';\n if (seconds < 60) return `${seconds.toFixed(1)}s`;\n const mins = Math.floor(seconds / 60);\n const secs = seconds % 60;\n return `${mins}m ${secs.toFixed(0)}s`;\n}\n\n/**\n * Handle scenarios run command\n */\nasync function handleScenariosRun(\n id: string,\n options: {\n agent?: string;\n mode?: string;\n phone?: string;\n watch?: boolean;\n dryRun?: boolean;\n }\n): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Starting scenario execution...').start();\n\n try {\n const response = await sdk.scenarios.run(id, {\n agentId: options.agent,\n simulationMode: options.mode as 'text' | 'websocket' | 'phone',\n phoneNumber: options.phone,\n dryRun: options.dryRun,\n });\n\n if (!response.success || !response.data) {\n spinner.fail('Failed to start execution');\n printError('Error', response.message || 'Unknown error');\n process.exitCode = 1;\n return;\n }\n\n const { execution, executionId } = response.data;\n const execId = executionId || execution?.id || execution?.executionId;\n\n if (options.dryRun) {\n spinner.succeed('Dry run validation passed');\n printInfo('Scenario is valid and ready to execute');\n return;\n }\n\n spinner.succeed(`Execution started: ${execId}`);\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n if (!options.watch) {\n printBlank();\n printLabel('Execution ID', execId || 'N/A');\n printLabel('Status', formatExecutionStatus(execution?.status));\n printInfo(`Run 'chanl scenarios execution ${execId}' to check status`);\n printBlank();\n return;\n }\n\n // Watch mode - poll until complete\n await watchExecution(sdk, execId!, options.mode === 'phone');\n } catch (error) {\n spinner.fail('Failed to execute scenario');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Watch execution until completion\n * Uses SDK LiveExecution for event-driven monitoring\n */\nasync function watchExecution(\n sdk: ChanlSDK,\n executionId: string,\n isPhoneMode = false,\n): Promise<void> {\n const startTime = new Date();\n let spinner = ora(\n isPhoneMode\n ? `${chalk.red('LIVE')} — ${formatElapsed(startTime)} | Watching voice execution...`\n : 'Watching execution...'\n ).start();\n\n const live = sdk.scenarios.watchExecution(executionId);\n let finalExecution: ScenarioExecution | undefined;\n let scorecardReceived = false;\n\n live.on('status', (status) => {\n if (isPhoneMode) {\n spinner.text = `${chalk.red('LIVE')} — ${formatElapsed(startTime)} | Status: ${status}`;\n } else {\n spinner.text = `Status: ${status}`;\n }\n });\n\n live.on('step', (step) => {\n if (!isPhoneMode) {\n spinner.stop();\n const stepStatus = step.status === 'completed' ? chalk.green('✓') : chalk.red('✗');\n console.log(` ${stepStatus} Step ${step.stepId}: ${step.response?.slice(0, 80) || '-'}`);\n if (step.toolCalls.length > 0) {\n for (const tc of step.toolCalls) {\n const tcIcon = tc.status === 'success' ? chalk.green('✓') : chalk.red('✗');\n const dur = tc.durationMs ? chalk.dim(` (${tc.durationMs}ms)`) : '';\n console.log(` ${tcIcon} ${chalk.yellow(tc.name)}${dur}`);\n }\n }\n spinner.start();\n }\n });\n\n live.on('transcript', (seg) => {\n spinner.stop();\n printSegment(seg);\n spinner.start();\n });\n\n live.on('completed', (execution) => {\n finalExecution = execution;\n const status = execution.status;\n\n if (status === 'completed') {\n spinner.succeed(\n isPhoneMode\n ? `Execution complete — ${formatElapsed(startTime)}`\n : 'Execution completed'\n );\n } else if (status === 'failed') {\n spinner.fail(\n isPhoneMode\n ? `Execution failed — ${formatElapsed(startTime)}`\n : 'Execution failed'\n );\n } else {\n spinner.warn(`Execution ${status}`);\n }\n\n printBlank();\n printExecutionDetails(execution);\n\n // Start scorecard spinner for phone mode\n if (isPhoneMode && execution.callDetails?.callId) {\n spinner = ora('Checking for scorecard...').start();\n }\n });\n\n live.on('scorecard', (results) => {\n scorecardReceived = true;\n spinner.stop();\n displayScorecard(results);\n printBlank();\n });\n\n live.on('timeout', () => {\n spinner.warn('Timeout waiting for execution to complete');\n printInfo(`Run 'chanl scenarios execution ${executionId}' to check status`);\n });\n\n live.on('error', (err) => {\n spinner.fail('Error while watching');\n printError('Error', err.message);\n process.exitCode = 1;\n });\n\n await live.completed;\n\n // Post-completion: if phone mode and no scorecard arrived, clean up spinner\n if (finalExecution && isPhoneMode && finalExecution.callDetails?.callId && !scorecardReceived) {\n spinner.stop();\n }\n}\n\n/**\n * Print execution details\n */\nfunction printExecutionDetails(execution: ScenarioExecution): void {\n console.log(chalk.bold('Execution Results:'));\n console.log(` Execution ID: ${execution.id || execution.executionId}`);\n console.log(` Scenario ID: ${execution.scenarioId}`);\n console.log(` Status: ${formatExecutionStatus(execution.status)}`);\n console.log(` Score: ${formatScore(execution.overallScore)}`);\n console.log(` Duration: ${formatDuration(execution.duration)}`);\n\n if (execution.metrics) {\n console.log(chalk.bold('\\n Metrics:'));\n if (execution.metrics.responseTime !== undefined) {\n console.log(` Response Time: ${execution.metrics.responseTime.toFixed(0)}ms`);\n }\n if (execution.metrics.accuracy !== undefined) {\n console.log(` Accuracy: ${formatScore(execution.metrics.accuracy)}`);\n }\n if (execution.metrics.completion !== undefined) {\n console.log(` Completion: ${formatScore(execution.metrics.completion)}`);\n }\n }\n\n if (execution.callDetails?.callId) {\n console.log(chalk.bold('\\n Call Details:'));\n console.log(` Call ID: ${execution.callDetails.callId}`);\n if (execution.callDetails.phoneNumber) {\n console.log(` Phone: ${execution.callDetails.phoneNumber}`);\n }\n }\n\n // Show tool calls from step results\n const allToolCalls = (execution.stepResults ?? []).flatMap((s) => s.toolCalls ?? []);\n if (allToolCalls.length > 0) {\n console.log(chalk.bold('\\n Tool Calls:'));\n printScenarioToolCalls(allToolCalls);\n }\n\n if (execution.errorMessages && execution.errorMessages.length > 0) {\n console.log(chalk.bold('\\n Errors:'));\n execution.errorMessages.forEach((msg) => {\n console.log(chalk.red(` - ${msg}`));\n });\n }\n\n printBlank();\n}\n\n/**\n * Print tool calls from scenario execution\n */\nfunction printScenarioToolCalls(toolCalls: ToolCall[]): void {\n for (const tc of toolCalls) {\n const statusIcon =\n tc.status === 'success'\n ? chalk.green('✓')\n : tc.status === 'error'\n ? chalk.red('✗')\n : tc.status === 'timeout'\n ? chalk.yellow('⏱')\n : chalk.dim('…');\n const duration = tc.durationMs ? chalk.dim(` (${tc.durationMs}ms)`) : '';\n const params = Object.keys(tc.parameters).length\n ? chalk.dim(` ${JSON.stringify(tc.parameters)}`)\n : '';\n\n console.log(` ${statusIcon} ${chalk.yellow(tc.name)}${params}${duration}`);\n\n if (tc.status === 'error' && tc.error) {\n console.log(` ${chalk.red(tc.error.message)}`);\n }\n }\n}\n\n/**\n * Handle scenarios executions command\n */\nasync function handleScenariosExecutions(options: {\n scenario?: string;\n status?: string;\n limit: string;\n page: string;\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.scenarios.getExecutions({\n scenarioId: options.scenario,\n status: options.status,\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 executions', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { executions, total } = response.data;\n\n if (isJsonOutput()) {\n printJson(response.data);\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', 'Scenario', 'Status', 'Score', 'Duration', 'Started'],\n executions.map((e) => [\n (e.id || e.executionId || '').slice(-12),\n e.scenarioId?.slice(-8) || '-',\n formatExecutionStatus(e.status),\n formatScore(e.overallScore),\n formatDuration(e.duration),\n e.startTime ? formatDate(e.startTime) : '-',\n ])\n );\n\n printBlank();\n printInfo(`Total: ${total} executions`);\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 scenarios execution command\n */\nasync function handleScenariosExecution(executionId: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching execution...').start();\n\n try {\n const response = await sdk.scenarios.getExecution(executionId);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch execution', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const { execution } = response.data;\n printBlank();\n printExecutionDetails(execution);\n } catch (error) {\n spinner.fail('Failed to fetch execution');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle scenarios history command\n */\nasync function handleScenariosHistory(\n scenarioId: string,\n options: { limit: string }\n): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching simulation history...').start();\n\n try {\n const response = await sdk.scenarios.getSimulations(\n scenarioId,\n parseInt(options.limit, 10)\n );\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch history', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { simulations } = response.data;\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n if (simulations.length === 0) {\n printInfo('No simulation history found for this scenario');\n return;\n }\n\n printBlank();\n console.log(chalk.bold(`Simulation History for ${scenarioId}`));\n console.log(chalk.dim('─'.repeat(60)));\n\n printSimpleTable(\n ['#', 'Status', 'Score', 'Duration', 'Started'],\n simulations.map((s, i) => [\n (i + 1).toString(),\n formatExecutionStatus(s.status),\n formatScore(s.overallScore),\n formatDuration(s.duration),\n s.startTime ? formatDate(s.startTime) : '-',\n ])\n );\n\n printBlank();\n printInfo(`Showing last ${simulations.length} simulations`);\n } catch (error) {\n spinner.fail('Failed to fetch history');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle scenarios run-all command\n */\nasync function handleScenariosRunAll(options: {\n agent: string;\n minScore: string;\n parallel: string;\n mode?: string;\n}): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const minScore = parseInt(options.minScore, 10);\n const parallel = parseInt(options.parallel, 10);\n\n const spinner = ora(`Running all scenarios for agent ${options.agent}...`).start();\n\n try {\n const result: BatchResult = await sdk.scenarios.runAll({\n agentId: options.agent,\n minScore,\n parallel,\n mode: options.mode as 'text' | 'phone' | undefined,\n });\n\n spinner.stop();\n\n if (isJsonOutput()) {\n printJson(result);\n if (!result.allPassed) {\n process.exitCode = 1;\n }\n return;\n }\n\n if (result.totalScenarios === 0) {\n printInfo('No active scenarios found for this agent');\n return;\n }\n\n printBlank();\n console.log(chalk.bold('Batch Scenario Results'));\n console.log(chalk.dim('─'.repeat(60)));\n\n // Per-scenario results\n printSimpleTable(\n ['Scenario', 'Status', 'Score', 'Duration', 'Tools', 'Result'],\n result.results.map((r) => [\n r.scenarioName,\n formatExecutionStatus(r.status),\n formatScore(r.score),\n formatDuration(r.duration),\n r.toolCallCount.toString(),\n r.passed ? chalk.green('PASS') : chalk.red('FAIL'),\n ])\n );\n\n // Summary\n printBlank();\n console.log(chalk.bold('Summary'));\n console.log(` Total: ${result.totalScenarios}`);\n console.log(` Passed: ${chalk.green(result.passed.toString())}`);\n console.log(` Failed: ${result.failed > 0 ? chalk.red(result.failed.toString()) : '0'}`);\n console.log(` Average Score: ${formatScore(result.averageScore)}`);\n console.log(` Min Score: ${result.minScore}`);\n\n printBlank();\n if (result.allPassed) {\n console.log(chalk.green(`All ${result.totalScenarios} scenarios passed`));\n } else {\n console.log(chalk.red(`${result.failed} of ${result.totalScenarios} scenarios failed`));\n process.exitCode = 1;\n }\n printBlank();\n } catch (error) {\n spinner.fail('Failed to run scenarios');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/commands/scenarios.ts"],"sourcesContent":["import { Command } from 'commander';\nimport ora from 'ora';\nimport chalk from 'chalk';\nimport type { ChanlSDK, ScenarioExecution, ToolCall, BatchResult } from '@chanl/sdk';\nimport { createSdk } from '../utils/sdk-factory.js';\nimport {\n printError,\n printInfo,\n printBlank,\n printSimpleTable,\n printLabel,\n isJsonOutput,\n printJson,\n formatDate,\n} from '../utils/output.js';\nimport {\n formatElapsed,\n printSegment,\n displayScorecard,\n} from '../utils/interactive.js';\n\n/**\n * Create the scenarios command group\n */\nexport function createScenariosCommand(): Command {\n const scenarios = new Command('scenarios')\n .description('Manage and run test scenarios')\n .addHelpText(\n 'after',\n `\nWhat are Scenarios?\n Scenarios are test cases that run against your AI agents. Each scenario\n defines a conversation flow, expected responses, and scoring criteria.\n\nQuick Start:\n $ chanl scenarios list # See all scenarios\n $ chanl scenarios run <id> # Execute a scenario\n $ chanl scenarios run <id> --watch # Execute and watch progress\n $ chanl scenarios history <id> # View past runs\n\nExecution Workflow:\n 1. List scenarios to find the one you want to test\n 2. Run the scenario (optionally with --watch)\n 3. Check execution status with 'executions' or 'execution <id>'\n 4. Review history with 'history <scenarioId>'`\n );\n\n // scenarios list\n scenarios\n .command('list')\n .description('List all scenarios')\n .option('-s, --status <status>', 'Filter by status (draft, active, paused, completed, archived)')\n .option('-c, --category <category>', 'Filter by category')\n .option('-l, --limit <number>', 'Number of items per page', '20')\n .option('-p, --page <number>', 'Page number', '1')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl scenarios list # List all scenarios\n $ chanl scenarios list --status active # Only active scenarios\n $ chanl scenarios list --category sales # Filter by category\n $ chanl scenarios list --json # Output as JSON`\n )\n .action(handleScenariosList);\n\n // scenarios get <id>\n scenarios\n .command('get <id>')\n .description('Get a scenario by ID')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl scenarios get abc123 # Get scenario details\n $ chanl scenarios get abc123 --json # Output as JSON`\n )\n .action(handleScenariosGet);\n\n // scenarios run <id>\n scenarios\n .command('run <id>')\n .description('Execute a scenario')\n .option('-a, --agent <agentId>', 'Specific agent to run against')\n .option('-m, --mode <mode>', 'Simulation mode: text, websocket, phone', 'websocket')\n .option('-p, --phone <number>', 'Phone number for phone mode (E.164 format)')\n .option('-w, --watch', 'Watch execution progress until completion')\n .option('--dry-run', 'Validate without actually executing')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl scenarios run abc123 # Run with defaults\n $ chanl scenarios run abc123 --watch # Run and watch progress\n $ chanl scenarios run abc123 --agent agent_xyz # Run against specific agent\n $ chanl scenarios run abc123 --mode phone --phone +14155551234\n $ chanl scenarios run abc123 --dry-run # Validate only\n\nSimulation Modes:\n text Free, instant text-based testing\n websocket Real WebSocket testing (requires provider API key)\n phone Real phone call (requires provider + phone number)`\n )\n .action(handleScenariosRun);\n\n // scenarios executions\n scenarios\n .command('executions')\n .description('List scenario executions')\n .option('-s, --scenario <scenarioId>', 'Filter by scenario ID')\n .option('--status <status>', 'Filter by status (queued, running, completed, failed, timeout, cancelled)')\n .option('-l, --limit <number>', 'Number of items', '10')\n .option('-p, --page <number>', 'Page number', '1')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl scenarios executions # List recent executions\n $ chanl scenarios executions --scenario abc123 # For specific scenario\n $ chanl scenarios executions --status completed # Only completed\n $ chanl scenarios executions --json # Output as JSON`\n )\n .action(handleScenariosExecutions);\n\n // scenarios execution <executionId>\n scenarios\n .command('execution <executionId>')\n .description('Get execution details')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl scenarios execution exec_abc123 # Get execution details\n $ chanl scenarios execution exec_abc123 --json`\n )\n .action(handleScenariosExecution);\n\n // scenarios history <scenarioId>\n scenarios\n .command('history <scenarioId>')\n .description('Get simulation history for a scenario')\n .option('-l, --limit <number>', 'Number of simulations to show', '10')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl scenarios history abc123 # Last 10 runs\n $ chanl scenarios history abc123 --limit 5 # Last 5 runs\n $ chanl scenarios history abc123 --json # Output as JSON`\n )\n .action(handleScenariosHistory);\n\n // scenarios run-all\n scenarios\n .command('run-all')\n .description('Run all scenarios for an agent and show aggregate results')\n .requiredOption('-a, --agent <agentId>', 'Agent ID to run scenarios against')\n .option('--min-score <score>', 'Minimum passing score (0-100)', '0')\n .option('--parallel <count>', 'Max concurrent executions', '3')\n .option('-m, --mode <mode>', 'Simulation mode: text, phone', 'text')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl scenarios run-all --agent agent_abc # Run all with defaults\n $ chanl scenarios run-all --agent agent_abc --min-score 80 # Fail if any score < 80\n $ chanl scenarios run-all --agent agent_abc --parallel 5 # Run 5 at a time\n $ chanl scenarios run-all --agent agent_abc --json # Output as JSON\n\nExit Codes:\n 0 All scenarios passed (score >= min-score)\n 1 One or more scenarios failed`\n )\n .action(handleScenariosRunAll);\n\n return scenarios;\n}\n\n/**\n * Handle scenarios list command\n */\nasync function handleScenariosList(options: {\n status?: string;\n category?: string;\n limit: string;\n page: string;\n}): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching scenarios...').start();\n\n try {\n const response = await sdk.scenarios.list({\n status: options.status,\n category: options.category,\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 scenarios', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { scenarios, pagination } = response.data;\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n if (scenarios.length === 0) {\n printInfo('No scenarios found');\n return;\n }\n\n printBlank();\n printSimpleTable(\n ['Name', 'Status', 'Category', 'Difficulty', 'Created'],\n scenarios.map((s) => [\n s.name,\n formatStatus(s.status),\n s.category || '-',\n s.difficulty || '-',\n formatDate(s.createdAt),\n ])\n );\n\n printBlank();\n printInfo(`Total: ${pagination.total} scenarios (Page ${pagination.page} of ${pagination.totalPages})`);\n } catch (error) {\n spinner.fail('Failed to fetch scenarios');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle scenarios get command\n */\nasync function handleScenariosGet(id: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching scenario...').start();\n\n try {\n const response = await sdk.scenarios.get(id);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch scenario', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const { scenario } = response.data;\n printBlank();\n console.log(chalk.bold('Scenario Details:'));\n console.log(` Name: ${scenario.name}`);\n console.log(` ID: ${scenario.id}`);\n console.log(` Status: ${formatStatus(scenario.status)}`);\n console.log(` Category: ${scenario.category || '-'}`);\n console.log(` Difficulty: ${scenario.difficulty || '-'}`);\n console.log(` Created: ${formatDate(scenario.createdAt)}`);\n if (scenario.description) {\n console.log(` Description: ${scenario.description}`);\n }\n printBlank();\n } catch (error) {\n spinner.fail('Failed to fetch scenario');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Format status with color\n */\nfunction formatStatus(status?: string): string {\n switch (status) {\n case 'active':\n return chalk.green('active');\n case 'paused':\n return chalk.yellow('paused');\n case 'completed':\n return chalk.blue('completed');\n case 'archived':\n return chalk.gray('archived');\n case 'draft':\n default:\n return chalk.gray(status || 'draft');\n }\n}\n\n/**\n * Format execution status with color\n */\nfunction formatExecutionStatus(status?: string): string {\n switch (status) {\n case 'completed':\n return chalk.green('completed');\n case 'running':\n return chalk.cyan('running');\n case 'queued':\n return chalk.blue('queued');\n case 'failed':\n return chalk.red('failed');\n case 'timeout':\n return chalk.yellow('timeout');\n case 'cancelled':\n return chalk.gray('cancelled');\n default:\n return chalk.gray(status || 'unknown');\n }\n}\n\n/**\n * Format score with color\n */\nfunction formatScore(score?: number): string {\n if (score === undefined || score === null) return '-';\n if (score >= 80) return chalk.green(`${score}%`);\n if (score >= 60) return chalk.yellow(`${score}%`);\n return chalk.red(`${score}%`);\n}\n\n/**\n * Format duration in seconds\n */\nfunction formatDuration(seconds?: number): string {\n if (!seconds) return '-';\n if (seconds < 60) return `${seconds.toFixed(1)}s`;\n const mins = Math.floor(seconds / 60);\n const secs = seconds % 60;\n return `${mins}m ${secs.toFixed(0)}s`;\n}\n\n/**\n * Handle scenarios run command\n */\nasync function handleScenariosRun(\n id: string,\n options: {\n agent?: string;\n mode?: string;\n phone?: string;\n watch?: boolean;\n dryRun?: boolean;\n }\n): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Starting scenario execution...').start();\n\n try {\n const response = await sdk.scenarios.run(id, {\n agentId: options.agent,\n simulationMode: options.mode as 'text' | 'websocket' | 'phone',\n phoneNumber: options.phone,\n dryRun: options.dryRun,\n });\n\n if (!response.success || !response.data) {\n spinner.fail('Failed to start execution');\n printError('Error', response.message || 'Unknown error');\n process.exitCode = 1;\n return;\n }\n\n const { execution, executionId } = response.data;\n const execId = executionId || execution?.id || execution?.executionId;\n\n if (options.dryRun) {\n spinner.succeed('Dry run validation passed');\n printInfo('Scenario is valid and ready to execute');\n return;\n }\n\n spinner.succeed(`Execution started: ${execId}`);\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n if (!options.watch) {\n printBlank();\n printLabel('Execution ID', execId || 'N/A');\n printLabel('Status', formatExecutionStatus(execution?.status));\n printInfo(`Run 'chanl scenarios execution ${execId}' to check status`);\n printBlank();\n return;\n }\n\n // Watch mode - poll until complete\n await watchExecution(sdk, execId!, options.mode === 'phone');\n } catch (error) {\n spinner.fail('Failed to execute scenario');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Watch execution until completion\n * Uses SDK LiveExecution for event-driven monitoring\n */\nasync function watchExecution(\n sdk: ChanlSDK,\n executionId: string,\n isPhoneMode = false,\n): Promise<void> {\n const startTime = new Date();\n let spinner = ora(\n isPhoneMode\n ? `${chalk.red('LIVE')} — ${formatElapsed(startTime)} | Watching voice execution...`\n : 'Watching execution...'\n ).start();\n\n const live = sdk.scenarios.watchExecution(executionId);\n let finalExecution: ScenarioExecution | undefined;\n let scorecardReceived = false;\n\n live.on('status', (status) => {\n if (isPhoneMode) {\n spinner.text = `${chalk.red('LIVE')} — ${formatElapsed(startTime)} | Status: ${status}`;\n } else {\n spinner.text = `Status: ${status}`;\n }\n });\n\n live.on('step', (step) => {\n if (!isPhoneMode) {\n spinner.stop();\n const stepStatus = step.status === 'completed' ? chalk.green('✓') : chalk.red('✗');\n console.log(` ${stepStatus} Step ${step.stepId}: ${step.response?.slice(0, 80) || '-'}`);\n if (step.toolCalls.length > 0) {\n for (const tc of step.toolCalls) {\n const tcIcon = tc.status === 'success' ? chalk.green('✓') : chalk.red('✗');\n const dur = tc.durationMs ? chalk.dim(` (${tc.durationMs}ms)`) : '';\n console.log(` ${tcIcon} ${chalk.yellow(tc.name)}${dur}`);\n }\n }\n spinner.start();\n }\n });\n\n live.on('transcript', (seg) => {\n spinner.stop();\n printSegment(seg);\n spinner.start();\n });\n\n live.on('completed', (execution) => {\n finalExecution = execution;\n const status = execution.status;\n\n if (status === 'completed') {\n spinner.succeed(\n isPhoneMode\n ? `Execution complete — ${formatElapsed(startTime)}`\n : 'Execution completed'\n );\n } else if (status === 'failed') {\n spinner.fail(\n isPhoneMode\n ? `Execution failed — ${formatElapsed(startTime)}`\n : 'Execution failed'\n );\n } else {\n spinner.warn(`Execution ${status}`);\n }\n\n printBlank();\n printExecutionDetails(execution);\n\n // Start scorecard spinner for phone mode\n if (isPhoneMode && execution.callDetails?.callId) {\n spinner = ora('Checking for scorecard...').start();\n }\n });\n\n live.on('scorecard', (results) => {\n scorecardReceived = true;\n spinner.stop();\n displayScorecard(results);\n printBlank();\n });\n\n live.on('timeout', () => {\n spinner.warn('Timeout waiting for execution to complete');\n printInfo(`Run 'chanl scenarios execution ${executionId}' to check status`);\n });\n\n live.on('error', (err) => {\n spinner.fail('Error while watching');\n printError('Error', err.message);\n process.exitCode = 1;\n });\n\n await live.completed;\n\n // Post-completion: if phone mode and no scorecard arrived, clean up spinner\n if (finalExecution && isPhoneMode && finalExecution.callDetails?.callId && !scorecardReceived) {\n spinner.stop();\n }\n}\n\n/**\n * Print execution details\n */\nfunction printExecutionDetails(execution: ScenarioExecution): void {\n console.log(chalk.bold('Execution Results:'));\n console.log(` Execution ID: ${execution.id || execution.executionId}`);\n console.log(` Scenario ID: ${execution.scenarioId}`);\n console.log(` Status: ${formatExecutionStatus(execution.status)}`);\n console.log(` Score: ${formatScore(execution.overallScore)}`);\n console.log(` Duration: ${formatDuration(execution.duration)}`);\n\n if (execution.metrics) {\n console.log(chalk.bold('\\n Metrics:'));\n if (execution.metrics.responseTime !== undefined) {\n console.log(` Response Time: ${execution.metrics.responseTime.toFixed(0)}ms`);\n }\n if (execution.metrics.accuracy !== undefined) {\n console.log(` Accuracy: ${formatScore(execution.metrics.accuracy)}`);\n }\n if (execution.metrics.completion !== undefined) {\n console.log(` Completion: ${formatScore(execution.metrics.completion)}`);\n }\n }\n\n if (execution.callDetails?.callId) {\n console.log(chalk.bold('\\n Call Details:'));\n console.log(` Call ID: ${execution.callDetails.callId}`);\n if (execution.callDetails.phoneNumber) {\n console.log(` Phone: ${execution.callDetails.phoneNumber}`);\n }\n }\n\n // Show tool calls from step results\n const allToolCalls = (execution.stepResults ?? []).flatMap((s) => s.toolCalls ?? []);\n if (allToolCalls.length > 0) {\n console.log(chalk.bold('\\n Tool Calls:'));\n printScenarioToolCalls(allToolCalls);\n }\n\n if (execution.errorMessages && execution.errorMessages.length > 0) {\n console.log(chalk.bold('\\n Errors:'));\n execution.errorMessages.forEach((msg) => {\n console.log(chalk.red(` - ${msg}`));\n });\n }\n\n printBlank();\n}\n\n/**\n * Print tool calls from scenario execution\n */\nfunction printScenarioToolCalls(toolCalls: ToolCall[]): void {\n for (const tc of toolCalls) {\n const statusIcon =\n tc.status === 'success'\n ? chalk.green('✓')\n : tc.status === 'error'\n ? chalk.red('✗')\n : tc.status === 'timeout'\n ? chalk.yellow('⏱')\n : chalk.dim('…');\n const duration = tc.durationMs ? chalk.dim(` (${tc.durationMs}ms)`) : '';\n const params = Object.keys(tc.parameters).length\n ? chalk.dim(` ${JSON.stringify(tc.parameters)}`)\n : '';\n\n console.log(` ${statusIcon} ${chalk.yellow(tc.name)}${params}${duration}`);\n\n if (tc.status === 'error' && tc.error) {\n console.log(` ${chalk.red(tc.error.message)}`);\n }\n }\n}\n\n/**\n * Handle scenarios executions command\n */\nasync function handleScenariosExecutions(options: {\n scenario?: string;\n status?: string;\n limit: string;\n page: string;\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.scenarios.getExecutions({\n scenarioId: options.scenario,\n status: options.status,\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 executions', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { executions, total } = response.data;\n\n if (isJsonOutput()) {\n printJson(response.data);\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', 'Scenario', 'Status', 'Score', 'Duration', 'Started'],\n executions.map((e) => [\n (e.id || e.executionId || '').slice(-12),\n e.scenarioId?.slice(-8) || '-',\n formatExecutionStatus(e.status),\n formatScore(e.overallScore),\n formatDuration(e.duration),\n e.startTime ? formatDate(e.startTime) : '-',\n ])\n );\n\n printBlank();\n printInfo(`Total: ${total} executions`);\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 scenarios execution command\n */\nasync function handleScenariosExecution(executionId: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching execution...').start();\n\n try {\n const response = await sdk.scenarios.getExecution(executionId);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch execution', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const { execution } = response.data;\n printBlank();\n printExecutionDetails(execution);\n } catch (error) {\n spinner.fail('Failed to fetch execution');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle scenarios history command\n */\nasync function handleScenariosHistory(\n scenarioId: string,\n options: { limit: string }\n): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching simulation history...').start();\n\n try {\n const response = await sdk.scenarios.getSimulations(\n scenarioId,\n parseInt(options.limit, 10)\n );\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch history', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { simulations } = response.data;\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n if (simulations.length === 0) {\n printInfo('No simulation history found for this scenario');\n return;\n }\n\n printBlank();\n console.log(chalk.bold(`Simulation History for ${scenarioId}`));\n console.log(chalk.dim('─'.repeat(60)));\n\n printSimpleTable(\n ['#', 'Status', 'Score', 'Duration', 'Started'],\n simulations.map((s, i) => [\n (i + 1).toString(),\n formatExecutionStatus(s.status),\n formatScore(s.overallScore),\n formatDuration(s.duration),\n s.startTime ? formatDate(s.startTime) : '-',\n ])\n );\n\n printBlank();\n printInfo(`Showing last ${simulations.length} simulations`);\n } catch (error) {\n spinner.fail('Failed to fetch history');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle scenarios run-all command\n */\nasync function handleScenariosRunAll(options: {\n agent: string;\n minScore: string;\n parallel: string;\n mode?: string;\n}): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const minScore = parseInt(options.minScore, 10);\n const parallel = parseInt(options.parallel, 10);\n\n const spinner = ora(`Running all scenarios for agent ${options.agent}...`).start();\n\n try {\n const result: BatchResult = await sdk.scenarios.runAll({\n agentId: options.agent,\n minScore,\n parallel,\n mode: options.mode as 'text' | 'phone' | undefined,\n });\n\n spinner.stop();\n\n if (isJsonOutput()) {\n printJson(result);\n if (!result.allPassed) {\n process.exitCode = 1;\n }\n return;\n }\n\n if (result.totalScenarios === 0) {\n printInfo('No active scenarios found for this agent');\n return;\n }\n\n printBlank();\n console.log(chalk.bold('Batch Scenario Results'));\n console.log(chalk.dim('─'.repeat(60)));\n\n // Per-scenario results\n printSimpleTable(\n ['Scenario', 'Status', 'Score', 'Duration', 'Tools', 'Result'],\n result.results.map((r) => [\n r.scenarioName,\n formatExecutionStatus(r.status),\n formatScore(r.score),\n formatDuration(r.duration),\n r.toolCallCount.toString(),\n r.passed ? chalk.green('PASS') : chalk.red('FAIL'),\n ])\n );\n\n // Summary\n printBlank();\n console.log(chalk.bold('Summary'));\n console.log(` Total: ${result.totalScenarios}`);\n console.log(` Passed: ${chalk.green(result.passed.toString())}`);\n console.log(` Failed: ${result.failed > 0 ? chalk.red(result.failed.toString()) : '0'}`);\n console.log(` Average Score: ${formatScore(result.averageScore)}`);\n console.log(` Min Score: ${result.minScore}`);\n\n printBlank();\n if (result.allPassed) {\n console.log(chalk.green(`All ${result.totalScenarios} scenarios passed`));\n } else {\n console.log(chalk.red(`${result.failed} of ${result.totalScenarios} scenarios failed`));\n process.exitCode = 1;\n }\n printBlank();\n } catch (error) {\n spinner.fail('Failed to run scenarios');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,8 @@
1
+ import { Command } from 'commander';
2
+
3
+ /**
4
+ * Create the scorecards command group
5
+ */
6
+ declare function createScorecardsCommand(): Command;
7
+
8
+ export { createScorecardsCommand };
@@ -184,7 +184,7 @@ async function handleScorecardsList(options) {
184
184
  );
185
185
  printBlank();
186
186
  if (pagination) {
187
- printInfo(`Total: ${pagination.total} scorecards (Page ${pagination.page} of ${pagination.pages})`);
187
+ printInfo(`Total: ${pagination.total} scorecards (Page ${pagination.page} of ${pagination.totalPages})`);
188
188
  }
189
189
  } catch (error) {
190
190
  spinner.fail("Failed to fetch scorecards");