batrachian-toad 0.5.22__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- batrachian_toad-0.5.22.dist-info/METADATA +197 -0
- batrachian_toad-0.5.22.dist-info/RECORD +120 -0
- batrachian_toad-0.5.22.dist-info/WHEEL +4 -0
- batrachian_toad-0.5.22.dist-info/entry_points.txt +2 -0
- batrachian_toad-0.5.22.dist-info/licenses/LICENSE +661 -0
- toad/__init__.py +46 -0
- toad/__main__.py +4 -0
- toad/_loop.py +86 -0
- toad/about.py +90 -0
- toad/acp/agent.py +671 -0
- toad/acp/api.py +47 -0
- toad/acp/encode_tool_call_id.py +12 -0
- toad/acp/messages.py +138 -0
- toad/acp/prompt.py +54 -0
- toad/acp/protocol.py +426 -0
- toad/agent.py +62 -0
- toad/agent_schema.py +70 -0
- toad/agents.py +45 -0
- toad/ansi/__init__.py +1 -0
- toad/ansi/_ansi.py +1612 -0
- toad/ansi/_ansi_colors.py +264 -0
- toad/ansi/_control_codes.py +37 -0
- toad/ansi/_keys.py +251 -0
- toad/ansi/_sgr_styles.py +64 -0
- toad/ansi/_stream_parser.py +418 -0
- toad/answer.py +22 -0
- toad/app.py +557 -0
- toad/atomic.py +37 -0
- toad/cli.py +257 -0
- toad/code_analyze.py +28 -0
- toad/complete.py +34 -0
- toad/constants.py +58 -0
- toad/conversation_markdown.py +19 -0
- toad/danger.py +371 -0
- toad/data/agents/ampcode.com.toml +51 -0
- toad/data/agents/augmentcode.com.toml +40 -0
- toad/data/agents/claude.com.toml +41 -0
- toad/data/agents/docker.com.toml +59 -0
- toad/data/agents/geminicli.com.toml +28 -0
- toad/data/agents/goose.ai.toml +51 -0
- toad/data/agents/inference.huggingface.co.toml +33 -0
- toad/data/agents/kimi.com.toml +35 -0
- toad/data/agents/openai.com.toml +53 -0
- toad/data/agents/opencode.ai.toml +61 -0
- toad/data/agents/openhands.dev.toml +44 -0
- toad/data/agents/stakpak.dev.toml +61 -0
- toad/data/agents/vibe.mistral.ai.toml +27 -0
- toad/data/agents/vtcode.dev.toml +62 -0
- toad/data/images/frog.png +0 -0
- toad/data/sounds/turn-over.wav +0 -0
- toad/db.py +5 -0
- toad/dec.py +332 -0
- toad/directory.py +234 -0
- toad/directory_watcher.py +96 -0
- toad/fuzzy.py +140 -0
- toad/gist.py +2 -0
- toad/history.py +138 -0
- toad/jsonrpc.py +576 -0
- toad/menus.py +14 -0
- toad/messages.py +74 -0
- toad/option_content.py +51 -0
- toad/os.py +0 -0
- toad/path_complete.py +145 -0
- toad/path_filter.py +124 -0
- toad/paths.py +71 -0
- toad/pill.py +23 -0
- toad/prompt/extract.py +19 -0
- toad/prompt/resource.py +68 -0
- toad/protocol.py +28 -0
- toad/screens/action_modal.py +94 -0
- toad/screens/agent_modal.py +172 -0
- toad/screens/command_edit_modal.py +58 -0
- toad/screens/main.py +192 -0
- toad/screens/permissions.py +390 -0
- toad/screens/permissions.tcss +72 -0
- toad/screens/settings.py +254 -0
- toad/screens/settings.tcss +101 -0
- toad/screens/store.py +476 -0
- toad/screens/store.tcss +261 -0
- toad/settings.py +354 -0
- toad/settings_schema.py +318 -0
- toad/shell.py +263 -0
- toad/shell_read.py +42 -0
- toad/slash_command.py +34 -0
- toad/toad.tcss +752 -0
- toad/version.py +80 -0
- toad/visuals/columns.py +273 -0
- toad/widgets/agent_response.py +79 -0
- toad/widgets/agent_thought.py +41 -0
- toad/widgets/command_pane.py +224 -0
- toad/widgets/condensed_path.py +93 -0
- toad/widgets/conversation.py +1626 -0
- toad/widgets/danger_warning.py +65 -0
- toad/widgets/diff_view.py +709 -0
- toad/widgets/flash.py +81 -0
- toad/widgets/future_text.py +126 -0
- toad/widgets/grid_select.py +223 -0
- toad/widgets/highlighted_textarea.py +180 -0
- toad/widgets/mandelbrot.py +294 -0
- toad/widgets/markdown_note.py +13 -0
- toad/widgets/menu.py +147 -0
- toad/widgets/non_selectable_label.py +5 -0
- toad/widgets/note.py +18 -0
- toad/widgets/path_search.py +381 -0
- toad/widgets/plan.py +180 -0
- toad/widgets/project_directory_tree.py +74 -0
- toad/widgets/prompt.py +741 -0
- toad/widgets/question.py +337 -0
- toad/widgets/shell_result.py +35 -0
- toad/widgets/shell_terminal.py +18 -0
- toad/widgets/side_bar.py +74 -0
- toad/widgets/slash_complete.py +211 -0
- toad/widgets/strike_text.py +66 -0
- toad/widgets/terminal.py +526 -0
- toad/widgets/terminal_tool.py +338 -0
- toad/widgets/throbber.py +90 -0
- toad/widgets/tool_call.py +303 -0
- toad/widgets/user_input.py +23 -0
- toad/widgets/version.py +5 -0
- toad/widgets/welcome.py +31 -0
toad/agent.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from textual.content import Content
|
|
6
|
+
from textual.message import Message
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class AgentReady(Message):
|
|
10
|
+
"""Agent is ready."""
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class AgentFail(Message):
|
|
15
|
+
"""Agent failed to start."""
|
|
16
|
+
|
|
17
|
+
message: str
|
|
18
|
+
details: str = ""
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class AgentBase(ABC):
|
|
22
|
+
"""Base class for an 'agent'."""
|
|
23
|
+
|
|
24
|
+
def __init__(self, project_root: Path) -> None:
|
|
25
|
+
self.project_root_path = project_root
|
|
26
|
+
super().__init__()
|
|
27
|
+
|
|
28
|
+
@abstractmethod
|
|
29
|
+
async def send_prompt(self, prompt: str) -> str | None:
|
|
30
|
+
"""Send a prompt to the agent.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
prompt: Prompt text.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
str: The stop reason.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
async def set_mode(self, mode_id: str) -> str | None:
|
|
40
|
+
"""Put the agent in a new mode.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
mode_id: Mode id.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
str: The stop reason.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
async def cancel(self) -> bool:
|
|
50
|
+
"""Cancel prompt.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
bool: `True` if success, `False` if the turn wasn't cancelled.
|
|
54
|
+
|
|
55
|
+
"""
|
|
56
|
+
return False
|
|
57
|
+
|
|
58
|
+
def get_info(self) -> Content:
|
|
59
|
+
return Content("")
|
|
60
|
+
|
|
61
|
+
async def stop(self) -> None:
|
|
62
|
+
"""Stop the agent (gracefully exit the process)"""
|
toad/agent_schema.py
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
from typing import TypedDict, Literal, NotRequired
|
|
2
|
+
|
|
3
|
+
type Tag = str
|
|
4
|
+
"""A tag used for categorizing the agent. For example: 'open-source', 'reasoning'."""
|
|
5
|
+
type OS = Literal["macos", "linux", "windows", "*"]
|
|
6
|
+
"""An operating system identifier, or a '*" wildcard, if it is the same for all OSes."""
|
|
7
|
+
type Action = str
|
|
8
|
+
"""An action which the agent supports."""
|
|
9
|
+
type AgentType = Literal["coding", "chat"]
|
|
10
|
+
"""The type of agent. More types TBD."""
|
|
11
|
+
type AgentProtocol = Literal["acp"]
|
|
12
|
+
"""The protocol used to communicate with the agent. Currently only "acp" is supported."""
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Command(TypedDict):
|
|
16
|
+
"""Used to perform an action associate with an Agent."""
|
|
17
|
+
|
|
18
|
+
description: str
|
|
19
|
+
"""Describes what the script will do. For example: 'Install Claude Code'."""
|
|
20
|
+
command: str
|
|
21
|
+
"""Command to run."""
|
|
22
|
+
bootstrap_uv: NotRequired[bool]
|
|
23
|
+
"""Bootstrap UV installer (set to `true` if the command users `uv`)."""
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Agent(TypedDict):
|
|
27
|
+
"""Describes an agent which Toad can connect to. Currently only Agent Client Protocol is supported.
|
|
28
|
+
|
|
29
|
+
This information is stoed within TOML files, where the filename is the "identity" key plus the extension ".toml"
|
|
30
|
+
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
active: NotRequired[bool]
|
|
34
|
+
"""If `True` (default), the agent will be shown in the UI. If `False` the agent will be removed from the UI."""
|
|
35
|
+
recommended: NotRequired[bool]
|
|
36
|
+
"""Agent is in recommended set. Set to `True` in main branch only if previously agreed with Will McGugan."""
|
|
37
|
+
identity: str
|
|
38
|
+
"""A unique identifier for this agent. Should be a domain the agent developer owns,
|
|
39
|
+
although it doesn't have to resolve to anything. Must be useable in a filename on all platforms.
|
|
40
|
+
For example: 'claude.anthropic.ai'"""
|
|
41
|
+
name: str
|
|
42
|
+
"""The name of the agent. For example: 'Claude Code'."""
|
|
43
|
+
short_name: str
|
|
44
|
+
"""A short name, usable on the command line. Try to make it unique. For example: 'claude'."""
|
|
45
|
+
url: str
|
|
46
|
+
"""A URL for the agent."""
|
|
47
|
+
protocol: AgentProtocol
|
|
48
|
+
"""The protocol used by the agent. Currently only 'acp' is supported."""
|
|
49
|
+
type: "AgentType"
|
|
50
|
+
"""The type of the agent. Currently "coding" or "chat". More types TBD."""
|
|
51
|
+
author_name: str
|
|
52
|
+
"""The author of the agent. For example 'Anthropic'."""
|
|
53
|
+
author_url: str
|
|
54
|
+
"""The authors homepage. For example 'https://www.anthropic.com/'."""
|
|
55
|
+
publisher_name: str
|
|
56
|
+
"""The publisher's name (individual or organization that wrote this data)."""
|
|
57
|
+
publisher_url: str
|
|
58
|
+
"""The publisher's url."""
|
|
59
|
+
description: str
|
|
60
|
+
"""A description of the agent. A few sentences max. May contain content markup (https://textual.textualize.io/guide/content/#markup) if used subtly."""
|
|
61
|
+
tags: list[Tag]
|
|
62
|
+
"""Tags which identify the agent. Should be empty for now."""
|
|
63
|
+
help: str
|
|
64
|
+
"""A Markdown document with additional details regarding the agent."""
|
|
65
|
+
welcome: NotRequired[str]
|
|
66
|
+
"""A Markdown document shown to the user when the conversation starts. Should contain a welcome message and any advice on getting started."""
|
|
67
|
+
run_command: dict[OS, str]
|
|
68
|
+
"""Command to run the agent, by OS or wildcard."""
|
|
69
|
+
actions: dict[OS, dict[Action, Command]]
|
|
70
|
+
"""Scripts to perform actions, typically at least to install the agent."""
|
toad/agents.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from importlib.resources import files
|
|
2
|
+
import asyncio
|
|
3
|
+
|
|
4
|
+
from toad.agent_schema import Agent
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class AgentReadError(Exception):
|
|
8
|
+
"""Problem reading the agents."""
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
async def read_agents() -> dict[str, Agent]:
|
|
12
|
+
"""Read agent information from data/agents
|
|
13
|
+
|
|
14
|
+
Raises:
|
|
15
|
+
AgentReadError: If the files could not be read.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
A mapping of identity on to Agent dict.
|
|
19
|
+
"""
|
|
20
|
+
import tomllib
|
|
21
|
+
|
|
22
|
+
def read_agents() -> list[Agent]:
|
|
23
|
+
"""Read agent information.
|
|
24
|
+
|
|
25
|
+
Stored in data/agents
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
List of agent dicts.
|
|
29
|
+
"""
|
|
30
|
+
agents: list[Agent] = []
|
|
31
|
+
try:
|
|
32
|
+
for file in files("toad.data").joinpath("agents").iterdir():
|
|
33
|
+
agent: Agent = tomllib.load(file.open("rb"))
|
|
34
|
+
if agent.get("active", True):
|
|
35
|
+
agents.append(agent)
|
|
36
|
+
|
|
37
|
+
except Exception as error:
|
|
38
|
+
raise AgentReadError(f"Failed to read agents; {error}")
|
|
39
|
+
|
|
40
|
+
return agents
|
|
41
|
+
|
|
42
|
+
agents = await asyncio.to_thread(read_agents)
|
|
43
|
+
agent_map = {agent["identity"]: agent for agent in agents}
|
|
44
|
+
|
|
45
|
+
return agent_map
|
toad/ansi/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from toad.ansi._ansi import TerminalState as TerminalState
|