pi-python-core 0.8.1__py3-none-any.whl → 0.8.2__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_python/_version.py +1 -1
- pi_python/providers/__init__.py +1 -1
- pi_python/providers/oauth.py +6 -1
- pi_python_core-0.8.2.dist-info/METADATA +124 -0
- {pi_python_core-0.8.1.dist-info → pi_python_core-0.8.2.dist-info}/RECORD +8 -8
- pi_python_core-0.8.1.dist-info/METADATA +0 -119
- {pi_python_core-0.8.1.dist-info → pi_python_core-0.8.2.dist-info}/WHEEL +0 -0
- {pi_python_core-0.8.1.dist-info → pi_python_core-0.8.2.dist-info}/licenses/LICENSE +0 -0
- {pi_python_core-0.8.1.dist-info → pi_python_core-0.8.2.dist-info}/licenses/NOTICE +0 -0
pi_python/_version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.8.
|
|
1
|
+
__version__ = "0.8.2"
|
pi_python/providers/__init__.py
CHANGED
pi_python/providers/oauth.py
CHANGED
|
@@ -279,7 +279,12 @@ class OAuthClient:
|
|
|
279
279
|
async def _verify_id_token(
|
|
280
280
|
self, token: Any, clientid: str, nonce: str | None, cancel: CancelToken
|
|
281
281
|
) -> dict[str, Any]:
|
|
282
|
-
|
|
282
|
+
try:
|
|
283
|
+
import jwt
|
|
284
|
+
except ImportError as exc:
|
|
285
|
+
raise ImportError(
|
|
286
|
+
"ChatGPT sign-in needs PyJWT: pip install 'pi-python-core[oauth]'"
|
|
287
|
+
) from exc
|
|
283
288
|
|
|
284
289
|
if not isinstance(token, str) or not token:
|
|
285
290
|
raise ConfigurationError("ChatGPT sign-in lacks ID token")
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pi-python-core
|
|
3
|
+
Version: 0.8.2
|
|
4
|
+
Summary: An embeddable asyncio agent core with opt-in Claude and OpenAI providers
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
License-File: NOTICE
|
|
8
|
+
Classifier: Framework :: AsyncIO
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
+
Classifier: Programming Language :: Python :: Free Threading :: 2 - Beta
|
|
17
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
18
|
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
19
|
+
Classifier: Typing :: Typed
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Requires-Dist: httpx<1,>=0.27
|
|
22
|
+
Requires-Dist: jsonschema<5,>=4.18
|
|
23
|
+
Requires-Dist: websockets>=14.2
|
|
24
|
+
Provides-Extra: mcp
|
|
25
|
+
Requires-Dist: mcp>=1.10; extra == 'mcp'
|
|
26
|
+
Provides-Extra: oauth
|
|
27
|
+
Requires-Dist: pyjwt[crypto]<3,>=2.8; extra == 'oauth'
|
|
28
|
+
Provides-Extra: providers
|
|
29
|
+
Requires-Dist: pyjwt[crypto]<3,>=2.8; extra == 'providers'
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# pi-python-core
|
|
33
|
+
|
|
34
|
+
**English** | [中文](README.zh-CN.md)
|
|
35
|
+
|
|
36
|
+
An embeddable Python agent core, ported from [Pi](https://github.com/earendil-works/pi) (pinned to `v1.0.0`). It does one job: send the conversation to a model, run the tools the model asks for, hand the results back, and repeat until the model answers. Tools are plain Python functions; the model can be Claude, GPT, DeepSeek, or an open model running on your own machine or cluster.
|
|
37
|
+
|
|
38
|
+
`pi-agent-core` on PyPI is a separate project that ports an older version from pi-mono (early 2026). This library follows the behavior of Pi v1.0.0, compared case by case with the upstream code's actual output, and ships its own connectors for Claude, OpenAI, DeepSeek and local models, with no model SDK required.
|
|
39
|
+
|
|
40
|
+
## Install
|
|
41
|
+
|
|
42
|
+
Python 3.11–3.14 (including free-threaded 3.14t) and PyPy 3.11. No Node.js or model SDK needed.
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pip install pi-python-core # or: uv add pi-python-core
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
You install `pi-python-core` and import `pi_python`.
|
|
49
|
+
|
|
50
|
+
| Option | What it adds |
|
|
51
|
+
|---|---|
|
|
52
|
+
| (none) | The agent core and the built-in model connectors: Claude, OpenAI, Codex, DeepSeek, and any OpenAI-compatible server (Ollama, vLLM, llama.cpp, …) |
|
|
53
|
+
| `[oauth]` | Verifies the identity token when you sign in with a ChatGPT account (`openai-chatgpt`); it brings in the compiled `cryptography` package. Claude subscription and Codex sign-in do not need it |
|
|
54
|
+
| `[providers]` | Same as `[oauth]`; keeps install commands from 0.8.1 and earlier working |
|
|
55
|
+
| `[mcp]` | Gives the agent the tools of MCP servers |
|
|
56
|
+
|
|
57
|
+
Dependencies are version ranges rather than pins, so the package fits into most existing environments.
|
|
58
|
+
|
|
59
|
+
## Five-minute start
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
from pi_python import Agent, tool
|
|
63
|
+
from pi_python.providers import AnthropicProvider
|
|
64
|
+
|
|
65
|
+
@tool
|
|
66
|
+
def word_count(text: str) -> int:
|
|
67
|
+
"""Count the words in a text."""
|
|
68
|
+
return len(text.split())
|
|
69
|
+
|
|
70
|
+
agent = Agent(provider=AnthropicProvider(api_key="..."), model="claude-sonnet-4-5", tools=[word_count])
|
|
71
|
+
result = agent.prompt_sync("How many words are in 'to be or not to be'?")
|
|
72
|
+
print(result.messages[-1].content[0].text)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`@tool` builds a tool from the function's signature and docstring; both plain and `async` functions work. In async code, use `await agent.prompt(...)`. Switching to a local model changes two lines:
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
from pi_python.providers import OpenAICompletionsProvider
|
|
79
|
+
|
|
80
|
+
llm = OpenAICompletionsProvider(base_url="http://localhost:11434/v1", name="ollama")
|
|
81
|
+
agent = Agent(provider=llm, model=llm.model("qwen3:8b", context_window=40960), tools=[word_count])
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
To try it offline first: `python examples/quickstart.py`.
|
|
85
|
+
|
|
86
|
+
## What it does
|
|
87
|
+
|
|
88
|
+
| Need | How | Example |
|
|
89
|
+
|---|---|---|
|
|
90
|
+
| Write tools | Decorate a plain function with `@tool`; arguments such as pydantic models, dataclasses, enums and dates are converted automatically; hand-written or MCP-generated JSON Schema works too | [quickstart](examples/quickstart.py) |
|
|
91
|
+
| Connect a model | Claude and GPT through an API key or subscription sign-in; DeepSeek; any OpenAI-compatible server | [local_model](examples/local_model.py), [provider_chat](examples/provider_chat.py) |
|
|
92
|
+
| Use MCP tools | `async with connect_stdio(...) as tools` | [mcp_tools](examples/mcp_tools.py) |
|
|
93
|
+
| Let one agent call another | Wrap the sub-agent as a tool; cancellation propagates down | [subagent](examples/subagent.py) |
|
|
94
|
+
| Intervene mid-run | `steer` injects guidance, `follow_up` queues the next task, `abort` cancels at any time (callable from any thread) | |
|
|
95
|
+
| Context full, service errors | `is_context_overflow` and `is_retryable_error` tell you why, `continue_run()` retries, `transform_context` compacts | [recovery](examples/recovery.py) |
|
|
96
|
+
| Save and restore conversations | `encode_messages` / `decode_messages`; your application decides where to store them | [save_restore](examples/save_restore.py) |
|
|
97
|
+
| Observe and audit | Subscribe to events; hooks before and after tool execution can block or rewrite tool calls | |
|
|
98
|
+
|
|
99
|
+
Apart from `provider_chat`, which needs real credentials, every example runs offline without an API key, and the tests run each one.
|
|
100
|
+
|
|
101
|
+
## Relationship to Pi
|
|
102
|
+
|
|
103
|
+
The run loop, event order, hooks, queues, and the handling of errors and cancellation all match Pi, and this is checked differentially: the same inputs go to the pinned upstream code and to this library, and the model requests, tool calls, events and final transcript are compared item by item. All cases currently agree: 25 for the core loop, 50 for model connectors, 2 for multi-turn WebSocket, and 44 error-classification samples.
|
|
104
|
+
|
|
105
|
+
A few differences are deliberate, such as strict tool-argument validation without type coercion, and returning copies of state to callers. Others are additions for Python users, such as `@tool`, blocking calls, and calling `continue_run()` directly after a failure. Each one is recorded in the [coverage map](compat/COVERAGE.md) (Chinese). Features Pi keeps in its application layer (terminal UI, session file format, context compaction) are not in this core; compaction can be built with hooks, and an example shows the full approach. This project uses its own version numbers and is not an official Pi release.
|
|
106
|
+
|
|
107
|
+
## Documentation
|
|
108
|
+
|
|
109
|
+
- [Concepts on one page: five ideas and one turn](docs/CONCEPTS.md)
|
|
110
|
+
- [Public API](docs/API.md)
|
|
111
|
+
- [Model connectors, subscription sign-in and local models](docs/PROVIDERS.md)
|
|
112
|
+
- [Implementation and verification results](docs/IMPLEMENTATION.md) (Chinese)
|
|
113
|
+
- [Item-by-item comparison with Pi, and deliberate differences](compat/COVERAGE.md) (Chinese)
|
|
114
|
+
- [Rebuilding the reference and checking release candidates](reference/README.md) (Chinese)
|
|
115
|
+
|
|
116
|
+
## Development
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
uv sync --locked --extra oauth --extra mcp
|
|
120
|
+
uv run pytest -q
|
|
121
|
+
uv run python scripts/verify.py # every check, including the comparison with upstream (needs Node)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
CI is defined in `.github/workflows/ci.yml` and runs on GitHub Actions for every push: each Python version on Linux (including 3.14t and PyPy), plus macOS and Windows.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
pi_python/__init__.py,sha256=jmQw2LTIjdt9Sn3lTAaAUAvgDrNqfZ1rDGvccAAuPOY,3751
|
|
2
|
-
pi_python/_version.py,sha256=
|
|
2
|
+
pi_python/_version.py,sha256=B7GiO0rd49YwtLYjvPg4lmCZEDlMTonslQKdSImaMJk,22
|
|
3
3
|
pi_python/agent.py,sha256=eFbmkO5prBbWssaIycgTRWd4VRJ6I3FJMDU414kpL1w,15264
|
|
4
4
|
pi_python/cancellation.py,sha256=DoQVdX7DcQdVLkl4OvhcpMhKZJEW0Kscl2-xxF6i6Y0,608
|
|
5
5
|
pi_python/errors.py,sha256=65lT0nYfzqxRfUlFG-Y9vgYxfDHEuFiBfgqmFnX9_O8,675
|
|
@@ -25,15 +25,15 @@ pi_python/testing.py,sha256=XfTSOkEv0CenqrBILI_T205jOhyitW53YQZ9yiMXir4,1046
|
|
|
25
25
|
pi_python/tools.py,sha256=7hpquuOoVeRAhVxlYOXsooFvTcXEgfVkVBrTjvMbqa8,20503
|
|
26
26
|
pi_python/transcript.py,sha256=g6Tg8eiyMCAK43iLpcBv220MHBq8kO7Ty-6OYLCzw2A,6685
|
|
27
27
|
pi_python/data/models.json,sha256=oa_LGv7vaRrS-l7_Z7iu8f7WTyoJJLPhUQyptUz7OmE,77549
|
|
28
|
-
pi_python/providers/__init__.py,sha256=
|
|
28
|
+
pi_python/providers/__init__.py,sha256=X__USnHZ-Vvv49LKD1uCCB3Kel2OWh7Q_XXRbyB5mj8,680
|
|
29
29
|
pi_python/providers/anthropic.py,sha256=35ZwPGh2VUg-86iNROyHz5MAv1bYZB2XGLR-DHYELAY,30204
|
|
30
30
|
pi_python/providers/common.py,sha256=z8dB2pIc-dRscPAppnA3ZwF_wJygunQb9pI9Wl4CvaA,8051
|
|
31
31
|
pi_python/providers/completions.py,sha256=7tFrS_j2u6mV90mSE8uZYZDfj6DqRVxJXbIrUDay3mg,50289
|
|
32
|
-
pi_python/providers/oauth.py,sha256=
|
|
32
|
+
pi_python/providers/oauth.py,sha256=D0E7clQvTUFEpgtTRtvSL4fJHSgPRZA4cUUfyK_e6bc,23011
|
|
33
33
|
pi_python/providers/openai.py,sha256=36KBHaFUgM_QGKBSTxVxAfroCzmcoh5DPKuX667WmLs,30112
|
|
34
34
|
pi_python/providers/transport.py,sha256=R9AbUmlTXwuGXJEv9Q1joZrTJAd1shxnz7Uxwuzl0nA,21990
|
|
35
|
-
pi_python_core-0.8.
|
|
36
|
-
pi_python_core-0.8.
|
|
37
|
-
pi_python_core-0.8.
|
|
38
|
-
pi_python_core-0.8.
|
|
39
|
-
pi_python_core-0.8.
|
|
35
|
+
pi_python_core-0.8.2.dist-info/METADATA,sha256=j9acRx_i1YR-zfpnu1VDK-8AhxSWV30IpWT3IY_NDSU,7205
|
|
36
|
+
pi_python_core-0.8.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
37
|
+
pi_python_core-0.8.2.dist-info/licenses/LICENSE,sha256=BFf1vOw7OyEWBd-10aSQQv1jjzaGpBD-CZwkolrxPEg,1069
|
|
38
|
+
pi_python_core-0.8.2.dist-info/licenses/NOTICE,sha256=fJna16fm1ECHN7zVZhtyNmjLw8KGxGp8mL9blISF1K0,633
|
|
39
|
+
pi_python_core-0.8.2.dist-info/RECORD,,
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: pi-python-core
|
|
3
|
-
Version: 0.8.1
|
|
4
|
-
Summary: An embeddable asyncio agent core with opt-in Claude and OpenAI providers
|
|
5
|
-
License-Expression: MIT
|
|
6
|
-
License-File: LICENSE
|
|
7
|
-
License-File: NOTICE
|
|
8
|
-
Classifier: Framework :: AsyncIO
|
|
9
|
-
Classifier: Operating System :: OS Independent
|
|
10
|
-
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
-
Classifier: Programming Language :: Python :: Free Threading :: 2 - Beta
|
|
17
|
-
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
18
|
-
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
19
|
-
Classifier: Typing :: Typed
|
|
20
|
-
Requires-Python: >=3.11
|
|
21
|
-
Requires-Dist: jsonschema<5,>=4.18
|
|
22
|
-
Provides-Extra: mcp
|
|
23
|
-
Requires-Dist: mcp>=1.10; extra == 'mcp'
|
|
24
|
-
Provides-Extra: providers
|
|
25
|
-
Requires-Dist: httpx<1,>=0.27; extra == 'providers'
|
|
26
|
-
Requires-Dist: pyjwt[crypto]<3,>=2.8; extra == 'providers'
|
|
27
|
-
Requires-Dist: websockets>=14.2; extra == 'providers'
|
|
28
|
-
Description-Content-Type: text/markdown
|
|
29
|
-
|
|
30
|
-
# pi-python-core
|
|
31
|
-
|
|
32
|
-
一个可嵌入的 Python agent 核心,移植自 [Pi](https://github.com/earendil-works/pi)(固定参照 `v1.0.0`)。它负责一件事:把对话发给模型,执行模型要求的工具,把结果交回模型,直到得到回答。工具就是普通的 Python 函数;模型可以是 Claude、GPT、DeepSeek,也可以是本机或集群上的开源模型。
|
|
33
|
-
|
|
34
|
-
PyPI 上的 `pi-agent-core` 是另一个独立项目,移植的是 2026 年初 pi-mono 中的旧版本。本库对照 Pi v1.0.0 的行为,与上游的实际运行结果逐组比较;并自带 Claude、OpenAI、DeepSeek 和本地模型的接入,不需要安装任何模型 SDK。
|
|
35
|
-
|
|
36
|
-
## 安装
|
|
37
|
-
|
|
38
|
-
支持 Python 3.11–3.14(包括无 GIL 的 3.14t)和 PyPy 3.11,不需要 Node 或任何模型 SDK。
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
pip install 'pi-python-core[providers]' # 或 uv add 'pi-python-core[providers]'
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
安装名是 `pi-python-core`,导入名是 `pi_python`。
|
|
45
|
-
|
|
46
|
-
| 安装选项 | 带来什么 |
|
|
47
|
-
|---|---|
|
|
48
|
-
| 不加选项 | 执行核心,只依赖 `jsonschema` |
|
|
49
|
-
| `[providers]` | 真实模型接入:Claude、OpenAI、Codex、DeepSeek,以及任何 OpenAI 兼容服务(Ollama、vLLM、llama.cpp 等) |
|
|
50
|
-
| `[mcp]` | 把 MCP 服务器的工具交给 agent |
|
|
51
|
-
|
|
52
|
-
依赖写的是版本范围而不是固定版本,能和大多数已有环境共存。
|
|
53
|
-
|
|
54
|
-
## 五分钟上手
|
|
55
|
-
|
|
56
|
-
```python
|
|
57
|
-
from pi_python import Agent, tool
|
|
58
|
-
from pi_python.providers import AnthropicProvider
|
|
59
|
-
|
|
60
|
-
@tool
|
|
61
|
-
def word_count(text: str) -> int:
|
|
62
|
-
"""Count the words in a text."""
|
|
63
|
-
return len(text.split())
|
|
64
|
-
|
|
65
|
-
agent = Agent(provider=AnthropicProvider(api_key="..."), model="claude-sonnet-4-5", tools=[word_count])
|
|
66
|
-
result = agent.prompt_sync("How many words are in 'to be or not to be'?")
|
|
67
|
-
print(result.messages[-1].content[0].text)
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
`@tool` 从函数签名和文档字符串生成工具;普通函数和 `async` 函数都可以。在异步程序里用 `await agent.prompt(...)`。换成本地模型只改两行:
|
|
71
|
-
|
|
72
|
-
```python
|
|
73
|
-
from pi_python.providers import OpenAICompletionsProvider
|
|
74
|
-
|
|
75
|
-
llm = OpenAICompletionsProvider(base_url="http://localhost:11434/v1", name="ollama")
|
|
76
|
-
agent = Agent(provider=llm, model=llm.model("qwen3:8b", context_window=40960), tools=[word_count])
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
不联网也能先跑起来:`python examples/quickstart.py`。
|
|
80
|
-
|
|
81
|
-
## 能做什么
|
|
82
|
-
|
|
83
|
-
| 需要 | 怎么做 | 示例 |
|
|
84
|
-
|---|---|---|
|
|
85
|
-
| 写工具 | `@tool` 装饰普通函数;pydantic 模型、dataclass、枚举、日期等参数自动转换;也接受手写或 MCP 生成的 JSON Schema | [quickstart](examples/quickstart.py) |
|
|
86
|
-
| 接模型 | Claude 与 GPT 的 API key 或订阅登录;DeepSeek;任何 OpenAI 兼容服务 | [local_model](examples/local_model.py),[provider_chat](examples/provider_chat.py) |
|
|
87
|
-
| 用 MCP 工具 | `async with connect_stdio(...) as tools` | [mcp_tools](examples/mcp_tools.py) |
|
|
88
|
-
| 让一个 agent 调用另一个 | 把子 agent 包成工具,取消会一路传下去 | [subagent](examples/subagent.py) |
|
|
89
|
-
| 中途干预 | `steer` 插入指导,`follow_up` 排队后续任务,`abort` 随时取消(任何线程都可以调用) | |
|
|
90
|
-
| 上下文满了、服务出错 | `is_context_overflow`、`is_retryable_error` 判断原因,`continue_run()` 重试,`transform_context` 压缩 | [recovery](examples/recovery.py) |
|
|
91
|
-
| 保存与恢复对话 | `encode_messages` / `decode_messages`,应用决定存在哪里 | [save_restore](examples/save_restore.py) |
|
|
92
|
-
| 观察与审计 | 订阅事件;执行前后的钩子可以阻止、改写工具调用 | |
|
|
93
|
-
|
|
94
|
-
除 `provider_chat` 需要真实凭据外,示例都能离线运行,不需要 API key;测试会逐个运行它们。
|
|
95
|
-
|
|
96
|
-
## 与 Pi 的关系
|
|
97
|
-
|
|
98
|
-
执行循环、事件顺序、钩子、队列、出错与取消的处理都与 Pi 一致,并用差分验证:同一组输入分别交给固定版本的上游代码和本库运行,逐项比较模型请求、工具调用、事件和最终记录。目前核心循环 25 组、模型接入 50 组、WebSocket 多轮 2 组、出错判断 44 条样例全部一致。
|
|
99
|
-
|
|
100
|
-
有几处是有意的差异,例如工具参数严格校验、不自动转换类型,返回给调用者的状态是副本;另一些是为 Python 用户加的,例如 `@tool`、同步调用、失败后直接 `continue_run()`。逐项记录见[验收映射](compat/COVERAGE.md)。Pi 放在应用层的功能(终端界面、会话文件格式、上下文压缩)不在本库核心里;压缩可以用钩子实现,示例里有完整做法。本项目使用自己的版本号,并非 Pi 官方发行版。
|
|
101
|
-
|
|
102
|
-
## 文档
|
|
103
|
-
|
|
104
|
-
- [一页看懂:五个概念和一轮的流程](docs/CONCEPTS.md)
|
|
105
|
-
- [公开 API](docs/API.md)
|
|
106
|
-
- [模型接入、订阅登录与本地模型](docs/PROVIDERS.md)
|
|
107
|
-
- [实施与验证结果](docs/IMPLEMENTATION.md)
|
|
108
|
-
- [与 Pi 的逐项对照和有意差异](compat/COVERAGE.md)
|
|
109
|
-
- [参照重建与候选版本验证](reference/README.md)
|
|
110
|
-
|
|
111
|
-
## 开发
|
|
112
|
-
|
|
113
|
-
```bash
|
|
114
|
-
uv sync --locked --extra providers --extra mcp
|
|
115
|
-
uv run pytest -q
|
|
116
|
-
uv run python scripts/verify.py # 全部检查,含与上游的差分(需要 Node)
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
CI 配置在 `.github/workflows/ci.yml`,每次推送都在 GitHub Actions 上运行,覆盖 Linux 上的各个 Python 版本(含 3.14t 和 PyPy)以及 macOS 和 Windows。
|
|
File without changes
|
|
File without changes
|
|
File without changes
|