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
12 changes: 12 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,15 @@ jobs:
- run: npm ci
- run: npm run verify
- run: npm run artifact:check

windows-package:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run package:smoke
- run: npm run artifact:check
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@

- Run `npm run verify` (or `pnpm run verify`) for source, consumer typecheck, tests, package smoke,
quickstart, and the clean-room packed install. Keep scripts package-manager neutral.
- Keep package lifecycle and clean-room scripts OS-neutral. Use Node filesystem APIs for cleanup and
invoke installed bins through the active package manager; do not assume Unix `rm` or bin shims.
- Keep the clean-room `example:fresh-dev` in `verify`; it must install the packed artifact into a
new temporary project, use an unmistakably mock receipt, and perform no external request or spend.
- Keep installed `acm partner-check` no-spend by default. Its funded path must require both a
Expand Down
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ Give an AI agent permission to buy **one exact x402 resource** under a bounded g

> Developer preview. The protected buyer flow is implemented and tested on Base Sepolia. Seller and data-exchange helpers are experimental local previews; they do not settle payments or prove buyer demand.

Current release: [`v0.1.0-preview.23`](docs/releases/v0.1.0-preview.23.md).

## 60-second no-spend check

Requirements: Node.js 20+ and internet access. No clone, account, wallet, or private key is required.

```bash
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.22.tar.gz doctor \
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.23.tar.gz doctor \
> acm-no-spend-report.json
```

Expand All @@ -32,15 +34,15 @@ The check reads Coinbase's public x402 Bazaar catalog, confirms all nine canonic
## Five-minute local demo

```bash
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.22.tar.gz demo buyer
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.23.tar.gz demo buyer
```

The deterministic demo creates a bounded grant, validates a fresh synthetic result, revokes the grant, and proves the next request is denied. Any `0xmock_...` receipt is deliberately not a chain transaction.

## Install as a dependency

```bash
npm install github:InTheta/agent-capability-middleware#v0.1.0-preview.22
npm install github:InTheta/agent-capability-middleware#v0.1.0-preview.23
```

