@blockrun/clawrouter 0.12.271 → 0.12.273
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 +31 -3
- package/dist/cli.js +569 -118
- package/dist/index.js +261 -65
- package/package.json +1 -1
- package/skills/surf/SKILL.md +14 -3
package/dist/index.js
CHANGED
|
@@ -55864,7 +55864,7 @@ var require_websocket = __commonJS({
|
|
|
55864
55864
|
var net3 = __require("net");
|
|
55865
55865
|
var tls2 = __require("tls");
|
|
55866
55866
|
var { randomBytes: randomBytes9, createHash: createHash4 } = __require("crypto");
|
|
55867
|
-
var { Duplex, Readable:
|
|
55867
|
+
var { Duplex, Readable: Readable3 } = __require("stream");
|
|
55868
55868
|
var { URL: URL3 } = __require("url");
|
|
55869
55869
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
55870
55870
|
var Receiver2 = require_receiver();
|
|
@@ -59926,16 +59926,20 @@ function maskApiKey(key2) {
|
|
|
59926
59926
|
async function readOptional2(path5) {
|
|
59927
59927
|
try {
|
|
59928
59928
|
return (await readTextFile(path5)).trim() || void 0;
|
|
59929
|
-
} catch {
|
|
59930
|
-
return void 0;
|
|
59929
|
+
} catch (error) {
|
|
59930
|
+
if (error.code === "ENOENT") return void 0;
|
|
59931
|
+
throw new Error(
|
|
59932
|
+
`Cannot read BlockRun API key file ${path5}; refusing to fall back to another account or wallet.`,
|
|
59933
|
+
{ cause: error }
|
|
59934
|
+
);
|
|
59931
59935
|
}
|
|
59932
59936
|
}
|
|
59933
59937
|
async function resolveApiKey() {
|
|
59934
59938
|
const envKey = process["env"].BLOCKRUN_API_KEY?.trim();
|
|
59935
59939
|
if (envKey) {
|
|
59936
59940
|
if (isValidApiKey(envKey)) return { key: envKey, source: "env" };
|
|
59937
|
-
|
|
59938
|
-
`
|
|
59941
|
+
throw new Error(
|
|
59942
|
+
`BLOCKRUN_API_KEY is malformed (expected brk_\u2026). Mint one at ${PORTAL_KEYS_URL}, or unset it to pay from the wallet. Refusing to fall back silently.`
|
|
59939
59943
|
);
|
|
59940
59944
|
}
|
|
59941
59945
|
for (const [path5, source] of [
|
|
@@ -59945,8 +59949,8 @@ async function resolveApiKey() {
|
|
|
59945
59949
|
const stored = await readOptional2(path5);
|
|
59946
59950
|
if (stored === void 0) continue;
|
|
59947
59951
|
if (isValidApiKey(stored)) return { key: stored, source };
|
|
59948
|
-
|
|
59949
|
-
|
|
59952
|
+
throw new Error(
|
|
59953
|
+
`${path5} does not contain a BlockRun key (expected brk_\u2026). Run "clawrouter login" with a valid key, or "clawrouter logout" to return to wallet billing. Refusing to fall back silently: the next source could bill a different account or spend from a wallet.`
|
|
59950
59954
|
);
|
|
59951
59955
|
}
|
|
59952
59956
|
return void 0;
|
|
@@ -59985,16 +59989,61 @@ function formatCreditBalance(b) {
|
|
|
59985
59989
|
const mode = b.billingMode === "ungated" ? "no prepaid limit" : b.billingMode ?? "unknown";
|
|
59986
59990
|
return `${spent ? `spent ${spent}` : "unknown"} \u2014 ${mode}`;
|
|
59987
59991
|
}
|
|
59988
|
-
function
|
|
59992
|
+
function normalizeApiKeyBase(raw) {
|
|
59993
|
+
const base4 = raw.replace(/\/+$/, "").replace(/\/v1$/, "");
|
|
59994
|
+
const url2 = new URL(base4);
|
|
59995
|
+
if (url2.username || url2.password || url2.search || url2.hash || url2.protocol !== "https:" && !(url2.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]"].includes(url2.hostname))) {
|
|
59996
|
+
throw new Error(
|
|
59997
|
+
"BlockRun account API URL requires HTTPS (except localhost) and no credentials, query or fragment."
|
|
59998
|
+
);
|
|
59999
|
+
}
|
|
60000
|
+
return base4;
|
|
60001
|
+
}
|
|
60002
|
+
function createApiKeyFetch(apiKey, baseFetch = fetch, apiBase = BLOCKRUN_API_KEY_API) {
|
|
60003
|
+
const base4 = new URL(normalizeApiKeyBase(apiBase));
|
|
59989
60004
|
return async (input, init2) => {
|
|
59990
|
-
const
|
|
60005
|
+
const request2 = input instanceof Request ? input : void 0;
|
|
60006
|
+
const url2 = new URL(request2?.url ?? String(input), `${base4}/`);
|
|
60007
|
+
if (url2.origin !== base4.origin || url2.username || url2.password) {
|
|
60008
|
+
throw new Error("Refusing to forward a BlockRun account key to another origin.");
|
|
60009
|
+
}
|
|
60010
|
+
if (base4.pathname === "/" && url2.pathname.startsWith("/api/v1/")) {
|
|
60011
|
+
url2.pathname = url2.pathname.slice(4);
|
|
60012
|
+
}
|
|
60013
|
+
const headers = new Headers(init2?.headers ?? request2?.headers);
|
|
60014
|
+
for (const name of [...headers.keys()]) {
|
|
60015
|
+
if (/payment/i.test(name) || name.toLowerCase() === "x-api-key") headers.delete(name);
|
|
60016
|
+
}
|
|
59991
60017
|
headers.set("authorization", `Bearer ${apiKey}`);
|
|
59992
|
-
|
|
59993
|
-
|
|
59994
|
-
|
|
60018
|
+
const response = await baseFetch(request2 ? new Request(url2, request2) : url2.href, {
|
|
60019
|
+
...init2,
|
|
60020
|
+
headers,
|
|
60021
|
+
redirect: "error"
|
|
60022
|
+
});
|
|
59995
60023
|
return response.ok ? response : explainApiKeyFailure(response);
|
|
59996
60024
|
};
|
|
59997
60025
|
}
|
|
60026
|
+
async function pollApiKeyJob(response, payFetch, apiBase, signal, intervalMs = 2e3) {
|
|
60027
|
+
if (response.status !== 202) return response;
|
|
60028
|
+
const initial = await response.clone().json();
|
|
60029
|
+
if (!initial.poll_url) throw new Error("Async account response missing poll_url");
|
|
60030
|
+
const pollUrl = new URL(initial.poll_url, `${normalizeApiKeyBase(apiBase)}/`).href;
|
|
60031
|
+
const abort = AbortSignal.any([signal, AbortSignal.timeout(15 * 6e4)]);
|
|
60032
|
+
while (!abort.aborted) {
|
|
60033
|
+
const polled = await payFetch(pollUrl, { signal: abort });
|
|
60034
|
+
if ([502, 503, 504, 522, 524].includes(polled.status)) {
|
|
60035
|
+
await polled.body?.cancel();
|
|
60036
|
+
} else {
|
|
60037
|
+
if (!polled.ok) return polled;
|
|
60038
|
+
const data = await polled.clone().json();
|
|
60039
|
+
if (data.status === "completed") return polled;
|
|
60040
|
+
if (data.status === "failed") return polled;
|
|
60041
|
+
await polled.body?.cancel();
|
|
60042
|
+
}
|
|
60043
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
60044
|
+
}
|
|
60045
|
+
throw new Error("Async account job did not complete before the client aborted or timed out.");
|
|
60046
|
+
}
|
|
59998
60047
|
async function explainApiKeyFailure(response) {
|
|
59999
60048
|
const hint = HINTS[response.status];
|
|
60000
60049
|
if (!hint) return response;
|
|
@@ -60028,7 +60077,7 @@ var init_api_key = __esm({
|
|
|
60028
60077
|
PORTAL_URL = "https://user.blockrun.ai";
|
|
60029
60078
|
PORTAL_KEYS_URL = `${PORTAL_URL}/dashboard/keys`;
|
|
60030
60079
|
PORTAL_CREDITS_URL = `${PORTAL_URL}/dashboard/credits`;
|
|
60031
|
-
BLOCKRUN_API_KEY_API = process["env"].BLOCKRUN_API_BASE_URL?.replace(/\/+$/, "") || "https://api.blockrun.ai";
|
|
60080
|
+
BLOCKRUN_API_KEY_API = process["env"].BLOCKRUN_API_BASE_URL?.replace(/\/+$/, "").replace(/\/v1$/, "") || "https://api.blockrun.ai";
|
|
60032
60081
|
HINTS = {
|
|
60033
60082
|
401: `Check BLOCKRUN_API_KEY, or mint a new key at ${PORTAL_KEYS_URL}.`,
|
|
60034
60083
|
402: `Top up your BlockRun credit at ${PORTAL_CREDITS_URL}.`,
|
|
@@ -69174,7 +69223,7 @@ var require_client_h2 = __commonJS({
|
|
|
69174
69223
|
"node_modules/undici/lib/dispatcher/client-h2.js"(exports, module) {
|
|
69175
69224
|
"use strict";
|
|
69176
69225
|
var assert10 = __require("assert");
|
|
69177
|
-
var { pipeline } = __require("stream");
|
|
69226
|
+
var { pipeline: pipeline2 } = __require("stream");
|
|
69178
69227
|
var util5 = require_util();
|
|
69179
69228
|
var {
|
|
69180
69229
|
RequestContentLengthMismatchError,
|
|
@@ -70321,7 +70370,7 @@ var require_client_h2 = __commonJS({
|
|
|
70321
70370
|
}
|
|
70322
70371
|
function writeStream(abort, socket, expectsPayload, h2stream, body, client, request2, contentLength) {
|
|
70323
70372
|
assert10(contentLength !== 0 || client[kRunning] === 0, "stream body cannot be pipelined");
|
|
70324
|
-
const pipe2 =
|
|
70373
|
+
const pipe2 = pipeline2(
|
|
70325
70374
|
body,
|
|
70326
70375
|
h2stream,
|
|
70327
70376
|
(err) => {
|
|
@@ -73476,7 +73525,7 @@ var require_readable = __commonJS({
|
|
|
73476
73525
|
"use strict";
|
|
73477
73526
|
var assert10 = __require("assert");
|
|
73478
73527
|
var { addAbortListener } = __require("events");
|
|
73479
|
-
var { Readable:
|
|
73528
|
+
var { Readable: Readable3 } = __require("stream");
|
|
73480
73529
|
var { RequestAbortedError, NotSupportedError, InvalidArgumentError, AbortError } = require_errors();
|
|
73481
73530
|
var util5 = require_util();
|
|
73482
73531
|
var { ReadableStreamFrom } = require_util();
|
|
@@ -73490,7 +73539,7 @@ var require_readable = __commonJS({
|
|
|
73490
73539
|
var kBytesRead = /* @__PURE__ */ Symbol("kBytesRead");
|
|
73491
73540
|
var noop2 = () => {
|
|
73492
73541
|
};
|
|
73493
|
-
var BodyReadable = class extends
|
|
73542
|
+
var BodyReadable = class extends Readable3 {
|
|
73494
73543
|
/**
|
|
73495
73544
|
* @param {object} opts
|
|
73496
73545
|
* @param {(this: Readable, size: number) => void} opts.resume
|
|
@@ -73889,7 +73938,7 @@ var require_api_request = __commonJS({
|
|
|
73889
73938
|
"use strict";
|
|
73890
73939
|
var assert10 = __require("assert");
|
|
73891
73940
|
var { AsyncResource } = __require("async_hooks");
|
|
73892
|
-
var { Readable:
|
|
73941
|
+
var { Readable: Readable3 } = require_readable();
|
|
73893
73942
|
var { InvalidArgumentError, RequestAbortedError } = require_errors();
|
|
73894
73943
|
var util5 = require_util();
|
|
73895
73944
|
function noop2() {
|
|
@@ -73975,7 +74024,7 @@ var require_api_request = __commonJS({
|
|
|
73975
74024
|
const parsedHeaders = headers;
|
|
73976
74025
|
const contentType = parsedHeaders?.["content-type"];
|
|
73977
74026
|
const contentLength = parsedHeaders?.["content-length"];
|
|
73978
|
-
const res = new
|
|
74027
|
+
const res = new Readable3({
|
|
73979
74028
|
resume: () => controller.resume(),
|
|
73980
74029
|
abort: (reason) => controller.abort(reason),
|
|
73981
74030
|
contentType,
|
|
@@ -74351,7 +74400,7 @@ var require_api_pipeline = __commonJS({
|
|
|
74351
74400
|
"node_modules/undici/lib/api/api-pipeline.js"(exports, module) {
|
|
74352
74401
|
"use strict";
|
|
74353
74402
|
var {
|
|
74354
|
-
Readable:
|
|
74403
|
+
Readable: Readable3,
|
|
74355
74404
|
Duplex,
|
|
74356
74405
|
PassThrough
|
|
74357
74406
|
} = __require("stream");
|
|
@@ -74368,7 +74417,7 @@ var require_api_pipeline = __commonJS({
|
|
|
74368
74417
|
function noop2() {
|
|
74369
74418
|
}
|
|
74370
74419
|
var kResume = /* @__PURE__ */ Symbol("resume");
|
|
74371
|
-
var PipelineRequest = class extends
|
|
74420
|
+
var PipelineRequest = class extends Readable3 {
|
|
74372
74421
|
constructor() {
|
|
74373
74422
|
super({ autoDestroy: true });
|
|
74374
74423
|
this[kResume] = null;
|
|
@@ -74386,7 +74435,7 @@ var require_api_pipeline = __commonJS({
|
|
|
74386
74435
|
callback(err);
|
|
74387
74436
|
}
|
|
74388
74437
|
};
|
|
74389
|
-
var PipelineResponse = class extends
|
|
74438
|
+
var PipelineResponse = class extends Readable3 {
|
|
74390
74439
|
constructor(resume2) {
|
|
74391
74440
|
super({ autoDestroy: true });
|
|
74392
74441
|
this[kResume] = resume2;
|
|
@@ -74540,7 +74589,7 @@ var require_api_pipeline = __commonJS({
|
|
|
74540
74589
|
util5.destroy(ret, err);
|
|
74541
74590
|
}
|
|
74542
74591
|
};
|
|
74543
|
-
function
|
|
74592
|
+
function pipeline2(opts, handler) {
|
|
74544
74593
|
try {
|
|
74545
74594
|
const pipelineHandler = new PipelineHandler(opts, handler);
|
|
74546
74595
|
this.dispatch({ ...opts, body: pipelineHandler.req }, pipelineHandler);
|
|
@@ -74549,7 +74598,7 @@ var require_api_pipeline = __commonJS({
|
|
|
74549
74598
|
return new PassThrough().destroy(err);
|
|
74550
74599
|
}
|
|
74551
74600
|
}
|
|
74552
|
-
module.exports =
|
|
74601
|
+
module.exports = pipeline2;
|
|
74553
74602
|
}
|
|
74554
74603
|
});
|
|
74555
74604
|
|
|
@@ -79667,7 +79716,7 @@ var require_cache2 = __commonJS({
|
|
|
79667
79716
|
"node_modules/undici/lib/interceptor/cache.js"(exports, module) {
|
|
79668
79717
|
"use strict";
|
|
79669
79718
|
var assert10 = __require("assert");
|
|
79670
|
-
var { Readable:
|
|
79719
|
+
var { Readable: Readable3 } = __require("stream");
|
|
79671
79720
|
var util5 = require_util();
|
|
79672
79721
|
var CacheHandler = require_cache_handler();
|
|
79673
79722
|
var MemoryCacheStore = require_memory_cache_store();
|
|
@@ -79843,7 +79892,7 @@ var require_cache2 = __commonJS({
|
|
|
79843
79892
|
return dispatch(opts, new CacheHandler(globalOpts, cacheKey2, handler));
|
|
79844
79893
|
}
|
|
79845
79894
|
function sendCachedValue(handler, opts, result, age, context, isStale2) {
|
|
79846
|
-
const stream4 = util5.isStream(result.body) ? result.body :
|
|
79895
|
+
const stream4 = util5.isStream(result.body) ? result.body : Readable3.from(result.body ?? []);
|
|
79847
79896
|
assert10(!stream4.destroyed, "stream should not be destroyed");
|
|
79848
79897
|
assert10(!stream4.readableDidRead, "stream should not be readableDidRead");
|
|
79849
79898
|
const controller = {
|
|
@@ -80088,7 +80137,7 @@ var require_decompress = __commonJS({
|
|
|
80088
80137
|
"node_modules/undici/lib/interceptor/decompress.js"(exports, module) {
|
|
80089
80138
|
"use strict";
|
|
80090
80139
|
var { createInflate, createGunzip, createBrotliDecompress, createZstdDecompress } = __require("zlib");
|
|
80091
|
-
var { pipeline } = __require("stream");
|
|
80140
|
+
var { pipeline: pipeline2 } = __require("stream");
|
|
80092
80141
|
var DecoratorHandler = require_decorator_handler();
|
|
80093
80142
|
var supportedEncodings = {
|
|
80094
80143
|
gzip: createGunzip,
|
|
@@ -80198,7 +80247,7 @@ var require_decompress = __commonJS({
|
|
|
80198
80247
|
#setupMultipleDecompressors(controller) {
|
|
80199
80248
|
const lastDecompressor = this.#decompressors[this.#decompressors.length - 1];
|
|
80200
80249
|
this.#setupDecompressorEvents(lastDecompressor, controller);
|
|
80201
|
-
|
|
80250
|
+
pipeline2(this.#decompressors, (err) => {
|
|
80202
80251
|
if (err) {
|
|
80203
80252
|
super.onResponseError(controller, err);
|
|
80204
80253
|
return;
|
|
@@ -82992,7 +83041,7 @@ var require_fetch = __commonJS({
|
|
|
82992
83041
|
subresourceSet
|
|
82993
83042
|
} = require_constants4();
|
|
82994
83043
|
var EE = __require("events");
|
|
82995
|
-
var { Readable:
|
|
83044
|
+
var { Readable: Readable3, pipeline: pipeline2, finished: finished2, isErrored, isReadable } = __require("stream");
|
|
82996
83045
|
var { addAbortListener, bufferToLowerCasedHeaderName } = require_util();
|
|
82997
83046
|
var { dataURLProcessor, serializeAMimeType, minimizeSupportedMimeType } = require_data_url();
|
|
82998
83047
|
var { getGlobalDispatcher } = require_global2();
|
|
@@ -83968,7 +84017,7 @@ var require_fetch = __commonJS({
|
|
|
83968
84017
|
const headersList = new HeadersList();
|
|
83969
84018
|
appendHeadersListFromResponseHeaders(headersList, headers, rawHeaders);
|
|
83970
84019
|
const location = headersList.get("location", true);
|
|
83971
|
-
this.body = new
|
|
84020
|
+
this.body = new Readable3({ read: () => controller.resume() });
|
|
83972
84021
|
const willFollow = location && request2.redirect === "follow" && redirectStatusSet.has(status);
|
|
83973
84022
|
const decoders = [];
|
|
83974
84023
|
if (request2.method !== "HEAD" && request2.method !== "CONNECT" && !nullBodyStatus.includes(status) && !willFollow) {
|
|
@@ -84016,7 +84065,7 @@ var require_fetch = __commonJS({
|
|
|
84016
84065
|
status,
|
|
84017
84066
|
statusText,
|
|
84018
84067
|
headersList,
|
|
84019
|
-
body: decoders.length ?
|
|
84068
|
+
body: decoders.length ? pipeline2(this.body, ...decoders, (err) => {
|
|
84020
84069
|
if (err) {
|
|
84021
84070
|
this.onResponseError(controller, err);
|
|
84022
84071
|
}
|
|
@@ -87828,7 +87877,7 @@ ${value}`;
|
|
|
87828
87877
|
var require_eventsource = __commonJS({
|
|
87829
87878
|
"node_modules/undici/lib/web/eventsource/eventsource.js"(exports, module) {
|
|
87830
87879
|
"use strict";
|
|
87831
|
-
var { pipeline } = __require("stream");
|
|
87880
|
+
var { pipeline: pipeline2 } = __require("stream");
|
|
87832
87881
|
var { fetching } = require_fetch();
|
|
87833
87882
|
var { webidl } = require_webidl();
|
|
87834
87883
|
var { EventSourceStream } = require_eventsource_stream();
|
|
@@ -87978,7 +88027,7 @@ var require_eventsource = __commonJS({
|
|
|
87978
88027
|
));
|
|
87979
88028
|
}
|
|
87980
88029
|
});
|
|
87981
|
-
|
|
88030
|
+
pipeline2(
|
|
87982
88031
|
response.body.stream,
|
|
87983
88032
|
eventSourceStream,
|
|
87984
88033
|
(error) => {
|
|
@@ -90528,7 +90577,8 @@ var init_v1 = __esm({
|
|
|
90528
90577
|
import { AsyncLocalStorage } from "async_hooks";
|
|
90529
90578
|
import { createHmac } from "crypto";
|
|
90530
90579
|
import { createServer } from "http";
|
|
90531
|
-
import { finished } from "stream";
|
|
90580
|
+
import { finished, Readable } from "stream";
|
|
90581
|
+
import { pipeline } from "stream/promises";
|
|
90532
90582
|
import { homedir as homedir8 } from "os";
|
|
90533
90583
|
import { join as join11 } from "path";
|
|
90534
90584
|
import { mkdir as mkdir5, writeFile as writeFile3, readFile as readFile2, stat as fsStat } from "fs/promises";
|
|
@@ -90537,10 +90587,10 @@ async function loadGatewayCatalog(apiBase, apiKey) {
|
|
|
90537
90587
|
try {
|
|
90538
90588
|
const controller = new AbortController();
|
|
90539
90589
|
const timer2 = setTimeout(() => controller.abort(), GATEWAY_CATALOG_TIMEOUT_MS);
|
|
90540
|
-
const res = await fetch
|
|
90541
|
-
|
|
90542
|
-
|
|
90543
|
-
|
|
90590
|
+
const res = await (apiKey ? createApiKeyFetch(apiKey, fetch, apiBase) : fetch)(
|
|
90591
|
+
`${apiBase}/v1/models`,
|
|
90592
|
+
{ signal: controller.signal }
|
|
90593
|
+
);
|
|
90544
90594
|
clearTimeout(timer2);
|
|
90545
90595
|
if (!res.ok) return;
|
|
90546
90596
|
const body = await res.json();
|
|
@@ -90841,7 +90891,12 @@ async function checkExistingProxy(port) {
|
|
|
90841
90891
|
const data = await response.json();
|
|
90842
90892
|
const authMode = data.authMode === "api-key" ? "api-key" : "wallet";
|
|
90843
90893
|
if (data.status === "ok" && (data.wallet || authMode === "api-key")) {
|
|
90844
|
-
return {
|
|
90894
|
+
return {
|
|
90895
|
+
wallet: data.wallet ?? "",
|
|
90896
|
+
paymentChain: data.paymentChain,
|
|
90897
|
+
authMode,
|
|
90898
|
+
apiKeyLabel: typeof data.apiKey === "string" ? data.apiKey : void 0
|
|
90899
|
+
};
|
|
90845
90900
|
}
|
|
90846
90901
|
}
|
|
90847
90902
|
return void 0;
|
|
@@ -91286,6 +91341,39 @@ function blockrunRequestId(response) {
|
|
|
91286
91341
|
}
|
|
91287
91342
|
return void 0;
|
|
91288
91343
|
}
|
|
91344
|
+
function gatewayRemainingCreditUsd(response) {
|
|
91345
|
+
const raw = response?.headers.get("x-blockrun-credit-remaining-usd");
|
|
91346
|
+
if (raw === null || raw === void 0) return void 0;
|
|
91347
|
+
const trimmed = raw.trim();
|
|
91348
|
+
if (trimmed === "") return void 0;
|
|
91349
|
+
const value = Number(trimmed);
|
|
91350
|
+
if (!Number.isFinite(value) || value < 0) return void 0;
|
|
91351
|
+
return value;
|
|
91352
|
+
}
|
|
91353
|
+
function settledMediaCostUsd(upstream, body, x402AmountUsd, estimate) {
|
|
91354
|
+
const header = gatewaySettledCostUsd(upstream);
|
|
91355
|
+
if (header !== void 0) return header;
|
|
91356
|
+
const price = body?.price?.amount;
|
|
91357
|
+
if (typeof price === "string" || typeof price === "number") {
|
|
91358
|
+
const parsed = Number(price);
|
|
91359
|
+
if (Number.isFinite(parsed) && parsed >= 0) return parsed;
|
|
91360
|
+
}
|
|
91361
|
+
if (typeof x402AmountUsd === "number" && x402AmountUsd > 0) return x402AmountUsd;
|
|
91362
|
+
return estimate;
|
|
91363
|
+
}
|
|
91364
|
+
function noteRemainingCredit(response) {
|
|
91365
|
+
const remaining = gatewayRemainingCreditUsd(response);
|
|
91366
|
+
if (remaining === void 0) return;
|
|
91367
|
+
if (remaining > LOW_CREDIT_USD) {
|
|
91368
|
+
lowCreditWarned = false;
|
|
91369
|
+
return;
|
|
91370
|
+
}
|
|
91371
|
+
if (lowCreditWarned) return;
|
|
91372
|
+
lowCreditWarned = true;
|
|
91373
|
+
console.warn(
|
|
91374
|
+
remaining <= 0 ? `[ClawRouter] \u26A0 BlockRun account credit is exhausted \u2014 calls will fail with 402. Top up: ${PORTAL_CREDITS_URL}` : `[ClawRouter] \u26A0 BlockRun account credit low: $${remaining.toFixed(2)} remaining. Top up: ${PORTAL_CREDITS_URL}`
|
|
91375
|
+
);
|
|
91376
|
+
}
|
|
91289
91377
|
function gatewaySettledCostUsd(response) {
|
|
91290
91378
|
const raw = response?.headers.get("x-blockrun-cost-usd");
|
|
91291
91379
|
if (raw === null || raw === void 0) return void 0;
|
|
@@ -91295,7 +91383,7 @@ function gatewaySettledCostUsd(response) {
|
|
|
91295
91383
|
if (!Number.isFinite(value) || value < 0) return void 0;
|
|
91296
91384
|
return value;
|
|
91297
91385
|
}
|
|
91298
|
-
async function proxyPaidApiRequest(req, res, apiBase, payFetch, getActualPaymentUsd) {
|
|
91386
|
+
async function proxyPaidApiRequest(req, res, apiBase, payFetch, getActualPaymentUsd, accountPassthrough = false, authMode = "wallet") {
|
|
91299
91387
|
const startTime = Date.now();
|
|
91300
91388
|
const upstreamUrl = `${apiBase}${req.url}`;
|
|
91301
91389
|
const isBlockrunExa = req.url?.startsWith("/v1/exa/") ?? false;
|
|
@@ -91334,16 +91422,32 @@ async function proxyPaidApiRequest(req, res, apiBase, payFetch, getActualPayment
|
|
|
91334
91422
|
return;
|
|
91335
91423
|
responseHeaders[key2] = value;
|
|
91336
91424
|
});
|
|
91425
|
+
if (accountPassthrough || authMode === "api-key") {
|
|
91426
|
+
responseHeaders["cache-control"] = "no-store";
|
|
91427
|
+
}
|
|
91337
91428
|
res.writeHead(upstream.status, responseHeaders);
|
|
91338
|
-
if (
|
|
91339
|
-
|
|
91340
|
-
|
|
91341
|
-
|
|
91429
|
+
if (accountPassthrough) {
|
|
91430
|
+
if (upstream.body) {
|
|
91431
|
+
await pipeline(
|
|
91432
|
+
Readable.fromWeb(upstream.body),
|
|
91433
|
+
res,
|
|
91434
|
+
{ signal: clientAbort.signal }
|
|
91435
|
+
);
|
|
91436
|
+
} else {
|
|
91437
|
+
res.end();
|
|
91438
|
+
}
|
|
91439
|
+
} else {
|
|
91440
|
+
if (upstream.body) {
|
|
91441
|
+
const chunks = await readBodyWithTimeout(upstream.body, ERROR_BODY_READ_TIMEOUT_MS);
|
|
91442
|
+
for (const chunk of chunks) {
|
|
91443
|
+
safeWrite(res, Buffer.from(chunk));
|
|
91444
|
+
}
|
|
91342
91445
|
}
|
|
91446
|
+
res.end();
|
|
91343
91447
|
}
|
|
91344
|
-
res.end();
|
|
91345
91448
|
const latencyMs = Date.now() - startTime;
|
|
91346
91449
|
console.log(`[ClawRouter] ${requestLabel} response: ${upstream.status} (${latencyMs}ms)`);
|
|
91450
|
+
noteRemainingCredit(upstream);
|
|
91347
91451
|
const settledCostUsd = gatewaySettledCostUsd(upstream);
|
|
91348
91452
|
const paidAmount = settledCostUsd ?? getActualPaymentUsd();
|
|
91349
91453
|
const requestCost = settledCostUsd !== void 0 ? settledCostUsd : resolvePhoneTelemetryCost({
|
|
@@ -91447,7 +91551,8 @@ async function startProxy(options) {
|
|
|
91447
91551
|
const walletKey = options.wallet === void 0 ? void 0 : typeof options.wallet === "string" ? options.wallet : options.wallet.key;
|
|
91448
91552
|
const solanaPrivateKeyBytes = options.wallet === void 0 || typeof options.wallet === "string" ? void 0 : options.wallet.solanaPrivateKeyBytes;
|
|
91449
91553
|
const paymentChain = options.paymentChain ?? await resolvePaymentChain();
|
|
91450
|
-
const
|
|
91554
|
+
const requestedApiBase = options.apiBase ?? (authMode === "api-key" ? BLOCKRUN_API_KEY_API : paymentChain === "solana" && solanaPrivateKeyBytes ? BLOCKRUN_SOLANA_API : BLOCKRUN_API);
|
|
91555
|
+
const apiBase = authMode === "api-key" ? normalizeApiKeyBase(requestedApiBase) : requestedApiBase;
|
|
91451
91556
|
if (authMode === "api-key") {
|
|
91452
91557
|
console.log(`[ClawRouter] Auth: BlockRun API key ${maskApiKey(apiKey)} (${apiBase})`);
|
|
91453
91558
|
console.log(`[ClawRouter] Billing: account credit \u2014 top up at ${PORTAL_CREDITS_URL}`);
|
|
@@ -91474,13 +91579,20 @@ async function startProxy(options) {
|
|
|
91474
91579
|
);
|
|
91475
91580
|
}
|
|
91476
91581
|
if (authMode === "api-key") {
|
|
91582
|
+
const runningLabel = existingProxy.apiKeyLabel;
|
|
91583
|
+
const ourLabel = maskApiKey(apiKey);
|
|
91584
|
+
if (runningLabel !== ourLabel) {
|
|
91585
|
+
throw new Error(
|
|
91586
|
+
`Existing proxy on port ${listenPort} is billing ${runningLabel ?? "an unidentified BlockRun account"}, but this process is configured for ${ourLabel}. Reusing it would charge the other account. Stop that proxy first, or use a different port.`
|
|
91587
|
+
);
|
|
91588
|
+
}
|
|
91477
91589
|
options.onReady?.(listenPort);
|
|
91478
91590
|
return {
|
|
91479
91591
|
port: listenPort,
|
|
91480
91592
|
baseUrl: baseUrl2,
|
|
91481
91593
|
walletAddress: "",
|
|
91482
91594
|
authMode,
|
|
91483
|
-
apiKeyLabel:
|
|
91595
|
+
apiKeyLabel: ourLabel,
|
|
91484
91596
|
balanceMonitor: new ApiKeyBalanceMonitor(),
|
|
91485
91597
|
// No-op: we didn't start this proxy, so we shouldn't close it
|
|
91486
91598
|
close: async () => {
|
|
@@ -91576,7 +91688,7 @@ async function startProxy(options) {
|
|
|
91576
91688
|
if (store) store.amountUsd = amountUsd;
|
|
91577
91689
|
console.log(`[ClawRouter] Payment signed on ${chain3} (${network}) \u2014 $${amountUsd.toFixed(6)}`);
|
|
91578
91690
|
});
|
|
91579
|
-
const payFetch = authMode === "api-key" ? createApiKeyFetch(apiKey) : createPayFetchWithPreAuth(fetch, x402, void 0, {
|
|
91691
|
+
const payFetch = authMode === "api-key" ? createApiKeyFetch(apiKey, fetch, apiBase) : createPayFetchWithPreAuth(fetch, x402, void 0, {
|
|
91580
91692
|
skipPreAuth: paymentChain === "solana",
|
|
91581
91693
|
// Per-request cost estimate so pre-auth is only reused when the cached
|
|
91582
91694
|
// payment still covers the (possibly larger) request — BlockRun prices per
|
|
@@ -92080,9 +92192,15 @@ async function startProxy(options) {
|
|
|
92080
92192
|
}
|
|
92081
92193
|
}
|
|
92082
92194
|
}
|
|
92083
|
-
const imgActualCost =
|
|
92195
|
+
const imgActualCost = settledMediaCostUsd(
|
|
92196
|
+
upstream,
|
|
92197
|
+
result,
|
|
92198
|
+
paymentStore.getStore()?.amountUsd,
|
|
92199
|
+
imgCost
|
|
92200
|
+
);
|
|
92084
92201
|
logUsage({
|
|
92085
92202
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
92203
|
+
...blockrunRequestId(upstream) ? { requestId: blockrunRequestId(upstream) } : {},
|
|
92086
92204
|
model: imgModel,
|
|
92087
92205
|
tier: "IMAGE",
|
|
92088
92206
|
cost: imgActualCost,
|
|
@@ -92151,12 +92269,15 @@ async function startProxy(options) {
|
|
|
92151
92269
|
return;
|
|
92152
92270
|
}
|
|
92153
92271
|
try {
|
|
92154
|
-
|
|
92272
|
+
let upstream = await payFetch(`${apiBase}/v1/images/image2image`, {
|
|
92155
92273
|
method: "POST",
|
|
92156
92274
|
headers: { "content-type": "application/json", "user-agent": USER_AGENT },
|
|
92157
92275
|
body: reqBody,
|
|
92158
92276
|
signal: clientAbort.signal
|
|
92159
92277
|
});
|
|
92278
|
+
if (authMode === "api-key") {
|
|
92279
|
+
upstream = await pollApiKeyJob(upstream, payFetch, apiBase, clientAbort.signal);
|
|
92280
|
+
}
|
|
92160
92281
|
const text = await upstream.text();
|
|
92161
92282
|
if (!upstream.ok) {
|
|
92162
92283
|
res.writeHead(upstream.status, { "Content-Type": "application/json" });
|
|
@@ -92203,9 +92324,15 @@ async function startProxy(options) {
|
|
|
92203
92324
|
}
|
|
92204
92325
|
}
|
|
92205
92326
|
}
|
|
92206
|
-
const img2imgActualCost =
|
|
92327
|
+
const img2imgActualCost = settledMediaCostUsd(
|
|
92328
|
+
upstream,
|
|
92329
|
+
result,
|
|
92330
|
+
paymentStore.getStore()?.amountUsd,
|
|
92331
|
+
img2imgCost
|
|
92332
|
+
);
|
|
92207
92333
|
logUsage({
|
|
92208
92334
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
92335
|
+
...blockrunRequestId(upstream) ? { requestId: blockrunRequestId(upstream) } : {},
|
|
92209
92336
|
model: img2imgModel,
|
|
92210
92337
|
tier: "IMAGE",
|
|
92211
92338
|
cost: img2imgActualCost,
|
|
@@ -92245,12 +92372,15 @@ async function startProxy(options) {
|
|
|
92245
92372
|
} catch {
|
|
92246
92373
|
}
|
|
92247
92374
|
try {
|
|
92248
|
-
|
|
92375
|
+
let upstream = await payFetch(`${apiBase}/v1/audio/generations`, {
|
|
92249
92376
|
method: "POST",
|
|
92250
92377
|
headers: { "content-type": "application/json", "user-agent": USER_AGENT },
|
|
92251
92378
|
body: reqBody,
|
|
92252
92379
|
signal: clientAbort.signal
|
|
92253
92380
|
});
|
|
92381
|
+
if (authMode === "api-key") {
|
|
92382
|
+
upstream = await pollApiKeyJob(upstream, payFetch, apiBase, clientAbort.signal);
|
|
92383
|
+
}
|
|
92254
92384
|
const text = await upstream.text();
|
|
92255
92385
|
if (!upstream.ok) {
|
|
92256
92386
|
res.writeHead(upstream.status, { "Content-Type": "application/json" });
|
|
@@ -92289,9 +92419,15 @@ async function startProxy(options) {
|
|
|
92289
92419
|
}
|
|
92290
92420
|
}
|
|
92291
92421
|
}
|
|
92292
|
-
const audioActualCost =
|
|
92422
|
+
const audioActualCost = settledMediaCostUsd(
|
|
92423
|
+
upstream,
|
|
92424
|
+
result,
|
|
92425
|
+
paymentStore.getStore()?.amountUsd,
|
|
92426
|
+
0.15
|
|
92427
|
+
);
|
|
92293
92428
|
logUsage({
|
|
92294
92429
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
92430
|
+
...blockrunRequestId(upstream) ? { requestId: blockrunRequestId(upstream) } : {},
|
|
92295
92431
|
model: audioModel,
|
|
92296
92432
|
tier: "AUDIO",
|
|
92297
92433
|
cost: audioActualCost,
|
|
@@ -92449,7 +92585,12 @@ async function startProxy(options) {
|
|
|
92449
92585
|
}
|
|
92450
92586
|
}
|
|
92451
92587
|
}
|
|
92452
|
-
const videoActualCost =
|
|
92588
|
+
const videoActualCost = settledMediaCostUsd(
|
|
92589
|
+
void 0,
|
|
92590
|
+
submitResult,
|
|
92591
|
+
paymentStore.getStore()?.amountUsd,
|
|
92592
|
+
estimateVideoCost(videoModel, videoDuration, videoHasImageInput)
|
|
92593
|
+
);
|
|
92453
92594
|
logUsage({
|
|
92454
92595
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
92455
92596
|
model: videoModel,
|
|
@@ -92483,7 +92624,9 @@ async function startProxy(options) {
|
|
|
92483
92624
|
res,
|
|
92484
92625
|
apiBase,
|
|
92485
92626
|
payFetch,
|
|
92486
|
-
() => paymentStore.getStore()?.amountUsd ?? 0
|
|
92627
|
+
() => paymentStore.getStore()?.amountUsd ?? 0,
|
|
92628
|
+
false,
|
|
92629
|
+
authMode
|
|
92487
92630
|
);
|
|
92488
92631
|
} catch (err) {
|
|
92489
92632
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
@@ -92506,6 +92649,33 @@ async function startProxy(options) {
|
|
|
92506
92649
|
res.end(JSON.stringify({ error: "Not found" }));
|
|
92507
92650
|
return;
|
|
92508
92651
|
}
|
|
92652
|
+
if (authMode === "api-key" && /^\/v1\//.test(req.url ?? "") && !/^\/v1\/(?:chat\/completions|messages)(?:\?|$)/.test(req.url ?? "")) {
|
|
92653
|
+
try {
|
|
92654
|
+
await proxyPaidApiRequest(
|
|
92655
|
+
req,
|
|
92656
|
+
res,
|
|
92657
|
+
apiBase,
|
|
92658
|
+
payFetch,
|
|
92659
|
+
() => paymentStore.getStore()?.amountUsd ?? 0,
|
|
92660
|
+
true,
|
|
92661
|
+
authMode
|
|
92662
|
+
);
|
|
92663
|
+
} catch (err) {
|
|
92664
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
92665
|
+
options.onError?.(error);
|
|
92666
|
+
if (!res.headersSent) {
|
|
92667
|
+
res.writeHead(502, { "Content-Type": "application/json" });
|
|
92668
|
+
res.end(
|
|
92669
|
+
JSON.stringify({
|
|
92670
|
+
error: { message: `Account API error: ${error.message}`, type: "account_error" }
|
|
92671
|
+
})
|
|
92672
|
+
);
|
|
92673
|
+
} else if (!res.writableEnded) {
|
|
92674
|
+
res.end();
|
|
92675
|
+
}
|
|
92676
|
+
}
|
|
92677
|
+
return;
|
|
92678
|
+
}
|
|
92509
92679
|
if (!req.url.includes("/chat/completions")) {
|
|
92510
92680
|
res.writeHead(404, { "Content-Type": "application/json" });
|
|
92511
92681
|
res.end(
|
|
@@ -93189,9 +93359,15 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
93189
93359
|
responseText = lines.join("\n");
|
|
93190
93360
|
}
|
|
93191
93361
|
console.log(`[ClawRouter] /imagegen success: ${images.length} image(s) generated`);
|
|
93192
|
-
const imagegenActualCost =
|
|
93362
|
+
const imagegenActualCost = settledMediaCostUsd(
|
|
93363
|
+
imageResponse,
|
|
93364
|
+
imageResult,
|
|
93365
|
+
paymentStore.getStore()?.amountUsd,
|
|
93366
|
+
estimateImageCost(imageModel, imageSize, 1)
|
|
93367
|
+
);
|
|
93193
93368
|
logUsage({
|
|
93194
93369
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
93370
|
+
...blockrunRequestId(imageResponse) ? { requestId: blockrunRequestId(imageResponse) } : {},
|
|
93195
93371
|
model: imageModel,
|
|
93196
93372
|
tier: "IMAGE",
|
|
93197
93373
|
cost: imagegenActualCost,
|
|
@@ -93415,9 +93591,15 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
93415
93591
|
responseText = lines.join("\n");
|
|
93416
93592
|
}
|
|
93417
93593
|
console.log(`[ClawRouter] /img2img success: ${images.length} image(s)`);
|
|
93418
|
-
const img2imgActualCost2 =
|
|
93594
|
+
const img2imgActualCost2 = settledMediaCostUsd(
|
|
93595
|
+
img2imgResponse,
|
|
93596
|
+
img2imgResult,
|
|
93597
|
+
paymentStore.getStore()?.amountUsd,
|
|
93598
|
+
estimateImageCost(img2imgModel, img2imgSize, 1)
|
|
93599
|
+
);
|
|
93419
93600
|
logUsage({
|
|
93420
93601
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
93602
|
+
...blockrunRequestId(img2imgResponse) ? { requestId: blockrunRequestId(img2imgResponse) } : {},
|
|
93421
93603
|
model: img2imgModel,
|
|
93422
93604
|
tier: "IMAGE",
|
|
93423
93605
|
cost: img2imgActualCost2,
|
|
@@ -94473,6 +94655,7 @@ data: [DONE]
|
|
|
94473
94655
|
}
|
|
94474
94656
|
}
|
|
94475
94657
|
upstreamRequestId = blockrunRequestId(upstream);
|
|
94658
|
+
noteRemainingCredit(upstream);
|
|
94476
94659
|
if (!upstream) {
|
|
94477
94660
|
const attemptSummary = failedAttempts.length > 0 ? failedAttempts.map((a) => `${a.model} (${a.reason})`).join(", ") : "unknown";
|
|
94478
94661
|
const structuredMessage = failedAttempts.length > 0 ? `All ${failedAttempts.length} models failed. Tried: ${attemptSummary}` : "All models in fallback chain failed";
|
|
@@ -95013,7 +95196,7 @@ data: [DONE]
|
|
|
95013
95196
|
});
|
|
95014
95197
|
}
|
|
95015
95198
|
}
|
|
95016
|
-
var paymentStore, BLOCKRUN_API, BLOCKRUN_SOLANA_API, DESKTOP_SERVICE_TOKEN_FILE, IMAGE_DIR, AUDIO_DIR, VIDEO_DIR, AUTO_MODEL, ROUTING_PROFILES, FREE_MODELS, gatewayModelIds, FREE_MODEL, FREE_UPSTREAM_OVERRIDES, MAX_MESSAGES, CONTEXT_LIMIT_KB, HEARTBEAT_INTERVAL_MS, BALANCE_CHECK_TIMEOUT_MS, GATEWAY_CATALOG_TIMEOUT_MS, DEFAULT_REQUEST_TIMEOUT_MS, PER_MODEL_TIMEOUT_MS, REASONING_MODEL_TIMEOUT_MS, REASONING_MODEL_IDS, MAX_FALLBACK_ATTEMPTS, HEALTH_CHECK_TIMEOUT_MS, RATE_LIMIT_COOLDOWN_MS, OVERLOAD_COOLDOWN_MS, PORT_RETRY_ATTEMPTS, PORT_RETRY_DELAY_MS, MODEL_BODY_READ_TIMEOUT_MS, ERROR_BODY_READ_TIMEOUT_MS, ClientDisconnectedError, rateLimitedModels, overloadedModels, perProviderErrors, BALANCE_CHECK_BUFFER, BALANCE_PREFLIGHT_OUTPUT_TOKEN_CAP, PROVIDER_ERROR_PATTERNS, DEGRADED_RESPONSE_PATTERNS, DEGRADED_LOOP_PATTERNS, VALID_ROLES, ROLE_MAPPINGS, VALID_TOOL_ID_PATTERN, KIMI_BLOCK_RE, KIMI_TOKEN_RE, THINKING_TAG_RE, THINKING_BLOCK_RE, BLOCKRUN_MODEL_BY_ID, IMAGE_PRICING, IMAGE_MODEL_IDS, IMAGE_MODEL_SIZES, IMAGE_MODEL_ALIASES, VIDEO_PRICING, PHONE_PRICING;
|
|
95199
|
+
var paymentStore, BLOCKRUN_API, BLOCKRUN_SOLANA_API, DESKTOP_SERVICE_TOKEN_FILE, IMAGE_DIR, AUDIO_DIR, VIDEO_DIR, AUTO_MODEL, ROUTING_PROFILES, FREE_MODELS, gatewayModelIds, FREE_MODEL, FREE_UPSTREAM_OVERRIDES, MAX_MESSAGES, CONTEXT_LIMIT_KB, HEARTBEAT_INTERVAL_MS, BALANCE_CHECK_TIMEOUT_MS, GATEWAY_CATALOG_TIMEOUT_MS, DEFAULT_REQUEST_TIMEOUT_MS, PER_MODEL_TIMEOUT_MS, REASONING_MODEL_TIMEOUT_MS, REASONING_MODEL_IDS, MAX_FALLBACK_ATTEMPTS, HEALTH_CHECK_TIMEOUT_MS, RATE_LIMIT_COOLDOWN_MS, OVERLOAD_COOLDOWN_MS, PORT_RETRY_ATTEMPTS, PORT_RETRY_DELAY_MS, MODEL_BODY_READ_TIMEOUT_MS, ERROR_BODY_READ_TIMEOUT_MS, ClientDisconnectedError, rateLimitedModels, overloadedModels, perProviderErrors, BALANCE_CHECK_BUFFER, BALANCE_PREFLIGHT_OUTPUT_TOKEN_CAP, PROVIDER_ERROR_PATTERNS, DEGRADED_RESPONSE_PATTERNS, DEGRADED_LOOP_PATTERNS, VALID_ROLES, ROLE_MAPPINGS, VALID_TOOL_ID_PATTERN, KIMI_BLOCK_RE, KIMI_TOKEN_RE, THINKING_TAG_RE, THINKING_BLOCK_RE, BLOCKRUN_MODEL_BY_ID, IMAGE_PRICING, IMAGE_MODEL_IDS, IMAGE_MODEL_SIZES, IMAGE_MODEL_ALIASES, VIDEO_PRICING, PHONE_PRICING, LOW_CREDIT_USD, lowCreditWarned;
|
|
95017
95200
|
var init_proxy = __esm({
|
|
95018
95201
|
"src/proxy.ts"() {
|
|
95019
95202
|
"use strict";
|
|
@@ -95275,6 +95458,8 @@ var init_proxy = __esm({
|
|
|
95275
95458
|
"phone/numbers/release": 0,
|
|
95276
95459
|
"voice/call": 0.54
|
|
95277
95460
|
};
|
|
95461
|
+
LOW_CREDIT_USD = 1;
|
|
95462
|
+
lowCreditWarned = false;
|
|
95278
95463
|
}
|
|
95279
95464
|
});
|
|
95280
95465
|
|
|
@@ -112104,7 +112289,7 @@ var init_readBlob = __esm({
|
|
|
112104
112289
|
|
|
112105
112290
|
// node_modules/axios/lib/helpers/formDataToStream.js
|
|
112106
112291
|
import util2 from "util";
|
|
112107
|
-
import { Readable } from "stream";
|
|
112292
|
+
import { Readable as Readable2 } from "stream";
|
|
112108
112293
|
var BOUNDARY_ALPHABET, textEncoder, CRLF, CRLF_BYTES, CRLF_BYTES_COUNT, FormDataPart, formDataToStream, formDataToStream_default;
|
|
112109
112294
|
var init_formDataToStream = __esm({
|
|
112110
112295
|
"node_modules/axios/lib/helpers/formDataToStream.js"() {
|
|
@@ -112184,7 +112369,7 @@ var init_formDataToStream = __esm({
|
|
|
112184
112369
|
computedHeaders["Content-Length"] = contentLength;
|
|
112185
112370
|
}
|
|
112186
112371
|
headersHandler && headersHandler(computedHeaders);
|
|
112187
|
-
return
|
|
112372
|
+
return Readable2.from(
|
|
112188
112373
|
(async function* () {
|
|
112189
112374
|
for (const part of parts) {
|
|
112190
112375
|
yield boundaryBytes;
|
|
@@ -228294,12 +228479,12 @@ async function startProxyInBackground(api, startupGeneration) {
|
|
|
228294
228479
|
proc.__clawrouterStartupPhase = "starting";
|
|
228295
228480
|
}
|
|
228296
228481
|
const pluginApiKey = api.pluginConfig?.apiKey;
|
|
228297
|
-
|
|
228298
|
-
|
|
228299
|
-
|
|
228300
|
-
`pluginConfig.apiKey is set but invalid (expected brk_...) \u2014 ignoring it and looking elsewhere`
|
|
228482
|
+
if (typeof pluginApiKey === "string" && pluginApiKey.trim() && !isValidApiKey(pluginApiKey)) {
|
|
228483
|
+
throw new Error(
|
|
228484
|
+
`pluginConfig.apiKey is set but is not a BlockRun key (expected brk_\u2026). Fix it or remove it \u2014 refusing to fall back to another credential.`
|
|
228301
228485
|
);
|
|
228302
228486
|
}
|
|
228487
|
+
const resolvedApiKey = typeof pluginApiKey === "string" && isValidApiKey(pluginApiKey) ? { key: pluginApiKey.trim(), source: "config" } : await resolveApiKey();
|
|
228303
228488
|
const apiKey = resolvedApiKey?.key;
|
|
228304
228489
|
const configKey = api.pluginConfig?.walletKey;
|
|
228305
228490
|
let wallet;
|
|
@@ -229485,7 +229670,18 @@ ${errText}`
|
|
|
229485
229670
|
if (!isGatewayMode()) {
|
|
229486
229671
|
if (shouldLogRegistration) {
|
|
229487
229672
|
void (async () => {
|
|
229488
|
-
|
|
229673
|
+
let keyResolution;
|
|
229674
|
+
try {
|
|
229675
|
+
keyResolution = await resolveApiKey();
|
|
229676
|
+
} catch (error) {
|
|
229677
|
+
api.logger.error(
|
|
229678
|
+
`BlockRun API key is configured but unusable: ${error instanceof Error ? error.message : String(error)}`
|
|
229679
|
+
);
|
|
229680
|
+
api.logger.error(
|
|
229681
|
+
`Not falling back to a wallet \u2014 fix the key, or run "clawrouter logout" to pay from the wallet deliberately.`
|
|
229682
|
+
);
|
|
229683
|
+
return;
|
|
229684
|
+
}
|
|
229489
229685
|
if (keyResolution) {
|
|
229490
229686
|
api.logger.info(
|
|
229491
229687
|
`Using BlockRun API key ${maskApiKey(keyResolution.key)} (from ${keyResolution.source}) \u2014 billing account credit, no wallet`
|