Prechádzať zdrojové kódy

fix(client-runtime): settle-only dispatch windows carry null callTime

Responding to ds-review-bot on #664 (root cause lives here): when a history
window carries a tool/code-dispatch settle without its paired start, the
runtime fabricated callTime = settle time, so downstream duration views
presented a measured 0 ms. Match the native tool-result contract instead —
callTime: null = unknown — and pin it; the trajectory cell already renders
null as the em dash, and the waterfall gains explicit unknown handling in
its own PR.
Tianyi Cui 2 mesiacov pred
rodič
commit
3e1a22eb2b

+ 4 - 2
packages/client/runtime/src/client/sessions/session.ts

@@ -661,8 +661,10 @@ export class Session implements ObservableSnapshot<ConversationSnapshot> {
         kind: 'tool-result', seq: event.seq, time: event.time,
         kind: 'tool-result', seq: event.seq, time: event.time,
         callId: data.subCallId,
         callId: data.subCallId,
         call: { name: data.name, argsRaw: JSON.stringify(data.arguments) },
         call: { name: data.name, argsRaw: JSON.stringify(data.arguments) },
-        // Duration source: the paired start's time when observed.
-        callTime: started === undefined ? event.time : started.time,
+        // Duration source: the paired start's time when observed; null =
+        // unknown (settle-only window), matching the native tool-result
+        // contract so views never present a fabricated zero duration.
+        callTime: started === undefined ? null : started.time,
         content: data.content, isError: data.isError,
         content: data.content, isError: data.isError,
         callView: null, resultView: null,
         callView: null, resultView: null,
       }
       }

+ 3 - 0
packages/client/runtime/tests/session.spec.ts

@@ -688,6 +688,9 @@ describe('run_code sub-dispatch indexing', () => {
       isError: false, content: [{ type: 'text', text: 'demo.txt' }],
       isError: false, content: [{ type: 'text', text: 'demo.txt' }],
     })
     })
     expect(subs?.[1]).toMatchObject({ callId: 'p1:code:2', isError: true })
     expect(subs?.[1]).toMatchObject({ callId: 'p1:code:2', isError: true })
+    // No paired start in the window: duration is UNKNOWN (null), never a
+    // fabricated zero-duration span.
+    expect(subs?.[0]).toMatchObject({ callTime: null })
     // Sub-dispatches never join the surface flow.
     // Sub-dispatches never join the surface flow.
     expect(session.getSnapshot().nodes.some(n => n.kind === 'tool-result' && n.callId.includes(':code:'))).toBe(false)
     expect(session.getSnapshot().nodes.some(n => n.kind === 'tool-result' && n.callId.includes(':code:'))).toBe(false)
   })
   })