callkaro-cli-unofficial 0.7.1 → 0.8.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.
- package/dist/commands/agentVersions.js +153 -0
- package/dist/commands/aiTools.js +64 -0
- package/dist/commands/analytics.js +66 -0
- package/dist/commands/analyzers.js +99 -0
- package/dist/commands/dnd.js +105 -0
- package/dist/commands/feedback.js +84 -0
- package/dist/commands/knowledge.js +33 -0
- package/dist/commands/kpi.js +631 -12
- package/dist/commands/simulations.js +68 -0
- package/dist/index.js +310 -1
- package/dist/lib/dashboardApi.js +262 -0
- package/dist/lib/kpiReport.js +363 -0
- package/package.json +1 -1
|
@@ -5,7 +5,15 @@ exports.agentsPublishCommand = agentsPublishCommand;
|
|
|
5
5
|
exports.agentsToggleActiveCommand = agentsToggleActiveCommand;
|
|
6
6
|
exports.agentsAbCommand = agentsAbCommand;
|
|
7
7
|
exports.agentsAbAdvancedCommand = agentsAbAdvancedCommand;
|
|
8
|
+
exports.agentsCommitsCommand = agentsCommitsCommand;
|
|
9
|
+
exports.agentsCommitShowCommand = agentsCommitShowCommand;
|
|
10
|
+
exports.agentsDiffCommand = agentsDiffCommand;
|
|
11
|
+
exports.agentsRevertCommand = agentsRevertCommand;
|
|
12
|
+
exports.agentsSaveV2Command = agentsSaveV2Command;
|
|
13
|
+
exports.agentsDeleteVersionCommand = agentsDeleteVersionCommand;
|
|
14
|
+
exports.agentsDuplicateCommand = agentsDuplicateCommand;
|
|
8
15
|
const session_1 = require("../lib/session");
|
|
16
|
+
const dashboardApi_1 = require("../lib/dashboardApi");
|
|
9
17
|
const ui_1 = require("../lib/ui");
|
|
10
18
|
const versions_1 = require("../lib/versions");
|
|
11
19
|
const agentUpdate_1 = require("../lib/agentUpdate");
|
|
@@ -226,3 +234,148 @@ async function agentsAbAdvancedCommand(agentId, opts) {
|
|
|
226
234
|
(0, ui_1.handleError)(err);
|
|
227
235
|
}
|
|
228
236
|
}
|
|
237
|
+
/** `cku agents commits <agentId>` */
|
|
238
|
+
async function agentsCommitsCommand(agentId, opts) {
|
|
239
|
+
try {
|
|
240
|
+
const res = await (0, dashboardApi_1.dashboardApi)().agentCommits(agentId, {
|
|
241
|
+
version: opts.versions ? (0, versions_1.firstVersion)(opts.versions) : undefined,
|
|
242
|
+
page: Number(opts.page) || 1,
|
|
243
|
+
pageSize: Number(opts.limit) || 25,
|
|
244
|
+
});
|
|
245
|
+
if (opts.json)
|
|
246
|
+
return void console.log(JSON.stringify(res?.commits || res, null, 2));
|
|
247
|
+
const rows = res?.commits || [];
|
|
248
|
+
if (!rows.length)
|
|
249
|
+
return void (0, ui_1.info)('No commits.');
|
|
250
|
+
(0, ui_1.table)(['COMMIT ID', 'VERSION', 'MESSAGE', 'AUTHOR', 'CREATED'], rows.map((c) => [
|
|
251
|
+
c._id,
|
|
252
|
+
c.versionId,
|
|
253
|
+
c.commitMessage || c.message || '',
|
|
254
|
+
c.author?.name || c.author?.email || c.user?.email || '',
|
|
255
|
+
c.createdAt,
|
|
256
|
+
]));
|
|
257
|
+
}
|
|
258
|
+
catch (err) {
|
|
259
|
+
(0, ui_1.handleError)(err);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
/** `cku agents commit-show <commitId>` */
|
|
263
|
+
async function agentsCommitShowCommand(commitId, opts) {
|
|
264
|
+
try {
|
|
265
|
+
const res = await (0, dashboardApi_1.dashboardApi)().agentCommit(commitId);
|
|
266
|
+
const c = res?.commit || res;
|
|
267
|
+
if (opts.json)
|
|
268
|
+
return void console.log(JSON.stringify(c, null, 2));
|
|
269
|
+
(0, ui_1.keyValue)({
|
|
270
|
+
id: c?._id,
|
|
271
|
+
versionId: c?.versionId,
|
|
272
|
+
commitMessage: c?.commitMessage,
|
|
273
|
+
createdAt: c?.createdAt,
|
|
274
|
+
model: c?.model,
|
|
275
|
+
voice_provider: c?.voice_provider,
|
|
276
|
+
functions: (c?.functions || []).length,
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
catch (err) {
|
|
280
|
+
(0, ui_1.handleError)(err);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
/** `cku agents diff <agentId> --commits a,b | --versions a,b` */
|
|
284
|
+
async function agentsDiffCommand(agentId, opts) {
|
|
285
|
+
const usage = 'Pass --commits <idA,idB> or --versions <vA,vB> (two comma-separated ids).';
|
|
286
|
+
const commits = opts.commits ? (0, versions_1.versionList)(opts.commits) : [];
|
|
287
|
+
const versions = opts.versions ? (0, versions_1.versionList)(opts.versions) : [];
|
|
288
|
+
const ids = commits.length ? commits : versions;
|
|
289
|
+
if (ids.length < 2)
|
|
290
|
+
return (0, ui_1.handleError)(new Error(usage));
|
|
291
|
+
try {
|
|
292
|
+
const api = (0, dashboardApi_1.dashboardApi)();
|
|
293
|
+
const res = commits.length
|
|
294
|
+
? await api.compareAgentCommits(agentId, ids[0], ids[1])
|
|
295
|
+
: await api.compareAgentVersions([ids[0], ids[1]]);
|
|
296
|
+
if (opts.json)
|
|
297
|
+
return void console.log(JSON.stringify(res, null, 2));
|
|
298
|
+
const diff = res?.diff ?? res?.changes ?? res;
|
|
299
|
+
if (Array.isArray(diff)) {
|
|
300
|
+
if (!diff.length)
|
|
301
|
+
return void (0, ui_1.info)('No differences.');
|
|
302
|
+
(0, ui_1.table)(['FIELD', 'A', 'B'], diff.map((d) => [d.field || d.key || d.path || '', clipVal(d.a ?? d.before ?? d.from), clipVal(d.b ?? d.after ?? d.to)]));
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
const keys = diff && typeof diff === 'object' ? Object.keys(diff) : [];
|
|
306
|
+
if (!keys.length)
|
|
307
|
+
return void (0, ui_1.info)('No differences.');
|
|
308
|
+
(0, ui_1.info)(`Changed keys (${keys.length}):`);
|
|
309
|
+
keys.forEach((k) => (0, ui_1.info)(` ${k}`));
|
|
310
|
+
(0, ui_1.info)('Full detail: add --json');
|
|
311
|
+
}
|
|
312
|
+
catch (err) {
|
|
313
|
+
(0, ui_1.handleError)(err);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
function clipVal(v) {
|
|
317
|
+
const t = v === undefined || v === null ? '' : typeof v === 'string' ? v : JSON.stringify(v);
|
|
318
|
+
return t.length > 60 ? `${t.slice(0, 59)}…` : t;
|
|
319
|
+
}
|
|
320
|
+
/** `cku agents revert <agentId> <commitId>` */
|
|
321
|
+
async function agentsRevertCommand(agentId, commitId, opts) {
|
|
322
|
+
try {
|
|
323
|
+
if (!(await (0, ui_1.confirm)(`Revert agent ${agentId} to commit ${commitId}?`, opts.yes)))
|
|
324
|
+
return;
|
|
325
|
+
const res = await (0, dashboardApi_1.dashboardApi)().revertAgentCommit(agentId, commitId);
|
|
326
|
+
if (opts.json)
|
|
327
|
+
return void console.log(JSON.stringify(res, null, 2));
|
|
328
|
+
(0, ui_1.success)(`Reverted ${agentId} to commit ${commitId}.`);
|
|
329
|
+
}
|
|
330
|
+
catch (err) {
|
|
331
|
+
(0, ui_1.handleError)(err);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
/** `cku agents save-v2 <agentId> --set <json>` */
|
|
335
|
+
async function agentsSaveV2Command(agentId, opts) {
|
|
336
|
+
try {
|
|
337
|
+
const body = { ...(0, setJson_1.readSetJson)(opts.set) };
|
|
338
|
+
if (opts.message)
|
|
339
|
+
body.commitMessage = opts.message;
|
|
340
|
+
const versionId = opts.versions ? (0, versions_1.firstVersion)(opts.versions) : undefined;
|
|
341
|
+
const res = await (0, dashboardApi_1.dashboardApi)().updateAgentV2(agentId, versionId, body);
|
|
342
|
+
if (opts.json)
|
|
343
|
+
return void console.log(JSON.stringify(res, null, 2));
|
|
344
|
+
(0, ui_1.success)(`Saved ${agentId}${opts.versions ? ` (version ${(0, versions_1.firstVersion)(opts.versions)})` : ''} via /v2/agents.`);
|
|
345
|
+
}
|
|
346
|
+
catch (err) {
|
|
347
|
+
(0, ui_1.handleError)(err);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
/** `cku agents delete-version <agentId> <versionId>` */
|
|
351
|
+
async function agentsDeleteVersionCommand(agentId, versionId, opts) {
|
|
352
|
+
try {
|
|
353
|
+
if (!(await (0, ui_1.confirm)(`Delete version ${versionId} of agent ${agentId}?`, opts.yes)))
|
|
354
|
+
return;
|
|
355
|
+
const res = await (0, dashboardApi_1.dashboardApi)().deleteAgentVersionV2(agentId, versionId);
|
|
356
|
+
if (opts.json)
|
|
357
|
+
return void console.log(JSON.stringify(res, null, 2));
|
|
358
|
+
(0, ui_1.success)(`Deleted version ${versionId}.`);
|
|
359
|
+
}
|
|
360
|
+
catch (err) {
|
|
361
|
+
(0, ui_1.handleError)(err);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
/** `cku agents duplicate <agentId> --name <n>` */
|
|
365
|
+
async function agentsDuplicateCommand(agentId, opts) {
|
|
366
|
+
if (!opts.name?.trim())
|
|
367
|
+
return (0, ui_1.handleError)(new Error('--name <newName> is required'));
|
|
368
|
+
try {
|
|
369
|
+
const res = await (0, dashboardApi_1.dashboardApi)().duplicateAgentV2(agentId, {
|
|
370
|
+
name: opts.name.trim(),
|
|
371
|
+
...(opts.versions ? { versions: (0, versions_1.versionList)(opts.versions) } : {}),
|
|
372
|
+
});
|
|
373
|
+
if (opts.json)
|
|
374
|
+
return void console.log(JSON.stringify(res, null, 2));
|
|
375
|
+
const newId = res?.agent?._id || res?._id || res?.agentId;
|
|
376
|
+
(0, ui_1.success)(`Duplicated ${agentId} as "${opts.name.trim()}"${newId ? ` (id ${newId})` : ''}.`);
|
|
377
|
+
}
|
|
378
|
+
catch (err) {
|
|
379
|
+
(0, ui_1.handleError)(err);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.aiGenerateFunctionCommand = aiGenerateFunctionCommand;
|
|
4
|
+
exports.aiGeneratePostcallCommand = aiGeneratePostcallCommand;
|
|
5
|
+
exports.aiGenerateAuditStrategyCommand = aiGenerateAuditStrategyCommand;
|
|
6
|
+
exports.aiGenerateCallflowSummaryCommand = aiGenerateCallflowSummaryCommand;
|
|
7
|
+
exports.aiGenerateWorkflowCodeCommand = aiGenerateWorkflowCodeCommand;
|
|
8
|
+
const dashboardApi_1 = require("../lib/dashboardApi");
|
|
9
|
+
const ui_1 = require("../lib/ui");
|
|
10
|
+
const setJson_1 = require("./setJson");
|
|
11
|
+
const show = (res) => console.log(typeof res === 'string' ? res : JSON.stringify(res, null, 2));
|
|
12
|
+
async function aiGenerateFunctionCommand(opts) {
|
|
13
|
+
try {
|
|
14
|
+
const api = (0, dashboardApi_1.dashboardApi)();
|
|
15
|
+
const vars = opts.vars ? opts.vars.split(',').map((s) => s.trim()).filter(Boolean) : undefined;
|
|
16
|
+
const body = {
|
|
17
|
+
prompt: opts.prompt,
|
|
18
|
+
...(opts.code ? { existingCode: opts.code } : {}),
|
|
19
|
+
...(opts.name ? { name: opts.name } : {}),
|
|
20
|
+
...(opts.description ? { description: opts.description } : {}),
|
|
21
|
+
...(opts.type ? { type: opts.type } : {}),
|
|
22
|
+
...(vars ? { prompt_variables: vars } : {}),
|
|
23
|
+
};
|
|
24
|
+
const res = opts.chat
|
|
25
|
+
? await api.request('POST', '/openai-tools/generate-chat-function', body)
|
|
26
|
+
: await api.generateFunctionCode(body);
|
|
27
|
+
show(res);
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
(0, ui_1.handleError)(err);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async function aiGeneratePostcallCommand(opts) {
|
|
34
|
+
try {
|
|
35
|
+
show(await (0, dashboardApi_1.dashboardApi)().generatePostcallConfig((0, setJson_1.readSetJson)(opts.set)));
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
(0, ui_1.handleError)(err);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function aiGenerateAuditStrategyCommand(agentId, opts) {
|
|
42
|
+
try {
|
|
43
|
+
show(await (0, dashboardApi_1.dashboardApi)().generateAuditStrategyDraft({ agentId, text_input: opts.prompt, existingAuditStrategy: opts.existing }));
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
(0, ui_1.handleError)(err);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async function aiGenerateCallflowSummaryCommand(agentId, opts) {
|
|
50
|
+
try {
|
|
51
|
+
show(await (0, dashboardApi_1.dashboardApi)().generateCallflowSummaryDraft({ agentId, text_input: opts.prompt, existingCallflowSummary: opts.existing }));
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
(0, ui_1.handleError)(err);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async function aiGenerateWorkflowCodeCommand(opts) {
|
|
58
|
+
try {
|
|
59
|
+
show(await (0, dashboardApi_1.dashboardApi)().generateWorkflowCode({ prompt: opts.prompt, stepName: opts.name, stepKey: opts.key, existingCode: opts.existing }));
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
(0, ui_1.handleError)(err);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -3,6 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.analyticsOverviewCommand = analyticsOverviewCommand;
|
|
4
4
|
exports.analyticsPerformanceCommand = analyticsPerformanceCommand;
|
|
5
5
|
exports.analyticsVersionCommand = analyticsVersionCommand;
|
|
6
|
+
exports.analyticsFailedResponsesCommand = analyticsFailedResponsesCommand;
|
|
7
|
+
exports.analyticsFunctionsCommand = analyticsFunctionsCommand;
|
|
8
|
+
exports.analyticsChatCommand = analyticsChatCommand;
|
|
9
|
+
const dashboardApi_1 = require("../lib/dashboardApi");
|
|
6
10
|
const session_1 = require("../lib/session");
|
|
7
11
|
const ui_1 = require("../lib/ui");
|
|
8
12
|
async function analyticsOverviewCommand(opts) {
|
|
@@ -75,3 +79,65 @@ async function analyticsVersionCommand(agentId, opts) {
|
|
|
75
79
|
(0, ui_1.handleError)(err);
|
|
76
80
|
}
|
|
77
81
|
}
|
|
82
|
+
/** Render rows of objects as a table over their scalar keys. */
|
|
83
|
+
function objectTable(rows) {
|
|
84
|
+
const keys = Object.keys(rows[0] || {}).filter((k) => rows[0][k] === null || typeof rows[0][k] !== 'object');
|
|
85
|
+
(0, ui_1.table)(keys.map((k) => k.toUpperCase()), rows.map((r) => keys.map((k) => r[k] ?? '')));
|
|
86
|
+
}
|
|
87
|
+
/** `cku analytics failed-responses` */
|
|
88
|
+
async function analyticsFailedResponsesCommand(opts) {
|
|
89
|
+
try {
|
|
90
|
+
const q = { agent_ids: opts.agent, startDate: opts.start, endDate: opts.end };
|
|
91
|
+
const res = opts.response
|
|
92
|
+
? await (0, dashboardApi_1.dashboardApi)().failedResponseCalls({ ...q, response: opts.response, limit: Number(opts.limit) || 25 })
|
|
93
|
+
: await (0, dashboardApi_1.dashboardApi)().failedResponses(q);
|
|
94
|
+
if (opts.json)
|
|
95
|
+
return void console.log(JSON.stringify(res, null, 2));
|
|
96
|
+
const rows = res?.data || res?.calls || res?.responses || (Array.isArray(res) ? res : []);
|
|
97
|
+
if (!rows.length)
|
|
98
|
+
return void (0, ui_1.info)('No failed responses.');
|
|
99
|
+
objectTable(rows);
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
(0, ui_1.handleError)(err);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/** `cku analytics functions` */
|
|
106
|
+
async function analyticsFunctionsCommand(opts) {
|
|
107
|
+
try {
|
|
108
|
+
const res = await (0, dashboardApi_1.dashboardApi)().functionAnalytics({ agent_ids: opts.agent, startDate: opts.start, endDate: opts.end });
|
|
109
|
+
if (opts.json)
|
|
110
|
+
return void console.log(JSON.stringify(res, null, 2));
|
|
111
|
+
const rows = res?.data || res?.functions || (Array.isArray(res) ? res : []);
|
|
112
|
+
if (!rows.length)
|
|
113
|
+
return void (0, ui_1.info)('No function analytics.');
|
|
114
|
+
objectTable(rows);
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
(0, ui_1.handleError)(err);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/** `cku analytics chat` */
|
|
121
|
+
async function analyticsChatCommand(opts) {
|
|
122
|
+
try {
|
|
123
|
+
const res = await (0, dashboardApi_1.dashboardApi)().chatAnalytics({
|
|
124
|
+
chat_agent_id: opts.agent,
|
|
125
|
+
agent_ids: opts.agent,
|
|
126
|
+
startDate: opts.start,
|
|
127
|
+
endDate: opts.end,
|
|
128
|
+
});
|
|
129
|
+
if (opts.json)
|
|
130
|
+
return void console.log(JSON.stringify(res, null, 2));
|
|
131
|
+
const d = res?.data ?? res;
|
|
132
|
+
if (Array.isArray(d))
|
|
133
|
+
return void (d.length ? objectTable(d) : (0, ui_1.info)('No chat analytics.'));
|
|
134
|
+
const scalars = {};
|
|
135
|
+
for (const [k, v] of Object.entries(d || {}))
|
|
136
|
+
if (v === null || typeof v !== 'object')
|
|
137
|
+
scalars[k] = v;
|
|
138
|
+
(0, ui_1.keyValue)(scalars);
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
(0, ui_1.handleError)(err);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -4,6 +4,9 @@ exports.analyzersListCommand = analyzersListCommand;
|
|
|
4
4
|
exports.analyzersShowCommand = analyzersShowCommand;
|
|
5
5
|
exports.analyzersAuditReportsCommand = analyzersAuditReportsCommand;
|
|
6
6
|
exports.analyzersAuditStrategiesCommand = analyzersAuditStrategiesCommand;
|
|
7
|
+
exports.analyzersSummaryCommand = analyzersSummaryCommand;
|
|
8
|
+
exports.analyzersCallsCommand = analyzersCallsCommand;
|
|
9
|
+
exports.analyzersCallDetailCommand = analyzersCallDetailCommand;
|
|
7
10
|
const dashboardApi_1 = require("../lib/dashboardApi");
|
|
8
11
|
const ui_1 = require("../lib/ui");
|
|
9
12
|
const when = (value) => {
|
|
@@ -128,3 +131,99 @@ async function analyzersAuditStrategiesCommand(opts) {
|
|
|
128
131
|
(0, ui_1.handleError)(err);
|
|
129
132
|
}
|
|
130
133
|
}
|
|
134
|
+
const resolveScope = (opts) => (opts.batch ? 'batches' : 'strategies');
|
|
135
|
+
/** Print an object-or-array breakdown as a two-column table. */
|
|
136
|
+
function breakdown(title, v) {
|
|
137
|
+
if (!v)
|
|
138
|
+
return;
|
|
139
|
+
const rows = Array.isArray(v)
|
|
140
|
+
? v.map((x) => [x?.name ?? x?.category ?? x?.severity ?? x?.value ?? x?._id ?? '', x?.count ?? x?.total ?? clip(JSON.stringify(x))])
|
|
141
|
+
: typeof v === 'object'
|
|
142
|
+
? Object.entries(v).map(([k, x]) => [k, typeof x === 'object' ? clip(JSON.stringify(x), 80) : x])
|
|
143
|
+
: [];
|
|
144
|
+
if (!rows.length)
|
|
145
|
+
return;
|
|
146
|
+
(0, ui_1.info)(`\n${title}:`);
|
|
147
|
+
(0, ui_1.table)(['NAME', 'VALUE'], rows);
|
|
148
|
+
}
|
|
149
|
+
/** `cku analyzers summary <id> [--batch]` */
|
|
150
|
+
async function analyzersSummaryCommand(id, opts) {
|
|
151
|
+
try {
|
|
152
|
+
const res = await (0, dashboardApi_1.dashboardApi)().auditSummary(resolveScope(opts), id, {
|
|
153
|
+
severity: opts.severity,
|
|
154
|
+
dimension: opts.dimension,
|
|
155
|
+
startDate: opts.since,
|
|
156
|
+
endDate: opts.until,
|
|
157
|
+
});
|
|
158
|
+
if (opts.json)
|
|
159
|
+
return void console.log(JSON.stringify(res, null, 2));
|
|
160
|
+
const d = res?.data ?? res ?? {};
|
|
161
|
+
const scalars = {};
|
|
162
|
+
for (const [k, v] of Object.entries(d))
|
|
163
|
+
if (v === null || typeof v !== 'object')
|
|
164
|
+
scalars[k] = v;
|
|
165
|
+
(0, ui_1.keyValue)(scalars);
|
|
166
|
+
for (const [k, v] of Object.entries(d))
|
|
167
|
+
if (v && typeof v === 'object')
|
|
168
|
+
breakdown(k, v);
|
|
169
|
+
}
|
|
170
|
+
catch (err) {
|
|
171
|
+
(0, ui_1.handleError)(err);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/** `cku analyzers calls <id>` — drill into audited calls. */
|
|
175
|
+
async function analyzersCallsCommand(id, opts) {
|
|
176
|
+
const scope = resolveScope(opts);
|
|
177
|
+
const q = { page: Number(opts.page) || 1, page_size: pageSize(opts.limit) };
|
|
178
|
+
try {
|
|
179
|
+
const api = (0, dashboardApi_1.dashboardApi)();
|
|
180
|
+
let res;
|
|
181
|
+
if (opts.below80)
|
|
182
|
+
res = await api.auditBelow80Calls(scope, id, { ...q, sort: opts.sort });
|
|
183
|
+
else if (opts.severity)
|
|
184
|
+
res = await api.auditSeverityCalls(scope, id, opts.severity, q);
|
|
185
|
+
else if (opts.dimension && opts.category)
|
|
186
|
+
res = await api.auditCategoryCalls(scope, id, opts.dimension, opts.category, q);
|
|
187
|
+
else if (opts.varName && opts.varValue !== undefined)
|
|
188
|
+
res = await api.auditExtraVariableCalls(scope, id, opts.varName, opts.varValue, q);
|
|
189
|
+
else {
|
|
190
|
+
return (0, ui_1.handleError)(new Error('Pass one filter: --below-80, --severity <sev>, --dimension <d> --category <c>, or --var-name <n> --var-value <v>.'));
|
|
191
|
+
}
|
|
192
|
+
if (opts.json)
|
|
193
|
+
return void console.log(JSON.stringify(res, null, 2));
|
|
194
|
+
const rows = res?.calls || res?.data || (Array.isArray(res) ? res : []);
|
|
195
|
+
if (!rows.length)
|
|
196
|
+
return void (0, ui_1.info)('No calls.');
|
|
197
|
+
(0, ui_1.table)(['CALL ID', 'SCORE', 'SEVERITY', 'SUMMARY'], rows.map((c) => [
|
|
198
|
+
c.callId || c.call_id || c._id || '',
|
|
199
|
+
score(c.overallScore ?? c.score ?? c.overall_score),
|
|
200
|
+
c.severity || '',
|
|
201
|
+
clip(c.summary || c.reason, 70),
|
|
202
|
+
]));
|
|
203
|
+
}
|
|
204
|
+
catch (err) {
|
|
205
|
+
(0, ui_1.handleError)(err);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/** `cku analyzers call <id> <callId>` */
|
|
209
|
+
async function analyzersCallDetailCommand(id, callId, opts) {
|
|
210
|
+
try {
|
|
211
|
+
const res = await (0, dashboardApi_1.dashboardApi)().auditCallDetail(resolveScope(opts), id, callId);
|
|
212
|
+
if (opts.json)
|
|
213
|
+
return void console.log(JSON.stringify(res, null, 2));
|
|
214
|
+
const d = res?.data ?? res?.call ?? res ?? {};
|
|
215
|
+
const scalars = {};
|
|
216
|
+
for (const [k, v] of Object.entries(d))
|
|
217
|
+
if (v === null || typeof v !== 'object')
|
|
218
|
+
scalars[k] = v;
|
|
219
|
+
(0, ui_1.keyValue)(scalars);
|
|
220
|
+
const findings = d.findings || d.issues;
|
|
221
|
+
if (Array.isArray(findings) && findings.length) {
|
|
222
|
+
(0, ui_1.info)('\nFindings:');
|
|
223
|
+
findings.forEach((f) => (0, ui_1.info)(` - ${clip(typeof f === 'string' ? f : f.description || f.summary || JSON.stringify(f), 200)}`));
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
catch (err) {
|
|
227
|
+
(0, ui_1.handleError)(err);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.dndListCommand = dndListCommand;
|
|
4
|
+
exports.dndAddCommand = dndAddCommand;
|
|
5
|
+
exports.dndUpdateCommand = dndUpdateCommand;
|
|
6
|
+
exports.dndRemoveCommand = dndRemoveCommand;
|
|
7
|
+
exports.dndImportCommand = dndImportCommand;
|
|
8
|
+
const fs_1 = require("fs");
|
|
9
|
+
const dashboardApi_1 = require("../lib/dashboardApi");
|
|
10
|
+
const ui_1 = require("../lib/ui");
|
|
11
|
+
const day = (s) => {
|
|
12
|
+
if (!s)
|
|
13
|
+
return undefined;
|
|
14
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(s))
|
|
15
|
+
throw new Error(`Date "${s}" must be YYYY-MM-DD.`);
|
|
16
|
+
return s;
|
|
17
|
+
};
|
|
18
|
+
async function dndListCommand(opts) {
|
|
19
|
+
try {
|
|
20
|
+
const res = await (0, dashboardApi_1.dashboardApi)().listDndNumbers({
|
|
21
|
+
page: Number(opts.page) || 1,
|
|
22
|
+
limit: Number(opts.limit) || 20,
|
|
23
|
+
search: opts.search,
|
|
24
|
+
startDate: day(opts.since),
|
|
25
|
+
endDate: day(opts.until),
|
|
26
|
+
});
|
|
27
|
+
if (opts.json)
|
|
28
|
+
return void console.log(JSON.stringify(res, null, 2));
|
|
29
|
+
const rows = res?.data || res?.numbers || res?.phoneNumbers || (Array.isArray(res) ? res : []);
|
|
30
|
+
if (!rows.length)
|
|
31
|
+
return void (0, ui_1.info)('No DND numbers.');
|
|
32
|
+
(0, ui_1.table)(['ID', 'PHONE', 'CREATED'], rows.map((r) => [r._id || r.id || '', r.phoneNumber || '', r.createdAt || '']));
|
|
33
|
+
if (res?.total !== undefined)
|
|
34
|
+
(0, ui_1.info)(`\nTotal: ${res.total}`);
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
(0, ui_1.handleError)(err);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async function dndAddCommand(phoneNumber, opts) {
|
|
41
|
+
try {
|
|
42
|
+
const res = await (0, dashboardApi_1.dashboardApi)().addDndNumber(phoneNumber);
|
|
43
|
+
if (opts.json)
|
|
44
|
+
return void console.log(JSON.stringify(res, null, 2));
|
|
45
|
+
(0, ui_1.success)(`Added ${phoneNumber} to DND.`);
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
(0, ui_1.handleError)(err);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async function dndUpdateCommand(id, phoneNumber, opts) {
|
|
52
|
+
try {
|
|
53
|
+
const res = await (0, dashboardApi_1.dashboardApi)().updateDndNumber(id, phoneNumber);
|
|
54
|
+
if (opts.json)
|
|
55
|
+
return void console.log(JSON.stringify(res, null, 2));
|
|
56
|
+
(0, ui_1.success)(`Updated ${id} to ${phoneNumber}.`);
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
(0, ui_1.handleError)(err);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async function dndRemoveCommand(idsCsv, opts) {
|
|
63
|
+
try {
|
|
64
|
+
const ids = idsCsv.split(',').map((s) => s.trim()).filter(Boolean);
|
|
65
|
+
if (!ids.length)
|
|
66
|
+
throw new Error('Give one or more DND record ids (comma-separated). List them with: cku dnd list');
|
|
67
|
+
if (!(await (0, ui_1.confirm)(`Remove ${ids.length} DND record(s)? Those numbers can be called again.`, opts.yes)))
|
|
68
|
+
return;
|
|
69
|
+
const api = (0, dashboardApi_1.dashboardApi)();
|
|
70
|
+
const res = ids.length === 1 ? await api.removeDndNumber(ids[0]) : await api.removeDndNumbers(ids);
|
|
71
|
+
if (opts.json)
|
|
72
|
+
return void console.log(JSON.stringify(res, null, 2));
|
|
73
|
+
(0, ui_1.success)(`Removed ${ids.length} DND record(s).`);
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
(0, ui_1.handleError)(err);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
async function dndImportCommand(opts) {
|
|
80
|
+
try {
|
|
81
|
+
if (!opts.phones && !opts.file)
|
|
82
|
+
throw new Error('Pass --phones <a,b,...> or --file <path> (comma/newline list or JSON array).');
|
|
83
|
+
const text = (opts.phones ?? (0, fs_1.readFileSync)(opts.file, 'utf8')).trim();
|
|
84
|
+
let phones;
|
|
85
|
+
if (text.startsWith('[')) {
|
|
86
|
+
const arr = JSON.parse(text);
|
|
87
|
+
if (!Array.isArray(arr))
|
|
88
|
+
throw new Error('JSON input must be an array of phone numbers.');
|
|
89
|
+
phones = arr.map((p) => String(p).trim());
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
phones = text.split(/[,\n\r]+/).map((s) => s.trim());
|
|
93
|
+
}
|
|
94
|
+
phones = phones.filter(Boolean);
|
|
95
|
+
if (!phones.length)
|
|
96
|
+
throw new Error('No phone numbers found in input.');
|
|
97
|
+
const res = await (0, dashboardApi_1.dashboardApi)().importDndNumbers(phones);
|
|
98
|
+
if (opts.json)
|
|
99
|
+
return void console.log(JSON.stringify(res, null, 2));
|
|
100
|
+
(0, ui_1.success)(`Imported ${phones.length} number(s) to DND.`);
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
(0, ui_1.handleError)(err);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.feedbackListCommand = feedbackListCommand;
|
|
4
|
+
exports.feedbackCreateCommand = feedbackCreateCommand;
|
|
5
|
+
exports.feedbackCommentCommand = feedbackCommentCommand;
|
|
6
|
+
exports.feedbackSubmitReviewCommand = feedbackSubmitReviewCommand;
|
|
7
|
+
exports.feedbackReopenCommand = feedbackReopenCommand;
|
|
8
|
+
exports.feedbackResolveCommand = feedbackResolveCommand;
|
|
9
|
+
const dashboardApi_1 = require("../lib/dashboardApi");
|
|
10
|
+
const ui_1 = require("../lib/ui");
|
|
11
|
+
const STATUSES = ['processing', 'in-review', 'resolved'];
|
|
12
|
+
const list = (s) => (s || '').split(',').map((x) => x.trim()).filter(Boolean);
|
|
13
|
+
const out = (json, res, msg) => json ? console.log(JSON.stringify(res, null, 2)) : (0, ui_1.success)(msg);
|
|
14
|
+
async function feedbackListCommand(opts) {
|
|
15
|
+
try {
|
|
16
|
+
const status = opts.status || 'processing';
|
|
17
|
+
if (!STATUSES.includes(status))
|
|
18
|
+
throw new Error(`--status must be one of: ${STATUSES.join(', ')} (got "${status}").`);
|
|
19
|
+
const res = await (0, dashboardApi_1.dashboardApi)().listFeedback({ status, page: Number(opts.page) || 1 });
|
|
20
|
+
if (opts.json)
|
|
21
|
+
return void console.log(JSON.stringify(res, null, 2));
|
|
22
|
+
const rows = res?.data || res?.feedbacks || res?.feedback || (Array.isArray(res) ? res : []);
|
|
23
|
+
if (!rows.length)
|
|
24
|
+
return void (0, ui_1.info)(`No ${status} feedback tickets.`);
|
|
25
|
+
(0, ui_1.table)(['ID', 'NAME', 'STATUS', 'CALL', 'ISSUE'], rows.map((r) => [r._id || r.id || '', r.feedbackName || '', r.status || status, r.issueCallId || '', String(r.callIssue || '').slice(0, 60)]));
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
(0, ui_1.handleError)(err);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async function feedbackCreateCommand(opts) {
|
|
32
|
+
try {
|
|
33
|
+
const res = await (0, dashboardApi_1.dashboardApi)().createFeedback({
|
|
34
|
+
engineerId: opts.engineer,
|
|
35
|
+
callIssue: opts.issue,
|
|
36
|
+
feedbackName: opts.name,
|
|
37
|
+
issueCallId: opts.call,
|
|
38
|
+
...(opts.version ? { versionId: opts.version } : {}),
|
|
39
|
+
});
|
|
40
|
+
out(opts.json, res, 'Feedback ticket created.');
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
(0, ui_1.handleError)(err);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async function feedbackCommentCommand(id, text, opts) {
|
|
47
|
+
try {
|
|
48
|
+
if (!text?.trim())
|
|
49
|
+
throw new Error('Comment text is required.');
|
|
50
|
+
out(opts.json, await (0, dashboardApi_1.dashboardApi)().commentFeedback(id, text), `Comment added to ${id}.`);
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
(0, ui_1.handleError)(err);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async function feedbackSubmitReviewCommand(id, opts) {
|
|
57
|
+
try {
|
|
58
|
+
const body = {
|
|
59
|
+
...(opts.calls ? { resolvedCallUrls: list(opts.calls) } : {}),
|
|
60
|
+
...(opts.versionUrl ? { resolvedVersionUrl: opts.versionUrl } : {}),
|
|
61
|
+
...(opts.comment ? { comment: opts.comment } : {}),
|
|
62
|
+
};
|
|
63
|
+
out(opts.json, await (0, dashboardApi_1.dashboardApi)().submitFeedbackReview(id, body), `${id} submitted for review.`);
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
(0, ui_1.handleError)(err);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async function feedbackReopenCommand(id, opts) {
|
|
70
|
+
try {
|
|
71
|
+
out(opts.json, await (0, dashboardApi_1.dashboardApi)().reopenFeedback(id, opts.comment), `${id} sent back to processing.`);
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
(0, ui_1.handleError)(err);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async function feedbackResolveCommand(id, opts) {
|
|
78
|
+
try {
|
|
79
|
+
out(opts.json, await (0, dashboardApi_1.dashboardApi)().resolveFeedback(id, opts.comment), `${id} resolved.`);
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
(0, ui_1.handleError)(err);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.knowledgeListCommand = knowledgeListCommand;
|
|
4
|
+
exports.knowledgeDeleteCommand = knowledgeDeleteCommand;
|
|
5
|
+
const dashboardApi_1 = require("../lib/dashboardApi");
|
|
6
|
+
const ui_1 = require("../lib/ui");
|
|
7
|
+
async function knowledgeListCommand(opts) {
|
|
8
|
+
try {
|
|
9
|
+
const res = await (0, dashboardApi_1.dashboardApi)().listKnowledge();
|
|
10
|
+
if (opts.json)
|
|
11
|
+
return void console.log(JSON.stringify(res, null, 2));
|
|
12
|
+
const rows = res?.data || res?.knowledge || (Array.isArray(res) ? res : []);
|
|
13
|
+
if (!rows.length)
|
|
14
|
+
return void (0, ui_1.info)('No knowledge base items.');
|
|
15
|
+
(0, ui_1.table)(['ID', 'NAME', 'TYPE', 'CREATED'], rows.map((r) => [r._id || r.id || '', r.name || r.title || '', r.type || '', r.createdAt || '']));
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
(0, ui_1.handleError)(err);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
async function knowledgeDeleteCommand(id, opts) {
|
|
22
|
+
try {
|
|
23
|
+
if (!(await (0, ui_1.confirm)(`Delete knowledge item ${id}? This cannot be undone.`, opts.yes)))
|
|
24
|
+
return;
|
|
25
|
+
const res = await (0, dashboardApi_1.dashboardApi)().deleteKnowledge(id);
|
|
26
|
+
if (opts.json)
|
|
27
|
+
return void console.log(JSON.stringify(res ?? { id }, null, 2));
|
|
28
|
+
(0, ui_1.success)(`Deleted ${id}.`);
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
(0, ui_1.handleError)(err);
|
|
32
|
+
}
|
|
33
|
+
}
|