fix: render the seeded first-message on the web UI (v0.19.9)
The #347 auto-seed worked (the greeting was in the session ledger at seq-0), but the web UI never showed it: there was no GET /api/sessions/{id}/messages route and startSession() went straight from create to persona/tools/admin hydration, so the transcript only filled from the live turn stream + user echoes — a seeded turn-0 was invisible. - server: new proxy route GET /api/sessions/{id}/messages -> get_session_messages (mirrors the tools/bifrost proxies; status-preserving envelope). - SPA: loadTranscript(sessionId) fetches it on open and renders existing turns (assistant -> .response .md-body via markdownSafe escape-first; user -> .prompt-echo via textContent), called after the workspace opens. Best-effort. web_debug_surface contract amended (endpoint + loadTranscript). 2 web route tests, suite 617 green. Playwright DOM check proved the render end-to-end (drive the real UI -> Sindra's greeting bubble appears).
This commit is contained in:
@@ -35,6 +35,17 @@ functions:
|
||||
steps: "Open client_factory() client; await get_session_tools(client, session_id); return 200. Except SessionApiFailed -> status-preserving envelope."
|
||||
flexibility: "prescriptive"
|
||||
|
||||
- name: "_session_messages_endpoint"
|
||||
signature: "async _session_messages_endpoint(request: Request) -> JSONResponse"
|
||||
description: "GET /api/sessions/{session_id}/messages — proxy the session's message history so the SPA renders existing turns on open (notably a #347 authored first-message seeded at create-time; without it a seeded session's transcript is blank until the user speaks)."
|
||||
preconditions:
|
||||
- "session_id in path_params."
|
||||
postconditions:
|
||||
- "POST-001: 200 with the upstream {session_id, items, next_cursor} dict verbatim on success."
|
||||
- "POST-002: on SessionApiFailed(status) -> JSONResponse({error_code:'session_messages_unavailable', status}, status_code=status) — status-preserving."
|
||||
steps: "Open client_factory() client; await get_session_messages(client, session_id); return 200. Except SessionApiFailed -> status-preserving envelope."
|
||||
flexibility: "prescriptive"
|
||||
|
||||
- name: "_session_bifrost_endpoint"
|
||||
signature: "async _session_bifrost_endpoint(request: Request) -> JSONResponse"
|
||||
description: "GET /api/sessions/{session_id}/bifrost — proxy admin-scoped Bifrost dispatch state."
|
||||
@@ -95,6 +106,14 @@ functions:
|
||||
- "POST-002: a scheduled poll no-ops if a NEW turn has started (state.turnId truthy) or already settled — no refresh of a stale agent, no unbounded polling."
|
||||
flexibility: "open"
|
||||
|
||||
- name: "loadTranscript (index.html)"
|
||||
signature: "async loadTranscript(sessionId) -> void"
|
||||
description: "On session open, GET /api/sessions/{id}/messages and render each EXISTING turn into #transcript — notably a #347 authored first-message seeded at create-time (which lives in the ledger, not the live turn stream, so without this the transcript is blank until the user speaks)."
|
||||
postconditions:
|
||||
- "POST-001: assistant items render as a .response .md-body bubble via markdownSafe(content) (escape-first whitelist, same path as appendResponse); user items render as a .prompt-echo via textContent — no upstream content reaches innerHTML unescaped (INV-004)."
|
||||
- "POST-002: any non-200, fetch error, or parse error is swallowed (best-effort) — a blank transcript is acceptable; opening the workspace is never blocked."
|
||||
flexibility: "prescriptive"
|
||||
|
||||
- name: "web pane renderers (index.html: renderToolsInventory / renderBifrostState / openAdminEvents)"
|
||||
signature: "renderToolsInventory(inv) ; renderBifrostState(b) ; openAdminEvents(sessionId)"
|
||||
description: "Render the three new surfaces; all content escaped (INV-004)."
|
||||
|
||||
Reference in New Issue
Block a user