From fedfd9ae95bfc89677a2e2d6c46cba1d69ec4a80 Mon Sep 17 00:00:00 2001 From: Matias Date: Tue, 24 Feb 2026 12:31:41 -0300 Subject: [PATCH 1/5] f: update package-lock.json --- package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 32e79c6..75d4ce4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockrun/clawrouter", - "version": "0.10.4", + "version": "0.10.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@blockrun/clawrouter", - "version": "0.10.4", + "version": "0.10.6", "license": "MIT", "dependencies": { "viem": "^2.39.3" From 5b99a5b0884331bdbab493b1e888d0e6d3121524 Mon Sep 17 00:00:00 2001 From: Matias Date: Tue, 24 Feb 2026 16:53:14 -0300 Subject: [PATCH 2/5] chore: fork setup * Rename to @ampersend_ai/clawrouter-core * Add release workflow --- .github/workflows/release.yml | 98 +++++++++++++++++++++++++++++++++++ package.json | 4 +- 2 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..c3ec190 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,98 @@ +name: Release + +on: + push: + tags: + - "v*.*.*" + - "v*.*.*-alpha.*" + - "v*.*.*-beta.*" + +permissions: + contents: read + id-token: write # Required for npm provenance + +env: + NODE_VERSION: "22.x" + +jobs: + verify-version: + name: Verify version + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Extract version from tag + id: tag + run: | + TAG=${GITHUB_REF#refs/tags/v} + echo "version=$TAG" >> $GITHUB_OUTPUT + echo "Tagged version: $TAG" + + - name: Read package.json version + id: package + run: | + VERSION=$(node -p "require('./package.json').version") + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "Package version: $VERSION" + + - name: Compare versions + run: | + if [ "${{ steps.tag.outputs.version }}" != "${{ steps.package.outputs.version }}" ]; then + echo "ERROR: Tag version (${{ steps.tag.outputs.version }}) does not match package.json version (${{ steps.package.outputs.version }})" + exit 1 + fi + echo "Versions match: ${{ steps.tag.outputs.version }}" + + publish: + name: Publish to npm + runs-on: ubuntu-latest + needs: verify-version + environment: + name: npm + url: https://www.npmjs.com/package/@ampersend_ai/clawrouter-core + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + package_json_file: package.json + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + registry-url: "https://registry.npmjs.org" + cache: "pnpm" + cache-dependency-path: pnpm-lock.yaml + + - name: Update npm + run: npm install -g npm@latest + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Build package + run: pnpm build + + - name: Determine publish tag + id: publish-tag + run: | + VERSION="${GITHUB_REF#refs/tags/v}" + if [[ "$VERSION" == *"-alpha."* ]]; then + echo "tag=alpha" >> $GITHUB_OUTPUT + echo "Publishing with tag: alpha" + elif [[ "$VERSION" == *"-beta."* ]]; then + echo "tag=beta" >> $GITHUB_OUTPUT + echo "Publishing with tag: beta" + else + echo "tag=latest" >> $GITHUB_OUTPUT + echo "Publishing with tag: latest" + fi + + - name: Publish to npm + run: npm publish --access public --tag ${{ steps.publish-tag.outputs.tag }} diff --git a/package.json b/package.json index 1253dc4..9231e69 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "@blockrun/clawrouter", + "name": "@ampersend_ai/clawrouter-core", "version": "0.10.6", "description": "Smart LLM router — save 92% on inference costs. 41+ models, one wallet, x402 micropayments.", "type": "module", @@ -65,7 +65,7 @@ "license": "MIT", "repository": { "type": "git", - "url": "git+https://github.com/BlockRunAI/ClawRouter.git" + "url": "git+https://github.com/edgeandnode/ClawRouter.git" }, "dependencies": { "viem": "^2.39.3" From f02c75bc0151780d230922b5af3422970f4194f8 Mon Sep 17 00:00:00 2001 From: Matias Date: Tue, 24 Feb 2026 16:58:48 -0300 Subject: [PATCH 3/5] fix: missing package-lock.json --- package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 75d4ce4..e34e055 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "@blockrun/clawrouter", + "name": "@ampersend_ai/clawrouter-core", "version": "0.10.6", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@blockrun/clawrouter", + "name": "@ampersend_ai/clawrouter-core", "version": "0.10.6", "license": "MIT", "dependencies": { From e52b2d525adf283f9f8b9fd4c65432eedfa16013 Mon Sep 17 00:00:00 2001 From: Matias Date: Tue, 24 Feb 2026 17:03:59 -0300 Subject: [PATCH 4/5] feat: add custom paymentFetch option to proxy --- src/proxy.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/proxy.ts b/src/proxy.ts index 4f28248..6654d63 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -814,6 +814,18 @@ export type ProxyOptions = { /** Port to listen on (default: 8402) */ port?: number; routingConfig?: Partial; + /** + * Custom payment-enabled fetch function. When provided, replaces the built-in + * x402 payment handler. Use this to integrate alternative payment systems + * (e.g., spend limits, budget enforcement, or custom payment flows). + * + * If not provided, uses built-in createPaymentFetch with walletKey. + */ + paymentFetch?: ( + input: RequestInfo | URL, + init?: RequestInit, + preAuth?: PreAuthParams, + ) => Promise; /** Request timeout in ms (default: 180000 = 3 minutes). Covers on-chain tx + LLM response. */ requestTimeoutMs?: number; /** Skip balance checks (for testing only). Default: false */ @@ -1069,9 +1081,10 @@ export async function startProxy(options: ProxyOptions): Promise { }; } - // Create x402 payment-enabled fetch from wallet private key + // Create x402 payment-enabled fetch from wallet private key (or use custom paymentFetch) const account = privateKeyToAccount(options.walletKey as `0x${string}`); - const { fetch: payFetch } = createPaymentFetch(options.walletKey as `0x${string}`); + const payFetch = + options.paymentFetch ?? createPaymentFetch(options.walletKey as `0x${string}`).fetch; // Create balance monitor for pre-request checks const balanceMonitor = new BalanceMonitor(account.address); From 90a63aab1d0641cd16d3824b6df4002686674aa8 Mon Sep 17 00:00:00 2001 From: Matias Date: Tue, 24 Feb 2026 17:01:14 -0300 Subject: [PATCH 5/5] chore: apply prettier formatting --- RELEASE-v0.10.5.md | 50 +++++++++++++++++++++---------------------- src/cli.ts | 4 +++- src/index.ts | 13 +++++------ src/partners/tools.ts | 5 +---- src/proxy.ts | 10 +++++++-- 5 files changed, 44 insertions(+), 38 deletions(-) diff --git a/RELEASE-v0.10.5.md b/RELEASE-v0.10.5.md index 5510809..78c2ce3 100644 --- a/RELEASE-v0.10.5.md +++ b/RELEASE-v0.10.5.md @@ -21,43 +21,43 @@ OpenClaw 2026.2.22 added multilingual memory search for Spanish, Portuguese, Jap ### Keywords Added Across All 12 Dimensions -| Dimension | ES | PT | KO | AR | -| ---------------------- | -- | -- | -- | -- | -| codeKeywords | ✅ | ✅ | ✅ | ✅ | -| reasoningKeywords | ✅ | ✅ | ✅ | ✅ | -| simpleKeywords | ✅ | ✅ | ✅ | ✅ | -| technicalKeywords | ✅ | ✅ | ✅ | ✅ | -| creativeKeywords | ✅ | ✅ | ✅ | ✅ | -| imperativeVerbs | ✅ | ✅ | ✅ | ✅ | -| constraintIndicators | ✅ | ✅ | ✅ | ✅ | -| outputFormatKeywords | ✅ | ✅ | ✅ | ✅ | -| referenceKeywords | ✅ | ✅ | ✅ | ✅ | -| negationKeywords | ✅ | ✅ | ✅ | ✅ | -| domainSpecificKeywords | ✅ | ✅ | ✅ | ✅ | -| agenticTaskKeywords | ✅ | ✅ | ✅ | ✅ | +| Dimension | ES | PT | KO | AR | +| ---------------------- | --- | --- | --- | --- | +| codeKeywords | ✅ | ✅ | ✅ | ✅ | +| reasoningKeywords | ✅ | ✅ | ✅ | ✅ | +| simpleKeywords | ✅ | ✅ | ✅ | ✅ | +| technicalKeywords | ✅ | ✅ | ✅ | ✅ | +| creativeKeywords | ✅ | ✅ | ✅ | ✅ | +| imperativeVerbs | ✅ | ✅ | ✅ | ✅ | +| constraintIndicators | ✅ | ✅ | ✅ | ✅ | +| outputFormatKeywords | ✅ | ✅ | ✅ | ✅ | +| referenceKeywords | ✅ | ✅ | ✅ | ✅ | +| negationKeywords | ✅ | ✅ | ✅ | ✅ | +| domainSpecificKeywords | ✅ | ✅ | ✅ | ✅ | +| agenticTaskKeywords | ✅ | ✅ | ✅ | ✅ | --- ## 📝 Metadata Updates -| File | Change | -| ---------------------- | ----------------------------------- | -| `package.json` | Version 0.10.4 → 0.10.5 | -| `package.json` | Description: "41 models" → "41+" | +| File | Change | +| ---------------------- | ------------------------------------- | +| `package.json` | Version 0.10.4 → 0.10.5 | +| `package.json` | Description: "41 models" → "41+" | | `openclaw.plugin.json` | "30+ models, 78%" → "41+ models, 92%" | -| `README.md` | All model counts: 38+/30+ → 41+ | +| `README.md` | All model counts: 38+/30+ → 41+ | --- ## 📋 OpenClaw 2026.2.22 Compatibility Notes -| OpenClaw Feature | ClawRouter Impact | Status | -| ------------------------ | ----------------- | ---------- | +| OpenClaw Feature | ClawRouter Impact | Status | +| ------------------------ | ----------------- | ---------------------------------------- | | Mistral provider support | Add models | ⏳ Pending (blocked on BlockRun backend) | -| Multilingual memory | Keyword expansion | ✅ Done | -| Auto-updater | No impact | ✅ N/A | -| Cron parallel runs | Proxy handles it | ✅ OK | -| 40+ security fixes | No impact | ✅ N/A | +| Multilingual memory | Keyword expansion | ✅ Done | +| Auto-updater | No impact | ✅ N/A | +| Cron parallel runs | Proxy handles it | ✅ OK | +| 40+ security fixes | No impact | ✅ N/A | --- diff --git a/src/cli.ts b/src/cli.ts index 1d0a1e2..1038db7 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -154,7 +154,9 @@ async function main(): Promise { console.log(` ${svc.description}`); console.log(` Tool: blockrun_${svc.id}`); console.log(` Method: ${svc.method} /v1${svc.proxyPath}`); - console.log(` Pricing: ${svc.pricing.perUnit} per ${svc.pricing.unit} (min ${svc.pricing.minimum}, max ${svc.pricing.maximum})`); + console.log( + ` Pricing: ${svc.pricing.perUnit} per ${svc.pricing.unit} (min ${svc.pricing.minimum}, max ${svc.pricing.maximum})`, + ); console.log(); } diff --git a/src/index.ts b/src/index.ts index 2090060..afbbd02 100644 --- a/src/index.ts +++ b/src/index.ts @@ -674,7 +674,9 @@ const plugin: OpenClawPluginDefinition = { api.registerTool(tool); } if (partnerTools.length > 0) { - api.logger.info(`Registered ${partnerTools.length} partner tool(s): ${partnerTools.map((t) => t.name).join(", ")}`); + api.logger.info( + `Registered ${partnerTools.length} partner tool(s): ${partnerTools.map((t) => t.name).join(", ")}`, + ); } // Register /partners command @@ -688,16 +690,15 @@ const plugin: OpenClawPluginDefinition = { return { text: "No partner APIs available." }; } - const lines = [ - "**Partner APIs** (paid via your ClawRouter wallet)", - "", - ]; + const lines = ["**Partner APIs** (paid via your ClawRouter wallet)", ""]; for (const svc of PARTNER_SERVICES) { lines.push(`**${svc.name}** (${svc.partner})`); lines.push(` ${svc.description}`); lines.push(` Tool: \`${`blockrun_${svc.id}`}\``); - lines.push(` Pricing: ${svc.pricing.perUnit} per ${svc.pricing.unit} (min ${svc.pricing.minimum}, max ${svc.pricing.maximum})`); + lines.push( + ` Pricing: ${svc.pricing.perUnit} per ${svc.pricing.unit} (min ${svc.pricing.minimum}, max ${svc.pricing.maximum})`, + ); lines.push(""); } diff --git a/src/partners/tools.ts b/src/partners/tools.ts index 3fd70d3..27b63c2 100644 --- a/src/partners/tools.ts +++ b/src/partners/tools.ts @@ -23,10 +23,7 @@ export type PartnerToolDefinition = { /** * Build a single partner tool from a service definition. */ -function buildTool( - service: PartnerServiceDefinition, - proxyBaseUrl: string, -): PartnerToolDefinition { +function buildTool(service: PartnerServiceDefinition, proxyBaseUrl: string): PartnerToolDefinition { // Build JSON Schema properties from service params const properties: Record = {}; const required: string[] = []; diff --git a/src/proxy.ts b/src/proxy.ts index 6654d63..03873e3 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -982,7 +982,12 @@ async function proxyPartnerRequest( // Forward headers (strip hop-by-hop) const headers: Record = {}; for (const [key, value] of Object.entries(req.headers)) { - if (key === "host" || key === "connection" || key === "transfer-encoding" || key === "content-length") + if ( + key === "host" || + key === "connection" || + key === "transfer-encoding" || + key === "content-length" + ) continue; if (typeof value === "string") headers[key] = value; } @@ -1034,7 +1039,8 @@ async function proxyPartnerRequest( baselineCost: 0, savings: 0, latencyMs, - partnerId: (req.url?.split("?")[0] ?? "").replace(/^\/v1\//, "").replace(/\//g, "_") || "unknown", + partnerId: + (req.url?.split("?")[0] ?? "").replace(/^\/v1\//, "").replace(/\//g, "_") || "unknown", service: "partner", }).catch(() => {}); }