callkaro-cli-unofficial 0.9.0 → 0.9.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.
@@ -60,8 +60,12 @@ async function analyticsPerformanceCommand(opts) {
60
60
  async function analyticsVersionCommand(agentId, opts) {
61
61
  const api = (0, session_1.requireApi)();
62
62
  try {
63
+ if (opts.cohort && opts.cohort !== 'leads')
64
+ throw new Error(`--cohort must be "leads" (got "${opts.cohort}"). Omit it for the call view.`);
63
65
  const res = await api.versionAnalytics(agentId, {
64
66
  version_ids: opts.versions,
67
+ initial_version_ids: opts.initialVersions,
68
+ cohort: opts.cohort,
65
69
  startDate: opts.start,
66
70
  endDate: opts.end,
67
71
  });
@@ -71,7 +75,7 @@ async function analyticsVersionCommand(agentId, opts) {
71
75
  if (!rows.length)
72
76
  return void (0, ui_1.info)('No version analytics.');
73
77
  (0, ui_1.table)(['VERSION', 'CALLS', 'CONNECTED', 'CONVERTED', 'RECEIPT→CONV %', 'CONN→CONV %'], rows.map((r) => [
74
- r._id, r.total_calls ?? '', r.connected_calls ?? '', r.converted_calls ?? '',
78
+ r.versionName ?? r._id, r.total_calls ?? '', r.connected_calls ?? '', r.converted_calls ?? '',
75
79
  r.overall_receipt_to_conversion_pct ?? '', r.overall_connected_to_conversion_pct ?? '',
76
80
  ]));
77
81
  }
@@ -33,6 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.chatAgentsCollectFile = void 0;
36
37
  exports.chatAgentsModelsCommand = chatAgentsModelsCommand;
37
38
  exports.chatAgentsTemplatesCommand = chatAgentsTemplatesCommand;
38
39
  exports.chatAgentsTemplateCommand = chatAgentsTemplateCommand;
@@ -44,10 +45,18 @@ exports.chatAgentsUpdateCommand = chatAgentsUpdateCommand;
44
45
  exports.chatAgentsCreateVersionCommand = chatAgentsCreateVersionCommand;
45
46
  exports.chatAgentsPublishCommand = chatAgentsPublishCommand;
46
47
  exports.chatAgentsDiffCommand = chatAgentsDiffCommand;
48
+ exports.chatAgentsDeleteVersionCommand = chatAgentsDeleteVersionCommand;
49
+ exports.chatAgentsImportVersionsCommand = chatAgentsImportVersionsCommand;
50
+ exports.chatAgentsImportCommand = chatAgentsImportCommand;
51
+ exports.chatAgentsCommitsCommand = chatAgentsCommitsCommand;
52
+ exports.chatAgentsCommitCommand = chatAgentsCommitCommand;
53
+ exports.chatAgentsRevertCommand = chatAgentsRevertCommand;
47
54
  const dashboardApi_1 = require("../lib/dashboardApi");
48
55
  const session_1 = require("../lib/session");
49
56
  const dashboardAuth_1 = require("../lib/dashboardAuth");
57
+ const fs_1 = require("fs");
50
58
  const ui_1 = require("../lib/ui");
59
+ const looseJson_1 = require("../lib/looseJson");
51
60
  const versions_1 = require("../lib/versions");
52
61
  const jsonInput_1 = require("./jsonInput");
53
62
  const dbFields_1 = require("../lib/dbFields");
@@ -271,3 +280,124 @@ async function chatAgentsDiffCommand(chatAgentId, opts) {
271
280
  (0, ui_1.handleError)(err);
272
281
  }
273
282
  }
283
+ function readEntries(files) {
284
+ if (!files.length)
285
+ throw new Error('--file <path> is required (repeat it for several files).');
286
+ const entries = [];
287
+ for (const path of files) {
288
+ if (!(0, fs_1.existsSync)(path))
289
+ throw new Error(`File not found: ${path}`);
290
+ const parsed = JSON.parse((0, looseJson_1.readJsonFile)(path));
291
+ (Array.isArray(parsed) ? parsed : [parsed]).forEach((entry, i) => {
292
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
293
+ throw new Error(`${path}: entry ${i + 1} must be a JSON object.`);
294
+ }
295
+ entries.push(entry);
296
+ });
297
+ }
298
+ return entries;
299
+ }
300
+ const chatAgentsCollectFile = (value, previous = []) => [...previous, value];
301
+ exports.chatAgentsCollectFile = chatAgentsCollectFile;
302
+ async function chatAgentsDeleteVersionCommand(agentId, opts) {
303
+ const versionId = (0, versions_1.firstVersion)(opts.versions);
304
+ if (!versionId)
305
+ return (0, ui_1.handleError)(new Error('--versions <id> is required.'));
306
+ try {
307
+ const response = await (0, session_1.requireApi)().deleteChatAgentVersion(agentId, versionId);
308
+ if (opts.json)
309
+ return void console.log(JSON.stringify(response, null, 2));
310
+ (0, ui_1.success)(response.msg || 'Version deleted.');
311
+ }
312
+ catch (error) {
313
+ (0, ui_1.handleError)(error);
314
+ }
315
+ }
316
+ async function chatAgentsImportVersionsCommand(agentId, opts) {
317
+ try {
318
+ const response = await (0, session_1.requireApi)().importChatAgentVersions(agentId, readEntries(opts.file || []));
319
+ if (opts.json)
320
+ return void console.log(JSON.stringify(response, null, 2));
321
+ (0, ui_1.success)(response.msg || 'Versions imported.');
322
+ for (const v of response.newVersions || [])
323
+ (0, ui_1.info)(` ${v.versionName || ''} ${v._id}`);
324
+ }
325
+ catch (error) {
326
+ (0, ui_1.handleError)(error);
327
+ }
328
+ }
329
+ async function chatAgentsImportCommand(opts) {
330
+ try {
331
+ const response = await (0, session_1.requireApi)().importChatAgent(readEntries(opts.file || []));
332
+ if (opts.json)
333
+ return void console.log(JSON.stringify(response, null, 2));
334
+ (0, ui_1.success)(response.msg || 'Chat agent imported.');
335
+ if (response.chatAgent) {
336
+ (0, ui_1.info)(` id: ${response.chatAgent._id}`);
337
+ (0, ui_1.info)(` version: ${response.chatAgent.versionId}`);
338
+ }
339
+ }
340
+ catch (error) {
341
+ (0, ui_1.handleError)(error);
342
+ }
343
+ }
344
+ async function chatAgentsCommitsCommand(agentId, opts) {
345
+ try {
346
+ const response = await (0, session_1.requireApi)().listChatAgentCommits(agentId, {
347
+ version: (0, versions_1.firstVersion)(opts.versions),
348
+ page: opts.page ? Number(opts.page) : undefined,
349
+ });
350
+ if (opts.file) {
351
+ (0, fs_1.writeFileSync)(opts.file, JSON.stringify(response, null, 2));
352
+ return void (0, ui_1.success)(`Saved commits for ${agentId} to ${opts.file}`);
353
+ }
354
+ if (opts.json)
355
+ return void console.log(JSON.stringify(response, null, 2));
356
+ const commits = response.commits || [];
357
+ if (!commits.length)
358
+ return void (0, ui_1.info)('No commits found.');
359
+ (0, ui_1.table)(['COMMIT ID', 'VERSION', 'MESSAGE', 'BY', 'WHEN'], commits.map((c) => [c._id, c.versionName || '', c.commitMessage || '', c.commited_by?.name || '', c.createdAt || '']));
360
+ if (response.pagination) {
361
+ const { page, totalPages, totalDocs } = response.pagination;
362
+ (0, ui_1.info)(`page ${page} of ${totalPages || 1} (${totalDocs} commits)`);
363
+ }
364
+ }
365
+ catch (error) {
366
+ (0, ui_1.handleError)(error);
367
+ }
368
+ }
369
+ async function chatAgentsCommitCommand(commitId, opts) {
370
+ try {
371
+ const response = await (0, session_1.requireApi)().getChatAgentCommit(commitId);
372
+ if (opts.file) {
373
+ (0, fs_1.writeFileSync)(opts.file, JSON.stringify(response, null, 2));
374
+ return void (0, ui_1.success)(`Saved commit ${commitId} to ${opts.file}`);
375
+ }
376
+ if (opts.json)
377
+ return void console.log(JSON.stringify(response, null, 2));
378
+ const c = response.commit || response;
379
+ (0, ui_1.keyValue)({
380
+ id: c._id,
381
+ version: c.versionName,
382
+ versionId: c.versionId,
383
+ message: c.commitMessage,
384
+ by: c.commited_by?.name,
385
+ at: c.createdAt,
386
+ });
387
+ (0, ui_1.info)('Use --json to see the full saved state.');
388
+ }
389
+ catch (error) {
390
+ (0, ui_1.handleError)(error);
391
+ }
392
+ }
393
+ async function chatAgentsRevertCommand(agentId, commitId, opts) {
394
+ try {
395
+ const response = await (0, session_1.requireApi)().revertChatAgentCommit(agentId, commitId);
396
+ if (opts.json)
397
+ return void console.log(JSON.stringify(response, null, 2));
398
+ (0, ui_1.success)(response.msg || 'Reverted.');
399
+ }
400
+ catch (error) {
401
+ (0, ui_1.handleError)(error);
402
+ }
403
+ }
@@ -28,8 +28,10 @@ function buildFields(opts) {
28
28
  ...(opts.set ? (0, setJson_1.readSetJson)(opts.set) : {}),
29
29
  name: opts.name,
30
30
  audit_strategy: opts.strategy,
31
+ ...(opts.chatflowSummary !== undefined ? { chatflow_summary: opts.chatflowSummary } : {}),
31
32
  active: opts.disable ? false : opts.active,
32
- llms: opts.model ? { name: opts.model } : undefined,
33
+ // ponytail: only add llms when --model given, so --set llms survives pruneUndefined
34
+ ...(opts.model ? { llms: { name: opts.model } } : {}),
33
35
  percentage_per_day: numericFlag(opts.pctPerDay, '--pct-per-day'),
34
36
  max_conversations_per_day: numericFlag(opts.maxPerDay, '--max-per-day'),
35
37
  min_user_messages: numericFlag(opts.minUserMessages, '--min-user-messages'),
@@ -63,6 +65,7 @@ async function chatAuditGetCommand(agentId, strategyId, opts) {
63
65
  id: strategy._id,
64
66
  active: strategy.active,
65
67
  audit_strategy: strategy.audit_strategy,
68
+ chatflow_summary: strategy.chatflow_summary,
66
69
  llms: JSON.stringify(strategy.llms),
67
70
  audit_filters: JSON.stringify(strategy.audit_filters),
68
71
  percentage_per_day: strategy.percentage_per_day,
@@ -58,7 +58,7 @@ async function updateCommand(opts) {
58
58
  (0, ui_1.info)('Removing legacy @callkaro/cli installation …');
59
59
  (0, child_process_1.execFileSync)(bin('npm'), ['uninstall', '--global', '@callkaro/cli'], { stdio: 'ignore', shell: win });
60
60
  }
61
- (0, child_process_1.execFileSync)(bin('npm'), ['install', '--global', 'callkaro-cli-unofficial'], { stdio: 'ignore', shell: win });
61
+ (0, child_process_1.execFileSync)(bin('npm'), ['install', '--global', 'callkaro-cli-unofficial@latest'], { stdio: 'ignore', shell: win });
62
62
  }
63
63
  catch {
64
64
  if (win) {
package/dist/index.js CHANGED
@@ -81,6 +81,7 @@ const adminAuth_1 = require("./lib/adminAuth");
81
81
  const admin_1 = require("./commands/admin");
82
82
  const auditStrategies_1 = require("./commands/auditStrategies");
83
83
  const chatAgents_1 = require("./commands/chatAgents");
84
+ const updateCheck_1 = require("./lib/updateCheck");
84
85
  // The command this fork installs as. Deliberately NOT `ck` or `callkaro`:
85
86
  // those belong to @callkaro-official/cli, and both packages write to the same
86
87
  // global node_modules/.bin, so sharing a name means whichever npm install ran
@@ -1002,6 +1003,18 @@ chatAgents.command('publish <agentId>').description('publish a chat-agent versio
1002
1003
  .requiredOption('--versions <id>', 'version id to publish')
1003
1004
  .option('--json', 'output the raw response')
1004
1005
  .action(chatAgents_1.chatAgentsPublishCommand);
1006
+ chatAgents.command('delete-version <agentId>').description('delete a chat-agent version and its commit history (refused if published or assigned by another version)')
1007
+ .requiredOption('--versions <id>', 'version id to delete').option('--json', 'output the raw response').action(chatAgents_1.chatAgentsDeleteVersionCommand);
1008
+ chatAgents.command('import-versions <agentId>').description('add versions to a chat agent from exported JSON (object or array; repeat --file for several files)')
1009
+ .requiredOption('--file <path>', 'exported JSON file', chatAgents_1.chatAgentsCollectFile).option('--json', 'output the raw response').action(chatAgents_1.chatAgentsImportVersionsCommand);
1010
+ chatAgents.command('import').description('create a chat agent from exported JSON; several versions become one agent (agent-level fields must match)')
1011
+ .requiredOption('--file <path>', 'exported JSON file', chatAgents_1.chatAgentsCollectFile).option('--json', 'output the raw response').action(chatAgents_1.chatAgentsImportCommand);
1012
+ chatAgents.command('commits <agentId>').description("list a chat agent's version commits, newest first")
1013
+ .option('--versions <id>', 'only this version').option('--page <n>', 'page number').option('--json', 'output raw JSON').option('--file <path>', 'save JSON to a file').action(chatAgents_1.chatAgentsCommitsCommand);
1014
+ chatAgents.command('commit <commitId>').description('show a commit (use --json for its full saved state)')
1015
+ .option('--json', 'output raw JSON').option('--file <path>', 'save JSON to a file').action(chatAgents_1.chatAgentsCommitCommand);
1016
+ chatAgents.command('revert <agentId> <commitId>').description("set a version back to a commit's saved state")
1017
+ .option('--json', 'output the raw response').action(chatAgents_1.chatAgentsRevertCommand);
1005
1018
  // --- skills ----------------------------------------------------------------
1006
1019
  const skills = program.command('skills').description('AI skill pack for Claude Code & other agents');
1007
1020
  function addSkillsProviderOptions(command) {
@@ -1282,7 +1295,9 @@ analytics.command('performance').description('per-agent performance')
1282
1295
  .option('--json', 'raw JSON')
1283
1296
  .action(analytics_1.analyticsPerformanceCommand);
1284
1297
  analytics.command('version <agentId>').description('per-version analytics for an agent')
1285
- .option('--versions <ids>', 'comma-separated version ids')
1298
+ .option('--versions <ids>', 'comma-separated final version ids')
1299
+ .option('--initial-versions <ids>', 'comma-separated initial version ids (calls that started on these versions)')
1300
+ .option('--cohort <view>', 'leads = Lead View (count each lead once) instead of per-call')
1286
1301
  .option('--start <date>', 'start date')
1287
1302
  .option('--end <date>', 'end date')
1288
1303
  .option('--json', 'raw JSON')
@@ -1453,6 +1468,7 @@ chatAudit.command('create <agentId>').description('create a chat audit strategy'
1453
1468
  .option('--min-user-messages <n>', 'skip conversations with fewer customer messages (default 1)')
1454
1469
  .option('--min-messages <n>', 'skip conversations with fewer total messages (default 2)')
1455
1470
  .option('--set <json|@file>', 'JSON for audit_filters/extra_variables/llms; attribute names/values: `cku contacts attributes list`')
1471
+ .option('--chatflow-summary <text>', 'how the conversation should go (stages, required actions, outcome); the auditor judges against this, not the published version')
1456
1472
  .action(chatAuditStrategies_1.chatAuditCreateCommand);
1457
1473
  chatAudit.command('update <agentId> <strategyId>').description('update a chat audit strategy (only named fields change)')
1458
1474
  .option('--name <name>', 'strategy name')
@@ -1465,6 +1481,7 @@ chatAudit.command('update <agentId> <strategyId>').description('update a chat au
1465
1481
  .option('--min-user-messages <n>', 'skip conversations with fewer customer messages')
1466
1482
  .option('--min-messages <n>', 'skip conversations with fewer total messages')
1467
1483
  .option('--set <json|@file>', 'JSON for audit_filters/extra_variables/llms; each replaces the stored value')
1484
+ .option('--chatflow-summary <text>', 'how the conversation should go (stages, required actions, outcome); the auditor judges against this, not the published version')
1468
1485
  .action(chatAuditStrategies_1.chatAuditUpdateCommand);
1469
1486
  chatAudit.command('reports').description('list chat audit report batches (dashboard session)')
1470
1487
  .option('--agent <id>', 'chat agent id').option('--page <n>', 'page number').option('--json', 'raw JSON')
@@ -1592,6 +1609,7 @@ if (process.argv.length <= 2) {
1592
1609
  program.outputHelp();
1593
1610
  process.exit(0);
1594
1611
  }
1612
+ (0, updateCheck_1.notifyIfOutdated)(VERSION, process.argv.slice(2));
1595
1613
  program.parseAsync(rewriteGetVersions(process.argv));
1596
1614
  /**
1597
1615
  * Rewrite `agents get versions <agentId>` → `agents versions <agentId>`.
package/dist/lib/api.js CHANGED
@@ -270,6 +270,24 @@ class Api {
270
270
  publishChatAgentVersion(agentId, versionId) {
271
271
  return this.request('POST', `/cli/chat-agents/${agentId}/publish`, { versionId });
272
272
  }
273
+ deleteChatAgentVersion(agentId, versionId) {
274
+ return this.request('DELETE', `/cli/chat-agents/${agentId}/versions/${versionId}`);
275
+ }
276
+ importChatAgentVersions(agentId, entries) {
277
+ return this.request('POST', `/cli/chat-agents/${agentId}/import-versions`, entries);
278
+ }
279
+ importChatAgent(entries) {
280
+ return this.request('POST', '/cli/chat-agents/import-multiple', entries);
281
+ }
282
+ listChatAgentCommits(agentId, opts = {}) {
283
+ return this.request('GET', `/cli/chat-agents/${agentId}/commits${qs(opts)}`);
284
+ }
285
+ getChatAgentCommit(commitId) {
286
+ return this.request('GET', `/cli/chat-agents/commits/${commitId}`);
287
+ }
288
+ revertChatAgentCommit(agentId, commitId) {
289
+ return this.request('POST', `/cli/chat-agents/${agentId}/commits/${commitId}/revert`, {});
290
+ }
273
291
  // --- whatsapp numbers -----------------------------------------------------
274
292
  // Numbers come from Meta (the linked WhatsApp Business Account), not a
275
293
  // platform pool, so there is no buy/catalog counterpart to /cli/numbers.
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.isNewer = isNewer;
7
+ exports.notifyIfOutdated = notifyIfOutdated;
8
+ const os_1 = require("os");
9
+ const path_1 = require("path");
10
+ const fs_1 = require("fs");
11
+ const child_process_1 = require("child_process");
12
+ const chalk_1 = __importDefault(require("chalk"));
13
+ const CACHE = (0, path_1.join)(process.env.CK_CONFIG_DIR || (0, path_1.join)((0, os_1.homedir)(), '.config', 'callkaro-unofficial'), 'update-check.json');
14
+ const DAY = 24 * 60 * 60 * 1000;
15
+ const REGISTRY = 'https://registry.npmjs.org/callkaro-cli-unofficial/latest';
16
+ /** True when `latest` is a higher x.y.z than `current` (pre-release tags ignored). */
17
+ function isNewer(latest, current) {
18
+ const n = (v) => v.split('-')[0].split('.').map((x) => parseInt(x, 10) || 0);
19
+ const [a, b] = [n(latest), n(current)];
20
+ for (let i = 0; i < 3; i++) {
21
+ if ((a[i] || 0) !== (b[i] || 0))
22
+ return (a[i] || 0) > (b[i] || 0);
23
+ }
24
+ return false;
25
+ }
26
+ /**
27
+ * Tell the user (or the agent driving the CLI) when a newer release exists.
28
+ *
29
+ * Reads the answer cached by an earlier run and prints it to stderr after the
30
+ * command's own output, so stdout / --json stay clean. The npm lookup runs in a
31
+ * detached child at most once a day, so it never delays or breaks a command.
32
+ * Opt out with CK_NO_UPDATE_CHECK=1 (or when running under `node --test`).
33
+ */
34
+ function notifyIfOutdated(current, argv) {
35
+ try {
36
+ if (process.env.CK_NO_UPDATE_CHECK || process.env.NODE_TEST_CONTEXT)
37
+ return;
38
+ if (argv.some((a) => ['update', '-v', '--version', '-h', '--help'].includes(a)))
39
+ return;
40
+ let cache = {};
41
+ try {
42
+ cache = JSON.parse((0, fs_1.readFileSync)(CACHE, 'utf8'));
43
+ }
44
+ catch {
45
+ /* first run */
46
+ }
47
+ if (cache.latest && isNewer(cache.latest, current)) {
48
+ process.on('exit', () => {
49
+ process.stderr.write(chalk_1.default.yellow(`\nA newer CallKaro CLI (cku) is available: ${current} -> ${cache.latest}.\n` +
50
+ `AI agents: tell the user the CLI is outdated and ask if they want to upgrade; if yes, run \`cku update\`.\n`));
51
+ });
52
+ }
53
+ if (!cache.checkedAt || Date.now() - cache.checkedAt > DAY) {
54
+ const script = `
55
+ const fs = require('fs'), path = require('path');
56
+ const file = process.argv[1];
57
+ (async () => {
58
+ let latest;
59
+ try { latest = (await (await fetch(${JSON.stringify(REGISTRY)}, { signal: AbortSignal.timeout(5000) })).json()).version; } catch {}
60
+ fs.mkdirSync(path.dirname(file), { recursive: true });
61
+ fs.writeFileSync(file, JSON.stringify({ checkedAt: Date.now(), latest }));
62
+ })();`;
63
+ (0, child_process_1.spawn)(process.execPath, ['-e', script, CACHE], { detached: true, stdio: 'ignore' }).unref();
64
+ }
65
+ }
66
+ catch {
67
+ /* an update check must never break a command */
68
+ }
69
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "callkaro-cli-unofficial",
3
- "version": "0.9.0",
3
+ "version": "0.9.2",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Unofficial fork of the CallKaro CLI — manage your voice AI agents from the terminal",
6
6
  "bin": {