From ca65d37801bea99ed988ad40c3665d2b80ac664c Mon Sep 17 00:00:00 2001 From: AnyEnv Sandbox Date: Sun, 25 Oct 2026 15:04:06 +0000 Subject: [PATCH 1/2] fix: build SDK fixtures from the published server runtime --- .agents/README.md | 2 + ...026-10-25-public-runtime-fixture-images.md | 33 ++++++++++++ ...026-10-25-public-runtime-fixture-images.md | 52 +++++++++++++++++++ .github/workflows/ci.yml | 45 ++++++++++++++++ CHANGELOG.md | 4 ++ docs/en/guide/testing-e2e.md | 8 +++ docs/zh/guide/testing-e2e.md | 7 +++ examples/templates/agents-cli/Dockerfile | 8 +-- examples/templates/agents-cli/README.md | 11 +++- examples/templates/python-hello/Dockerfile | 12 +---- 10 files changed, 164 insertions(+), 18 deletions(-) create mode 100644 .agents/evidence/verify/2026-10-25-public-runtime-fixture-images.md create mode 100644 .agents/notes/proposed/process/2026-10-25-public-runtime-fixture-images.md diff --git a/.agents/README.md b/.agents/README.md index 3301e112..fa745f5c 100644 --- a/.agents/README.md +++ b/.agents/README.md @@ -169,3 +169,5 @@ Builtin transport: [direct HTTP](notes/implemented/architecture/2026-10-18-nativ - [Command execution deadline](notes/proposed/feature/2026-10-25-command-execution-deadline.md) · [verification](evidence/verify/2026-10-25-command-execution-deadline.md) - [Bounded public PyPI readback](notes/proposed/process/2026-10-25-pypi-public-readback.md) · [verification](evidence/verify/2026-10-25-pypi-public-readback.md) + +- [Public runtime fixture images](notes/proposed/process/2026-10-25-public-runtime-fixture-images.md) · [verification](evidence/verify/2026-10-25-public-runtime-fixture-images.md) diff --git a/.agents/evidence/verify/2026-10-25-public-runtime-fixture-images.md b/.agents/evidence/verify/2026-10-25-public-runtime-fixture-images.md new file mode 100644 index 00000000..a8c33f62 --- /dev/null +++ b/.agents/evidence/verify/2026-10-25-public-runtime-fixture-images.md @@ -0,0 +1,33 @@ +# Verification: public runtime fixture images + +- Date: 2026-10-25 +- Base: ea4df4e9cf2bdf4ae120f2863e130fb3a318b64b plus scoped fixture/CI/docs changes. +- Runtime: official PyPI agent-sandbox-server0.4.0a2, unchanged published files. +- Local result: PARTIAL; YAML/shell and owner static gates pass. Docker unavailable + locally; actual builds and HTTP runtime acceptance are required from current-head CI. + +## Regression scope + +The previous Dockerfiles COPY local wheels before a fallback shell, and install +an unversioned server if reached. This is a source finding; no unavailable local +Docker execution is represented as a pass or an observed build failure. + +The existing CI now builds each actual fixture Dockerfile without injecting files, +checks the server distribution version and import inside the image, starts the +image unchanged, checks public health and either the hello business result or +agents runtime listing, and removes the owned container even on failure. +A separate daemon check and inventory confirm cleanup absence. No model CLI or +model endpoint is substituted into these image checks. + +## Executed local checks + +- PASS: workflow YAML loads; each maintained shell step passes bash-n. +- PASS: public a2 healthcheck help confirms its host/port/timeout contract. +- Owner health/hygiene and remote build/HTTP results: pending before merge. + +## Limits + +These are SDK offline fixtures, not a new template publishing source or an +OpenSandbox/Express template matrix. Agents runtime listing does not establish +model execution; real Codex/Qwen calls retain their installation/auth requirements. +No cloud resources or external registry uploads were created by local validation. diff --git a/.agents/notes/proposed/process/2026-10-25-public-runtime-fixture-images.md b/.agents/notes/proposed/process/2026-10-25-public-runtime-fixture-images.md new file mode 100644 index 00000000..a1f746b7 --- /dev/null +++ b/.agents/notes/proposed/process/2026-10-25-public-runtime-fixture-images.md @@ -0,0 +1,52 @@ +# Decision: Build SDK fixtures with the published server runtime +Status: proposed + +## Problem + +Both offline fixture Dockerfiles require local wheel files before their shell +fallback could run. The fallback installs an unversioned server. Neither behavior +matches the documented public-package path. The agents fixture README also +incorrectly describes omitted-adapter requests as HTTP400 rather than200/default. + +## Decision + +Install the exact public server0.4.0a2 from the official PyPI index in both images. +Remove the wheel COPY and fallback entirely. Correct the README and retain the +explicit offline-fixture and real-model prerequisites. Build both unmodified +Dockerfiles in the existing CI, check their actual guest runtime version and +HTTP application, then remove and independently confirm absence of owned containers. + +## API Design + +No product API, package version or source-fallback compatibility is added. Python +hello still serves its registered command; agents-cli still requires installed +real agent CLIs and model credentials for actual model execution. + +## Alternatives considered + +Supplying candidate wheels or manufacturing empty files preserves an unnecessary +second installation path. Merely checking Dockerfile text does not prove the build. +A new test framework or cloud service is unnecessary; use existing Docker CI. + +## Dependencies + +Docker, the existing public base images and the official PyPI server0.4.0a2. +No cloud/model credentials or provider account are needed. + +## Test Strategy + +Run the actual Docker builds, verify package imports/version inside each image, +start the image unchanged and check health plus hello command or agents runtime +listing. Use owned container cleanup even on failure. The smoke does not claim +real Codex/Qwen model execution. Run owner health/hygiene and required CI. + +## Acceptance criteria + +- Both fixture images build without a local wheel or source fallback. +- Actual guest package is0.4.0a2; expected HTTP behavior passes. +- Owned containers are removed and confirmed absent, including after failures. +- README accurately distinguishes protocol fixtures from actual agent execution. + +## Evidence + +- [Verification](../../../evidence/verify/2026-10-25-public-runtime-fixture-images.md) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 253d61eb..c920d6cb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -188,3 +188,48 @@ jobs: ABX_TEST_CLI_DIR: ${{ github.workspace }}/.test-deps/cli ABX_TEST_PROVIDERS_DIR: ${{ github.workspace }}/.test-deps/providers run: python -m pytest -c client-sdk/pyproject.toml client-sdk/tests/test_providers/test_engine_provider.py -v + + fixture-images: + name: Public runtime fixture (${{ matrix.fixture }}) + runs-on: ubuntu-latest + timeout-minutes: 15 + strategy: + fail-fast: false + matrix: + fixture: [python-hello, agents-cli] + steps: + - uses: actions/checkout@v4 + - name: Build the unmodified fixture Dockerfile + run: docker build --tag abx-sdk-fixture:current "examples/templates/${{ matrix.fixture }}" + - name: Verify the published guest runtime + run: | + docker run --rm --entrypoint python3 abx-sdk-fixture:current -c 'from importlib.metadata import version; from agent_sandbox.server import start; assert version("agent-sandbox-server") == "0.4.0a2" and callable(start)' + - name: Start the fixture and check its real HTTP application + env: + FIXTURE_NAME: ${{ matrix.fixture }} + run: | + docker run -d --name abx-sdk-fixture-server abx-sdk-fixture:current + for attempt in 1 2 3 4 5 6; do + if docker exec abx-sdk-fixture-server agent-sandbox-server healthcheck --port 9000; then break; fi + if [ "$attempt" = 6 ]; then exit 1; fi + sleep 1 + done + docker exec -i -e FIXTURE_NAME="$FIXTURE_NAME" abx-sdk-fixture-server python3 - <<'PYTHON' + import json, os, urllib.request + base = "http://127.0.0.1:9000" + if os.environ["FIXTURE_NAME"] == "python-hello": + request = urllib.request.Request(base + "/commands/hello", data=b'{"name":"Fixture"}', headers={"Content-Type":"application/json"}) + with urllib.request.urlopen(request, timeout=10) as response: + assert json.load(response)["result"] == "Hello, Fixture!" + else: + with urllib.request.urlopen(base + "/v1/agents/runtimes", timeout=10) as response: + assert isinstance(json.load(response)["data"], list) + PYTHON + - name: Remove the owned fixture container and verify absence + if: always() + run: | + if docker container inspect abx-sdk-fixture-server >/dev/null 2>&1; then + docker rm -f abx-sdk-fixture-server + fi + docker info >/dev/null + test -z "$(docker ps -aq --filter 'name=^abx-sdk-fixture-server$')" diff --git a/CHANGELOG.md b/CHANGELOG.md index fe65919e..c1642bdf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/). ### Fixed +- Build both SDK offline fixtures from the exact public a2 server on official PyPI, remove unreachable local-wheel fallback, and verify actual guest HTTP behavior and cleanup in CI. / SDK 两个离线夹具统一从官方 PyPI 安装精确 a2 服务端,删除不可达的本地 wheel 回退,并通过 CI 验证真实镜像 HTTP 行为及清理。 + +### Fixed + - Bound public PyPI metadata and fresh-install propagation retries while keeping artifact digest mismatches and dependency/import failures fatal. / 为公开 PyPI 元数据及全新安装增加有限传播重试,保持产物哈希、依赖与导入检查失败即中止。 ### Fixed diff --git a/docs/en/guide/testing-e2e.md b/docs/en/guide/testing-e2e.md index a46cccfc..80a8f213 100644 --- a/docs/en/guide/testing-e2e.md +++ b/docs/en/guide/testing-e2e.md @@ -64,3 +64,11 @@ The separate fresh installation from the official PyPI index has the same bounde retry interval because that index may appear later than package metadata. Each failed installation remains visible in the log. Dependency and public import checks run once after installation succeeds; their failures stop the release. + +## SDK fixture images + +The SDK repository keeps offline python-hello and agents-cli fixtures, separate +from the template catalog. Their Dockerfiles install public server0.4.0a2 from +the official PyPI index without local wheels. CI builds both, checks the actual +guest package and HTTP application, and confirms owned container cleanup. +Agents runtime listing does not prove an installed agent or a real model call. diff --git a/docs/zh/guide/testing-e2e.md b/docs/zh/guide/testing-e2e.md index cad7ff45..5ab6b770 100644 --- a/docs/zh/guide/testing-e2e.md +++ b/docs/zh/guide/testing-e2e.md @@ -61,3 +61,10 @@ make e2e-cleanup # 清理遗留资源的 dry-run janitor;ARGS=--yes 才 会立即失败。通过官方 PyPI 索引进行的全新安装也采用同样的有限重试,因为索引 可能晚于包元数据同步。每次安装失败均保留在日志中。安装成功后只执行一次依赖 及公开导入检查,这些检查失败会直接阻止发布。 + +## SDK 夹具镜像 + +SDK 仓库保留独立于模板目录的 python-hello 和 agents-cli 离线夹具。两个 +Dockerfile 均从官方 PyPI 安装公开 server0.4.0a2,不需要本地 wheel。CI 构建 +两个镜像,检查实际客体包与 HTTP 应用,并确认自有容器清理。Agents 运行时 +列表不代表已安装 Agent 或完成真实模型调用。 diff --git a/examples/templates/agents-cli/Dockerfile b/examples/templates/agents-cli/Dockerfile index 4fa907d9..78cad2cd 100644 --- a/examples/templates/agents-cli/Dockerfile +++ b/examples/templates/agents-cli/Dockerfile @@ -12,12 +12,8 @@ ENV ABX_SERVER_ENABLED_GROUPS=agents # RUN apt-get update && apt-get install -y --no-install-recommends nodejs npm ca-certificates \ # && npm install -g @qwen-code/qwen-code && rm -rf /var/lib/apt/lists/* -COPY *.whl /tmp/ -RUN if ls /tmp/*.whl 1>/dev/null 2>&1; then \ - pip install --no-cache-dir /tmp/*.whl && rm -f /tmp/*.whl; \ - else \ - pip install --no-cache-dir agent-sandbox-server; \ - fi +# Install the published runtime; no local wheel or source fallback is required. +RUN python3 -m pip install --index-url https://pypi.org/simple --no-cache-dir "agent-sandbox-server==0.4.0a2" WORKDIR /app COPY commands.py . diff --git a/examples/templates/agents-cli/README.md b/examples/templates/agents-cli/README.md index db1044b7..ff13306b 100644 --- a/examples/templates/agents-cli/README.md +++ b/examples/templates/agents-cli/README.md @@ -80,10 +80,17 @@ E2E_RUN_LLM=0 ABX_SERVER_PORT=9000 python3 commands.py E2E_BASE_URL=http://127.0.0.1:9000 python3 e2e_test.py ``` -测试会检查:健康检查、未指定适配器时 400、`claude-code` 为 404、名为 `codex` 与 `qwen` 的本地程序各完成一轮并带回文本。 +测试会检查:健康检查、未指定适配器时使用默认运行时并返回 200、`claude-code` 为 404、名为 `codex` 与 `qwen` 的本地程序各完成一轮并带回文本。 ## English This template turns on the sandbox Agents API for **Codex** and **Qwen Code**. The image does not install either CLI. Add the `npm install -g` line for the one you call, or install it inside a running sandbox. Other adapter names, including Claude Code, Cursor, and Qoder, are HTTP 404. -The server listens on port **9000**. Point `examples/agents/hosted_codex.py` or `hosted_qwen.py` at it. When `E2E_RUN_LLM=0`, `e2e_test.py` puts the local programs in `e2e-bin/` on `PATH`. Those programs are named `codex` and `qwen`. +The server listens on port **9000**. Point `examples/agents/hosted_codex.py` or `hosted_qwen.py` at it. When `E2E_RUN_LLM=0`, `commands.py` puts the local programs in `e2e-bin/` on `PATH`. Those programs are named `codex` and `qwen`. + +Both offline fixture Dockerfiles install `agent-sandbox-server==0.4.0a2` from the +official PyPI index. No local wheel is required. The image does not include real +Codex/Qwen CLIs; model execution still requires the selected CLI and credentials. + +两个离线夹具 Dockerfile 均从官方 PyPI 安装 `agent-sandbox-server==0.4.0a2`, +不需要本地 wheel。镜像不预装真实 Codex/Qwen CLI;模型执行仍需相应工具和凭据。 diff --git a/examples/templates/python-hello/Dockerfile b/examples/templates/python-hello/Dockerfile index 58af7bef..a565a8e1 100644 --- a/examples/templates/python-hello/Dockerfile +++ b/examples/templates/python-hello/Dockerfile @@ -2,16 +2,8 @@ FROM ubuntu:22.04 ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y python3 python3-pip && rm -rf /var/lib/apt/lists/* -# Install the agent-sandbox-server runtime (the container-side `agent_sandbox.server`). -# When building locally via `abx template deploy`, the agent-sandbox-server wheel -# is automatically injected into the build context as .whl file. -# Fallback: install from PyPI if the wheel is not present. -COPY *.whl /tmp/ -RUN if ls /tmp/*.whl 1>/dev/null 2>&1; then \ - pip3 install --no-cache-dir /tmp/*.whl && rm -f /tmp/*.whl; \ - else \ - pip3 install --no-cache-dir agent-sandbox-server; \ - fi +# Install the published runtime; no local wheel or source fallback is required. +RUN python3 -m pip install --index-url https://pypi.org/simple --no-cache-dir "agent-sandbox-server==0.4.0a2" WORKDIR /app COPY commands.py . From 5c02dc5e43c04828226af8380167c8cce9470fc1 Mon Sep 17 00:00:00 2001 From: AnyEnv Sandbox Date: Sun, 25 Oct 2026 15:10:05 +0000 Subject: [PATCH 2/2] docs: record real fixture image HTTP and cleanup acceptance --- ...25-public-runtime-fixture-images-jobs.json | 100 ++++++++++++++++++ ...026-10-25-public-runtime-fixture-images.md | 16 ++- ...026-10-25-public-runtime-fixture-images.md | 8 +- docs/en/guide/testing-e2e.md | 2 +- docs/zh/guide/testing-e2e.md | 2 +- 5 files changed, 118 insertions(+), 10 deletions(-) create mode 100644 .agents/evidence/verify/2026-10-25-public-runtime-fixture-images-jobs.json diff --git a/.agents/evidence/verify/2026-10-25-public-runtime-fixture-images-jobs.json b/.agents/evidence/verify/2026-10-25-public-runtime-fixture-images-jobs.json new file mode 100644 index 00000000..65413e3c --- /dev/null +++ b/.agents/evidence/verify/2026-10-25-public-runtime-fixture-images-jobs.json @@ -0,0 +1,100 @@ +[ + { + "name": "Public runtime fixture (python-hello)", + "head_sha": "ca65d37801bea99ed988ad40c3665d2b80ac664c", + "html_url": "https://github.com/Alibaba-Agent-Sandbox/python-sdk/actions/runs/40205183614/job/121204482025", + "status": "completed", + "conclusion": "success", + "steps": [ + { + "name": "Set up job", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Run actions/checkout@v4", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Build the unmodified fixture Dockerfile", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Verify the published guest runtime", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Start the fixture and check its real HTTP application", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Remove the owned fixture container and verify absence", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Post Run actions/checkout@v4", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Complete job", + "status": "completed", + "conclusion": "success" + } + ] + }, + { + "name": "Public runtime fixture (agents-cli)", + "head_sha": "ca65d37801bea99ed988ad40c3665d2b80ac664c", + "html_url": "https://github.com/Alibaba-Agent-Sandbox/python-sdk/actions/runs/40205183614/job/121204481973", + "status": "completed", + "conclusion": "success", + "steps": [ + { + "name": "Set up job", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Run actions/checkout@v4", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Build the unmodified fixture Dockerfile", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Verify the published guest runtime", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Start the fixture and check its real HTTP application", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Remove the owned fixture container and verify absence", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Post Run actions/checkout@v4", + "status": "completed", + "conclusion": "success" + }, + { + "name": "Complete job", + "status": "completed", + "conclusion": "success" + } + ] + } +] diff --git a/.agents/evidence/verify/2026-10-25-public-runtime-fixture-images.md b/.agents/evidence/verify/2026-10-25-public-runtime-fixture-images.md index a8c33f62..625e9f2b 100644 --- a/.agents/evidence/verify/2026-10-25-public-runtime-fixture-images.md +++ b/.agents/evidence/verify/2026-10-25-public-runtime-fixture-images.md @@ -2,9 +2,10 @@ - Date: 2026-10-25 - Base: ea4df4e9cf2bdf4ae120f2863e130fb3a318b64b plus scoped fixture/CI/docs changes. -- Runtime: official PyPI agent-sandbox-server0.4.0a2, unchanged published files. -- Local result: PARTIAL; YAML/shell and owner static gates pass. Docker unavailable - locally; actual builds and HTTP runtime acceptance are required from current-head CI. +- Runtime: official PyPI agent-sandbox-server 0.4.0a2, unchanged published files. +- Result: PASS for actual Docker fixture build/guest/HTTP/cleanup at reviewed + functional revision ca65d37801bea99ed988ad40c3665d2b80ac664c. Docker remains + unavailable on the author host; these actual checks executed in GitHub CI. ## Regression scope @@ -23,7 +24,14 @@ model endpoint is substituted into these image checks. - PASS: workflow YAML loads; each maintained shell step passes bash-n. - PASS: public a2 healthcheck help confirms its host/port/timeout contract. -- Owner health/hygiene and remote build/HTTP results: pending before merge. +- PASS: owner health 106 PASS / 1 warning / 0 failures; hygiene/diff checks. +- PASS: [python-hello Docker job](https://github.com/Alibaba-Agent-Sandbox/python-sdk/actions/runs/40205183614/job/121204482025). +- PASS: [agents-cli Docker job](https://github.com/Alibaba-Agent-Sandbox/python-sdk/actions/runs/40205183614/job/121204481973). + Independently queried each job and every step: actual Docker build, guest package + check, unchanged image startup and HTTP application, owned container removal + and absence all completed SUCCESS. No skip was counted as a pass. +- [Sanitized job/step receipt](2026-10-25-public-runtime-fixture-images-jobs.json). +- All final-head required CI and independent review remain mandatory before merge. ## Limits diff --git a/.agents/notes/proposed/process/2026-10-25-public-runtime-fixture-images.md b/.agents/notes/proposed/process/2026-10-25-public-runtime-fixture-images.md index a1f746b7..caff991d 100644 --- a/.agents/notes/proposed/process/2026-10-25-public-runtime-fixture-images.md +++ b/.agents/notes/proposed/process/2026-10-25-public-runtime-fixture-images.md @@ -6,11 +6,11 @@ Status: proposed Both offline fixture Dockerfiles require local wheel files before their shell fallback could run. The fallback installs an unversioned server. Neither behavior matches the documented public-package path. The agents fixture README also -incorrectly describes omitted-adapter requests as HTTP400 rather than200/default. +incorrectly describes omitted-adapter requests as HTTP 400 rather than 200/default. ## Decision -Install the exact public server0.4.0a2 from the official PyPI index in both images. +Install the exact public server 0.4.0a2 from the official PyPI index in both images. Remove the wheel COPY and fallback entirely. Correct the README and retain the explicit offline-fixture and real-model prerequisites. Build both unmodified Dockerfiles in the existing CI, check their actual guest runtime version and @@ -30,7 +30,7 @@ A new test framework or cloud service is unnecessary; use existing Docker CI. ## Dependencies -Docker, the existing public base images and the official PyPI server0.4.0a2. +Docker, the existing public base images and the official PyPI server 0.4.0a2. No cloud/model credentials or provider account are needed. ## Test Strategy @@ -43,7 +43,7 @@ real Codex/Qwen model execution. Run owner health/hygiene and required CI. ## Acceptance criteria - Both fixture images build without a local wheel or source fallback. -- Actual guest package is0.4.0a2; expected HTTP behavior passes. +- Actual guest package is 0.4.0a2; expected HTTP behavior passes. - Owned containers are removed and confirmed absent, including after failures. - README accurately distinguishes protocol fixtures from actual agent execution. diff --git a/docs/en/guide/testing-e2e.md b/docs/en/guide/testing-e2e.md index 80a8f213..257629dd 100644 --- a/docs/en/guide/testing-e2e.md +++ b/docs/en/guide/testing-e2e.md @@ -68,7 +68,7 @@ run once after installation succeeds; their failures stop the release. ## SDK fixture images The SDK repository keeps offline python-hello and agents-cli fixtures, separate -from the template catalog. Their Dockerfiles install public server0.4.0a2 from +from the template catalog. Their Dockerfiles install public server 0.4.0a2 from the official PyPI index without local wheels. CI builds both, checks the actual guest package and HTTP application, and confirms owned container cleanup. Agents runtime listing does not prove an installed agent or a real model call. diff --git a/docs/zh/guide/testing-e2e.md b/docs/zh/guide/testing-e2e.md index 5ab6b770..7e32da55 100644 --- a/docs/zh/guide/testing-e2e.md +++ b/docs/zh/guide/testing-e2e.md @@ -65,6 +65,6 @@ make e2e-cleanup # 清理遗留资源的 dry-run janitor;ARGS=--yes 才 ## SDK 夹具镜像 SDK 仓库保留独立于模板目录的 python-hello 和 agents-cli 离线夹具。两个 -Dockerfile 均从官方 PyPI 安装公开 server0.4.0a2,不需要本地 wheel。CI 构建 +Dockerfile 均从官方 PyPI 安装公开 server 0.4.0a2,不需要本地 wheel。CI 构建 两个镜像,检查实际客体包与 HTTP 应用,并确认自有容器清理。Agents 运行时 列表不代表已安装 Agent 或完成真实模型调用。