@velaro/cli 1.4.62 → 1.4.64
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/bin/velaro.js +2 -0
- package/lib/commands/experience-impact.js +33 -0
- package/lib/commands/migrate.js +26 -1
- package/package.json +1 -1
package/bin/velaro.js
CHANGED
|
@@ -40,6 +40,7 @@ import { appointmentsCommand } from '../lib/commands/appointments.js';
|
|
|
40
40
|
import { bookingCommand } from '../lib/commands/booking.js';
|
|
41
41
|
import { reportCommand } from '../lib/commands/report.js';
|
|
42
42
|
import { scheduleAdherenceCommand } from '../lib/commands/schedule-adherence.js';
|
|
43
|
+
import { experienceImpactCommand } from '../lib/commands/experience-impact.js';
|
|
43
44
|
import { conversationEfficiencyCommand } from '../lib/commands/conversation-efficiency.js';
|
|
44
45
|
import { dbCommand } from '../lib/commands/db.js';
|
|
45
46
|
import { focusCommand } from '../lib/commands/focus.js';
|
|
@@ -141,6 +142,7 @@ await yargs(hideBin(process.argv))
|
|
|
141
142
|
.command(reportCommand)
|
|
142
143
|
.command(conversationEfficiencyCommand)
|
|
143
144
|
.command(scheduleAdherenceCommand)
|
|
145
|
+
.command(experienceImpactCommand)
|
|
144
146
|
.command(dbCommand)
|
|
145
147
|
.command(focusCommand)
|
|
146
148
|
.command(automationDraftCommand)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { messagingGet } from '../api.js';
|
|
2
|
+
import { runCommand } from '../run.js';
|
|
3
|
+
|
|
4
|
+
// -- velaro experience-impact ---------------------------------------------------
|
|
5
|
+
// Backend: velaro-messaging GET /Reports/experience-impact?from=&to=&teamId=
|
|
6
|
+
// Site scope comes from the caller's auth, never an argument.
|
|
7
|
+
|
|
8
|
+
export const experienceImpactCommand = {
|
|
9
|
+
command: 'experience-impact',
|
|
10
|
+
describe: 'Experience index (0-100) tying schedule adherence, service level, missed chats and CSAT together',
|
|
11
|
+
builder: (y) => y
|
|
12
|
+
.option('from', { type: 'string', describe: 'yyyy-MM-dd (default: 7 days ago)' })
|
|
13
|
+
.option('to', { type: 'string', describe: 'yyyy-MM-dd (default: today)' })
|
|
14
|
+
.option('team-id', { type: 'number', describe: 'Narrow to one team' })
|
|
15
|
+
.option('json', { type: 'boolean', default: false, describe: 'Raw JSON output' }),
|
|
16
|
+
handler: runCommand(async (argv) => {
|
|
17
|
+
const qs = new URLSearchParams();
|
|
18
|
+
if (argv.from) qs.set('from', argv.from);
|
|
19
|
+
if (argv.to) qs.set('to', argv.to);
|
|
20
|
+
if (argv.teamId) qs.set('teamId', String(argv.teamId));
|
|
21
|
+
const q = qs.toString();
|
|
22
|
+
const d = await messagingGet(`/Reports/experience-impact${q ? `?${q}` : ''}`);
|
|
23
|
+
if (argv.json) { console.log(JSON.stringify(d, null, 2)); return; }
|
|
24
|
+
const s = d.summary ?? {};
|
|
25
|
+
console.log(`\nExperience Impact ${d.range?.from}..${d.range?.to}`);
|
|
26
|
+
console.log(` Experience index: ${s.experienceIndex} / 100`);
|
|
27
|
+
console.log(` Adherence ${s.adherencePct}% | Service level ${s.serviceLevelPct}% | Missed chats ${s.missedChats} | Avg wait ${s.avgWaitSec}s | CSAT ${s.csatAvg ?? '-'} (${s.csatResponses ?? 0})`);
|
|
28
|
+
for (const i of d.insights ?? []) console.log(` [${i.severity}] ${i.text}`);
|
|
29
|
+
for (const a of d.agents ?? []) {
|
|
30
|
+
console.log(` [${a.agentId}] ${a.name}: index ${a.experienceIndex} adherence ${a.adherencePct}% CSAT ${a.csatAvg ?? '-'} handled ${a.handled}`);
|
|
31
|
+
}
|
|
32
|
+
}),
|
|
33
|
+
};
|
package/lib/commands/migrate.js
CHANGED
|
@@ -8,7 +8,8 @@ export const migrateCommand = {
|
|
|
8
8
|
yargs
|
|
9
9
|
.command(migrateExportCommand)
|
|
10
10
|
.command(migrateLivefluenceCommand)
|
|
11
|
-
.
|
|
11
|
+
.command(migrateUrlRulesCommand)
|
|
12
|
+
.demandCommand(1, 'Specify a subcommand: export, livefluence, url-rules'),
|
|
12
13
|
handler: () => {},
|
|
13
14
|
};
|
|
14
15
|
|
|
@@ -132,3 +133,27 @@ const migrateLivefluenceCommand = {
|
|
|
132
133
|
console.log(`${'─'.repeat(60)}\n`);
|
|
133
134
|
}),
|
|
134
135
|
};
|
|
136
|
+
|
|
137
|
+
// -- seed v20 URL routing rules from a v10 rules JSON file ---------------------
|
|
138
|
+
|
|
139
|
+
const migrateUrlRulesCommand = {
|
|
140
|
+
command: 'url-rules',
|
|
141
|
+
describe: 'Seed v20 use-ai routing rules (path-only "url contains") from a v10 rules JSON file',
|
|
142
|
+
builder: (y) =>
|
|
143
|
+
y
|
|
144
|
+
.option('site', { type: 'number', alias: 's', demandOption: true, describe: 'V20 destination site ID' })
|
|
145
|
+
.option('ai-config-id', { type: 'number', alias: 'a', demandOption: true, describe: 'AI config on that site that receives the routed chats' })
|
|
146
|
+
.option('file', { type: 'string', alias: 'f', demandOption: true, describe: 'JSON array of {name, urls[]} in v10 priority order' })
|
|
147
|
+
.option('dry-run', { type: 'boolean', default: false }),
|
|
148
|
+
handler: runCommand(async (argv) => {
|
|
149
|
+
const { readFileSync } = await import('fs');
|
|
150
|
+
const src = JSON.parse(readFileSync(argv.file, 'utf8'));
|
|
151
|
+
const rules = src.map((r, i) => ({ name: r.name, priority: (i + 1) * 10, paths: r.urls || [] }));
|
|
152
|
+
const result = await post('/DatabaseTool/V10SeedUrlRules', {
|
|
153
|
+
siteId: argv.site, aiConfigId: argv['ai-config-id'], dryRun: argv['dry-run'], rules,
|
|
154
|
+
});
|
|
155
|
+
for (const i of result.createdItems || []) console.log(` + [${i.priority}] ${i.name} (${i.pathCount} paths)`);
|
|
156
|
+
for (const i of result.skippedItems || []) console.log(` - ${i.name}: ${i.reason}`);
|
|
157
|
+
console.log(`\n ${result.dryRun ? 'DRY RUN: ' : ''}created ${result.created}, skipped ${result.skipped}`);
|
|
158
|
+
}),
|
|
159
|
+
};
|
package/package.json
CHANGED