@@ -7,6 +7,27 @@ type AgentRuntimeModule = {
77 openLearningPathDock : ( preferredAtomId ?: string ) => void ;
88 hidePathDock : ( ) => void ;
99 togglePathFullscreen : ( ) => void ;
10+ getDiagnosticsSnapshot : ( ) => {
11+ conversationRequests : number ;
12+ replayCandidateTurns : number ;
13+ turnCounts : {
14+ user : number ;
15+ assistant : number ;
16+ system : number ;
17+ total : number ;
18+ } ;
19+ turns : Array < Record < string , unknown > > ;
20+ capabilityEvents : Array < Record < string , unknown > > ;
21+ lastCapabilityEvent : Record < string , unknown > | null ;
22+ lastConversation : Record < string , unknown > | null ;
23+ lastFailure : Record < string , unknown > | null ;
24+ pathState : {
25+ visible : boolean ;
26+ fullscreen : boolean ;
27+ } ;
28+ latestFocusAtomId : string ;
29+ latestKnowledgePoints : number ;
30+ } ;
1031 } ;
1132} ;
1233
@@ -1482,4 +1503,135 @@ describe('agent workspace runtime behavior', () => {
14821503 runtime . togglePathFullscreen ( ) ;
14831504 expect ( pathFullscreenButton . textContent ) . toBe ( '路径全屏 ZH' ) ;
14841505 } ) ;
1506+
1507+ test ( 'records replay candidates and capability execution diagnostics snapshot' , async ( ) => {
1508+ const fetchMock = jest
1509+ . fn ( )
1510+ . mockResolvedValueOnce ( {
1511+ ok : true ,
1512+ status : 200 ,
1513+ json : async ( ) => ( {
1514+ success : true ,
1515+ result : {
1516+ userId : 'agent_user_default' ,
1517+ message : 'Found 1 local knowledge point(s).' ,
1518+ knowledgePoints : [
1519+ {
1520+ atomId : 'atom-diagnostic-1' ,
1521+ title : 'Diagnostic Candidate' ,
1522+ snippet : 'Replay and capability diagnostics.' ,
1523+ score : 0.81 ,
1524+ capabilities : [
1525+ {
1526+ actionId : 'open_learning_path' ,
1527+ label : 'Learning Path' ,
1528+ request : {
1529+ userId : 'agent_user_default' ,
1530+ atomId : 'atom-diagnostic-1' ,
1531+ } ,
1532+ execution : {
1533+ kind : 'knowledge_operation' ,
1534+ operationId : 'build_learning_path' ,
1535+ resultPresentation : 'learning_path_card' ,
1536+ } ,
1537+ } ,
1538+ ] ,
1539+ } ,
1540+ ] ,
1541+ } ,
1542+ } ) ,
1543+ } )
1544+ . mockResolvedValueOnce ( {
1545+ ok : true ,
1546+ status : 200 ,
1547+ json : async ( ) => ( {
1548+ success : true ,
1549+ result : {
1550+ userId : 'agent_user_default' ,
1551+ message : 'Found 1 local knowledge point(s).' ,
1552+ knowledgePoints : [
1553+ {
1554+ atomId : 'atom-diagnostic-1' ,
1555+ title : 'Diagnostic Candidate' ,
1556+ snippet : 'Replay and capability diagnostics.' ,
1557+ score : 0.81 ,
1558+ capabilities : [
1559+ {
1560+ actionId : 'open_learning_path' ,
1561+ label : 'Learning Path' ,
1562+ request : {
1563+ userId : 'agent_user_default' ,
1564+ atomId : 'atom-diagnostic-1' ,
1565+ } ,
1566+ execution : {
1567+ kind : 'knowledge_operation' ,
1568+ operationId : 'build_learning_path' ,
1569+ resultPresentation : 'learning_path_card' ,
1570+ } ,
1571+ } ,
1572+ ] ,
1573+ } ,
1574+ ] ,
1575+ } ,
1576+ } ) ,
1577+ } )
1578+ . mockResolvedValueOnce ( {
1579+ ok : true ,
1580+ status : 200 ,
1581+ json : async ( ) => ( {
1582+ success : true ,
1583+ result : {
1584+ masteryPaths : [ { id : 'mastery-1' } ] ,
1585+ divergencePaths : [ { id : 'divergence-1' } ] ,
1586+ } ,
1587+ } ) ,
1588+ } ) ;
1589+ ( global as unknown as Record < string , unknown > ) . fetch = fetchMock ;
1590+
1591+ const runtime = runtimeModule . createAgentWorkspaceRuntime ( { defaultUserId : 'agent_user_default' } ) ;
1592+ runtime . init ( ) ;
1593+
1594+ const input = document . getElementById ( 'agent-workspace-input' ) as HTMLTextAreaElement ;
1595+ const form = document . getElementById ( 'agent-workspace-form' ) as HTMLFormElement ;
1596+ input . value = 'repeat diagnostics' ;
1597+ form . dispatchEvent ( new dom ! . window . Event ( 'submit' , { bubbles : true , cancelable : true } ) ) ;
1598+ await flushAsync ( ) ;
1599+
1600+ input . value = 'repeat diagnostics' ;
1601+ form . dispatchEvent ( new dom ! . window . Event ( 'submit' , { bubbles : true , cancelable : true } ) ) ;
1602+ await flushAsync ( ) ;
1603+
1604+ const actionButton = document . querySelector ( '.agent-workspace-action-button' ) as HTMLButtonElement ;
1605+ expect ( actionButton ) . not . toBeNull ( ) ;
1606+ actionButton . click ( ) ;
1607+ await flushAsync ( ) ;
1608+
1609+ const snapshot = runtime . getDiagnosticsSnapshot ( ) ;
1610+ expect ( snapshot . conversationRequests ) . toBe ( 2 ) ;
1611+ expect ( snapshot . replayCandidateTurns ) . toBe ( 1 ) ;
1612+ expect ( snapshot . turnCounts . user ) . toBe ( 2 ) ;
1613+ expect ( snapshot . latestKnowledgePoints ) . toBe ( 1 ) ;
1614+ expect ( snapshot . pathState . visible ) . toBe ( true ) ;
1615+ expect ( snapshot . pathState . fullscreen ) . toBe ( false ) ;
1616+ expect ( snapshot . lastConversation ) . toEqual (
1617+ expect . objectContaining ( {
1618+ status : 'success' ,
1619+ replayCandidate : true ,
1620+ knowledgePoints : 1 ,
1621+ } )
1622+ ) ;
1623+
1624+ const requestEvent = snapshot . capabilityEvents . find (
1625+ ( event ) => event . phase === 'request' && event . operationId === 'build_learning_path'
1626+ ) ;
1627+ expect ( requestEvent ) . toBeDefined ( ) ;
1628+ expect ( snapshot . lastCapabilityEvent ) . toEqual (
1629+ expect . objectContaining ( {
1630+ phase : 'result' ,
1631+ status : 'success' ,
1632+ operationId : 'build_learning_path' ,
1633+ resultPresentation : 'learning_path_card' ,
1634+ } )
1635+ ) ;
1636+ } ) ;
14851637} ) ;
0 commit comments