pi-agent-python-sdk 0.1.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.
- pi_agent/__init__.py +47 -0
- pi_agent/_events.py +108 -0
- pi_agent/_launch.py +203 -0
- pi_agent/_runs.py +317 -0
- pi_agent/_transport.py +360 -0
- pi_agent/_usage.py +88 -0
- pi_agent/client.py +796 -0
- pi_agent/errors.py +87 -0
- pi_agent/py.typed +0 -0
- pi_agent/sync.py +684 -0
- pi_agent/types.py +960 -0
- pi_agent_python_sdk-0.1.0.dist-info/METADATA +231 -0
- pi_agent_python_sdk-0.1.0.dist-info/RECORD +15 -0
- pi_agent_python_sdk-0.1.0.dist-info/WHEEL +4 -0
- pi_agent_python_sdk-0.1.0.dist-info/licenses/LICENSE +21 -0
pi_agent/types.py
ADDED
|
@@ -0,0 +1,960 @@
|
|
|
1
|
+
"""Pi 0.85.1 wire annotations and small Python conveniences.
|
|
2
|
+
|
|
3
|
+
Wire fields retain Pi's spelling and remain ordinary dictionaries. These
|
|
4
|
+
annotations describe known shapes, not a recursive runtime validator: extensions
|
|
5
|
+
and newer runtimes may add fields and discriminators. Provider compatibility
|
|
6
|
+
metadata is deliberately opaque JSON. See docs/discovery.md for pinned sources.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import math
|
|
12
|
+
from dataclasses import dataclass, field, fields
|
|
13
|
+
from typing import Any, Literal, NotRequired, TypeAlias, TypedDict
|
|
14
|
+
|
|
15
|
+
from .errors import PiProtocolError
|
|
16
|
+
|
|
17
|
+
JSONValue: TypeAlias = None | bool | int | float | str | list["JSONValue"] | dict[str, "JSONValue"]
|
|
18
|
+
JSONObject: TypeAlias = dict[str, JSONValue]
|
|
19
|
+
RawRecord: TypeAlias = dict[str, Any]
|
|
20
|
+
ThinkingLevel: TypeAlias = Literal["off", "minimal", "low", "medium", "high", "xhigh", "max"]
|
|
21
|
+
QueueMode: TypeAlias = Literal["all", "one-at-a-time"]
|
|
22
|
+
StreamingBehavior: TypeAlias = Literal["steer", "followUp"]
|
|
23
|
+
CompactionReason: TypeAlias = Literal["manual", "threshold", "overflow"]
|
|
24
|
+
StopReason: TypeAlias = Literal[
|
|
25
|
+
"pending", "stop", "length", "toolUse", "error", "aborted", "deferred"
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class TextContent(TypedDict):
|
|
30
|
+
type: Literal["text"]
|
|
31
|
+
text: str
|
|
32
|
+
textSignature: NotRequired[str]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class ThinkingContent(TypedDict):
|
|
36
|
+
type: Literal["thinking"]
|
|
37
|
+
thinking: str
|
|
38
|
+
thinkingSignature: NotRequired[str]
|
|
39
|
+
redacted: NotRequired[bool]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class ImageContent(TypedDict):
|
|
43
|
+
type: Literal["image"]
|
|
44
|
+
data: str
|
|
45
|
+
mimeType: str
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class ToolCall(TypedDict):
|
|
49
|
+
type: Literal["toolCall"]
|
|
50
|
+
id: str
|
|
51
|
+
name: str
|
|
52
|
+
arguments: JSONObject
|
|
53
|
+
thoughtSignature: NotRequired[str]
|
|
54
|
+
namespace: NotRequired[str]
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class UsageCost(TypedDict):
|
|
58
|
+
input: float
|
|
59
|
+
output: float
|
|
60
|
+
cacheRead: float
|
|
61
|
+
cacheWrite: float
|
|
62
|
+
total: float
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class Usage(TypedDict):
|
|
66
|
+
input: float
|
|
67
|
+
output: float
|
|
68
|
+
cacheRead: float
|
|
69
|
+
cacheWrite: float
|
|
70
|
+
cacheWrite1h: NotRequired[float]
|
|
71
|
+
reasoning: NotRequired[float]
|
|
72
|
+
totalTokens: float
|
|
73
|
+
cost: UsageCost
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class DeferredHandle(TypedDict):
|
|
77
|
+
provider: str
|
|
78
|
+
modelId: str
|
|
79
|
+
api: str
|
|
80
|
+
id: str
|
|
81
|
+
expiresAt: NotRequired[float]
|
|
82
|
+
pollAfterMs: NotRequired[float]
|
|
83
|
+
data: NotRequired[JSONValue]
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class DiagnosticError(TypedDict):
|
|
87
|
+
message: str
|
|
88
|
+
name: NotRequired[str]
|
|
89
|
+
stack: NotRequired[str]
|
|
90
|
+
code: NotRequired[str | float]
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class AssistantMessageDiagnostic(TypedDict):
|
|
94
|
+
type: str
|
|
95
|
+
timestamp: float
|
|
96
|
+
error: NotRequired[DiagnosticError]
|
|
97
|
+
details: NotRequired[JSONObject]
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class UserMessage(TypedDict):
|
|
101
|
+
role: Literal["user"]
|
|
102
|
+
content: str | list[TextContent | ImageContent]
|
|
103
|
+
timestamp: float
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class AssistantMessage(TypedDict):
|
|
107
|
+
role: Literal["assistant"]
|
|
108
|
+
content: list[TextContent | ThinkingContent | ToolCall]
|
|
109
|
+
api: str
|
|
110
|
+
provider: str
|
|
111
|
+
model: str
|
|
112
|
+
responseModel: NotRequired[str]
|
|
113
|
+
responseId: NotRequired[str]
|
|
114
|
+
providerThinkingLevel: NotRequired[str]
|
|
115
|
+
diagnostics: NotRequired[list[AssistantMessageDiagnostic]]
|
|
116
|
+
usage: Usage
|
|
117
|
+
stopReason: StopReason
|
|
118
|
+
deferred: NotRequired[DeferredHandle]
|
|
119
|
+
errorMessage: NotRequired[str]
|
|
120
|
+
rawStopReason: NotRequired[str]
|
|
121
|
+
endTurn: NotRequired[bool]
|
|
122
|
+
timestamp: float
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class ToolResultMessage(TypedDict):
|
|
126
|
+
role: Literal["toolResult"]
|
|
127
|
+
toolCallId: str
|
|
128
|
+
toolName: str
|
|
129
|
+
content: list[TextContent | ImageContent]
|
|
130
|
+
details: NotRequired[JSONValue]
|
|
131
|
+
usage: NotRequired[Usage]
|
|
132
|
+
addedToolNames: NotRequired[list[str]]
|
|
133
|
+
isError: bool
|
|
134
|
+
timestamp: float
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class BashExecutionMessage(TypedDict):
|
|
138
|
+
role: Literal["bashExecution"]
|
|
139
|
+
command: str
|
|
140
|
+
output: str
|
|
141
|
+
exitCode: NotRequired[float]
|
|
142
|
+
cancelled: bool
|
|
143
|
+
truncated: bool
|
|
144
|
+
fullOutputPath: NotRequired[str]
|
|
145
|
+
timestamp: float
|
|
146
|
+
excludeFromContext: NotRequired[bool]
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class CustomMessage(TypedDict):
|
|
150
|
+
role: Literal["custom"]
|
|
151
|
+
customType: str
|
|
152
|
+
content: str | list[TextContent | ImageContent]
|
|
153
|
+
display: bool
|
|
154
|
+
details: NotRequired[JSONValue]
|
|
155
|
+
timestamp: float
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class BranchSummaryMessage(TypedDict):
|
|
159
|
+
role: Literal["branchSummary"]
|
|
160
|
+
summary: str
|
|
161
|
+
fromId: str | None
|
|
162
|
+
timestamp: float
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
class CompactionSummaryMessage(TypedDict):
|
|
166
|
+
role: Literal["compactionSummary"]
|
|
167
|
+
summary: str
|
|
168
|
+
tokensBefore: float
|
|
169
|
+
timestamp: float
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
AgentMessage: TypeAlias = (
|
|
173
|
+
UserMessage
|
|
174
|
+
| AssistantMessage
|
|
175
|
+
| ToolResultMessage
|
|
176
|
+
| BashExecutionMessage
|
|
177
|
+
| CustomMessage
|
|
178
|
+
| BranchSummaryMessage
|
|
179
|
+
| CompactionSummaryMessage
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
class ModelCostRates(TypedDict):
|
|
184
|
+
input: float
|
|
185
|
+
output: float
|
|
186
|
+
cacheRead: float
|
|
187
|
+
cacheWrite: float
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
class ModelCostTier(ModelCostRates):
|
|
191
|
+
inputTokensAbove: float
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
class ModelCost(ModelCostRates):
|
|
195
|
+
tiers: NotRequired[list[ModelCostTier]]
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
class Model(TypedDict):
|
|
199
|
+
id: str
|
|
200
|
+
name: str
|
|
201
|
+
api: str
|
|
202
|
+
provider: str
|
|
203
|
+
baseUrl: str
|
|
204
|
+
reasoning: bool
|
|
205
|
+
thinkingLevelMap: NotRequired[dict[ThinkingLevel, str | None]]
|
|
206
|
+
input: list[Literal["text", "image"]]
|
|
207
|
+
cost: ModelCost
|
|
208
|
+
contextWindow: float
|
|
209
|
+
maxTokens: float
|
|
210
|
+
samplingParams: NotRequired[JSONObject]
|
|
211
|
+
headers: NotRequired[dict[str, str]]
|
|
212
|
+
compat: NotRequired[JSONObject]
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
class SessionState(TypedDict):
|
|
216
|
+
model: NotRequired[Model]
|
|
217
|
+
thinkingLevel: ThinkingLevel
|
|
218
|
+
isStreaming: bool
|
|
219
|
+
isCompacting: bool
|
|
220
|
+
steeringMode: QueueMode
|
|
221
|
+
followUpMode: QueueMode
|
|
222
|
+
sessionFile: NotRequired[str]
|
|
223
|
+
sessionId: str
|
|
224
|
+
sessionName: NotRequired[str]
|
|
225
|
+
autoCompactionEnabled: bool
|
|
226
|
+
messageCount: float
|
|
227
|
+
pendingMessageCount: float
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
class CompactionResult(TypedDict):
|
|
231
|
+
summary: str
|
|
232
|
+
firstKeptEntryId: str
|
|
233
|
+
tokensBefore: float
|
|
234
|
+
estimatedTokensAfter: NotRequired[float]
|
|
235
|
+
usage: NotRequired[Usage]
|
|
236
|
+
details: NotRequired[JSONValue]
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
class BashResult(TypedDict):
|
|
240
|
+
output: str
|
|
241
|
+
exitCode: NotRequired[float]
|
|
242
|
+
cancelled: bool
|
|
243
|
+
truncated: bool
|
|
244
|
+
fullOutputPath: NotRequired[str]
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
class ContextUsage(TypedDict):
|
|
248
|
+
tokens: float | None
|
|
249
|
+
contextWindow: float
|
|
250
|
+
percent: float | None
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
class SessionTokens(TypedDict):
|
|
254
|
+
input: float
|
|
255
|
+
output: float
|
|
256
|
+
cacheRead: float
|
|
257
|
+
cacheWrite: float
|
|
258
|
+
total: float
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
class SessionStats(TypedDict):
|
|
262
|
+
sessionFile: NotRequired[str]
|
|
263
|
+
sessionId: str
|
|
264
|
+
userMessages: float
|
|
265
|
+
assistantMessages: float
|
|
266
|
+
toolCalls: float
|
|
267
|
+
toolResults: float
|
|
268
|
+
totalMessages: float
|
|
269
|
+
tokens: SessionTokens
|
|
270
|
+
cost: float
|
|
271
|
+
contextUsage: NotRequired[ContextUsage]
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
class SourceInfo(TypedDict):
|
|
275
|
+
path: str
|
|
276
|
+
source: str
|
|
277
|
+
scope: Literal["user", "project", "temporary"]
|
|
278
|
+
origin: Literal["package", "top-level"]
|
|
279
|
+
baseDir: NotRequired[str]
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
class SlashCommand(TypedDict):
|
|
283
|
+
name: str
|
|
284
|
+
description: NotRequired[str]
|
|
285
|
+
source: Literal["extension", "prompt", "skill"]
|
|
286
|
+
sourceInfo: SourceInfo
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
class _EntryBase(TypedDict):
|
|
290
|
+
id: str
|
|
291
|
+
parentId: str | None
|
|
292
|
+
timestamp: str
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
class MessageEntry(_EntryBase):
|
|
296
|
+
type: Literal["message"]
|
|
297
|
+
message: AgentMessage
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
class ThinkingLevelChangeEntry(_EntryBase):
|
|
301
|
+
type: Literal["thinking_level_change"]
|
|
302
|
+
thinkingLevel: str
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
class ModelChangeEntry(_EntryBase):
|
|
306
|
+
type: Literal["model_change"]
|
|
307
|
+
provider: str
|
|
308
|
+
modelId: str
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
class CompactionEntry(_EntryBase):
|
|
312
|
+
type: Literal["compaction"]
|
|
313
|
+
summary: str
|
|
314
|
+
firstKeptEntryId: str
|
|
315
|
+
tokensBefore: float
|
|
316
|
+
details: NotRequired[JSONValue]
|
|
317
|
+
usage: NotRequired[Usage]
|
|
318
|
+
fromHook: NotRequired[bool]
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
class BranchSummaryEntry(_EntryBase):
|
|
322
|
+
type: Literal["branch_summary"]
|
|
323
|
+
fromId: str
|
|
324
|
+
summary: str
|
|
325
|
+
details: NotRequired[JSONValue]
|
|
326
|
+
usage: NotRequired[Usage]
|
|
327
|
+
fromHook: NotRequired[bool]
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
class CustomEntry(_EntryBase):
|
|
331
|
+
type: Literal["custom"]
|
|
332
|
+
customType: str
|
|
333
|
+
data: NotRequired[JSONValue]
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
class CustomMessageEntry(_EntryBase):
|
|
337
|
+
type: Literal["custom_message"]
|
|
338
|
+
customType: str
|
|
339
|
+
content: str | list[TextContent | ImageContent]
|
|
340
|
+
details: NotRequired[JSONValue]
|
|
341
|
+
display: bool
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
class LabelEntry(_EntryBase):
|
|
345
|
+
type: Literal["label"]
|
|
346
|
+
targetId: str
|
|
347
|
+
label: NotRequired[str]
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
class SessionInfoEntry(_EntryBase):
|
|
351
|
+
type: Literal["session_info"]
|
|
352
|
+
name: NotRequired[str]
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
SessionEntry: TypeAlias = (
|
|
356
|
+
MessageEntry
|
|
357
|
+
| ThinkingLevelChangeEntry
|
|
358
|
+
| ModelChangeEntry
|
|
359
|
+
| CompactionEntry
|
|
360
|
+
| BranchSummaryEntry
|
|
361
|
+
| CustomEntry
|
|
362
|
+
| CustomMessageEntry
|
|
363
|
+
| LabelEntry
|
|
364
|
+
| SessionInfoEntry
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
class SessionTreeNode(TypedDict):
|
|
369
|
+
entry: SessionEntry
|
|
370
|
+
children: list[SessionTreeNode]
|
|
371
|
+
label: NotRequired[str]
|
|
372
|
+
labelTimestamp: NotRequired[str]
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
class QueueState(TypedDict):
|
|
376
|
+
steering: list[str]
|
|
377
|
+
followUp: list[str]
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
class SessionChangeResult(TypedDict):
|
|
381
|
+
cancelled: bool
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
class ForkResult(SessionChangeResult):
|
|
385
|
+
# A veto omits text despite upstream's required-string declaration.
|
|
386
|
+
text: NotRequired[str]
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
class ModelCycleResult(TypedDict):
|
|
390
|
+
model: Model
|
|
391
|
+
thinkingLevel: ThinkingLevel
|
|
392
|
+
isScoped: bool
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
class ForkMessage(TypedDict):
|
|
396
|
+
entryId: str
|
|
397
|
+
text: str
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
class EntriesResult(TypedDict):
|
|
401
|
+
entries: list[SessionEntry]
|
|
402
|
+
leafId: str | None
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
class TreeResult(TypedDict):
|
|
406
|
+
tree: list[SessionTreeNode]
|
|
407
|
+
leafId: str | None
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
class _CommandBase(TypedDict):
|
|
411
|
+
id: NotRequired[str]
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
class PromptCommand(_CommandBase):
|
|
415
|
+
type: Literal["prompt"]
|
|
416
|
+
message: str
|
|
417
|
+
images: NotRequired[list[ImageContent]]
|
|
418
|
+
streamingBehavior: NotRequired[StreamingBehavior]
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
class QueueMessageCommand(_CommandBase):
|
|
422
|
+
type: Literal["steer", "follow_up"]
|
|
423
|
+
message: str
|
|
424
|
+
images: NotRequired[list[ImageContent]]
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
class EmptyCommand(_CommandBase):
|
|
428
|
+
"""Commands with no arguments beyond the envelope."""
|
|
429
|
+
|
|
430
|
+
type: Literal[
|
|
431
|
+
"abort",
|
|
432
|
+
"clear_queue",
|
|
433
|
+
"get_state",
|
|
434
|
+
"cycle_model",
|
|
435
|
+
"get_available_models",
|
|
436
|
+
"cycle_thinking_level",
|
|
437
|
+
"get_available_thinking_levels",
|
|
438
|
+
"abort_retry",
|
|
439
|
+
"abort_bash",
|
|
440
|
+
"get_session_stats",
|
|
441
|
+
"clone",
|
|
442
|
+
"get_fork_messages",
|
|
443
|
+
"get_tree",
|
|
444
|
+
"get_last_assistant_text",
|
|
445
|
+
"get_messages",
|
|
446
|
+
"get_commands",
|
|
447
|
+
]
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
class NewSessionCommand(_CommandBase):
|
|
451
|
+
type: Literal["new_session"]
|
|
452
|
+
parentSession: NotRequired[str]
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
class SetModelCommand(_CommandBase):
|
|
456
|
+
type: Literal["set_model"]
|
|
457
|
+
provider: str
|
|
458
|
+
modelId: str
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
class SetThinkingLevelCommand(_CommandBase):
|
|
462
|
+
type: Literal["set_thinking_level"]
|
|
463
|
+
level: ThinkingLevel
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
class SetQueueModeCommand(_CommandBase):
|
|
467
|
+
type: Literal["set_steering_mode", "set_follow_up_mode"]
|
|
468
|
+
mode: QueueMode
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
class CompactCommand(_CommandBase):
|
|
472
|
+
type: Literal["compact"]
|
|
473
|
+
customInstructions: NotRequired[str]
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
class SetAutomaticCommand(_CommandBase):
|
|
477
|
+
type: Literal["set_auto_compaction", "set_auto_retry"]
|
|
478
|
+
enabled: bool
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
class BashCommand(_CommandBase):
|
|
482
|
+
type: Literal["bash"]
|
|
483
|
+
command: str
|
|
484
|
+
excludeFromContext: NotRequired[bool]
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
class ExportHtmlCommand(_CommandBase):
|
|
488
|
+
type: Literal["export_html"]
|
|
489
|
+
outputPath: NotRequired[str]
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
class SwitchSessionCommand(_CommandBase):
|
|
493
|
+
type: Literal["switch_session"]
|
|
494
|
+
sessionPath: str
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
class ForkCommand(_CommandBase):
|
|
498
|
+
type: Literal["fork"]
|
|
499
|
+
entryId: str
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
class GetEntriesCommand(_CommandBase):
|
|
503
|
+
type: Literal["get_entries"]
|
|
504
|
+
since: NotRequired[str]
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
class SetSessionNameCommand(_CommandBase):
|
|
508
|
+
type: Literal["set_session_name"]
|
|
509
|
+
name: str
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
RpcCommand: TypeAlias = (
|
|
513
|
+
PromptCommand
|
|
514
|
+
| QueueMessageCommand
|
|
515
|
+
| EmptyCommand
|
|
516
|
+
| NewSessionCommand
|
|
517
|
+
| SetModelCommand
|
|
518
|
+
| SetThinkingLevelCommand
|
|
519
|
+
| SetQueueModeCommand
|
|
520
|
+
| CompactCommand
|
|
521
|
+
| SetAutomaticCommand
|
|
522
|
+
| BashCommand
|
|
523
|
+
| ExportHtmlCommand
|
|
524
|
+
| SwitchSessionCommand
|
|
525
|
+
| ForkCommand
|
|
526
|
+
| GetEntriesCommand
|
|
527
|
+
| SetSessionNameCommand
|
|
528
|
+
)
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
class AcceptanceReceipt(TypedDict):
|
|
532
|
+
"""Successful prompt acknowledgement; it says nothing about run disposition."""
|
|
533
|
+
|
|
534
|
+
type: Literal["response"]
|
|
535
|
+
id: str
|
|
536
|
+
command: Literal["prompt"]
|
|
537
|
+
success: Literal[True]
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
class RpcSuccessResponse(TypedDict):
|
|
541
|
+
type: Literal["response"]
|
|
542
|
+
id: NotRequired[str]
|
|
543
|
+
command: str
|
|
544
|
+
success: Literal[True]
|
|
545
|
+
data: NotRequired[JSONValue]
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
class RpcErrorResponse(TypedDict):
|
|
549
|
+
type: Literal["response"]
|
|
550
|
+
id: NotRequired[str]
|
|
551
|
+
command: str
|
|
552
|
+
success: Literal[False]
|
|
553
|
+
error: str
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
RpcResponse: TypeAlias = RpcSuccessResponse | RpcErrorResponse
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
class AssistantStartEvent(TypedDict):
|
|
560
|
+
type: Literal["start"]
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
class ContentStartEvent(TypedDict):
|
|
564
|
+
type: Literal["text_start", "thinking_start"]
|
|
565
|
+
contentIndex: float
|
|
566
|
+
|
|
567
|
+
|
|
568
|
+
class ContentDeltaEvent(TypedDict):
|
|
569
|
+
type: Literal["text_delta", "thinking_delta", "toolcall_delta"]
|
|
570
|
+
contentIndex: float
|
|
571
|
+
delta: str
|
|
572
|
+
|
|
573
|
+
|
|
574
|
+
class ContentEndEvent(TypedDict):
|
|
575
|
+
type: Literal["text_end", "thinking_end"]
|
|
576
|
+
contentIndex: float
|
|
577
|
+
content: str
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
class ToolCallStartEvent(TypedDict):
|
|
581
|
+
type: Literal["toolcall_start"]
|
|
582
|
+
contentIndex: float
|
|
583
|
+
id: str
|
|
584
|
+
toolName: str
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
class ToolCallEndEvent(TypedDict):
|
|
588
|
+
type: Literal["toolcall_end"]
|
|
589
|
+
contentIndex: float
|
|
590
|
+
toolCall: ToolCall
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
class AssistantDoneEvent(TypedDict):
|
|
594
|
+
type: Literal["done"]
|
|
595
|
+
reason: Literal["stop", "length", "toolUse", "deferred"]
|
|
596
|
+
message: AssistantMessage
|
|
597
|
+
|
|
598
|
+
|
|
599
|
+
class AssistantErrorEvent(TypedDict):
|
|
600
|
+
type: Literal["error"]
|
|
601
|
+
reason: Literal["aborted", "error"]
|
|
602
|
+
error: AssistantMessage
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
AssistantMessageEvent: TypeAlias = (
|
|
606
|
+
AssistantStartEvent
|
|
607
|
+
| ContentStartEvent
|
|
608
|
+
| ContentDeltaEvent
|
|
609
|
+
| ContentEndEvent
|
|
610
|
+
| ToolCallStartEvent
|
|
611
|
+
| ToolCallEndEvent
|
|
612
|
+
| AssistantDoneEvent
|
|
613
|
+
| AssistantErrorEvent
|
|
614
|
+
)
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
class EmptySessionEvent(TypedDict):
|
|
618
|
+
type: Literal["agent_start", "agent_settled", "turn_start", "summarization_retry_finished"]
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
class AgentEndEvent(TypedDict):
|
|
622
|
+
type: Literal["agent_end"]
|
|
623
|
+
messages: list[AgentMessage]
|
|
624
|
+
willRetry: bool
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
class TurnEndEvent(TypedDict):
|
|
628
|
+
type: Literal["turn_end"]
|
|
629
|
+
message: AgentMessage
|
|
630
|
+
toolResults: list[ToolResultMessage]
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
class MessageBoundaryEvent(TypedDict):
|
|
634
|
+
type: Literal["message_start", "message_end"]
|
|
635
|
+
message: AgentMessage
|
|
636
|
+
|
|
637
|
+
|
|
638
|
+
class MessageUpdateEvent(TypedDict):
|
|
639
|
+
"""Serialized shape: Pi removes cumulative message/partial snapshots."""
|
|
640
|
+
|
|
641
|
+
type: Literal["message_update"]
|
|
642
|
+
usage: Usage
|
|
643
|
+
assistantMessageEvent: AssistantMessageEvent
|
|
644
|
+
|
|
645
|
+
|
|
646
|
+
class ToolExecutionStartEvent(TypedDict):
|
|
647
|
+
type: Literal["tool_execution_start"]
|
|
648
|
+
toolCallId: str
|
|
649
|
+
toolName: str
|
|
650
|
+
args: JSONValue
|
|
651
|
+
|
|
652
|
+
|
|
653
|
+
class ToolExecutionUpdateEvent(TypedDict):
|
|
654
|
+
type: Literal["tool_execution_update"]
|
|
655
|
+
toolCallId: str
|
|
656
|
+
toolName: str
|
|
657
|
+
args: JSONValue
|
|
658
|
+
partialResult: JSONValue
|
|
659
|
+
|
|
660
|
+
|
|
661
|
+
class ToolExecutionEndEvent(TypedDict):
|
|
662
|
+
type: Literal["tool_execution_end"]
|
|
663
|
+
toolCallId: str
|
|
664
|
+
toolName: str
|
|
665
|
+
result: JSONValue
|
|
666
|
+
isError: bool
|
|
667
|
+
|
|
668
|
+
|
|
669
|
+
class QueueUpdateEvent(QueueState):
|
|
670
|
+
type: Literal["queue_update"]
|
|
671
|
+
|
|
672
|
+
|
|
673
|
+
class CompactionStartEvent(TypedDict):
|
|
674
|
+
type: Literal["compaction_start"]
|
|
675
|
+
reason: CompactionReason
|
|
676
|
+
|
|
677
|
+
|
|
678
|
+
class CompactionEndEvent(TypedDict):
|
|
679
|
+
type: Literal["compaction_end"]
|
|
680
|
+
reason: CompactionReason
|
|
681
|
+
result: NotRequired[CompactionResult]
|
|
682
|
+
aborted: bool
|
|
683
|
+
willRetry: bool
|
|
684
|
+
errorMessage: NotRequired[str]
|
|
685
|
+
|
|
686
|
+
|
|
687
|
+
class EntryAppendedEvent(TypedDict):
|
|
688
|
+
type: Literal["entry_appended"]
|
|
689
|
+
entry: SessionEntry
|
|
690
|
+
|
|
691
|
+
|
|
692
|
+
class SessionInfoChangedEvent(TypedDict):
|
|
693
|
+
type: Literal["session_info_changed"]
|
|
694
|
+
name: NotRequired[str]
|
|
695
|
+
|
|
696
|
+
|
|
697
|
+
class ThinkingLevelChangedEvent(TypedDict):
|
|
698
|
+
type: Literal["thinking_level_changed"]
|
|
699
|
+
level: ThinkingLevel
|
|
700
|
+
|
|
701
|
+
|
|
702
|
+
class RetryStartEvent(TypedDict):
|
|
703
|
+
type: Literal["auto_retry_start", "summarization_retry_scheduled"]
|
|
704
|
+
attempt: float
|
|
705
|
+
maxAttempts: float
|
|
706
|
+
delayMs: float
|
|
707
|
+
errorMessage: str
|
|
708
|
+
|
|
709
|
+
|
|
710
|
+
class AutoRetryEndEvent(TypedDict):
|
|
711
|
+
type: Literal["auto_retry_end"]
|
|
712
|
+
success: bool
|
|
713
|
+
attempt: float
|
|
714
|
+
finalError: NotRequired[str]
|
|
715
|
+
|
|
716
|
+
|
|
717
|
+
class CompactionRetryAttemptEvent(TypedDict):
|
|
718
|
+
type: Literal["summarization_retry_attempt_start"]
|
|
719
|
+
source: Literal["compaction"]
|
|
720
|
+
reason: CompactionReason
|
|
721
|
+
|
|
722
|
+
|
|
723
|
+
class BranchRetryAttemptEvent(TypedDict):
|
|
724
|
+
type: Literal["summarization_retry_attempt_start"]
|
|
725
|
+
source: Literal["branchSummary"]
|
|
726
|
+
|
|
727
|
+
|
|
728
|
+
class BashExecutionUpdateEvent(TypedDict):
|
|
729
|
+
type: Literal["bash_execution_update"]
|
|
730
|
+
id: NotRequired[str]
|
|
731
|
+
delta: str
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
SessionEvent: TypeAlias = (
|
|
735
|
+
EmptySessionEvent
|
|
736
|
+
| AgentEndEvent
|
|
737
|
+
| TurnEndEvent
|
|
738
|
+
| MessageBoundaryEvent
|
|
739
|
+
| MessageUpdateEvent
|
|
740
|
+
| ToolExecutionStartEvent
|
|
741
|
+
| ToolExecutionUpdateEvent
|
|
742
|
+
| ToolExecutionEndEvent
|
|
743
|
+
| QueueUpdateEvent
|
|
744
|
+
| CompactionStartEvent
|
|
745
|
+
| CompactionEndEvent
|
|
746
|
+
| EntryAppendedEvent
|
|
747
|
+
| SessionInfoChangedEvent
|
|
748
|
+
| ThinkingLevelChangedEvent
|
|
749
|
+
| RetryStartEvent
|
|
750
|
+
| AutoRetryEndEvent
|
|
751
|
+
| CompactionRetryAttemptEvent
|
|
752
|
+
| BranchRetryAttemptEvent
|
|
753
|
+
| BashExecutionUpdateEvent
|
|
754
|
+
)
|
|
755
|
+
|
|
756
|
+
|
|
757
|
+
class ExtensionErrorEvent(TypedDict):
|
|
758
|
+
type: Literal["extension_error"]
|
|
759
|
+
extensionPath: str
|
|
760
|
+
event: str
|
|
761
|
+
error: str
|
|
762
|
+
|
|
763
|
+
|
|
764
|
+
class _UIRequestBase(TypedDict):
|
|
765
|
+
type: Literal["extension_ui_request"]
|
|
766
|
+
id: str
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
class UISelectRequest(_UIRequestBase):
|
|
770
|
+
method: Literal["select"]
|
|
771
|
+
title: str
|
|
772
|
+
options: list[str]
|
|
773
|
+
timeout: NotRequired[float]
|
|
774
|
+
|
|
775
|
+
|
|
776
|
+
class UIConfirmRequest(_UIRequestBase):
|
|
777
|
+
method: Literal["confirm"]
|
|
778
|
+
title: str
|
|
779
|
+
message: str
|
|
780
|
+
timeout: NotRequired[float]
|
|
781
|
+
|
|
782
|
+
|
|
783
|
+
class UIInputRequest(_UIRequestBase):
|
|
784
|
+
method: Literal["input"]
|
|
785
|
+
title: str
|
|
786
|
+
placeholder: NotRequired[str]
|
|
787
|
+
timeout: NotRequired[float]
|
|
788
|
+
|
|
789
|
+
|
|
790
|
+
class UIEditorRequest(_UIRequestBase):
|
|
791
|
+
method: Literal["editor"]
|
|
792
|
+
title: str
|
|
793
|
+
prefill: NotRequired[str]
|
|
794
|
+
|
|
795
|
+
|
|
796
|
+
class UINotifyRequest(_UIRequestBase):
|
|
797
|
+
method: Literal["notify"]
|
|
798
|
+
message: str
|
|
799
|
+
notifyType: NotRequired[Literal["info", "warning", "error"]]
|
|
800
|
+
|
|
801
|
+
|
|
802
|
+
class UISetStatusRequest(_UIRequestBase):
|
|
803
|
+
method: Literal["setStatus"]
|
|
804
|
+
statusKey: str
|
|
805
|
+
statusText: NotRequired[str]
|
|
806
|
+
|
|
807
|
+
|
|
808
|
+
class UISetWidgetRequest(_UIRequestBase):
|
|
809
|
+
method: Literal["setWidget"]
|
|
810
|
+
widgetKey: str
|
|
811
|
+
widgetLines: NotRequired[list[str]]
|
|
812
|
+
widgetPlacement: NotRequired[Literal["aboveEditor", "belowEditor"]]
|
|
813
|
+
|
|
814
|
+
|
|
815
|
+
class UISetTitleRequest(_UIRequestBase):
|
|
816
|
+
method: Literal["setTitle"]
|
|
817
|
+
title: str
|
|
818
|
+
|
|
819
|
+
|
|
820
|
+
class UISetEditorTextRequest(_UIRequestBase):
|
|
821
|
+
method: Literal["set_editor_text"]
|
|
822
|
+
text: str
|
|
823
|
+
|
|
824
|
+
|
|
825
|
+
ExtensionUIRequest: TypeAlias = (
|
|
826
|
+
UISelectRequest
|
|
827
|
+
| UIConfirmRequest
|
|
828
|
+
| UIInputRequest
|
|
829
|
+
| UIEditorRequest
|
|
830
|
+
| UINotifyRequest
|
|
831
|
+
| UISetStatusRequest
|
|
832
|
+
| UISetWidgetRequest
|
|
833
|
+
| UISetTitleRequest
|
|
834
|
+
| UISetEditorTextRequest
|
|
835
|
+
)
|
|
836
|
+
|
|
837
|
+
|
|
838
|
+
class _UIResponseBase(TypedDict):
|
|
839
|
+
type: Literal["extension_ui_response"]
|
|
840
|
+
id: str
|
|
841
|
+
|
|
842
|
+
|
|
843
|
+
class UIValueResponse(_UIResponseBase):
|
|
844
|
+
value: str
|
|
845
|
+
|
|
846
|
+
|
|
847
|
+
class UIConfirmResponse(_UIResponseBase):
|
|
848
|
+
confirmed: bool
|
|
849
|
+
|
|
850
|
+
|
|
851
|
+
class UICancelResponse(_UIResponseBase):
|
|
852
|
+
cancelled: Literal[True]
|
|
853
|
+
|
|
854
|
+
|
|
855
|
+
ExtensionUIResponse: TypeAlias = UIValueResponse | UIConfirmResponse | UICancelResponse
|
|
856
|
+
RpcEvent: TypeAlias = SessionEvent | ExtensionErrorEvent | ExtensionUIRequest
|
|
857
|
+
|
|
858
|
+
|
|
859
|
+
@dataclass(frozen=True)
|
|
860
|
+
class Event:
|
|
861
|
+
"""An unconverted event; raw preserves unknown fields and is omitted from repr."""
|
|
862
|
+
|
|
863
|
+
raw: RawRecord = field(repr=False)
|
|
864
|
+
|
|
865
|
+
@property
|
|
866
|
+
def type(self) -> str:
|
|
867
|
+
value = self.raw.get("type")
|
|
868
|
+
return value if isinstance(value, str) else ""
|
|
869
|
+
|
|
870
|
+
@property
|
|
871
|
+
def text_delta(self) -> str | None:
|
|
872
|
+
if self.type != "message_update":
|
|
873
|
+
return None
|
|
874
|
+
nested = self.raw.get("assistantMessageEvent")
|
|
875
|
+
if isinstance(nested, dict) and nested.get("type") == "text_delta":
|
|
876
|
+
delta = nested.get("delta")
|
|
877
|
+
if not isinstance(delta, str):
|
|
878
|
+
raise PiProtocolError("text_delta requires a string delta")
|
|
879
|
+
return delta
|
|
880
|
+
return None
|
|
881
|
+
|
|
882
|
+
|
|
883
|
+
@dataclass(frozen=True)
|
|
884
|
+
class SessionInfo:
|
|
885
|
+
"""Session identity snapshot; paths and names are omitted from repr."""
|
|
886
|
+
|
|
887
|
+
session_id: str | None = None
|
|
888
|
+
session_file: str | None = field(default=None, repr=False)
|
|
889
|
+
session_name: str | None = field(default=None, repr=False)
|
|
890
|
+
|
|
891
|
+
|
|
892
|
+
@dataclass(frozen=True)
|
|
893
|
+
class UsageSummary:
|
|
894
|
+
"""Observed assistant usage, not total billing; None means unknown.
|
|
895
|
+
|
|
896
|
+
Reasoning is a subset of output_tokens. It must not be added again.
|
|
897
|
+
A field remains unknown if any observed assistant omitted that measurement.
|
|
898
|
+
"""
|
|
899
|
+
|
|
900
|
+
input_tokens: int | None = None
|
|
901
|
+
output_tokens: int | None = None
|
|
902
|
+
cache_read_tokens: int | None = None
|
|
903
|
+
cache_write_tokens: int | None = None
|
|
904
|
+
cache_write_1h_tokens: int | None = None
|
|
905
|
+
reasoning_tokens: int | None = None
|
|
906
|
+
total_tokens: int | None = None
|
|
907
|
+
cost: float | None = None
|
|
908
|
+
assistant_messages: int = 0
|
|
909
|
+
|
|
910
|
+
|
|
911
|
+
@dataclass(frozen=True)
|
|
912
|
+
class RunResult:
|
|
913
|
+
"""Finalized messages from one settled run, including partial failed work.
|
|
914
|
+
|
|
915
|
+
Session is the identity current at completion, not an attribution of each
|
|
916
|
+
event. Text and messages can contain sensitive content and are not in repr.
|
|
917
|
+
"""
|
|
918
|
+
|
|
919
|
+
text: str = field(repr=False)
|
|
920
|
+
messages: list[RawRecord] = field(repr=False)
|
|
921
|
+
stop_reason: str | None
|
|
922
|
+
session: SessionInfo
|
|
923
|
+
elapsed_seconds: float
|
|
924
|
+
usage: UsageSummary | None = None
|
|
925
|
+
|
|
926
|
+
|
|
927
|
+
@dataclass(frozen=True)
|
|
928
|
+
class Limits:
|
|
929
|
+
"""Client deadlines (seconds) and bounded transport/subscription storage."""
|
|
930
|
+
|
|
931
|
+
startup_timeout: float = 30.0
|
|
932
|
+
command_timeout: float = 30.0
|
|
933
|
+
run_start_timeout: float = 30.0
|
|
934
|
+
cleanup_timeout: float = 5.0
|
|
935
|
+
max_record_bytes: int = 16 * 1024 * 1024
|
|
936
|
+
event_queue_size: int = 256
|
|
937
|
+
event_queue_bytes: int = 16 * 1024 * 1024
|
|
938
|
+
stderr_tail_bytes: int = 0
|
|
939
|
+
result_message_count: int = 4096
|
|
940
|
+
result_message_bytes: int = 64 * 1024 * 1024
|
|
941
|
+
|
|
942
|
+
def __post_init__(self) -> None:
|
|
943
|
+
for descriptor in fields(self):
|
|
944
|
+
name = descriptor.name
|
|
945
|
+
value = getattr(self, name)
|
|
946
|
+
if name.endswith("timeout"):
|
|
947
|
+
if (
|
|
948
|
+
isinstance(value, bool)
|
|
949
|
+
or not isinstance(value, (int, float))
|
|
950
|
+
or not math.isfinite(value)
|
|
951
|
+
or value <= 0
|
|
952
|
+
):
|
|
953
|
+
raise ValueError(f"{name} must be a positive finite number")
|
|
954
|
+
elif (
|
|
955
|
+
isinstance(value, bool)
|
|
956
|
+
or not isinstance(value, int)
|
|
957
|
+
or value < (0 if name == "stderr_tail_bytes" else 1)
|
|
958
|
+
):
|
|
959
|
+
minimum = "nonnegative" if name == "stderr_tail_bytes" else "positive"
|
|
960
|
+
raise ValueError(f"{name} must be a {minimum} integer")
|