Skip to content

Fix APP-4853: restore subagent chips and agent names after session reopen#13664

Draft
seemeroland wants to merge 1 commit into
masterfrom
oz-agent/APP-4853
Draft

Fix APP-4853: restore subagent chips and agent names after session reopen#13664
seemeroland wants to merge 1 commit into
masterfrom
oz-agent/APP-4853

Conversation

@seemeroland

Copy link
Copy Markdown
Contributor

Description

Fixes APP-4853: subagent chips are missing and "Unknown agent" is displayed when reopening a session that used orchestrated child agents.

Root Cause

The TUI startup speedup (PR #13449 / commit 0ac6f59) changed the app to load agent_conversations metadata-only at startup — agent_conversation.tasks is always empty. The initialize_historical_conversations eager child-hydration path was updated to call load_conversation_from_db(&conversation_id) when tasks.is_empty(), but without a fallback: if the read-only DB connection cannot be established (or any read error occurs), the call returns None and the child is never inserted into conversations_by_id.

That missing insertion caused two visible regressions after an app restart:

  1. Missing pill bar chips: OrchestrationPillBar::pill_specs filters descendant IDs through history.conversation(&id), so unhydrated children produce an empty pill list → no chips.
  2. "Unknown agent" in transcripts: participant_for_agent_id resolves the agent ID to a conversation, then looks it up in conversations_by_id. When that lookup returns None, it falls back to OrchestrationParticipant::unknown_child().

The pre-regression code (QUALITY-768 / #11722) always called convert_persisted_conversation_to_ai_conversation_with_metadata(agent_conversation.clone()) directly, which synthesises a minimal AIConversation from conversation_data (task_id/run_id, agent_name, parent linkage) even when tasks is empty. The TUI speedup PR replaced this direct call with a DB load and dropped the fallback.

Fix

In conversation_loader.rs, when agent_conversation.tasks.is_empty(), try load_conversation_from_db first (to get full task data for rich display), and fall back to convert_persisted_conversation_to_ai_conversation_with_metadata if the DB load fails. The fallback synthesises a minimal AIConversation carrying the correct task_id, agent_name, and parent linkage — exactly what the pill bar and name resolution need.

A new regression test …with_empty_tasks exercises this production code path (tasks == []) to pin the fallback behaviour. The existing test test_initialize_historical_conversations_eagerly_hydrates_orchestration_children passed non-empty tasks, so it always took the direct-conversion branch and missed the regression.

Linked Issue

  • Fixes APP-4853

  • The linked issue is labeled ready-to-spec or ready-to-implement.

  • Where appropriate, screenshots or a short video of the implementation are included below (especially for user-visible or UI changes).

Testing

Added test_initialize_historical_conversations_eagerly_hydrates_orchestration_children_with_empty_tasks which:

  • Creates conversations with tasks: vec![] (the production startup shape after TUI speedup)
  • Verifies the child ends up in conversations_by_id via the fallback
  • Verifies agent_name and run_id are correctly restored
  • Verifies children_by_parent and agent_id_to_conversation_id indices are populated

cargo check --tests and cargo clippy --tests -- -D warnings both pass.

  • I have manually tested my changes locally with ./script/run

Agent Mode

  • Warp Agent Mode - This PR was created via Warp's AI Agent Mode

CHANGELOG-BUG-FIX: Fixed subagent chips missing and "Unknown agent" shown when reopening a session that used orchestrated child agents.

Conversation: https://staging.warp.dev/conversation/4e5df828-99f9-412c-bdf9-b73408bf1141
Run: https://oz.staging.warp.dev/runs/019f5cde-754c-7ebb-bd3e-f487495818ca

This PR was generated with Oz.

The TUI startup speedup (commit 0ac6f59) changed startup to deliver
conversations with empty task lists, then load full task payloads lazily
from the local DB on demand.  The eager orchestration-child hydration path
in `initialize_historical_conversations` was updated to call
`load_conversation_from_db` when `agent_conversation.tasks.is_empty()`,
but without a fallback: if the RO DB connection cannot be established (or
any other read error occurs), the function returns `None` and the child
is never inserted into `conversations_by_id`.

That missing insertion caused the regression:

- `OrchestrationPillBar::pill_specs` filters descendant IDs through
  `history.conversation(&id)`, so unhydrated children produce an empty
  pill list → no chips at the top of the conversation.
- `participant_for_agent_id` resolves an agent ID to a conversation, then
  looks it up in `conversations_by_id`.  When the lookup fails it falls
  back to `OrchestrationParticipant::unknown_child()` → "Unknown agent"
  in send_message / messages_received transcript rows.

The fix: when `agent_conversation.tasks.is_empty()`, try
`load_conversation_from_db` first (to get full task data for rich display)
and fall back to `convert_persisted_conversation_to_ai_conversation_with_metadata`
if that fails.  The fallback synthesizes a minimal `AIConversation` from
the `conversation_data` column already in memory — same as the pre-TUI-
speedup code path in QUALITY-768.  The synthesized conversation carries the
correct `task_id` (run_id), `agent_name`, and parent linkage, which is all
the pill bar and name resolution need.

A new test, `…with_empty_tasks`, exercises the production code path
(tasks == []) to pin the fallback behaviour.  The existing test
`test_initialize_historical_conversations_eagerly_hydrates_orchestration_children`
used non-empty tasks, so it took the direct-conversion branch and missed
the regression entirely.

CHANGELOG-BUG-FIX: Fixed subagent chips being missing and 'Unknown agent' displayed when reopening a session that used orchestrated subagents.

Co-Authored-By: Oz <oz-agent@warp.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant