Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions src/toad/conversation_kind.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from agent_comms.declared_family import DeclaredFamily
from agent_comms.comms import Comms
from agent_comms.message_page import MessagePage
from toad.widgets.session_details import SessionDetails


class ConversationKind(DeclaredFamily, affix="Conversation"):
Expand Down Expand Up @@ -94,8 +93,8 @@ async def status_text(cls, comms, target, *, read_only: bool) -> str: ...

@classmethod
@abstractmethod
def activity_widgets(cls) -> tuple[type[SessionDetails], ...]:
"""Declare widget classes; the composing view owns their instances."""
def compose_activity(cls, view):
"""Select the view's explicit composition for this conversation kind."""
...

@classmethod
Expand Down Expand Up @@ -153,7 +152,7 @@ def current_identity(cls, page: MessagePage) -> tuple | None:
)

@classmethod
def activity_widgets(cls) -> tuple[type[SessionDetails], ...]:
def compose_activity(cls, view):
return ()

@classmethod
Expand Down Expand Up @@ -271,8 +270,8 @@ def label(cls, target: str) -> str:
return f"@{target}"

@classmethod
def activity_widgets(cls) -> tuple[type[SessionDetails], ...]:
return (SessionDetails,)
def compose_activity(cls, view):
return view.compose_dm_activity()

@classmethod
async def update_mentions(cls, view, comms) -> None:
Expand Down
16 changes: 10 additions & 6 deletions src/toad/widgets/comms_chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
)
from toad.widgets.flash import Flash
from toad.widgets.native_history import NativeHistory
from toad.widgets.session_details import SessionDetails
from toad.widgets.prompt import Prompt
from toad.screens.session_view import SessionView
from toad.command_catalog import CommandCatalog
Expand Down Expand Up @@ -127,12 +128,7 @@ def compose(self) -> ComposeResult:
yield ChannelActivityTray(id="comms-activity")
yield Flash()
with containers.Vertical(id="prompt-stack"):
for activity_type in self.conversation_kind.activity_widgets():
self.thread_activity = activity_type(
history=NativeHistory(),
status_source=lambda: self.thread_activity.row,
)
yield self.thread_activity
yield from self.conversation_kind.compose_activity(self)
yield self.throbber
yield self.conversation_kind.prompt(self.target).data_bind(
project_path=Conversation.project_path,
Expand All @@ -142,6 +138,14 @@ def compose(self) -> ComposeResult:
status=Conversation.status,
)

def compose_dm_activity(self) -> ComposeResult:
"""The direct-message view owns its peer's status widget."""
self.thread_activity = SessionDetails(
history=NativeHistory(),
status_source=lambda: self.thread_activity.row,
)
yield self.thread_activity

async def initialize_view(self) -> None:
# Reuse the canonical core service already shared by tab sidebars and
# transcript readers. Its revision-aware caches remain model-owned.
Expand Down