From 841dae8e018ce410685a33f0def4f3810662355f Mon Sep 17 00:00:00 2001 From: anycodes <21079031+anycodes@users.noreply.github.com> Date: Sun, 18 Oct 2026 17:11:14 +0000 Subject: [PATCH] fix(providers): enforce native terminal capability before wire access --- .agents/README.md | 2 ++ .../verify/2026-10-18-provider-preflight.md | 20 +++++++++++ .../feature/2026-10-18-provider-preflight.md | 36 +++++++++++++++++++ CHANGELOG.md | 2 ++ .../providers/alicloud_express/provider.py | 1 + .../test_terminal_feature_contract.py | 13 +++++++ docs/en/guide/providers.md | 5 +++ docs/zh/guide/providers.md | 3 ++ 8 files changed, 82 insertions(+) create mode 100644 .agents/evidence/verify/2026-10-18-provider-preflight.md create mode 100644 .agents/notes/proposed/feature/2026-10-18-provider-preflight.md create mode 100644 client-sdk/tests/test_providers/test_terminal_feature_contract.py diff --git a/.agents/README.md b/.agents/README.md index 50c0faa..07403ae 100644 --- a/.agents/README.md +++ b/.agents/README.md @@ -77,3 +77,5 @@ Builtin transport: [direct HTTP](notes/implemented/architecture/2026-10-18-nativ - [Final provider convergence acceptance](evidence/verify/2026-10-18-provider-convergence-acceptance.md) - [Provider-owned metadata follow-up](evidence/verify/2026-10-18-provider-owned-metadata-followup.md) + +- [Provider preflight](notes/proposed/feature/2026-10-18-provider-preflight.md) · [verification](evidence/verify/2026-10-18-provider-preflight.md) diff --git a/.agents/evidence/verify/2026-10-18-provider-preflight.md b/.agents/evidence/verify/2026-10-18-provider-preflight.md new file mode 100644 index 0000000..078534c --- /dev/null +++ b/.agents/evidence/verify/2026-10-18-provider-preflight.md @@ -0,0 +1,20 @@ +# Native provider preflight verification — 2026-10-18 + +Result: scoped local PASS; exact-head full hosted matrix pending. + +Base5a99f0fa; Python3.13 with the locked development environment and actual current +client/server sources selected before imports. + +- Regression before fix:1 FAIL (session.url accessed on absent context); after: + 1 PASS with ProviderFeatureNotSupportedError before context or wire access. +- Full maintained client2180 PASS/24 SKIP. Lint/format/typecheck PASS for both packages. +- Actual local Express suite112 PASS/2 Volume opt-in SKIP/2 slow DESELECT/1 existing + KI-009 XFAIL (Jupyter404 and documented shell fallback). No assertion weakened. +- Task tracker cleanup executed; independent complete read-only list confirmed zero + current-date E2E-tagged sandboxes. No unrelated resource was deleted. +- Server code/distribution metadata are unchanged; full hosted Python3.10/3.11/3.12 + client/server/package matrix is required before merge. No cloud/model Actions run. +- Final owner record/link/hygiene checks follow preparation. + +The standard migration and successful account-dependent pause/snapshot acceptance +remain separate in PR47. This patch enables no new capability or package release. diff --git a/.agents/notes/proposed/feature/2026-10-18-provider-preflight.md b/.agents/notes/proposed/feature/2026-10-18-provider-preflight.md new file mode 100644 index 0000000..626c992 --- /dev/null +++ b/.agents/notes/proposed/feature/2026-10-18-provider-preflight.md @@ -0,0 +1,36 @@ +# Decision: Check native PTY before terminal context or wire access + +Status: proposed + +## Problem +The native Express terminal implementation did not enforce its declared PTY +feature before touching the supplied session and wire adapter. The fix was trapped +in the larger conditional migration branch. + +## Decision +Apply the provider declaration check at the start of open_terminal. Preserve the +existing native public API and available Express behavior independently of migration. + +## API Design +Undeclared PTY raises ProviderFeatureNotSupportedError before context or network +access. Valid declared terminal calls continue through the existing adapter. + +## Alternatives considered +Waiting for unrelated snapshot/standard frontend prerequisites leaves the defect +on main. Failing later with attribute or transport errors loses the typed contract. + +## Dependencies +Current accepted main5a99f0fa. Related owner migration issue: +https://github.com/Alibaba-Agent-Sandbox/python-sdk/issues/36 +Companion CLI issue https://github.com/Alibaba-Agent-Sandbox/agent-sandbox/issues/33. + +## Test Strategy +Observe failing unguarded access, verify the feature error, run all maintained client +checks and real available Express lifecycle/terminal/server coverage and cleanup. + +## Acceptance criteria +Regression, maintained client checks and real available backend acceptance pass; +latest full hosted matrix passes before normal merge. No conditional feature is enabled. + +## Evidence +[Verification](../../../evidence/verify/2026-10-18-provider-preflight.md). diff --git a/CHANGELOG.md b/CHANGELOG.md index f2fd246..52002da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/). ### Fixed +- Reject undeclared native Express PTY before session/context or wire access. + - Reconcile provider isolation with accepted native transport, explicit-key authentication and retired-module cleanup; preserve canonical compatibility aliases and pure configuration metadata. ### Documentation diff --git a/client-sdk/src/agent_sandbox/providers/alicloud_express/provider.py b/client-sdk/src/agent_sandbox/providers/alicloud_express/provider.py index 8b117ca..498b561 100644 --- a/client-sdk/src/agent_sandbox/providers/alicloud_express/provider.py +++ b/client-sdk/src/agent_sandbox/providers/alicloud_express/provider.py @@ -156,6 +156,7 @@ async def prepare_session( return binding async def open_terminal(self, sandbox: Any, **options: Any) -> Any: + self.require("pty") from agent_sandbox.providers.shared.e2b.terminal import TerminalSession return await TerminalSession.create( diff --git a/client-sdk/tests/test_providers/test_terminal_feature_contract.py b/client-sdk/tests/test_providers/test_terminal_feature_contract.py new file mode 100644 index 0000000..397ad5f --- /dev/null +++ b/client-sdk/tests/test_providers/test_terminal_feature_contract.py @@ -0,0 +1,13 @@ +"""Declared absence must refuse PTY before touching session or wire state.""" + +import pytest + +from agent_sandbox.models.errors import ProviderFeatureNotSupportedError +from agent_sandbox.providers.alicloud_express.provider import AlicloudExpressProvider + + +async def test_native_terminal_checks_feature_before_session_access() -> None: + provider = AlicloudExpressProvider() + provider.features = provider.features - {"pty"} + with pytest.raises(ProviderFeatureNotSupportedError): + await provider.open_terminal(None) diff --git a/docs/en/guide/providers.md b/docs/en/guide/providers.md index b0545f9..0f5467d 100644 --- a/docs/en/guide/providers.md +++ b/docs/en/guide/providers.md @@ -400,3 +400,8 @@ A package can also publish an entry point in the group `agent_sandbox.providers` - [Configuration reference](../reference/configuration.md) — names, aliases, precedence - [Authentication](authentication.md) - [Design: providers and credentials](../design/providers-and-credentials.md) + +Native terminal access enforces the provider's `pty` declaration before reading +session context or starting its wire adapter. An unsupported terminal returns the +typed provider feature error; declaring a client method does not enable an account +or function capability. diff --git a/docs/zh/guide/providers.md b/docs/zh/guide/providers.md index 7b3e276..4d990a3 100644 --- a/docs/zh/guide/providers.md +++ b/docs/zh/guide/providers.md @@ -395,3 +395,6 @@ register_provider(MyProvider()) - [配置参考](../reference/configuration.md) —— 名称、别名、优先级 - [认证详解](authentication.md) - [设计:提供方与凭证](../design/providers-and-credentials.md) + +原生终端在读取会话上下文或启动协议适配器前检查 Provider 的 `pty` 声明。 +不支持时返回明确的能力错误;客户端存在方法并不代表账号或函数已开通该能力。