@agentcash/router 1.9.4 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/index.cjs +39 -28
- package/dist/index.js +39 -28
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -2177,6 +2177,21 @@ function getAllowedStrategies(allowed) {
|
|
|
2177
2177
|
return allowed.map((name) => STRATEGIES[name]);
|
|
2178
2178
|
}
|
|
2179
2179
|
|
|
2180
|
+
// src/protocols/detect.ts
|
|
2181
|
+
function detectProtocol(request) {
|
|
2182
|
+
if (request.headers.get(HEADERS.X402_PAYMENT_SIGNATURE) ?? request.headers.get(HEADERS.X402_PAYMENT_LEGACY)) {
|
|
2183
|
+
return "x402";
|
|
2184
|
+
}
|
|
2185
|
+
const auth = request.headers.get(HEADERS.AUTHORIZATION);
|
|
2186
|
+
if (auth && auth.startsWith(AUTH_SCHEME.MPP_PAYMENT)) {
|
|
2187
|
+
return "mpp";
|
|
2188
|
+
}
|
|
2189
|
+
if (request.headers.get(HEADERS.SIWX)) {
|
|
2190
|
+
return "siwx";
|
|
2191
|
+
}
|
|
2192
|
+
return null;
|
|
2193
|
+
}
|
|
2194
|
+
|
|
2180
2195
|
// src/pipeline/flows/api-key-only.ts
|
|
2181
2196
|
async function runApiKeyOnlyFlow(ctx) {
|
|
2182
2197
|
if (!ctx.routeEntry.apiKeyResolver) {
|
|
@@ -2192,6 +2207,11 @@ async function runApiKeyOnlyFlow(ctx) {
|
|
|
2192
2207
|
var DynamicPricing = class {
|
|
2193
2208
|
constructor(opts) {
|
|
2194
2209
|
this.opts = opts;
|
|
2210
|
+
if (!isPositiveDecimal(opts.maxPrice)) {
|
|
2211
|
+
throw new Error(
|
|
2212
|
+
`route '${opts.route ?? "unknown"}': dynamic pricing requires a positive maxPrice, got '${opts.maxPrice}'`
|
|
2213
|
+
);
|
|
2214
|
+
}
|
|
2195
2215
|
}
|
|
2196
2216
|
needsBody = true;
|
|
2197
2217
|
async quote(body) {
|
|
@@ -2205,11 +2225,8 @@ var DynamicPricing = class {
|
|
|
2205
2225
|
error: err instanceof Error ? err.stack : String(err),
|
|
2206
2226
|
body
|
|
2207
2227
|
});
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
return this.opts.maxPrice;
|
|
2211
|
-
}
|
|
2212
|
-
throw err;
|
|
2228
|
+
this.alert("warn", `Using maxPrice ${this.opts.maxPrice} as fallback after pricing error`);
|
|
2229
|
+
return this.opts.maxPrice;
|
|
2213
2230
|
}
|
|
2214
2231
|
if (!isPositiveDecimal(priced)) {
|
|
2215
2232
|
throw new HttpError(
|
|
@@ -2220,18 +2237,17 @@ var DynamicPricing = class {
|
|
|
2220
2237
|
return priced;
|
|
2221
2238
|
}
|
|
2222
2239
|
challengeQuote(body) {
|
|
2223
|
-
if (body === void 0) return Promise.resolve(this.opts.maxPrice
|
|
2240
|
+
if (body === void 0) return Promise.resolve(this.opts.maxPrice);
|
|
2224
2241
|
return this.quote(body);
|
|
2225
2242
|
}
|
|
2226
2243
|
describe() {
|
|
2227
2244
|
return {
|
|
2228
2245
|
mode: "dynamic",
|
|
2229
2246
|
min: this.opts.minPrice ?? "0",
|
|
2230
|
-
max: this.opts.maxPrice
|
|
2247
|
+
max: this.opts.maxPrice
|
|
2231
2248
|
};
|
|
2232
2249
|
}
|
|
2233
2250
|
cap(raw, body) {
|
|
2234
|
-
if (!this.opts.maxPrice) return raw;
|
|
2235
2251
|
let overCap;
|
|
2236
2252
|
try {
|
|
2237
2253
|
overCap = compareDecimals(raw, this.opts.maxPrice) > 0;
|
|
@@ -2331,6 +2347,9 @@ function selectPricing(raw, deps = {}) {
|
|
|
2331
2347
|
return new FixedPricing(raw);
|
|
2332
2348
|
}
|
|
2333
2349
|
if (typeof raw === "function") {
|
|
2350
|
+
if (!deps.maxPrice) {
|
|
2351
|
+
throw new Error(`route '${deps.route ?? "unknown"}': dynamic pricing requires maxPrice`);
|
|
2352
|
+
}
|
|
2334
2353
|
return new DynamicPricing({
|
|
2335
2354
|
fn: raw,
|
|
2336
2355
|
maxPrice: deps.maxPrice,
|
|
@@ -3215,21 +3234,6 @@ async function createKvMppStore(kv, options) {
|
|
|
3215
3234
|
});
|
|
3216
3235
|
}
|
|
3217
3236
|
|
|
3218
|
-
// src/protocols/detect.ts
|
|
3219
|
-
function detectProtocol(request) {
|
|
3220
|
-
if (request.headers.get(HEADERS.X402_PAYMENT_SIGNATURE) ?? request.headers.get(HEADERS.X402_PAYMENT_LEGACY)) {
|
|
3221
|
-
return "x402";
|
|
3222
|
-
}
|
|
3223
|
-
const auth = request.headers.get(HEADERS.AUTHORIZATION);
|
|
3224
|
-
if (auth && auth.startsWith(AUTH_SCHEME.MPP_PAYMENT)) {
|
|
3225
|
-
return "mpp";
|
|
3226
|
-
}
|
|
3227
|
-
if (request.headers.get(HEADERS.SIWX)) {
|
|
3228
|
-
return "siwx";
|
|
3229
|
-
}
|
|
3230
|
-
return null;
|
|
3231
|
-
}
|
|
3232
|
-
|
|
3233
3237
|
// src/protocols/mpp/siwx-mode.ts
|
|
3234
3238
|
var import_mppx3 = require("mppx");
|
|
3235
3239
|
async function verifyMppSiwx(request, mppx) {
|
|
@@ -3252,8 +3256,6 @@ async function runSiwxOnlyFlow(ctx) {
|
|
|
3252
3256
|
if (earlyBody.ok) {
|
|
3253
3257
|
const validateErr = await runValidate(ctx, earlyBody.data);
|
|
3254
3258
|
if (validateErr) return validateErr;
|
|
3255
|
-
} else {
|
|
3256
|
-
return earlyBody.response;
|
|
3257
3259
|
}
|
|
3258
3260
|
}
|
|
3259
3261
|
const siwxHeader = request.headers.get(HEADERS.SIWX);
|
|
@@ -3386,9 +3388,13 @@ async function runUnprotectedFlow(ctx) {
|
|
|
3386
3388
|
|
|
3387
3389
|
// src/pipeline/orchestrate.ts
|
|
3388
3390
|
function shouldSkipQueryValidation(routeEntry, request) {
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3391
|
+
if (routeEntry.pricing || routeEntry.authMode === "paid") {
|
|
3392
|
+
return selectIncomingStrategy(request, routeEntry.protocols) === null;
|
|
3393
|
+
}
|
|
3394
|
+
if (routeEntry.authMode === "siwx") {
|
|
3395
|
+
return !request.headers.get(HEADERS.SIWX) && detectProtocol(request) !== "mpp";
|
|
3396
|
+
}
|
|
3397
|
+
return false;
|
|
3392
3398
|
}
|
|
3393
3399
|
function createRequestHandler(routeEntry, handler, deps) {
|
|
3394
3400
|
return async (request) => {
|
|
@@ -3582,6 +3588,11 @@ var RouteBuilder = class _RouteBuilder {
|
|
|
3582
3588
|
`route '${this.#s.key}': price '${pricing}' must be a positive decimal string`
|
|
3583
3589
|
);
|
|
3584
3590
|
}
|
|
3591
|
+
if (typeof pricing === "function" && next.#s.maxPrice === void 0) {
|
|
3592
|
+
throw new Error(
|
|
3593
|
+
`route '${this.#s.key}': dynamic pricing requires maxPrice \u2014 without it, bare probes would advertise a $0 challenge`
|
|
3594
|
+
);
|
|
3595
|
+
}
|
|
3585
3596
|
if (next.#s.maxPrice !== void 0 && !isPositiveDecimal(next.#s.maxPrice)) {
|
|
3586
3597
|
throw new Error(
|
|
3587
3598
|
`route '${this.#s.key}': maxPrice '${next.#s.maxPrice}' must be a positive decimal string`
|
package/dist/index.js
CHANGED
|
@@ -2136,6 +2136,21 @@ function getAllowedStrategies(allowed) {
|
|
|
2136
2136
|
return allowed.map((name) => STRATEGIES[name]);
|
|
2137
2137
|
}
|
|
2138
2138
|
|
|
2139
|
+
// src/protocols/detect.ts
|
|
2140
|
+
function detectProtocol(request) {
|
|
2141
|
+
if (request.headers.get(HEADERS.X402_PAYMENT_SIGNATURE) ?? request.headers.get(HEADERS.X402_PAYMENT_LEGACY)) {
|
|
2142
|
+
return "x402";
|
|
2143
|
+
}
|
|
2144
|
+
const auth = request.headers.get(HEADERS.AUTHORIZATION);
|
|
2145
|
+
if (auth && auth.startsWith(AUTH_SCHEME.MPP_PAYMENT)) {
|
|
2146
|
+
return "mpp";
|
|
2147
|
+
}
|
|
2148
|
+
if (request.headers.get(HEADERS.SIWX)) {
|
|
2149
|
+
return "siwx";
|
|
2150
|
+
}
|
|
2151
|
+
return null;
|
|
2152
|
+
}
|
|
2153
|
+
|
|
2139
2154
|
// src/pipeline/flows/api-key-only.ts
|
|
2140
2155
|
async function runApiKeyOnlyFlow(ctx) {
|
|
2141
2156
|
if (!ctx.routeEntry.apiKeyResolver) {
|
|
@@ -2151,6 +2166,11 @@ async function runApiKeyOnlyFlow(ctx) {
|
|
|
2151
2166
|
var DynamicPricing = class {
|
|
2152
2167
|
constructor(opts) {
|
|
2153
2168
|
this.opts = opts;
|
|
2169
|
+
if (!isPositiveDecimal(opts.maxPrice)) {
|
|
2170
|
+
throw new Error(
|
|
2171
|
+
`route '${opts.route ?? "unknown"}': dynamic pricing requires a positive maxPrice, got '${opts.maxPrice}'`
|
|
2172
|
+
);
|
|
2173
|
+
}
|
|
2154
2174
|
}
|
|
2155
2175
|
needsBody = true;
|
|
2156
2176
|
async quote(body) {
|
|
@@ -2164,11 +2184,8 @@ var DynamicPricing = class {
|
|
|
2164
2184
|
error: err instanceof Error ? err.stack : String(err),
|
|
2165
2185
|
body
|
|
2166
2186
|
});
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
return this.opts.maxPrice;
|
|
2170
|
-
}
|
|
2171
|
-
throw err;
|
|
2187
|
+
this.alert("warn", `Using maxPrice ${this.opts.maxPrice} as fallback after pricing error`);
|
|
2188
|
+
return this.opts.maxPrice;
|
|
2172
2189
|
}
|
|
2173
2190
|
if (!isPositiveDecimal(priced)) {
|
|
2174
2191
|
throw new HttpError(
|
|
@@ -2179,18 +2196,17 @@ var DynamicPricing = class {
|
|
|
2179
2196
|
return priced;
|
|
2180
2197
|
}
|
|
2181
2198
|
challengeQuote(body) {
|
|
2182
|
-
if (body === void 0) return Promise.resolve(this.opts.maxPrice
|
|
2199
|
+
if (body === void 0) return Promise.resolve(this.opts.maxPrice);
|
|
2183
2200
|
return this.quote(body);
|
|
2184
2201
|
}
|
|
2185
2202
|
describe() {
|
|
2186
2203
|
return {
|
|
2187
2204
|
mode: "dynamic",
|
|
2188
2205
|
min: this.opts.minPrice ?? "0",
|
|
2189
|
-
max: this.opts.maxPrice
|
|
2206
|
+
max: this.opts.maxPrice
|
|
2190
2207
|
};
|
|
2191
2208
|
}
|
|
2192
2209
|
cap(raw, body) {
|
|
2193
|
-
if (!this.opts.maxPrice) return raw;
|
|
2194
2210
|
let overCap;
|
|
2195
2211
|
try {
|
|
2196
2212
|
overCap = compareDecimals(raw, this.opts.maxPrice) > 0;
|
|
@@ -2290,6 +2306,9 @@ function selectPricing(raw, deps = {}) {
|
|
|
2290
2306
|
return new FixedPricing(raw);
|
|
2291
2307
|
}
|
|
2292
2308
|
if (typeof raw === "function") {
|
|
2309
|
+
if (!deps.maxPrice) {
|
|
2310
|
+
throw new Error(`route '${deps.route ?? "unknown"}': dynamic pricing requires maxPrice`);
|
|
2311
|
+
}
|
|
2293
2312
|
return new DynamicPricing({
|
|
2294
2313
|
fn: raw,
|
|
2295
2314
|
maxPrice: deps.maxPrice,
|
|
@@ -3174,21 +3193,6 @@ async function createKvMppStore(kv, options) {
|
|
|
3174
3193
|
});
|
|
3175
3194
|
}
|
|
3176
3195
|
|
|
3177
|
-
// src/protocols/detect.ts
|
|
3178
|
-
function detectProtocol(request) {
|
|
3179
|
-
if (request.headers.get(HEADERS.X402_PAYMENT_SIGNATURE) ?? request.headers.get(HEADERS.X402_PAYMENT_LEGACY)) {
|
|
3180
|
-
return "x402";
|
|
3181
|
-
}
|
|
3182
|
-
const auth = request.headers.get(HEADERS.AUTHORIZATION);
|
|
3183
|
-
if (auth && auth.startsWith(AUTH_SCHEME.MPP_PAYMENT)) {
|
|
3184
|
-
return "mpp";
|
|
3185
|
-
}
|
|
3186
|
-
if (request.headers.get(HEADERS.SIWX)) {
|
|
3187
|
-
return "siwx";
|
|
3188
|
-
}
|
|
3189
|
-
return null;
|
|
3190
|
-
}
|
|
3191
|
-
|
|
3192
3196
|
// src/protocols/mpp/siwx-mode.ts
|
|
3193
3197
|
import { Credential as Credential2 } from "mppx";
|
|
3194
3198
|
async function verifyMppSiwx(request, mppx) {
|
|
@@ -3211,8 +3215,6 @@ async function runSiwxOnlyFlow(ctx) {
|
|
|
3211
3215
|
if (earlyBody.ok) {
|
|
3212
3216
|
const validateErr = await runValidate(ctx, earlyBody.data);
|
|
3213
3217
|
if (validateErr) return validateErr;
|
|
3214
|
-
} else {
|
|
3215
|
-
return earlyBody.response;
|
|
3216
3218
|
}
|
|
3217
3219
|
}
|
|
3218
3220
|
const siwxHeader = request.headers.get(HEADERS.SIWX);
|
|
@@ -3345,9 +3347,13 @@ async function runUnprotectedFlow(ctx) {
|
|
|
3345
3347
|
|
|
3346
3348
|
// src/pipeline/orchestrate.ts
|
|
3347
3349
|
function shouldSkipQueryValidation(routeEntry, request) {
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3350
|
+
if (routeEntry.pricing || routeEntry.authMode === "paid") {
|
|
3351
|
+
return selectIncomingStrategy(request, routeEntry.protocols) === null;
|
|
3352
|
+
}
|
|
3353
|
+
if (routeEntry.authMode === "siwx") {
|
|
3354
|
+
return !request.headers.get(HEADERS.SIWX) && detectProtocol(request) !== "mpp";
|
|
3355
|
+
}
|
|
3356
|
+
return false;
|
|
3351
3357
|
}
|
|
3352
3358
|
function createRequestHandler(routeEntry, handler, deps) {
|
|
3353
3359
|
return async (request) => {
|
|
@@ -3541,6 +3547,11 @@ var RouteBuilder = class _RouteBuilder {
|
|
|
3541
3547
|
`route '${this.#s.key}': price '${pricing}' must be a positive decimal string`
|
|
3542
3548
|
);
|
|
3543
3549
|
}
|
|
3550
|
+
if (typeof pricing === "function" && next.#s.maxPrice === void 0) {
|
|
3551
|
+
throw new Error(
|
|
3552
|
+
`route '${this.#s.key}': dynamic pricing requires maxPrice \u2014 without it, bare probes would advertise a $0 challenge`
|
|
3553
|
+
);
|
|
3554
|
+
}
|
|
3544
3555
|
if (next.#s.maxPrice !== void 0 && !isPositiveDecimal(next.#s.maxPrice)) {
|
|
3545
3556
|
throw new Error(
|
|
3546
3557
|
`route '${this.#s.key}': maxPrice '${next.#s.maxPrice}' must be a positive decimal string`
|