fix(ui-stdio): seed turn labels from the registry; drop stale taxonomy line

Address review on the event-taxonomy PR:

- ui-stdio built its session-id→agent-id label map only from live
  `agent/created` events, so an agent registered before the UI fiber
  installed — the pre-created `main` agent, or any agent surviving an HMR
  reload of just this fiber — was missed and its turns rendered the raw
  session id instead of `[main turn N]`. Seed the map from
  `ctx.agents.list()` at install, then keep it live. Regression test proven
  red without the seed.
- The agent event-domain doc still listed "the turn boundaries" among the
  TRANSIENT `agent/*` emits, contradicting the rule ten lines below that a
  turn/step boundary is a durable `session/event`, not an `agent/*` mirror.
This commit is contained in:
Tianyi Cui
2026-07-02 13:57:59 +08:00
parent 9e575a2a2c
commit 1e87b6fea4
6 changed files with 46 additions and 16 deletions

View File

@@ -16,6 +16,9 @@ function fakeContext(): Context {
return {
on: vi.fn(() => vi.fn()),
effect: vi.fn((callback: () => () => void) => callback()),
// The UI seeds its label map from the registry at install; this suite only
// exercises readline terminal-mode selection, so an empty roster suffices.
agents: { list: vi.fn(() => []) },
} as unknown as Context
}

View File

@@ -149,6 +149,26 @@ describe('createStdioChat rendering', () => {
expect(out.text()).toContain('[orphan-session turn 1] ')
})
it('seeds labels for agents already registered before the UI installs', async () => {
// The pre-created `main` agent (and any agent surviving an HMR reload of just
// this fiber) fired its `agent/created` before the UI's listener existed, so
// the live listener alone would miss it. Seeding from `ctx.agents.list()` at
// install time is what keeps its turn header showing `[main turn N]` instead
// of the raw session id.
const ctx = new Context()
await ctx.plugin(AgentRegistry)
const agent = makeAgent('main')
ctx.agents.register(agent) // registered BEFORE the UI plugin below
const { runtime, out } = makeRuntime()
await ctx.plugin(Object.assign((inner: Context) => {
createStdioChat(inner, CONFIG, runtime)
}, { inject: ['agents'] }))
ctx.emit('session/event', makeSession('main'), {
type: 'turn/start', seq: 1, time: 0, data: { turn: 5, trigger: { kind: 'message' } },
} as SessionEvent)
expect(out.text()).toContain('[main turn 5] ')
})
it('resets dim styling at turn/end if a turn ends mid-reasoning', async () => {
const { ctx, out } = await setup()
const agent = makeAgent('main')