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
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"""Google Generative AI (Gemini API) adapter.
|
|
2
|
+
|
|
3
|
+
Streams through the official ``google-genai`` SDK (``client.aio.models.generate_content_stream``),
|
|
4
|
+
as pi upstream does with ``@google/genai``.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from collections.abc import Mapping
|
|
10
|
+
from typing import Any, Literal
|
|
11
|
+
|
|
12
|
+
from google.genai import Client
|
|
13
|
+
from google.genai import types as genai_types
|
|
14
|
+
|
|
15
|
+
from ..event_stream import AssistantMessageEventStream
|
|
16
|
+
from ..models import clamp_thinking_level
|
|
17
|
+
from ..types import Model, StreamOptions, TranscriptContext
|
|
18
|
+
from ..utils.http import get_http_client
|
|
19
|
+
from ..utils.misc import get_provider_env_value
|
|
20
|
+
from .google_shared import (
|
|
21
|
+
GoogleThinkingOptions,
|
|
22
|
+
ResolvedGoogleThinkingLevel,
|
|
23
|
+
get_google_client,
|
|
24
|
+
new_google_output,
|
|
25
|
+
resolve_google_thinking_level,
|
|
26
|
+
run_google_stream,
|
|
27
|
+
to_google_thinking_level,
|
|
28
|
+
uses_google_thinking_level,
|
|
29
|
+
)
|
|
30
|
+
from .simple_options import build_base_options
|
|
31
|
+
|
|
32
|
+
__all__ = ["GoogleOptions", "stream", "stream_simple", "get_google_budget"]
|
|
33
|
+
|
|
34
|
+
_DEFAULT_BASE_URL = "https://generativelanguage.googleapis.com/"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class GoogleOptions(StreamOptions, total=False):
|
|
38
|
+
tool_choice: Literal["auto", "none", "any"]
|
|
39
|
+
thinking: GoogleThinkingOptions
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def stream(
|
|
43
|
+
model: Model, context: TranscriptContext, options: Mapping[str, Any] | None = None
|
|
44
|
+
) -> AssistantMessageEventStream:
|
|
45
|
+
"""Stream a Gemini API response."""
|
|
46
|
+
opts = dict(options or {})
|
|
47
|
+
out = AssistantMessageEventStream()
|
|
48
|
+
output = new_google_output(model)
|
|
49
|
+
out.start(
|
|
50
|
+
run_google_stream(
|
|
51
|
+
model,
|
|
52
|
+
context,
|
|
53
|
+
opts,
|
|
54
|
+
out,
|
|
55
|
+
output,
|
|
56
|
+
create_client=lambda: _create_client(model, opts),
|
|
57
|
+
missing_finish_reason_message="Google stream ended without a finish reason",
|
|
58
|
+
)
|
|
59
|
+
)
|
|
60
|
+
return out
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def stream_simple(
|
|
64
|
+
model: Model, context: TranscriptContext, options: Mapping[str, Any] | None = None
|
|
65
|
+
) -> AssistantMessageEventStream:
|
|
66
|
+
"""Stream with provider-neutral options (``reasoning``, ``tool_choice``, ``thinking_budgets``)."""
|
|
67
|
+
options = options or {}
|
|
68
|
+
api_key = options.get("api_key")
|
|
69
|
+
if not api_key:
|
|
70
|
+
raise ValueError(f"No API key for provider: {model.provider}")
|
|
71
|
+
|
|
72
|
+
base: dict[str, Any] = build_base_options(model, context, options, api_key)
|
|
73
|
+
if options.get("tool_choice") is not None:
|
|
74
|
+
base["tool_choice"] = options["tool_choice"]
|
|
75
|
+
reasoning = options.get("reasoning")
|
|
76
|
+
if not reasoning:
|
|
77
|
+
return stream(model, context, {**base, "thinking": {"enabled": False}})
|
|
78
|
+
|
|
79
|
+
clamped = clamp_thinking_level(model, reasoning)
|
|
80
|
+
if clamped == "off":
|
|
81
|
+
return stream(model, context, {**base, "thinking": {"enabled": False}})
|
|
82
|
+
resolved = resolve_google_thinking_level(model, clamped)
|
|
83
|
+
|
|
84
|
+
if uses_google_thinking_level(model):
|
|
85
|
+
return stream(
|
|
86
|
+
model, context, {**base, "thinking": {"enabled": True, "level": to_google_thinking_level(resolved)}}
|
|
87
|
+
)
|
|
88
|
+
return stream(
|
|
89
|
+
model,
|
|
90
|
+
context,
|
|
91
|
+
{
|
|
92
|
+
**base,
|
|
93
|
+
"thinking": {
|
|
94
|
+
"enabled": True,
|
|
95
|
+
"budget_tokens": get_google_budget(model, resolved, options.get("thinking_budgets")),
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
async def _create_client(model: Model, options: Mapping[str, Any]) -> Client:
|
|
102
|
+
api_key = options.get("api_key")
|
|
103
|
+
if not api_key:
|
|
104
|
+
raise ValueError(f"No API key for provider: {model.provider}")
|
|
105
|
+
|
|
106
|
+
base_url: str | None
|
|
107
|
+
api_version: str | None = None
|
|
108
|
+
if model.base_url:
|
|
109
|
+
# The catalog baseUrl already includes the version path; don't append one.
|
|
110
|
+
base_url, api_version = model.base_url, ""
|
|
111
|
+
else:
|
|
112
|
+
# The SDK reads GOOGLE_GEMINI_BASE_URL from os.environ itself; this also honors the provider env.
|
|
113
|
+
base_url = (get_provider_env_value("GOOGLE_GEMINI_BASE_URL", options.get("env")) or "").strip() or None
|
|
114
|
+
http_client = get_http_client(base_url or _DEFAULT_BASE_URL, options)
|
|
115
|
+
|
|
116
|
+
async def factory() -> Client:
|
|
117
|
+
http_options = genai_types.HttpOptions(
|
|
118
|
+
base_url=base_url, api_version=api_version, httpx_async_client=http_client
|
|
119
|
+
)
|
|
120
|
+
return Client(vertexai=False, api_key=api_key, http_options=http_options)
|
|
121
|
+
|
|
122
|
+
# Headers are sent per request (see run_google_stream), so they are not part of the key.
|
|
123
|
+
return await get_google_client(http_client, ("gemini", api_key, base_url, api_version), factory)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def get_google_budget(
|
|
127
|
+
model: Model, level: ResolvedGoogleThinkingLevel, custom_budgets: Mapping[str, int] | None = None
|
|
128
|
+
) -> int:
|
|
129
|
+
"""Token budget for a thinking level on budget-based Gemini models (-1 = dynamic)."""
|
|
130
|
+
if custom_budgets and custom_budgets.get(level) is not None:
|
|
131
|
+
return custom_budgets[level]
|
|
132
|
+
if "2.5-pro" in model.id:
|
|
133
|
+
return {"minimal": 128, "low": 2048, "medium": 8192, "high": 32768}[level]
|
|
134
|
+
if "2.5-flash-lite" in model.id:
|
|
135
|
+
return {"minimal": 512, "low": 2048, "medium": 8192, "high": 24576}[level]
|
|
136
|
+
if "2.5-flash" in model.id:
|
|
137
|
+
return {"minimal": 128, "low": 2048, "medium": 8192, "high": 24576}[level]
|
|
138
|
+
return -1
|