@chanl/cli 2.0.4 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/__tests__/agents.test.js +574 -0
  2. package/dist/__tests__/agents.test.js.map +1 -0
  3. package/dist/__tests__/auth.test.d.ts +2 -0
  4. package/dist/__tests__/auth.test.js +87 -0
  5. package/dist/__tests__/auth.test.js.map +1 -0
  6. package/dist/__tests__/calls.test.d.ts +2 -0
  7. package/dist/__tests__/calls.test.js +115 -0
  8. package/dist/__tests__/calls.test.js.map +1 -0
  9. package/dist/__tests__/chat.test.d.ts +2 -0
  10. package/dist/__tests__/chat.test.js +357 -0
  11. package/dist/__tests__/chat.test.js.map +1 -0
  12. package/dist/__tests__/cli-base.test.d.ts +2 -0
  13. package/dist/__tests__/cli-base.test.js +87 -0
  14. package/dist/__tests__/cli-base.test.js.map +1 -0
  15. package/dist/__tests__/cli-missing.test.d.ts +2 -0
  16. package/dist/__tests__/cli-missing.test.js +546 -0
  17. package/dist/__tests__/cli-missing.test.js.map +1 -0
  18. package/dist/__tests__/cli-p0-scenarios.test.d.ts +2 -0
  19. package/dist/__tests__/cli-p0-scenarios.test.js +123 -0
  20. package/dist/__tests__/cli-p0-scenarios.test.js.map +1 -0
  21. package/dist/__tests__/helpers.d.ts +234 -0
  22. package/dist/__tests__/helpers.js +314 -0
  23. package/dist/__tests__/helpers.js.map +1 -0
  24. package/dist/__tests__/mcp.test.d.ts +2 -0
  25. package/dist/__tests__/mcp.test.js +470 -0
  26. package/dist/__tests__/mcp.test.js.map +1 -0
  27. package/dist/__tests__/prompts.test.d.ts +2 -0
  28. package/dist/__tests__/prompts.test.js +227 -0
  29. package/dist/__tests__/prompts.test.js.map +1 -0
  30. package/dist/__tests__/scenarios.test.d.ts +2 -0
  31. package/dist/__tests__/scenarios.test.js +270 -0
  32. package/dist/__tests__/scenarios.test.js.map +1 -0
  33. package/dist/__tests__/tools.test.d.ts +2 -0
  34. package/dist/__tests__/tools.test.js +331 -0
  35. package/dist/__tests__/tools.test.js.map +1 -0
  36. package/dist/__tests__/toolsets.test.d.ts +2 -0
  37. package/dist/__tests__/toolsets.test.js +196 -0
  38. package/dist/__tests__/toolsets.test.js.map +1 -0
  39. package/dist/__tests__/workspaces.test.d.ts +2 -0
  40. package/dist/__tests__/workspaces.test.js +155 -0
  41. package/dist/__tests__/workspaces.test.js.map +1 -0
  42. package/dist/cli.js +8 -0
  43. package/dist/cli.js.map +1 -1
  44. package/dist/commands/agents.js +194 -6
  45. package/dist/commands/agents.js.map +1 -1
  46. package/dist/commands/chat.js +2 -2
  47. package/dist/commands/chat.js.map +1 -1
  48. package/dist/commands/config.js +24 -2
  49. package/dist/commands/config.js.map +1 -1
  50. package/dist/commands/customers.d.ts +8 -0
  51. package/dist/commands/customers.js +289 -0
  52. package/dist/commands/customers.js.map +1 -0
  53. package/dist/commands/index.d.ts +3 -0
  54. package/dist/commands/index.js +7 -0
  55. package/dist/commands/index.js.map +1 -1
  56. package/dist/commands/memory.js +134 -1
  57. package/dist/commands/memory.js.map +1 -1
  58. package/dist/commands/messaging.d.ts +12 -0
  59. package/dist/commands/messaging.js +208 -0
  60. package/dist/commands/messaging.js.map +1 -0
  61. package/dist/commands/prompts.js +148 -1
  62. package/dist/commands/prompts.js.map +1 -1
  63. package/dist/commands/scenarios.js +121 -0
  64. package/dist/commands/scenarios.js.map +1 -1
  65. package/dist/commands/scorecards.js +3 -3
  66. package/dist/commands/scorecards.js.map +1 -1
  67. package/dist/commands/whatsapp.d.ts +8 -0
  68. package/dist/commands/whatsapp.js +332 -0
  69. package/dist/commands/whatsapp.js.map +1 -0
  70. package/dist/utils/config-store.d.ts +8 -0
  71. package/dist/utils/config-store.js +18 -1
  72. package/dist/utils/config-store.js.map +1 -1
  73. package/dist/utils/sdk-factory.js +15 -3
  74. package/dist/utils/sdk-factory.js.map +1 -1
  75. package/package.json +4 -4
  76. package/dist/__tests__/cli.test.js +0 -2308
  77. package/dist/__tests__/cli.test.js.map +0 -1
  78. /package/dist/__tests__/{cli.test.d.ts → agents.test.d.ts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/memory.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { readFile } from 'fs/promises';\nimport { confirm } from '@inquirer/prompts';\nimport ora from 'ora';\nimport chalk from 'chalk';\nimport type {\n Memory,\n MemorySearchResult,\n CreateMemoryInput,\n UpdateMemoryInput,\n SearchMemoryInput,\n MemoryEntityType,\n MemorySource,\n} from '@chanl/sdk';\nimport { createSdk } from '../utils/sdk-factory.js';\nimport {\n printSuccess,\n printError,\n printInfo,\n printLabel,\n printBlank,\n printSimpleTable,\n isJsonOutput,\n printJson,\n formatDate,\n} from '../utils/output.js';\n\n/**\n * Create the memory command group\n */\nexport function createMemoryCommand(): Command {\n const memory = new Command('memory').description('Manage agent memory');\n\n // memory list\n memory\n .command('list')\n .description('List memories with optional filters')\n .option('--entity-type <type>', 'Filter by entity type: customer, session, agent, conversation')\n .option('--entity-id <id>', 'Filter by entity ID')\n .option('--agent-id <id>', 'Filter by agent ID')\n .option('--source <source>', 'Filter by source: conversation, manual, extraction')\n .option('-l, --limit <number>', 'Items per page (default: 20)', '20')\n .option('-p, --page <number>', 'Page number (default: 1)', '1')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl memory list # List all memories\n $ chanl memory list --entity-type customer # Filter by entity type\n $ chanl memory list --entity-id cust_123 --limit 10 # Filter by entity ID\n $ chanl memory list --agent-id agent_abc # Filter by agent\n $ chanl memory list --source manual # Filter by source\n $ chanl memory list --json # Output as JSON`\n )\n .action(handleMemoryList);\n\n // memory get <id>\n memory\n .command('get <id>')\n .description('Get detailed info about a memory')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl memory get 680a1b2c3d4e5f6789012345\n $ chanl memory get 680a1b2c3d4e5f6789012345 --json`\n )\n .action(handleMemoryGet);\n\n // memory create\n memory\n .command('create')\n .description('Create a new memory')\n .option('--entity-type <type>', 'Entity type: customer, session, agent, conversation')\n .option('--entity-id <id>', 'Entity ID')\n .option('--content <text>', 'Memory content text')\n .option('--agent-id <id>', 'Optional agent scope')\n .option('--source <source>', 'Source: conversation, manual, extraction')\n .option('--ttl <seconds>', 'Time-to-live in seconds')\n .option('-f, --file <path>', 'Path to JSON file with memory definition (overrides other options)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl memory create --entity-type customer --entity-id cust_123 --content \"Prefers email\"\n $ chanl memory create --entity-type customer --entity-id cust_123 --content \"VIP\" --source manual\n $ chanl memory create --entity-type customer --entity-id cust_123 --content \"Note\" --ttl 86400\n $ chanl memory create -f memory.json\n\nRequired (unless using -f):\n --entity-type Entity type\n --entity-id Entity ID\n --content Memory content text\n\nOptional:\n --agent-id Scope to a specific agent\n --source Memory source (sets metadata.source)\n --ttl TTL in seconds\n -f, --file JSON file (overrides all other options)`\n )\n .action(handleMemoryCreate);\n\n // memory update <id>\n memory\n .command('update <id>')\n .description('Update an existing memory')\n .option('--content <text>', 'Updated content text')\n .option('--deactivate', 'Deactivate the memory (sets isActive: false)')\n .option('--activate', 'Reactivate the memory (sets isActive: true)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl memory update 680a1b2c3d4e5f6789012345 --content \"Updated preference\"\n $ chanl memory update 680a1b2c3d4e5f6789012345 --deactivate\n $ chanl memory update 680a1b2c3d4e5f6789012345 --activate\n $ chanl memory update 680a1b2c3d4e5f6789012345 --content \"New text\" --deactivate`\n )\n .action(handleMemoryUpdate);\n\n // memory delete <id>\n memory\n .command('delete <id>')\n .description('Delete a memory permanently')\n .option('-y, --yes', 'Skip confirmation prompt')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl memory delete 680a1b2c3d4e5f6789012345 # With confirmation\n $ chanl memory delete 680a1b2c3d4e5f6789012345 -y # Skip confirmation`\n )\n .action(handleMemoryDelete);\n\n // memory search\n memory\n .command('search')\n .description('Search memories using semantic similarity')\n .option('--entity-type <type>', 'Entity type (required): customer, session, agent, conversation')\n .option('--entity-id <id>', 'Entity ID (required)')\n .option('--query <text>', 'Search query text (required)')\n .option('--agent-id <id>', 'Optional agent scope filter')\n .option('-l, --limit <number>', 'Maximum results')\n .option('--min-score <number>', 'Minimum relevance score (0-1)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl memory search --entity-type customer --entity-id cust_123 --query \"email preferences\"\n $ chanl memory search --entity-type customer --entity-id cust_123 --query \"contact\" --limit 5\n $ chanl memory search --entity-type customer --entity-id cust_123 --query \"VIP\" --min-score 0.8\n $ chanl memory search --entity-type customer --entity-id cust_123 --query \"test\" --json`\n )\n .action(handleMemorySearch);\n\n return memory;\n}\n\n// ============================================================================\n// Helpers (module-local)\n// ============================================================================\n\n/**\n * Truncate a string to a max length, appending '...' if truncated\n */\nfunction truncate(str: string, maxLen: number): string {\n if (str.length <= maxLen) return str;\n return str.substring(0, maxLen - 3) + '...';\n}\n\n// ============================================================================\n// Command Handlers\n// ============================================================================\n\n/**\n * Handle memory list command\n */\nasync function handleMemoryList(options: {\n entityType?: string;\n entityId?: string;\n agentId?: string;\n source?: string;\n limit: string;\n page: string;\n}): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching memories...').start();\n\n try {\n const response = await sdk.memory.list({\n entityType: options.entityType as MemoryEntityType | undefined,\n entityId: options.entityId,\n agentId: options.agentId,\n source: options.source as MemorySource | undefined,\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 memories', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { memories, total, pagination } = response.data;\n\n if (isJsonOutput()) {\n printJson({ memories, total, pagination });\n return;\n }\n\n if (memories.length === 0) {\n printInfo('No memories found');\n return;\n }\n\n printBlank();\n printSimpleTable(\n ['ID', 'Entity Type', 'Entity ID', 'Content', 'Source', 'Active', 'Created'],\n memories.map((m: Memory) => [\n truncate(m.id, 12),\n m.entityType,\n m.entityId,\n truncate(m.content, 50),\n m.metadata?.source || 'unknown',\n m.isActive ? chalk.green('Yes') : chalk.red('No'),\n formatDate(m.createdAt),\n ])\n );\n\n printBlank();\n if (pagination) {\n printInfo(`Total: ${total} memories (Page ${pagination.page} of ${pagination.totalPages})`);\n } else {\n printInfo(`Total: ${total} memories`);\n }\n } catch (error) {\n spinner.fail('Failed to fetch memories');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle memory get command\n */\nasync function handleMemoryGet(id: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching memory...').start();\n\n try {\n const response = await sdk.memory.get(id);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch memory', response.message);\n process.exitCode = 1;\n return;\n }\n\n const memory = response.data;\n\n if (isJsonOutput()) {\n printJson(memory);\n return;\n }\n\n printBlank();\n printMemoryDetails(memory);\n } catch (error) {\n spinner.fail('Failed to fetch memory');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle memory create command\n */\nasync function handleMemoryCreate(options: {\n entityType?: string;\n entityId?: string;\n content?: string;\n agentId?: string;\n source?: string;\n ttl?: string;\n file?: string;\n}): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n let input: CreateMemoryInput;\n\n if (options.file) {\n // Read from JSON file\n try {\n const content = await readFile(options.file, 'utf-8');\n input = JSON.parse(content);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Failed to read file', message);\n process.exitCode = 1;\n return;\n }\n } else {\n // Build from individual options\n if (!options.entityType || !options.entityId || !options.content) {\n printError(\n 'Missing required options',\n \"Provide --entity-type, --entity-id, and --content, or use '-f <path>' for JSON file\"\n );\n printInfo(\"Run 'chanl memory create --help' for usage\");\n process.exitCode = 1;\n return;\n }\n\n input = {\n entityType: options.entityType as MemoryEntityType,\n entityId: options.entityId,\n content: options.content,\n };\n\n if (options.agentId) {\n input.agentId = options.agentId;\n }\n\n if (options.source) {\n input.metadata = { ...input.metadata, source: options.source as MemorySource };\n }\n\n if (options.ttl) {\n const ttl = parseInt(options.ttl, 10);\n if (isNaN(ttl) || ttl <= 0) {\n printError('Invalid TTL value', 'TTL must be a positive number of seconds');\n process.exitCode = 1;\n return;\n }\n input.ttlSeconds = ttl;\n }\n }\n\n const spinner = ora('Creating memory...').start();\n\n try {\n const response = await sdk.memory.create(input);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to create memory', response.message);\n process.exitCode = 1;\n return;\n }\n\n const memory = response.data;\n\n if (isJsonOutput()) {\n printJson({ success: true, memory });\n return;\n }\n\n printSuccess(`Created memory: ${memory.id}`);\n } catch (error) {\n spinner.fail('Failed to create memory');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle memory update command\n */\nasync function handleMemoryUpdate(\n id: string,\n options: {\n content?: string;\n deactivate?: boolean;\n activate?: boolean;\n }\n): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const input: UpdateMemoryInput = {};\n\n if (options.content) {\n input.content = options.content;\n }\n\n if (options.deactivate) {\n input.isActive = false;\n }\n\n if (options.activate) {\n input.isActive = true;\n }\n\n if (!options.content && !options.deactivate && !options.activate) {\n printError('No updates specified', 'Provide --content, --deactivate, or --activate');\n process.exitCode = 1;\n return;\n }\n\n const spinner = ora('Updating memory...').start();\n\n try {\n const response = await sdk.memory.update(id, input);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to update memory', response.message);\n process.exitCode = 1;\n return;\n }\n\n const memory = response.data;\n\n if (isJsonOutput()) {\n printJson({ success: true, memory });\n return;\n }\n\n printSuccess(`Updated memory: ${memory.id}`);\n } catch (error) {\n spinner.fail('Failed to update memory');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle memory delete command\n */\nasync function handleMemoryDelete(id: string, options: { yes?: boolean }): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n // Confirm deletion unless --yes flag is provided\n if (!options.yes) {\n try {\n const confirmed = await confirm({\n message: `Are you sure you want to delete memory '${id}'?`,\n default: false,\n });\n\n if (!confirmed) {\n printInfo('Deletion cancelled');\n return;\n }\n } catch {\n // User cancelled (Ctrl+C)\n printBlank();\n printInfo('Deletion cancelled');\n return;\n }\n }\n\n const spinner = ora('Deleting memory...').start();\n\n try {\n const response = await sdk.memory.delete(id);\n\n spinner.stop();\n\n if (!response.success) {\n printError('Failed to delete memory', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson({ success: true, deleted: true, id });\n return;\n }\n\n printSuccess(`Deleted memory: ${id}`);\n } catch (error) {\n spinner.fail('Failed to delete memory');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle memory search command\n */\nasync function handleMemorySearch(options: {\n entityType?: string;\n entityId?: string;\n query?: string;\n agentId?: string;\n limit?: string;\n minScore?: string;\n}): Promise<void> {\n if (!options.entityType || !options.entityId || !options.query) {\n printError('Missing required options', 'Provide --entity-type, --entity-id, and --query');\n printInfo(\"Run 'chanl memory search --help' for usage\");\n process.exitCode = 1;\n return;\n }\n\n const sdk = createSdk();\n if (!sdk) return;\n\n const input: SearchMemoryInput = {\n entityType: options.entityType as MemoryEntityType,\n entityId: options.entityId,\n query: options.query,\n };\n\n if (options.agentId) {\n input.agentId = options.agentId;\n }\n\n if (options.limit) {\n input.limit = parseInt(options.limit, 10);\n }\n\n if (options.minScore) {\n input.minScore = parseFloat(options.minScore);\n }\n\n const spinner = ora('Searching memories...').start();\n\n try {\n const response = await sdk.memory.search(input);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to search memories', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { memories } = response.data;\n\n if (isJsonOutput()) {\n printJson({ memories });\n return;\n }\n\n if (memories.length === 0) {\n printInfo('No matching memories found');\n return;\n }\n\n printBlank();\n printSimpleTable(\n ['ID', 'Score', 'Content', 'Entity Type', 'Entity ID'],\n memories.map((m: MemorySearchResult) => [\n truncate(m.id, 12),\n (m.score ?? 0).toFixed(2),\n truncate(m.content, 50),\n m.entityType,\n m.entityId,\n ])\n );\n\n printBlank();\n printInfo(`Found ${memories.length} matching memories`);\n } catch (error) {\n spinner.fail('Failed to search memories');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n// ============================================================================\n// Display Helpers\n// ============================================================================\n\n/**\n * Print memory details in formatted output\n */\nfunction printMemoryDetails(memory: Memory): void {\n printLabel('ID', memory.id);\n printLabel('Entity Type', memory.entityType);\n printLabel('Entity ID', memory.entityId);\n\n printBlank();\n printInfo('Content:');\n console.log(chalk.gray(memory.content));\n\n if (memory.agentId) {\n printBlank();\n printLabel('Agent ID', memory.agentId);\n }\n\n printBlank();\n printLabel('Active', memory.isActive ? chalk.green('Yes') : chalk.red('No'));\n\n if (memory.metadata && Object.keys(memory.metadata).length > 0) {\n printBlank();\n printInfo('Metadata:');\n console.log(chalk.gray(JSON.stringify(memory.metadata, null, 2)));\n }\n\n if (memory.expiresAt) {\n printLabel('Expires', formatDate(memory.expiresAt));\n }\n\n printBlank();\n printLabel('Created', formatDate(memory.createdAt));\n if (memory.updatedAt) {\n printLabel('Updated', formatDate(memory.updatedAt));\n }\n printBlank();\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/commands/memory.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { readFile } from 'fs/promises';\nimport { confirm } from '@inquirer/prompts';\nimport ora from 'ora';\nimport chalk from 'chalk';\nimport type {\n Memory,\n MemorySearchResult,\n CreateMemoryInput,\n UpdateMemoryInput,\n SearchMemoryInput,\n GlobalSearchMemoryInput,\n MemoryStats,\n MemoryEntityType,\n MemorySource,\n} from '@chanl/sdk';\nimport { createSdk } from '../utils/sdk-factory.js';\nimport {\n printSuccess,\n printError,\n printInfo,\n printLabel,\n printBlank,\n printSimpleTable,\n isJsonOutput,\n printJson,\n formatDate,\n} from '../utils/output.js';\n\n/**\n * Create the memory command group\n */\nexport function createMemoryCommand(): Command {\n const memory = new Command('memory').description('Manage agent memory');\n\n // memory list\n memory\n .command('list')\n .description('List memories with optional filters')\n .option('--entity-type <type>', 'Filter by entity type: customer, session, agent, conversation')\n .option('--entity-id <id>', 'Filter by entity ID')\n .option('--agent-id <id>', 'Filter by agent ID')\n .option('--source <source>', 'Filter by source: conversation, manual, extraction')\n .option('-l, --limit <number>', 'Items per page (default: 20)', '20')\n .option('-p, --page <number>', 'Page number (default: 1)', '1')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl memory list # List all memories\n $ chanl memory list --entity-type customer # Filter by entity type\n $ chanl memory list --entity-id cust_123 --limit 10 # Filter by entity ID\n $ chanl memory list --agent-id agent_abc # Filter by agent\n $ chanl memory list --source manual # Filter by source\n $ chanl memory list --json # Output as JSON`\n )\n .action(handleMemoryList);\n\n // memory get <id>\n memory\n .command('get <id>')\n .description('Get detailed info about a memory')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl memory get 680a1b2c3d4e5f6789012345\n $ chanl memory get 680a1b2c3d4e5f6789012345 --json`\n )\n .action(handleMemoryGet);\n\n // memory create\n memory\n .command('create')\n .description('Create a new memory')\n .option('--entity-type <type>', 'Entity type: customer, session, agent, conversation')\n .option('--entity-id <id>', 'Entity ID')\n .option('--content <text>', 'Memory content text')\n .option('--agent-id <id>', 'Optional agent scope')\n .option('--source <source>', 'Source: conversation, manual, extraction')\n .option('--ttl <seconds>', 'Time-to-live in seconds')\n .option('-f, --file <path>', 'Path to JSON file with memory definition (overrides other options)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl memory create --entity-type customer --entity-id cust_123 --content \"Prefers email\"\n $ chanl memory create --entity-type customer --entity-id cust_123 --content \"VIP\" --source manual\n $ chanl memory create --entity-type customer --entity-id cust_123 --content \"Note\" --ttl 86400\n $ chanl memory create -f memory.json\n\nRequired (unless using -f):\n --entity-type Entity type\n --entity-id Entity ID\n --content Memory content text\n\nOptional:\n --agent-id Scope to a specific agent\n --source Memory source (sets metadata.source)\n --ttl TTL in seconds\n -f, --file JSON file (overrides all other options)`\n )\n .action(handleMemoryCreate);\n\n // memory update <id>\n memory\n .command('update <id>')\n .description('Update an existing memory')\n .option('--content <text>', 'Updated content text')\n .option('--deactivate', 'Deactivate the memory (sets isActive: false)')\n .option('--activate', 'Reactivate the memory (sets isActive: true)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl memory update 680a1b2c3d4e5f6789012345 --content \"Updated preference\"\n $ chanl memory update 680a1b2c3d4e5f6789012345 --deactivate\n $ chanl memory update 680a1b2c3d4e5f6789012345 --activate\n $ chanl memory update 680a1b2c3d4e5f6789012345 --content \"New text\" --deactivate`\n )\n .action(handleMemoryUpdate);\n\n // memory delete <id>\n memory\n .command('delete <id>')\n .description('Delete a memory permanently')\n .option('-y, --yes', 'Skip confirmation prompt')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl memory delete 680a1b2c3d4e5f6789012345 # With confirmation\n $ chanl memory delete 680a1b2c3d4e5f6789012345 -y # Skip confirmation`\n )\n .action(handleMemoryDelete);\n\n // memory search\n memory\n .command('search')\n .description('Search memories using semantic similarity')\n .option('--entity-type <type>', 'Entity type (required): customer, session, agent, conversation')\n .option('--entity-id <id>', 'Entity ID (required)')\n .option('--query <text>', 'Search query text (required)')\n .option('--agent-id <id>', 'Optional agent scope filter')\n .option('-l, --limit <number>', 'Maximum results')\n .option('--min-score <number>', 'Minimum relevance score (0-1)')\n .option('--min-confidence <number>', 'Minimum extraction confidence (0-1)')\n .option('--created-after <iso>', 'Only memories created at/after this ISO-8601 timestamp')\n .option('--created-before <iso>', 'Only memories created at/before this ISO-8601 timestamp')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl memory search --entity-type customer --entity-id cust_123 --query \"email preferences\"\n $ chanl memory search --entity-type customer --entity-id cust_123 --query \"contact\" --limit 5\n $ chanl memory search --entity-type customer --entity-id cust_123 --query \"VIP\" --min-score 0.8\n $ chanl memory search --entity-type customer --entity-id cust_123 --query \"recent\" --created-after 2026-05-01T00:00:00Z\n $ chanl memory search --entity-type customer --entity-id cust_123 --query \"test\" --json`\n )\n .action(handleMemorySearch);\n\n // memory search-global\n memory\n .command('search-global')\n .description('Search ALL memories in the workspace (no entity scope)')\n .option('--query <text>', 'Search query text (required)')\n .option('--entity-type <type>', 'Optional: narrow to an entity type')\n .option('--agent-id <id>', 'Optional agent scope filter')\n .option('--source <source>', 'Filter by source: conversation, manual, extraction')\n .option('-l, --limit <number>', 'Maximum results')\n .option('--min-score <number>', 'Minimum relevance score (0-1)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl memory search-global --query \"billing preferences\"\n $ chanl memory search-global --query \"VIP\" --entity-type customer --limit 10\n $ chanl memory search-global --query \"test\" --json`\n )\n .action(handleMemorySearchGlobal);\n\n // memory stats\n memory\n .command('stats')\n .description('Aggregate memory statistics (totals, by type/source, top-accessed)')\n .option('--entity-type <type>', 'Optionally scope stats to an entity type')\n .option('--entity-id <id>', 'Optionally scope stats to an entity ID')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl memory stats # Workspace-wide\n $ chanl memory stats --entity-type customer --entity-id cust_123\n $ chanl memory stats --json`\n )\n .action(handleMemoryStats);\n\n return memory;\n}\n\n// ============================================================================\n// Helpers (module-local)\n// ============================================================================\n\n/**\n * Truncate a string to a max length, appending '...' if truncated\n */\nfunction truncate(str: string, maxLen: number): string {\n if (str.length <= maxLen) return str;\n return str.substring(0, maxLen - 3) + '...';\n}\n\n// ============================================================================\n// Command Handlers\n// ============================================================================\n\n/**\n * Handle memory list command\n */\nasync function handleMemoryList(options: {\n entityType?: string;\n entityId?: string;\n agentId?: string;\n source?: string;\n limit: string;\n page: string;\n}): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching memories...').start();\n\n try {\n const response = await sdk.memory.list({\n entityType: options.entityType as MemoryEntityType | undefined,\n entityId: options.entityId,\n agentId: options.agentId,\n source: options.source as MemorySource | undefined,\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 memories', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { memories, total, pagination } = response.data;\n\n if (isJsonOutput()) {\n printJson({ memories, total, pagination });\n return;\n }\n\n if (memories.length === 0) {\n printInfo('No memories found');\n return;\n }\n\n printBlank();\n printSimpleTable(\n ['ID', 'Entity Type', 'Entity ID', 'Content', 'Source', 'Active', 'Created'],\n memories.map((m: Memory) => [\n truncate(m.id, 12),\n m.entityType,\n m.entityId,\n truncate(m.content, 50),\n m.metadata?.source || 'unknown',\n m.isActive ? chalk.green('Yes') : chalk.red('No'),\n formatDate(m.createdAt),\n ])\n );\n\n printBlank();\n if (pagination) {\n printInfo(`Total: ${total} memories (Page ${pagination.page} of ${pagination.totalPages})`);\n } else {\n printInfo(`Total: ${total} memories`);\n }\n } catch (error) {\n spinner.fail('Failed to fetch memories');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle memory get command\n */\nasync function handleMemoryGet(id: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching memory...').start();\n\n try {\n const response = await sdk.memory.get(id);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch memory', response.message);\n process.exitCode = 1;\n return;\n }\n\n const memory = response.data;\n\n if (isJsonOutput()) {\n printJson(memory);\n return;\n }\n\n printBlank();\n printMemoryDetails(memory);\n } catch (error) {\n spinner.fail('Failed to fetch memory');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle memory create command\n */\nasync function handleMemoryCreate(options: {\n entityType?: string;\n entityId?: string;\n content?: string;\n agentId?: string;\n source?: string;\n ttl?: string;\n file?: string;\n}): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n let input: CreateMemoryInput;\n\n if (options.file) {\n // Read from JSON file\n try {\n const content = await readFile(options.file, 'utf-8');\n input = JSON.parse(content);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Failed to read file', message);\n process.exitCode = 1;\n return;\n }\n } else {\n // Build from individual options\n if (!options.entityType || !options.entityId || !options.content) {\n printError(\n 'Missing required options',\n \"Provide --entity-type, --entity-id, and --content, or use '-f <path>' for JSON file\"\n );\n printInfo(\"Run 'chanl memory create --help' for usage\");\n process.exitCode = 1;\n return;\n }\n\n input = {\n entityType: options.entityType as MemoryEntityType,\n entityId: options.entityId,\n content: options.content,\n };\n\n if (options.agentId) {\n input.agentId = options.agentId;\n }\n\n if (options.source) {\n input.metadata = { ...input.metadata, source: options.source as MemorySource };\n }\n\n if (options.ttl) {\n const ttl = parseInt(options.ttl, 10);\n if (isNaN(ttl) || ttl <= 0) {\n printError('Invalid TTL value', 'TTL must be a positive number of seconds');\n process.exitCode = 1;\n return;\n }\n input.ttlSeconds = ttl;\n }\n }\n\n const spinner = ora('Creating memory...').start();\n\n try {\n const response = await sdk.memory.create(input);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to create memory', response.message);\n process.exitCode = 1;\n return;\n }\n\n const memory = response.data;\n\n if (isJsonOutput()) {\n printJson({ success: true, memory });\n return;\n }\n\n printSuccess(`Created memory: ${memory.id}`);\n } catch (error) {\n spinner.fail('Failed to create memory');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle memory update command\n */\nasync function handleMemoryUpdate(\n id: string,\n options: {\n content?: string;\n deactivate?: boolean;\n activate?: boolean;\n }\n): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const input: UpdateMemoryInput = {};\n\n if (options.content) {\n input.content = options.content;\n }\n\n if (options.deactivate) {\n input.isActive = false;\n }\n\n if (options.activate) {\n input.isActive = true;\n }\n\n if (!options.content && !options.deactivate && !options.activate) {\n printError('No updates specified', 'Provide --content, --deactivate, or --activate');\n process.exitCode = 1;\n return;\n }\n\n const spinner = ora('Updating memory...').start();\n\n try {\n const response = await sdk.memory.update(id, input);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to update memory', response.message);\n process.exitCode = 1;\n return;\n }\n\n const memory = response.data;\n\n if (isJsonOutput()) {\n printJson({ success: true, memory });\n return;\n }\n\n printSuccess(`Updated memory: ${memory.id}`);\n } catch (error) {\n spinner.fail('Failed to update memory');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle memory delete command\n */\nasync function handleMemoryDelete(id: string, options: { yes?: boolean }): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n // Confirm deletion unless --yes flag is provided\n if (!options.yes) {\n try {\n const confirmed = await confirm({\n message: `Are you sure you want to delete memory '${id}'?`,\n default: false,\n });\n\n if (!confirmed) {\n printInfo('Deletion cancelled');\n return;\n }\n } catch {\n // User cancelled (Ctrl+C)\n printBlank();\n printInfo('Deletion cancelled');\n return;\n }\n }\n\n const spinner = ora('Deleting memory...').start();\n\n try {\n const response = await sdk.memory.delete(id);\n\n spinner.stop();\n\n if (!response.success) {\n printError('Failed to delete memory', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson({ success: true, deleted: true, id });\n return;\n }\n\n printSuccess(`Deleted memory: ${id}`);\n } catch (error) {\n spinner.fail('Failed to delete memory');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle memory search command\n */\nasync function handleMemorySearch(options: {\n entityType?: string;\n entityId?: string;\n query?: string;\n agentId?: string;\n limit?: string;\n minScore?: string;\n minConfidence?: string;\n createdAfter?: string;\n createdBefore?: string;\n}): Promise<void> {\n if (!options.entityType || !options.entityId || !options.query) {\n printError('Missing required options', 'Provide --entity-type, --entity-id, and --query');\n printInfo(\"Run 'chanl memory search --help' for usage\");\n process.exitCode = 1;\n return;\n }\n\n const sdk = createSdk();\n if (!sdk) return;\n\n const input: SearchMemoryInput = {\n entityType: options.entityType as MemoryEntityType,\n entityId: options.entityId,\n query: options.query,\n };\n\n if (options.agentId) {\n input.agentId = options.agentId;\n }\n\n if (options.limit) {\n input.limit = parseInt(options.limit, 10);\n }\n\n if (options.minScore) {\n input.minScore = parseFloat(options.minScore);\n }\n\n if (options.minConfidence) {\n input.minConfidence = parseFloat(options.minConfidence);\n }\n\n if (options.createdAfter) {\n input.createdAfter = options.createdAfter;\n }\n\n if (options.createdBefore) {\n input.createdBefore = options.createdBefore;\n }\n\n const spinner = ora('Searching memories...').start();\n\n try {\n const response = await sdk.memory.search(input);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to search memories', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { memories } = response.data;\n\n if (isJsonOutput()) {\n printJson({ memories });\n return;\n }\n\n if (memories.length === 0) {\n printInfo('No matching memories found');\n return;\n }\n\n printBlank();\n printSimpleTable(\n ['ID', 'Score', 'Content', 'Entity Type', 'Entity ID'],\n memories.map((m: MemorySearchResult) => [\n truncate(m.id, 12),\n (m.score ?? 0).toFixed(2),\n truncate(m.content, 50),\n m.entityType,\n m.entityId,\n ])\n );\n\n printBlank();\n printInfo(`Found ${memories.length} matching memories`);\n } catch (error) {\n spinner.fail('Failed to search memories');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle memory search-global command\n */\nasync function handleMemorySearchGlobal(options: {\n query?: string;\n entityType?: string;\n agentId?: string;\n source?: string;\n limit?: string;\n minScore?: string;\n}): Promise<void> {\n if (!options.query) {\n printError('Missing required option', 'Provide --query');\n printInfo(\"Run 'chanl memory search-global --help' for usage\");\n process.exitCode = 1;\n return;\n }\n\n const sdk = createSdk();\n if (!sdk) return;\n\n const input: GlobalSearchMemoryInput = { query: options.query };\n if (options.entityType) input.entityType = options.entityType as MemoryEntityType;\n if (options.agentId) input.agentId = options.agentId;\n if (options.source) input.source = options.source as MemorySource;\n if (options.limit) input.limit = parseInt(options.limit, 10);\n if (options.minScore) input.minScore = parseFloat(options.minScore);\n\n const spinner = ora('Searching all memories...').start();\n\n try {\n const response = await sdk.memory.searchGlobal(input);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to search memories', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { memories } = response.data;\n\n if (isJsonOutput()) {\n printJson({ memories });\n return;\n }\n\n if (memories.length === 0) {\n printInfo('No matching memories found');\n return;\n }\n\n printBlank();\n printSimpleTable(\n ['ID', 'Score', 'Content', 'Entity Type', 'Entity ID'],\n memories.map((m: MemorySearchResult) => [\n truncate(m.id, 12),\n (m.score ?? 0).toFixed(2),\n truncate(m.content, 50),\n m.entityType,\n m.entityId,\n ])\n );\n\n printBlank();\n printInfo(`Found ${memories.length} matching memories`);\n } catch (error) {\n spinner.fail('Failed to search memories');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle memory stats command\n */\nasync function handleMemoryStats(options: {\n entityType?: string;\n entityId?: string;\n}): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Aggregating memory stats...').start();\n\n try {\n const response = await sdk.memory.stats({\n entityType: options.entityType as MemoryEntityType | undefined,\n entityId: options.entityId,\n });\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch memory stats', response.message);\n process.exitCode = 1;\n return;\n }\n\n const stats: MemoryStats = response.data;\n\n if (isJsonOutput()) {\n printJson(stats);\n return;\n }\n\n printBlank();\n printLabel('Total', String(stats.total));\n printLabel('Active', chalk.green(String(stats.active)));\n printLabel('Inactive', String(stats.inactive));\n printLabel('Expired', stats.expired > 0 ? chalk.yellow(String(stats.expired)) : '0');\n printLabel('Avg confidence', stats.avgConfidence.toFixed(3));\n\n printBlank();\n printInfo('By type:');\n printSimpleTable(\n ['Entity Type', 'Count'],\n Object.entries(stats.byType).map(([k, v]) => [k, String(v)])\n );\n\n printBlank();\n printInfo('By source:');\n printSimpleTable(\n ['Source', 'Count'],\n Object.entries(stats.bySource).map(([k, v]) => [k, String(v)])\n );\n\n if (stats.topAccessed.length > 0) {\n printBlank();\n printInfo('Top accessed:');\n printSimpleTable(\n ['ID', 'Access Count', 'Content'],\n stats.topAccessed.map((t) => [truncate(t.id, 12), String(t.accessCount), truncate(t.content, 50)])\n );\n }\n printBlank();\n } catch (error) {\n spinner.fail('Failed to fetch memory stats');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n// ============================================================================\n// Display Helpers\n// ============================================================================\n\n/**\n * Print memory details in formatted output\n */\nfunction printMemoryDetails(memory: Memory): void {\n printLabel('ID', memory.id);\n printLabel('Entity Type', memory.entityType);\n printLabel('Entity ID', memory.entityId);\n\n printBlank();\n printInfo('Content:');\n console.log(chalk.gray(memory.content));\n\n if (memory.agentId) {\n printBlank();\n printLabel('Agent ID', memory.agentId);\n }\n\n printBlank();\n printLabel('Active', memory.isActive ? chalk.green('Yes') : chalk.red('No'));\n\n if (memory.metadata && Object.keys(memory.metadata).length > 0) {\n printBlank();\n printInfo('Metadata:');\n console.log(chalk.gray(JSON.stringify(memory.metadata, null, 2)));\n }\n\n if (memory.expiresAt) {\n printLabel('Expires', formatDate(memory.expiresAt));\n }\n\n printBlank();\n printLabel('Created', formatDate(memory.createdAt));\n if (memory.updatedAt) {\n printLabel('Updated', formatDate(memory.updatedAt));\n }\n printBlank();\n}\n"],"mappings":"AAAA,SAAS,eAAe;AACxB,SAAS,gBAAgB;AACzB,SAAS,eAAe;AACxB,OAAO,SAAS;AAChB,OAAO,WAAW;AAYlB,SAAS,iBAAiB;AAC1B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAKA,SAAS,sBAA+B;AAC7C,QAAM,SAAS,IAAI,QAAQ,QAAQ,EAAE,YAAY,qBAAqB;AAGtE,SACG,QAAQ,MAAM,EACd,YAAY,qCAAqC,EACjD,OAAO,wBAAwB,+DAA+D,EAC9F,OAAO,oBAAoB,qBAAqB,EAChD,OAAO,mBAAmB,oBAAoB,EAC9C,OAAO,qBAAqB,oDAAoD,EAChF,OAAO,wBAAwB,gCAAgC,IAAI,EACnE,OAAO,uBAAuB,4BAA4B,GAAG,EAC7D;AAAA,IACC;AAAA,IACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQF,EACC,OAAO,gBAAgB;AAG1B,SACG,QAAQ,UAAU,EAClB,YAAY,kCAAkC,EAC9C;AAAA,IACC;AAAA,IACA;AAAA;AAAA;AAAA;AAAA,EAIF,EACC,OAAO,eAAe;AAGzB,SACG,QAAQ,QAAQ,EAChB,YAAY,qBAAqB,EACjC,OAAO,wBAAwB,qDAAqD,EACpF,OAAO,oBAAoB,WAAW,EACtC,OAAO,oBAAoB,qBAAqB,EAChD,OAAO,mBAAmB,sBAAsB,EAChD,OAAO,qBAAqB,0CAA0C,EACtE,OAAO,mBAAmB,yBAAyB,EACnD,OAAO,qBAAqB,oEAAoE,EAChG;AAAA,IACC;AAAA,IACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBF,EACC,OAAO,kBAAkB;AAG5B,SACG,QAAQ,aAAa,EACrB,YAAY,2BAA2B,EACvC,OAAO,oBAAoB,sBAAsB,EACjD,OAAO,gBAAgB,8CAA8C,EACrE,OAAO,cAAc,6CAA6C,EAClE;AAAA,IACC;AAAA,IACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMF,EACC,OAAO,kBAAkB;AAG5B,SACG,QAAQ,aAAa,EACrB,YAAY,6BAA6B,EACzC,OAAO,aAAa,0BAA0B,EAC9C;AAAA,IACC;AAAA,IACA;AAAA;AAAA;AAAA;AAAA,EAIF,EACC,OAAO,kBAAkB;AAG5B,SACG,QAAQ,QAAQ,EAChB,YAAY,2CAA2C,EACvD,OAAO,wBAAwB,gEAAgE,EAC/F,OAAO,oBAAoB,sBAAsB,EACjD,OAAO,kBAAkB,8BAA8B,EACvD,OAAO,mBAAmB,6BAA6B,EACvD,OAAO,wBAAwB,iBAAiB,EAChD,OAAO,wBAAwB,+BAA+B,EAC9D,OAAO,6BAA6B,qCAAqC,EACzE,OAAO,yBAAyB,wDAAwD,EACxF,OAAO,0BAA0B,yDAAyD,EAC1F;AAAA,IACC;AAAA,IACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOF,EACC,OAAO,kBAAkB;AAG5B,SACG,QAAQ,eAAe,EACvB,YAAY,wDAAwD,EACpE,OAAO,kBAAkB,8BAA8B,EACvD,OAAO,wBAAwB,oCAAoC,EACnE,OAAO,mBAAmB,6BAA6B,EACvD,OAAO,qBAAqB,oDAAoD,EAChF,OAAO,wBAAwB,iBAAiB,EAChD,OAAO,wBAAwB,+BAA+B,EAC9D;AAAA,IACC;AAAA,IACA;AAAA;AAAA;AAAA;AAAA;AAAA,EAKF,EACC,OAAO,wBAAwB;AAGlC,SACG,QAAQ,OAAO,EACf,YAAY,oEAAoE,EAChF,OAAO,wBAAwB,0CAA0C,EACzE,OAAO,oBAAoB,wCAAwC,EACnE;AAAA,IACC;AAAA,IACA;AAAA;AAAA;AAAA;AAAA;AAAA,EAKF,EACC,OAAO,iBAAiB;AAE3B,SAAO;AACT;AASA,SAAS,SAAS,KAAa,QAAwB;AACrD,MAAI,IAAI,UAAU,OAAQ,QAAO;AACjC,SAAO,IAAI,UAAU,GAAG,SAAS,CAAC,IAAI;AACxC;AASA,eAAe,iBAAiB,SAOd;AAChB,QAAM,MAAM,UAAU;AACtB,MAAI,CAAC,IAAK;AAEV,QAAM,UAAU,IAAI,sBAAsB,EAAE,MAAM;AAElD,MAAI;AACF,UAAM,WAAW,MAAM,IAAI,OAAO,KAAK;AAAA,MACrC,YAAY,QAAQ;AAAA,MACpB,UAAU,QAAQ;AAAA,MAClB,SAAS,QAAQ;AAAA,MACjB,QAAQ,QAAQ;AAAA,MAChB,OAAO,SAAS,QAAQ,OAAO,EAAE;AAAA,MACjC,MAAM,SAAS,QAAQ,MAAM,EAAE;AAAA,IACjC,CAAC;AAED,YAAQ,KAAK;AAEb,QAAI,CAAC,SAAS,WAAW,CAAC,SAAS,MAAM;AACvC,iBAAW,4BAA4B,SAAS,OAAO;AACvD,cAAQ,WAAW;AACnB;AAAA,IACF;AAEA,UAAM,EAAE,UAAU,OAAO,WAAW,IAAI,SAAS;AAEjD,QAAI,aAAa,GAAG;AAClB,gBAAU,EAAE,UAAU,OAAO,WAAW,CAAC;AACzC;AAAA,IACF;AAEA,QAAI,SAAS,WAAW,GAAG;AACzB,gBAAU,mBAAmB;AAC7B;AAAA,IACF;AAEA,eAAW;AACX;AAAA,MACE,CAAC,MAAM,eAAe,aAAa,WAAW,UAAU,UAAU,SAAS;AAAA,MAC3E,SAAS,IAAI,CAAC,MAAc;AAAA,QAC1B,SAAS,EAAE,IAAI,EAAE;AAAA,QACjB,EAAE;AAAA,QACF,EAAE;AAAA,QACF,SAAS,EAAE,SAAS,EAAE;AAAA,QACtB,EAAE,UAAU,UAAU;AAAA,QACtB,EAAE,WAAW,MAAM,MAAM,KAAK,IAAI,MAAM,IAAI,IAAI;AAAA,QAChD,WAAW,EAAE,SAAS;AAAA,MACxB,CAAC;AAAA,IACH;AAEA,eAAW;AACX,QAAI,YAAY;AACd,gBAAU,UAAU,KAAK,mBAAmB,WAAW,IAAI,OAAO,WAAW,UAAU,GAAG;AAAA,IAC5F,OAAO;AACL,gBAAU,UAAU,KAAK,WAAW;AAAA,IACtC;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,KAAK,0BAA0B;AACvC,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,eAAW,SAAS,OAAO;AAC3B,YAAQ,WAAW;AAAA,EACrB;AACF;AAKA,eAAe,gBAAgB,IAA2B;AACxD,QAAM,MAAM,UAAU;AACtB,MAAI,CAAC,IAAK;AAEV,QAAM,UAAU,IAAI,oBAAoB,EAAE,MAAM;AAEhD,MAAI;AACF,UAAM,WAAW,MAAM,IAAI,OAAO,IAAI,EAAE;AAExC,YAAQ,KAAK;AAEb,QAAI,CAAC,SAAS,WAAW,CAAC,SAAS,MAAM;AACvC,iBAAW,0BAA0B,SAAS,OAAO;AACrD,cAAQ,WAAW;AACnB;AAAA,IACF;AAEA,UAAM,SAAS,SAAS;AAExB,QAAI,aAAa,GAAG;AAClB,gBAAU,MAAM;AAChB;AAAA,IACF;AAEA,eAAW;AACX,uBAAmB,MAAM;AAAA,EAC3B,SAAS,OAAO;AACd,YAAQ,KAAK,wBAAwB;AACrC,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,eAAW,SAAS,OAAO;AAC3B,YAAQ,WAAW;AAAA,EACrB;AACF;AAKA,eAAe,mBAAmB,SAQhB;AAChB,QAAM,MAAM,UAAU;AACtB,MAAI,CAAC,IAAK;AAEV,MAAI;AAEJ,MAAI,QAAQ,MAAM;AAEhB,QAAI;AACF,YAAM,UAAU,MAAM,SAAS,QAAQ,MAAM,OAAO;AACpD,cAAQ,KAAK,MAAM,OAAO;AAAA,IAC5B,SAAS,OAAO;AACd,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,iBAAW,uBAAuB,OAAO;AACzC,cAAQ,WAAW;AACnB;AAAA,IACF;AAAA,EACF,OAAO;AAEL,QAAI,CAAC,QAAQ,cAAc,CAAC,QAAQ,YAAY,CAAC,QAAQ,SAAS;AAChE;AAAA,QACE;AAAA,QACA;AAAA,MACF;AACA,gBAAU,4CAA4C;AACtD,cAAQ,WAAW;AACnB;AAAA,IACF;AAEA,YAAQ;AAAA,MACN,YAAY,QAAQ;AAAA,MACpB,UAAU,QAAQ;AAAA,MAClB,SAAS,QAAQ;AAAA,IACnB;AAEA,QAAI,QAAQ,SAAS;AACnB,YAAM,UAAU,QAAQ;AAAA,IAC1B;AAEA,QAAI,QAAQ,QAAQ;AAClB,YAAM,WAAW,EAAE,GAAG,MAAM,UAAU,QAAQ,QAAQ,OAAuB;AAAA,IAC/E;AAEA,QAAI,QAAQ,KAAK;AACf,YAAM,MAAM,SAAS,QAAQ,KAAK,EAAE;AACpC,UAAI,MAAM,GAAG,KAAK,OAAO,GAAG;AAC1B,mBAAW,qBAAqB,0CAA0C;AAC1E,gBAAQ,WAAW;AACnB;AAAA,MACF;AACA,YAAM,aAAa;AAAA,IACrB;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,oBAAoB,EAAE,MAAM;AAEhD,MAAI;AACF,UAAM,WAAW,MAAM,IAAI,OAAO,OAAO,KAAK;AAE9C,YAAQ,KAAK;AAEb,QAAI,CAAC,SAAS,WAAW,CAAC,SAAS,MAAM;AACvC,iBAAW,2BAA2B,SAAS,OAAO;AACtD,cAAQ,WAAW;AACnB;AAAA,IACF;AAEA,UAAM,SAAS,SAAS;AAExB,QAAI,aAAa,GAAG;AAClB,gBAAU,EAAE,SAAS,MAAM,OAAO,CAAC;AACnC;AAAA,IACF;AAEA,iBAAa,mBAAmB,OAAO,EAAE,EAAE;AAAA,EAC7C,SAAS,OAAO;AACd,YAAQ,KAAK,yBAAyB;AACtC,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,eAAW,SAAS,OAAO;AAC3B,YAAQ,WAAW;AAAA,EACrB;AACF;AAKA,eAAe,mBACb,IACA,SAKe;AACf,QAAM,MAAM,UAAU;AACtB,MAAI,CAAC,IAAK;AAEV,QAAM,QAA2B,CAAC;AAElC,MAAI,QAAQ,SAAS;AACnB,UAAM,UAAU,QAAQ;AAAA,EAC1B;AAEA,MAAI,QAAQ,YAAY;AACtB,UAAM,WAAW;AAAA,EACnB;AAEA,MAAI,QAAQ,UAAU;AACpB,UAAM,WAAW;AAAA,EACnB;AAEA,MAAI,CAAC,QAAQ,WAAW,CAAC,QAAQ,cAAc,CAAC,QAAQ,UAAU;AAChE,eAAW,wBAAwB,gDAAgD;AACnF,YAAQ,WAAW;AACnB;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,oBAAoB,EAAE,MAAM;AAEhD,MAAI;AACF,UAAM,WAAW,MAAM,IAAI,OAAO,OAAO,IAAI,KAAK;AAElD,YAAQ,KAAK;AAEb,QAAI,CAAC,SAAS,WAAW,CAAC,SAAS,MAAM;AACvC,iBAAW,2BAA2B,SAAS,OAAO;AACtD,cAAQ,WAAW;AACnB;AAAA,IACF;AAEA,UAAM,SAAS,SAAS;AAExB,QAAI,aAAa,GAAG;AAClB,gBAAU,EAAE,SAAS,MAAM,OAAO,CAAC;AACnC;AAAA,IACF;AAEA,iBAAa,mBAAmB,OAAO,EAAE,EAAE;AAAA,EAC7C,SAAS,OAAO;AACd,YAAQ,KAAK,yBAAyB;AACtC,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,eAAW,SAAS,OAAO;AAC3B,YAAQ,WAAW;AAAA,EACrB;AACF;AAKA,eAAe,mBAAmB,IAAY,SAA2C;AACvF,QAAM,MAAM,UAAU;AACtB,MAAI,CAAC,IAAK;AAGV,MAAI,CAAC,QAAQ,KAAK;AAChB,QAAI;AACF,YAAM,YAAY,MAAM,QAAQ;AAAA,QAC9B,SAAS,2CAA2C,EAAE;AAAA,QACtD,SAAS;AAAA,MACX,CAAC;AAED,UAAI,CAAC,WAAW;AACd,kBAAU,oBAAoB;AAC9B;AAAA,MACF;AAAA,IACF,QAAQ;AAEN,iBAAW;AACX,gBAAU,oBAAoB;AAC9B;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,oBAAoB,EAAE,MAAM;AAEhD,MAAI;AACF,UAAM,WAAW,MAAM,IAAI,OAAO,OAAO,EAAE;AAE3C,YAAQ,KAAK;AAEb,QAAI,CAAC,SAAS,SAAS;AACrB,iBAAW,2BAA2B,SAAS,OAAO;AACtD,cAAQ,WAAW;AACnB;AAAA,IACF;AAEA,QAAI,aAAa,GAAG;AAClB,gBAAU,EAAE,SAAS,MAAM,SAAS,MAAM,GAAG,CAAC;AAC9C;AAAA,IACF;AAEA,iBAAa,mBAAmB,EAAE,EAAE;AAAA,EACtC,SAAS,OAAO;AACd,YAAQ,KAAK,yBAAyB;AACtC,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,eAAW,SAAS,OAAO;AAC3B,YAAQ,WAAW;AAAA,EACrB;AACF;AAKA,eAAe,mBAAmB,SAUhB;AAChB,MAAI,CAAC,QAAQ,cAAc,CAAC,QAAQ,YAAY,CAAC,QAAQ,OAAO;AAC9D,eAAW,4BAA4B,iDAAiD;AACxF,cAAU,4CAA4C;AACtD,YAAQ,WAAW;AACnB;AAAA,EACF;AAEA,QAAM,MAAM,UAAU;AACtB,MAAI,CAAC,IAAK;AAEV,QAAM,QAA2B;AAAA,IAC/B,YAAY,QAAQ;AAAA,IACpB,UAAU,QAAQ;AAAA,IAClB,OAAO,QAAQ;AAAA,EACjB;AAEA,MAAI,QAAQ,SAAS;AACnB,UAAM,UAAU,QAAQ;AAAA,EAC1B;AAEA,MAAI,QAAQ,OAAO;AACjB,UAAM,QAAQ,SAAS,QAAQ,OAAO,EAAE;AAAA,EAC1C;AAEA,MAAI,QAAQ,UAAU;AACpB,UAAM,WAAW,WAAW,QAAQ,QAAQ;AAAA,EAC9C;AAEA,MAAI,QAAQ,eAAe;AACzB,UAAM,gBAAgB,WAAW,QAAQ,aAAa;AAAA,EACxD;AAEA,MAAI,QAAQ,cAAc;AACxB,UAAM,eAAe,QAAQ;AAAA,EAC/B;AAEA,MAAI,QAAQ,eAAe;AACzB,UAAM,gBAAgB,QAAQ;AAAA,EAChC;AAEA,QAAM,UAAU,IAAI,uBAAuB,EAAE,MAAM;AAEnD,MAAI;AACF,UAAM,WAAW,MAAM,IAAI,OAAO,OAAO,KAAK;AAE9C,YAAQ,KAAK;AAEb,QAAI,CAAC,SAAS,WAAW,CAAC,SAAS,MAAM;AACvC,iBAAW,6BAA6B,SAAS,OAAO;AACxD,cAAQ,WAAW;AACnB;AAAA,IACF;AAEA,UAAM,EAAE,SAAS,IAAI,SAAS;AAE9B,QAAI,aAAa,GAAG;AAClB,gBAAU,EAAE,SAAS,CAAC;AACtB;AAAA,IACF;AAEA,QAAI,SAAS,WAAW,GAAG;AACzB,gBAAU,4BAA4B;AACtC;AAAA,IACF;AAEA,eAAW;AACX;AAAA,MACE,CAAC,MAAM,SAAS,WAAW,eAAe,WAAW;AAAA,MACrD,SAAS,IAAI,CAAC,MAA0B;AAAA,QACtC,SAAS,EAAE,IAAI,EAAE;AAAA,SAChB,EAAE,SAAS,GAAG,QAAQ,CAAC;AAAA,QACxB,SAAS,EAAE,SAAS,EAAE;AAAA,QACtB,EAAE;AAAA,QACF,EAAE;AAAA,MACJ,CAAC;AAAA,IACH;AAEA,eAAW;AACX,cAAU,SAAS,SAAS,MAAM,oBAAoB;AAAA,EACxD,SAAS,OAAO;AACd,YAAQ,KAAK,2BAA2B;AACxC,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,eAAW,SAAS,OAAO;AAC3B,YAAQ,WAAW;AAAA,EACrB;AACF;AAKA,eAAe,yBAAyB,SAOtB;AAChB,MAAI,CAAC,QAAQ,OAAO;AAClB,eAAW,2BAA2B,iBAAiB;AACvD,cAAU,mDAAmD;AAC7D,YAAQ,WAAW;AACnB;AAAA,EACF;AAEA,QAAM,MAAM,UAAU;AACtB,MAAI,CAAC,IAAK;AAEV,QAAM,QAAiC,EAAE,OAAO,QAAQ,MAAM;AAC9D,MAAI,QAAQ,WAAY,OAAM,aAAa,QAAQ;AACnD,MAAI,QAAQ,QAAS,OAAM,UAAU,QAAQ;AAC7C,MAAI,QAAQ,OAAQ,OAAM,SAAS,QAAQ;AAC3C,MAAI,QAAQ,MAAO,OAAM,QAAQ,SAAS,QAAQ,OAAO,EAAE;AAC3D,MAAI,QAAQ,SAAU,OAAM,WAAW,WAAW,QAAQ,QAAQ;AAElE,QAAM,UAAU,IAAI,2BAA2B,EAAE,MAAM;AAEvD,MAAI;AACF,UAAM,WAAW,MAAM,IAAI,OAAO,aAAa,KAAK;AAEpD,YAAQ,KAAK;AAEb,QAAI,CAAC,SAAS,WAAW,CAAC,SAAS,MAAM;AACvC,iBAAW,6BAA6B,SAAS,OAAO;AACxD,cAAQ,WAAW;AACnB;AAAA,IACF;AAEA,UAAM,EAAE,SAAS,IAAI,SAAS;AAE9B,QAAI,aAAa,GAAG;AAClB,gBAAU,EAAE,SAAS,CAAC;AACtB;AAAA,IACF;AAEA,QAAI,SAAS,WAAW,GAAG;AACzB,gBAAU,4BAA4B;AACtC;AAAA,IACF;AAEA,eAAW;AACX;AAAA,MACE,CAAC,MAAM,SAAS,WAAW,eAAe,WAAW;AAAA,MACrD,SAAS,IAAI,CAAC,MAA0B;AAAA,QACtC,SAAS,EAAE,IAAI,EAAE;AAAA,SAChB,EAAE,SAAS,GAAG,QAAQ,CAAC;AAAA,QACxB,SAAS,EAAE,SAAS,EAAE;AAAA,QACtB,EAAE;AAAA,QACF,EAAE;AAAA,MACJ,CAAC;AAAA,IACH;AAEA,eAAW;AACX,cAAU,SAAS,SAAS,MAAM,oBAAoB;AAAA,EACxD,SAAS,OAAO;AACd,YAAQ,KAAK,2BAA2B;AACxC,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,eAAW,SAAS,OAAO;AAC3B,YAAQ,WAAW;AAAA,EACrB;AACF;AAKA,eAAe,kBAAkB,SAGf;AAChB,QAAM,MAAM,UAAU;AACtB,MAAI,CAAC,IAAK;AAEV,QAAM,UAAU,IAAI,6BAA6B,EAAE,MAAM;AAEzD,MAAI;AACF,UAAM,WAAW,MAAM,IAAI,OAAO,MAAM;AAAA,MACtC,YAAY,QAAQ;AAAA,MACpB,UAAU,QAAQ;AAAA,IACpB,CAAC;AAED,YAAQ,KAAK;AAEb,QAAI,CAAC,SAAS,WAAW,CAAC,SAAS,MAAM;AACvC,iBAAW,gCAAgC,SAAS,OAAO;AAC3D,cAAQ,WAAW;AACnB;AAAA,IACF;AAEA,UAAM,QAAqB,SAAS;AAEpC,QAAI,aAAa,GAAG;AAClB,gBAAU,KAAK;AACf;AAAA,IACF;AAEA,eAAW;AACX,eAAW,SAAS,OAAO,MAAM,KAAK,CAAC;AACvC,eAAW,UAAU,MAAM,MAAM,OAAO,MAAM,MAAM,CAAC,CAAC;AACtD,eAAW,YAAY,OAAO,MAAM,QAAQ,CAAC;AAC7C,eAAW,WAAW,MAAM,UAAU,IAAI,MAAM,OAAO,OAAO,MAAM,OAAO,CAAC,IAAI,GAAG;AACnF,eAAW,kBAAkB,MAAM,cAAc,QAAQ,CAAC,CAAC;AAE3D,eAAW;AACX,cAAU,UAAU;AACpB;AAAA,MACE,CAAC,eAAe,OAAO;AAAA,MACvB,OAAO,QAAQ,MAAM,MAAM,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;AAAA,IAC7D;AAEA,eAAW;AACX,cAAU,YAAY;AACtB;AAAA,MACE,CAAC,UAAU,OAAO;AAAA,MAClB,OAAO,QAAQ,MAAM,QAAQ,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;AAAA,IAC/D;AAEA,QAAI,MAAM,YAAY,SAAS,GAAG;AAChC,iBAAW;AACX,gBAAU,eAAe;AACzB;AAAA,QACE,CAAC,MAAM,gBAAgB,SAAS;AAAA,QAChC,MAAM,YAAY,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,WAAW,GAAG,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;AAAA,MACnG;AAAA,IACF;AACA,eAAW;AAAA,EACb,SAAS,OAAO;AACd,YAAQ,KAAK,8BAA8B;AAC3C,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,eAAW,SAAS,OAAO;AAC3B,YAAQ,WAAW;AAAA,EACrB;AACF;AASA,SAAS,mBAAmB,QAAsB;AAChD,aAAW,MAAM,OAAO,EAAE;AAC1B,aAAW,eAAe,OAAO,UAAU;AAC3C,aAAW,aAAa,OAAO,QAAQ;AAEvC,aAAW;AACX,YAAU,UAAU;AACpB,UAAQ,IAAI,MAAM,KAAK,OAAO,OAAO,CAAC;AAEtC,MAAI,OAAO,SAAS;AAClB,eAAW;AACX,eAAW,YAAY,OAAO,OAAO;AAAA,EACvC;AAEA,aAAW;AACX,aAAW,UAAU,OAAO,WAAW,MAAM,MAAM,KAAK,IAAI,MAAM,IAAI,IAAI,CAAC;AAE3E,MAAI,OAAO,YAAY,OAAO,KAAK,OAAO,QAAQ,EAAE,SAAS,GAAG;AAC9D,eAAW;AACX,cAAU,WAAW;AACrB,YAAQ,IAAI,MAAM,KAAK,KAAK,UAAU,OAAO,UAAU,MAAM,CAAC,CAAC,CAAC;AAAA,EAClE;AAEA,MAAI,OAAO,WAAW;AACpB,eAAW,WAAW,WAAW,OAAO,SAAS,CAAC;AAAA,EACpD;AAEA,aAAW;AACX,aAAW,WAAW,WAAW,OAAO,SAAS,CAAC;AAClD,MAAI,OAAO,WAAW;AACpB,eAAW,WAAW,WAAW,OAAO,SAAS,CAAC;AAAA,EACpD;AACA,aAAW;AACb;","names":[]}
@@ -0,0 +1,12 @@
1
+ import { Command } from 'commander';
2
+
3
+ /**
4
+ * Create the conversations command group
5
+ */
6
+ declare function createConversationsCommand(): Command;
7
+ /**
8
+ * Create the messages command group
9
+ */
10
+ declare function createMessagesCommand(): Command;
11
+
12
+ export { createConversationsCommand, createMessagesCommand };
@@ -0,0 +1,208 @@
1
+ import { Command } from "commander";
2
+ import ora from "ora";
3
+ import { createSdk } from "../utils/sdk-factory.js";
4
+ import {
5
+ printError,
6
+ printSuccess,
7
+ printInfo,
8
+ printBlank,
9
+ printSimpleTable,
10
+ printLabel,
11
+ isJsonOutput,
12
+ printJson,
13
+ formatDate
14
+ } from "../utils/output.js";
15
+ function createConversationsCommand() {
16
+ const conversations = new Command("conversations").description("Browse messaging conversations (WhatsApp, SMS, chat)").addHelpText(
17
+ "after",
18
+ `
19
+ Quick Start:
20
+ $ chanl conversations list # Recent conversations
21
+ $ chanl conversations list --channel whatsapp # Filter by channel type
22
+ $ chanl conversations get <id> # Conversation + messages
23
+ $ chanl conversations close <id> # Close a conversation
24
+
25
+ Send messages with: chanl messages send`
26
+ );
27
+ conversations.command("list").description("List conversations").option("-c, --channel <type>", "Filter by channel type (whatsapp, sms, chat)").option("--status <status>", "Filter by status (open, closed)").option("--limit <number>", "Number of items per page", "20").option("-p, --page <number>", "Page number", "1").action(handleConversationsList);
28
+ conversations.command("get <id>").description("Show a conversation with its messages").option("--limit <number>", "Messages per page", "50").action(handleConversationsGet);
29
+ conversations.command("close <id>").description("Close a conversation").action(handleConversationsClose);
30
+ return conversations;
31
+ }
32
+ function createMessagesCommand() {
33
+ const messages = new Command("messages").description("Send outbound messages on a channel").addHelpText(
34
+ "after",
35
+ `
36
+ Session vs template (WhatsApp):
37
+ Free-form (--body) delivers only inside the 24h window opened by the
38
+ customer's last inbound message. Outside it, use an approved template
39
+ (--template HX... --var 1=Dean); a free-form attempt fails with a
40
+ 63016-class provider error.
41
+
42
+ Examples:
43
+ $ chanl messages send --channel <channelId> --to +14155551234 --body "Hi!"
44
+ $ chanl messages send --channel <channelId> --to +14155551234 \\
45
+ --template HX0123456789abcdef --var 1=Dean --var 2=tomorrow`
46
+ );
47
+ messages.command("send").description("Send a message (free-form body or template)").requiredOption("--channel <channelId>", "Channel id to send through").requiredOption("--to <address>", "Recipient (E.164 for phone channels)").option("--body <text>", "Free-form message body (24h session window)").option("--media <url>", "Media URL to attach").option("--template <contentSid>", "Approved template SID (HX...)").option("--var <key=value...>", "Template variable (repeatable)", collectVars, {}).action(handleMessagesSend);
48
+ return messages;
49
+ }
50
+ function collectVars(value, acc) {
51
+ const idx = value.indexOf("=");
52
+ if (idx === -1) {
53
+ throw new Error(`--var expects key=value, got "${value}"`);
54
+ }
55
+ acc[value.slice(0, idx)] = value.slice(idx + 1);
56
+ return acc;
57
+ }
58
+ async function handleConversationsList(options) {
59
+ const sdk = createSdk();
60
+ if (!sdk) return;
61
+ const spinner = ora("Fetching conversations...").start();
62
+ try {
63
+ const response = await sdk.conversations.list({
64
+ channelType: options.channel,
65
+ status: options.status,
66
+ limit: parseInt(options.limit, 10),
67
+ page: parseInt(options.page, 10)
68
+ });
69
+ spinner.stop();
70
+ if (!response.success || !response.data) {
71
+ printError("Failed to fetch conversations", response.message);
72
+ process.exitCode = 1;
73
+ return;
74
+ }
75
+ const { items, pagination } = response.data;
76
+ if (isJsonOutput()) {
77
+ printJson(response.data);
78
+ return;
79
+ }
80
+ if (items.length === 0) {
81
+ printInfo("No conversations found");
82
+ return;
83
+ }
84
+ printBlank();
85
+ printSimpleTable(
86
+ ["ID", "Channel", "Customer", "Status", "Last message"],
87
+ items.map((c) => [
88
+ c.id.slice(-12),
89
+ c.channelType || "-",
90
+ c.customerAddress || c.customerId?.slice(-8) || "-",
91
+ c.status || "-",
92
+ c.lastMessageAt ? formatDate(c.lastMessageAt) : "-"
93
+ ])
94
+ );
95
+ printBlank();
96
+ if (pagination) {
97
+ printInfo(`Total: ${pagination.total} conversations (Page ${pagination.page} of ${pagination.totalPages})`);
98
+ }
99
+ } catch (error) {
100
+ spinner.fail("Failed to fetch conversations");
101
+ printError("Error", error instanceof Error ? error.message : "Unknown error");
102
+ process.exitCode = 1;
103
+ }
104
+ }
105
+ async function handleConversationsGet(id, options) {
106
+ const sdk = createSdk();
107
+ if (!sdk) return;
108
+ const spinner = ora("Fetching conversation...").start();
109
+ try {
110
+ const response = await sdk.conversations.get(id, { limit: parseInt(options.limit, 10) });
111
+ spinner.stop();
112
+ if (!response.success || !response.data) {
113
+ printError("Failed to fetch conversation", response.message);
114
+ process.exitCode = 1;
115
+ return;
116
+ }
117
+ if (isJsonOutput()) {
118
+ printJson(response.data);
119
+ return;
120
+ }
121
+ const { conversation, messages } = response.data;
122
+ printBlank();
123
+ printLabel("ID", conversation.id);
124
+ printLabel("Channel", conversation.channelType || "-");
125
+ printLabel("Customer", conversation.customerAddress || "-");
126
+ printLabel("Status", conversation.status || "-");
127
+ printBlank();
128
+ if (!messages || messages.length === 0) {
129
+ printInfo("No messages yet");
130
+ return;
131
+ }
132
+ printSimpleTable(
133
+ ["Time", "Dir", "Body", "Status"],
134
+ messages.map((m) => [
135
+ formatDate(m.createdAt),
136
+ m.direction === "inbound" ? "\u2192 in" : "\u2190 out",
137
+ (m.body || (m.mediaUrl ? "[media]" : "")).slice(0, 48),
138
+ m.status || "-"
139
+ ])
140
+ );
141
+ printBlank();
142
+ } catch (error) {
143
+ spinner.fail("Failed to fetch conversation");
144
+ printError("Error", error instanceof Error ? error.message : "Unknown error");
145
+ process.exitCode = 1;
146
+ }
147
+ }
148
+ async function handleConversationsClose(id) {
149
+ const sdk = createSdk();
150
+ if (!sdk) return;
151
+ const spinner = ora("Closing conversation...").start();
152
+ try {
153
+ const response = await sdk.conversations.close(id);
154
+ spinner.stop();
155
+ if (!response.success) {
156
+ printError("Failed to close conversation", response.message);
157
+ process.exitCode = 1;
158
+ return;
159
+ }
160
+ printSuccess(`Conversation closed: ${id}`);
161
+ } catch (error) {
162
+ spinner.fail("Failed to close conversation");
163
+ printError("Error", error instanceof Error ? error.message : "Unknown error");
164
+ process.exitCode = 1;
165
+ }
166
+ }
167
+ async function handleMessagesSend(options) {
168
+ const sdk = createSdk();
169
+ if (!sdk) return;
170
+ if (!options.body && !options.template) {
171
+ printError("Nothing to send", "Provide --body or --template HX...");
172
+ process.exitCode = 1;
173
+ return;
174
+ }
175
+ const spinner = ora("Sending message...").start();
176
+ try {
177
+ const response = await sdk.conversations.send({
178
+ channelId: options.channel,
179
+ to: options.to,
180
+ body: options.body,
181
+ mediaUrl: options.media,
182
+ contentSid: options.template,
183
+ contentVariables: Object.keys(options.var).length > 0 ? options.var : void 0
184
+ });
185
+ spinner.stop();
186
+ if (!response.success || !response.data) {
187
+ printError("Failed to send message", response.message);
188
+ process.exitCode = 1;
189
+ return;
190
+ }
191
+ if (isJsonOutput()) {
192
+ printJson(response.data);
193
+ return;
194
+ }
195
+ printSuccess(`Message sent to ${options.to}`);
196
+ const m = response.data;
197
+ if (m.id) printInfo(`Message id: ${m.id}${m.status ? ` (${m.status})` : ""}`);
198
+ } catch (error) {
199
+ spinner.fail("Failed to send message");
200
+ printError("Error", error instanceof Error ? error.message : "Unknown error");
201
+ process.exitCode = 1;
202
+ }
203
+ }
204
+ export {
205
+ createConversationsCommand,
206
+ createMessagesCommand
207
+ };
208
+ //# sourceMappingURL=messaging.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/commands/messaging.ts"],"sourcesContent":["import { Command } from 'commander';\nimport ora from 'ora';\nimport type { Conversation } 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 conversations command group\n */\nexport function createConversationsCommand(): Command {\n const conversations = new Command('conversations')\n .description('Browse messaging conversations (WhatsApp, SMS, chat)')\n .addHelpText(\n 'after',\n `\nQuick Start:\n $ chanl conversations list # Recent conversations\n $ chanl conversations list --channel whatsapp # Filter by channel type\n $ chanl conversations get <id> # Conversation + messages\n $ chanl conversations close <id> # Close a conversation\n\nSend messages with: chanl messages send`\n );\n\n conversations\n .command('list')\n .description('List conversations')\n .option('-c, --channel <type>', 'Filter by channel type (whatsapp, sms, chat)')\n .option('--status <status>', 'Filter by status (open, closed)')\n .option('--limit <number>', 'Number of items per page', '20')\n .option('-p, --page <number>', 'Page number', '1')\n .action(handleConversationsList);\n\n conversations\n .command('get <id>')\n .description('Show a conversation with its messages')\n .option('--limit <number>', 'Messages per page', '50')\n .action(handleConversationsGet);\n\n conversations\n .command('close <id>')\n .description('Close a conversation')\n .action(handleConversationsClose);\n\n return conversations;\n}\n\n/**\n * Create the messages command group\n */\nexport function createMessagesCommand(): Command {\n const messages = new Command('messages')\n .description('Send outbound messages on a channel')\n .addHelpText(\n 'after',\n `\nSession vs template (WhatsApp):\n Free-form (--body) delivers only inside the 24h window opened by the\n customer's last inbound message. Outside it, use an approved template\n (--template HX... --var 1=Dean); a free-form attempt fails with a\n 63016-class provider error.\n\nExamples:\n $ chanl messages send --channel <channelId> --to +14155551234 --body \"Hi!\"\n $ chanl messages send --channel <channelId> --to +14155551234 \\\\\n --template HX0123456789abcdef --var 1=Dean --var 2=tomorrow`\n );\n\n messages\n .command('send')\n .description('Send a message (free-form body or template)')\n .requiredOption('--channel <channelId>', 'Channel id to send through')\n .requiredOption('--to <address>', 'Recipient (E.164 for phone channels)')\n .option('--body <text>', 'Free-form message body (24h session window)')\n .option('--media <url>', 'Media URL to attach')\n .option('--template <contentSid>', 'Approved template SID (HX...)')\n .option('--var <key=value...>', 'Template variable (repeatable)', collectVars, {})\n .action(handleMessagesSend);\n\n return messages;\n}\n\nfunction collectVars(value: string, acc: Record<string, string>): Record<string, string> {\n const idx = value.indexOf('=');\n if (idx === -1) {\n throw new Error(`--var expects key=value, got \"${value}\"`);\n }\n acc[value.slice(0, idx)] = value.slice(idx + 1);\n return acc;\n}\n\nasync function handleConversationsList(options: {\n channel?: 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 conversations...').start();\n\n try {\n const response = await sdk.conversations.list({\n channelType: options.channel,\n status: options.status,\n limit: parseInt(options.limit, 10),\n page: parseInt(options.page, 10),\n });\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch conversations', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { items, pagination } = response.data;\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n if (items.length === 0) {\n printInfo('No conversations found');\n return;\n }\n\n printBlank();\n printSimpleTable(\n ['ID', 'Channel', 'Customer', 'Status', 'Last message'],\n items.map((c: Conversation) => [\n c.id.slice(-12),\n c.channelType || '-',\n c.customerAddress || c.customerId?.slice(-8) || '-',\n c.status || '-',\n c.lastMessageAt ? formatDate(c.lastMessageAt) : '-',\n ])\n );\n printBlank();\n if (pagination) {\n printInfo(`Total: ${pagination.total} conversations (Page ${pagination.page} of ${pagination.totalPages})`);\n }\n } catch (error) {\n spinner.fail('Failed to fetch conversations');\n printError('Error', error instanceof Error ? error.message : 'Unknown error');\n process.exitCode = 1;\n }\n}\n\nasync function handleConversationsGet(id: string, options: { limit: string }): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching conversation...').start();\n\n try {\n const response = await sdk.conversations.get(id, { limit: parseInt(options.limit, 10) });\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch conversation', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const { conversation, messages } = response.data;\n printBlank();\n printLabel('ID', conversation.id);\n printLabel('Channel', conversation.channelType || '-');\n printLabel('Customer', conversation.customerAddress || '-');\n printLabel('Status', conversation.status || '-');\n printBlank();\n\n if (!messages || messages.length === 0) {\n printInfo('No messages yet');\n return;\n }\n\n printSimpleTable(\n ['Time', 'Dir', 'Body', 'Status'],\n messages.map((m) => [\n formatDate(m.createdAt),\n m.direction === 'inbound' ? '→ in' : '← out',\n (m.body || (m.mediaUrl ? '[media]' : '')).slice(0, 48),\n m.status || '-',\n ])\n );\n printBlank();\n } catch (error) {\n spinner.fail('Failed to fetch conversation');\n printError('Error', error instanceof Error ? error.message : 'Unknown error');\n process.exitCode = 1;\n }\n}\n\nasync function handleConversationsClose(id: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Closing conversation...').start();\n\n try {\n const response = await sdk.conversations.close(id);\n spinner.stop();\n\n if (!response.success) {\n printError('Failed to close conversation', response.message);\n process.exitCode = 1;\n return;\n }\n printSuccess(`Conversation closed: ${id}`);\n } catch (error) {\n spinner.fail('Failed to close conversation');\n printError('Error', error instanceof Error ? error.message : 'Unknown error');\n process.exitCode = 1;\n }\n}\n\nasync function handleMessagesSend(options: {\n channel: string;\n to: string;\n body?: string;\n media?: string;\n template?: string;\n var: Record<string, string>;\n}): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n if (!options.body && !options.template) {\n printError('Nothing to send', 'Provide --body or --template HX...');\n process.exitCode = 1;\n return;\n }\n\n const spinner = ora('Sending message...').start();\n\n try {\n const response = await sdk.conversations.send({\n channelId: options.channel,\n to: options.to,\n body: options.body,\n mediaUrl: options.media,\n contentSid: options.template,\n contentVariables: Object.keys(options.var).length > 0 ? options.var : undefined,\n });\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to send message', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n printSuccess(`Message sent to ${options.to}`);\n const m = response.data;\n if (m.id) printInfo(`Message id: ${m.id}${m.status ? ` (${m.status})` : ''}`);\n } catch (error) {\n spinner.fail('Failed to send message');\n printError('Error', error instanceof Error ? error.message : 'Unknown error');\n process.exitCode = 1;\n }\n}\n"],"mappings":"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","names":[]}
@@ -73,6 +73,12 @@ Examples:
73
73
  $ chanl prompts delete abc123
74
74
  $ chanl prompts delete abc123 --yes # Skip confirmation`
75
75
  ).action(handlePromptsDelete);
76
+ prompts.command("versions").description("Prompt version operations").addCommand(
77
+ new Command("list").argument("<id>", "Prompt ID").description("List version history for a prompt").action(handlePromptsVersionsList)
78
+ );
79
+ prompts.command("revert <id>").description("Revert a prompt to a previous version").requiredOption("--to-version <number>", "Version number to revert to").action(handlePromptsRevert);
80
+ prompts.command("resolve <id>").description("Resolve template variables in prompt content").option("-f, --file <path>", 'JSON file with { "variables": { ... } }').action(handlePromptsResolve);
81
+ prompts.command("apply <id>").description("Apply a prompt to an agent").requiredOption("-a, --agent <agentId>", "Agent ID").option("--sync", "Sync agent to external platform after apply").action(handlePromptsApply);
76
82
  return prompts;
77
83
  }
