pi-python-core 0.10.2__tar.gz → 0.11.0__tar.gz
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_core-0.10.2 → pi_python_core-0.11.0}/PKG-INFO +2 -2
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/README.md +1 -1
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/README.zh-CN.md +1 -1
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/COVERAGE.md +10 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/verification.json +38 -25
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/docs/API.md +2 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/docs/CODING_AGENTS.md +2 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/docs/PROVIDERS.md +37 -1
- pi_python_core-0.11.0/docs/releases/0.11.0.md +40 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/docs/zh/API.md +2 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/docs/zh/CODING_AGENTS.md +2 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/docs/zh/PROVIDERS.md +37 -1
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/pyproject.toml +1 -1
- pi_python_core-0.11.0/src/pi_python/_version.py +1 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/agent.py +35 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/features.py +1 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/loop.py +8 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/provider.py +18 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/providers/openai.py +23 -11
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_application_tools.py +4 -1
- pi_python_core-0.11.0/tests/test_cache_sessions.py +310 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_features.py +1 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_websocket_continuation.py +49 -3
- pi_python_core-0.10.2/src/pi_python/_version.py +0 -1
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/.gitignore +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/LICENSE +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/NOTICE +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/__init__.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/baseline.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/contracts/release-candidate.example.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/contracts/release-candidate.schema.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/contracts/upstream-baseline.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C01-text.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C02-tool.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C03-sequential.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C04-parallel.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C05-one-sequential.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C06-one-failure.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C07-unknown.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C08-prepare.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C09-before-error.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C09-block.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C09-replace.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C10-length.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C11-transform.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C12-system.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C13-steering.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C14-followup-all.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C14-followup-one.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C15-prepare.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C16-continue.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C16-end.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C16-mixed.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C16-terminate.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C19-abort-stream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C19-abort-tools.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/fixtures/C24-provider-error.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/plugin-cases.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/plugin-fixtures/prompts/notes.txt +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/plugin-fixtures/prompts/plan.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/plugin-fixtures/prompts/review.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/plugin-fixtures/prompts/sub/nested.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/plugin-fixtures/prompts/summarize.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/plugin-fixtures/skills/.hidden/SKILL.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/plugin-fixtures/skills/alpha/SKILL.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/plugin-fixtures/skills/alpha/references/notes.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/plugin-fixtures/skills/beta/SKILL.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/plugin-fixtures/skills/broken/SKILL.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/plugin-fixtures/skills/delta/SKILL.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/plugin-fixtures/skills/gamma/SKILL.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/plugin-fixtures/skills/longdesc/SKILL.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/plugin-fixtures/skills/loose.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/plugin-fixtures/skills/nested/group/epsilon/SKILL.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/plugin-fixtures/skills/noname/SKILL.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/plugin-fixtures/skills/plain.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/plugin-fixtures/skills/zeta/SKILL.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/plugin-fixtures/skills/zeta/sub/eta/SKILL.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/anthropic-oauth.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/anthropic-request-cache-long.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/anthropic-request-cache-none.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/anthropic-request-replay.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/anthropic-request-tools-image.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/anthropic-text.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/anthropic-thinking.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/anthropic-tool.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/codex-request-tools-image.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/codex-text.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/completions-compat-strict.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/completions-deepseek.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/completions-format-ant-ling.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/completions-format-baseten.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/completions-format-string-thinking.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/completions-format-together.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/completions-format-zai.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/completions-midconvo-tools.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/completions-moonshot-usage.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/completions-openai-off.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/completions-openrouter.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/completions-qwen-length.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/completions-reasoning-content.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/completions-request-replay.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/completions-text.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/completions-tool-stream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/openai-incomplete.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/openai-request-cache-long.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/openai-request-cache-none.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/openai-request-reasoning.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/openai-request-replay.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/openai-request-tools-image.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/openai-text.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/openai-thinking-backfill.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/openai-thinking.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/openai-tool.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/proxy-text.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/proxy-thinking-tool.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/session-anthropic-collapse-budget.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/session-anthropic-native-tools.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/session-anthropic-oauth-effort.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/session-anthropic-redefinition.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/session-anthropic-server-fallback.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/session-anthropic-thinking-off.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/session-codex-tool-search.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/session-openai-additional-tools.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/session-openai-collapse.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/session-openai-explicit-cache-long.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/session-openai-explicit-cache-none.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/provider-fixtures/session-openai-removal.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/recovery-cases.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/release.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C01-text.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C01-text.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C02-tool.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C02-tool.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C03-sequential.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C03-sequential.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C04-parallel.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C04-parallel.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C05-one-sequential.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C05-one-sequential.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C06-one-failure.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C06-one-failure.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C07-unknown.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C07-unknown.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C08-prepare.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C08-prepare.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C09-before-error.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C09-before-error.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C09-block.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C09-block.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C09-replace.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C09-replace.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C10-length.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C10-length.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C11-transform.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C11-transform.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C12-system.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C12-system.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C13-steering.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C13-steering.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C14-followup-all.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C14-followup-all.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C14-followup-one.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C14-followup-one.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C15-prepare.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C15-prepare.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C16-continue.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C16-continue.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C16-end.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C16-end.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C16-mixed.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C16-mixed.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C16-terminate.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C16-terminate.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C19-abort-stream.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C19-abort-stream.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C19-abort-tools.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C19-abort-tools.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C24-provider-error.python.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/C24-provider-error.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/artifacts.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/benchmark.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/bootstrap.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/candidate-live-noop.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/conformance.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/linux-3.11.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/linux-3.12.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/linux-3.13.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/linux-3.14.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/linux-install-hash-repair.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/live-0.5-regression.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/live-0.5-session-claude.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/live-0.5-session-codex.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/live-claude-reasoning-replay.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/live-final-matrix.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/live-initial.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/live-loop-initial.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/live-providers.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/live-reasoning-replay.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/live-refresh.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/live-regression-0.4-deepseek.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/live-regression-0.4-first-run.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/live-regression-0.4.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/live-session-claude.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/live-session-codex.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/live-websocket-cached-recheck.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/live-websocket-cached.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/live-websocket-final.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/plugins.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/provider-conformance.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/recovery-conformance.upstream.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/runtime-dependencies.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/source-verification.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.1.0/artifacts.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.1.0/linux-3.11.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.1.0/linux-3.12.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.1.0/linux-3.13.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.1.0/verification.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.2.0/artifacts.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.2.0/linux-3.11.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.2.0/linux-3.12.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.2.0/linux-3.13.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.2.0/verification.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.3.0/against-0.4-fixtures.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.3.0/artifacts.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.3.0/linux-3.11.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.3.0/linux-3.12.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.3.0/linux-3.13.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.3.0/provider-conformance.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.3.0/verification.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.4.0/artifacts.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.4.0/linux-3.11.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.4.0/linux-3.12.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.4.0/linux-3.13.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.4.0/verification.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.5.0/artifacts.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.5.0/linux-3.11.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.5.0/linux-3.12.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.5.0/linux-3.13.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.5.0/verification.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.6.0/artifacts.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.6.0/linux-3.11.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.6.0/linux-3.12.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.6.0/linux-3.13.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.6.0/verification.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.7.0/artifacts.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.7.0/linux-3.11.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.7.0/linux-3.12.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.7.0/linux-3.13.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.7.0/linux-3.14.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.7.0/verification.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.8.0/artifacts.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.8.0/linux-3.11.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.8.0/linux-3.12.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.8.0/linux-3.13.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.8.0/linux-3.14.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/v0.8.0/verification.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/results/websocket-conformance.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/runner.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/websocket-fixtures/codex-continuation-lost-state.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/compat/websocket-fixtures/codex-continuation-tool-loop.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/docs/APPLICATION_TOOLS_IMPLEMENTATION.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/docs/CONCEPTS.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/docs/IMPLEMENTATION.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/docs/MCP_INTERACTION.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/docs/PLUGINS.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/docs/PLUGIN_DEVELOPMENT.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/docs/history/IMPLEMENTATION-0.3.0.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/docs/history/IMPLEMENTATION-0.4.0.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/docs/history/IMPLEMENTATION-0.5.0.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/docs/history/IMPLEMENTATION-0.6.0.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/docs/history/IMPLEMENTATION-0.7.0.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/docs/history/IMPLEMENTATION-0.8.0.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/docs/releases/0.10.2.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/docs/zh/CONCEPTS.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/docs/zh/MCP_HOST_VERIFICATION.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/docs/zh/MCP_INTERACTION.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/docs/zh/PLUGINS.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/docs/zh/PLUGIN_DEVELOPMENT.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/examples/capability_composition.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/examples/in_memory.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/examples/local_model.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/examples/mcp_interactive.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/examples/mcp_interactive_server.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/examples/mcp_tools.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/examples/memory_demo.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/examples/plugin_demo.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/examples/plugins/lab_tools/agents/reviewer.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/examples/plugins/lab_tools/ops.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/examples/plugins/lab_tools/plugin.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/examples/plugins/lab_tools/prompts/dedup.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/examples/plugins/lab_tools/skills/dedup-window/SKILL.md +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/examples/plugins/memory/plugin.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/examples/provider_chat.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/examples/quickstart.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/examples/recovery.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/examples/save_restore.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/examples/subagent.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/__init__.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/_mcp_host.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/_mcp_interaction.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/_mcp_process.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/_mcp_sampling.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/cancellation.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/data/models.json +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/errors.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/estimate.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/events.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/function_tools.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/hooks.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/limits.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/lowlevel.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/mcp.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/messages.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/models.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/plugins/__init__.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/plugins/_compose.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/plugins/_frontmatter.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/plugins/_resources.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/plugins/_subagents.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/providers/__init__.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/providers/anthropic.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/providers/common.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/providers/completions.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/providers/oauth.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/providers/transport.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/proxy.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/py.typed +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/queues.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/recovery.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/run.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/stream.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/sync.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/tasks.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/testing.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/tools.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/src/pi_python/transcript.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/servers/mcp_interactive_server.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/servers/mcp_process_server.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/servers/mcp_server.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_application_compatibility.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_capability_composition.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_completions.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_conformance.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_contract_v3.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_control.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_examples.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_extended_core.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_function_tools.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_lifecycle_contracts.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_loop.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_mcp.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_mcp_delta.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_mcp_host.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_mcp_interaction.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_mcp_process.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_messages.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_models.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_nested_agents.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_oauth.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_plugin_conformance.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_plugins.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_providers.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_recovery.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_recovery_conformance.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_recovery_helpers.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_release.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_session_changes.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_sync.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_tasks.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_tools.py +0 -0
- {pi_python_core-0.10.2 → pi_python_core-0.11.0}/tests/test_typeddict_annotations.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pi-python-core
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.11.0
|
|
4
4
|
Summary: An embeddable asyncio agent core with opt-in Claude and OpenAI providers
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -111,7 +111,7 @@ Apart from `provider_chat`, which needs real credentials, every example runs off
|
|
|
111
111
|
|
|
112
112
|
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. The plugin rules for skills, prompt templates and frontmatter are compared the same way against Pi's coding-agent code.
|
|
113
113
|
|
|
114
|
-
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. Plugins are
|
|
114
|
+
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. The Agent also supplies cache-only session IDs for Codex, a responsibility upstream assigns to its coding-agent layer; see [cache sessions and the opt-out](docs/PROVIDERS.md#automatic-codex-cache-sessions). Plugins are another piece taken from that layer: an optional module that reads Pi's package format and builds an ordinary Agent from it. This project uses its own version numbers and is not an official Pi release.
|
|
115
115
|
|
|
116
116
|
## Documentation
|
|
117
117
|
|
|
@@ -77,7 +77,7 @@ Apart from `provider_chat`, which needs real credentials, every example runs off
|
|
|
77
77
|
|
|
78
78
|
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. The plugin rules for skills, prompt templates and frontmatter are compared the same way against Pi's coding-agent code.
|
|
79
79
|
|
|
80
|
-
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. Plugins are
|
|
80
|
+
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. The Agent also supplies cache-only session IDs for Codex, a responsibility upstream assigns to its coding-agent layer; see [cache sessions and the opt-out](docs/PROVIDERS.md#automatic-codex-cache-sessions). Plugins are another piece taken from that layer: an optional module that reads Pi's package format and builds an ordinary Agent from it. This project uses its own version numbers and is not an official Pi release.
|
|
81
81
|
|
|
82
82
|
## Documentation
|
|
83
83
|
|
|
@@ -77,7 +77,7 @@ agent = Agent(provider=llm, model=llm.model("qwen3:8b", context_window=40960), t
|
|
|
77
77
|
|
|
78
78
|
执行循环、事件顺序、钩子、队列、出错与取消的处理都与 Pi 一致,并用差分验证:同一组输入分别交给固定版本的上游代码和本库运行,逐项比较模型请求、工具调用、事件和最终记录。目前核心循环 25 组、模型接入 50 组、WebSocket 多轮 2 组、出错判断 44 条样例全部一致。插件里技能、提示模板和文件头元数据的规则,也用同样的方法和 Pi 的 coding-agent 代码对照。
|
|
79
79
|
|
|
80
|
-
有几处是有意的差异,例如工具参数严格校验、不自动转换类型,返回给调用者的状态是副本;另一些是为 Python 用户加的,例如 `@tool`、同步调用、失败后直接 `continue_run()`。逐项记录见[验收映射](compat/COVERAGE.md)。Pi
|
|
80
|
+
有几处是有意的差异,例如工具参数严格校验、不自动转换类型,返回给调用者的状态是副本;另一些是为 Python 用户加的,例如 `@tool`、同步调用、失败后直接 `continue_run()`。逐项记录见[验收映射](compat/COVERAGE.md)。Pi 放在应用层的功能(终端界面、会话文件格式、上下文压缩)不在本库核心里;压缩可以用钩子实现,示例里有完整做法。Agent 还为 Codex 自动提供缓存专用会话标识,补齐上游 coding-agent 层承担的职责;见[缓存会话与关闭方式](docs/zh/PROVIDERS.md#codex-自动缓存会话)。插件也是从应用层取来的功能:一个可选模块,读取 Pi 的 package 格式,再据此构造普通的 Agent。本项目使用自己的版本号,并非 Pi 官方发行版。
|
|
81
81
|
|
|
82
82
|
## 文档
|
|
83
83
|
|
|
@@ -45,6 +45,16 @@
|
|
|
45
45
|
|
|
46
46
|
本次沿用现行版本的默认无预算上限、已知取消与显式未知结果的区分,以及可选扩展能力,不把它们按早期草案回退。跨 run 预算、领域效果、科研判断内化和新的包加载器不在本次实现范围内。上述旧验证文件记录的是各自运行时的版本,不自动成为 D9 的验证证据。
|
|
47
47
|
|
|
48
|
+
## D10:Agent 管理 Codex 缓存会话标识
|
|
49
|
+
|
|
50
|
+
0.11.0 在 Agent 入口补齐缓存会话生命周期。官方 Pi v1.0.0 的底层 Agent 只转发 `sessionId`,由 coding-agent 的 `createAgentSession()` 从 `SessionManager` 取值;这一分工在核查的 v1.3.0 中也相同。Python 没有对应的完整上层应用,因而默认在 Agent 提供此便利能力。它是经用户确认的有意差异,不是上游 core 行为完全一致的声明,也不升级固定参照。
|
|
51
|
+
|
|
52
|
+
core 只识别可选的 `supports_agent_cache_session=True` 能力,不绑定模型名或 Provider 类。内置 Codex Provider 使用 `request.cache_session_id` 作为缓存键与会话头的后备值;其他内置 Provider、自定义流和未声明支持的 Provider 不接收自动标识。`DefaultProvider` 转发实际接入的能力。
|
|
53
|
+
|
|
54
|
+
自动值不写入 `options.session_id`,因此不能满足 `websocket-cached` 的显式配置要求,也不能启动连接复用或 `previous_response_id` 续接。原有显式值、钩子及配置更新的优先级保留;自动值尊重应用自定义请求头。`auto_session_id=False` 恢复旧默认,`cache_retention="none"` 抑制库生成的缓存字段。新增属性与构造参数支持保存、恢复后备标识;消息编解码、事件、结果和 ModelRequest 的 dataclass 字段不变。
|
|
55
|
+
|
|
56
|
+
证据:`tests/test_cache_sessions.py` 捕获实际构造的 HTTP 请求,覆盖默认头、工具循环、重试、配置替换、跨 Agent/子 Agent 隔离、重置、恢复、显式优先、禁用、通道切换、自定义 Provider 能力及旧请求结构;`tests/test_websocket_continuation.py` 用本地服务器检查连接数、完整输入和续接字段。恢复的自动值也不触发连接复用;显式标识的原有增量行为单独验证。真实后端命中率、订阅配额节省与所有上层应用不在这些离线检查的证明范围内。
|
|
57
|
+
|
|
48
58
|
## 有意差异与范围外行为
|
|
49
59
|
|
|
50
60
|
D1–D8 保持原设计的含义。D1 严格输入;D2 执行前钩子不能通过原地修改参数改变调用;D3 资源预算;D4 Python 取消及未知结果;D5 状态复制;D6 输出检查;D7 诊断、原始结果和完整流校验;D8 文本与工具子集。每项有独立 Python 断言,不以 skip 代替验收。
|
|
@@ -18,9 +18,9 @@
|
|
|
18
18
|
"mcp-interactive"
|
|
19
19
|
],
|
|
20
20
|
"exit_code": 0,
|
|
21
|
-
"seconds": 0.
|
|
21
|
+
"seconds": 0.021437582792714238,
|
|
22
22
|
"stdout": "",
|
|
23
|
-
"stderr": "Resolved 60 packages in 2ms\nAudited 57 packages in
|
|
23
|
+
"stderr": "Resolved 60 packages in 2ms\nAudited 57 packages in 6ms\n"
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
26
|
"command": [
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"scripts"
|
|
36
36
|
],
|
|
37
37
|
"exit_code": 0,
|
|
38
|
-
"seconds": 0.
|
|
38
|
+
"seconds": 0.061738125048577785,
|
|
39
39
|
"stdout": "All checks passed!\n",
|
|
40
40
|
"stderr": ""
|
|
41
41
|
},
|
|
@@ -53,8 +53,8 @@
|
|
|
53
53
|
"scripts"
|
|
54
54
|
],
|
|
55
55
|
"exit_code": 0,
|
|
56
|
-
"seconds": 0.
|
|
57
|
-
"stdout": "
|
|
56
|
+
"seconds": 0.02676033414900303,
|
|
57
|
+
"stdout": "115 files already formatted\n",
|
|
58
58
|
"stderr": ""
|
|
59
59
|
},
|
|
60
60
|
{
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"src/pi_python"
|
|
66
66
|
],
|
|
67
67
|
"exit_code": 0,
|
|
68
|
-
"seconds": 0.
|
|
68
|
+
"seconds": 0.40783704188652337,
|
|
69
69
|
"stdout": "Success: no issues found in 43 source files\n",
|
|
70
70
|
"stderr": ""
|
|
71
71
|
},
|
|
@@ -77,8 +77,8 @@
|
|
|
77
77
|
"-q"
|
|
78
78
|
],
|
|
79
79
|
"exit_code": 0,
|
|
80
|
-
"seconds":
|
|
81
|
-
"stdout": "........................................................................ [
|
|
80
|
+
"seconds": 143.989434374962,
|
|
81
|
+
"stdout": "........................................................................ [ 8%]\n........................................................................ [ 17%]\n........................................................................ [ 25%]\n........................................................................ [ 34%]\n........................................................................ [ 43%]\n........................................................................ [ 51%]\n........................................................................ [ 60%]\n........................................................................ [ 69%]\n...................................................ss................... [ 77%]\n........................................................................ [ 86%]\n........................................................................ [ 94%]\n.......................................... [100%]\n832 passed, 2 skipped in 143.31s (0:02:23)\n",
|
|
82
82
|
"stderr": ""
|
|
83
83
|
},
|
|
84
84
|
{
|
|
@@ -89,10 +89,22 @@
|
|
|
89
89
|
"examples/in_memory.py"
|
|
90
90
|
],
|
|
91
91
|
"exit_code": 0,
|
|
92
|
-
"seconds": 0.
|
|
92
|
+
"seconds": 0.49026058288291097,
|
|
93
93
|
"stdout": "The telemetry contains 3 complete records.\n",
|
|
94
94
|
"stderr": ""
|
|
95
95
|
},
|
|
96
|
+
{
|
|
97
|
+
"command": [
|
|
98
|
+
"uv",
|
|
99
|
+
"run",
|
|
100
|
+
"python",
|
|
101
|
+
"examples/capability_composition.py"
|
|
102
|
+
],
|
|
103
|
+
"exit_code": 0,
|
|
104
|
+
"seconds": 0.5047036670148373,
|
|
105
|
+
"stdout": "run=completed; domain_passed=False\nBoth paths use the same tool; the application batch made zero model requests.\n",
|
|
106
|
+
"stderr": ""
|
|
107
|
+
},
|
|
96
108
|
{
|
|
97
109
|
"command": [
|
|
98
110
|
"npm",
|
|
@@ -104,8 +116,8 @@
|
|
|
104
116
|
"test/agent.test.ts"
|
|
105
117
|
],
|
|
106
118
|
"exit_code": 0,
|
|
107
|
-
"seconds": 1.
|
|
108
|
-
"stdout": "\n> @earendil-works/pi-agent-core@1.0.0 test\n> vitest --run test/agent-loop.test.ts test/agent.test.ts\n\n\n RUN v4.1.11 /Users/daidong/Documents/gitrepos/pi-python/reference/pi/packages/agent\n\n\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\n\n Test Files 2 passed (2)\n Tests 77 passed (77)\n Start at 12:
|
|
119
|
+
"seconds": 1.0130393749568611,
|
|
120
|
+
"stdout": "\n> @earendil-works/pi-agent-core@1.0.0 test\n> vitest --run test/agent-loop.test.ts test/agent.test.ts\n\n\n RUN v4.1.11 /Users/daidong/Documents/gitrepos/pi-python/reference/pi/packages/agent\n\n\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\n\n Test Files 2 passed (2)\n Tests 77 passed (77)\n Start at 12:56:57\n Duration 643ms (transform 451ms, setup 0ms, import 858ms, tests 171ms, environment 0ms)\n\n",
|
|
109
121
|
"stderr": ""
|
|
110
122
|
},
|
|
111
123
|
{
|
|
@@ -121,8 +133,8 @@
|
|
|
121
133
|
"test/openai-codex-stream.test.ts"
|
|
122
134
|
],
|
|
123
135
|
"exit_code": 0,
|
|
124
|
-
"seconds": 1.
|
|
125
|
-
"stdout": "\n> @earendil-works/pi-ai@1.0.0 test\n> vitest --run test/transcript-tool-changes.test.ts test/validation.test.ts test/anthropic-mid-conversation-effort.test.ts test/openai-codex-stream.test.ts\n\n\n RUN v4.1.11 /Users/daidong/Documents/gitrepos/pi-python/reference/pi/packages/ai\n\n\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\n\n Test Files 4 passed (4)\n Tests 70 passed (70)\n Start at 12:
|
|
136
|
+
"seconds": 1.0957162089180201,
|
|
137
|
+
"stdout": "\n> @earendil-works/pi-ai@1.0.0 test\n> vitest --run test/transcript-tool-changes.test.ts test/validation.test.ts test/anthropic-mid-conversation-effort.test.ts test/openai-codex-stream.test.ts\n\n\n RUN v4.1.11 /Users/daidong/Documents/gitrepos/pi-python/reference/pi/packages/ai\n\n\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\n\n Test Files 4 passed (4)\n Tests 70 passed (70)\n Start at 12:56:58\n Duration 808ms (transform 968ms, setup 0ms, import 1.57s, tests 208ms, environment 0ms)\n\n",
|
|
126
138
|
"stderr": ""
|
|
127
139
|
},
|
|
128
140
|
{
|
|
@@ -133,7 +145,7 @@
|
|
|
133
145
|
"scripts/conformance.py"
|
|
134
146
|
],
|
|
135
147
|
"exit_code": 0,
|
|
136
|
-
"seconds":
|
|
148
|
+
"seconds": 4.930072667077184,
|
|
137
149
|
"stdout": "C01-text: passed []\nC02-tool: passed []\nC03-sequential: passed []\nC04-parallel: passed []\nC05-one-sequential: passed []\nC06-one-failure: passed []\nC07-unknown: passed []\nC08-prepare: passed []\nC09-before-error: passed []\nC09-block: passed []\nC09-replace: passed []\nC10-length: passed []\nC11-transform: passed []\nC12-system: passed []\nC13-steering: passed []\nC14-followup-all: passed []\nC14-followup-one: passed []\nC15-prepare: passed []\nC16-continue: passed []\nC16-end: passed []\nC16-mixed: passed []\nC16-terminate: passed []\nC19-abort-stream: passed []\nC19-abort-tools: passed []\nC24-provider-error: passed []\n",
|
|
138
150
|
"stderr": ""
|
|
139
151
|
},
|
|
@@ -145,7 +157,7 @@
|
|
|
145
157
|
"scripts/provider_conformance.py"
|
|
146
158
|
],
|
|
147
159
|
"exit_code": 0,
|
|
148
|
-
"seconds":
|
|
160
|
+
"seconds": 12.895416000159457,
|
|
149
161
|
"stdout": "anthropic-oauth.json passed\nanthropic-request-cache-long.json passed\nanthropic-request-cache-none.json passed\nanthropic-request-replay.json passed\nanthropic-request-tools-image.json passed\nanthropic-text.json passed\nanthropic-thinking.json passed\nanthropic-tool.json passed\ncodex-request-tools-image.json passed\ncodex-text.json passed\ncompletions-compat-strict.json passed\ncompletions-deepseek.json passed\ncompletions-format-ant-ling.json passed\ncompletions-format-baseten.json passed\ncompletions-format-string-thinking.json passed\ncompletions-format-together.json passed\ncompletions-format-zai.json passed\ncompletions-midconvo-tools.json passed\ncompletions-moonshot-usage.json passed\ncompletions-openai-off.json passed\ncompletions-openrouter.json passed\ncompletions-qwen-length.json passed\ncompletions-reasoning-content.json passed\ncompletions-request-replay.json passed\ncompletions-text.json passed\ncompletions-tool-stream.json passed\nopenai-incomplete.json passed\nopenai-request-cache-long.json passed\nopenai-request-cache-none.json passed\nopenai-request-reasoning.json passed\nopenai-request-replay.json passed\nopenai-request-tools-image.json passed\nopenai-text.json passed\nopenai-thinking-backfill.json passed\nopenai-thinking.json passed\nopenai-tool.json passed\nproxy-text.json passed\nproxy-thinking-tool.json passed\nsession-anthropic-collapse-budget.json passed\nsession-anthropic-native-tools.json passed\nsession-anthropic-oauth-effort.json passed\nsession-anthropic-redefinition.json passed\nsession-anthropic-server-fallback.json passed\nsession-anthropic-thinking-off.json passed\nsession-codex-tool-search.json passed\nsession-openai-additional-tools.json passed\nsession-openai-collapse.json passed\nsession-openai-explicit-cache-long.json passed\nsession-openai-explicit-cache-none.json passed\nsession-openai-removal.json passed\n",
|
|
150
162
|
"stderr": ""
|
|
151
163
|
},
|
|
@@ -157,7 +169,7 @@
|
|
|
157
169
|
"scripts/websocket_conformance.py"
|
|
158
170
|
],
|
|
159
171
|
"exit_code": 0,
|
|
160
|
-
"seconds": 0.
|
|
172
|
+
"seconds": 0.7594145000912249,
|
|
161
173
|
"stdout": "codex-continuation-lost-state.json passed\ncodex-continuation-tool-loop.json passed\n",
|
|
162
174
|
"stderr": ""
|
|
163
175
|
},
|
|
@@ -169,7 +181,7 @@
|
|
|
169
181
|
"scripts/recovery_conformance.py"
|
|
170
182
|
],
|
|
171
183
|
"exit_code": 0,
|
|
172
|
-
"seconds": 0.
|
|
184
|
+
"seconds": 0.5641300419811159,
|
|
173
185
|
"stdout": "recovery classifiers: 44/44 match upstream \n",
|
|
174
186
|
"stderr": ""
|
|
175
187
|
},
|
|
@@ -181,8 +193,8 @@
|
|
|
181
193
|
"scripts/plugin_conformance.py"
|
|
182
194
|
],
|
|
183
195
|
"exit_code": 0,
|
|
184
|
-
"seconds": 1.
|
|
185
|
-
"stdout": "....... [100%]\n7 passed in 0.
|
|
196
|
+
"seconds": 1.0472173751331866,
|
|
197
|
+
"stdout": "....... [100%]\n7 passed in 0.63s\n",
|
|
186
198
|
"stderr": ""
|
|
187
199
|
},
|
|
188
200
|
{
|
|
@@ -193,7 +205,7 @@
|
|
|
193
205
|
"examples/plugin_demo.py"
|
|
194
206
|
],
|
|
195
207
|
"exit_code": 0,
|
|
196
|
-
"seconds": 0.
|
|
208
|
+
"seconds": 0.5162342919502407,
|
|
197
209
|
"stdout": "loaded: lab_tools 0.1.0\ncheck: counts_duplicates passed\nprompt: Find duplicate events in events.csv using a 30 second window. Read the dedup-window skill first.\ntools used: ['read_skill', 'subagent']\nanswer: The reviewer found 2 duplicate rows.\n",
|
|
198
210
|
"stderr": ""
|
|
199
211
|
},
|
|
@@ -205,7 +217,7 @@
|
|
|
205
217
|
"examples/mcp_interactive.py"
|
|
206
218
|
],
|
|
207
219
|
"exit_code": 0,
|
|
208
|
-
"seconds": 1.
|
|
220
|
+
"seconds": 1.685829000081867,
|
|
209
221
|
"stdout": "Model task=demo-run request=1 profile=default attempt=1 usage=None\nModel task=demo-run request=2 profile=default attempt=1 usage=None\nModel task=demo-run request=3 profile=json attempt=1 usage={'input': 4, 'output': 3, 'cacheRead': 1}\nModel task=demo-run request=4 profile=text attempt=1 usage={'input': 4, 'output': 3, 'cacheRead': 1}\nForm from business: Choose output for report\nDemo user chooses: short, confirmed\n{\"label\": \"report\", \"model_reply\": \"[report] [ready]\", \"action\": \"accept\", \"selection\": {\"style\": \"short\", \"confirmed\": true}, \"auxiliary\": {\"json\": {\"ok\": true}, \"text\": \"Ready\"}}\n",
|
|
210
222
|
"stderr": ""
|
|
211
223
|
},
|
|
@@ -218,7 +230,7 @@
|
|
|
218
230
|
"--help"
|
|
219
231
|
],
|
|
220
232
|
"exit_code": 0,
|
|
221
|
-
"seconds": 0.
|
|
233
|
+
"seconds": 0.5009769999887794,
|
|
222
234
|
"stdout": "usage: provider_chat.py [-h]\n --provider {anthropic,openai,openai-codex,openai-chatgpt,deepseek}\n --model MODEL [--prompt PROMPT]\n [--credential-file CREDENTIAL_FILE] [--login]\n [--device]\n [--thinking {off,minimal,low,medium,high,xhigh,max}]\n [--transport {sse,websocket,websocket-cached,auto}]\n [--session-id SESSION_ID]\n\nExplicit API/OAuth example. Invoke --help; never imported by the core.\n\noptions:\n -h, --help show this help message and exit\n --provider {anthropic,openai,openai-codex,openai-chatgpt,deepseek}\n --model MODEL Model ID enabled for this account\n --prompt PROMPT\n --credential-file CREDENTIAL_FILE\n App-owned OAuth file (never reuse another client file)\n --login\n --device Codex device authorization instead of browser callback\n --thinking {off,minimal,low,medium,high,xhigh,max}\n --transport {sse,websocket,websocket-cached,auto}\n --session-id SESSION_ID\n Required for websocket-cached\n",
|
|
223
235
|
"stderr": ""
|
|
224
236
|
},
|
|
@@ -228,10 +240,11 @@
|
|
|
228
240
|
"build"
|
|
229
241
|
],
|
|
230
242
|
"exit_code": 0,
|
|
231
|
-
"seconds":
|
|
243
|
+
"seconds": 0.8976772499736398,
|
|
232
244
|
"stdout": "",
|
|
233
|
-
"stderr": "Building source distribution...\nBuilding wheel from source distribution...\nSuccessfully built dist/pi_python_core-0.
|
|
245
|
+
"stderr": "Building source distribution...\nBuilding wheel from source distribution...\nSuccessfully built dist/pi_python_core-0.11.0.tar.gz\nSuccessfully built dist/pi_python_core-0.11.0-py3-none-any.whl\n"
|
|
234
246
|
}
|
|
235
247
|
],
|
|
236
|
-
"status": "passed"
|
|
248
|
+
"status": "passed",
|
|
249
|
+
"runner_timeout_seconds": 600
|
|
237
250
|
}
|
|
@@ -271,6 +271,8 @@ The event stream uses a bounded queue. If you only wait for the result, `result(
|
|
|
271
271
|
|
|
272
272
|
An Agent can also be constructed with `thinking_level`, `thinking_budgets`, `transport`, `session_id`, `get_api_key`, `on_payload`, `on_response` and `on_provider_stream_event`. The last four can also go in Hooks; explicit constructor arguments take precedence. Their protocols, and the Provider parameters, are described in [the connector guide](PROVIDERS.md).
|
|
273
273
|
|
|
274
|
+
`auto_session_id=True` supplies an Agent-owned cache-only ID to Providers that opt in (the built-in Codex Provider). `agent.cache_session_id` reads that managed fallback; restore it with `Agent(cache_session_id=saved_id, ...)`. Explicit `session_id` takes precedence. `reset()` rotates the managed fallback, and `auto_session_id=False` disables it. Automatic/restored cache IDs never enable connection reuse. See [cache sessions, persistence and Provider opt-in](PROVIDERS.md#automatic-codex-cache-sessions).
|
|
275
|
+
|
|
274
276
|
## Fields of messages, tool results and events
|
|
275
277
|
|
|
276
278
|
`SystemMessage.content` accepts a string or a list of text blocks. `AssistantMessage` also contains `response_model`, `response_id`, `thinking_level`, `diagnostics`, `raw_stop_reason`, `end_turn` and `deferred`. `provider_thinking_level` is the provider's native effort; `thinking_level` is the requested level. Fields whose value is null in arbitrary user JSON are preserved intact.
|
|
@@ -139,6 +139,8 @@ Do not move that connection to `run_sync`'s separate loop. See
|
|
|
139
139
|
These APIs and feature declarations are part of the 0.10.0 source line; check
|
|
140
140
|
`require_features(["task-scope-v1", "loop-portal-v1"])` when depending on them.
|
|
141
141
|
|
|
142
|
+
For Codex subscriptions, Agent supplies a stable cache ID by default. Save `agent.cache_session_id` alongside the message history and restore it with `Agent(cache_session_id=..., messages=...)`. This retains cache-only behavior; it does not enable connection reuse. Use `auto_session_id=False` to opt out. Other built-in Providers and custom streams keep their existing behavior. See [cache sessions](PROVIDERS.md#automatic-codex-cache-sessions).
|
|
143
|
+
|
|
142
144
|
## 5. Choose the smallest integration surface
|
|
143
145
|
|
|
144
146
|
| Need | Start here |
|
|
@@ -100,7 +100,7 @@ Claude models that support changing reasoning effort mid-conversation (`supports
|
|
|
100
100
|
|
|
101
101
|
OpenAI maps `thinking_level` to reasoning effort. `options` supports `max_tokens`, `reasoning_summary`, `temperature`, `top_p`, `tool_choice`, `parallel_tool_calls`, `metadata`, `service_tier`, `text` and `headers`; Claude also supports `thinking_budgets`, `thinking_display`, `interleaved_thinking`, `top_k`, `stop_sequences`, and direct overrides of `thinking` and `output_config`. As upstream does, Claude forwards only `metadata.user_id`, writes a string `tool_choice` as `{"type": ...}`, and does not send `temperature` when reasoning is on, when the model does not support it, or when effort markers are in use. Which parameters a given model accepts is up to the server.
|
|
102
102
|
|
|
103
|
-
Claude uses SSE. OpenAI and Codex support `sse`, `websocket`, `websocket-cached` and `auto`. `websocket-cached` requires `session_id`; as upstream does, `auto` also reuses the connection when there is
|
|
103
|
+
Claude uses SSE. OpenAI and Codex support `sse`, `websocket`, `websocket-cached` and `auto`. `websocket-cached` requires an application-supplied `session_id`; as upstream does, `auto` also reuses the connection when there is an application-supplied `session_id`. The Agent-managed cache ID does not enable either behavior. With `cache_retention="none"`, each request uses a one-off connection. Connections are kept apart by endpoint, session and request headers, and each connection is used by one request at a time. A connection is no longer reused after 5 idle minutes or 55 minutes after it was opened, and a connection the server has closed is rebuilt instead of failing on the old one. These limits can be changed with `HTTPTransport(websocket_idle_ttl=..., websocket_max_age=...)`.
|
|
104
104
|
|
|
105
105
|
Expired idle connections are swept on WebSocket requests and cache returns. At most 64 idle connections are retained, evicting the least recently returned first; set `HTTPTransport(websocket_cache_size=...)` to change this limit, or `0` to disable retention. Session locks are removed when their last active or waiting request exits. Sweeping is demand-driven, with no background timer. Call `await provider.aclose()` when you are done; the application manages the lifetime of a shared transport.
|
|
106
106
|
|
|
@@ -123,6 +123,42 @@ Usage is normalized to `input`, `output`, `cache_read`, `cache_write`, `reasonin
|
|
|
123
123
|
counters remain present for compatibility; those default zeros are not measured consumption.
|
|
124
124
|
MCP sampling observations report `usage=None` for this case. A tool's own usage is stored separately in the tool result and is not mixed into the main model's token counts.
|
|
125
125
|
|
|
126
|
+
## Automatic Codex cache sessions
|
|
127
|
+
|
|
128
|
+
From 0.11.0, `Agent` supplies a stable cache ID when using `OpenAICodexProvider` without an application-supplied `session_id`. It fills the `session-id` and `x-client-request-id` headers and `prompt_cache_key`. This applies to the ChatGPT Codex subscription channel, not to OpenAI API-key calls or Claude. The Codex CLI [identifies the session header as the cache-affinity input](https://github.com/openai/codex/blob/e4568a3538c9cab6627d64ff8cdfc7d98b79b7db/codex-rs/core/src/client.rs#L660); sending an ID does not guarantee a cache hit or a particular subscription quota saving.
|
|
129
|
+
|
|
130
|
+
The ID belongs to the Agent, not to the shared Provider or an individual request. Tool loops, later prompts, retries and configuration replacement keep it. Different Agents, including nested Agents, receive independent IDs. `reset()` discards the managed ID, including a restored one; the next access or request generates a new ID. An explicit `session_id` always takes precedence and retains its existing reset behavior. Automatic headers respect application-supplied header values, including differently cased names.
|
|
131
|
+
|
|
132
|
+
The automatic ID **never enables connection reuse or response continuation**. The default transport remains SSE. In `auto` or `websocket` mode it still uses one-off connections and full context unless the application explicitly supplies `session_id` to an eligible mode. `websocket-cached` still requires an explicit `session_id`. Cache affinity and transport session state are separate.
|
|
133
|
+
|
|
134
|
+
Use `Agent(auto_session_id=False, ...)` to keep the previous default. This does not suppress an explicit `session_id`. `options={"cache_retention": "none"}` suppresses library-generated cache keys and session headers for either kind of ID.
|
|
135
|
+
|
|
136
|
+
Save the read-only `agent.cache_session_id` alongside history and restore it through the constructor's `cache_session_id=` argument:
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
from pi_python import Agent, encode_messages, decode_messages
|
|
140
|
+
|
|
141
|
+
# provider is an application-owned OpenAICodexProvider.
|
|
142
|
+
agent = Agent(provider=provider, model=model_id)
|
|
143
|
+
await agent.prompt("Remember the task constraints.")
|
|
144
|
+
saved = {
|
|
145
|
+
"messages": encode_messages(list(agent.state.messages)),
|
|
146
|
+
"cache_session_id": agent.cache_session_id,
|
|
147
|
+
}
|
|
148
|
+
restored = Agent(
|
|
149
|
+
provider=provider, model=model_id,
|
|
150
|
+
messages=decode_messages(saved["messages"]),
|
|
151
|
+
cache_session_id=saved["cache_session_id"],
|
|
152
|
+
)
|
|
153
|
+
await restored.prompt("Continue the task.")
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
The application chooses how to store this object; message encoding itself has not changed. `cache_session_id` is the Agent-managed fallback, not a report of a request's effective routing ID when an explicit `session_id` or custom headers override it. Applications that manage `session_id` must persist that configuration themselves. Restoring with `cache_session_id=` retains cache-only behavior; restoring it as `session_id=` opts into the existing transport semantics. Restored cache IDs must contain 1–64 printable ASCII characters without spaces and require `auto_session_id=True`. The property returns `None` when automatic handling is disabled or the current Provider does not opt in.
|
|
157
|
+
|
|
158
|
+
The core uses an optional Provider capability, `supports_agent_cache_session = True`, rather than inspecting model names or importing a Codex adapter. Only the built-in Codex Provider enables it. Custom Providers may opt in and read `request.cache_session_id`; existing Providers and `stream_fn` implementations require no changes. Wrappers that opt in must preserve the request object or use `deepcopy`: rebuilding it from its serialized dataclass fields drops this cache-only metadata. The default-stream wrapper forwards the underlying Provider's capability. The ID is separate from `request.options`, and does not add dataclass fields to `ModelRequest` or fields to messages, events or results. Calling a Provider directly does not generate an ID.
|
|
159
|
+
|
|
160
|
+
This is an intentional difference from Pi's core Agent, which only forwards an optional ID. Pi's coding-agent layer supplies it through `SessionManager`; pi-python provides that convenience at its primary Agent entry point. The upstream baseline is unchanged. Applications can check `require_features(["codex-auto-cache-session-v1"])` before using this API. See the [0.11.0 compatibility and verification notes](releases/0.11.0.md).
|
|
161
|
+
|
|
126
162
|
## Model table and DeepSeek
|
|
127
163
|
|
|
128
164
|
```python
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# 0.11.0:Codex 默认缓存会话,不改变连接复用
|
|
2
|
+
|
|
3
|
+
使用 Codex 订阅通道的应用过去需要自行提供 `session_id`,漏传时不会自动发送稳定的会话请求头。本版本由 Agent 默认管理缓存标识,减少这种遗漏。自动标识只用于缓存,不会启动 WebSocket 连接复用或上一响应续接。
|
|
4
|
+
|
|
5
|
+
## 使用与生命周期
|
|
6
|
+
|
|
7
|
+
- `Agent(auto_session_id=True)` 为主动声明支持的 Provider 提供稳定标识;内置 Provider 中只有 `OpenAICodexProvider` 开启。core 不按模型名或特定 Provider 类分支,自定义 Provider 和流保持原有合同。
|
|
8
|
+
- 同一 Agent 的工具循环、后续请求、重试和配置替换复用标识;不同 Agent(包括子 Agent)独立生成。`reset()` 后换新标识。
|
|
9
|
+
- `agent.cache_session_id` 读取 Agent 管理的后备标识。与历史一起保存后,用 `Agent(cache_session_id=saved_id, messages=..., ...)` 恢复;恢复后仍不启用连接复用。
|
|
10
|
+
- 应用显式 `session_id` 优先,沿用原有传输语义及 reset 行为。自定义请求头也不会被自动头覆盖。
|
|
11
|
+
- `auto_session_id=False` 恢复旧默认;`options={"cache_retention": "none"}` 停止库自动设置缓存键和关联会话头。
|
|
12
|
+
- `require_features(["codex-auto-cache-session-v1"])` 可检查是否支持此合同。
|
|
13
|
+
|
|
14
|
+
## 兼容性与迁移
|
|
15
|
+
|
|
16
|
+
未传 `session_id` 的 Codex Agent 请求现在会包含 `prompt_cache_key`、`session-id` 和 `x-client-request-id`。严格检查请求内容、快照或自定义网关的应用需要接纳这些字段,或用 `auto_session_id=False` 保持旧请求形状。默认仍为 SSE;自动值不会让已有 `auto` 模式开始复用连接,`websocket-cached` 仍要求应用显式提供 `session_id`。
|
|
17
|
+
|
|
18
|
+
消息编码与历史格式、事件和运行结果字段不变。自动标识通过独立的请求元数据传递,不加入 `ModelRequest` 的 dataclass 字段或 `request.options`。只保存消息不会保存缓存会话;需要跨进程复用的应用须另外保存 `cache_session_id`。应用自己管理显式 `session_id` 时,仍应保存自己的配置。
|
|
19
|
+
|
|
20
|
+
这是对官方 Pi core 的有意扩展:上游底层 Agent 不生成标识,上层 coding-agent 才生成并传入;Python 在主要接入入口补齐该职责。固定参照仍为 Pi v1.0.0。通用 core 仅识别可选能力,其他内置通道不增加自动缓存字段。直接调用 Provider 的应用仍自行管理会话。
|
|
21
|
+
|
|
22
|
+
这一默认行为变化已在实施前经用户确认。库内测试不等于所有实际上层应用兼容。固定版本环境只有升级后才获得此行为。
|
|
23
|
+
|
|
24
|
+
## 验证范围
|
|
25
|
+
|
|
26
|
+
验证覆盖请求头与缓存键、跨轮次与重试、子 Agent 隔离、重置与恢复、显式配置优先、禁用和自定义 Provider。WebSocket 检查使用本地服务器,核对连接次数、完整输入和续接字段。缺少默认会话头的回归测试已在修改前的版本上确认失败。
|
|
27
|
+
|
|
28
|
+
本地全量测试 832 通过、2 跳过;Ruff、格式、mypy 和全部上游差分检查通过,其中核心差分覆盖 25 组。两项跳过适用于不支持 `meta` 的旧版 MCP SDK。完整记录见 [verification.json](../../compat/results/verification.json)。验证运行器的单命令超时临时放宽至 600 秒,仓库脚本未修改。
|
|
29
|
+
|
|
30
|
+
wheel 与源码包通过 `twine check --strict`。wheel 在仓库外的独立 Python 3.11 环境中安装后,版本检查、基础示例与 78 项缓存、WebSocket 和应用兼容性定向测试通过。发布标签为 `v0.11.0`,远端验证与构建通过后才上传 PyPI。
|
|
31
|
+
|
|
32
|
+
首次远端 Windows / Python 3.11 检查发现已有运行超时测试的时序假设:20 毫秒期限可能在工具启动前到达。断言现接受运行超时后的“未启动”或“已取消”,工具自身超时仍要求“已取消”;运行实现没有改变。修正后本地相关定向测试 88 项通过。
|
|
33
|
+
|
|
34
|
+
没有用这些离线结果宣称真实 Codex 缓存命中率、订阅配额节省或所有模型效果。服务端是否命中应通过实际 `cache_read` 用量观察。
|
|
35
|
+
|
|
36
|
+
## 文档
|
|
37
|
+
|
|
38
|
+
- [中文接入与恢复示例](../zh/PROVIDERS.md#codex-自动缓存会话)
|
|
39
|
+
- [English provider guide](../PROVIDERS.md#automatic-codex-cache-sessions)
|
|
40
|
+
- [与上游的差异及验收映射](../../compat/COVERAGE.md#d10agent-管理-codex-缓存会话标识)
|
|
@@ -257,6 +257,8 @@ SDK 不支持 `meta` 时,注册会抛出 `ConfigurationError`。
|
|
|
257
257
|
|
|
258
258
|
构造 Agent 还可传 `thinking_level`、`thinking_budgets`、`transport`、`session_id`、`get_api_key`、`on_payload`、`on_response`、`on_provider_stream_event`。后四项也可放在 Hooks 中,明确的构造参数优先。它们的协议与 Provider 参数详见 [接入说明](PROVIDERS.md)。
|
|
259
259
|
|
|
260
|
+
`auto_session_id=True` 为主动声明支持的 Provider(内置 Codex Provider)提供 Agent 管理的缓存专用标识。用 `agent.cache_session_id` 读取后备标识,用 `Agent(cache_session_id=saved_id, ...)` 恢复。显式 `session_id` 优先;`reset()` 更新后备标识,`auto_session_id=False` 关闭自动处理。自动或恢复的缓存标识不会开启连接复用。详见[缓存会话、持久化与 Provider 能力声明](PROVIDERS.md#codex-自动缓存会话)。
|
|
261
|
+
|
|
260
262
|
## 消息、工具结果与事件的字段
|
|
261
263
|
|
|
262
264
|
`SystemMessage.content` 接受字符串或文本块列表。`AssistantMessage` 还包含 `response_model`、`response_id`、`thinking_level`、`diagnostics`、`raw_stop_reason`、`end_turn` 和 `deferred`。`provider_thinking_level` 是原生 effort,`thinking_level` 是请求等级。任意用户 JSON 中值为 null 的字段完整保留。
|
|
@@ -111,6 +111,8 @@ finally:
|
|
|
111
111
|
|
|
112
112
|
应用自己的异步工作可以交给 `TaskScope`。同步工具的工作线程需要访问已有异步连接时,由连接所属事件循环创建 `LoopPortal`,再用它提交调用,不要把连接移到 `run_sync` 的独立循环。见 [任务归属和线程调用](API.md)。这些 API 和能力声明属于 0.10.0 源码系列;依赖它们时可用 `require_features(["task-scope-v1", "loop-portal-v1"])` 检查。
|
|
113
113
|
|
|
114
|
+
使用 Codex 订阅通道时,Agent 默认提供稳定的缓存标识。将 `agent.cache_session_id` 与消息历史一起保存,并用 `Agent(cache_session_id=..., messages=...)` 恢复,仍保持“只用于缓存”,不会开启连接复用。用 `auto_session_id=False` 关闭自动处理。其他内置 Provider 和自定义流保持原有行为。详见[缓存会话](PROVIDERS.md#codex-自动缓存会话)。
|
|
115
|
+
|
|
114
116
|
## 5. 按需求选择接入方式
|
|
115
117
|
|
|
116
118
|
| 需要什么 | 从哪里开始 |
|
|
@@ -100,7 +100,7 @@ Claude 的推理方式由模型记录决定:`compat["forceAdaptiveThinking"]`
|
|
|
100
100
|
|
|
101
101
|
OpenAI 将 `thinking_level` 映射到 reasoning effort。`options` 支持 `max_tokens`、`reasoning_summary`、`temperature`、`top_p`、`tool_choice`、`parallel_tool_calls`、`metadata`、`service_tier`、`text`、`headers`;Claude 另支持 `thinking_budgets`、`thinking_display`、`interleaved_thinking`、`top_k`、`stop_sequences`,以及直接覆盖的 `thinking` 和 `output_config`。与上游一致,Claude 只转发 `metadata.user_id`,字符串形式的 `tool_choice` 写成 `{"type": ...}`;推理开启、模型不支持或使用强度标记时不发送 `temperature`。具体模型允许哪些参数由服务端决定。
|
|
102
102
|
|
|
103
|
-
Claude 使用 SSE。OpenAI/Codex 支持 `sse`、`websocket`、`websocket-cached` 和 `auto`。`websocket-cached`
|
|
103
|
+
Claude 使用 SSE。OpenAI/Codex 支持 `sse`、`websocket`、`websocket-cached` 和 `auto`。`websocket-cached` 要求应用显式提供 `session_id`;与上游一致,`auto` 在有显式 `session_id` 时也复用连接。Agent 自动管理的缓存标识不会启用上述行为。`cache_retention="none"` 时每次请求使用一次性连接。连接按端点、会话和请求头隔离,同一连接串行使用;空闲 5 分钟或建立满 55 分钟后不再复用,已被服务端关闭的连接也会重建,而不是在旧连接上失败。时限可用 `HTTPTransport(websocket_idle_ttl=..., websocket_max_age=...)` 调整。
|
|
104
104
|
|
|
105
105
|
每次 WebSocket 请求及归还连接时清扫过期的空闲连接。默认最多保留 64 条空闲连接,超限时先关闭最早归还的连接;可用 `HTTPTransport(websocket_cache_size=...)` 调整,设为 `0` 则不保留连接。会话锁在最后一个运行或等待中的请求退出后移除。清扫由请求触发,没有后台定时器。结束后调用 `await provider.aclose()`;共享 transport 由应用管理生命周期。
|
|
106
106
|
|
|
@@ -120,6 +120,42 @@ OpenAI 对已知模型默认发送模型输出上限(按上下文估算截短
|
|
|
120
120
|
|
|
121
121
|
用量归一化为 `input`、`output`、`cache_read`、`cache_write`、`reasoning`、`total_tokens`。工具自己的用量独立保存在工具结果中,不混入主模型 token 计数。
|
|
122
122
|
|
|
123
|
+
## Codex 自动缓存会话
|
|
124
|
+
|
|
125
|
+
从 0.11.0 起,使用 `OpenAICodexProvider` 的 Agent 在应用未传 `session_id` 时,自动提供稳定的缓存标识,用于 `session-id`、`x-client-request-id` 请求头和 `prompt_cache_key`。这针对 ChatGPT Codex 订阅通道,不适用于 OpenAI API key 通道或 Claude。Codex CLI [明确说明会话头用于缓存亲和性](https://github.com/openai/codex/blob/e4568a3538c9cab6627d64ff8cdfc7d98b79b7db/codex-rs/core/src/client.rs#L660);发送标识不保证命中,也不保证具体的订阅配额节省。
|
|
126
|
+
|
|
127
|
+
标识属于 Agent,不属于共享 Provider 或单次请求。同一 Agent 的工具循环、后续 prompt、重试和配置替换保持标识;不同 Agent(包括子 Agent)各自生成。`reset()` 丢弃自动管理的标识,包括恢复时传入的标识,下次读取或请求时生成新值。应用显式传入的 `session_id` 始终优先,并保持原有 reset 行为。自动请求头尊重应用自行设置的同名头,包括不同大小写形式。
|
|
128
|
+
|
|
129
|
+
自动标识**不会启用连接复用或上一响应续接**。默认传输仍为 SSE。使用 `auto` 或 `websocket` 时,除非应用显式传入 `session_id` 并选择支持复用的模式,否则仍使用一次性连接、发送完整上下文。`websocket-cached` 仍要求显式 `session_id`。缓存亲和性与传输会话状态分开管理。
|
|
130
|
+
|
|
131
|
+
用 `Agent(auto_session_id=False, ...)` 恢复旧默认行为;该开关不屏蔽显式 `session_id`。`options={"cache_retention": "none"}` 对两类标识都停止自动设置缓存键和关联会话头。
|
|
132
|
+
|
|
133
|
+
将只读属性 `agent.cache_session_id` 与历史一起保存,并通过构造参数 `cache_session_id=` 恢复:
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
from pi_python import Agent, encode_messages, decode_messages
|
|
137
|
+
|
|
138
|
+
# provider 是应用管理的 OpenAICodexProvider。
|
|
139
|
+
agent = Agent(provider=provider, model=model_id)
|
|
140
|
+
await agent.prompt("记住任务约束。")
|
|
141
|
+
saved = {
|
|
142
|
+
"messages": encode_messages(list(agent.state.messages)),
|
|
143
|
+
"cache_session_id": agent.cache_session_id,
|
|
144
|
+
}
|
|
145
|
+
restored = Agent(
|
|
146
|
+
provider=provider, model=model_id,
|
|
147
|
+
messages=decode_messages(saved["messages"]),
|
|
148
|
+
cache_session_id=saved["cache_session_id"],
|
|
149
|
+
)
|
|
150
|
+
await restored.prompt("继续任务。")
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
上述对象由应用自行持久化,消息编码格式没有变化。`cache_session_id` 表示 Agent 管理的后备标识;当显式 `session_id` 或自定义请求头覆盖它时,该属性不代表实际请求的路由标识。自行管理 `session_id` 的应用仍需保存自己的配置。通过 `cache_session_id=` 恢复保持“只用于缓存”;改用 `session_id=` 恢复则会采用原有传输语义。恢复值须为 1–64 个不含空格的可打印 ASCII 字符,且 `auto_session_id` 须为 True。关闭自动处理或当前 Provider 未声明支持时,该属性返回 None。
|
|
154
|
+
|
|
155
|
+
core 通过可选的 Provider 能力 `supports_agent_cache_session = True` 判断,不检查模型名,也不导入 Codex 适配器。内置 Provider 中只有 Codex 开启它。自定义 Provider 可主动声明支持并读取 `request.cache_session_id`;已有 Provider 和 `stream_fn` 不需要修改。主动声明支持的包装器应保留原请求或使用 `deepcopy`;通过序列化的 dataclass 字段重建请求会丢失这项缓存专用元数据。默认流包装器会转发底层 Provider 的能力。标识不放入 `request.options`,不增加 `ModelRequest` 的 dataclass 字段,也不增加消息、事件或结果字段。直接调用底层 Provider 不会自动生成标识。
|
|
156
|
+
|
|
157
|
+
这是与官方 Pi core 的有意差异:上游底层 Agent 只转发可选标识,由 coding-agent 的 `SessionManager` 提供;pi-python 在主要的 Agent 接入入口补齐该便利功能。上游参照版本不变。应用可用 `require_features(["codex-auto-cache-session-v1"])` 检查支持情况。兼容性与验证范围见 [0.11.0 发布说明](../releases/0.11.0.md)。
|
|
158
|
+
|
|
123
159
|
## 模型能力表和 DeepSeek
|
|
124
160
|
|
|
125
161
|
```python
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.11.0"
|
|
@@ -69,6 +69,8 @@ class Agent:
|
|
|
69
69
|
thinking_budgets: dict[str, int] | None = None,
|
|
70
70
|
transport: str | None = None,
|
|
71
71
|
session_id: str | None = None,
|
|
72
|
+
auto_session_id: bool = True,
|
|
73
|
+
cache_session_id: str | None = None,
|
|
72
74
|
get_api_key: Callable | None = None,
|
|
73
75
|
on_payload: Callable | None = None,
|
|
74
76
|
on_response: Callable | None = None,
|
|
@@ -87,6 +89,21 @@ class Agent:
|
|
|
87
89
|
if type(include_tool_origin) is not bool:
|
|
88
90
|
raise ConfigurationError("include_tool_origin must be a boolean")
|
|
89
91
|
self.include_tool_origin = include_tool_origin
|
|
92
|
+
if type(auto_session_id) is not bool:
|
|
93
|
+
raise ConfigurationError("auto_session_id must be a boolean")
|
|
94
|
+
if cache_session_id is not None:
|
|
95
|
+
if (
|
|
96
|
+
not isinstance(cache_session_id, str)
|
|
97
|
+
or not 1 <= len(cache_session_id) <= 64
|
|
98
|
+
or any(not "!" <= char <= "~" for char in cache_session_id)
|
|
99
|
+
):
|
|
100
|
+
raise ConfigurationError(
|
|
101
|
+
"cache_session_id must contain 1–64 printable ASCII characters without spaces"
|
|
102
|
+
)
|
|
103
|
+
if not auto_session_id:
|
|
104
|
+
raise ConfigurationError("cache_session_id requires auto_session_id=True")
|
|
105
|
+
self._auto_session_id = auto_session_id
|
|
106
|
+
self._cache_session_id = cache_session_id
|
|
90
107
|
self._queues = MessageQueues(steering_mode, follow_up_mode)
|
|
91
108
|
if provider is not None and stream_fn is not None:
|
|
92
109
|
raise ConfigurationError("Pass provider or stream_fn, not both")
|
|
@@ -148,6 +165,23 @@ class Agent:
|
|
|
148
165
|
self._settled = asyncio.Event()
|
|
149
166
|
self._settled.set()
|
|
150
167
|
|
|
168
|
+
@property
|
|
169
|
+
def cache_session_id(self) -> str | None:
|
|
170
|
+
"""Agent-managed Codex cache fallback, independent of explicit session_id.
|
|
171
|
+
|
|
172
|
+
Save this alongside history and restore it with cache_session_id=... .
|
|
173
|
+
Reading it does not enable connection reuse. Explicit session_id takes
|
|
174
|
+
precedence on requests; cache_retention='none' suppresses both on the wire.
|
|
175
|
+
"""
|
|
176
|
+
if (
|
|
177
|
+
not self._auto_session_id
|
|
178
|
+
or getattr(self.provider, "supports_agent_cache_session", False) is not True
|
|
179
|
+
):
|
|
180
|
+
return None
|
|
181
|
+
if self._cache_session_id is None:
|
|
182
|
+
self._cache_session_id = str(uuid4())
|
|
183
|
+
return self._cache_session_id
|
|
184
|
+
|
|
151
185
|
@property
|
|
152
186
|
def steering_mode(self) -> str:
|
|
153
187
|
return self._queues.steering_mode
|
|
@@ -265,6 +299,7 @@ class Agent:
|
|
|
265
299
|
raise AgentBusyError("Cannot reset while running")
|
|
266
300
|
baseline = current_system_message(self._messages)
|
|
267
301
|
self._messages = [baseline] if baseline else []
|
|
302
|
+
self._cache_session_id = None
|
|
268
303
|
self._last_error = None
|
|
269
304
|
self._run = None
|
|
270
305
|
self.clear_all_queues()
|
|
@@ -105,6 +105,14 @@ async def stream_response(run: Run) -> tuple[AssistantMessage, bool]:
|
|
|
105
105
|
deepcopy(context.options),
|
|
106
106
|
model_info=deepcopy(model) if isinstance(model, ModelInfo) else None,
|
|
107
107
|
)
|
|
108
|
+
if (
|
|
109
|
+
getattr(run.provider, "supports_agent_cache_session", False) is True
|
|
110
|
+
and not request.options.get("session_id")
|
|
111
|
+
and request.options.get("cache_retention") != "none"
|
|
112
|
+
):
|
|
113
|
+
cache_session_id = run.agent.cache_session_id
|
|
114
|
+
if cache_session_id is not None:
|
|
115
|
+
request._set_cache_session_id(cache_session_id)
|
|
108
116
|
if run.hooks.get_api_key:
|
|
109
117
|
request.api_key = await run.hook(
|
|
110
118
|
"get_api_key", getattr(run.provider, "name", request.model)
|
|
@@ -28,6 +28,20 @@ class ModelRequest:
|
|
|
28
28
|
on_response: Callable | None = field(default=None, repr=False)
|
|
29
29
|
on_provider_stream_event: Callable | None = field(default=None, repr=False)
|
|
30
30
|
|
|
31
|
+
def _set_cache_session_id(self, value: str) -> None:
|
|
32
|
+
# Per-request metadata, deliberately outside the public dataclass fields
|
|
33
|
+
# and options. It must never be interpreted as a transport session_id.
|
|
34
|
+
self._agent_cache_session_id = value
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def cache_session_id(self) -> str | None:
|
|
38
|
+
"""Optional Agent-owned cache affinity, never a transport session.
|
|
39
|
+
|
|
40
|
+
Providers opt in with supports_agent_cache_session=True. This property
|
|
41
|
+
is not a dataclass field and does not change serialized request options.
|
|
42
|
+
"""
|
|
43
|
+
return getattr(self, "_agent_cache_session_id", None)
|
|
44
|
+
|
|
31
45
|
|
|
32
46
|
@dataclass
|
|
33
47
|
class ModelEvent:
|
|
@@ -109,6 +123,10 @@ def has_default_stream() -> bool:
|
|
|
109
123
|
|
|
110
124
|
|
|
111
125
|
class DefaultProvider:
|
|
126
|
+
@property
|
|
127
|
+
def supports_agent_cache_session(self) -> bool:
|
|
128
|
+
return getattr(_default_stream, "supports_agent_cache_session", False) is True
|
|
129
|
+
|
|
112
130
|
@property
|
|
113
131
|
def name(self) -> str:
|
|
114
132
|
return getattr(_default_stream, "name", "custom")
|