Repository navigation
chat: persist timing for contiguous reasoning runs - #345121
Merged
Justin Chen (justschen) merged 4 commits intoOct 30, 2026
Merged
Conversation
Preserve producer-owned timing across live updates, reconnection, and saved chat history so fallback thinking headers retain their elapsed time. Record Copilot reasoning against durable assistant-message IDs without timing replay or inventing missing historical durations. Sync the optional protocol fields from microsoft/agent-host-protocol commit f9d401d7. Co-authored-by: Copilot <[email protected]>
Contributor
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Reasoning timing is lost after import and reopen, does not refresh finalized headers or ARIA labels, and can produce fabricated totals after reconnect when hosts omit timing fields.
3 open issues
What changed in this PR
This PR carries producer-recorded reasoning durations through the Agent Host and chat UI so untitled thinking sections can retain labels such as “Thought for 45s” after reload or reconnect.
Changes:
- Measures Copilot reasoning fragments and persists timing with turn remapping and pruning support.
- Adds optional protocol timing fields and forwards them through live updates, restored history, imports, and chat serialization.
- Updates fallback headers and accessible labels, with focused persistence, reconnect, model, and UI tests.
| File | Description |
|---|---|
src/vs/workbench/contrib/chat/test/common/model/chatModel.test.ts |
Tests timing-only updates, distinct IDs, and serialization. |
src/vs/workbench/contrib/chat/test/browser/widget/chatContentParts/chatThinkingContentPart.test.ts |
Tests recorded-duration headers and accessible labels. |
src/vs/workbench/contrib/chat/test/browser/agentSessions/stateToProgressAdapter.test.ts |
Tests history and reconnect timing conversion. |
src/vs/workbench/contrib/chat/test/browser/agentSessions/importLocalConversationToAgentSession.test.ts |
Tests timing fields in imported turns. |
src/vs/workbench/contrib/chat/test/browser/agentSessions/agentHostChatContribution.test.ts |
Tests timing-only updates on opaque advertised chats. |
src/vs/workbench/contrib/chat/common/model/chatModel.ts |
Applies timing updates and separates reasoning IDs. |
src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatThinkingContentPart.ts |
Displays recorded durations in fallback thinking titles. |
src/vs/workbench/contrib/chat/browser/agentSessions/agentHost/stateToProgressAdapter.ts |
Converts protocol timing into chat thinking metadata. |
src/vs/workbench/contrib/chat/browser/agentSessions/agentHost/importLocalConversationToAgentSession.ts |
Includes timing in imported reasoning parts. |
src/vs/workbench/contrib/chat/browser/agentSessions/agentHost/agentHostSessionHandler.ts |
Emits timing changes independently of text changes. |
src/vs/platform/agentHost/test/node/sessionDatabase.test.ts |
Tests timing storage, validation, remapping, and pruning. |
src/vs/platform/agentHost/test/node/README.md |
Documents timing semantics and test coverage. |
src/vs/platform/agentHost/test/node/copilotReasoningTiming.test.ts |
Tests measurement and database reopen restoration. |
src/vs/platform/agentHost/test/node/copilotAgentSession.test.ts |
Tests producer timing publication and persistence. |
src/vs/platform/agentHost/test/common/sessionTestHelpers.ts |
Adds timing storage to the database test double. |
src/vs/platform/agentHost/node/sessionDatabase.ts |
Adds the timing table and persistence operations. |
src/vs/platform/agentHost/node/copilot/mapSessionEvents.ts |
Restores timing by durable assistant-event ID. |
src/vs/platform/agentHost/node/copilot/copilotSubagentTracking.ts |
Exposes the owning root turn for subagent timing. |
src/vs/platform/agentHost/node/copilot/copilotReasoningTiming.ts |
Measures and aggregates live reasoning intervals. |
src/vs/platform/agentHost/node/copilot/copilotAgentSession.ts |
Integrates measurement with provider events and storage. |
src/vs/platform/agentHost/node/compatibleSessionDatabase.ts |
Delegates timing persistence operations. |
src/vs/platform/agentHost/common/state/protocol/channels-chat/state.ts |
Adds optional reasoning start and duration fields. |
src/vs/platform/agentHost/common/state/protocol/channels-chat/reducer.ts |
Applies reasoning timing updates to protocol state. |
src/vs/platform/agentHost/common/state/protocol/channels-chat/actions.ts |
Defines optional timing fields and timing-only updates. |
src/vs/platform/agentHost/common/state/protocol/.ahp-version |
Pins the companion protocol revision. |
src/vs/platform/agentHost/common/sessionDataService.ts |
Defines the reasoning timing persistence contract. |
Review effort: Balanced
Keep one reasoning identity and clock until markdown, a new tool call, or turn termination. Persist the observed response-part ordering and update runs that span SDK messages, rather than storing message-level totals. Restore separate run durations and canonical tool positions, retain conversation grouping with per-run labels, and cover 5s/12s boundaries across database restart and UI reload. Pin the clarified contract from microsoft/agent-host-protocol#552. Co-authored-by: Copilot <[email protected]>
Persist imported response projections against synthesized Copilot event IDs before resume. Refresh timing labels on finalized reasoning sections, including array and grouped content, and keep AHP timing provider-owned even when optional timing fields are absent. Add import/reopen, late visible/ARIA label, and untimed reconnect regressions while preserving local-provider measurement. Co-authored-by: Copilot <[email protected]>
Reference the merge commit of microsoft/agent-host-protocol#552. The generated protocol sources are unchanged. Co-authored-by: Copilot <[email protected]>
Justin Chen (justschen)
marked this pull request as ready for review
October 30, 2026 17:40
Justin Chen (justschen)
enabled auto-merge (squash)
October 30, 2026 17:41
Ben Villalobos (benvillalobos)
approved these changes
Oct 30, 2026
Justin Chen (justschen)
deleted the
agents/persistence-timing-tools-reasoning
branch
October 30, 2026 18:43
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
Persist the duration of each contiguous thinking run, not a total for an assistant message or a UI group.
This retains two independent durations,
5000and12000, including after database restart and UI reload. A run starts at its first nonempty reasoning text and ends at the next markdown/tool part or turn termination. SDK reasoning IDs, reasoning-complete events, full-message boundaries, and sideband notifications do not split it.assistant_response_parts, keyed by durable assistant-message IDs. Final timing updates earlier fragments of an unfinished run.reasoning_timingrows as individual run timings. Unknown or unfinished history stays untimed.Companion protocol PR: microsoft/agent-host-protocol#552 is merged. The generated protocol source is pinned to merge commit
d7a5579b; the protocol dependency is satisfied.Scope: producer-side capture is implemented for Copilot. Other conforming hosts can supply the optional timing fields; this does not add capture to other providers, estimate older history, or change tool timing. Local, non-AHP providers retain their existing client-side reasoning measurement.
No issue was supplied for this feature request.
Validation
npm run build-fast -- --client-only— passed.npm run typecheck-client— passed.Changed-file ESLint — passed, using this command before committing:
Repository hygiene — passed, using this command before committing:
npm run stylelint -- src/vs/workbench/contrib/chat/browser/widget/chatContentParts/media/chatThinkingContent.css— passed, with 15 pre-existing design-token suggestions. CSS is unchanged by the review follow-up.Initial contiguous-run implementation validation, before the review follow-up below — 3,378 passed; 2 existing pending:
./scripts/test.sh --reporter dot \ --run src/vs/platform/agentHost/test/node/copilotReasoningTiming.test.ts \ --run src/vs/platform/agentHost/test/node/sessionDatabase.test.ts \ --run src/vs/platform/agentHost/test/node/mapSessionEvents.test.ts \ --run src/vs/platform/agentHost/test/node/copilotAgentSession.test.ts \ --run src/vs/platform/agentHost/test/node/copilotSubagentTracking.test.ts \ --run src/vs/workbench/contrib/chat/test/common/model/chatModel.test.ts \ --run src/vs/workbench/contrib/chat/test/browser/agentSessions/stateToProgressAdapter.test.ts \ --run src/vs/workbench/contrib/chat/test/browser/agentSessions/agentHostChatContribution.test.ts \ --run src/vs/workbench/contrib/chat/test/browser/agentSessions/importLocalConversationToAgentSession.test.ts \ --run src/vs/workbench/contrib/chat/test/browser/widget/chatContentParts/chatThinkingContentPart.test.ts \ --run src/vs/workbench/contrib/chat/test/browser/widget/chatListRenderer.test.ts \ --grep 'CopilotAgentSession|CopilotReasoningTiming|SessionDatabase|mapSessionEvents|ChatModel|^Response|ChatResponseModel|stateToProgressAdapter|ChatThinkingContentPart|importedTurnsFromChatModel|CopilotSubagentTracking|ChatList|AgentHostChatContribution.*reasoning'The tests cover separate 5s/12s markdown/tool boundaries through real SQLite close/reopen and UI reload in Compact, Verbose, and Conversation modes; a single run spanning SDK messages; partial/mismatched recordings; parent/child isolation; legacy aggregate migration; and accessible labels.
The final AHP pin update left all 62 generated protocol TypeScript files byte-identical to the validated code. The companion PR records protocol/client validation and Kotlin/.NET toolchain limitations.
Live-provider/E2E flows and manual screen-reader testing were not run.
Review follow-up validation
Commit
4709ddbace5addresses the three selected review comments. New regressions cover imported 45s/zero/unknown timing through event-log and real database reopen (including synthesized turn IDs), late header/ARIA refresh for string and array reasoning, an earlier run in a finalized conversation group, and continued untimed AHP output after reconnect without changing local-provider measurement.Build, client type-check, changed-file ESLint, and hygiene were rerun successfully. The focused surrounding regression selection passed 1,773 tests, with 2 existing pending:
./scripts/test.sh --reporter dot \ --run src/vs/platform/agentHost/test/node/buildSessionEvents.test.ts \ --run src/vs/platform/agentHost/test/node/copilotAgent.test.ts \ --run src/vs/platform/agentHost/test/node/mapSessionEvents.test.ts \ --run src/vs/platform/agentHost/test/node/copilotReasoningTiming.test.ts \ --run src/vs/workbench/contrib/chat/test/common/model/chatModel.test.ts \ --run src/vs/workbench/contrib/chat/test/browser/agentSessions/stateToProgressAdapter.test.ts \ --run src/vs/workbench/contrib/chat/test/browser/agentSessions/agentHostChatContribution.test.ts \ --run src/vs/workbench/contrib/chat/test/browser/widget/chatContentParts/chatThinkingContentPart.test.ts \ --run src/vs/workbench/contrib/chat/test/browser/widget/chatListRenderer.test.ts \ --grep 'buildSessionEventsFromTurns|CopilotAgent.*import|mapSessionEvents|CopilotReasoningTiming|ChatModel|^Response|ChatResponseModel|stateToProgressAdapter|ChatThinkingContentPart|ChatList|AgentHostChatContribution.*reasoning'