```ts
Expand Down Expand Up @@ -75,7 +77,7 @@ After an ACM operator provides a protected gateway URL and confirms its dedicate
```bash
export ACM_GATEWAY_URL='https://provided-gateway.example'
export ACM_CONFIRM_TESTNET_SPEND=yes
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.22.tar.gz partner-check \
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.23.tar.gz partner-check \
> acm-paid-report.json
unset ACM_API_KEY ACM_CONFIRM_TESTNET_SPEND
```
Expand Down Expand Up @@ -126,9 +128,9 @@ MCP can carry tool calls, OAuth/OIDC can identify workloads and users, verifiabl
ACM also explores the other side of the market: a developer can describe a paid API, and a user can offer a confirmed, minimized capability under **Free, Paid, Ask, or Deny** policy. These helpers are useful for product design and local testing, but they are not yet hosted settlement, fulfilment, an auction, or a production data marketplace.

```bash
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.22.tar.gz demo developer-seller
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.22.tar.gz demo user-seller
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.22.tar.gz demo exchange
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.23.tar.gz demo developer-seller
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.23.tar.gz demo user-seller
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.23.tar.gz demo exchange
```

See [runnable examples](docs/examples.md) and the [user seller preview](docs/user-seller-agent.md).
Expand Down
4 changes: 2 additions & 2 deletions docs/design-partner-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ No clone, Git installation, account, environment file, or wallet is required:

```bash
node --version
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.22.tar.gz doctor \
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.23.tar.gz doctor \
> acm-no-spend-report.json
```

Expand Down Expand Up @@ -60,7 +60,7 @@ Enter the credential through a hidden prompt:
```bash
export ACM_GATEWAY_URL='https://provided-gateway.example'
export ACM_CONFIRM_TESTNET_SPEND=yes
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.22.tar.gz partner-check \
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.23.tar.gz partner-check \
> acm-paid-report.json
unset ACM_API_KEY ACM_CONFIRM_TESTNET_SPEND
```
Expand Down
6 changes: 3 additions & 3 deletions docs/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Start with the buyer path. Seller and exchange examples are clearly separated be
From any empty directory with Node.js 20+:

```bash
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.22.tar.gz partner-check \
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.23.tar.gz partner-check \
> acm-no-spend-report.json
```

Expand All @@ -27,7 +27,7 @@ Expected fields:
## 2. Deterministic buyer demo — no spend

```bash
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.22.tar.gz demo buyer
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.23.tar.gz demo buyer
```

This demonstrates the policy lifecycle without a chain transaction:
Expand All @@ -45,7 +45,7 @@ Run only after an ACM operator provides a protected gateway URL and confirms its
```bash
export ACM_GATEWAY_URL='https://provided-gateway.example'
export ACM_CONFIRM_TESTNET_SPEND=yes
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.22.tar.gz partner-check \
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.23.tar.gz partner-check \
> acm-paid-report.json
unset ACM_API_KEY ACM_CONFIRM_TESTNET_SPEND
```
Expand Down
14 changes: 7 additions & 7 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Requirements: Node.js 20+ and npm. The first two steps require no account, walle
Run the pinned preview from any empty directory:

```bash
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.22.tar.gz doctor \
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.23.tar.gz doctor \
> acm-no-spend-report.json
```

Expand All @@ -30,7 +30,7 @@ This checks Coinbase's public x402 Bazaar catalog, the nine canonical Omni route
## 2. Run the buyer lifecycle locally

```bash
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.22.tar.gz demo buyer
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.23.tar.gz demo buyer
```

Expected outcome:
Expand All @@ -47,7 +47,7 @@ The local `0xmock_...` receipt is not a blockchain transaction.
```bash
mkdir acm-example && cd acm-example
npm init -y
npm install github:InTheta/agent-capability-middleware#v0.1.0-preview.22
npm install github:InTheta/agent-capability-middleware#v0.1.0-preview.23
```

Create `buy-market-risk.mjs`:
Expand Down Expand Up @@ -86,7 +86,7 @@ Stop until an ACM operator provides a protected gateway URL and confirms its ded
```bash
export ACM_GATEWAY_URL='https://provided-gateway.example'
export ACM_CONFIRM_TESTNET_SPEND=yes
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.22.tar.gz partner-check \
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.23.tar.gz partner-check \
> acm-paid-report.json
unset ACM_API_KEY ACM_CONFIRM_TESTNET_SPEND
```
Expand Down Expand Up @@ -121,9 +121,9 @@ The paid report must show a public receipt, an ACM audit event, fresh `market_ri
These are local offer-policy helpers, not live settlement or marketplace claims:

```bash
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.22.tar.gz demo developer-seller
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.22.tar.gz demo user-seller
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.22.tar.gz demo exchange
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.23.tar.gz demo developer-seller
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.23.tar.gz demo user-seller
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.23.tar.gz demo exchange
```

See [runnable examples](examples.md) for their exact boundaries.
2 changes: 1 addition & 1 deletion docs/omni-agent-recipes.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ into exact URLs, expected schemas, prices, and Base Sepolia payment constraints
wallet key in agent code.

```bash
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.22.tar.gz recipes
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.23.tar.gz recipes
```

This command plans requests only. It does not create a grant, sign, or pay.
Expand Down
38 changes: 38 additions & 0 deletions docs/releases/v0.1.0-preview.23.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# ACM SDK v0.1.0-preview.23

Release date: 3 August 2026

`preview.23` is the first preview whose packed-install verification is enforced on both Linux and
Windows. It preserves the `preview.22` public API and fixes the package lifecycle scripts so a
Windows developer can build and pack the SDK without a Unix `rm` executable.

## Public entry points

Run the live, read-only readiness check without cloning the repository or creating a payment:

```bash
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.23.tar.gz doctor
```

Install the SDK as a pinned dependency:

```bash
npm install github:InTheta/agent-capability-middleware#v0.1.0-preview.23
```

## Verified scope

- nine canonical Omni HTTP x402 route templates;
- four bounded paid Omni MCP tools plus the free catalog tool;
- exact grant, resource, network, asset, amount and payee binding;
- protected gateway custody—the public SDK accepts no payer private key;
- no-spend doctor and deterministic buyer demo;
- explicitly armed Base Sepolia partner acceptance;
- clean packed installation, consumer type checking and CLI execution;
- Windows and Linux packaging.

