Skip to content
Merged
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
2 changes: 1 addition & 1 deletion src/toad/acp/transcript_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ async def read(self, request: AwaitedRead):
observed = await self.access.preparation.run_thread(
self.access.observation.observed
)
return await observed.process.read(request)
return await observed.read(request)

async def service(self, root):
return await self.access.preparation.run_thread(
Expand Down
16 changes: 15 additions & 1 deletion src/toad/comms_root.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import asyncio
import threading
from abc import ABC, abstractmethod
from collections.abc import Callable, Mapping
from dataclasses import dataclass, field
from functools import partial
Expand All @@ -32,6 +33,7 @@
from agent_comms.route_selection import RouteSelection
from agent_comms.root_runtime import RootRuntime
from agent_comms.ui_model.observation import (
AwaitedRead,
CommanderHudObserved,
CommanderHudUnreadable,
ObserveCommanderHud,
Expand Down Expand Up @@ -96,7 +98,7 @@ class UnselectedRoute:


@dataclass(frozen=True, kw_only=True)
class Observation:
class Observation(ABC):
access: CoordinationAccess = field(compare=False)
subscriptions: ResourceRelease = field(default_factory=ResourceRelease, compare=False)
# View updates end before the views close; `subscriptions` retires the observation after them.
Expand All @@ -105,6 +107,9 @@ class Observation:
def observed(self):
return self

@abstractmethod
async def read(self, request: AwaitedRead) -> object: ...

def is_current(self) -> bool:
return self is self.access.observation

Expand Down Expand Up @@ -163,12 +168,18 @@ class NotObserving(Observation):
def observed(self):
return self.access.open_current()

async def read(self, request: AwaitedRead) -> object:
return await self.observed().read(request)


@dataclass(frozen=True, eq=False)
class FailedObservation(Observation):
error: Exception = field(compare=False, repr=False)
selection: RouteSelection | UnselectedRoute

async def read(self, request: AwaitedRead) -> object:
raise self.error

def __eq__(self, other: object) -> bool:
# Exceptions declare their type, constructor fields and extra state through
# reconstruction; OSError includes filenames that are absent from args.
Expand Down Expand Up @@ -219,6 +230,9 @@ class Observing(Observation):
sidebar: SidebarModel = field()
process: ObservationProcess = field(compare=False)

async def read(self, request: AwaitedRead) -> object:
return await self.process.read(request)

def observes(self, root: str | Path) -> bool:
return self.service.root == Path(root).resolve()

Expand Down
Loading