Files
galaxy/specs/APP-4382/INCREMENT-2-navigation-and-conversation-list.md

51 lines
4.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Increment 2: navigation resolver and conversation list migration
## Context
The conversation list currently caches `ConversationOrTaskId`s 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:
```rust
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:
1. if an ambient run id is attached and `ActiveAgentViewsModel` has an open ambient session, focus/open that tab;
2. if a local conversation id is attached and currently open, focus it;
3. if the ambient run has an active execution with parseable `session_id`, open ambient shared session;
4. if a local conversation id is attached, restore/navigate to the local conversation with the requested layout;
5. if a server token is attached, open the cloud transcript viewer;
6. otherwise return `None`.
The resolver may initially return existing `WorkspaceAction` variants. If focusing an already-open ambient session still relies on `WorkspaceAction::OpenAmbientAgentSession` plus workspace fallback, keep that behavior but ensure the resolver prefers the open ambient identity before transcript fallback.
Migrate `ConversationListViewModel` to cache `AgentConversationEntryId` and `ConversationEntry { id, highlight_indices }`. It should source entries from `AgentConversationsModel::get_entries` with the same personal/all status defaults currently used by the conversation list. Do not filter out completed cloud entries simply because `get_session_status()` is unavailable; filter based on normalized `capabilities.can_open`.
Migrate `render_item` props to take `AgentConversationEntry` or a lightweight view data struct instead of `ConversationOrTask`. The leading icon can continue to use existing helper behavior if Increment 1 exposes enough display data; otherwise add a normalized icon helper that consumes `AgentConversationEntry`.
Migrate click/Enter to call `resolve_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_id` restores local conversation;
- task row with `session_link` but no parseable `session_id` does 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 workspaces `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.