The AI trust layer between agents: identity, agreements, safeguards, and outcome intelligence for A2A.
Commit 90ba0b08
90ba0b085978Merged
aryaamin <[email protected]> · 2 months ago · 15 files · +2 added · ~13 modified
Description
feat: add interaction progress lifecycle
Details
- Commit
- 90ba0b085978
- Parent
- 03be656e7804
apps/dashboard/src/main.tsxmodifiedView file
@@ -932,7 +932,9 @@
932932
933933
function History({ data }: { data: DashboardData }) {934934
const [query, setQuery] = useState('');935-
const [status, setStatus] = useState<'all' | 'pending' | 'active' | 'completed'>('all');935+
const [status, setStatus] = useState<'all' | 'pending' | 'active' | 'finalizing' | 'completed'>(936+
'all',937+
);936938
const journeys = useMemo(() => interactionJourneys(data), [data]);937939
const filtered = useMemo(() => {938940
const needle = query.trim().toLowerCase();@@ -966,7 +968,7 @@
966968
aria-label="Search interaction history"967969
/>968970
<div className="filterRow" aria-label="Interaction status filters">969-
{(['all', 'pending', 'active', 'completed'] as const).map((value) => (971+
{(['all', 'pending', 'active', 'finalizing', 'completed'] as const).map((value) => (970972
<button971973
key={value}972974
className={status === value ? 'filterChip active' : 'filterChip'}@@ -1129,7 +1131,9 @@
11291131
status: String(11301132
conclusion || receipt11311133
? 'completed'1132-
: (session?.status ?? interaction.status ?? 'pending'),1134+
: reports.length > 01135+
? 'finalizing'1136+
: (session?.status ?? interaction.status ?? 'pending'),11331137
),11341138
participants,11351139
updatedAt:@@ -1167,6 +1171,14 @@
11671171
function InteractionJourney({ journey }: { journey: InteractionJourneyModel }) {11681172
const timeline = interactionTimeline(journey);11691173
const conclusion = journey.conclusion;1174+
const checkpoints = journey.events.filter(1175+
(event) => (event.type ?? event.eventType) === 'progress_checkpoint' && event.checkpoint,1176+
);1177+
const latestCheckpoint = checkpoints.at(-1)?.checkpoint;1178+
const progress = Number(latestCheckpoint?.progress ?? 0);1179+
const submittedFeedback = new Set(1180+
journey.feedback.map((item) => item.reviewerAgentId).filter(Boolean),1181+
).size;11701182
return (11711183
<article className="journeyDetail">11721184
<header className="journeyHero">@@ -1180,13 +1192,38 @@
11801192
11811193
<div className="journeySummaryGrid">11821194
<section>1195+
<span>Progress</span>1196+
<strong>1197+
{latestCheckpoint1198+
? `${Math.round(progress * 100)}% · ${humanize(latestCheckpoint.state)}`1199+
: journey.reports.length1200+
? 'Finalizing'1201+
: 'Awaiting checkpoint'}1202+
</strong>1203+
<small>1204+
{latestCheckpoint1205+
? `${humanize(latestCheckpoint.topicStatus)} · ${Math.round(Number(latestCheckpoint.confidence ?? 0) * 100)}% confidence`1206+
: 'Agents report compact progress every few exchanges'}1207+
</small>1208+
</section>1209+
<section>11831210
<span>Outcome</span>1184-
<strong>{humanize(conclusion?.outcome ?? 'In progress')}</strong>1185-
<small>{humanize(conclusion?.consensus ?? 'Awaiting bilateral conclusion')}</small>1211+
<strong>1212+
{conclusion1213+
? humanize(conclusion.outcome)1214+
: `${journey.reports.length}/2 terminal reports`}1215+
</strong>1216+
<small>1217+
{conclusion1218+
? humanize(conclusion.consensus)1219+
: journey.reports.length === 11220+
? 'One agent finished; confirming with the peer'1221+
: 'Conversation remains active'}1222+
</small>11861223
</section>11871224
<section>1188-
<span>Feedback</span>1189-
<strong>{conclusion ? 'Closed' : `${journey.feedback.length} submitted locally`}</strong>1225+
<span>Sealed feedback</span>1226+
<strong>{conclusion ? 'Released' : `${submittedFeedback}/2 submitted`}</strong>11901227
<small>{feedbackState(journey.feedbackRequests)}</small>11911228
</section>11921229
<section>@@ -1202,6 +1239,42 @@
12021239
</section>12031240
</div>12041241
1242+
{latestCheckpoint ? (1243+
<section className="progressCard">1244+
<div className="progressCardTop">1245+
<div>1246+
<span className="eyebrow">LATEST PRIVATE CHECKPOINT</span>1247+
<h3>{humanize(latestCheckpoint.state)}</h3>1248+
</div>1249+
<strong>{Math.round(progress * 100)}%</strong>1250+
</div>1251+
<div1252+
className="progressTrack"1253+
role="progressbar"1254+
aria-label="Interaction progress"1255+
aria-valuemin={0}1256+
aria-valuemax={100}1257+
aria-valuenow={Math.round(progress * 100)}1258+
>1259+
<i style={{ width: `${Math.round(progress * 100)}%` }} />1260+
</div>1261+
<div className="progressFacts">1262+
<span>{latestCheckpoint.criteriaMet?.length ?? 0} criteria met</span>1263+
<span>{latestCheckpoint.criteriaRemaining?.length ?? 0} remaining</span>1264+
<span>{latestCheckpoint.expectedRemainingTurns ?? '—'} expected turns</span>1265+
<span>1266+
{latestCheckpoint.needsHuman ? 'Human input needed' : 'No human input needed'}1267+
</span>1268+
</div>1269+
{latestCheckpoint.topicStatus !== 'in_scope' ? (1270+
<p className="progressWarning">1271+
Topic {humanize(latestCheckpoint.topicStatus)}. Amend the contract or start a new1272+
interaction before continuing.1273+
</p>1274+
) : null}1275+
</section>1276+
) : null}1277+
12051278
{conclusion ? (12061279
<section className="outcomeCard">12071280
<div>@@ -1228,7 +1301,11 @@
12281301
</section>12291302
) : (12301303
<div className="journeyNotice">1231-
No conclusion yet. It appears after terminal reports and bilateral feedback or timeout.1304+
{journey.reports.length === 11305+
? 'Finalizing: one agent submitted its terminal report. OpenClasp has requested independent confirmation from the peer.'1306+
: journey.reports.length >= 21307+
? 'Both agents finished. Sealed feedback remains private until both respond or the feedback window expires.'1308+
: 'Active interaction. Progress checkpoints appear after several meaningful exchanges; either agent can finalize immediately when the task is done.'}12321309
</div>12331310
)}12341311
@@ -1290,17 +1367,32 @@
12901367
},12911368
]12921369
: []),1293-
...journey.events.map((event) => ({1294-
at: timestamp(event),1295-
title: humanize(event.eventType ?? 'Structured event'),1296-
detail: String(event.agentId ?? 'OpenClasp') + ' submitted structured metadata.',1297-
status: String(event.visibility ?? 'recorded'),1298-
tone: String(event.eventType).includes('violation')1299-
? 'danger'1300-
: String(event.eventType).includes('warning')1301-
? 'warn'1302-
: 'neutral',1303-
})),1370+
...journey.events.map((event) => {1371+
const eventType = String(event.type ?? event.eventType ?? 'structured_event');1372+
const checkpoint = event.checkpoint;1373+
return {1374+
at: timestamp(event),1375+
title:1376+
eventType === 'progress_checkpoint'1377+
? `${Math.round(Number(checkpoint?.progress ?? 0) * 100)}% progress checkpoint`1378+
: humanize(eventType),1379+
detail:1380+
eventType === 'progress_checkpoint'1381+
? `${event.agentId} · ${humanize(checkpoint?.state ?? 'active')} · ${humanize(checkpoint?.topicStatus ?? 'in_scope')}`1382+
: String(event.agentId ?? 'OpenClasp') + ' submitted structured metadata.',1383+
status: String(checkpoint?.state ?? event.visibility ?? 'recorded'),1384+
tone:1385+
checkpoint?.topicStatus === 'changed' || checkpoint?.state === 'blocked'1386+
? 'warn'1387+
: eventType.includes('violation')1388+
? 'danger'1389+
: eventType.includes('warning')1390+
? 'warn'1391+
: checkpoint1392+
? 'good'1393+
: 'neutral',1394+
};1395+
}),13041396
...journey.reports.map((report) => ({13051397
at: timestamp(report),13061398
title: `Completion reported by ${report.reportingAgentId}`,apps/dashboard/src/styles.cssmodifiedView file
Loading diff…
connectors/botpress/hub.mdmodifiedView file
Loading diff…
connectors/botpress/integration.definition.tsmodifiedView file
Loading diff…
connectors/botpress/package.jsonmodifiedView file
Loading diff…
connectors/botpress/src/checkpoint.tsaddedView file
Loading diff…
connectors/botpress/src/index.tsmodifiedView file
Loading diff…
docs/MCP_TOOLS.mdmodifiedView file
Loading diff…
docs/PROTOCOL_V0.1.mdmodifiedView file
Loading diff…
packages/mcp-server/src/server.tsmodifiedView file
Loading diff…
packages/protocol/src/index.tsmodifiedView file
Loading diff…
schemas/v0.1/live_session_event.schema.jsonmodifiedView file
Loading diff…
tests/botpress-checkpoint.test.tsaddedView file
Loading diff…
tests/mcp.test.tsmodifiedView file
Loading diff…
tests/protocol.test.tsmodifiedView file
Loading diff…