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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .agents/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Node SDK engineering records

This repository owns decisions and verification for its HTTP client, public
configuration schema, ESM/TypeScript exports and examples. New records use English;
source contracts in other repositories are linked through absolute GitHub URLs.

Notes live in `notes/proposed/<architecture|feature|process>/YYYY-MM-DD-<topic>.md`.
Acceptance moves them to `notes/implemented/` with the same category and an updated
`Status:`. Rejected and superseded notes use flat state directories. A note has
Problem, Decision, API Design, Alternatives considered, Dependencies, Test Strategy
and Acceptance criteria sections.

Evidence lives in `evidence/verify/YYYY-MM-DD-<topic>.md` and records revision,
environment, actual commands/results, behavior, cleanup and unrun gates. Use PASS,
PARTIAL, BLOCKED or FAIL honestly. Merged evidence is immutable; add a new file for
a later run. Keep credentials, private data and raw sensitive logs out of records.

Include scoped records in the owning PR. Run applicable tests/build, inspect exact
latest-head required CI and independent review, and verify actual remote merge
state. A local/runtime result is not cloud acceptance or package publication.

- [Configuration reservations and installation](notes/proposed/process/2026-10-18-config-provider-reservations.md)
- [Verification](evidence/verify/2026-10-18-config-provider-reservations.md)
60 changes: 60 additions & 0 deletions .agents/evidence/verify/2026-10-18-config-provider-reservations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Verification: Node configuration reservations and source installation

- Date: 2026-10-18
- Base: `90335324461b6d01e361908211b7d69a4c57305b`.
- Authority: Python SDK `145341d462df2f4753c03a62365114f1872acd1a`.
- Result: PARTIAL (local acceptance complete; new exact-head CI/review pending).
- Environment: Linux; Node 22.22.2; npm 12.0.2; matching server 0.3.0 with Python 3.12.15.

## Reproduction and authority

The actual `config_keys.py --json` export from the pinned Python source and the
unchanged Node JSON differ only at `reserved_provider_ids`: Node additionally
reserves `e2b`. All 23 key entries and other metadata agree. After the one-id fix,
the complete parsed JSON structures match. CI repeats the full-structure comparison
against a pinned source checkout rather than fetching mutable main or only checking
one field.

The new public-export test was executed after `npm run build` against the unchanged
schema: **1 FAIL**, with `true !== false`. This is a real negative control through
`dist/index.js`, not an assertion about source prose.

An anonymous GET to `https://registry.npmjs.org/@agent-sandbox%2Fsdk` returned
HTTP 404 and `{ "error": "Not found" }`. No authentication header was sent.
The publication statement is a dated observation, not a future availability claim.

## Commands and results

- `npm ci`: PASS, committed lockfile unchanged.
- `npm run typecheck`: PASS.
- `npm test` with matching `python3` server environment: **9 PASS / zero SKIP**,
821.36 milliseconds; includes the public export and actual local server loop.
- `node examples/agent-loop.mjs` with the same Python environment: PASS; health,
command stdout `4` plus newline, file round trip, SIGTERM and reaped process.
- Complete JSON comparison with actual pinned Python `--json` output: PASS.
- `npm pack --json`: PASS, 22 package files. Fresh temporary consumer installs
from both the built local checkout and the packed tarball: PASS. Each imports
`@agent-sandbox/sdk`, verifies `e2b` is unreserved, keeps the builtin reservation,
resolves the existing env name and exports `ServerClient`.
- The first verification harness assumed array-shaped npm JSON and stopped before
consumer installation. Local npm returned an object keyed by package name;
correcting only the harness enabled the two actual successful installations.
- Workflow YAML parses; the whole-schema comparison step uses the pinned source's
real `--json` export and compares complete JSON structures.
- Scoped diff and relative engineering-record links: PASS.

## CI and review scope

The repository had no tracked workflow and its remote workflow count was zero.
This change introduces normal Node 20/22 checks with fixed Python 3.12.15, the pinned
server source, lockfile installation, whole-schema comparison, typecheck and existing
real local tests. No package publishing step, cloud credential or cloud operation
is added. Local Node 22 success does not replace the pending Node 20/22 hosted run.

## Cleanup and limits

Temporary consumer projects/artifacts are task-owned and removed after validation.
The local server process is terminated and reaped by the existing loop; no cloud
resource was created. Public npm publication, Node cloud-provider execution and
real native-provider acceptance are outside this change. Existing unrelated original
checkout engineering proposals remain untouched.
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Decision: Synchronize the public configuration contract

Status: proposed

## Problem

The Node schema still reserves `e2b`, unlike the authoritative Python export where
it is an installable catalog id. Both README languages also give an immediate
public npm install command although current package metadata returns 404.

## Decision

