New-conversation "+" button: conv is created but never appears in sidebar or opens #6
Labels
No labels
prio_critical
prio_low
type_bug
type_contact
type_issue
type_lead
type_question
type_story
type_task
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lhumina_code/hero_agent#6
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Clicking the
+button in the Chat sidebar does send aPOST /api/conversationsrequest and the conversation is created on the server, but:Repro
Chattab.+button next toConversations.POST /api/conversations→ 200 with{id, title, ...}.No conversations yet.Verified live against the running server:
Root cause
Bug 1 — list endpoint shape mismatch
GET /api/conversationsreturns an object, but the frontend expects a bare array.Server (
crates/hero_agent_server/src/routes.rs:808-810):Frontend (
crates/hero_agent_ui/static/js/dashboard.js:106-111):Array.isArray({conversations: []})isfalse, so the sidebar always renders "No conversations yet" regardless of how many conversations exist on the server. This is why the newly-created conversation never appears aftercreateConversationcallsloadConversations().Note: the sibling endpoint
GET /api/conversations/{id}/messagesreturns a bare array (crates/hero_agent_server/src/routes.rs:877), soloadConversationMessagesworks correctly. The list endpoint is the inconsistent one.Bug 2 — createConversation doesn't visibly switch context
createConversation(crates/hero_agent_ui/static/js/dashboard.js:136-152) setscurrentConversationIdand callsloadConversationMessages(data.id), but:#chat-conversation-label(onlyselectConversationdoes that, line 131).loadConversationMessagesjust renders the same welcome state that was already there.Net effect: nothing in the chat area visibly changes when the new conv is created, so it looks like the click did nothing.
Suggested fixes
Bug 1 — pick one:
list_conversationstoJson(serde_json::json!(conversations))(bare array — matchesget_conversation_messagesstyle).var convs = (await api('conversations')).conversations || [].Server-side fix is preferred for consistency with the rest of the API.
Bug 2: in
createConversation, after the POST succeeds, just delegate toselectConversation(data.id)so the label, sidebar highlight, and message pane all update through one path.Affected files
crates/hero_agent_server/src/routes.rs(list_conversations)crates/hero_agent_ui/static/js/dashboard.js(loadConversations,createConversation)Implementation Spec: Issue #6
New-conversation
+button: conv is created but never appears in sidebar or opensObjective
Fix two regressions in the Chat sidebar so that:
GET /api/conversationsis rendered in the sidebar (not always shown as "No conversations yet").+button creates a new conversation AND visibly switches the chat UI to that new conversation (sidebar highlight, label, and message pane all update through one path).Requirements
GET /api/conversationsMUST return a JSON array of conversation summaries (consistent withGET /api/conversations/:id/messages, which already returns a bare array).openrpc.json) foragent.conversations.listand the matching schema MUST be updated to advertise the array shape.openrpc.client.generated.rs) MUST be regenerated to match the new schema.{ "conversations": [...] }shape MUST be updated to expect the bare-array shape.POST /api/conversations, the frontend MUST callselectConversation(newId)so the sidebar highlight, the#chat-conversation-label, and the message pane all reflect the new conversation through a single code path.loadConversationMessages's empty-array branch).Files to Modify
1.
crates/hero_agent_server/src/routes.rslist_conversations(lines 857-878): change to return a bare array instead of{"conversations": ...}."type": "array", so it stays consistent (verify after edit).2.
crates/hero_agent_server/openrpc.jsonagent.conversations.listmethod (lines 266-276): changeresult.schema.$reffromConversationListResponseto an inline array ofConversationSummary.ConversationListResponseschema (lines 825-836): remove the now-orphan schema.3.
crates/hero_agent_server/openrpc.client.generated.rsopenrpc.json. Regenerate after step 2. Expected diff:ConversationListResponsestruct disappears;AgentConversationsListOutputbecomes a bareVec<ConversationSummary>.4.
crates/hero_agent_ui/static/js/dashboard.jsloadConversations(lines 104-127): already correctly checksArray.isArray(convs). After server fix, works without modification.createConversation(lines 136-152): afterdata.idis received, replace the manualcurrentConversationId = data.id; loadConversations(); loadConversationMessages(data.id);block withselectConversation(data.id)so label, sidebar highlight, and message pane all update through one path.5.
scripts/smoke-test.shif echo "$resp" | grep -q "conversations"will no longer match a bare array. Update to assert the response starts with[, matching the existing/api/jobsassertion pattern.6.
tests/browser/chat_ui_test.mdStep-by-Step Implementation Plan
Step 1 — Change
list_conversationsto return a bare arraycrates/hero_agent_server/src/routes.rsJson(serde_json::json!({ "conversations": conversations }))withJson(serde_json::json!(conversations)).Step 2 — Update
openrpc.jsonschema foragent.conversations.listcrates/hero_agent_server/openrpc.json{"type":"array","items":{"$ref":"#/components/schemas/ConversationSummary"}}.ConversationListResponsecomponent schema.Step 3 — Regenerate the OpenRPC client inspection file
crates/hero_agent_server/openrpc.client.generated.rshero_agent_serverto refresh the inspection copy via theopenrpc_client!macro.Step 4 — Wire
createConversationthroughselectConversationcrates/hero_agent_ui/static/js/dashboard.jscreateConversation, afterif (data.id) {, replace the body with a single call:selectConversation(data.id);Step 5 — Update smoke-test assertion
scripts/smoke-test.shgrep -q "conversations"to assert array shape ([), update messages to mention "array".Step 6 — Tighten chat UI test documentation
tests/browser/chat_ui_test.mdStep 7 — Build, run smoke tests, and manual repro
scripts/smoke-test.shto verify the new assertion holds.+, confirm sidebar lists/highlights it, label updates, chat area shows welcome state.Acceptance Criteria
GET /api/conversationsreturns a JSON array (bare[...]), not an object.openrpc.jsonagree: result isarray.openrpc.jsonno longer referencesConversationListResponse; the orphan schema is removed.openrpc.client.generated.rsis regenerated and reflects the new array shape.+in the Chat sidebar creates a conversation AND immediately:#chat-conversation-labelto the new conversation ID,loadConversationscorrectly renders existing conversations on dashboard load.scripts/smoke-test.shpasses with the updated assertion.scripts/browser-mcp-test.shtest 4.5 and test 6.2 still pass.Notes
Risks / consumers
ConversationListResponseandAgentConversationsListOutputwill change shape. A repo-wide grep shows NO consumers outside the generated file itself — inspection-only. Safe.agent.conversations.listJSON-RPC method: the inline OpenRPC spec at routes.rs:119-123 already advertises"type": "array"(already inconsistent with the REST handler today). The dispatcher does NOT actually implement this method — calls fall through to "Method not found". No live RPC consumer depends on the wire shape today. Safe."conversations"substring).conversations|\[, so it keeps passing. Optional cleanup only.Why server-side fix is correct
GET /api/conversations/:id/messages, which already returns a bare array.Edge case
selectConversation(id)usesidas the label text. For a brand-new conv, the label shows the UUID. Friendlier labels (e.g.data.title) are an unrelated UX improvement and out of scope.Test Results
Command:
cargo test --workspaceAll tests passed across the workspace (hero_agent: 76, hero_agent integration: 2, hero_agent_server: 8).
Implementation Summary
All steps from the approved spec have been completed on branch
development_fix_chat_sidebar_create_conv.Files modified
crates/hero_agent_server/src/routes.rs—list_conversationsnow returns a bare JSON array instead of{"conversations": [...]}.crates/hero_agent_server/openrpc.json—agent.conversations.listresult schema changed to an inline array ofConversationSummary; the orphanConversationListResponseschema was removed. JSON validates cleanly.crates/hero_agent_server/openrpc.client.generated.rs— regenerated by theopenrpc_client!macro.ConversationListResponseis gone;AgentConversationsListOutputis now a#[serde(transparent)]newtype wrappingVec<ConversationSummary>.crates/hero_agent_ui/static/js/dashboard.js—createConversationnow delegates toselectConversation(data.id)after the POST succeeds, so the sidebar highlight,#chat-conversation-label, and message pane all update through one path.scripts/smoke-test.sh—/api/conversationsassertion updated to expect a JSON array, mirroring the/api/jobspattern.tests/browser/chat_ui_test.md— test 5.1 expected-result tightened to "Array of conversation summaries".Test results
cargo test --workspace— 86 passed, 0 failed, 0 ignored. Workspace builds cleanly.Notes
"type": "array", so it now agrees with the REST handler and the staticopenrpc.json.ConversationListResponseoutside the auto-generated file.agent.conversations.listover JSON-RPC today, so no live RPC consumer was affected by the wire-shape change.+button is still recommended once the branch is built and running locally to confirm sidebar/label/message-pane all update visibly.Status update
The two bugs in this issue (sidebar list shape mismatch +
+button not switching context) are both fixed inhero_agentand tests pass. While verifying end-to-end against the running services, three additional layers of breakage were found that block the+button from working in deployment:hero_agentcreateConversation->selectConversationhero_agentOSIS_URLdefault port6666(router is on9988)hero_agenthero_osisbuilt without theaifeature (gated out ofall-domainsas "still under development") sohero_osis_aiRPC server never spawnshero_osis/rpc/{context}URL but per-domain servers only accept/rpc-> 404 on every callhero_rpcThe
hero_agentPR is correct and self-consistent — the fixes will work end-to-end once #4 is enabled and #10 is resolved. Sub-issue #10 has full repro and proposed fix options.End-to-end verified
The
+button now works fully on this machine. Final state:hero_agentcreateConversation->selectConversationhero_agentOSIS_URLdefault port6666->9988hero_agentOSIS_URLdefault path -> router root (SDK appends/hero_osis_<domain>/rpcitself)hero_agentCargo.lockbump forhero_rpc91c30ef->38a0929(picks up the SDK URL fix that already shipped)hero_agentaienabled inhero_osis_serverall-domainssohero_osis_ai/rpc.sockis spawnedhero_osisSub-issue #10 was closed — the SDK URL pattern was already corrected in
hero_rpc development.hero_agentjust needed a lock bump andOSIS_URLadjustment to pick it up.Verification:
Opening the
hero_agentPR next.Test Results (post-fix)
Command:
cargo test --workspaceAll tests pass after the lock bump and
OSIS_URLchange.