Skip to content

trading_agent.terminal.widgets.request_dock

The dock above the message box that holds the desk's pending question, plan or permission request.

It shows one request at a time, permission requests first because they lapse, with "1 of N waiting for you" when more are waiting. The dock never takes the focus by itself: the user presses Tab to answer and Escape to go back, so typing meant for the message box can never answer a request, and Enter can never allow a tool call by accident. A card stays in place while its request is still first, so a half-written answer is not lost when the list is read again.

Typical usage example:

dock = RequestDock(gateway) dock.show(pending_requests)

RequestDock

RequestDock(gateway)

Bases: VerticalScroll

The request dock; hidden while nothing waits.

Creates the dock, hidden and empty.

Parameters:

Name Type Description Default
gateway GatewayClient

The gateway, which the cards send answers to.

required
Source code in src/trading_agent/terminal/widgets/request_dock.py
def __init__(self, gateway: gateway_client.GatewayClient):
    """Creates the dock, hidden and empty.

    Args:
        gateway (gateway_client.GatewayClient): The gateway, which the cards send answers to.
    """
    super().__init__(id='request-dock')
    self._gateway = gateway
    self._count = widgets.Static('', classes='request-count')
    self._card: Any = None

Answered

Bases: Message

The shown request was answered, decided or dismissed.

Left

Bases: Message

The user pressed Escape on a card to go back to the message box.

compose

compose()

Builds the dock's count line.

Yields:

Type Description
Widget

The count line.

Source code in src/trading_agent/terminal/widgets/request_dock.py
def compose(self):
    """Builds the dock's count line.

    Yields:
        Widget: The count line.
    """
    yield self._count

on_mount

on_mount()

Hides the dock until a request waits.

Source code in src/trading_agent/terminal/widgets/request_dock.py
def on_mount(self) -> None:
    """Hides the dock until a request waits."""
    self.display = False

shown_request_id

shown_request_id()

The request the dock shows.

Returns:

Type Description
str | None

Its id, or None when the dock is empty.

Source code in src/trading_agent/terminal/widgets/request_dock.py
def shown_request_id(self) -> str | None:
    """The request the dock shows.

    Returns:
        str | None: Its id, or None when the dock is empty.
    """
    if self._card is None:
        return None
    return self._card.request_id

focus_card

focus_card()

Puts the focus on the shown card.

Returns:

Type Description
bool

True when there is a card to focus.

Source code in src/trading_agent/terminal/widgets/request_dock.py
def focus_card(self) -> bool:
    """Puts the focus on the shown card.

    Returns:
        bool: True when there is a card to focus.
    """
    if self._card is None:
        return False
    self._card.focus_card()
    return True

show

show(requests)

Shows the first waiting request, permission requests first.

Parameters:

Name Type Description Default
requests list[dict[str, Any]]

The desk's pending requests.

required

Returns:

Type Description
bool

True when a different request is now shown, so the screen can move the focus to it.

Source code in src/trading_agent/terminal/widgets/request_dock.py
def show(self, requests: list[dict[str, Any]]) -> bool:
    """Shows the first waiting request, permission requests first.

    Args:
        requests (list[dict[str, Any]]): The desk's pending requests.

    Returns:
        bool: True when a different request is now shown, so the screen can move the focus to it.
    """
    waiting = []
    for request in requests:
        if request.get('kind') == 'permission':
            waiting.append(request)
    for request in requests:
        if request.get('kind') != 'permission':
            waiting.append(request)
    self.display = bool(waiting)
    count = ''
    if len(waiting) > 1:
        count = f'1 of {len(waiting)} waiting for you · '
    self._count.update(
        Content.from_markup(
            '[dim]$count tab to answer · esc to go back to the message box[/dim]',
            count=count,
        )
    )
    if not waiting:
        changed = self._card is not None
        self._remove_card()
        return changed
    first = waiting[0]
    if (
        self._card is not None
        and self._card.request_id == first['request_id']
    ):
        return False
    self._remove_card()
    self._card = self._new_card(first)
    self.mount(self._card)
    return True

on_question_card_done

on_question_card_done(event)

Passes on that the questions were answered.

Parameters:

Name Type Description Default
event Done

The notice.

required
Source code in src/trading_agent/terminal/widgets/request_dock.py
def on_question_card_done(
    self, event: question_card.QuestionCard.Done
) -> None:
    """Passes on that the questions were answered.

    Args:
        event (question_card.QuestionCard.Done): The notice.
    """
    event.stop()
    self.post_message(self.Answered())

on_plan_card_done

on_plan_card_done(event)

Passes on that the plan was decided.

Parameters:

Name Type Description Default
event Done

The notice.

required
Source code in src/trading_agent/terminal/widgets/request_dock.py
def on_plan_card_done(self, event: plan_card.PlanCard.Done) -> None:
    """Passes on that the plan was decided.

    Args:
        event (plan_card.PlanCard.Done): The notice.
    """
    event.stop()
    self.post_message(self.Answered())

on_permission_card_done

on_permission_card_done(event)

Passes on that the permission was decided.

Parameters:

Name Type Description Default
event Done

The notice.

required
Source code in src/trading_agent/terminal/widgets/request_dock.py
def on_permission_card_done(
    self, event: permission_card.PermissionCard.Done
) -> None:
    """Passes on that the permission was decided.

    Args:
        event (permission_card.PermissionCard.Done): The notice.
    """
    event.stop()
    self.post_message(self.Answered())

key_escape

key_escape()

Leaves the card for the message box.

Source code in src/trading_agent/terminal/widgets/request_dock.py
def key_escape(self) -> None:
    """Leaves the card for the message box."""
    self.post_message(self.Left())