const COPILOT_SEED = [
{ role: "user", text: "Why is profit decreasing in Q2?" },
{ role: "assistant", streaming: false, text: "Q2 net profit is down **4.2%** vs Q1, but the story is nuanced — this is a **margin compression story, not a revenue story**. Here's the decomposition:", charts: ["waterfall"], sources: ["gem_transactions", "state_revenue_daily", "vendor_master"], followups: ["Which department contributed most?", "Show forecast for Q3", "Compare with FY25 Q2"] },
];
function CopilotScreen() {
const [messages, setMessages] = useState(COPILOT_SEED);
const [input, setInput] = useState("");
const [streaming, setStreaming] = useState(false);
const scrollRef = useRef(null);
useEffect(() => {
scrollRef.current?.scrollTo({ top: scrollRef.current.scrollHeight, behavior: 'smooth' });
}, [messages, streaming]);
const send = (text) => {
const q = text || input;
if (!q.trim()) return;
setMessages(m => [...m, { role: "user", text: q }]);
setInput("");
setStreaming(true);
setTimeout(() => {
setMessages(m => [...m, {
role: "assistant",
text: "Analyzing across **3 datasets**, executing federated query on ClickHouse + PostgreSQL…",
charts: ["line"],
sources: ["gem_transactions", "vendor_master"],
followups: ["Break this down by department", "Forecast next 90 days", "Export as PDF report"]
}]);
setStreaming(false);
}, 900);
};
return (
{/* Left: history / examples */}
Recent
{[
"Q2 profit decrease analysis",
"State-wise procurement report",
"Vendor risk assessment",
"GeM Q1 vs Q2 comparison",
"Predict Q3 tender volumes",
].map((h, i) => (
{h}
))}
Data Scope
4 datasets selected
gem_transactions · vendor_master · state_revenue_daily · scheme_disbursement
{/* Main chat */}
VyaparBI Copilot
Multi-agent · RAG over 12 datasets · Multilingual (हिन्दी, English, 22 Indian langs)
XAI Enabled
{messages.map((m, i) => (
))}
{streaming && (
Planning query… routing to ClickHouse and Postgres
)}
{["Try:", "Explain revenue anomalies", "Compare states YoY", "Predict Q3 volumes", "Vendor risk scores"].map((c, i) => (
i === 0 ? {c} :
))}
Answers cite source rows. Numbers verified against live database.
Model: vyapar-agent-v3 · Tokens: 4.2K/1M
{/* Right: analytical trace */}
Cited Sources
{["gem_transactions (208 rows)", "vendor_master (18 rows)", "state_revenue_daily (92 rows)"].map((s, i) => (
{s}
))}
);
}
function TraceStep({ num, title, body, ok, last }) {
return (
);
}
function Message({ m, onFollowup }) {
if (m.role === "user") {
return (
);
}
return (
$1') }}/>
{m.charts?.includes("waterfall") && (
Q1 → Q2 Profit Bridge (₹ Cr)
Root cause: Vendor cost inflation (+₹38 Cr) driven by 3 large steel & electronics contracts renegotiated at higher rates. Revenue growth was healthy but couldn't fully offset input costs.
)}
{m.charts?.includes("line") && (
Revenue Trend — Last 6 Months
)}
{m.sources && (
Sources:
{m.sources.map((s, i) => (
{s}
))}
)}
{m.followups && (
{m.followups.map((f, i) => (
))}
)}
);
}
function Waterfall({ items }) {
const values = items.map(i => i.value);
const cumulative = [];
let running = 0;
items.forEach((it, i) => {
if (it.kind === "start") { cumulative.push({ base: 0, height: it.value, isFloat: false }); running = it.value; }
else if (it.kind === "end") { cumulative.push({ base: 0, height: it.value, isFloat: false }); }
else if (it.kind === "up") { cumulative.push({ base: running, height: it.value, isFloat: true }); running += it.value; }
else { cumulative.push({ base: running + it.value, height: -it.value, isFloat: true }); running += it.value; }
});
const max = Math.max(...cumulative.map(c => c.base + c.height));
const h = 160, pad = 32, w = 560;
const iw = w - 20; // account for padding
const barW = iw / items.length * 0.65;
const gap = iw / items.length * 0.35;
return (
);
}
// Floating drawer copilot
function CopilotDrawer({ onClose }) {
const [messages, setMessages] = useState([
{ role: "assistant", text: "Hi Aditi 👋 I've reviewed today's dashboards. **Delhi NCR is up 22.1%** — want me to dig into what's driving it?", followups: ["Yes, break it down", "Show anomalies today", "Summarize this week"] }
]);
const [input, setInput] = useState("");
const scrollRef = useRef(null);
useEffect(() => { scrollRef.current?.scrollTo({ top: 9999 }); }, [messages]);
const send = (t) => {
const q = t || input;
if (!q.trim()) return;
setMessages(m => [...m, { role: "user", text: q }]);
setInput("");
setTimeout(() => setMessages(m => [...m, { role: "assistant", text: "Running federated query… Delhi NCR growth is driven by **3 large IT infrastructure tenders** from CDAC and NIC totaling ₹42 Cr.", followups: ["Show the tenders", "Compare with Mumbai", "Export as PDF"] }]), 700);
};
return (
Copilot
Grounded on this page's data
{messages.map((m, i) => (
m.role === "user" ? (
) : (
$1') }}/>
{m.followups && (
{m.followups.map((f, j) => (
))}
)}
)
))}
setInput(e.target.value)} onKeyDown={e => e.key === 'Enter' && send()}
placeholder="Ask about this page…"
style={{ flex: 1, border: '1px solid var(--border)', background: 'var(--panel-2)', borderRadius: 8, padding: '8px 10px', fontSize: 12, color: 'var(--ink)', fontFamily: 'inherit', outline: 'none' }}
/>
);
}
Object.assign(window, { CopilotScreen, CopilotDrawer });