removed the voice agent
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
/* How far do the agent's numbers drift from the CRM dashboard?
|
||||
|
||||
The dashboard resolves a lead's stage by looking up `leadstages` and taking
|
||||
the furthest stage across pipelines; the CRM's own code comments say
|
||||
`Lead.current_stage` is "stale and never written". The agent's lead tools
|
||||
read that stale field, so this measures the resulting gap.
|
||||
*/
|
||||
import jwt from 'jsonwebtoken';
|
||||
import dotenv from 'dotenv';
|
||||
import { connectMongo } from '../src/data/mongo.js';
|
||||
import { Lead } from '../src/data/models/index.js';
|
||||
|
||||
dotenv.config();
|
||||
const CRM = process.env.CRM_PUBLIC_URL || 'https://crm.wele.in';
|
||||
const token = jwt.sign({ id: '6a00cefe524bebd27037a968' }, process.env.CRM_JWT_SECRET, { expiresIn: '15m' });
|
||||
|
||||
await connectMongo();
|
||||
|
||||
// ── what the AGENT currently reports (stale field) ──────────────────────────
|
||||
const agentStages = await Lead.aggregate([
|
||||
{ $group: { _id: '$current_stage', n: { $sum: 1 } } },
|
||||
{ $sort: { n: -1 } },
|
||||
]);
|
||||
const agent = Object.fromEntries(agentStages.map((r) => [r._id || 'unset', r.n]));
|
||||
const agentTotal = agentStages.reduce((s, r) => s + r.n, 0);
|
||||
|
||||
// ── what the DASHBOARD reports (leadstages lookup, workshop excluded) ───────
|
||||
// parseRange takes from/to as YYYY-MM-DD in IST and DEFAULTS TO TODAY — a
|
||||
// missing range silently returns one day, which is the first trap here.
|
||||
const today = new Date(Date.now() + 5.5 * 3600e3).toISOString().slice(0, 10);
|
||||
const res = await fetch(`${CRM}/api/dashboard/leads?from=2020-01-01&to=${today}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
signal: AbortSignal.timeout(60000),
|
||||
});
|
||||
if (!res.ok) {
|
||||
console.log(`dashboard call failed: ${res.status} ${(await res.text()).slice(0, 200)}`);
|
||||
process.exit(1);
|
||||
}
|
||||
const dash = await res.json();
|
||||
|
||||
console.log('=== DASHBOARD response shape ===');
|
||||
console.log(' ', Object.keys(dash).join(', '));
|
||||
const d = dash.data ?? dash;
|
||||
console.log(' data keys:', Object.keys(d).join(', '));
|
||||
|
||||
console.log('\n=== TOTAL LEADS ===');
|
||||
console.log(` agent (Lead collection) ${agentTotal}`);
|
||||
console.log(` dashboard totalLeads ${d.totalLeads ?? d.total ?? '(not found)'}`);
|
||||
|
||||
console.log('\n=== STAGE DISTRIBUTION ===');
|
||||
console.log(` ${'stage'.padEnd(24)} ${'agent'.padStart(7)} ${'dashboard'.padStart(10)} gap`);
|
||||
console.log(` dashboard cards.total_leads ${d.cards?.total_leads}`);
|
||||
console.log(` dashboard range ${d.range?.from} → ${d.range?.to}`);
|
||||
const funnel = d.funnel || d.stages || {};
|
||||
const dashStages = Array.isArray(funnel)
|
||||
? Object.fromEntries(funnel.map((f) => [f._id || f.stage || f.name, f.count ?? f.total]))
|
||||
: funnel;
|
||||
|
||||
const keys = [...new Set([...Object.keys(agent), ...Object.keys(dashStages)])];
|
||||
for (const k of keys) {
|
||||
const a = agent[k] ?? 0;
|
||||
const b = dashStages[k] ?? 0;
|
||||
const gap = b - a;
|
||||
console.log(` ${String(k).padEnd(24)} ${String(a).padStart(7)} ${String(b).padStart(10)} ${gap === 0 ? '—' : (gap > 0 ? '+' : '') + gap}`);
|
||||
}
|
||||
|
||||
console.log('\nRaw dashboard payload (first 900 chars) for field mapping:');
|
||||
console.log(JSON.stringify(d).slice(0, 900));
|
||||
process.exit(0);
|
||||
@@ -0,0 +1,50 @@
|
||||
/* Shape of every CRM dashboard endpoint, so the agent tools can be written
|
||||
against what they actually return rather than against a guess. */
|
||||
import jwt from 'jsonwebtoken';
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config();
|
||||
|
||||
const CRM = process.env.CRM_PUBLIC_URL || 'https://crm.wele.in';
|
||||
const token = jwt.sign({ id: '6a00cefe524bebd27037a968' }, process.env.CRM_JWT_SECRET, { expiresIn: '15m' });
|
||||
const today = new Date(Date.now() + 5.5 * 3600e3).toISOString().slice(0, 10);
|
||||
const from = '2026-08-01';
|
||||
|
||||
const ENDPOINTS = [
|
||||
'dashboard/leads',
|
||||
'dashboard/marketing',
|
||||
'dashboard/retargeting',
|
||||
'dashboard/budget',
|
||||
'dashboard/courses',
|
||||
'dashboard/analytics',
|
||||
'dashboard/meta-analytics',
|
||||
];
|
||||
|
||||
const shape = (v, depth = 0) => {
|
||||
if (Array.isArray(v)) return v.length ? `[${v.length} × ${shape(v[0], depth + 1)}]` : '[]';
|
||||
if (v && typeof v === 'object') {
|
||||
const keys = Object.keys(v);
|
||||
if (depth >= 1) return `{${keys.slice(0, 8).join(', ')}${keys.length > 8 ? ', …' : ''}}`;
|
||||
return `{\n${keys.map((k) => ` ${k}: ${shape(v[k], depth + 1)}`).join('\n')}\n }`;
|
||||
}
|
||||
return typeof v === 'string' ? `"${String(v).slice(0, 24)}"` : String(v);
|
||||
};
|
||||
|
||||
for (const ep of ENDPOINTS) {
|
||||
const url = `${CRM}/api/${ep}?from=${from}&to=${today}`;
|
||||
try {
|
||||
const res = await fetch(url, { headers: { Authorization: `Bearer ${token}` }, signal: AbortSignal.timeout(90000) });
|
||||
const body = await res.text();
|
||||
if (!res.ok) { console.log(`\n${ep} HTTP ${res.status} ${body.slice(0, 120)}`); continue; }
|
||||
const j = JSON.parse(body);
|
||||
const d = j.data ?? j;
|
||||
console.log(`\n${'─'.repeat(70)}\n${ep} (${(body.length / 1024).toFixed(1)} kB)`);
|
||||
console.log(` ${shape(d)}`);
|
||||
// Headline numbers are what the assistant will most often be asked for.
|
||||
if (d.cards) console.log(` cards → ${JSON.stringify(d.cards)}`);
|
||||
if (d.totals) console.log(` totals → ${JSON.stringify(d.totals).slice(0, 300)}`);
|
||||
if (d.summary) console.log(` summary → ${JSON.stringify(d.summary).slice(0, 300)}`);
|
||||
} catch (e) {
|
||||
console.log(`\n${ep} ERROR ${e.message.slice(0, 90)}`);
|
||||
}
|
||||
}
|
||||
process.exit(0);
|
||||
@@ -0,0 +1,29 @@
|
||||
/* Does crm_dashboard return the dashboard's own numbers, across every section? */
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config();
|
||||
process.env.CRM_API_BASE = process.env.CRM_PUBLIC_URL || 'https://crm.wele.in';
|
||||
|
||||
const { crmDashboard } = await import('../src/tools/crm/dashboard.tools.js');
|
||||
const cfg = { configurable: { user: { id: '6a00cefe524bebd27037a968', name: 'Test', role: 'admin' }, runtime: { toolCallCount: 0 } } };
|
||||
|
||||
const CASES = [
|
||||
['leads', 'all_time'], ['leads', 'this_month'], ['marketing', 'this_month'],
|
||||
['budget', 'this_month'], ['courses', 'this_month'], ['analytics', 'last_7_days'],
|
||||
['retargeting', 'this_month'], ['meta_analytics', 'this_month'],
|
||||
];
|
||||
|
||||
let pass = 0;
|
||||
for (const [section, range] of CASES) {
|
||||
try {
|
||||
const raw = await crmDashboard.invoke({ section, range }, cfg);
|
||||
const r = typeof raw === 'string' ? JSON.parse(raw) : raw;
|
||||
if (r.ok === false) { console.log(`FAIL ${section}/${range}: ${r.error}`); continue; }
|
||||
const d = r.data ?? r;
|
||||
const head = d.cards ? JSON.stringify(d.cards) : (d.overview ? JSON.stringify(d.overview).slice(0,150) : Object.keys(d).slice(0,6).join(','));
|
||||
console.log(`PASS ${section.padEnd(15)} ${range.padEnd(12)} ${d.period?.from}→${d.period?.to}`);
|
||||
console.log(` ${head.slice(0, 190)}`);
|
||||
pass++;
|
||||
} catch (e) { console.log(`FAIL ${section}/${range}: ${e.message.slice(0,120)}`); }
|
||||
}
|
||||
console.log(`\n${pass}/${CASES.length} sections working`);
|
||||
process.exit(0);
|
||||
Reference in New Issue
Block a user