mirror of
https://github.com/CopilotKit/CopilotKit.git
synced 2026-09-14 16:26:20 +08:00
01f5dbd1ee
Northstar AI CRM — a full-featured agentic sales CRM for an enterprise hardware seller, built with CopilotKit, the AG-UI protocol, and a TypeScript Strands agent (@strands-agents/sdk + @ag-ui/aws-strands). The first TypeScript Strands example under examples/. Highlights: - Agentic canvas: tool calls render on the workspace — quote approval opens a quote page; analyze_team and generate_weekly_report open dedicated report pages; frontend tools navigate the workspace. - Generative UI cards, human-in-the-loop follow-up approval, and a live STATE_SNAPSHOT that syncs a SQLite CRM store with the board, dashboard, and report pages. - Dashboard, pipeline (Kanban), products, team, and reports surfaces. Self-contained under examples/showcases/strands-crm with an agent/ + frontend/ split and a concurrently dev script; listed in examples/README.md.
90 lines
2.5 KiB
TypeScript
90 lines
2.5 KiB
TypeScript
import type { EnrichmentResult } from "../lib/crm";
|
||
|
||
export function EnrichmentCard({
|
||
result,
|
||
status,
|
||
}: {
|
||
result?: EnrichmentResult;
|
||
status: string;
|
||
}) {
|
||
if (status !== "complete") {
|
||
return (
|
||
<div className="rounded-xl border border-border bg-card p-3 text-sm text-muted-foreground">
|
||
Researching the account…
|
||
</div>
|
||
);
|
||
}
|
||
if (!result || typeof result.summary !== "string") {
|
||
return (
|
||
<div className="rounded-xl border border-border bg-card p-3 text-sm text-muted-foreground">
|
||
Research isn’t available right now.
|
||
</div>
|
||
);
|
||
}
|
||
const talkingPoints = result.talkingPoints ?? [];
|
||
const recentNews = result.recentNews ?? [];
|
||
const sources = result.sources ?? [];
|
||
return (
|
||
<div className="rounded-xl border border-border bg-card p-4 text-sm shadow-sm">
|
||
<div className="mb-1 text-xs font-semibold uppercase tracking-wide text-primary">
|
||
Account research
|
||
</div>
|
||
<p className="text-foreground/90">{result.summary}</p>
|
||
{talkingPoints.length > 0 && (
|
||
<>
|
||
<div className="mt-2 text-xs font-medium text-muted-foreground">
|
||
Talking points
|
||
</div>
|
||
<ul className="list-disc pl-5 text-muted-foreground">
|
||
{talkingPoints.map((t, i) => (
|
||
<li key={i}>{t}</li>
|
||
))}
|
||
</ul>
|
||
</>
|
||
)}
|
||
{recentNews.length > 0 && (
|
||
<>
|
||
<div className="mt-2 text-xs font-medium text-muted-foreground">
|
||
Recent news
|
||
</div>
|
||
<ul className="space-y-0.5">
|
||
{recentNews.map((n, i) => (
|
||
<li key={i}>
|
||
<a
|
||
className="text-primary hover:underline"
|
||
href={n.url}
|
||
target="_blank"
|
||
rel="noreferrer"
|
||
>
|
||
{n.title}
|
||
</a>
|
||
</li>
|
||
))}
|
||
</ul>
|
||
</>
|
||
)}
|
||
{sources.length > 0 && (
|
||
<>
|
||
<div className="mt-2 text-xs font-medium text-muted-foreground">
|
||
Sources
|
||
</div>
|
||
<ul className="space-y-0.5">
|
||
{sources.map((s, i) => (
|
||
<li key={i}>
|
||
<a
|
||
className="text-primary hover:underline"
|
||
href={s.url}
|
||
target="_blank"
|
||
rel="noreferrer"
|
||
>
|
||
{s.title}
|
||
</a>
|
||
</li>
|
||
))}
|
||
</ul>
|
||
</>
|
||
)}
|
||
</div>
|
||
);
|
||
}
|