## Boundaries

This remains a developer preview. It does not provide a public hosted ACM gateway, tenant
isolation, autonomous mainnet spending, or a live user-data marketplace. Mainnet use remains a
separate operator-controlled gateway capability and is not enabled by installing this package.
2 changes: 1 addition & 1 deletion docs/sdk-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ This is the complete reference. New integrations should begin with the
Until npm publication, run the CLI directly from GitHub:

```bash
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.22.tar.gz inspect
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.23.tar.gz inspect
```

All `demo` commands are local, keyless, and non-settling.
Expand Down
2 changes: 1 addition & 1 deletion docs/user-seller-agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ The public SDK now includes a local, keyless preview of **Sell one capability**.
## Try it

```bash
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.22.tar.gz demo user-seller
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.23.tar.gz demo user-seller
```

The example creates one user-confirmed running-shoe purchase intent and evaluates a fixed-price request. It does not settle payment.
Expand Down
4 changes: 2 additions & 2 deletions docs/x402-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ The installed acceptance runner creates a 15-minute grant restricted to `x402.pa
phase first:

```bash
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.22.tar.gz partner-check \
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.23.tar.gz partner-check \
> acm-no-spend-report.json
```

Expand All @@ -99,7 +99,7 @@ payer is ready, explicitly arm one paid acceptance:
```bash
export ACM_GATEWAY_URL='https://provided-gateway.example'
export ACM_CONFIRM_TESTNET_SPEND=yes
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.22.tar.gz partner-check \
npx --yes https://github.com/InTheta/agent-capability-middleware/archive/refs/tags/v0.1.0-preview.23.tar.gz partner-check \
> acm-paid-report.json
unset ACM_API_KEY ACM_CONFIRM_TESTNET_SPEND
```
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@agent-capability-middleware/sdk",
"version": "0.1.0-preview.22",
"version": "0.1.0-preview.23",
"description": "TypeScript SDK for policy-bound x402 buying and experimental capability offers",
"type": "module",
"license": "Apache-2.0",
Expand Down Expand Up @@ -39,7 +39,7 @@
}
},
"scripts": {
"build": "rm -rf dist && tsc -p tsconfig.json",
"build": "node scripts/clean-dist.mjs && tsc -p tsconfig.json",
"typecheck": "tsc --noEmit -p tsconfig.json",
"typecheck:consumer": "tsc -p tsconfig.json && tsc --noEmit --strict --target ES2022 --module NodeNext --moduleResolution NodeNext examples/typecheck.ts",
"test": "tsc -p tsconfig.json && node --test tests/*.test.mjs",
Expand All @@ -57,7 +57,7 @@
"artifact:check": "npm run build && git diff --exit-code -- dist",
"cli:smoke": "tsc -p tsconfig.json && node dist/cli.js doctor --local && node dist/cli.js help",
"verify": "tsc --noEmit -p tsconfig.json && tsc -p tsconfig.json && tsc --noEmit --strict --target ES2022 --module NodeNext --moduleResolution NodeNext examples/typecheck.ts && node --test tests/*.test.mjs && node scripts/verify-offers.mjs && node scripts/verify-partner-check.mjs && node examples/developer-sells-api.mjs && node examples/user-sells-capability.mjs && node examples/data-exchange.mjs && node examples/omni-agent-recipes.mjs && node scripts/smoke-package.mjs && node scripts/run-quickstart.mjs && node scripts/fresh-dev-setup.mjs && node dist/cli.js doctor --local && node dist/cli.js recipes && node dist/cli.js demo exchange && node dist/cli.js help",
"prepack": "rm -rf dist && tsc -p tsconfig.json"
"prepack": "node scripts/clean-dist.mjs && tsc -p tsconfig.json"
},
"engines": {
"node": ">=20"
Expand Down
4 changes: 4 additions & 0 deletions scripts/clean-dist.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { rmSync } from "node:fs";
import { resolve } from "node:path";

rmSync(resolve("dist"), { recursive: true, force: true });
16 changes: 14 additions & 2 deletions scripts/fresh-dev-setup.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,20 @@ try {
if (consumer.status !== 0) throw new Error(`Fresh consumer exited ${consumer.status ?? "unknown"}`);
if (!consumer.stdout?.includes("FRESH_DEV_MOCK_OK")) throw new Error("Fresh consumer omitted success marker");
} finally {
gateway?.kill("SIGTERM");
await rm(temporaryDirectory, { recursive: true, force: true });
if (gateway?.exitCode === null) {
const exited = new Promise((resolveExit) => gateway.once("exit", resolveExit));
gateway.kill("SIGTERM");
await Promise.race([
exited,
new Promise((resolveWait) => setTimeout(resolveWait, 5_000)),
]);
}
await rm(temporaryDirectory, {
recursive: true,
force: true,
maxRetries: 5,
retryDelay: 100,
});
}

function runNpm(arguments_, cwd = process.cwd()) {
Expand Down
37 changes: 16 additions & 21 deletions scripts/smoke-package.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -65,46 +65,34 @@ try {
if (smoke.status !== 0) throw new Error(smoke.stderr || smoke.stdout);
process.stdout.write(smoke.stdout);

const cli = spawnSync(join(temporaryDirectory, "node_modules", ".bin", "acm"), ["doctor", "--local"], {
cwd: temporaryDirectory,
encoding: "utf8",
});
if (cli.status !== 0) throw new Error(cli.stderr || cli.stdout);
const doctorReport = JSON.parse(cli.stdout);
const cliOutput = runInstalledCli(["doctor", "--local"]);
const doctorReport = JSON.parse(cliOutput);
if (
doctorReport.ok !== true
|| doctorReport.mode !== "local"
|| doctorReport.walletKeyRequired !== false
|| doctorReport.networkRequestCreated !== false
|| doctorReport.spent !== false
) {
throw new Error(`Installed ACM CLI did not preserve the key boundary: ${cli.stdout}`);
throw new Error(`Installed ACM CLI did not preserve the key boundary: ${cliOutput}`);
}
process.stdout.write("EXTERNAL_CLI_SMOKE_OK\n");

const recipes = spawnSync(join(temporaryDirectory, "node_modules", ".bin", "acm"), ["recipes"], {
cwd: temporaryDirectory,
encoding: "utf8",
});
if (recipes.status !== 0) throw new Error(recipes.stderr || recipes.stdout);
const recipeReport = JSON.parse(recipes.stdout);
const recipesOutput = runInstalledCli(["recipes"]);
const recipeReport = JSON.parse(recipesOutput);
if (
recipeReport.canonicalRouteTemplates !== 9 ||
recipeReport.catalogedRouteTemplates !== 9 ||
recipeReport.recipes?.length !== 25 ||
recipeReport.spent !== false
) {
throw new Error(`Installed ACM CLI returned an invalid recipe plan: ${recipes.stdout}`);
throw new Error(`Installed ACM CLI returned an invalid recipe plan: ${recipesOutput}`);
}
process.stdout.write("EXTERNAL_RECIPES_CLI_SMOKE_OK\n");

const exchange = spawnSync(join(temporaryDirectory, "node_modules", ".bin", "acm"), ["demo", "exchange"], {
cwd: temporaryDirectory,
encoding: "utf8",
});
if (exchange.status !== 0) throw new Error(exchange.stderr || exchange.stdout);
if (!exchange.stdout.includes("ACM_EXCHANGE_DEMO_OK")) {
throw new Error(`Installed ACM CLI could not run the exchange demo: ${exchange.stdout}`);
const exchangeOutput = runInstalledCli(["demo", "exchange"]);
if (!exchangeOutput.includes("ACM_EXCHANGE_DEMO_OK")) {
throw new Error(`Installed ACM CLI could not run the exchange demo: ${exchangeOutput}`);
}
process.stdout.write("EXTERNAL_EXCHANGE_CLI_SMOKE_OK\n");
} finally {
Expand All @@ -116,3 +104,10 @@ function runNpm(arguments_, cwd = process.cwd()) {
if (result.status !== 0) throw new Error(result.stderr || result.stdout);
return result.stdout;
}

function runInstalledCli(arguments_) {
const execArguments = npmCli.includes("pnpm")
? ["exec", "acm", ...arguments_]
: ["exec", "--", "acm", ...arguments_];
return runNpm(execArguments, temporaryDirectory);
}
Loading