pi-ai-python 1.3.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 +127 -0
- pi_agent/agent.py +617 -0
- pi_agent/agent_loop.py +820 -0
- pi_agent/proxy.py +269 -0
- pi_agent/py.typed +0 -0
- pi_agent/stream_fn.py +27 -0
- pi_agent/tools.py +327 -0
- pi_agent/types.py +394 -0
- pi_ai/__init__.py +263 -0
- pi_ai/abort.py +315 -0
- pi_ai/api/__init__.py +1 -0
- pi_ai/api/anthropic_messages.py +1782 -0
- pi_ai/api/azure_openai_config.py +138 -0
- pi_ai/api/azure_openai_responses.py +245 -0
- pi_ai/api/bedrock_converse_stream.py +1598 -0
- pi_ai/api/classifier_shared.py +211 -0
- pi_ai/api/cloudflare.py +36 -0
- pi_ai/api/cloudflare_workers_ai_system_one.py +80 -0
- pi_ai/api/constrained_sampling.py +279 -0
- pi_ai/api/github_copilot_headers.py +30 -0
- pi_ai/api/google_generative_ai.py +138 -0
- pi_ai/api/google_shared.py +927 -0
- pi_ai/api/google_vertex.py +234 -0
- pi_ai/api/lazy.py +156 -0
- pi_ai/api/llama_cpp_classify.py +449 -0
- pi_ai/api/mistral_conversations.py +756 -0
- pi_ai/api/openai_codex_responses.py +1545 -0
- pi_ai/api/openai_completions.py +1594 -0
- pi_ai/api/openai_decisions.py +210 -0
- pi_ai/api/openai_prompt_cache.py +19 -0
- pi_ai/api/openai_responses.py +418 -0
- pi_ai/api/openai_responses_shared.py +840 -0
- pi_ai/api/openai_sdk.py +204 -0
- pi_ai/api/openrouter_images.py +153 -0
- pi_ai/api/pi_messages.py +449 -0
- pi_ai/api/registry.py +103 -0
- pi_ai/api/simple_options.py +119 -0
- pi_ai/api/system_one_shared.py +148 -0
- pi_ai/api/transform_messages.py +211 -0
- pi_ai/api/typesafe_system_one.py +43 -0
- pi_ai/auth/__init__.py +1 -0
- pi_ai/auth/context.py +47 -0
- pi_ai/auth/credential_store.py +208 -0
- pi_ai/auth/helpers.py +123 -0
- pi_ai/auth/oauth/__init__.py +5 -0
- pi_ai/auth/oauth/_common.py +454 -0
- pi_ai/auth/oauth/anthropic.py +283 -0
- pi_ai/auth/oauth/callback_server.py +339 -0
- pi_ai/auth/oauth/device_code.py +127 -0
- pi_ai/auth/oauth/github_copilot.py +508 -0
- pi_ai/auth/oauth/kimi_coding.py +283 -0
- pi_ai/auth/oauth/load.py +64 -0
- pi_ai/auth/oauth/meta.py +238 -0
- pi_ai/auth/oauth/openai_chatgpt.py +321 -0
- pi_ai/auth/oauth/openai_codex.py +391 -0
- pi_ai/auth/oauth/openrouter.py +173 -0
- pi_ai/auth/oauth/pkce.py +23 -0
- pi_ai/auth/oauth/radius.py +311 -0
- pi_ai/auth/oauth/xai.py +220 -0
- pi_ai/auth/resolve.py +190 -0
- pi_ai/auth/types.py +292 -0
- pi_ai/cli.py +265 -0
- pi_ai/compat.py +651 -0
- pi_ai/env_api_keys.py +137 -0
- pi_ai/event_stream.py +329 -0
- pi_ai/models.py +1191 -0
- pi_ai/models_store.py +121 -0
- pi_ai/oauth.py +90 -0
- pi_ai/providers/__init__.py +1 -0
- pi_ai/providers/all.py +154 -0
- pi_ai/providers/amazon_bedrock.py +116 -0
- pi_ai/providers/ant_ling.py +23 -0
- pi_ai/providers/anthropic.py +105 -0
- pi_ai/providers/azure.py +103 -0
- pi_ai/providers/baseten.py +23 -0
- pi_ai/providers/catalog.py +167 -0
- pi_ai/providers/cerebras.py +23 -0
- pi_ai/providers/cloudflare_ai_gateway.py +30 -0
- pi_ai/providers/cloudflare_auth.py +112 -0
- pi_ai/providers/cloudflare_stream.py +84 -0
- pi_ai/providers/cloudflare_workers_ai.py +26 -0
- pi_ai/providers/data/amazon-bedrock.json +1 -0
- pi_ai/providers/data/ant-ling.json +1 -0
- pi_ai/providers/data/anthropic.json +1 -0
- pi_ai/providers/data/azure.json +1 -0
- pi_ai/providers/data/baseten.json +1 -0
- pi_ai/providers/data/cerebras.json +1 -0
- pi_ai/providers/data/cloudflare-ai-gateway.json +1 -0
- pi_ai/providers/data/cloudflare-workers-ai.json +1 -0
- pi_ai/providers/data/deepseek.json +1 -0
- pi_ai/providers/data/fireworks.json +1 -0
- pi_ai/providers/data/github-copilot.json +1 -0
- pi_ai/providers/data/google-vertex.json +1 -0
- pi_ai/providers/data/google.json +1 -0
- pi_ai/providers/data/groq.json +1 -0
- pi_ai/providers/data/huggingface.json +1 -0
- pi_ai/providers/data/kimi-coding.json +1 -0
- pi_ai/providers/data/manifest.json +1 -0
- pi_ai/providers/data/meta.json +1 -0
- pi_ai/providers/data/minimax-cn.json +1 -0
- pi_ai/providers/data/minimax.json +1 -0
- pi_ai/providers/data/mistral.json +1 -0
- pi_ai/providers/data/moonshotai-cn.json +1 -0
- pi_ai/providers/data/moonshotai.json +1 -0
- pi_ai/providers/data/nvidia.json +1 -0
- pi_ai/providers/data/openai-codex.json +1 -0
- pi_ai/providers/data/openai.json +1 -0
- pi_ai/providers/data/opencode-go.json +1 -0
- pi_ai/providers/data/opencode.json +1 -0
- pi_ai/providers/data/openrouter.json +1 -0
- pi_ai/providers/data/qwen-token-plan-cn.json +1 -0
- pi_ai/providers/data/qwen-token-plan-individual.json +1 -0
- pi_ai/providers/data/qwen-token-plan.json +1 -0
- pi_ai/providers/data/radius.json +1 -0
- pi_ai/providers/data/together.json +1 -0
- pi_ai/providers/data/typesafe.json +1 -0
- pi_ai/providers/data/vercel-ai-gateway.json +1 -0
- pi_ai/providers/data/xai.json +1 -0
- pi_ai/providers/data/xiaomi-token-plan-ams.json +1 -0
- pi_ai/providers/data/xiaomi-token-plan-cn.json +1 -0
- pi_ai/providers/data/xiaomi-token-plan-sgp.json +1 -0
- pi_ai/providers/data/xiaomi.json +1 -0
- pi_ai/providers/data/zai-coding-cn.json +1 -0
- pi_ai/providers/data/zai.json +1 -0
- pi_ai/providers/deepseek.py +23 -0
- pi_ai/providers/faux.py +680 -0
- pi_ai/providers/fireworks.py +26 -0
- pi_ai/providers/github_copilot.py +46 -0
- pi_ai/providers/google.py +23 -0
- pi_ai/providers/google_vertex.py +131 -0
- pi_ai/providers/groq.py +23 -0
- pi_ai/providers/huggingface.py +23 -0
- pi_ai/providers/kimi_coding.py +32 -0
- pi_ai/providers/meta.py +32 -0
- pi_ai/providers/minimax.py +23 -0
- pi_ai/providers/minimax_cn.py +23 -0
- pi_ai/providers/mistral.py +23 -0
- pi_ai/providers/moonshotai.py +23 -0
- pi_ai/providers/moonshotai_cn.py +23 -0
- pi_ai/providers/nvidia.py +23 -0
- pi_ai/providers/openai.py +44 -0
- pi_ai/providers/openai_codex.py +26 -0
- pi_ai/providers/opencode.py +36 -0
- pi_ai/providers/opencode_go.py +33 -0
- pi_ai/providers/opencode_headers.py +60 -0
- pi_ai/providers/openrouter.py +145 -0
- pi_ai/providers/openrouter_api.py +122 -0
- pi_ai/providers/qwen_token_plan.py +23 -0
- pi_ai/providers/qwen_token_plan_cn.py +23 -0
- pi_ai/providers/qwen_token_plan_individual.py +23 -0
- pi_ai/providers/radius.py +146 -0
- pi_ai/providers/radius_config.py +136 -0
- pi_ai/providers/together.py +23 -0
- pi_ai/providers/typesafe.py +22 -0
- pi_ai/providers/vercel_ai_gateway.py +25 -0
- pi_ai/providers/xai.py +32 -0
- pi_ai/providers/xiaomi.py +23 -0
- pi_ai/providers/xiaomi_token_plan_ams.py +23 -0
- pi_ai/providers/xiaomi_token_plan_cn.py +23 -0
- pi_ai/providers/xiaomi_token_plan_sgp.py +23 -0
- pi_ai/providers/zai.py +23 -0
- pi_ai/providers/zai_coding_cn.py +23 -0
- pi_ai/py.typed +0 -0
- pi_ai/serialization.py +477 -0
- pi_ai/session_resources.py +33 -0
- pi_ai/types.py +1003 -0
- pi_ai/utils/__init__.py +1 -0
- pi_ai/utils/callbacks.py +15 -0
- pi_ai/utils/diagnostics.py +70 -0
- pi_ai/utils/error_body.py +89 -0
- pi_ai/utils/estimate.py +125 -0
- pi_ai/utils/fastjson.py +63 -0
- pi_ai/utils/http.py +409 -0
- pi_ai/utils/json_parse.py +424 -0
- pi_ai/utils/misc.py +193 -0
- pi_ai/utils/model_operations.py +73 -0
- pi_ai/utils/models_error.py +35 -0
- pi_ai/utils/oauth_page.py +121 -0
- pi_ai/utils/overflow.py +87 -0
- pi_ai/utils/retry.py +193 -0
- pi_ai/utils/schema.py +283 -0
- pi_ai/utils/text.py +65 -0
- pi_ai/utils/transcript.py +271 -0
- pi_ai/utils/validation.py +813 -0
- pi_ai_python-1.3.0.dist-info/METADATA +167 -0
- pi_ai_python-1.3.0.dist-info/RECORD +189 -0
- pi_ai_python-1.3.0.dist-info/WHEEL +4 -0
- pi_ai_python-1.3.0.dist-info/entry_points.txt +2 -0
- pi_ai_python-1.3.0.dist-info/licenses/LICENSE +22 -0
pi_agent/types.py
ADDED
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
"""Types for the agent runtime (mirrors ``@earendil-works/pi-agent-core`` ``src/types.ts``)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Awaitable, Callable, Mapping
|
|
6
|
+
from dataclasses import KW_ONLY, dataclass, field
|
|
7
|
+
from typing import TYPE_CHECKING, Any, ClassVar, Literal, Protocol, TypeAlias
|
|
8
|
+
|
|
9
|
+
from pi_ai import (
|
|
10
|
+
AbortSignal,
|
|
11
|
+
AssistantMessage,
|
|
12
|
+
AssistantMessageEvent,
|
|
13
|
+
AssistantMessageEventStream,
|
|
14
|
+
ImageContent,
|
|
15
|
+
Message,
|
|
16
|
+
Model,
|
|
17
|
+
TextContent,
|
|
18
|
+
Tool,
|
|
19
|
+
ToolCall,
|
|
20
|
+
ToolResultMessage,
|
|
21
|
+
TranscriptContext,
|
|
22
|
+
Usage,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
__all__ = [
|
|
29
|
+
"StreamFn",
|
|
30
|
+
"ToolExecutionMode",
|
|
31
|
+
"QueueMode",
|
|
32
|
+
"ThinkingLevel",
|
|
33
|
+
"AgentToolCall",
|
|
34
|
+
"AgentMessage",
|
|
35
|
+
"BeforeToolCallResult",
|
|
36
|
+
"AfterToolCallResult",
|
|
37
|
+
"BeforeToolCallContext",
|
|
38
|
+
"AfterToolCallContext",
|
|
39
|
+
"AgentTurnContext",
|
|
40
|
+
"AgentTurnDecision",
|
|
41
|
+
"FinishTurn",
|
|
42
|
+
"AgentLoopTurnUpdate",
|
|
43
|
+
"PrepareRequestContext",
|
|
44
|
+
"AgentRequestUpdate",
|
|
45
|
+
"PrepareRequest",
|
|
46
|
+
"PrepareNextTurnContext",
|
|
47
|
+
"AgentLoopConfig",
|
|
48
|
+
"AgentToolResult",
|
|
49
|
+
"AgentToolCallOutcome",
|
|
50
|
+
"AgentToolUpdateCallback",
|
|
51
|
+
"AgentTool",
|
|
52
|
+
"AgentContext",
|
|
53
|
+
"AgentStartEvent",
|
|
54
|
+
"AgentEndEvent",
|
|
55
|
+
"TurnStartEvent",
|
|
56
|
+
"TurnEndEvent",
|
|
57
|
+
"MessageStartEvent",
|
|
58
|
+
"MessageUpdateEvent",
|
|
59
|
+
"MessageEndEvent",
|
|
60
|
+
"ToolExecutionStartEvent",
|
|
61
|
+
"ToolExecutionUpdateEvent",
|
|
62
|
+
"ToolExecutionEndEvent",
|
|
63
|
+
"AgentEvent",
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
#: Stream function used by the agent loop (``models.stream_simple`` satisfies it).
|
|
67
|
+
#:
|
|
68
|
+
#: It receives a normalized transcript (prompt and tools live in system messages) and
|
|
69
|
+
#: must encode failures in the returned stream instead of raising.
|
|
70
|
+
StreamFn: TypeAlias = Callable[
|
|
71
|
+
[Model, TranscriptContext, "Mapping[str, Any] | None"],
|
|
72
|
+
"AssistantMessageEventStream | Awaitable[AssistantMessageEventStream]",
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
#: ``sequential``: each tool call is prepared, executed and finalized before the next starts.
|
|
76
|
+
#: ``parallel``: tool calls are prepared sequentially, then allowed tools execute concurrently.
|
|
77
|
+
ToolExecutionMode: TypeAlias = Literal["sequential", "parallel"]
|
|
78
|
+
|
|
79
|
+
#: How many queued messages are injected at a drain point: every message, or only the oldest.
|
|
80
|
+
QueueMode: TypeAlias = Literal["all", "one-at-a-time"]
|
|
81
|
+
|
|
82
|
+
ThinkingLevel: TypeAlias = Literal["off", "minimal", "low", "medium", "high", "xhigh", "max"]
|
|
83
|
+
|
|
84
|
+
AgentToolCall: TypeAlias = ToolCall
|
|
85
|
+
|
|
86
|
+
#: Any message in an agent transcript: the LLM messages plus app-defined custom
|
|
87
|
+
#: messages (any object with a ``role`` attribute, e.g. a dataclass).
|
|
88
|
+
AgentMessage: TypeAlias = Any
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@dataclass(slots=True)
|
|
92
|
+
class BeforeToolCallResult:
|
|
93
|
+
"""Returned from ``before_tool_call``. ``block=True`` prevents execution with an error result."""
|
|
94
|
+
|
|
95
|
+
block: bool = False
|
|
96
|
+
#: Text of the error result when blocked. Defaults to "Tool execution was blocked".
|
|
97
|
+
reason: str | None = None
|
|
98
|
+
#: Hint to stop after the current tool batch when blocked (only when every result in the batch terminates).
|
|
99
|
+
terminate: bool | None = None
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@dataclass(slots=True)
|
|
103
|
+
class AfterToolCallResult:
|
|
104
|
+
"""Partial override returned from ``after_tool_call``; omitted (``None``) fields keep their values.
|
|
105
|
+
|
|
106
|
+
``content`` without ``structured_content`` drops the original structured content, because it
|
|
107
|
+
may no longer match. No deep merge is performed.
|
|
108
|
+
"""
|
|
109
|
+
|
|
110
|
+
content: list[TextContent | ImageContent] | None = None
|
|
111
|
+
details: Any = None
|
|
112
|
+
structured_content: Any = None
|
|
113
|
+
is_error: bool | None = None
|
|
114
|
+
usage: Usage | None = None
|
|
115
|
+
terminate: bool | None = None
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
@dataclass(slots=True)
|
|
119
|
+
class BeforeToolCallContext:
|
|
120
|
+
assistant_message: AssistantMessage
|
|
121
|
+
tool_call: ToolCall
|
|
122
|
+
#: Validated tool arguments.
|
|
123
|
+
args: Any
|
|
124
|
+
context: AgentContext
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@dataclass(slots=True)
|
|
128
|
+
class AfterToolCallContext:
|
|
129
|
+
assistant_message: AssistantMessage
|
|
130
|
+
tool_call: ToolCall
|
|
131
|
+
args: Any
|
|
132
|
+
#: The executed tool result before overrides are applied.
|
|
133
|
+
result: AgentToolResult
|
|
134
|
+
is_error: bool
|
|
135
|
+
context: AgentContext
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
@dataclass(slots=True)
|
|
139
|
+
class AgentTurnContext:
|
|
140
|
+
"""Context passed to completed-turn callbacks."""
|
|
141
|
+
|
|
142
|
+
message: AssistantMessage
|
|
143
|
+
tool_results: list[ToolResultMessage]
|
|
144
|
+
#: Agent context after the turn's assistant message and tool results were appended.
|
|
145
|
+
context: AgentContext
|
|
146
|
+
#: Messages this loop invocation returns if it exits now.
|
|
147
|
+
new_messages: list[Any]
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
PrepareNextTurnContext = AgentTurnContext
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
@dataclass(slots=True)
|
|
154
|
+
class AgentTurnDecision:
|
|
155
|
+
"""Decision returned by ``finish_turn``: ``"continue"`` or ``"end"``.
|
|
156
|
+
|
|
157
|
+
``finish_turn`` may also return the plain strings or ``{"action": ...}`` dicts.
|
|
158
|
+
"""
|
|
159
|
+
|
|
160
|
+
action: Literal["continue", "end"]
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
FinishTurn: TypeAlias = Callable[[AgentTurnContext, "AbortSignal | None"], Any]
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
@dataclass(slots=True)
|
|
167
|
+
class AgentLoopTurnUpdate:
|
|
168
|
+
"""Replacement runtime state used before starting another provider request."""
|
|
169
|
+
|
|
170
|
+
context: AgentContext | None = None
|
|
171
|
+
#: Messages to append before the next provider request, with normal lifecycle events.
|
|
172
|
+
messages: list[Any] | None = None
|
|
173
|
+
model: Model | None = None
|
|
174
|
+
thinking_level: ThinkingLevel | None = None
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
@dataclass(slots=True)
|
|
178
|
+
class PrepareRequestContext:
|
|
179
|
+
context: AgentContext
|
|
180
|
+
model: Model
|
|
181
|
+
thinking_level: ThinkingLevel
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
@dataclass(slots=True)
|
|
185
|
+
class AgentRequestUpdate:
|
|
186
|
+
"""Replacement runtime state for the provider request being prepared."""
|
|
187
|
+
|
|
188
|
+
context: AgentContext | None = None
|
|
189
|
+
model: Model | None = None
|
|
190
|
+
thinking_level: ThinkingLevel | None = None
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
PrepareRequest: TypeAlias = Callable[[PrepareRequestContext, "AbortSignal | None"], Any]
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
@dataclass(slots=True, kw_only=True)
|
|
197
|
+
class AgentLoopConfig:
|
|
198
|
+
"""Configuration of the low-level agent loop.
|
|
199
|
+
|
|
200
|
+
``stream_options`` holds the ``SimpleStreamOptions`` forwarded to the stream function
|
|
201
|
+
(``session_id``, ``transport``, ``thinking_budgets``, ``on_payload``, ``temperature``...).
|
|
202
|
+
"""
|
|
203
|
+
|
|
204
|
+
model: Model
|
|
205
|
+
#: Convert agent messages to LLM messages before each call. Must not raise.
|
|
206
|
+
convert_to_llm: Callable[[list[Any]], list[Message] | Awaitable[list[Message]]]
|
|
207
|
+
#: Requested reasoning level (``None`` means off).
|
|
208
|
+
reasoning: ThinkingLevel | None = None
|
|
209
|
+
api_key: str | None = None
|
|
210
|
+
stream_options: dict[str, Any] = field(default_factory=dict)
|
|
211
|
+
#: Optional transform applied before ``convert_to_llm`` (pruning, context injection). Must not raise.
|
|
212
|
+
transform_context: Callable[[list[Any], AbortSignal | None], Awaitable[list[Any]]] | None = None
|
|
213
|
+
#: Resolve an API key per call (short-lived OAuth tokens). Must not raise.
|
|
214
|
+
get_api_key: Callable[[str], str | Awaitable[str | None] | None] | None = None
|
|
215
|
+
finish_turn: FinishTurn | None = None
|
|
216
|
+
prepare_request: PrepareRequest | None = None
|
|
217
|
+
prepare_next_turn: Callable[[AgentTurnContext], Any] | None = None
|
|
218
|
+
get_steering_messages: Callable[[], Awaitable[list[Any]]] | None = None
|
|
219
|
+
get_follow_up_messages: Callable[[], Awaitable[list[Any]]] | None = None
|
|
220
|
+
#: Default ``"parallel"``.
|
|
221
|
+
tool_execution: ToolExecutionMode = "parallel"
|
|
222
|
+
before_tool_call: (
|
|
223
|
+
Callable[[BeforeToolCallContext, AbortSignal | None], Awaitable[BeforeToolCallResult | None]] | None
|
|
224
|
+
) = None
|
|
225
|
+
after_tool_call: (
|
|
226
|
+
Callable[[AfterToolCallContext, AbortSignal | None], Awaitable[AfterToolCallResult | None]] | None
|
|
227
|
+
) = None
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
@dataclass(slots=True)
|
|
231
|
+
class AgentToolResult:
|
|
232
|
+
"""Final or partial result produced by a tool."""
|
|
233
|
+
|
|
234
|
+
#: Text or image content returned to the model.
|
|
235
|
+
content: list[TextContent | ImageContent] = field(default_factory=list)
|
|
236
|
+
#: Arbitrary structured details for logs or UI rendering.
|
|
237
|
+
details: Any = None
|
|
238
|
+
_: KW_ONLY
|
|
239
|
+
#: Machine-readable result matching the tool's ``output_schema``; not sent to the model.
|
|
240
|
+
structured_content: Any = None
|
|
241
|
+
usage: Usage | None = None
|
|
242
|
+
#: Report a failure without raising; ``details``/``structured_content`` are kept.
|
|
243
|
+
is_error: bool | None = None
|
|
244
|
+
#: Hint to stop after the current tool batch (only when every result in the batch terminates).
|
|
245
|
+
terminate: bool | None = None
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
@dataclass(slots=True)
|
|
249
|
+
class AgentToolCallOutcome:
|
|
250
|
+
tool_call: ToolCall
|
|
251
|
+
result: AgentToolResult
|
|
252
|
+
is_error: bool
|
|
253
|
+
#: Milliseconds ``execute()`` took; ``None`` when the tool did not run.
|
|
254
|
+
duration_ms: int | None = None
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
AgentToolUpdateCallback: TypeAlias = Callable[[AgentToolResult], Any]
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
class _Execute(Protocol):
|
|
261
|
+
def __call__(
|
|
262
|
+
self,
|
|
263
|
+
tool_call_id: str,
|
|
264
|
+
params: Any,
|
|
265
|
+
signal: AbortSignal | None = None,
|
|
266
|
+
on_update: AgentToolUpdateCallback | None = None,
|
|
267
|
+
) -> Awaitable[AgentToolResult]: ...
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
@dataclass(slots=True, kw_only=True)
|
|
271
|
+
class AgentTool(Tool):
|
|
272
|
+
"""A tool the agent can execute.
|
|
273
|
+
|
|
274
|
+
``execute(tool_call_id, params, signal, on_update)`` receives validated parameters
|
|
275
|
+
(a dict, or a model instance for Pydantic parameters). Raise on failure, or return a
|
|
276
|
+
result with ``is_error=True``; do not only describe the failure in ``content``.
|
|
277
|
+
"""
|
|
278
|
+
|
|
279
|
+
execute: _Execute
|
|
280
|
+
#: Human-readable label for UI display (defaults to ``name``).
|
|
281
|
+
label: str = ""
|
|
282
|
+
#: Compatibility shim for raw arguments before schema validation.
|
|
283
|
+
prepare_arguments: Callable[[Any], Any] | None = None
|
|
284
|
+
#: JSON Schema of ``structured_content`` in successful results.
|
|
285
|
+
output_schema: Any = None
|
|
286
|
+
#: Recovery policy for an effect whose durable intent exists but whose outcome is unknown.
|
|
287
|
+
replay: Literal["never", "safe"] | None = None
|
|
288
|
+
#: Per-tool execution mode override; ``"sequential"`` forces the whole batch to run sequentially.
|
|
289
|
+
execution_mode: ToolExecutionMode | None = None
|
|
290
|
+
|
|
291
|
+
def __post_init__(self) -> None:
|
|
292
|
+
if not self.label:
|
|
293
|
+
self.label = self.name
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
@dataclass(slots=True)
|
|
297
|
+
class AgentContext:
|
|
298
|
+
"""Context snapshot passed into the low-level agent loop."""
|
|
299
|
+
|
|
300
|
+
messages: list[Any] = field(default_factory=list)
|
|
301
|
+
tools: list[AgentTool] | None = None
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
# ---------------------------------------------------------------------------
|
|
305
|
+
# Events
|
|
306
|
+
# ---------------------------------------------------------------------------
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
@dataclass(slots=True)
|
|
310
|
+
class AgentStartEvent:
|
|
311
|
+
type: ClassVar[Literal["agent_start"]] = "agent_start"
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
@dataclass(slots=True)
|
|
315
|
+
class AgentEndEvent:
|
|
316
|
+
"""Last event of a run. Awaited ``Agent.subscribe`` listeners still count toward settlement."""
|
|
317
|
+
|
|
318
|
+
type: ClassVar[Literal["agent_end"]] = "agent_end"
|
|
319
|
+
messages: list[Any]
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
@dataclass(slots=True)
|
|
323
|
+
class TurnStartEvent:
|
|
324
|
+
type: ClassVar[Literal["turn_start"]] = "turn_start"
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
@dataclass(slots=True)
|
|
328
|
+
class TurnEndEvent:
|
|
329
|
+
type: ClassVar[Literal["turn_end"]] = "turn_end"
|
|
330
|
+
message: Any
|
|
331
|
+
tool_results: list[ToolResultMessage]
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
@dataclass(slots=True)
|
|
335
|
+
class MessageStartEvent:
|
|
336
|
+
type: ClassVar[Literal["message_start"]] = "message_start"
|
|
337
|
+
message: Any
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
@dataclass(slots=True)
|
|
341
|
+
class MessageUpdateEvent:
|
|
342
|
+
"""Only emitted for assistant messages during streaming."""
|
|
343
|
+
|
|
344
|
+
type: ClassVar[Literal["message_update"]] = "message_update"
|
|
345
|
+
message: Any
|
|
346
|
+
assistant_message_event: AssistantMessageEvent
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
@dataclass(slots=True)
|
|
350
|
+
class MessageEndEvent:
|
|
351
|
+
type: ClassVar[Literal["message_end"]] = "message_end"
|
|
352
|
+
message: Any
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
@dataclass(slots=True)
|
|
356
|
+
class ToolExecutionStartEvent:
|
|
357
|
+
type: ClassVar[Literal["tool_execution_start"]] = "tool_execution_start"
|
|
358
|
+
tool_call_id: str
|
|
359
|
+
tool_name: str
|
|
360
|
+
args: Any
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
@dataclass(slots=True)
|
|
364
|
+
class ToolExecutionUpdateEvent:
|
|
365
|
+
type: ClassVar[Literal["tool_execution_update"]] = "tool_execution_update"
|
|
366
|
+
tool_call_id: str
|
|
367
|
+
tool_name: str
|
|
368
|
+
args: Any
|
|
369
|
+
partial_result: Any
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
@dataclass(slots=True)
|
|
373
|
+
class ToolExecutionEndEvent:
|
|
374
|
+
type: ClassVar[Literal["tool_execution_end"]] = "tool_execution_end"
|
|
375
|
+
tool_call_id: str
|
|
376
|
+
tool_name: str
|
|
377
|
+
result: Any
|
|
378
|
+
is_error: bool
|
|
379
|
+
#: Milliseconds ``execute()`` took; ``None`` when the tool did not run.
|
|
380
|
+
duration_ms: int | None = None
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
AgentEvent: TypeAlias = (
|
|
384
|
+
AgentStartEvent
|
|
385
|
+
| AgentEndEvent
|
|
386
|
+
| TurnStartEvent
|
|
387
|
+
| TurnEndEvent
|
|
388
|
+
| MessageStartEvent
|
|
389
|
+
| MessageUpdateEvent
|
|
390
|
+
| MessageEndEvent
|
|
391
|
+
| ToolExecutionStartEvent
|
|
392
|
+
| ToolExecutionUpdateEvent
|
|
393
|
+
| ToolExecutionEndEvent
|
|
394
|
+
)
|
pi_ai/__init__.py
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
"""pi-ai: unified LLM API with provider collections, auth resolution, streaming events,
|
|
2
|
+
token/cost tracking and cross-provider context hand-off.
|
|
3
|
+
|
|
4
|
+
Python port of ``@earendil-works/pi-ai``. The core entry point does not import
|
|
5
|
+
built-in catalogs or provider implementations; use :mod:`pi_ai.providers.all`
|
|
6
|
+
(``builtin_models()``) or individual provider factories such as
|
|
7
|
+
:func:`pi_ai.providers.anthropic.anthropic_provider`.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from .abort import AbortController, AbortError, AbortSignal, abort_scope
|
|
13
|
+
from .api.lazy import LazyApi, lazy_api, lazy_stream
|
|
14
|
+
from .auth.context import DefaultAuthContext, default_provider_auth_context
|
|
15
|
+
from .auth.credential_store import FileCredentialStore, InMemoryCredentialStore
|
|
16
|
+
from .auth.helpers import env_api_key_auth, keyless_auth, lazy_oauth
|
|
17
|
+
from .auth.resolve import AuthResolutionOverrides
|
|
18
|
+
from .auth.types import (
|
|
19
|
+
ApiKeyAuth,
|
|
20
|
+
ApiKeyCredential,
|
|
21
|
+
AuthCheck,
|
|
22
|
+
AuthContext,
|
|
23
|
+
AuthEvent,
|
|
24
|
+
AuthInfoLink,
|
|
25
|
+
AuthInteraction,
|
|
26
|
+
AuthPrompt,
|
|
27
|
+
AuthResult,
|
|
28
|
+
AuthSelectOption,
|
|
29
|
+
AuthType,
|
|
30
|
+
Credential,
|
|
31
|
+
CredentialInfo,
|
|
32
|
+
CredentialStore,
|
|
33
|
+
LoginOptions,
|
|
34
|
+
ModelAuth,
|
|
35
|
+
OAuthAuth,
|
|
36
|
+
OAuthCredential,
|
|
37
|
+
OAuthCredentials,
|
|
38
|
+
ProviderAuth,
|
|
39
|
+
ProviderAuthInteraction,
|
|
40
|
+
)
|
|
41
|
+
from .event_stream import AssistantMessageEventStream, EventStream, create_assistant_message_event_stream
|
|
42
|
+
from .models import (
|
|
43
|
+
UNCHANGED,
|
|
44
|
+
Models,
|
|
45
|
+
ModelsError,
|
|
46
|
+
ModelsErrorCode,
|
|
47
|
+
ModelsPublication,
|
|
48
|
+
ModelsRefreshResult,
|
|
49
|
+
MutableModels,
|
|
50
|
+
Provider,
|
|
51
|
+
RefreshModelsContext,
|
|
52
|
+
calculate_cost,
|
|
53
|
+
clamp_thinking_level,
|
|
54
|
+
create_models,
|
|
55
|
+
create_provider,
|
|
56
|
+
get_model_type,
|
|
57
|
+
get_supported_thinking_levels,
|
|
58
|
+
has_api,
|
|
59
|
+
is_model_type,
|
|
60
|
+
models_are_equal,
|
|
61
|
+
)
|
|
62
|
+
from .models_store import FileModelsStore, InMemoryModelsStore, ModelsStore, ModelsStoreEntry
|
|
63
|
+
from .providers.faux import (
|
|
64
|
+
FauxModelDefinition,
|
|
65
|
+
FauxProviderHandle,
|
|
66
|
+
FauxProviderState,
|
|
67
|
+
faux_assistant_message,
|
|
68
|
+
faux_provider,
|
|
69
|
+
faux_text,
|
|
70
|
+
faux_thinking,
|
|
71
|
+
faux_tool_call,
|
|
72
|
+
)
|
|
73
|
+
from .session_resources import cleanup_session_resources, register_session_resource_cleanup
|
|
74
|
+
from .types import * # noqa: F403
|
|
75
|
+
from .types import __all__ as _types_all
|
|
76
|
+
from .utils.diagnostics import (
|
|
77
|
+
AssistantMessageDiagnostic,
|
|
78
|
+
DiagnosticErrorInfo,
|
|
79
|
+
append_assistant_message_diagnostic,
|
|
80
|
+
create_assistant_message_diagnostic,
|
|
81
|
+
extract_diagnostic_error,
|
|
82
|
+
format_thrown_value,
|
|
83
|
+
)
|
|
84
|
+
from .utils.http import ProviderHttpError, aclose_http_clients
|
|
85
|
+
from .utils.json_parse import (
|
|
86
|
+
StreamingJsonParser,
|
|
87
|
+
parse_json_with_repair,
|
|
88
|
+
parse_streaming_json,
|
|
89
|
+
parse_tool_call_arguments,
|
|
90
|
+
repair_json,
|
|
91
|
+
)
|
|
92
|
+
from .utils.misc import uuidv7
|
|
93
|
+
from .utils.overflow import get_overflow_patterns, is_context_overflow, is_recoverable_length
|
|
94
|
+
from .utils.retry import (
|
|
95
|
+
DEFAULT_MAX_AGENT_RETRY_DELAY_MS,
|
|
96
|
+
RetryCallbacks,
|
|
97
|
+
RetryPolicy,
|
|
98
|
+
is_retryable_assistant_error,
|
|
99
|
+
retry_assistant_call,
|
|
100
|
+
retry_delay_ms,
|
|
101
|
+
)
|
|
102
|
+
from .utils.schema import StringEnum, TSchema, Type
|
|
103
|
+
from .utils.text import content_text, get_system_message_text, render_system_message_update
|
|
104
|
+
from .utils.transcript import (
|
|
105
|
+
ToolStateChanges,
|
|
106
|
+
TranscriptTools,
|
|
107
|
+
collapse_system_messages,
|
|
108
|
+
create_initial_system_message,
|
|
109
|
+
declarations_equal,
|
|
110
|
+
get_current_system_message,
|
|
111
|
+
get_current_system_prompt,
|
|
112
|
+
get_current_tools,
|
|
113
|
+
get_declared_tools,
|
|
114
|
+
get_initial_system_message,
|
|
115
|
+
get_tool_state_changes,
|
|
116
|
+
has_non_additive_tool_changes,
|
|
117
|
+
has_tool_redefinitions,
|
|
118
|
+
normalize_context,
|
|
119
|
+
resolve_transcript,
|
|
120
|
+
resolve_transcript_tools,
|
|
121
|
+
to_tool_declaration,
|
|
122
|
+
without_initial_system_message,
|
|
123
|
+
)
|
|
124
|
+
from .utils.validation import ToolValidationError, validate_tool_arguments, validate_tool_call
|
|
125
|
+
|
|
126
|
+
__version__ = "1.3.0"
|
|
127
|
+
|
|
128
|
+
__all__ = [
|
|
129
|
+
*_types_all,
|
|
130
|
+
"__version__",
|
|
131
|
+
# cancellation
|
|
132
|
+
"AbortController",
|
|
133
|
+
"AbortError",
|
|
134
|
+
"AbortSignal",
|
|
135
|
+
"abort_scope",
|
|
136
|
+
# streams
|
|
137
|
+
"EventStream",
|
|
138
|
+
"AssistantMessageEventStream",
|
|
139
|
+
"create_assistant_message_event_stream",
|
|
140
|
+
"lazy_stream",
|
|
141
|
+
"lazy_api",
|
|
142
|
+
"LazyApi",
|
|
143
|
+
# models runtime
|
|
144
|
+
"Models",
|
|
145
|
+
"MutableModels",
|
|
146
|
+
"Provider",
|
|
147
|
+
"ModelsError",
|
|
148
|
+
"ModelsErrorCode",
|
|
149
|
+
"ModelsPublication",
|
|
150
|
+
"ModelsRefreshResult",
|
|
151
|
+
"RefreshModelsContext",
|
|
152
|
+
"UNCHANGED",
|
|
153
|
+
"create_models",
|
|
154
|
+
"create_provider",
|
|
155
|
+
"has_api",
|
|
156
|
+
"get_model_type",
|
|
157
|
+
"is_model_type",
|
|
158
|
+
"calculate_cost",
|
|
159
|
+
"get_supported_thinking_levels",
|
|
160
|
+
"clamp_thinking_level",
|
|
161
|
+
"models_are_equal",
|
|
162
|
+
"ModelsStore",
|
|
163
|
+
"ModelsStoreEntry",
|
|
164
|
+
"InMemoryModelsStore",
|
|
165
|
+
"FileModelsStore",
|
|
166
|
+
# auth
|
|
167
|
+
"ApiKeyAuth",
|
|
168
|
+
"ApiKeyCredential",
|
|
169
|
+
"AuthCheck",
|
|
170
|
+
"AuthContext",
|
|
171
|
+
"AuthEvent",
|
|
172
|
+
"AuthInfoLink",
|
|
173
|
+
"AuthInteraction",
|
|
174
|
+
"AuthPrompt",
|
|
175
|
+
"AuthResult",
|
|
176
|
+
"AuthResolutionOverrides",
|
|
177
|
+
"AuthSelectOption",
|
|
178
|
+
"AuthType",
|
|
179
|
+
"Credential",
|
|
180
|
+
"CredentialInfo",
|
|
181
|
+
"CredentialStore",
|
|
182
|
+
"LoginOptions",
|
|
183
|
+
"ModelAuth",
|
|
184
|
+
"OAuthAuth",
|
|
185
|
+
"OAuthCredential",
|
|
186
|
+
"OAuthCredentials",
|
|
187
|
+
"ProviderAuth",
|
|
188
|
+
"ProviderAuthInteraction",
|
|
189
|
+
"DefaultAuthContext",
|
|
190
|
+
"default_provider_auth_context",
|
|
191
|
+
"InMemoryCredentialStore",
|
|
192
|
+
"FileCredentialStore",
|
|
193
|
+
"env_api_key_auth",
|
|
194
|
+
"keyless_auth",
|
|
195
|
+
"lazy_oauth",
|
|
196
|
+
# faux
|
|
197
|
+
"FauxModelDefinition",
|
|
198
|
+
"FauxProviderHandle",
|
|
199
|
+
"FauxProviderState",
|
|
200
|
+
"faux_provider",
|
|
201
|
+
"faux_assistant_message",
|
|
202
|
+
"faux_text",
|
|
203
|
+
"faux_thinking",
|
|
204
|
+
"faux_tool_call",
|
|
205
|
+
# tools & schemas
|
|
206
|
+
"Type",
|
|
207
|
+
"TSchema",
|
|
208
|
+
"StringEnum",
|
|
209
|
+
"validate_tool_call",
|
|
210
|
+
"validate_tool_arguments",
|
|
211
|
+
"ToolValidationError",
|
|
212
|
+
# json
|
|
213
|
+
"parse_streaming_json",
|
|
214
|
+
"parse_json_with_repair",
|
|
215
|
+
"parse_tool_call_arguments",
|
|
216
|
+
"repair_json",
|
|
217
|
+
"StreamingJsonParser",
|
|
218
|
+
# transcript
|
|
219
|
+
"normalize_context",
|
|
220
|
+
"create_initial_system_message",
|
|
221
|
+
"get_initial_system_message",
|
|
222
|
+
"without_initial_system_message",
|
|
223
|
+
"get_current_tools",
|
|
224
|
+
"get_current_system_message",
|
|
225
|
+
"get_current_system_prompt",
|
|
226
|
+
"collapse_system_messages",
|
|
227
|
+
"resolve_transcript",
|
|
228
|
+
"to_tool_declaration",
|
|
229
|
+
"declarations_equal",
|
|
230
|
+
"ToolStateChanges",
|
|
231
|
+
"get_tool_state_changes",
|
|
232
|
+
"get_declared_tools",
|
|
233
|
+
"has_tool_redefinitions",
|
|
234
|
+
"has_non_additive_tool_changes",
|
|
235
|
+
"TranscriptTools",
|
|
236
|
+
"resolve_transcript_tools",
|
|
237
|
+
"content_text",
|
|
238
|
+
"get_system_message_text",
|
|
239
|
+
"render_system_message_update",
|
|
240
|
+
# errors, retry, overflow
|
|
241
|
+
"ProviderHttpError",
|
|
242
|
+
"aclose_http_clients",
|
|
243
|
+
"is_context_overflow",
|
|
244
|
+
"is_recoverable_length",
|
|
245
|
+
"get_overflow_patterns",
|
|
246
|
+
"RetryPolicy",
|
|
247
|
+
"RetryCallbacks",
|
|
248
|
+
"DEFAULT_MAX_AGENT_RETRY_DELAY_MS",
|
|
249
|
+
"retry_delay_ms",
|
|
250
|
+
"retry_assistant_call",
|
|
251
|
+
"is_retryable_assistant_error",
|
|
252
|
+
# diagnostics
|
|
253
|
+
"AssistantMessageDiagnostic",
|
|
254
|
+
"DiagnosticErrorInfo",
|
|
255
|
+
"append_assistant_message_diagnostic",
|
|
256
|
+
"create_assistant_message_diagnostic",
|
|
257
|
+
"extract_diagnostic_error",
|
|
258
|
+
"format_thrown_value",
|
|
259
|
+
# misc
|
|
260
|
+
"uuidv7",
|
|
261
|
+
"cleanup_session_resources",
|
|
262
|
+
"register_session_resource_cleanup",
|
|
263
|
+
]
|