Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,24 @@
本项目在 `CHANGELOG.md` 中保留公共的、用户可见的变更记录。
具体的提交记录参见 [GitHub Releases](https://github.com/earendil-works/pi-py/releases)。

## 0.82.1 (2026-07-27)

对齐上游 v0.82.1。

### 新增

- `Tool.constrainedSampling`:支持 strict JSON Schema 与 OpenAI Lark/regex grammar 工具。
- OpenAI 与 Anthropic provider 请求级可取消重试,并遵循服务端 retry headers。

### 修复

- DNS `getaddrinfo`、`ENOTFOUND`、`EAI_AGAIN` 传输失败可触发 assistant 重试。
- Compaction 摘要请求使用独立 routing session,并禁用 prompt-cache 写入。

### 维护

- 五个 Python 包统一升级到 0.82.1,内部依赖范围更新为 `<0.83`。

## 0.81.1 (2026-07-22) — 初始基线

首次发布,对齐上游 v0.81.1。
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

## 同步状态

- **当前对齐版本**:[`v0.81.1`](./UPSTREAM_VERSION)(2026-07-21
- **当前对齐版本**:[`v0.82.1`](./UPSTREAM_VERSION)(2026-07-25
- **同步策略**:仅在上游发布 `0.x.0`(minor)时集中同步,详见 [`SYNC.md`](./SYNC.md)

| 包 | 上游对应 | 状态 | 说明 |
Expand Down Expand Up @@ -139,7 +139,7 @@ uv run mypy # 类型检查(strict)

## 路线图

- [x] 5 包基线完成(对齐上游 v0.81.1)
- [x] 5 包基线完成(对齐上游 v0.82.1)
- [x] OpenAI/DeepSeek provider 真实验证
- [x] Anthropic provider(纯逻辑测试,待真实 API 验证)
- [ ] Google / Mistral / Bedrock provider
Expand Down
1 change: 1 addition & 0 deletions SYNC.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,4 @@ LLM provider 的 API 变动频繁,两个 minor 之间可能积累"上游已修
| 日期 | 上游版本 | 说明 |
|---|---|---|
| 2026-07-22 | 0.81.1 | 推翻重建,建立新基线(对应上游 v0.81.1) |
| 2026-07-27 | 0.82.1 | 适配受约束工具采样、可取消 provider 重试与摘要请求隔离 |
2 changes: 1 addition & 1 deletion UPSTREAM_VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.81.1
0.82.1
10 changes: 9 additions & 1 deletion packages/pi-agent-core/PORTING.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# pi-agent-core 移植注记

对应上游:[`@earendil-works/pi-agent-core`](https://github.com/earendil-works/pi/tree/main/packages/agent)(v0.81.1)
对应上游:[`@earendil-works/pi-agent-core`](https://github.com/earendil-works/pi/tree/main/packages/agent)(v0.82.1)

## 有意偏离上游

Expand All @@ -15,6 +15,14 @@

(暂无)

## v0.82.1 同步说明

- Compaction/summary 请求使用独立 routing session,并强制
`cache_retention="none"`,避免污染主会话缓存。
- Agent tools 会将 `constrained_sampling` 透传到 pi-ai。
- 上游新增的 Harness execution tools 与本仓库 `pi-coding-agent` 工具集职责重叠;
当前精简 Harness 尚未公开 `ExecutionEnv`/`toolContext`,因此未引入不完整兼容层。

## 待办

- [ ] agent-loop.ts(无状态循环引擎)
Expand Down
4 changes: 2 additions & 2 deletions packages/pi-agent-core/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
[project]
name = "pi-agent-core"
version = "0.81.1"
version = "0.82.1"
description = "Python port of @earendil-works/pi-agent-core — General-purpose agent runtime"
readme = "README.md"
license = { text = "MIT" }
requires-python = ">=3.11"
authors = [{ name = "Justin Gao" }]
dependencies = [
"pi-ai>=0.81.1,<0.82",
"pi-ai>=0.82.1,<0.83",
"pydantic>=2.7",
"pyyaml>=6",
]
Expand Down
4 changes: 2 additions & 2 deletions packages/pi-agent-core/src/pi_agent_core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ async def execute(self, tool_call_id, params, cancel_event, on_update):

from __future__ import annotations

__version__ = "0.81.1"
__upstream_ref__ = "earendil-works/pi@v0.81.1"
__version__ = "0.82.1"
__upstream_ref__ = "earendil-works/pi@v0.82.1"

# ---- 类型 ----
# ---- 有状态 Agent ----
Expand Down
9 changes: 8 additions & 1 deletion packages/pi-agent-core/src/pi_agent_core/agent_loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,14 @@ def _convert_tools(tools: list[AgentTool]) -> list[Any]:
out = []
for t in tools:
params = t.parameters
out.append(Tool(name=t.name, description=t.description, parameters=params))
out.append(
Tool(
name=t.name,
description=t.description,
parameters=params,
constrained_sampling=getattr(t, "constrained_sampling", None),
)
)
return out


Expand Down
12 changes: 7 additions & 5 deletions packages/pi-agent-core/src/pi_agent_core/harness/compaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from __future__ import annotations

import json
import uuid
from dataclasses import dataclass, field
from typing import Any

Expand Down Expand Up @@ -187,11 +188,12 @@ async def generate_summary(
from pi_ai import Context, SimpleStreamOptions

ctx = Context(system_prompt=SUMMARIZATION_SYSTEM_PROMPT, messages=[ctx_msg])
opts = (
SimpleStreamOptions(max_tokens=2000, **options)
if options
else SimpleStreamOptions(max_tokens=2000)
)
isolated_options = {
**options,
"session_id": str(uuid.uuid4()),
"cache_retention": "none",
Comment on lines +191 to +194

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Apply compaction isolation options in built-in providers

When compaction uses either built-in OpenAI or Anthropic provider, these newly assigned values do not isolate anything because neither provider reads session_id or cache_retention when building its request (the fields otherwise only occur in the option models). The summary therefore uses the provider's normal routing and cache behavior despite the random session and none retention; translate these options into the appropriate request parameters or headers before relying on them here.

Useful? React with 👍 / 👎.

}
opts = SimpleStreamOptions(max_tokens=2000, **isolated_options)
result = await complete_simple(model, ctx, opts)
# 提取文本
if result.content and isinstance(result.content[0], TextContent):
Expand Down
30 changes: 30 additions & 0 deletions packages/pi-agent-core/tests/test_compaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
)
from pi_ai import (
AssistantMessage,
Model,
TextContent,
ToolCall,
ToolResultMessage,
Expand Down Expand Up @@ -144,3 +145,32 @@ def test_find_cut_point_avoids_tool_result():

def test_find_cut_point_empty():
assert find_cut_point([], keep_recent_tokens=100) == 0


async def test_generate_summary_isolates_routing_session_and_disables_cache(monkeypatch):
from pi_agent_core.harness import compaction

captured = []

async def fake_complete(model, context, options):
captured.append(options)
return AssistantMessage(content=[TextContent(text="summary")])

monkeypatch.setattr(compaction, "complete_simple", fake_complete)
model = Model(
id="test",
name="test",
api="openai-completions",
provider="test",
base_url="https://example.com",
)

first = await compaction.generate_summary(
model, [_user("first")], session_id="original", cache_retention="long"
)
second = await compaction.generate_summary(model, [_user("second")])

assert first == second == "summary"
assert captured[0].cache_retention == "none"
assert captured[0].session_id != "original"
assert captured[0].session_id != captured[1].session_id
4 changes: 2 additions & 2 deletions packages/pi-agent-core/tests/test_smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
def test_import() -> None:
import pi_agent_core

assert pi_agent_core.__version__
assert pi_agent_core.__upstream_ref__ == "earendil-works/pi@v0.81.1"
assert pi_agent_core.__version__ == "0.82.1"
assert pi_agent_core.__upstream_ref__ == "earendil-works/pi@v0.82.1"
13 changes: 12 additions & 1 deletion packages/pi-ai/PORTING.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# pi-ai 移植注记

对应上游:[`@earendil-works/pi-ai`](https://github.com/earendil-works/pi/tree/main/packages/ai)(v0.81.1)
对应上游:[`@earendil-works/pi-ai`](https://github.com/earendil-works/pi/tree/main/packages/ai)(v0.82.1)

## 进度

Expand All @@ -16,6 +16,7 @@
| providers/openai(Chat Completions) | ✅ | `api/openai-completions.ts` |
| providers/anthropic(含 thinking 支持) | ✅ | `api/anthropic-messages.ts` |
| retry(重试工具) | ✅ | `utils/retry.ts` |
| constrained sampling(strict JSON Schema + OpenAI grammar) | ✅ | `api/constrained-sampling.ts` |
| providers/google / mistral / bedrock | 🟡 后续 | `api/*.ts` |
| auth(OAuth) | 🟡 后续 | `auth/*` |
| images(图像生成) | 🟡 后续 | `images*.ts` |
Expand Down Expand Up @@ -47,6 +48,16 @@

(暂无)

## v0.82.1 同步说明

- `Tool.constrainedSampling` 已映射为 Pydantic 的 `constrained_sampling`
(序列化别名保持 camelCase)。
- OpenAI Chat Completions 支持 strict JSON Schema 与 Lark/regex grammar 工具定义;
Anthropic Messages 支持 strict tool schema。
- OpenAI/Anthropic SDK 内建重试保持关闭,由可取消的 provider retry 包装器处理。
- DNS `getaddrinfo` / `ENOTFOUND` / `EAI_AGAIN` 错误纳入 assistant 自动重试分类。
- OAuth、新 provider 与完整动态模型目录仍属于既有裁剪范围,未在本轮扩展。

## 待办(下一轮)

- [x] Anthropic provider(含 thinking 支持)
Expand Down
2 changes: 1 addition & 1 deletion packages/pi-ai/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "pi-ai"
version = "0.81.1"
version = "0.82.1"
description = "Python port of @earendil-works/pi-ai — Unified LLM API with multi-provider streaming"
readme = "README.md"
license = { text = "MIT" }
Expand Down
4 changes: 2 additions & 2 deletions packages/pi-ai/src/pi_ai/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@

from __future__ import annotations

__version__ = "0.81.1"
__upstream_ref__ = "earendil-works/pi@v0.81.1"
__version__ = "0.82.1"
__upstream_ref__ = "earendil-works/pi@v0.82.1"

# ---- 类型 ----
# ---- 事件流 ----
Expand Down
Loading
Loading