78
84
  function formatStatus(status) {
@@ -105,7 +111,8 @@ async function handlePromptsList(options) {
105
111
  process.exitCode = 1;
106
112
  return;
107
113
  }
108
- const prompts = Array.isArray(response.data) ? response.data : [];
114
+ const data = response.data;
115
+ const prompts = Array.isArray(data) ? data : data?.prompts ?? [];
109
116
  if (isJsonOutput()) {
110
117
  printJson(prompts);
111
118
  return;
@@ -289,6 +296,146 @@ async function handlePromptsDelete(id, options) {
289
296
  process.exitCode = 1;
290
297
  }
291
298
  }
299
+ async function handlePromptsVersionsList(id) {
300
+ const sdk = createSdk();
301
+ if (!sdk) return;
302
+ const spinner = ora("Fetching versions...").start();
303
+ try {
304
+ const response = await sdk.prompts.getVersions(id);
305
+ spinner.stop();
306
+ if (!response.success || !response.data) {
307
+ printError("Failed to fetch versions", response.message);
308
+ process.exitCode = 1;
309
+ return;
310
+ }
311
+ const versions = Array.isArray(response.data) ? response.data : [];
312
+ if (isJsonOutput()) {
313
+ printJson(versions);
314
+ return;
315
+ }
316
+ if (versions.length === 0) {
317
+ printInfo("No versions found");
318
+ return;
319
+ }
320
+ printBlank();
321
+ printSimpleTable(
322
+ ["Version", "Name", "Active", "Created"],
323
+ versions.map((v) => [
324
+ String(v.version ?? "-"),
325
+ (v.versionName || "-").slice(0, 30),
326
+ v.isActive ? chalk.green("yes") : chalk.gray("no"),
327
+ formatDate(v.createdAt)
328
+ ])
329
+ );
330
+ } catch (error) {
331
+ spinner.fail("Failed to fetch versions");
332
+ const message = error instanceof Error ? error.message : "Unknown error";
333
+ printError("Error", message);
334
+ process.exitCode = 1;
335
+ }
336
+ }
337
+ async function handlePromptsRevert(id, options) {
338
+ const sdk = createSdk();
339
+ if (!sdk) return;
340
+ const version = parseInt(options.toVersion, 10);
341
+ if (Number.isNaN(version)) {
342
+ printError("Invalid version", "Version must be a number");
343
+ process.exitCode = 1;
344
+ return;
345
+ }
346
+ const spinner = ora("Reverting prompt...").start();
347
+ try {
348
+ const response = await sdk.prompts.revert(id, { version });
349
+ spinner.stop();
350
+ if (!response.success || !response.data) {
351
+ printError("Failed to revert prompt", response.message);
352
+ process.exitCode = 1;
353
+ return;
354
+ }
355
+ if (isJsonOutput()) {
356
+ printJson(response.data);
357
+ return;
358
+ }
359
+ printSuccess(`Prompt reverted to version ${version}`);
360
+ printLabel("ID", response.data.id);
361
+ printLabel("Current version", String(response.data.version ?? version));
362
+ } catch (error) {
363
+ spinner.fail("Failed to revert prompt");
364
+ const message = error instanceof Error ? error.message : "Unknown error";
365
+ printError("Error", message);
366
+ process.exitCode = 1;
367
+ }
368
+ }
369
+ async function handlePromptsResolve(id, options) {
370
+ const sdk = createSdk();
371
+ if (!sdk) return;
372
+ let variables;
373
+ if (options.file) {
374
+ try {
375
+ const content = readFileSync(options.file, "utf-8");
376
+ const parsed = JSON.parse(content);
377
+ variables = parsed.variables ?? parsed;
378
+ } catch (error) {
379
+ const message = error instanceof Error ? error.message : "Unknown error";
380
+ printError("Failed to read file", message);
381
+ process.exitCode = 1;
382
+ return;
383
+ }
384
+ }
385
+ const spinner = ora("Resolving variables...").start();
386
+ try {
387
+ const response = await sdk.prompts.resolve(id, variables ? { variables } : void 0);
388
+ spinner.stop();
389
+ if (!response.success || !response.data) {
390
+ printError("Failed to resolve prompt", response.message);
391
+ process.exitCode = 1;
392
+ return;
393
+ }
394
+ if (isJsonOutput()) {
395
+ printJson(response.data);
396
+ return;
397
+ }
398
+ printBlank();
399
+ console.log(chalk.bold("Resolved content:"));
400
+ console.log(response.data.content);
401
+ if (response.data.unresolvedVariables?.length) {
402
+ printBlank();
403
+ printInfo(`Unresolved: ${response.data.unresolvedVariables.join(", ")}`);
404
+ }
405
+ } catch (error) {
406
+ spinner.fail("Failed to resolve prompt");
407
+ const message = error instanceof Error ? error.message : "Unknown error";
408
+ printError("Error", message);
409
+ process.exitCode = 1;
410
+ }
411
+ }
412
+ async function handlePromptsApply(id, options) {
413
+ const sdk = createSdk();
414
+ if (!sdk) return;
415
+ const spinner = ora("Applying prompt to agent...").start();
416
+ try {
417
+ const response = await sdk.prompts.apply(id, {
418
+ agentId: options.agent,
419
+ syncToPlatform: options.sync
420
+ });
421
+ spinner.stop();
422
+ if (!response.success) {
423
+ printError("Failed to apply prompt", response.message);
424
+ process.exitCode = 1;
425
+ return;
426
+ }
427
+ if (isJsonOutput()) {
428
+ printJson(response.data ?? { success: true });
429
+ return;
430
+ }
431
+ printSuccess(`Prompt applied to agent ${options.agent}`);
432
+ } catch (error) {
433
+ spinner.fail("Failed to apply prompt");
434
+ const message = error instanceof Error ? error.message : "Unknown error";
435
+ printError("Error", message);
436
+ process.exitCode = 1;
437
+ }
438
+ }
292
439
  export {
293
440
  createPromptsCommand
294
441
  };