From 401bd6796d3a1345f307b4b583c95723567c5d1a Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 25 Jul 2026 18:50:21 +0000 Subject: [PATCH] =?UTF-8?q?chore(admin):=20remove=20dead=20sections=20?= =?UTF-8?q?=E2=80=94=20B20,=20Comm=20Intel,=20Outreach,=20Pending=20Replie?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dropped 4 sections that are no longer part of the active workflow: B20Section, CommIntelSection, OutreachSection, PendingRepliesSection. Also cleaned up: - Dead types: PendingReply, CommEntry, BLANK_FORM, LABEL_COLOR, B20TokenResult/IndexReport/DetectResult/DetectReport/Report, OutreachAgent - pendingRepliesCount state + /api/admin/pending-replies fetch in root - Nav badge for pending-replies - Removed "intel" nav group; moved Subagent Runs into "system" group 4504 → 3571 lines (-933 lines) --- src/app/luca-admin/page.tsx | 941 +----------------------------------- 1 file changed, 4 insertions(+), 937 deletions(-) diff --git a/src/app/luca-admin/page.tsx b/src/app/luca-admin/page.tsx index 162ab8d..773433a 100644 --- a/src/app/luca-admin/page.tsx +++ b/src/app/luca-admin/page.tsx @@ -16,7 +16,7 @@ import type { AddressType } from "@/lib/address-classifier"; // ── Types ───────────────────────────────────────────────────────────────────── -type Section = "overview" | "registry" | "attribution" | "economics" | "growth" | "reports" | "comm" | "outreach" | "settings" | "subagent-runs" | "pending-replies" | "truth-engine" | "pending-updates" | "attribution-health" | "address-classification" | "erc8004" | "revenue-audit" | "accuracy-report" | "confidence-labels" | "b20"; +type Section = "overview" | "registry" | "attribution" | "economics" | "growth" | "reports" | "settings" | "subagent-runs" | "truth-engine" | "pending-updates" | "attribution-health" | "address-classification" | "erc8004" | "revenue-audit" | "accuracy-report" | "confidence-labels"; type EcoPeriod = "7d" | "30d"; type HealthData = { @@ -85,19 +85,6 @@ type SubagentRun = { triggered_by: string | null; }; -type PendingReply = { - id: string; - target_user: string | null; - target_post_url: string | null; - draft_reply: string; - risk_level: "low" | "medium" | "high"; - recommendation: string | null; - status: "pending" | "approved" | "rejected" | "posted"; - reviewer_notes: string | null; - reviewed_at: string | null; - posted_at: string | null; - created_at: string; -}; // ── Static data ─────────────────────────────────────────────────────────────── @@ -168,11 +155,7 @@ const NAV: { section: Section; label: string; group: string }[] = [ { section: "confidence-labels", label: "Confidence Labels", group: "financial" }, { section: "growth", label: "Growth OS", group: "growth" }, { section: "reports", label: "Reports", group: "growth" }, - { section: "b20", label: "B20 Intelligence", group: "growth" }, - { section: "comm", label: "Comm Intel", group: "intel" }, - { section: "outreach", label: "Outreach CRM", group: "intel" }, - { section: "subagent-runs", label: "Subagent Runs", group: "intel" }, - { section: "pending-replies", label: "Pending Replies", group: "intel" }, + { section: "subagent-runs", label: "Subagent Runs", group: "system" }, { section: "settings", label: "Settings", group: "system" }, ]; @@ -182,7 +165,6 @@ const GROUP_LABELS: Record = { "data-integrity":"Data Integrity", financial: "Financial", growth: "Growth OS", - intel: "Intelligence", system: "System", }; @@ -1897,242 +1879,6 @@ const PLATFORM_COLORS: Record = { farcaster: "#8B7CF6", other: "var(--muted)", }; - -const LABEL_COLOR: Record = { - "payment request observed": "#F4B942", - "settlement not confirmed": "#F46060", - "needs wallet confirmation": "var(--blue)", - "reconciliation candidate": "#8B7CF6", -}; - -type CommEntry = { - id?: string; - agent_name: string; - platform: string; - handle: string; - url?: string | null; - confidence: string; - labels: string[]; - notes?: string | null; -}; - -const BLANK_FORM = { agent_name: "", platform: "wiretap", handle: "", url: "", confidence: "unverified", labels: [] as string[], notes: "" }; - -function CommIntelSection({ secret }: { secret: string }) { - const [entries, setEntries] = useState([]); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(""); - const [search, setSearch] = useState(""); - const [addOpen, setAddOpen] = useState(false); - const [form, setForm] = useState({ ...BLANK_FORM }); - const [saving, setSaving] = useState(false); - const [saveError, setSaveError] = useState(""); - const [deleting, setDeleting] = useState(null); - - const headers = { Authorization: `Bearer ${secret}`, "Content-Type": "application/json" }; - - useEffect(() => { - fetch("/api/registry/comm-identities", { headers: { Authorization: `Bearer ${secret}` } }) - .then((r) => r.json()) - .then((d: { ok: boolean; data?: CommEntry[]; error?: string }) => { - if (d.ok) setEntries(d.data ?? []); - else setError(d.error ?? "Failed to load"); - }) - .catch(() => setError("Network error")) - .finally(() => setLoading(false)); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [secret]); - - function toggleLabel(label: string) { - setForm((f) => ({ - ...f, - labels: f.labels.includes(label) ? f.labels.filter((l) => l !== label) : [...f.labels, label], - })); - } - - async function handleAdd(e: React.FormEvent) { - e.preventDefault(); - setSaving(true); - setSaveError(""); - const res = await fetch("/api/registry/comm-identities", { - method: "POST", - headers, - body: JSON.stringify({ ...form, url: form.url || null, notes: form.notes || null }), - }); - const data = await res.json() as { ok: boolean; id?: string; error?: string }; - if (data.ok && data.id) { - setEntries((prev) => [{ ...form, id: data.id, url: form.url || null, notes: form.notes || null }, ...prev]); - setForm({ ...BLANK_FORM }); - setAddOpen(false); - } else { - setSaveError(data.error ?? "Failed to save"); - } - setSaving(false); - } - - async function handleDelete(id: string) { - setDeleting(id); - const res = await fetch(`/api/registry/comm-identities/${id}`, { method: "DELETE", headers }); - const data = await res.json() as { ok: boolean }; - if (data.ok) setEntries((prev) => prev.filter((e) => e.id !== id)); - setDeleting(null); - } - - const filtered = entries.filter( - (e) => !search || e.agent_name.toLowerCase().includes(search.toLowerCase()) || e.handle.toLowerCase().includes(search.toLowerCase()), - ); - - return ( -
-
-

Intelligence

-

Comm Intel

-

Agent communication identities — admin only. Not shown publicly.

-
- -
-
- Comm identities are not wallet verification -

Confirmed handle ≠ verified wallet. Payment request observed ≠ confirmed revenue.

-
- -
- - {addOpen && ( -
-

New Identity

-
-
-
- - setForm((f) => ({ ...f, agent_name: e.target.value }))} - placeholder="e.g. Bankr" className={styles.formInput} /> -
-
- - -
-
- - setForm((f) => ({ ...f, handle: e.target.value }))} - placeholder="@handle or ID" className={styles.formInput} /> -
-
- - setForm((f) => ({ ...f, url: e.target.value }))} - placeholder="https://…" className={styles.formInput} /> -
-
- - -
-
- - setForm((f) => ({ ...f, notes: e.target.value }))} - placeholder="Context…" className={styles.formInput} /> -
-
-
-

Labels

-
- {COMM_LABELS.map((label) => { - const active = form.labels.includes(label); - const c = LABEL_COLOR[label]; - return ( - - ); - })} -
-
- {saveError &&

{saveError}

} - -
-
- )} - - setSearch(e.target.value)} placeholder="Search agents or handles…" - className={styles.formInput} style={{ marginBottom: 12 }} /> - - {loading &&
Loading comm identities…
} - {!loading && error &&
{error}
} - - {!loading && !error && filtered.length === 0 && ( -
-

No comm identities yet

-

Add the first one above.

-
- )} - - {!loading && !error && filtered.length > 0 && ( -
- {filtered.map((entry) => { - const pc = PLATFORM_COLORS[entry.platform] ?? "var(--muted)"; - const cc = entry.confidence === "confirmed" ? "var(--accent)" : "#F4B942"; - return ( -
-
-
-
- {entry.agent_name} - - {entry.platform} - - {entry.handle} - - {entry.confidence} - -
- {entry.labels.length > 0 && ( -
- {entry.labels.map((l) => { - const lc = LABEL_COLOR[l] ?? "var(--muted)"; - return ( - - {l} - - ); - })} -
- )} - {entry.notes &&

{entry.notes}

} - {entry.url && {entry.url}} -
- {entry.id && ( - - )} -
-
- ); - })} -
- )} -
- ); -} - function ReportsSection({ secret }: { secret: string }) { const [status, setStatus] = useState<"idle" | "sending" | "done" | "error">("idle"); const [preview, setPreview] = useState(""); @@ -3480,142 +3226,6 @@ function ConfidenceLabelsSection({ secret }: { secret: string }) { ); } -// ── B20 Intelligence section ─────────────────────────────────────────────────── - -type B20TokenResult = { address: string; name: string | null; symbol: string | null; linked_agent: string | null; link_confidence: string; manifest_status: string; activity_events_inserted: number; status: "indexed" | "skipped" | "error"; error?: string }; -type B20IndexReport = { ok: boolean; dry_run: boolean; summary: { tokens_discovered: number; tokens_indexed: number; errors: number; attributed: number; candidates: number; awaiting_manifest: number; data_integrity_note: string }; tokens: B20TokenResult[]; generated_at: string; error?: string }; -type B20DetectResult = { address: string; agent_name: string; passes_prefix: boolean; confirmed_on_chain: boolean; name: string | null; symbol: string | null; recommendation: string }; -type B20DetectReport = { ok: boolean; total_with_token_address: number; b20_prefix_matches: number; confirmed_b20: number; results: B20DetectResult[]; non_b20_addresses: { agent_name: string; address: string }[]; note: string; generated_at: string; error?: string }; - -type B20Report = B20IndexReport | B20DetectReport; - -function B20Section({ secret }: { secret: string }) { - const [mode, setMode] = useState<"detect_from_registry" | "from_registry" | "single" | "activity_only">("detect_from_registry"); - const [chain, setChain] = useState<"base" | "base-sepolia">("base"); - const [dryRun, setDryRun] = useState(true); - const [singleAddr, setSingleAddr] = useState(""); - const [loading, setLoading] = useState(false); - const [error, setError] = useState(""); - const [report, setReport] = useState(null); - - async function run() { - setLoading(true); setError(""); setReport(null); - const body: Record = { mode, chain, dryRun }; - if (mode === "single") body.tokenAddress = singleAddr; - try { - const res = await fetch("/api/admin/index-b20", { - method: "POST", headers: { "Content-Type": "application/json", "x-internal-secret": secret }, - body: JSON.stringify(body), - }); - const json = await res.json() as B20Report; - if (!json.ok) { setError((json as { error?: string }).error ?? "Failed"); return; } - setReport(json); - } catch (e) { setError((e as Error).message); } - finally { setLoading(false); } - } - - const isDetect = mode === "detect_from_registry"; - const isIndex = !isDetect && report && "summary" in report; - - return ( -
-
-

Growth OS

-

B20 Intelligence

-

Detect and index B20 token contracts linked to registry agents.

-
-
-
- {(["detect_from_registry", "from_registry", "single", "activity_only"] as const).map((m) => ( - - ))} -
-
- {(["base", "base-sepolia"] as const).map((c) => ( - - ))} -
- {mode === "single" && ( -
- setSingleAddr(e.target.value)} placeholder="Token address (0x…)" - style={{ padding: "6px 10px", borderRadius: 6, border: "1px solid var(--line)", background: "var(--bg)", color: "var(--ink)", fontSize: 12, width: 340, fontFamily: "var(--font-mono)" }} /> -
- )} - {!isDetect && ( -
- - Dry Run -
- )} - -
- {error &&
{error}
} - {report && isDetect && "results" in report && ( - <> -
- {[ - { label: "With Token Address", value: (report as B20DetectReport).total_with_token_address }, - { label: "B20 Prefix Matches", value: (report as B20DetectReport).b20_prefix_matches }, - { label: "Confirmed B20", value: (report as B20DetectReport).confirmed_b20 }, - ].map((kpi) => ( -
-
{kpi.label}
-
{kpi.value}
-
- ))} -
-
- - - - {(report as B20DetectReport).results.map((r, i) => ( - - - - - - - - ))} - -
AgentToken AddressSymbolConfirmedRecommendation
{r.agent_name}{r.address.slice(0, 10)}…{r.symbol ?? "—"}{r.confirmed_on_chain ? "Yes" : "No"}{r.recommendation}
-
- - )} - {report && isIndex && "summary" in report && ( - <> - {(report as B20IndexReport).dry_run &&
[DRY RUN]
} -
- ⚠ {(report as B20IndexReport).summary.data_integrity_note} -
-
- {[ - { label: "Discovered", value: (report as B20IndexReport).summary.tokens_discovered }, - { label: "Indexed", value: (report as B20IndexReport).summary.tokens_indexed }, - { label: "Attributed", value: (report as B20IndexReport).summary.attributed }, - { label: "Candidates", value: (report as B20IndexReport).summary.candidates }, - { label: "Errors", value: (report as B20IndexReport).summary.errors }, - ].map((kpi) => ( -
-
{kpi.label}
-
{kpi.value}
-
- ))} -
- - )} -
- ); -} - function SettingsSection({ onSignOut, health }: { onSignOut: () => void; health: HealthData | null }) { const envStatus = [ { key: "ZETTA_INTERNAL_SECRET", ok: true }, @@ -3781,538 +3391,6 @@ const STATUS_BG: Record = { posted: "#4AE8A0", }; -function PendingRepliesSection({ secret }: { secret: string }) { - const [replies, setReplies] = useState([]); - const [loading, setLoading] = useState(true); - const [filter, setFilter] = useState<"pending" | "approved" | "all">("pending"); - const [notes, setNotes] = useState>({}); - const [editedDrafts, setEdited] = useState>({}); - const [acting, setActing] = useState(null); - const [copied, setCopied] = useState(null); - - const load = useCallback(() => { - setLoading(true); - fetch(`/api/admin/pending-replies?status=${filter}`, { headers: { Authorization: `Bearer ${secret}` } }) - .then((r) => r.json()) - .then((d: { ok: boolean; replies?: PendingReply[] }) => { setReplies(d.replies ?? []); setLoading(false); }) - .catch(() => setLoading(false)); - }, [secret, filter]); - - useEffect(() => { load(); }, [load]); - - async function act(id: string, action: "approve" | "reject" | "post") { - setActing(id); - await fetch(`/api/admin/pending-replies/${id}`, { - method: "PATCH", - headers: { "Content-Type": "application/json", Authorization: `Bearer ${secret}` }, - body: JSON.stringify({ - action, - reviewer_notes: notes[id] ?? null, - edited_reply: editedDrafts[id] ?? null, - }), - }); - setActing(null); - load(); - } - - function copyReply(id: string, draft: string) { - const text = editedDrafts[id] ?? draft; - navigator.clipboard.writeText(text).then(() => { - setCopied(id); - setTimeout(() => setCopied((c) => (c === id ? null : c)), 2000); - }).catch(() => {}); - } - - const pendingCount = replies.filter((r) => r.status === "pending").length; - - return ( -
-
-

Luca Intelligence

-

- X Reply Queue - {pendingCount > 0 && ( - - {pendingCount} - - )} -

-

Luca drafts replies here. Edit, copy to X manually, then mark as posted. Nothing auto-posts.

-
- -
- {(["pending", "approved", "all"] as const).map((f) => ( - - ))} -
- - {loading ? ( -
Loading replies…
- ) : replies.length === 0 ? ( -
- {filter === "pending" - ? "No pending replies. Luca will queue drafts here before anything posts publicly." - : filter === "approved" - ? "No approved replies awaiting posting." - : "No replies logged yet."} -
- ) : ( -
- {replies.map((reply) => { - const draftText = editedDrafts[reply.id] ?? reply.draft_reply; - const isEdited = editedDrafts[reply.id] !== undefined && editedDrafts[reply.id] !== reply.draft_reply; - const isPending = reply.status === "pending"; - const isApproved = reply.status === "approved"; - - return ( -
- {/* Header */} -
- {reply.target_user && ( - - @{reply.target_user.replace("@", "")} - - )} - {reply.target_post_url && ( - - View post ↗ - - )} - - {reply.risk_level} risk - - {reply.status !== "pending" && ( - - {reply.status} - - )} -
- - {/* Editable draft */} -
-