From f5043d37aa8e07ec9897f75f947253a189cb2187 Mon Sep 17 00:00:00 2001 From: a2a-cloud Date: Sat, 18 Jul 2026 07:38:52 +0000 Subject: [PATCH] a2a-source-edit: write frontend/src/App.jsx --- frontend/src/App.jsx | 338 +++++++++++++++++++++++++++++++------------ 1 file changed, 242 insertions(+), 96 deletions(-) diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index c73da08..2733bfd 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,41 +1,37 @@ import { useEffect, useMemo, useState } from "react"; -import { - callSkill, - loadAgentConfig, - loadSession, - sampleArgs, - signInUrl, -} from "./a2a.js"; +import { callSkill, loadAgentConfig, loadSession, signInUrl } from "./a2a.js"; + +const SUCCESS_FIXTURE = + "This Agreement renews automatically on 2026-12-31 unless either party gives at least 60 days written notice. Invoices are due 30 days after receipt."; +const FAILURE_FIXTURE = "Agreement renews sometime next spring."; +const MAX_UPLOAD_BYTES = 512000; +const ACCEPTED_TYPES = ["text/plain", "text/markdown", "application/octet-stream", ""]; export function App() { const [config, setConfig] = useState(null); const [session, setSession] = useState(null); - const [selectedSkillName, setSelectedSkillName] = useState(""); - const [argsText, setArgsText] = useState("{}"); + const [contractId, setContractId] = useState("studio-contract-v1"); + const [title, setTitle] = useState("Studio Renewal Agreement"); + const [text, setText] = useState(SUCCESS_FIXTURE); + const [selectedFile, setSelectedFile] = useState(null); const [result, setResult] = useState(null); + const [reloadResult, setReloadResult] = useState(null); + const [historyId, setHistoryId] = useState("studio-contract-v1"); const [error, setError] = useState(null); const [running, setRunning] = useState(false); + const [loadingSession, setLoadingSession] = useState(true); useEffect(() => { loadAgentConfig() .then((data) => { setConfig(data); - const firstSkill = data.skills?.[0]; - if (firstSkill) { - setSelectedSkillName(firstSkill.name); - setArgsText(JSON.stringify(sampleArgs(firstSkill), null, 2)); - } return loadSession(data).catch(() => null); }) .then((sessionData) => setSession(sessionData)) - .catch((err) => setError(err.message || String(err))); + .catch((err) => setError(err.message || String(err))) + .finally(() => setLoadingSession(false)); }, []); - const selectedSkill = useMemo( - () => config?.skills?.find((skill) => skill.name === selectedSkillName), - [config, selectedSkillName], - ); - const needsSignIn = Boolean( config?.auth?.invokeRequiresSession && session && !session.authenticated, ); @@ -44,23 +40,30 @@ 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 analyze(event) { event.preventDefault(); - if (!config || !selectedSkill) return; + if (!config || running) return; setRunning(true); setError(null); setResult(null); try { - const args = JSON.parse(argsText || "{}"); - const data = await callSkill(config, selectedSkill.name, args); + let data; + if (selectedFile) { + const document = await fileToBrowserDocument(selectedFile); + data = await callSkill(config, "analyze_contract_upload", { + contract_id: contractId.trim(), + title: title.trim() || selectedFile.name, + document, + }); + } else { + data = await callSkill(config, "analyze_contract", { + contract_id: contractId.trim(), + title: title.trim(), + text, + }); + } setResult(data); + if (data?.ok) setHistoryId(data.contract_id); } catch (err) { setError(err.message || String(err)); } finally { @@ -68,91 +71,234 @@ export function App() { } } + async function reloadTimeline(event) { + event.preventDefault(); + if (!config || running) return; + setRunning(true); + setError(null); + setReloadResult(null); + try { + const data = await callSkill(config, "get_contract_deadlines", { + contract_id: historyId.trim(), + }); + setReloadResult(data); + } catch (err) { + setError(err.message || String(err)); + } finally { + setRunning(false); + } + } + + function loadFailureFixture() { + setContractId("studio-contract-invalid"); + setTitle("Ambiguous Agreement"); + setText(FAILURE_FIXTURE); + setSelectedFile(null); + setResult(null); + } + + function loadSuccessFixture() { + setContractId("studio-contract-v1"); + setTitle("Studio Renewal Agreement"); + setText(SUCCESS_FIXTURE); + setSelectedFile(null); + setResult(null); + } + if (!config) { return (
-

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

+

{error || "Loading ContractClock Studio..."}

); } return ( -
- + + -
-
-
-

Skill runner

-

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

+
+
+
+
+

Workflow

+

Analyze contract

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