Remove the stale id while preserving all built-in/core reservations, existing 23
keys, ESM types, env aliases and HTTP behavior. Document independent lockfile-based
source build and local-dependency installation in both languages. Add the missing
normal PR CI for Node 20/22, using Python 3.12.15 and a matching pinned server source.
No workflow existed before this change; the new checks are not historical gates.

## API Design

`configSchema.reserved_provider_ids` no longer includes `e2b`. No exported symbol,
configuration key or provider execution API is added. The public npm installation
command is described as applicable after publication; this change does not publish.

## Alternatives considered

- Keep the old id: preserves a contradictory public metadata contract.
- Change Python to match stale Node metadata: rejects an intentional catalog id.
- Claim source builds prove npm publication: contradicted by the registry result.
- Test only the source JSON: misses the built public export and real package use.

## Dependencies

- Schema: https://github.com/Alibaba-Agent-Sandbox/nodejs-sdk/issues/1
- Installation: https://github.com/Alibaba-Agent-Sandbox/nodejs-sdk/issues/2
- Authority: https://github.com/Alibaba-Agent-Sandbox/python-sdk/blob/145341d462df2f4753c03a62365114f1872acd1a/client-sdk/src/agent_sandbox/utils/config_keys.py
- CI source/server revision: `145341d462df2f4753c03a62365114f1872acd1a`.

## Test Strategy

Demonstrate the public-export regression against a built unchanged schema before
fixing it. Compare the complete JSON structure with the actual pinned Python
export. Execute lockfile install, typecheck, the full existing tests and actual
local server loop. Verify fresh consumer installation/import from the built local
checkout and packed artifact. Require exact-head Node 20/22 CI and independent
review before any authorized merge; no cloud or release is involved.

## Acceptance criteria

- Built public metadata matches the Python contract, leaving `e2b` unreserved.
- Existing built-in/core ids and all 23 keys remain unchanged.
- Regression fails before the fix; current unit/runtime/package checks pass.
- Both README languages disclose verified publication status and usable source setup.
- CI compares the complete source schema and runs existing real local behavior.
- Changelog and owner records are included; publication/merge evidence is not invented.

## Evidence

- [Verification](../../../evidence/verify/2026-10-18-config-provider-reservations.md)
53 changes: 53 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: CI

on:
pull_request:
push:
branches: [main]

permissions:
contents: read

