unbridled-41 opened a new issue, #5003:
URL: https://github.com/apache/rocketmq-dashboard/issues/5003
### Studio Version
branch: rocketmq-studio
git commit id: 1ef5d860799ac3fabfcdea942cc4dcc77ded7be6
### Runtime Environment
Service-level reproduction in the repository's test suite (AiRunServiceTest,
MockMvc-free); no browser, cluster or MySQL needed.
### Connected RocketMQ Cluster
Not applicable — the defect is in the AI run stream replay path, independent
of any RocketMQ cluster topology.
### Describe the Bug
Reconnecting to a finished agent run (`GET /api/ai/runs/:runId/stream`, the
replay path in `AiRunService.attach`) delivers a terminal `run_finished` frame
**without** the `durationMs` field. The live path (`AiRunExecutor.finalizeRun`
→ `RunFinished(runId, status, durationMs)`) always carries it, so a replayed
block is observably different from what the run originally streamed.
`AgentEventProjector.replay`
(`server/src/main/java/org/apache/rocketmq/studio/ops/ai/conversation/event/AgentEventProjector.java:272-273`
at 1ef5d860) maps a persisted terminal to `new LiveEvent.RunFinished(runId,
terminal.status(), null)`, and the class is annotated
`@JsonInclude(JsonInclude.Include.NON_NULL)` (`LiveEvent.java:49`), so the null
duration is omitted from the serialized frame entirely. The projector's own doc
comment at `:240-243` promises the opposite ("Same wire vocabulary on both
sides, so the client cannot tell a replayed block from a streamed one").
### Steps to Reproduce
1. Run an agent run to completion.
2. Reconnect to it via `GET /api/ai/runs/{runId}/stream?after=0`.
3. Observe the replayed `run_finished` frame: it has `type`, `runId`,
`status` but no `durationMs` key.
The repository's own contract artifacts state the field must exist:
- `web/src/api/aiEvents.contract.test.ts:139` — `run_finished: { type: true,
runId: true, status: true, durationMs: true }`, and the live absent-field
matrix at `:424-433` expects `['run_finished', []]` (no field may be absent).
- `web/src/api/aiEvents.ts:169` — `LiveRunFinishedEvent.durationMs: number`
(non-optional).
- `docs/api-spec.md:2424` — `run_finished` fields listed as `runId, status,
durationMs` (no `?` marker, unlike `tool_done`'s `durationMs?`).
### What Did You Expect to See?
A replayed `run_finished` carries `durationMs` with the run row's persisted
duration, indistinguishable from the live frame.
### What Did You See Instead?
The `durationMs` key is absent from the replayed frame (NON_NULL
serialization drops the hard-coded null).
### Additional Context
Note on current impact: the web render layer today maps `run_finished` to a
terminal status and does not read `durationMs` (`foldTimeline.ts:178`,
`reduceLive.ts:48-50`), so the defect surfaces as a contract/type drift rather
than a visible crash. `equivalence.test.ts` builds its scenarios with the field
set, so the equivalence property the projector cites assumes it.
Corresponding pull request: #4999.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]