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.
Files changed (120) hide show
  1. batrachian_toad-0.5.22.dist-info/METADATA +197 -0
  2. batrachian_toad-0.5.22.dist-info/RECORD +120 -0
  3. batrachian_toad-0.5.22.dist-info/WHEEL +4 -0
  4. batrachian_toad-0.5.22.dist-info/entry_points.txt +2 -0
  5. batrachian_toad-0.5.22.dist-info/licenses/LICENSE +661 -0
  6. toad/__init__.py +46 -0
  7. toad/__main__.py +4 -0
  8. toad/_loop.py +86 -0
  9. toad/about.py +90 -0
  10. toad/acp/agent.py +671 -0
  11. toad/acp/api.py +47 -0
  12. toad/acp/encode_tool_call_id.py +12 -0
  13. toad/acp/messages.py +138 -0
  14. toad/acp/prompt.py +54 -0
  15. toad/acp/protocol.py +426 -0
  16. toad/agent.py +62 -0
  17. toad/agent_schema.py +70 -0
  18. toad/agents.py +45 -0
  19. toad/ansi/__init__.py +1 -0
  20. toad/ansi/_ansi.py +1612 -0
  21. toad/ansi/_ansi_colors.py +264 -0
  22. toad/ansi/_control_codes.py +37 -0
  23. toad/ansi/_keys.py +251 -0
  24. toad/ansi/_sgr_styles.py +64 -0
  25. toad/ansi/_stream_parser.py +418 -0
  26. toad/answer.py +22 -0
  27. toad/app.py +557 -0
  28. toad/atomic.py +37 -0
  29. toad/cli.py +257 -0
  30. toad/code_analyze.py +28 -0
  31. toad/complete.py +34 -0
  32. toad/constants.py +58 -0
  33. toad/conversation_markdown.py +19 -0
  34. toad/danger.py +371 -0
  35. toad/data/agents/ampcode.com.toml +51 -0
  36. toad/data/agents/augmentcode.com.toml +40 -0
  37. toad/data/agents/claude.com.toml +41 -0
  38. toad/data/agents/docker.com.toml +59 -0
  39. toad/data/agents/geminicli.com.toml +28 -0
  40. toad/data/agents/goose.ai.toml +51 -0
  41. toad/data/agents/inference.huggingface.co.toml +33 -0
  42. toad/data/agents/kimi.com.toml +35 -0
  43. toad/data/agents/openai.com.toml +53 -0
  44. toad/data/agents/opencode.ai.toml +61 -0
  45. toad/data/agents/openhands.dev.toml +44 -0
  46. toad/data/agents/stakpak.dev.toml +61 -0
  47. toad/data/agents/vibe.mistral.ai.toml +27 -0
  48. toad/data/agents/vtcode.dev.toml +62 -0
  49. toad/data/images/frog.png +0 -0
  50. toad/data/sounds/turn-over.wav +0 -0
  51. toad/db.py +5 -0
  52. toad/dec.py +332 -0
  53. toad/directory.py +234 -0
  54. toad/directory_watcher.py +96 -0
  55. toad/fuzzy.py +140 -0
  56. toad/gist.py +2 -0
  57. toad/history.py +138 -0
  58. toad/jsonrpc.py +576 -0
  59. toad/menus.py +14 -0
  60. toad/messages.py +74 -0
  61. toad/option_content.py +51 -0
  62. toad/os.py +0 -0
  63. toad/path_complete.py +145 -0
  64. toad/path_filter.py +124 -0
  65. toad/paths.py +71 -0
  66. toad/pill.py +23 -0
  67. toad/prompt/extract.py +19 -0
  68. toad/prompt/resource.py +68 -0
  69. toad/protocol.py +28 -0
  70. toad/screens/action_modal.py +94 -0
  71. toad/screens/agent_modal.py +172 -0
  72. toad/screens/command_edit_modal.py +58 -0
  73. toad/screens/main.py +192 -0
  74. toad/screens/permissions.py +390 -0
  75. toad/screens/permissions.tcss +72 -0
  76. toad/screens/settings.py +254 -0
  77. toad/screens/settings.tcss +101 -0
  78. toad/screens/store.py +476 -0
  79. toad/screens/store.tcss +261 -0
  80. toad/settings.py +354 -0
  81. toad/settings_schema.py +318 -0
  82. toad/shell.py +263 -0
  83. toad/shell_read.py +42 -0
  84. toad/slash_command.py +34 -0
  85. toad/toad.tcss +752 -0
  86. toad/version.py +80 -0
  87. toad/visuals/columns.py +273 -0
  88. toad/widgets/agent_response.py +79 -0
  89. toad/widgets/agent_thought.py +41 -0
  90. toad/widgets/command_pane.py +224 -0
  91. toad/widgets/condensed_path.py +93 -0
  92. toad/widgets/conversation.py +1626 -0
  93. toad/widgets/danger_warning.py +65 -0
  94. toad/widgets/diff_view.py +709 -0
  95. toad/widgets/flash.py +81 -0
  96. toad/widgets/future_text.py +126 -0
  97. toad/widgets/grid_select.py +223 -0
  98. toad/widgets/highlighted_textarea.py +180 -0
  99. toad/widgets/mandelbrot.py +294 -0
  100. toad/widgets/markdown_note.py +13 -0
  101. toad/widgets/menu.py +147 -0
  102. toad/widgets/non_selectable_label.py +5 -0
  103. toad/widgets/note.py +18 -0
  104. toad/widgets/path_search.py +381 -0
  105. toad/widgets/plan.py +180 -0
  106. toad/widgets/project_directory_tree.py +74 -0
  107. toad/widgets/prompt.py +741 -0
  108. toad/widgets/question.py +337 -0
  109. toad/widgets/shell_result.py +35 -0
  110. toad/widgets/shell_terminal.py +18 -0
  111. toad/widgets/side_bar.py +74 -0
  112. toad/widgets/slash_complete.py +211 -0
  113. toad/widgets/strike_text.py +66 -0
  114. toad/widgets/terminal.py +526 -0
  115. toad/widgets/terminal_tool.py +338 -0
  116. toad/widgets/throbber.py +90 -0
  117. toad/widgets/tool_call.py +303 -0
  118. toad/widgets/user_input.py +23 -0
  119. toad/widgets/version.py +5 -0
  120. toad/widgets/welcome.py +31 -0
toad/acp/api.py ADDED
@@ -0,0 +1,47 @@
1
+ # mypy: disable-error-code="empty-body"
2
+ """
3
+ ACP remote API
4
+ """
5
+
6
+ from toad import jsonrpc
7
+ from toad.acp import protocol
8
+
9
+ API = jsonrpc.API()
10
+
11
+
12
+ @API.method()
13
+ def initialize(
14
+ protocolVersion: int,
15
+ clientCapabilities: protocol.ClientCapabilities,
16
+ clientInfo: protocol.Implementation,
17
+ ) -> protocol.InitializeResponse:
18
+ """https://agentclientprotocol.com/protocol/initialization"""
19
+ ...
20
+
21
+
22
+ @API.method(name="session/new")
23
+ def session_new(
24
+ cwd: str, mcpServers: list[protocol.McpServer]
25
+ ) -> protocol.NewSessionResponse:
26
+ """https://agentclientprotocol.com/protocol/session-setup#session-id"""
27
+ ...
28
+
29
+
30
+ @API.notification(name="session/cancel")
31
+ def session_cancel(sessionId: str, _meta: dict):
32
+ """https://agentclientprotocol.com/protocol/prompt-turn#cancellation"""
33
+ ...
34
+
35
+
36
+ @API.method(name="session/prompt")
37
+ def session_prompt(
38
+ prompt: list[protocol.ContentBlock], sessionId: str
39
+ ) -> protocol.SessionPromptResponse:
40
+ """https://agentclientprotocol.com/protocol/prompt-turn#1-user-message"""
41
+ ...
42
+
43
+
44
+ @API.method(name="session/set_mode")
45
+ def session_set_mode(sessionId: str, modeId: str) -> protocol.SetSessionModeResponse:
46
+ """https://agentclientprotocol.com/protocol/session-modes#from-the-client"""
47
+ ...
@@ -0,0 +1,12 @@
1
+ def encode_tool_call_id(tool_call_id: str) -> str:
2
+ """Encode the tool call id so that it fits within a TCSS id.
3
+
4
+ Args:
5
+ tool_call_id: Raw tool call id.
6
+
7
+ Returns:
8
+ Tool call usable as widget id.
9
+ """
10
+ hex_tool_call_id = "".join(f"{ord(character):2X}" for character in tool_call_id)
11
+ encoded_tool_call_id = f"tool-call-{hex_tool_call_id}"
12
+ return encoded_tool_call_id
toad/acp/messages.py ADDED
@@ -0,0 +1,138 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+
5
+ from asyncio import Future
6
+ from typing import Any, Mapping, TYPE_CHECKING
7
+ from textual.message import Message
8
+
9
+ import rich.repr
10
+
11
+ from toad.answer import Answer
12
+ from toad.acp import protocol
13
+ from toad.acp.encode_tool_call_id import encode_tool_call_id
14
+ from toad.acp.agent import Mode
15
+
16
+ if TYPE_CHECKING:
17
+ from toad.widgets.terminal_tool import ToolState
18
+
19
+
20
+ class AgentMessage(Message):
21
+ pass
22
+
23
+
24
+ @dataclass
25
+ class Thinking(AgentMessage):
26
+ type: str
27
+ text: str
28
+
29
+
30
+ @dataclass
31
+ class UpdateStatusLine(AgentMessage):
32
+ status_line: str
33
+
34
+
35
+ @dataclass
36
+ class Update(AgentMessage):
37
+ type: str
38
+ text: str
39
+
40
+
41
+ @dataclass
42
+ @rich.repr.auto
43
+ class RequestPermission(AgentMessage):
44
+ options: list[protocol.PermissionOption]
45
+ tool_call: protocol.ToolCallUpdatePermissionRequest
46
+ result_future: Future[Answer]
47
+
48
+
49
+ @dataclass
50
+ class Plan(AgentMessage):
51
+ entries: list[protocol.PlanEntry]
52
+
53
+
54
+ @dataclass
55
+ class ToolCall(AgentMessage):
56
+ tool_call: protocol.ToolCall
57
+
58
+ @property
59
+ def tool_id(self) -> str:
60
+ """An id suitable for use as a TCSS ID."""
61
+ return encode_tool_call_id(self.tool_call["toolCallId"])
62
+
63
+
64
+ @dataclass
65
+ class ToolCallUpdate(AgentMessage):
66
+ tool_call: protocol.ToolCall
67
+ update: protocol.ToolCallUpdate
68
+
69
+ @property
70
+ def tool_id(self) -> str:
71
+ """An id suitable for use as a TCSS ID."""
72
+ return encode_tool_call_id(self.tool_call["toolCallId"])
73
+
74
+
75
+ @dataclass
76
+ class AvailableCommandsUpdate(AgentMessage):
77
+ """The agent is reporting its slash commands."""
78
+
79
+ commands: list[protocol.AvailableCommand]
80
+
81
+
82
+ @dataclass
83
+ class CreateTerminal(AgentMessage):
84
+ """Request a terminal in the conversation."""
85
+
86
+ terminal_id: str
87
+ command: str
88
+ result_future: Future[bool]
89
+ args: list[str] | None = None
90
+ cwd: str | None = None
91
+ env: Mapping[str, str] | None = None
92
+ output_byte_limit: int | None = None
93
+
94
+
95
+ @dataclass
96
+ class KillTerminal(AgentMessage):
97
+ """Kill a terminal process."""
98
+
99
+ terminal_id: str
100
+
101
+
102
+ @dataclass
103
+ class GetTerminalState(AgentMessage):
104
+ """Get the state of the terminal."""
105
+
106
+ terminal_id: str
107
+ result_future: Future[ToolState]
108
+
109
+
110
+ @dataclass
111
+ class ReleaseTerminal(AgentMessage):
112
+ """Release the terminal."""
113
+
114
+ terminal_id: str
115
+
116
+
117
+ @dataclass
118
+ class WaitForTerminalExit(AgentMessage):
119
+ """Wait for the terminal to exit."""
120
+
121
+ terminal_id: str
122
+ result_future: Future[tuple[int, str | None]]
123
+
124
+
125
+ @rich.repr.auto
126
+ @dataclass
127
+ class SetModes(AgentMessage):
128
+ """Set modes from agent."""
129
+
130
+ current_mode: str
131
+ modes: dict[str, Mode]
132
+
133
+
134
+ @dataclass
135
+ class ModeUpdate(AgentMessage):
136
+ """Agent informed us about a mode change."""
137
+
138
+ current_mode: str
toad/acp/prompt.py ADDED
@@ -0,0 +1,54 @@
1
+ import base64
2
+ from pathlib import Path
3
+
4
+ from toad.acp import protocol
5
+ from toad.prompt.extract import extract_paths_from_prompt
6
+ from toad.prompt.resource import load_resource, ResourceError
7
+
8
+
9
+ def build(project_path: Path, prompt: str) -> list[protocol.ContentBlock]:
10
+ """Build the prompt structure and extract paths with the @ syntax.
11
+
12
+ Args:
13
+ project_path: The project root.
14
+ prompt: The prompt text.
15
+
16
+ Returns:
17
+ A list of content blocks.
18
+ """
19
+ prompt_content: list[protocol.ContentBlock] = []
20
+
21
+ prompt_content.append({"type": "text", "text": prompt})
22
+ for path, _, _ in extract_paths_from_prompt(prompt):
23
+ if path.endswith("/"):
24
+ continue
25
+ try:
26
+ resource = load_resource(project_path, Path(path))
27
+ except ResourceError:
28
+ # TODO: How should this be handled?
29
+ continue
30
+ uri = f"file://{resource.path.absolute().resolve()}"
31
+ if resource.text is not None:
32
+ prompt_content.append(
33
+ {
34
+ "type": "resource",
35
+ "resource": {
36
+ "uri": uri,
37
+ "text": resource.text,
38
+ "mimeType": resource.mime_type,
39
+ },
40
+ }
41
+ )
42
+ elif resource.data is not None:
43
+ prompt_content.append(
44
+ {
45
+ "type": "resource",
46
+ "resource": {
47
+ "uri": uri,
48
+ "blob": base64.b64encode(resource.data).decode("utf-8"),
49
+ "mimeType": resource.mime_type,
50
+ },
51
+ }
52
+ )
53
+
54
+ return prompt_content
toad/acp/protocol.py ADDED
@@ -0,0 +1,426 @@
1
+ from typing import TypedDict, Required, Literal
2
+
3
+
4
+ class SchemaDict(TypedDict, total=False):
5
+ pass
6
+
7
+
8
+ # ---------------------------------------------------------------------------------------
9
+ # Types
10
+
11
+
12
+ class FileSystemCapability(SchemaDict, total=False):
13
+ readTextFile: bool
14
+ writeTextFile: bool
15
+
16
+
17
+ # https://agentclientprotocol.com/protocol/schema#clientcapabilities
18
+ class ClientCapabilities(SchemaDict, total=False):
19
+ fs: FileSystemCapability
20
+ terminal: bool
21
+
22
+
23
+ # https://agentclientprotocol.com/protocol/schema#implementation
24
+ class Implementation(SchemaDict, total=False):
25
+ name: Required[str]
26
+ title: str | None
27
+ version: Required[str]
28
+
29
+
30
+ # https://agentclientprotocol.com/protocol/schema#promptcapabilities
31
+ class PromptCapabilities(SchemaDict, total=False):
32
+ audio: bool
33
+ embeddedContent: bool
34
+ image: bool
35
+
36
+
37
+ # https://agentclientprotocol.com/protocol/schema#agentcapabilities
38
+ class AgentCapabilities(SchemaDict, total=False):
39
+ loadSession: bool
40
+ promptCapabilities: PromptCapabilities
41
+
42
+
43
+ class AuthMethod(SchemaDict, total=False):
44
+ description: str | None
45
+ id: Required[str]
46
+ name: Required[str]
47
+
48
+
49
+ # https://agentclientprotocol.com/protocol/schema#envvariable
50
+ class EnvVariable(SchemaDict, total=False):
51
+ _meta: dict
52
+ name: Required[str]
53
+ value: Required[str]
54
+
55
+
56
+ # https://agentclientprotocol.com/protocol/schema#terminalexitstatus
57
+ class TerminalExitStatus(SchemaDict, total=False):
58
+ _meta: dict
59
+ exitCode: int | None
60
+ signal: str | None
61
+
62
+
63
+ # https://agentclientprotocol.com/protocol/schema#mcpserver
64
+ class McpServer(SchemaDict, total=False):
65
+ args: list[str]
66
+ command: str
67
+ env: list[EnvVariable]
68
+ name: str
69
+
70
+
71
+ # https://modelcontextprotocol.io/specification/2025-06-18/server/resources#annotations
72
+ class Annotations(SchemaDict, total=False):
73
+ audience: list[str]
74
+ priority: float
75
+ lastModified: str
76
+
77
+
78
+ class TextContent(SchemaDict, total=False):
79
+ type: Required[str]
80
+ text: Required[str]
81
+ annotations: Annotations
82
+
83
+
84
+ class ImageContent(SchemaDict, total=False):
85
+ type: Required[str]
86
+ data: Required[str]
87
+ mimeType: Required[str]
88
+ url: str
89
+ annotations: Annotations
90
+
91
+
92
+ class AudioContent(SchemaDict, total=False):
93
+ type: Required[str]
94
+ data: Required[str]
95
+ mimeType: Required[str]
96
+ Annotations: Annotations
97
+
98
+
99
+ class EmbeddedResourceText(SchemaDict, total=False):
100
+ uri: Required[str]
101
+ text: Required[str]
102
+ mimeType: str
103
+
104
+
105
+ class EmbeddedResourceBlob(SchemaDict, total=False):
106
+ uri: Required[str]
107
+ blob: Required[str]
108
+ mimeType: str
109
+
110
+
111
+ # https://agentclientprotocol.com/protocol/content#embedded-resource
112
+ class EmbeddedResourceContent(SchemaDict, total=False):
113
+ type: Required[str]
114
+ resource: EmbeddedResourceText | EmbeddedResourceBlob
115
+
116
+
117
+ class ResourceLinkContent(SchemaDict, total=False):
118
+ annotations: Annotations | None
119
+ description: str | None
120
+ mimeType: str | None
121
+ name: Required[str]
122
+ size: int | None
123
+ title: str | None
124
+ type: Required[str]
125
+ uri: Required[str]
126
+
127
+
128
+ # https://agentclientprotocol.com/protocol/schema#contentblock
129
+ type ContentBlock = (
130
+ TextContent
131
+ | ImageContent
132
+ | AudioContent
133
+ | EmbeddedResourceContent
134
+ | ResourceLinkContent
135
+ )
136
+
137
+
138
+ # https://agentclientprotocol.com/protocol/schema#param-user-message-chunk
139
+ class UserMessageChunk(SchemaDict, total=False):
140
+ content: Required[ContentBlock]
141
+ sessionUpdate: Required[Literal["user_message_chunk"]]
142
+
143
+
144
+ class AgentMessageChunk(SchemaDict, total=False):
145
+ content: Required[ContentBlock]
146
+ sessionUpdate: Required[Literal["agent_message_chunk"]]
147
+
148
+
149
+ class AgentThoughtChunk(SchemaDict, total=False):
150
+ content: Required[ContentBlock]
151
+ sessionUpdate: Required[Literal["agent_thought_chunk"]]
152
+
153
+
154
+ class ToolCallContentContent(SchemaDict, total=False):
155
+ content: Required[ContentBlock]
156
+ type: Required[Literal["content"]]
157
+
158
+
159
+ # https://agentclientprotocol.com/protocol/schema#param-diff
160
+ class ToolCallContentDiff(SchemaDict, total=False):
161
+ newText: Required[str]
162
+ oldText: str | None
163
+ path: Required[str]
164
+ type: Required[Literal["diff"]]
165
+
166
+
167
+ class ToolCallContentTerminal(SchemaDict, total=False):
168
+ terminalId: Required[str]
169
+ type: Required[Literal["terminal"]]
170
+
171
+
172
+ # https://agentclientprotocol.com/protocol/schema#toolcallcontent
173
+ type ToolCallContent = (
174
+ ToolCallContentContent | ToolCallContentDiff | ToolCallContentTerminal
175
+ )
176
+
177
+ # https://agentclientprotocol.com/protocol/schema#toolkind
178
+ type ToolKind = Literal[
179
+ "read",
180
+ "edit",
181
+ "delete",
182
+ "move",
183
+ "search",
184
+ "execute",
185
+ "think",
186
+ "fetch",
187
+ "switch_mode",
188
+ "other",
189
+ ]
190
+
191
+ type ToolCallStatus = Literal["pending", "in_progress", "completed", "failed"]
192
+
193
+
194
+ class ToolCallLocation(SchemaDict, total=False):
195
+ line: int | None
196
+ path: Required[str]
197
+
198
+
199
+ type ToolCallId = str
200
+
201
+
202
+ # https://agentclientprotocol.com/protocol/schema#toolcall
203
+ class ToolCall(SchemaDict, total=False):
204
+ _meta: dict
205
+ content: list[ToolCallContent]
206
+ kind: ToolKind
207
+ locations: list[ToolCallLocation]
208
+ rawInput: dict
209
+ rawOutput: dict
210
+ sessionUpdate: Required[Literal["tool_call"]]
211
+ status: ToolCallStatus
212
+ title: Required[str]
213
+ toolCallId: Required[ToolCallId]
214
+
215
+
216
+ # https://agentclientprotocol.com/protocol/schema#toolcallupdate
217
+ class ToolCallUpdate(SchemaDict, total=False):
218
+ _meta: dict
219
+ content: list[ToolCallContent] | None
220
+ kind: ToolKind | None
221
+ locations: list | None
222
+ rawInput: dict
223
+ rawOutput: dict
224
+ sessionUpdate: Required[Literal["tool_call_update"]]
225
+ status: ToolCallStatus | None
226
+ title: str | None
227
+ toolCallId: Required[ToolCallId]
228
+
229
+
230
+ # https://agentclientprotocol.com/protocol/schema#param-tool-call
231
+ # Use in the session/request_permission call (not the same as ToolCallUpdate)
232
+ class ToolCallUpdatePermissionRequest(SchemaDict, total=False):
233
+ _meta: dict
234
+ content: list[ToolCallContent] | None
235
+ kind: ToolKind | None
236
+ locations: list | None
237
+ rawInput: dict
238
+ rawOutput: dict
239
+ status: ToolCallStatus | None
240
+ title: str | None
241
+ toolCallId: Required[ToolCallId]
242
+
243
+
244
+ class PlanEntry(SchemaDict, total=False):
245
+ content: Required[str]
246
+ priority: Literal["high", "medium", "low"]
247
+ status: Literal["pending", "in_progress", "completed"]
248
+
249
+
250
+ type SessionModeId = str
251
+
252
+
253
+ # https://agentclientprotocol.com/protocol/schema#sessionmode
254
+ class SessionMode(SchemaDict, total=False):
255
+ _meta: dict
256
+ description: str | None
257
+ id: Required[SessionModeId]
258
+ name: Required[str]
259
+
260
+
261
+ class SessionModeState(SchemaDict, total=False):
262
+ _meta: dict
263
+ availableModes: Required[list[SessionMode]]
264
+ currentModeId: Required[SessionModeId]
265
+
266
+
267
+ type ModelId = str
268
+
269
+
270
+ # https://agentclientprotocol.com/protocol/schema#modelinfo
271
+ class ModelInfo(SchemaDict, total=False):
272
+ _meta: dict
273
+ description: str | None
274
+ modelId: Required[ModelId]
275
+ name: Required[str]
276
+
277
+
278
+ # https://agentclientprotocol.com/protocol/schema#sessionmodelstate
279
+ class SessionModelState(SchemaDict, total=False):
280
+ _meta: dict
281
+ availableModels: Required[list[ModelInfo]]
282
+ currentModelId: Required[ModelId]
283
+
284
+
285
+ # https://agentclientprotocol.com/protocol/schema#param-plan
286
+ class Plan(SchemaDict, total=False):
287
+ entries: Required[list[PlanEntry]]
288
+ sessionUpdate: Required[Literal["plan"]]
289
+
290
+
291
+ class AvailableCommandInput(SchemaDict, total=False):
292
+ hint: Required[str]
293
+
294
+
295
+ class AvailableCommand(SchemaDict, total=False):
296
+ description: Required[str]
297
+ input: AvailableCommandInput | None
298
+ name: Required[str]
299
+
300
+
301
+ class AvailableCommandsUpdate(SchemaDict, total=False):
302
+ availableCommands: Required[list[AvailableCommand]]
303
+ sessionUpdate: Required[Literal["available_commands_update"]]
304
+
305
+
306
+ class CurrentModeUpdate(SchemaDict, total=False):
307
+ currentModeId: Required[str]
308
+ sessionUpdate: Required[Literal["current_mode_update"]]
309
+
310
+
311
+ type SessionUpdate = (
312
+ UserMessageChunk
313
+ | AgentMessageChunk
314
+ | AgentThoughtChunk
315
+ | ToolCall
316
+ | ToolCallUpdate
317
+ | Plan
318
+ | AvailableCommandsUpdate
319
+ | CurrentModeUpdate
320
+ )
321
+
322
+
323
+ class SessionNotification(TypedDict, total=False):
324
+ sessionId: str
325
+ update: SessionUpdate
326
+
327
+
328
+ type PermissionOptionKind = Literal[
329
+ "allow_once", "allow_always", "reject_once", "reject_always"
330
+ ]
331
+ type PermissionOptionId = str
332
+
333
+
334
+ class PermissionOption(TypedDict, total=False):
335
+ _meta: dict
336
+ kind: Required[PermissionOptionKind]
337
+ name: Required[str]
338
+ optionId: Required[PermissionOptionId]
339
+
340
+
341
+ class OutcomeCancelled(TypedDict, total=False):
342
+ outcome: Literal["cancelled"]
343
+
344
+
345
+ class OutcomeSelected(TypedDict, total=False):
346
+ optionId: Required[PermissionOptionId]
347
+ outcome: Literal["selected"]
348
+
349
+
350
+ # https://agentclientprotocol.com/protocol/schema#requestpermissionoutcome
351
+ type RequestPermissionOutcome = OutcomeSelected | OutcomeCancelled
352
+
353
+ # ---------------------------------------------------------------------------------------
354
+ # RPC responses
355
+
356
+
357
+ class InitializeResponse(SchemaDict, total=False):
358
+ agentCapabilities: AgentCapabilities
359
+ authMethods: list[AuthMethod]
360
+ protocolVersion: Required[int]
361
+
362
+
363
+ # https://agentclientprotocol.com/protocol/schema#newsessionresponse
364
+ class NewSessionResponse(SchemaDict, total=False):
365
+ _meta: object
366
+ sessionId: Required[str]
367
+ # Unstable from here
368
+ models: SessionModelState | None
369
+ modes: SessionModeState | None
370
+
371
+
372
+ class SessionPromptResponse(SchemaDict, total=False):
373
+ stopReason: Required[
374
+ Literal[
375
+ "end_turn",
376
+ "max_tokens",
377
+ "max_turn_requests",
378
+ "refusal",
379
+ "cancelled",
380
+ ]
381
+ ]
382
+
383
+
384
+ # https://agentclientprotocol.com/protocol/schema#requestpermissionresponse
385
+ class RequestPermissionResponse(TypedDict, total=False):
386
+ _meta: dict
387
+ outcome: Required[RequestPermissionOutcome]
388
+
389
+
390
+ # https://agentclientprotocol.com/protocol/schema#createterminalresponse
391
+ class CreateTerminalResponse(TypedDict, total=False):
392
+ _meta: dict
393
+ terminalId: Required[str]
394
+
395
+
396
+ # https://agentclientprotocol.com/protocol/schema#killterminalcommandresponse
397
+ class KillTerminalCommandResponse(TypedDict, total=False):
398
+ _meta: dict
399
+
400
+
401
+ # https://agentclientprotocol.com/protocol/schema#terminaloutputresponse
402
+ class TerminalOutputResponse(TypedDict, total=False):
403
+ _meta: dict
404
+ exitStatus: TerminalExitStatus | None
405
+ output: Required[str]
406
+ truncated: Required[bool]
407
+
408
+
409
+ # https://agentclientprotocol.com/protocol/schema#releaseterminalresponse
410
+ class ReleaseTerminalResponse(TypedDict, total=False):
411
+ _meta: dict
412
+
413
+
414
+ # https://agentclientprotocol.com/protocol/schema#waitforterminalexitresponse
415
+ class WaitForTerminalExitResponse(TypedDict, total=False):
416
+ _meta: dict
417
+ exitCode: int | None
418
+ signal: str | None
419
+
420
+
421
+ # https://agentclientprotocol.com/protocol/schema#setsessionmoderesponse
422
+ class SetSessionModeResponse(TypedDict, total=False):
423
+ meta: dict
424
+
425
+
426
+ # ---------------------------------------------------------------------------------------