bma-executor-sdk 0.4.0__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.
- bma_executor_sdk/__init__.py +77 -0
- bma_executor_sdk/_rpc.py +192 -0
- bma_executor_sdk/agent.py +558 -0
- bma_executor_sdk/client.py +675 -0
- bma_executor_sdk/generated.py +1155 -0
- bma_executor_sdk/harness.py +769 -0
- bma_executor_sdk/transport.py +189 -0
- bma_executor_sdk-0.4.0.dist-info/METADATA +28 -0
- bma_executor_sdk-0.4.0.dist-info/RECORD +10 -0
- bma_executor_sdk-0.4.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,1155 @@
|
|
|
1
|
+
# Code generated by tools/contract/gen-python.mjs from contracts/bma (executor protocol 1.1.0). DO NOT EDIT.
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from enum import Enum, IntEnum
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Literal, TypedDict
|
|
8
|
+
|
|
9
|
+
# Annotations stay strings (PEP 563), so NotRequired is only needed by type
|
|
10
|
+
# checkers and Python 3.10 works without typing_extensions at runtime.
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from typing_extensions import NotRequired
|
|
13
|
+
|
|
14
|
+
class Ack(TypedDict):
|
|
15
|
+
"""Generic acknowledgement returned by executor RPC methods."""
|
|
16
|
+
accepted: bool
|
|
17
|
+
|
|
18
|
+
class AgentCapability(TypedDict):
|
|
19
|
+
"""agent capability. Present with enabled=true when the executor runs a complete agent and accepts turn.start, turn.input, turn.cancel, session.close and interaction.response."""
|
|
20
|
+
enabled: bool
|
|
21
|
+
models: NotRequired[list[AgentModel]]
|
|
22
|
+
permission_modes: NotRequired[list[str]]
|
|
23
|
+
interaction_kinds: NotRequired[list[InteractionKind]]
|
|
24
|
+
file_inputs: NotRequired[bool]
|
|
25
|
+
max_sessions: NotRequired[int]
|
|
26
|
+
|
|
27
|
+
class AgentErrorInfo(TypedDict):
|
|
28
|
+
"""Typed session error."""
|
|
29
|
+
type: str
|
|
30
|
+
message: NotRequired[str]
|
|
31
|
+
|
|
32
|
+
class AgentEventType(str, Enum):
|
|
33
|
+
"""Durable events an agent executor emits with session.event. Names and members follow Anthropic Managed Agents session events. user.* events are written by the platform, never by the executor."""
|
|
34
|
+
AgentMessage = "agent.message"
|
|
35
|
+
AgentThinking = "agent.thinking"
|
|
36
|
+
AgentToolUse = "agent.tool_use"
|
|
37
|
+
AgentToolResult = "agent.tool_result"
|
|
38
|
+
AgentMcpToolUse = "agent.mcp_tool_use"
|
|
39
|
+
AgentMcpToolResult = "agent.mcp_tool_result"
|
|
40
|
+
SessionStatusRunning = "session.status_running"
|
|
41
|
+
SessionStatusIdle = "session.status_idle"
|
|
42
|
+
SessionError = "session.error"
|
|
43
|
+
|
|
44
|
+
class AgentInputBlock(TypedDict):
|
|
45
|
+
"""One block of user input. A file block references a platform session file by file_id; the executor downloads it through the executor files API. File bytes never travel on the control channel."""
|
|
46
|
+
type: AgentInputBlockType
|
|
47
|
+
text: NotRequired[str]
|
|
48
|
+
file_id: NotRequired[str]
|
|
49
|
+
name: NotRequired[str]
|
|
50
|
+
mime_type: NotRequired[str]
|
|
51
|
+
size_bytes: NotRequired[int]
|
|
52
|
+
|
|
53
|
+
class AgentInputBlockType(str, Enum):
|
|
54
|
+
"""Agent input block type."""
|
|
55
|
+
Text = "text"
|
|
56
|
+
File = "file"
|
|
57
|
+
|
|
58
|
+
class AgentMcpToolResultEvent(TypedDict):
|
|
59
|
+
"""Result of an agent.mcp_tool_use."""
|
|
60
|
+
type: Literal["agent.mcp_tool_result"]
|
|
61
|
+
mcp_tool_use_id: str
|
|
62
|
+
content: NotRequired[list[ContentBlock]]
|
|
63
|
+
is_error: NotRequired[bool]
|
|
64
|
+
|
|
65
|
+
class AgentMcpToolUseEvent(TypedDict):
|
|
66
|
+
"""An MCP tool the local agent is calling. Its event_id is the mcp_tool_use_id."""
|
|
67
|
+
type: Literal["agent.mcp_tool_use"]
|
|
68
|
+
mcp_server_name: str
|
|
69
|
+
name: str
|
|
70
|
+
input: dict[str, Any]
|
|
71
|
+
evaluated_permission: NotRequired[EvaluatedPermission]
|
|
72
|
+
|
|
73
|
+
class AgentMessageEvent(TypedDict):
|
|
74
|
+
"""Final assistant text. Streaming previews for the same event_id arrive earlier as session.event_delta."""
|
|
75
|
+
type: Literal["agent.message"]
|
|
76
|
+
content: list[ContentBlock]
|
|
77
|
+
|
|
78
|
+
class AgentModel(TypedDict):
|
|
79
|
+
"""One model the local agent can run."""
|
|
80
|
+
id: str
|
|
81
|
+
display_name: NotRequired[str]
|
|
82
|
+
thinking_levels: NotRequired[list[str]]
|
|
83
|
+
default_thinking_level: NotRequired[str]
|
|
84
|
+
|
|
85
|
+
class AgentThinkingEvent(TypedDict):
|
|
86
|
+
"""Model thinking. content may be empty when the model only reports that it thought."""
|
|
87
|
+
type: Literal["agent.thinking"]
|
|
88
|
+
content: NotRequired[list[ContentBlock]]
|
|
89
|
+
|
|
90
|
+
class AgentToolResultEvent(TypedDict):
|
|
91
|
+
"""Result of an agent.tool_use."""
|
|
92
|
+
type: Literal["agent.tool_result"]
|
|
93
|
+
tool_use_id: str
|
|
94
|
+
content: NotRequired[list[ContentBlock]]
|
|
95
|
+
is_error: NotRequired[bool]
|
|
96
|
+
|
|
97
|
+
class AgentToolUseEvent(TypedDict):
|
|
98
|
+
"""A built-in or custom tool the local agent is calling. Its event_id is the tool_use_id."""
|
|
99
|
+
type: Literal["agent.tool_use"]
|
|
100
|
+
name: str
|
|
101
|
+
input: dict[str, Any]
|
|
102
|
+
evaluated_permission: NotRequired[EvaluatedPermission]
|
|
103
|
+
|
|
104
|
+
class AgentTurnConfig(TypedDict):
|
|
105
|
+
"""Requested (turn.start) or effective (TurnStartResult.effective) turn configuration. Every member is optional in a request; the executor reports the values it actually applied."""
|
|
106
|
+
model: NotRequired[str]
|
|
107
|
+
thinking_level: NotRequired[str]
|
|
108
|
+
permission_mode: NotRequired[str]
|
|
109
|
+
cwd: NotRequired[str]
|
|
110
|
+
system: NotRequired[str]
|
|
111
|
+
|
|
112
|
+
class ArtifactCapability(TypedDict):
|
|
113
|
+
"""v1.1 artifact upload (POST /v1/executors/artifacts). Environment-scoped executors only."""
|
|
114
|
+
upload: bool
|
|
115
|
+
max_bytes: NotRequired[int]
|
|
116
|
+
|
|
117
|
+
class ArtifactRef(TypedDict):
|
|
118
|
+
"""Artifact reference returned by POST /v1/executors/artifacts and listed in tool.result artifacts (v1.1 §6.5)."""
|
|
119
|
+
artifact_id: str
|
|
120
|
+
name: NotRequired[str]
|
|
121
|
+
mime_type: str
|
|
122
|
+
size_bytes: int
|
|
123
|
+
digest: str
|
|
124
|
+
created_at: NotRequired[str]
|
|
125
|
+
|
|
126
|
+
class Capabilities(TypedDict):
|
|
127
|
+
"""Executor capability object. The server only sends a method to an executor that advertised its capability; otherwise the executor answers -32012 capability_unavailable."""
|
|
128
|
+
shell: NotRequired[ShellCapability]
|
|
129
|
+
files: NotRequired[FilesCapability]
|
|
130
|
+
mcp: NotRequired[McpCapability]
|
|
131
|
+
chrome: NotRequired[bool]
|
|
132
|
+
computer_use: NotRequired[bool]
|
|
133
|
+
display: NotRequired[bool | DisplayCapability]
|
|
134
|
+
process: NotRequired[ProcessCapability]
|
|
135
|
+
artifacts: NotRequired[ArtifactCapability]
|
|
136
|
+
terminal: NotRequired[TerminalCapability]
|
|
137
|
+
skills: NotRequired[SkillsCapability]
|
|
138
|
+
workspace: NotRequired[WorkspaceCapability]
|
|
139
|
+
agent: NotRequired[AgentCapability]
|
|
140
|
+
|
|
141
|
+
class ChannelScope(str, Enum):
|
|
142
|
+
"""Channels a short-lived executor JWT may open."""
|
|
143
|
+
Control = "control"
|
|
144
|
+
Mcp = "mcp"
|
|
145
|
+
|
|
146
|
+
class ComputerAction(str, Enum):
|
|
147
|
+
"""Input actions accepted by the computer_action tool."""
|
|
148
|
+
Click = "click"
|
|
149
|
+
Type = "type"
|
|
150
|
+
Key = "key"
|
|
151
|
+
Scroll = "scroll"
|
|
152
|
+
Drag = "drag"
|
|
153
|
+
|
|
154
|
+
class ConnectionState(str, Enum):
|
|
155
|
+
"""Executor control channel state machine."""
|
|
156
|
+
Disconnected = "disconnected"
|
|
157
|
+
Connecting = "connecting"
|
|
158
|
+
Registered = "registered"
|
|
159
|
+
Ready = "ready"
|
|
160
|
+
Draining = "draining"
|
|
161
|
+
Closed = "closed"
|
|
162
|
+
|
|
163
|
+
class ContentBlock(TypedDict):
|
|
164
|
+
"""Tool result content block. An artifact block carries artifact_id and mime_type instead of text (v1.1 §6.5)."""
|
|
165
|
+
type: ContentBlockType
|
|
166
|
+
text: NotRequired[str]
|
|
167
|
+
data: NotRequired[str]
|
|
168
|
+
mime_type: NotRequired[str]
|
|
169
|
+
url: NotRequired[str]
|
|
170
|
+
artifact_id: NotRequired[str]
|
|
171
|
+
|
|
172
|
+
class ContentBlockType(str, Enum):
|
|
173
|
+
"""Tool result content block type."""
|
|
174
|
+
Text = "text"
|
|
175
|
+
Image = "image"
|
|
176
|
+
Resource = "resource"
|
|
177
|
+
Artifact = "artifact"
|
|
178
|
+
|
|
179
|
+
class Cursors(TypedDict):
|
|
180
|
+
"""Per-stream byte cursors."""
|
|
181
|
+
stdout: int
|
|
182
|
+
stderr: int
|
|
183
|
+
|
|
184
|
+
class DisplayCapability(TypedDict):
|
|
185
|
+
"""v1.1 display object. v1 sent a boolean; the server accepts both."""
|
|
186
|
+
rfb: NotRequired[bool]
|
|
187
|
+
|
|
188
|
+
class EvaluatedPermission(TypedDict):
|
|
189
|
+
"""Permission decision the executor applied to a tool use. ask means the executor opened an interaction.request for it."""
|
|
190
|
+
type: Literal["allow", "ask", "deny"]
|
|
191
|
+
|
|
192
|
+
class EventDeltaType(str, Enum):
|
|
193
|
+
"""Durable event type a streaming preview belongs to."""
|
|
194
|
+
AgentMessage = "agent.message"
|
|
195
|
+
AgentThinking = "agent.thinking"
|
|
196
|
+
|
|
197
|
+
class ExecutorDrainResult(TypedDict):
|
|
198
|
+
"""executor.drain result."""
|
|
199
|
+
accepted: bool
|
|
200
|
+
active_sessions: list[str]
|
|
201
|
+
|
|
202
|
+
class ExecutorHeartbeatResult(TypedDict):
|
|
203
|
+
"""executor.heartbeat result."""
|
|
204
|
+
server_time: str
|
|
205
|
+
lease_ttl_ms: int
|
|
206
|
+
drain: bool
|
|
207
|
+
|
|
208
|
+
class ExecutorInfo(TypedDict):
|
|
209
|
+
"""Executor identity reported at token bootstrap and registration."""
|
|
210
|
+
name: str
|
|
211
|
+
os: str
|
|
212
|
+
arch: str
|
|
213
|
+
version: str
|
|
214
|
+
|
|
215
|
+
class ExecutorLoad(TypedDict):
|
|
216
|
+
"""Advisory executor load reported with executor.heartbeat. The server does not act on it."""
|
|
217
|
+
cpu_percent: NotRequired[float]
|
|
218
|
+
memory_percent: NotRequired[float]
|
|
219
|
+
|
|
220
|
+
class ExecutorRegisterResult(TypedDict):
|
|
221
|
+
"""executor.register result. protocol and limits are v1.1 only."""
|
|
222
|
+
executor_id: str
|
|
223
|
+
connection_id: str
|
|
224
|
+
server_time: str
|
|
225
|
+
heartbeat_interval_ms: int
|
|
226
|
+
lease_ttl_ms: int
|
|
227
|
+
max_control_frame_bytes: int
|
|
228
|
+
max_mcp_frame_bytes: int
|
|
229
|
+
drain: bool
|
|
230
|
+
protocol: NotRequired[ProtocolVersion]
|
|
231
|
+
limits: NotRequired[Limits]
|
|
232
|
+
|
|
233
|
+
class ExecutorResume(TypedDict):
|
|
234
|
+
"""Reattach state sent on reconnect."""
|
|
235
|
+
executor_id: NotRequired[str]
|
|
236
|
+
last_connection_id: NotRequired[str]
|
|
237
|
+
active_sessions: NotRequired[list[str]]
|
|
238
|
+
|
|
239
|
+
class ExecutorTokenRequest(TypedDict):
|
|
240
|
+
"""POST /v1/executors/token body. The bearer is an environment key, or a machine daemon token. An empty environment_id with a machine token requests a machine-scoped executor: its executor_id is exec_<machine_id>, stable across refreshes, and the JWT carries machine_id and daemon_token_id."""
|
|
241
|
+
environment_id: str
|
|
242
|
+
executor: ExecutorInfo
|
|
243
|
+
|
|
244
|
+
class ExecutorTokenResponse(TypedDict):
|
|
245
|
+
"""POST /v1/executors/token response."""
|
|
246
|
+
executor_id: str
|
|
247
|
+
token: str
|
|
248
|
+
expires_in: int
|
|
249
|
+
ws_url: str
|
|
250
|
+
channel_scope: list[ChannelScope]
|
|
251
|
+
|
|
252
|
+
class FileTransferDirection(str, Enum):
|
|
253
|
+
"""File transfer direction relative to the machine."""
|
|
254
|
+
Upload = "upload"
|
|
255
|
+
Download = "download"
|
|
256
|
+
|
|
257
|
+
class FileTransferError(TypedDict):
|
|
258
|
+
"""Failed file transfer."""
|
|
259
|
+
code: str
|
|
260
|
+
error: str
|
|
261
|
+
current_digest: NotRequired[str]
|
|
262
|
+
|
|
263
|
+
class FileTransferResult(TypedDict):
|
|
264
|
+
"""Ended file transfer outcome: the uploaded path and digest, the downloaded digest, or an error."""
|
|
265
|
+
path: NotRequired[str]
|
|
266
|
+
digest: NotRequired[str]
|
|
267
|
+
error: NotRequired[FileTransferError]
|
|
268
|
+
|
|
269
|
+
class FilesCapability(TypedDict):
|
|
270
|
+
"""v1 file tools."""
|
|
271
|
+
enabled: bool
|
|
272
|
+
read_roots: NotRequired[list[str]]
|
|
273
|
+
write_roots: NotRequired[list[str]]
|
|
274
|
+
|
|
275
|
+
class IOMode(str, Enum):
|
|
276
|
+
"""process.start io_mode. "pty" runs the command on a 24x80 pseudo-terminal: stdout is the PTY output, stdin writes go to the PTY and close_stdin is rejected. Requires process.pty."""
|
|
277
|
+
Pty = "pty"
|
|
278
|
+
|
|
279
|
+
class InteractionCancelReason(str, Enum):
|
|
280
|
+
"""Why the executor withdrew an open interaction."""
|
|
281
|
+
ResolvedLocally = "resolved_locally"
|
|
282
|
+
TurnCanceled = "turn_canceled"
|
|
283
|
+
Expired = "expired"
|
|
284
|
+
ToolCanceled = "tool_canceled"
|
|
285
|
+
|
|
286
|
+
class InteractionKind(str, Enum):
|
|
287
|
+
"""Interaction kinds; they map 1:1 to platform agent interactions."""
|
|
288
|
+
Permission = "permission"
|
|
289
|
+
Question = "question"
|
|
290
|
+
|
|
291
|
+
class InteractionOutcome(str, Enum):
|
|
292
|
+
"""How the platform resolved an interaction. allow/deny answer permission, answered answers question, expired and canceled close either kind without an answer."""
|
|
293
|
+
Allow = "allow"
|
|
294
|
+
Deny = "deny"
|
|
295
|
+
Answered = "answered"
|
|
296
|
+
Expired = "expired"
|
|
297
|
+
Canceled = "canceled"
|
|
298
|
+
|
|
299
|
+
class InteractionQuestion(TypedDict):
|
|
300
|
+
"""Question shown to the user."""
|
|
301
|
+
prompt: str
|
|
302
|
+
options: NotRequired[list[InteractionQuestionOption]]
|
|
303
|
+
multi_select: NotRequired[bool]
|
|
304
|
+
allow_free_text: NotRequired[bool]
|
|
305
|
+
|
|
306
|
+
class InteractionQuestionOption(TypedDict):
|
|
307
|
+
"""One answer option of a question interaction."""
|
|
308
|
+
id: str
|
|
309
|
+
label: str
|
|
310
|
+
|
|
311
|
+
class InteractionRequestResult(TypedDict):
|
|
312
|
+
"""interaction.request result. Idempotent by interaction_id: a repeat returns the same platform interaction."""
|
|
313
|
+
accepted: bool
|
|
314
|
+
platform_interaction_id: str
|
|
315
|
+
|
|
316
|
+
class InteractionResponder(TypedDict):
|
|
317
|
+
"""Who answered, for local audit. surface is the client that resolved it, for example desktop, mobile, web, slack."""
|
|
318
|
+
actor_id: NotRequired[str]
|
|
319
|
+
surface: NotRequired[str]
|
|
320
|
+
|
|
321
|
+
class InteractionResponseResult(TypedDict):
|
|
322
|
+
"""interaction.response result. accepted=false when the interaction is unknown or already resolved (first answer wins); the platform then marks its copy stale."""
|
|
323
|
+
accepted: bool
|
|
324
|
+
|
|
325
|
+
class InteractionScope(str, Enum):
|
|
326
|
+
"""How long a permission grant lasts on the executor: this tool use only, or the rest of the session."""
|
|
327
|
+
Once = "once"
|
|
328
|
+
Session = "session"
|
|
329
|
+
|
|
330
|
+
class JsonRpcError(TypedDict):
|
|
331
|
+
"""JSON-RPC 2.0 error object."""
|
|
332
|
+
code: JsonRpcErrorCode
|
|
333
|
+
message: str
|
|
334
|
+
data: NotRequired[JsonRpcErrorData]
|
|
335
|
+
|
|
336
|
+
class JsonRpcErrorCode(IntEnum):
|
|
337
|
+
"""Executor protocol JSON-RPC error codes. -32011..-32013 are v1.1 additions."""
|
|
338
|
+
ParseError = -32700
|
|
339
|
+
InvalidRequest = -32600
|
|
340
|
+
MethodNotFound = -32601
|
|
341
|
+
InvalidParams = -32602
|
|
342
|
+
InternalError = -32603
|
|
343
|
+
Unauthorized = -32000
|
|
344
|
+
Forbidden = -32001
|
|
345
|
+
NotFound = -32002
|
|
346
|
+
LeaseExpired = -32003
|
|
347
|
+
Timeout = -32004
|
|
348
|
+
Canceled = -32005
|
|
349
|
+
PayloadTooLarge = -32006
|
|
350
|
+
SessionNotActive = -32007
|
|
351
|
+
McpUnavailable = -32008
|
|
352
|
+
ExecutorBusy = -32009
|
|
353
|
+
UnsupportedProtocol = -32010
|
|
354
|
+
ResourceUnavailable = -32011
|
|
355
|
+
CapabilityUnavailable = -32012
|
|
356
|
+
Conflict = -32013
|
|
357
|
+
|
|
358
|
+
class JsonRpcErrorData(TypedDict):
|
|
359
|
+
"""JSON-RPC error.data. Members are code-specific; unknown members are ignored."""
|
|
360
|
+
retryable: NotRequired[bool]
|
|
361
|
+
detail: NotRequired[str]
|
|
362
|
+
capability: NotRequired[str]
|
|
363
|
+
reason: NotRequired[str]
|
|
364
|
+
terminal_code: NotRequired[str]
|
|
365
|
+
expected_sequence: NotRequired[int]
|
|
366
|
+
|
|
367
|
+
class JsonRpcErrorResponse(TypedDict):
|
|
368
|
+
"""JSON-RPC 2.0 error response envelope."""
|
|
369
|
+
jsonrpc: Literal["2.0"]
|
|
370
|
+
id: JsonRpcId
|
|
371
|
+
error: JsonRpcError
|
|
372
|
+
|
|
373
|
+
class JsonRpcNotification(TypedDict):
|
|
374
|
+
"""JSON-RPC 2.0 notification envelope (no id)."""
|
|
375
|
+
jsonrpc: Literal["2.0"]
|
|
376
|
+
method: str
|
|
377
|
+
params: dict[str, Any]
|
|
378
|
+
|
|
379
|
+
class JsonRpcRequest(TypedDict):
|
|
380
|
+
"""JSON-RPC 2.0 request envelope."""
|
|
381
|
+
jsonrpc: Literal["2.0"]
|
|
382
|
+
id: JsonRpcId
|
|
383
|
+
method: str
|
|
384
|
+
params: dict[str, Any]
|
|
385
|
+
|
|
386
|
+
class JsonRpcSuccessResponse(TypedDict):
|
|
387
|
+
"""JSON-RPC 2.0 success response envelope."""
|
|
388
|
+
jsonrpc: Literal["2.0"]
|
|
389
|
+
id: JsonRpcId
|
|
390
|
+
result: Any
|
|
391
|
+
|
|
392
|
+
class Lease(TypedDict):
|
|
393
|
+
"""Fencing lease for a session assignment."""
|
|
394
|
+
token: str
|
|
395
|
+
fencing_token: int
|
|
396
|
+
|
|
397
|
+
class Limits(TypedDict):
|
|
398
|
+
"""Limits the executor must enforce, advertised in the v1.1 executor.register result (v1.1 §1.3)."""
|
|
399
|
+
max_inflight_requests: int
|
|
400
|
+
max_concurrent_process_reads: int
|
|
401
|
+
max_process_read_bytes: int
|
|
402
|
+
max_process_write_bytes: int
|
|
403
|
+
max_processes_per_session: int
|
|
404
|
+
max_artifact_bytes: int
|
|
405
|
+
|
|
406
|
+
class McpCapability(TypedDict):
|
|
407
|
+
"""Environment-origin MCP servers."""
|
|
408
|
+
stdio: NotRequired[bool]
|
|
409
|
+
http: NotRequired[bool]
|
|
410
|
+
max_servers: NotRequired[int]
|
|
411
|
+
|
|
412
|
+
class McpConnectionOrigin(str, Enum):
|
|
413
|
+
"""Who connects the MCP server. environment means the executor starts/connects it; service means the harness connects."""
|
|
414
|
+
Service = "service"
|
|
415
|
+
Environment = "environment"
|
|
416
|
+
|
|
417
|
+
class McpContentBlock(TypedDict):
|
|
418
|
+
"""MCP tool content block. Large binary content must go to artifact storage."""
|
|
419
|
+
type: Literal["text", "image", "resource"]
|
|
420
|
+
text: NotRequired[str]
|
|
421
|
+
data: NotRequired[str]
|
|
422
|
+
mimeType: NotRequired[str]
|
|
423
|
+
resource: NotRequired[Any]
|
|
424
|
+
|
|
425
|
+
class McpImplementation(TypedDict):
|
|
426
|
+
name: str
|
|
427
|
+
version: str
|
|
428
|
+
|
|
429
|
+
class McpInitializeParams(TypedDict):
|
|
430
|
+
protocolVersion: str
|
|
431
|
+
capabilities: dict[str, Any]
|
|
432
|
+
clientInfo: McpImplementation
|
|
433
|
+
|
|
434
|
+
class McpInitializeResult(TypedDict):
|
|
435
|
+
protocolVersion: str
|
|
436
|
+
capabilities: dict[str, Any]
|
|
437
|
+
serverInfo: McpImplementation
|
|
438
|
+
|
|
439
|
+
class McpJsonRpcError(TypedDict):
|
|
440
|
+
code: int
|
|
441
|
+
message: str
|
|
442
|
+
data: NotRequired[Any]
|
|
443
|
+
|
|
444
|
+
class McpJsonRpcErrorResponse(TypedDict):
|
|
445
|
+
jsonrpc: Literal["2.0"]
|
|
446
|
+
id: McpJsonRpcId
|
|
447
|
+
error: McpJsonRpcError
|
|
448
|
+
|
|
449
|
+
class McpJsonRpcNotification(TypedDict):
|
|
450
|
+
jsonrpc: Literal["2.0"]
|
|
451
|
+
method: str
|
|
452
|
+
params: NotRequired[dict[str, Any]]
|
|
453
|
+
|
|
454
|
+
class McpJsonRpcRequest(TypedDict):
|
|
455
|
+
jsonrpc: Literal["2.0"]
|
|
456
|
+
id: McpJsonRpcId
|
|
457
|
+
method: str
|
|
458
|
+
params: NotRequired[dict[str, Any]]
|
|
459
|
+
|
|
460
|
+
class McpJsonRpcSuccessResponse(TypedDict):
|
|
461
|
+
jsonrpc: Literal["2.0"]
|
|
462
|
+
id: McpJsonRpcId
|
|
463
|
+
result: Any
|
|
464
|
+
|
|
465
|
+
class McpProgressParams(TypedDict):
|
|
466
|
+
progressToken: str | int
|
|
467
|
+
progress: float
|
|
468
|
+
total: NotRequired[float]
|
|
469
|
+
|
|
470
|
+
class McpServerConfig(TypedDict):
|
|
471
|
+
server_key: str
|
|
472
|
+
connection_origin: McpConnectionOrigin
|
|
473
|
+
transport: McpServerTransport
|
|
474
|
+
|
|
475
|
+
class McpServerTransport(TypedDict):
|
|
476
|
+
"""Transport for one MCP server. stdio requires command; http requires url. Fields for the other transport are omitted."""
|
|
477
|
+
type: McpTransportType
|
|
478
|
+
command: NotRequired[str]
|
|
479
|
+
args: NotRequired[list[str]]
|
|
480
|
+
cwd: NotRequired[str]
|
|
481
|
+
env: NotRequired[dict[str, str]]
|
|
482
|
+
timeout_ms: NotRequired[int]
|
|
483
|
+
command_sha256: NotRequired[str]
|
|
484
|
+
url: NotRequired[str]
|
|
485
|
+
|
|
486
|
+
class McpTool(TypedDict):
|
|
487
|
+
name: str
|
|
488
|
+
description: NotRequired[str]
|
|
489
|
+
inputSchema: dict[str, Any]
|
|
490
|
+
|
|
491
|
+
class McpToolsCallParams(TypedDict):
|
|
492
|
+
name: str
|
|
493
|
+
arguments: dict[str, Any]
|
|
494
|
+
|
|
495
|
+
class McpToolsCallResult(TypedDict):
|
|
496
|
+
content: list[McpContentBlock]
|
|
497
|
+
isError: NotRequired[bool]
|
|
498
|
+
structuredContent: NotRequired[Any]
|
|
499
|
+
|
|
500
|
+
class McpToolsListParams(TypedDict):
|
|
501
|
+
cursor: NotRequired[str]
|
|
502
|
+
|
|
503
|
+
class McpToolsListResult(TypedDict):
|
|
504
|
+
tools: list[McpTool]
|
|
505
|
+
nextCursor: NotRequired[str | None]
|
|
506
|
+
|
|
507
|
+
class McpTransportType(str, Enum):
|
|
508
|
+
Stdio = "stdio"
|
|
509
|
+
Http = "http"
|
|
510
|
+
|
|
511
|
+
class PermissionMode(str, Enum):
|
|
512
|
+
"""Tool permission mode; always_ask means the harness already resolved approval."""
|
|
513
|
+
AlwaysAllow = "always_allow"
|
|
514
|
+
AlwaysAsk = "always_ask"
|
|
515
|
+
|
|
516
|
+
class ProcessCapability(TypedDict):
|
|
517
|
+
"""v1.1 process.* support. pty, file_transfer and git_credentials are additive: the harness only sends the matching process.start fields to an executor that set them, and fails the process explicitly otherwise."""
|
|
518
|
+
enabled: bool
|
|
519
|
+
max_processes: NotRequired[int]
|
|
520
|
+
buffer_bytes: NotRequired[int]
|
|
521
|
+
pty: NotRequired[bool]
|
|
522
|
+
file_transfer: NotRequired[bool]
|
|
523
|
+
git_credentials: NotRequired[bool]
|
|
524
|
+
|
|
525
|
+
class ProcessFileTransfer(TypedDict):
|
|
526
|
+
"""Replaces argv: the executor moves one file between the machine and the process BMA file endpoint and reports the outcome in ProcessState.file_transfer. Requires process.file_transfer."""
|
|
527
|
+
direction: FileTransferDirection
|
|
528
|
+
local_path: str
|
|
529
|
+
|
|
530
|
+
class ProcessListResult(TypedDict):
|
|
531
|
+
"""process.list result."""
|
|
532
|
+
processes: list[ProcessState]
|
|
533
|
+
|
|
534
|
+
class ProcessReadResult(TypedDict):
|
|
535
|
+
"""process.read result."""
|
|
536
|
+
process_id: str
|
|
537
|
+
stream: ProcessStream
|
|
538
|
+
data: str
|
|
539
|
+
from_cursor: int
|
|
540
|
+
next_cursor: int
|
|
541
|
+
earliest_cursor: int
|
|
542
|
+
gap: bool
|
|
543
|
+
truncated: bool
|
|
544
|
+
eof: bool
|
|
545
|
+
state: ProcessStateName
|
|
546
|
+
ended_at: NotRequired[str]
|
|
547
|
+
reason: NotRequired[str]
|
|
548
|
+
exit_code: int | None
|
|
549
|
+
exit_signal: str | None
|
|
550
|
+
file_transfer: NotRequired[FileTransferResult]
|
|
551
|
+
|
|
552
|
+
class ProcessState(TypedDict):
|
|
553
|
+
"""Result of process.start/interrupt/terminate and one process.list entry. ended_at (RFC 3339, executor clock) is set once the process is no longer running; reason explains a "failed" state (for example "timeout"). A spawn failure never creates a state: it is the process.start error with data.reason "spawn_failed"."""
|
|
554
|
+
process_id: str
|
|
555
|
+
state: ProcessStateName
|
|
556
|
+
pid: NotRequired[int]
|
|
557
|
+
started_at: NotRequired[str]
|
|
558
|
+
ended_at: NotRequired[str]
|
|
559
|
+
reason: NotRequired[str]
|
|
560
|
+
cursors: Cursors
|
|
561
|
+
exit_code: int | None
|
|
562
|
+
exit_signal: str | None
|
|
563
|
+
stderr: NotRequired[str]
|
|
564
|
+
accepted: NotRequired[bool]
|
|
565
|
+
file_transfer: NotRequired[FileTransferResult]
|
|
566
|
+
|
|
567
|
+
class ProcessStateName(str, Enum):
|
|
568
|
+
"""Process state (v1.1 §3.3)."""
|
|
569
|
+
Running = "running"
|
|
570
|
+
Exited = "exited"
|
|
571
|
+
Failed = "failed"
|
|
572
|
+
Killed = "killed"
|
|
573
|
+
|
|
574
|
+
class ProcessStream(str, Enum):
|
|
575
|
+
"""Process output stream (v1.1 §3.2)."""
|
|
576
|
+
Stdout = "stdout"
|
|
577
|
+
Stderr = "stderr"
|
|
578
|
+
|
|
579
|
+
class ProcessWriteResult(TypedDict):
|
|
580
|
+
"""process.write result."""
|
|
581
|
+
accepted: bool
|
|
582
|
+
|
|
583
|
+
class ProtocolVersion(str, Enum):
|
|
584
|
+
"""Value of both the WebSocket subprotocol and executor.register protocol. A v1.1 server serves v1 executors and never sends them v1.1 methods."""
|
|
585
|
+
BmaExecutorV1 = "bma.executor.v1"
|
|
586
|
+
BmaExecutorV11 = "bma.executor.v1.1"
|
|
587
|
+
|
|
588
|
+
class SessionAssignResult(TypedDict):
|
|
589
|
+
"""session.assign result."""
|
|
590
|
+
accepted: bool
|
|
591
|
+
session_id: str
|
|
592
|
+
|
|
593
|
+
class SessionCloseResult(TypedDict):
|
|
594
|
+
"""session.close result."""
|
|
595
|
+
closed: bool
|
|
596
|
+
|
|
597
|
+
class SessionErrorEvent(TypedDict):
|
|
598
|
+
"""A turn-level error. A failed turn still ends with session.status_idle turn_outcome=failed."""
|
|
599
|
+
type: Literal["session.error"]
|
|
600
|
+
error: AgentErrorInfo
|
|
601
|
+
|
|
602
|
+
class SessionEvent(TypedDict):
|
|
603
|
+
"""Durable session event emitted by the executor."""
|
|
604
|
+
type: SessionEventType
|
|
605
|
+
tool_use_id: NotRequired[str]
|
|
606
|
+
content: NotRequired[list[ContentBlock]]
|
|
607
|
+
is_error: NotRequired[bool]
|
|
608
|
+
|
|
609
|
+
class SessionEventResult(TypedDict):
|
|
610
|
+
"""session.event result."""
|
|
611
|
+
accepted: bool
|
|
612
|
+
event_id: str
|
|
613
|
+
acked_sequence: NotRequired[int]
|
|
614
|
+
|
|
615
|
+
class SessionEventType(str, Enum):
|
|
616
|
+
"""Durable event types an executor may emit. Event names follow Anthropic Managed Agents; the executor must not invent new names. A tool executor emits agent.tool_result only; an agent executor (capability agent) emits every type, shaped as schemas/agent.json AgentEvent."""
|
|
617
|
+
AgentToolResult = "agent.tool_result"
|
|
618
|
+
AgentMessage = "agent.message"
|
|
619
|
+
AgentThinking = "agent.thinking"
|
|
620
|
+
AgentToolUse = "agent.tool_use"
|
|
621
|
+
AgentMcpToolUse = "agent.mcp_tool_use"
|
|
622
|
+
AgentMcpToolResult = "agent.mcp_tool_result"
|
|
623
|
+
SessionStatusRunning = "session.status_running"
|
|
624
|
+
SessionStatusIdle = "session.status_idle"
|
|
625
|
+
SessionError = "session.error"
|
|
626
|
+
|
|
627
|
+
class SessionMemoryResource(TypedDict):
|
|
628
|
+
"""A memory store mounted into the session workspace."""
|
|
629
|
+
type: Literal["memory_store"]
|
|
630
|
+
memory_store_id: str
|
|
631
|
+
mount_path: str
|
|
632
|
+
|
|
633
|
+
class SessionStatus(str, Enum):
|
|
634
|
+
"""Lifecycle status reported by the executor."""
|
|
635
|
+
Starting = "starting"
|
|
636
|
+
Running = "running"
|
|
637
|
+
Idle = "idle"
|
|
638
|
+
Stopping = "stopping"
|
|
639
|
+
Stopped = "stopped"
|
|
640
|
+
Error = "error"
|
|
641
|
+
|
|
642
|
+
class SessionStatusIdleEvent(TypedDict):
|
|
643
|
+
"""The turn ended. It is the last event of its turn_id; the platform publishes the turn as finished only after it accepted this event and every lower sequence."""
|
|
644
|
+
type: Literal["session.status_idle"]
|
|
645
|
+
stop_reason: StopReason
|
|
646
|
+
turn_outcome: TurnOutcome
|
|
647
|
+
|
|
648
|
+
class SessionStatusRunningEvent(TypedDict):
|
|
649
|
+
"""The local agent started working on the turn."""
|
|
650
|
+
type: Literal["session.status_running"]
|
|
651
|
+
|
|
652
|
+
class SessionStopResult(TypedDict):
|
|
653
|
+
"""session.stop result."""
|
|
654
|
+
stopped: bool
|
|
655
|
+
|
|
656
|
+
class ShellCapability(TypedDict):
|
|
657
|
+
"""v1 one-shot shell tools."""
|
|
658
|
+
enabled: bool
|
|
659
|
+
|
|
660
|
+
class SkillInstallResult(TypedDict):
|
|
661
|
+
"""skill.install result. state is "ready", or "failed" with error_code and error."""
|
|
662
|
+
state: Literal["ready", "failed"]
|
|
663
|
+
error_code: NotRequired[str]
|
|
664
|
+
error: NotRequired[str]
|
|
665
|
+
|
|
666
|
+
class SkillsCapability(TypedDict):
|
|
667
|
+
"""skill.install support. Machine-scoped executors only."""
|
|
668
|
+
install: bool
|
|
669
|
+
|
|
670
|
+
class StderrMode(str, Enum):
|
|
671
|
+
"""process.start stderr mode. "merge" redirects stderr into stdout at the OS level so one cursor covers both."""
|
|
672
|
+
Merge = "merge"
|
|
673
|
+
|
|
674
|
+
class StdinMode(str, Enum):
|
|
675
|
+
"""process.start stdin mode. Empty or "closed" closes stdin at start; "open" keeps it open for process.write."""
|
|
676
|
+
Open = "open"
|
|
677
|
+
Closed = "closed"
|
|
678
|
+
|
|
679
|
+
class StopReason(TypedDict):
|
|
680
|
+
"""Why the turn stopped."""
|
|
681
|
+
type: StopReasonType
|
|
682
|
+
|
|
683
|
+
class StopReasonType(str, Enum):
|
|
684
|
+
"""Anthropic stop_reason types an executor may report. requires_action is not in the list: the platform projects it from open interactions."""
|
|
685
|
+
EndTurn = "end_turn"
|
|
686
|
+
RetriesExhausted = "retries_exhausted"
|
|
687
|
+
|
|
688
|
+
class TerminalAttachResult(TypedDict):
|
|
689
|
+
"""terminal.attach result, returned after the host socket is connected and the attached frame was written on it."""
|
|
690
|
+
accepted: bool
|
|
691
|
+
writer_epoch: int
|
|
692
|
+
|
|
693
|
+
class TerminalCapability(TypedDict):
|
|
694
|
+
"""v1.1 terminal.* support. Machine-scoped executors only."""
|
|
695
|
+
enabled: bool
|
|
696
|
+
kinds: NotRequired[list[str]]
|
|
697
|
+
max_sessions: NotRequired[int]
|
|
698
|
+
|
|
699
|
+
class TerminalCloseResult(TypedDict):
|
|
700
|
+
"""terminal.close result. Idempotent: closing an unknown or closed terminal returns closed=true."""
|
|
701
|
+
closed: bool
|
|
702
|
+
exit_code: NotRequired[int | None]
|
|
703
|
+
|
|
704
|
+
class TerminalErrorData(TypedDict):
|
|
705
|
+
"""JSON-RPC error.data of a failed terminal.* call. terminal_code is the bma.terminal.v1 code the harness relays to the attach (for example terminal_writer_busy)."""
|
|
706
|
+
terminal_code: NotRequired[str]
|
|
707
|
+
|
|
708
|
+
class TerminalHost(TypedDict):
|
|
709
|
+
"""Outbound host socket for one attach. The ticket is a single-use, short-lived bearer credential sent only in the Authorization header, never in the URL."""
|
|
710
|
+
url: str
|
|
711
|
+
ticket: str
|
|
712
|
+
|
|
713
|
+
class TerminalOpenResult(TypedDict):
|
|
714
|
+
"""terminal.open result. epoch starts at 1 and increments when the executor recreates the PTY under the same terminal_id; attach is fenced by it."""
|
|
715
|
+
terminal_id: str
|
|
716
|
+
epoch: int
|
|
717
|
+
pid: int
|
|
718
|
+
rows: int
|
|
719
|
+
cols: int
|
|
720
|
+
earliest_seq: int
|
|
721
|
+
latest_seq: int
|
|
722
|
+
created_at: str
|
|
723
|
+
|
|
724
|
+
class ToolCancelResult(TypedDict):
|
|
725
|
+
"""tool.cancel result."""
|
|
726
|
+
canceled: bool
|
|
727
|
+
|
|
728
|
+
class ToolInput(TypedDict):
|
|
729
|
+
"""Built-in tool input. The selected tool decides which members are meaningful; unknown members are ignored."""
|
|
730
|
+
command: NotRequired[str]
|
|
731
|
+
cwd: NotRequired[str]
|
|
732
|
+
timeout_ms: NotRequired[int]
|
|
733
|
+
env: NotRequired[dict[str, str]]
|
|
734
|
+
path: NotRequired[str]
|
|
735
|
+
offset: NotRequired[int]
|
|
736
|
+
limit: NotRequired[int]
|
|
737
|
+
content: NotRequired[str]
|
|
738
|
+
old_string: NotRequired[str]
|
|
739
|
+
new_string: NotRequired[str]
|
|
740
|
+
pattern: NotRequired[str]
|
|
741
|
+
glob: NotRequired[str]
|
|
742
|
+
display: NotRequired[str]
|
|
743
|
+
action: NotRequired[ComputerAction]
|
|
744
|
+
|
|
745
|
+
class ToolName(str, Enum):
|
|
746
|
+
"""Built-in tool names. bmad serves bash only and answers -32012 for the rest."""
|
|
747
|
+
Bash = "bash"
|
|
748
|
+
Read = "read"
|
|
749
|
+
Write = "write"
|
|
750
|
+
Edit = "edit"
|
|
751
|
+
Glob = "glob"
|
|
752
|
+
Grep = "grep"
|
|
753
|
+
ListFiles = "list_files"
|
|
754
|
+
ComputerObserve = "computer_observe"
|
|
755
|
+
ComputerAction = "computer_action"
|
|
756
|
+
|
|
757
|
+
class ToolOutcome(str, Enum):
|
|
758
|
+
"""Tool outcome."""
|
|
759
|
+
Succeeded = "succeeded"
|
|
760
|
+
Failed = "failed"
|
|
761
|
+
Canceled = "canceled"
|
|
762
|
+
|
|
763
|
+
class ToolPermission(TypedDict):
|
|
764
|
+
"""Tool permission resolved by the harness."""
|
|
765
|
+
mode: PermissionMode
|
|
766
|
+
|
|
767
|
+
class TurnCancelResult(TypedDict):
|
|
768
|
+
"""turn.cancel result. canceled=false when the turn is unknown or already ended; the turn still ends with its own session.status_idle event."""
|
|
769
|
+
canceled: bool
|
|
770
|
+
|
|
771
|
+
class TurnOutcome(str, Enum):
|
|
772
|
+
"""BMA extension on session.status_idle: how the turn ended."""
|
|
773
|
+
Completed = "completed"
|
|
774
|
+
Canceled = "canceled"
|
|
775
|
+
Failed = "failed"
|
|
776
|
+
|
|
777
|
+
class TurnStartResult(TypedDict):
|
|
778
|
+
"""turn.start result. Idempotent by turn_id: a repeated turn.start for a turn the executor already accepted returns the same result without starting a second run."""
|
|
779
|
+
accepted: bool
|
|
780
|
+
turn_id: str
|
|
781
|
+
executor_session_ref: str
|
|
782
|
+
resumed: bool
|
|
783
|
+
effective: AgentTurnConfig
|
|
784
|
+
|
|
785
|
+
class WorkspaceBackupResult(TypedDict):
|
|
786
|
+
"""workspace.backup result. digest and size_bytes describe the archive as the server stored it; skipped counts entries that could not be read (missing from the archive)."""
|
|
787
|
+
state: Literal["uploaded", "unchanged", "failed"]
|
|
788
|
+
fingerprint: NotRequired[str]
|
|
789
|
+
digest: NotRequired[str]
|
|
790
|
+
size_bytes: NotRequired[int]
|
|
791
|
+
entries: NotRequired[int]
|
|
792
|
+
skipped: NotRequired[int]
|
|
793
|
+
error: NotRequired[str]
|
|
794
|
+
|
|
795
|
+
class WorkspaceCapability(TypedDict):
|
|
796
|
+
"""workspace.backup support and the startup restore of a pending backup. Machine-scoped executors only."""
|
|
797
|
+
backup: bool
|
|
798
|
+
|
|
799
|
+
AgentEvent = AgentMessageEvent | AgentThinkingEvent | AgentToolUseEvent | AgentToolResultEvent | AgentMcpToolUseEvent | AgentMcpToolResultEvent | SessionStatusRunningEvent | SessionStatusIdleEvent | SessionErrorEvent
|
|
800
|
+
|
|
801
|
+
JsonRpcId = str
|
|
802
|
+
|
|
803
|
+
McpJsonRpcId = str | int
|
|
804
|
+
|
|
805
|
+
class ExecutorRegisterParams(TypedDict):
|
|
806
|
+
"Params object of executor.register."
|
|
807
|
+
protocol: ProtocolVersion
|
|
808
|
+
environment_id: str
|
|
809
|
+
executor: ExecutorInfo
|
|
810
|
+
capabilities: Capabilities
|
|
811
|
+
resume: NotRequired[ExecutorResume]
|
|
812
|
+
|
|
813
|
+
class ExecutorHeartbeatParams(TypedDict):
|
|
814
|
+
"Params object of executor.heartbeat."
|
|
815
|
+
connection_id: str
|
|
816
|
+
active_sessions: list[str]
|
|
817
|
+
load: NotRequired[ExecutorLoad]
|
|
818
|
+
|
|
819
|
+
class ExecutorCapabilitiesUpdateParams(TypedDict):
|
|
820
|
+
"Params object of executor.capabilities.update."
|
|
821
|
+
capabilities: Capabilities
|
|
822
|
+
|
|
823
|
+
class ExecutorDrainParams(TypedDict):
|
|
824
|
+
"Params object of executor.drain."
|
|
825
|
+
reason: str
|
|
826
|
+
deadline_ms: NotRequired[int]
|
|
827
|
+
|
|
828
|
+
class ExecutorCloseParams(TypedDict):
|
|
829
|
+
"Params object of executor.close."
|
|
830
|
+
reason: str
|
|
831
|
+
|
|
832
|
+
class SessionAssignParams(TypedDict):
|
|
833
|
+
"Params object of session.assign."
|
|
834
|
+
session_id: str
|
|
835
|
+
work_id: str
|
|
836
|
+
agent_id: NotRequired[str]
|
|
837
|
+
environment_id: str
|
|
838
|
+
deadline_ms: NotRequired[int]
|
|
839
|
+
lease: Lease
|
|
840
|
+
resources: NotRequired[list[SessionMemoryResource]]
|
|
841
|
+
mcp_servers: NotRequired[list[McpServerConfig]]
|
|
842
|
+
metadata: NotRequired[dict[str, str]]
|
|
843
|
+
|
|
844
|
+
class SessionReadyParams(TypedDict):
|
|
845
|
+
"Params object of session.ready."
|
|
846
|
+
session_id: str
|
|
847
|
+
work_id: str
|
|
848
|
+
lease_token: str
|
|
849
|
+
|
|
850
|
+
class SessionEventParams(TypedDict):
|
|
851
|
+
"Params object of session.event."
|
|
852
|
+
session_id: str
|
|
853
|
+
turn_id: NotRequired[str]
|
|
854
|
+
event_id: NotRequired[str]
|
|
855
|
+
sequence: NotRequired[int]
|
|
856
|
+
event: SessionEvent
|
|
857
|
+
|
|
858
|
+
class SessionStatusParams(TypedDict):
|
|
859
|
+
"Params object of session.status."
|
|
860
|
+
session_id: str
|
|
861
|
+
status: SessionStatus
|
|
862
|
+
detail: NotRequired[str]
|
|
863
|
+
|
|
864
|
+
class SessionStopParams(TypedDict):
|
|
865
|
+
"Params object of session.stop."
|
|
866
|
+
session_id: str
|
|
867
|
+
reason: str
|
|
868
|
+
deadline_ms: NotRequired[int]
|
|
869
|
+
|
|
870
|
+
class SessionEndedParams(TypedDict):
|
|
871
|
+
"Params object of session.ended."
|
|
872
|
+
session_id: str
|
|
873
|
+
reason: str
|
|
874
|
+
|
|
875
|
+
class ToolCallParams(TypedDict):
|
|
876
|
+
"Params object of tool.call."
|
|
877
|
+
session_id: str
|
|
878
|
+
tool_call_id: str
|
|
879
|
+
tool: ToolName
|
|
880
|
+
input: ToolInput
|
|
881
|
+
deadline_ms: NotRequired[int]
|
|
882
|
+
permission: NotRequired[ToolPermission]
|
|
883
|
+
|
|
884
|
+
class ToolResultParams(TypedDict):
|
|
885
|
+
"Params object of tool.result."
|
|
886
|
+
session_id: str
|
|
887
|
+
tool_call_id: str
|
|
888
|
+
outcome: ToolOutcome
|
|
889
|
+
is_error: bool
|
|
890
|
+
content: list[ContentBlock]
|
|
891
|
+
duration_ms: NotRequired[int]
|
|
892
|
+
artifacts: NotRequired[list[ArtifactRef]]
|
|
893
|
+
|
|
894
|
+
class ToolCancelParams(TypedDict):
|
|
895
|
+
"Params object of tool.cancel."
|
|
896
|
+
session_id: str
|
|
897
|
+
tool_call_id: str
|
|
898
|
+
reason: NotRequired[str]
|
|
899
|
+
|
|
900
|
+
class ToolProgressParams(TypedDict):
|
|
901
|
+
"Params object of tool.progress."
|
|
902
|
+
session_id: str
|
|
903
|
+
tool_call_id: str
|
|
904
|
+
message: str
|
|
905
|
+
|
|
906
|
+
class ProcessStartParams(TypedDict):
|
|
907
|
+
"Params object of process.start."
|
|
908
|
+
session_id: str
|
|
909
|
+
process_id: str
|
|
910
|
+
argv: list[str]
|
|
911
|
+
cwd: NotRequired[str]
|
|
912
|
+
env: NotRequired[dict[str, str]]
|
|
913
|
+
stdin: NotRequired[StdinMode]
|
|
914
|
+
stderr: NotRequired[StderrMode]
|
|
915
|
+
wait_ms: NotRequired[int]
|
|
916
|
+
timeout_ms: NotRequired[int]
|
|
917
|
+
metadata: NotRequired[dict[str, str]]
|
|
918
|
+
io_mode: NotRequired[IOMode]
|
|
919
|
+
file_transfer: NotRequired[ProcessFileTransfer]
|
|
920
|
+
git_credentials: NotRequired[bool]
|
|
921
|
+
|
|
922
|
+
class ProcessReadParams(TypedDict):
|
|
923
|
+
"Params object of process.read."
|
|
924
|
+
session_id: str
|
|
925
|
+
process_id: str
|
|
926
|
+
stream: ProcessStream
|
|
927
|
+
cursor: int
|
|
928
|
+
max_bytes: NotRequired[int]
|
|
929
|
+
wait_ms: NotRequired[int]
|
|
930
|
+
|
|
931
|
+
class ProcessWriteParams(TypedDict):
|
|
932
|
+
"Params object of process.write."
|
|
933
|
+
session_id: str
|
|
934
|
+
process_id: str
|
|
935
|
+
data: NotRequired[str]
|
|
936
|
+
close_stdin: NotRequired[bool]
|
|
937
|
+
|
|
938
|
+
class ProcessSignalParams(TypedDict):
|
|
939
|
+
"Params object of process.interrupt and process.terminate."
|
|
940
|
+
session_id: str
|
|
941
|
+
process_id: str
|
|
942
|
+
grace_ms: NotRequired[int | None]
|
|
943
|
+
|
|
944
|
+
class ProcessListParams(TypedDict):
|
|
945
|
+
"Params object of process.list."
|
|
946
|
+
session_id: str
|
|
947
|
+
|
|
948
|
+
class ProcessStatusParams(TypedDict):
|
|
949
|
+
"Params object of process.status."
|
|
950
|
+
session_id: str
|
|
951
|
+
process_id: str
|
|
952
|
+
state: ProcessStateName
|
|
953
|
+
exit_code: NotRequired[int | None]
|
|
954
|
+
exit_signal: NotRequired[str | None]
|
|
955
|
+
ended_at: NotRequired[str]
|
|
956
|
+
reason: NotRequired[str]
|
|
957
|
+
observed_at: str
|
|
958
|
+
|
|
959
|
+
class TerminalOpenParams(TypedDict):
|
|
960
|
+
"Params object of terminal.open."
|
|
961
|
+
terminal_id: str
|
|
962
|
+
kind: str
|
|
963
|
+
shell: NotRequired[str]
|
|
964
|
+
argv: NotRequired[list[str]]
|
|
965
|
+
cwd: NotRequired[str]
|
|
966
|
+
env: NotRequired[dict[str, str]]
|
|
967
|
+
rows: NotRequired[int]
|
|
968
|
+
cols: NotRequired[int]
|
|
969
|
+
|
|
970
|
+
class TerminalAttachParams(TypedDict):
|
|
971
|
+
"Params object of terminal.attach."
|
|
972
|
+
terminal_id: str
|
|
973
|
+
epoch: int
|
|
974
|
+
stream_id: str
|
|
975
|
+
can_write: bool
|
|
976
|
+
from_seq: int
|
|
977
|
+
ack_seq: int
|
|
978
|
+
host: TerminalHost
|
|
979
|
+
|
|
980
|
+
class TerminalCloseParams(TypedDict):
|
|
981
|
+
"Params object of terminal.close."
|
|
982
|
+
terminal_id: str
|
|
983
|
+
reason: NotRequired[str]
|
|
984
|
+
|
|
985
|
+
class SkillInstallParams(TypedDict):
|
|
986
|
+
"Params object of skill.install."
|
|
987
|
+
machine_id: str
|
|
988
|
+
skill_id: str
|
|
989
|
+
revision_id: str
|
|
990
|
+
digest: str
|
|
991
|
+
download_token: str
|
|
992
|
+
download_expires_at: int
|
|
993
|
+
|
|
994
|
+
class WorkspaceBackupParams(TypedDict):
|
|
995
|
+
"Params object of workspace.backup."
|
|
996
|
+
backup_id: str
|
|
997
|
+
paths: list[str]
|
|
998
|
+
exclude: NotRequired[list[str]]
|
|
999
|
+
skip_if_fingerprint: NotRequired[str]
|
|
1000
|
+
|
|
1001
|
+
class TurnStartParams(TypedDict):
|
|
1002
|
+
"Params object of turn.start."
|
|
1003
|
+
session_id: str
|
|
1004
|
+
turn_id: str
|
|
1005
|
+
input_id: str
|
|
1006
|
+
input: list[AgentInputBlock]
|
|
1007
|
+
executor_session_ref: NotRequired[str]
|
|
1008
|
+
config: NotRequired[AgentTurnConfig]
|
|
1009
|
+
deadline_ms: NotRequired[int]
|
|
1010
|
+
metadata: NotRequired[dict[str, str]]
|
|
1011
|
+
|
|
1012
|
+
class TurnInputParams(TypedDict):
|
|
1013
|
+
"Params object of turn.input."
|
|
1014
|
+
session_id: str
|
|
1015
|
+
turn_id: str
|
|
1016
|
+
input_id: str
|
|
1017
|
+
input: list[AgentInputBlock]
|
|
1018
|
+
|
|
1019
|
+
class TurnCancelParams(TypedDict):
|
|
1020
|
+
"Params object of turn.cancel."
|
|
1021
|
+
session_id: str
|
|
1022
|
+
turn_id: str
|
|
1023
|
+
reason: NotRequired[str]
|
|
1024
|
+
|
|
1025
|
+
class SessionCloseParams(TypedDict):
|
|
1026
|
+
"Params object of session.close."
|
|
1027
|
+
session_id: str
|
|
1028
|
+
reason: str
|
|
1029
|
+
|
|
1030
|
+
class SessionEventDeltaParams(TypedDict):
|
|
1031
|
+
"Params object of session.event_delta."
|
|
1032
|
+
session_id: str
|
|
1033
|
+
turn_id: str
|
|
1034
|
+
event_id: str
|
|
1035
|
+
event_type: EventDeltaType
|
|
1036
|
+
index: int
|
|
1037
|
+
text: str
|
|
1038
|
+
|
|
1039
|
+
class InteractionRequestParams(TypedDict):
|
|
1040
|
+
"Params object of interaction.request."
|
|
1041
|
+
session_id: str
|
|
1042
|
+
turn_id: str
|
|
1043
|
+
interaction_id: str
|
|
1044
|
+
kind: InteractionKind
|
|
1045
|
+
tool_use_id: NotRequired[str]
|
|
1046
|
+
tool_name: NotRequired[str]
|
|
1047
|
+
tool_input: NotRequired[dict[str, Any]]
|
|
1048
|
+
scopes: NotRequired[list[InteractionScope]]
|
|
1049
|
+
question: NotRequired[InteractionQuestion]
|
|
1050
|
+
expires_at: NotRequired[str]
|
|
1051
|
+
|
|
1052
|
+
class InteractionResponseParams(TypedDict):
|
|
1053
|
+
"Params object of interaction.response."
|
|
1054
|
+
session_id: str
|
|
1055
|
+
interaction_id: str
|
|
1056
|
+
outcome: InteractionOutcome
|
|
1057
|
+
scope: NotRequired[InteractionScope]
|
|
1058
|
+
deny_message: NotRequired[str]
|
|
1059
|
+
answers: NotRequired[list[str]]
|
|
1060
|
+
responder: NotRequired[InteractionResponder]
|
|
1061
|
+
|
|
1062
|
+
class InteractionCancelParams(TypedDict):
|
|
1063
|
+
"Params object of interaction.cancel."
|
|
1064
|
+
session_id: str
|
|
1065
|
+
interaction_id: str
|
|
1066
|
+
reason: InteractionCancelReason
|
|
1067
|
+
|
|
1068
|
+
|
|
1069
|
+
@dataclass(frozen=True, slots=True)
|
|
1070
|
+
class MethodSpec:
|
|
1071
|
+
"since is the first protocol that has the method; result_type is the Python type expression of a request result; capability is the capability bit the harness checks before sending it."
|
|
1072
|
+
|
|
1073
|
+
name: str
|
|
1074
|
+
direction: str
|
|
1075
|
+
kind: str
|
|
1076
|
+
since: str
|
|
1077
|
+
params_type: str
|
|
1078
|
+
result_type: str | None = None
|
|
1079
|
+
capability: str | None = None
|
|
1080
|
+
idempotent_by: str | None = None
|
|
1081
|
+
|
|
1082
|
+
|
|
1083
|
+
METHOD_EXECUTOR_REGISTER = "executor.register"
|
|
1084
|
+
METHOD_EXECUTOR_HEARTBEAT = "executor.heartbeat"
|
|
1085
|
+
METHOD_EXECUTOR_CAPABILITIES_UPDATE = "executor.capabilities.update"
|
|
1086
|
+
METHOD_EXECUTOR_DRAIN = "executor.drain"
|
|
1087
|
+
METHOD_EXECUTOR_CLOSE = "executor.close"
|
|
1088
|
+
METHOD_SESSION_ASSIGN = "session.assign"
|
|
1089
|
+
METHOD_SESSION_READY = "session.ready"
|
|
1090
|
+
METHOD_SESSION_EVENT = "session.event"
|
|
1091
|
+
METHOD_SESSION_STATUS = "session.status"
|
|
1092
|
+
METHOD_SESSION_STOP = "session.stop"
|
|
1093
|
+
METHOD_SESSION_ENDED = "session.ended"
|
|
1094
|
+
METHOD_TOOL_CALL = "tool.call"
|
|
1095
|
+
METHOD_TOOL_RESULT = "tool.result"
|
|
1096
|
+
METHOD_TOOL_CANCEL = "tool.cancel"
|
|
1097
|
+
METHOD_TOOL_PROGRESS = "tool.progress"
|
|
1098
|
+
METHOD_PROCESS_START = "process.start"
|
|
1099
|
+
METHOD_PROCESS_READ = "process.read"
|
|
1100
|
+
METHOD_PROCESS_WRITE = "process.write"
|
|
1101
|
+
METHOD_PROCESS_INTERRUPT = "process.interrupt"
|
|
1102
|
+
METHOD_PROCESS_TERMINATE = "process.terminate"
|
|
1103
|
+
METHOD_PROCESS_LIST = "process.list"
|
|
1104
|
+
METHOD_PROCESS_STATUS = "process.status"
|
|
1105
|
+
METHOD_TERMINAL_OPEN = "terminal.open"
|
|
1106
|
+
METHOD_TERMINAL_ATTACH = "terminal.attach"
|
|
1107
|
+
METHOD_TERMINAL_CLOSE = "terminal.close"
|
|
1108
|
+
METHOD_SKILL_INSTALL = "skill.install"
|
|
1109
|
+
METHOD_WORKSPACE_BACKUP = "workspace.backup"
|
|
1110
|
+
METHOD_TURN_START = "turn.start"
|
|
1111
|
+
METHOD_TURN_INPUT = "turn.input"
|
|
1112
|
+
METHOD_TURN_CANCEL = "turn.cancel"
|
|
1113
|
+
METHOD_SESSION_CLOSE = "session.close"
|
|
1114
|
+
METHOD_SESSION_EVENT_DELTA = "session.event_delta"
|
|
1115
|
+
METHOD_INTERACTION_REQUEST = "interaction.request"
|
|
1116
|
+
METHOD_INTERACTION_RESPONSE = "interaction.response"
|
|
1117
|
+
METHOD_INTERACTION_CANCEL = "interaction.cancel"
|
|
1118
|
+
|
|
1119
|
+
METHODS: dict[str, MethodSpec] = {
|
|
1120
|
+
"executor.register": MethodSpec(name="executor.register", direction="executor-to-harness", kind="request", since="bma.executor.v1", params_type="ExecutorRegisterParams", result_type="ExecutorRegisterResult", capability=None, idempotent_by=None),
|
|
1121
|
+
"executor.heartbeat": MethodSpec(name="executor.heartbeat", direction="executor-to-harness", kind="request", since="bma.executor.v1", params_type="ExecutorHeartbeatParams", result_type="ExecutorHeartbeatResult", capability=None, idempotent_by=None),
|
|
1122
|
+
"executor.capabilities.update": MethodSpec(name="executor.capabilities.update", direction="executor-to-harness", kind="notification", since="bma.executor.v1", params_type="ExecutorCapabilitiesUpdateParams", result_type=None, capability=None, idempotent_by=None),
|
|
1123
|
+
"executor.drain": MethodSpec(name="executor.drain", direction="harness-to-executor", kind="request", since="bma.executor.v1", params_type="ExecutorDrainParams", result_type="ExecutorDrainResult", capability=None, idempotent_by=None),
|
|
1124
|
+
"executor.close": MethodSpec(name="executor.close", direction="bidirectional", kind="notification", since="bma.executor.v1", params_type="ExecutorCloseParams", result_type=None, capability=None, idempotent_by=None),
|
|
1125
|
+
"session.assign": MethodSpec(name="session.assign", direction="harness-to-executor", kind="request", since="bma.executor.v1", params_type="SessionAssignParams", result_type="SessionAssignResult", capability=None, idempotent_by=None),
|
|
1126
|
+
"session.ready": MethodSpec(name="session.ready", direction="executor-to-harness", kind="request", since="bma.executor.v1", params_type="SessionReadyParams", result_type="Ack", capability=None, idempotent_by=None),
|
|
1127
|
+
"session.event": MethodSpec(name="session.event", direction="executor-to-harness", kind="request", since="bma.executor.v1", params_type="SessionEventParams", result_type="SessionEventResult", capability=None, idempotent_by="jsonrpc_id"),
|
|
1128
|
+
"session.status": MethodSpec(name="session.status", direction="executor-to-harness", kind="notification", since="bma.executor.v1", params_type="SessionStatusParams", result_type=None, capability=None, idempotent_by=None),
|
|
1129
|
+
"session.stop": MethodSpec(name="session.stop", direction="harness-to-executor", kind="request", since="bma.executor.v1", params_type="SessionStopParams", result_type="SessionStopResult", capability=None, idempotent_by=None),
|
|
1130
|
+
"session.ended": MethodSpec(name="session.ended", direction="executor-to-harness", kind="request", since="bma.executor.v1", params_type="SessionEndedParams", result_type="Ack", capability=None, idempotent_by=None),
|
|
1131
|
+
"tool.call": MethodSpec(name="tool.call", direction="harness-to-executor", kind="request", since="bma.executor.v1", params_type="ToolCallParams", result_type="Ack", capability=None, idempotent_by=None),
|
|
1132
|
+
"tool.result": MethodSpec(name="tool.result", direction="executor-to-harness", kind="request", since="bma.executor.v1", params_type="ToolResultParams", result_type="Ack", capability=None, idempotent_by="tool_call_id"),
|
|
1133
|
+
"tool.cancel": MethodSpec(name="tool.cancel", direction="harness-to-executor", kind="request", since="bma.executor.v1", params_type="ToolCancelParams", result_type="ToolCancelResult", capability=None, idempotent_by=None),
|
|
1134
|
+
"tool.progress": MethodSpec(name="tool.progress", direction="executor-to-harness", kind="notification", since="bma.executor.v1", params_type="ToolProgressParams", result_type=None, capability=None, idempotent_by=None),
|
|
1135
|
+
"process.start": MethodSpec(name="process.start", direction="harness-to-executor", kind="request", since="bma.executor.v1.1", params_type="ProcessStartParams", result_type="ProcessState", capability="process.enabled", idempotent_by="session_id+process_id"),
|
|
1136
|
+
"process.read": MethodSpec(name="process.read", direction="harness-to-executor", kind="request", since="bma.executor.v1.1", params_type="ProcessReadParams", result_type="ProcessReadResult", capability="process.enabled", idempotent_by=None),
|
|
1137
|
+
"process.write": MethodSpec(name="process.write", direction="harness-to-executor", kind="request", since="bma.executor.v1.1", params_type="ProcessWriteParams", result_type="ProcessWriteResult", capability="process.enabled", idempotent_by=None),
|
|
1138
|
+
"process.interrupt": MethodSpec(name="process.interrupt", direction="harness-to-executor", kind="request", since="bma.executor.v1.1", params_type="ProcessSignalParams", result_type="ProcessState", capability="process.enabled", idempotent_by=None),
|
|
1139
|
+
"process.terminate": MethodSpec(name="process.terminate", direction="harness-to-executor", kind="request", since="bma.executor.v1.1", params_type="ProcessSignalParams", result_type="ProcessState", capability="process.enabled", idempotent_by=None),
|
|
1140
|
+
"process.list": MethodSpec(name="process.list", direction="harness-to-executor", kind="request", since="bma.executor.v1.1", params_type="ProcessListParams", result_type="ProcessListResult", capability="process.enabled", idempotent_by=None),
|
|
1141
|
+
"process.status": MethodSpec(name="process.status", direction="executor-to-harness", kind="notification", since="bma.executor.v1.1", params_type="ProcessStatusParams", result_type=None, capability="process.enabled", idempotent_by=None),
|
|
1142
|
+
"terminal.open": MethodSpec(name="terminal.open", direction="harness-to-executor", kind="request", since="bma.executor.v1.1", params_type="TerminalOpenParams", result_type="TerminalOpenResult", capability="terminal.enabled", idempotent_by="terminal_id"),
|
|
1143
|
+
"terminal.attach": MethodSpec(name="terminal.attach", direction="harness-to-executor", kind="request", since="bma.executor.v1.1", params_type="TerminalAttachParams", result_type="TerminalAttachResult", capability="terminal.enabled", idempotent_by=None),
|
|
1144
|
+
"terminal.close": MethodSpec(name="terminal.close", direction="harness-to-executor", kind="request", since="bma.executor.v1.1", params_type="TerminalCloseParams", result_type="TerminalCloseResult", capability="terminal.enabled", idempotent_by="terminal_id"),
|
|
1145
|
+
"skill.install": MethodSpec(name="skill.install", direction="harness-to-executor", kind="request", since="bma.executor.v1.1", params_type="SkillInstallParams", result_type="SkillInstallResult", capability="skills.install", idempotent_by="skill_id+revision_id+digest"),
|
|
1146
|
+
"workspace.backup": MethodSpec(name="workspace.backup", direction="harness-to-executor", kind="request", since="bma.executor.v1.1", params_type="WorkspaceBackupParams", result_type="WorkspaceBackupResult", capability="workspace.backup", idempotent_by="backup_id"),
|
|
1147
|
+
"turn.start": MethodSpec(name="turn.start", direction="harness-to-executor", kind="request", since="bma.executor.v1.1", params_type="TurnStartParams", result_type="TurnStartResult", capability="agent", idempotent_by="turn_id"),
|
|
1148
|
+
"turn.input": MethodSpec(name="turn.input", direction="harness-to-executor", kind="request", since="bma.executor.v1.1", params_type="TurnInputParams", result_type="Ack", capability="agent", idempotent_by="input_id"),
|
|
1149
|
+
"turn.cancel": MethodSpec(name="turn.cancel", direction="harness-to-executor", kind="request", since="bma.executor.v1.1", params_type="TurnCancelParams", result_type="TurnCancelResult", capability="agent", idempotent_by=None),
|
|
1150
|
+
"session.close": MethodSpec(name="session.close", direction="harness-to-executor", kind="request", since="bma.executor.v1.1", params_type="SessionCloseParams", result_type="SessionCloseResult", capability="agent", idempotent_by=None),
|
|
1151
|
+
"session.event_delta": MethodSpec(name="session.event_delta", direction="executor-to-harness", kind="notification", since="bma.executor.v1.1", params_type="SessionEventDeltaParams", result_type=None, capability="agent", idempotent_by=None),
|
|
1152
|
+
"interaction.request": MethodSpec(name="interaction.request", direction="executor-to-harness", kind="request", since="bma.executor.v1.1", params_type="InteractionRequestParams", result_type="InteractionRequestResult", capability="agent", idempotent_by="interaction_id"),
|
|
1153
|
+
"interaction.response": MethodSpec(name="interaction.response", direction="harness-to-executor", kind="request", since="bma.executor.v1.1", params_type="InteractionResponseParams", result_type="InteractionResponseResult", capability="agent", idempotent_by="interaction_id"),
|
|
1154
|
+
"interaction.cancel": MethodSpec(name="interaction.cancel", direction="executor-to-harness", kind="request", since="bma.executor.v1.1", params_type="InteractionCancelParams", result_type="Ack", capability="agent", idempotent_by="interaction_id"),
|
|
1155
|
+
}
|