@blockrun/clawrouter 0.12.255 → 0.12.257

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/dist/index.js CHANGED
@@ -29310,8 +29310,8 @@ var init_parseUtil = __esm({
29310
29310
  init_errors4();
29311
29311
  init_en();
29312
29312
  makeIssue = (params) => {
29313
- const { data, path: path6, errorMaps, issueData } = params;
29314
- const fullPath = [...path6, ...issueData.path || []];
29313
+ const { data, path: path5, errorMaps, issueData } = params;
29314
+ const fullPath = [...path5, ...issueData.path || []];
29315
29315
  const fullIssue = {
29316
29316
  ...issueData,
29317
29317
  path: fullPath
@@ -29622,11 +29622,11 @@ var init_types = __esm({
29622
29622
  init_parseUtil();
29623
29623
  init_util();
29624
29624
  ParseInputLazyPath = class {
29625
- constructor(parent, value, path6, key2) {
29625
+ constructor(parent, value, path5, key2) {
29626
29626
  this._cachedPath = [];
29627
29627
  this.parent = parent;
29628
29628
  this.data = value;
29629
- this._path = path6;
29629
+ this._path = path5;
29630
29630
  this._key = key2;
29631
29631
  }
29632
29632
  get path() {
@@ -34035,6 +34035,613 @@ var init_max_tokens = __esm({
34035
34035
  }
34036
34036
  });
34037
34037
 
34038
+ // src/fs-read.ts
34039
+ import { open } from "fs/promises";
34040
+ import { openSync, readSync, closeSync, fstatSync } from "fs";
34041
+ async function readTextFile(filePath) {
34042
+ const fh = await open(filePath, "r");
34043
+ try {
34044
+ const size5 = (await fh.stat()).size;
34045
+ const buf = Buffer.alloc(size5);
34046
+ let offset = 0;
34047
+ while (offset < size5) {
34048
+ const { bytesRead } = await fh.read(buf, offset, size5 - offset, offset);
34049
+ if (bytesRead === 0) break;
34050
+ offset += bytesRead;
34051
+ }
34052
+ return buf.subarray(0, offset).toString("utf-8");
34053
+ } finally {
34054
+ await fh.close();
34055
+ }
34056
+ }
34057
+ function readTextFileSync(filePath) {
34058
+ const fd = openSync(filePath, "r");
34059
+ try {
34060
+ const size5 = fstatSync(fd).size;
34061
+ const buf = Buffer.alloc(size5);
34062
+ let offset = 0;
34063
+ while (offset < size5) {
34064
+ const bytesRead = readSync(fd, buf, offset, size5 - offset, offset);
34065
+ if (bytesRead === 0) break;
34066
+ offset += bytesRead;
34067
+ }
34068
+ return buf.subarray(0, offset).toString("utf-8");
34069
+ } finally {
34070
+ closeSync(fd);
34071
+ }
34072
+ }
34073
+ var init_fs_read = __esm({
34074
+ "src/fs-read.ts"() {
34075
+ "use strict";
34076
+ }
34077
+ });
34078
+
34079
+ // src/spend-control.ts
34080
+ import * as fs from "fs";
34081
+ import * as path from "path";
34082
+ import { homedir } from "os";
34083
+ function normalizePayee(value) {
34084
+ return EVM_ADDRESS.test(value) ? value.toLowerCase() : value;
34085
+ }
34086
+ function isAddressList(list) {
34087
+ return ADDRESS_LISTS.includes(list);
34088
+ }
34089
+ function normalizePolicyValues(list, values) {
34090
+ return isAddressList(list) ? values.map(normalizePayee) : [...values];
34091
+ }
34092
+ function isValidPolicyValues(values) {
34093
+ return Array.isArray(values) && values.every((v) => typeof v === "string" && v.length > 0);
34094
+ }
34095
+ function isPolicyList(value) {
34096
+ return POLICY_LISTS.includes(value);
34097
+ }
34098
+ function cloneLimits(limits) {
34099
+ const clone = { ...limits };
34100
+ for (const key2 of POLICY_LISTS) {
34101
+ const val = limits[key2];
34102
+ if (val !== void 0) {
34103
+ clone[key2] = [...val];
34104
+ }
34105
+ }
34106
+ return clone;
34107
+ }
34108
+ function parseQuotedAmountUsd(selected) {
34109
+ const raw = selected.amount ?? selected.maxAmountRequired;
34110
+ if (typeof raw !== "string" || !CANONICAL_AMOUNT.test(raw)) {
34111
+ return void 0;
34112
+ }
34113
+ const micros = Number(raw);
34114
+ if (!Number.isSafeInteger(micros)) {
34115
+ return void 0;
34116
+ }
34117
+ return micros / 1e6;
34118
+ }
34119
+ function assertSpendPolicyAllows(control, selected) {
34120
+ const quoted = parseQuotedAmountUsd(selected);
34121
+ if (quoted === void 0 && control.hasAmountLimits()) {
34122
+ throw new SpendPolicyError(
34123
+ `Payment quote carries no usable amount (${JSON.stringify(
34124
+ selected.amount ?? selected.maxAmountRequired
34125
+ )}); refusing to sign against a configured spend limit`
34126
+ );
34127
+ }
34128
+ const estimatedCost2 = quoted ?? 0;
34129
+ const result = control.check(estimatedCost2, {
34130
+ payTo: selected.payTo,
34131
+ network: selected.network,
34132
+ asset: selected.asset
34133
+ });
34134
+ if (!result.allowed) {
34135
+ throw new SpendPolicyError(result.reason ?? "blocked by spend policy", {
34136
+ blockedBy: result.blockedBy,
34137
+ blockedByPolicy: result.blockedByPolicy
34138
+ });
34139
+ }
34140
+ if (!control.hasAggregateLimits()) {
34141
+ return void 0;
34142
+ }
34143
+ return control.reserve(estimatedCost2);
34144
+ }
34145
+ function registerSpendPolicyHook(x402, control) {
34146
+ const reservations = /* @__PURE__ */ new WeakMap();
34147
+ x402.onBeforePaymentCreation(async (ctx) => {
34148
+ const selected = ctx.selectedRequirements;
34149
+ const reservationId = assertSpendPolicyAllows(control, selected);
34150
+ if (reservationId !== void 0) {
34151
+ reservations.set(ctx.selectedRequirements, reservationId);
34152
+ }
34153
+ });
34154
+ x402.onAfterPaymentCreation(async (ctx) => {
34155
+ const key2 = ctx.selectedRequirements;
34156
+ const id2 = reservations.get(key2);
34157
+ if (id2 !== void 0) {
34158
+ reservations.delete(key2);
34159
+ control.settleReservation(id2, { action: "x402 payment" });
34160
+ }
34161
+ });
34162
+ x402.onPaymentCreationFailure(async (ctx) => {
34163
+ const key2 = ctx.selectedRequirements;
34164
+ const id2 = reservations.get(key2);
34165
+ if (id2 !== void 0) {
34166
+ reservations.delete(key2);
34167
+ control.releaseReservation(id2);
34168
+ }
34169
+ });
34170
+ }
34171
+ function formatDuration(seconds) {
34172
+ if (seconds < 60) {
34173
+ return `${seconds}s`;
34174
+ } else if (seconds < 3600) {
34175
+ const mins = Math.ceil(seconds / 60);
34176
+ return `${mins} min`;
34177
+ } else {
34178
+ const hours = Math.floor(seconds / 3600);
34179
+ const mins = Math.ceil(seconds % 3600 / 60);
34180
+ return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;
34181
+ }
34182
+ }
34183
+ var WALLET_DIR, HOUR_MS, DAY_MS, CAIP2_BASE, CAIP2_SOLANA_MAINNET, POLICY_LISTS, ADDRESS_LISTS, EVM_ADDRESS, MalformedSpendPolicyError, FileSpendControlStorage, InMemorySpendControlStorage, RESERVATION_TTL_MS, SpendControl, SpendPolicyError, CANONICAL_AMOUNT;
34184
+ var init_spend_control = __esm({
34185
+ "src/spend-control.ts"() {
34186
+ "use strict";
34187
+ init_fs_read();
34188
+ WALLET_DIR = path.join(homedir(), ".openclaw", "blockrun");
34189
+ HOUR_MS = 60 * 60 * 1e3;
34190
+ DAY_MS = 24 * HOUR_MS;
34191
+ CAIP2_BASE = "eip155:8453";
34192
+ CAIP2_SOLANA_MAINNET = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d";
34193
+ POLICY_LISTS = [
34194
+ "allowedPayees",
34195
+ "blockedPayees",
34196
+ "allowedNetworks",
34197
+ "allowedAssets"
34198
+ ];
34199
+ ADDRESS_LISTS = ["allowedPayees", "blockedPayees", "allowedAssets"];
34200
+ EVM_ADDRESS = /^0x[0-9a-fA-F]{40}$/;
34201
+ MalformedSpendPolicyError = class extends Error {
34202
+ constructor(key2) {
34203
+ super(
34204
+ `[ClawRouter] refusing to load spending.json: ${key2} is malformed; a corrupted policy file must not widen what the agent may pay`
34205
+ );
34206
+ this.name = "MalformedSpendPolicyError";
34207
+ }
34208
+ };
34209
+ FileSpendControlStorage = class {
34210
+ spendingFile;
34211
+ constructor() {
34212
+ this.spendingFile = path.join(WALLET_DIR, "spending.json");
34213
+ }
34214
+ load() {
34215
+ try {
34216
+ if (fs.existsSync(this.spendingFile)) {
34217
+ const data = JSON.parse(readTextFileSync(this.spendingFile));
34218
+ const rawLimits = data.limits ?? {};
34219
+ const rawHistory = data.history ?? [];
34220
+ const limits = {};
34221
+ for (const key2 of ["perRequest", "hourly", "daily", "session"]) {
34222
+ const val = rawLimits[key2];
34223
+ if (typeof val === "number" && val > 0 && Number.isFinite(val)) {
34224
+ limits[key2] = val;
34225
+ }
34226
+ }
34227
+ for (const key2 of POLICY_LISTS) {
34228
+ if (!Object.prototype.hasOwnProperty.call(rawLimits, key2)) continue;
34229
+ const val = rawLimits[key2];
34230
+ if (!isValidPolicyValues(val)) {
34231
+ throw new MalformedSpendPolicyError(key2);
34232
+ }
34233
+ if (val.length === 0) continue;
34234
+ limits[key2] = normalizePolicyValues(key2, val);
34235
+ }
34236
+ const history = [];
34237
+ if (Array.isArray(rawHistory)) {
34238
+ for (const r2 of rawHistory) {
34239
+ if (typeof r2?.timestamp === "number" && typeof r2?.amount === "number" && Number.isFinite(r2.timestamp) && Number.isFinite(r2.amount) && r2.amount >= 0) {
34240
+ history.push({
34241
+ timestamp: r2.timestamp,
34242
+ amount: r2.amount,
34243
+ model: typeof r2.model === "string" ? r2.model : void 0,
34244
+ action: typeof r2.action === "string" ? r2.action : void 0
34245
+ });
34246
+ }
34247
+ }
34248
+ }
34249
+ return { limits, history };
34250
+ }
34251
+ } catch (err) {
34252
+ if (err instanceof MalformedSpendPolicyError) {
34253
+ throw err;
34254
+ }
34255
+ console.error(
34256
+ `[ClawRouter] Failed to load spending data, starting fresh (any configured spend policy is NOT in effect until this file is repaired): ${err}`
34257
+ );
34258
+ }
34259
+ return null;
34260
+ }
34261
+ save(data) {
34262
+ try {
34263
+ if (!fs.existsSync(WALLET_DIR)) {
34264
+ fs.mkdirSync(WALLET_DIR, { recursive: true, mode: 448 });
34265
+ }
34266
+ const tmp = `${this.spendingFile}.${process.pid}.tmp`;
34267
+ fs.writeFileSync(tmp, JSON.stringify(data, null, 2), { mode: 384 });
34268
+ fs.renameSync(tmp, this.spendingFile);
34269
+ } catch (err) {
34270
+ console.error(`[ClawRouter] Failed to save spending data: ${err}`);
34271
+ }
34272
+ }
34273
+ /**
34274
+ * Persist history while leaving the stored limits exactly as they are on
34275
+ * disk. Recording spend must not rewrite policy: the proxy reads limits once
34276
+ * at startup, so writing its in-memory copy back on every payment would
34277
+ * erase an operator's hand-edit to spending.json seconds after they made it.
34278
+ */
34279
+ saveHistory(history) {
34280
+ let storedLimits = {};
34281
+ try {
34282
+ const current = this.load();
34283
+ if (current) storedLimits = current.limits;
34284
+ } catch {
34285
+ return;
34286
+ }
34287
+ this.save({ limits: storedLimits, history });
34288
+ }
34289
+ };
34290
+ InMemorySpendControlStorage = class {
34291
+ data = null;
34292
+ load() {
34293
+ return this.data ? {
34294
+ limits: cloneLimits(this.data.limits),
34295
+ history: this.data.history.map((r2) => ({ ...r2 }))
34296
+ } : null;
34297
+ }
34298
+ save(data) {
34299
+ this.data = {
34300
+ limits: cloneLimits(data.limits),
34301
+ history: data.history.map((r2) => ({ ...r2 }))
34302
+ };
34303
+ }
34304
+ };
34305
+ RESERVATION_TTL_MS = 2 * 60 * 1e3;
34306
+ SpendControl = class {
34307
+ limits = {};
34308
+ history = [];
34309
+ sessionSpent = 0;
34310
+ sessionCalls = 0;
34311
+ pending = /* @__PURE__ */ new Map();
34312
+ reservationSeq = 0;
34313
+ /** Limits we loaded and have not changed; history-only saves must not clobber operator edits. */
34314
+ limitsDirty = false;
34315
+ /** Set when spending.json held an unusable policy list: refuse every payment. */
34316
+ policyFileBroken;
34317
+ storage;
34318
+ now;
34319
+ constructor(options) {
34320
+ this.storage = options?.storage ?? new FileSpendControlStorage();
34321
+ this.now = options?.now ?? (() => Date.now());
34322
+ this.load();
34323
+ }
34324
+ setLimit(window2, amount) {
34325
+ if (!Number.isFinite(amount) || amount <= 0) {
34326
+ throw new Error("Limit must be a finite positive number");
34327
+ }
34328
+ this.limits[window2] = amount;
34329
+ this.limitsDirty = true;
34330
+ this.save();
34331
+ }
34332
+ clearLimit(window2) {
34333
+ delete this.limits[window2];
34334
+ this.limitsDirty = true;
34335
+ this.save();
34336
+ }
34337
+ setPolicy(list, values) {
34338
+ if (!isPolicyList(list)) {
34339
+ throw new Error(`Unknown policy list: ${String(list)}`);
34340
+ }
34341
+ if (!isValidPolicyValues(values) || values.length === 0) {
34342
+ throw new Error("Policy list must be a non-empty array of non-empty strings");
34343
+ }
34344
+ this.limits[list] = normalizePolicyValues(list, values);
34345
+ this.limitsDirty = true;
34346
+ this.save();
34347
+ }
34348
+ clearPolicy(list) {
34349
+ if (!isPolicyList(list)) {
34350
+ throw new Error(`Unknown policy list: ${String(list)}`);
34351
+ }
34352
+ delete this.limits[list];
34353
+ this.limitsDirty = true;
34354
+ this.save();
34355
+ }
34356
+ getLimits() {
34357
+ return cloneLimits(this.limits);
34358
+ }
34359
+ check(estimatedCost2, counterparty) {
34360
+ if (this.policyFileBroken !== void 0) {
34361
+ return {
34362
+ allowed: false,
34363
+ reason: `Spend policy is unreadable, refusing all payments: ${this.policyFileBroken}`
34364
+ };
34365
+ }
34366
+ const payeePolicySet = this.limits.blockedPayees && this.limits.blockedPayees.length > 0 || this.limits.allowedPayees && this.limits.allowedPayees.length > 0;
34367
+ if (payeePolicySet) {
34368
+ if (counterparty?.payTo === void 0) {
34369
+ return {
34370
+ allowed: false,
34371
+ blockedByPolicy: this.limits.blockedPayees?.length ? "blockedPayees" : "allowedPayees",
34372
+ reason: "Payee policy is configured but no payTo was provided to check()"
34373
+ };
34374
+ }
34375
+ const payTo = normalizePayee(counterparty.payTo);
34376
+ if (this.limits.blockedPayees?.includes(payTo)) {
34377
+ return {
34378
+ allowed: false,
34379
+ blockedByPolicy: "blockedPayees",
34380
+ reason: `Payee is blocked by policy: ${counterparty.payTo}`
34381
+ };
34382
+ }
34383
+ if (this.limits.allowedPayees && this.limits.allowedPayees.length > 0 && !this.limits.allowedPayees.includes(payTo)) {
34384
+ return {
34385
+ allowed: false,
34386
+ blockedByPolicy: "allowedPayees",
34387
+ reason: `Payee is not in the configured allowlist: ${counterparty.payTo}`
34388
+ };
34389
+ }
34390
+ }
34391
+ if (this.limits.allowedNetworks && this.limits.allowedNetworks.length > 0) {
34392
+ if (counterparty?.network === void 0) {
34393
+ return {
34394
+ allowed: false,
34395
+ blockedByPolicy: "allowedNetworks",
34396
+ reason: "Network policy is configured but no network was provided to check()"
34397
+ };
34398
+ }
34399
+ if (!this.limits.allowedNetworks.includes(counterparty.network)) {
34400
+ return {
34401
+ allowed: false,
34402
+ blockedByPolicy: "allowedNetworks",
34403
+ reason: `Network is not in the configured allowlist: ${counterparty.network}`
34404
+ };
34405
+ }
34406
+ }
34407
+ if (this.limits.allowedAssets && this.limits.allowedAssets.length > 0) {
34408
+ if (counterparty?.asset === void 0) {
34409
+ return {
34410
+ allowed: false,
34411
+ blockedByPolicy: "allowedAssets",
34412
+ reason: "Asset policy is configured but no asset was provided to check()"
34413
+ };
34414
+ }
34415
+ if (!this.limits.allowedAssets.includes(normalizePayee(counterparty.asset))) {
34416
+ return {
34417
+ allowed: false,
34418
+ blockedByPolicy: "allowedAssets",
34419
+ reason: `Asset is not in the configured allowlist: ${counterparty.asset}`
34420
+ };
34421
+ }
34422
+ }
34423
+ const now2 = this.now();
34424
+ if (this.limits.perRequest !== void 0) {
34425
+ if (estimatedCost2 > this.limits.perRequest) {
34426
+ return {
34427
+ allowed: false,
34428
+ blockedBy: "perRequest",
34429
+ remaining: this.limits.perRequest,
34430
+ reason: `Per-request limit exceeded: $${estimatedCost2.toFixed(4)} > $${this.limits.perRequest.toFixed(2)} max`
34431
+ };
34432
+ }
34433
+ }
34434
+ if (this.limits.hourly !== void 0) {
34435
+ const hourlySpent = this.getSpendingInWindow(now2 - HOUR_MS, now2);
34436
+ const remaining = this.limits.hourly - hourlySpent;
34437
+ if (estimatedCost2 > remaining) {
34438
+ const oldestInWindow = this.history.find((r2) => r2.timestamp >= now2 - HOUR_MS);
34439
+ const resetIn = oldestInWindow ? Math.ceil((oldestInWindow.timestamp + HOUR_MS - now2) / 1e3) : 0;
34440
+ return {
34441
+ allowed: false,
34442
+ blockedBy: "hourly",
34443
+ remaining,
34444
+ reason: `Hourly limit exceeded: $${(hourlySpent + estimatedCost2).toFixed(2)} > $${this.limits.hourly.toFixed(2)} max`,
34445
+ resetIn
34446
+ };
34447
+ }
34448
+ }
34449
+ if (this.limits.daily !== void 0) {
34450
+ const dailySpent = this.getSpendingInWindow(now2 - DAY_MS, now2);
34451
+ const remaining = this.limits.daily - dailySpent;
34452
+ if (estimatedCost2 > remaining) {
34453
+ const oldestInWindow = this.history.find((r2) => r2.timestamp >= now2 - DAY_MS);
34454
+ const resetIn = oldestInWindow ? Math.ceil((oldestInWindow.timestamp + DAY_MS - now2) / 1e3) : 0;
34455
+ return {
34456
+ allowed: false,
34457
+ blockedBy: "daily",
34458
+ remaining,
34459
+ reason: `Daily limit exceeded: $${(dailySpent + estimatedCost2).toFixed(2)} > $${this.limits.daily.toFixed(2)} max`,
34460
+ resetIn
34461
+ };
34462
+ }
34463
+ }
34464
+ if (this.limits.session !== void 0) {
34465
+ const sessionSpent = this.sessionSpent + this.pendingTotal();
34466
+ const remaining = this.limits.session - sessionSpent;
34467
+ if (estimatedCost2 > remaining) {
34468
+ return {
34469
+ allowed: false,
34470
+ blockedBy: "session",
34471
+ remaining,
34472
+ reason: `Session limit exceeded: $${(sessionSpent + estimatedCost2).toFixed(2)} > $${this.limits.session.toFixed(2)} max`
34473
+ };
34474
+ }
34475
+ }
34476
+ return { allowed: true };
34477
+ }
34478
+ record(amount, metadata) {
34479
+ if (!Number.isFinite(amount) || amount < 0) {
34480
+ throw new Error("Record amount must be a non-negative finite number");
34481
+ }
34482
+ const record = {
34483
+ timestamp: this.now(),
34484
+ amount,
34485
+ model: metadata?.model,
34486
+ action: metadata?.action
34487
+ };
34488
+ this.history.push(record);
34489
+ this.sessionSpent += amount;
34490
+ this.sessionCalls += 1;
34491
+ this.cleanup();
34492
+ this.save();
34493
+ }
34494
+ /** True when any window that this module can compare an amount against is set. */
34495
+ hasAmountLimits() {
34496
+ return this.limits.perRequest !== void 0 || this.limits.hourly !== void 0 || this.limits.daily !== void 0 || this.limits.session !== void 0;
34497
+ }
34498
+ /** True when a window spans more than one request, so reservations matter. */
34499
+ hasAggregateLimits() {
34500
+ return this.limits.hourly !== void 0 || this.limits.daily !== void 0 || this.limits.session !== void 0;
34501
+ }
34502
+ /**
34503
+ * Hold `amount` against the aggregate windows before a payment is signed.
34504
+ *
34505
+ * Reservations live in memory only and are never persisted: an unsettled
34506
+ * reservation is not spend, and writing it to disk is what made a failed
34507
+ * signer permanently consume budget. They expire on their own so a caller
34508
+ * that never settles or releases (process killed mid-payment, a transport
34509
+ * that hangs past the payment timeout) cannot wedge the window shut.
34510
+ */
34511
+ reserve(amount) {
34512
+ if (!Number.isFinite(amount) || amount < 0) {
34513
+ throw new Error("Reservation amount must be a non-negative finite number");
34514
+ }
34515
+ const id2 = `${this.now()}-${this.reservationSeq += 1}`;
34516
+ this.pending.set(id2, { amount, expiresAt: this.now() + RESERVATION_TTL_MS });
34517
+ return id2;
34518
+ }
34519
+ /** Convert a reservation into recorded spend (the payment was signed). */
34520
+ settleReservation(id2, metadata) {
34521
+ const held = this.pending.get(id2);
34522
+ if (!held) return;
34523
+ this.pending.delete(id2);
34524
+ this.record(held.amount, metadata);
34525
+ }
34526
+ /** Drop a reservation without recording spend (the payment was never signed). */
34527
+ releaseReservation(id2) {
34528
+ this.pending.delete(id2);
34529
+ }
34530
+ /** Total currently held but not yet settled. */
34531
+ pendingTotal() {
34532
+ this.expireReservations();
34533
+ let total = 0;
34534
+ for (const held of this.pending.values()) {
34535
+ total += held.amount;
34536
+ }
34537
+ return total;
34538
+ }
34539
+ expireReservations() {
34540
+ const now2 = this.now();
34541
+ for (const [id2, held] of this.pending) {
34542
+ if (held.expiresAt <= now2) {
34543
+ this.pending.delete(id2);
34544
+ }
34545
+ }
34546
+ }
34547
+ getSpendingInWindow(from15, to) {
34548
+ const recorded = this.history.filter((r2) => r2.timestamp >= from15 && r2.timestamp <= to).reduce((sum, r2) => sum + r2.amount, 0);
34549
+ return recorded + (to >= this.now() ? this.pendingTotal() : 0);
34550
+ }
34551
+ getSpending(window2) {
34552
+ const now2 = this.now();
34553
+ switch (window2) {
34554
+ case "hourly":
34555
+ return this.getSpendingInWindow(now2 - HOUR_MS, now2);
34556
+ case "daily":
34557
+ return this.getSpendingInWindow(now2 - DAY_MS, now2);
34558
+ case "session":
34559
+ return this.sessionSpent + this.pendingTotal();
34560
+ }
34561
+ }
34562
+ getRemaining(window2) {
34563
+ const limit = this.limits[window2];
34564
+ if (limit === void 0) return null;
34565
+ return Math.max(0, limit - this.getSpending(window2));
34566
+ }
34567
+ getStatus() {
34568
+ const now2 = this.now();
34569
+ const hourlySpent = this.getSpendingInWindow(now2 - HOUR_MS, now2);
34570
+ const dailySpent = this.getSpendingInWindow(now2 - DAY_MS, now2);
34571
+ return {
34572
+ limits: cloneLimits(this.limits),
34573
+ spending: {
34574
+ hourly: hourlySpent,
34575
+ daily: dailySpent,
34576
+ session: this.sessionSpent
34577
+ },
34578
+ remaining: {
34579
+ hourly: this.limits.hourly !== void 0 ? this.limits.hourly - hourlySpent : null,
34580
+ daily: this.limits.daily !== void 0 ? this.limits.daily - dailySpent : null,
34581
+ session: this.limits.session !== void 0 ? this.limits.session - (this.sessionSpent + this.pendingTotal()) : null
34582
+ },
34583
+ calls: this.sessionCalls
34584
+ };
34585
+ }
34586
+ getHistory(limit) {
34587
+ const records = [...this.history].reverse();
34588
+ return limit ? records.slice(0, limit) : records;
34589
+ }
34590
+ resetSession() {
34591
+ this.sessionSpent = 0;
34592
+ this.sessionCalls = 0;
34593
+ }
34594
+ cleanup() {
34595
+ const cutoff = this.now() - DAY_MS;
34596
+ this.history = this.history.filter((r2) => r2.timestamp >= cutoff);
34597
+ }
34598
+ save() {
34599
+ if (this.policyFileBroken !== void 0) {
34600
+ return;
34601
+ }
34602
+ if (!this.limitsDirty && this.storage.saveHistory) {
34603
+ this.storage.saveHistory([...this.history]);
34604
+ return;
34605
+ }
34606
+ this.storage.save({
34607
+ limits: cloneLimits(this.limits),
34608
+ history: [...this.history]
34609
+ });
34610
+ }
34611
+ load() {
34612
+ let data;
34613
+ try {
34614
+ data = this.storage.load();
34615
+ } catch (err) {
34616
+ if (!(err instanceof MalformedSpendPolicyError)) throw err;
34617
+ this.policyFileBroken = err.message;
34618
+ console.error(`[ClawRouter] ${err.message}`);
34619
+ console.error(
34620
+ "[ClawRouter] All paid requests will be refused until spending.json is repaired. Free models are unaffected."
34621
+ );
34622
+ return;
34623
+ }
34624
+ if (data) {
34625
+ this.limits = cloneLimits(data.limits);
34626
+ this.history = data.history;
34627
+ this.cleanup();
34628
+ }
34629
+ }
34630
+ };
34631
+ SpendPolicyError = class extends Error {
34632
+ blockedBy;
34633
+ blockedByPolicy;
34634
+ constructor(reason, blocked) {
34635
+ super(`Payment creation aborted: ${reason}`);
34636
+ this.name = "SpendPolicyError";
34637
+ this.blockedBy = blocked?.blockedBy;
34638
+ this.blockedByPolicy = blocked?.blockedByPolicy;
34639
+ }
34640
+ };
34641
+ CANONICAL_AMOUNT = /^\d+$/;
34642
+ }
34643
+ });
34644
+
34038
34645
  // src/payment-preauth.ts
34039
34646
  function createPayFetchWithPreAuth(baseFetch, client, ttlMs = DEFAULT_TTL_MS, options) {
34040
34647
  const httpClient = new x402HTTPClient(client);
@@ -34079,8 +34686,11 @@ function createPayFetchWithPreAuth(baseFetch, client, ttlMs = DEFAULT_TTL_MS, op
34079
34686
  return response2;
34080
34687
  }
34081
34688
  cache2.delete(cacheKey2);
34082
- } catch {
34689
+ } catch (err) {
34083
34690
  cache2.delete(cacheKey2);
34691
+ if (err instanceof SpendPolicyError) {
34692
+ throw err;
34693
+ }
34084
34694
  }
34085
34695
  }
34086
34696
  const clonedRequest = request2.clone();
@@ -34124,6 +34734,7 @@ var init_payment_preauth = __esm({
34124
34734
  "use strict";
34125
34735
  init_esm4();
34126
34736
  init_max_tokens();
34737
+ init_spend_control();
34127
34738
  DEFAULT_TTL_MS = 36e5;
34128
34739
  }
34129
34740
  });
@@ -38823,8 +39434,8 @@ var init_router = __esm({
38823
39434
 
38824
39435
  // src/logger.ts
38825
39436
  import { appendFile, mkdir } from "fs/promises";
38826
- import { join as join2 } from "path";
38827
- import { homedir } from "os";
39437
+ import { join as join3 } from "path";
39438
+ import { homedir as homedir2 } from "os";
38828
39439
  async function ensureDir() {
38829
39440
  if (dirReady) return;
38830
39441
  await mkdir(LOG_DIR, { recursive: true });
@@ -38834,7 +39445,7 @@ async function logUsage(entry) {
38834
39445
  try {
38835
39446
  await ensureDir();
38836
39447
  const date = entry.timestamp.slice(0, 10);
38837
- const file = join2(LOG_DIR, `usage-${date}.jsonl`);
39448
+ const file = join3(LOG_DIR, `usage-${date}.jsonl`);
38838
39449
  await appendFile(file, JSON.stringify(entry) + "\n");
38839
39450
  } catch {
38840
39451
  }
@@ -38843,56 +39454,15 @@ var LOG_DIR, dirReady;
38843
39454
  var init_logger = __esm({
38844
39455
  "src/logger.ts"() {
38845
39456
  "use strict";
38846
- LOG_DIR = join2(homedir(), ".openclaw", "blockrun", "logs");
39457
+ LOG_DIR = join3(homedir2(), ".openclaw", "blockrun", "logs");
38847
39458
  dirReady = false;
38848
39459
  }
38849
39460
  });
38850
39461
 
38851
- // src/fs-read.ts
38852
- import { open } from "fs/promises";
38853
- import { openSync, readSync, closeSync, fstatSync } from "fs";
38854
- async function readTextFile(filePath) {
38855
- const fh = await open(filePath, "r");
38856
- try {
38857
- const size5 = (await fh.stat()).size;
38858
- const buf = Buffer.alloc(size5);
38859
- let offset = 0;
38860
- while (offset < size5) {
38861
- const { bytesRead } = await fh.read(buf, offset, size5 - offset, offset);
38862
- if (bytesRead === 0) break;
38863
- offset += bytesRead;
38864
- }
38865
- return buf.subarray(0, offset).toString("utf-8");
38866
- } finally {
38867
- await fh.close();
38868
- }
38869
- }
38870
- function readTextFileSync(filePath) {
38871
- const fd = openSync(filePath, "r");
38872
- try {
38873
- const size5 = fstatSync(fd).size;
38874
- const buf = Buffer.alloc(size5);
38875
- let offset = 0;
38876
- while (offset < size5) {
38877
- const bytesRead = readSync(fd, buf, offset, size5 - offset, offset);
38878
- if (bytesRead === 0) break;
38879
- offset += bytesRead;
38880
- }
38881
- return buf.subarray(0, offset).toString("utf-8");
38882
- } finally {
38883
- closeSync(fd);
38884
- }
38885
- }
38886
- var init_fs_read = __esm({
38887
- "src/fs-read.ts"() {
38888
- "use strict";
38889
- }
38890
- });
38891
-
38892
39462
  // src/version.ts
38893
39463
  import { createRequire } from "module";
38894
39464
  import { fileURLToPath } from "url";
38895
- import { dirname, join as join3 } from "path";
39465
+ import { dirname, join as join4 } from "path";
38896
39466
  function clientTag() {
38897
39467
  const raw = (process.env.CLAWROUTER_CLIENT ?? "").trim();
38898
39468
  if (!raw) return "";
@@ -38906,7 +39476,7 @@ var init_version4 = __esm({
38906
39476
  __filename2 = fileURLToPath(import.meta.url);
38907
39477
  __dirname = dirname(__filename2);
38908
39478
  require2 = createRequire(import.meta.url);
38909
- pkg = require2(join3(__dirname, "..", "package.json"));
39479
+ pkg = require2(join4(__dirname, "..", "package.json"));
38910
39480
  VERSION = pkg.version;
38911
39481
  USER_AGENT = `clawrouter/${VERSION}${clientTag()}`;
38912
39482
  }
@@ -38914,8 +39484,8 @@ var init_version4 = __esm({
38914
39484
 
38915
39485
  // src/stats.ts
38916
39486
  import { readdir, unlink } from "fs/promises";
38917
- import { join as join4 } from "path";
38918
- import { homedir as homedir2 } from "os";
39487
+ import { join as join5 } from "path";
39488
+ import { homedir as homedir3 } from "os";
38919
39489
  async function parseLogFile(filePath) {
38920
39490
  try {
38921
39491
  const content = await readTextFile(filePath);
@@ -38987,7 +39557,7 @@ async function getStats(days = 7) {
38987
39557
  let totalLatency = 0;
38988
39558
  for (const file of filesToRead) {
38989
39559
  const date = file.replace("usage-", "").replace(".jsonl", "");
38990
- const filePath = join4(LOG_DIR2, file);
39560
+ const filePath = join5(LOG_DIR2, file);
38991
39561
  const entries = await parseLogFile(filePath);
38992
39562
  if (entries.length === 0) continue;
38993
39563
  const dayStats = aggregateDay(date, entries);
@@ -39105,7 +39675,7 @@ async function clearStats() {
39105
39675
  try {
39106
39676
  const files = await readdir(LOG_DIR2);
39107
39677
  const logFiles = files.filter((f) => f.startsWith("usage-") && f.endsWith(".jsonl"));
39108
- await Promise.all(logFiles.map((f) => unlink(join4(LOG_DIR2, f))));
39678
+ await Promise.all(logFiles.map((f) => unlink(join5(LOG_DIR2, f))));
39109
39679
  return { deletedFiles: logFiles.length };
39110
39680
  } catch {
39111
39681
  return { deletedFiles: 0 };
@@ -39117,7 +39687,27 @@ var init_stats = __esm({
39117
39687
  "use strict";
39118
39688
  init_fs_read();
39119
39689
  init_version4();
39120
- LOG_DIR2 = join4(homedir2(), ".openclaw", "blockrun", "logs");
39690
+ LOG_DIR2 = join5(homedir3(), ".openclaw", "blockrun", "logs");
39691
+ }
39692
+ });
39693
+
39694
+ // src/timestamp-strip.ts
39695
+ function stripLeadingTextBlockTimestamp(blocks) {
39696
+ let stripped = false;
39697
+ return blocks.map((block) => {
39698
+ if (!stripped && block !== null && typeof block === "object" && block.type === "text" && typeof block.text === "string") {
39699
+ stripped = true;
39700
+ const b = block;
39701
+ return { ...b, text: b.text.replace(TIMESTAMP_PATTERN, "") };
39702
+ }
39703
+ return block;
39704
+ });
39705
+ }
39706
+ var TIMESTAMP_PATTERN;
39707
+ var init_timestamp_strip = __esm({
39708
+ "src/timestamp-strip.ts"() {
39709
+ "use strict";
39710
+ TIMESTAMP_PATTERN = /^\[\w{3}\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}\s+\w+\]\s*/;
39121
39711
  }
39122
39712
  });
39123
39713
 
@@ -39147,19 +39737,21 @@ function stripTimestamps(obj) {
39147
39737
  for (const [key2, value] of Object.entries(obj)) {
39148
39738
  if (key2 === "content" && typeof value === "string") {
39149
39739
  result[key2] = value.replace(TIMESTAMP_PATTERN, "");
39740
+ } else if (key2 === "content" && Array.isArray(value)) {
39741
+ result[key2] = stripLeadingTextBlockTimestamp(value.map(stripTimestamps));
39150
39742
  } else {
39151
39743
  result[key2] = stripTimestamps(value);
39152
39744
  }
39153
39745
  }
39154
39746
  return result;
39155
39747
  }
39156
- var DEFAULT_TTL_MS2, MAX_BODY_SIZE, TIMESTAMP_PATTERN, RequestDeduplicator;
39748
+ var DEFAULT_TTL_MS2, MAX_BODY_SIZE, RequestDeduplicator;
39157
39749
  var init_dedup = __esm({
39158
39750
  "src/dedup.ts"() {
39159
39751
  "use strict";
39752
+ init_timestamp_strip();
39160
39753
  DEFAULT_TTL_MS2 = 3e4;
39161
39754
  MAX_BODY_SIZE = 1048576;
39162
- TIMESTAMP_PATTERN = /^\[\w{3}\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}\s+\w+\]\s*/;
39163
39755
  RequestDeduplicator = class {
39164
39756
  inflight = /* @__PURE__ */ new Map();
39165
39757
  completed = /* @__PURE__ */ new Map();
@@ -39277,7 +39869,10 @@ function normalizeForCache(obj) {
39277
39869
  if (typeof msg === "object" && msg !== null) {
39278
39870
  const m = msg;
39279
39871
  if (typeof m.content === "string") {
39280
- return { ...m, content: m.content.replace(TIMESTAMP_PATTERN2, "") };
39872
+ return { ...m, content: m.content.replace(TIMESTAMP_PATTERN, "") };
39873
+ }
39874
+ if (Array.isArray(m.content)) {
39875
+ return { ...m, content: stripLeadingTextBlockTimestamp(m.content) };
39281
39876
  }
39282
39877
  }
39283
39878
  return msg;
@@ -39288,10 +39883,11 @@ function normalizeForCache(obj) {
39288
39883
  }
39289
39884
  return result;
39290
39885
  }
39291
- var DEFAULT_CONFIG, TIMESTAMP_PATTERN2, ResponseCache;
39886
+ var DEFAULT_CONFIG, ResponseCache;
39292
39887
  var init_response_cache = __esm({
39293
39888
  "src/response-cache.ts"() {
39294
39889
  "use strict";
39890
+ init_timestamp_strip();
39295
39891
  DEFAULT_CONFIG = {
39296
39892
  maxSize: 200,
39297
39893
  defaultTTL: 600,
@@ -39299,7 +39895,6 @@ var init_response_cache = __esm({
39299
39895
  // 1MB
39300
39896
  enabled: true
39301
39897
  };
39302
- TIMESTAMP_PATTERN2 = /^\[\w{3}\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}\s+\w+\]\s*/;
39303
39898
  ResponseCache = class {
39304
39899
  cache = /* @__PURE__ */ new Map();
39305
39900
  expirationHeap = [];
@@ -42911,7 +43506,7 @@ function alphabet2(letters) {
42911
43506
  };
42912
43507
  }
42913
43508
  // @__NO_SIDE_EFFECTS__
42914
- function join5(separator = "") {
43509
+ function join6(separator = "") {
42915
43510
  astr2("join", separator);
42916
43511
  return {
42917
43512
  encode: (from15) => {
@@ -43021,7 +43616,7 @@ var genBase58, base58, createBase58check;
43021
43616
  var init_base3 = __esm({
43022
43617
  "node_modules/@scure/base/index.js"() {
43023
43618
  "use strict";
43024
- genBase58 = /* @__NO_SIDE_EFFECTS__ */ (abc) => /* @__PURE__ */ chain2(/* @__PURE__ */ radix3(58), /* @__PURE__ */ alphabet2(abc), /* @__PURE__ */ join5(""));
43619
+ genBase58 = /* @__NO_SIDE_EFFECTS__ */ (abc) => /* @__PURE__ */ chain2(/* @__PURE__ */ radix3(58), /* @__PURE__ */ alphabet2(abc), /* @__PURE__ */ join6(""));
43025
43620
  base58 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ genBase58("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"));
43026
43621
  createBase58check = (sha25610) => {
43027
43622
  afn2(sha25610);
@@ -43170,14 +43765,14 @@ var init_bip32 = __esm({
43170
43765
  }
43171
43766
  this.pubHash = hash160(this._publicKey);
43172
43767
  }
43173
- derive(path6) {
43174
- if (!/^[mM]'?/.test(path6)) {
43768
+ derive(path5) {
43769
+ if (!/^[mM]'?/.test(path5)) {
43175
43770
  throw new Error('Path must start with "m" or "M"');
43176
43771
  }
43177
- if (/^[mM]'?$/.test(path6)) {
43772
+ if (/^[mM]'?$/.test(path5)) {
43178
43773
  return this;
43179
43774
  }
43180
- const parts = path6.replace(/^[mM]'?\//, "").split("/");
43775
+ const parts = path5.replace(/^[mM]'?\//, "").split("/");
43181
43776
  let child = this;
43182
43777
  for (const c of parts) {
43183
43778
  const m = /^(\d+)('?)$/.exec(c);
@@ -51467,14 +52062,14 @@ function createSolanaJsonRpcIntegerOverflowError(methodName, keyPath, value) {
51467
52062
  } else {
51468
52063
  argumentLabel = `\`${keyPath[0].toString()}\``;
51469
52064
  }
51470
- const path6 = keyPath.length > 1 ? keyPath.slice(1).map((pathPart) => typeof pathPart === "number" ? `[${pathPart}]` : pathPart).join(".") : void 0;
52065
+ const path5 = keyPath.length > 1 ? keyPath.slice(1).map((pathPart) => typeof pathPart === "number" ? `[${pathPart}]` : pathPart).join(".") : void 0;
51471
52066
  const error = new SolanaError(SOLANA_ERROR__RPC__INTEGER_OVERFLOW, {
51472
52067
  argumentLabel,
51473
52068
  keyPath,
51474
52069
  methodName,
51475
- optionalPathLabel: path6 ? ` at path \`${path6}\`` : "",
52070
+ optionalPathLabel: path5 ? ` at path \`${path5}\`` : "",
51476
52071
  value,
51477
- ...path6 !== void 0 ? { path: path6 } : void 0
52072
+ ...path5 !== void 0 ? { path: path5 } : void 0
51478
52073
  });
51479
52074
  safeCaptureStackTrace(error, createSolanaJsonRpcIntegerOverflowError);
51480
52075
  return error;
@@ -56138,14 +56733,14 @@ function createSolanaJsonRpcIntegerOverflowError2(methodName, keyPath, value) {
56138
56733
  } else {
56139
56734
  argumentLabel = `\`${keyPath[0].toString()}\``;
56140
56735
  }
56141
- const path6 = keyPath.length > 1 ? keyPath.slice(1).map((pathPart) => typeof pathPart === "number" ? `[${pathPart}]` : pathPart).join(".") : void 0;
56736
+ const path5 = keyPath.length > 1 ? keyPath.slice(1).map((pathPart) => typeof pathPart === "number" ? `[${pathPart}]` : pathPart).join(".") : void 0;
56142
56737
  const error = new SolanaError(SOLANA_ERROR__RPC__INTEGER_OVERFLOW, {
56143
56738
  argumentLabel,
56144
56739
  keyPath,
56145
56740
  methodName,
56146
- optionalPathLabel: path6 ? ` at path \`${path6}\`` : "",
56741
+ optionalPathLabel: path5 ? ` at path \`${path5}\`` : "",
56147
56742
  value,
56148
- ...path6 !== void 0 ? { path: path6 } : void 0
56743
+ ...path5 !== void 0 ? { path: path5 } : void 0
56149
56744
  });
56150
56745
  safeCaptureStackTrace(error, createSolanaJsonRpcIntegerOverflowError2);
56151
56746
  return error;
@@ -58213,8 +58808,8 @@ var init_wallet2 = __esm({
58213
58808
 
58214
58809
  // src/auth.ts
58215
58810
  import { writeFile, mkdir as mkdir2 } from "fs/promises";
58216
- import { join as join6 } from "path";
58217
- import { homedir as homedir3 } from "os";
58811
+ import { join as join7 } from "path";
58812
+ import { homedir as homedir4 } from "os";
58218
58813
  async function loadSavedWallet() {
58219
58814
  try {
58220
58815
  const key2 = (await readTextFile(WALLET_FILE)).trim();
@@ -58263,7 +58858,7 @@ async function loadMnemonic() {
58263
58858
  return void 0;
58264
58859
  }
58265
58860
  async function saveMnemonic(mnemonic) {
58266
- await mkdir2(WALLET_DIR, { recursive: true });
58861
+ await mkdir2(WALLET_DIR2, { recursive: true });
58267
58862
  await writeFile(MNEMONIC_FILE, mnemonic + "\n", { mode: 384 });
58268
58863
  }
58269
58864
  async function generateAndSaveWallet() {
@@ -58282,7 +58877,7 @@ Then run: npx @blockrun/clawrouter`
58282
58877
  }
58283
58878
  const mnemonic = generateWalletMnemonic();
58284
58879
  const derived = deriveAllKeys(mnemonic);
58285
- await mkdir2(WALLET_DIR, { recursive: true });
58880
+ await mkdir2(WALLET_DIR2, { recursive: true });
58286
58881
  await writeFile(WALLET_FILE, derived.evmPrivateKey + "\n", { mode: 384 });
58287
58882
  await writeFile(MNEMONIC_FILE, mnemonic + "\n", { mode: 384 });
58288
58883
  try {
@@ -58404,7 +58999,7 @@ async function setupSolana() {
58404
58999
  return { mnemonic, solanaPrivateKeyBytes: solanaKeyBytes };
58405
59000
  }
58406
59001
  async function savePaymentChain(chain3) {
58407
- await mkdir2(WALLET_DIR, { recursive: true });
59002
+ await mkdir2(WALLET_DIR2, { recursive: true });
58408
59003
  await writeFile(CHAIN_FILE, chain3 + "\n", { mode: 384 });
58409
59004
  }
58410
59005
  async function loadPaymentChain() {
@@ -58421,17 +59016,17 @@ async function resolvePaymentChain() {
58421
59016
  if (process["env"].CLAWROUTER_PAYMENT_CHAIN === "base") return "base";
58422
59017
  return loadPaymentChain();
58423
59018
  }
58424
- var WALLET_DIR, WALLET_FILE, MNEMONIC_FILE, CHAIN_FILE;
59019
+ var WALLET_DIR2, WALLET_FILE, MNEMONIC_FILE, CHAIN_FILE;
58425
59020
  var init_auth = __esm({
58426
59021
  "src/auth.ts"() {
58427
59022
  "use strict";
58428
59023
  init_fs_read();
58429
59024
  init_accounts();
58430
59025
  init_wallet2();
58431
- WALLET_DIR = join6(homedir3(), ".openclaw", "blockrun");
58432
- WALLET_FILE = join6(WALLET_DIR, "wallet.key");
58433
- MNEMONIC_FILE = join6(WALLET_DIR, "mnemonic");
58434
- CHAIN_FILE = join6(WALLET_DIR, "payment-chain");
59026
+ WALLET_DIR2 = join7(homedir4(), ".openclaw", "blockrun");
59027
+ WALLET_FILE = join7(WALLET_DIR2, "wallet.key");
59028
+ MNEMONIC_FILE = join7(WALLET_DIR2, "mnemonic");
59029
+ CHAIN_FILE = join7(WALLET_DIR2, "payment-chain");
58435
59030
  }
58436
59031
  });
58437
59032
 
@@ -58590,7 +59185,7 @@ function generateCodebookHeader(usedCodes, pathMap = {}) {
58590
59185
  parts.push(`[Dict: ${codeEntries}]`);
58591
59186
  }
58592
59187
  if (Object.keys(pathMap).length > 0) {
58593
- const pathEntries = Object.entries(pathMap).map(([code, path6]) => `${code}=${path6}`).join(", ");
59188
+ const pathEntries = Object.entries(pathMap).map(([code, path5]) => `${code}=${path5}`).join(", ");
58594
59189
  parts.push(`[Paths: ${pathEntries}]`);
58595
59190
  }
58596
59191
  return parts.join("\n");
@@ -58738,8 +59333,8 @@ function extractPaths(messages) {
58738
59333
  }
58739
59334
  function findFrequentPrefixes(paths) {
58740
59335
  const prefixCounts = /* @__PURE__ */ new Map();
58741
- for (const path6 of paths) {
58742
- const parts = path6.split("/").filter(Boolean);
59336
+ for (const path5 of paths) {
59337
+ const parts = path5.split("/").filter(Boolean);
58743
59338
  for (let i = 2; i < parts.length; i++) {
58744
59339
  const prefix = "/" + parts.slice(0, i).join("/") + "/";
58745
59340
  prefixCounts.set(prefix, (prefixCounts.get(prefix) || 0) + 1);
@@ -59523,9 +60118,9 @@ var init_updater = __esm({
59523
60118
  });
59524
60119
 
59525
60120
  // src/exclude-models.ts
59526
- import { readFileSync, writeFileSync, mkdirSync, statSync } from "fs";
59527
- import { join as join7, dirname as dirname2 } from "path";
59528
- import { homedir as homedir4 } from "os";
60121
+ import { readFileSync, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, statSync } from "fs";
60122
+ import { join as join8, dirname as dirname2 } from "path";
60123
+ import { homedir as homedir5 } from "os";
59529
60124
  function loadExcludeList(filePath = DEFAULT_FILE_PATH) {
59530
60125
  try {
59531
60126
  const mtimeMs = statSync(filePath).mtimeMs;
@@ -59546,8 +60141,8 @@ function loadExcludeList(filePath = DEFAULT_FILE_PATH) {
59546
60141
  function saveExcludeList(set, filePath) {
59547
60142
  const sorted = [...set].sort();
59548
60143
  const dir = dirname2(filePath);
59549
- mkdirSync(dir, { recursive: true });
59550
- writeFileSync(filePath, JSON.stringify(sorted, null, 2) + "\n", "utf-8");
60144
+ mkdirSync2(dir, { recursive: true });
60145
+ writeFileSync2(filePath, JSON.stringify(sorted, null, 2) + "\n", "utf-8");
59551
60146
  loadCache.delete(filePath);
59552
60147
  }
59553
60148
  function addExclusion(model, filePath = DEFAULT_FILE_PATH) {
@@ -59574,7 +60169,7 @@ var init_exclude_models = __esm({
59574
60169
  "src/exclude-models.ts"() {
59575
60170
  "use strict";
59576
60171
  init_models();
59577
- DEFAULT_FILE_PATH = join7(homedir4(), ".openclaw", "blockrun", "exclude-models.json");
60172
+ DEFAULT_FILE_PATH = join8(homedir5(), ".openclaw", "blockrun", "exclude-models.json");
59578
60173
  loadCache = /* @__PURE__ */ new Map();
59579
60174
  }
59580
60175
  });
@@ -60879,14 +61474,14 @@ var require_util = __commonJS({
60879
61474
  }
60880
61475
  const port = url2.port != null ? url2.port : url2.protocol === "https:" ? 443 : 80;
60881
61476
  let origin2 = url2.origin != null ? url2.origin : `${url2.protocol || ""}//${url2.hostname || ""}:${port}`;
60882
- let path6 = url2.path != null ? url2.path : `${url2.pathname || ""}${url2.search || ""}`;
61477
+ let path5 = url2.path != null ? url2.path : `${url2.pathname || ""}${url2.search || ""}`;
60883
61478
  if (origin2[origin2.length - 1] === "/") {
60884
61479
  origin2 = origin2.slice(0, origin2.length - 1);
60885
61480
  }
60886
- if (path6 && path6[0] !== "/") {
60887
- path6 = `/${path6}`;
61481
+ if (path5 && path5[0] !== "/") {
61482
+ path5 = `/${path5}`;
60888
61483
  }
60889
- return new URL(`${origin2}${path6}`);
61484
+ return new URL(`${origin2}${path5}`);
60890
61485
  }
60891
61486
  if (!isHttpOrHttpsPrefixed(url2.origin || url2.protocol)) {
60892
61487
  throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`.");
@@ -61757,9 +62352,9 @@ var require_diagnostics = __commonJS({
61757
62352
  "undici:client:sendHeaders",
61758
62353
  (evt) => {
61759
62354
  const {
61760
- request: { method, path: path6, origin: origin2 }
62355
+ request: { method, path: path5, origin: origin2 }
61761
62356
  } = evt;
61762
- debugLog("sending request to %s %s%s", method, origin2, path6);
62357
+ debugLog("sending request to %s %s%s", method, origin2, path5);
61763
62358
  }
61764
62359
  );
61765
62360
  }
@@ -61777,14 +62372,14 @@ var require_diagnostics = __commonJS({
61777
62372
  "undici:request:headers",
61778
62373
  (evt) => {
61779
62374
  const {
61780
- request: { method, path: path6, origin: origin2 },
62375
+ request: { method, path: path5, origin: origin2 },
61781
62376
  response: { statusCode }
61782
62377
  } = evt;
61783
62378
  debugLog(
61784
62379
  "received response to %s %s%s - HTTP %d",
61785
62380
  method,
61786
62381
  origin2,
61787
- path6,
62382
+ path5,
61788
62383
  statusCode
61789
62384
  );
61790
62385
  }
@@ -61793,23 +62388,23 @@ var require_diagnostics = __commonJS({
61793
62388
  "undici:request:trailers",
61794
62389
  (evt) => {
61795
62390
  const {
61796
- request: { method, path: path6, origin: origin2 }
62391
+ request: { method, path: path5, origin: origin2 }
61797
62392
  } = evt;
61798
- debugLog("trailers received from %s %s%s", method, origin2, path6);
62393
+ debugLog("trailers received from %s %s%s", method, origin2, path5);
61799
62394
  }
61800
62395
  );
61801
62396
  diagnosticsChannel.subscribe(
61802
62397
  "undici:request:error",
61803
62398
  (evt) => {
61804
62399
  const {
61805
- request: { method, path: path6, origin: origin2 },
62400
+ request: { method, path: path5, origin: origin2 },
61806
62401
  error
61807
62402
  } = evt;
61808
62403
  debugLog(
61809
62404
  "request to %s %s%s errored - %s",
61810
62405
  method,
61811
62406
  origin2,
61812
- path6,
62407
+ path5,
61813
62408
  error.message
61814
62409
  );
61815
62410
  }
@@ -61964,7 +62559,7 @@ var require_request = __commonJS({
61964
62559
  };
61965
62560
  var Request2 = class {
61966
62561
  constructor(origin2, {
61967
- path: path6,
62562
+ path: path5,
61968
62563
  method,
61969
62564
  body,
61970
62565
  headers,
@@ -61981,11 +62576,11 @@ var require_request = __commonJS({
61981
62576
  maxRedirections,
61982
62577
  typeOfService
61983
62578
  }, handler) {
61984
- if (typeof path6 !== "string") {
62579
+ if (typeof path5 !== "string") {
61985
62580
  throw new InvalidArgumentError("path must be a string");
61986
- } else if (path6[0] !== "/" && !(path6.startsWith("http://") || path6.startsWith("https://")) && method !== "CONNECT") {
62581
+ } else if (path5[0] !== "/" && !(path5.startsWith("http://") || path5.startsWith("https://")) && method !== "CONNECT") {
61987
62582
  throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
61988
- } else if (invalidPathRegex.test(path6)) {
62583
+ } else if (invalidPathRegex.test(path5)) {
61989
62584
  throw new InvalidArgumentError("invalid request path");
61990
62585
  }
61991
62586
  if (typeof method !== "string") {
@@ -62060,7 +62655,7 @@ var require_request = __commonJS({
62060
62655
  this.completed = false;
62061
62656
  this.aborted = false;
62062
62657
  this.upgrade = upgrade || null;
62063
- this.path = query ? serializePathWithQuery(path6, query) : path6;
62658
+ this.path = query ? serializePathWithQuery(path5, query) : path5;
62064
62659
  this.origin = origin2;
62065
62660
  this.protocol = getProtocolFromUrlString(origin2);
62066
62661
  this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" || method === "QUERY" : idempotent;
@@ -67146,7 +67741,7 @@ var require_client_h1 = __commonJS({
67146
67741
  }
67147
67742
  }
67148
67743
  function writeH1(client, request2) {
67149
- const { method, path: path6, host, upgrade, blocking, reset } = request2;
67744
+ const { method, path: path5, host, upgrade, blocking, reset } = request2;
67150
67745
  let { body, headers, contentLength } = request2;
67151
67746
  const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
67152
67747
  if (util5.isFormDataLike(body)) {
@@ -67222,7 +67817,7 @@ var require_client_h1 = __commonJS({
67222
67817
  socket[kBlocking] = true;
67223
67818
  }
67224
67819
  setTypeOfService(socket, request2);
67225
- let header = `${method} ${path6} HTTP/1.1\r
67820
+ let header = `${method} ${path5} HTTP/1.1\r
67226
67821
  `;
67227
67822
  if (typeof host === "string") {
67228
67823
  header += `host: ${host}\r
@@ -68303,7 +68898,7 @@ var require_client_h2 = __commonJS({
68303
68898
  const headersTimeout = request2.headersTimeout ?? client[kHeadersTimeout];
68304
68899
  const bodyTimeout = request2.bodyTimeout ?? client[kBodyTimeout];
68305
68900
  const session = client[kHTTP2Session];
68306
- const { method, path: path6, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request2;
68901
+ const { method, path: path5, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request2;
68307
68902
  if (upgrade != null && upgrade !== "websocket") {
68308
68903
  util5.errorRequest(client, request2, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`));
68309
68904
  return false;
@@ -68366,7 +68961,7 @@ var require_client_h2 = __commonJS({
68366
68961
  }
68367
68962
  headers[HTTP2_HEADER_METHOD] = "CONNECT";
68368
68963
  headers[HTTP2_HEADER_PROTOCOL] = "websocket";
68369
- headers[HTTP2_HEADER_PATH] = path6;
68964
+ headers[HTTP2_HEADER_PATH] = path5;
68370
68965
  if (protocol === "ws:" || protocol === "wss:") {
68371
68966
  headers[HTTP2_HEADER_SCHEME] = protocol === "ws:" ? "http" : "https";
68372
68967
  } else {
@@ -68388,7 +68983,7 @@ var require_client_h2 = __commonJS({
68388
68983
  setupUpgradeStream(stream4, state);
68389
68984
  return true;
68390
68985
  }
68391
- headers[HTTP2_HEADER_PATH] = path6;
68986
+ headers[HTTP2_HEADER_PATH] = path5;
68392
68987
  headers[HTTP2_HEADER_SCHEME] = protocol === "http:" ? "http" : "https";
68393
68988
  const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
68394
68989
  let body = state.body;
@@ -71058,10 +71653,10 @@ var require_proxy_agent = __commonJS({
71058
71653
  };
71059
71654
  const {
71060
71655
  origin: origin2,
71061
- path: path6 = "/",
71656
+ path: path5 = "/",
71062
71657
  headers = {}
71063
71658
  } = opts;
71064
- opts.path = origin2 + path6;
71659
+ opts.path = origin2 + path5;
71065
71660
  if (!("host" in headers) && !("Host" in headers)) {
71066
71661
  const { host } = new URL(origin2);
71067
71662
  headers.host = host;
@@ -73326,20 +73921,20 @@ var require_mock_utils = __commonJS({
73326
73921
  }
73327
73922
  return normalizedQp;
73328
73923
  }
73329
- function safeUrl(path6) {
73330
- if (typeof path6 !== "string") {
73331
- return path6;
73924
+ function safeUrl(path5) {
73925
+ if (typeof path5 !== "string") {
73926
+ return path5;
73332
73927
  }
73333
- const pathSegments = path6.split("?", 3);
73928
+ const pathSegments = path5.split("?", 3);
73334
73929
  if (pathSegments.length !== 2) {
73335
- return path6;
73930
+ return path5;
73336
73931
  }
73337
73932
  const qp = new URLSearchParams(pathSegments.pop());
73338
73933
  qp.sort();
73339
73934
  return [...pathSegments, qp.toString()].join("?");
73340
73935
  }
73341
- function matchKey(mockDispatch2, { path: path6, method, body, headers }) {
73342
- const pathMatch = matchValue(mockDispatch2.path, path6);
73936
+ function matchKey(mockDispatch2, { path: path5, method, body, headers }) {
73937
+ const pathMatch = matchValue(mockDispatch2.path, path5);
73343
73938
  const methodMatch = matchValue(mockDispatch2.method, method);
73344
73939
  const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
73345
73940
  const headersMatch = matchHeaders(mockDispatch2, headers);
@@ -73366,8 +73961,8 @@ var require_mock_utils = __commonJS({
73366
73961
  const basePath = key2.query ? serializePathWithQuery(key2.path, key2.query) : key2.path;
73367
73962
  const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
73368
73963
  const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath);
73369
- let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path6, ignoreTrailingSlash }) => {
73370
- return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path6)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path6), resolvedPath);
73964
+ let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path5, ignoreTrailingSlash }) => {
73965
+ return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path5)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path5), resolvedPath);
73371
73966
  });
73372
73967
  if (matchedMockDispatches.length === 0) {
73373
73968
  throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
@@ -73406,22 +74001,22 @@ var require_mock_utils = __commonJS({
73406
74001
  mockDispatches.splice(index2, 1);
73407
74002
  }
73408
74003
  }
73409
- function removeTrailingSlash(path6) {
73410
- if (typeof path6 !== "string") {
73411
- return path6;
74004
+ function removeTrailingSlash(path5) {
74005
+ if (typeof path5 !== "string") {
74006
+ return path5;
73412
74007
  }
73413
- while (path6.endsWith("/")) {
73414
- path6 = path6.slice(0, -1);
74008
+ while (path5.endsWith("/")) {
74009
+ path5 = path5.slice(0, -1);
73415
74010
  }
73416
- if (path6.length === 0) {
73417
- path6 = "/";
74011
+ if (path5.length === 0) {
74012
+ path5 = "/";
73418
74013
  }
73419
- return path6;
74014
+ return path5;
73420
74015
  }
73421
74016
  function buildKey(opts) {
73422
- const { path: path6, method, body, headers, query } = opts;
74017
+ const { path: path5, method, body, headers, query } = opts;
73423
74018
  return {
73424
- path: path6,
74019
+ path: path5,
73425
74020
  method,
73426
74021
  body,
73427
74022
  headers,
@@ -74292,10 +74887,10 @@ var require_pending_interceptors_formatter = __commonJS({
74292
74887
  }
74293
74888
  format(pendingInterceptors) {
74294
74889
  const withPrettyHeaders = pendingInterceptors.map(
74295
- ({ method, path: path6, data: { statusCode }, persist, times, timesInvoked, origin: origin2 }) => ({
74890
+ ({ method, path: path5, data: { statusCode }, persist, times, timesInvoked, origin: origin2 }) => ({
74296
74891
  Method: method,
74297
74892
  Origin: origin2,
74298
- Path: path6,
74893
+ Path: path5,
74299
74894
  "Status code": statusCode,
74300
74895
  Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
74301
74896
  Invocations: timesInvoked,
@@ -74377,9 +74972,9 @@ var require_mock_agent = __commonJS({
74377
74972
  const acceptNonStandardSearchParameters = this[kMockAgentAcceptsNonStandardSearchParameters];
74378
74973
  const dispatchOpts = { ...opts };
74379
74974
  if (acceptNonStandardSearchParameters && dispatchOpts.path) {
74380
- const [path6, searchParams] = dispatchOpts.path.split("?");
74975
+ const [path5, searchParams] = dispatchOpts.path.split("?");
74381
74976
  const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters);
74382
- dispatchOpts.path = `${path6}?${normalizedSearchParams}`;
74977
+ dispatchOpts.path = `${path5}?${normalizedSearchParams}`;
74383
74978
  }
74384
74979
  return this[kAgent].dispatch(dispatchOpts, handler);
74385
74980
  }
@@ -74795,12 +75390,12 @@ var require_snapshot_recorder = __commonJS({
74795
75390
  * @return {Promise<void>} - Resolves when snapshots are loaded
74796
75391
  */
74797
75392
  async loadSnapshots(filePath) {
74798
- const path6 = filePath || this.#snapshotPath;
74799
- if (!path6) {
75393
+ const path5 = filePath || this.#snapshotPath;
75394
+ if (!path5) {
74800
75395
  throw new InvalidArgumentError("Snapshot path is required");
74801
75396
  }
74802
75397
  try {
74803
- const data = await readFile3(resolve(path6), "utf8");
75398
+ const data = await readFile3(resolve(path5), "utf8");
74804
75399
  const parsed = JSON.parse(data);
74805
75400
  if (Array.isArray(parsed)) {
74806
75401
  this.#snapshots.clear();
@@ -74814,7 +75409,7 @@ var require_snapshot_recorder = __commonJS({
74814
75409
  if (error.code === "ENOENT") {
74815
75410
  this.#snapshots.clear();
74816
75411
  } else {
74817
- throw new UndiciError(`Failed to load snapshots from ${path6}`, { cause: error });
75412
+ throw new UndiciError(`Failed to load snapshots from ${path5}`, { cause: error });
74818
75413
  }
74819
75414
  }
74820
75415
  }
@@ -74825,11 +75420,11 @@ var require_snapshot_recorder = __commonJS({
74825
75420
  * @returns {Promise<void>} - Resolves when snapshots are saved
74826
75421
  */
74827
75422
  async saveSnapshots(filePath) {
74828
- const path6 = filePath || this.#snapshotPath;
74829
- if (!path6) {
75423
+ const path5 = filePath || this.#snapshotPath;
75424
+ if (!path5) {
74830
75425
  throw new InvalidArgumentError("Snapshot path is required");
74831
75426
  }
74832
- const resolvedPath = resolve(path6);
75427
+ const resolvedPath = resolve(path5);
74833
75428
  await mkdir5(dirname5(resolvedPath), { recursive: true });
74834
75429
  const data = Array.from(this.#snapshots.entries()).map(([hash5, snapshot]) => ({
74835
75430
  hash: hash5,
@@ -75466,15 +76061,15 @@ var require_redirect_handler = __commonJS({
75466
76061
  return;
75467
76062
  }
75468
76063
  const { origin: origin2, pathname, search } = util5.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
75469
- const path6 = search ? `${pathname}${search}` : pathname;
75470
- const redirectUrlString = `${origin2}${path6}`;
76064
+ const path5 = search ? `${pathname}${search}` : pathname;
76065
+ const redirectUrlString = `${origin2}${path5}`;
75471
76066
  for (const historyUrl of this.history) {
75472
76067
  if (historyUrl.toString() === redirectUrlString) {
75473
76068
  throw new InvalidArgumentError(`Redirect loop detected. Cannot redirect to ${origin2}. This typically happens when using a Client or Pool with cross-origin redirects. Use an Agent for cross-origin redirects.`);
75474
76069
  }
75475
76070
  }
75476
76071
  this.opts.headers = cleanRequestHeaders(this.opts.headers, removeContentHeaders, this.opts.origin !== origin2, this.stripHeadersOnRedirect, this.stripHeadersOnCrossOriginRedirect);
75477
- this.opts.path = path6;
76072
+ this.opts.path = path5;
75478
76073
  this.opts.origin = origin2;
75479
76074
  this.opts.query = null;
75480
76075
  }
@@ -77302,10 +77897,10 @@ var require_cache_handler = __commonJS({
77302
77897
  }
77303
77898
  return locationUrl.pathname + locationUrl.search;
77304
77899
  }
77305
- function deleteCachedUri(store, cacheKey2, path6) {
77900
+ function deleteCachedUri(store, cacheKey2, path5) {
77306
77901
  deleteCachedValue(store, {
77307
77902
  ...cacheKey2,
77308
- path: path6
77903
+ path: path5
77309
77904
  });
77310
77905
  for (let i = 0; i < util5.safeHTTPMethods.length; i++) {
77311
77906
  const method = util5.safeHTTPMethods[i];
@@ -77313,7 +77908,7 @@ var require_cache_handler = __commonJS({
77313
77908
  deleteCachedValue(store, {
77314
77909
  ...cacheKey2,
77315
77910
  method,
77316
- path: path6
77911
+ path: path5
77317
77912
  });
77318
77913
  }
77319
77914
  }
@@ -77324,9 +77919,9 @@ var require_cache_handler = __commonJS({
77324
77919
  }
77325
77920
  const values = Array.isArray(headerValue) ? headerValue : [headerValue];
77326
77921
  for (let i = 0; i < values.length; i++) {
77327
- const path6 = getSameOriginPath(cacheKey2, values[i]);
77328
- if (path6 !== void 0) {
77329
- deleteCachedUri(store, cacheKey2, path6);
77922
+ const path5 = getSameOriginPath(cacheKey2, values[i]);
77923
+ if (path5 !== void 0) {
77924
+ deleteCachedUri(store, cacheKey2, path5);
77330
77925
  }
77331
77926
  }
77332
77927
  }
@@ -82323,13 +82918,13 @@ var require_fetch = __commonJS({
82323
82918
  function dispatch({ body }) {
82324
82919
  const url2 = requestCurrentURL(request2);
82325
82920
  const agent = fetchParams.controller.dispatcher;
82326
- const path6 = url2.pathname + url2.search;
82921
+ const path5 = url2.pathname + url2.search;
82327
82922
  const hasTrailingQuestionMark = url2.search.length === 0 && url2.href[url2.href.length - url2.hash.length - 1] === "?";
82328
82923
  return dispatchWithProtocolPreference(body);
82329
82924
  function dispatchWithProtocolPreference(body2, allowH2) {
82330
82925
  return new Promise((resolve, reject) => agent.dispatch(
82331
82926
  {
82332
- path: hasTrailingQuestionMark ? `${path6}?` : path6,
82927
+ path: hasTrailingQuestionMark ? `${path5}?` : path5,
82333
82928
  origin: url2.origin,
82334
82929
  method: request2.method,
82335
82930
  body: agent.isMockActive ? request2.body && (request2.body.source || request2.body.stream) : body2,
@@ -83241,9 +83836,9 @@ var require_util4 = __commonJS({
83241
83836
  }
83242
83837
  }
83243
83838
  }
83244
- function validateCookiePath(path6) {
83245
- for (let i = 0; i < path6.length; ++i) {
83246
- const code = path6.charCodeAt(i);
83839
+ function validateCookiePath(path5) {
83840
+ for (let i = 0; i < path5.length; ++i) {
83841
+ const code = path5.charCodeAt(i);
83247
83842
  if (code < 32 || // exclude CTLs (0-31)
83248
83843
  code > 126 || // exclude non-ascii and DEL
83249
83844
  code === 59) {
@@ -86615,11 +87210,11 @@ var require_undici = __commonJS({
86615
87210
  if (typeof opts.path !== "string") {
86616
87211
  throw new InvalidArgumentError("invalid opts.path");
86617
87212
  }
86618
- let path6 = opts.path;
87213
+ let path5 = opts.path;
86619
87214
  if (!opts.path.startsWith("/")) {
86620
- path6 = `/${path6}`;
87215
+ path5 = `/${path5}`;
86621
87216
  }
86622
- url2 = new URL(util5.parseOrigin(url2).origin + path6);
87217
+ url2 = new URL(util5.parseOrigin(url2).origin + path5);
86623
87218
  } else {
86624
87219
  if (!opts) {
86625
87220
  opts = typeof url2 === "object" ? url2 : {};
@@ -87165,8 +87760,8 @@ var init_textual_tool_calls = __esm({
87165
87760
 
87166
87761
  // src/response-store.ts
87167
87762
  import { appendFile as appendFile2, mkdir as mkdir3, readFile, readdir as readdir2 } from "fs/promises";
87168
- import { homedir as homedir5 } from "os";
87169
- import { join as join8 } from "path";
87763
+ import { homedir as homedir6 } from "os";
87764
+ import { join as join9 } from "path";
87170
87765
  import { randomBytes as randomBytes7 } from "crypto";
87171
87766
  function isEnabled() {
87172
87767
  const v = process.env.BLOCKRUN_RESPONSE_STORE;
@@ -87179,7 +87774,7 @@ async function ensureDir2() {
87179
87774
  }
87180
87775
  function dailyFile(date = /* @__PURE__ */ new Date()) {
87181
87776
  const iso = date.toISOString().slice(0, 10);
87182
- return join8(STORE_DIR, `responses-${iso}.jsonl`);
87777
+ return join9(STORE_DIR, `responses-${iso}.jsonl`);
87183
87778
  }
87184
87779
  function genId() {
87185
87780
  return `resp_${Date.now()}_${randomBytes7(3).toString("hex")}`;
@@ -87229,7 +87824,7 @@ async function listRecent(limit = 20, daysBack = 7) {
87229
87824
  d.setUTCDate(d.getUTCDate() - i);
87230
87825
  const iso = d.toISOString().slice(0, 10);
87231
87826
  const name = `responses-${iso}.jsonl`;
87232
- if (files.includes(name)) candidateFiles.push(join8(STORE_DIR, name));
87827
+ if (files.includes(name)) candidateFiles.push(join9(STORE_DIR, name));
87233
87828
  }
87234
87829
  const all3 = [];
87235
87830
  for (const f of candidateFiles) {
@@ -87258,7 +87853,7 @@ var STORE_DIR, dirReady2;
87258
87853
  var init_response_store = __esm({
87259
87854
  "src/response-store.ts"() {
87260
87855
  "use strict";
87261
- STORE_DIR = join8(homedir5(), ".openclaw", "blockrun", "responses");
87856
+ STORE_DIR = join9(homedir6(), ".openclaw", "blockrun", "responses");
87262
87857
  dirReady2 = false;
87263
87858
  }
87264
87859
  });
@@ -88908,10 +89503,10 @@ var init_client3 = __esm({
88908
89503
  import { AsyncLocalStorage } from "async_hooks";
88909
89504
  import { createServer } from "http";
88910
89505
  import { finished } from "stream";
88911
- import { homedir as homedir6 } from "os";
88912
- import { join as join9 } from "path";
89506
+ import { homedir as homedir7 } from "os";
89507
+ import { join as join10 } from "path";
88913
89508
  import { mkdir as mkdir4, writeFile as writeFile2, readFile as readFile2, stat as fsStat } from "fs/promises";
88914
- import { readFileSync as readFileSync2, existsSync } from "fs";
89509
+ import { readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
88915
89510
  function pickFreeModel(excludeList) {
88916
89511
  for (const m of FREE_MODELS) {
88917
89512
  if (!excludeList?.has(m)) return m;
@@ -89677,8 +90272,8 @@ async function proxyPaidApiRequest(req, res, apiBase, payFetch, getActualPayment
89677
90272
  });
89678
90273
  }
89679
90274
  function readImageFileAsDataUri(filePath) {
89680
- const resolved = filePath.startsWith("~/") ? join9(homedir6(), filePath.slice(2)) : filePath;
89681
- if (!existsSync(resolved)) {
90275
+ const resolved = filePath.startsWith("~/") ? join10(homedir7(), filePath.slice(2)) : filePath;
90276
+ if (!existsSync2(resolved)) {
89682
90277
  throw new Error(`Image file not found: ${resolved}`);
89683
90278
  }
89684
90279
  const ext = resolved.split(".").pop()?.toLowerCase() ?? "png";
@@ -89792,6 +90387,8 @@ async function startProxy(options) {
89792
90387
  const evmPublicClient = createPublicClient({ chain: base, transport: http() });
89793
90388
  const evmSigner = toClientEvmSigner(account, evmPublicClient);
89794
90389
  const x402 = new x402Client();
90390
+ const spendControl = options.spendControl ?? new SpendControl();
90391
+ registerSpendPolicyHook(x402, spendControl);
89795
90392
  registerExactEvmScheme(x402, { signer: evmSigner });
89796
90393
  let solanaAddress;
89797
90394
  if (solanaPrivateKeyBytes) {
@@ -89960,8 +90557,8 @@ async function startProxy(options) {
89960
90557
  if (req.url?.startsWith("/share") && req.method === "GET") {
89961
90558
  try {
89962
90559
  const url2 = new URL(req.url, "http://localhost");
89963
- const path6 = url2.pathname;
89964
- if (path6 === "/share/list") {
90560
+ const path5 = url2.pathname;
90561
+ if (path5 === "/share/list") {
89965
90562
  const limit = Math.min(parseInt(url2.searchParams.get("limit") || "20", 10), 100);
89966
90563
  const entries = await listRecent(limit);
89967
90564
  res.writeHead(200, { "Content-Type": "application/json" });
@@ -89979,7 +90576,7 @@ async function startProxy(options) {
89979
90576
  );
89980
90577
  return;
89981
90578
  }
89982
- if (path6 === "/share/last") {
90579
+ if (path5 === "/share/last") {
89983
90580
  const sessionId = url2.searchParams.get("sessionId") || void 0;
89984
90581
  const entry = await getLast(sessionId);
89985
90582
  if (!entry) {
@@ -90008,7 +90605,7 @@ async function startProxy(options) {
90008
90605
  res.end(JSON.stringify(entry));
90009
90606
  return;
90010
90607
  }
90011
- const idMatch = path6.match(/^\/share\/(resp_[A-Za-z0-9_]+)(?:\/render)?$/);
90608
+ const idMatch = path5.match(/^\/share\/(resp_[A-Za-z0-9_]+)(?:\/render)?$/);
90012
90609
  if (idMatch) {
90013
90610
  const id2 = idMatch[1];
90014
90611
  const entry = await getById(id2);
@@ -90054,7 +90651,7 @@ async function startProxy(options) {
90054
90651
  res.end("Bad request");
90055
90652
  return;
90056
90653
  }
90057
- const filePath = join9(IMAGE_DIR, filename);
90654
+ const filePath = join10(IMAGE_DIR, filename);
90058
90655
  try {
90059
90656
  const s3 = await fsStat(filePath);
90060
90657
  if (!s3.isFile()) throw new Error("not a file");
@@ -90085,7 +90682,7 @@ async function startProxy(options) {
90085
90682
  res.end("Bad request");
90086
90683
  return;
90087
90684
  }
90088
- const filePath = join9(AUDIO_DIR, filename);
90685
+ const filePath = join10(AUDIO_DIR, filename);
90089
90686
  try {
90090
90687
  const s3 = await fsStat(filePath);
90091
90688
  if (!s3.isFile()) throw new Error("not a file");
@@ -90115,7 +90712,7 @@ async function startProxy(options) {
90115
90712
  res.end("Bad request");
90116
90713
  return;
90117
90714
  }
90118
- const filePath = join9(VIDEO_DIR, filename);
90715
+ const filePath = join10(VIDEO_DIR, filename);
90119
90716
  try {
90120
90717
  const s3 = await fsStat(filePath);
90121
90718
  if (!s3.isFile()) throw new Error("not a file");
@@ -90256,7 +90853,7 @@ async function startProxy(options) {
90256
90853
  const [, mimeType, b64] = dataUriMatch;
90257
90854
  const ext = mimeType === "image/jpeg" ? "jpg" : mimeType.split("/")[1] ?? "png";
90258
90855
  const filename = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}.${ext}`;
90259
- await writeFile2(join9(IMAGE_DIR, filename), Buffer.from(b64, "base64"));
90856
+ await writeFile2(join10(IMAGE_DIR, filename), Buffer.from(b64, "base64"));
90260
90857
  img.url = `http://localhost:${port2}/images/${filename}`;
90261
90858
  console.log(`[ClawRouter] Image saved \u2192 ${img.url}`);
90262
90859
  } else if (img.url?.startsWith("https://") || img.url?.startsWith("http://")) {
@@ -90267,7 +90864,7 @@ async function startProxy(options) {
90267
90864
  const ext = contentType.includes("jpeg") || contentType.includes("jpg") ? "jpg" : contentType.includes("webp") ? "webp" : "png";
90268
90865
  const filename = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}.${ext}`;
90269
90866
  const buf = Buffer.from(await imgResp.arrayBuffer());
90270
- await writeFile2(join9(IMAGE_DIR, filename), buf);
90867
+ await writeFile2(join10(IMAGE_DIR, filename), buf);
90271
90868
  img.url = `http://localhost:${port2}/images/${filename}`;
90272
90869
  console.log(`[ClawRouter] Image downloaded & saved \u2192 ${img.url}`);
90273
90870
  }
@@ -90379,7 +90976,7 @@ async function startProxy(options) {
90379
90976
  const [, mimeType, b64] = dataUriMatch;
90380
90977
  const ext = mimeType === "image/jpeg" ? "jpg" : mimeType.split("/")[1] ?? "png";
90381
90978
  const filename = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}.${ext}`;
90382
- await writeFile2(join9(IMAGE_DIR, filename), Buffer.from(b64, "base64"));
90979
+ await writeFile2(join10(IMAGE_DIR, filename), Buffer.from(b64, "base64"));
90383
90980
  img.url = `http://localhost:${port2}/images/${filename}`;
90384
90981
  console.log(`[ClawRouter] Image saved \u2192 ${img.url}`);
90385
90982
  } else if (img.url?.startsWith("https://") || img.url?.startsWith("http://")) {
@@ -90390,7 +90987,7 @@ async function startProxy(options) {
90390
90987
  const ext = contentType.includes("jpeg") || contentType.includes("jpg") ? "jpg" : contentType.includes("webp") ? "webp" : "png";
90391
90988
  const filename = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}.${ext}`;
90392
90989
  const buf = Buffer.from(await imgResp.arrayBuffer());
90393
- await writeFile2(join9(IMAGE_DIR, filename), buf);
90990
+ await writeFile2(join10(IMAGE_DIR, filename), buf);
90394
90991
  img.url = `http://localhost:${port2}/images/${filename}`;
90395
90992
  console.log(`[ClawRouter] Image downloaded & saved \u2192 ${img.url}`);
90396
90993
  }
@@ -90476,7 +91073,7 @@ async function startProxy(options) {
90476
91073
  const ext = contentType.includes("wav") ? "wav" : "mp3";
90477
91074
  const filename = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}.${ext}`;
90478
91075
  const buf = Buffer.from(await audioResp.arrayBuffer());
90479
- await writeFile2(join9(AUDIO_DIR, filename), buf);
91076
+ await writeFile2(join10(AUDIO_DIR, filename), buf);
90480
91077
  track.url = `http://localhost:${port2}/audio/${filename}`;
90481
91078
  console.log(`[ClawRouter] Audio saved \u2192 ${track.url}`);
90482
91079
  }
@@ -90636,7 +91233,7 @@ async function startProxy(options) {
90636
91233
  const ext = contentType.includes("webm") ? "webm" : contentType.includes("quicktime") ? "mov" : "mp4";
90637
91234
  const filename = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}.${ext}`;
90638
91235
  const buf = Buffer.from(await videoResp.arrayBuffer());
90639
- await writeFile2(join9(VIDEO_DIR, filename), buf);
91236
+ await writeFile2(join10(VIDEO_DIR, filename), buf);
90640
91237
  clip.url = `http://localhost:${port2}/videos/${filename}`;
90641
91238
  console.log(`[ClawRouter] Video saved \u2192 ${clip.url}`);
90642
91239
  }
@@ -90976,6 +91573,17 @@ async function tryModelRequest(upstreamUrl, method, headers, body, modelId, maxT
90976
91573
  return { success: true, response };
90977
91574
  } catch (err) {
90978
91575
  const errorMsg = err instanceof Error ? err.message : String(err);
91576
+ if (err instanceof SpendPolicyError) {
91577
+ return {
91578
+ success: false,
91579
+ errorBody: JSON.stringify({
91580
+ error: { message: errorMsg, type: "spend_policy_denied", status: 403 }
91581
+ }),
91582
+ errorStatus: 403,
91583
+ isProviderError: false,
91584
+ errorCategory: "payment_error"
91585
+ };
91586
+ }
90979
91587
  return {
90980
91588
  success: false,
90981
91589
  errorBody: errorMsg,
@@ -93162,6 +93770,7 @@ var init_proxy = __esm({
93162
93770
  init_response_cache();
93163
93771
  init_balance();
93164
93772
  init_auth();
93773
+ init_spend_control();
93165
93774
  init_compression();
93166
93775
  init_version4();
93167
93776
  init_session();
@@ -93177,9 +93786,9 @@ var init_proxy = __esm({
93177
93786
  paymentStore = new AsyncLocalStorage();
93178
93787
  BLOCKRUN_API = "https://blockrun.ai/api";
93179
93788
  BLOCKRUN_SOLANA_API = "https://sol.blockrun.ai/api";
93180
- IMAGE_DIR = join9(homedir6(), ".openclaw", "blockrun", "images");
93181
- AUDIO_DIR = join9(homedir6(), ".openclaw", "blockrun", "audio");
93182
- VIDEO_DIR = join9(homedir6(), ".openclaw", "blockrun", "videos");
93789
+ IMAGE_DIR = join10(homedir7(), ".openclaw", "blockrun", "images");
93790
+ AUDIO_DIR = join10(homedir7(), ".openclaw", "blockrun", "audio");
93791
+ VIDEO_DIR = join10(homedir7(), ".openclaw", "blockrun", "videos");
93183
93792
  AUTO_MODEL = "blockrun/auto";
93184
93793
  ROUTING_PROFILES = /* @__PURE__ */ new Set([
93185
93794
  "blockrun/eco",
@@ -94515,7 +95124,7 @@ function buildTool(service, proxyBaseUrl) {
94515
95124
  required
94516
95125
  },
94517
95126
  execute: async (_toolCallId, params) => {
94518
- let path6;
95127
+ let path5;
94519
95128
  const leftoverParams = {};
94520
95129
  let dynamicMethod = "GET";
94521
95130
  let dynamicBody = void 0;
@@ -94527,7 +95136,7 @@ function buildTool(service, proxyBaseUrl) {
94527
95136
  `predexon_endpoint_call: invalid path '${rawPath}' \u2014 must begin with '/pm/' and contain no '..'`
94528
95137
  );
94529
95138
  }
94530
- path6 = `/v1${normalized}`;
95139
+ path5 = `/v1${normalized}`;
94531
95140
  if (typeof params.method === "string") {
94532
95141
  const upper = params.method.toUpperCase();
94533
95142
  if (upper !== "GET" && upper !== "POST") {
@@ -94576,19 +95185,19 @@ function buildTool(service, proxyBaseUrl) {
94576
95185
  }
94577
95186
  }
94578
95187
  } else {
94579
- path6 = `/v1${service.proxyPath}`;
95188
+ path5 = `/v1${service.proxyPath}`;
94580
95189
  for (const [key2, value] of Object.entries(params)) {
94581
95190
  if (value === void 0 || value === null) continue;
94582
95191
  const placeholder = `:${key2}`;
94583
- if (path6.includes(placeholder)) {
94584
- path6 = path6.replace(placeholder, encodeURIComponent(String(value)));
95192
+ if (path5.includes(placeholder)) {
95193
+ path5 = path5.replace(placeholder, encodeURIComponent(String(value)));
94585
95194
  } else {
94586
95195
  leftoverParams[key2] = value;
94587
95196
  }
94588
95197
  }
94589
95198
  }
94590
95199
  const effectiveMethod = service.proxyPath === "/pm/__dynamic__" ? dynamicMethod : service.method;
94591
- let url2 = `${proxyBaseUrl}${path6}`;
95200
+ let url2 = `${proxyBaseUrl}${path5}`;
94592
95201
  if (effectiveMethod === "GET" && Object.keys(leftoverParams).length > 0) {
94593
95202
  const qs = new URLSearchParams();
94594
95203
  for (const [key2, value] of Object.entries(leftoverParams)) {
@@ -105996,11 +106605,11 @@ var require_mime_types = __commonJS({
105996
106605
  }
105997
106606
  return exts[0];
105998
106607
  }
105999
- function lookup(path6) {
106000
- if (!path6 || typeof path6 !== "string") {
106608
+ function lookup(path5) {
106609
+ if (!path5 || typeof path5 !== "string") {
106001
106610
  return false;
106002
106611
  }
106003
- var extension3 = extname("x." + path6).toLowerCase().substr(1);
106612
+ var extension3 = extname("x." + path5).toLowerCase().substr(1);
106004
106613
  if (!extension3) {
106005
106614
  return false;
106006
106615
  }
@@ -107115,7 +107724,7 @@ var require_form_data = __commonJS({
107115
107724
  "use strict";
107116
107725
  var CombinedStream = require_combined_stream();
107117
107726
  var util5 = __require("util");
107118
- var path6 = __require("path");
107727
+ var path5 = __require("path");
107119
107728
  var http5 = __require("http");
107120
107729
  var https2 = __require("https");
107121
107730
  var parseUrl3 = __require("url").parse;
@@ -107246,11 +107855,11 @@ var require_form_data = __commonJS({
107246
107855
  FormData3.prototype._getContentDisposition = function(value, options) {
107247
107856
  var filename;
107248
107857
  if (typeof options.filepath === "string") {
107249
- filename = path6.normalize(options.filepath).replace(/\\/g, "/");
107858
+ filename = path5.normalize(options.filepath).replace(/\\/g, "/");
107250
107859
  } else if (options.filename || value && (value.name || value.path)) {
107251
- filename = path6.basename(options.filename || value && (value.name || value.path));
107860
+ filename = path5.basename(options.filename || value && (value.name || value.path));
107252
107861
  } else if (value && value.readable && hasOwn(value, "httpVersion")) {
107253
- filename = path6.basename(value.client._httpMessage.path || "");
107862
+ filename = path5.basename(value.client._httpMessage.path || "");
107254
107863
  }
107255
107864
  if (filename) {
107256
107865
  return 'filename="' + escapeHeaderParam(filename) + '"';
@@ -107464,9 +108073,9 @@ function isVisitable(thing) {
107464
108073
  function removeBrackets(key2) {
107465
108074
  return utils_default.endsWith(key2, "[]") ? key2.slice(0, -2) : key2;
107466
108075
  }
107467
- function renderKey(path6, key2, dots) {
107468
- if (!path6) return key2;
107469
- return path6.concat(key2).map(function each(token, i) {
108076
+ function renderKey(path5, key2, dots) {
108077
+ if (!path5) return key2;
108078
+ return path5.concat(key2).map(function each(token, i) {
107470
108079
  token = removeBrackets(token);
107471
108080
  return !dots && i ? "[" + token + "]" : token;
107472
108081
  }).join(dots ? "." : "");
@@ -107549,13 +108158,13 @@ function toFormData(obj, formData, options) {
107549
108158
  return currentValue;
107550
108159
  });
107551
108160
  }
107552
- function defaultVisitor(value, key2, path6) {
108161
+ function defaultVisitor(value, key2, path5) {
107553
108162
  let arr = value;
107554
108163
  if (utils_default.isReactNative(formData) && utils_default.isReactNativeBlob(value)) {
107555
- formData.append(renderKey(path6, key2, dots), convertValue(value));
108164
+ formData.append(renderKey(path5, key2, dots), convertValue(value));
107556
108165
  return false;
107557
108166
  }
107558
- if (value && !path6 && typeof value === "object") {
108167
+ if (value && !path5 && typeof value === "object") {
107559
108168
  if (utils_default.endsWith(key2, "{}")) {
107560
108169
  key2 = metaTokens ? key2 : key2.slice(0, -2);
107561
108170
  value = stringifyWithDepthLimit(value, 1);
@@ -107574,7 +108183,7 @@ function toFormData(obj, formData, options) {
107574
108183
  if (isVisitable(value)) {
107575
108184
  return true;
107576
108185
  }
107577
- formData.append(renderKey(path6, key2, dots), convertValue(value));
108186
+ formData.append(renderKey(path5, key2, dots), convertValue(value));
107578
108187
  return false;
107579
108188
  }
107580
108189
  const exposedHelpers = Object.assign(predicates, {
@@ -107582,17 +108191,17 @@ function toFormData(obj, formData, options) {
107582
108191
  convertValue,
107583
108192
  isVisitable
107584
108193
  });
107585
- function build(value, path6, depth = 0) {
108194
+ function build(value, path5, depth = 0) {
107586
108195
  if (utils_default.isUndefined(value)) return;
107587
108196
  throwIfMaxDepthExceeded(depth);
107588
108197
  if (stack.indexOf(value) !== -1) {
107589
- throw new Error("Circular reference detected in " + path6.join("."));
108198
+ throw new Error("Circular reference detected in " + path5.join("."));
107590
108199
  }
107591
108200
  stack.push(value);
107592
108201
  utils_default.forEach(value, function each(el, key2) {
107593
- const result = !(utils_default.isUndefined(el) || el === null) && visitor.call(formData, el, utils_default.isString(key2) ? key2.trim() : key2, path6, exposedHelpers);
108202
+ const result = !(utils_default.isUndefined(el) || el === null) && visitor.call(formData, el, utils_default.isString(key2) ? key2.trim() : key2, path5, exposedHelpers);
107594
108203
  if (result === true) {
107595
- build(el, path6 ? path6.concat(key2) : [key2], depth + 1);
108204
+ build(el, path5 ? path5.concat(key2) : [key2], depth + 1);
107596
108205
  }
107597
108206
  });
107598
108207
  stack.pop();
@@ -107871,7 +108480,7 @@ var init_platform = __esm({
107871
108480
  // node_modules/axios/lib/helpers/toURLEncodedForm.js
107872
108481
  function toURLEncodedForm(data, options) {
107873
108482
  return toFormData_default(data, new platform_default.classes.URLSearchParams(), {
107874
- visitor: function(value, key2, path6, helpers) {
108483
+ visitor: function(value, key2, path5, helpers) {
107875
108484
  if (platform_default.isNode && utils_default.isBuffer(value)) {
107876
108485
  this.append(key2, value.toString("base64"));
107877
108486
  return false;
@@ -107900,14 +108509,14 @@ function throwIfDepthExceeded(index2) {
107900
108509
  }
107901
108510
  }
107902
108511
  function parsePropPath(name) {
107903
- const path6 = [];
108512
+ const path5 = [];
107904
108513
  const pattern = /[^.[\]]+|\[([^.[\]]*)]/g;
107905
108514
  let match;
107906
108515
  while ((match = pattern.exec(name)) !== null) {
107907
- throwIfDepthExceeded(path6.length);
107908
- path6.push(match[0] === "[]" ? "" : match[1] || match[0]);
108516
+ throwIfDepthExceeded(path5.length);
108517
+ path5.push(match[0] === "[]" ? "" : match[1] || match[0]);
107909
108518
  }
107910
- return path6;
108519
+ return path5;
107911
108520
  }
107912
108521
  function arrayToObject(arr) {
107913
108522
  const obj = {};
@@ -107922,12 +108531,12 @@ function arrayToObject(arr) {
107922
108531
  return obj;
107923
108532
  }
107924
108533
  function formDataToJSON(formData) {
107925
- function buildPath(path6, value, target, index2) {
108534
+ function buildPath(path5, value, target, index2) {
107926
108535
  throwIfDepthExceeded(index2);
107927
- let name = path6[index2++];
108536
+ let name = path5[index2++];
107928
108537
  if (name === "__proto__") return true;
107929
108538
  const isNumericKey = Number.isFinite(+name);
107930
- const isLast = index2 >= path6.length;
108539
+ const isLast = index2 >= path5.length;
107931
108540
  name = !name && utils_default.isArray(target) ? target.length : name;
107932
108541
  if (isLast) {
107933
108542
  if (utils_default.hasOwnProp(target, name)) {
@@ -107940,7 +108549,7 @@ function formDataToJSON(formData) {
107940
108549
  if (!utils_default.hasOwnProp(target, name) || !utils_default.isObject(target[name])) {
107941
108550
  target[name] = [];
107942
108551
  }
107943
- const result = buildPath(path6, value, target[name], index2);
108552
+ const result = buildPath(path5, value, target[name], index2);
107944
108553
  if (result && utils_default.isArray(target[name])) {
107945
108554
  target[name] = arrayToObject(target[name]);
107946
108555
  }
@@ -111487,9 +112096,9 @@ var init_http4 = __esm({
111487
112096
  auth = urlUsername + ":" + urlPassword;
111488
112097
  }
111489
112098
  auth && headers.delete("authorization");
111490
- let path6;
112099
+ let path5;
111491
112100
  try {
111492
- path6 = buildURL(
112101
+ path5 = buildURL(
111493
112102
  parsed.pathname + parsed.search,
111494
112103
  own2("params"),
111495
112104
  own2("paramsSerializer")
@@ -111508,7 +112117,7 @@ var init_http4 = __esm({
111508
112117
  false
111509
112118
  );
111510
112119
  const options = Object.assign(/* @__PURE__ */ Object.create(null), {
111511
- path: path6,
112120
+ path: path5,
111512
112121
  method,
111513
112122
  headers: toByteStringHeaderObject(headers),
111514
112123
  agents: { http: httpAgent, https: httpsAgent },
@@ -111925,14 +112534,14 @@ var init_cookies = __esm({
111925
112534
  cookies_default = platform_default.hasStandardBrowserEnv ? (
111926
112535
  // Standard browser envs support document.cookie
111927
112536
  {
111928
- write(name, value, expires, path6, domain, secure, sameSite) {
112537
+ write(name, value, expires, path5, domain, secure, sameSite) {
111929
112538
  if (typeof document === "undefined") return;
111930
112539
  const cookie = [`${name}=${encodeURIComponent(value)}`];
111931
112540
  if (utils_default.isNumber(expires)) {
111932
112541
  cookie.push(`expires=${new Date(expires).toUTCString()}`);
111933
112542
  }
111934
- if (utils_default.isString(path6)) {
111935
- cookie.push(`path=${path6}`);
112543
+ if (utils_default.isString(path5)) {
112544
+ cookie.push(`path=${path5}`);
111936
112545
  }
111937
112546
  if (utils_default.isString(domain)) {
111938
112547
  cookie.push(`domain=${domain}`);
@@ -115361,15 +115970,15 @@ var init_constants3 = __esm({
115361
115970
  });
115362
115971
 
115363
115972
  // src/polymarket/wallet-adapter.ts
115364
- import fs from "fs";
115365
- import { homedir as homedir7 } from "os";
115366
- import { join as join10 } from "path";
115973
+ import fs2 from "fs";
115974
+ import { homedir as homedir8 } from "os";
115975
+ import { join as join11 } from "path";
115367
115976
  function getOrCreateWalletKey() {
115368
115977
  const envKey = process.env.BLOCKRUN_WALLET_KEY?.trim();
115369
115978
  if (envKey && /^0x[0-9a-fA-F]{64}$/.test(envKey)) return envKey;
115370
115979
  let key2;
115371
115980
  try {
115372
- key2 = fs.readFileSync(WALLET_FILE2, "utf-8").trim();
115981
+ key2 = fs2.readFileSync(WALLET_FILE2, "utf-8").trim();
115373
115982
  } catch (err) {
115374
115983
  if (err.code === "ENOENT") {
115375
115984
  throw new Error(
@@ -115411,7 +116020,7 @@ var init_wallet_adapter = __esm({
115411
116020
  init_esm();
115412
116021
  init_chains();
115413
116022
  init_constants3();
115414
- WALLET_FILE2 = join10(homedir7(), ".openclaw", "blockrun", "wallet.key");
116023
+ WALLET_FILE2 = join11(homedir8(), ".openclaw", "blockrun", "wallet.key");
115415
116024
  BASE_RPC_URLS = [
115416
116025
  "https://mainnet.base.org",
115417
116026
  "https://base.llamarpc.com",
@@ -115422,21 +116031,21 @@ var init_wallet_adapter = __esm({
115422
116031
  });
115423
116032
 
115424
116033
  // src/polymarket/creds.ts
115425
- import fs2 from "fs";
115426
- import path from "path";
116034
+ import fs3 from "fs";
116035
+ import path2 from "path";
115427
116036
  import os from "os";
115428
116037
  function readJsonFile(file) {
115429
116038
  try {
115430
- if (!fs2.existsSync(file)) return null;
115431
- const raw = fs2.readFileSync(file, "utf-8").trim();
116039
+ if (!fs3.existsSync(file)) return null;
116040
+ const raw = fs3.readFileSync(file, "utf-8").trim();
115432
116041
  return raw ? JSON.parse(raw) : null;
115433
116042
  } catch {
115434
116043
  return null;
115435
116044
  }
115436
116045
  }
115437
116046
  function writeJsonFile(file, value) {
115438
- fs2.mkdirSync(BLOCKRUN_DIR, { recursive: true });
115439
- fs2.writeFileSync(file, JSON.stringify(value, null, 2), { mode: 384 });
116047
+ fs3.mkdirSync(BLOCKRUN_DIR, { recursive: true });
116048
+ fs3.writeFileSync(file, JSON.stringify(value, null, 2), { mode: 384 });
115440
116049
  }
115441
116050
  function credsKey(address2, sigType) {
115442
116051
  return `${address2.toLowerCase()}:${sigType}`;
@@ -115488,10 +116097,10 @@ var BLOCKRUN_DIR, CREDS_FILE, BUILDER_CREDS_FILE, STATE_FILE;
115488
116097
  var init_creds = __esm({
115489
116098
  "src/polymarket/creds.ts"() {
115490
116099
  "use strict";
115491
- BLOCKRUN_DIR = path.join(os.homedir(), ".openclaw", "blockrun");
115492
- CREDS_FILE = path.join(BLOCKRUN_DIR, ".polymarket-creds");
115493
- BUILDER_CREDS_FILE = path.join(BLOCKRUN_DIR, ".polymarket-builder-creds");
115494
- STATE_FILE = path.join(BLOCKRUN_DIR, ".polymarket.json");
116100
+ BLOCKRUN_DIR = path2.join(os.homedir(), ".openclaw", "blockrun");
116101
+ CREDS_FILE = path2.join(BLOCKRUN_DIR, ".polymarket-creds");
116102
+ BUILDER_CREDS_FILE = path2.join(BLOCKRUN_DIR, ".polymarket-builder-creds");
116103
+ STATE_FILE = path2.join(BLOCKRUN_DIR, ".polymarket.json");
115495
116104
  }
115496
116105
  });
115497
116106
 
@@ -116673,13 +117282,13 @@ function __disposeResources(env) {
116673
117282
  }
116674
117283
  return next();
116675
117284
  }
116676
- function __rewriteRelativeImportExtension(path6, preserveJsx) {
116677
- if (typeof path6 === "string" && /^\.\.?\//.test(path6)) {
116678
- return path6.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m, tsx, d, ext, cm) {
117285
+ function __rewriteRelativeImportExtension(path5, preserveJsx) {
117286
+ if (typeof path5 === "string" && /^\.\.?\//.test(path5)) {
117287
+ return path5.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m, tsx, d, ext, cm) {
116679
117288
  return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : d + ext + "." + cm.toLowerCase() + "js";
116680
117289
  });
116681
117290
  }
116682
- return path6;
117291
+ return path5;
116683
117292
  }
116684
117293
  var extendStatics, __assign, __createBinding, __setModuleDefault, ownKeys, _SuppressedError, tslib_es6_default;
116685
117294
  var init_tslib_es6 = __esm({
@@ -148976,9 +149585,9 @@ var require_setupKzg = __commonJS({
148976
149585
  Object.defineProperty(exports, "__esModule", { value: true });
148977
149586
  exports.setupKzg = setupKzg;
148978
149587
  var defineKzg_js_1 = require_defineKzg();
148979
- function setupKzg(parameters, path6) {
149588
+ function setupKzg(parameters, path5) {
148980
149589
  try {
148981
- parameters.loadTrustedSetup(path6);
149590
+ parameters.loadTrustedSetup(path5);
148982
149591
  } catch (e7) {
148983
149592
  const error = e7;
148984
149593
  if (!error.message.includes("trusted setup is already loaded"))
@@ -197063,12 +197672,12 @@ var init_fragments = __esm({
197063
197672
  // node_modules/@ethersproject/abi/lib.esm/coders/abstract-coder.js
197064
197673
  function checkResultErrors(result) {
197065
197674
  const errors = [];
197066
- const checkErrors = function(path6, object) {
197675
+ const checkErrors = function(path5, object) {
197067
197676
  if (!Array.isArray(object)) {
197068
197677
  return;
197069
197678
  }
197070
197679
  for (let key2 in object) {
197071
- const childPath = path6.slice();
197680
+ const childPath = path5.slice();
197072
197681
  childPath.push(key2);
197073
197682
  try {
197074
197683
  checkErrors(childPath, object[key2]);
@@ -202886,8 +203495,8 @@ function createCommonjsModule(fn, basedir, module) {
202886
203495
  return module = {
202887
203496
  path: basedir,
202888
203497
  exports: {},
202889
- require: function(path6, base3) {
202890
- return commonjsRequire(path6, base3 === void 0 || base3 === null ? module.path : base3);
203498
+ require: function(path5, base3) {
203499
+ return commonjsRequire(path5, base3 === void 0 || base3 === null ? module.path : base3);
202891
203500
  }
202892
203501
  }, fn(module, module.exports), module.exports;
202893
203502
  }
@@ -206737,9 +207346,9 @@ var init_lib23 = __esm({
206737
207346
  if (index2 > 4294967295) {
206738
207347
  throw new Error("invalid index - " + String(index2));
206739
207348
  }
206740
- let path6 = this.path;
206741
- if (path6) {
206742
- path6 += "/" + (index2 & ~HardenedBit);
207349
+ let path5 = this.path;
207350
+ if (path5) {
207351
+ path5 += "/" + (index2 & ~HardenedBit);
206743
207352
  }
206744
207353
  const data = new Uint8Array(37);
206745
207354
  if (index2 & HardenedBit) {
@@ -206747,8 +207356,8 @@ var init_lib23 = __esm({
206747
207356
  throw new Error("cannot derive child of neutered node");
206748
207357
  }
206749
207358
  data.set(arrayify(this.privateKey), 1);
206750
- if (path6) {
206751
- path6 += "'";
207359
+ if (path5) {
207360
+ path5 += "'";
206752
207361
  }
206753
207362
  } else {
206754
207363
  data.set(arrayify(this.publicKey));
@@ -206767,21 +207376,21 @@ var init_lib23 = __esm({
206767
207376
  const ek = new SigningKey(hexlify(IL));
206768
207377
  Ki = ek._addPoint(this.publicKey);
206769
207378
  }
206770
- let mnemonicOrPath = path6;
207379
+ let mnemonicOrPath = path5;
206771
207380
  const srcMnemonic = this.mnemonic;
206772
207381
  if (srcMnemonic) {
206773
207382
  mnemonicOrPath = Object.freeze({
206774
207383
  phrase: srcMnemonic.phrase,
206775
- path: path6,
207384
+ path: path5,
206776
207385
  locale: srcMnemonic.locale || "en"
206777
207386
  });
206778
207387
  }
206779
207388
  return new _HDNode(_constructorGuard4, ki, Ki, this.fingerprint, bytes32(IR), index2, this.depth + 1, mnemonicOrPath);
206780
207389
  }
206781
- derivePath(path6) {
206782
- const components = path6.split("/");
207390
+ derivePath(path5) {
207391
+ const components = path5.split("/");
206783
207392
  if (components.length === 0 || components[0] === "m" && this.depth !== 0) {
206784
- throw new Error("invalid path - " + path6);
207393
+ throw new Error("invalid path - " + path5);
206785
207394
  }
206786
207395
  if (components[0] === "m") {
206787
207396
  components.shift();
@@ -207516,9 +208125,9 @@ function getPassword(password) {
207516
208125
  }
207517
208126
  return arrayify(password);
207518
208127
  }
207519
- function searchPath(object, path6) {
208128
+ function searchPath(object, path5) {
207520
208129
  let currentChild = object;
207521
- const comps = path6.toLowerCase().split("/");
208130
+ const comps = path5.toLowerCase().split("/");
207522
208131
  for (let i = 0; i < comps.length; i++) {
207523
208132
  let matchingChild = null;
207524
208133
  for (const key2 in currentChild) {
@@ -208167,12 +208776,12 @@ function _getAccount(data, key2) {
208167
208776
  const mnemonicIv = looseArrayify(searchPath(data, "x-ethers/mnemonicCounter"));
208168
208777
  const mnemonicCounter = new import_aes_js2.default.Counter(mnemonicIv);
208169
208778
  const mnemonicAesCtr = new import_aes_js2.default.ModeOfOperation.ctr(mnemonicKey, mnemonicCounter);
208170
- const path6 = searchPath(data, "x-ethers/path") || defaultPath;
208779
+ const path5 = searchPath(data, "x-ethers/path") || defaultPath;
208171
208780
  const locale = searchPath(data, "x-ethers/locale") || "en";
208172
208781
  const entropy = arrayify(mnemonicAesCtr.decrypt(mnemonicCiphertext));
208173
208782
  try {
208174
208783
  const mnemonic = entropyToMnemonic2(entropy, locale);
208175
- const node = HDNode.fromMnemonic(mnemonic, null, locale).derivePath(path6);
208784
+ const node = HDNode.fromMnemonic(mnemonic, null, locale).derivePath(path5);
208176
208785
  if (node.privateKey != account.privateKey) {
208177
208786
  throw new Error("mnemonic mismatch");
208178
208787
  }
@@ -208272,12 +208881,12 @@ function encrypt(account, password, options, progressCallback) {
208272
208881
  const privateKey = arrayify(account.privateKey);
208273
208882
  const passwordBytes = getPassword(password);
208274
208883
  let entropy = null;
208275
- let path6 = null;
208884
+ let path5 = null;
208276
208885
  let locale = null;
208277
208886
  if (hasMnemonic(account)) {
208278
208887
  const srcMnemonic = account.mnemonic;
208279
208888
  entropy = arrayify(mnemonicToEntropy2(srcMnemonic.phrase, srcMnemonic.locale || "en"));
208280
- path6 = srcMnemonic.path || defaultPath;
208889
+ path5 = srcMnemonic.path || defaultPath;
208281
208890
  locale = srcMnemonic.locale || "en";
208282
208891
  }
208283
208892
  let client = options.client;
@@ -208363,7 +208972,7 @@ function encrypt(account, password, options, progressCallback) {
208363
208972
  gethFilename: "UTC--" + timestamp + "--" + data.address,
208364
208973
  mnemonicCounter: hexlify(mnemonicIv).substring(2),
208365
208974
  mnemonicCiphertext: hexlify(mnemonicCiphertext).substring(2),
208366
- path: path6,
208975
+ path: path5,
208367
208976
  locale,
208368
208977
  version: "0.1"
208369
208978
  };
@@ -208657,11 +209266,11 @@ var init_lib26 = __esm({
208657
209266
  static fromEncryptedJsonSync(json, password) {
208658
209267
  return new _Wallet(decryptJsonWalletSync(json, password));
208659
209268
  }
208660
- static fromMnemonic(mnemonic, path6, wordlist3) {
208661
- if (!path6) {
208662
- path6 = defaultPath;
209269
+ static fromMnemonic(mnemonic, path5, wordlist3) {
209270
+ if (!path5) {
209271
+ path5 = defaultPath;
208663
209272
  }
208664
- return new _Wallet(HDNode.fromMnemonic(mnemonic, null, wordlist3).derivePath(path6));
209273
+ return new _Wallet(HDNode.fromMnemonic(mnemonic, null, wordlist3).derivePath(path5));
208665
209274
  }
208666
209275
  };
208667
209276
  }
@@ -214657,21 +215266,21 @@ var init_web3_provider = __esm({
214657
215266
  if (provider == null) {
214658
215267
  logger43.throwArgumentError("missing provider", "provider", provider);
214659
215268
  }
214660
- let path6 = null;
215269
+ let path5 = null;
214661
215270
  let jsonRpcFetchFunc = null;
214662
215271
  let subprovider = null;
214663
215272
  if (typeof provider === "function") {
214664
- path6 = "unknown:";
215273
+ path5 = "unknown:";
214665
215274
  jsonRpcFetchFunc = provider;
214666
215275
  } else {
214667
- path6 = provider.host || provider.path || "";
214668
- if (!path6 && provider.isMetaMask) {
214669
- path6 = "metamask";
215276
+ path5 = provider.host || provider.path || "";
215277
+ if (!path5 && provider.isMetaMask) {
215278
+ path5 = "metamask";
214670
215279
  }
214671
215280
  subprovider = provider;
214672
215281
  if (provider.request) {
214673
- if (path6 === "") {
214674
- path6 = "eip-1193:";
215282
+ if (path5 === "") {
215283
+ path5 = "eip-1193:";
214675
215284
  }
214676
215285
  jsonRpcFetchFunc = buildEip1193Fetcher(provider);
214677
215286
  } else if (provider.sendAsync) {
@@ -214681,11 +215290,11 @@ var init_web3_provider = __esm({
214681
215290
  } else {
214682
215291
  logger43.throwArgumentError("unsupported provider", "provider", provider);
214683
215292
  }
214684
- if (!path6) {
214685
- path6 = "unknown:";
215293
+ if (!path5) {
215294
+ path5 = "unknown:";
214686
215295
  }
214687
215296
  }
214688
- super(path6, network);
215297
+ super(path5, network);
214689
215298
  defineReadOnly(this, "jsonRpcFetchFunc", jsonRpcFetchFunc);
214690
215299
  defineReadOnly(this, "provider", subprovider);
214691
215300
  }
@@ -215523,7 +216132,7 @@ var require_axios = __commonJS({
215523
216132
  var https2 = __require("https");
215524
216133
  var http23 = __require("http2");
215525
216134
  var util5 = __require("util");
215526
- var path6 = __require("path");
216135
+ var path5 = __require("path");
215527
216136
  var followRedirects2 = require_follow_redirects();
215528
216137
  var zlib2 = __require("zlib");
215529
216138
  var stream4 = __require("stream");
@@ -216591,9 +217200,9 @@ var require_axios = __commonJS({
216591
217200
  function removeBrackets2(key2) {
216592
217201
  return utils$1.endsWith(key2, "[]") ? key2.slice(0, -2) : key2;
216593
217202
  }
216594
- function renderKey2(path7, key2, dots) {
216595
- if (!path7) return key2;
216596
- return path7.concat(key2).map(function each(token, i) {
217203
+ function renderKey2(path6, key2, dots) {
217204
+ if (!path6) return key2;
217205
+ return path6.concat(key2).map(function each(token, i) {
216597
217206
  token = removeBrackets2(token);
216598
217207
  return !dots && i ? "[" + token + "]" : token;
216599
217208
  }).join(dots ? "." : "");
@@ -216671,13 +217280,13 @@ var require_axios = __commonJS({
216671
217280
  return currentValue;
216672
217281
  });
216673
217282
  }
216674
- function defaultVisitor(value, key2, path7) {
217283
+ function defaultVisitor(value, key2, path6) {
216675
217284
  let arr = value;
216676
217285
  if (utils$1.isReactNative(formData) && utils$1.isReactNativeBlob(value)) {
216677
- formData.append(renderKey2(path7, key2, dots), convertValue(value));
217286
+ formData.append(renderKey2(path6, key2, dots), convertValue(value));
216678
217287
  return false;
216679
217288
  }
216680
- if (value && !path7 && typeof value === "object") {
217289
+ if (value && !path6 && typeof value === "object") {
216681
217290
  if (utils$1.endsWith(key2, "{}")) {
216682
217291
  key2 = metaTokens ? key2 : key2.slice(0, -2);
216683
217292
  value = stringifyWithDepthLimit(value, 1);
@@ -216696,7 +217305,7 @@ var require_axios = __commonJS({
216696
217305
  if (isVisitable2(value)) {
216697
217306
  return true;
216698
217307
  }
216699
- formData.append(renderKey2(path7, key2, dots), convertValue(value));
217308
+ formData.append(renderKey2(path6, key2, dots), convertValue(value));
216700
217309
  return false;
216701
217310
  }
216702
217311
  const exposedHelpers = Object.assign(predicates2, {
@@ -216704,17 +217313,17 @@ var require_axios = __commonJS({
216704
217313
  convertValue,
216705
217314
  isVisitable: isVisitable2
216706
217315
  });
216707
- function build(value, path7, depth = 0) {
217316
+ function build(value, path6, depth = 0) {
216708
217317
  if (utils$1.isUndefined(value)) return;
216709
217318
  throwIfMaxDepthExceeded(depth);
216710
217319
  if (stack.indexOf(value) !== -1) {
216711
- throw new Error("Circular reference detected in " + path7.join("."));
217320
+ throw new Error("Circular reference detected in " + path6.join("."));
216712
217321
  }
216713
217322
  stack.push(value);
216714
217323
  utils$1.forEach(value, function each(el, key2) {
216715
- const result = !(utils$1.isUndefined(el) || el === null) && visitor.call(formData, el, utils$1.isString(key2) ? key2.trim() : key2, path7, exposedHelpers);
217324
+ const result = !(utils$1.isUndefined(el) || el === null) && visitor.call(formData, el, utils$1.isString(key2) ? key2.trim() : key2, path6, exposedHelpers);
216716
217325
  if (result === true) {
216717
- build(el, path7 ? path7.concat(key2) : [key2], depth + 1);
217326
+ build(el, path6 ? path6.concat(key2) : [key2], depth + 1);
216718
217327
  }
216719
217328
  });
216720
217329
  stack.pop();
@@ -216903,7 +217512,7 @@ var require_axios = __commonJS({
216903
217512
  };
216904
217513
  function toURLEncodedForm2(data, options) {
216905
217514
  return toFormData3(data, new platform.classes.URLSearchParams(), {
216906
- visitor: function(value, key2, path7, helpers) {
217515
+ visitor: function(value, key2, path6, helpers) {
216907
217516
  if (platform.isNode && utils$1.isBuffer(value)) {
216908
217517
  this.append(key2, value.toString("base64"));
216909
217518
  return false;
@@ -216920,14 +217529,14 @@ var require_axios = __commonJS({
216920
217529
  }
216921
217530
  }
216922
217531
  function parsePropPath2(name) {
216923
- const path7 = [];
217532
+ const path6 = [];
216924
217533
  const pattern = /[^.[\]]+|\[([^.[\]]*)]/g;
216925
217534
  let match;
216926
217535
  while ((match = pattern.exec(name)) !== null) {
216927
- throwIfDepthExceeded2(path7.length);
216928
- path7.push(match[0] === "[]" ? "" : match[1] || match[0]);
217536
+ throwIfDepthExceeded2(path6.length);
217537
+ path6.push(match[0] === "[]" ? "" : match[1] || match[0]);
216929
217538
  }
216930
- return path7;
217539
+ return path6;
216931
217540
  }
216932
217541
  function arrayToObject2(arr) {
216933
217542
  const obj = {};
@@ -216942,12 +217551,12 @@ var require_axios = __commonJS({
216942
217551
  return obj;
216943
217552
  }
216944
217553
  function formDataToJSON2(formData) {
216945
- function buildPath(path7, value, target, index2) {
217554
+ function buildPath(path6, value, target, index2) {
216946
217555
  throwIfDepthExceeded2(index2);
216947
- let name = path7[index2++];
217556
+ let name = path6[index2++];
216948
217557
  if (name === "__proto__") return true;
216949
217558
  const isNumericKey = Number.isFinite(+name);
216950
- const isLast = index2 >= path7.length;
217559
+ const isLast = index2 >= path6.length;
216951
217560
  name = !name && utils$1.isArray(target) ? target.length : name;
216952
217561
  if (isLast) {
216953
217562
  if (utils$1.hasOwnProp(target, name)) {
@@ -216960,7 +217569,7 @@ var require_axios = __commonJS({
216960
217569
  if (!utils$1.hasOwnProp(target, name) || !utils$1.isObject(target[name])) {
216961
217570
  target[name] = [];
216962
217571
  }
216963
- const result = buildPath(path7, value, target[name], index2);
217572
+ const result = buildPath(path6, value, target[name], index2);
216964
217573
  if (result && utils$1.isArray(target[name])) {
216965
217574
  target[name] = arrayToObject2(target[name]);
216966
217575
  }
@@ -218571,8 +219180,8 @@ var require_axios = __commonJS({
218571
219180
  const allowedSocketPaths = own3("allowedSocketPaths");
218572
219181
  if (allowedSocketPaths != null) {
218573
219182
  const allowed = Array.isArray(allowedSocketPaths) ? allowedSocketPaths : [allowedSocketPaths];
218574
- const resolvedSocket = path6.resolve(socketPath);
218575
- const isAllowed = allowed.some((entry) => typeof entry === "string" && path6.resolve(entry) === resolvedSocket);
219183
+ const resolvedSocket = path5.resolve(socketPath);
219184
+ const isAllowed = allowed.some((entry) => typeof entry === "string" && path5.resolve(entry) === resolvedSocket);
218576
219185
  if (!isAllowed) {
218577
219186
  return reject(new AxiosError3(`socketPath "${socketPath}" is not permitted by allowedSocketPaths`, AxiosError3.ERR_BAD_OPTION_VALUE, config));
218578
219187
  }
@@ -218871,14 +219480,14 @@ var require_axios = __commonJS({
218871
219480
  var cookies = platform.hasStandardBrowserEnv ? (
218872
219481
  // Standard browser envs support document.cookie
218873
219482
  {
218874
- write(name, value, expires, path7, domain, secure, sameSite) {
219483
+ write(name, value, expires, path6, domain, secure, sameSite) {
218875
219484
  if (typeof document === "undefined") return;
218876
219485
  const cookie = [`${name}=${encodeURIComponent(value)}`];
218877
219486
  if (utils$1.isNumber(expires)) {
218878
219487
  cookie.push(`expires=${new Date(expires).toUTCString()}`);
218879
219488
  }
218880
- if (utils$1.isString(path7)) {
218881
- cookie.push(`path=${path7}`);
219489
+ if (utils$1.isString(path6)) {
219490
+ cookie.push(`path=${path6}`);
218882
219491
  }
218883
219492
  if (utils$1.isString(domain)) {
218884
219493
  cookie.push(`domain=${domain}`);
@@ -223367,18 +223976,18 @@ var require_client2 = __commonJS({
223367
223976
  }
223368
223977
  console.log(`Transaction not found or not in given states, timing out!`);
223369
223978
  }
223370
- async sendAuthedRequest(method, path6, body) {
223979
+ async sendAuthedRequest(method, path5, body) {
223371
223980
  if (this.canBuilderAuth()) {
223372
- const builderHeaders = await this._generateBuilderHeaders(method, path6, body);
223981
+ const builderHeaders = await this._generateBuilderHeaders(method, path5, body);
223373
223982
  if (builderHeaders !== void 0) {
223374
- return this.send(path6, method, { headers: builderHeaders, data: body });
223983
+ return this.send(path5, method, { headers: builderHeaders, data: body });
223375
223984
  }
223376
223985
  }
223377
- return this.send(path6, method, { data: body });
223986
+ return this.send(path5, method, { data: body });
223378
223987
  }
223379
- async _generateBuilderHeaders(method, path6, body) {
223988
+ async _generateBuilderHeaders(method, path5, body) {
223380
223989
  if (this.builderConfig !== void 0) {
223381
- const builderHeaders = await this.builderConfig.generateBuilderHeaders(method, path6, body);
223990
+ const builderHeaders = await this.builderConfig.generateBuilderHeaders(method, path5, body);
223382
223991
  if (builderHeaders == void 0) {
223383
223992
  return void 0;
223384
223993
  }
@@ -223469,12 +224078,12 @@ var require_signer = __commonJS({
223469
224078
  constructor(creds) {
223470
224079
  this.creds = creds;
223471
224080
  }
223472
- createBuilderHeaderPayload(method, path6, body, timestamp) {
224081
+ createBuilderHeaderPayload(method, path5, body, timestamp) {
223473
224082
  let ts = Math.floor(Date.now() / 1e3);
223474
224083
  if (timestamp !== void 0) {
223475
224084
  ts = timestamp;
223476
224085
  }
223477
- const builderSig = (0, signing_1.buildHmacSignature)(this.creds.secret, ts, method, path6, body);
224086
+ const builderSig = (0, signing_1.buildHmacSignature)(this.creds.secret, ts, method, path5, body);
223478
224087
  return {
223479
224088
  POLY_BUILDER_API_KEY: this.creds.key,
223480
224089
  POLY_BUILDER_PASSPHRASE: this.creds.passphrase,
@@ -223563,17 +224172,17 @@ var require_config2 = __commonJS({
223563
224172
  * @param path
223564
224173
  * @param body
223565
224174
  */
223566
- async generateBuilderHeaders(method, path6, body, timestamp) {
224175
+ async generateBuilderHeaders(method, path5, body, timestamp) {
223567
224176
  this.ensureValid();
223568
224177
  const builderType = this.getBuilderType();
223569
224178
  if (builderType == types_1.BuilderType.LOCAL) {
223570
- return Promise.resolve(this.signer?.createBuilderHeaderPayload(method, path6, body, timestamp));
224179
+ return Promise.resolve(this.signer?.createBuilderHeaderPayload(method, path5, body, timestamp));
223571
224180
  }
223572
224181
  if (builderType == types_1.BuilderType.REMOTE) {
223573
224182
  const url2 = this.remoteBuilderConfig.url;
223574
224183
  const payload = {
223575
224184
  method,
223576
- path: path6,
224185
+ path: path5,
223577
224186
  body,
223578
224187
  timestamp
223579
224188
  };
@@ -224355,11 +224964,11 @@ var init_withdraw = __esm({
224355
224964
  });
224356
224965
 
224357
224966
  // node_modules/@blockrun/llm/dist/index.js
224358
- import * as path2 from "path";
224967
+ import * as path3 from "path";
224359
224968
  import * as os2 from "os";
224360
224969
  import * as path22 from "path";
224361
224970
  import * as os22 from "os";
224362
- import * as path3 from "path";
224971
+ import * as path32 from "path";
224363
224972
  import * as os3 from "os";
224364
224973
  import * as path4 from "path";
224365
224974
  import * as os4 from "os";
@@ -224533,7 +225142,7 @@ function resolveDefaultTimeout() {
224533
225142
  function sleep2(ms) {
224534
225143
  return new Promise((r2) => setTimeout(r2, ms));
224535
225144
  }
224536
- var BlockrunError, PaymentError, APIError, BASE_CHAIN_ID2, USDC_BASE2, USDC_DOMAIN, TRANSFER_TYPES, BLOCKRUN_SERVICE_CODE2, LOCALHOST_DOMAINS, BLOCKRUN_DIR2, COST_LOG_FILE, SDK_VERSION, USER_AGENT2, DEFAULT_TIMEOUT, PHONE_PRICES, DEFAULT_API_URL13, DEFAULT_TIMEOUT13, DEFAULT_POLL_INTERVAL_MS, DEFAULT_POLL_BUDGET_MS, MAX_SIGNED_AUTH_SECONDS, BlockrunClient, WALLET_DIR2, WALLET_FILE3, WALLET_DIR22, SOLANA_WALLET_FILE, CACHE_DIR, DATA_DIR, COST_LOG_FILE2, DEFAULT_TTL;
225145
+ var BlockrunError, PaymentError, APIError, BASE_CHAIN_ID2, USDC_BASE2, USDC_DOMAIN, TRANSFER_TYPES, BLOCKRUN_SERVICE_CODE2, LOCALHOST_DOMAINS, BLOCKRUN_DIR2, COST_LOG_FILE, SDK_VERSION, USER_AGENT2, DEFAULT_TIMEOUT, PHONE_PRICES, DEFAULT_API_URL13, DEFAULT_TIMEOUT13, DEFAULT_POLL_INTERVAL_MS, DEFAULT_POLL_BUDGET_MS, MAX_SIGNED_AUTH_SECONDS, BlockrunClient, WALLET_DIR3, WALLET_FILE3, WALLET_DIR22, SOLANA_WALLET_FILE, CACHE_DIR, DATA_DIR, COST_LOG_FILE2, DEFAULT_TTL;
224537
225146
  var init_dist7 = __esm({
224538
225147
  "node_modules/@blockrun/llm/dist/index.js"() {
224539
225148
  "use strict";
@@ -224581,8 +225190,8 @@ var init_dist7 = __esm({
224581
225190
  };
224582
225191
  BLOCKRUN_SERVICE_CODE2 = "blockrun";
224583
225192
  LOCALHOST_DOMAINS = ["localhost", "127.0.0.1"];
224584
- BLOCKRUN_DIR2 = path2.join(os2.homedir(), ".blockrun");
224585
- COST_LOG_FILE = path2.join(BLOCKRUN_DIR2, "cost_log.jsonl");
225193
+ BLOCKRUN_DIR2 = path3.join(os2.homedir(), ".blockrun");
225194
+ COST_LOG_FILE = path3.join(BLOCKRUN_DIR2, "cost_log.jsonl");
224586
225195
  SDK_VERSION = "3.10.0";
224587
225196
  USER_AGENT2 = `blockrun-ts/${SDK_VERSION}`;
224588
225197
  DEFAULT_TIMEOUT = resolveDefaultTimeout();
@@ -224627,15 +225236,15 @@ var init_dist7 = __esm({
224627
225236
  * `/api` is tolerated and stripped). Query params are URL-encoded; arrays
224628
225237
  * become repeated keys (`?a=1&a=2`); undefined/null are dropped.
224629
225238
  */
224630
- async get(path52, params) {
224631
- const url2 = this.buildUrl(path52, params);
225239
+ async get(path5, params) {
225240
+ const url2 = this.buildUrl(path5, params);
224632
225241
  return this.requestWithPayment(url2, "GET");
224633
225242
  }
224634
225243
  /**
224635
225244
  * POST a BlockRun endpoint with a JSON body.
224636
225245
  */
224637
- async post(path52, body) {
224638
- const url2 = this.buildUrl(path52);
225246
+ async post(path5, body) {
225247
+ const url2 = this.buildUrl(path5);
224639
225248
  return this.requestWithPayment(url2, "POST", body);
224640
225249
  }
224641
225250
  /**
@@ -224650,8 +225259,8 @@ var init_dist7 = __esm({
224650
225259
  * short-circuits and returns the body. Most long-running endpoints (image,
224651
225260
  * video, music, voice) return 202 with a poll_url.
224652
225261
  */
224653
- async poll(path52, body, options) {
224654
- const submitUrl = this.buildUrl(path52);
225262
+ async poll(path5, body, options) {
225263
+ const submitUrl = this.buildUrl(path5);
224655
225264
  const budgetMs = options?.budgetMs ?? DEFAULT_POLL_BUDGET_MS;
224656
225265
  const intervalMs = options?.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;
224657
225266
  const resp402 = await this.fetchWithTimeout(submitUrl, {
@@ -224750,8 +225359,8 @@ var init_dist7 = __esm({
224750
225359
  * process.stdout.write(chunk.choices?.[0]?.delta?.content ?? "");
224751
225360
  * }
224752
225361
  */
224753
- async *stream(path52, body) {
224754
- const url2 = this.buildUrl(path52);
225362
+ async *stream(path5, body) {
225363
+ const url2 = this.buildUrl(path5);
224755
225364
  const requestBody = JSON.stringify(body ?? {});
224756
225365
  const resp402 = await this.fetchWithTimeout(url2, {
224757
225366
  method: "POST",
@@ -224817,8 +225426,8 @@ var init_dist7 = __esm({
224817
225426
  // --------------------------------------------------------------------
224818
225427
  // Internal: shared infrastructure
224819
225428
  // --------------------------------------------------------------------
224820
- buildUrl(path52, params) {
224821
- let normalized = path52.startsWith("/") ? path52 : `/${path52}`;
225429
+ buildUrl(path5, params) {
225430
+ let normalized = path5.startsWith("/") ? path5 : `/${path5}`;
224822
225431
  if (normalized.startsWith("/api/")) {
224823
225432
  normalized = normalized.slice(4);
224824
225433
  }
@@ -224966,10 +225575,10 @@ var init_dist7 = __esm({
224966
225575
  return { totalUsd: this.sessionTotalUsd, calls: this.sessionCalls };
224967
225576
  }
224968
225577
  };
224969
- WALLET_DIR2 = path22.join(os22.homedir(), ".blockrun");
224970
- WALLET_FILE3 = path22.join(WALLET_DIR2, ".session");
224971
- WALLET_DIR22 = path3.join(os3.homedir(), ".blockrun");
224972
- SOLANA_WALLET_FILE = path3.join(WALLET_DIR22, ".solana-session");
225578
+ WALLET_DIR3 = path22.join(os22.homedir(), ".blockrun");
225579
+ WALLET_FILE3 = path22.join(WALLET_DIR3, ".session");
225580
+ WALLET_DIR22 = path32.join(os3.homedir(), ".blockrun");
225581
+ SOLANA_WALLET_FILE = path32.join(WALLET_DIR22, ".solana-session");
224973
225582
  CACHE_DIR = path4.join(os4.homedir(), ".blockrun", "cache");
224974
225583
  DATA_DIR = path4.join(os4.homedir(), ".blockrun", "data");
224975
225584
  COST_LOG_FILE2 = path4.join(os4.homedir(), ".blockrun", "cost_log.jsonl");
@@ -225465,261 +226074,6 @@ var init_mcp_config = __esm({
225465
226074
  }
225466
226075
  });
225467
226076
 
225468
- // src/spend-control.ts
225469
- import * as fs3 from "fs";
225470
- import * as path5 from "path";
225471
- import { homedir as homedir12 } from "os";
225472
- function formatDuration(seconds) {
225473
- if (seconds < 60) {
225474
- return `${seconds}s`;
225475
- } else if (seconds < 3600) {
225476
- const mins = Math.ceil(seconds / 60);
225477
- return `${mins} min`;
225478
- } else {
225479
- const hours = Math.floor(seconds / 3600);
225480
- const mins = Math.ceil(seconds % 3600 / 60);
225481
- return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;
225482
- }
225483
- }
225484
- var WALLET_DIR3, HOUR_MS, DAY_MS, FileSpendControlStorage, InMemorySpendControlStorage, SpendControl;
225485
- var init_spend_control = __esm({
225486
- "src/spend-control.ts"() {
225487
- "use strict";
225488
- init_fs_read();
225489
- WALLET_DIR3 = path5.join(homedir12(), ".openclaw", "blockrun");
225490
- HOUR_MS = 60 * 60 * 1e3;
225491
- DAY_MS = 24 * HOUR_MS;
225492
- FileSpendControlStorage = class {
225493
- spendingFile;
225494
- constructor() {
225495
- this.spendingFile = path5.join(WALLET_DIR3, "spending.json");
225496
- }
225497
- load() {
225498
- try {
225499
- if (fs3.existsSync(this.spendingFile)) {
225500
- const data = JSON.parse(readTextFileSync(this.spendingFile));
225501
- const rawLimits = data.limits ?? {};
225502
- const rawHistory = data.history ?? [];
225503
- const limits = {};
225504
- for (const key2 of ["perRequest", "hourly", "daily", "session"]) {
225505
- const val = rawLimits[key2];
225506
- if (typeof val === "number" && val > 0 && Number.isFinite(val)) {
225507
- limits[key2] = val;
225508
- }
225509
- }
225510
- const history = [];
225511
- if (Array.isArray(rawHistory)) {
225512
- for (const r2 of rawHistory) {
225513
- if (typeof r2?.timestamp === "number" && typeof r2?.amount === "number" && Number.isFinite(r2.timestamp) && Number.isFinite(r2.amount) && r2.amount >= 0) {
225514
- history.push({
225515
- timestamp: r2.timestamp,
225516
- amount: r2.amount,
225517
- model: typeof r2.model === "string" ? r2.model : void 0,
225518
- action: typeof r2.action === "string" ? r2.action : void 0
225519
- });
225520
- }
225521
- }
225522
- }
225523
- return { limits, history };
225524
- }
225525
- } catch (err) {
225526
- console.error(`[ClawRouter] Failed to load spending data, starting fresh: ${err}`);
225527
- }
225528
- return null;
225529
- }
225530
- save(data) {
225531
- try {
225532
- if (!fs3.existsSync(WALLET_DIR3)) {
225533
- fs3.mkdirSync(WALLET_DIR3, { recursive: true, mode: 448 });
225534
- }
225535
- fs3.writeFileSync(this.spendingFile, JSON.stringify(data, null, 2), {
225536
- mode: 384
225537
- });
225538
- } catch (err) {
225539
- console.error(`[ClawRouter] Failed to save spending data: ${err}`);
225540
- }
225541
- }
225542
- };
225543
- InMemorySpendControlStorage = class {
225544
- data = null;
225545
- load() {
225546
- return this.data ? {
225547
- limits: { ...this.data.limits },
225548
- history: this.data.history.map((r2) => ({ ...r2 }))
225549
- } : null;
225550
- }
225551
- save(data) {
225552
- this.data = {
225553
- limits: { ...data.limits },
225554
- history: data.history.map((r2) => ({ ...r2 }))
225555
- };
225556
- }
225557
- };
225558
- SpendControl = class {
225559
- limits = {};
225560
- history = [];
225561
- sessionSpent = 0;
225562
- sessionCalls = 0;
225563
- storage;
225564
- now;
225565
- constructor(options) {
225566
- this.storage = options?.storage ?? new FileSpendControlStorage();
225567
- this.now = options?.now ?? (() => Date.now());
225568
- this.load();
225569
- }
225570
- setLimit(window2, amount) {
225571
- if (!Number.isFinite(amount) || amount <= 0) {
225572
- throw new Error("Limit must be a finite positive number");
225573
- }
225574
- this.limits[window2] = amount;
225575
- this.save();
225576
- }
225577
- clearLimit(window2) {
225578
- delete this.limits[window2];
225579
- this.save();
225580
- }
225581
- getLimits() {
225582
- return { ...this.limits };
225583
- }
225584
- check(estimatedCost2) {
225585
- const now2 = this.now();
225586
- if (this.limits.perRequest !== void 0) {
225587
- if (estimatedCost2 > this.limits.perRequest) {
225588
- return {
225589
- allowed: false,
225590
- blockedBy: "perRequest",
225591
- remaining: this.limits.perRequest,
225592
- reason: `Per-request limit exceeded: $${estimatedCost2.toFixed(4)} > $${this.limits.perRequest.toFixed(2)} max`
225593
- };
225594
- }
225595
- }
225596
- if (this.limits.hourly !== void 0) {
225597
- const hourlySpent = this.getSpendingInWindow(now2 - HOUR_MS, now2);
225598
- const remaining = this.limits.hourly - hourlySpent;
225599
- if (estimatedCost2 > remaining) {
225600
- const oldestInWindow = this.history.find((r2) => r2.timestamp >= now2 - HOUR_MS);
225601
- const resetIn = oldestInWindow ? Math.ceil((oldestInWindow.timestamp + HOUR_MS - now2) / 1e3) : 0;
225602
- return {
225603
- allowed: false,
225604
- blockedBy: "hourly",
225605
- remaining,
225606
- reason: `Hourly limit exceeded: $${(hourlySpent + estimatedCost2).toFixed(2)} > $${this.limits.hourly.toFixed(2)} max`,
225607
- resetIn
225608
- };
225609
- }
225610
- }
225611
- if (this.limits.daily !== void 0) {
225612
- const dailySpent = this.getSpendingInWindow(now2 - DAY_MS, now2);
225613
- const remaining = this.limits.daily - dailySpent;
225614
- if (estimatedCost2 > remaining) {
225615
- const oldestInWindow = this.history.find((r2) => r2.timestamp >= now2 - DAY_MS);
225616
- const resetIn = oldestInWindow ? Math.ceil((oldestInWindow.timestamp + DAY_MS - now2) / 1e3) : 0;
225617
- return {
225618
- allowed: false,
225619
- blockedBy: "daily",
225620
- remaining,
225621
- reason: `Daily limit exceeded: $${(dailySpent + estimatedCost2).toFixed(2)} > $${this.limits.daily.toFixed(2)} max`,
225622
- resetIn
225623
- };
225624
- }
225625
- }
225626
- if (this.limits.session !== void 0) {
225627
- const remaining = this.limits.session - this.sessionSpent;
225628
- if (estimatedCost2 > remaining) {
225629
- return {
225630
- allowed: false,
225631
- blockedBy: "session",
225632
- remaining,
225633
- reason: `Session limit exceeded: $${(this.sessionSpent + estimatedCost2).toFixed(2)} > $${this.limits.session.toFixed(2)} max`
225634
- };
225635
- }
225636
- }
225637
- return { allowed: true };
225638
- }
225639
- record(amount, metadata) {
225640
- if (!Number.isFinite(amount) || amount < 0) {
225641
- throw new Error("Record amount must be a non-negative finite number");
225642
- }
225643
- const record = {
225644
- timestamp: this.now(),
225645
- amount,
225646
- model: metadata?.model,
225647
- action: metadata?.action
225648
- };
225649
- this.history.push(record);
225650
- this.sessionSpent += amount;
225651
- this.sessionCalls += 1;
225652
- this.cleanup();
225653
- this.save();
225654
- }
225655
- getSpendingInWindow(from15, to) {
225656
- return this.history.filter((r2) => r2.timestamp >= from15 && r2.timestamp <= to).reduce((sum, r2) => sum + r2.amount, 0);
225657
- }
225658
- getSpending(window2) {
225659
- const now2 = this.now();
225660
- switch (window2) {
225661
- case "hourly":
225662
- return this.getSpendingInWindow(now2 - HOUR_MS, now2);
225663
- case "daily":
225664
- return this.getSpendingInWindow(now2 - DAY_MS, now2);
225665
- case "session":
225666
- return this.sessionSpent;
225667
- }
225668
- }
225669
- getRemaining(window2) {
225670
- const limit = this.limits[window2];
225671
- if (limit === void 0) return null;
225672
- return Math.max(0, limit - this.getSpending(window2));
225673
- }
225674
- getStatus() {
225675
- const now2 = this.now();
225676
- const hourlySpent = this.getSpendingInWindow(now2 - HOUR_MS, now2);
225677
- const dailySpent = this.getSpendingInWindow(now2 - DAY_MS, now2);
225678
- return {
225679
- limits: { ...this.limits },
225680
- spending: {
225681
- hourly: hourlySpent,
225682
- daily: dailySpent,
225683
- session: this.sessionSpent
225684
- },
225685
- remaining: {
225686
- hourly: this.limits.hourly !== void 0 ? this.limits.hourly - hourlySpent : null,
225687
- daily: this.limits.daily !== void 0 ? this.limits.daily - dailySpent : null,
225688
- session: this.limits.session !== void 0 ? this.limits.session - this.sessionSpent : null
225689
- },
225690
- calls: this.sessionCalls
225691
- };
225692
- }
225693
- getHistory(limit) {
225694
- const records = [...this.history].reverse();
225695
- return limit ? records.slice(0, limit) : records;
225696
- }
225697
- resetSession() {
225698
- this.sessionSpent = 0;
225699
- this.sessionCalls = 0;
225700
- }
225701
- cleanup() {
225702
- const cutoff = this.now() - DAY_MS;
225703
- this.history = this.history.filter((r2) => r2.timestamp >= cutoff);
225704
- }
225705
- save() {
225706
- this.storage.save({
225707
- limits: { ...this.limits },
225708
- history: [...this.history]
225709
- });
225710
- }
225711
- load() {
225712
- const data = this.storage.load();
225713
- if (data) {
225714
- this.limits = data.limits;
225715
- this.history = data.history;
225716
- this.cleanup();
225717
- }
225718
- }
225719
- };
225720
- }
225721
- });
225722
-
225723
226077
  // src/retry.ts
225724
226078
  function sleep3(ms) {
225725
226079
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -225789,7 +226143,7 @@ import {
225789
226143
  readdirSync,
225790
226144
  mkdirSync as mkdirSync3,
225791
226145
  copyFileSync,
225792
- renameSync
226146
+ renameSync as renameSync2
225793
226147
  } from "fs";
225794
226148
  import { readFile as readFileAsync } from "fs/promises";
225795
226149
  import { homedir as homedir13 } from "os";
@@ -226067,7 +226421,7 @@ function injectModelsConfig(logger48, options = {}) {
226067
226421
  try {
226068
226422
  const tmpPath = `${configPath}.tmp.${process.pid}`;
226069
226423
  writeFileSync3(tmpPath, JSON.stringify(config, null, 2));
226070
- renameSync(tmpPath, configPath);
226424
+ renameSync2(tmpPath, configPath);
226071
226425
  logger48.info("Smart routing enabled (blockrun/auto)");
226072
226426
  } catch (err) {
226073
226427
  logger48.info(`Failed to write config: ${err instanceof Error ? err.message : String(err)}`);
@@ -226103,7 +226457,7 @@ function syncAgentModelCache(logger48, options = {}) {
226103
226457
  entry.models = VISIBLE_OPENCLAW_MODELS;
226104
226458
  const tmpPath = `${cachePath}.tmp.${process.pid}`;
226105
226459
  writeFileSync3(tmpPath, JSON.stringify(cache2, null, 2));
226106
- renameSync(tmpPath, cachePath);
226460
+ renameSync2(tmpPath, cachePath);
226107
226461
  logger48.info(
226108
226462
  `Repaired ${agent} model cache: ${staleCount} \u2192 ${expectedIds.length} BlockRun models`
226109
226463
  );
@@ -227466,7 +227820,7 @@ ${errText}`
227466
227820
  }
227467
227821
  const tmpPath = `${configPath}.tmp.${process.pid}`;
227468
227822
  writeFileSync3(tmpPath, JSON.stringify(config, null, 2));
227469
- renameSync(tmpPath, configPath);
227823
+ renameSync2(tmpPath, configPath);
227470
227824
  api.logger.info("ClawRouter config cleaned up");
227471
227825
  }
227472
227826
  } catch (err) {
@@ -227502,6 +227856,8 @@ export {
227502
227856
  BALANCE_THRESHOLDS,
227503
227857
  BLOCKRUN_MODELS,
227504
227858
  BalanceMonitor,
227859
+ CAIP2_BASE,
227860
+ CAIP2_SOLANA_MAINNET,
227505
227861
  DEFAULT_RETRY_CONFIG,
227506
227862
  DEFAULT_ROUTING_CONFIG,
227507
227863
  DEFAULT_SESSION_CONFIG,
@@ -227510,6 +227866,7 @@ export {
227510
227866
  InMemorySpendControlStorage,
227511
227867
  InsufficientFundsError2 as InsufficientFundsError,
227512
227868
  MODEL_ALIASES,
227869
+ MalformedSpendPolicyError,
227513
227870
  OPENCLAW_MODELS,
227514
227871
  PARTNER_SERVICES,
227515
227872
  RequestDeduplicator,
@@ -227518,6 +227875,7 @@ export {
227518
227875
  SessionStore,
227519
227876
  SolanaBalanceMonitor,
227520
227877
  SpendControl,
227878
+ SpendPolicyError,
227521
227879
  VISIBLE_OPENCLAW_MODELS,
227522
227880
  blockrunProvider,
227523
227881
  buildImageGenerationProvider,
@@ -227557,6 +227915,7 @@ export {
227557
227915
  loadPaymentChain,
227558
227916
  logUsage,
227559
227917
  parseCallArgs,
227918
+ registerSpendPolicyHook,
227560
227919
  resolveModelAlias,
227561
227920
  resolvePaymentChain,
227562
227921
  route,