Skip to content

chat: add turn timing metadata#332

Draft
justschen wants to merge 2 commits into
mainfrom
justin/corviknight
Draft

chat: add turn timing metadata#332
justschen wants to merge 2 commits into
mainfrom
justin/corviknight

Conversation

@justschen

Copy link
Copy Markdown
  • Carries authoritative start and end timestamps through turn lifecycle actions so clients can render consistent timing information.
  • Persists turn start times and derived durations in state while preserving compatibility with older completed turns.
  • Keeps reducer behavior aligned across TypeScript, Rust, Kotlin, Swift, and Go, including invalid timestamp handling.
  • Regenerates schemas and client wire types and extends shared conformance fixtures.

References microsoft/vscode#325061

(Commit message generated by Copilot)

- Carries authoritative start and end timestamps through turn lifecycle actions so clients can render consistent timing information.
- Persists turn start times and derived durations in state while preserving compatibility with older completed turns.
- Keeps reducer behavior aligned across TypeScript, Rust, Kotlin, Swift, and Go, including invalid timestamp handling.
- Regenerates schemas and client wire types and extends shared conformance fixtures.

References microsoft/vscode#325061

(Commit message generated by Copilot)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds authoritative turn timing metadata to the chat turn lifecycle so all clients can display consistent “started at” and “duration” information, and reducers stop synthesizing timestamps locally for turn boundaries.

Changes:

  • Extend chat turn lifecycle actions to carry startedAt / endedAt, and extend turn state to expose startedAt / duration.
  • Update reducers (TypeScript, Rust, Kotlin, Swift, Go) to validate timestamps, propagate authoritative timestamps into modifiedAt, and compute/clamp turn duration.
  • Regenerate schemas and client wire types, add cross-language reducer fixtures, and add a changelog fragment.
Show a summary per file
File Description
types/channels-chat/actions.ts Adds startedAt/endedAt to turn lifecycle actions.
types/channels-chat/state.ts Exposes startedAt/duration on completed turns; requires startedAt on active turns.
types/channels-chat/reducer.ts Validates timestamps, uses authoritative timestamps for modifiedAt, computes/clamps duration.
types/reducers.test.ts Updates fixture-driven test inputs for required startedAt.
types/test-cases/reducers/005-session-turnstarted.json Updates fixtures for required startedAt and modifiedAt behavior.
types/test-cases/reducers/006-turnstarted-with-queuedmessageid-removes-from-queuedmessages.json Updates fixtures for required startedAt and modifiedAt behavior.
types/test-cases/reducers/007-turnstarted-with-queuedmessageid-removes-last-queued-message.json Updates fixtures for required startedAt and modifiedAt behavior.
types/test-cases/reducers/008-turnstarted-with-queuedmessageid-removes-matching-steering-message.json Updates fixtures for required startedAt and modifiedAt behavior.
types/test-cases/reducers/009-turnstarted-without-queuedmessageid-does-not-touch-pending-messages.json Updates fixtures for required startedAt and modifiedAt behavior.
types/test-cases/reducers/010-session-delta-appends-content.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/011-session-delta-with-wrong-turnid-is-no-op.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/013-session-responsepart-adds-to-responseparts.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/014-session-turncomplete-finalizes-turn.json Updates fixtures for endedAt and expected duration.
types/test-cases/reducers/015-session-turncancelled-finalizes-turn.json Updates fixtures for endedAt and expected duration.
types/test-cases/reducers/016-session-error-finalizes-turn-with-error.json Updates fixtures for endedAt and expected duration.
types/test-cases/reducers/017-turncomplete-force-cancels-in-progress-tool-calls.json Updates fixtures for endedAt and expected duration.
types/test-cases/reducers/018-turncomplete-with-wrong-turnid-is-no-op.json Updates fixtures for endedAt presence on the action.
types/test-cases/reducers/019-tool-call-full-lifecycle-start-delta-ready-confirmed-complete.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/020-tool-call-ready-with-auto-confirm-transitions-to-running.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/021-tool-call-denied-transitions-to-cancelled.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/022-tool-call-result-confirmation-pending-approved.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/023-tool-call-result-denied-cancelled-with-result-denied-reason.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/024-tool-call-complete-from-pending-confirmation-defaults-confirmed.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/025-tool-call-actions-for-unknown-toolcallid-are-no-op.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/026-toolcallready-transitions-running-tool-back-to-pending-confirmation.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/027-toolcallready-re-confirmation-approved-transitions-back-to-running.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/028-toolcallready-re-confirmation-denied-transitions-to-cancelled.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/029-toolcallready-ignores-non-streaming-non-running-tool-calls.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/031-session-usage-updates-usage-on-active-turn.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/032-session-reasoning-appends-reasoning-content.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/067-session-truncated-drops-active-turn.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/068-session-truncated-drops-active-turn-even-when-clearing-all.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/070-full-turn-flow-with-tool-calls-and-re-confirmation.json Updates fixtures for endedAt and expected duration.
types/test-cases/reducers/075-turnstarted-clears-isread.json Updates fixtures for startedAt and modifiedAt behavior.
types/test-cases/reducers/084-toolcall-contentchanged-updates-running.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/085-toolcall-contentchanged-noop-non-running.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/086-toolcall-contentchanged-replaces-existing.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/090-toolcalldelta-wrong-turnid-is-no-op.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/091-responsepart-wrong-turnid-is-no-op.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/092-toolcallstart-wrong-turnid-is-no-op.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/093-usage-wrong-turnid-is-no-op.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/094-delta-nonexistent-partid-is-no-op.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/095-toolcalldelta-wrong-status-is-no-op.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/096-toolcallconfirmed-wrong-status-is-no-op.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/097-toolcallcomplete-wrong-status-is-no-op.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/098-toolcallresultconfirmed-wrong-status-is-no-op.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/099-endturn-force-cancels-running-tool-call.json Updates fixtures for endedAt and expected duration.
types/test-cases/reducers/100-delta-targeting-toolcall-partid-is-no-op.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/101-toolcalldelta-without-invocationmessage.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/102-reasoning-targeting-non-reasoning-is-no-op.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/103-delta-skips-parts-without-id.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/105-session-input-full-draft-and-complete-flow.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/106-session-input-requested-with-drafts-status.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/107-session-input-turn-end-cleans-turn-scoped-only.json Updates fixtures for endedAt and expected duration.
types/test-cases/reducers/108-session-input-upsert-and-clear-answer.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/110-session-input-completion-and-truncation-filtering.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/111-toolcall-pending-confirmation-sets-input-needed-status.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/112-toolcall-pending-result-confirmation-sets-input-needed-status.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/127-toolcallready-with-confirmation-options.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/128-toolcallconfirmed-approved-with-selectedoption.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/129-toolcallconfirmed-denied-with-selectedoption.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/130-selectedoption-carries-through-to-completed.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/131-selectedoption-carries-through-result-confirmation.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/132-selectedoption-carries-through-result-denied.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/158-toolcallconfirmed-approved-with-editedtoolinput-overrides-original.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/161-chat-turn-lifecycle-on-chat.json Updates lifecycle fixtures for startedAt/endedAt and duration.
types/test-cases/reducers/163-toolcallstart-carries-mcp-contributor-through-lifecycle.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/220-toolcall-actions-update-meta.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/235-session-input-completion-records-declined-request-in-turn.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/237-session-input-completion-no-op-unknown-id-with-open-requests.json Updates fixtures for required startedAt on activeTurn.
types/test-cases/reducers/238-invalid-turn-start-timestamp-is-no-op.json Adds fixture coverage for invalid startedAt no-op behavior.
types/test-cases/reducers/239-invalid-turn-end-timestamp-is-no-op.json Adds fixture coverage for invalid endedAt no-op behavior.
types/test-cases/reducers/240-turn-duration-is-clamped-to-zero.json Adds fixture coverage for negative duration clamping.
schema/actions.schema.json Regenerates action schema with startedAt/endedAt requiredness.
schema/commands.schema.json Regenerates command schema to reflect updated action/state shapes.
schema/errors.schema.json Regenerates error schema to reflect updated action/state shapes.
schema/notifications.schema.json Regenerates notification schema to reflect updated state shapes.
schema/state.schema.json Regenerates state schema with startedAt/duration and ActiveTurn.startedAt required.
docs/.changes/20260709-turn-timing.json Adds changelog fragment documenting the user-visible protocol change.
clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Reducers.swift Updates Swift reducer to validate and propagate timestamps and compute duration.
clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/Actions.generated.swift Regenerates Swift action wire types for new fields.
clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/State.generated.swift Regenerates Swift state wire types for new fields.
clients/swift/AgentHostProtocol/Tests/AgentHostProtocolTests/ReducersTests.swift Updates Swift reducer tests for required timestamps and modifiedAt semantics.
clients/swift/AgentHostProtocol/Tests/AgentHostProtocolTests/NativeReducerTests.swift Updates Swift native reducer test state setup for required startedAt.
clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/Reducers.kt Updates Kotlin reducer to validate timestamps and compute duration/modifiedAt from action timestamps.
clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/Actions.generated.kt Regenerates Kotlin action wire types for new fields.
clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/State.generated.kt Regenerates Kotlin state wire types for new fields.
clients/kotlin/src/test/kotlin/com/microsoft/agenthostprotocol/ReducersTest.kt Updates Kotlin reducer tests to assert timestamp propagation.
clients/rust/crates/ahp/src/reducers.rs Updates Rust reducer to validate timestamps, propagate modifiedAt, and compute duration.
clients/rust/crates/ahp-types/src/actions.rs Regenerates Rust action wire types for new fields.
clients/rust/crates/ahp-types/src/state.rs Regenerates Rust state wire types for new fields.
clients/rust/crates/ahp/Cargo.toml Adds chrono dependency used for RFC3339 parsing in reducer.
clients/rust/Cargo.toml Adds/pins chrono in the Rust workspace.
clients/rust/Cargo.lock Updates lockfile for chrono and transitive deps.
clients/go/ahp/reducers.go Updates Go reducer to validate timestamps, propagate modifiedAt, and compute duration.
clients/go/ahptypes/actions.generated.go Regenerates Go action wire types for new fields.
clients/go/ahptypes/state.generated.go Regenerates Go state wire types for new fields.
clients/go/examples/reducers_demo/main.go Updates Go example usage for required timestamps.

Review details

  • Files reviewed: 93/98 changed files
  • Comments generated: 0
  • Review effort level: Low

Normalize timestamp fractions to whole milliseconds before converting through Foundation so floating-point representation cannot undercount elapsed turn durations.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants