Skip to content

Add AgentConversationEntry and friends.#10167

Merged
zachbai merged 2 commits intomasterfrom
zb/agent-conversation-entry
May 5, 2026
Merged

Add AgentConversationEntry and friends.#10167
zachbai merged 2 commits intomasterfrom
zb/agent-conversation-entry

Conversation

@zachbai
Copy link
Copy Markdown
Contributor

@zachbai zachbai commented May 5, 2026

Adds a new AgentConversationEntry abstraction designed to replace ConversationOrTask.

ConversationOrTask requires a bifurcation between local and cloud conversations that is prone to skew. Downstream of ConversationOrTask, navigation policy (e.g. should clicking this item open a cloud mode pane? or open a cloud transcript view?) and other behaviors are computed and cached. With cloud conversation continuation and local->cloud handoff, it makes less sense to do this bifurcation up front, and instead introduce a unified abstraction that broadly represents an AI conversation, whether its a local conversation started by the user, a cloud ambient agent conversation, or a conversation for which we only currently have server metadata (e.g. have not actually fetched transcript contents from storage).

This refactor will make it easier to implement correct behavior for UI that depends on a conversation's provenance.

This is the first PR in a 4 pr stack, introducing the abstraction itself - but does not hook it into anythinganything. There is 1 master tech spec and 4 more granular specs for each incremental PR.

@cla-bot cla-bot Bot added the cla-signed label May 5, 2026
Copy link
Copy Markdown
Contributor Author

zachbai commented May 5, 2026

This stack of pull requests is managed by Graphite. Learn more about stacking.

@zachbai zachbai requested a review from harryalbert May 5, 2026 18:06
@zachbai zachbai marked this pull request as ready for review May 5, 2026 18:06
@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 5, 2026

@zachbai

I'm starting a first review of this pull request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

This PR introduces the AgentConversationEntry projection and supporting tests/specs for a staged migration away from ConversationOrTask. The schema is directionally aligned with the stated goal, but the builder currently preserves two of the gaps it is intended to remove.

Concerns

  • Task-backed entries compute capabilities.can_open through the legacy task-only action path, so entries that successfully attach a local conversation or server token can still be marked unopenable.
  • The metadata-only pass uses a helper that filters out ambient-agent metadata, so cloud ambient conversations without a current task row are omitted from the new projection.

Found: 0 critical, 2 important, 0 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

has_ambient_run: true,
},
capabilities: AgentConversationCapabilities {
can_open: item.get_open_action(None, app).is_some(),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [IMPORTANT] This reuses the legacy task-only open action, so a task entry that attached local_conversation_id by run id but lacks a task conversation_id/session is still marked unopenable; compute this from the entry identity instead.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This gets changed in a later PR in the stack.

entries.push(entry);
}

for metadata in history_model.get_local_conversations_metadata() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [IMPORTANT] get_local_conversations_metadata() excludes metadata with ambient_agent_task_id, so cloud ambient conversations without a current task row are dropped from get_entries; add an ambient-metadata pass or iterate all metadata and only skip child conversations explicitly.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is intended for this increment.

Copy link
Copy Markdown
Contributor

@harryalbert harryalbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

awesome. Had some small comments and questions but overally LGTM

Comment thread specs/APP-4382/TECH.md
`AgentConversationsModel` currently exposes `ConversationOrTask`, a wrapper over either `AmbientAgentTask` or `ConversationMetadata`, to list, details, filtering, and navigation surfaces in `app/src/ai/agent_conversations_model.rs (399-813)`. The wrapper centralizes several display helpers, but still encodes important behavior as “task vs conversation” decisions. The most problematic example is `link_preference()` and `get_open_action()` in `app/src/ai/agent_conversations_model.rs (624-813)`: task rows choose between session, conversation transcript, or no action from cached task fields, while local conversation rows restore/navigate from `ConversationNavigationData`.
The model also intentionally hides local conversation rows when a task appears to represent the same logical run in `app/src/ai/agent_conversations_model.rs (1382-1497)`. That shadowing is useful for preserving cloud-run affordances, but it means the visible task row can discard better local-conversation navigation data. A task row with a stale or incomplete `session_id`, `session_link`, `conversation_id`, or `is_sandbox_running` can therefore be unopenable even when the hidden conversation representation is restorable.
The underlying sources are already separate. `BlocklistAIHistoryModel` owns loaded `AIConversation` contents in `conversations_by_id` and lightweight historical/cloud metadata in `all_conversations_metadata` in `app/src/ai/blocklist/history_model.rs (49-214)`. Cloud metadata can exist without a loaded conversation via `AIConversationMetadata` and `merge_cloud_conversation_metadata` in `app/src/ai/blocklist/history_model/conversation_loader.rs (334-453)`, while `load_conversation_data` loads content only on demand in `app/src/ai/blocklist/history_model/conversation_loader.rs (145-236)`. `ActiveAgentViewsModel` separately tracks which local conversations and ambient sessions are currently open in `app/src/ai/active_agent_views_model.rs (45-531)`.
This migration introduces a projection-layer `AgentConversationEntry` for list/navigation/detail surfaces. It should not replace `AIConversation`, `BlocklistAIHistoryModel`, or transcript content APIs. Its job is to merge provenance and lightweight display data into one logical row so UI surfaces no longer choose between task and conversation representations.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

amazing

Comment thread specs/APP-4382/TECH.md
pub ambient_run_id: Option<AmbientAgentTaskId>,
pub server_conversation_token: Option<ServerConversationToken>,
pub parent_conversation_id: Option<AIConversationId>,
pub parent_run_id: Option<AmbientAgentTaskId>,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this for orchestration purposes?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea


/// Availability flags for the source data that contributed to an entry.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct AgentConversationBacking {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, but I don't think this struct naming is super clear

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed to AgentConversationBackingData.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should. these increments maybe be added with their respective branches? I'm skipping reviewing increments 2 through 4 just because they're not implemented yet (but I can review if you think it makes more sense to cover it all up-front)

- `AgentConversationProvenance`
- `AgentConversationBacking`
- `AgentConversationCapabilities`
Add an internal builder that consumes current model state and `AppContext`. The builder should:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you have an intuition for how intensive this operation is/how often it'll happen? I think keeping this function pure would be really nice, but wondering if we should do some caching in case it's called very frequently and is expensive

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall be addressed in follow ups

@zachbai zachbai force-pushed the zb/agent-conversation-entry branch from aad9222 to bc6b7ef Compare May 5, 2026 19:38
@zachbai zachbai force-pushed the zb/agent-conversation-entry branch from b6a5b47 to ab1fa14 Compare May 5, 2026 23:26
@zachbai zachbai merged commit 27d8ef6 into master May 5, 2026
30 checks passed
@zachbai zachbai deleted the zb/agent-conversation-entry branch May 5, 2026 23:51
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.

2 participants