+ {turn.blocks.map((b, i) => {
+ if (b.kind === "text") {
+ return b.text ? (
+
+ {b.text}
+
+ ) : null;
+ }
+ if (b.kind === "tool") {
+ return
;
+ }
+ return (
+
+ );
+ })}
+
+ );
+}
+
+function ToolStepRow({ step, onOpen }: { step: ToolStep; onOpen: (url: string) => void }) {
+ return (
+
+
+ {step.done ? (
+
+ ) : (
+
+ )}
+
+ {toolLabel(step.tool)}
+ {step.result && — {step.result}}
+
+ {step.done && step.openURL && (step.entityType === "campaign" || step.entityType === "automation") && (
+
+ )}
+
+ );
+}
+
+function ApprovalCard({
+ pending,
+ onDecide,
+}: {
+ pending: Pending;
+ onDecide: (d: "approve" | "deny" | "always_allow") => void;
+}) {
+ const isSend = pending.risk === "send";
+ return (
+
+
+
+ {isSend ? "Send this?" : "Approve this action?"}
+
+
+ {toolLabel(pending.tool)}
+ {pending.argsSummary && (
+ — {pending.argsSummary}
+ )}
+
+
+
+
+ {!isSend && (
+
+ )}
+
+
+ );
+}
+
+function EmptyState() {
+ return (
+
+
+
+
+
How can I help?
+
+ Ask me to find contacts, check a campaign, draft a reply, or set up a
+ draft campaign. I ask before changing anything.
+
+
+ );
+}
+
+// toolLabel renders a friendly label for a tool name.
+function toolLabel(tool: string): string {
+ const map: Record