4.8 KiB
Increment 2: navigation resolver and conversation list migration
Context
The conversation list currently caches ConversationOrTaskIds in ConversationListViewModel and filters out task rows whose get_session_status() is not available in app/src/workspace/view/conversation_list/view_model.rs (31-183). Rendering checks conversation.get_open_action(None, app) for cursor/clickability in app/src/workspace/view/conversation_list/item.rs (377-407), and activation recomputes the action in app/src/workspace/view/conversation_list/view.rs (535-548).
This can fail when a visible task row shadows a local conversation row but lacks fresh session/conversation fields. Increment 2 replaces that path with normalized entries and a dynamic navigation resolver.
Proposed changes
Add an entry navigation resolver near AgentConversationsModel, for example:
pub enum AgentConversationNavigationSubject {
Entry(AgentConversationEntryId),
ServerToken(ServerConversationToken),
}
pub fn resolve_open_action(
subject: AgentConversationNavigationSubject,
restore_layout: Option<RestoreConversationLayout>,
app: &AppContext,
) -> Option<WorkspaceAction>
The resolver should re-read current state at click time. For Entry, resolve the latest AgentConversationEntry or equivalent identity refs from AgentConversationsModel. For ServerToken, resolve through BlocklistAIHistoryModel::find_conversation_id_by_server_token and fall back to transcript loading where the caller supports it.
Default resolver order for listed entries:
- if an ambient run id is attached and
ActiveAgentViewsModelhas an open ambient session, focus/open that tab; - if a local conversation id is attached and currently open, focus it;
- if the ambient run has an active execution with parseable
session_id, open ambient shared session; - if a local conversation id is attached, restore/navigate to the local conversation with the requested layout;
- if a server token is attached, open the cloud transcript viewer;
- otherwise return
None. The resolver may initially return existingWorkspaceActionvariants. If focusing an already-open ambient session still relies onWorkspaceAction::OpenAmbientAgentSessionplus workspace fallback, keep that behavior but ensure the resolver prefers the open ambient identity before transcript fallback. MigrateConversationListViewModelto cacheAgentConversationEntryIdandConversationEntry { id, highlight_indices }. It should source entries fromAgentConversationsModel::get_entrieswith the same personal/all status defaults currently used by the conversation list. Do not filter out completed cloud entries simply becauseget_session_status()is unavailable; filter based on normalizedcapabilities.can_open. Migraterender_itemprops to takeAgentConversationEntryor a lightweight view data struct instead ofConversationOrTask. The leading icon can continue to use existing helper behavior if Increment 1 exposes enough display data; otherwise add a normalized icon helper that consumesAgentConversationEntry. Migrate click/Enter to callresolve_open_action(Entry(entry.id), None, ctx).
Testing and validation
Add unit tests for the resolver:
- task row with matching local conversation but missing task
conversation_idrestores local conversation; - task row with
session_linkbut no parseablesession_iddoes not claim session-open capability and falls back to local/server token when available; - active ambient session is preferred over transcript opening;
- active local conversation is preferred over restoring into a new tab;
- server-token-only navigation can open transcript when no local id is known. Add conversation-list view-model tests if existing harness support is sufficient:
- cloud metadata-only entries appear when openable by token;
- stale/unavailable session status does not hide a restorable local conversation attached to a task;
- search still matches titles from normalized display data. Manual validation:
- open a local cloud-mode conversation that also has a task row and verify clicking the list item focuses/restores the local conversation even if the task has no active session;
- open a live cloud task and verify clicking the list item focuses/joins the live session;
- open a completed cloud run and verify clicking opens/restores transcript/local conversation consistently.
Risks and mitigations
Workspace action gaps
The existing workspace actions may not express “focus open ambient session by task id” directly. If needed, add a small focused action or keep using OpenAmbientAgentSession with the workspace’s find_tab_with_ambient_agent_conversation fallback.
UI state churn
Changing list item IDs can reset hover/selection state. Use AgentConversationEntryId as a stable key and preserve row state maps by that key.