Skip to content

Server-generated assistant turns omit stable id / createdAt #1087

Description

@kolaworld

TanStack AI version

0.44.0

Framework/Library version

@tanstack/ai-client: 0.23.2 | @tanstack/ai-persistence: 0.1.2 | @tanstack/ai-svelte: 0.16.2

Describe the bug and the steps to reproduce it

Issue #1063 / PR #1066 and Issue #1064 / PR #1069 fixed UI → model conversion so client-supplied UIMessage.id and UIMessage.createdAt copy onto ModelMessage.

Those fixes are ancestors of @tanstack/ai@0.44.0, and the conversion path now preserves both fields in messages.ts#L186-L193 (and the assistant-segment builders beside it).

Server-generated assistant turns do not pass through that conversion.

When the model emits tool calls, addAssistantToolCallMessage() appends a new ModelMessage with only role, content, toolCalls, and optional thinking — no id or createdAt index.ts#L1948-L1963.

That message is what withPersistence saves on the interrupt / agent-loop boundary via ctx.messages, so a hydrated tool-call turn gets a fresh client id and timestamp.

The terminal-text persistence path is only a partial fix. finishedTranscript() stamps the streamed messageId onto the final assistant reply but still omits createdAt middleware.ts#L438-L459.

Streaming snapshots do the same: they optionally set id and never set createdAt.

So after #1063 / #1064, UI-originated messages round-trip, but server-authored assistant bubbles still lose stable identity and wall-clock time across persist → hydrate. That breaks in-place rendering for tool-call turns and leaves terminal turns without a durable createdAt.

Expected behavior

  • When the engine appends an assistant tool-call turn, stamp the current stream messageId (and a createdAt) onto that ModelMessage.
  • When persistence appends a terminal assistant turn in finishedTranscript() (and in streaming snapshots), copy the same createdAt contract used for UI → model conversion, not only id.

Your Minimal, Reproducible Example - (Sandbox Highly Recommended)

https://stackblitz.com/edit/vitejs-vite-cvbrdixn?file=package.json,index.html,src%2Fmain.ts

Screenshots or Videos (Optional)

No response

Do you intend to try to help solve this bug with your own PR?

None

Terms & Code of Conduct

  • I agree to follow this project's Code of Conduct
  • I understand that if my bug cannot be reliable reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    has-prAn open PR references this issuewaiting-on: maintainerThe ball is in the maintainers’ court

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions