diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 812a863..0ecdb5e 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,41 +1,38 @@ import { useEffect, useMemo, useState } from "react"; -import { - callSkill, - loadAgentConfig, - loadSession, - sampleArgs, - signInUrl, -} from "./a2a.js"; +import { callSkill, loadAgentConfig, loadSession, signInUrl } from "./a2a.js"; + +const FIXTURE_UPDATES = `2026-07-01 | Acme Portal | green | Sprint 18 shipped client dashboard, 3 blockers cleared, utilization 81%, margin 34%. +2026-07-02 | Beacon CRM | yellow | API integration waiting on customer credentials; utilization 74%, margin 27%, risk: delayed approval. +2026-07-03 | Cedar Mobile | red | Escalated crash fix is overdue; utilization 92%, margin 18%, blocker: App Store review. +2026-07-04 | Delta RevOps | green | Retainer reporting automated; utilization 68%, margin 39%, next: expansion proposal.`; export function App() { const [config, setConfig] = useState(null); const [session, setSession] = useState(null); - const [selectedSkillName, setSelectedSkillName] = useState(""); - const [argsText, setArgsText] = useState("{}"); + const [updatesText, setUpdatesText] = useState(FIXTURE_UPDATES); + const [agencyName, setAgencyName] = useState("Proofline Software Agency"); + const [windowLabel, setWindowLabel] = useState("This week"); + const [minSeverity, setMinSeverity] = useState("all"); const [result, setResult] = useState(null); + const [history, setHistory] = useState([]); const [error, setError] = useState(null); const [running, setRunning] = useState(false); useEffect(() => { loadAgentConfig() - .then((data) => { + .then(async (data) => { setConfig(data); - const firstSkill = data.skills?.[0]; - if (firstSkill) { - setSelectedSkillName(firstSkill.name); - setArgsText(JSON.stringify(sampleArgs(firstSkill), null, 2)); + const sessionData = await loadSession(data).catch(() => null); + setSession(sessionData); + if (!data.auth?.invokeRequiresSession || sessionData?.authenticated) { + callSkill(data, "list_history", { limit: 6 }) + .then((payload) => setHistory(payload?.history || [])) + .catch(() => setHistory([])); } - return loadSession(data).catch(() => null); }) - .then((sessionData) => setSession(sessionData)) .catch((err) => setError(err.message || String(err))); }, []); - const selectedSkill = useMemo( - () => config?.skills?.find((skill) => skill.name === selectedSkillName), - [config, selectedSkillName], - ); - const needsSignIn = Boolean( config?.auth?.invokeRequiresSession && session && !session.authenticated, ); @@ -44,23 +41,20 @@ export function App() { [config, needsSignIn], ); - function selectSkill(skill) { - setSelectedSkillName(skill.name); - setArgsText(JSON.stringify(sampleArgs(skill), null, 2)); - setResult(null); - setError(null); - } - - async function runSkill(event) { + async function runDashboard(event) { event.preventDefault(); - if (!config || !selectedSkill) return; + if (!config) return; setRunning(true); setError(null); - setResult(null); try { - const args = JSON.parse(argsText || "{}"); - const data = await callSkill(config, selectedSkill.name, args); - setResult(data); + const payload = await callSkill(config, "build_dashboard", { + updates_text: updatesText, + agency_name: agencyName, + window_label: windowLabel, + min_severity: minSeverity, + }); + setResult(payload); + setHistory(payload?.history || history); } catch (err) { setError(err.message || String(err)); } finally { @@ -68,91 +62,203 @@ export function App() { } } - if (!config) { - return ( -
-

{error || "Loading A2A agent contract..."}

-
- ); + function downloadArtifact() { + if (!result?.artifact?.content) return; + const blob = new Blob([result.artifact.content], { + type: result.artifact.media_type || "text/csv", + }); + const url = URL.createObjectURL(blob); + const anchor = document.createElement("a"); + anchor.href = url; + anchor.download = result.artifact.name || "agency-ops-dashboard.csv"; + document.body.appendChild(anchor); + anchor.click(); + anchor.remove(); + URL.revokeObjectURL(url); } + if (!config) { + return
{error || "Loading dashboard..."}
; + } + + const rows = result?.dashboard_data || []; + const trends = result?.trends || {}; + const exceptions = result?.exceptions || []; + return ( -
- + -
-
-
-

Skill runner

-

{selectedSkill?.name || "No skills found"}

-
- - Docs - -
- - {selectedSkill ? ( -
-