jobs:
test:
name: Node.js ${{ matrix.node }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node: [20, 22]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: npm
- uses: actions/setup-python@v5
with:
python-version: "3.12.15"
- name: Check out the matching Python server source
uses: actions/checkout@v4
with:
repository: Alibaba-Agent-Sandbox/python-sdk
ref: 145341d462df2f4753c03a62365114f1872acd1a
path: python-sdk
- name: Install the local server prerequisite
run: python -m pip install ./python-sdk/server-sdk
- name: Compare the complete Python and Node configuration schema
run: |
python - <<'PY'
import json
import subprocess
import sys
from pathlib import Path

exported = subprocess.check_output(
[sys.executable, "python-sdk/client-sdk/src/agent_sandbox/utils/config_keys.py", "--json"],
text=True,
)
assert json.loads(exported) == json.loads(Path("src/config-keys.json").read_text())
print("Complete Python/Node configuration schema matches")
PY
- run: npm ci
- run: npm run typecheck
- run: npm test
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Changelog

## [Unreleased]

### Fixed

- Match the Python configuration schema by leaving the installable `e2b` catalog
provider id unreserved while preserving all built-in/core reservations.
- Explain the current source-checkout installation path in English and Chinese;
public npm package metadata returns 404 until publication.

### Added

- A PR CI matrix for Node.js 20/22, including the existing real local server loop
against a pinned Python server source. No publication workflow is added.
28 changes: 19 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,24 @@ It is **not** a port of `Sandbox.create`, cloud providers, or the server SDK. Cr

## Install

```bash
npm install @agent-sandbox/sdk
```

The published entry is `dist/`. From a checkout:
`@agent-sandbox/sdk` is not published to public npm yet (package metadata returned
HTTP 404 on 2026-10-18). Build the `dist/` entry from a checkout:

```bash
npm install
npm test
node examples/agent-loop.mjs
git clone https://github.com/Alibaba-Agent-Sandbox/nodejs-sdk.git
cd nodejs-sdk
npm ci
npm run build
```

`npm test` builds first, then runs `node:test`.
To use the package-name imports below from another project, install that built
checkout as a local dependency with `npm install ../nodejs-sdk` (adjust the path).
The public command `npm install @agent-sandbox/sdk` applies after publication.

For validation, run `npm run typecheck` and `npm test`. The latter builds first,
then runs `node:test`, including a real local server loop. That loop requires
`agent-sandbox-server` in the `python3` environment; it needs no cloud credentials.
The PR workflow checks Node.js 20 and 22 with a pinned Python server source.

## ServerClient

Expand Down Expand Up @@ -59,6 +64,11 @@ await server.close();

`src/config-keys.json` is the canonical list, exported from `python -m agent_sandbox.utils.config_keys --json`. Each key has exactly one environment variable. There are no aliases. `readEnv` reads only that name.

`configSchema.reserved_provider_ids` follows the
[Python registry](https://github.com/Alibaba-Agent-Sandbox/python-sdk/blob/145341d462df2f4753c03a62365114f1872acd1a/client-sdk/src/agent_sandbox/utils/config_keys.py):
built-in/core identifiers stay reserved, while the installable catalog id `e2b`
is available. Provider execution belongs to the Python SDK and `abx`.

Product keys use the `ABX_` prefix: `ABX_SANDBOX_API_KEY`, `ABX_SANDBOX_BASE_URL`, `ABX_SANDBOX_DOMAIN`, `ABX_PROVIDER`.

Where the vendor already publishes a name, that name is the environment variable: `ALICLOUD_ACCESS_KEY_ID`, `ALICLOUD_ACCESS_KEY_SECRET`, `ALIBABA_CLOUD_REGION_ID`, and `GITHUB_TOKEN`.
Expand Down
27 changes: 18 additions & 9 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,23 @@

## 安装

```bash
npm install @agent-sandbox/sdk
```

发布入口是 `dist/`。在检出的仓库里:
`@agent-sandbox/sdk` 尚未发布到公共 npm(2026-10-18 查询包元数据返回 HTTP 404)。
请从独立检出的源码构建 `dist/` 入口:

```bash
npm install
npm test
node examples/agent-loop.mjs
git clone https://github.com/Alibaba-Agent-Sandbox/nodejs-sdk.git
cd nodejs-sdk
npm ci
npm run build
```

`npm test` 会先构建,再跑 `node:test`。
在其他项目中使用下方的包名导入示例时,先用 `npm install ../nodejs-sdk`
把构建好的检出目录作为本地依赖安装(请调整路径)。
公共安装命令 `npm install @agent-sandbox/sdk` 适用于正式发布之后。

验证时运行 `npm run typecheck` 和 `npm test`。后者先构建,再执行 `node:test`,
其中包含真实本地服务循环,需要 `python3` 环境已安装 `agent-sandbox-server`,不需要云凭据。
新增 PR 工作流使用固定的 Python server 源码,检查 Node.js 20 和 22。

## ServerClient

Expand Down Expand Up @@ -59,6 +63,11 @@ await server.close();

`src/config-keys.json` 是规范列表,来自 `python -m agent_sandbox.utils.config_keys --json`。每个 key 只有一个环境变量,没有别名。`readEnv` 只读这个名字。

`configSchema.reserved_provider_ids` 遵循
[Python 注册表](https://github.com/Alibaba-Agent-Sandbox/python-sdk/blob/145341d462df2f4753c03a62365114f1872acd1a/client-sdk/src/agent_sandbox/utils/config_keys.py):
内置及核心标识仍保留,可安装的目录提供方标识 `e2b` 不再保留。
提供方执行由 Python SDK 和 `abx` 负责。

产品 key 使用 `ABX_` 前缀:`ABX_SANDBOX_API_KEY`、`ABX_SANDBOX_BASE_URL`、`ABX_SANDBOX_DOMAIN`、`ABX_PROVIDER`。

厂商已经公布名字时,环境变量就用那个名字:`ALICLOUD_ACCESS_KEY_ID`、`ALICLOUD_ACCESS_KEY_SECRET`、`ALIBABA_CLOUD_REGION_ID`,以及 `GITHUB_TOKEN`。
Expand Down
3 changes: 1 addition & 2 deletions src/config-keys.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
"shortcuts",
"core",
"transport",
"providers",
"e2b"
"providers"
],
"reserved_provider_prefixes": [
"abx-",
Expand Down
15 changes: 15 additions & 0 deletions test/config-keys.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,21 @@ const source = JSON.parse(
readFileSync(new URL("../src/config-keys.json", import.meta.url), "utf8"),
);

test("reserved provider ids keep the E2B catalog id available", () => {
assert.equal(configSchema.reserved_provider_ids.includes("e2b"), false);
assert.deepEqual(configSchema.reserved_provider_ids, [
"alicloud-express",
"default",
"all",
"none",
"builtin",
"shortcuts",
"core",
"transport",
"providers",
]);
});

test("fixture is copied through with one env name per key", () => {
assert.equal(configSchema.schema_version, 1);
assert.equal(CONFIG_KEYS.length, source.keys.length);
Expand Down
Loading